diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..ef5092060 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,2 @@ +# These are supported funding model platforms +custom: ["https://www.paypal.me/pythongui"] diff --git a/.github/ISSUE_TEMPLATE/issue-form---must-fill-in-this-form-with-every-new-issue-submitted.md b/.github/ISSUE_TEMPLATE/issue-form---must-fill-in-this-form-with-every-new-issue-submitted.md index a1fed6f02..05026c028 100644 --- a/.github/ISSUE_TEMPLATE/issue-form---must-fill-in-this-form-with-every-new-issue-submitted.md +++ b/.github/ISSUE_TEMPLATE/issue-form---must-fill-in-this-form-with-every-new-issue-submitted.md @@ -1,7 +1,7 @@ --- -name: Issue Form - **Must fill in this form** PSG4 is no longer supported. You MUST supply your Priority Support Code to log an issue. +name: Issue Form - **Must fill in this form** with every new issue submitted. about: This form contains the information needed to help you solve your problem -title: "[ Enhancement/Bug/Question] NOTE You must supply your Priority Support Code in order to receive support- " +title: "[ Enhancement/Bug/Question] NOTE - you can also call sg.main() or sg.main_open_github_issue() to post an issue" labels: '' assignees: '' @@ -22,7 +22,7 @@ assignees: '' ---------------------------------------- -## Versions (NOTE - PSG4 is no longer supported) +## Versions Version information can be obtained by calling `sg.main_get_debug_data()` Or you can print each version shown in () @@ -35,14 +35,10 @@ Or you can print each version shown in () #### PySimpleGUI Version (`sg.__version__`) -#### GUI Version (tkinter (`sg.tclversion_detailed`), PySide2, WxPython, Remi) - #### GUI Version (tkinter (`sg.tclversion_detailed`), PySide2, WxPython, Remi) -### Priority Support Code - Only Commercially Licensed Users Receive Support as of Feb 2025 -Replace this text with your Priority Support Code --------------------- @@ -63,16 +59,13 @@ Anything else you think would be helpful? These items may solve your problem. Please check those you've done by changing - [ ] to - [X] -- [ ] Searched main docs for your problem [PySimpleGUI Documenation](https://docs.PySimpleGUI.com) -- [ ] Looked for Demo Programs that are similar to your goal. It is recommend you use the Demo Browser! [Demo Programs](Demos.PySimpleGUI.com) -- [ ] None of your GUI code was generated by an AI algorithm like GPT +- [ ] Searched main docs for your problem www.PySimpleGUI.org +- [ ] Looked for Demo Programs that are similar to your goal Demos.PySimpleGUI.org - [ ] If not tkinter - looked for Demo Programs for specific port - [ ] For non tkinter - Looked at readme for your specific port if not PySimpleGUI (Qt, WX, Remi) - [ ] Run your program outside of your debugger (from a command line) -- [ ] Searched through Issues (open and closed) to see if already reported Issues.PySimpleGUI.com -- [ ] Have upgraded to the latest release of PySimpleGUI on PyPI (lastest official version) -- [ ] Tried running the Development Build. Your problem may have already been fixed but not released. Check Home Window for release notes and upgrading capability -- [ ] For licensing questions please email license@PySimpleGUI.com +- [ ] Searched through Issues (open and closed) to see if already reported Issues.PySimpleGUI.org +- [ ] Tried using the PySimpleGUI.py file on GitHub. Your problem may have already been fixed but not released #### Detailed Description diff --git a/.github/workflows/close_prs.yml b/.github/workflows/close_prs.yml deleted file mode 100644 index 73f50c1f4..000000000 --- a/.github/workflows/close_prs.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Auto Close Pull Requests - -on: - pull_request: - types: - - opened - - reopened - -jobs: - close-pr: - runs-on: ubuntu-latest - - steps: - - name: Check Out Repository - uses: actions/checkout@v2 - - - name: Close Pull Request - run: | - gh pr close ${{ github.event.pull_request.number }} --comment "Hi there! - Thank you for your interest in contributing to PySimpleGUI. However, we do not accept pull requests at this time. - (Refer to CONTRIBUTING.md) - - Please open an issue instead and we'll be happy to discuss it with you. :D" - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - # - name: Error out - # run: - # exit 1 - # with this commented, when a pr is closed it has a checkmark. if you'd prefer it to have an X, uncomment the code above ^^^ - diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..000d76e6d --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ + +readme_creator/psg_gui.py diff --git a/images/ButtonGraphics/Exit.png b/ButtonGraphics/Exit.png similarity index 100% rename from images/ButtonGraphics/Exit.png rename to ButtonGraphics/Exit.png diff --git a/images/ButtonGraphics/Loop.png b/ButtonGraphics/Loop.png similarity index 100% rename from images/ButtonGraphics/Loop.png rename to ButtonGraphics/Loop.png diff --git a/images/ButtonGraphics/Next.png b/ButtonGraphics/Next.png similarity index 100% rename from images/ButtonGraphics/Next.png rename to ButtonGraphics/Next.png diff --git a/images/ButtonGraphics/Pause.png b/ButtonGraphics/Pause.png similarity index 100% rename from images/ButtonGraphics/Pause.png rename to ButtonGraphics/Pause.png diff --git a/images/ButtonGraphics/Play.png b/ButtonGraphics/Play.png similarity index 100% rename from images/ButtonGraphics/Play.png rename to ButtonGraphics/Play.png diff --git a/images/ButtonGraphics/Restart.png b/ButtonGraphics/Restart.png similarity index 100% rename from images/ButtonGraphics/Restart.png rename to ButtonGraphics/Restart.png diff --git a/images/ButtonGraphics/Rewind.png b/ButtonGraphics/Rewind.png similarity index 100% rename from images/ButtonGraphics/Rewind.png rename to ButtonGraphics/Rewind.png diff --git a/images/ButtonGraphics/RobotBack.png b/ButtonGraphics/RobotBack.png similarity index 100% rename from images/ButtonGraphics/RobotBack.png rename to ButtonGraphics/RobotBack.png diff --git a/images/ButtonGraphics/RobotForward.png b/ButtonGraphics/RobotForward.png similarity index 100% rename from images/ButtonGraphics/RobotForward.png rename to ButtonGraphics/RobotForward.png diff --git a/images/ButtonGraphics/RobotLeft.png b/ButtonGraphics/RobotLeft.png similarity index 100% rename from images/ButtonGraphics/RobotLeft.png rename to ButtonGraphics/RobotLeft.png diff --git a/images/ButtonGraphics/RobotRight.png b/ButtonGraphics/RobotRight.png similarity index 100% rename from images/ButtonGraphics/RobotRight.png rename to ButtonGraphics/RobotRight.png diff --git a/images/ButtonGraphics/Stop.png b/ButtonGraphics/Stop.png similarity index 100% rename from images/ButtonGraphics/Stop.png rename to ButtonGraphics/Stop.png diff --git a/images/ButtonGraphics/green.png b/ButtonGraphics/green.png similarity index 100% rename from images/ButtonGraphics/green.png rename to ButtonGraphics/green.png diff --git a/images/ButtonGraphics/green30.png b/ButtonGraphics/green30.png similarity index 100% rename from images/ButtonGraphics/green30.png rename to ButtonGraphics/green30.png diff --git a/images/ButtonGraphics/orange.png b/ButtonGraphics/orange.png similarity index 100% rename from images/ButtonGraphics/orange.png rename to ButtonGraphics/orange.png diff --git a/images/ButtonGraphics/orange30.png b/ButtonGraphics/orange30.png similarity index 100% rename from images/ButtonGraphics/orange30.png rename to ButtonGraphics/orange30.png diff --git a/images/ButtonGraphics/red.png b/ButtonGraphics/red.png similarity index 100% rename from images/ButtonGraphics/red.png rename to ButtonGraphics/red.png diff --git a/images/ButtonGraphics/red30.png b/ButtonGraphics/red30.png similarity index 100% rename from images/ButtonGraphics/red30.png rename to ButtonGraphics/red30.png diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cc30e198a..715cee12f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,7 +1,26 @@ ## Contributing to PySimpleGUI -We are happy to receive issues describing bug reports and feature requests! If your bug report relates to a security vulnerability, please do not file a public issue, and please instead reach out to us at issues@PySimpleGUI.com. +### Open Source License, but Private Development -We do not accept (and do not wish to receive) contributions of user-created or third-party code, including patches, pull requests, or code snippets incorporated into submitted issues. Please do not send us any such code! Bug reports and feature requests should not include any source code. +PySimpleGUI is different than most projects on GitHub. It is licensed using the "Open Source License" LGPL3. However, the coding and development of the project is not "open source". -If you nonetheless submit any user-created or third-party code to us, (1) you assign to us all rights and title in or relating to the code; and (2) to the extent any such assignment is not fully effective, you hereby grant to us a royalty-free, perpetual, irrevocable, worldwide, unlimited, sublicensable, transferrable license under all intellectual property rights embodied therein or relating thereto, to exploit the code in any manner we choose, including to incorporate the code into PySimpleGUI and to redistribute it under any terms at our discretion. +This project does not accept user submitted code. + +#### Write Applications, Use PySimpleGUI, Write Tutorials, Teach Others + +These are a few of the ways you can directly contribute to PySimpleGUI. Using the package to make cool stuff and helping others learn how to use it to make cool stuff and a big help to PySimpleGUI. **Everyone** learns from seeing other people's implementations. It's through user's creating applications that new problems and needs are discovered. These have had a profound and positive impact on the project in the past. + +#### Pull Requests + +Pull requests are *not being accepted* for the project. This includes sending code changes via other means than "pull requests". Plainly put, core code you send will not be used. + + +#### Bug Fixes + +If you file an Issue for a bug, have located the bug, and found a fix in 10 lines of code or less.... and you wish to share your fix with the community, then feel free to include it with the filed Issue. If it's longer than 10 lines and wish to discuss it, then send an email to help@PySimpleGUI.org. + +## Thank You + +The support from the user community has been amazing. Your passion for creating PySimpleGUI applications is infectious. Every "thank you" is noticed and appreciated! Your passion for wanting to see PySimpleGUI improve is neither ignored nor unappreciated. + +It's understood that this way of development of a Python package is unorthodox. You may find it frustrating and slow, but hope you can respect the decision for it to operate in this manner and be supportive. diff --git a/Chess/ChessPiecesArray.png b/Chess/ChessPiecesArray.png new file mode 100644 index 000000000..101c0c9d6 Binary files /dev/null and b/Chess/ChessPiecesArray.png differ diff --git a/Chess/Demo_Chess_AGAINST_AI.py b/Chess/Demo_Chess_AGAINST_AI.py new file mode 100644 index 000000000..cf6cbc995 --- /dev/null +++ b/Chess/Demo_Chess_AGAINST_AI.py @@ -0,0 +1,233 @@ +import PySimpleGUI as sg +import os +import sys +import chess +import chess.pgn +import copy +import chess.uci + +CHESS_PATH = '.' # path to the chess pieces + +BLANK = 0 # piece names +PAWNB = 1 +KNIGHTB = 2 +BISHOPB = 3 +ROOKB = 4 +KINGB = 5 +QUEENB = 6 +PAWNW = 7 +KNIGHTW = 8 +BISHOPW = 9 +ROOKW = 10 +KINGW = 11 +QUEENW = 12 + +initial_board = [[ROOKB, KNIGHTB, BISHOPB, QUEENB, KINGB, BISHOPB, KNIGHTB, ROOKB], + [PAWNB, ] * 8, + [BLANK, ] * 8, + [BLANK, ] * 8, + [BLANK, ] * 8, + [BLANK, ] * 8, + [PAWNW, ] * 8, + [ROOKW, KNIGHTW, BISHOPW, QUEENW, KINGW, BISHOPW, KNIGHTW, ROOKW]] + +blank = os.path.join(CHESS_PATH, 'blank.png') +bishopB = os.path.join(CHESS_PATH, 'nbishopb.png') +bishopW = os.path.join(CHESS_PATH, 'nbishopw.png') +pawnB = os.path.join(CHESS_PATH, 'npawnb.png') +pawnW = os.path.join(CHESS_PATH, 'npawnw.png') +knightB = os.path.join(CHESS_PATH, 'nknightb.png') +knightW = os.path.join(CHESS_PATH, 'nknightw.png') +rookB = os.path.join(CHESS_PATH, 'nrookb.png') +rookW = os.path.join(CHESS_PATH, 'nrookw.png') +queenB = os.path.join(CHESS_PATH, 'nqueenb.png') +queenW = os.path.join(CHESS_PATH, 'nqueenw.png') +kingB = os.path.join(CHESS_PATH, 'nkingb.png') +kingW = os.path.join(CHESS_PATH, 'nkingw.png') + +images = {BISHOPB: bishopB, BISHOPW: bishopW, PAWNB: pawnB, PAWNW: pawnW, KNIGHTB: knightB, KNIGHTW: knightW, + ROOKB: rookB, ROOKW: rookW, KINGB: kingB, KINGW: kingW, QUEENB: queenB, QUEENW: queenW, BLANK: blank} + + +def open_pgn_file(filename): + pgn = open(filename) + first_game = chess.pgn.read_game(pgn) + moves = [move for move in first_game.main_line()] + return moves + + +def render_square(image, key, location): + if (location[0] + location[1]) % 2: + color = '#B58863' + else: + color = '#F0D9B5' + return sg.RButton('', image_filename=image, size=(1, 1), button_color=('white', color), pad=(0, 0), key=key) + + +def redraw_board(window, board): + for i in range(8): + for j in range(8): + color = '#B58863' if (i + j) % 2 else '#F0D9B5' + piece_image = images[board[i][j]] + elem = window.FindElement(key=(i, j)) + elem.Update(button_color=('white', color), + image_filename=piece_image, ) + + +def PlayGame(): + menu_def = [['&File', ['&Open PGN File', 'E&xit']], + ['&Help', '&About...'], ] + + # sg.SetOptions(margins=(0,0)) + sg.ChangeLookAndFeel('GreenTan') + # create initial board setup + psg_board = copy.deepcopy(initial_board) + # the main board display layout + board_layout = [[sg.T(' ')] + [sg.T('{}'.format(a), pad=((23, 27), 0), font='Any 13') for a in 'abcdefgh']] + # loop though board and create buttons with images + for i in range(8): + row = [sg.T(str(8 - i) + ' ', font='Any 13')] + for j in range(8): + piece_image = images[psg_board[i][j]] + row.append(render_square(piece_image, key=(i, j), location=(i, j))) + row.append(sg.T(str(8 - i) + ' ', font='Any 13')) + board_layout.append(row) + # add the labels across bottom of board + board_layout.append([sg.T(' ')] + [sg.T('{}'.format(a), pad=((23, 27), 0), font='Any 13') for a in 'abcdefgh']) + + # setup the controls on the right side of screen + openings = ( + 'Any', 'Defense', 'Attack', 'Trap', 'Gambit', 'Counter', 'Sicillian', 'English', 'French', 'Queen\'s openings', + 'King\'s Openings', 'Indian Openings') + + board_controls = [[sg.RButton('New Game', key='New Game'), sg.RButton('Draw')], + [sg.RButton('Resign Game'), sg.RButton('Set FEN')], + [sg.RButton('Player Odds'), sg.RButton('Training')], + [sg.Drop(openings), sg.Text('Opening/Style')], + [sg.CBox('Play As White', key='_white_')], + [sg.Drop([2, 3, 4, 5, 6, 7, 8, 9, 10], size=(3, 1), key='_level_'), sg.Text('Difficulty Level')], + [sg.Text('Move List')], + [sg.Multiline([], do_not_clear=True, autoscroll=True, size=(15, 10), key='_movelist_')], + ] + + # layouts for the tabs + controls_layout = [[sg.Text('Performance Parameters', font='_ 20')], + [sg.T('Put stuff like AI engine tuning parms on this tab')]] + + statistics_layout = [[sg.Text('Statistics', font=('_ 20'))], + [sg.T('Game statistics go here?')]] + + board_tab = [[sg.Column(board_layout)]] + + # the main window layout + layout = [[sg.Menu(menu_def, tearoff=False)], + [sg.TabGroup([[sg.Tab('Board', board_tab), + sg.Tab('Controls', controls_layout), + sg.Tab('Statistics', statistics_layout)]], title_color='red'), + sg.Column(board_controls)], + [sg.Text('Click anywhere on board for next move', font='_ 14')]] + + window = sg.Window('Chess', + default_button_element_size=(12, 1), + auto_size_buttons=False, + icon='kingb.ico').Layout(layout) + + filename = sg.PopupGetFile('\n'.join(('To begin, set location of AI EXE file', + 'If you have not done so already, download the engine', + 'Download the StockFish Chess engine at: https://stockfishchess.org/download/')), + file_types=(('Chess AI Engine EXE File', '*.exe'),)) + if filename is None: + sys.exit() + engine = chess.uci.popen_engine(filename) + engine.uci() + info_handler = chess.uci.InfoHandler() + engine.info_handlers.append(info_handler) + + board = chess.Board() + move_count = 1 + move_state = move_from = move_to = 0 + # ---===--- Loop taking in user input --- # + while not board.is_game_over(): + + if board.turn == chess.WHITE: + engine.position(board) + + # human_player(board) + move_state = 0 + while True: + button, value = window.Read() + if button in (None, 'Exit'): + exit() + if button == 'New Game': + sg.Popup('You have to restart the program to start a new game... sorry....') + break + psg_board = copy.deepcopy(initial_board) + redraw_board(window, psg_board) + move_state = 0 + break + level = value['_level_'] + if type(button) is tuple: + if move_state == 0: + move_from = button + row, col = move_from + piece = psg_board[row][col] # get the move-from piece + button_square = window.FindElement(key=(row, col)) + button_square.Update(button_color=('white', 'red')) + move_state = 1 + elif move_state == 1: + move_to = button + row, col = move_to + if move_to == move_from: # cancelled move + color = '#B58863' if (row + col) % 2 else '#F0D9B5' + button_square.Update(button_color=('white', color)) + move_state = 0 + continue + + picked_move = '{}{}{}{}'.format('abcdefgh'[move_from[1]], 8 - move_from[0], + 'abcdefgh'[move_to[1]], 8 - move_to[0]) + + if picked_move in [str(move) for move in board.legal_moves]: + board.push(chess.Move.from_uci(picked_move)) + else: + print('Illegal move') + move_state = 0 + color = '#B58863' if (move_from[0] + move_from[1]) % 2 else '#F0D9B5' + button_square.Update(button_color=('white', color)) + continue + + psg_board[move_from[0]][move_from[1]] = BLANK # place blank where piece was + psg_board[row][col] = piece # place piece in the move-to square + redraw_board(window, psg_board) + move_count += 1 + + window.FindElement('_movelist_').Update(picked_move + '\n', append=True) + + break + else: + engine.position(board) + best_move = engine.go(searchmoves=board.legal_moves, depth=level, movetime=(level * 100)).bestmove + move_str = str(best_move) + from_col = ord(move_str[0]) - ord('a') + from_row = 8 - int(move_str[1]) + to_col = ord(move_str[2]) - ord('a') + to_row = 8 - int(move_str[3]) + + window.FindElement('_movelist_').Update(move_str + '\n', append=True) + + piece = psg_board[from_row][from_col] + psg_board[from_row][from_col] = BLANK + psg_board[to_row][to_col] = piece + redraw_board(window, psg_board) + + board.push(best_move) + move_count += 1 + sg.Popup('Game over!', 'Thank you for playing') + + +# Download the StockFish Chess engine at: https://stockfishchess.org/download/ +# engine = chess.uci.popen_engine(r'E:\DownloadsE\stockfish-9-win\Windows\stockfish_9_x64.exe') +# engine.uci() +# info_handler = chess.uci.InfoHandler() +# engine.info_handlers.append(info_handler) +# level = 2 +PlayGame() diff --git a/Chess/Demo_Chess_Board.py b/Chess/Demo_Chess_Board.py new file mode 100644 index 000000000..279e0ce1a --- /dev/null +++ b/Chess/Demo_Chess_Board.py @@ -0,0 +1,160 @@ +import PySimpleGUI as sg +import os +import chess +import chess.pgn +import copy +import time + +button_names = ('close', 'cookbook', 'cpu', 'github', 'pysimplegui', 'run', 'storage', 'timer') + +CHESS_PATH = '.' # path to the chess pieces + +BLANK = 0 # piece names +PAWNB = 1 +KNIGHTB = 2 +BISHOPB = 3 +ROOKB = 4 +KINGB = 5 +QUEENB = 6 +PAWNW = 7 +KNIGHTW = 8 +BISHOPW = 9 +ROOKW = 10 +KINGW = 11 +QUEENW = 12 + +initial_board = [[ROOKB, KNIGHTB, BISHOPB, KINGB, QUEENB, BISHOPB, KNIGHTB, ROOKB ], + [PAWNB,]*8, + [BLANK,]*8, + [BLANK,]*8, + [BLANK,]*8, + [BLANK,]*8, + [PAWNW,]*8, + [ROOKW, KNIGHTW, BISHOPW, KINGW, QUEENW, BISHOPW, KNIGHTW, ROOKW]] + +blank = os.path.join(CHESS_PATH, 'blank.png') +bishopB = os.path.join(CHESS_PATH, 'nbishopb.png') +bishopW = os.path.join(CHESS_PATH, 'nbishopw.png') +pawnB = os.path.join(CHESS_PATH, 'npawnb.png') +pawnW = os.path.join(CHESS_PATH, 'npawnw.png') +knightB = os.path.join(CHESS_PATH, 'nknightb.png') +knightW = os.path.join(CHESS_PATH, 'nknightw.png') +rookB = os.path.join(CHESS_PATH, 'nrookb.png') +rookW = os.path.join(CHESS_PATH, 'nrookw.png') +queenB = os.path.join(CHESS_PATH, 'nqueenB.png') +queenW = os.path.join(CHESS_PATH, 'nqueenW.png') +kingB = os.path.join(CHESS_PATH, 'nkingb.png') +kingW = os.path.join(CHESS_PATH, 'nkingw.png') + +images = {BISHOPB: bishopB, BISHOPW: bishopW, PAWNB: pawnB, PAWNW: pawnW, KNIGHTB: knightB, KNIGHTW: knightW, + ROOKB: rookB, ROOKW: rookW, KINGB: kingB, KINGW: kingW, QUEENB: queenB, QUEENW: queenW, BLANK: blank} + +def open_pgn_file(filename): + pgn = open(filename) + first_game = chess.pgn.read_game(pgn) + moves = [move for move in first_game.main_line()] + return moves + +def render_square(image, key, location): + if (location[0] + location[1]) % 2: + color = '#B58863' + else: + color = '#F0D9B5' + return sg.RButton('', image_filename=image, size=(1, 1), button_color=('white', color), pad=(0, 0), key=key) + +def redraw_board(window, board): + for i in range(8): + for j in range(8): + color = '#B58863' if (i+j) % 2 else '#F0D9B5' + piece_image = images[board[i][j]] + elem = window.FindElement(key=(i,j)) + elem.Update(button_color = ('white', color), + image_filename=piece_image,) + +def PlayGame(): + + menu_def = [['&File', ['&Open PGN File', 'E&xit' ]], + ['&Help', '&About...'],] + + # sg.SetOptions(margins=(0,0)) + sg.ChangeLookAndFeel('GreenTan') + # create initial board setup + board = copy.deepcopy(initial_board) + # the main board display layout + board_layout = [[sg.T(' ')] + [sg.T('{}'.format(a), pad=((23,27),0), font='Any 13') for a in 'abcdefgh']] + # loop though board and create buttons with images + for i in range(8): + row = [sg.T(str(8-i)+' ', font='Any 13')] + for j in range(8): + piece_image = images[board[i][j]] + row.append(render_square(piece_image, key=(i,j), location=(i,j))) + row.append(sg.T(str(8-i)+' ', font='Any 13')) + board_layout.append(row) + # add the labels across bottom of board + board_layout.append([sg.T(' ')] + [sg.T('{}'.format(a), pad=((23,27),0), font='Any 13') for a in 'abcdefgh']) + + # setup the controls on the right side of screen + openings = ('Any', 'Defense', 'Attack', 'Trap', 'Gambit','Counter', 'Sicillian', 'English','French', 'Queen\'s openings', 'King\'s Openings','Indian Openings') + + board_controls = [[sg.RButton('New Game', key='Open PGN File'), sg.RButton('Draw')], + [sg.RButton('Resign Game'), sg.RButton('Set FEN')], + [sg.RButton('Player Odds'),sg.RButton('Training') ], + [sg.Drop(openings),sg.Text('Opening/Style')], + [sg.CBox('Play a White', key='_white_')], + [sg.Text('Move List')], + [sg.Multiline([], do_not_clear=True, autoscroll=True, size=(15,10),key='_movelist_')],] + + # layouts for the tabs + controls_layout = [[sg.Text('Performance Parameters', font='_ 20')], + [sg.T('Put stuff like AI engine tuning parms on this tab')]] + + statistics_layout = [[sg.Text('Statistics', font=('_ 20'))], + [sg.T('Game statistics go here?')]] + + board_tab = [[sg.Column(board_layout)]] + + # the main window layout + layout = [[sg.Menu(menu_def, tearoff=False)], + [sg.TabGroup([[sg.Tab('Board',board_tab), + sg.Tab('Controls', controls_layout), + sg.Tab('Statistics', statistics_layout)]], title_color='red'), + sg.Column(board_controls)], + [sg.Text('Click anywhere on board for next move', font='_ 14')]] + + window = sg.Window('Chess', default_button_element_size=(12,1), auto_size_buttons=False, icon='kingb.ico').Layout(layout) + + # ---===--- Loop taking in user input --- # + i = 0 + moves = None + while True: + button, value = window.Read() + if button in (None, 'Exit'): + break + if button == 'Open PGN File': + filename = sg.PopupGetFile('', no_window=True) + if filename is not None: + moves = open_pgn_file(filename) + i = 0 + board = copy.deepcopy(initial_board) + window.FindElement('_movelist_').Update(value='') + if button == 'About...': + sg.Popup('Powerd by Engine Kibitz Chess Engine') + if type(button) is tuple and moves is not None and i < len(moves): + move = moves[i] # get the current move + window.FindElement('_movelist_').Update(value='{} {}\n'.format(i+1, str(move)), append=True) + move_from = move.from_square # parse the move-from and move-to squares + move_to = move.to_square + row, col = move_from // 8, move_from % 8 + piece = board[row][col] # get the move-from piece + button = window.FindElement(key=(row,col)) + for x in range(3): + button.Update(button_color = ('white' , 'red' if x % 2 else 'white')) + window.Refresh() + time.sleep(.05) + board[row][col] = BLANK # place blank where piece was + row, col = move_to // 8, move_to % 8 # compute move-to square + board[row][col] = piece # place piece in the move-to square + redraw_board(window, board) + i += 1 + +PlayGame() \ No newline at end of file diff --git a/Chess/bishopb.png b/Chess/bishopb.png new file mode 100644 index 000000000..453cb3235 Binary files /dev/null and b/Chess/bishopb.png differ diff --git a/Chess/bishopw.png b/Chess/bishopw.png new file mode 100644 index 000000000..26dae01cf Binary files /dev/null and b/Chess/bishopw.png differ diff --git a/Chess/blank.png b/Chess/blank.png new file mode 100644 index 000000000..09ffa6d69 Binary files /dev/null and b/Chess/blank.png differ diff --git a/Chess/game.pgn b/Chess/game.pgn new file mode 100644 index 000000000..1dda9fbd5 --- /dev/null +++ b/Chess/game.pgn @@ -0,0 +1,36 @@ +[Event "Wch U12"] +[Site "Duisburg"] +[Date "1992.??.??"] +[Round "1"] +[White "Malakhov, Vladimir"] +[Black "Ab Rahman, M."] +[Result "1-0"] +[WhiteElo ""] +[BlackElo ""] +[ECO "A05"] + +1.Nf3 Nf6 2.b3 g6 3.Bb2 Bg7 4.g3 d6 5.Bg2 O-O 6.O-O c6 7.d3 e5 8.c4 Ne8 9.Nbd2 f5 +10.Qc2 Na6 11.c5 Nxc5 12.Nxe5 Qe7 13.d4 Na6 14.Qc4+ Kh8 15.Nef3 Be6 16.Qc3 f4 +17.gxf4 Rxf4 18.Qe3 Rf8 19.Ng5 Nec7 20.Nc4 Rae8 21.Nxe6 Qxe6 22.Qxe6 Rxe6 +23.e3 d5 24.Ne5 g5 25.Ba3 Rff6 26.Bh3 Re8 27.Bd7 Rd8 28.Be7 Rxd7 29.Bxf6 1-0 + + +[Event "Wch U12"] +[Site "Duisburg"] +[Date "1992.??.??"] +[Round "2"] +[White "Malakhov, Vladimir"] +[Black "Berescu, Alin"] +[Result "1-0"] +[WhiteElo ""] +[BlackElo ""] +[ECO "D05"] + +1.d4 Nf6 2.Nd2 d5 3.Ngf3 e6 4.e3 c5 5.c3 Nbd7 6.Bd3 Bd6 7.O-O O-O 8.Re1 b6 +9.e4 dxe4 10.Nxe4 Be7 11.Ne5 Bb7 12.Ng5 g6 13.Qe2 Nxe5 14.dxe5 Nh5 15.Ne4 Qd5 +16.f4 Rfd8 17.Bc2 Qc6 18.Be3 Rd7 19.Rad1 Rad8 20.Rxd7 Rxd7 21.Nd2 Ng7 22.Be4 Qc8 +23.g4 Qd8 24.Bxb7 Rxb7 25.Ne4 Rd7 26.c4 h5 27.h3 h4 28.Kh2 Ne8 29.f5 Qc7 +30.Bf4 Rd4 31.Qf2 Rxc4 32.f6 Qb7 33.Ng5 Bf8 34.b3 Rc3 35.Qd2 Rf3 36.Nxf3 Qxf3 +37.Qe3 Qd5 38.Qe4 Qd7 39.Qf3 Nc7 40.Rd1 Nd5 41.Bg5 Qc7 42.Re1 b5 43.Qd1 c4 +44.Qc1 Bb4 45.Bd2 Bxd2 46.Qxd2 Nxf6 47.bxc4 bxc4 48.Qd6 Qa5 49.Rf1 Nd5 50.Qd7 Qd2+ +51.Kh1 f5 52.exf6 1-0 diff --git a/Chess/kingb.ico b/Chess/kingb.ico new file mode 100644 index 000000000..6e6030b33 Binary files /dev/null and b/Chess/kingb.ico differ diff --git a/Chess/kingb.png b/Chess/kingb.png new file mode 100644 index 000000000..0d94a1c29 Binary files /dev/null and b/Chess/kingb.png differ diff --git a/Chess/kingw.png b/Chess/kingw.png new file mode 100644 index 000000000..a4fe68c80 Binary files /dev/null and b/Chess/kingw.png differ diff --git a/Chess/knightb.png b/Chess/knightb.png new file mode 100644 index 000000000..8e3d04e6f Binary files /dev/null and b/Chess/knightb.png differ diff --git a/Chess/knightw.png b/Chess/knightw.png new file mode 100644 index 000000000..2d716b15b Binary files /dev/null and b/Chess/knightw.png differ diff --git a/Chess/nbishopb.png b/Chess/nbishopb.png new file mode 100644 index 000000000..c52b6779b Binary files /dev/null and b/Chess/nbishopb.png differ diff --git a/Chess/nbishopw.png b/Chess/nbishopw.png new file mode 100644 index 000000000..ab73bae61 Binary files /dev/null and b/Chess/nbishopw.png differ diff --git a/Chess/nkingb.png b/Chess/nkingb.png new file mode 100644 index 000000000..945a4898a Binary files /dev/null and b/Chess/nkingb.png differ diff --git a/Chess/nkingw.png b/Chess/nkingw.png new file mode 100644 index 000000000..6662f3233 Binary files /dev/null and b/Chess/nkingw.png differ diff --git a/Chess/nknightb.png b/Chess/nknightb.png new file mode 100644 index 000000000..e28cbb170 Binary files /dev/null and b/Chess/nknightb.png differ diff --git a/Chess/nknightw.png b/Chess/nknightw.png new file mode 100644 index 000000000..34da37f91 Binary files /dev/null and b/Chess/nknightw.png differ diff --git a/Chess/npawnb.png b/Chess/npawnb.png new file mode 100644 index 000000000..a47983505 Binary files /dev/null and b/Chess/npawnb.png differ diff --git a/Chess/npawnw.png b/Chess/npawnw.png new file mode 100644 index 000000000..a05034abb Binary files /dev/null and b/Chess/npawnw.png differ diff --git a/Chess/nqueenb.png b/Chess/nqueenb.png new file mode 100644 index 000000000..54231369c Binary files /dev/null and b/Chess/nqueenb.png differ diff --git a/Chess/nqueenw.png b/Chess/nqueenw.png new file mode 100644 index 000000000..afaab4859 Binary files /dev/null and b/Chess/nqueenw.png differ diff --git a/Chess/nrookb.png b/Chess/nrookb.png new file mode 100644 index 000000000..8b18a6f57 Binary files /dev/null and b/Chess/nrookb.png differ diff --git a/Chess/nrookw.png b/Chess/nrookw.png new file mode 100644 index 000000000..31522a369 Binary files /dev/null and b/Chess/nrookw.png differ diff --git a/Chess/pawnb.png b/Chess/pawnb.png new file mode 100644 index 000000000..c432d38ae Binary files /dev/null and b/Chess/pawnb.png differ diff --git a/Chess/pawnw.png b/Chess/pawnw.png new file mode 100644 index 000000000..e98fae2bd Binary files /dev/null and b/Chess/pawnw.png differ diff --git a/Chess/queenb.png b/Chess/queenb.png new file mode 100644 index 000000000..225f869e9 Binary files /dev/null and b/Chess/queenb.png differ diff --git a/Chess/queenw.png b/Chess/queenw.png new file mode 100644 index 000000000..d7341649b Binary files /dev/null and b/Chess/queenw.png differ diff --git a/Chess/readme.md b/Chess/readme.md new file mode 100644 index 000000000..037f51006 --- /dev/null +++ b/Chess/readme.md @@ -0,0 +1,16 @@ +# PySimpleGUI-Chess A Chess Game Playback Program + +![image](https://user-images.githubusercontent.com/46163555/64135781-4c58a600-cdba-11e9-968d-60ddfb4c8952.png) + + +## Introduction +This is the start of a front-end GUI for an AI engine that plays chess. It simply reads moves the a PGN file and steps through it showing each of the moves on the board. + +To play against the AI run the program +Demo_Chess_AGAINST_AI.py + +Locate where the pacakge was installed and run the programs from that folder. You need to run from the installed folder so that the images of the chess pieces are located. + +## Home Page (GitHub) + +[www.PySimpleGUI.com](www.PySimpleGUI.com) diff --git a/Chess/requirements.txt b/Chess/requirements.txt new file mode 100644 index 000000000..5003cd5ff --- /dev/null +++ b/Chess/requirements.txt @@ -0,0 +1,2 @@ +PySimpleGUI==3.9.1 +python-chess==0.23.9 diff --git a/Chess/rookb.png b/Chess/rookb.png new file mode 100644 index 000000000..b9748e87f Binary files /dev/null and b/Chess/rookb.png differ diff --git a/Chess/rookw.png b/Chess/rookw.png new file mode 100644 index 000000000..a805de496 Binary files /dev/null and b/Chess/rookw.png differ diff --git a/DemoPrograms/Browser_START_HERE_Demo_Programs_Browser.py b/DemoPrograms/Browser_START_HERE_Demo_Programs_Browser.py index 00b41d515..6fe12e1d3 100644 --- a/DemoPrograms/Browser_START_HERE_Demo_Programs_Browser.py +++ b/DemoPrograms/Browser_START_HERE_Demo_Programs_Browser.py @@ -1,27 +1,10 @@ -''' -Copyright 2022-2024 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - -Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject -to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - -You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant -to the PySimpleGUI License Agreement. -''' - -import os +import os.path +import subprocess import sys import mmap, re import warnings -import PySimpleGUI as sg - -version = '5.3.0' -__version__ = version.split()[0] - -packages_with_weird_names = {'cv2':'opencv-python', - 'PIL':'pillow', - 'vlc':'python-vlc', - } +import PySimpleGUI as sg """ @@ -50,32 +33,14 @@ Keeps a "history" of the previously chosen folders to easy switching between projects - Versions: - 5.0.0 11-Feb-2024 The NEW Demo Browser for use with PySimpleGUI 5! - 5.1.0 08-Apr-2024 Several new Demo Programs, updated Matplotlib ping demo, license ver 1.1 - 5.2.0 14-Aug-2024 Fixed erronous import error (when import line started with "from") - Added a new "Path" input so that an arbitrary file can be executed easily (or edited) - 5.3.0 15-Aug-2024 One last change for the new path input... clear other fields if chars are entered - Copyright 2021, 2022, 2023, 2024 PySimpleSoft Inc. + Copyright 2021 PySimpleGUI.org """ -''' -MM""""""""`M oo dP -MM mmmmmmmM 88 -M' MMMM dP 88 .d8888b. -MM MMMMMMMM 88 88 88ooood8 -MM MMMMMMMM 88 88 88. ... -MM MMMMMMMM dP dP `88888P' -MMMMMMMMMMMM - -MM""""""""`M -MM mmmmmmmM -M' MMMM dP dP 88d888b. .d8888b. .d8888b. -MM MMMMMMMM 88 88 88' `88 88' `"" Y8ooooo. -MM MMMMMMMM 88. .88 88 88 88. ... 88 -MM MMMMMMMM `88888P' dP dP `88888P' `88888P' -MMMMMMMMMMMM -''' +def running_linux(): + return sys.platform.startswith('linux') + +def running_windows(): + return sys.platform.startswith('win') def get_file_list_dict(): """ @@ -86,12 +51,12 @@ def get_file_list_dict(): :return: Dictionary of demo files :rtype: Dict[str:str] """ - python_only = not sg.user_settings_get_entry('-show all files-', False) + demo_path = get_demo_path() demo_files_dict = {} for dirname, dirnames, filenames in os.walk(demo_path): for filename in filenames: - if python_only is not True or filename.endswith('.py') or filename.endswith('.pyw'): + if filename.endswith('.py') or filename.endswith('.pyw'): fname_full = os.path.join(dirname, filename) if filename not in demo_files_dict.keys(): demo_files_dict[filename] = fname_full @@ -117,18 +82,6 @@ def get_file_list(): return sorted(list(get_file_list_dict().keys())) -def get_file_list_full_filename(): - """ - Returns list of filenames of files to display - No path is shown, only the short filename - - :return: List of filenames - :rtype: List[str] - """ - return sorted(list(get_file_list_dict().values())) - - - def get_demo_path(): """ Get the top-level folder path @@ -200,7 +153,7 @@ def advanced_mode(): :return: True if user indicated wants the advanced GUI to be shown (set in the settings window) :rtype: bool """ - return sg.user_settings_get_entry('-advanced mode-', True) + return sg.user_settings_get_entry('-advanced mode-', False) @@ -238,138 +191,6 @@ def get_line_number(file_path, string, dupe_lines): def kill_ascii(s): return "".join([x if ord(x) < 128 else '?' for x in s]) -''' -MM'""""'YMM dP dP -M' .mmm. `M 88 88 -M MMMMMooM 88d888b. .d8888b. .d8888b. 88 .dP -M MMMMMMMM 88' `88 88ooood8 88' `"" 88888" -M. `MMM' .M 88 88 88. ... 88. ... 88 `8b. -MM. .dM dP dP `88888P' `88888P' dP `YP -MMMMMMMMMMM - -M""M dP -M M 88 -M M 88d8b.d8b. 88d888b. .d8888b. 88d888b. d8888P .d8888b. -M M 88'`88'`88 88' `88 88' `88 88' `88 88 Y8ooooo. -M M 88 88 88 88. .88 88. .88 88 88 88 -M M dP dP dP 88Y888P' `88888P' dP dP `88888P' -MMMM 88 - dP -''' - - -def offer_install(module): - if sg.popup_yes_no(f'The program failed to import a package. You need to install {module}.', 'Would you like PySimpleGUI to install this package for you?', - title=f'Package {module} not found') != 'Yes': - return False - if module in packages_with_weird_names.keys(): - module = packages_with_weird_names[module] - try: - sg.execute_pip_install_package(module) - sg.cprint(f'Module {module} successfully installed.', colors='white on green') - sg.popup('Restarting your application to reload the modules...', auto_close_duration=2, auto_close=True) - sg.execute_command_subprocess(sys.executable, __file__, pipe_output=False, wait=False) - exit() - return True - except Exception as e: - sg.popup('Error performing the pip install. You may need a newer version of PySimpleGUI.', e) - # pip_install_latest(package) - # sg.popup('Restarting your application...', auto_close_duration=2, auto_close=True) - # sg.execute_command_subprocess(sys.executable, __file__, pipe_output=False, wait=False) - return False - -def check_module(module): - try: - __import__(module) - # print(f'{module} passed') - return True - except ImportError: - sg.cprint(f'Module {module} not found.', colors='white on red') - if offer_install(module): - return True - return False - - -def check_modules_on_import_line(line:str): - modules = line.split(' ', 1)[1].split(',') - # print(f'modules = {modules}') - for module in modules: - if ' as ' in module: - module = module.split('as')[0].strip() - if '.' in module: - module = module.split('.')[0].strip() - # print(f'checking "{module}"') - if not check_module(module): - return False - - return True - - - - -def check_imports_in_file(filename): - # Check if the file exists - if not os.path.exists(filename): - print("File does not exist") - return False - all_passed = True - # Open the file - file = open(filename, 'r', encoding='utf-8') - lines = file.readlines() - # Read the file line by line - for line in lines: - # print(line) - # Check if the line is an import statement - sline = line.strip() # strip the line in case it's indented - if sline.startswith('import'): - # Check if the module exists - if not check_modules_on_import_line(sline): - all_passed = False - elif sline.startswith('from') and 'import' in sline: - module = re.search(r'from (\w+)', sline).group(1) - if not check_module(module): - all_passed = False - # Close the file - file.close() - return all_passed - -''' -MM""""""""`M oo dP -MM mmmmmmmM 88 -M' MMMM dP 88 .d8888b. -MM MMMMMMMM 88 88 88ooood8 -MM MMMMMMMM 88 88 88. ... -MM MMMMMMMM dP dP `88888P' -MMMMMMMMMMMM - -MP""""""`MM dP -M mmmmm..M 88 -M. `YM .d8888b. .d8888b. 88d888b. .d8888b. 88d888b. -MMMMMMM. M 88ooood8 88' `88 88' `88 88' `"" 88' `88 -M. .MMM' M 88. ... 88. .88 88 88. ... 88 88 -Mb. .dM `88888P' `88888P8 dP `88888P' dP dP -MMMMMMMMMMM -''' - - - -# def search_files(file_list, search_string): -# found_list = [] -# for file in file_list: -# with open(file, 'r') as f: -# # Memory-map the file -# try: -# mmapped_file = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) -# except: -# continue -# # Search for the string in the file -# if mmapped_file.find(bytes(search_string, 'utf-8')) != -1: -# # print(f"String found in file: {file}") -# found_list.append(os.path.basename(file)) -# # else: -# # print(f"String not found in file: {file}") -# return found_list - def find_in_file(string, demo_files_dict, regex=False, verbose=False, window=None, ignore_case=True, show_first_match=True): """ Search through the demo files for a string. @@ -411,7 +232,7 @@ def find_in_file(string, demo_files_dict, regex=False, verbose=False, window=Non matches = None with open(full_filename, 'rb', 0) as f, mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) as s: - if regex: + if (regex): window['-FIND NUMBER-'].update(f'{num_files} files') window.refresh() matches = re.finditer(bytes("^.*(" + string + ").*$", 'utf-8'), s, re.MULTILINE) @@ -428,13 +249,13 @@ def find_in_file(string, demo_files_dict, regex=False, verbose=False, window=Non window['-FIND NUMBER-'].update(f'{num_files} files') window.refresh() matches = None - if ignore_case: - if show_first_match: + if (ignore_case): + if (show_first_match): matches = re.search(br'(?i)^' + bytes(".*("+re.escape(string.lower()) + ").*$", 'utf-8'), s, re.MULTILINE) else: matches = re.finditer(br'(?i)^' + bytes(".*("+re.escape(string.lower()) + ").*$", 'utf-8'), s, re.MULTILINE) else: - if show_first_match: + if (show_first_match): matches = re.search(br'^' + bytes(".*("+re.escape(string) + ").*$", 'utf-8'), s, re.MULTILINE) else: matches = re.finditer(br'^' + bytes(".*("+re.escape(string) + ").*$", 'utf-8'), s, re.MULTILINE) @@ -490,7 +311,7 @@ def find_in_file(string, demo_files_dict, regex=False, verbose=False, window=Non file_match_list = [] - if verbose: + if (verbose): sg.cprint(f"{tail}:", c='white on green') try: dupe_lines = [] @@ -499,7 +320,7 @@ def find_in_file(string, demo_files_dict, regex=False, verbose=False, window=Non dupe_lines.append(line_num_match) file_array_new.append(line_num_match) file_match_list.append(_match) # I *really* overthinked this. - if verbose: + if (verbose): sg.cprint(f"Line: {line_num_match} ", c='white on purple', end='') sg.cprint(f"{_match.strip()}\n") # Make a list of the matches found in this file to add to the dictionry @@ -507,7 +328,7 @@ def find_in_file(string, demo_files_dict, regex=False, verbose=False, window=Non file_array_old.append(file_array_new) file_array_old.append(file_match_list) - if tail in file_lines_dict: + if (tail in file_lines_dict): for i in range(1, 100): new_tail = f'{tail}_{i}' if new_tail not in file_lines_dict: @@ -550,25 +371,6 @@ def window_choose_line_to_edit(filename, full_filename, line_num_list, match_li window.close() return full_filename, line_chosen -''' -MP""""""`MM dP dP oo -M mmmmm..M 88 88 -M. `YM .d8888b. d8888P d8888P dP 88d888b. .d8888b. .d8888b. -MMMMMMM. M 88ooood8 88 88 88 88' `88 88' `88 Y8ooooo. -M. .MMM' M 88. ... 88 88 88 88 88 88. .88 88 -Mb. .dM `88888P' dP dP dP dP dP `8888P88 `88888P' -MMMMMMMMMMM .88 - d8888P -M""MMM""MMM""M oo dP -M MMM MMM M 88 -M MMP MMP M dP 88d888b. .d888b88 .d8888b. dP dP dP -M MM' MM' .M 88 88' `88 88' `88 88' `88 88 88 88 -M `' . '' .MM 88 88 88 88. .88 88. .88 88.88b.88' -M .d .dMMM dP dP dP `88888P8 `88888P' 8888P Y8P -MMMMMMMMMMMMMM - -''' - def settings_window(): """ @@ -607,7 +409,6 @@ def settings_window(): [sg.T('Leave blank to use global default'), sg.T(global_theme)], [sg.Combo(['']+sg.theme_list(),sg.user_settings_get_entry('-theme-', ''), readonly=True, k='-THEME-')], [sg.T('Double-click a File Will:'), sg.R('Run', 2, sg.user_settings_get_entry('-dclick runs-', False), k='-DCLICK RUNS-'), sg.R('Edit', 2, sg.user_settings_get_entry('-dclick edits-', False), k='-DCLICK EDITS-'), sg.R('Nothing', 2, sg.user_settings_get_entry('-dclick none-', False), k='-DCLICK NONE-')], - [sg.CB('Check That Imported Modules Are Installed', sg.user_settings_get_entry('-check imports-', False), k='-CHECK IMPORTS-')], [sg.CB('Use Advanced Interface', default=advanced_mode() ,k='-ADVANCED MODE-')], [sg.B('Ok', bind_return_key=True), sg.B('Cancel')], ] @@ -630,7 +431,6 @@ def settings_window(): sg.user_settings_set_entry('-dclick runs-', values['-DCLICK RUNS-']) sg.user_settings_set_entry('-dclick edits-', values['-DCLICK EDITS-']) sg.user_settings_set_entry('-dclick nothing-', values['-DCLICK NONE-']) - sg.user_settings_set_entry('-check imports-', values['-CHECK IMPORTS-']) settings_changed = True break elif event == 'Clear History': @@ -641,26 +441,6 @@ def settings_window(): window.close() return settings_changed - - -''' -M"""""`'"""`YM oo -M mm. mm. M -M MMM MMM M .d8888b. dP 88d888b. -M MMM MMM M 88' `88 88 88' `88 -M MMM MMM M 88. .88 88 88 88 -M MMM MMM M `88888P8 dP dP dP -MMMMMMMMMMMMMM - -M""MMM""MMM""M oo dP -M MMM MMM M 88 -M MMP MMP M dP 88d888b. .d888b88 .d8888b. dP dP dP -M MM' MM' .M 88 88' `88 88' `88 88' `88 88 88 88 -M `' . '' .MM 88 88 88 88. .88 88. .88 88.88b.88' -M .d .dMMM dP dP dP `88888P8 `88888P' 8888P Y8P -MMMMMMMMMMMMMM -''' - ML_KEY = '-ML-' # Multline's key # --------------------------------- Create the window --------------------------------- @@ -679,36 +459,32 @@ def make_window(): find_tooltip = "Find in file\nEnter a string in box to search for string inside of the files.\nFile list will update with list of files string found inside." filter_tooltip = "Filter files\nEnter a string in box to narrow down the list of files.\nFile list will update with list of files with string in filename." find_re_tooltip = "Find in file using Regular Expression\nEnter a string in box to search for string inside of the files.\nSearch is performed after clicking the FindRE button." - run_tooltip = "Run any python file\nEnter full absolute path and then click RUN button." left_col = sg.Column([ - [sg.Listbox(values=get_file_list(), select_mode=sg.SELECT_MODE_EXTENDED, size=(50,20), bind_return_key=True, key='-DEMO LIST-', expand_x=True, expand_y=True)], - [sg.Text('Filter (F1):', tooltip=filter_tooltip, s=8), sg.Input(size=(25, 1), focus=True, enable_events=True, key='-FILTER-', tooltip=filter_tooltip), + [sg.Listbox(values=get_file_list(), select_mode=sg.SELECT_MODE_EXTENDED, size=(50,20), bind_return_key=True, key='-DEMO LIST-')], + [sg.Text('Filter (F1):', tooltip=filter_tooltip), sg.Input(size=(25, 1), focus=True, enable_events=True, key='-FILTER-', tooltip=filter_tooltip), sg.T(size=(15,1), k='-FILTER NUMBER-')], [sg.Button('Run'), sg.B('Edit'), sg.B('Clear'), sg.B('Open Folder'), sg.B('Copy Path')], - [sg.Text('Find (F2):', tooltip=find_tooltip, s=8), sg.Input(size=(25, 1), enable_events=True, key='-FIND-', tooltip=find_tooltip), + [sg.Text('Find (F2):', tooltip=find_tooltip), sg.Input(size=(25, 1), enable_events=True, key='-FIND-', tooltip=find_tooltip), sg.T(size=(15,1), k='-FIND NUMBER-')], - [sg.Text('Path (F3):', tooltip=run_tooltip, s=8), sg.Input(size=(25, 1), enable_events=True, key='-RUN PATH-', tooltip=run_tooltip)], ], element_justification='l', expand_x=True, expand_y=True) lef_col_find_re = sg.pin(sg.Col([ - [sg.Text('Find (F4):', tooltip=find_re_tooltip, s=8), sg.Input(size=(25, 1),key='-FIND RE-', tooltip=find_re_tooltip),sg.B('Find RE')]], k='-RE COL-')) + [sg.Text('Find (F3):', tooltip=find_re_tooltip), sg.Input(size=(25, 1),key='-FIND RE-', tooltip=find_re_tooltip),sg.B('Find RE')]], k='-RE COL-')) right_col = [ - [sg.Multiline(size=(70, 21), write_only=True, expand_x=True, expand_y=True, key=ML_KEY, reroute_stdout=True, echo_stdout_stderr=True, reroute_cprint=True)], - [sg.B('Settings'), sg.Button('Exit')], - [sg.T('Demo Browser Ver ' + version)], + [sg.Multiline(size=(70, 21), write_only=True, key=ML_KEY, reroute_stdout=True, echo_stdout_stderr=True, reroute_cprint=True)], + [sg.Button('Edit Me (this program)'), sg.B('Settings'), sg.Button('Exit')], [sg.T('PySimpleGUI ver ' + sg.version.split(' ')[0] + ' tkinter ver ' + sg.tclversion_detailed, font='Default 8', pad=(0,0))], [sg.T('Python ver ' + sys.version, font='Default 8', pad=(0,0))], - [sg.T('Interpreter ' + sg.execute_py_get_interpreter(), font='Default 8', pad=(0,0))], + [sg.T('Interpreter ' + execute_py_get_interpreter(), font='Default 8', pad=(0,0))], ] - options_at_bottom = sg.pin(sg.Column([[sg.CB('Verbose', enable_events=True, k='-VERBOSE-', tooltip='Enable to see the matches in the right hand column'), - sg.CB('Show only first match in file', default=True, enable_events=True, k='-FIRST MATCH ONLY-', tooltip='Disable to see ALL matches found in files'), + options_at_bottom = sg.pin(sg.Column([[sg.CB('Verbose', enable_events=True, k='-VERBOSE-'), + sg.CB('Show only first match in file', default=True, enable_events=True, k='-FIRST MATCH ONLY-'), sg.CB('Find ignore case', default=True, enable_events=True, k='-IGNORE CASE-'), - sg.CB('Wait for Runs to Complete', default=False, enable_events=True, k='-WAIT-'), - sg.CB('Show ALL file types', default=sg.user_settings_get_entry('-show all files-', False), enable_events=True, k='-SHOW ALL FILES-'), + sg.CB('Wait for Runs to Complete', default=False, enable_events=True, k='-WAIT-') ]], pad=(0,0), k='-OPTIONS BOTTOM-', expand_x=True, expand_y=False), expand_x=True, expand_y=False) @@ -719,165 +495,30 @@ def make_window(): layout = [[sg.Text('PySimpleGUI Demo Program & Project Browser', font='Any 20')], [choose_folder_at_top], # [sg.Column([[left_col],[ lef_col_find_re]], element_justification='l', expand_x=True, expand_y=True), sg.Column(right_col, element_justification='c', expand_x=True, expand_y=True)], - [sg.Pane([sg.Column([[left_col],[ lef_col_find_re]], element_justification='l', expand_x=True, expand_y=True), sg.Column(right_col, element_justification='c', expand_x=True, expand_y=True) ], orientation='h', relief=sg.RELIEF_SUNKEN, expand_x=True, expand_y=True, k='-PANE-')], - [options_at_bottom, sg.Sizegrip()]] + [sg.Pane([sg.Column([[left_col],[ lef_col_find_re]], element_justification='l', expand_x=True, expand_y=True), sg.Column(right_col, element_justification='c', expand_x=True, expand_y=True) ], orientation='h', relief=sg.RELIEF_SUNKEN, k='-PANE-')], + [options_at_bottom]] # --------------------------------- Create Window --------------------------------- - window = sg.Window('PSG Demo & Project Browser', layout, finalize=True, resizable=True, use_default_focus=False, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT, auto_save_location=True) + window = sg.Window('PSG Demo & Project Browser', layout, finalize=True, icon=icon, resizable=True, use_default_focus=False) window.set_min_size(window.size) - - # window.bind("", 'Exit') # matches the underscore shown on the Exit button (For now disabled this feature until buttons with underscore released to PyPI) + window['-DEMO LIST-'].expand(True, True, True) + window[ML_KEY].expand(True, True, True) + window['-PANE-'].expand(True, True, True) window.bind('', '-FOCUS FILTER-') window.bind('', '-FOCUS FIND-') - window.bind('', '-FOCUS RUN PATH-') - window.bind('', '-FOCUS RE FIND-') + window.bind('', '-FOCUS RE FIND-') if not advanced_mode(): window['-FOLDER CHOOSE-'].update(visible=False) window['-RE COL-'].update(visible=False) window['-OPTIONS BOTTOM-'].update(visible=False) + # sg.cprint_set_output_destination(window, ML_KEY) window.bring_to_front() return window -''' -M""M dP dP dP -M M 88 88 88 -M M 88d888b. .d8888b. d8888P .d8888b. 88 88 .d8888b. 88d888b. -M M 88' `88 Y8ooooo. 88 88' `88 88 88 88ooood8 88' `88 -M M 88 88 88 88 88. .88 88 88 88. ... 88 -M M dP dP `88888P' dP `88888P8 dP dP `88888P' dP -MMMM -''' - - -def pip_install_thread(window, sp): - window.write_event_value('-THREAD-', (sp, 'Install thread started')) - for line in sp.stdout: - oline = line.decode().rstrip() - window.write_event_value('-THREAD-', (sp, oline)) - - - -def pip_install_latest(): - - pip_command = '-m pip install --upgrade --no-cache-dir PySimpleGUI>=5' - - python_command = sys.executable # always use the currently running interpreter to perform the pip! - if 'pythonw' in python_command: - python_command = python_command.replace('pythonw', 'python') - - layout = [[sg.Text('Installing PySimpleGUI', font='_ 14')], - [sg.Multiline(s=(90, 15), k='-MLINE-', reroute_cprint=True, reroute_stdout=True, echo_stdout_stderr=True, write_only=True, expand_x=True, expand_y=True)], - [sg.Push(), sg.Button('Downloading...', k='-EXIT-'), sg.Sizegrip()]] - - window = sg.Window('Pip Install PySimpleGUI Utilities', layout, finalize=True, keep_on_top=True, modal=True, disable_close=True, resizable=True) - - window.disable_debugger() - - sg.cprint('Installing with the Python interpreter =', python_command, c='white on purple') - - sp = sg.execute_command_subprocess(python_command, pip_command, pipe_output=True, wait=False) - - window.start_thread(lambda: pip_install_thread(window, sp), end_key='-THREAD DONE-') - - while True: - event, values = window.read() - if event == sg.WIN_CLOSED or (event == '-EXIT-' and window['-EXIT-'].ButtonText == 'Done'): - break - elif event == '-THREAD DONE-': - sg.cprint('\n') - show_package_version('PySimpleGUI') - sg.cprint('Done Installing PySimpleGUI. Click Done and the program will restart.', c='white on red', font='default 12 italic') - window['-EXIT-'].update(text='Done', button_color='white on red') - elif event == '-THREAD-': - sg.cprint(values['-THREAD-'][1]) - - window.close() - -def suggest_upgrade_gui(): - layout = [[sg.Image(sg.EMOJI_BASE64_HAPPY_GASP), sg.Text(f'PySimpleGUI 5+ Required', font='_ 15 bold')], - [sg.Text(f'PySimpleGUI 5+ required for this program to function correctly.')], - [sg.Text(f'You are running PySimpleGUI {sg.version}')], - [sg.Text('Would you like to upgrade to the latest version of PySimpleGUI now?')], - [sg.Push(), sg.Button('Upgrade', size=8, k='-UPGRADE-'), sg.Button('Cancel', size=8)]] - - window = sg.Window(title=f'Newer version of PySimpleGUI required', layout=layout, font='_ 12') - - while True: - event, values = window.read() - - if event in (sg.WIN_CLOSED, 'Cancel'): - window.close() - break - elif event == '-UPGRADE-': - window.close() - pip_install_latest() - sg.execute_command_subprocess(sys.executable, __file__, pipe_output=True, wait=False) - break - - -def make_str_pre_38(package): - return f""" -import warnings -warnings.filterwarnings("ignore", category=DeprecationWarning) -import pkg_resources -try: - ver=pkg_resources.get_distribution("{package}").version.rstrip() -except: - ver=' ' -print(ver, end='') -""" - -def make_str(package): - return f""" -import importlib.metadata - -try: - ver = importlib.metadata.version("{package}") -except importlib.metadata.PackageNotFoundError: - ver = ' ' -print(ver, end='') -""" - - -def show_package_version(package): - """ - Function that shows all versions of a package - """ - interpreter = sg.execute_py_get_interpreter() - sg.cprint(f'{package} upgraded to ', end='', c='red') - # print(f'{interpreter}') - if sys.version_info.major == 3 and sys.version_info.minor in (6, 7): # if running Python version 3.6 or 3.7 - pstr = make_str_pre_38(package) - else: - pstr = make_str(package) - temp_file = os.path.join(os.path.dirname(__file__), 'temp_py.py') - with open(temp_file, 'w') as file: - file.write(pstr) - sg.execute_py_file(temp_file, interpreter_command=interpreter, pipe_output=True, wait=True) - os.remove(temp_file) - - - -def upgrade_check(): - if not sg.version.startswith('5'): - suggest_upgrade_gui() - exit() - - - -''' -M"""""`'"""`YM oo -M mm. mm. M -M MMM MMM M .d8888b. dP 88d888b. -M MMM MMM M 88' `88 88 88' `88 -M MMM MMM M 88. .88 88 88 88 -M MMM MMM M `88888P8 dP dP dP -MMMMMMMMMMMMMM -''' # --------------------------------- Main Program Layout --------------------------------- def main(): @@ -886,11 +527,6 @@ def main(): It will call the make_window function to create the window. """ - sg.user_settings_filename(filename='psgdemos.json') - upgrade_check() - - sg.user_settings_filename('psgdemos.json') - sg.set_options(icon=sg.EMOJI_BASE64_HAPPY_IDEA) find_in_file.file_list_dict = None old_typed_value = None @@ -900,7 +536,6 @@ def main(): window = make_window() window['-FILTER NUMBER-'].update(f'{len(file_list)} files') window.force_focus() - window['-FILTER-'].set_focus() counter = 0 while True: event, values = window.read() @@ -925,88 +560,61 @@ def main(): sg.cprint(f'Editing using {editor_program}', c='white on red', end='') sg.cprint('') sg.cprint(f'{full_filename}', c='white on purple') - if not get_editor(): - sg.popup_error_with_traceback('No editor has been configured', 'You need to configure an editor in order to use this feature', 'You can configure the editor in the Demo Brower Settings or the PySimpleGUI Global Settings') + # if line != 1: + if using_local_editor(): + execute_command_subprocess(editor_program, full_filename) else: - if using_local_editor(): - sg.execute_command_subprocess(editor_program, f'"{full_filename}"') - else: - try: - sg.execute_editor(full_filename, line_number=int(line)) - except: - sg.execute_command_subprocess(editor_program, f'"{full_filename}"') + try: + sg.execute_editor(full_filename, line_number=int(line)) + except: + execute_command_subprocess(editor_program, full_filename) + # else: + # sg.execute_editor(full_filename) else: sg.cprint('Editing canceled') elif event == 'Run': sg.cprint('Running....', c='white on green', end='') sg.cprint('') - if values['-RUN PATH-']: # if a manual file was entered: - files_to_run = (values['-RUN PATH-'],) - else: - files_to_run = values['-DEMO LIST-'] - # for file in values['-DEMO LIST-']: - for file in files_to_run: + for file in values['-DEMO LIST-']: + file_to_run = str(file_list_dict[file]) + sg.cprint(file_to_run,text_color='white', background_color='purple') try: - file_to_run = str(file_list_dict[file]) - except: - file_to_run = file - # sg.cprint('Checking Imports....', c='white on green') - if sg.user_settings_get_entry('-check imports-', False) and not check_imports_in_file(file_to_run): - sg.cprint(f'The demo program {os.path.basename(file_to_run)} depends on modules that are not installed.') - else: - sg.cprint(file_to_run,text_color='white', background_color='purple') - try: - sp = sg.execute_py_file(file_to_run, pipe_output=values['-WAIT-']) - except Exception as e: - sg.cprint(f'Error trying to run python file. Error info:', e, c='white on red') - try: - if values['-WAIT-']: - sg.cprint(f'Waiting on results..', text_color='white', background_color='red', end='') - while True: - results = sg.execute_get_results(sp) - sg.cprint(f'STDOUT:', text_color='white', background_color='green') - sg.cprint(results[0]) - sg.cprint(f'STDERR:', text_color='white', background_color='green') - sg.cprint(results[1]) - if not sg.execute_subprocess_still_running(sp): - break - except AttributeError: - sg.cprint('Your version of PySimpleGUI needs to be upgraded to fully use the "WAIT" feature.', c='white on red') + sp = execute_py_file(file_to_run, pipe_output=values['-WAIT-']) + except TypeError: + sg.cprint('Consider upgrading to a newer PySimpleGUI.... 4.37.0 has better execution controls', c='white on red') + sp = execute_py_file_with_pipe_output(f'{file_to_run}', pipe_output=values['-WAIT-']) + try: + if values['-WAIT-']: + sg.cprint(f'Waiting on results..', text_color='white', background_color='red', end='') + while True: + results = sg.execute_get_results(sp) + sg.cprint(f'STDOUT:', text_color='white', background_color='green') + sg.cprint(results[0]) + sg.cprint(f'STDERR:', text_color='white', background_color='green') + sg.cprint(results[1]) + if not sg.execute_subprocess_still_running(sp): + break + except AttributeError: + sg.cprint('Your version of PySimpleGUI needs to be upgraded to fully use the "WAIT" feature.', c='white on red') elif event.startswith('Edit Me'): editor_program = get_editor() sg.cprint(f'opening using {editor_program}:') sg.cprint(f'{__file__}', text_color='white', background_color='red', end='') - sg.execute_command_subprocess(f'{editor_program}', f'"{__file__}"') + execute_command_subprocess(f'{editor_program}', f'"{__file__}"') elif event == '-FILTER-': new_list = [i for i in file_list if values['-FILTER-'].lower() in i.lower()] window['-DEMO LIST-'].update(new_list) window['-FILTER NUMBER-'].update(f'{len(new_list)} files') window['-FIND NUMBER-'].update('') window['-FIND-'].update('') - window['-RUN PATH-'].update('') window['-FIND RE-'].update('') - elif event == '-RUN PATH-': - file_list = get_file_list() - window['-FILTER-'].update('') - window['-FILTER NUMBER-'].update(f'{len(file_list)} files') - window['-FIND-'].update('') - window['-DEMO LIST-'].update(file_list) - window['-FIND NUMBER-'].update('') - window['-FIND RE-'].update('') - window['-ML-'].update('') elif event == '-FOCUS FIND-': window['-FIND-'].set_focus() elif event == '-FOCUS FILTER-': window['-FILTER-'].set_focus() elif event == '-FOCUS RE FIND-': window['-FIND RE-'].set_focus() - elif event == '-FOCUS RUN PATH-': - window['-RUN PATH-'].set_focus() elif event == '-FIND-' or event == '-FIRST MATCH ONLY-' or event == '-VERBOSE-' or event == '-FIND RE-': - # file_list = (search_files(get_file_list_full_filename(), values['-FIND-'])) - # window['-DEMO LIST-'].update(file_list) - # continue - is_ignore_case = values['-IGNORE CASE-'] old_ignore_case = False current_typed_value = str(values['-FIND-']) @@ -1032,7 +640,6 @@ def main(): window['-FILTER NUMBER-'].update('') window['-FIND RE-'].update('') window['-FILTER-'].update('') - window['-RUN PATH-'].update('') elif values['-FIND RE-']: window['-ML-'].update('') file_list = find_in_file(values['-FIND RE-'], get_file_list_dict(), regex=True, verbose=values['-VERBOSE-'],window=window) @@ -1041,7 +648,6 @@ def main(): window['-FILTER NUMBER-'].update('') window['-FIND-'].update('') window['-FILTER-'].update('') - window['-RUN PATH-'].update('') elif event == 'Find RE': window['-ML-'].update('') file_list = find_in_file(values['-FIND RE-'], get_file_list_dict(), regex=True, verbose=values['-VERBOSE-'],window=window) @@ -1050,7 +656,6 @@ def main(): window['-FILTER NUMBER-'].update('') window['-FIND-'].update('') window['-FILTER-'].update('') - window['-RUN PATH-'].update('') sg.cprint('Regular expression find completed') elif event == 'Settings': if settings_window() is True: @@ -1067,7 +672,6 @@ def main(): window['-DEMO LIST-'].update(file_list) window['-FIND NUMBER-'].update('') window['-FIND RE-'].update('') - window['-RUN PATH-'].update('') window['-ML-'].update('') elif event == '-FOLDERNAME-': sg.user_settings_set_entry('-demos folder-', values['-FOLDERNAME-']) @@ -1080,7 +684,6 @@ def main(): window['-FIND-'].update('') window['-FIND RE-'].update('') window['-FILTER-'].update('') - window['-RUN PATH-'].update('') elif event == 'Open Folder': explorer_program = get_explorer() if explorer_program: @@ -1089,10 +692,10 @@ def main(): for file in values['-DEMO LIST-']: file_selected = str(file_list_dict[file]) file_path = os.path.dirname(file_selected) - if sg.running_windows(): + if running_windows(): file_path = file_path.replace('/', '\\') sg.cprint(file_path, text_color='white', background_color='purple') - sg.execute_command_subprocess(explorer_program, file_path) + execute_command_subprocess(explorer_program, file_path) elif event == 'Copy Path': for file in values['-DEMO LIST-']: sg.cprint('Copying the last highlighted filename in your list') @@ -1103,27 +706,185 @@ def main(): if line is not None: sg.cprint(f'Added to Clipboard Full Path {full_filename}', c='white on purple') sg.clipboard_set(full_filename) - elif event == 'Version': - sg.popup_scrolled(sg.get_versions(), f'This Program: {__file__}' ,keep_on_top=True, non_blocking=True) - elif event == '-SHOW ALL FILES-': - sg.user_settings_set_entry('-show all files-', values[event]) - file_list_dict = get_file_list_dict() - file_list = get_file_list() - window['-DEMO LIST-'].update(values=file_list) - window['-FILTER NUMBER-'].update(f'{len(file_list)} files') - window['-ML-'].update('') - window['-FIND NUMBER-'].update('') - window['-FIND-'].update('') - window['-FIND RE-'].update('') - window['-FILTER-'].update('') - window['-RUN PATH-'].update('') + window.close() +# +# .########.##.....##.########..######......######.....###....##.......##........######. +# .##........##...##..##.......##....##....##....##...##.##...##.......##.......##....## +# .##.........##.##...##.......##..........##........##...##..##.......##.......##...... +# .######......###....######...##..........##.......##.....##.##.......##........######. +# .##.........##.##...##.......##..........##.......#########.##.......##.............## +# .##........##...##..##.......##....##....##....##.##.....##.##.......##.......##....## +# .########.##.....##.########..######......######..##.....##.########.########..######. +# +# .##....##..#######..########..##.....##....###....##.......##.......##....## +# .###...##.##.....##.##.....##.###...###...##.##...##.......##........##..##. +# .####..##.##.....##.##.....##.####.####..##...##..##.......##.........####.. +# .##.##.##.##.....##.########..##.###.##.##.....##.##.......##..........##... +# .##..####.##.....##.##...##...##.....##.#########.##.......##..........##... +# .##...###.##.....##.##....##..##.....##.##.....##.##.......##..........##... +# .##....##..#######..##.....##.##.....##.##.....##.########.########....##... +# +# .########..########...#######..##.....##.####.########..########.########. +# .##.....##.##.....##.##.....##.##.....##..##..##.....##.##.......##.....## +# .##.....##.##.....##.##.....##.##.....##..##..##.....##.##.......##.....## +# .########..########..##.....##.##.....##..##..##.....##.######...##.....## +# .##........##...##...##.....##..##...##...##..##.....##.##.......##.....## +# .##........##....##..##.....##...##.##....##..##.....##.##.......##.....## +# .##........##.....##..#######.....###....####.########..########.########. +# +# .########..##....##....########...######...######.. +# .##.....##..##..##.....##.....##.##....##.##....##. +# .##.....##...####......##.....##.##.......##....... +# .########.....##.......########...######..##...#### +# .##.....##....##.......##..............##.##....##. +# .##.....##....##.......##........##....##.##....##. +# .########.....##.......##.........######...######.. + + + +def execute_py_file_with_pipe_output(pyfile, parms=None, cwd=None, interpreter_command=None, wait=False, pipe_output=False): + """ + Executes a Python file. + The interpreter to use is chosen based on this priority order: + 1. interpreter_command paramter + 2. global setting "-python command-" + 3. the interpreter running running PySimpleGUI + :param pyfile: the file to run + :type pyfile: (str) + :param parms: parameters to pass on the command line + :type parms: (str) + :param cwd: the working directory to use + :type cwd: (str) + :param interpreter_command: the command used to invoke the Python interpreter + :type interpreter_command: (str) + :param wait: the working directory to use + :type wait: (bool) + :param pipe_output: If True then output from the subprocess will be piped. You MUST empty the pipe by calling execute_get_results or your subprocess will block until no longer full + :type pipe_output: (bool) + :return: Popen object + :rtype: (subprocess.Popen) | None + """ + + if pyfile[0] != '"' and ' ' in pyfile: + pyfile = '"'+pyfile+'"' + try: + if interpreter_command is not None: + python_program = interpreter_command + else: + python_program = sg.pysimplegui_user_settings.get('-python command-', '') + except: + python_program = '' + + if python_program == '': + python_program = 'python' if sys.platform.startswith('win') else 'python3' + if parms is not None and python_program: + sp = execute_command_subprocess_with_pipe_output(python_program, pyfile, parms, wait=wait, cwd=cwd, pipe_output=pipe_output) + elif python_program: + sp = execute_command_subprocess_with_pipe_output(python_program, pyfile, wait=wait, cwd=cwd, pipe_output=pipe_output) + else: + print('execute_py_file - No interpreter has been configured') + sp = None + return sp + + +def execute_command_subprocess_with_pipe_output(command, *args, wait=False, cwd=None, pipe_output=False): + """ + Runs the specified command as a subprocess. + By default the call is non-blocking. + The function will immediately return without waiting for the process to complete running. You can use the returned Popen object to communicate with the subprocess and get the results. + Returns a subprocess Popen object. + + :param command: Filename to load settings from (and save to in the future) + :type command: (str) + :param *args: Variable number of arguments that are passed to the program being started as command line parms + :type *args: (Any) + :param wait: If True then wait for the subprocess to finish + :type wait: (bool) + :param cwd: Working directory to use when executing the subprocess + :type cwd: (str)) + :param pipe_output: If True then output from the subprocess will be piped. You MUST empty the pipe by calling execute_get_results or your subprocess will block until no longer full + :type pipe_output: (bool) + :return: Popen object + :rtype: (subprocess.Popen) + """ + try: + if args is not None: + expanded_args = ' '.join(args) + # print('executing subprocess command:',command, 'args:',expanded_args) + if command[0] != '"' and ' ' in command: + command = '"'+command+'"' + # print('calling popen with:', command +' '+ expanded_args) + # sp = subprocess.Popen(command +' '+ expanded_args, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, cwd=cwd) + if pipe_output: + sp = subprocess.Popen(command +' '+ expanded_args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd) + else: + sp = subprocess.Popen(command +' '+ expanded_args, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, cwd=cwd) + else: + sp = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd) + if wait: + out, err = sp.communicate() + if out: + print(out.decode("utf-8")) + if err: + print(err.decode("utf-8")) + except Exception as e: + print('** Error executing subprocess **', 'Command:', command) + print('error:', e) + sp = None + return sp + + +def execute_py_get_interpreter(): + """ + Returns the command that was specified in the global options that will be used to execute Python files + when the execute_py_file function is called. + :return: Full path to python interpreter or '' if nothing entered + :rtype: (str) + """ + + return sg.pysimplegui_user_settings.get('-python command-', '') + + +# Normally you want to use the PySimpleGUI version of these functions +try: + execute_py_file = sg.execute_py_file +except: + execute_py_file = execute_py_file_with_pipe_output + +try: + execute_py_get_interpreter = sg.execute_py_get_interpreter +except: + execute_py_get_interpreter = execute_py_get_interpreter + + +try: + execute_command_subprocess = sg.execute_command_subprocess +except: + execute_command_subprocess = execute_command_subprocess_with_pipe_output if __name__ == '__main__': + # https://www.vecteezy.com/free-vector/idea-bulb is where I got the icon + icon = b'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsSAAALEgHS3X78AAAK/2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4NCjx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDA3IDEuMTM2ODgxLCAyMDEwLzA2LzEwLTE4OjExOjM1ICAgICAgICAiPg0KICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPg0KICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1wTU06RG9jdW1lbnRJRD0iRUM4REZFNUEyMEM0QjcwMzFBMjNBRDA4NENCNzZCODAiIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0iRUM4REZFNUEyMEM0QjcwMzFBMjNBRDA4NENCNzZCODAiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OUVBNkIyNzA3NjYyRTkxMThDQzNFODdFN0ZEQTgwNTEiIGRjOmZvcm1hdD0iaW1hZ2UvanBlZyIgeG1wOlJhdGluZz0iNSIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAxOS0wNC0xOVQxMjoxMTozOSswNDozMCI+DQogICAgICA8eG1wTU06SGlzdG9yeT4NCiAgICAgICAgPHJkZjpTZXE+DQogICAgICAgICAgPHJkZjpsaSBzdEV2dDphY3Rpb249InNhdmVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOkYwNjRBQzcwNzY2MkU5MTFBNkU1QzYwODhFRTUxMzM5IiBzdEV2dDp3aGVuPSIyMDE5LTA0LTE5VDEyOjExOjM5KzA0OjMwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ2FtZXJhIFJhdyA3LjAiIHN0RXZ0OmNoYW5nZWQ9Ii9tZXRhZGF0YSIgLz4NCiAgICAgICAgICA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6OUVBNkIyNzA3NjYyRTkxMThDQzNFODdFN0ZEQTgwNTEiIHN0RXZ0OndoZW49IjIwMTktMDQtMTlUMTI6MTE6MzkrMDQ6MzAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDYW1lcmEgUmF3IDcuMCAoV2luZG93cykiIHN0RXZ0OmNoYW5nZWQ9Ii9tZXRhZGF0YSIgLz4NCiAgICAgICAgPC9yZGY6U2VxPg0KICAgICAgPC94bXBNTTpIaXN0b3J5Pg0KICAgICAgPGRjOnRpdGxlPg0KICAgICAgICA8cmRmOkFsdD4NCiAgICAgICAgICA8cmRmOmxpIHhtbDpsYW5nPSJ4LWRlZmF1bHQiPkJ1bGIgSWNvbiBEZXNpZ248L3JkZjpsaT4NCiAgICAgICAgPC9yZGY6QWx0Pg0KICAgICAgPC9kYzp0aXRsZT4NCiAgICAgIDxkYzpjcmVhdG9yPg0KICAgICAgICA8cmRmOlNlcT4NCiAgICAgICAgICA8cmRmOmxpPklZSUtPTjwvcmRmOmxpPg0KICAgICAgICA8L3JkZjpTZXE+DQogICAgICA8L2RjOmNyZWF0b3I+DQogICAgICA8ZGM6ZGVzY3JpcHRpb24+DQogICAgICAgIDxyZGY6QWx0Pg0KICAgICAgICAgIDxyZGY6bGkgeG1sOmxhbmc9IngtZGVmYXVsdCI+QnVsYiBJY29uIERlc2lnbg0KPC9yZGY6bGk+DQogICAgICAgIDwvcmRmOkFsdD4NCiAgICAgIDwvZGM6ZGVzY3JpcHRpb24+DQogICAgICA8ZGM6c3ViamVjdD4NCiAgICAgICAgPHJkZjpCYWc+DQogICAgICAgICAgPHJkZjpsaT5idWxiPC9yZGY6bGk+DQogICAgICAgICAgPHJkZjpsaT5lbmVyZ3k8L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPmlkZWE8L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPmxpZ2h0PC9yZGY6bGk+DQogICAgICAgICAgPHJkZjpsaT5saWdodGJ1bGI8L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPmJ1bGIgaWNvbjwvcmRmOmxpPg0KICAgICAgICAgIDxyZGY6bGk+ZW5lcmd5IGljb248L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPmlkZWEgaWNvbjwvcmRmOmxpPg0KICAgICAgICAgIDxyZGY6bGk+bGlnaHQgaWNvbjwvcmRmOmxpPg0KICAgICAgICAgIDxyZGY6bGk+bGlnaHRidWxiIGljb248L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPmljb248L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPmlsbHVzdHJhdGlvbjwvcmRmOmxpPg0KICAgICAgICAgIDxyZGY6bGk+ZGVzaWduPC9yZGY6bGk+DQogICAgICAgICAgPHJkZjpsaT5zaWduPC9yZGY6bGk+DQogICAgICAgICAgPHJkZjpsaT5zeW1ib2w8L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPmdyYXBoaWM8L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPmxpbmU8L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPmxpbmVhcjwvcmRmOmxpPg0KICAgICAgICAgIDxyZGY6bGk+b3V0bGluZTwvcmRmOmxpPg0KICAgICAgICAgIDxyZGY6bGk+ZmxhdDwvcmRmOmxpPg0KICAgICAgICAgIDxyZGY6bGk+Z2x5cGg8L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPmdyYWRpZW50PC9yZGY6bGk+DQogICAgICAgICAgPHJkZjpsaT5jaXJjbGU8L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPnNoYWRvdzwvcmRmOmxpPg0KICAgICAgICAgIDxyZGY6bGk+bG93IHBvbHk8L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPnBvbHlnb25hbDwvcmRmOmxpPg0KICAgICAgICAgIDxyZGY6bGk+c3F1YXJlPC9yZGY6bGk+DQogICAgICAgIDwvcmRmOkJhZz4NCiAgICAgIDwvZGM6c3ViamVjdD4NCiAgICA8L3JkZjpEZXNjcmlwdGlvbj4NCiAgPC9yZGY6UkRGPg0KPC94OnhtcG1ldGE+DQo8P3hwYWNrZXQgZW5kPSJyIj8+ncdlNwAABG5JREFUWMPtV2tMk1cYfr6vINBRKpVLpVIuGZfOjiARochYO/EyMWHDjOIYYSyQ6MaignEkEgJLyNxMRthmJBkalKmgUacsjMiCBRFWqKsBFJEwtkILLYxBuQi0/c5+sE5mJmvBxR/zJO+fc877vE/ey5NzKEIInuWi8YzXcwIrInCtuirlWnVVykowHGy9qFYqo+bn5pyj4uIarXtBope6H7+nbGp6dZWT0+yGqCjlUyUQEBTUW15SkiOOiLj9/eXLu1sVN6Q6jUYIAD5CoUYilSleT0q6dLO+fmvmwYOfP/UScN3df+cLBIPvbN92fWpijJedtk5XWQT6TM5PkR9Izrw72ZpRkRrr/yvfhz/MXe02aSsuZYsOMAxDH87MPMlfJxjcn7OnitWReg7GjrDH75ktQGkVMDz/csdnFReSWZzgnmVnwGwyOSbLpI1davWGY/n5xaFhYR2HPko/zWrb0vBPwQHAgQXkpgKhvM6wY+/HNXU1X0xOlkkbzSaT4xMZEEKeaDPT02xVy62YrKQ3rxDGQltubmq31NDEFsuUUKTthPjezNQkZ6kYS/aAC5s9U1lWti+36OMCMvxtEsZVG22tbU4qhW8u3hU5G69vX3YTMgxDD/T3B4SIxZ1EVyW3Z75D/IABPcBoq+XLJjA0MOArDAj4GQAwcSfCXpERegO6PnXEsglMTU1xXN3cjAtdaXSz7s/MAl19gHZKqNGOAF0634GZOQcz3GNaF/u7soHpyUd+dhPw8PQ06HVDPgAA57W6v2aXAgrKCBrazKyGzrVDBSfmHSn/vWXU6si2xf6GMWCN9yM/u5VwjZeXYdSg9559+JDt5LWzlvw5fi5OQFoChS+qtAK88GLv/rzs4+zASBVpkd2w+s7OASPjgEfQztoVCdH5k+WZo3q994e5WV8zivXdMI3xFsYX2H2YAC4C7ZXbGl/SvqsWhrodVr+vLgAeXryxt4vviuDkZVi2FMsz3julutWyuV31IJgKr0gHxbJYyyDfRkH+ik6AcWX04uDt9wDVfdoiP1SRvlRwmwjQNM2UVlamfZKXd7T3t4B+SvxltvWMRS8YmDkn616vBvj0NFB66ng2i5/w3b+OylIqtdi0Go0wMUbSOjQ4KGB6CossNTSpPrBgzKhCaqmhibaCJokiigw2FxbZimszAUIIutTq8D3xW36wmE0OFmVC7WICpqs0SQmnSOf5hFpCGMpWTAd7hGV9ePgdiVSmyNu7r8zPx3egU7XQwCOl51J/URJItr5xVZxYcgCgbH9q25MBQgiM4+NcmUjUrair23FJFtt81hnkrDPIZhZIf37eUXvx7H4TcrjcCZ6nx0hsfHx9nEzWsJEGImiAC8B1leP8f/Ym/JvEctwm5a/JFMyQzsc0T4EBwIuK/pGbkVVuN5i9KSOE4C2ZVMFYLPRI4ZHiHjbIfTbILhbISOGRYnuxqOV8zaL9/TR+gYF98w96Qs3DQ3wA0HO4xmalctOq4JAee7Co53/D/z2BPwAlMRlLdQS6SQAAAABJRU5ErkJggg==' + +if __name__ == '__main__': + try: + version = sg.version + version_parts = version.split('.') + major_version, minor_version = int(version_parts[0]), int(version_parts[1]) + if major_version < 4 or minor_version < 32: + sg.popup('Warning - Your PySimpleGUI version is less then 4.35.0', + 'As a result, you will not be able to use the EDIT features of this program', + 'Please upgrade to at least 4.35.0', + f'You are currently running version:', + sg.version, + background_color='red', text_color='white') + except Exception as e: + print(f'** Warning Exception parsing version: {version} ** ', f'{e}') main() diff --git a/DemoPrograms/ButtonClick.wav b/DemoPrograms/ButtonClick.wav new file mode 100644 index 000000000..6d021b8da Binary files /dev/null and b/DemoPrograms/ButtonClick.wav differ diff --git a/DemoPrograms/ButtonClick1.wav b/DemoPrograms/ButtonClick1.wav new file mode 100644 index 000000000..f774f70e4 Binary files /dev/null and b/DemoPrograms/ButtonClick1.wav differ diff --git a/DemoPrograms/CONTRIBUTING.md b/DemoPrograms/CONTRIBUTING.md deleted file mode 100644 index cc30e198a..000000000 --- a/DemoPrograms/CONTRIBUTING.md +++ /dev/null @@ -1,7 +0,0 @@ -## Contributing to PySimpleGUI - -We are happy to receive issues describing bug reports and feature requests! If your bug report relates to a security vulnerability, please do not file a public issue, and please instead reach out to us at issues@PySimpleGUI.com. - -We do not accept (and do not wish to receive) contributions of user-created or third-party code, including patches, pull requests, or code snippets incorporated into submitted issues. Please do not send us any such code! Bug reports and feature requests should not include any source code. - -If you nonetheless submit any user-created or third-party code to us, (1) you assign to us all rights and title in or relating to the code; and (2) to the extent any such assignment is not fully effective, you hereby grant to us a royalty-free, perpetual, irrevocable, worldwide, unlimited, sublicensable, transferrable license under all intellectual property rights embodied therein or relating thereto, to exploit the code in any manner we choose, including to incorporate the code into PySimpleGUI and to redistribute it under any terms at our discretion. diff --git a/DemoPrograms/Demo_All_Elements.py b/DemoPrograms/Demo_All_Elements.py index 45532beeb..a85328e02 100644 --- a/DemoPrograms/Demo_All_Elements.py +++ b/DemoPrograms/Demo_All_Elements.py @@ -11,11 +11,7 @@ Displays the values dictionary entry for each element And more! - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ import PySimpleGUI as sg @@ -24,41 +20,33 @@ def make_window(theme): sg.theme(theme) menu_def = [['&Application', ['E&xit']], ['&Help', ['&About']] ] - right_click_menu_def = [[], ['Edit Me', 'Versions', 'Nothing','More Nothing','Exit']] - graph_right_click_menu_def = [[], ['Erase','Draw Line', 'Draw',['Circle', 'Rectangle', 'Image'], 'Exit']] + right_click_menu_def = [[], ['Nothing','More Nothing','Exit']] # Table Data data = [["John", 10], ["Jen", 5]] headings = ["Name", "Score"] - input_layout = [ - - # [sg.Menu(menu_def, key='-MENU-')], + input_layout = [[sg.Menu(menu_def, key='-MENU-')], [sg.Text('Anything that requires user-input is in this tab!')], [sg.Input(key='-INPUT-')], [sg.Slider(orientation='h', key='-SKIDER-'), sg.Image(data=sg.DEFAULT_BASE64_LOADING_GIF, enable_events=True, key='-GIF-IMAGE-'),], [sg.Checkbox('Checkbox', default=True, k='-CB-')], [sg.Radio('Radio1', "RadioDemo", default=True, size=(10,1), k='-R1-'), sg.Radio('Radio2', "RadioDemo", default=True, size=(10,1), k='-R2-')], - [sg.Combo(values=('Combo 1', 'Combo 2', 'Combo 3'), default_value='Combo 1', readonly=False, k='-COMBO-'), + [sg.Combo(values=('Combo 1', 'Combo 2', 'Combo 3'), default_value='Combo 1', readonly=True, k='-COMBO-'), sg.OptionMenu(values=('Option 1', 'Option 2', 'Option 3'), k='-OPTION MENU-'),], [sg.Spin([i for i in range(1,11)], initial_value=10, k='-SPIN-'), sg.Text('Spin')], - [sg.Multiline('Demo of a Multi-Line Text Element!\nLine 2\nLine 3\nLine 4\nLine 5\nLine 6\nLine 7\nYou get the point.', size=(45,5), expand_x=True, expand_y=True, k='-MLINE-')], + [sg.Multiline('Demo of a Multi-Line Text Element!\nLine 2\nLine 3\nLine 4\nLine 5\nLine 6\nLine 7\nYou get the point.', size=(45,5), k='-MLINE-')], [sg.Button('Button'), sg.Button('Popup'), sg.Button(image_data=sg.DEFAULT_BASE64_ICON, key='-LOGO-')]] asthetic_layout = [[sg.T('Anything that you would use for asthetics is in this tab!')], [sg.Image(data=sg.DEFAULT_BASE64_ICON, k='-IMAGE-')], - [sg.ProgressBar(100, orientation='h', size=(20, 20), key='-PROGRESS BAR-'), sg.Button('Test Progress bar')]] + [sg.ProgressBar(1000, orientation='h', size=(20, 20), key='-PROGRESS BAR-'), sg.Button('Test Progress bar')]] - logging_layout = [[sg.Text("Anything printed will display here!")], - [sg.Multiline(size=(60,15), font='Courier 8', expand_x=True, expand_y=True, write_only=True, - reroute_stdout=True, reroute_stderr=True, echo_stdout_stderr=True, autoscroll=True, auto_refresh=True)] - # [sg.Output(size=(60,15), font='Courier 8', expand_x=True, expand_y=True)] - ] + logging_layout = [[sg.Text("Anything printed will display here!")], [sg.Output(size=(60,15), font='Courier 8')]] graphing_layout = [[sg.Text("Anything you would use to graph will display here!")], - [sg.Graph((200,200), (0,0),(200,200),background_color="black", key='-GRAPH-', enable_events=True, - right_click_menu=graph_right_click_menu_def)], + [sg.Graph((200,200), (0,0),(200,200),background_color="black", key='-GRAPH-', enable_events=True)], [sg.T('Click anywhere on graph to draw a circle')], [sg.Table(values=data, headings=headings, max_col_width=25, background_color='black', @@ -70,9 +58,9 @@ def make_window(theme): key='-TABLE-', row_height=25)]] - popup_layout = [[sg.Text("Popup Testing")], - [sg.Button("Open Folder")], - [sg.Button("Open File")]] + specalty_layout = [[sg.Text("Any \"special\" elements will display here!")], + [sg.Button("Open Folder")], + [sg.Button("Open File")]] theme_layout = [[sg.Text("See how elements look under different themes by choosing a different theme here!")], [sg.Listbox(values = sg.theme_list(), @@ -81,28 +69,25 @@ def make_window(theme): enable_events = True)], [sg.Button("Set Theme")]] - layout = [ [sg.MenubarCustom(menu_def, key='-MENU-', font='Courier 15', tearoff=True)], - [sg.Text('Demo Of (Almost) All Elements', size=(38, 1), justification='center', font=("Helvetica", 16), relief=sg.RELIEF_RIDGE, k='-TEXT HEADING-', enable_events=True)]] + layout = [[sg.Text('Demo Of (Almost) All Elements', size=(38, 1), justification='center', font=("Helvetica", 16), relief=sg.RELIEF_RIDGE, k='-TEXT HEADING-', enable_events=True)]] layout +=[[sg.TabGroup([[ sg.Tab('Input Elements', input_layout), sg.Tab('Asthetic Elements', asthetic_layout), sg.Tab('Graphing', graphing_layout), - sg.Tab('Popups', popup_layout), + sg.Tab('Specialty', specalty_layout), sg.Tab('Theming', theme_layout), - sg.Tab('Output', logging_layout)]], key='-TAB GROUP-', expand_x=True, expand_y=True), + sg.Tab('Output', logging_layout)]], key='-TAB GROUP-')]] + + return sg.Window('All Elements Demo', layout, right_click_menu=right_click_menu_def) - ]] - layout[-1].append(sg.Sizegrip()) - window = sg.Window('All Elements Demo', layout, right_click_menu=right_click_menu_def, right_click_menu_tearoff=True, grab_anywhere=True, resizable=True, margins=(0,0), use_custom_titlebar=True, finalize=True, keep_on_top=True) - window.set_min_size(window.size) - return window def main(): window = make_window(sg.theme()) - + # This is an Event Loop while True: event, values = window.read(timeout=100) # keep an animation running so show things are happening + window['-GIF-IMAGE-'].update_animation(sg.DEFAULT_BASE64_LOADING_GIF, time_between_frames=100) if event not in (sg.TIMEOUT_EVENT, sg.WIN_CLOSED): print('============ Event = ', event, ' ==============') print('-------- Values Dictionary (key=value) --------') @@ -111,25 +96,23 @@ def main(): if event in (None, 'Exit'): print("[LOG] Clicked Exit!") break - - window['-GIF-IMAGE-'].update_animation(sg.DEFAULT_BASE64_LOADING_GIF, time_between_frames=100) - if event == 'About': + elif event == 'About': print("[LOG] Clicked About!") sg.popup('PySimpleGUI Demo All Elements', 'Right click anywhere to see right click menu', 'Visit each of the tabs to see available elements', 'Output of event and values can be see in Output tab', - 'The event and values dictionary is printed after every event', keep_on_top=True) + 'The event and values dictionary is printed after every event') elif event == 'Popup': print("[LOG] Clicked Popup Button!") - sg.popup("You pressed a button!", keep_on_top=True) + sg.popup("You pressed a button!") print("[LOG] Dismissing Popup!") elif event == 'Test Progress bar': print("[LOG] Clicked Test Progress Bar!") progress_bar = window['-PROGRESS BAR-'] - for i in range(100): + for i in range(1000): print("[LOG] Updating progress bar by 1 step ("+str(i)+")") - progress_bar.update(current_count=i + 1) + progress_bar.UpdateBar(i + 1) print("[LOG] Progress bar complete!") elif event == "-GRAPH-": graph = window['-GRAPH-'] # type: sg.Graph @@ -137,13 +120,13 @@ def main(): print("[LOG] Circle drawn at: " + str(values['-GRAPH-'])) elif event == "Open Folder": print("[LOG] Clicked Open Folder!") - folder_or_file = sg.popup_get_folder('Choose your folder', keep_on_top=True) - sg.popup("You chose: " + str(folder_or_file), keep_on_top=True) + folder_or_file = sg.popup_get_folder('Choose your folder') + sg.popup("You chose: " + str(folder_or_file)) print("[LOG] User chose folder: " + str(folder_or_file)) elif event == "Open File": print("[LOG] Clicked Open File!") - folder_or_file = sg.popup_get_file('Choose your file', keep_on_top=True) - sg.popup("You chose: " + str(folder_or_file), keep_on_top=True) + folder_or_file = sg.popup_get_file('Choose your file') + sg.popup("You chose: " + str(folder_or_file)) print("[LOG] User chose file: " + str(folder_or_file)) elif event == "Set Theme": print("[LOG] Clicked Set Theme!") @@ -151,17 +134,9 @@ def main(): print("[LOG] User Chose Theme: " + str(theme_chosen)) window.close() window = make_window(theme_chosen) - elif event == 'Edit Me': - sg.execute_editor(__file__) - elif event == 'Versions': - sg.popup_scrolled(__file__, sg.get_versions(), keep_on_top=True, non_blocking=True) window.close() exit(0) if __name__ == '__main__': - sg.theme('black') - sg.theme('dark red') - sg.theme('dark green 7') - # sg.theme('DefaultNoMoreNagging') main() \ No newline at end of file diff --git a/DemoPrograms/Demo_All_Elements_Simple.py b/DemoPrograms/Demo_All_Elements_Simple.py deleted file mode 100644 index 4fa78e86a..000000000 --- a/DemoPrograms/Demo_All_Elements_Simple.py +++ /dev/null @@ -1,111 +0,0 @@ -import PySimpleGUI as sg - -""" - Demo - Element List - - All elements shown in 1 window as simply as possible. - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - - -use_custom_titlebar = True if sg.running_trinket() else False - -def make_window(theme=None): - - NAME_SIZE = 23 - - - def name(name): - dots = NAME_SIZE-len(name)-2 - return sg.Text(name + ' ' + '•'*dots, size=(NAME_SIZE,1), justification='r',pad=(0,0), font='Courier 10') - - sg.theme(theme) - - # NOTE that we're using our own LOCAL Menu element - if use_custom_titlebar: - Menu = sg.MenubarCustom - else: - Menu = sg.Menu - - treedata = sg.TreeData() - - treedata.Insert("", '_A_', 'Tree Item 1', [1234], ) - treedata.Insert("", '_B_', 'B', []) - treedata.Insert("_A_", '_A1_', 'Sub Item 1', ['can', 'be', 'anything'], ) - - layout_l = [ - [name('Text'), sg.Text('Text')], - [name('Input'), sg.Input(s=15)], - [name('Multiline'), sg.Multiline(s=(15,2))], - [name('Output'), sg.Output(s=(15,2))], - [name('Combo'), sg.Combo(sg.theme_list(), default_value=sg.theme(), s=(15,22), enable_events=True, readonly=True, k='-COMBO-')], - [name('OptionMenu'), sg.OptionMenu(['OptionMenu',],s=(15,2))], - [name('Checkbox'), sg.Checkbox('Checkbox')], - [name('Radio'), sg.Radio('Radio', 1)], - [name('Spin'), sg.Spin(['Spin',], s=(15,2))], - [name('Button'), sg.Button('Button')], - [name('ButtonMenu'), sg.ButtonMenu('ButtonMenu', sg.MENU_RIGHT_CLICK_EDITME_EXIT)], - [name('Slider'), sg.Slider((0,10), orientation='h', s=(10,15))], - [name('Listbox'), sg.Listbox(['Listbox', 'Listbox 2'], no_scrollbar=True, s=(15,2))], - [name('Image'), sg.Image(sg.EMOJI_BASE64_HAPPY_THUMBS_UP)], - [name('Graph'), sg.Graph((125, 50), (0,0), (125,50), k='-GRAPH-')] ] - - layout_r = [[name('Canvas'), sg.Canvas(background_color=sg.theme_button_color()[1], size=(125,40))], - [name('ProgressBar'), sg.ProgressBar(100, orientation='h', s=(10,20), k='-PBAR-')], - [name('Table'), sg.Table([[1,2,3], [4,5,6]], ['Col 1','Col 2','Col 3'], num_rows=2)], - [name('Tree'), sg.Tree(treedata, ['Heading',], num_rows=3)], - [name('Horizontal Separator'), sg.HSep()], - [name('Vertical Separator'), sg.VSep()], - [name('Frame'), sg.Frame('Frame', [[sg.T(s=15)]])], - [name('Column'), sg.Column([[sg.T(s=15)]])], - [name('Tab, TabGroup'), sg.TabGroup([[sg.Tab('Tab1',[[sg.T(s=(15,2))]]), sg.Tab('Tab2', [[]])]])], - [name('Pane'), sg.Pane([sg.Col([[sg.T('Pane 1')]]), sg.Col([[sg.T('Pane 2')]])])], - [name('Push'), sg.Push(), sg.T('Pushed over')], - [name('VPush'), sg.VPush()], - [name('Sizer'), sg.Sizer(1,1)], - [name('StatusBar'), sg.StatusBar('StatusBar')], - [name('Sizegrip'), sg.Sizegrip()] ] - - # Note - LOCAL Menu element is used (see about for how that's defined) - layout = [[Menu([['File', ['Exit']], ['Edit', ['Edit Me', ]]], k='-CUST MENUBAR-',p=0)], - [sg.T('PySimpleGUI Elements - Use Combo to Change Themes', font='_ 14', justification='c', expand_x=True)], - [sg.Checkbox('Use Custom Titlebar & Menubar', use_custom_titlebar, enable_events=True, k='-USE CUSTOM TITLEBAR-', p=0)], - [sg.Col(layout_l, p=0), sg.Col(layout_r, p=0)]] - - window = sg.Window('The PySimpleGUI Element List', layout, finalize=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT, keep_on_top=True, use_custom_titlebar=use_custom_titlebar) - - window['-PBAR-'].update(30) # Show 30% complete on ProgressBar - window['-GRAPH-'].draw_image(data=sg.EMOJI_BASE64_HAPPY_JOY, location=(0,50)) # Draw something in the Graph Element - - return window - - -window = make_window() - -while True: - event, values = window.read() - # sg.Print(event, values) - if event == sg.WIN_CLOSED or event == 'Exit': - break - - if values['-COMBO-'] != sg.theme(): - sg.theme(values['-COMBO-']) - window.close() - window = make_window() - if event == '-USE CUSTOM TITLEBAR-': - use_custom_titlebar = values['-USE CUSTOM TITLEBAR-'] - sg.set_options(use_custom_titlebar=use_custom_titlebar) - window.close() - window = make_window() - if event == 'Edit Me': - sg.execute_editor(__file__) - elif event == 'Version': - sg.popup_scrolled(__file__, sg.get_versions(), keep_on_top=True, non_blocking=True) -window.close() - - diff --git a/DemoPrograms/Demo_Animated_GIFs.py b/DemoPrograms/Demo_Animated_GIFs.py index 5f0baaaee..89d544b69 100644 --- a/DemoPrograms/Demo_Animated_GIFs.py +++ b/DemoPrograms/Demo_Animated_GIFs.py @@ -11,12 +11,6 @@ The first image that uses popup_animated will stop after a few seconds on its own. The remaining images are shown 1 at a time. To move on to the next image, click the current image. If you want to exit before reaching the final image, right click the image and choose 'exit' - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ # ---------------------------- Base 64 GIFs ---------------------------- @@ -35,20 +29,18 @@ gifs = [ring_blue, red_dots_ring, ring_black_dots, ring_gray_segments, ring_lines, blue_dots, red_dots_ring, bar_striped, line_boxes, line_bubbles] # first show how to use popup_animated using built-in GIF image -for i in range(1000): - if not sg.popup_animated(sg.DEFAULT_BASE64_LOADING_GIF, message='Right Click To Exit GIF Windows That Follow\nLeft click to move to next one', no_titlebar=False, time_between_frames=100, text_color='black', background_color='white'): - break +for i in range(100000): + sg.popup_animated(sg.DEFAULT_BASE64_LOADING_GIF, message='Right Click To Exit GIF Windows That Follow\nLeft click to move to next one', no_titlebar=False, time_between_frames=100, text_color='black', background_color='white') sg.popup_animated(None) # close all Animated Popups # Next demo is to show how to create custom windows with animations -layout = [[sg.Image(data=gifs[0], enable_events=True, background_color='white', key='-IMAGE-', right_click_menu=['UNUSED', ['Exit']], pad=0)],] +layout = [[sg.Image(data=gifs[0], enable_events=True, background_color='white', key='-IMAGE-', right_click_menu=['UNUSED', ['Exit']])],] window = sg.Window('My new window', layout, no_titlebar=True, grab_anywhere=True, keep_on_top=True, background_color='white', - # transparent_color='white' if sg.running_windows() else None, alpha_channel=.8, margins=(0,0)) diff --git a/DemoPrograms/Demo_Animated_GIFs_Using_PIL.py b/DemoPrograms/Demo_Animated_GIFs_Using_PIL.py index fc8bce5fb..4ffb80637 100644 --- a/DemoPrograms/Demo_Animated_GIFs_Using_PIL.py +++ b/DemoPrograms/Demo_Animated_GIFs_Using_PIL.py @@ -11,11 +11,7 @@ this is one possible technique. This particular demo will loop playing the GIF file over and over. To not loop, remove the while True statement. - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ gif_filename = r'ExampleGIF.gif' diff --git a/DemoPrograms/Demo_Auto_Save_Window_Position.py b/DemoPrograms/Demo_Auto_Save_Window_Position.py index 19684ebe7..ef7f63687 100644 --- a/DemoPrograms/Demo_Auto_Save_Window_Position.py +++ b/DemoPrograms/Demo_Auto_Save_Window_Position.py @@ -11,11 +11,7 @@ There is one added line of code. When the user attempts to close the window, that's when the position is saved. When the program starts, it reads the previously saved position as part of the window creation. User Settings APIs rock! - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ layout = [[sg.Text('Window that Auto-saves position', font='_ 25')], diff --git a/DemoPrograms/Demo_Bar_Chart.py b/DemoPrograms/Demo_Bar_Chart.py index 797cd00d6..5bd719394 100644 --- a/DemoPrograms/Demo_Bar_Chart.py +++ b/DemoPrograms/Demo_Bar_Chart.py @@ -1,59 +1,49 @@ import PySimpleGUI as sg import random -""" - Demo - Using a Graph Element to make Bar Charts - - The Graph Element is very versatile. Because you can define your own - coordinate system, it makes producing graphs of many lines (bar, line, etc) very - straightforward. - - In this Demo a "bar" is nothing more than a rectangle drawn in a Graph Element (draw_rectangle). - - To make things a little more interesting, this is a barchart with that data values - placed as labels atop each bar, another Graph element method (draw_text) - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - - - -BAR_WIDTH = 50 # width of each bar -BAR_SPACING = 75 # space between each bar -EDGE_OFFSET = 3 # offset from the left edge for first bar -GRAPH_SIZE= DATA_SIZE = (500,500) # size in pixels - -sg.theme('Light brown 1') +# Bars drawing in PySimpleGUI +# +# .--. +# | | +# .--.| |.--. +# | || || | +# | || || | +# | || || | +# .--.| || || | +# .--.| || || || |.--. +# | || || || || || | +# | || || || || || | +# .--.| || || || || || |.--. +# | || || || || || || || |.--. +# | || || || || || || || || | +# '--''--''--''--''--''--''--''--''--' + + +BAR_WIDTH = 50 +BAR_SPACING = 75 +EDGE_OFFSET = 3 +GRAPH_SIZE = (500,500) +DATA_SIZE = (500,500) + +sg.theme('Light Brown 1') + +graph = sg.Graph(GRAPH_SIZE, (0,0), DATA_SIZE) layout = [[sg.Text('Labelled Bar graphs using PySimpleGUI')], - [sg.Graph(GRAPH_SIZE, (0,0), DATA_SIZE, k='-GRAPH-')], + [graph], [sg.Button('OK'), sg.T('Click to display more data'), sg.Exit()]] -window = sg.Window('Bar Graph', layout, finalize=True) - -graph = window['-GRAPH-'] # type: sg.Graph +window = sg.Window('Window Title', layout) while True: - - graph.erase() - for i in range(7): - graph_value = random.randint(0, GRAPH_SIZE[1]-25) # choose an int just short of the max value to give room for the label - graph.draw_rectangle(top_left=(i * BAR_SPACING + EDGE_OFFSET, graph_value), - bottom_right=(i * BAR_SPACING + EDGE_OFFSET + BAR_WIDTH, 0), - fill_color='green') - # fill_color=sg.theme_button_color()[1]) - - graph.draw_text(text=graph_value, location=(i*BAR_SPACING+EDGE_OFFSET+25, graph_value+10), font='_ 14') - - # Normally at the top of the loop, but because we're drawing the graph first, making it at the bottom event, values = window.read() - if event in (sg.WIN_CLOSED, 'Exit'): break - + graph.erase() + for i in range(7): + graph_value = random.randint(0, 400) + graph.draw_rectangle(top_left=(i * BAR_SPACING + EDGE_OFFSET, graph_value), + bottom_right=(i * BAR_SPACING + EDGE_OFFSET + BAR_WIDTH, 0), fill_color='blue') + graph.draw_text(text=graph_value, location=(i*BAR_SPACING+EDGE_OFFSET+25, graph_value+10)) window.close() \ No newline at end of file diff --git a/DemoPrograms/Demo_Base64_Image_Encoder.py b/DemoPrograms/Demo_Base64_Image_Encoder.py index 41c5a8709..6ad4dc68c 100644 --- a/DemoPrograms/Demo_Base64_Image_Encoder.py +++ b/DemoPrograms/Demo_Base64_Image_Encoder.py @@ -7,12 +7,6 @@ Make base64 images input: folder with .png .ico .gif 's output: output.py file with variables - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. ''' def main(): diff --git a/DemoPrograms/Demo_Base64_Single_Image_Encoder.py b/DemoPrograms/Demo_Base64_Single_Image_Encoder.py index 830514e19..7655a5a1a 100644 --- a/DemoPrograms/Demo_Base64_Single_Image_Encoder.py +++ b/DemoPrograms/Demo_Base64_Single_Image_Encoder.py @@ -19,11 +19,7 @@ Input: a single image file Output: clipboard will contain the Base64 Byte String of the source image - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ diff --git a/DemoPrograms/Demo_Borderless_Window.py b/DemoPrograms/Demo_Borderless_Window.py index cac809845..6ff2c7f84 100644 --- a/DemoPrograms/Demo_Borderless_Window.py +++ b/DemoPrograms/Demo_Borderless_Window.py @@ -1,14 +1,6 @@ #!/usr/bin/env python import PySimpleGUI as sg -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - # Turn off padding in order to get a really tight looking layout. sg.theme('Dark') diff --git a/DemoPrograms/Demo_Button_Can_Button_Images.py b/DemoPrograms/Demo_Button_Can_Button_Images.py deleted file mode 100644 index 0e133ab0c..000000000 --- a/DemoPrograms/Demo_Button_Can_Button_Images.py +++ /dev/null @@ -1,53 +0,0 @@ -import PySimpleGUI as sg - -""" - Demo - Can Buttons - - How to use an Image element to make Can Buttons. - - The metadata for the Image Element holds the current button state. In this case the state is an offset into a list of button images. - - The technique is much like the toggle buttons except you can have more than 2 states. - - A Custom Titlebar was used to make the overall appearance cleaner while still providing the ability to easily exit. - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - - -def main(): - boost_images = (can_boost_off, can_boost_blue, can_boost_green) - seat_images = (can_seat_off, can_seat_red) - sg.theme('black') - sg.theme_background_color('#222222') - sg.theme_text_color('#888888') - sg.set_options(titlebar_background_color=sg.theme_background_color(), titlebar_text_color=sg.theme_text_color(), use_custom_titlebar=True, titlebar_icon=sg.BLANK_BASE64) - - layout = [[sg.Im(boost_images[0], k='-BOOST-', enable_events=True, metadata=0), sg.Im(seat_images[0], enable_events=True, k='-SEAT-', metadata=0)]] - - window = sg.Window('', layout) - while True: - event, values = window.read() - if event == sg.WIN_CLOSED or event == 'Exit': - break - if event == '-SEAT-': - window[event].metadata = (window[event].metadata + 1) % len(seat_images) - window[event].update(seat_images[window[event].metadata]) - if event == '-BOOST-': - window[event].metadata = (window[event].metadata + 1) % len(boost_images) - window[event].update(boost_images[window[event].metadata]) - window.close() - - -if __name__ == '__main__': - - can_boost_off = b'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' - can_boost_blue = b'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' - can_boost_green = b'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' - can_seat_off = b'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' - can_seat_red = b'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' - main() diff --git a/DemoPrograms/Demo_Button_Click.py b/DemoPrograms/Demo_Button_Click.py index cb0419126..d47d451ce 100644 --- a/DemoPrograms/Demo_Button_Click.py +++ b/DemoPrograms/Demo_Button_Click.py @@ -2,14 +2,6 @@ import sys import PySimpleGUI as sg -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - if not sys.platform.startswith('win'): sg.popup_error('Sorry, you gotta be on Windows') sys.exit() diff --git a/DemoPrograms/Demo_Button_Events_From_Browse.py b/DemoPrograms/Demo_Button_Events_From_Browse.py index 8d4600ed0..cd74e7071 100644 --- a/DemoPrograms/Demo_Button_Events_From_Browse.py +++ b/DemoPrograms/Demo_Button_Events_From_Browse.py @@ -11,12 +11,8 @@ be generated when the Chooser Button fills in the element This particular demo users a list of chosen files to populate a listbox - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + + """ diff --git a/DemoPrograms/Demo_Button_Func_Calls.py b/DemoPrograms/Demo_Button_Func_Calls.py index 1498f0c8c..e6d715876 100644 --- a/DemoPrograms/Demo_Button_Func_Calls.py +++ b/DemoPrograms/Demo_Button_Func_Calls.py @@ -12,12 +12,6 @@ It is quite easy to simulate these callbacks however. The way to do this is to add the calls to your Event Loop - -Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - -Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - -You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ diff --git a/DemoPrograms/Demo_Button_Simulated_With_Highlighting_Using_Bind.py b/DemoPrograms/Demo_Button_Simulated_With_Highlighting_Using_Bind.py deleted file mode 100644 index 07b3a06b4..000000000 --- a/DemoPrograms/Demo_Button_Simulated_With_Highlighting_Using_Bind.py +++ /dev/null @@ -1,83 +0,0 @@ -import PySimpleGUI as sg - -""" - Demo Program - Simulated Buttons with Mouseover Highlights - - The purpose of this demo is to teach you 5 unique PySimpleGUI constructs that when combined - create a "Button" that highlights on mouseover regarless of the Operating System. - Because of how tktiner works, mouseover highlighting is inconsistent across operating systems for Buttons. - This is one (dare I say "clever") way to get this effect in your program - - 1. Binding the Enter and Leave tkinter events - 2. Using Tuples as keys - 3. Using List Comprehensions to build a layout - 4. Using Text Elements to Simulate Buttons - 5. Using a "User Defined Element" to make what appears to be a new type of Button in the layout - - The KEY to making this work simply is these "Buttons" have a tuple as a key. - The format of the key is ('-B-', button_text) - - An element's bind method will make a tuple if the original key is a tuple. - (('-B-', button_text), 'ENTER') will be the event when the mouse is moved over the "Button" - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - -# sg.theme('dark red') - -def TextButton(text): - """ - A User Defined Element. It looks like a Button, but is a Text element - :param text: The text that will be put on the "Button" - :return: A Text element with a tuple as the key - """ - return sg.Text(text, key=('-B-', text), relief='raised', enable_events=True, font='_ 15',text_color=sg.theme_button_color_text(), background_color=sg.theme_button_color_background()) - -def do_binds(window, button_text): - """ - This is magic code that enables the mouseover highlighting to work. - """ - for btext in button_text: - window[('-B-', btext)].bind('', 'ENTER') - window[('-B-', btext)].bind('', 'EXIT') - -def main(): - # Defines the text on the 3 buttons we're making - button_text = ('Button 1', 'Button 2', 'Button 3') - - # The window's layout - layout = [[TextButton(text) for text in button_text], - [sg.Text(font='_ 14', k='-STATUS-')], - [sg.Ok(), sg.Exit()]] - - window = sg.Window('Custom Mouseover Highlighting Buttons', layout, finalize=True) - - # After the window is finalized, then can perform the bindings - do_binds(window, button_text) - - # The Event Looop - while True: - event, values = window.read() - print(event, values) - if event == sg.WIN_CLOSED or event == 'Exit': - break - # if the event is a tuple, it's one of our TextButtons - if isinstance(event, tuple): - # if second item is one of the bound strings, then do the mouseeover code - if event[1] in ('ENTER', 'EXIT'): - button_key = event[0] - if event[1] == 'ENTER': - window[button_key].update(text_color=sg.theme_button_color_background(), background_color=sg.theme_button_color_text()) - if event[1] == 'EXIT': - window[button_key].update(text_color=sg.theme_button_color_text(), background_color=sg.theme_button_color_background()) - else: # a "normal" button click (Text clicked) so print the text which we put into the tuple - window['-STATUS-'].update(f'Button pressed = {event[1]}') - window.close() - - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/DemoPrograms/Demo_Button_States.py b/DemoPrograms/Demo_Button_States.py index 416168476..161eadf6e 100644 --- a/DemoPrograms/Demo_Button_States.py +++ b/DemoPrograms/Demo_Button_States.py @@ -5,12 +5,6 @@ Demonstrates using a "tight" layout with a Dark theme. Shows how button states can be controlled by a user application. The program manages the disabled/enabled states for buttons and changes the text color to show greyed-out (disabled) buttons - -Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - -Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - -You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ sg.theme('Dark') diff --git a/DemoPrograms/Demo_Button_Toggle.py b/DemoPrograms/Demo_Button_Toggle.py index 0e6eb7ae1..75c67dc6e 100644 --- a/DemoPrograms/Demo_Button_Toggle.py +++ b/DemoPrograms/Demo_Button_Toggle.py @@ -7,11 +7,7 @@ A HUGE thank you to the PySimpleGUI community memeber that donated his time and skill in creating the buttons! The text of the button toggles between Off and On - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ def main(): diff --git a/DemoPrograms/Demo_Button_Toggle2.py b/DemoPrograms/Demo_Button_Toggle2.py index 8fc936455..af458d941 100644 --- a/DemoPrograms/Demo_Button_Toggle2.py +++ b/DemoPrograms/Demo_Button_Toggle2.py @@ -26,11 +26,7 @@ no text, there is no default key. It's better to be explicit with buttons that change text or have graphics. - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ import PySimpleGUI as sg diff --git a/DemoPrograms/Demo_Button_Toggle_Simple_Graphic.py b/DemoPrograms/Demo_Button_Toggle_Simple_Graphic.py index b69a55d1d..076c67068 100644 --- a/DemoPrograms/Demo_Button_Toggle_Simple_Graphic.py +++ b/DemoPrograms/Demo_Button_Toggle_Simple_Graphic.py @@ -6,11 +6,7 @@ A simple graphic that toggles. The "State" of on/off is stored in the button's Metadata - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ diff --git a/DemoPrograms/Demo_Buttons_Base64_Shaded.py b/DemoPrograms/Demo_Buttons_Base64_Shaded.py index dfa26cd86..4c485294d 100644 --- a/DemoPrograms/Demo_Buttons_Base64_Shaded.py +++ b/DemoPrograms/Demo_Buttons_Base64_Shaded.py @@ -12,11 +12,7 @@ These images are not going to win any awards but they get the point across. - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ def main(): diff --git a/DemoPrograms/Demo_Buttons_Base64_Simple.py b/DemoPrograms/Demo_Buttons_Base64_Simple.py index f4244a52a..87e893fd7 100644 --- a/DemoPrograms/Demo_Buttons_Base64_Simple.py +++ b/DemoPrograms/Demo_Buttons_Base64_Simple.py @@ -1,16 +1,5 @@ +#!/usr/bin/env python import PySimpleGUI as sg -""" - Demo - Base64 Buttons with Images - - This is perhaps the easiest, quickest, and safest way to use buttons with images in PySimpleGUI. - By putting the button into your code, then you only have to distribute a single file. - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" # First the button images @@ -18,19 +7,24 @@ stop = b'iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAABmJLR0QA/wD/AP+gvaeTAAAAaklEQVRoge3ZQQqAMAxFwSre/8p6AZFUiXzKzLqLPNJVOwYAvLcVzpztU9Q8zrr/NUW3Y+JsZXsdSjdimY0ISSMkjZA0QtIISSMkjZA0QtIISSMkjZA0QtIISSMkzcxrfMo/ya1lNgIAX1zq+ANHUjXZuAAAAABJRU5ErkJggg==' eject = b'iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAABmJLR0QA/wD/AP+gvaeTAAAByklEQVRoge3YO2gUURSA4S+JRnyACIGADyxERAsb0UKrWIidWIidlSA2YpFWSauNVtrYiIU2YpFCLGwEEWwsBAsLEbFQFARFfKBZizkyK5pkZvZmZ7PeH05z595z/sPszpxdMplMJpMZbDZFLGsm8CxiomWXxqzBQ3QiHmNdq0YNGMc9RQOvIjqxNt6iVy1GcF0h/h47sR1vY+0mRluzq8ElhfBn7O9a34tPce1KC161OK8Q/Y7D/7h+EF9jz7k+etXilELwJ44vsO8ofsTeM33wqsURpdzZCvtPK5s+toRetZjCF4XYTI1zM3HmGw4lt6rJbnxQCF1tcP5ynP2IPQm9arENb0LkDsYa5BjFrcjxDjuS2VVkI16EwH2s6iHXStxVvjy39GxXkfV4Iu3Y0T3OPMWGBDkXZDUeRMHnmEyY+/eA2cEjrE2Y+w/GcDsKvcbWJaixGS+jxixWpC4wgmvK+WlX6gJddM9lN6J2Mi4q56cDKRPPwz7lXHYhVdJp5W+KtmK61yZOYG4AGpnDyV6byWT+ZxZ7Rnf6YlGdeX2XxZ8AVag6AiR9uzZg0U/G0NyR3MigUfU7MmhPr78YmjuSyWQymUxmmPgFokSdfYSQKDwAAAAASUVORK5CYII=' -sg.theme('Light Green 3') +sg.theme('Light Green 3') # Set a color theme + +bg = sg.LOOK_AND_FEEL_TABLE[sg.CURRENT_LOOK_AND_FEEL]['BACKGROUND'] # Get the background for the current theme # Define the window's layout -layout = [[sg.Button(image_data=play, key='-PLAY-', button_color=sg.theme_background_color(), border_width=0), - sg.Button(image_data=stop, key='-STOP-', button_color=sg.theme_background_color(), border_width=0), - sg.Button(image_data=eject, key='-EXIT-', button_color=sg.theme_background_color(), border_width=0)] ] +layout = [ [sg.Text('Your Application', font='Any 15')], + [sg.Text('Event = '), sg.Text(size=(12,1), key='-OUT-')], + [sg.Button(image_data=play, key='Play', border_width=0, button_color=(bg, bg)), + sg.Button(image_data=stop, key='Stop', button_color=(bg, bg), border_width=0), + sg.Button(image_data=eject, key='Exit', button_color=(bg, bg), border_width=0)] ] # Create the window -window = sg.Window('Simple Base64 Buttons', layout) +window = sg.Window('Window Title', layout) while True: # Event Loop event, values = window.read() # type: str, dict print(event, values) - if event in (sg.WIN_CLOSED, '-EXIT-'): # If the user exits + if event in (sg.WIN_CLOSED, 'Exit'): # If the user exits break -window.close() # Exiting so clean up + window['-OUT-'].Update(event) # Output the event to the window +window.close(); del window # Exiting so clean up diff --git a/DemoPrograms/Demo_Buttons_Base64_User_Settings.py b/DemoPrograms/Demo_Buttons_Base64_User_Settings.py index ddb3be698..7c38758a9 100644 --- a/DemoPrograms/Demo_Buttons_Base64_User_Settings.py +++ b/DemoPrograms/Demo_Buttons_Base64_User_Settings.py @@ -8,11 +8,7 @@ Often the better buttons are in Photoshop format. These all orignally had text as part of the button. Processing the buttons - The text was removed, the Photoshop image saved as PNG, PNG file converted to Base64 - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ diff --git a/DemoPrograms/Demo_Buttons_Mac.py b/DemoPrograms/Demo_Buttons_Mac.py index 34f5b8487..1ec4154e2 100644 --- a/DemoPrograms/Demo_Buttons_Mac.py +++ b/DemoPrograms/Demo_Buttons_Mac.py @@ -3,14 +3,6 @@ import time import PySimpleGUI as sg -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - def show_win(): sg.set_options(border_width=0, margins=(0, 0), element_padding=(5, 3)) diff --git a/DemoPrograms/Demo_Buttons_Nice_Graphics.py b/DemoPrograms/Demo_Buttons_Nice_Graphics.py index 5466022db..3d3724162 100644 --- a/DemoPrograms/Demo_Buttons_Nice_Graphics.py +++ b/DemoPrograms/Demo_Buttons_Nice_Graphics.py @@ -11,12 +11,6 @@ using the tkinter version of PySimpleGUI (except for crude "Scaling") The PIL code resizes the button images prior to creating the sg.B - -Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - -Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - -You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ @@ -32,7 +26,7 @@ def resize_base64_image(image64, size): ''' image_file = io.BytesIO(base64.b64decode(image64)) img = Image.open(image_file) - img.thumbnail(size, Image.LANCZOS) + img.thumbnail(size, Image.ANTIALIAS) bio = io.BytesIO() img.save(bio, format='PNG') imgbytes = bio.getvalue() diff --git a/DemoPrograms/Demo_Buttons_Realtime.py b/DemoPrograms/Demo_Buttons_Realtime.py index 8c657fb13..a3b0b4b52 100644 --- a/DemoPrograms/Demo_Buttons_Realtime.py +++ b/DemoPrograms/Demo_Buttons_Realtime.py @@ -13,11 +13,7 @@ the timeout is 100, so there will be 100ms between releasing a button and your program detecting this has happened. - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ import PySimpleGUI as sg diff --git a/DemoPrograms/Demo_CLI_or_GUI.py b/DemoPrograms/Demo_CLI_or_GUI.py deleted file mode 100644 index 92e3cd1ed..000000000 --- a/DemoPrograms/Demo_CLI_or_GUI.py +++ /dev/null @@ -1,30 +0,0 @@ -""" - Demo Command Line Application or GUI Application - - If your program is run with arguments, then a command line version is used. - If no arguments are given, then a GUI is shown that asks for a filename. - - http://www.PySimpleGUI.org - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - -import PySimpleGUI as sg -import sys - -def main_cli(filename): - print(f'Your filename = {filename}') - - -def main_gui(): - filename = sg.popup_get_file('Please enter a filename:') - main_cli(filename) - -if __name__ == '__main__': - if len(sys.argv) < 2: - main_gui() - else: - main_cli(sys.argv[1]) diff --git a/DemoPrograms/Demo_Calendar.py b/DemoPrograms/Demo_Calendar.py index 020bb270a..f6a4fa84a 100644 --- a/DemoPrograms/Demo_Calendar.py +++ b/DemoPrograms/Demo_Calendar.py @@ -3,12 +3,6 @@ """ Simple test harness to demonstate how to use the CalendarButton and the get date popup - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ # sg.theme('Dark Red') layout = [[sg.Text('Date Chooser Test Harness', key='-TXT-')], diff --git a/DemoPrograms/Demo_Canvas.py b/DemoPrograms/Demo_Canvas.py index 0d6cbb588..9cf20a83b 100644 --- a/DemoPrograms/Demo_Canvas.py +++ b/DemoPrograms/Demo_Canvas.py @@ -1,14 +1,6 @@ #!/usr/bin/env python import PySimpleGUI as sg -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - layout = [ [sg.Canvas(size=(150, 150), background_color='red', key='canvas')], [sg.Text('Change circle color to:'), sg.Button('Red'), sg.Button('Blue')] diff --git a/DemoPrograms/Demo_Chat.py b/DemoPrograms/Demo_Chat.py index b4bdc6fd7..76b9a6355 100644 --- a/DemoPrograms/Demo_Chat.py +++ b/DemoPrograms/Demo_Chat.py @@ -4,32 +4,25 @@ ''' A simple send/response chat window. Add call to your send-routine and print the response If async responses can come in, then will need to use a different design that uses PySimpleGUI async design pattern - -Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - -Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - -You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. - ''' sg.theme('GreenTan') # give our window a spiffy set of colors layout = [[sg.Text('Your output will go here', size=(40, 1))], [sg.Output(size=(110, 20), font=('Helvetica 10'))], - [sg.Multiline(size=(70, 5), enter_submits=True, key='-QUERY-', do_not_clear=False), + [sg.Multiline(size=(70, 5), enter_submits=False, key='-QUERY-', do_not_clear=False), sg.Button('SEND', button_color=(sg.YELLOWS[0], sg.BLUES[0]), bind_return_key=True), sg.Button('EXIT', button_color=(sg.YELLOWS[0], sg.GREENS[0]))]] window = sg.Window('Chat window', layout, font=('Helvetica', ' 13'), default_button_element_size=(8,2), use_default_focus=False) while True: # The Event Loop - event, values = window.read() + event, value = window.read() if event in (sg.WIN_CLOSED, 'EXIT'): # quit if exit button or X break if event == 'SEND': - query = values['-QUERY-'].rstrip() + query = value['-QUERY-'].rstrip() # EXECUTE YOUR COMMAND HERE print('The command you entered was {}'.format(query), flush=True) -window.close() +window.close() \ No newline at end of file diff --git a/DemoPrograms/Demo_Chat_With_History.py b/DemoPrograms/Demo_Chat_With_History.py index 194d86a29..f7bade052 100644 --- a/DemoPrograms/Demo_Chat_With_History.py +++ b/DemoPrograms/Demo_Chat_With_History.py @@ -9,12 +9,6 @@ Down arrow - scroll down in commands Escape - clear current command Control C - exit form - -Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - -Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - -You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. ''' diff --git a/DemoPrograms/Demo_Chatterbot.py b/DemoPrograms/Demo_Chatterbot.py index 4f27f20d7..67726c6dd 100644 --- a/DemoPrograms/Demo_Chatterbot.py +++ b/DemoPrograms/Demo_Chatterbot.py @@ -12,15 +12,9 @@ It still runs fine with the old version. -A GUI wrapped around the Chatterbot package. +A GUI wrapped arouind the Chatterbot package. The GUI is used to show progress bars during the training process and to collect user input that is sent to the chatbot. The reply is displayed in the GUI window - -Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - -Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - -You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. ''' # Create the 'Trainer GUI' diff --git a/DemoPrograms/Demo_Chatterbot_With_TTS.py b/DemoPrograms/Demo_Chatterbot_With_TTS.py index fda23d8a1..ca6775c96 100644 --- a/DemoPrograms/Demo_Chatterbot_With_TTS.py +++ b/DemoPrograms/Demo_Chatterbot_With_TTS.py @@ -17,15 +17,9 @@ It still runs fine with the old version. -A GUI wrapped around the Chatterbot package. +A GUI wrapped arouind the Chatterbot package. The GUI is used to show progress bars during the training process and to collect user input that is sent to the chatbot. The reply is displayed in the GUI window - -Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - -Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - -You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. ''' # Create the 'Trainer GUI' diff --git a/DemoPrograms/Demo_Checkboxes_Custom.py b/DemoPrograms/Demo_Checkboxes_Custom.py deleted file mode 100644 index 74d1ea602..000000000 --- a/DemoPrograms/Demo_Checkboxes_Custom.py +++ /dev/null @@ -1,49 +0,0 @@ -import PySimpleGUI as sg - -""" - Demo - Custom Checkboxes done simply - - The Base64 Image encoding feature of PySimpleGUI makes it possible to create beautiful GUIs very simply - - These 2 checkboxes required 3 extra lines of code than a normal checkbox. - 1. Keep track of the current value using the Image Element's Metadata - 2. Changle / Update the image when clicked - 3. The Base64 image definition - - Enable the event on the Image with the checkbox so that you can take action (flip the value) - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - -def main(): - layout = [[sg.Text('Fancy Checkboxes... Simply')], - [sg.Image(checked, key=('-IMAGE-', 1), metadata=True, enable_events=True), sg.Text(True, enable_events=True, k=('-TEXT-', 1))], - [sg.Image(unchecked, key=('-IMAGE-', 2), metadata=False, enable_events=True), sg.Text(False, enable_events=True, k=('-TEXT-', 2))], - [sg.Button('Go'), sg.Button('Exit')]] - - window = sg.Window('Custom Checkboxes', layout, font="_ 14") - while True: - event, values = window.read() - print(event, values) - if event == sg.WIN_CLOSED or event == 'Exit': - break - # if a checkbox is clicked, flip the vale and the image - if event[0] in ('-IMAGE-', '-TEXT-'): - cbox_key = ('-IMAGE-', event[1]) - text_key = ('-TEXT-', event[1]) - window[cbox_key].metadata = not window[cbox_key].metadata - window[cbox_key].update(checked if window[cbox_key].metadata else unchecked) - # Update the string next to the checkbox - window[text_key].update(window[cbox_key].metadata) - - window.close() - - -if __name__ == '__main__': - checked = b'iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAKMGlDQ1BJQ0MgUHJvZmlsZQAAeJydlndUVNcWh8+9d3qhzTAUKUPvvQ0gvTep0kRhmBlgKAMOMzSxIaICEUVEBBVBgiIGjIYisSKKhYBgwR6QIKDEYBRRUXkzslZ05eW9l5ffH2d9a5+99z1n733WugCQvP25vHRYCoA0noAf4uVKj4yKpmP7AQzwAAPMAGCyMjMCQj3DgEg+Hm70TJET+CIIgDd3xCsAN428g+h08P9JmpXBF4jSBInYgs3JZIm4UMSp2YIMsX1GxNT4FDHDKDHzRQcUsbyYExfZ8LPPIjuLmZ3GY4tYfOYMdhpbzD0i3pol5IgY8RdxURaXky3iWyLWTBWmcUX8VhybxmFmAoAiie0CDitJxKYiJvHDQtxEvBQAHCnxK47/igWcHIH4Um7pGbl8bmKSgK7L0qOb2doy6N6c7FSOQGAUxGSlMPlsult6WgaTlwvA4p0/S0ZcW7qoyNZmttbWRubGZl8V6r9u/k2Je7tIr4I/9wyi9X2x/ZVfej0AjFlRbXZ8scXvBaBjMwDy97/YNA8CICnqW/vAV/ehieclSSDIsDMxyc7ONuZyWMbigv6h/+nwN/TV94zF6f4oD92dk8AUpgro4rqx0lPThXx6ZgaTxaEb/XmI/3HgX5/DMISTwOFzeKKIcNGUcXmJonbz2FwBN51H5/L+UxP/YdiftDjXIlEaPgFqrDGQGqAC5Nc+gKIQARJzQLQD/dE3f3w4EL+8CNWJxbn/LOjfs8Jl4iWTm/g5zi0kjM4S8rMW98TPEqABAUgCKlAAKkAD6AIjYA5sgD1wBh7AFwSCMBAFVgEWSAJpgA+yQT7YCIpACdgBdoNqUAsaQBNoASdABzgNLoDL4Dq4AW6DB2AEjIPnYAa8AfMQBGEhMkSBFCBVSAsygMwhBuQIeUD+UAgUBcVBiRAPEkL50CaoBCqHqqE6qAn6HjoFXYCuQoPQPWgUmoJ+h97DCEyCqbAyrA2bwAzYBfaDw+CVcCK8Gs6DC+HtcBVcDx+D2+EL8HX4NjwCP4dnEYAQERqihhghDMQNCUSikQSEj6xDipFKpB5pQbqQXuQmMoJMI+9QGBQFRUcZoexR3qjlKBZqNWodqhRVjTqCakf1oG6iRlEzqE9oMloJbYC2Q/ugI9GJ6Gx0EboS3YhuQ19C30aPo99gMBgaRgdjg/HGRGGSMWswpZj9mFbMecwgZgwzi8ViFbAGWAdsIJaJFWCLsHuxx7DnsEPYcexbHBGnijPHeeKicTxcAa4SdxR3FjeEm8DN46XwWng7fCCejc/Fl+Eb8F34Afw4fp4gTdAhOBDCCMmEjYQqQgvhEuEh4RWRSFQn2hKDiVziBmIV8TjxCnGU+I4kQ9InuZFiSELSdtJh0nnSPdIrMpmsTXYmR5MF5O3kJvJF8mPyWwmKhLGEjwRbYr1EjUS7xJDEC0m8pJaki+QqyTzJSsmTkgOS01J4KW0pNymm1DqpGqlTUsNSs9IUaTPpQOk06VLpo9JXpSdlsDLaMh4ybJlCmUMyF2XGKAhFg+JGYVE2URoolyjjVAxVh+pDTaaWUL+j9lNnZGVkLWXDZXNka2TPyI7QEJo2zYeWSiujnaDdob2XU5ZzkePIbZNrkRuSm5NfIu8sz5Evlm+Vvy3/XoGu4KGQorBToUPhkSJKUV8xWDFb8YDiJcXpJdQl9ktYS4qXnFhyXwlW0lcKUVqjdEipT2lWWUXZSzlDea/yReVpFZqKs0qySoXKWZUpVYqqoypXtUL1nOozuizdhZ5Kr6L30GfUlNS81YRqdWr9avPqOurL1QvUW9UfaRA0GBoJGhUa3RozmqqaAZr5ms2a97XwWgytJK09Wr1ac9o62hHaW7Q7tCd15HV8dPJ0mnUe6pJ1nXRX69br3tLD6DH0UvT2693Qh/Wt9JP0a/QHDGADawOuwX6DQUO0oa0hz7DecNiIZORilGXUbDRqTDP2Ny4w7jB+YaJpEm2y06TX5JOplWmqaYPpAzMZM1+zArMus9/N9c1Z5jXmtyzIFp4W6y06LV5aGlhyLA9Y3rWiWAVYbbHqtvpobWPNt26xnrLRtImz2WczzKAyghiljCu2aFtX2/W2p23f2VnbCexO2P1mb2SfYn/UfnKpzlLO0oalYw7qDkyHOocRR7pjnONBxxEnNSemU73TE2cNZ7Zzo/OEi55Lsssxlxeupq581zbXOTc7t7Vu590Rdy/3Yvd+DxmP5R7VHo891T0TPZs9Z7ysvNZ4nfdGe/t57/Qe9lH2Yfk0+cz42viu9e3xI/mF+lX7PfHX9+f7dwXAAb4BuwIeLtNaxlvWEQgCfQJ3BT4K0glaHfRjMCY4KLgm+GmIWUh+SG8oJTQ29GjomzDXsLKwB8t1lwuXd4dLhseEN4XPRbhHlEeMRJpEro28HqUYxY3qjMZGh0c3Rs+u8Fixe8V4jFVMUcydlTorc1ZeXaW4KnXVmVjJWGbsyTh0XETc0bgPzEBmPXM23id+X/wMy421h/Wc7cyuYE9xHDjlnIkEh4TyhMlEh8RdiVNJTkmVSdNcN24192Wyd3Jt8lxKYMrhlIXUiNTWNFxaXNopngwvhdeTrpKekz6YYZBRlDGy2m717tUzfD9+YyaUuTKzU0AV/Uz1CXWFm4WjWY5ZNVlvs8OzT+ZI5/By+nL1c7flTuR55n27BrWGtaY7Xy1/Y/7oWpe1deugdfHrutdrrC9cP77Ba8ORjYSNKRt/KjAtKC94vSliU1ehcuGGwrHNXpubiySK+EXDW+y31G5FbeVu7d9msW3vtk/F7OJrJaYllSUfSlml174x+6bqm4XtCdv7y6zLDuzA7ODtuLPTaeeRcunyvPKxXQG72ivoFcUVr3fH7r5aaVlZu4ewR7hnpMq/qnOv5t4dez9UJ1XfrnGtad2ntG/bvrn97P1DB5wPtNQq15bUvj/IPXi3zquuvV67vvIQ5lDWoacN4Q293zK+bWpUbCxp/HiYd3jkSMiRniabpqajSkfLmuFmYfPUsZhjN75z/66zxailrpXWWnIcHBcef/Z93Pd3Tvid6D7JONnyg9YP+9oobcXtUHtu+0xHUsdIZ1Tn4CnfU91d9l1tPxr/ePi02umaM7Jnys4SzhaeXTiXd272fMb56QuJF8a6Y7sfXIy8eKsnuKf/kt+lK5c9L1/sdek9d8XhyumrdldPXWNc67hufb29z6qv7Sern9r6rfvbB2wGOm/Y3ugaXDp4dshp6MJN95uXb/ncun572e3BO8vv3B2OGR65y747eS/13sv7WffnH2x4iH5Y/EjqUeVjpcf1P+v93DpiPXJm1H2070nokwdjrLHnv2T+8mG88Cn5aeWE6kTTpPnk6SnPqRvPVjwbf57xfH666FfpX/e90H3xw2/Ov/XNRM6Mv+S/XPi99JXCq8OvLV93zwbNPn6T9mZ+rvitwtsj7xjvet9HvJ+Yz/6A/VD1Ue9j1ye/Tw8X0hYW/gUDmPP8uaxzGQAAAp1JREFUeJzFlk1rE1EUhp9z5iat9kMlVXGhKH4uXEo1CoIKrnSnoHs3unLnxpW7ipuCv0BwoRv/gCBY2/gLxI2gBcHGT9KmmmTmHBeTlLRJGquT+jJ3djPPfV/OPefK1UfvD0hIHotpsf7jm4mq4k6mEsEtsfz2gpr4rGpyPYjGjyUMFy1peNg5odkSV0nNDNFwxhv2JAhR0ZKGA0JiIAPCpgTczaVhRa1//2qoprhBQdv/LSKNasVUVAcZb/c9/A9oSwMDq6Rr08DSXNW68TN2pAc8U3CLsVQ3bpwocHb/CEs16+o8ZAoVWKwZNycLXD62DYDyUszbLzW2BMHa+lIm4Fa8lZpx6+QEl46OA1CaX+ZjpUFeV0MzAbecdoPen1lABHKRdHThdcECiNCx27XQxTXQufllHrxaIFKItBMK6xSXCCSeFsoKZO2m6AUtE0lvaE+wCPyKna055erx7SSWul7pes1Xpd4Z74OZhfQMrwOFLlELYAbjeeXuud0cKQyxZyzHw9efGQ6KStrve8WrCpHSd7J2gL1Jjx0qvxIALh4aIxJhulRmKBKWY+8Zbz+nLXWNWgXqsXPvxSfm5qsAXDg4yu3iLn7Gzq3Jv4t3XceQxpSLQFWZelnmztldnN43wvmDoxyeGGLvtlyb0z+Pt69jSItJBfJBmHpZXnG+Gtq/ejcMhtSBCuQjYWqmzOyHFD77oZo63WC87erbudzTGAMwXfrM2y81nr+rIGw83nb90XQyh9Ccb8/e/CAxCF3aYOZgaB4zYDSffvKvN+ANz+NefXvg4KykbmabDXU30/yOguKbyHYnNzKuwUnmhPxpF3Ok19UsM2r6BEpB6n7NpPFU6smpuLpoqCgZFdCKBDC3MDKmntNSVEuu/AYecjifoa3JogAAAABJRU5ErkJggg==' - unchecked = b'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' - main() diff --git a/DemoPrograms/Demo_Class_Wrapper.py b/DemoPrograms/Demo_Class_Wrapper.py deleted file mode 100644 index 10947e6ce..000000000 --- a/DemoPrograms/Demo_Class_Wrapper.py +++ /dev/null @@ -1,111 +0,0 @@ -import PySimpleGUI as sg - -""" - Demo - Class wrapper - - Using a class to encapsulate PySimpleGUI Window creation & event loop - - This is NOT a recommended design pattern. It mimics the object oriented design that many OO-based - GUI frameworks use, but there is no advantage to structuring you code in his manner. It adds - confusion, not clarity. - - The class version is 18 lines of code. The plain version is 13 lines of code. - - Two things about the class wrapper jump out as adding confusion: - 1. Unneccessary fragmentation of the event loop - the button click code is pulled out of the loop entirely - 2. "self" clutters the code without adding value - - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - -''' - MM'""""'YMM dP - M' .mmm. `M 88 - M MMMMMooM 88 .d8888b. .d8888b. .d8888b. - M MMMMMMMM 88 88' `88 Y8ooooo. Y8ooooo. - M. `MMM' .M 88 88. .88 88 88 - MM. .dM dP `88888P8 `88888P' `88888P' - MMMMMMMMMMM - - M""MMMMM""M oo - M MMMMM M - M MMMMP M .d8888b. 88d888b. .d8888b. dP .d8888b. 88d888b. - M MMMM' .M 88ooood8 88' `88 Y8ooooo. 88 88' `88 88' `88 - M MMP' .MM 88. ... 88 88 88 88. .88 88 88 - M .dMMM `88888P' dP `88888P' dP `88888P' dP dP - MMMMMMMMMMM -''' - - -class SampleGUI(): - - def __init__(self): - self.layout = [[sg.Text('My layout')], - [sg.Input(key='-IN-')], - [sg.Button('Go'), sg.Button('Exit')]] - - self.window = sg.Window('My new window', self.layout) - - def run(self): - while True: # Event Loop - self.event, self.values = self.window.read() - if self.event in (sg.WIN_CLOSED, 'Exit'): - break - - if self.event == 'Go': - self.button_go() - - self.window.close() - - def button_go(self): - sg.popup('Go button clicked', 'Input value:', self.values['-IN-']) - - -# Create the class -my_gui = SampleGUI() -# run the event loop -my_gui.run() - -''' - M"""""""`YM dP - M mmmm. M 88 - M MMMMM M .d8888b. 88d888b. 88d8b.d8b. .d8888b. 88 - M MMMMM M 88' `88 88' `88 88'`88'`88 88' `88 88 - M MMMMM M 88. .88 88 88 88 88 88. .88 88 - M MMMMM M `88888P' dP dP dP dP `88888P8 dP - MMMMMMMMMMM - - M""MMMMM""M oo - M MMMMM M - M MMMMP M .d8888b. 88d888b. .d8888b. dP .d8888b. 88d888b. - M MMMM' .M 88ooood8 88' `88 Y8ooooo. 88 88' `88 88' `88 - M MMP' .MM 88. ... 88 88 88 88. .88 88 88 - M .dMMM `88888P' dP `88888P' dP `88888P' dP dP - MMMMMMMMMMM -''' - - -def gui_function(): - layout = [[sg.Text('My layout')], - [sg.Input(key='-IN-')], - [sg.Button('Go'), sg.Button('Exit')]] - - window = sg.Window('My new window', layout) - - while True: # Event Loop - event, values = window.read() - if event in (sg.WIN_CLOSED, 'Exit'): - break - - if event == 'Go': - sg.popup('Go button clicked', 'Input value:', values['-IN-']) - - window.close() - - -gui_function() diff --git a/DemoPrograms/Demo_Close_Attempted_Event.py b/DemoPrograms/Demo_Close_Attempted_Event.py index cccc819b1..6fbf22a8b 100644 --- a/DemoPrograms/Demo_Close_Attempted_Event.py +++ b/DemoPrograms/Demo_Close_Attempted_Event.py @@ -4,11 +4,7 @@ Catches if a window close was tried by user (click "X") and confirms with a popup. Requires PySimpleGUI 4.33.0 and later - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI Inc. """ import PySimpleGUI as sg diff --git a/DemoPrograms/Demo_Color_Chooser_Custom.py b/DemoPrograms/Demo_Color_Chooser_Custom.py index fb0fa9354..3a998853c 100644 --- a/DemoPrograms/Demo_Color_Chooser_Custom.py +++ b/DemoPrograms/Demo_Color_Chooser_Custom.py @@ -1,16 +1,9 @@ import PySimpleGUI as sg -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - def popup_color_chooser(look_and_feel=None): """ + :return: Any(str, None) Returns hex string of color chosen or None if nothing was chosen """ color_map = { diff --git a/DemoPrograms/Demo_Color_Names.py b/DemoPrograms/Demo_Color_Names.py index b63b18fb8..9d779d696 100644 --- a/DemoPrograms/Demo_Color_Names.py +++ b/DemoPrograms/Demo_Color_Names.py @@ -10,11 +10,7 @@ You will find the list of tkinter colors here: http://www.tcl.tk/man/tcl8.5/TkCmd/colors.htm - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ color_map = { diff --git a/DemoPrograms/Demo_Color_Names_Smaller_List.py b/DemoPrograms/Demo_Color_Names_Smaller_List.py index 223f640a2..dacd1a302 100644 --- a/DemoPrograms/Demo_Color_Names_Smaller_List.py +++ b/DemoPrograms/Demo_Color_Names_Smaller_List.py @@ -8,12 +8,6 @@ Shows a big chart of colors... give it a few seconds to create it Once large window is shown, you can click on any color and another window will popup showing both white and black text on that color - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ diff --git a/DemoPrograms/Demo_Color_Swatches.py b/DemoPrograms/Demo_Color_Swatches.py index a9c397009..e5a7bc5aa 100644 --- a/DemoPrograms/Demo_Color_Swatches.py +++ b/DemoPrograms/Demo_Color_Swatches.py @@ -14,11 +14,7 @@ You will find the list of tkinter colors here: http://www.tcl.tk/man/tcl8.5/TkCmd/colors.htm - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ color_map = { diff --git a/DemoPrograms/Demo_Column_And_Frames.py b/DemoPrograms/Demo_Column_And_Frames.py index 459ecf423..1e17a6ecf 100644 --- a/DemoPrograms/Demo_Column_And_Frames.py +++ b/DemoPrograms/Demo_Column_And_Frames.py @@ -18,11 +18,7 @@ aligned along their center. If you want them to be top-aligned, then you need to use the vtop helper function to make that happen. - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ col2 = sg.Column([[sg.Frame('Accounts:', [[sg.Column([[sg.Listbox(['Account '+str(i) for i in range(1,16)], diff --git a/DemoPrograms/Demo_Column_Collapsible_Sections.py b/DemoPrograms/Demo_Column_Collapsible_Sections.py index 0273335eb..54e55b0f5 100644 --- a/DemoPrograms/Demo_Column_Collapsible_Sections.py +++ b/DemoPrograms/Demo_Column_Collapsible_Sections.py @@ -12,11 +12,7 @@ Feel free to modify to use the fonts and sizes of your choosing. It's 1 line of code to make the section. It could have been done directly in the layout. - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI.org """ diff --git a/DemoPrograms/Demo_Column_Elem_Swap_Entire_Window.py b/DemoPrograms/Demo_Column_Elem_Swap_Entire_Window.py index 66e370bee..66936c045 100644 --- a/DemoPrograms/Demo_Column_Elem_Swap_Entire_Window.py +++ b/DemoPrograms/Demo_Column_Elem_Swap_Entire_Window.py @@ -10,12 +10,6 @@ To "swap out" a portion of a window, use a Column element for that portion. Add multiple Columns on the same row and make only 1 of them active at a time - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ # ----------- Create the 3 layouts this Window will display ----------- diff --git a/DemoPrograms/Demo_Column_Fixed_Size_Justified_Elements.py b/DemoPrograms/Demo_Column_Fixed_Size_Justified_Elements.py index 932c11efa..74d136f2a 100644 --- a/DemoPrograms/Demo_Column_Fixed_Size_Justified_Elements.py +++ b/DemoPrograms/Demo_Column_Fixed_Size_Justified_Elements.py @@ -15,11 +15,7 @@ It is an invisible "padding" type of element. It has a width and a height parameter. - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ diff --git a/DemoPrograms/Demo_Columns.py b/DemoPrograms/Demo_Columns.py index e53a14b8c..eb6574354 100644 --- a/DemoPrograms/Demo_Columns.py +++ b/DemoPrograms/Demo_Columns.py @@ -1,16 +1,8 @@ #!/usr/bin/env python import PySimpleGUI as sg - +print(sg.version, sg) ''' Usage of Column Element - - How to embed a layout in a layout - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. ''' sg.theme('BlueMono') @@ -22,12 +14,12 @@ # Window layout layout = [[sg.Listbox(values=('Listbox Item 1', 'Listbox Item 2', 'Listbox Item 3'), select_mode=sg.LISTBOX_SELECT_MODE_MULTIPLE, size=(20, 3)), - sg.Column(col, background_color='blue')], + sg.Col(col, background_color='blue')], [sg.Input('Last input')], [sg.OK()]] # Display the window and get values -window = sg.Window('Column Element', layout, margins=(0,0), element_padding=(0,0)) +window = sg.Window('Compact 1-line form with column', layout, margins=(0,0), element_padding=(0,0)) event, values = window.read() sg.popup(event, values, line_width=200) diff --git a/DemoPrograms/Demo_Combo_Filechooser_With_History_And_Clear.py b/DemoPrograms/Demo_Combo_Filechooser_With_History_And_Clear.py index 5c20efe3d..3ba65023b 100644 --- a/DemoPrograms/Demo_Combo_Filechooser_With_History_And_Clear.py +++ b/DemoPrograms/Demo_Combo_Filechooser_With_History_And_Clear.py @@ -16,17 +16,13 @@ The code is as sparse as possible to enable easy integration into your code. - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ layout = [[sg.Combo(sorted(sg.user_settings_get_entry('-filenames-', [])), default_value=sg.user_settings_get_entry('-last filename-', ''), size=(50, 1), key='-FILENAME-'), sg.FileBrowse(), sg.B('Clear History')], - [sg.Button('Ok', bind_return_key=True), sg.Button('Cancel')]] + [sg.Button('Ok'), sg.Button('Cancel')]] window = sg.Window('Filename Chooser With History', layout) diff --git a/DemoPrograms/Demo_Compact_Layouts_Element_Renaming.py b/DemoPrograms/Demo_Compact_Layouts_Element_Renaming.py index 764508764..1056aff16 100644 --- a/DemoPrograms/Demo_Compact_Layouts_Element_Renaming.py +++ b/DemoPrograms/Demo_Compact_Layouts_Element_Renaming.py @@ -28,13 +28,7 @@ PLEASE OH PLEASE OH PLEASE NEVER EVER EVER do this: from PySimpleGUI import * There is a bot scanning GitHub for this statement. If found in your code, a squad of assassins will be dispatched - from the PySimpleGUI headquarters and you will be hunted down and forced to change your code. - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + from the PySimpleGUI headquarters and you will be hunted down and forced to change your code. """ # A user created shortcut.... diff --git a/DemoPrograms/Demo_Compare_Files.py b/DemoPrograms/Demo_Compare_Files.py index 4239a32df..93c565796 100644 --- a/DemoPrograms/Demo_Compare_Files.py +++ b/DemoPrograms/Demo_Compare_Files.py @@ -3,12 +3,6 @@ ''' Simple "diff" in PySimpleGUI - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. ''' sg.theme('Dark Blue 3') diff --git a/DemoPrograms/Demo_Control_Panel_Button_Grid.py b/DemoPrograms/Demo_Control_Panel_Button_Grid.py index fbee7abb7..efeca60da 100644 --- a/DemoPrograms/Demo_Control_Panel_Button_Grid.py +++ b/DemoPrograms/Demo_Control_Panel_Button_Grid.py @@ -5,12 +5,6 @@ This window looks much like a control panel NOTE - The SCROLLING using the mousewheel is known to have a bug in the tkinter port. You will need to have your mouse over the scrollbar to scroll with the mousewheel - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ def GraphicButton(text:str, key:str, image_data): diff --git a/DemoPrograms/Demo_Conways_Game_of_Life.py b/DemoPrograms/Demo_Conways_Game_of_Life.py new file mode 100644 index 000000000..b1462119d --- /dev/null +++ b/DemoPrograms/Demo_Conways_Game_of_Life.py @@ -0,0 +1,194 @@ +#!/usr/bin/env python + +# John Conway's "Game of Life" using a GUI. +# Copyright (C) 2018 PySimpleGUI.org +# GUI provided by PySimpleGUI. +# Core game engine provied by Christian Jacobs + +# An implementation of Conway's Game of Life in Python. + +# Copyright (C) 2013 Christian Jacobs. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import numpy +import PySimpleGUI as sg + +BOX_SIZE = 15 + + +class GameOfLife: + + def __init__(self, N=20, T=200): + """ Set up Conway's Game of Life. """ + # Here we create two grids to hold the old and new configurations. + # This assumes an N*N grid of points. + # Each point is either alive or dead, represented by integer values of 1 and 0, respectively. + self.N = N + self.old_grid = numpy.zeros(N * N, dtype='i').reshape(N, N) + self.new_grid = numpy.zeros(N * N, dtype='i').reshape(N, N) + self.T = T # The maximum number of generations + + # Set up a random initial configuration for the grid. + for i in range(0, self.N): + for j in range(0, self.N): + self.old_grid[i][j] = 0 + self.init_graphics() + self.manual_board_setup() + + def live_neighbours(self, i, j): + """ Count the number of live neighbours around point (i, j). """ + s = 0 # The total number of live neighbours. + # Loop over all the neighbours. + for x in [i - 1, i, i + 1]: + for y in [j - 1, j, j + 1]: + if (x == i and y == j): + continue # Skip the current point itself - we only want to count the neighbours! + if (x != self.N and y != self.N): + s += self.old_grid[x][y] + # The remaining branches handle the case where the neighbour is off the end of the grid. + # In this case, we loop back round such that the grid becomes a "toroidal array". + elif (x == self.N and y != self.N): + s += self.old_grid[0][y] + elif (x != self.N and y == self.N): + s += self.old_grid[x][0] + else: + s += self.old_grid[0][0] + return s + + def play(self): + """ Play Conway's Game of Life. """ + + # Write the initial configuration to file. + + self.t = 1 # Current time level + while self.t <= self.T: # Evolve! + # print( "At time level %d" % t) + + # Loop over each cell of the grid and apply Conway's rules. + for i in range(self.N): + for j in range(self.N): + live = self.live_neighbours(i, j) + if (self.old_grid[i][j] == 1 and live < 2): + self.new_grid[i][j] = 0 # Dead from starvation. + elif (self.old_grid[i][j] == 1 and (live == 2 or live == 3)): + self.new_grid[i][j] = 1 # Continue living. + elif (self.old_grid[i][j] == 1 and live > 3): + self.new_grid[i][j] = 0 # Dead from overcrowding. + elif (self.old_grid[i][j] == 0 and live == 3): + self.new_grid[i][j] = 1 # Alive from reproduction. + + # Output the new configuration. + + # The new configuration becomes the old configuration for the next generation. + self.old_grid = self.new_grid.copy() + self.draw_board() + # Move on to the next time level + self.t += 1 + + def init_graphics(self): + self.graph = sg.Graph((600, 600), (0, 0), (450, 450), + key='-GRAPH-', + change_submits=True, + drag_submits=False, + background_color='lightblue') + layout = [ + [sg.Text('Game of Life', font='ANY 15'), + sg.Text('Click below to place cells', key='-OUTPUT-', size=(30, 1), font='ANY 15')], + [self.graph], + [sg.Button('Go!', key='-DONE-'), + sg.Text(' Delay (ms)'), + sg.Slider((0, 800), 100, + orientation='h', + key='-SLIDER-', + enable_events=True, + size=(15, 15)), + sg.Text('', size=(3, 1), key='-S1-OUT-'), + sg.Text(' Num Generations'), sg.Slider([0, 20000], + default_value=4000, + orientation='h', + size=(15, 15), + enable_events=True, + key='-SLIDER2-'), + sg.Text('', size=(3, 1), key='-S2-OUT-')] + ] + + self.window = sg.Window('John Conway\'s Game of Life', layout, finalize=True) + event, values = self.window.read(timeout=0) + self.delay = values['-SLIDER-'] + self.window['-S1-OUT-'].update(values['-SLIDER-']) + self.window['-S2-OUT-'].update(values['-SLIDER2-']) + + def draw_board(self): + BOX_SIZE = 15 + self.graph.erase() + for i in range(self.N): + for j in range(self.N): + if self.old_grid[i][j]: + self.graph.draw_rectangle((i * BOX_SIZE, j * BOX_SIZE), + (i * BOX_SIZE + BOX_SIZE, + j * (BOX_SIZE) + BOX_SIZE), + line_color='black', fill_color='yellow') + event, values = self.window.read(timeout=self.delay) + if event in (sg.WIN_CLOSED, '-DONE-'): + sg.popup('Click OK to exit the program...') + self.window.close() + exit() + self.delay = values['-SLIDER-'] + self.T = int(values['-SLIDER2-']) + self.window['-S1-OUT-'].update(values['-SLIDER-']) + self.window['-S2-OUT-'].update(values['-SLIDER2-']) + self.window['-OUTPUT-'].update('Generation {}'.format(self.t)) + + def manual_board_setup(self): + ids = [] + for i in range(self.N): + ids.append([]) + for j in range(self.N): + ids[i].append(0) + while True: # Event Loop + event, values = self.window.read() + if event == sg.WIN_CLOSED or event == '-DONE-': + break + self.window['-S1-OUT-'].update(values['-SLIDER-']) + self.window['-S2-OUT-'].update(values['-SLIDER2-']) + mouse = values['-GRAPH-'] + + if event == '-GRAPH-': + if mouse == (None, None): + continue + box_x = mouse[0] // BOX_SIZE + box_y = mouse[1] // BOX_SIZE + if self.old_grid[box_x][box_y] == 1: + id_val = ids[box_x][box_y] + self.graph.delete_figure(id_val) + self.old_grid[box_x][box_y] = 0 + else: + id_val = self.graph.draw_rectangle((box_x * BOX_SIZE, box_y * BOX_SIZE), + (box_x * BOX_SIZE + BOX_SIZE, + box_y * (BOX_SIZE) + BOX_SIZE), + line_color='black', fill_color='yellow') + ids[box_x][box_y] = id_val + self.old_grid[box_x][box_y] = 1 + if event == sg.WIN_CLOSED: + self.window.close() + else: + self.window['-DONE-'].update(text='Exit') + + +if (__name__ == "__main__"): + game = GameOfLife(N=35, T=200) + game.play() + sg.popup('Completed running.', 'Click OK to exit the program') + game.window.close() diff --git a/DemoPrograms/Demo_Crossword_Puzzle.py b/DemoPrograms/Demo_Crossword_Puzzle.py index e25d15236..593686bdf 100644 --- a/DemoPrograms/Demo_Crossword_Puzzle.py +++ b/DemoPrograms/Demo_Crossword_Puzzle.py @@ -6,12 +6,6 @@ Demo application to show how to draw rectangles and letters on a Graph Element This demo mocks up a crossword puzzle board It will place a letter where you click on the puzzle - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ diff --git a/DemoPrograms/Demo_Cursor_Previewer.py b/DemoPrograms/Demo_Cursor_Previewer.py deleted file mode 100644 index 6af733840..000000000 --- a/DemoPrograms/Demo_Cursor_Previewer.py +++ /dev/null @@ -1,52 +0,0 @@ -import PySimpleGUI as sg - -""" - Demo - Preview tkinter cursors - - Shows the standard tkinter cursors using Buttons - - The name of the cursor is on the Button. Mouse over the Button and you'll see - what that cursor looks like. - This list of cursors is a constant defined in PySimpleGUI. The constant name is: - sg.TKINTER_CURSORS - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. - -""" - -cursors = sg.TKINTER_CURSORS -# Make a layout that's 10 buttons across -NUM_BUTTONS_PER_ROW = 10 -layout = [[]] -row = [] -for i, c in enumerate(cursors): - # print(i, c) - row.append(sg.Button(c, size=(14,3), k=c)) - if ((i+1) % NUM_BUTTONS_PER_ROW) == 0: - layout.append(row) - row = [] - # print(row) -# Add on the last, partial row -start = len(cursors)//NUM_BUTTONS_PER_ROW * NUM_BUTTONS_PER_ROW -row = [] -for i in range(start, len(cursors)): - row.append(sg.Button(cursors[i], size=(14,3), k=cursors[i])) -layout.append(row) - -window = sg.Window('Cursor Previewer',layout, finalize=True) - -# set the cursor on each of the buttons that has the name of the cursor as the text -for c in cursors: - window[c].set_cursor(c) - -# The ubiquitous event loop... -while True: - event, values = window.read() - if event == sg.WIN_CLOSED: - break - -window.close() \ No newline at end of file diff --git a/DemoPrograms/Demo_Cursors.py b/DemoPrograms/Demo_Cursors.py index 39b2400fa..e050022e0 100644 --- a/DemoPrograms/Demo_Cursors.py +++ b/DemoPrograms/Demo_Cursors.py @@ -9,15 +9,11 @@ If you want no cursor, set the cursor to the string 'none'. - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ # Here is a more complete list of cursors you can choose from -cursors = sg.TKINTER_CURSORS +cursors = ('X_cursor', 'no', 'arrow','based_arrow_down','based_arrow_up','boat','bogosity','bottom_left_corner','bottom_right_corner','bottom_side','bottom_tee','box_spiral','center_ptr','circle','clock','coffee_mug','cross','cross_reverse','crosshair','diamond_cross','dot','dotbox','double_arrow','draft_large','draft_small','draped_box','exchange','fleur','gobbler','gumby','hand1','hand2','heart','icon','iron_cross','left_ptr','left_side','left_tee','leftbutton','ll_angle','lr_angle','man','middlebutton','mouse','no','pencil','pirate','plus','question_arrow','right_ptr','right_side','right_tee','rightbutton','rtl_logo','sailboat','sb_down_arrow','sb_h_double_arrow','sb_left_arrow','sb_right_arrow','sb_up_arrow','sb_v_double_arrow','shuttle','sizing','spider','spraycan','star','target','tcross','top_left_arrow','top_left_corner','top_right_corner','top_side','top_tee','trek','ul_angle','umbrella','ur_angle','watch','xterm','arrow','center_ptr','crosshair','fleur','ibeam','icon','sb_h_double_arrow','sb_v_double_arrow','watch','xterm','no','starting','size','size_ne_sw','size_ns','size_nw_se','size_we','uparrow','wait','arrow','cross','crosshair','ibeam','plus','watch','xterm') sg.theme('Light Blue 2') diff --git a/DemoPrograms/Demo_DOC_Viewer_PIL.py b/DemoPrograms/Demo_DOC_Viewer_PIL.py new file mode 100644 index 000000000..617ae8e42 --- /dev/null +++ b/DemoPrograms/Demo_DOC_Viewer_PIL.py @@ -0,0 +1,237 @@ +""" +@created: 2018-08-19 18:00:00 +@author: (c) 2018 Jorj X. McKie +Display a PyMuPDF Document using Tkinter +------------------------------------------------------------------------------- +Dependencies: +------------- +PyMuPDF, PySimpleGUI (requires Python 3), Tkinter, PIL +License: +-------- +GNU GPL V3+ +Description +------------ +Get filename and start displaying page 1. Please note that all file types +of MuPDF are supported (including EPUB e-books and HTML files for example). +Pages can be directly jumped to, or buttons can be used for paging. + +This version contains enhancements: +* Use of PIL improves response times by a factor 3 or more. +* Zooming is now flexible: only one button serves as a toggle. Arrow keys can + be used for moving the window when zooming. + +We also interpret keyboard events (PageDown / PageUp) and mouse wheel actions +to support paging as if a button was clicked. Similarly, we do not include +a 'Quit' button. Instead, the ESCAPE key can be used, or cancelling the window. +To improve paging performance, we are not directly creating pixmaps from +pages, but instead from the fitz.DisplayList of the page. A display list +will be stored in a list and looked up by page number. This way, zooming +pixmaps and page re-visits will re-use a once-created display list. + +""" +import sys +import fitz +import sys +import PySimpleGUI as sg + +import tkinter as tk +from PIL import Image, ImageTk +import time + +if len(sys.argv) == 1: + fname = sg.popup_get_file('Document Browser', 'Document file to open', + no_window=True, + file_types=( + ("PDF Files", "*.pdf"), + ("XPS Files", "*.*xps"), + ("Epub Files", "*.epub"), + ("Fiction Books", "*.fb2"), + ("Comic Books", "*.cbz"), + ("HTML", "*.htm*") + # add more document types here + ) + ) +else: + fname = sys.argv[1] + +if not fname: + sg.popup("Cancelling:", "No filename supplied") + raise SystemExit("Cancelled: no filename supplied") + +doc = fitz.open(fname) +page_count = len(doc) + +# used for response time statistics only +fitz_img_time = 0.0 +tk_img_time = 0.0 +img_count = 1 + +# allocate storage for page display lists +dlist_tab = [None] * page_count + +title = "PyMuPDF display of '%s', pages: %i" % (fname, page_count) + + +def get_page(pno, zoom=False, max_size=None, first=False): + """Return a PNG image for a document page number. + """ + dlist = dlist_tab[pno] # get display list of page number + if not dlist: # create if not yet there + dlist_tab[pno] = doc[pno].getDisplayList() + dlist = dlist_tab[pno] + r = dlist.rect # the page rectangle + clip = r + # ensure image fits screen: + # exploit, but do not exceed width or height + zoom_0 = 1 + if max_size: + zoom_0 = min(1, max_size[0] / r.width, max_size[1] / r.height) + if zoom_0 == 1: + zoom_0 = min(max_size[0] / r.width, max_size[1] / r.height) + mat_0 = fitz.Matrix(zoom_0, zoom_0) + + if not zoom: # show total page + pix = dlist.getPixmap(matrix=mat_0, alpha=False) + else: + mp = r.tl + (r.br - r.tl) * 0.5 # page rect center + w2 = r.width / 2 + h2 = r.height / 2 + clip = r * 0.5 + tl = zoom[0] # old top-left + tl.x += zoom[1] * (w2 / 2) + tl.x = max(0, tl.x) + tl.x = min(w2, tl.x) + tl.y += zoom[2] * (h2 / 2) + tl.y = max(0, tl.y) + tl.y = min(h2, tl.y) + clip = fitz.Rect(tl, tl.x + w2, tl.y + h2) + + mat = mat_0 * fitz.Matrix(2, 2) # zoom matrix + pix = dlist.getPixmap(alpha=False, matrix=mat, clip=clip) + + if first: # first call: tkinter still inactive + img = pix.getPNGData() # so use fitz png output + else: # else take tk photo image + pilimg = Image.frombytes("RGB", [pix.width, pix.height], pix.samples) + img = ImageTk.PhotoImage(pilimg) + + return img, clip.tl # return image, clip position + + +root = tk.Tk() +max_width = root.winfo_screenwidth() - 20 +max_height = root.winfo_screenheight() - 135 +max_size = (max_width, max_height) +root.destroy() +del root + + +cur_page = 0 +data, clip_pos = get_page(cur_page, zoom=False, max_size=max_size, first=True) + +image_elem = sg.Image(data=data) + +goto = sg.InputText(str(cur_page + 1), size=(5, 1), key="-PageNumber-") + +layout = [[ + sg.ReadButton('Next'), + sg.ReadButton('Prev'), + sg.Text('Page:'), + goto, + sg.Text('(%i)' % page_count), + sg.ReadButton('Zoom'), + sg.Text('(toggle on/off, use arrows to navigate while zooming)'), + ], + [image_elem], +] + +window = sg.Window(title, layout, return_keyboard_events=True, + location=(0, 0), use_default_focus=False, no_titlebar=False) + +# now define the buttons / events we want to handle +enter_buttons = [chr(13), "Return:13"] +quit_buttons = ["Escape:27", chr(27)] +next_buttons = ["Next", "Next:34", "MouseWheel:Down"] +prev_buttons = ["Prev", "Prior:33", "MouseWheel:Up"] +Up = "Up:38" +Left = "Left:37" +Right = "Right:39" +Down = "Down:40" +zoom_buttons = ["Zoom", Up, Down, Left, Right] + +# all the buttons we will handle +my_keys = enter_buttons + next_buttons + prev_buttons + zoom_buttons + +# old page store and zoom toggle +old_page = 0 +old_zoom = False + +while True: + event, value = window.read() + if event == sg.WIN_CLOSED and (value is None or value['-PageNumber-'] is None): + break + if event in quit_buttons: + break + + zoom_pressed = False + zoom = False + + if event in enter_buttons: + try: + cur_page = int(value['-PageNumber-']) - 1 # check if valid + while cur_page < 0: + cur_page += page_count + except: + cur_page = 0 # this guy's trying to fool me + + elif event in next_buttons: + cur_page += 1 + elif event in prev_buttons: + cur_page -= 1 + elif event == Up: + zoom = (clip_pos, 0, -1) + elif event == Down: + zoom = (clip_pos, 0, 1) + elif event == Left: + zoom = (clip_pos, -1, 0) + elif event == Right: + zoom = (clip_pos, 1, 0) + elif event == "Zoom": + zoom_pressed = True + zoom = (clip_pos, 0, 0) + + # sanitize page number + if cur_page >= page_count: # wrap around + cur_page = 0 + while cur_page < 0: # pages > 0 look nicer + cur_page += page_count + + if zoom_pressed and old_zoom: + zoom = zoom_pressed = old_zoom = False + + t0 = time.perf_counter() + data, clip_pos = get_page(cur_page, zoom=zoom, max_size=max_size, + first=False) + t1 = time.perf_counter() + image_elem.update(data=data) + t2 = time.perf_counter() + fitz_img_time += t1 - t0 + tk_img_time += t2 - t1 + img_count += 1 + old_page = cur_page + old_zoom = zoom_pressed or zoom + + # update page number field + if event in my_keys: + goto.update(str(cur_page + 1)) + +window.close() + +# print some response time statistics +if img_count > 0: + print("response times for '%s'" % doc.name) + print("%.4f" % (fitz_img_time/img_count), "sec fitz avg. image time") + print("%.4f" % (tk_img_time/img_count), "sec tk avg. image time") + print("%.4f" % ((fitz_img_time + tk_img_time)/img_count), "sec avg. total time") + print(img_count, "images read") + print(page_count, "pages") diff --git a/DemoPrograms/Demo_Dashboard.py b/DemoPrograms/Demo_Dashboard.py index 49febe6da..1308fff39 100644 --- a/DemoPrograms/Demo_Dashboard.py +++ b/DemoPrograms/Demo_Dashboard.py @@ -3,11 +3,7 @@ """ Dashboard using blocks of information. - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ diff --git a/DemoPrograms/Demo_Date_Chooser.py b/DemoPrograms/Demo_Date_Chooser.py index 3af731578..723e26231 100644 --- a/DemoPrograms/Demo_Date_Chooser.py +++ b/DemoPrograms/Demo_Date_Chooser.py @@ -10,11 +10,7 @@ It is shown here in a demo program form to demonstrate to you that PySimpleGUI is being used to implement user features. The underlying GUI framework is no longer being used like it was previously - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI """ diff --git a/DemoPrograms/Demo_Debugger_Built_Into_PSG.py b/DemoPrograms/Demo_Debugger_Built_Into_PSG.py index 730bf15fd..f95b21a15 100644 --- a/DemoPrograms/Demo_Debugger_Built_Into_PSG.py +++ b/DemoPrograms/Demo_Debugger_Built_Into_PSG.py @@ -16,12 +16,6 @@ 3. You must find a location in your code to "refresh" the debugger. Some loop that's executed often. In this loop add this call: imwatchingyou.refresh() - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ layout = [ diff --git a/DemoPrograms/Demo_Debugger_Button.py b/DemoPrograms/Demo_Debugger_Button.py index 42b8ca9b6..4593346c5 100644 --- a/DemoPrograms/Demo_Debugger_Button.py +++ b/DemoPrograms/Demo_Debugger_Button.py @@ -17,12 +17,6 @@ 3. You must find a location in your code to "refresh" the debugger. Some loop that's executed often. In this loop add this call: imwatchingyou.refresh() - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ layout = [ diff --git a/DemoPrograms/Demo_Debugger_ImWatchingYou.py b/DemoPrograms/Demo_Debugger_ImWatchingYou.py index 72930ee69..00f86b04a 100644 --- a/DemoPrograms/Demo_Debugger_ImWatchingYou.py +++ b/DemoPrograms/Demo_Debugger_ImWatchingYou.py @@ -17,12 +17,6 @@ 3. You must find a location in your code to "refresh" the debugger. Some loop that's executed often. In this loop add this call: imwatchingyou.refresh() - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ layout = [ diff --git a/DemoPrograms/Demo_Demo_Programs_Browser.py b/DemoPrograms/Demo_Demo_Programs_Browser.py index 3855afed6..640256847 100644 --- a/DemoPrograms/Demo_Demo_Programs_Browser.py +++ b/DemoPrograms/Demo_Demo_Programs_Browser.py @@ -31,11 +31,7 @@ Keeps a "history" of the previously chosen folders to easy switching between projects - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI.org """ def running_linux(): diff --git a/DemoPrograms/Demo_Design_Pattern_Multiple_Windows.py b/DemoPrograms/Demo_Design_Pattern_Multiple_Windows.py index ba4ef9d6d..6c8e9defa 100644 --- a/DemoPrograms/Demo_Design_Pattern_Multiple_Windows.py +++ b/DemoPrograms/Demo_Design_Pattern_Multiple_Windows.py @@ -7,11 +7,7 @@ Both windows have buttons to launch popups. The popups are "modal" and thus no other windows will be active - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ def make_win1(): @@ -28,29 +24,23 @@ def make_win2(): [sg.Button('Erase'), sg.Button('Popup'), sg.Button('Exit')]] return sg.Window('Second Window', layout, finalize=True) - - -def main(): - window1, window2 = make_win1(), None # start off with 1 window open - - while True: # Event Loop - window, event, values = sg.read_all_windows() - if event == sg.WIN_CLOSED or event == 'Exit': - window.close() - if window == window2: # if closing win 2, mark as closed - window2 = None - elif window == window1: # if closing win 1, exit program - break - elif event == 'Popup': - sg.popup('This is a BLOCKING popup','all windows remain inactive while popup active') - elif event == 'Launch 2nd Window' and not window2: - window2 = make_win2() - elif event == '-IN-': - window['-OUTPUT-'].update(f'You enetered {values["-IN-"]}') - elif event == 'Erase': - window['-OUTPUT-'].update('') - window['-IN-'].update('') - window.close() - -if __name__ == '__main__': - main() \ No newline at end of file +window1, window2 = make_win1(), None # start off with 1 window open + +while True: # Event Loop + window, event, values = sg.read_all_windows() + if event == sg.WIN_CLOSED or event == 'Exit': + window.close() + if window == window2: # if closing win 2, mark as closed + window2 = None + elif window == window1: # if closing win 1, exit program + break + elif event == 'Popup': + sg.popup('This is a BLOCKING popup','all windows remain inactive while popup active') + elif event == 'Launch 2nd Window' and not window2: + window2 = make_win2() + elif event == '-IN-': + window['-OUTPUT-'].update(f'You enetered {values["-IN-"]}') + elif event == 'Erase': + window['-OUTPUT-'].update('') + window['-IN-'].update('') +window.close() \ No newline at end of file diff --git a/DemoPrograms/Demo_Design_Pattern_Multiple_Windows1.py b/DemoPrograms/Demo_Design_Pattern_Multiple_Windows1.py index e8d9c4ca2..8c7aec144 100644 --- a/DemoPrograms/Demo_Design_Pattern_Multiple_Windows1.py +++ b/DemoPrograms/Demo_Design_Pattern_Multiple_Windows1.py @@ -10,11 +10,7 @@ When Window2 closes, Window1 reappears Program exits when Window1 is closed - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ diff --git a/DemoPrograms/Demo_Design_Pattern_Multiple_Windows2.py b/DemoPrograms/Demo_Design_Pattern_Multiple_Windows2.py index a92d9f87c..f44a250de 100644 --- a/DemoPrograms/Demo_Design_Pattern_Multiple_Windows2.py +++ b/DemoPrograms/Demo_Design_Pattern_Multiple_Windows2.py @@ -8,11 +8,7 @@ Window 1 remains visible and active while Window 2 is active Closing Window 1 exits application - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ diff --git a/DemoPrograms/Demo_Design_Pattern_Multiple_Windows3.py b/DemoPrograms/Demo_Design_Pattern_Multiple_Windows3.py index 5576c988e..a2b9785cc 100644 --- a/DemoPrograms/Demo_Design_Pattern_Multiple_Windows3.py +++ b/DemoPrograms/Demo_Design_Pattern_Multiple_Windows3.py @@ -2,12 +2,6 @@ ''' Example of wizard-like PySimpleGUI windows - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. ''' def make_window1(): diff --git a/DemoPrograms/Demo_Design_Pattern_Multiple_Windows_Both_Visible.py b/DemoPrograms/Demo_Design_Pattern_Multiple_Windows_Both_Visible.py index 0aea3fcd0..c85cb3993 100644 --- a/DemoPrograms/Demo_Design_Pattern_Multiple_Windows_Both_Visible.py +++ b/DemoPrograms/Demo_Design_Pattern_Multiple_Windows_Both_Visible.py @@ -9,11 +9,7 @@ The program exits when both windows have been closed - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ def make_win1(): diff --git a/DemoPrograms/Demo_Design_Pattern_Multiple_Windows_OLD METHOD.py b/DemoPrograms/Demo_Design_Pattern_Multiple_Windows_OLD METHOD.py index 050e83c98..1020bc873 100644 --- a/DemoPrograms/Demo_Design_Pattern_Multiple_Windows_OLD METHOD.py +++ b/DemoPrograms/Demo_Design_Pattern_Multiple_Windows_OLD METHOD.py @@ -6,12 +6,6 @@ 2. The read calls have timeout values of 100 and 0. You can change the 100 to whatever interval you wish but must keep the second window's timeout at 0 3. There is a safeguard to stop from launching multiple copies of window2. Only 1 window2 is visible at a time - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ sg.theme('Dark Blue 3') diff --git a/DemoPrograms/Demo_Design_Pattern_Persistent_Window.py b/DemoPrograms/Demo_Design_Pattern_Persistent_Window.py index 0a6c1c4f7..1ac360887 100644 --- a/DemoPrograms/Demo_Design_Pattern_Persistent_Window.py +++ b/DemoPrograms/Demo_Design_Pattern_Persistent_Window.py @@ -1,13 +1,5 @@ import PySimpleGUI as sg -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - layout = [ [sg.Text('Your typed chars appear here:'), sg.Text(size=(20, 1), key='-OUTPUT-')], diff --git a/DemoPrograms/Demo_Design_Pattern_Save_Theme.py b/DemoPrograms/Demo_Design_Pattern_Save_Theme.py index 74c62078e..3d0e08491 100644 --- a/DemoPrograms/Demo_Design_Pattern_Save_Theme.py +++ b/DemoPrograms/Demo_Design_Pattern_Save_Theme.py @@ -6,11 +6,7 @@ * Saves theme as a user variable * Puts main code into a main function so that multiprocessing works if you later convert to use - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ diff --git a/DemoPrograms/Demo_Design_Patterns.py b/DemoPrograms/Demo_Design_Patterns.py index 31f3f728e..ac4f2db0e 100644 --- a/DemoPrograms/Demo_Design_Patterns.py +++ b/DemoPrograms/Demo_Design_Patterns.py @@ -6,12 +6,6 @@ 2. A "One Shot" window in 1 line of code 3. A persistent window that stays open after button clicks (uses an event loop) 4. A persistent window that need to perform update of an element before the window.read - -Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - -Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - -You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ # -----------------------------------# # DESIGN PATTERN 1 - One-shot Window # diff --git a/DemoPrograms/Demo_Desktop_Floating_Toolbar.py b/DemoPrograms/Demo_Desktop_Floating_Toolbar.py index df771fd23..377be986f 100644 --- a/DemoPrograms/Demo_Desktop_Floating_Toolbar.py +++ b/DemoPrograms/Demo_Desktop_Floating_Toolbar.py @@ -12,12 +12,6 @@ You can setup a specific program to launch when a button is clicked, or use the Combobox to select a .py file found in the root folder, and run that file. - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. - """ ROOT_PATH = './' diff --git a/DemoPrograms/Demo_Desktop_Widget_CPU_Dashboard.py b/DemoPrograms/Demo_Desktop_Widget_CPU_Dashboard.py index 9201c3ecb..333f5a876 100644 --- a/DemoPrograms/Demo_Desktop_Widget_CPU_Dashboard.py +++ b/DemoPrograms/Demo_Desktop_Widget_CPU_Dashboard.py @@ -15,11 +15,7 @@ Grab anywhere, making window easy to move around Note that the keys are tuples, with a tuple as the second item ('-KEY-', (row, col)) - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI """ GRAPH_WIDTH = 120 # each individual graph size in pixels @@ -69,7 +65,8 @@ def GraphColumn(name, key): sg.theme('Black') - layout = [[sg.Text('CPU Core Usage', justification='c', expand_x=True)] ] + layout = [[ sg.Text(sg.SYMBOL_X, enable_events=True, key='Exit', tooltip='Closes window'), + sg.Text(' CPU Core Usage')] ] # add on the graphs for rows in range(num_cores//NUM_COLS+1): @@ -88,9 +85,7 @@ def GraphColumn(name, key): margins=(1,1), element_padding=(0,0), border_depth=0, - location=location, - enable_close_attempted_event=True, - right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT) + location=location) graphs = [] @@ -100,20 +95,12 @@ def GraphColumn(name, key): window[('-TXT-', (rows, cols))], 0, colors[(rows*NUM_COLS+cols)%len(colors)])] - # ---------------- main loop ---------------- while True : # --------- Read and update window once every Polling Frequency -------- event, values = window.read(timeout=POLL_FREQUENCY) - if event in (sg.WIN_CLOSE_ATTEMPTED_EVENT, 'Exit'): # Be nice and give an exit - sg.user_settings_set_entry('-location-', window.current_location()) # save window location before exiting - break - elif event == sg.WIN_CLOSED: + if event in (sg.WIN_CLOSED, 'Exit'): # Be nice and give an exit break - elif event == 'Edit Me': - sg.execute_editor(__file__) - elif event == 'Version': - sg.popup_scrolled(__file__, sg.get_versions(), keep_on_top=True, location=window.current_location()) # read CPU for each core stats = psutil.cpu_percent(percpu=True) @@ -130,6 +117,5 @@ def GraphColumn(name, key): location = sys.argv[1].split(',') location = (int(location[0]), int(location[1])) else: - location = sg.user_settings_get_entry('-location-', (None, None)) - + location = (None, None) main(location) \ No newline at end of file diff --git a/DemoPrograms/Demo_Desktop_Widget_CPU_Gauge.py b/DemoPrograms/Demo_Desktop_Widget_CPU_Gauge.py index b64fbe7a6..a387b1ac3 100644 --- a/DemoPrograms/Demo_Desktop_Widget_CPU_Gauge.py +++ b/DemoPrograms/Demo_Desktop_Widget_CPU_Gauge.py @@ -14,11 +14,7 @@ This is a good example of how you can use Graph Elements to create your own custom elements. This Gauge element is created from a Graph element. - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ class Gauge(): @@ -46,7 +42,7 @@ def add(number1, number2): : Return Addition result for number1 and number2. """ - return number1 + number2 + return number1 + number1 def limit(number): """ @@ -278,7 +274,7 @@ def main(location): [sg.T(size=(5, 1), font='Any 20', justification='c', background_color='black', k='-gauge VALUE-')]] - window = sg.Window('CPU Usage Widget Square', layout, location=location, no_titlebar=True, grab_anywhere=True, margins=(0, 0), element_padding=(0, 0), alpha_channel=ALPHA, background_color='black', element_justification='c', finalize=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT, enable_close_attempted_event=True) + window = sg.Window('CPU Usage Widget Square', layout, location=location, no_titlebar=True, grab_anywhere=True, margins=(0, 0), element_padding=(0, 0), alpha_channel=ALPHA, background_color='black', element_justification='c', finalize=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_EXIT) gauge = Gauge(pointer_color=sg.theme_text_color(), clock_color=sg.theme_text_color(), major_tick_color=sg.theme_text_color(), minor_tick_color=sg.theme_input_background_color(), pointer_outer_color=sg.theme_text_color(), major_tick_start_radius=45, @@ -297,13 +293,10 @@ def main(location): # ----------- update the graphics and text in the window ------------ # update the window, wait for a while, then check for exit event, values = window.read(timeout=UPDATE_FREQUENCY_MILLISECONDS) - if event in (sg.WIN_CLOSE_ATTEMPTED_EVENT, 'Exit'): - sg.user_settings_set_entry('-location-', window.current_location()) # The line of code to save the position before exiting + if event == sg.WIN_CLOSED or event == 'Exit': break if event == 'Edit Me': sg.execute_editor(__file__) - elif event == 'Version': - sg.popup_scrolled(__file__, sg.get_versions(), location=window.current_location(), keep_on_top=True, non_blocking=True) window.close() @@ -313,5 +306,5 @@ def main(location): location = sys.argv[1].split(',') location = (int(location[0]), int(location[1])) else: - location = sg.user_settings_get_entry('-location-', (None, None)) + location = (None, None) main(location) diff --git a/DemoPrograms/Demo_Desktop_Widget_CPU_Graph.py b/DemoPrograms/Demo_Desktop_Widget_CPU_Graph.py index acb5e4980..8e853f4e0 100644 --- a/DemoPrograms/Demo_Desktop_Widget_CPU_Graph.py +++ b/DemoPrograms/Demo_Desktop_Widget_CPU_Graph.py @@ -4,14 +4,6 @@ import psutil from threading import Thread -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - STEP_SIZE = 3 SAMPLES = 300 diff --git a/DemoPrograms/Demo_Desktop_Widget_CPU_Grid_Of_Gauges.py b/DemoPrograms/Demo_Desktop_Widget_CPU_Grid_Of_Gauges.py index 0b6f95a33..96ecd7385 100644 --- a/DemoPrograms/Demo_Desktop_Widget_CPU_Grid_Of_Gauges.py +++ b/DemoPrograms/Demo_Desktop_Widget_CPU_Grid_Of_Gauges.py @@ -2,7 +2,6 @@ import PySimpleGUI as sg import sys import psutil -import math """ Desktop floating widget - CPU Cores as Gauges @@ -15,24 +14,23 @@ An alpha-channel setting of 0.8 to give a little transparency No titlebar Grab anywhere, making window easy to move around - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI """ -# gsize = (120, 75) -# gsize = (85, 40) -gsize = (55, 30) - +GRAPH_WIDTH = 120 # each individual graph size in pixels +GRAPH_HEIGHT = 40 TRANSPARENCY = .8 # how transparent the window looks. 0 = invisible, 1 = normal window NUM_COLS = 4 -POLL_FREQUENCY = 1500 # how often to update graphs in milliseconds +POLL_FREQUENCY = 2000 # how often to update graphs in milliseconds colors = ('#23a0a0', '#56d856', '#be45be', '#5681d8', '#d34545', '#BE7C29') + +import math +import random + + class Gauge(): def mapping(func, sequence, *argc): """ @@ -58,7 +56,7 @@ def add(number1, number2): : Return Addition result for number1 and number2. """ - return number1 + number2 + return number1 + number1 def limit(number): """ @@ -69,6 +67,7 @@ def limit(number): angel degree in 0 ~ 360, return 0 if number < 0, 360 if number > 360. """ return max(min(360, number), 0) + class Clock(): """ Draw background circle or arc @@ -135,7 +134,7 @@ def __init__(self, center_x=0, center_y=0, angle=0, inner_radius=20, self.figure = [] self.stop_angle = angle self.graph_elem = graph_elem - self.new(degree=angle, color=pointer_color) + self.new(degree=angle) def new(self, degree=0, color=None): """ @@ -225,10 +224,10 @@ def move(self, delta_x, delta_y): All angles defined as count clockwise from negative x-axis. Should create instance of clock, pointer, minor tick and major tick first. """ - def __init__(self, center=(0, 0), start_angle=0, stop_angle=180, major_tick_width=5, minor_tick_width=2,major_tick_start_radius=90, major_tick_stop_radius=100, minor_tick_step=5, major_tick_step=30, clock_radius=100, pointer_line_width=5, pointer_inner_radius=10, pointer_outer_radius=75, pointer_color='white', pointer_origin_color='black', pointer_outer_color='white', pointer_angle=0, degree=0, clock_color='white', major_tick_color='black', minor_tick_color='black', minor_tick_start_radius=90, minor_tick_stop_radius=100, graph_elem=None): + def __init__(self, center=(0, 0), start_angle=0, stop_angle=180, major_tick_width=5, minor_tick_width=2,major_tick_start_radius=90, major_tick_stop_radius=100, major_tick_step=30, clock_radius=100, pointer_line_width=5, pointer_inner_radius=10, pointer_outer_radius=75, pointer_color='white', pointer_origin_color='black', pointer_outer_color='white', pointer_angle=0, degree=0, clock_color='white', major_tick_color='black', minor_tick_color='black', minor_tick_start_radius=90, minor_tick_stop_radius=100, graph_elem=None): self.clock = Gauge.Clock(start_angle=start_angle, stop_angle=stop_angle, fill_color=clock_color, radius=clock_radius, graph_elem=graph_elem) - self.minor_tick = Gauge.Tick(start_angle=start_angle, stop_angle=stop_angle, line_width=minor_tick_width, line_color=minor_tick_color, start_radius=minor_tick_start_radius, stop_radius=minor_tick_stop_radius, graph_elem=graph_elem, step=minor_tick_step) + self.minor_tick = Gauge.Tick(start_angle=start_angle, stop_angle=stop_angle, line_width=minor_tick_width, line_color=minor_tick_color, start_radius=minor_tick_start_radius, stop_radius=minor_tick_stop_radius, graph_elem=graph_elem) self.major_tick = Gauge.Tick(start_angle=start_angle, stop_angle=stop_angle, line_width=major_tick_width, start_radius=major_tick_start_radius, stop_radius=major_tick_stop_radius, step=major_tick_step, line_color=major_tick_color, graph_elem=graph_elem) self.pointer = Gauge.Pointer(angle=pointer_angle, inner_radius=pointer_inner_radius, outer_radius=pointer_outer_radius, pointer_color=pointer_color, outer_color=pointer_outer_color, origin_color=pointer_origin_color, line_width=pointer_line_width, graph_elem=graph_elem) @@ -251,7 +250,7 @@ def move(self, delta_x, delta_y): if self.pointer: self.pointer.move(delta_x, delta_y) - def change(self, degree=None, step=1, pointer_color=None): + def change(self, degree=None, step=1): """ Rotation of pointer call it with degree and step to set initial options for rotation. @@ -267,17 +266,17 @@ def change(self, degree=None, step=1, pointer_color=None): new_degree = now + step if ((step > 0 and new_degree < self.pointer.stop_degree) or (step < 0 and new_degree > self.pointer.stop_degree)): - self.pointer.new(degree=new_degree, color=pointer_color) + self.pointer.new(degree=new_degree, color='red' if new_degree > 90 else None) return False else: - self.pointer.new(degree=self.pointer.stop_degree, color=pointer_color) + self.pointer.new(degree=self.pointer.stop_degree, color='red' if self.pointer.stop_degree > 90 else None) return True -# ------------------------------ BEGINNING OF CPU WIDGET GUI CODE ------------------------------ + # DashGraph does the drawing of each graph class DashGraph(object): - def __init__(self, gsize, graph_elem, text_elem, starting_count, color): + def __init__(self, graph_elem, text_elem, starting_count, color): self.graph_current_item = 0 self.graph_elem = graph_elem # type: sg.Graph self.text_elem = text_elem @@ -286,36 +285,26 @@ def __init__(self, gsize, graph_elem, text_elem, starting_count, color): self.color = color self.line_list = [] # list of currently visible lines. Used to delete oild figures - self.gauge = Gauge(pointer_color=color, - clock_color=color, - major_tick_color=color, - minor_tick_color=color, - pointer_outer_color=color, - major_tick_start_radius=gsize[1] - 10, - minor_tick_start_radius=gsize[1] - 10, - minor_tick_stop_radius=gsize[1] - 5, - major_tick_stop_radius=gsize[1] - 5, - clock_radius=gsize[1] - 5, - pointer_outer_radius=gsize[1] - 5, - major_tick_step=30, - minor_tick_step=15, - pointer_line_width=3, - pointer_inner_radius=10, - graph_elem=graph_elem) - + self.gauge = Gauge(pointer_color=color, clock_color=color, major_tick_color=color, + minor_tick_color=color, pointer_outer_color=sg.theme_text_color(), major_tick_start_radius=45, + minor_tick_start_radius=45, minor_tick_stop_radius=50, major_tick_stop_radius=50, major_tick_step=30, clock_radius=50, pointer_line_width=3, + pointer_inner_radius=10, pointer_outer_radius=50, graph_elem=graph_elem) self.gauge.change(degree=0) def graph_percentage_abs(self, value): - if self.gauge.change(pointer_color='red' if value > 50 else None): + if self.gauge.change(): new_angle = value*180/100 - self.gauge.change(degree=new_angle, step=100, pointer_color='red' if value > 50 else None) - self.gauge.change(pointer_color='red' if value > 50 else None) + self.gauge.change(degree=new_angle, step=new_angle) + self.gauge.change() def text_display(self, text): self.text_elem.update(text) def main(location): + gsize = (100, 55) + + # A couple of "User defined elements" that combine several elements and enable bulk edits def Txt(text, **kwargs): return(sg.Text(text, font=('Helvetica 8'), **kwargs)) @@ -323,7 +312,7 @@ def Txt(text, **kwargs): def GraphColumn(name, key): layout = [ [sg.Graph(gsize, (-gsize[0] // 2, 0), (gsize[0] // 2, gsize[1]), key=key+'-GRAPH-')], - [sg.T(size=(5, 1), justification='c', font='Courier 10', k=key+'-GAUGE VALUE-')]] + [sg.T(size=(5, 1), justification='c', font='Courier 14', k=key+'-GAUGE VALUE-')]] return sg.Column(layout, pad=(2, 2), element_justification='c') num_cores = len(psutil.cpu_percent(percpu=True)) # get the number of cores in the CPU @@ -331,7 +320,9 @@ def GraphColumn(name, key): sg.theme('black') sg.set_options(element_padding=(0,0), margins=(1,1), border_width=0) - layout = [[ sg.Button(image_data=sg.red_x, button_color=('black', 'black'), key='Exit', tooltip='Closes window'), + # the clever Red X graphic + red_x = "R0lGODlhEAAQAPeQAIsAAI0AAI4AAI8AAJIAAJUAAJQCApkAAJoAAJ4AAJkJCaAAAKYAAKcAAKcCAKcDA6cGAKgAAKsAAKsCAKwAAK0AAK8AAK4CAK8DAqUJAKULAKwLALAAALEAALIAALMAALMDALQAALUAALYAALcEALoAALsAALsCALwAAL8AALkJAL4NAL8NAKoTAKwbAbEQALMVAL0QAL0RAKsREaodHbkQELMsALg2ALk3ALs+ALE2FbgpKbA1Nbc1Nb44N8AAAMIWAMsvAMUgDMcxAKVABb9NBbVJErFYEq1iMrtoMr5kP8BKAMFLAMxKANBBANFCANJFANFEB9JKAMFcANFZANZcANpfAMJUEMZVEc5hAM5pAMluBdRsANR8AM9YOrdERMpIQs1UVMR5WNt8X8VgYMdlZcxtYtx4YNF/btp9eraNf9qXXNCCZsyLeNSLd8SSecySf82kd9qqc9uBgdyBgd+EhN6JgtSIiNuJieGHhOGLg+GKhOKamty1ste4sNO+ueenp+inp+HHrebGrefKuOPTzejWzera1O7b1vLb2/bl4vTu7fbw7ffx7vnz8f///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAJAALAAAAAAQABAAAAjUACEJHEiwYEEABniQKfNFgQCDkATQwAMokEU+PQgUFDAjjR09e/LUmUNnh8aBCcCgUeRmzBkzie6EeQBAoAAMXuA8ciRGCaJHfXzUMCAQgYooWN48anTokR8dQk4sELggBhQrU9Q8evSHiJQgLCIIfMDCSZUjhbYuQkLFCRAMAiOQGGLE0CNBcZYmaRIDLqQFGF60eTRoSxc5jwjhACFWIAgMLtgUocJFy5orL0IQRHAiQgsbRZYswbEhBIiCCH6EiJAhAwQMKU5DjHCi9gnZEHMTDAgAOw==" + layout = [[ sg.Button(image_data=red_x, button_color=('black', 'black'), key='Exit', tooltip='Closes window'), sg.Text(' CPU Core Usage')] ] # add on the graphs @@ -351,12 +342,10 @@ def GraphColumn(name, key): use_default_focus=False, finalize=True, location=location, - right_click_menu=[[''], 'Exit'], - # transparent_color='black', - ) + right_click_menu=[[''], 'Exit']) # setup graphs & initial values - graphs = [DashGraph(gsize, window['-CPU-'+str(i)+'-GRAPH-'], + graphs = [DashGraph(window['-CPU-'+str(i)+'-GRAPH-'], window['-CPU-'+str(i) + '-GAUGE VALUE-'], 0, colors[i%6]) for i in range(num_cores) ] diff --git a/DemoPrograms/Demo_Desktop_Widget_CPU_Square.py b/DemoPrograms/Demo_Desktop_Widget_CPU_Square.py index 28f87bc39..7d2a66190 100644 --- a/DemoPrograms/Demo_Desktop_Widget_CPU_Square.py +++ b/DemoPrograms/Demo_Desktop_Widget_CPU_Square.py @@ -4,32 +4,32 @@ """ Another simple Desktop Widget using PySimpleGUI - This time a CPU Usage indicator. The Widget is square. + This time a RAM indicator. The Widget is square. The bottom section will be shaded to represent the total amount CPU currently in use. Uses the theme's button color for colors. - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ ALPHA = 0.5 -THEME = 'Dark purple 6' +THEME = 'Dark purple 6 ' GSIZE = (160, 160) UPDATE_FREQUENCY_MILLISECONDS = 2 * 1000 -def main(location): - graph = sg.Graph(GSIZE, (0, 0), GSIZE, key='-GRAPH-') +def human_size(bytes, units=(' bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB')): + """ Returns a human readable string reprentation of bytes""" + return str(bytes) + ' ' + units[0] if bytes < 1024 else human_size(bytes >> 10, units[1:]) + +def main(location): + graph = sg.Graph(GSIZE, (0, 0), GSIZE, key='-GRAPH-', enable_events=True) layout = [[graph]] - window = sg.Window('CPU Usage Widget Square', layout, location=location, no_titlebar=True, grab_anywhere=True, margins=(0, 0), element_padding=(0, 0), alpha_channel=ALPHA, finalize=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT, enable_close_attempted_event=True) + window = sg.Window('CPU Usage Widget Square', layout, location=location, no_titlebar=True, grab_anywhere=True, margins=(0, 0), element_padding=(0, 0), alpha_channel=ALPHA, finalize=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_EXIT) - text_id2 = graph.draw_text(f'CPU', (GSIZE[0] // 2, GSIZE[1] // 4), font='Any 20', text_location=sg.TEXT_LOCATION_CENTER, color=sg.theme_button_color()[0]) + text_id2 = graph.draw_text(f'CPU', (GSIZE[0] // 2, GSIZE[1] // 4), font='Any 20', text_location=sg.TEXT_LOCATION_CENTER, color=sg.theme_button_color()[0]) while True: # Event Loop @@ -45,13 +45,10 @@ def main(location): # update the window, wait for a while, then check for exit event, values = window.read(timeout=UPDATE_FREQUENCY_MILLISECONDS) - if event in (sg.WIN_CLOSE_ATTEMPTED_EVENT, 'Exit'): - sg.user_settings_set_entry('-location-', window.current_location()) # The line of code to save the position before exiting + if event == sg.WIN_CLOSED or event == 'Exit': break if event == 'Edit Me': sg.execute_editor(__file__) - elif event == 'Version': - sg.popup_scrolled(__file__, sg.get_versions(), location=window.current_location(), keep_on_top=True, non_blocking=True) # erase figures so they can be redrawn graph.delete_figure(rect_id) graph.delete_figure(text_id1) @@ -65,5 +62,5 @@ def main(location): location = sys.argv[1].split(',') location = (int(location[0]), int(location[1])) else: - location = sg.user_settings_get_entry('-location-', (None, None)) + location = (None, None) main(location) diff --git a/DemoPrograms/Demo_Desktop_Widget_CPU_Top_Processes.py b/DemoPrograms/Demo_Desktop_Widget_CPU_Top_Processes.py index 2e60db99b..e18532396 100644 --- a/DemoPrograms/Demo_Desktop_Widget_CPU_Top_Processes.py +++ b/DemoPrograms/Demo_Desktop_Widget_CPU_Top_Processes.py @@ -1,95 +1,105 @@ #!/usr/bin/env python import PySimpleGUI as sg import psutil +import time +from threading import Thread import operator +import sys """ - PSUTIL "Top" CPU Processes - Desktop Widget - - Creates a floating CPU utilization window running something similar to a "top" command. - + PSUTIL Desktop Widget + Creates a floating CPU utilization window that is always on top of other windows + You move it by grabbing anywhere on the window + Good example of how to do a non-blocking, polling program using PySimpleGUI Use the spinner to adjust the number of seconds between readings of the CPU utilizaiton - Rather than calling the threading module this program uses the PySimpleGUI perform_long_operation method. - The result is similar. The function is run as a thread... the call is simply wrapped. - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + + NOTE - you will get a warning message printed when you exit using exit button. + It will look something like: + invalid command name "1616802625480StopMove" """ -# global used to communicate with thread. -g_interval = 1 # how often to poll for CPU usage +# globale used to communicate with thread.. yea yea... it's working fine +g_interval = 1 +g_cpu_percent = 0 +g_procs = None +g_exit = False -def CPU_thread(window:sg.Window): - while True: - cpu_percent = psutil.cpu_percent(interval=g_interval) - procs = psutil.process_iter() - window.write_event_value('-CPU UPDATE FROM THREAD-', (cpu_percent, procs)) +def CPU_thread(args): + global g_interval, g_cpu_percent, g_procs, g_exit + while not g_exit: + try: + g_cpu_percent = psutil.cpu_percent(interval=g_interval) + g_procs = psutil.process_iter() + except: + pass -def main(): - global g_interval - location = sg.user_settings_get_entry('-location-', (None, None)) +def main(location): + global g_interval, g_procs, g_exit # ---------------- Create Form ---------------- sg.theme('Black') + layout = [ + [sg.Text('', size=(8, 1), font=('Helvetica', 20), + text_color=sg.YELLOWS[0], justification='center', key='text')], + [sg.Text('', size=(30, 8), font=('Courier New', 12), + text_color='white', justification='left', key='processes')], + [sg.Text('Update every '), + sg.Spin([x+1 for x in range(10)], 3, key='spin'), sg.T('seconds '), + sg.Text('❎', enable_events=True, key='Exit') + ] + ] - layout = [[sg.Text(font=('Helvetica', 20), text_color=sg.YELLOWS[0], key='-CPU PERCENT-')], - [sg.Text(size=(35, 12), font=('Courier New', 12), key='-PROCESSES-')], # size will determine how many processes shown - [sg.Text('Update every '), sg.Spin([x+1 for x in range(10)], 3, key='-SPIN-'), sg.T('seconds')]] - - window = sg.Window('Top CPU Processes', layout, no_titlebar=True, keep_on_top=True,location=location, use_default_focus=False, alpha_channel=.8, grab_anywhere=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT, enable_close_attempted_event=True) + window = sg.Window('Top CPU Processes', layout, + no_titlebar=True, keep_on_top=True,location=location, use_default_focus=False, alpha_channel=.8, grab_anywhere=True) # start cpu measurement thread - # using the PySimpleGUI call to start and manage the thread - window.start_thread(lambda: CPU_thread(window), '-THREAD FINISHED-') + thread = Thread(target=CPU_thread, args=(None,)) + thread.start() + timeout_value = 1 # make first read really quick g_interval = 1 - # Unusual construct of a Try around entire event loop... something is crashing, we need to find out what... - try: - # ---------------- main loop ---------------- - while True: - # --------- Read and update window -------- - event, values = window.read() - # print(event, values) - # --------- Do Button Operations -------- - if event in (sg.WIN_CLOSE_ATTEMPTED_EVENT, 'Exit'): - sg.user_settings_set_entry('-location-', window.current_location()) # save window location before exiting - break - if event == 'Edit Me': - sp = sg.execute_editor(__file__) - elif event == 'Version': - sg.popup_scrolled(__file__, sg.get_versions(), keep_on_top=True, location=window.current_location()) - elif event == '-CPU UPDATE FROM THREAD-': # indicates data from the thread has arrived - cpu_percent, procs = values[event] # the thread sends a tuple - if procs: - # --------- Create dictionary of top % CPU processes. Format is name:cpu_percent -------- - top = {} - for proc in procs: - try: - top[proc.name()] = proc.cpu_percent() - except Exception as e: - pass # it's OK to get an exception here because processes come and go... one may have gone... - # sg.Print('*** GOT Exception looping through procs ***', c='white on red', font='_ 18') - # sg.Print('Exception = ', e, 'procs=', procs, 'proc', proc) - - top_sorted = sorted(top.items(), key=operator.itemgetter(1), reverse=True) # reverse sort to get highest CPU usage on top - if top_sorted: - top_sorted.pop(0) # remove the idle process - display_string = '\n'.join([f'{cpu/10:2.2f} {proc:23}' for proc, cpu in top_sorted]) - # --------- Display timer and proceses in window -------- - window['-CPU PERCENT-'].update(f'CPU {cpu_percent}') - window['-PROCESSES-'].update(display_string) - # get the timeout from the spinner - g_interval = int(values['-SPIN-']) - except Exception as e: - sg.Print('*** GOT Exception in event loop ***', c='white on red', font='_ 18') - sg.Print('Exception = ', e, wait=True) # IMPORTANT to add a wait/blocking so that the print pauses execution. Otherwise program continue and exits + # ---------------- main loop ---------------- + while True: + # --------- Read and update window -------- + event, values = window.read(timeout_value) + # --------- Do Button Operations -------- + if event in (sg.WIN_CLOSED, 'Exit'): + break + + timeout_value = int(values['spin']) * 1000 # for now on, use spinner for timeout + + cpu_percent = g_cpu_percent + display_string = '' + if g_procs: + # --------- Create list of top % CPU porocesses -------- + try: + top = {proc.name(): proc.cpu_percent() for proc in g_procs} + except: + pass + + top_sorted = sorted( + top.items(), key=operator.itemgetter(1), reverse=True) + if top_sorted: + top_sorted.pop(0) + display_string = '' + for proc, cpu in top_sorted: + display_string += '{:2.2f} {}\n'.format(cpu/10, proc) + + # --------- Display timer and proceses in window -------- + window['text'].update('CPU ' + str(cpu_percent)) + window['processes'].update(display_string) + + g_exit = True + thread.join() window.close() if __name__ == '__main__': - main() + if len(sys.argv) > 1: + location = sys.argv[1].split(',') + location = (int(location[0]), int(location[1])) + else: + location = (None, None) + main(location) diff --git a/DemoPrograms/Demo_Desktop_Widget_CPU_Utilization_Simple.py b/DemoPrograms/Demo_Desktop_Widget_CPU_Utilization_Simple.py index 275e25a70..3169bf2df 100644 --- a/DemoPrograms/Demo_Desktop_Widget_CPU_Utilization_Simple.py +++ b/DemoPrograms/Demo_Desktop_Widget_CPU_Utilization_Simple.py @@ -2,14 +2,6 @@ import PySimpleGUI as sg import psutil -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - # Yet another usage of CPU data # ---------------- Create Form ---------------- diff --git a/DemoPrograms/Demo_Desktop_Widget_Count_To_A_Goal.py b/DemoPrograms/Demo_Desktop_Widget_Count_To_A_Goal.py index e447acb80..f53b2d943 100644 --- a/DemoPrograms/Demo_Desktop_Widget_Count_To_A_Goal.py +++ b/DemoPrograms/Demo_Desktop_Widget_Count_To_A_Goal.py @@ -12,11 +12,7 @@ you the current count and the total along with your % complete via a gauge. (Again, thank you to Jason for the gauge!) - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ ALPHA = 0.9 # Initial alpha until user changes @@ -54,7 +50,7 @@ def add(number1, number2): : Return Addition result for number1 and number2. """ - return number1 + number2 + return number1 + number1 def limit(number): """ diff --git a/DemoPrograms/Demo_Desktop_Widget_Date.py b/DemoPrograms/Demo_Desktop_Widget_Date.py index 628ad48ef..b4a3d8874 100644 --- a/DemoPrograms/Demo_Desktop_Widget_Date.py +++ b/DemoPrograms/Demo_Desktop_Widget_Date.py @@ -9,11 +9,7 @@ You can change the format by modifying the function get_date_string - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ ALPHA = 0.9 # Initial alpha until user changes diff --git a/DemoPrograms/Demo_Desktop_Widget_Days_Counter.py b/DemoPrograms/Demo_Desktop_Widget_Days_Counter.py index 291407bc7..4d8aa1349 100644 --- a/DemoPrograms/Demo_Desktop_Widget_Days_Counter.py +++ b/DemoPrograms/Demo_Desktop_Widget_Days_Counter.py @@ -11,11 +11,7 @@ Or perhaps when you got married.... or divorced.... or stopped some activity Or started some activity.... you get the idea. It tracks a time delta in days - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ ALPHA = 0.9 # Initial alpha until user changes diff --git a/DemoPrograms/Demo_Desktop_Widget_Days_Until_Date.pyw b/DemoPrograms/Demo_Desktop_Widget_Days_Until_Date.pyw new file mode 100644 index 000000000..45fd8e117 --- /dev/null +++ b/DemoPrograms/Demo_Desktop_Widget_Days_Until_Date.pyw @@ -0,0 +1,189 @@ +import PySimpleGUI as sg +import sys +import datetime + +""" + Another simple Desktop Widget using PySimpleGUI + The "Days UNTIL _______" Desktop Widget (Like Rainmeter) + + This widget counts the number of days UNTIL some date of your choosing. + Maybe you want to track the number of days until an anniversary? + + Unlike other demos, this one is being released as a .pyw file. If launched on Windows, open with Pythonw.exe so + that you don't get a console Window. That's how these desktop widgets are supposed to be launched, with no + console. I usually launch them from another Python program that starts them all at once using the Exec APIs + built into PySimpleGUI. + + Copyright 2021 PySimpleGUI Project +""" + +ALPHA = 0.9 # Initial alpha until user changes +THEME = 'Dark green 3' # Initial theme until user changes +refresh_font = sg.user_settings_get_entry('-refresh font-', 'Courier 8') +title_font = sg.user_settings_get_entry('-title font-', 'Courier 8') +main_number_font = sg.user_settings_get_entry('-main number font-', 'Courier 70') +main_info_size = (None, 1) +# May add ability to change theme from the user interface. For now forcing to constant + +UPDATE_FREQUENCY_MILLISECONDS = 1000 * 60 * 60 # update every hour + + +def choose_theme(location): + layout = [[sg.Text(f'Current theme {sg.theme()}')], + [sg.Listbox(values=sg.theme_list(), size=(20, 20), key='-LIST-', enable_events=True)], + [sg.OK(), sg.Cancel()]] + + window = sg.Window('Look and Feel Browser', layout, location=location, keep_on_top=True) + old_theme = sg.theme() + while True: # Event Loop + event, values = window.read() + if event in (sg.WIN_CLOSED, 'Exit', 'OK', 'Cancel'): + break + sg.theme(values['-LIST-'][0]) + test_window = make_window(location=(location[0] - 200, location[1]), test_window=True) + test_window.read(close=True) + window.close() + + if event == 'OK' and values['-LIST-']: + sg.theme(values['-LIST-'][0]) + sg.user_settings_set_entry('-theme-', values['-LIST-'][0]) + return values['-LIST-'][0] + else: + sg.theme(old_theme) + return None + + +def make_window(location, test_window=False): + title_font = sg.user_settings_get_entry('-title font-', 'Courier 8') + title = sg.user_settings_get_entry('-title-', '') + main_number_font = sg.user_settings_get_entry('-main number font-', 'Courier 70') + + if not test_window: + theme = sg.user_settings_get_entry('-theme-', THEME) + sg.theme(theme) + + alpha = sg.user_settings_get_entry('-alpha-', ALPHA) + + # ------------------- Window Layout ------------------- + # If this is a test window (for choosing theme), then uses some extra Text Elements to display theme info + # and also enables events for the elements to make the window easy to close + if test_window: + top_elements = [[sg.Text(title, font=title_font, justification='c', k='-TITLE-', enable_events=True)], + [sg.Text('Click to close', font=title_font, enable_events=True)], + [sg.Text('This is theme', font=title_font, enable_events=True)], + [sg.Text(sg.theme(), font=title_font, enable_events=True)]] + right_click_menu = [[''], ['Exit', ]] + else: + top_elements = [[sg.Text(title, size=(20, 1), font=title_font, justification='c', k='-TITLE-')]] + right_click_menu = [[''], + ['Choose Date', 'Choose Title', '---', 'Set Title Font', 'Set Main Font', 'Edit Me', 'Change Theme', '---', 'Refresh', 'Show Refresh Info', 'Hide Refresh Info', '---', 'Alpha', [str(x) for x in range(1, 11)], '---', 'Show Debug Info', 'Route Print To Screen', 'Stop print to screen', 'Exit', ]] + + layout = top_elements + \ + [[sg.pin(sg.Text('0', size=main_info_size, font=main_number_font, k='-MAIN INFO NUM-', justification='c', enable_events=test_window, pad=(0, 0)))], + [sg.pin(sg.Text(size=(15, None), font=refresh_font, k='-REFRESHED-', justification='c', visible=sg.user_settings_get_entry('-show refresh-', False)))]] + + try: + window = sg.Window('Day Number', layout, location=location, no_titlebar=True, grab_anywhere=True, margins=(0, 0), element_justification='c', + element_padding=(0, 0), alpha_channel=alpha, finalize=True, right_click_menu=right_click_menu, right_click_menu_tearoff=False, + keep_on_top=True, enable_close_attempted_event=True) + except Exception as e: + if sg.popup_yes_no('Error creating your window', e, 'These are your current settings:', sg.user_settings(), + 'Do you want to delete your settings file?') == 'Yes': + sg.user_settings_delete_filename() + sg.popup('Settings deleted.', 'Please restart your program') + exit() + window = None + + return window + + +def main(location): + if sg.user_settings_get_entry('-end date-', None) is None: + sg.popup('You have no yet set up an end date - set an end date to begin.', + 'When you close this Window you will be shown a calendar to choose an ending date.') + new_end = sg.popup_get_date( keep_on_top=True) + if new_end is not None: + sg.user_settings_set_entry('-end date-', new_end) + else: + sg.popup_error('You have to set an end date to use this program. Try again later when you are ready to begin for real....') + exit() + loc = sg.user_settings_get_entry('-location-', location) + if sg.user_settings_get_entry('-print to debug-', False) is True: + mprint = sg.Print + else: + mprint = print + window = make_window(loc) + + saved_date = sg.user_settings_get_entry('-end date-', (1, 1, 2021)) + end_date = datetime.datetime(saved_date[2], saved_date[0], saved_date[1]) + + while True: # Event Loop + # First update the status information + delta = end_date - datetime.datetime.now() + title_data = delta.days + 1 + msg_num = f'{title_data}' + window['-MAIN INFO NUM-'].update(msg_num) + # for debugging show the last update date time + window['-REFRESHED-'].update(datetime.datetime.now().strftime("%m/%d/%Y\n%I:%M:%S %p") + \ + f'\nEnd date '+ end_date.strftime("%m/%d/%Y")) + # -------------- Start of normal event loop -------------- + event, values = window.read(timeout=UPDATE_FREQUENCY_MILLISECONDS) + mprint(event, values) + if event == sg.WIN_CLOSE_ATTEMPTED_EVENT or event == 'Exit': + sg.user_settings_set_entry('-location-', window.current_location()) # The line of code to save the position before exiting + break + if event == 'Edit Me': + sg.execute_editor(__file__) + elif event == 'Choose Date': + new_end = sg.popup_get_date(location=window.current_location(), keep_on_top=True) + if new_end is not None: + end_date = datetime.datetime(new_end[2], new_end[0], new_end[1]) + sg.user_settings_set_entry('-end date-', new_end) + elif event == 'Choose Title': + new_title = sg.popup_get_text('Choose a title for your date', default_text=sg.user_settings_get_entry('-title-', ''), location=window.current_location(), keep_on_top=True) + if new_title is not None: + window['-TITLE-'].update(new_title) + sg.user_settings_set_entry('-title-', new_title) + elif event == 'Show Refresh Info': + window['-REFRESHED-'].update(visible=True) + sg.user_settings_set_entry('-show refresh-', True) + elif event == 'Hide Refresh Info': + window['-REFRESHED-'].update(visible=False) + sg.user_settings_set_entry('-show refresh-', False) + elif event in [str(x) for x in range(1, 11)]: + window.set_alpha(int(event) / 10) + sg.user_settings_set_entry('-alpha-', int(event) / 10) + elif event == 'Change Theme': + loc = window.current_location() + if choose_theme(loc) is not None: + # this is result of hacking code down to 99 lines in total. Not tried it before. Interesting test. + _, window = window.close(), make_window(loc) + elif event == 'Set Main Font': + font = sg.popup_get_text('Main Information Font and Size (e.g. courier 70)', default_text=sg.user_settings_get_entry('-main number font-'), keep_on_top=True, location=window.current_location()) + if font: + sg.user_settings_set_entry('-main number font-', font) + _, window = window.close(), make_window(loc) + elif event == 'Set Title Font': + font = sg.popup_get_text('Title Font and Size (e.g. courier 8)', default_text=sg.user_settings_get_entry('-title font-'), keep_on_top=True, location=window.current_location()) + if font: + sg.user_settings_set_entry('-title font-', font) + _, window = window.close(), make_window(loc) + elif event == 'Show Debug Info': + mprint(sg.get_versions()) + elif event == 'Route Print To Screen': + mprint = sg.Print + elif event == 'Stop print to screen': + mprint = print + + window.close() + + +if __name__ == '__main__': + # To start the window at a specific location, get this location on the command line + # The location should be in form x,y with no spaces + if len(sys.argv) > 1: + location = sys.argv[1].split(',') + location = (int(location[0]), int(location[1])) + else: + location = (None, None) + main(location) \ No newline at end of file diff --git a/DemoPrograms/Demo_Desktop_Widget_Digital_Picture_Frame.py b/DemoPrograms/Demo_Desktop_Widget_Digital_Picture_Frame.py index 390041a50..8ee2c9592 100644 --- a/DemoPrograms/Demo_Desktop_Widget_Digital_Picture_Frame.py +++ b/DemoPrograms/Demo_Desktop_Widget_Digital_Picture_Frame.py @@ -1,11 +1,8 @@ import PySimpleGUI as sg import datetime -import PIL -from PIL import Image +import PIL.Image, PIL.ImageTk import random import os -import io -import base64 """ Another simple Desktop Widget using PySimpleGUI @@ -18,84 +15,18 @@ * Image size * How long to show the image and if you wnt this time to vary semi-randomly * Folder containing your images - - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + + Copyright 2021 PySimpleGUI """ ALPHA = 0.9 # Initial alpha until user changes refresh_font = sg.user_settings_get_entry('-refresh font-', 'Courier 8') - -def make_square(im, fill_color=(0, 0, 0, 0)): - x, y = im.size - size = max(x, y) - new_im = Image.new('RGBA', (size, size), fill_color) - new_im.paste(im, (int((size - x) / 2), int((size - y) / 2))) - return new_im - - -def get_image_size(source): - if isinstance(source, str): - image = PIL.Image.open(source) - elif isinstance(source, bytes): - image = PIL.Image.open(io.BytesIO(base64.b64decode(source))) - else: - image = PIL.Image.open(io.BytesIO(source)) - - width, height = image.size - return (width, height) - - -def convert_to_bytes(source, size=(None, None), subsample=None, zoom=None, fill=False): - """ - Will convert into bytes and optionally resize an image that is a file or a base64 bytes object. - Turns into PNG format in the process so that can be displayed by tkinter - :param source: either a string filename or a bytes base64 image object - :type source: (Union[str, bytes]) - :param size: optional new size (width, height) - :type size: (Tuple[int, int] or None) - :param subsample: change the size by multiplying width and height by 1/subsample - :type subsample: (int) - :param zoom: change the size by multiplying width and height by zoom - :type zoom: (int) - :param fill: If True then the image is filled/padded so that the image is square - :type fill: (bool) - :return: (bytes) a byte-string object - :rtype: (bytes) - """ - # print(f'converting {source} {size}') - if isinstance(source, str): - image = PIL.Image.open(source) - elif isinstance(source, bytes): - image = PIL.Image.open(io.BytesIO(base64.b64decode(source))) - else: - image = PIL.Image.open(io.BytesIO(source)) - - width, height = image.size - - scale = None - if size != (None, None): - new_width, new_height = size - scale = min(new_height / height, new_width / width) - elif subsample is not None: - scale = 1 / subsample - elif zoom is not None: - scale = zoom - - resized_image = image.resize((int(width * scale), int(height * scale)), - Image.LANCZOS) if scale is not None else image - if fill and scale is not None: - resized_image = make_square(resized_image) - # encode a PNG formatted version of image into BASE64 - with io.BytesIO() as bio: - resized_image.save(bio, format="PNG") - contents = bio.getvalue() - encoded = base64.b64encode(contents) - return encoded +def convert_to_bytes(file_or_bytes, resize=None): + image = PIL.Image.open(file_or_bytes) + image.thumbnail(resize) + photo_img = PIL.ImageTk.PhotoImage(image) + return photo_img def choose_theme(location): @@ -113,40 +44,24 @@ def choose_theme(location): return None -def reset_settings(): - sg.user_settings_set_entry('-time per image-', 60) - sg.user_settings_set_entry('-random time-', False) - sg.user_settings_set_entry('-image size-', (None, None)) - sg.user_settings_set_entry('-image_folder-', None) - sg.user_settings_set_entry('-location-', (None, None)) - sg.user_settings_set_entry('-single image-', None) - sg.user_settings_set_entry('-alpha-', ALPHA) - - def make_window(location): alpha = sg.user_settings_get_entry('-alpha-', ALPHA) # ------------------- Window Layout ------------------- # If this is a test window (for choosing theme), then uses some extra Text Elements to display theme info # and also enables events for the elements to make the window easy to close - right_click_menu = [[''], - ['Choose Image Folder', 'Choose Single Image', 'Edit Me', 'Change Theme', 'Set Image Size', - 'Set Time Per Image', 'Save Location', 'Refresh', 'Show Refresh Info', 'Hide Refresh Info', - 'Alpha', - [str(x) for x in range(1, 11)], 'Exit', ]] + right_click_menu = [[''], ['Choose Image Folder', 'Choose Single Image', 'Edit Me', 'Change Theme', 'Set Image Size', + 'Set Time Per Image','Save Location', 'Refresh', 'Show Refresh Info', 'Hide Refresh Info', 'Alpha', + [str(x) for x in range(1, 11)], 'Exit', ]] refresh_info = [[sg.T(size=(25, 1), font=refresh_font, k='-REFRESHED-', justification='c')], - [sg.T(size=(40, 1), justification='c', font=refresh_font, k='-FOLDER-')], - [sg.T(size=(40, 1), justification='c', font=refresh_font, k='-FILENAME-')]] + [sg.T(size=(40,1), justification='c', font=refresh_font, k='-FOLDER-')], + [sg.T(size=(40,1), justification='c', font=refresh_font, k='-FILENAME-')]] layout = [[sg.Image(k='-IMAGE-', enable_events=True)], - [sg.pin(sg.Column(refresh_info, key='-REFRESH INFO-', element_justification='c', - visible=sg.user_settings_get_entry('-show refresh-', True)))]] + [sg.pin(sg.Column(refresh_info, key='-REFRESH INFO-', element_justification='c', visible=sg.user_settings_get_entry('-show refresh-', True)))]] - window = sg.Window('Photo Frame', layout, location=location, no_titlebar=True, grab_anywhere=True, margins=(0, 0), - element_justification='c', element_padding=(0, 0), alpha_channel=alpha, finalize=True, - right_click_menu=right_click_menu, keep_on_top=True, enable_close_attempted_event=True, - enable_window_config_events=True) + window = sg.Window('Photo Frame', layout, location=location, no_titlebar=True, grab_anywhere=True, margins=(0, 0), element_justification='c', element_padding=(0, 0), alpha_channel=alpha, finalize=True, right_click_menu=right_click_menu, keep_on_top=True, enable_close_attempted_event=True) return window @@ -154,76 +69,61 @@ def make_window(location): def main(): loc = sg.user_settings_get_entry('-location-', (None, None)) sg.theme(sg.user_settings_get_entry('-theme-', None)) + window = make_window(loc) time_per_image = sg.user_settings_get_entry('-time per image-', 60) vary_randomly = sg.user_settings_get_entry('-random time-', False) - width, height = sg.user_settings_get_entry('-image size-', (None, None)) + width, height = sg.user_settings_get_entry('-image size-', (400,300)) image_folder = sg.user_settings_get_entry('-image_folder-', None) try: - os.listdir(image_folder) # Try reading the folder to check to see if it is read + os.listdir(image_folder) # Try reading the folder to check to see if it is read except: image_folder = None sg.user_settings_set_entry('-image_folder-', None) - image_name = single_image = sg.user_settings_get_entry('-single image-', None) + single_image = sg.user_settings_get_entry('-single image-', None) if image_folder is None and single_image is None: - image_name = single_image = sg.popup_get_file('Choose a starting image', keep_on_top=True) - if not single_image: - if sg.popup_yes_no('No folder entered', 'Go you want to exit the program entirely?', - keep_on_top=True) == 'Yes': - exit() - if image_folder is not None and single_image is None: + while True: + images = None + image_folder = sg.popup_get_folder('Choose location of your images', location=window.current_location(), keep_on_top=True) + if image_folder is not None: + sg.user_settings_set_entry('-image_folder-', image_folder) + break + else: + if sg.popup_yes_no('No folder entered','Go you want to exit the program entirely?', keep_on_top=True) == 'Yes': + exit() + elif single_image is None: images = os.listdir(image_folder) images = [i for i in images if i.lower().endswith(('.png', '.jpg', '.gif'))] - image_name = os.path.join(image_folder, random.choice(images)) - else: # means single image is not none + else: # means single image is not none images = None - image_name = single_image - window = make_window(loc) - - window_size = window.size - image_data = convert_to_bytes(image_name, (width, height)) - while True: # Event Loop + # First update the status information + # for debugging show the last update date time + if single_image is None: + image_name =random.choice(images) + image_data = convert_to_bytes(os.path.join(image_folder, image_name), (width, height)) + window['-FOLDER-'].update(image_folder) + else: + image_name = single_image + image_data = convert_to_bytes(single_image, (width, height)) + window['-FILENAME-'].update(image_name) + window['-IMAGE-'].update(data=image_data) + window['-REFRESHED-'].update(datetime.datetime.now().strftime("%m/%d/%Y %I:%M:%S %p")) # -------------- Start of normal event loop -------------- - timeout = time_per_image * 1000 + (random.randint(int(-time_per_image * 500), - int(time_per_image * 500)) if vary_randomly else 0) if single_image is None else None + timeout = time_per_image * 1000 + (random.randint(int(-time_per_image * 500), int(time_per_image * 500)) if vary_randomly else 0) if single_image is None else None event, values = window.read(timeout=timeout) if event == sg.WIN_CLOSED: break elif event in (sg.WIN_CLOSE_ATTEMPTED_EVENT, 'Exit'): - sg.user_settings_set_entry('-location-', - window.current_location()) # The line of code to save the position before exiting + sg.user_settings_set_entry('-location-', window.current_location()) # The line of code to save the position before exiting break - # First update the status information - # for debugging show the last update date time - if event == sg.TIMEOUT_EVENT: - if single_image is None: - image_name = random.choice(images) - image_data = convert_to_bytes(os.path.join(image_folder, image_name)) - window['-FOLDER-'].update(image_folder) - else: - image_name = single_image - image_data = convert_to_bytes(single_image, (width, height)) - window['-FILENAME-'].update(image_name) - window['-IMAGE-'].update(data=image_data) - window['-REFRESHED-'].update(datetime.datetime.now().strftime("%m/%d/%Y %I:%M:%S %p")) - if event == sg.WINDOW_CONFIG_EVENT: - new_size = window.size - if new_size != window_size: - print(f'resizing {new_size}') - (width, height) = new_size - image_data = convert_to_bytes(image_data, (width, height)) - window['-IMAGE-'].update(data=image_data) - window.size = get_image_size(image_data) - window_size = window.size if event == 'Edit Me': sg.execute_editor(__file__) elif event == 'Choose Image Folder': - folder = sg.popup_get_folder('Choose location of your images', default_path=image_folder, - location=window.current_location(), keep_on_top=True) + folder = sg.popup_get_folder('Choose location of your images', default_path=image_folder, location=window.current_location(), keep_on_top=True) if folder is not None: image_folder = folder window['-FOLDER-'].update(image_folder) @@ -234,11 +134,10 @@ def main(): single_image = None elif event == 'Set Time Per Image': layout = [[sg.T('Enter number of seconds each image should be displayed')], - [sg.I(time_per_image, size=(5, 1), k='-TIME PER IMAGE-')], - [sg.CB('Use some randomness', vary_randomly, k='-RANDOM TIME-')], - [sg.Ok(), sg.Cancel()]] - event, values = sg.Window('Display duration', layout, location=window.current_location(), keep_on_top=True, - no_titlebar=True).read(close=True) + [sg.I(time_per_image, size=(5,1),k='-TIME PER IMAGE-')], + [sg.CB('Use some randomness', vary_randomly, k='-RANDOM TIME-')], + [sg.Ok(), sg.Cancel()]] + event, values = sg.Window('Display duration',layout, location=window.current_location(), keep_on_top=True, no_titlebar=True ).read(close=True) if event == 'Ok': try: time_per_image = int(values['-TIME PER IMAGE-']) @@ -246,22 +145,19 @@ def main(): sg.user_settings_set_entry('-time per image-', time_per_image) sg.user_settings_set_entry('-random time-', values['-RANDOM TIME-']) except: - sg.popup_error('Bad number of seconds entered', location=window.current_location(), - keep_on_top=True) + sg.popup_error('Bad number of seconds entered', location=window.current_location(), keep_on_top=True) elif event == 'Set Image Size': layout = [[sg.T('Enter size should be shown at in pixels (width, height)')], - [sg.I(width, size=(4, 1), k='-W-'), sg.I(height, size=(4, 1), k='-H-')], - [sg.Ok(), sg.Cancel()]] - event, values = sg.Window('Image Dimensions', layout, location=window.current_location(), keep_on_top=True, - no_titlebar=True).read(close=True) + [sg.I(width, size=(4,1),k='-W-'), sg.I(height, size=(4,1),k='-H-')], + [sg.Ok(), sg.Cancel()]] + event, values = sg.Window('Image Dimensions',layout, location=window.current_location(), keep_on_top=True, no_titlebar=True ).read(close=True) if event == 'Ok': try: - w, h = int(values['-W-']), int(values['-H-']) - sg.user_settings_set_entry('-image size-', (w, h)) - width, height = w, h + w,h = int(values['-W-']), int(values['-H-']) + sg.user_settings_set_entry('-image size-', (w,h)) + width, height = w,h except: - sg.popup_error('Bad size specified. Use integers only', location=window.current_location(), - keep_on_top=True) + sg.popup_error('Bad size specified. Use integers only', location=window.current_location(), keep_on_top=True) elif event == 'Show Refresh Info': window['-REFRESH INFO-'].update(visible=True) sg.user_settings_set_entry('-show refresh-', True) @@ -279,16 +175,12 @@ def main(): window.close() window = make_window(loc) elif event == 'Choose Single Image': - image_name = single_image = sg.popup_get_file('Choose single image to show', history=True) + single_image = sg.popup_get_file('Choose single image to show', history=True) sg.user_settings_set_entry('-single image-', single_image) - (width, height) = get_image_size(single_image) - sg.user_settings_set_entry('-image size-', (width, height)) - image_data = convert_to_bytes(image_name, (width, height)) - window['-IMAGE-'].update(data=image_data) - window.size = window_size = (width, height) - window.close() + + window.close() + if __name__ == '__main__': - # reset_settings() # if get corrupted problems, uncomment this - main() + main() \ No newline at end of file diff --git a/DemoPrograms/Demo_Desktop_Widget_Drive_Usage.py b/DemoPrograms/Demo_Desktop_Widget_Drive_Usage.py index 97c1aa6c9..a3c75c240 100644 --- a/DemoPrograms/Demo_Desktop_Widget_Drive_Usage.py +++ b/DemoPrograms/Demo_Desktop_Widget_Drive_Usage.py @@ -7,11 +7,6 @@ Desktop "Rainmeter" style widget - Drive usage Requires: psutil Shows a bar graph of space used for each drive partician that psutil finds - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ ALPHA = 0.7 @@ -21,21 +16,13 @@ BAR_COLORS = ('#23a0a0', '#56d856', '#be45be', '#5681d8', '#d34545', '#BE7C29') -class Globals(): - drive_list = None - def __init__(self): - return - - def human_size(bytes, units=(' bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB')): """ Returns a human readable string reprentation of bytes""" return str(bytes) + ' ' + units[0] if bytes < 1024 else human_size(bytes >> 10, units[1:]) def update_window(window): - drive_list = [] particians = psutil.disk_partitions() - all_ok = True for count, part in enumerate(particians): mount = part[0] try: @@ -44,19 +31,15 @@ def update_window(window): window[('-PROG-', mount)].update_bar(int(usage.percent)) window[('-%-', mount)].update(f'{usage.percent}%') window[('-STATS-', mount)].update(f'{human_size(usage.used)} / {human_size(usage.total)} = {human_size(usage.free)} free') - drive_list.append(str(mount)) - except KeyError as e: # A key error means a new drive was added - all_ok = False - except Exception as e: + except: pass - all_ok = Globals.drive_list == drive_list and all_ok - Globals.drive_list = drive_list - return all_ok +def main(location): + sg.theme(THEME) # ---------------- Create Layout ---------------- -def create_window(location): + layout = [[sg.Text('Drive Status', font='Any 16')]] # Add a row for every partician that has a bar graph and text stats @@ -73,48 +56,20 @@ def create_window(location): sg.Text(f'{usage.percent}%', size=(6, 1), key=('-%-', mount)), sg.T(stats_info, size=(30, 1), key=('-STATS-', mount))]] except: pass - layout += [[sg.Text('Refresh', font='Any 8', key='-REFRESH-', enable_events=True)]] + layout += [[sg.Text('Refresh', font='Any 8', key='-REFRESH-', enable_events=True), sg.Text('❎', enable_events=True, key='Exit Text')]] # ---------------- Create Window ---------------- - window = sg.Window('Drive Status Widget', layout, location=location, keep_on_top=True, grab_anywhere=True, no_titlebar=True, alpha_channel=ALPHA, use_default_focus=False,right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT, - finalize=True, enable_close_attempted_event=True) - - return window - -def main(location): - # we rely on a key error to tell us if a drive was added. So.... we don't want pesky popups or other key erros to be shown - sg.set_options(suppress_error_popups=True, suppress_raise_key_errors=False, suppress_key_guessing=True) + window = sg.Window('Drive Status Widget', layout, location=location, keep_on_top=True, grab_anywhere=True, no_titlebar=True, alpha_channel=ALPHA, use_default_focus=False, + finalize=True) - sg.theme(THEME) - window = create_window(location) update_window(window) # sets the progress bars - try: - # ---------------- Event Loop ---------------- - while True: - event, values = window.read(timeout=UPDATE_FREQUENCY_MILLISECONDS) - if event in (sg.WIN_CLOSED, sg.WIN_CLOSE_ATTEMPTED_EVENT, 'Exit'): - if event != sg.WIN_CLOSED: - sg.user_settings_set_entry('-location-', window.current_location()) # The line of code to save the position before exiting - break - - if event == 'Edit Me': - sp = sg.execute_editor(__file__) - elif event == 'Version': - sg.popup_scrolled(__file__, sg.get_versions(), keep_on_top=True, location=window.current_location()) - - if not update_window(window): # update the window.. if not True then something changed and need to make a new window - window.close() - window = create_window(location) - update_window(window) - - - except Exception as e: - sg.Print('ERROR in event loop', e) - sg.popup_error_with_traceback('Crashed', e) - - sg.popup('Check the error!') - + # ---------------- Event Loop ---------------- + while True: + event, values = window.read(timeout=UPDATE_FREQUENCY_MILLISECONDS) + if event == sg.WIN_CLOSED or event.startswith('Exit'): + break + update_window(window) if __name__ == '__main__': @@ -122,6 +77,6 @@ def main(location): location = sys.argv[1].split(',') location = (int(location[0]), int(location[1])) else: - location = sg.user_settings_get_entry('-location-', (None, None)) + location = (None, None) main(location) diff --git a/DemoPrograms/Demo_Desktop_Widget_Drive_Usage_Gauges.py b/DemoPrograms/Demo_Desktop_Widget_Drive_Usage_Gauges.py deleted file mode 100644 index 692842e17..000000000 --- a/DemoPrograms/Demo_Desktop_Widget_Drive_Usage_Gauges.py +++ /dev/null @@ -1,365 +0,0 @@ -#!/usr/bin/env python -import PySimpleGUI as sg -import psutil -import sys -import math - -""" - Desktop "Rainmeter" style widget - Drive usage - Requires: psutil - Uses a "Gauge" to display drive usage - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - -ALPHA = 0.7 -THEME = 'black' -UPDATE_FREQUENCY_MILLISECONDS = 20 * 1000 - -BAR_COLORS = ('#23a0a0', '#56d856', '#be45be', '#5681d8', '#d34545', '#BE7C29') -gsize = (50, 30) - -class Gauge(): - def mapping(func, sequence, *argc): - """ - Map function with extra argument, not for tuple. - : Parameters - func - function to call. - sequence - list for iteration. - argc - more arguments for func. - : Return - list of func(element of sequence, *argc) - """ - if isinstance(sequence, list): - return list(map(lambda i: func(i, *argc), sequence)) - else: - return func(sequence, *argc) - - def add(number1, number2): - """ - Add two number - : Parameter - number1 - number to add. - numeer2 - number to add. - : Return - Addition result for number1 and number2. - """ - return number1 + number1 - - def limit(number): - """ - Limit angle in range 0 ~ 360 - : Parameter - number: angle degree. - : Return - angel degree in 0 ~ 360, return 0 if number < 0, 360 if number > 360. - """ - return max(min(360, number), 0) - class Clock(): - """ - Draw background circle or arc - All angles defined as clockwise from negative x-axis. - """ - - def __init__(self, center_x=0, center_y=0, radius=100, start_angle=0, - stop_angle=360, fill_color='white', line_color='black', line_width=2, graph_elem=None): - - instance = Gauge.mapping(isinstance, [center_x, center_y, radius, start_angle, - stop_angle, line_width], (int, float)) + Gauge.mapping(isinstance, - [fill_color, line_color], str) - if False in instance: - raise ValueError - start_angle, stop_angle = Gauge.limit(start_angle), Gauge.limit(stop_angle) - self.all = [center_x, center_y, radius, start_angle, stop_angle, - fill_color, line_color, line_width] - self.figure = [] - self.graph_elem = graph_elem - self.new() - - def new(self): - """ - Draw Arc or circle - """ - x, y, r, start, stop, fill, line, width = self.all - start, stop = (180 - start, 180 - stop) if stop < start else (180 - stop, 180 - start) - if start == stop % 360: - self.figure.append(self.graph_elem.DrawCircle((x, y), r, fill_color=fill, - line_color=line, line_width=width)) - else: - self.figure.append(self.graph_elem.DrawArc((x - r, y + r), (x + r, y - r), stop - start, - start, style='arc', arc_color=fill)) - - def move(self, delta_x, delta_y): - """ - Move circle or arc in clock by delta x, delta y - """ - if False in Gauge.mapping(isinstance, [delta_x, delta_y], (int, float)): - raise ValueError - self.all[0] += delta_x - self.all[1] += delta_y - for figure in self.figure: - self.graph_elem.MoveFigure(figure, delta_x, delta_y) - - class Pointer(): - """ - Draw pointer of clock - All angles defined as clockwise from negative x-axis. - """ - - def __init__(self, center_x=0, center_y=0, angle=0, inner_radius=20, - outer_radius=80, outer_color='white', pointer_color='blue', - origin_color='black', line_width=2, graph_elem=None): - - instance = Gauge.mapping(isinstance, [center_x, center_y, angle, inner_radius, - outer_radius, line_width], (int, float)) + Gauge.mapping(isinstance, - [outer_color, pointer_color, origin_color], str) - if False in instance: - raise ValueError - - self.all = [center_x, center_y, angle, inner_radius, outer_radius, - outer_color, pointer_color, origin_color, line_width] - self.figure = [] - self.stop_angle = angle - self.graph_elem = graph_elem - self.new(degree=angle, color=pointer_color) - - def new(self, degree=0, color=None): - """ - Draw new pointer by angle, erase old pointer if exist - degree defined as clockwise from negative x-axis. - """ - (center_x, center_y, angle, inner_radius, outer_radius, - outer_color, pointer_color, origin_color, line_width) = self.all - pointer_color = color or pointer_color - if self.figure != []: - for figure in self.figure: - self.graph_elem.DeleteFigure(figure) - self.figure = [] - d = degree - 90 - self.all[2] = degree - dx1 = int(2 * inner_radius * math.sin(d / 180 * math.pi)) - dy1 = int(2 * inner_radius * math.cos(d / 180 * math.pi)) - dx2 = int(outer_radius * math.sin(d / 180 * math.pi)) - dy2 = int(outer_radius * math.cos(d / 180 * math.pi)) - self.figure.append(self.graph_elem.DrawLine((center_x - dx1, center_y - dy1), - (center_x + dx2, center_y + dy2), - color=pointer_color, width=line_width)) - self.figure.append(self.graph_elem.DrawCircle((center_x, center_y), inner_radius, - fill_color=origin_color, line_color=outer_color, line_width=line_width)) - - def move(self, delta_x, delta_y): - """ - Move pointer with delta x and delta y - """ - if False in Gauge.mapping(isinstance, [delta_x, delta_y], (int, float)): - raise ValueError - self.all[:2] = [self.all[0] + delta_x, self.all[1] + delta_y] - for figure in self.figure: - self.graph_elem.MoveFigure(figure, delta_x, delta_y) - - class Tick(): - """ - Create tick on click for minor tick, also for major tick - All angles defined as clockwise from negative x-axis. - """ - - def __init__(self, center_x=0, center_y=0, start_radius=90, stop_radius=100, - start_angle=0, stop_angle=360, step=6, line_color='black', line_width=2, graph_elem=None): - - instance = Gauge.mapping(isinstance, [center_x, center_y, start_radius, - stop_radius, start_angle, stop_angle, step, line_width], - (int, float)) + [Gauge.mapping(isinstance, line_color, (list, str))] - if False in instance: - raise ValueError - start_angle, stop_angle = Gauge.limit(start_angle), Gauge.limit(stop_angle) - self.all = [center_x, center_y, start_radius, stop_radius, - start_angle, stop_angle, step, line_color, line_width] - self.figure = [] - self.graph_elem = graph_elem - - self.new() - - def new(self): - """ - Draw ticks on clock - """ - (x, y, start_radius, stop_radius, start_angle, stop_angle, step, - line_color, line_width) = self.all - start_angle, stop_angle = (180 - start_angle, 180 - stop_angle - ) if stop_angle < start_angle else (180 - stop_angle, 180 - start_angle) - for i in range(start_angle, stop_angle + 1, step): - start_x = x + start_radius * math.cos(i / 180 * math.pi) - start_y = y + start_radius * math.sin(i / 180 * math.pi) - stop_x = x + stop_radius * math.cos(i / 180 * math.pi) - stop_y = y + stop_radius * math.sin(i / 180 * math.pi) - self.figure.append(self.graph_elem.DrawLine((start_x, start_y), - (stop_x, stop_y), color=line_color, width=line_width)) - - def move(self, delta_x, delta_y): - """ - Move ticks by delta x and delta y - """ - if False in Gauge.mapping(isinstance, [delta_x, delta_y], (int, float)): - raise ValueError - self.all[0] += delta_x - self.all[1] += delta_y - for figure in self.figure: - self.graph_elem.MoveFigure(figure, delta_x, delta_y) - - """ - Create Gauge - All angles defined as count clockwise from negative x-axis. - Should create instance of clock, pointer, minor tick and major tick first. - """ - def __init__(self, center=(0, 0), start_angle=0, stop_angle=180, major_tick_width=5, minor_tick_width=2,major_tick_start_radius=90, major_tick_stop_radius=100, minor_tick_step=5, major_tick_step=30, clock_radius=100, pointer_line_width=5, pointer_inner_radius=10, pointer_outer_radius=75, pointer_color='white', pointer_origin_color='black', pointer_outer_color='white', pointer_angle=0, degree=0, clock_color='white', major_tick_color='black', minor_tick_color='black', minor_tick_start_radius=90, minor_tick_stop_radius=100, graph_elem=None): - - self.clock = Gauge.Clock(start_angle=start_angle, stop_angle=stop_angle, fill_color=clock_color, radius=clock_radius, graph_elem=graph_elem) - self.minor_tick = Gauge.Tick(start_angle=start_angle, stop_angle=stop_angle, line_width=minor_tick_width, line_color=minor_tick_color, start_radius=minor_tick_start_radius, stop_radius=minor_tick_stop_radius, graph_elem=graph_elem, step=minor_tick_step) - self.major_tick = Gauge.Tick(start_angle=start_angle, stop_angle=stop_angle, line_width=major_tick_width, start_radius=major_tick_start_radius, stop_radius=major_tick_stop_radius, step=major_tick_step, line_color=major_tick_color, graph_elem=graph_elem) - self.pointer = Gauge.Pointer(angle=pointer_angle, inner_radius=pointer_inner_radius, outer_radius=pointer_outer_radius, pointer_color=pointer_color, outer_color=pointer_outer_color, origin_color=pointer_origin_color, line_width=pointer_line_width, graph_elem=graph_elem) - - self.center_x, self.center_y = self.center = center - self.degree = degree - self.dx = self.dy = 1 - - def move(self, delta_x, delta_y): - """ - Move gauge to move all componenets in gauge. - """ - self.center_x, self.center_y =self.center = ( - self.center_x+delta_x, self.center_y+delta_y) - if self.clock: - self.clock.move(delta_x, delta_y) - if self.minor_tick: - self.minor_tick.move(delta_x, delta_y) - if self.major_tick: - self.major_tick.move(delta_x, delta_y) - if self.pointer: - self.pointer.move(delta_x, delta_y) - - def change(self, degree=None, step=1, pointer_color=None): - """ - Rotation of pointer - call it with degree and step to set initial options for rotation. - Without any option to start rotation. - """ - if self.pointer: - if degree != None: - self.pointer.stop_degree = degree - self.pointer.step = step if self.pointer.all[2] < degree else -step - return True - now = self.pointer.all[2] - step = self.pointer.step - new_degree = now + step - if ((step > 0 and new_degree < self.pointer.stop_degree) or - (step < 0 and new_degree > self.pointer.stop_degree)): - self.pointer.new(degree=new_degree, color=pointer_color) - return False - else: - self.pointer.new(degree=self.pointer.stop_degree, color=pointer_color) - return True - - - -def human_size(bytes, units=(' bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB')): - """ Returns a human readable string reprentation of bytes""" - return str(bytes) + ' ' + units[0] if bytes < 1024 else human_size(bytes >> 10, units[1:]) - - -def update_window(window): - particians = psutil.disk_partitions() - for count, part in enumerate(particians): - mount = part[0] - try: - usage = psutil.disk_usage(mount) - window[('-NAME-', mount)].update(mount) - # window[('-PROG-', mount)].update_bar(int(usage.percent)) - window[('-%-', mount)].update(f'{usage.percent}%') - window[('-STATS-', mount)].update(f'{human_size(usage.used)} / {human_size(usage.total)} = {human_size(usage.free)} free') - gauge = Gauge(pointer_color=window[('-GRAPH-', mount)].metadata, - clock_color=window[('-GRAPH-', mount)].metadata, - major_tick_color=sg.theme_input_background_color(), - minor_tick_color=sg.theme_input_text_color(), - pointer_outer_color=sg.theme_input_background_color(), - major_tick_start_radius=gsize[1] - 10, - minor_tick_start_radius=gsize[1] - 10, - minor_tick_stop_radius=gsize[1] - 5, - major_tick_stop_radius=gsize[1] - 5, - clock_radius=gsize[1] - 5, - pointer_outer_radius=gsize[1] - 5, - major_tick_step=30, - minor_tick_step=15, - pointer_line_width=3, - pointer_inner_radius=10, - graph_elem=window[('-GRAPH-', mount)]) - gauge.change(degree=0) - gauge.change(degree=180 * usage.percent / 100, step=180) - gauge.change() - except KeyError as e: # A key error means a new drive was added - print('Got a key error, so a new drive was added. Window will restart') - return False - except BaseException as e: - print(e) - - - - return True - -def create_window(location): - layout = [[sg.Text('Drive Status', font='Any 16')]] - - # Add a row for every partician that has a bar graph and text stats - particians = psutil.disk_partitions() - for count, part in enumerate(particians): - mount = part[0] - try: - bar_color = sg.theme_progress_bar_color() - this_color = BAR_COLORS[count % len(BAR_COLORS)] - usage = psutil.disk_usage(mount) - stats_info = f'{human_size(usage.used)} / {human_size(usage.total)} = {human_size(usage.free)} free' - layout += [[sg.Text(mount, size=(3, 1), key=('-NAME-', mount)), - sg.Graph(gsize, (-gsize[0] // 2, 0), (gsize[0] // 2, gsize[1]), key=('-GRAPH-', mount), metadata=this_color), - # sg.ProgressBar(100, 'h', size=(10, 15), key=('-PROG-', mount), bar_color=(this_color, bar_color[1])), - sg.Text(f'{usage.percent}%', size=(6, 1), key=('-%-', mount)), sg.T(stats_info, size=(30, 1), key=('-STATS-', mount)), - ]] - except: - pass - layout += [[sg.Text('Refresh', font='Any 8', key='-REFRESH-', enable_events=True), sg.Text('❎', enable_events=True, key='Exit Text')]] - - # ---------------- Create Window ---------------- - window = sg.Window('Drive Status Widget', layout, location=location, keep_on_top=True, grab_anywhere=True, no_titlebar=True, alpha_channel=ALPHA, use_default_focus=False, - finalize=True) - return window - -def main(location): - # Turn off the popups because key errors are normal in this program. - # Will get a key error is a new drive is added. Want to get the key error as an exception. - sg.set_options(suppress_error_popups=True, suppress_raise_key_errors=False, suppress_key_guessing=True) - sg.theme(THEME) - - window = create_window(location) - - update_window(window) # sets the progress bars - - # ---------------- Event Loop ---------------- - while True: - event, values = window.read(timeout=UPDATE_FREQUENCY_MILLISECONDS) - if event == sg.WIN_CLOSED or event.startswith('Exit'): - break - if not update_window(window): - window.close() - window = create_window(location) - update_window(window) - -if __name__ == '__main__': - if len(sys.argv) > 1: - location = sys.argv[1].split(',') - location = (int(location[0]), int(location[1])) - else: - location = (None, None) - main(location) - diff --git a/DemoPrograms/Demo_Desktop_Widget_Email_Notification.py b/DemoPrograms/Demo_Desktop_Widget_Email_Notification.py index 084422a48..ea7d4fadd 100644 --- a/DemoPrograms/Demo_Desktop_Widget_Email_Notification.py +++ b/DemoPrograms/Demo_Desktop_Widget_Email_Notification.py @@ -7,12 +7,6 @@ ''' Usage of Notification in PSG - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. ''' IMAP_SERVER_GMAIL = 'imap.gmail.com' # gmail server address diff --git a/DemoPrograms/Demo_Desktop_Widget_FedEx_Package_Tracking.py b/DemoPrograms/Demo_Desktop_Widget_FedEx_Package_Tracking.py new file mode 100644 index 000000000..0b5222a8c --- /dev/null +++ b/DemoPrograms/Demo_Desktop_Widget_FedEx_Package_Tracking.py @@ -0,0 +1,187 @@ +import requests +import PySimpleGUI as sg +import datetime + +""" + Demo - FedEx Package Tracking + + A simple Desktop Widget that checks your FedEx tracking number and + shows the current delivery estimate. + + USING: + Enter a tracking number in the input element + Right click and choose Refresh + If additional tracking numbers are desired, right click and choose Add Package + + The status information is courtesy of @israel-dryer (https://github.com/israel-dryer) + He used web scraping to gather the data. This removes the need for using an account and access package. + + At the moment only FedEx is supported. The drop-down list is there for future support of other carriers. + + Like other PySimpleGUI Desktop Widgets, a number of standard features are include such as: + * Alpha Channel + * Theme Selection + * Screen location + * Edit Me (launcher your editor for easy code modification) + + Copyright 2021 PySimpleGUI, Israel Dryer +""" + +def choose_theme(location): + layout = [[sg.Text(f'Current theme {sg.theme()}')], + [sg.Listbox(values=sg.theme_list(), size=(20, 20), key='-LIST-', enable_events=True)], + [sg.OK(), sg.Cancel()]] + + window = sg.Window('Look and Feel Browser', layout, location=location, keep_on_top=True, no_titlebar=True) + old_theme = sg.theme() + while True: # Event Loop + event, values = window.read() + if event in (sg.WIN_CLOSED, 'Exit', 'OK', 'Cancel'): + break + sg.theme(values['-LIST-'][0]) + window.close() + + if event == 'OK' and values['-LIST-']: + sg.theme(values['-LIST-'][0]) + sg.user_settings_set_entry('-theme-', values['-LIST-'][0]) + return values['-LIST-'][0] + else: + sg.theme(old_theme) + return None + + +def shipping_status(tracking_num): + """Request shipment status via tracking number. + Args: + tracking_num (str): The FedEx tracking number assigned to the shipment. + """ + url = "https://www.fedex.com/trackingCal/track" + headers = { + 'Host': 'www.fedex.com', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0', + 'Accept': '*/*', + 'Accept-Language': 'en-US,en;q=0.5', + 'Accept-Encoding': 'gzip, deflate, br', + 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', + 'X-Requested-With': 'XMLHttpRequest', + 'Origin': 'https://www.fedex.com', + 'Connection': 'keep-alive', + 'Referer': 'https://www.fedex.com/en-us/home.html', + } + payload = '''data=%7B%22TrackPackagesRequest%22%3A%7B%22appType%22%3A%22WTRK%22%2C%22appDeviceType%22%3A%22%22%2C%22supportHTML%22%3Atrue%2C%22supportCurrentLocation%22%3Atrue%2C%22uniqueKey%22%3A%22%22%2C%22processingParameters%22%3A%7B%7D%2C%22trackingInfoList%22%3A%5B%7B%22trackNumberInfo%22%3A%7B%22trackingNumber%22%3A%22{}%22%2C%22trackingQualifier%22%3A%22%22%2C%22trackingCarrier%22%3A%22%22%7D%7D%5D%7D%7D&action=trackpackages&locale=en_US&version=1&format=json''' + + response = requests.post(url, headers=headers, data=payload.format(tracking_num)) + if response.status_code == 200: + return response.json() + else: + return (None, response.status_code) + + +def package_row(item_num, tracking_num=''): + carrier_list = ('FedEx', 'USPS') + tracking_numbers = sg.user_settings_get_entry('-packages-', []) + row = [sg.pin(sg.Col([[sg.B(sg.SYMBOL_X, border_width=0, button_color=(sg.theme_text_color(), sg.theme_background_color()), k=('-DEL-', item_num), tooltip='Delete this item'), + sg.Combo(tracking_numbers, default_value=tracking_num, size=(20, 1), key=('-ID-', item_num)), + sg.In(size=(20,1), k=('-DESC-', item_num)), + # sg.Input(default_text=tracking_num, s=(20,1), key=('-ID-', item_num), tooltip='Enter your package ID'), + sg.Combo(carrier_list, default_value=carrier_list[0], readonly=True, s=(10,10), k=('-CARRIER-', item_num), tooltip='Not implemented'), sg.T(size=(15,1), k=('-STATUS-', item_num))]], k=('-ROW-', item_num)))] + return row + + +def refresh(window: sg.Window): + row_count = window.metadata+1 + # make and save package list. ID, Description, + package_list = [] + for row in range(row_count): + if not window[('-ROW-', row)].visible: # skip deleted rows + continue + status = shipping_status(window[('-ID-', row)].get()) + single_package = (window[('-ID-', row)].get(), window[('-DESC-', row)].get()) + package_list.append(single_package) + if isinstance(status, tuple): # an error occured + delivery_datetime = 'Error' + else: + delivery_datetime = status['TrackPackagesResponse']['packageList'][0]['displayEstDeliveryDateTime'] + window[('-STATUS-', row)].update(delivery_datetime) + window['-REFRESHED-'].update(f'Refreshed {datetime.datetime.now().strftime("%m/%d/%Y %I:%M:%S %p")}') + sg.user_settings_set_entry('-packages-', package_list) + + +def add_packages_to_window(window: sg.Window): + packages = sg.user_settings_get_entry('-packages-', []) + for i, package in enumerate(packages): + in_elem = window.find_element(('-ID-', i), silent_on_error=True) + if isinstance(in_elem, sg.ErrorElement): + window.metadata += 1 + window.extend_layout(window['-TRACKING SECTION-'], [package_row(window.metadata)]) + in_elem = window.find_element(('-ID-', window.metadata), silent_on_error=True) + in_elem.update(package[0]) + else: + in_elem.update(package[0]) + desc_elem = window.find_element(('-DESC-', i), silent_on_error=True) + if not isinstance(desc_elem, sg.ErrorElement): + desc_elem.update(package[1]) + +def make_window(location): + location = sg.user_settings_get_entry('-location-',location) + alpha = sg.user_settings_get_entry('-alpha-', 0.9) + + layout = [ [sg.Text('FedEx Package Tracking', font='_ 15')], + [sg.Col([package_row(0)], k='-TRACKING SECTION-')], + [sg.pin(sg.Text(size=(35,1), font='_ 8', k='-REFRESHED-',))], + [sg.T(sg.SYMBOL_X, enable_events=True, k='Exit', tooltip='Exit Application'), sg.T('↻', enable_events=True, k='Refresh', tooltip='Save Changes & Refresh'), sg.T('+', enable_events=True, k='Add Package', tooltip='Add Another Package')]] + + right_click_menu = [[''], ['Add Package', 'Edit Me', 'Change Theme', 'Save Location', 'Refresh', 'Alpha', [str(x) for x in range(1, 11)], 'Exit', ]] + + window = sg.Window('Window Title', layout, finalize=True, no_titlebar=True, grab_anywhere=True, keep_on_top=True, + right_click_menu=right_click_menu, alpha_channel=alpha, location=location, use_default_focus=False, font='_ 15', metadata=0) + add_packages_to_window(window) + + return window + + +def main(): + theme = sg.user_settings_get_entry('-theme-', 'Dark Gray 14') + sg.theme(theme) + location = sg.user_settings_get_entry('-location-', (None, None)) + + window = make_window(location) + refresh(window) + while True: + event, values = window.read(timeout=1000*60*60) # wake every hour + if event == sg.WIN_CLOSED or event == 'Exit': + break + if event == 'Add Package': + window.metadata += 1 + window.extend_layout(window['-TRACKING SECTION-'], [package_row(window.metadata)]) + elif event == 'Edit Me': + sg.execute_editor(__file__) + elif event == 'Save Location': + sg.user_settings_set_entry('-location-', window.current_location()) + elif event == 'Change Theme': + loc = window.current_location() + if choose_theme(loc) is not None: + _, window = window.close(), make_window(loc) + elif event in ('Refresh', sg.TIMEOUT_KEY): + # Invert colors of simulated "button" (Text Element) while the refresh is happening + window['Refresh'].update(text_color=sg.theme_text_element_background_color(), background_color=sg.theme_text_color()) + window.refresh() + refresh(window) + window['Refresh'].update(text_color=sg.theme_text_color(), background_color=sg.theme_text_element_background_color()) + elif event in [str(x) for x in range(1,11)]: + window.set_alpha(int(event)/10) + sg.user_settings_set_entry('-alpha-', int(event)/10) + if isinstance(event, tuple): + if event[0] == '-DEL-': + window[('-ROW-', event[1])].update(visible=False) + packages: list = sg.user_settings_get_entry('-packages-', []) + try: + packages.remove(window[('-ID-', event[1])].get()) + except: + pass + sg.user_settings_set_entry('-packages-', packages) + window.close() + + +if __name__ == '__main__': + main() diff --git a/DemoPrograms/Demo_Desktop_Widget_Launcher_Bar.py b/DemoPrograms/Demo_Desktop_Widget_Launcher_Bar.py index 0f4d975bd..f3c15abbf 100644 --- a/DemoPrograms/Demo_Desktop_Widget_Launcher_Bar.py +++ b/DemoPrograms/Demo_Desktop_Widget_Launcher_Bar.py @@ -8,11 +8,7 @@ This tool will perhaps help make for a more GUI-like environment for your Python activities - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ excel_icon = b'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAACXBIWXMAAAsSAAALEgHS3X78AAAFB0lEQVRIx51We0xTZxQ/X3t5lZY+QLwgLYgg4MSJOAQCOgED23SgMjedr2mY2UQhwblHNpK5xCxTM+Nkf+Dc2NTMZJCpEF3YsqU6y5ZsGpextSD0AcKlBeVR+rrt/fbHhcv1tlTGSdN8j3O/33mfgxiGAR4hhDDG7D/MTgghAGA5+efcCbdAAgA+jGDLYDzuspuGByZck7JwSZYmw/9dARgAEEHE9Hhp08iAftBooEx6ytg1ZB4YtblpDwCsVKe11ZzlC8sJxNmA3c4A0D7vg0fWbqtZP2gyUCYDZTIO97tozyw2mhGce4t9mv86QggxDNOobW69p+219U+4HQEt5k8xMsXGFWv9zzEGDBghFCImSjJyC1KzCISQrufeXYse/g+FikNTYjVBGMac9vorDb8cPU8Ej5ZZNZAqXiuo4Ftf4I/BMds3utYnODkIDYxa6680AEBRek5GfHLDz5fxtGvyU1aWPpUPABgwxnieAMP20fO3vgcAZaSclMd8+esVzhKEWMwCIEDz10ASGp5GJgEAGRUdERqWpU7HMAWwSBE7HUKAECL8U0ytIqVhEqOt30m7AWBLdkmiitR2/XnH/C/HlhKraT38Gbe9dviMf54DIIwxIchABKhxd31mQurbzacvdrQlL0g4ta3O46MvdLTx2fSUMf/4LkBQtbZyXVr2rnPvcRrsWPP8oeIdAAgBIIREgihiMNOobcYYb88pA4CdeRtDiZCLHW3D9lFBklseUpYRasw5QXu97Jr9PXKMY4wBMCAI7OTWv7R1pXsyE5ZmJy17afUGu8vRqG0R8JDy6N15LwJA7pIVMTLlW2V7AYDVYVViOj+TAwDQXu8Xt1o+qqj+eGuNUhJ17mbL0PiIgCcqQlq6PJ9NaVmYhA0bllSRcn49CRxFzX/8VFuyMyMu2eFxNd5s9mfooszFJ6sA4EjpnucyC0pOvc6Z+sC6yg82HeAKqmiWcg8+zCCExCJROBH2xMYgqIOPmSgAB8Ce/PKFUdF3zP9kaTLeWL/t6HefChiWkomf73wfAC+QKmXhkT/WNcKUE5AqMoorfQAQQAN5hLRq7ZZJt7P28gmnx7U1uyQxOk7AM+6cbO/UtXd29Nj67W5He6eO3bZ36rqGzFOKYAjsg32Fm6Oliku/Xe+x9l27p335mdKDRa8IlKDGhj+58RUAHCnbK5dIT/zQNOODZysLU1cBYBzQBwqJbH/BZi/j+1p3FQCabl/1MUzl6g1qFflYuSZC1CpSrSLlEZEhIkKtWshu1SpSESHjcwo1cNGe8rM1YpGoe8gCAH8/uP9Oy+lFytikmPi+hxTHlk4uvl7bwG11716YLQT8Adw91j5+4/729xv+X963WjadOQQAr+a9kL/k6epLx7mCsHlV0f7CLTMazK/hODwutgkWL8t10u67FgP3Ts7i5Xz5AofpXDpaedZ6AMjSpCklUfsKKrirNcmZ/Flmnv0gXhH7YfmbXKIdqzjoNx1NddB5AozYR5tuXw3e9OUS6VQURYSEiUUi39wGFpbcPrrH1j+TsXhqUoLp1kyIiGPlBxE7AdA+78CotXvIwk5wBsrUa+t3etxBAASTnWCg4wcOgTEOERMaVZxGFVeyLJe9o31e88iggTLqB416ytQ1ZH7wyOqi3YLJzn9uFIBhjINN0ZxEDGYmnJPGkQH9YK+BMjs8TrWSrC7ePhdjBgYPuAgyu8/I63f1H5J3l/PVeWn1AAAAAElFTkSuQmCC' diff --git a/DemoPrograms/Demo_Desktop_Widget_Launcher_Bar.pyw b/DemoPrograms/Demo_Desktop_Widget_Launcher_Bar.pyw new file mode 100644 index 000000000..a06b3cc19 --- /dev/null +++ b/DemoPrograms/Demo_Desktop_Widget_Launcher_Bar.pyw @@ -0,0 +1,182 @@ +import PySimpleGUI as sg + +""" + Demo Launcher Bar + + A 2021 version of a PySimpleGUI based launcher. + Once making the GUI leap, it's hard to go back.... at least for some people. + This tool will perhaps help make for a more GUI-like environment for your Python activities + + + Copyright 2021 PySimpleGUI +""" + + + +excel_icon = b'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAACXBIWXMAAAsSAAALEgHS3X78AAAFB0lEQVRIx51We0xTZxQ/X3t5lZY+QLwgLYgg4MSJOAQCOgED23SgMjedr2mY2UQhwblHNpK5xCxTM+Nkf+Dc2NTMZJCpEF3YsqU6y5ZsGpextSD0AcKlBeVR+rrt/fbHhcv1tlTGSdN8j3O/33mfgxiGAR4hhDDG7D/MTgghAGA5+efcCbdAAgA+jGDLYDzuspuGByZck7JwSZYmw/9dARgAEEHE9Hhp08iAftBooEx6ytg1ZB4YtblpDwCsVKe11ZzlC8sJxNmA3c4A0D7vg0fWbqtZP2gyUCYDZTIO97tozyw2mhGce4t9mv86QggxDNOobW69p+219U+4HQEt5k8xMsXGFWv9zzEGDBghFCImSjJyC1KzCISQrufeXYse/g+FikNTYjVBGMac9vorDb8cPU8Ej5ZZNZAqXiuo4Ftf4I/BMds3utYnODkIDYxa6680AEBRek5GfHLDz5fxtGvyU1aWPpUPABgwxnieAMP20fO3vgcAZaSclMd8+esVzhKEWMwCIEDz10ASGp5GJgEAGRUdERqWpU7HMAWwSBE7HUKAECL8U0ytIqVhEqOt30m7AWBLdkmiitR2/XnH/C/HlhKraT38Gbe9dviMf54DIIwxIchABKhxd31mQurbzacvdrQlL0g4ta3O46MvdLTx2fSUMf/4LkBQtbZyXVr2rnPvcRrsWPP8oeIdAAgBIIREgihiMNOobcYYb88pA4CdeRtDiZCLHW3D9lFBklseUpYRasw5QXu97Jr9PXKMY4wBMCAI7OTWv7R1pXsyE5ZmJy17afUGu8vRqG0R8JDy6N15LwJA7pIVMTLlW2V7AYDVYVViOj+TAwDQXu8Xt1o+qqj+eGuNUhJ17mbL0PiIgCcqQlq6PJ9NaVmYhA0bllSRcn49CRxFzX/8VFuyMyMu2eFxNd5s9mfooszFJ6sA4EjpnucyC0pOvc6Z+sC6yg82HeAKqmiWcg8+zCCExCJROBH2xMYgqIOPmSgAB8Ce/PKFUdF3zP9kaTLeWL/t6HefChiWkomf73wfAC+QKmXhkT/WNcKUE5AqMoorfQAQQAN5hLRq7ZZJt7P28gmnx7U1uyQxOk7AM+6cbO/UtXd29Nj67W5He6eO3bZ36rqGzFOKYAjsg32Fm6Oliku/Xe+x9l27p335mdKDRa8IlKDGhj+58RUAHCnbK5dIT/zQNOODZysLU1cBYBzQBwqJbH/BZi/j+1p3FQCabl/1MUzl6g1qFflYuSZC1CpSrSLlEZEhIkKtWshu1SpSESHjcwo1cNGe8rM1YpGoe8gCAH8/uP9Oy+lFytikmPi+hxTHlk4uvl7bwG11716YLQT8Adw91j5+4/729xv+X963WjadOQQAr+a9kL/k6epLx7mCsHlV0f7CLTMazK/hODwutgkWL8t10u67FgP3Ts7i5Xz5AofpXDpaedZ6AMjSpCklUfsKKrirNcmZ/Flmnv0gXhH7YfmbXKIdqzjoNx1NddB5AozYR5tuXw3e9OUS6VQURYSEiUUi39wGFpbcPrrH1j+TsXhqUoLp1kyIiGPlBxE7AdA+78CotXvIwk5wBsrUa+t3etxBAASTnWCg4wcOgTEOERMaVZxGFVeyLJe9o31e88iggTLqB416ytQ1ZH7wyOqi3YLJzn9uFIBhjINN0ZxEDGYmnJPGkQH9YK+BMjs8TrWSrC7ePhdjBgYPuAgyu8/I63f1H5J3l/PVeWn1AAAAAElFTkSuQmCC' + +# This is your master table.... keys are what will be shown on the bar. The item is what you want to happen. +launcher_buttons1 = {sg.SYMBOL_DOWN_ARROWHEAD : None, + 'PSG Main': sg.main, + 'Word': r"C:\Program Files\Microsoft Office\root\Office16\WINWORD.EXE", + excel_icon: r"C:\Program Files\Microsoft Office\root\Office16\excel.EXE", + 'Notepad++': r"C:\Program Files\NotePad++\notepad++.exe", + sg.EMOJI_BASE64_PONDER: sg.main_sdk_help, + sg.EMOJI_BASE64_HAPPY_IDEA: r'C:\Python\PycharmProjects\PSG\DemoPrograms\Demo_Desktop_Widget_Postit.py', + 'All Elements' : r'C:\Python\PycharmProjects\PSG\DemoPrograms\Demo_All_Elements.py', + 'Exit': None } + +launcher_buttons2 = {sg.SYMBOL_DOWN_ARROWHEAD : None, + 'PSG Main': sg.main, + 'Exit': None} + +panel_rows = (launcher_buttons1, launcher_buttons2) +col_panel_list = [] +num_panels = len(panel_rows) +MINIMIZED_IMAGE = sg.EMOJI_BASE64_HAPPY_THUMBS_UP + +DEFAULT_SCREEN_BACKGROUND_COLOR = 'black' +DEFAULT_BUTTON_SIZE = (None, None) + +def settings(window:sg.Window): + layout = [[sg.T(f'Screen size = {sg.Window.get_screen_size()}')], + [sg.T(f'Your launcher is currently located at {window.current_location()}')], + [sg.T('Enable autosave and position your window where you want it to appear next time you run.')], + [sg.T('Your Screen Background Color'), sg.In(sg.user_settings_get_entry('-screen color-', DEFAULT_SCREEN_BACKGROUND_COLOR), s=15,k='-SCREEN COLOR-')], + [sg.CBox('Autosave Location on Exit', default=sg.user_settings_get_entry('-auto save location-', True), k='-AUTO SAVE LOCATION-')], + [sg.CBox('Keep launcher on top', default=sg.user_settings_get_entry('-keep on top-', True), k='-KEEP ON TOP-')], + [sg.CBox('Reroute STDOUT to Debug Window', default=sg.user_settings_get_entry('-reroute stdout-', True), k='-REROUTE STDOUT-')], + [sg.OK(), sg.Cancel()]] + event, values = sg.Window('Settings', layout).read(close=True) + if event == 'OK': + sg.user_settings_set_entry('-auto save location-', values['-AUTO SAVE LOCATION-']) + sg.user_settings_set_entry('-keep on top-', values['-KEEP ON TOP-']) + sg.user_settings_set_entry('-screen color-', values['-SCREEN COLOR-']) + sg.user_settings_set_entry('-reroute stdout-', values['-REROUTE STDOUT-']) + if values['-KEEP ON TOP-']: + window.keep_on_top_set() + else: + window.keep_on_top_clear() + + + +def ToolButton(item, background, tip): + if isinstance(item, bytes): + button = sg.Button(image_data=item, key=item, metadata=launcher_buttons1[item], button_color=background, tooltip=tip, border_width=0, + pad=1) + else: + button = sg.Button(item, key=item, metadata=launcher_buttons1[item], tooltip=tip, border_width=0, pad=1) + return button + +def make_window(): + global col_panel_list + screen_background_color = sg.user_settings_get_entry('-screen color-', None) + old_bg = sg.theme_background_color() + sg.set_options(border_width=0, background_color=screen_background_color) + sg.theme_background_color(screen_background_color) + col_panel_list = [] + for count, launcher_buttons in enumerate(panel_rows): + button_row = [] + for item in launcher_buttons.keys(): + tip = 'Grab anywhere to move the launcher\nClick an item to launch something\nRight Click to get to settings' + button = ToolButton(item, screen_background_color, tip) + button_row.append(button) + col_panel_list.append(button_row) + + + col_up_down = sg.Col([[sg.B(sg.SYMBOL_UP, button_color=screen_background_color)], [sg.B(sg.SYMBOL_DOWN, button_color=screen_background_color)]], p=0, k='-COL UP DOWN-') + col_buttons = sg.Column([col_panel_list[0], ], p=0, k='-BUTTON COL-',visible=True) + col_buttons2 = sg.Column([col_panel_list[1], ], p=0, k='-BUTTON COL2-', visible=False,) + col_minimized = sg.Column([[sg.Button(image_data=MINIMIZED_IMAGE, k='-MINIMIZED IMAGE-', button_color=screen_background_color, border_width=0)]], visible=False, k='-MINIMIZED COL-') + col_panel_list = [col_buttons, col_buttons2, col_up_down] + layout = [[sg.pin(col_minimized),sg.pin(col_up_down), sg.pin(col_buttons), sg.pin(col_buttons2), ]] + + screen_size = sg.Window.get_screen_size() + location = screen_size[0] // 2, screen_size[1] - 200 # set a default location centered and near the bottom of the screen + location = sg.user_settings_get_entry('-window location-', location) + keep_on_top = sg.user_settings_get_entry('-keep on top-', True) + + + + window = sg.Window('Window Title', layout, location=location, + keep_on_top=keep_on_top, no_titlebar=True, grab_anywhere=True, background_color=screen_background_color, + auto_size_buttons=True, default_button_element_size=DEFAULT_BUTTON_SIZE, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_SETTINGS_EXIT, + enable_close_attempted_event=True, use_default_focus=False, transparent_color=screen_background_color) + sg.theme_background_color(old_bg) + + return window, col_panel_list + + +def main(): + if sg.user_settings_get_entry('-reroute stdout-', False): + mprint = sg.Print + else: + mprint = print + window, col_panel_list = make_window() + cur_panel = col_panel_list[0] + count = 0 + while True: + event, values = window.read(timeout=1000) # Not needed but handy while debugging + if event != sg.TIMEOUT_EVENT: + mprint(event, values) + else: + continue + if event in (sg.WIN_CLOSE_ATTEMPTED_EVENT, 'Exit', sg.WIN_CLOSED) or str(event).startswith('Exit'): + if event != sg.WIN_CLOSED: + if sg.user_settings_get_entry('-auto save location-', True): + mprint('saving location', window.current_location()) + sg.user_settings_set_entry('-window location-', window.current_location()) + break + try: + action = window[event].metadata + except: + action = None + if action is not None: + if isinstance(action, str): + if action.endswith(('.py', '.pyw')): + sg.execute_py_file(action) + else: + sg.execute_command_subprocess(action) + elif callable(action): + action() + event = str(event) + if event == 'Edit Me': + sg.execute_editor(__file__) + elif event == 'Version': + sg.popup_scrolled(sg.get_versions()) + elif event == 'Settings': + settings(window) + window.close() + window, col_panel_list = make_window() + if sg.user_settings_get_entry('-reroute stdout-', False): + mprint = sg.Print + else: + mprint = print + elif event.startswith(sg.SYMBOL_DOWN_ARROWHEAD): + window['-BUTTON COL-'].update(visible=False) + window['-BUTTON COL2-'].update(visible=False) + window['-BUTTON COL2-'].update(visible=False) + window['-COL UP DOWN-'].update(visible=False) + window['-MINIMIZED COL-'].update(visible=True) + cur_panel = col_panel_list[count] + elif event == '-MINIMIZED IMAGE-': + cur_panel.update(visible=True) + window['-MINIMIZED COL-'].update(visible=False) + window['-COL UP DOWN-'].update(visible=True) + elif event.startswith(sg.SYMBOL_UP): + cur_panel = col_panel_list[count] + cur_panel.update(visible=False) + count = (count + (num_panels - 1)) % num_panels # Decrement - roll over to MAX from 0 + cur_panel = col_panel_list[count] + cur_panel.update(visible=True) + elif event == sg.SYMBOL_DOWN: + cur_panel = col_panel_list[count] + cur_panel.update(visible=False) + count = (count + 1) % num_panels # Increment to MAX then roll over to 0 + cur_panel = col_panel_list[count] + cur_panel.update(visible=True) + window.close() + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/DemoPrograms/Demo_Desktop_Widget_Manual_Counter.py b/DemoPrograms/Demo_Desktop_Widget_Manual_Counter.py index daf720c1c..6a4171868 100644 --- a/DemoPrograms/Demo_Desktop_Widget_Manual_Counter.py +++ b/DemoPrograms/Demo_Desktop_Widget_Manual_Counter.py @@ -6,11 +6,7 @@ This one is a manual counter. Click +/- to add and subtract to the counter Dedicated to @SuperScienceGirl for having the original analog clicker that spawned this digital one. - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ ALPHA = 0.9 # Initial alpha until user changes @@ -125,7 +121,7 @@ def main(): if new_count is not None: counter = int(new_count) elif event == 'Choose Title': - new_title = sg.popup_get_text('Choose a title for your counter', default_text=sg.user_settings_get_entry('-title-', ''), location=window.current_location(), ) + new_title = sg.popup_get_text('Choose a title for your counter', default_text=sg.user_settings_get_entry('-title-', ''), location=window.current_location(), keep_on_top=True) if new_title is not None: window['-TITLE-'].update(new_title) sg.user_settings_set_entry('-title-', new_title) @@ -138,7 +134,7 @@ def main(): # this is result of hacking code down to 99 lines in total. Not tried it before. Interesting test. _, window = window.close(), make_window(loc) elif event == 'Set Main Font': - font = sg.popup_get_text('Main Information Font and Size (e.g. courier 70)', default_text=sg.user_settings_get_entry('-main number font-'), keep_on_top=False, location=window.current_location()) + font = sg.popup_get_text('Main Information Font and Size (e.g. courier 70)', default_text=sg.user_settings_get_entry('-main number font-'), keep_on_top=True, location=window.current_location()) if font: sg.user_settings_set_entry('-main number font-', font) _, window = window.close(), make_window(loc) @@ -168,7 +164,7 @@ def main(): if sound_file is not None: sg.user_settings_set_entry('-sound file-', sound_file) elif event =='Show Settings': - sg.popup_scrolled(sg.UserSettings._default_for_function_interface, location=window.current_location()) + sg.Print(sg.UserSettings._default_for_function_interface) sg.user_settings_set_entry('-counter-', counter) @@ -176,5 +172,4 @@ def main(): if __name__ == '__main__': - sg.set_options(keep_on_top=True) main() \ No newline at end of file diff --git a/DemoPrograms/Demo_Desktop_Widget_Postit.py b/DemoPrograms/Demo_Desktop_Widget_Postit.py index f3fda311b..60be41514 100644 --- a/DemoPrograms/Demo_Desktop_Widget_Postit.py +++ b/DemoPrograms/Demo_Desktop_Widget_Postit.py @@ -8,11 +8,7 @@ Note that while the window has no scrollbar, you can still use the mousewheel to scroll - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ # ----- Make the window ----- diff --git a/DemoPrograms/Demo_Desktop_Widget_Postit_3_Lines.py b/DemoPrograms/Demo_Desktop_Widget_Postit_3_Lines.py index 7b3e7864e..c4e4e8890 100644 --- a/DemoPrograms/Demo_Desktop_Widget_Postit_3_Lines.py +++ b/DemoPrograms/Demo_Desktop_Widget_Postit_3_Lines.py @@ -12,11 +12,7 @@ Note that while the window has no scrollbar, you can still use the mousewheel to scroll - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ # ----- Make the window ----- diff --git a/DemoPrograms/Demo_Desktop_Widget_RAM_Gauge.py b/DemoPrograms/Demo_Desktop_Widget_RAM_Gauge.py index 261a72401..c3ec10b5b 100644 --- a/DemoPrograms/Demo_Desktop_Widget_RAM_Gauge.py +++ b/DemoPrograms/Demo_Desktop_Widget_RAM_Gauge.py @@ -14,11 +14,7 @@ This is a good example of how you can use Graph Elements to create your own custom elements. This Gauge element is created from a Graph element. - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ ALPHA = 0.5 @@ -55,7 +51,7 @@ def add(number1, number2): : Return Addition result for number1 and number2. """ - return number1 + number2 + return number1 + number1 def limit(number): """ @@ -279,7 +275,7 @@ def main(location): [sg.T(size=(8, 1), font='Any 14', justification='c', background_color='black', k='-RAM USED-')], ] - window = sg.Window('CPU Usage Widget Square', layout, location=location, no_titlebar=True, grab_anywhere=True, margins=(0, 0), element_padding=(0, 0), alpha_channel=ALPHA, background_color='black', element_justification='c', finalize=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT, enable_close_attempted_event=True) + window = sg.Window('CPU Usage Widget Square', layout, location=location, no_titlebar=True, grab_anywhere=True, margins=(0, 0), element_padding=(0, 0), alpha_channel=ALPHA, background_color='black', element_justification='c', finalize=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_EXIT) gauge = Gauge(pointer_color=sg.theme_text_color(), clock_color=sg.theme_text_color(), major_tick_color=sg.theme_text_color(), minor_tick_color=sg.theme_input_background_color(), pointer_outer_color=sg.theme_text_color(), major_tick_start_radius=45, @@ -294,7 +290,7 @@ def main(location): if gauge.change(): new_angle = ram_percent*180/100 - window['-gauge VALUE-'].update(f'{ram_percent}%') + window['-gauge VALUE-'].update(f'{ram_percent}') window['-RAM USED-'].update(f'{human_size(ram.used)}') gauge.change(degree=new_angle, step=180) gauge.change() @@ -302,13 +298,10 @@ def main(location): # update the window, wait for a while, then check for exit event, values = window.read(timeout=UPDATE_FREQUENCY_MILLISECONDS) - if event in (sg.WIN_CLOSE_ATTEMPTED_EVENT, 'Exit'): - sg.user_settings_set_entry('-location-', window.current_location()) # The line of code to save the position before exiting + if event == sg.WIN_CLOSED or event == 'Exit': break if event == 'Edit Me': sg.execute_editor(__file__) - elif event == 'Version': - sg.popup_scrolled(__file__, sg.get_versions(), location=window.current_location(), keep_on_top=True, non_blocking=True) window.close() @@ -318,5 +311,5 @@ def main(location): location = sys.argv[1].split(',') location = (int(location[0]), int(location[1])) else: - location = sg.user_settings_get_entry('-location-', (None, None)) + location = (None, None) main(location) diff --git a/DemoPrograms/Demo_Desktop_Widget_RAM_Square.py b/DemoPrograms/Demo_Desktop_Widget_RAM_Square.py index f80cfb1cb..7232f0e8f 100644 --- a/DemoPrograms/Demo_Desktop_Widget_RAM_Square.py +++ b/DemoPrograms/Demo_Desktop_Widget_RAM_Square.py @@ -9,11 +9,7 @@ The % and number of bytes in use is shown on top in text. Uses the theme's button color for colors. - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ ALPHA = 0.5 @@ -34,7 +30,7 @@ def main(location): graph = sg.Graph(GSIZE, (0, 0), GSIZE, key='-GRAPH-', enable_events=True) layout = [[graph]] - window = sg.Window('RAM Usage Widget Square', layout, location=location, no_titlebar=True, grab_anywhere=True, margins=(0, 0), element_padding=(0, 0), alpha_channel=ALPHA, finalize=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT, enable_close_attempted_event=True, keep_on_top=True) + window = sg.Window('RAM Usage Widget Square', layout, location=location, no_titlebar=True, grab_anywhere=True, margins=(0, 0), element_padding=(0, 0), alpha_channel=ALPHA, finalize=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_EXIT) while True: # Event Loop @@ -47,14 +43,10 @@ def main(location): text_id2 = graph.draw_text(f'{human_size(ram.used)} used', (GSIZE[0] // 2, GSIZE[1] // 4), font='Any 20', text_location=sg.TEXT_LOCATION_CENTER, color=sg.theme_button_color()[0]) event, values = window.read(timeout=UPDATE_FREQUENCY_MILLISECONDS) - if event in (sg.WIN_CLOSED, 'Exit', sg.WIN_CLOSE_ATTEMPTED_EVENT): - if event != sg.WIN_CLOSED: - sg.user_settings_set_entry('-location-', window.current_location()) # The line of code to save the position before exiting + if event == sg.WIN_CLOSED or event == 'Exit': break - if event == 'Edit Me': + elif event == 'Edit Me': sg.execute_editor(__file__) - elif event == 'Version': - sg.popup_scrolled(__file__, sg.get_versions(), location=window.current_location(), keep_on_top=True, non_blocking=True) graph.delete_figure(rect_id) graph.delete_figure(text_id1) @@ -67,5 +59,5 @@ def main(location): location = sys.argv[1].split(',') location = (int(location[0]), int(location[1])) else: - location = sg.user_settings_get_entry('-location-', (None, None)) + location = (None, None) main(location) diff --git a/DemoPrograms/Demo_Desktop_Widget_Template.py b/DemoPrograms/Demo_Desktop_Widget_Template.py index 3a0d52af5..4e152ecd3 100644 --- a/DemoPrograms/Demo_Desktop_Widget_Template.py +++ b/DemoPrograms/Demo_Desktop_Widget_Template.py @@ -32,11 +32,7 @@ * Naming User Settings keys in the format '-key-' * Using standard layout, window, event, values variable names - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ ALPHA = 0.9 # Initial alpha until user changes diff --git a/DemoPrograms/Demo_Desktop_Widget_Time_Handwritten.py b/DemoPrograms/Demo_Desktop_Widget_Time_Handwritten.py deleted file mode 100644 index bf2a7a4a2..000000000 --- a/DemoPrograms/Demo_Desktop_Widget_Time_Handwritten.py +++ /dev/null @@ -1,91 +0,0 @@ -import PySimpleGUI as sg -import datetime - -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - -sg.SYMBOL_CHECK_SMALL = '✓' # can remove line if using later PySimpleGUI version that has this symbol defined - -menu_sizes_original = ['Large::Large', 'Medium::Medium', 'Small::Small'] -menu_sizes = menu_sizes_original -max_digits = 8 - - -def right_click_meny_new_size(window, new_size): - current_size = window.metadata # Window's metadata has the subsample value - menu = window.RightClickMenu # Dangerous operation... directly accessing the right click menu with assumption same for entire window - menu_sizes[current_size - 1] = menu_sizes[current_size - 1][1:] # Remove checkmark from previous item - menu_sizes[new_size - 1] = sg.SYMBOL_CHECK_SMALL + menu_sizes[new_size - 1] # Add checkmark to new item - sg.user_settings_set_entry('-subsample-', new_size) - [window[('-IMAGE-', i)].set_right_click_menu(menu) for i in range(max_digits)] # Set right click menu for all image elements - window.metadata = new_size # Store the new subsample value as the Window's metadata - -def main(): - - base64_digits = {'0':i0, '1':i1, '2':i2, '3':i3, '4':i4, '5':i5, '6':i6, '7':i7, '8':i8, '9':i9, ':':colon, ' ':blank, '.':dot} - - subsample = sg.user_settings_get_entry('-subsample-', 2) - location =sg.user_settings_get_entry('-location-', (None, None)) - alpha = sg.user_settings_get_entry('-alpha-', 0.9) - menu_sizes[subsample-1] = sg.SYMBOL_CHECK_SMALL + menu_sizes[subsample-1] - right_click_menu = [[''], ['Version', 'Edit Me', 'Save Location', 'Size', menu_sizes, 'Alpha', [str(x) for x in range(1, 11)], 'Exit', ]] - - layout = [[sg.Image(blank, key=('-IMAGE-', i), p=0, subsample=subsample) for i in range(max_digits)]] - - window = sg.Window('', layout, background_color='black', no_titlebar=True, grab_anywhere=True, right_click_menu=right_click_menu, location=location, keep_on_top=True, enable_close_attempted_event=True, alpha_channel=alpha, metadata=subsample) - - while True: - event, values = window.read(timeout=300) - if event in (sg.WIN_CLOSED, 'Exit', sg.WIN_CLOSE_ATTEMPTED_EVENT): - if event != sg.WIN_CLOSED: - sg.user_settings_set_entry('-location-', window.current_location()) - break - # Update the Image Elements with current time - date = datetime.datetime.now() - time_string = f'{date:%I}:{date:%M}:{date:%S}' - subsample = window.metadata - for i, c in enumerate(time_string): - window[('-IMAGE-', i)].update(base64_digits[c], subsample=subsample) - - # Process the event - if event == sg.TIMEOUT_EVENT: # if a timeout, then do nothing (saves a TINY amount of time not checking all the if statements...) - pass - elif event == 'Edit Me': - sg.execute_editor(__file__) - elif event.startswith('Version'): - sg.popup_scrolled(sg.get_versions(), non_blocking=True, keep_on_top=True, grab_anywhere=False, location=window.current_location()) - elif event in [str(x) for x in range(1,11)]: # Alpha channel selected - window.set_alpha(int(event)/10) - sg.user_settings_set_entry('-alpha-', int(event)/10) - elif event.endswith('Small'): # Size changed to Small - right_click_meny_new_size(window, 3) - elif event.endswith('Medium'): # Size changed to Medium - right_click_meny_new_size(window, 2) - elif event.endswith('Large'): # Size changed to Large - right_click_meny_new_size(window, 1) - elif event == 'Save Location': # Gernally not neeeded since save on exit, but may make user feel better - sg.user_settings_set_entry('-location-', window.current_location()) - - window.close() - -if __name__ == '__main__': - - i0 = b'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' - i1 = b'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' - i2 = b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAAAAADji6uXAAAACXBIWXMAAAsSAAALEgHS3X78AAAQq0lEQVRo3u1a2XLcxpbMPFVYGuiNixZb9l1mbsz8/6/M24Qj7mbLlrhvvaBRdXIegCapq6Zl3dcxQlSQTQIHVWfLzDrEFy6SlAhJICiC0P53ZsxyCUS0wnLOGRJDjOYpZR14XsQXLQZIkkbrAAQNLwI4JQIAARKSCBJyuevg475o0Myo7KNBw942GLh/KscXICERUNbT3339CmlO+vAt9ns7rlBOkMMi9wZIKD/9+FUGCRLQuGXg42MGT7oE0gAJjqzsGnZEDgHjrV9hcNwlSABhAByD/4yAD59boDwLnt0doEUqywFCoL5yhTZsIqQhWqW9RbmG4AnRPGU3FyXSQgiuLIKg/o0VYojLIUKFRz8JY8BYCNkJR6ZgoMWQM/FJ/vxWg5KPjtPw9fQblw9bxt4859HdEpSTu8NwyIEAwsvxMnxh2EY+BeKwbB/tCwZ3F2k23ijXGG4vPPfXovTTUNuHqAgO3oQNCwMsUNmdRhKk77flq4JGeHSgAIH7tT450y1TAKIZnYAyYWamMbq/xiCxdzxtCDjaEDsuxBhiWRaVQg6bzaZLjyEiOPcx/NVRapQLHN+YFkga3N3Luq5ns/nMLfHy6urKlJ/KpzL/ndImWjCHyywSEixEoxk9pTyZNtPjk1cnYLaffrbdrnf3vQ3ns13/mhVaMDhBCyY5LMYQLMANrNv50TfffvdWzKywupBD/uh6vfjMX89Dz/JsqZpNZ0UZJwwRwQw5pdzMptOT09OTHDLPmyoEDwLGOg59Unm/wiCUHZicnJ7Opu0MZjAjPGVvJlU9m87mZNasqWKKCnQfIloUSB6Kml9PC1cOllEt3nx/cvL6hCJFgyf3UMVyUpaV0/BhVhmQs0CIY4OhEQe68K+vEIID1p68+8/v3r57TQdEStkVAmESA+jTSbRQ7ILLFYZaQtLo+LxdfKkfooqMy/lsUZUxQO4EAOM+OekKaF7/ab3ZrbvNerXJnp0kZPj6SkOSoa6ro+ViNq0CND6MMJAGB5xwVEff9il1/dXV5VW32zrMKEmur+74xnIyb4+Xy3lbB7g8k6SZ8WnbnfVp36Sc8/v3IW1WO8GiZU/uX19pgGoyny2Xi/mkioQ8k2YCjQIgCnLWJ/HERZ8V6UG9gRaC9g3zt7an/Z4evXr353ffvTltypIQzMxIGkWnzAkPcBnLojL3OCkDdiWpLB3sUC+ucFiBszz67i+nr4/aMsIBg0iSI1pzyYwsEaIy0i5Vs2nl67zLiWI45MT4a51JEJqTb/9jvjxaAsgDYILcDG7wfUcJVVF6UlZ5/Lb0+6uOXZ/NDjaoL/bDcvnuL7NqMuk9yWDGLDjNuQ96I0sAOWeVU9/23fXFXZ+6KNK/sKX8rPcC2N78uDxenBhF0EjP0LbrNn3fJ4EoylhO6roGiQhZ286PKO81NKgXE5/7//X8AwGr8x/Ld69jHWHBDDBDv7m5uV2vV2vQULd1e3x03DgNgjCZHh2r74LgemwfnxvkJ7jp+Qo3l2XKnB97jJGgPDNvbj6cX19f3ZFR80Uz/6YvZqSRlNXTo1Pv1qWn7C/7kE+I6Wl/h662vswPRXXytopj7oHqrt//eH7+8QqMfnK8ONXkFKDRiNxMF8vt/aTcUS6+EKVjD/sUuGogL96t8GFSeV1NSgPojvzj+7Pzq5vNyhBxr37dzk/fmJUkFJrjHri/7Bwm6XMsHMePNPaU55iQpDFvtTsrQ19XTRkAUvSff/54fnf7sDEFpO26Pjm+uilLRgPQHFm9+hizi8EPODECTxzzCRfuwVqgpbwpfXvd1NM6mBlEffz44Wx9v96aTGl3G09O7zaOQJlZfTQ7ufwHt2Y0y59bjAcy4elb0npPjt3DVVtP62jBSOLi4uxys+62ALCm+M355fUMoQDJZkL9dVHBByL0ld1CEkSkTcC2WpWBRjPazc3Dph/4AxzQ9u7sp+Nja41yG2p+Dvo6IDxSiQFrpo6+KcqCIBEYHh4eNjmJoEjIt9e/NH1o9plM0AxyHKyl1K9QGQcgQ96mLlgIABAC4nbXdVk00CkHtrfnRWyPJZGgZBpo90EVgy9hyEe6JOTUGQZ6rxBYJM85IBgoBjF3t6FrTrp9qMn27jiUh36QTvFZLjLuKdvwmTkgaCjNcgip2667XhEcGFsmwwj1X6g0+rR68xHRapRHpH+lbRoJmwPw1G37zEDuqwfJF5STqANL4/hPABiCKT29rh6TdaT7gHy3ttVOZntWvxcj8q+ICp+W06e6SpoN3IR65llqADQQAM99lx0khs8HLYX4Uj98lqcaANJIoOUaAPWe+eupIoFUUbfTpo72+A571jrA/d+Qh0/Md+R6e21m8NrA70WAMBJVu1jMJnGEQtJLotCBfkg8c9MoOGnIDgsGAYNsN+zAIKuQsZouZ3UYfCyHQBMOWz3cD58JXBjzxmhhAO/72NPIIMzqdr5s6whqkKf2AJEvAGH+a83W08/cozcXoUHOGrh/Nt8netUuXy/a6JTMxTTIZS7Xl8mMPjE8vuJwlwaboIljxo3AqpwuT+eT4DZUI3dJcnf5QYjBTyLl030XNdJKJ/KwOHAkMtDwLla2x2+O25BF42MUePaDif9Jz/qcsj7RdWXQEPIQJ7R9ahAsmvnJoo5DOZI8u8N1kMsg8nAHflbmBAx9QSGGorBgBLnZpqGO0ELVzI/aqhjqaMq7XZ+SBB4EUTxUYT8FcEMOMiGUZV0WZYTAe1sbCJjRYt0u6moIB09dt92lBNineuCnQaPP7fFZhowIMZRNW9VNCXcF9QQBC2Q5mS5KG8qy+m6z6fpM0pT1W/shnyxiUKIgIhR10zazGjnLu7X50N5DMZkt6ZRA5NRtuz7lQPsSt9jDXKNoIMhQloXE3JRl7cpoZ/PppG5LZtfrq8srB1DUofmvtzM3g3lmPrs6//i3j3cB8i9hGo0LI2kGGmLdTCYUNWvbVsxsp7NpXU0KuuPy6vpaBOo6Tr77pgVA8+S765/+/o/3Z1vTqI8fMvgs9IcAoRnJrKJdLs2J+XK5oCm0s9k0llWEhNur6xsRKpp6Oj9uJRK+67Yf/va/P9zePYzk6YuVZkgyMzPGHKeLk1MxhJPTV0dmCO101haxCJBwd3N7K0CzuppYFQiSSrvN9fsf/qeTh2fS278YfJYvZsHKqijLsixDFcqjxWJJp+aLo3kwsZlUZQhGAApVC4CIZVUhhoH6Eyjb07fb7Wr7wjnJADFGe2QsQtO2zbRp26qpqmkzmULwaTttxYy6KiMJyd1ZTANBWjCahUADaBaao1fvrm936xfVxL18TgEWy2K+WMwW8/mync7auqyr3pWasqqEpLKIxaBxSyzrasCf8hhi4AhHytnJJqJ7SF+SLwXAYllOlycnpycnJ8v58TSSwVPelcFiQu/RGAHI3bOFUgGGlFNf0sKebjXLtefttb8g6g8+3GODsl3OXr15+2rZzNtJGcxAOBXk7impL2I0ccBIgTLRAVqhYIAbFCosetaxqmer+9UDDpTv+JyjVbPj43fffPt6Ujb1pC4DQZgblByevJcLRgIcxKFRpRQohwNWhpBRN+WkmZ+fcy3zz9NCT61dRXv05pvv//SdQayraMOBCCll9Sn1cthwAhao8SzRaTYCRMHMFGeLZjo7nlp3JT/ID5/eoZoev/3++z/+IeUuhyKQAGIWlfrUp9QTQWnIUg6ntI4wCrISEIxset9N58tXWl3FdLg9cQ/d2Ry//dOb44kZIqMpybNWm+12vd1sDPDlfL4oQ4yAUS6XhE3uU845l6GIZVEU2R1Fk8Ifd8LDw92Df97xSclFmibLN388WlQgo8ldOfX57ubm7nZ1f29FjG9f5aIvK4KScsoiuVnfb/q0S23TTia1FWZi2YZm3YX6w4f+7gDEMFOmjIZm+c2fq6ZSIJU9537X9ednv1xc3F5ftZNJvd6FpnILpNFTl2iB27vz222/282XR3NHAffsNqld1WQW+/vzz1ZIBmqQ4W1y9M0faAIY4ci7brPdnf/8j59/uTg7n83msxSmS1iZjYLnPiHKVrdnF6tus329ybLYAKDFGAPL5rRfnR0KmkwzBBBZSnAPOXhQVFQuUp6deHN0c3M9aer223cn87KKNgjsMW/v1tuPZ+e/pE3qVveXx69PtxkWCE/OYqp5FQ9VGicYzJE9Z8+QfICHAZ5Tbr06erNe35dFLE7fHLVlWUZCsuDcXF9efzg7/+h97m+uZ4v7jWxSlKUkj2XDpi4+z0NKMosx5VFUUXbQYIQr7cJ8cpo2XdfJEBbL2TTGGIIZE63aXf79n9fn5+fuyu15Xd3vQrObWpuVsxehmTV2CERJogXPkKe0IwA3gSRjLHJjZXAp55xyVReTSDMQipa5ufzph4vLEWqEOlo5XXosXAKikU1d2GdBIzk8m8mhfnN/XcRYwGAuE2NFhhjkspCDl1UsUlbuU993aeM//P3Dxf0228g6drfvw25xND+eNNNJ2vX55qHzg/1QGa4sps3Nedu0Q4lBlkIVBowDuruHIpr6vlutV6tuu9798+f3F91WhSvLkXn/Md9Pl4vl2zdx+dDdbW7W/eEGLPcsGfL65rznJNAEugshllIWjSaHW8Ggfr26ub6+3qzX6/OLj1dZKLJnAYk33c37o+my/W8uQtre3NytXjDogFOGtLm7CnUCCbg7GCKyMwcLAQ4xyNRv7y/OPp7f36/u7+6v70orwzAUkuz+Vr5ojpq4+D769vbi9pBBG45d5SHZw3nD8/mr+XQyaTROkGR3wYDttusSEtar9frq5upqu11v1tvMjOTKGCZdJOzKO7yf2frq/Prin1frA8U7BPOcZKCvzrWez4/ny6PF0SBV7icGXDe3N7d92qWuS93DanXf73bdtksaZlkeuT3UC7+E1dn97f3dxeUBgxbKkHt3B7G53N60zaR5++7bbEUZlFMmAc/Jzz98+Ljrtp2y8rbru5yz90nMbiNiGFhIr9Bze/bX3WazXa3Xnye+hRCQSTp092BW1mX7h00OdVlF73uHGXKf8t9++vHv2/v1iow2SFCEuwTlgV2NM0zecX1/FmKv5DgosnuWiwZQwYxQv775xTexLIOnNBhM2c8+XD2kNPRPOUSB2A8QkRQ5DMG4icP4gA6fAXtPuI2DVmDeMV1zfRdCMM8ukHSXrm9u16lPEvNeZNwfZ2lUusb5DxfAAMDgB6QvKoE05qGcBbn3N/3NBfYSzQjqVttum6GQR2VRIkVyEGHHMZjxbNsoudH0wpbCAk3RMwnmnPP2VjEP6vMTA85yRATC/ZH92yg4kwNXJCg6lJWDzPIB0TuEUfqT5/GELiOEOIwmcD+mBLhEo5EuYVArRv13oMx5LxcJ1HBMAxySTQTafr4J8nFmzQI0zj/BMA62iQAdGmY05MCgyeCRfA4qmcaJGx7WSy1gvI2j8gvGstiNh/DjAIjvx1wAgmEYCoF8OGl3+qPK8jidooMTElEg5T6onY8DehYe5UqS4KdslqD5wICGcH0M0b0yB+oFfhiGuTd/0kOHoT+knHyv1zxKWEN+a5wK1KfaypN4OATFYYIYxuc9Styj+KyUnzSP/aOH4Bll59EJPHDcyV8ZOAmD5CvgmUJEuZLrs5uHGvN0aPOZ1qLnRzq/YQjxkAqFw+NbxG+7fuvf/X79fv1+/X79fv1+/b+6/g9YOdhuTCBe+QAAAABJRU5ErkJggg==' - i3 = b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAAAAADji6uXAAAACXBIWXMAAAsSAAALEgHS3X78AAAPSklEQVRo3u1a23Icy3GsrO657BW7WAAESFHnKML+/y/xo8OyLMuWjkniDuxlZufSXemHmV0AOgBI4JkTQQIMxkx1VVdlV2Y15LUHAhGIAIgkRQAKRb3XYDGKiACACoQUAgITI0SUJIW//6R/1R4gIkIhQIoItPtpkWbd16CqQlIAEdIIEqpqZnzGnrhXDSpUhOz/9P8WERGy/5xziVdaVHUONKMY1HsPedbe6x5Kt2zZhwYKCIVisvseoGpCEgoaSREC6mjPf/E7BikikJ3FbkP7vwSEdFE0M9JMd1Ek9wF4o0F2Pjz4CAEfJ5QILYBGIU36bRV2S3h7SCkUBUDuMgR9Hu3dpBi76PKRCVq0F1z8rocEsItoVyDYe9ttb78YGvrc6uL85pCCooAT9hmZQBPvMq9J4tLMRQa2VV23TayJCIr0ldoXCAXPZap/zTs458zMRCDOO5+nST7Kx6PBcJw3oWmK5XpVbiuxGE33qawQsS4gfKuHPknaYEahuCRJB3k+OJgfzg6ms+m2rqqby+vrYonaARYpFIpAu3IEFGR80x4C6rxZHxeXDkaD0ejDyenxyeHRoiyKzdfpKL1i2Jp1NbHLKwEpAIR4U0hJs2hmAqeYTQ8m0/F0Mj9czGbjzLlkIIcxHSyW93eb+80qWIh9vkCMxD5ObymL2DIEirpER/OTxXw6n00mk9F4kLmU0Kij6XqzWl9cXIampfWrRJ8qz1biq3vIyGhGgUv8ZPHp9Gh+tMizPEuSBF7g3aA9XRfr6q9JWCoCepgBKRAS8qYsFRETU6PA+TQ9WJx9/nD04chpoj1qc2iwuixryOpCogME1tnb4cJbPGRvE46D0Xh8/OHobHaQu9A2rSGoJpqqJEgGcEe3Z8XdDQsg4hH+vv08JAgHh8FkdnB6dnY2HA18VSw3ga2Mh/kgcYkXaDI/KZok1OjASLj78Y7TQmgqLp8cLg6PPpwmSarV8vwmsrXx4aFzTrwmiR0sKmNxZ+IecK9DOb4VSyHeJX4wmR+fnZ2dighDefu1aZt4xiRVpUJTmdf05VWKHl3wAP1v91CCCE00cTButnXx29ffvkYzK26uZ7ODg1maJakbzHg9n2QUsvMNL9n7jkGICKMYfOo9pLy5vf6/8y9faeTk6ny8OF4cTSZj1QHS8+kot2gRBF+w9UMegoxm4jKvYHn1j39cnH/7BoJ5ng8/nH0oDxvkOhhMv8zGmbWR7I9rvscgBMJoZnCJd7Dy5re/XJyfX6h4cc6lZ6uiDW544AeZLmbjQUsCQtJeNum+25c684MEYbve3Pz5r3//drcqakANIDPP6PLJzClweXdXw7UVd88Ln/yeQYEKHJuyWN3e/Pffv1wUZR0gIIRUtvVkMl8IVG+Wm4pxuzVSXjb3A2Vh6l3cNMvLUTbeFMVm2waVSAZRLVFvDo4qiLRMJh8KtLexx9P3Jg3FQ1luzJJMsza0wQsgoMBiCJXznzaNiJj54fykuEuMeP2L3y0LUhWAWAAtGoIqCNIEmuRJ6hFb59Sng/FslCciFEjfLr89SyFQGs0ooJIkAQHRwYlL8sHASyuWaJoNpoPM7U99e1fhdw0RRQRmEs1orjspRUDx2XAy8BKcCZLBuB2lfk8J5Jl+5gdCCuz6aViUR4BMgcBn+Sh3bJw5n+ajMMw8hEIIVCLe4SFJEddhsuuKGeJETSkibLeCVVMLxKTZrC7XZdt1y0KLFLwdvGkQKACAZjvfBFCCZKjNyjqSFMbt3eVdGXX3Ht/FLUA6daqqGmKIu+ZRAEYTa6jbZdFSADTF3dVyG7QPjL0rS4XoCKBzSmrX4KBLX0eRaIKqNqGRdbm8WW0DupR6GWv895BNaF2/oA5mwYSkdM04kKgOBoM8cWBbLq/uiwZkR90e88o3ZSloVDWFeFowdrzMaCbweZpOx6Oh97CqXN2uty078gZCIG/rvEXQMWyjqsJ5D5NooIE0QkmXZMPRIM+gbKrN8rbctg/sH+/xUKBGo6nCwbkYVbnLCRHx2XA6GY8GQrF2u7xu6lZ2/wd5V1nQCBVAFUFjNGiW5RnUlIE2nS2mvxwPpWq3zfVd2YSO+ILoAvpWgxSxjvQ6VTCKiWIyno2dFx9CjLPDw/nn46E0m9XmZlk0IXZUC9B3NsJCKFSdOrXQRlHR9ODkOEldWrfb9ujkw8n0MGe9vrm7ui+bGDtqr6qwd/alFEBVVY0hOOf89OjjpzRLsrrZNCcfTk8HeYpmfXN+tSqDRbPd3vM9Hu7kLBGxaEQyyPKjD2ef0zRJt2HbHM1nI6ub7fXF19/O7za/Uy7enDRQoOvbACORjkaT0z98/tUlLtnGuj0Yj/PYtsXt+W9/u73bPrJHk3fIJoAqxDo8g1CT0fzw+OzTL3BwMYRmkOeDdVuUNxdf/74qt3smKnwpoN9XE9Wk2xcHQTI8WHz4+PkXUSJGtomq27Je3Zz/9j8hhIjuSMLLzOI7ZUGDkVAKJXpabKqqXK9XziUqhDNBJElajGYE1bBTHt+ltZEGdvoaQVpoqm1VFqskyVMzVQEtdvAajd3RC4LCd54WYoQAEKPQKDE029Vqvc5z57xKL7MBYjHECOtFKKEYdhTq7eJeJ2ZRKBLbuqzLzdLEe1N4E7INkUYztb3yKPIKe3Lf44cCgOxURe/EYE1xv9qUdUQGKElgU2yrRBH0sZTwWHl8i8FeHhDAOdUYrCmX63VRRE3HADRSsNnWrZdYQx4UN2AvV7/RQ+lENGiisKZuytXdpixLzUYHEFWKum0dA0JdgPoENJ4L7Q8Y7N5y6tXaqi7Xt1frYltlo9mRKkTh06qNsa3LDXpZumuhtReH3ryHuuubSCPVEYkyOAntJlhmFFZNkLZe3wPUThWCKoTPHYnuB3JGH3CcJEyUobXY1DXSkYigobiiWK0gZp1Mo/oS7/6uQYXqzpaZiCogodpKW26YTg9Bk1ZcUq6ur2OPoFB1u71/s2winf65iw6MIoHU7f3VtU4/GhwwcsngfDrMaLYfD0knCz/n4bPl8rSc+qlHfxYDFOZO42Q4yJqWzkTd/WpdOMQWO9L1Aro5wSvS3261vXeiTtF/SSEcD7M0IMkBuPv1phS2DfqgvISmrgNLvGSq64X7l1W961gKRMViPnCOfjh00GS92ZYMdUVBJ7e8JJvgJQ/7oU8X0k6TVOdcjzsiFtokc95n47FzSVoUVWn1ZtO/9Nrx9Mh9yG5E2DMDCkHQlC4mlufDHKqy3ZQlxGJzP0qTSWGgI0nGuGt/rTupnm2i+OAf8GR1nYplAjhAvJfReDzK8jy9ubpuRSxul4lNj8u241TWnYLdGl8lM3zC6bs920+R0JEJ8RDNDw4PR+PR+H9R3UahVUur5ydlAARiFmMveXWig2I/1fx9HWI3SIMoBCa9bNB1iQ5wSCQZTubHh7P5zLV3DhG2tWrzcbUNcAZyN1AD99oJngtpP8/ATiugYBeb7m1onqd5PkpHi8PFItrV5d/OS2u70rRAqqqANLMOAPFomPSshw8TFIoQumdHIhAHan4wOZjOR/PpdHZwfnVxfXm5Dj6KqDCq84l3KjSLxo7892IAyOcGJZ2K06l1IpRuwMpHU2f6ydHJ8fHiZDicjMLl1b9Xq9KCOfb5qCIGYYxG0f2QpKfez5UFCGHnJnvY3EELANAPZyd/+Pjx08c8y7Mv8fI/0Kg5OIKMUO+7X3chlZ2Dz9fhbubGLp79QKUrI++RjPJx/vHk08nR8SSvl9v6P79sBM57dcrpcDz5vBgK2yDFZltWbWPCXQY+35v6h9786bIIUZ/5dHF4Mj9dfDgeTYbJ3eXl1X99WVFTr0y8P5rNF5+Px64NdSzKoqybyEcjrldafe57gX3yqADOJ/nhH3/9dHgwO0yzNA+Xf/nz9dUagGieOD87+/jp4/FAYrNtttuyrNpg6AfTFMFzAO53eMB/IllUqM/y0fHnf/nX2cF0LLRYfPnLv9VlZch8plmSLT7++sviaKwMbbkuirJqItkPifGKh/ucfIhmN4Kdzabzz2dHh5m3IFGYH/1pXddNlQ78ME2T5OzD6dHIW7W6X95f3iw3Vd0SnTa2m5k8l6WdboR+Mr+7c5FkPpufHJ/84XQ+9qkXRgl+/rFp66YejPOx+tTPD+YHacK6uL++Or9ZFW0TH+lxL2DpAxXvzkXrmxKfpIPp8afPp6eLicKZBWmyBYZtFavJZDJJkGKQ57mR1frm4su3q/uNhbi/3QCo0J4F74ciR3/9AKqaZPl4fvrHP82P5lMGCTFImy4GJ6FmfTCdTbzkAhGp6qra3F58ubxdbsAetdA3Cj/Annb3WKCqzAbjw0nmo2j0TGIicG1sYzscJE7Q+kqadrsuVl++fLm4LbYuSmesg0v7MboGgJ2z6tLR7CjPvRCAB1QTCyFYyPNERRibZlvf3q/uv51/u1wVocuCfQvxgorxkEfozsJd9+uAJB/PEgczByVcpzBECUnXacSqXJe315fXF1cXV2VTW48b6LsIvsoPgaetDUWTwWS2CDCoiqqjEEqJbD3ExWChKdebL5ffLq9ub27NIp/ef3lZEcau8NkvjDRhaMq7iy+HqdNUEjghYCJsm1h7hauqeru6v1/eXp/f3hd1NMoDPeTLwxnPbo60swhSCBOrYbK8/joZDEcjJyqiCoshbqtqm/jEr1br5fp+uVze36yKbW3YX+t5GbifHMDE/rKP0Ci+UV3ffEvnM3oXkSTiIaFutpuiSNMsvb26vlov1/erYlU0obV9Te2tvSCb9NJtX/7YHx7BJN5fJqxanyapU4BgbOrVerVO80F69e3rt+X9+r6qy7pr/BQQ4EH7f8HDvkAfVWlnNGqL4ta168vLqVfvnfcu1lVTlutas8zf3F/ebop13bSRe91hd8o/Gjw/m6WQJzjbbamZbNCur4fToYcqnIOFJjb1NsAnWhSroqq2dRv6Wzs7iHxk7jnNu9PvbM/lsG9gnWiWplnuswRdKESMFmIwUaAJTdu2TTCLREeo9oW+A26+eBcDD23ojg1KEGlE1Dquvm9ytA9aIgAtslOAOoN8rHsSxPMM+OlRuU9v7ZpMfUS9Ol7TNUr7K2UP2spjzHpR3nMPx9ajy3I7VHq44iVPSpoiqjvttptS2O+1lmdNut3S+GQsKjsU3mHV/nc8kkSFD+T5nz/+2uWBVydBT2pFntwV/Pn8fH4+P5+fz8/n5/PO5/8BfvwgqFy+yvAAAAAASUVORK5CYII=' - i4 = b'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' - i5 = b'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' - i6 = b'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' - i7 = b'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' - i8 = b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAAAAADji6uXAAAACXBIWXMAAAsSAAALEgHS3X78AAASpElEQVRo3q1a13YjSY69QESkIyk62e5qtzO7c+b/v2Ufesd0ObmS6E26CGAfMslSVVFSsXepI/HQKJFAwFxcgPDSgwgghqoCgAIKImYAEBUABCYmSBAmQxpEAVD7PwroN5c0L8sjJmrFNdJBhOZHVQkEAFBpPm2/CCZmoub7Xz/sa/KaO20lqQBQIWKCkoKwk0IKVSh2GpI23z1KIEBECkAJjTbNC6XmI8JOHhE18kA7kY12SnqUSVuTNAKaF0S7PyAiQKFExAwiEHFjyMa+2tzDEQI/ew5aByBupKsCzETQxvLNmRGzofY2RQ5Ie12gtrbTxqDN4SkUSszc+hOTYQMCMRvmxtDynJfaV+QpfxYHgLi5cQWDWTS05mYmAZonVd07No52GhDkSVB8vpaQqEpzYtCgqqKk0tgS1HjWtz7zskCixk21DQtAwy7WoIFUsXNVhQogjeG1iVgcOkX6zjgEEwMiQp/TQOsf7VGp7r26+T5BRPRPxKEqWlfXXZJrtCICg7R5HwBkF0FE2P3qEQKVdGcfAiCk7Q03J0NEpIRdzKF9osaHcDgqXjTpPpuAQLoL5V0yICJSVSbTZFGFijYOw9aaIEHkiUG+y6RNFmlyC1QUir3bERvSoCqGTOs3AmldjK0l78MhFb8jDpkAUGiy8RMFmYSgTMwEgoq0WRcgtk4D9GiBxERqBEaVyCnFURS7yMUwxMREKgpiw9Sen4Qgy/lmBXj1Aj6US1+JQ8MgqIqCjXG9Tqfb6fS6xhm7U5d3oQhS9SHcvPu4DkGDKLdaH1EP2VoOAhWoRhEnvfFoPByOByaykWhQYtPAAQVABuK9/Lds7y3VSkRWcITTUFMcDHsEUYVylA3Ori4vTq/OkjRKfPDC1rI2vqjEhsR7ccUDV+LVGGbIEWeogKoIgV0ad5I07SbZaDAYjQZZZOjppXaRoypgpIMf/2O7WW0BPZBnXtFQxYuzsR2eDU+zTifrpGnW6UTMzERsiKlFMzuMRcb0zt8spo+oBYJDEl+Ow6CwNk7Pf33zS5b2UsOG48iapkYw7RMogURVwUzZ6DKPpVyQBFE9zqRQFcAmvYvf/vL3bjpIfVXXIFgwE7iFjU3WhKoqEXNvXIDKtfUi4VjUBgvH4/Oz859+OOvFVmsfROsyVExEcRZlRVlUVVlUkUtcHEepQkPUOeN8u1nkRbEh/bYg2hcQlFqb2LM3b346vxx3LKsPolqtt2tVkdFgEBfr5Xq2Wq3SLE3Ho9GJqASTwa02i/mCfAPlvlugAuTidPTmP/92cnKSQYNXFSpW01kItd/4lOrlw+Pk7v5uOBwMS041KMN2O/3Nej4zKPlAwYclfcGkSad3+ea3v0VpEtWhEhWRajv/VBRFqdE4FKvp3dv3H9+fnY3PJB0Z8sFHscViPpnWuaUnuf6JhvTES3Zx1RQZpP3RaDTsd9my1sV2W2y3xeNkMq195Xuds/FiNn1YrvN84yQ43c6jpBN7h8hY55yhZ/xi1x/sinODO0HElPZPry4GHcsGFPLVYjJ9nK2X60XwPpwMp4vFYrFYbnO/JV+F/PF2PD4dp2QANtYwHcrdsNhh8r08auA8sUkG5z9dDnvWMlCtF7Pbm4/XeV5tVYKOxtPFYj6dLTfbeuOL9XbW6/36CzpsHYitNQzoQZjY4HLSPXJoNWRrs/7Z1dmgFzMEoVg9fvj3P/4VKq0ZwOnlbLGcz2bLbV6HwtA0it1a0lN2EYits3zYO2yj2T430Q5Q2NQl4/HF1TAjrxo0r8mxaB00QADU29VmutluysBxYCiZKM06WRpZFgQfxPMhBWH3nqTaonpVAiPJks7o7OKym1qpfRW2gdOIQ7k7mbpYzRbLTV6rcawi5NJuJ43jyLJKkBBElPCtm9pdrLRIvgElxGSi7GR4enFFrGXli6oKgSSoSItD62K73KzX20psUvsQYKI0SbtdNqSiIi1IPRAW+jVKa9rqtNsfjcen5xJqX5XrsvYUJzZUu16qyleT5WqTByEjASAbd7M0iYxlkhCqKgi/lrxpryoRkY2T2FkWkHEQO11Nlu8eC97B6nr1QLPpsvKQEASUDS9+uBxl1pD4Yj1/WOQ1geRbIPwEGzf9R/vaRmmWOAI3XYQJy9ubm3lhVBVkmP0K2+16UwaVIEKmM7z86WrUdRD4fPlwu8q9ke9sZlQBMi7NUscgJoghq4vr3xeLwogImJ3xy1Xk61BLEAERx/3zNxeD1GlAqFeT21KDoXAweX95F9RyCMbFSRJZECk5y17Wd/8qq5KhpGSsrVe5EFuoBGVDlA1/+Pm0l1kPqbfLyT1ZpYO9BX2Z1Bof1ACRgACFIPBqtVn8cbfwtdcQWIFQSZCmuzYR2U6Wdv7r1/N+zCjWy3z5bl44FcgzuJS+6RtVVYKIioiqeF18erz/425ZBlFihQZQECEGQaNOko2Gw9HVj1eDyKBe3d8//PHo41rCodbia6dRApFCmi4dINIgfnn//u3d3br2lXhSIpK6ZiKGKmynN7i8uPrhdDjua6jLh+v31/ezkl39Qm9BexV3yUggEkIQBcQXi7s/fl/MlgWUOAgLAVC2rFB12ej8t59//TnLsqQqynp5/69/rDdlXEDlYAHWJ6GAJ7Uq1GVeVHXtA0XZyejUgOpQB048+zRNk8g6oyI6PB2Nrk57iQmFX63Xqw9301mdF1V4hjex+nVDqE1ASl1s86KqycB0+uMVh3ojdfBCzIPReBRFsdEgOhwM+sP+iSOp6uVsOvt4+zAJZe19kOcK8D7jEe07UNVQF9ttUdZk2CTd4VZ9tQm1rzWQH1y++TFJUqc+SLc77GVxGokPfv7p7v76brL04tXrYexi9YtAbDBma9KiKKsqYmu7/byu883SVzVrUO5f/eWvadqJtfbSyU5SgFFIVSweb67vbj9NleUF6Pk5o6uqQAWsBKmLrZ0/nA463cyZzhCI02HwIUgF//PPb07jKHEIQeKU4H0I8/l8dfPp8W66yTkoKdGXzvF1aqOme9GWYQVCtcF8+nAygEOUiXHdk7kGlVBrdXV5ecHWGYgqO9a6LMvb2/tPk8VitlnX+wPaNc0HBLalUtAmHoUvgp/2T5LaZnDdqNMZnW1ZGHUl5ag/GDJxi4CC1sV6c//27dtNsdkUvmx4TDKk8hwQ3mMBadleIFQhLKa9OD6p4Wyqg7qqDAxV3ledLEsFqmCiOtTB56v5x3///nsd6rBH20SH6+EOOSn2WKqhA73qeprAsIutdZbYWAdDxnsb24bDIyVoqOvV5NPjZFUpEUh2ZCpwKLPB7JhsfdL4NmwMwbJ661wUYBwUao1hZnLOWWoVpKoqy4f76/c301UO9YFbAqrhiw6eIe3R0466btxLJJ/XaxdFWV8iIjZqYUmtJWohYIOSQrWZ3rxbLLcSxJLsaGhVPGdS+kxn6edcLqrberNI0mwgrqtgwMIyIKT43IeFutwuH2/e5XXpRCQ0GKE5nWcY4VbBnecQ7zIOg0hia2tr4xNRMmSYlESpoS2FSFm8gSeX9TsRGxLf2KetvQfPsHGoluPcJzhWAoGhMYXcJr0hWgK9PWWShmRUVbYcdQZpwgwp8h3/zgeHCHuBLWffMPPM3BJeKkHqquicDMZExhjDJE1rbZhaPt8449KTs8QFH3yZS/O2aU7wOVKBnnIzewpRoYLc55OT858qZhApiIN6wwyPwAJWGI67qujGdVWsWVqiH6SHs7fFbhKy+1FhJUBa6N/rj/p/uexZQEMIotui2lpiEyUu0+CDNUQMcNwdbwPquvI+tAQDDvmp3VHmuku1CmkPh8gYHlz9cPXLec+SBpG6lsV8NbOG7WDQzySEylhrLJHGnXFdVZs8z7ehyR+0J3S/Mal+bp+evIKCrT25/O2vp6ddkAb4sqxnd5M7Z429lBhS1WUkYDFESc+jqvJywVXRcm/0PBDWLznSfXFkZ4c//Pb3bqdjVUWqcls+3t5+NNZaiYdAKLfBgQSMuMu2Ltcr8StShRpiPo42YUHUTXvDk343i53ZbNfrfLVZPUzup8ZGJkms2aw3myS18clJNkBUd3qjjVhZzhqneAYmvkSbuLQ/GA/73dhZzicPk8VsMV+v5itjIhNFitV6s7ZpnJ5fsBgb00npudrEDc0v7fTvKCYq65/1e92OM85U85sPj4/Tx7wuK2diG7FisVjOu0mUlZwFGMe9gChfptSktUDHMsJq0/74dNTvMRkqZ9f/c3v/cE9QWBs5Uqnni8UsTpIOehcwxOqNyx67kSoBqiQ4ivNWQtwdXgw6EYcgfjZ5fFgWnpSJmAJtZrZerbfrpIg3o9liA1Jml6ET2SbuoThOIKBRd3gx7iVcV1U+mzzerdeFEqsBgq45rIuyrArj7Pl8lbMltpFSbI0SmJ8ZH75M0Lru6dXpSWyk2qzm88dPdelZiVg1yNqvYpFaWQ1dzpYbF1uYiGzmTDNkOBT1r/ClFHVH54NeQqFYzx8fP30iETDDBPWoCoFhNQjAZLHaJEQwbDWJDEDMKjjepNaY1FoBuaTbiRKnYGHhoMLKME2fZ1gdE7Mx1vtQV7UyoCI40I2+OrcwUWyZBDb2aexsM+BWge5GZ6pgNs6QEBvWuioqH7QZ2yod7J5eEsguSmIDYQfK0sgJFKpBQQzDDAkSImOcsYZBxnmEqhZlQJrR+zETUlKAjYssI5AlTuLINryQKgHEzIAolIwzTGrYGPXFJq+F2rHeAR7qFZIdxEyKQAyKnLUQaQeE0KBKSlY6nU7v6nTQjS2FYjl9nK4LbTpWouOna838IxAZ45yz6rVBZVCICoHYpP3h6GzU7zhLUqwebx5WJfASy/zqwFIFhtlaF0VaaTDEhJa4Y7bcGZ6fX4z7PRCFYvFw/bAsP5fX47x0vzQghox1zlnPUG0JQAGI2Nisf/bD5fgkE5G6WD7cTpalfEHCfL/TELbTm392O90eGMEmJxcLxwIIByW1jm2WdTqXby7fnPViybfF5sPH25vZNic1e35Jj3EaLRf3H8aniVGI2mxwZq34hn8B2yRKB/1+/+rq4nLQT6hYzmYfrm9u840HN+stenTg54/v+BczcKoBlAzPDcqca/EKoiiJO8Ozi7Pzi7PzNLY+n97ev7+5e9iGCsTGSFA90mkU5fKTzUY1q6jazuAMPi82Xj0YbJPO4PzHNz+ejs9GBqBi+fD+/fuPt9zwrQYqx3upLzeLdVGqiCIdVNLp9sbFeru2xtj+oNc/G5+d9hIjRVVXHz/e3M3z0HRPBFU9th6SItTVtqjqICDEfST90fl8vlzPk8jGw8Gw3+/1T6LYhHy9Xd/c3N1OlrkSKVFLFuiR6y3ky220LcugBEo4HQyXq9VytphmSZKOTk77SZzGrOQ38/nk5ububrX2bSg16e3oTCN1sc1LH5SBJCHk23w7mcwfulnaPTu5GDBYpKx9vny4vbm+vSvLumnVGmrwoE3NCxZlYg6p89W61IgYrlYSirjbH456vW5mWZXy5Xpyc/3xw83scVNKkGY5gxoqko4RCIAJYjTfFohPCGQCWxPFcW8wOOl10tiqqq4X04frj+/fTWaLbR2Ctp2h4uCuySvVIpTBfArzyV+pcx6xMbH3cFlP2DDHbKEgLVcPn64/vHu/LYsqKDGaTk2ZmDQctzGkIoEmq9us6l5xYIJllzC307EAFUjIN7P7mw9v30NE9otpKrpvco/bNgnk2dX55F03dpbTKE48M0GVqqIut0WR3z3cP9zN8qa5308fAVWh43qLXTmUUK8ebzrGWTPs9+MGrCiX6+1qOpvOlsv5fLoolBtyp+VeGuhzdC5tYwOrh5isc7bQGFABQXW7ms9v765v10Web7bFbvvsc4U43OK/JlDJA7SecOWsdeL6AmkuVm9m92//+Odb8SEE8fLkHEifyTLfo6EqxJcrI2wR16vpe24L82wyn9182vog4cly134v4+DA+btMqgIUawTiYBaT6yFUQcy8Wq3Xs8XKizxZfdotQu5d58+coSoKLTeBAqVZmqkK2FiTF0WRl1VoBH6Wt5spP6Pgy1tf+7syxnmpPRPZIAK2ztTihZiNyOe8Se1mBhQQ6J8zaUvbQhq2UvYxRlAShT6lfel1BV7bLyUGMbNp+bx2IYlURUT3O3SKL9YHVf+0wN3q4W7tGC0Jr7uDawvtFwIB4FmnMa/JIzCDoETm8xrXTquvgo32i736LPh+VeB+v3v3jjHErXd81T3sV5H/NNT/Inu0NQ7cIBb62nBfvqH4k5lmN/bWxlfbmbBAvtgkB30L7vX/ouHTaRjTjmR+4i1PFdQXr8Q4+rGHKnS4QcD/t8AXbKCviftzAvXgKe1W5un/XyA9ewvf8fhfsQwRbCVWoA8AAAAASUVORK5CYII=' - i9 = b'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' - blank = b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwBAMAAAA0zul4AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJUExURQAAAAsLCwEBASarxPMAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAnSURBVFjD7c0hAQAACAOwV6AB/VOiSIDAbAUWAAC4qn5IAQAAYCUD5JkAMsfpUwIAAAAASUVORK5CYII=' - colon = b'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' - dot = b'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' - main() \ No newline at end of file diff --git a/DemoPrograms/Demo_Desktop_Widget_Timer.py b/DemoPrograms/Demo_Desktop_Widget_Timer.py index 9f82daa58..6cc5550d4 100644 --- a/DemoPrograms/Demo_Desktop_Widget_Timer.py +++ b/DemoPrograms/Demo_Desktop_Widget_Timer.py @@ -13,11 +13,7 @@ this design were not used, then the time value displayed would slowly drift by the amount of time it takes to execute the PySimpleGUI read and update calls (not good!) - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ diff --git a/DemoPrograms/Demo_Desktop_Widget_Weather.py b/DemoPrograms/Demo_Desktop_Widget_Weather.py index 3d3520449..add15f264 100644 --- a/DemoPrograms/Demo_Desktop_Widget_Weather.py +++ b/DemoPrograms/Demo_Desktop_Widget_Weather.py @@ -24,11 +24,7 @@ This widget is an early version of a PSG Widget so it may not share the same names / constructs as the templates. - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI - www.PySimpleGUI.com """ @@ -79,11 +75,8 @@ def change_settings(settings, window_location=(None, None)): nearest_postal = '' layout = [[sg.T('Enter Zipcode or City for your location')], - [sg.I(settings.get('-location-', nearest_postal), size=(15, 1), key='-LOCATION-'), sg.T('City')], - [sg.I(settings.get('-country-', 'US'), size=(15, 1), key='-COUNTRY-'), sg.T('Country')], - [sg.I(settings.get('-friends name-', ''), size=(15, 1), key='-FRIENDS NAME-'), sg.T('Who')], + [sg.I(settings.get('-location-', nearest_postal), size=(15, 1), key='-LOCATION-')], [sg.I(settings.get('-api key-', ''), size=(32, 1), key='-API KEY-')], - [sg.CBox('Use Metric For Temperatures', default=settings.get('-celsius-', False),key='-CELSIUS-')], [sg.B('Ok', border_width=0, bind_return_key=True), sg.B('Register For a Key', border_width=0, k='-REGISTER-'), sg.B('Cancel', border_width=0)], ] window = sg.Window('Settings', layout, location=window_location, no_titlebar=True, keep_on_top=True, border_depth=0) @@ -98,10 +91,7 @@ def change_settings(settings, window_location=(None, None)): if event == 'Ok': user_location = settings['-location-'] = values['-LOCATION-'] - settings['-country-'] = values['-COUNTRY-'] API_KEY = settings['-api key-'] = values['-API KEY-'] - settings['-celsius-'] = values['-CELSIUS-'] - settings['-friends name-'] = values['-FRIENDS NAME-'] else: API_KEY = settings['-api key-'] user_location = settings['-location-'] @@ -113,11 +103,6 @@ def change_settings(settings, window_location=(None, None)): else: APP_DATA['City'] = user_location APP_DATA['Postal'] = '' - APP_DATA['Country'] = settings['-country-'] - if settings['-celsius-']: - APP_DATA['Units'] = 'metric' - else: - APP_DATA['Units'] = 'imperial' return settings @@ -134,14 +119,13 @@ def create_endpoint(endpoint_type=0): {0: default, 1: zipcode, 2: city_name}""" if endpoint_type == 1: try: - endpoint = f"http://api.openweathermap.org/data/2.5/weather?zip={APP_DATA['Postal']},{APP_DATA['Country']}&appid={API_KEY}&units={APP_DATA['Units']}" + endpoint = f"http://api.openweathermap.org/data/2.5/weather?zip={APP_DATA['Postal']},us&appid={API_KEY}&units={APP_DATA['Units']}" return endpoint except ConnectionError: return elif endpoint_type == 2: try: - # endpoint = f"http://api.openweathermap.org/data/2.5/weather?q={APP_DATA['City'].replace(' ', '%20')},us&APPID={API_KEY}&units={APP_DATA['Units']}" - endpoint = f"http://api.openweathermap.org/data/2.5/weather?q={APP_DATA['City'].replace(' ', '%20')},{APP_DATA['Country']}&APPID={API_KEY}&units={APP_DATA['Units']}" + endpoint = f"http://api.openweathermap.org/data/2.5/weather?q={APP_DATA['City'].replace(' ', '%20')},us&APPID={API_KEY}&units={APP_DATA['Units']}" return endpoint except ConnectionError: return @@ -164,19 +148,16 @@ def request_weather_data(endpoint): 'Is your API Key set correctly?', API_KEY, keep_on_top=True, location=win_location) return - if APP_DATA['Units'] == 'metric': - temp_units, speed_units = '°C', 'm/sec' - else: - temp_units, speed_units = '°F', 'miles/hr' + if response.reason == 'OK': weather = json.loads(response.read()) APP_DATA['City'] = weather['name'].title() APP_DATA['Description'] = weather['weather'][0]['description'] - APP_DATA['Temp'] = "{:,.0f}{}".format(weather['main']['temp'], temp_units) + APP_DATA['Temp'] = "{:,.0f}°F".format(weather['main']['temp']) APP_DATA['Humidity'] = "{:,d}%".format(weather['main']['humidity']) APP_DATA['Pressure'] = "{:,d} hPa".format(weather['main']['pressure']) - APP_DATA['Feels Like'] = "{:,.0f}{}".format(weather['main']['feels_like'], temp_units) - APP_DATA['Wind'] = "{:,.1f}{}".format(weather['wind']['speed'], speed_units) + APP_DATA['Feels Like'] = "{:,.0f}°F".format(weather['main']['feels_like']) + APP_DATA['Wind'] = "{:,.1f} m/h".format(weather['wind']['speed']) APP_DATA['Precip 1hr'] = None if not weather.get('rain') else "{:2} mm".format(weather['rain']['1h']) APP_DATA['Updated'] = 'Updated: ' + datetime.datetime.now().strftime("%B %d %I:%M:%S %p") APP_DATA['Lon'] = weather['coord']['lon'] @@ -192,46 +173,46 @@ def metric_row(metric): sg.Text(APP_DATA[metric], font=('Arial', 10, 'bold'), pad=(0, 0), size=(9, 1), key=metric)] -def create_window(win_location, settings): +def create_window(win_location): """ Create the application window """ - friends_name = settings.get('-friends name-', '') col1 = sg.Column( - [[sg.Text(APP_DATA['City'], font=('Arial Rounded MT Bold', 18), background_color=BG_COLOR, text_color=TXT_COLOR, key='City'), - sg.Text(f' - {friends_name}' if friends_name else '', background_color=BG_COLOR, text_color=TXT_COLOR, font=('Arial Rounded MT Bold', 18),)], + [[sg.Text(APP_DATA['City'], font=('Arial Rounded MT Bold', 18), pad=((10, 0), (50, 0)), size=(18, 1), background_color=BG_COLOR, text_color=TXT_COLOR, key='City')], [sg.Text(APP_DATA['Description'], font=('Arial', 12), pad=(10, 0), background_color=BG_COLOR, text_color=TXT_COLOR, key='Description')]], background_color=BG_COLOR, key='COL1') - col2 = sg.Column([[sg.Image(data=APP_DATA['Icon'], size=(100, 100), background_color=BG_COLOR, key='Icon')]], - element_justification='center', background_color=BG_COLOR, key='COL2') + col2 = sg.Column( + [[sg.Text('×', font=('Arial Black', 16), pad=(0, 0), justification='right', background_color=BG_COLOR, text_color=TXT_COLOR, enable_events=True, key='-QUIT-')], + [sg.Image(data=APP_DATA['Icon'], pad=((5, 10), (0, 0)), size=(100, 100), background_color=BG_COLOR, key='Icon')]], + element_justification='center', background_color=BG_COLOR, key='COL2') - col3 = sg.Column([[sg.Text(APP_DATA['Updated'], font=('Arial', 8), background_color=BG_COLOR, text_color=TXT_COLOR, key='Updated')]], - pad=(10, 5), element_justification='left', background_color=BG_COLOR, key='COL3') + col3 = sg.Column( + [[sg.Text(APP_DATA['Updated'], font=('Arial', 8), background_color=BG_COLOR, text_color=TXT_COLOR, key='Updated')]], + pad=(10, 5), element_justification='left', background_color=BG_COLOR, key='COL3') col4 = sg.Column( [[sg.Text('Settings', font=('Arial', 8, 'italic'), background_color=BG_COLOR, text_color=TXT_COLOR, enable_events=True, key='-CHANGE-'), sg.Text('Refresh', font=('Arial', 8, 'italic'), background_color=BG_COLOR, text_color=TXT_COLOR, enable_events=True, key='-REFRESH-')]], pad=(10, 5), element_justification='right', background_color=BG_COLOR, key='COL4') - top_col = sg.Column([[col1, sg.Push(background_color=BG_COLOR), col2, sg.Text('×', font=('Arial Black', 16), pad=(0, 0), justification='right', background_color=BG_COLOR, text_color=TXT_COLOR, enable_events=True, key='-QUIT-')]], pad=(0, 0), background_color=BG_COLOR, key='TopCOL') + top_col = sg.Column([[col1, col2]], pad=(0, 0), background_color=BG_COLOR, key='TopCOL') - bot_col = sg.Column([[col3, col4]], - pad=(0, 0), background_color=BG_COLOR, key='BotCOL') + bot_col = sg.Column([[col3, col4]], pad=(0, 0), background_color=BG_COLOR, key='BotCOL') lf_col = sg.Column( [[sg.Text(APP_DATA['Temp'], font=('Haettenschweiler', 90), pad=((10, 0), (0, 0)), justification='center', key='Temp')]], pad=(10, 0), element_justification='center', key='LfCOL') - rt_col = sg.Column([metric_row('Feels Like'), metric_row('Wind'), metric_row('Humidity'), metric_row('Precip 1hr'), metric_row('Pressure')], - pad=((15, 0), (25, 5)), key='RtCOL') + rt_col = sg.Column( + [metric_row('Feels Like'), metric_row('Wind'), metric_row('Humidity'), metric_row('Precip 1hr'), metric_row('Pressure')], + pad=((15, 0), (25, 5)), key='RtCOL') layout = [[top_col], [lf_col, rt_col], - [bot_col], - [sg.Text(f'PSG: {sg.ver} Tk:{sg.framework_version} Py:{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}', font=('Arial', 8), justification='c', background_color=BG_COLOR, text_color=TXT_COLOR, pad=(0,0), expand_x=True)]] + [bot_col]] window = sg.Window(layout=layout, title='Weather Widget', margins=(0, 0), finalize=True, location=win_location, element_justification='center', keep_on_top=True, no_titlebar=True, grab_anywhere=True, alpha_channel=ALPHA, - right_click_menu=[[''], ['Edit Me', 'Versions', 'Exit',]], enable_close_attempted_event=True) + right_click_menu=[[''], 'Exit']) for col in ['COL1', 'COL2', 'TopCOL', 'BotCOL', '-QUIT-']: window[col].expand(expand_y=True, expand_x=True) @@ -264,12 +245,6 @@ def main(refresh_rate, win_location): # Load settings from config file. If none found will create one settings = load_settings() location = settings['-location-'] - APP_DATA['Country'] = settings.get('-country-', 'US') - if settings.get('-celsius-'): - APP_DATA['Units'] = 'metric' - else: - APP_DATA['Units'] = 'imperial' - if location is not None: if location.isnumeric() and len(location) == 5 and location is not None: APP_DATA['Postal'] = location @@ -282,36 +257,23 @@ def main(refresh_rate, win_location): sg.popup_error('Having trouble with location. Your location: ', location) exit() - window = create_window(win_location, settings) - + window = create_window(win_location) while True: # Event Loop event, values = window.read(timeout=refresh_in_milliseconds) - if event in (None, '-QUIT-', 'Exit', sg.WIN_CLOSE_ATTEMPTED_EVENT): - sg.user_settings_set_entry('-win location-', window.current_location()) # The line of code to save the position before exiting + if event in (None, '-QUIT-', 'Exit'): break - try: - if event == '-CHANGE-': - x, y = window.current_location() - settings = change_settings(settings, (x + 200, y+50)) - window.close() - window = create_window(win_location, settings) - elif event == '-REFRESH-': - sg.popup_quick_message('Refreshing...', keep_on_top=True, background_color='red', text_color='white', - auto_close_duration=3, non_blocking=False, location=(window.current_location()[0]+window.size[0]//2-30, window.current_location()[1]+window.size[1]//2-10)) - elif event == 'Edit Me': - sg.execute_editor(__file__) - elif event == 'Versions': - sg.main_get_debug_data() - elif event != sg.TIMEOUT_KEY: - sg.Print('Unknown event received\nEvent & values:\n', event, values, location=win_location) - - update_weather() - update_metrics(window) - except Exception as e: - sg.Print('*** GOT Exception in event loop ***', c='white on red', location=window.current_location(), keep_on_top=True) - sg.Print('File = ', __file__, f'Window title: {window.Title}') - sg.Print('Exception = ', e, wait=True) # IMPORTANT to add a wait/blocking so that the print pauses execution. Otherwise program continue and exits + if event == '-CHANGE-': + x, y = window.current_location() + settings = change_settings(settings, (x + 200, y+50)) + elif event == '-REFRESH-': + sg.popup_quick_message('Refreshing...', keep_on_top=True, background_color='red', text_color='white', + auto_close_duration=3, non_blocking=False, location=(win_location[0]+170, win_location[1]+150)) + elif event != sg.TIMEOUT_KEY: + sg.Print('Unknown event received\nEvent & values:\n', event, values, location=win_location) + + update_weather() + update_metrics(window) window.close() @@ -320,6 +282,5 @@ def main(refresh_rate, win_location): win_location = sys.argv[1].split(',') win_location = (int(win_location[0]), int(win_location[1])) else: - win_location = sg.user_settings_get_entry('-win location-', (None, None)) - - main(refresh_rate=1, win_location=win_location) \ No newline at end of file + win_location = (None, None) + main(refresh_rate=1, win_location=win_location) diff --git a/DemoPrograms/Demo_Desktop_Widget_psutil_Dashboard.py b/DemoPrograms/Demo_Desktop_Widget_psutil_Dashboard.py index 863aed3c6..41c740c6a 100644 --- a/DemoPrograms/Demo_Desktop_Widget_psutil_Dashboard.py +++ b/DemoPrograms/Demo_Desktop_Widget_psutil_Dashboard.py @@ -1,6 +1,7 @@ #!/usr/bin/env python import PySimpleGUI as sg import psutil +import sys """ Desktop floating widget - System status dashboard @@ -10,11 +11,6 @@ CPU Used Mem Used Information is updated once a second and is shown as an area graph that scrolls - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ GRAPH_WIDTH, GRAPH_HEIGHT = 120, 40 # each individual graph size in pixels @@ -57,11 +53,10 @@ def human_size(bytes, units=(' bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB')): return str(bytes) + units[0] if bytes < 1024 else human_size(bytes >> 10, units[1:]) -def main(): +def main(location): # ---------------- Create Window ---------------- sg.theme('Black') sg.set_options(element_padding=(0, 0), margins=(1, 1), border_width=0) - location = sg.user_settings_get_entry('-location-', (None, None)) def GraphColumn(name, key): layout = [ @@ -73,8 +68,10 @@ def GraphColumn(name, key): key=key+'GRAPH_')]] return sg.Col(layout, pad=(2, 2)) + red_x = b"R0lGODlhEAAQAPeQAIsAAI0AAI4AAI8AAJIAAJUAAJQCApkAAJoAAJ4AAJkJCaAAAKYAAKcAAKcCAKcDA6cGAKgAAKsAAKsCAKwAAK0AAK8AAK4CAK8DAqUJAKULAKwLALAAALEAALIAALMAALMDALQAALUAALYAALcEALoAALsAALsCALwAAL8AALkJAL4NAL8NAKoTAKwbAbEQALMVAL0QAL0RAKsREaodHbkQELMsALg2ALk3ALs+ALE2FbgpKbA1Nbc1Nb44N8AAAMIWAMsvAMUgDMcxAKVABb9NBbVJErFYEq1iMrtoMr5kP8BKAMFLAMxKANBBANFCANJFANFEB9JKAMFcANFZANZcANpfAMJUEMZVEc5hAM5pAMluBdRsANR8AM9YOrdERMpIQs1UVMR5WNt8X8VgYMdlZcxtYtx4YNF/btp9eraNf9qXXNCCZsyLeNSLd8SSecySf82kd9qqc9uBgdyBgd+EhN6JgtSIiNuJieGHhOGLg+GKhOKamty1ste4sNO+ueenp+inp+HHrebGrefKuOPTzejWzera1O7b1vLb2/bl4vTu7fbw7ffx7vnz8f///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAJAALAAAAAAQABAAAAjUACEJHEiwYEEABniQKfNFgQCDkATQwAMokEU+PQgUFDAjjR09e/LUmUNnh8aBCcCgUeRmzBkzie6EeQBAoAAMXuA8ciRGCaJHfXzUMCAQgYooWN48anTokR8dQk4sELggBhQrU9Q8evSHiJQgLCIIfMDCSZUjhbYuQkLFCRAMAiOQGGLE0CNBcZYmaRIDLqQFGF60eTRoSxc5jwjhACFWIAgMLtgUocJFy5orL0IQRHAiQgsbRZYswbEhBIiCCH6EiJAhAwQMKU5DjHCi9gnZEHMTDAgAOw==" layout = [ - [sg.Text('System Status Dashboard'+' '*18)], + [sg.Text('System Status Dashboard'+' '*18), + sg.Button('', image_data=red_x, button_color=('black', 'black'), key='Exit', tooltip='Closes window')], [GraphColumn('Net Out', '_NET_OUT_'), GraphColumn('Net In', '_NET_IN_')], [GraphColumn('Disk Read', '_DISK_READ_'), @@ -85,8 +82,8 @@ def GraphColumn(name, key): window = sg.Window('PSG System Dashboard', layout, keep_on_top=True, grab_anywhere=True, no_titlebar=True, - return_keyboard_events=True, alpha_channel=ALPHA, enable_close_attempted_event=True, - use_default_focus=False, finalize=True, location=location,right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT,) + return_keyboard_events=True, alpha_channel=ALPHA, + use_default_focus=False, finalize=True, location=location) # setup graphs & initial values netio = psutil.net_io_counters() @@ -107,14 +104,9 @@ def GraphColumn(name, key): while True : # --------- Read and update window once a second-------- event, values = window.read(timeout=1000) - if event in (sg.WIN_CLOSE_ATTEMPTED_EVENT, 'Exit'): - sg.user_settings_set_entry('-location-', window.current_location()) # save window location before exiting + # Be nice and give an exit, expecially since there is no titlebar + if event in (sg.WIN_CLOSED, 'Exit'): break - elif event == 'Edit Me': - sp = sg.execute_editor(__file__) - elif event == 'Version': - sg.popup_scrolled(__file__, sg.get_versions(), keep_on_top=True, location=window.current_location()) - # ----- Network Graphs ----- netio = psutil.net_io_counters() write_bytes = net_graph_out.graph_value(netio.bytes_sent) @@ -137,5 +129,10 @@ def GraphColumn(name, key): window['_MEM_TXT_'].update('{}% Memory Used'.format(mem_used)) if __name__ == '__main__': - main() + if len(sys.argv) > 1: + location = sys.argv[1].split(',') + location = (int(location[0]), int(location[1])) + else: + location = (None, None) + main(location) diff --git a/DemoPrograms/Demo_Disable_Elements.py b/DemoPrograms/Demo_Disable_Elements.py index d1851796c..9003fd9ec 100644 --- a/DemoPrograms/Demo_Disable_Elements.py +++ b/DemoPrograms/Demo_Disable_Elements.py @@ -3,12 +3,6 @@ ''' Usage of Disable elements - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. ''' sg.theme('Dark') diff --git a/DemoPrograms/Demo_Dispatchers.py b/DemoPrograms/Demo_Dispatchers.py index 3fbfd7f72..7b9e3987f 100644 --- a/DemoPrograms/Demo_Dispatchers.py +++ b/DemoPrograms/Demo_Dispatchers.py @@ -12,7 +12,6 @@ * If-Else * Dictionaries * Functions as keys - * Lambda as key (callable like functions are) The handlers in this demo are all functions that are called once the event is detected @@ -23,11 +22,7 @@ event loop rather than functions, then do it in the event loop. http://www.PySimpleGUI.org - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ import PySimpleGUI as sg @@ -81,7 +76,7 @@ def main(): [sg.Text('Status:'), sg.Text(size=(3, 1), key='-STATUS-')], [sg.Text(size=(50, 1), key='-OUT-')], [sg.Button('Simple'), sg.Button('Go'), sg.Button('Stop'), sg.Button('Other', key=do_other), - sg.Button('Tuple', key=(1,2)), sg.Button('Lambda', key= lambda window: do_other(window)), sg.Button('Bad')]] + sg.Button('Tuple', key=(1,2)), sg.Button('Bad')]] window = sg.Window('Dispatchers', layout, font='Default 16', keep_on_top=True) diff --git a/DemoPrograms/Demo_DuplicateFileFinder.py b/DemoPrograms/Demo_DuplicateFileFinder.py index 45ada4c01..9ec425771 100644 --- a/DemoPrograms/Demo_DuplicateFileFinder.py +++ b/DemoPrograms/Demo_DuplicateFileFinder.py @@ -5,12 +5,6 @@ ''' Find dups with PySimpleGUI - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. ''' # ====____====____==== FUNCTION DeDuplicate_folder(path) ====____====____==== # diff --git a/DemoPrograms/Demo_EXE_Maker.py b/DemoPrograms/Demo_EXE_Maker.py index e01041d6c..9e02bc74f 100644 --- a/DemoPrograms/Demo_EXE_Maker.py +++ b/DemoPrograms/Demo_EXE_Maker.py @@ -5,12 +5,6 @@ import sys ''' Make a "Windows os" executable with PyInstaller - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. ''' def main(): diff --git a/DemoPrograms/Demo_Edit_Me_Option.py b/DemoPrograms/Demo_Edit_Me_Option.py index 84f52e521..c05130f1f 100644 --- a/DemoPrograms/Demo_Edit_Me_Option.py +++ b/DemoPrograms/Demo_Edit_Me_Option.py @@ -1,7 +1,7 @@ import PySimpleGUI as sg """ - Demo "Edit Me" (and Version) + Demo "Edit Me" More and more of these Demos are getting an "Edit me" option added. @@ -12,30 +12,26 @@ You can add this capability to your program by adding a right click menu to your window and calling the editor that you set up in the global PySimpleGUI options. - A constant MENU_RIGHT_CLICK_EDITME_VER_EXIT, when set at the right click menu shows a "Version" and "Edit Me" meny item. - + You need to do 2 things to make this work: + 1. Add a right click menu - requires you to add 1 parameter to your Window creation + 2. Add 1 if statement to your event loop. + You will need to have first set up your editor by using the menu in sg.main() - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI.org """ layout = [[sg.Text('Edit this program by right clicking and choosing "Edit me"')], [sg.Button('Exit')]] -window = sg.Window('Edit Me Right Click Menu Demo', layout, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT) +window = sg.Window('Edit Me Right Click Menu Demo', layout, right_click_menu=[[''], ['Edit Me', 'Exit',]]) while True: # Event Loop event, values = window.read() if event == sg.WIN_CLOSED or event == 'Exit': break if event == 'Edit Me': - sg.execute_editor(__file__) - elif event == 'Version': - sg.popup_scrolled(__file__, sg.get_versions(), location=window.current_location(), keep_on_top=True, non_blocking=True) + sg.execute_editor(__file__) window.close() diff --git a/DemoPrograms/Demo_Email_Send.py b/DemoPrograms/Demo_Email_Send.py index 5d9609901..9d443f3ae 100644 --- a/DemoPrograms/Demo_Email_Send.py +++ b/DemoPrograms/Demo_Email_Send.py @@ -1,40 +1,38 @@ import PySimpleGUI as sg +# import PySimpleGUIWeb as sg +# import PySimpleGUIWx as sg +# import PySimpleGUIQt as sg ''' - Learn how to send emails from PySimpleGUI using the smtplib and email modules - - The GUI portion is simple - + Copyright 2019 PySimpleGUI.org Based on a send-email script originally written by by Israel Dryer - (Thank you Israel for figuring out the hard part of the stmp and email module calls!) - - Copyright 2019-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. - ''' -# If you are using a mail service that's not gmail, hotmail, live or yahoo: -# then you can enter the smtp server address here so you don't have to keep typing it into the GUI -smtp_host_default = '' - # used for sending the email import smtplib as smtp # used to build the email from email.message import EmailMessage # create and send email -def send_an_email(from_address, to_address, subject, message_text, user, password, smtp_host, smtp_port): +def send_an_email(from_address, to_address, subject, message_text, user, password): + # SMTP Servers for popular free services... add your own if needed. Format is: address, port + google_smtp_server = 'smtp.gmail.com', 587 + microsoft_smtp_server = 'smtp.office365.com', 587 + yahoo_smtp_server = 'smtp.mail.yahoo.com', 587 # or port 465 + + # open the email server connection + if 'gmail' in user: + smtp_host, smtp_port = google_smtp_server + elif 'hotmail' in user or 'live' in user: + smtp_host, smtp_port = microsoft_smtp_server + elif 'yahoo' in user: + smtp_host, smtp_port = yahoo_smtp_server + else: + sg.popup('Username does not contain a supported email provider') + return server = smtp.SMTP(host=smtp_host, port=smtp_port) server.starttls() - try: - server.login(user=user, password=password) - except Exception as e: - sg.popup_error('Error authenticaing your email credentials', e, image=sg.EMOJI_BASE64_WEARY) - server.close() - return + server.login(user=user, password=password) # create the email message headers and set the payload msg = EmailMessage() @@ -44,15 +42,9 @@ def send_an_email(from_address, to_address, subject, message_text, user, passwor msg.set_payload(message_text) # open the email server and send the message - try: - server.send_message(msg) - except Exception as e: - sg.popup_error('Error sending your email', e, image=sg.EMOJI_BASE64_WEARY) - server.close() - return + server.send_message(msg) server.close() - sg.popup('Email sent successfully!', image=sg.EMOJI_BASE64_HAPPY_JOY) ''' important notes about using gmail @@ -69,47 +61,33 @@ def send_an_email(from_address, to_address, subject, message_text, user, passwor ''' def main(): - smtp_server_dict = {'gmail.com':'smtp.gmail.com','hotmail.com':'smtp.office365.com', 'live.com': 'smtp.office365.com', 'yahoo.com':'smtp.mail.yahoo.com'} - sg.theme('Dark Blue 3') layout = [[sg.Text('Send an Email', font='Default 18')], [sg.T('From:', size=(8,1)), sg.Input(key='-EMAIL FROM-', size=(35,1))], [sg.T('To:', size=(8,1)), sg.Input(key='-EMAIL TO-', size=(35,1))], [sg.T('Subject:', size=(8,1)), sg.Input(key='-EMAIL SUBJECT-', size=(35,1))], [sg.T('Mail login information', font='Default 18')], - [sg.T('User:', size=(8,1)), sg.Input(key='-USER-', size=(35,1), enable_events=True)], + [sg.T('User:', size=(8,1)), sg.Input(key='-USER-', size=(35,1))], [sg.T('Password:', size=(8,1)), sg.Input(password_char='*', key='-PASSWORD-', size=(35,1))], - [sg.T('SMTP Server Info', font='_ 14')], - [sg.T('SMTP Hostname'), sg.Input(smtp_host_default, s=20, key='-SMTP HOST-'), sg.T('SMTP Port'), sg.In(587, s=4, key='-SMTP PORT-') ], [sg.Multiline('Type your message here', size=(60,10), key='-EMAIL TEXT-')], [sg.Button('Send'), sg.Button('Exit')]] window = sg.Window('Send An Email', layout) - while True: + while True: # Event Loop event, values = window.read() if event in (sg.WIN_CLOSED, 'Exit'): break if event == 'Send': - if values['-SMTP HOST-']: + if sg.__name__ != 'PySimpleGUIWeb': # auto close popups not yet supported in PySimpleGUIWeb sg.popup_quick_message('Sending your message... this will take a moment...', background_color='red') - send_an_email(from_address=values['-EMAIL FROM-'], - to_address=values['-EMAIL TO-'], - subject=values['-EMAIL SUBJECT-'], - message_text=values['-EMAIL TEXT-'], - user=values['-USER-'], - password=values['-PASSWORD-'], - smtp_host=values['-SMTP HOST-'], - smtp_port = values['-SMTP PORT-']) - else: - sg.popup_error('Missing SMTP Hostname... you have to supply a hostname (gmail, hotmail, live, yahoo are autofilled)') - elif event == '-USER-': # as the email sender is typed in, try to fill in the smtp hostname automatically - for service in smtp_server_dict.keys(): - if service in values[event].lower(): - window['-SMTP HOST-'].update(smtp_server_dict[service]) - break + send_an_email(from_address=values['-EMAIL FROM-'], + to_address=values['-EMAIL TO-'], + subject=values['-EMAIL SUBJECT-'], + message_text=values['-EMAIL TEXT-'], + user=values['-USER-'], + password=values['-PASSWORD-']) window.close() -if __name__ == '__main__': - main() \ No newline at end of file +main() \ No newline at end of file diff --git a/DemoPrograms/Demo_Emoji_Toolbar_PIL.py b/DemoPrograms/Demo_Emoji_Toolbar_PIL.py deleted file mode 100644 index a373d9e84..000000000 --- a/DemoPrograms/Demo_Emoji_Toolbar_PIL.py +++ /dev/null @@ -1,410 +0,0 @@ -import PySimpleGUI as sg -import PIL -import PIL.Image -import io -import base64 -import win32clipboard -import win32con -import sys - -""" - Demo_Emoji_Toolbar - - Shows a toolbar of emoji icons and radio buttons to choose size. - When an emoji is clicked, the image is placed on the clipboard. - - If this program is invoked with a location on the command line, then it will - show the window at the indicated x,y location, get a SINGLE image click, and then close the window. - The idea here is to emulate the Window+. behavior like on Windows that enables emojis to be added - easily while typing in text. - - This program currently integrates with PySimpleHotkey to create this popup, single choice behavior. - - You can replace the emojis with your own version of emojis. Use one of the many PySimpleGUI Base64 encoder demos - to create your Base64 strings based on PNG files. PNG is what enables a transparent background. - - 6-Feb-2022 - The design took a turn and is kinda weird now... sorry about that but wanted to work in more emojis - and the pre-rendering approach from before got replaced with a resizing of a single starting image. - - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - -EMOJI_SIZES = (28, 56, 112) -NUM_ROWS = 3 # Number of rows of Emojis. Note, may be 1 more than this if there is an incomplete row - -''' -MM"""""""`YM M""M M""MMMMMMMM M""MMMMM""MM dP -MM mmmmm M M M M MMMMMMMM M MMMMM MM 88 -M' .M M M M MMMMMMMM M `M .d8888b. 88 88d888b. .d8888b. 88d888b. .d8888b. -MM MMMMMMMM M M M MMMMMMMM M MMMMM MM 88ooood8 88 88' `88 88ooood8 88' `88 Y8ooooo. -MM MMMMMMMM M M M MMMMMMMM M MMMMM MM 88. ... 88 88. .88 88. ... 88 88 -MM MMMMMMMM M M M M M MMMMM MM `88888P' dP 88Y888P' `88888P' dP `88888P' -MMMMMMMMMMMM MMMM MMMMMMMMMMM MMMMMMMMMMMM 88 - dP -''' - - -def make_square(im, min_size=256, fill_color=(0, 0, 0, 0)): - """ - - :param im: - :type im: - :param min_size: - :type min_size: - :param fill_color: - :type fill_color: - :return: - :rtype: - """ - - x, y = im.size - size = max(min_size, x, y) - new_im = PIL.Image.new('RGBA', (size, size), fill_color) - new_im.paste(im, (int((size - x) / 2), int((size - y) / 2))) - return new_im - - -def convert_to_bytes(file_or_bytes, resize=None, fill=False): - """ - Will convert into bytes and optionally resize an image that is a file or a base64 bytes object. - Turns into PNG format in the process so that can be displayed by tkinter - :param file_or_bytes: either a string filename or a bytes base64 image object - :type file_or_bytes: (Union[str, bytes]) - :param resize: optional new size - :type resize: (Tuple[int, int] or None) - :param fill: If True then the image is filled/padded so that the image is not distorted - :type fill: (bool) - :return: (bytes) a byte-string object - :rtype: (bytes) - """ - - if isinstance(file_or_bytes, str): - img = PIL.Image.open(file_or_bytes) - else: - try: - img = PIL.Image.open(io.BytesIO(base64.b64decode(file_or_bytes))) - except Exception as e: - dataBytesIO = io.BytesIO(file_or_bytes) - img = PIL.Image.open(dataBytesIO) - - cur_width, cur_height = img.size - if resize: - new_width, new_height = resize - scale = min(new_height / cur_height, new_width / cur_width) - img = img.resize((int(cur_width * scale), int(cur_height * scale)), PIL.Image.LANCZOS) - if fill: - if resize is not None: - img = make_square(img, resize[0]) - with io.BytesIO() as bio: - img.save(bio, format="PNG") - del img - return bio.getvalue() - - -''' -M"""""`'"""`YM dP -M mm. mm. M 88 -M MMM MMM M .d8888b. 88 .dP .d8888b. -M MMM MMM M 88' `88 88888" 88ooood8 -M MMM MMM M 88. .88 88 `8b. 88. ... -M MMM MMM M `88888P8 dP `YP `88888P' -MMMMMMMMMMMMMM - -M""MMM""MMM""M oo dP -M MMM MMM M 88 -M MMP MMP M dP 88d888b. .d888b88 .d8888b. dP dP dP -M MM' MM' .M 88 88' `88 88' `88 88' `88 88 88 88 -M `' . '' .MM 88 88 88 88. .88 88. .88 88.88b.88' -M .d .dMMM dP dP dP `88888P8 `88888P' 8888P Y8P -MMMMMMMMMMMMMM -''' - - -def make_toolbar(location=(None, None)): - buttons_per_row = len(all_emojis)//NUM_ROWS - button_rows = [] - for row_num in range(NUM_ROWS+1): - row = [] - for i in range(buttons_per_row*row_num, buttons_per_row*(row_num+1)): - try: # The final row may be partial, so avoid crashing when overflowing beyond the total length - row.append(sg.Button(image_data=all_emojis[i][2], border_width=0, tooltip=all_emojis[i][0], key=all_emojis[i])) - except: - pass - button_rows.append(row) - - size_col = [sg.Col([[sg.Radio(s, 1, default=True if s == EMOJI_SIZES[1] else False, font='_ 6', k=i, pad=(0, 0))] for i, s in enumerate(EMOJI_SIZES)], pad=(0, 0))] - layout = [] - for i, row in enumerate(button_rows): - if i == 0: - layout.append(sg.vtop(row+size_col)) - else: - layout.append(row) - - return sg.Window('', layout, element_padding=(0, 0), margins=(0, 0), finalize=True, no_titlebar=True, grab_anywhere=True, - right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT, keep_on_top=True, button_color='black', location=location) - - -''' -M"""""`'"""`YM oo -M mm. mm. M -M MMM MMM M .d8888b. dP 88d888b. -M MMM MMM M 88' `88 88 88' `88 -M MMM MMM M 88. .88 88 88 88 -M MMM MMM M `88888P8 dP dP dP -MMMMMMMMMMMMMM -''' - - -def main(location=(None, None)): - sg.theme('dark black') - window = make_toolbar(location) - - while True: - event, values = window.read() - # print(event, values) - if event in ('Exit', sg.WIN_CLOSED): - break - elif event == 'Edit Me': - sg.execute_editor(__file__) - elif event == 'Version': - sg.popup_scrolled(__file__, sg.get_versions(), location=window.current_location(), keep_on_top=True, non_blocking=True) - elif event != sg.TIMEOUT_EVENT: - emoji_data = None - for e in all_emojis: - if event == e: - print(f'you clicked {e[0]}') - emoji_data = e - break - if emoji_data is None: - continue - size_index = [key for key in values.keys() if values[key]][0] - size = EMOJI_SIZES[size_index] - decoded = emoji_data[size_index + 1] - - output = io.BytesIO() - image = PIL.Image.new("RGBA", (size, size)) - - win32clipboard.OpenClipboard() - win32clipboard.EmptyClipboard() - - image.save(output, "PNG") - fmt = win32clipboard.RegisterClipboardFormat("PNG") - win32clipboard.SetClipboardData(fmt, decoded) - - background = PIL.Image.new("RGB", image.size, (255, 255, 255)) - background.paste(image, mask=image.split()[3]) - output = io.BytesIO() - background.save(output, 'BMP') - data = output.getvalue()[14:] - win32clipboard.SetClipboardData(win32con.CF_DIB, data) - - win32clipboard.CloseClipboard() - break - # If started in a specific location, then assume should get ONE selection then close - if location != (None, None): - break - window.close() - - -if __name__ == '__main__': - ''' - MM""""""""`M oo oo - MM mmmmmmmM - M` MMMM 88d8b.d8b. .d8888b. dP dP .d8888b. - MM MMMMMMMM 88'`88'`88 88' `88 88 88 Y8ooooo. - MM MMMMMMMM 88 88 88 88. .88 88 88 88 - MM .M dP dP dP `88888P' 88 dP `88888P' - MMMMMMMMMMMM 88 - dP - ''' - # This is where the emoji images are defined - # Each emoji is a tuple with (description, starting image) - # Each image is the size found in the EMOJI_SIZES tuple - # These are the starting images that will be resized. They are LARGER than the version that is already in PySimpleGUI. - e_cry = ('Cry', - b'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UmVhZHlxyWU8AAADJmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6ODNCRDlCMUM3NjZBMTFFQ0FGNjFERkIyMDI1NzQwQjkiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6ODNCRDlCMUQ3NjZBMTFFQ0FGNjFERkIyMDI1NzQwQjkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4M0JEOUIxQTc2NkExMUVDQUY2MURGQjIwMjU3NDBCOSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4M0JEOUIxQjc2NkExMUVDQUY2MURGQjIwMjU3NDBCOSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Phe2EXkAACMVSURBVHja7F0HdFzVmf7e9KLRqMuSbFm23AvNGMeYZsAGTA2EkAC7S/FCSCOBPbvJhuXsIQnJbrJJNsmmQsISeggkS4lD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') - - e_dead = ('Dead', - b'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UmVhZHlxyWU8AAADJmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OEY3OTlCMkE3NjZBMTFFQzk1NUE5RTAzQkExMDE3QTIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OEY3OTlCMkI3NjZBMTFFQzk1NUE5RTAzQkExMDE3QTIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4Rjc5OUIyODc2NkExMUVDOTU1QTlFMDNCQTEwMTdBMiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4Rjc5OUIyOTc2NkExMUVDOTU1QTlFMDNCQTEwMTdBMiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PvXRfC0AACE2SURBVHja7F0JeFvVlT7vaZcl73a8JXEWnH0hBAKBBEIgKRC2Dk0ppVAK06aUUKDMB22H+fq1ZaCdMi3TdkpLYWAopR1K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') - - e_dream = ('Dream', - b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MzUxRkExNTQ2Q0U5MTFFQjhCMEJDMzEzNTZENkFERTYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MzUxRkExNTU2Q0U5MTFFQjhCMEJDMzEzNTZENkFERTYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDozNTFGQTE1MjZDRTkxMUVCOEIwQkMzMTM1NkQ2QURFNiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDozNTFGQTE1MzZDRTkxMUVCOEIwQkMzMTM1NkQ2QURFNiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PnhA2k0AACysSURBVHja7H0JfFxV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') - - e_eyebrow = ('Eyebrow', - b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6Mjg0NDU0QTY2Q0U5MTFFQjk2RDlFRjIxRUU4QjUzNzgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6Mjg0NDU0QTc2Q0U5MTFFQjk2RDlFRjIxRUU4QjUzNzgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDoyODQ0NTRBNDZDRTkxMUVCOTZEOUVGMjFFRThCNTM3OCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDoyODQ0NTRBNTZDRTkxMUVCOTZEOUVGMjFFRThCNTM3OCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PvF2CX8AACWtSURBVHja7H0JeBzV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') - - e_fingers_crossed = ('Fingers Crossed', - b'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UmVhZHlxyWU8AAADJmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NTFCRTVBQjk3NjZBMTFFQzgxMEZDQzE5RUVFMDZGMEMiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NTFCRTVBQkE3NjZBMTFFQzgxMEZDQzE5RUVFMDZGMEMiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo1MUJFNUFCNzc2NkExMUVDODEwRkNDMTlFRUUwNkYwQyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo1MUJFNUFCODc2NkExMUVDODEwRkNDMTlFRUUwNkYwQyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PjAxkeUAACr5SURBVHja7H0HmBzVle5f1bmnu6dnepImaWY0ygkUQCJIBAVAgG0MZnF+67zALvCcd41562d/++z9jHftt2t77X3gtb0O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') - - e_frust = ('Frustrated', - b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6Q0IzRjc4RkY2Q0U4MTFFQkE1NTlGNDQ1RUJGOTQ2QTciIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6Q0IzRjc5MDA2Q0U4MTFFQkE1NTlGNDQ1RUJGOTQ2QTciPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpDQjNGNzhGRDZDRTgxMUVCQTU1OUY0NDVFQkY5NDZBNyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpDQjNGNzhGRTZDRTgxMUVCQTU1OUY0NDVFQkY5NDZBNyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pn5lfqsAAC32SURBVHja7H0HmFRF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') - - e_gasp = ('Gasp', - b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QjQ5NDlCQUE3NkRGMTFFQjg3Rjc5NkVCRUQ5RDNEODMiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QjQ5NDlCQUI3NkRGMTFFQjg3Rjc5NkVCRUQ5RDNEODMiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpCNDk0OUJBODc2REYxMUVCODdGNzk2RUJFRDlEM0Q4MyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpCNDk0OUJBOTc2REYxMUVCODdGNzk2RUJFRDlEM0Q4MyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PrRdjb4AACb8SURBVHja7H0JnFTV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') - - e_grimace = ('Grimace', - b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NDAxMTY2MUM2Q0U5MTFFQkI0NTI5NDc3NjMxNDc0NDciIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NDAxMTY2MUQ2Q0U5MTFFQkI0NTI5NDc3NjMxNDc0NDciPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo0MDExNjYxQTZDRTkxMUVCQjQ1Mjk0Nzc2MzE0NzQ0NyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo0MDExNjYxQjZDRTkxMUVCQjQ1Mjk0Nzc2MzE0NzQ0NyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PnHJL3EAACP8SURBVHja7F0JnBTV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') - - e_guess = ('Gruess', - b'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UmVhZHlxyWU8AAADJmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QUM1QTE5NzI3NjZBMTFFQ0EwNjdCNzEwQkM3NzcxMUUiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QUM1QTE5NzM3NjZBMTFFQ0EwNjdCNzEwQkM3NzcxMUUiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpBQzVBMTk3MDc2NkExMUVDQTA2N0I3MTBCQzc3NzExRSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpBQzVBMTk3MTc2NkExMUVDQTA2N0I3MTBCQzc3NzExRSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PiscrbsAACzoSURBVHja7H0HfBzVtfd/tkir3VXvspolWS5ytzE22LTEQAwO8CBOAwIJhHRI8l56f8n7knyQvBAIhJCEFCAJhAAJzZgS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') - - e_happy = ('Happy', - b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NDc4QTIzQTU3OTk2MTFFQjk4QzJENkY0Q0Q0MUFDODQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NDc4QTIzQTY3OTk2MTFFQjk4QzJENkY0Q0Q0MUFDODQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo0NzhBMjNBMzc5OTYxMUVCOThDMkQ2RjRDRDQxQUM4NCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo0NzhBMjNBNDc5OTYxMUVCOThDMkQ2RjRDRDQxQUM4NCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pv80eF8AACEwSURBVHja7F0JeFzV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') - - e_clap = ('Clap', - b'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UmVhZHlxyWU8AAADJmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NUM2RjJGQzM3NjZBMTFFQ0E0M0VFMkNBNDBDNTI2MzAiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NUM2RjJGQzQ3NjZBMTFFQ0E0M0VFMkNBNDBDNTI2MzAiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo1QzZGMkZDMTc2NkExMUVDQTQzRUUyQ0E0MEM1MjYzMCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo1QzZGMkZDMjc2NkExMUVDQTQzRUUyQ0E0MEM1MjYzMCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pk/GOPYAACMNSURBVHja7F0HfFzFmf+/t1276pJVrWbZci8YN3ymm4CNgSP9wiVcSCAJcIGQXI5ckkvu6IQLSShJIBcOchcOCEeHAMYF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') - - e_idea = ('Idea', - b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RUJCN0VCMjY3NkRGMTFFQkI3RDFBN0ExNDRFOUZBNDYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RUJCN0VCMjc3NkRGMTFFQkI3RDFBN0ExNDRFOUZBNDYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpFQkI3RUIyNDc2REYxMUVCQjdEMUE3QTE0NEU5RkE0NiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpFQkI3RUIyNTc2REYxMUVCQjdEMUE3QTE0NEU5RkE0NiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PglD/LAAAChqSURBVHja7H0HfFzV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') - - e_joy = ('Joy', - b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NjBFNkMzQUY3NkRGMTFFQjk1NzE5NkM4MjcxQ0E0N0IiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NjBFNkMzQjA3NkRGMTFFQjk1NzE5NkM4MjcxQ0E0N0IiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo2MEU2QzNBRDc2REYxMUVCOTU3MTk2QzgyNzFDQTQ3QiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo2MEU2QzNBRTc2REYxMUVCOTU3MTk2QzgyNzFDQTQ3QiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Ph9nEOgAAC77SURBVHja7H0HmFzF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') - - e_laugh = ('Laugh', - b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QjdFQzYzOTk3NkRFMTFFQjhBMjhDNURDRDc2MUNCMDEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QjdFQzYzOUE3NkRFMTFFQjhBMjhDNURDRDc2MUNCMDEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpCN0VDNjM5Nzc2REUxMUVCOEEyOEM1RENENzYxQ0IwMSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpCN0VDNjM5ODc2REUxMUVCOEEyOEM1RENENzYxQ0IwMSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PgUBlpQAACOLSURBVHja7F0JeBzF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') - - e_love = ('Love', - b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NUJFREZGQjQ3OTk2MTFFQjg2MjRFRUI2RThFQzhBOUUiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NUJFREZGQjU3OTk2MTFFQjg2MjRFRUI2RThFQzhBOUUiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo1QkVERkZCMjc5OTYxMUVCODYyNEVFQjZFOEVDOEE5RSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo1QkVERkZCMzc5OTYxMUVCODYyNEVFQjZFOEVDOEE5RSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pp4lEjUAACvlSURBVHja7H0HnBzF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') - - e_no_hear = ('No Hear', - b'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UmVhZHlxyWU8AAADJmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NDc2N0E4QkY3NjZBMTFFQzhDQjRFMzU5OTQ3OUYxQ0UiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NDc2N0E4QzA3NjZBMTFFQzhDQjRFMzU5OTQ3OUYxQ0UiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo0NzY3QThCRDc2NkExMUVDOENCNEUzNTk5NDc5RjFDRSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo0NzY3QThCRTc2NkExMUVDOENCNEUzNTk5NDc5RjFDRSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PnMOIAoAACkuSURBVHja7H0JdBzVsfbXPTOaTftqLZYseV9kDF4xxjZgAyYQgyEQw4OEQxKWlz8bgfOSvKzvD++QvB8eCUlYAoQABgzB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') - - e_no_see = ('No See', - b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAKQ2lDQ1BJQ0MgcHJvZmlsZQAAeNqdU3dYk/cWPt/3ZQ9WQtjwsZdsgQAiI6wIyBBZohCSAGGEEBJAxYWIClYUFRGcSFXEgtUKSJ2I4qAouGdBiohai1VcOO4f3Ke1fXrv7e371/u855zn/M55zw+AERImkeaiagA5UoU8Otgfj09IxMm9gAIVSOAEIBDmy8JnBcUAAPADeXh+dLA//AGvbwACAHDVLiQSx+H/g7pQJlcAIJEA4CIS5wsBkFIAyC5UyBQAyBgAsFOzZAoAlAAAbHl8QiIAqg0A7PRJPgUA2KmT3BcA2KIcqQgAjQEAmShHJAJAuwBgVYFSLALAwgCgrEAiLgTArgGAWbYyRwKAvQUAdo5YkA9AYACAmUIszAAgOAIAQx4TzQMgTAOgMNK/4KlfcIW4SAEAwMuVzZdL0jMUuJXQGnfy8ODiIeLCbLFCYRcpEGYJ5CKcl5sjE0jnA0zODAAAGvnRwf44P5Dn5uTh5mbnbO/0xaL+a/BvIj4h8d/+vIwCBAAQTs/v2l/l5dYDcMcBsHW/a6lbANpWAGjf+V0z2wmgWgrQevmLeTj8QB6eoVDIPB0cCgsL7SViob0w44s+/zPhb+CLfvb8QB7+23rwAHGaQJmtwKOD/XFhbnauUo7nywRCMW735yP+x4V//Y4p0eI0sVwsFYrxWIm4UCJNx3m5UpFEIcmV4hLpfzLxH5b9CZN3DQCshk/ATrYHtctswH7uAQKLDljSdgBAfvMtjBoLkQAQZzQyefcAAJO/+Y9AKwEAzZek4wAAvOgYXKiUF0zGCAAARKCBKrBBBwzBFKzADpzBHbzAFwJhBkRADCTAPBBCBuSAHAqhGJZBGVTAOtgEtbADGqARmuEQtMExOA3n4BJcgetwFwZgGJ7CGLyGCQRByAgTYSE6iBFijtgizggXmY4EImFINJKApCDpiBRRIsXIcqQCqUJqkV1II/ItchQ5jVxA+pDbyCAyivyKvEcxlIGyUQPUAnVAuagfGorGoHPRdDQPXYCWomvRGrQePYC2oqfRS+h1dAB9io5jgNExDmaM2WFcjIdFYIlYGibHFmPlWDVWjzVjHVg3dhUbwJ5h7wgkAouAE+wIXoQQwmyCkJBHWExYQ6gl7CO0EroIVwmDhDHCJyKTqE+0JXoS+cR4YjqxkFhGrCbuIR4hniVeJw4TX5NIJA7JkuROCiElkDJJC0lrSNtILaRTpD7SEGmcTCbrkG3J3uQIsoCsIJeRt5APkE+S+8nD5LcUOsWI4kwJoiRSpJQSSjVlP+UEpZ8yQpmgqlHNqZ7UCKqIOp9aSW2gdlAvU4epEzR1miXNmxZDy6Qto9XQmmlnafdoL+l0ugndgx5Fl9CX0mvoB+nn6YP0dwwNhg2Dx0hiKBlrGXsZpxi3GS+ZTKYF05eZyFQw1zIbmWeYD5hvVVgq9ip8FZHKEpU6lVaVfpXnqlRVc1U/1XmqC1SrVQ+rXlZ9pkZVs1DjqQnUFqvVqR1Vu6k2rs5Sd1KPUM9RX6O+X/2C+mMNsoaFRqCGSKNUY7fGGY0hFsYyZfFYQtZyVgPrLGuYTWJbsvnsTHYF+xt2L3tMU0NzqmasZpFmneZxzQEOxrHg8DnZnErOIc4NznstAy0/LbHWaq1mrX6tN9p62r7aYu1y7Rbt69rvdXCdQJ0snfU6bTr3dQm6NrpRuoW623XP6j7TY+t56Qn1yvUO6d3RR/Vt9KP1F+rv1u/RHzcwNAg2kBlsMThj8MyQY+hrmGm40fCE4agRy2i6kcRoo9FJoye4Ju6HZ+M1eBc+ZqxvHGKsNN5l3Gs8YWJpMtukxKTF5L4pzZRrmma60bTTdMzMyCzcrNisyeyOOdWca55hvtm82/yNhaVFnMVKizaLx5balnzLBZZNlvesmFY+VnlW9VbXrEnWXOss623WV2xQG1ebDJs6m8u2qK2brcR2m23fFOIUjynSKfVTbtox7PzsCuya7AbtOfZh9iX2bfbPHcwcEh3WO3Q7fHJ0dcx2bHC866ThNMOpxKnD6VdnG2ehc53zNRemS5DLEpd2lxdTbaeKp26fesuV5RruutK10/Wjm7ub3K3ZbdTdzD3Ffav7TS6bG8ldwz3vQfTw91jicczjnaebp8LzkOcvXnZeWV77vR5Ps5wmntYwbcjbxFvgvct7YDo+PWX6zukDPsY+Ap96n4e+pr4i3z2+I37Wfpl+B/ye+zv6y/2P+L/hefIW8U4FYAHBAeUBvYEagbMDawMfBJkEpQc1BY0FuwYvDD4VQgwJDVkfcpNvwBfyG/ljM9xnLJrRFcoInRVaG/owzCZMHtYRjobPCN8Qfm+m+UzpzLYIiOBHbIi4H2kZmRf5fRQpKjKqLupRtFN0cXT3LNas5Fn7Z72O8Y+pjLk722q2cnZnrGpsUmxj7Ju4gLiquIF4h/hF8ZcSdBMkCe2J5MTYxD2J43MC52yaM5zkmlSWdGOu5dyiuRfm6c7Lnnc8WTVZkHw4hZgSl7I/5YMgQlAvGE/lp25NHRPyhJuFT0W+oo2iUbG3uEo8kuadVpX2ON07fUP6aIZPRnXGMwlPUit5kRmSuSPzTVZE1t6sz9lx2S05lJyUnKNSDWmWtCvXMLcot09mKyuTDeR55m3KG5OHyvfkI/lz89sVbIVM0aO0Uq5QDhZML6greFsYW3i4SL1IWtQz32b+6vkjC4IWfL2QsFC4sLPYuHhZ8eAiv0W7FiOLUxd3LjFdUrpkeGnw0n3LaMuylv1Q4lhSVfJqedzyjlKD0qWlQyuCVzSVqZTJy26u9Fq5YxVhlWRV72qX1VtWfyoXlV+scKyorviwRrjm4ldOX9V89Xlt2treSrfK7etI66Trbqz3Wb+vSr1qQdXQhvANrRvxjeUbX21K3nShemr1js20zcrNAzVhNe1bzLas2/KhNqP2ep1/XctW/a2rt77ZJtrWv913e/MOgx0VO97vlOy8tSt4V2u9RX31btLugt2PGmIbur/mft24R3dPxZ6Pe6V7B/ZF7+tqdG9s3K+/v7IJbVI2jR5IOnDlm4Bv2pvtmne1cFoqDsJB5cEn36Z8e+NQ6KHOw9zDzd+Zf7f1COtIeSvSOr91rC2jbaA9ob3v6IyjnR1eHUe+t/9+7zHjY3XHNY9XnqCdKD3x+eSCk+OnZKeenU4/PdSZ3Hn3TPyZa11RXb1nQ8+ePxd07ky3X/fJ897nj13wvHD0Ivdi2yW3S609rj1HfnD94UivW2/rZffL7Vc8rnT0Tes70e/Tf/pqwNVz1/jXLl2feb3vxuwbt24m3Ry4Jbr1+Hb27Rd3Cu5M3F16j3iv/L7a/eoH+g/qf7T+sWXAbeD4YMBgz8NZD+8OCYee/pT/04fh0kfMR9UjRiONj50fHxsNGr3yZM6T4aeypxPPyn5W/3nrc6vn3/3i+0vPWPzY8Av5i8+/rnmp83Lvq6mvOscjxx+8znk98ab8rc7bfe+477rfx70fmSj8QP5Q89H6Y8en0E/3Pud8/vwv94Tz+4A5JREAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAADJmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6M0FCNEQzMEU3NjZBMTFFQ0E2MjBGQTQ0MzU3OUM0RTgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6M0FCNEQzMEY3NjZBMTFFQ0E2MjBGQTQ0MzU3OUM0RTgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDozQUI0RDMwQzc2NkExMUVDQTYyMEZBNDQzNTc5QzRFOCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDozQUI0RDMwRDc2NkExMUVDQTYyMEZBNDQzNTc5QzRFOCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Ppi+AJIAACjOSURBVHja7H0JnFxVlf73Xu3V1Xt39ZqlO53Ovu8ECAkJQf5AosiiDDDggqCMjjijo6ijf3VkXPjpOKAiOsoQRWSTECASEZKQtbOnu9Pp9Jbeq5faumt/b865r3pN713dSST397v9qrpevXrvfvec8517zz1XUlUVV8rlW+QrTXAFwCvlCoBXyhUArwB4pVwB8Eq5AuCVcgXAD1SR/h4falMqbHTQR9+aqFp6feymqkRf+//SCv8VACcPmHQ6zKFaSHVqtNplGamyhDRFRZKqIpGqbsQNICFI33fSy7ZIBC18pNpAtZpqDdUSqmUEtPcKgKMDK44O11K9ihp5JVdFQVK37iflb0+Fmp8HZGdCSk0GEuK1qqPPjEaqhqgImrTzQyEgHNb+1+kjMSQ5DAZJJAkapwtobQcqq6HU1EGi933ahr5fQ+fvp5eHqb5LtYhAjVwBsC9oLFG3E1hb6LiGJElvIBCWLICyainkmflABsmgjRSkwcioUJWM0UpCp3QQSoQCxj++y0PEAQaXFG5dI4lhGbD3IJTySsj8GQHqIUD/Qqe+QHX7xZJQ6RIAjVoft1GDPEINsobAA4Gl3rQJ0pyZQGIimTLTFLJi+drRlEmiRVUmsxYh89VxHPAeo2MxATjx5oyltpkU7bFTwJ9eI2mthcxqmEB9kT5+koDc84EAkIBjYvEQAfdv1ChpKUlQbr0R8ub1QKoQs0VA3DzASihKhl6iQXrQQ4C5D5IePE3vL54WY0msJCv5yg7gr7uhBEMCzGP0/28SkH/+uwWQwLuXgHucgMsktajesQXS1VfFQ5e8iozYGsCce+GXfBVkqHaTtBWRGAQuOZvtJe39OinUl3dAaWsnDSvjED3fwwTk4b8bANnGUQ99mnroDblZUD99L6TVawms5E0E3HK6G32/Lk5GyEW8wUmcIVB7WTDlOgeB+Cbw1k6SyICQ0h/Rv78xUe6KNIng3UTg/Z5q/D23Q7rrTjt09i0acP0L2zYXgdZGXTriuaz8MlarpaRWHeSMvPY6cPy4cFVO0v+3EIiVlyWABN6D9BBPpaVA/daXdXLB8huBlJuIiAwgcW27qO4kNdk5vNoifz0M/eCfSwN/blb9MA8hEBb4yPsfu5r20K2XRRXG8ZNEU18ABz44SaXeSCAevKwAJPC+QIcnktcvx9YHF6Cw4BYYiUkGiXxyjZDPzY1c0enHXxyNaAiZ0EEuYAiGboBUuk2XlCiux9/x9RlYmdgSDw9kKHSXEcSrnj4AW9EpniJJdYr3/H8+n48hlxv6gBtxETcCzU4ceeawgrraTgJyI4F44LIAkMD7GB22GbfcisqHX8QnM/WI6zdGEiGV82IrsThnLLy3S7ekBuqw6MvXqYaacpbElQRi+SUNIIG3gNTmIcPVa41nvvY36Qs5ehj6/VqYEPslOcnHO/CBKFmd5Zj78CpV52orJUlcRiD6xntNeYLAMzJhiSSnG4998WXpkxkXgsdlm+ODAx6XBmsBGr63TSKTwOO534/FNSdqOumL1MPmeb73tLQ2PR3JhgtPKCZDv9eND1wpzt4M5YHP8MtHqKMvu+RUKN1UKklfpe6GzfHvP/ImvjcN0Ed/hYmAnmkJsc1nahrgCZKRJ8qSqLoEIWAiwCSAz2OWyFWnRsT/uCTALQjFYCyRP0tQR9crmER5pPgBP+siU0ycOukOe5MpD90Vf9cfvVMmXD7JIr7jQqI4v5Pu1KkkoFO2QZF6jL8t3I6VnyhQ9e62d3e2YP142ls/AZ3sYZK++H9cW42f2L6CdHUpTGpAsDVd1+C99xju7nzqEnLeJs4nPFquHRlEry4RXjkJHl0Szq01SId24Drq8CvH41roYyx9BlnGZ6fkQL1j7lkJiXb6r/PCE9veGloqCGcfuWmhsDbd4w9o00A+MvkRhSSjn91UVG16aKBrDFZscf1UEWmJuH7eiY6ExmwGeEbEZKTXJmowajGrRZueirMOo97ommb6no/u36p4RbWjTnw2fQFw6A3qOioeobf3XCoSuJUocsaHyUeHley0znbhGZ1ntXFNZqHUyHvJI3pvH3CukqB2XwjEpV66gExNAebNok68Dpg7q+dzk0EDsH9JTACWLIZ07Bjuoo7/RZJCx6UA4F3UW9X1V5OxiB/EPvMoC7T5tR/8N1BbP1JrLWm6aKJL/98Z5nd5esnj1WpVjTagvYoe/YsPAcmJGoCDleV03tGjAoPbqP78ogLIcSj0rDevWgrJYo5KYP8SIo+94yT2Hwa+/aOe2XFuJMWSANVggspdWtLIsa7DCSmgDalZk1ORkJsPo9UmxqX8rla4z1ci0KERHNVkQSTBjogtpQ9FU+ULoyukiGaLpRCRJFczdN52OlGBRDozMWsq4tIzobfYEKbf7mxxwFVXAYVvVmdAJC4JqtEizhffUSICRb5POaDp9gNFRDG/Avzo25oKHaxMI4JnJW5EpuGOiw4glY3UrsZrVtMrYxYZjuQLz3Dtwfk6Fd99oge8cHIWwulToep6uqrO5YCxsZzan7zdm2/HqptvgzEuAU1NTXA6nWQDOwSIemrwoLsdzWdOoObIPvgd1ZA9rQhmFxKggxsoVa/CQOfq2+oEDc+euxgZc5ciaUoewoombUajEfHx8bDb7Uik45nD7+Od3z0Fd0szIvGpCGXPpM7Rt/kYQENjBeROl5j0/Tp5et//5uANxqEfixZB2r8f60gA4kmNei4mgBv4z9KFLC4FA7Qa9VTnHvzsGS1UQQhk5gwBYO8iGrblPOzTZuCWf/oavGEF7x86IsAbtCRkIuXaW+E+cwzeitMwVx1HIHcOlLikAXWeqbYYMkm3ITEVifNXQk22o9EXRmPZ2QEvbyUxycvLwz/8x1M4suMlHHhlG6TyInTGZUA1WyFb4iBb46CY4hCYOh/GulLoqCOxSn1rF1A4b/BbL8gH9u0T/jhZT2wfbaPrYoVeYTx+nDcVaR+9hd4k0b2Yp/Y9wXscVaf24ulnoyyRVF0oIx+yj/w+dwupsTbonU3QtzegcPU6rLjzEyg6eQpnz54VEje87ZJhSs+GlGRHoKWBrtMIhSRF1fc1Qsa6EqEy9XkLkL7sGqEqhyuhUAgOhwNny8uRWTAHc1esQeWhPdCRxEmhAGQvMe0ON1S6lqTTU8dJho6eRSIVe55I55o1mikdqBD+2L1bvGys8GHnRRmJIfFPILMye0GX2TNPG0B97uawgx6ab0uGueIoTCQthuZK6FtrCUgHpi9ZjYT5q7Hv4CG43aMfqrGmZSBSsEy0mKG+rG9vpUbVedogEXjGnHw6ZXSPH6GHLC0tRUldM1Z9/EHIahimgJuqC2ZPE6zniqAnDaKSao8kZ4rvtLYB588Pfs14cmfsGcL0r72YNnBxlzoQzMGY2a8Lt4ugo3f3RbUp9VIjgWY0mnD1/Z9DzuyFaGp24MT+3QgmpKK+sXEctF6G3kQsasZiyGWHhSpjm8XeuqGFdBrZUp8lCek225h/w+/3o4pq6srrUTB/MaZOn04kxof9Lz+HmtPHIAf9CKflCFPA5cRJYOrUwa83dQokRzMWkSDoRhuqGKux0KX8h8P+YEjtG4Qkxp0OorxSRUPUjDFziydW+Ykf/RpxUwvxzt59OHWmDHJyBonJ+PuUxWKBT28R12KpEw/a4RLqDmQbdSQhev34f8eUnoPzTQ7yZQ/hbIMDW7/0bSwn0sWaRNfepLFVBvDE0B5Qbo74nLl74cUazJ7L7H8qxyIZMwZQn+/jyIkel8FERv9j33wCx4pLUFRURLxCiakrZzKZBEuVM6ZD1+kUrSNcBSpBvUl8HuvCJGv7669jyf+7HfPWbRa2XIkCyD7iUEolPb2nHS8KgIRJgT2N+IIuKoG9i6+KWq0RRcd7Bghv/cJjOFF6BtXV1RPii3dJlxqfIlinHCQfzU+tSCQjQu9jIX2DqdadO3fiqjvuQxq5JDpyJ7rK2SGmb5N6PK78iwIgSV9hbnZ0ZsOQ1vdD9z7hNpws0d4uuXErXIoONTU1Ezi8pT1WRK950VIwIJx2KT6lz+cTUZixvrt7L2548FHhx3bRz/KhAEwQbchKduakA0iGV6JOnWXvwk2X0Nf38xShuJTHPSVY4xMxdfm1OHXq1ORMMnSxTCUEKRIm9W6JKoGJHZLzer0oqazBylvv7DZ+VdXasNtg46lpWt+acjEkMI3NTUqXz6zrNbfWWSrCAl/aoanO5R++G8dOF084cOHuMbqoiudGpCpFpSESmfhobraJcdPnIC4pRUghL6xpaR38/MQkcXuZFwNAYYKTu/R47xkI92ERsVx0XELWzLlwyWahYia6BIPBKHBK1G0xCIdejY5Vdn0+0eXMuQos/NBt3VJYP8TAPQ98kyTmXDQAE7sETx99oZAUeI/i5ddZIlTYF6yAY6guGMPi82lzUjq/tmBIMWvDXEpbozDUgUAg5sx3QBXOwaAwISVnqpDC2rrBz2W3lG4p8WIAKKZGxQxEbwnsOAmvx4cXt0tIsGfDpRomx+5Ro3UPvTWcE7MUqsEMxZYMKRyCSVa77dRkFJfHg5TZi4UUlp0Zwnc1iVOMzCkmG0Ax7G/ucq3k6AvPYex4mydo6a6mFCI4CapT/Cw1GEuXWVKgdnoQTtLMSiSRFIWsg9ygTSa7XC5MVvGZkyAbTGhtlwYlMpaeyZPEyQZQiJy19+wNr9PzHscbuyTIRhMMGVMmpaEYuLa2NsEG5KqTZPeM3QDy1E84JRtqW4MAl+0ggz05bFgiQjMLSkQd1B+Upb4abbJHYvrx6BM4ey6EugYVluw8SPLkJMNoaWkRDNPS0S6kL2SfLqSu20dLzRWTxlL5Uejonvj8/ox1ooold4Y4FhUNNvzX/dJwEQGMdiPPoe6ZB0tO/qQ0EM9csESRtYNafUoMYEdEUFXvp9UhmEW+ctAHU9M5IbGNjY2YjJSb+rgEMf9YekZzKWI2aBHzO434oXp55kGCzhIHY3L6hDcOExKerzOSHpLKDohB5FDWwIMaPMkbSp8GtaUOVm+LYKSTBaIlJ4/AIzIz0LyxevEAjGjOcfRdx3GcqwiT06rCnDltUkhLc3MzjDrqMGf2i4ndwJS5YspqUEc/bYqQTvV8KSw+Jzo7O9HQ0DDhroUl2h7FA4xl9AqBdE82gJ4+N+Apwt5DXTc8dUIbpLW1VYBnoKeQS/aL/3FIQ9c0zpDOfvZMRBJIO1SdgrWjTfiOdXV1EzrQoLPaYEhIRknphWxU6ZHA0GQDGNCGr6J6wHsSew9q7NOYYp8wtskSwwFOJkmFrmSfGDMOTJknHPaR2msOforEp0GtKYbV0yzAq62t7R4ImIhipk7tI9eqqt9EjC+6nnW0gU2xAFCEXnuifnGTQ0FVDalPe+7ggSDjKNzILCms9ixKEHLx+0Jd+qcthGIe5Sw75wfJnaW5F7VlsBCx0Ya86ifMTzRHXaqSkgtVKN3OqHtOLABs6w3ge/u61EU8Aq2NCDmJ2vs6YhKUy5LBEsIgWjtagTMHoVhsCExbNCK1OZgkcnAVuxxqK/mIlcdg0GkuBhOjWJAbznYQ9jgRbGuCEg4J7XS6uG/n5mxR5Nm0jZrdxsIUiRvwiBQbeOZ/o6aw7Fi/zi5Bb4snKp1OqjVD9ETZZB65mJO6ZJunp6c0NJRBbW8SRCSYVdAdCDyeEmYfkdSvsf4M9MV7oStcIVwTdvgzMzNFGMYIx/JExw046hFsb0bE245I8EKz1h4Envw5cO892joNHvQny9A8Rsdt7GVTqpapaFYBdKVEjwtmJuEjH8mlHlcKvy8s1jp0kH6vbwSqzwO1DT2AGtOyYMufK2JLhhrbZEkQPp5Elv/sYUhkcEMZeRfElMbEkw36YaorgeTvgJRbCF9ChgCPQRwqFCPi70RHZQl8tWcRCWiLIXh0iuOEcjIBzuXGzjovjDHE56OmVsIfn69Ahl3Fpz4J/PKXUJsceIts4IcmFUAum9Ph4GxLq6+djcd+9BCMzU9pc4EDFBdJahEJ524ijfsOa5OcxqRUJC5YIxzdPo1Cvgn7aAG/X9B9lRgjq8pgzqzR27tRjX0pMDRViNhS2JIQnr5QRGxzlLatXzSbGgmTtjlO4J2mr6nIpT51/bXAmuVA3rRBaACPF+c8gsNHXPjqZ3+F2YViiE2lx32aAHxwVMw2BhIYTzf5jfSMZN33n34UFvefSB8cGdyIm7QHu24tffc6bYlBSbEPnTVnxRtTaqZ4ao4vYTKh0FOZG89CbahA85rbcOrRbZDVCKyOGm2idiKKrEPboo1oXbwJCaxOm6ugo/tydfiERrBGB37ZvrftfxP+5jrMmKYtaHn4fmDhPCA5aQgOx5EK5C9nz9tKUq3Hzh3lYr6ZPnm5wofdk61Cv0uHr/74mYcxf66BdORPRn2Niirgh08C5ZWkZrKmQVewGC2tbWJdvY5UJkJ+BDNn4NQjv0Hr3KvFd0yuZmQeeBX2ozthcjbGQHfK8EyZg9Z56+BYuB6B6CC4tf4sln9jI0wtNSIguNOcKMIWk+UwXEffg06K4JNkx7bcqIVGjKrEzSdT8BAeuv3bqK1sYl/w0ySBT08agAReGvWymrw77rR89LHvYFf1HuiCdbCrzZivnsJctRiZGFnjsp1//Keaao0kpEHOKYBUelDEdgZyZkOxJoiZ9dKPf4tAvKbPd211Z5BcdhDx54sRV18mwB2WtJAK7iAC1EG+oJtUpDN/CcLWhAtU6fSdTyP3r78lclMmgoSljGkIEojGmpOIt6n47leBWQUjay9edl0mFeK0NA8VyIdTSsLynKvhdbThhZuF6ftvAvBzkwngN+jwrc3vnsUZUwGeHgCrDDThemUXNqpv4xblNaSJpLgDl+om4Ge/Ao5HCSyvMGLnnGcQutuUuvn5Dffj/Pp7taVoA1HrTjeM3jYYPW3QBXoyPil6I4LUOQIJqQTW0NNu1uZqFLz0OBKqT3b/r2vhjSwTATOq+BypzOtXa6uMBnQfyEt7T7oWb8mbsVO6AUelJVD7NXk+EfEvk8u85wub0bRrp4NUaQ6BGJpwADkMnKME7BtuyLjmJ29J3yOGWT1MdioD3dfNynY8qPwCm9W+y6x5te7JCm059X/+gEyEX4a/YOWgY5pekpyqmz4L54ylsXW02xuQ++5zyDi0XVv716+wm8HL3z5+J7BgIXGRNCAzpe85dVIOnpQfxrPSPTgvDT8XygAm1r2Hd7bwAiXcQQC+MBmO/HXUWzJnP/jPEgNXPYLUYpzx4WX5w7hR/yaW6I9iu3Rz92dN7dp4YLNDczvEENcQA9I2Umnzf/V5LHryQWQU7RBSN9Zi6HCKa8z/9aNY/oO7hG0dCDzR0VI0l6e8ou99c2lAFj6j+zny9JX4nvzVEYHH5V0XkZ68q6BLFD3hnklRoSSBv4Te8Kmth514yWnFLufYrnOTugM/Cz8MV3m1SGDw3Dbg1GmSxCnzoVrj+0zIDsn8SZ16c+fCkzub7NpMUpPpRETsUHqpXx35eDry70zuFpjb6mBtqoKttlgw2gtGiug983qiwdqR3AU1FKIahNVVB33Ej0cf1fy7XLuM51K+gH/X/btIPzLaYiIx+uF0oHLbYzj1+HdD9NPpJIWuCQOQs1GQ+nRMv+cfE5f962/wZWKRznFMbCe0l+NrjZ/BvIZd+AkRmZDBCp8lrXu8kpc+C4pHVSwJY37eVcX/pGEfRVWV3qPhPUcGStWOQpTotQBsCBdFFwkgrqMJq8n+XXNLCh6z/AAH8x8Yl+r+NJHemd6T2LmRV8jiAQLwNxM5lHYNp/e/+rpFkP3FKAx5UYccNEkZQ6Z/HKy42/34svw47qrixIZ7EDQm9JWEXmEPl0JCvIjOhIjehIOHAnh26y9QFcojvU8CEzfqqEAkox1ZagPMXg+WpsXjXXJRAj4fJ32fUAA3CvU3tROpnn/D3WEtPTSDVynloViaiyPSUhySVmC/tJpuMXnwK3WQ7QoFYJM64Hj7GFS9mRrIiEu9BKiT6TodmOo4jio7AdjuGBJAziK1SD2OlepBUeeppzFbLUVil6Z0k+q1/ycOr5+JXW+cuH6kawXHBCBprBuypqSrKelpxEPP9LpYGDPVs6Juwatab4VOAPmWtBnb5I8LP6jvKLWWHmVZ/RuQO73otNpxOZSw3iL8UsMf/gfy57dAYQnk9Ye9bC4n29qqvIIt6qvYqLyNlKEmGzgzcaARq66di7d3nODxupVU98WchVLP4J1RlqzfNIdwJNXmrxxmrC6C1ep+fFP5Fs6EZ+FAeBX+QflfLe1WmNwdrxN6KQL973+rhQHqzbhcSsAQD7muFsu8e6OdUfNx56gl+HXkATSFMvBc5G7cofxxaPC6iq8ccxbN7no3ohxqY3EjuGfI85cWEHi1PNk1ui+T+ng2cg/KwoX4iFMbNVrq3gO5qUEEG+nT7CLjA+RLe18uSc9xppnimPTa78T/st2n8ELkdpwKz8f9ym9gG+1eIARgalYWrDYx1rp6omzgCv4zpWAadcGyMTdAvlqBb7d/FteGrsKOl50ispV9Lx7lkJJTxSi7oO3BAFU/1WAfMjO5aDFgBkhGEySTSTtGfdSQLx36o0dw34Yf41MpL2Gh108dcIy/468RozrLV+dh967TEweg2WpBagbxXsfbY26TTjIXfhLetLPvg+y55lA3VYgqFqNYE8X4p2JJhBpn62GkIQaS/bGw5puJGukVFjcOkBgUclm0ox6SwaABxyt6o1MLUtAHnaeF7LVb5JqRwkEtUd5r22C+D2glThY/VgBDTWJPjAVLp+G9t0+nk7maQkTmfEwBpJtdsmjZFG38zz/2vRzao6E7Bw9E20bSppaEXidnmyvatPVYbBs5WEkVq4ysUI1UbXF9sjt1ATzg627nQ7rgYfoce50vUUfhVb2y1wUpwPcTTaU1wAgN/9TZMm39H7eLqo4xHIgbINCAGbO6o/kWUY0dgNQjzHRzUwvnZEenEMY+jeMk89DWDpSU0k0ky7DkGRB2KzD6IjCHFDT1mlDgXq6jio72fhZcJ0ZaxGA3gSzWAZLkiOQ+siY13bnS+BhtfLFal0HiY5hX74bEyiVx5KXYocCwMTw8tpBNzdAUJok1SghUh0XY/OYbAI8PSBirFFKb2nOnd71jRrM9lhLIF5SmzyD1GSYRUsYWfhcIaerz6NGo6kzXCTqlT5KxcLGKm5YoIidoJRHc6hpe7Qo0NHIEdv/hfrKZPNsQ6MREFpamFHJlMzM10Djny7SpWh7Rn72pg9tHfLw5gv0HVWzYALi84wCQ1Ghy2gqxnkRVlGGzVowWQJEJM2ta1riljzv44SKxtBhKQg/jTLVpPT+OiOj8+Vrt9vkJ1MYmDuglFdwerU4OeNI+G48ZZDB470G+H15tnBw9cgqQDLu2H+FAJS1BFQDq03Twnw+j/BzdO3lCU8bqzpIvaDDokJWVoNbXOWfFGkChnJN4QXx47ClCeGcTlixu+LVXAyd6ZdbVDzF2zaDOyNfqgNonqAHJEV4cYM2xRWxWeLKYwWWQ+PrMUfg1L0rla3KExFgzj+ijfc+QIiNYq81lzpmlaRnTWNa0hjV/cer0eKmxwZkXawDFtmJxiWlEI4+NGUCvT8teJPzCZUApEZlgV/rJcUiR2LXT2Gu9/iSUUPR+JYOE+FQJJ0+r2OLTOqkpcSwX1ADMzIxjLZUx3JDaaL3lXL2BCIdF391TRn1/YQ2kE6c0m2InVTMlrWemoNV7ee3L3NbrfgtmS4InVVRobtLYRsqJW6hhZGRxYluBT0YsR2LSk+Kji8xDbWPusWzHOsgOzomOGs3J6QGwqvny2RmdO5urU+omOlev0JqG7WDnmDebo2uEnUhK7o40t8cMQLrJJFt81MNROscsgRXR2eyc6D6P83IjsJm1h3dSg1Q7Lg8QT1T3GOy5uQqy0lRkE787XTJwovORS2EnrHHdrCkplgCm2GxRlTHG/Wp51v18rdZj//A81Fdf09yEGxb2DJO9c1o3KfnNx1OYeR4+pwHIZGXdnDDOlGmLVDxuUq3OcVyc2jYurntWIzFmJIYaNcHYtQ3LGH1AZoNtmvYNkO988sABLN6/H3p7hqJMmxWW2yI61LfLeK9Ej3Vzw5ckeNwJXz2kF+YgxaoikRjYz36qKmQWWCD4pvXjyp9AbWsw6kYkgWNf3BIZmwTy5hqzZoBHWozBAJZHx7nKHPS+uSkynWcQzfGSciYsy0qbhClZKtLStH0WpIvIb7o6nsNBN1snw90YgfdcWPWEVL4rRZYEU2QA9by3/bSs8anQvqO0sR0LHVexkmb4188Cn/8UpINHxO7P0oEizCRmyqEtXpLyQ36P2ll9IrKg8him9hq6UtmhTk2DlERKJYEANVu0HVV4zQlXdiH4fdfoGathg7FPCg/0H/fmKUnOphjsqgHNfrE/6XYBLrdQ8WJj464hVUkSQTU8ksGGioN35NxsyLwmYt1aIDtj8jrWaAEMdtsmaXwr07iheYsCri4PpHd2A2+9A9u5Km0ik5qIpzr+BdoC0jnU6LPqGzCzuRl5pMJyohluJ7TIMlwc+0q/zbPWPHfGo+sciHoz/X621SI2OcGNG0YenT2yHzb1XpfojyWAbW6Poi0hkg1AjJL+cZ61rTdp9XQp8NLrwN6D2EggbqQGPEjPwlvT9Fl0wYtqovahf2Xl9Thno+DM+NrAdS87LiLZdCLJuhQOctLS70c7yQX1LYe2YpajEOjwTfrqd+leTNmZ2r3ecF10k5OYD77qyM3qprFtsSQxDpdbLRB6WTJNSK+fN1urTWRr/vAy8OZfsYIkYA81Ikdpfb5rDXn0yPV8P2A5mvbxiDVRLJ0erIh1DpGQ7y8t6pDbqNH1PsobONOzp+VPA+65HVizYoLtsWyG19MNYGssJbCypTVyVZjol55TKwfrJ+wZMtIJrU8DH70F0k+fBo6exP3UaGupQTcQeHW9GpjtEGuFrh4lEsTw0jOeGhrcXRYIJNH3p/ceieQG69oalT77Dh2+xlOPn76HJG79JBEpfQqqq7r9kMpYAnicdPPdbWSI7P1zY09QySGF+P2vA9teBH77PAqpAZ+PNuxHqDXXk1oY0ProW2pEHa6fDNRAm9KkBrouZzy4Op/g/c5XIKVNzuNqpNOQjNLiVu4s9TtbYqhCEQ1zK9p7Ah/aNHnhf9zr7/4o8Lf3gZpasUHGG/RP1ZScLplS7NCZLJDHOJ3gk41QulMzE3GIhKB42rOCtWezmKJ+5j6imZMGHkTSeLcrgONHOXsU3os1C91LjXniN0/tWjB74Z1S3iT6ZcVl2hp7vSUOSXOXIS47T+JsD+Mt1nBYLOMWSe/Y/eCg4tQ4YicJUEv2i+3kFs+fvOf0ydPxwrM7ENGmZX4x3PmjWmJdQZYh34Lzfl/gbo8ngqyMFiTZlD5+1kQVtoN1DeRjrd8KS8aU7qiw8bsKslgyzXln+qTa4qyGHU7U0ENvuAaIt038M7YRJfvroTT87inekVV9m2zx/48pgFEQz86wIqu6vHG5o1VBOtkoq3mMk5cj/c1q6oq/pd/Jno6EgtiLQxeIXdvadRejGWpLvZgQXr184p6PhY0Xt+4/Cvzq502qElFb6TZuorZ2xxxALgQg77K1uL4es3hqKD1TmybiYTJdjCcSuD3/6xltADx9+XVChU6M0z4AiGRbJXcLKsoDuPaqXnnBY/hsLS7gHJH5Q8eIpD0rIiQ76P83kvSNKL3/mACknhEhEIkXIo8I6cKSUqiZ2ZD8YW1gkyUyVmr1BNm+Xz9L18yahsTCRSNvHHZVR/lbnA+Gc8H02e6OpFBpaRCRZmtj6P+5O4n+kkloII75JonDa6+Jm24m8DYReIdHfM9jVmsaiK+wM03mY+PBw8IsSQnJPTGfDOR4HpjHJJ/8Hy1dv33V9dCZhw/1qkAytqMQB5CLJtjIq3cTU+ubGpC3Pp0zR9uhur1fpCJvy8OVbaImhVYhhdUVASxaTH7HOBkph1pUNQKNBNy5KuB3JHXFxWIceC+Bt5HAG1W4+7jyxDCpobqPiM3r7DOVl8N+9DhUm41InE1TD8zMOSP7aJc68JTNniPAH0nO49j2zVwwPFNFOv5Gfnk4+lhu8u3PIxF5aIchCuLWrcADDwBLlpBEkUOybBlQW9s9xaUJndEokgx17y/BwcRkC3mWfcE87XlGWzgSj+0cS1w9Hf+8HdhOrUb9hBMacLKITxJ4o14nHpMdPAnEBgKRV6p0BAJYc/IUjCVniLnFCzMCh1MLWjIS0TGMgDwy6GwXnn9Rm+y1r9wwrPQxeHtwYX5SH0FXRVKZLzlx78ci2LSp7+d8j7zDJsec9t6Li3PBcLIhscsL20JvG85X+FFQSH5h8shIG3fCVpemKh10bGoBdu2iTvmn7t3MeE+bWwm4V6kNxzSFHbMtWOkGFKp7CchfMwmnBlly7Dj0VFVeC2IliWz3RmNCuZfrByY8zMjK64CScuqh2zXmmTiM9A0GXlcJkBKtlpJw+8IW5E9TBxwoWLCA8273gMg6jUHkdM6C1Bg1KSRMkZWrSeFAO1TzqWwv6wmsKup8LjKnVeS/vvkW8OLL2m6e9HPsJ9zPbgK1Wdt42j1mAPYCsoPqmwTkM9x29MALSceb9+2H6vFC4ih4lYBrdmpgcvwk91QGjm1nZaNm+7b9njMgyshYs5l8a9OYwesN4qunUrAiYWAQuTCIZWVa4HAXM+22hyyFPg/qKzswcybP4GrR5Qw+axcGqoG+V9OkLXBxkG09RszylT9rUheVuDeoPkzAfZXaqCJGA28TWzalio1B7qMHfZB6p6CRaWlQFy+CNGsWkJN9IdEpIn/oT6RmmHWmLFg16LVrkUA6aHQ7tiVLfuz+p2LMmzswiC28ffjX++40xhtZiSy+AarFe5CdpeKhz1yoQThnKu8LUXwavGMb505gQfbQcz9HH//XSF2DiyqBA0hkiOrhc534ObHWl6Hlbc2rqED8oUPkvB6A2twktvjj1WKCTDz/AvV+UlnpqzZqGSoGKUeRBScs+DBKBds8h5Ror1QH7Zt+ksSckBPXLB84GRJHafOajOZei2vMRFfFJiG8cIbQ8NS3i9XUHObRQPatiMjWG6Qid+zQEppTJ+BUIewrPxYlJ2zjHBPRvnpMYqEH4XjsR0kqvwRtZvtW0k6bjxzDMpK67nuR9TpkrN4I2TB0sgMT8U0GK46IXBdcHPewDA0EbiZ9OjD1DQ6TyCojA+i9xSGr0XhiO5wAVsqaQYynHbvf59rHjvLcGkcRbCfw3hxt7utLVoWOUM3yvDYReuw2p2VK6Ss2QG8dfvDRCyNewhyCT+7OQcbgnYRdSNpAJQ2deOW+Eqy9avDrPvEEUNov3SmzUU73rEb3IoSLBCoUhJ5cjlC5WGawKNpBJ7VcEhG09OA888rzb5I5PXtE4HGxIYibye81RmM7hgMvhZyKH647MyR4f/vbheB1jdLExcX10NYkO5CeCympe1ot+2K03aUUAi2SkOnNo1tYx6BswRmsIkozHHg/XleK+z4++OYe770H/OEPg/9WN4C93YYeBpbzQQdQRFLqLKOft2Fbx4RmMPDs6MATw4C3fz/w+utDL8xlMiP1o8wRte/9f+AlUGce3fYBbcRCeexzKPB+sK4M9w4DXgoR2C99aeilaSJRe7+VnsImanOTH3gJFDZkNNNFEbr9N1AwKHgWojf/cfXIwCss1FbjcgbCxCFWIwy0B70uLkG5AiCrIOrhHN8y0uKAleRrcFdjsakV99w1tM3rAm/3bo19sh94222D/6bBcOEgqByXyCkTLwqJ0V9CAAZNyekuaoiqkX7BhIgpCf5Bt0jLsvnb29oGz7RH4AVJ2ow8YH78OOqJfXrLyzHVZhMdu2oQCUwkEPsEz+tsiaGwrPNpUYmTW/5PgAEAbRG88ZIqdcYAAAAASUVORK5CYII=') - - e_no_speak = ('No Speak', - b'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UmVhZHlxyWU8AAADJmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MkVCQkI3OUQ3NjZBMTFFQzgxMzFFRTI5NENENUMwNzEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MkVCQkI3OUU3NjZBMTFFQzgxMzFFRTI5NENENUMwNzEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDoyRUJCQjc5Qjc2NkExMUVDODEzMUVFMjk0Q0Q1QzA3MSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDoyRUJCQjc5Qzc2NkExMUVDODEzMUVFMjk0Q0Q1QzA3MSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PnkWjnUAACi0SURBVHja7F0HfFPX9f6epiXLtjywwTY22GwIM4wskkCa1Syyd5pB1j+0IUnTZqdNyGrS0CZNmjRtaPaehAwyCKSMQABj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') - - e_palm = ('Face Palm', - b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RjZERjVBOUI2Q0U4MTFFQkJGMjRDQ0NERjM5OEU2OTQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RjZERjVBOUM2Q0U4MTFFQkJGMjRDQ0NERjM5OEU2OTQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpGNkRGNUE5OTZDRTgxMUVCQkYyNENDQ0RGMzk4RTY5NCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpGNkRGNUE5QTZDRTgxMUVCQkYyNENDQ0RGMzk4RTY5NCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PvOvxIUAAC+ISURBVHja7H0HfBzVtf43s7ta9d4lS7JlufdugzEGG9NbsAkBQhIIJYQk5BEeKS/t5eX/SCEh1FACCSUEAsE004IhYNyxwU1yk1Ws3vu2mf859842aXe10q5EyMv9/ca71u7OzL3fPed8p9w7Cj4DbW0GMunlCjouURSs1HWY3Z+Z6V1GGpCWCsRY6IgB7Hb5mpoM1NYD1bVAX7//Oek8vXSe7fSWj/fp+MdbrejFZ6wp/+TAzaCX79Fgb6DBttAryiYBC+YA08qA0hIgJ4u/qVJP1EHd0eWha+JV0ySILW3A0Upg98fAhzuA/gEPoE66xgf09k06XiEw9/0bwNEDV0gvv6Dj83yPMatPR9cl12JxdgO+mrId02KdgLVAHmYSPcUU+oSubsDZQaLZTEcDHXXAAImloxG9vRqOnSAR3EbIbfYD9DgB+gK9fZ6llADV/w3g8MDx/dxEg3cnDV6i5ex1qLryJzDnLsUqUodT4wkv+kYqOjBZPyqOZHSN/oIaiWT/cTqO0XFUvG9pdWDXXuDZjdBr6+T40P2coPt5it4+SUCW/xvAwOAl0cvjdFyKCUV6xw/uVeqLLsDVpCJLYoP/LgvNmKIfRql+DLEYiOwmdDKefRVAD2nP3n3obm/D9o+AJ56DXt/gGatddDxMxzMEZte/ATRUJs3yN2iWz7BcfAm2fPEPmJuaisuzpMQNK0h01A24kG77BAtsL2OZbRNiXE30gY0OAtVFkqbbZHeVGO8PVSsdNDvUOMBEr6YEOkjUTTSXzPTqaDMk8zDa2jW89S7w9PNSzdL99tP9/pnO8ggBufX/LIAE3mQajDdpMCauOwMouvFzqM27HclpC+FCaNt2mHD5gGRgH3HHPs37d1axG7Rn8UXtTzhF3xLV+6X7FDbzj89ASKfRdtNxNx1/ITDt/2cAJPAmEnhbaFDy1l8IXHeVAiXvKiDlVDhgQbVShCNKGWqJ02jMNI3W7gCeapHADddYvX5F+wOu0f6IXDRE9f6Z1b71HvAoWccBKZXN1JcH6KP7CcjGf2kACbws6vBW6nDpVZcBX7yc/pi9nhy6NUO+a0cMjiuTBJhv9+biD00Kelwju56J5PkcfZMA83ztFZoejqj1hV2UTw4C9z0KvaqWcJQuyZ+YSROQFf9yABJ4cdTJ96mTCy86G7j5Wvpj+lnESD4X+oftf0d1yw6ig1fgSfUqHFRmjOr62WjCVdqTAsyZ+oGo9u1kPTGcJ8jH3OlxRv9Kx48JyIP/SgBSF3HVacvJS/8WcYgkAqLgFsMZD2R4aIo3P0sAbvb78x5lvgDyz+oVqEfeqO5lqb4dX9Uexue1Z5AQxUBMRyfwGNnJTW97gHzWALL8Mw0ggUdI4XcTi8jq/xyITcwEir9POi4+CHjktNc/BnTvCu6nk4J8S1mLP6hfwUb1IqFyR9qS0C2k8nrtIczT90atv9095BsRkC+/IWykRlrnIQPIxs8cgATeAurE9vg4mO67E0p+Lklc0XeAuElBwCM7VUcuV8/Hfn9mGh8XxDdsQzqeVr+Ax9Qv4yNlwajuc7G+Ezdov4+qVLJE3vOIjPgYcdif0p9/Q0A6PhMAEnixdON76Man/fA24NSl9MfMC4CM84ODV3svUb1yHCCl8wZpz0/IXDW1Ak6nDGIXFQIL5wCrVhDbLB16ik+UOXhc/RKeUK9Gi4iHj04qb9QexBz9k6jZyJ/+CnpltSA75TQeNxGI734WAPwNvXzrrNOB226md7HFhMB/Bo5jGuC11JTjrgchQlvDteIJdI1VwJrTiA+l+X/GLskr6vl4TPkyNqnnwOlNZoTdlutbhXpl/zIefRGPxzbyHH/2a2LYUv7up+M/Ccief0oACbxl9PJhThaU39NNx8cTaEXfIxALAxg00o8n78WxQ0dwx38DnYOCVbo5BrrJAsVph+Iaqn04Y7FwrgRzxRLAOsgcNpA3yLaSj2NK6Yj7koJOfFl7DF/T7keZfiSiceG0129/D7z9D3HfVSSNVxOI7/9TAUjgmenmdtPNzfkf4iqL57HLcA65DBcHlrzqX6O2shK30nc7u913qcKZng9nWh50i9V78/Z+mDubYKJDcdiGnI5srVCva0nqZ06V4HouRV1/RzkDv1dvwIvqxUJKR9rO0t/Ezdp9wq9UoY16jA4eBu4gi2izC5JDPced4WY/xgPAW+nlLnYZfvBtemfJACb+hK5sCao2b/0voLHZK3H2CTOhxSaEvI7a1wlzB4HZ3UKe9VAvPz9HArluNZneDP/PmsgzZFv5kHr9qKSyWK/CTdoDuFZ7lCxty6jGaYDm3w/vhL53n8DkVTq+EE6wXBlj8DJp1h+LtSLpsd9BEbYp/0ZiB/OHugq196C3RYJ3otr4M6lKW8kc6DFxIwiLkFPR3SokU+3tCKhiF5EWOPsMsmuLiQyZoieVVtgEc2WpZCY7mvaXF2Voju5zP0njuQRiTegI0xi20nj8L72cdvV6KEuY0ceTHsu6dCh4dQ9B6z6An/6S1Ik78KSqsBfNgj6M5A1FSBW/caVkw5WaIyaBKuyl0/OVugbgH1uBV94E2gnj7CyybclyNk9CJdbrzwk3IoukqVKZhHYlPaxLu4gcfazMw8PqV/Gaeh55o3ZM18vpr+HH/VjVz5gCvPM+sgnEKybF4c3j/aQkxlsCjSzDoYx0mEn6iEzQpYruIAeuxD/CQuChZ48IPz33ko+BJ7XpSkyL2v2o/d2kYhtg6gqsYmdNA85dS7NtuaytGSyVD6g3Cal0jXDOc76S1evXXPcjZwS++6a/k5P4oJDENpLE04OVeJjGUPruo5c5N3/F8NGSFhJ5OXMQJfwj0L0TW3YQj37Mh/bnTBISFM3G5MeVlCHIEKtkZrDMZD12kHDl+3jpdZJKcrpz6fLJSV6p3KA/i6/ofyDHvg/lyjRy78PTDH30vfeUVbjb9E0cVSajGNXIQ/2wv+PaH9YMH+4UcePLSRJfJklsGRcJNKSvoiAX6qN3s1ajeVLyY5raPqA0PSuC00xWbvoOCaER8GDg7PlTxsU3VWx9JJWNxGIb/VSsu82ZIaVy5VLiXj5SyaG659T1uE+9GVuV5SO+7kr9fXxL+y0u0jaKLEmo9jKp+XseFpJYSZK4hCSxZcwlkKTvLnqZf/01wOSJ9C6VnLKUZd4vtLwMtL0h0jA/ulOW/gn+YY2HvXCGP98fy2a2QCM1LaSSrs0g+rojPLk+2E6U8C05wQrygIR4mZqao+8TrPMi/SUBaLkyPewAQbVSjGfVy/En9YvkfJgwQz+IWNgCfncqaa9WcqeOHAXbk+U0tk+RJLrGDECSvhIa/0eJtivfuoFsj4k6VXCjLF3gRlKHlr+Jt38lHF9/x0s+BGmxxGDcG92wbk0QpMeVnCn+zz6mokvfzkZju78c+NtrwLFKqVpZxfI8y0MDgbiRHPsHyIVoFTnLDiU1vPgofe9NdR3uM92MViUD03EIKQE8hxRye+rJfDY2kgamaUcA/n3MAKQZ8kN6WXHtVTR7JrP0nUo9Xiw/7NxGd/G0Jyb4M5JTl+H/OnLJ7iWm41NvvlLJtpIZrI+trKmTkZN3PyCNQa52UYEkPXHoxyn6h/iGdg8WYTfaiLkeFz7l8NrETg7IVmUF7lW/jsPKFEzGMT/C09MPTCDoDh6E3tuHU2iM3yYQa6IOIFeW0ax8KiUJVo53mjniXHCDLBrq2U+k5RHAiFj8/Lc+qjM+hQAsxT9VY6lkdyQ1F1pSOsGgQ7X1A0aApKtHxmg3biKF0irVqyQ9Oqbqh0UQ/Ar9z0JFcuLZEUaKi7/LAfgHifF+qJ6CPL2eCNRx9JEG6Kc5lJ8HZdduEQQ/jUjN71mVmqIsfTfRy0WXXSjjkUheJm0f117W3St9PkgfjB1Wt+q0Fc2kqWTBP2vjaBAzWBeH8khCVceAh/Q4yRodPkZAEns9dESCmJ8r1WsGqdTz9NeEG5GGdhwiO9mtJId1TZbeJ8hGvqRehBS9A7ldh5CWqgt1Xl0NjiW1EoDbo8oWzsqke1Qw7ekHOSNAp574Y+nrVZOHrskIPkffv3wL0Nwqf+PMnABHVnF0hIZcA3NTFcxdzeK6TIpYurWENLgSUqNKjkw97TC119Nr25DPCkkaLz5Xhu5885ZMcpi93qV+G7uURSO6XpH9CL7U8r9YWfsk7vqlXaf5w/5hsSmK6pOMHW5fTvd1DtclJcwCEheQ0bhLlrYb7YVXZVLT7ZvZC6dFZWDV/i5Yq/bD1Ncpa/8YUKdDOPAmAtTcVg/V3idVIwfEI7wm20dXSpY4+FwquSTu67J63bFHRnp6ib0WTZCBdQ54z9b343rtYazV30YnUZYK8in1MOxkpykD7yVdhDezv4QpqU1K/659XMJQo0QRwMfp5ZqffRcQYbP8G6S7wOsQjMaZ9Ctv9Pp87O9Fw2HnAHbMycPGQhaa9QUTYUlOh729BfbWemiOQaWa5Jc6jVCbFpsYnQHQXMKnNLfXEYP1rxDneOtqmt5sWriUxLdVKhNxj3oLHlGvQ7coTh++JTrbseQL+TDZBz42RQm8BJqEj2dmwHLLdZyjpcnhIB1pq/L73vOvANt3u32+BDjyJkcOXmczgVchg14ETOqcFUiYPAc6qc7ECaVInDwL1vRs8Zmrv4cwdglJUQd6ZGiNVCALo8YB82BFVWHGYLW4JMle4xIlezV8Smarx6ukRB6okEvh8nKkEkhDB9bpbxh2sgP71VnoQehJZSdSWOo4BOXAvtyoAEjkhesBrzj/LIO8cGrI6W8bbCQE/+83Mm0i3YZS4TxHBF4XSV6djH4rJhPSl5xJbks26urq0NXVhc7OTgwMDBAJTkQiSWVS2WwBpoj49HYJIHmgGURzewMUzSnvSTVFrl5Zupm90oSR7FU29uf+/g8ZIIglTV5cKOL2Yl3HqfoW3KLdiyJUk2qdKnzDYC0tWUPc689FJ5RGEki6Euc/SFxlUkng73BNy6/v93ZwoHRhxCQipvagBIGYYcbStbBb4tDU1ER/CpwLjY2NRWJiojgYrP6Tx9FbdRjO7g4/9erIKISTjmiRHpZEc1udkPjBgXROsW24CLhwnazz8boUqgie/0L5DrarywKq0eXrMyL3Awm8VOrnQ8UToF5zefDvcWS9rd1gY1klpG5Gb3tY/VlrDgqbJyRv8RlwkEpubAwd7Xc6nejr6xOSaXM4EZOWhVSSytisfGh2G5yGVDIR4kMj10GIR0TiqAtnnqWR1Su7SypHeQwgmRewP7llp1y4mpzkDlLrmK4fwvqeRzGpfjNaLPmojZnsp0Yn7XwqcgBJfXKCb/15a4F5swJ/p+Io8ORfvTNcBKtHaW94Nlur90s/jGZO+sLVcJK9Gw68wc3hcBBD7BVgIiYWySVTkJBfDEdXG7SBPnEdTghrKZkR2kYFztYmeU7SFDoDmWbEXuka7igPlx1ydGfpQrk03BM2pr8nd1fh3M4nsar7JbSbs1FlnSYgnkLARgNAruGYdcM15LgGiYQ9txEoN+p/nCKykTHK2awReAfEDBYxwtnLoGbko6GhIQIBYefYJoBUCMj0slmC7Di728XgcqmGKzkrNIhMishdUW29Uu2aBge1dWg9PeQK90IneyiATEiBKy0Xemy8mCgcd2We8PF+WfbhVqe1LTJYwC3T2YCzuv6CNV3PoduUBrWjLTIASX3yuvVHiH1av3p1YJPBGQcuDXQvXRbkhSvLyEdj9TeSFlN/BKZeqYcTJ82AtXiaICy+Ni8mJgYZGRlIS0tDcnKysHsc0uPvuFyhUzdMeFgyM0unw9XnAyL5eC6WxMGUgQbd3FpLLPgQkaB6w9+sg4l8Ug4geIAkraP1Gr4w3YPW3yvOpFhjhSS6kjLpt00CRC7kYnIzezqNFSmZkwFKbNJczTij6wVgzx5EqOCxjMYliSvNgtl7Lsp12z7dEiuotm4bkMiOyF2Q1WfcrBm5SJgyH/X15OP5nCc9PR2FhYVISkqC1WoVB7/PzMzEhAkTUFRUJIC1WIKH7VitNpA6Tp17CmKzCw3C1AZLY6W/HSZpiz2+B5bmqiG5RJYo64mPPW6EwuKk+pXEwdVFNra7yyB1sTSxJ/sFO7hbXcOUn3JaK1IARYqdjW+wtnOP973LUJ1sD0bC8DiiYmk8LgfHGofU+SvFIDMpEX8jopGfny/AUUKcl4FjkBlIBpolVA1AUpjoNDU3I23hKlhSpF0QktXZ6HFfrJUfi5STe0KxC5O9+hKhGVhSWXLd9yzdxKHaxkXsVzeCDJzGchdvcS0sm5yuMKr6IwVwDY9XMPLCbYdPVbW7xkXr78dIigHMLd5Znkp2r72nT6g78RnN7oKCAsTFxY3oxlk6s7KyUFxcLCSUVa9v6yGb1dregfRFZ4hJI1X4MSGJMSfLJQMmUFJmL0fG8nVCWs0JyaIcRCmda0SIWkkKDdsRiM2SJLqlUIxPgjePyI5/V98YAmisdVhaMkFWdAVqvDLn+Akv+9Tik+WMY/2gh6dCGTgOUQk/LmeCcNQFczTAY8kbPPgjckloYFNSUoSKzcvL85sIfJ1um4OY7iqpMdjmtZ2Uv4uxImPF2UgonuIHekdHh3/xsdPhYaMBI3ADPjsQ+WRkOrq85CVY4/GNRALn845J00OUr5T7VJ6LmCOX/Nlshv0PD0DVJzidQOqpu1uSARMRIAYvlD0baYuPjxfnZPXKzj631tZW2GMSkDzdmz1g8DKXn42Y1Ew/t6SZ1K6JJe3YHiNcGO/1d/UQfqKbhPlMansYlYiRAiiqeaaXhQlgnPRQdXfNiRZeraRvjQoHqPtJ/bLUsB0rLR2bJDCr15ycHHENJkEMjDl/EmLzioXa5KiPOSnVzxVhV4YJlZXYJAy75sgr85qKUBrHDaAPGTKFUV7DvqM5gn6KOolpIQA8VhUIQKlSdKcz7Ci/b6+YuPDAXnjhhYJsVFdXY6waS3d2draQLo6tJs9airjcIiI2/n5sS0sL7HYiLSbSMDVyAS5HXdx9Fv0N5cIY6tV3sU5M7PABnvqGyCRwJqdJCvODf+FknQ8ORuDaDZwbyJE0Bo8HlMFj4pGQkIDxaAwk+5YWIjNxBZOGuB0MrvheS403XZU5wd8ZDsNk+NbeJA7TNWaqvLppVAAaDvz0CQVsi4IIjiYLlzyRPfIBffW9UKV6GAtwfHSJidTQ4sWLBYjc2A34NBtPKA6eC0JFal1vqPRIn+5DSHSXc9hwm3ix9/v4tKF/0toaGQstZQJTPCH4F7i62c2iPBlwX8A0HbrdNnyoy2cgNFu/h1y4JWO8pDBQY9voDiTEOLycn8OFfn1w2EPRYA/bdrtKXHsaO4wKrauLDMAS/ic3K/gXurp9OmAOzBS13uEXpArJdftJfd0eF8LdWLV9Go1VJ9tgLyWU+U8Oofm6EaIP9uAAKkbQ01f6MsNYDV5VFRmAojAgOys0Q/JKkdnD1vx9oL7Qs1PYTq9f5uhs86gsb2czPxUAW906zN1sfX599QfQFlUAeRgrTwil1jBaAAv4n6wQF+r33SE3WMkgxwTbW0WAN7iKMXmk0N7RLBzlfp+TczRlvBtnLxyDSZhR22PiNYk+zJnZZyjCphjaibMZ7pabG/r6nHzpkzVUm0cLoIiJJfpURPQOQBSgjrRx55wtDSFnqZuOOzpbxV0fO3bM8xkTGrPZjE+7cU7S7faIzLu7fwP9oflLjFS3nKT2SEdB6Gsd88bV3xwtgCluY+tubURrj9SS5NmGJVtDQSS242xphKuzPSDddscIOWtuJxCPHj3qFW6iwex0j2fj0N3gILidSJmSWWDEbms8hEQbDkBeC0J9dgPIpy3ID339w97d196ICEDf+HF3v2SdFTUBgrBu28cR+WAlChzY7emGo7FO5s587KXms9Czr/qIUKOcSnI3Dn2NZ+OMB0dohkhhziRv/La1VgAjUmeh7B+NB9e0uvvL0hcqtMt1pkekAvr4rVbUjxZAzS8CpHklj9+zJFp92L3a0+4J6pqSUoY5swZXRzucTXUigy1ZLJe2S8eov+YoXP29OHjQu3ccB6IVZXx3DUtNTR1yTSGF+TK8x+knvaczpK+rWKX65AItj382KfR1K4544qrPR8JCW93RAGGbAvmpZJsnlhg3qjlhqTssrqwmJkGNG76ckNUqExynIZHOjAmGMGvoqtiD2tpaEcIStph8w/EmM2x3Of84uNnTC3wyF7WhJdlg2GqvF8CystDX3eddaP1cJAAKN9K9vsERJNBw7jlejcmlEDH10naZ0jJEOUFYJMfpFBJpI7/EGSelt7/2GOztzdi9e7d35paO/+omlsLBqSwnqSClQKJgGehG0DQEl+PTGHAVt2q4ICyQxUXBr8fZh3Jp//a5dz0cLYDix5XVXrUZqLFpOu9cH2+ioxExQhJpBmdkhSWJvqp1gPe0NqL7nQd2CDvoZqQlJSUBs+tjbQvdYT0/0mW4FFzjYnI5gkhfrJjdXEfjbtOnBQ9NCtT2e+bD4x7zNMp756edYP8hT1QsaFuxHDh9lQ+InU2w1hwQdZGm9EyoSeHHMzXVDJtVkgeWQCY0O3fuFH4Zp4DGm8xIqbEKSfRtDt1rG02uwIEKNV5OXrMPgHPmhL7Wjh1CcNnJfCIiAEl8udijch8B2Ns3fEx65iIV1nyvryaLfvYK1WFKToWJpDHcAlp7TAoBKadp16Fd6OvswJYtcmPzGTNm4NNobAtNPqLD+2XB2N9G1RwB458qlxOS864Y6pMZfVmIpSI1NWKJNY/1SzT+zZFKILe/cmaIF2sOB+Df95kQk29CbInZk99k3W+t3CvK8dTYOJiz88KyizpNwYFYyUh51VEngcg5QfYNc3NzRdHSeDdW3YMJjZKcHhRANT5RiJKvw79gvn9p/RCVt8Pz9iG/c0Vw37xeWn/+Zf+KucGtsknFyTZ5GUumCfFTLDC7Y71kIywNxxBTcxAqs7bMbJhS04eVRqc5jo54D6EZaKzBtm3bRF5u1qxZn4oUDs6KKEZkRtUGMTwaK5XXZpBbxSur3G1xiPWeXEXy0V6BOVOYN6ICIIkxs5Fnq08CW0NsC7b3hL9VTslS8I2vA5N8/B2uu7Qe3y3K9tSERFhIGocjOP1xaSSN8vY7PtkKe18PNm/eLHzCTyNPaBrEPtwlguqg0hE1LgGKySzWEbrLLNj3CxVM2vWR/Cpput8N3sUwosrs0niwX3A97z67YIH/xnHCmNO9v/KRxU/FnrfAieIcXagMrkfiqDp/Lhhbd5usak4gJzkxGSpRdE8V2xAap0InW2hx9ouEqZMAVNJyRYqnjJypsSy1CNS46ts31cWAKs0yQ++wJMrJRiIkiBtrHmLj7m1MLrpw6A6K7sbL8Z5+WsTE2eu+5ni//4NFIgKQTtZAIKb19mIZuxKDjTCrzo+rvJfITtaxbq7TExctKZbUmUsvjKoEUUfptg16UhpJZBJhpUogB6ejTDHCxpjocPZ0irrMbjo9lwcykO7a0fFonCHhskKPpBGAalOVAWA8TTazDGLEJ8DSWiOzFuB7JX/57OBx4h27xPYi/CnvIfrmEHsahXv/L95t9v33AZ8kgWgt3f53Na9kaNqIO3DTDcD55/nEAHmGNlch9thusXxaJWm05OSJARhcD8yERje2be7Yt5UksRu7du0SBbvj2TjB6yeRPnNN2EGTKsKIbPs4zOZua88MDh5vCLH5XfE5U9XfBSRQkd447/NMgrGeLmJ/4inoLT6LMfoHuUCluVoQFgecsgK49ZtSIj1a0mETy6d5nYFwOVLSiK3mi1nsqdYj1dQfl+GJ2rTvfg9OktaKiopxs4WcqB4CIKt9g4wxgKbkNPF/S1OlJ19YVET9nR78vB+R7euRcf17aJzbAtreaHSAVGndpDjUkp6++PAR6LNnyTgtq9ATzbITVrJ3Z8wKXdzDdSBz5wKFBbLmw12xwNVaXJ0tlm+Rf6UkpQoywJLKq5zYwecQhdllE3UznFs0pecKB388GhcbDwZQhtK4dGxALF7Rswqh9nX5rZf4wueJ1AWJ7fNqriefEnOS9fLlNMZ9YwagAeJesoc2MgVryiugz5oJpc+p4rCR8EiN17GoNLxiXi4pWLqUg9TkwPKDNg1XitcFsn1kIPU4so2JKRJIAs+pm2B2DhBBcInEryk+SRQCj4f08eJSLQDRinHSBOolYmONE4tXRATKyBOy27BsWfDzbvkQKC8XeubnJH2bgrLfaHaGQPyAQIwhyTlt/wHoM6ZDOdQgL2ElIVk8Ofyda9kuTCgkIJdIEsoS6R4jAWS7se8LDQ5LpInIjtMSB3NvO7E7Hbamk4jNLoApNn5MAWxra/MvbvKVQJpMYF+PIy9EztxpI94z5uqr/TeWHez3PfW0mBucLvj8YOY5ZgAaIL5DIPYSATyrnEDMKjEp/U6FXAoFK6a6RrxvAEcnOMXCM5YB5DyuB0j3fp/M6Mi30lMyRFWYmcvbecUrOfhxhZOgmsdmGy9mnlxaGKxZ2GVrqxfuAqtPd9uwQZqJYO2V14DaWiF9/0HS92FI/3MsOkYgfkggHqSBvrij1mUqmqig26FiSp6GxNjRnZNt6pQpgYFUSFUxWzXTbOcSRvYjGVT2D+1tjYgvmCRckWg2LurlbIgeIo5oNhEGLbV+7g/7v6tPD37e2pPAxo1CA/GjYm6gsdTHHUADxINEbF6lLpzVVq2lZafqxB5VlGRH9jBoN5BLFstAAFcZum0kJ44ZOBPZHa5k4/9z6SL7iHF5JVHbNoSddgbPOcz6DpPKzrw3oMBVfFdfFTzmyROSmDyMBVgbSPpODBsBGkv7wI4+gfg4vZ3c1azPqD2q68TsldzcyMeSfUYOQS1fLnc+4jLNXh9TpPjEIBlAjVwS95LpSJq9txuNJ46L1bWswtkei21DeGcmdg844uJ2H9j2Gc48T7avXsfLAYKfe+t2kA8r3j5B4P02LK4wXo7u2gxcSaDdQ9okrYwk6IJzuaYzmmwQOFElB4ATn4FKMZOmzkdS2ZywT+joaoe9vUnkHnkS8DHsOgfI4l49NhF6fDJMhgRyXvSC84P/pp34zW/ulq4sPyDMN2X0TwGgASKXrN5Dx2U8UVetBE47Lfij5Ebb2P1jELl+5MhR/whcyqylSCiZFliFkf840FSLgYYa2FrqhI8ZrTaP/NvLNwRXnY/9ETCqJa8h8P4UNlvHp9AIyLUkjffSwE6Ji4N+1loZDI8ZA7LIOyNyJvudzd4C8LT5Kz3LxHjzu4GGavTVHoOtuS5gcpO3VZ5YTG5NvmSPvCaEVSFvB8IHO928/KG1XT6+oLJKbm7Ez0Rym0nWqnfcTlogwIaEW7YR83xZElAC74KR9O/TfAgyRz5vJCB/RGOWnkJ2bN1aYM7s0HUho20NjcBDDxn71dBFU2YuEeWJfTVHhOT5thwCaAWRpLkzgZnTSWqTRndNXgHwzgfA3UYK9swzgDWDH53RQCrpflFs10rjMJMAbBpzAGnwmQ2sY7NCB1vpd+jCnaM8FweTvkNjeit1IJ6A1M9YDYVVTrQlkssSHn1Mqtgh0Z90GtxVwOkrZGUYJ6mjVWp6y3elRLL0sRS6PRqeTA88yMvUxH8vojF8aaTnNo1iwK+ljnFa4xI6zuY4Hf3/NvL7lhLj1Oj1iO9zDcJgqjZ2/um3PE85jLng0CFYiIxwuk/hsFq09jHguCOH5ty+NwO0eL58ivYNXyL1OIFULj9EjT63ENVPiJJtZsC27pJqlpMkvCKONfXzf6P+y9Dobwm8343m3KYRAKcQOL+gt3cuWWhWf/WbJcp1l3dg2QI7khKJLbdgMtH49aT+bpkYiyz67mECpmMEQPbR8bYBpJ1Y5NzDhxG7bRt0UkUKF35FYy3nW29L1cb7dP7yJ9Sv1ZxXJGAJtO4+n0WpNMAZUUpm8OauXHrC1Xv8QMppxKE++JCOD8THHGm5kvqujRmAbK/4cQL09vqrrizCrQ+8ocTnLINacB0yixdiwcRduOTsXoVtht2J2JqT4omd3yQQLyZACug1l448OpLpUDnoHUxKDSA30+/42UutxNBmV1Ujaes2GaXgSgveY3O06o0LY9vapFSzK1NZDwwEiDRSP5CVGvluk8JnpWtxBR9v9spOOtddPf+CXN/Hw0vS1zHacythgBdPnXiBBnLdt2+bjbO/8Rz1+sdEt54x7i5XPtiDn/Hu6kEz3coBUgs7SWW89570x4JEmzje0GQcXF/Dj6rmkrljg65PBBtf5IWe7p1v00kFrTwFmD3bf4VUOI2j/K+8Kt/fSRKohagEm5hH10qKjhTyQ7XufdRQqSZBWmw0LqdSf3dHcl7TcASDwHudH3/23TsmK2uv/SVwiIxF5z984ko9QB9vOG7s+UWKoGdArovglBCXiTADTJo0A7HpObAkJosMgWq2WGkKpkNzTaDuzDNI0TdIOs+ng21pBR1cpPGgHhOr2CYthMaPxaHJYO/sQ3m5ji1bpTTFxnGZe3hSyZmArcau+fxUz6ycUKEwOm+U9kRn9b9xk1c9M3cg8N6J9LzKMOC9TRdbeMc3zcrqiy8EWjbyktNhT8qblFY3yRvlByz+gnDPmHcK6c+ZgSMevV0YaKlHb+1x9Dd6FoRw+J5VzBR7fhlcKd6R5pwaV7BxblDxkcrlS6VUpgxju371a9LNbXKPt2uuCaxCRfiLpHPOoNVCvBVyjTKBVMYU1Cn5qEeeeG1EDmywiuch8cOw+iBVAz/KnHcV5D2x1dtvhlOuDdtO4C2LxsQwBwOPyAg/YGnBd78JZdUKMgjNL4R90swUuc8lEwL3+hNrepCpTmJjSUwRR1LJNFFd1n38ILpPVCS7bP0CCn42Lj+uXOx2yM994A1/0gvEwWkaBrK9rRmvvqbjVZrls2ieLFpIWmBiYFeEg+EshbyDfKwlOIAdWjJedy3CPstC7FXmYZ8yWzzcagCjo6cXnnKKG8CoPdnSHMjmucH74W1Qli8a+Um7DDbXRMzunXdpFhZPgTUtvM0IzPGJSJu1BKkzFqHvZCW6Kg9ioLkeMX2dcp1gao7YxsO9EwRvoGePT5K73jqJeug4sH8/5tLBJRr63LlQeM0B+3Ymg5AwlWcA2T63NPM1Db9MTcDOhDOxK2E19sSvREXcfCFx0Wr9U/jZwSJKVsbjTFLYF1UADfA2EWFZSOBhNOBxO9ks1eeLG3l/gxikzR65tuD8XcKEUnFwULmLpLKn6jCUlhqYW2rF1pX8LCN+NfV0uHc5eo4G5QvUD97v8Upy2K/Yvh2FdIi1B1y0zUVTXAnnbvubcnB0waV4J/lSAu00OJSxe/xdZ85UpHhNF9v3T6JmA6nTvNHeSwTeubffAqw5bXQnbGyXjjCXgj9HhDVr0elILI7OEzlFhU/NUQGmvUOWv3Hejz1+UfBERMi3dpL6xOJDfBWfJ817EU2qAoMFikgLxynjv34TNq65f1zCh0X2o5i6wbOC8xK61xcjDhL4mKIHGTx+8spowWNbwraPV+6+9JKC+KzcqIEn7tFsRtLEaSg481Lkr75YnJsLew3wmNt9iUBb6XHaW6HR8T4dNxN4vMSXN+j7mebCbneQ2bln77jFfxstfltbFUVlTIyZ+iN6+fFVl5HDdfkopYOGr7xabjXCWeWKwybknXmZICdj2TgQ3U2qtbvqCBydnqLUA5Bpq8cIPHsQovY/9PI9V2wC3n2mK6q2LlQ7/ZpsWOSiFq42+37EEkgd+W8G7wyat1dviCBQ3CzB+2S/KAVH6swlYw6e6ECMFSlls5F92vmwLF4Ha9k83jyH/ZUH6TjGsVsOAwb4qViwZRroReHAkXGTQmu2h4BGZYspzvr/gJ+hftvXRh+eaiWVyREY3l7rb39TEJeZQz5f+Mu8XDS+R5GO11BGHG0uGYZpOImRhUB4rXpicgrsydlQ5p0B66wV/BwItnm8DG4jgTjYO/RsF1DYsX/cALRkeVbzRqVo1ZyUCPzgP0IvLgzVeIemqkaZVeb4nsOpIm/h6rBmQxviUE4TkcEb8CHE/H4TgXkpDtEn/SPINqSICmneBstuTYQ6d5Wi1h+Ho/YIJ0m3Eojn+RQK8X5HbDwTUhrJIcyNPljswJfpRzBH/0QeRDpfbD0IY1fRqORYzPys2/TU0f3YRn7U0ZPS/n24TZYEZC1aKcJlwZqTbA0DVkHANSJ4ekED19Xl4PThC7N8YgKK2PzOvQmQpunQcibCmpwO28HtvP56J4HIebcPeZ0dvWevek4MMVvMHf0gcrRlin4Y0/Ry+UrTcqpeIQ6OwPi2TV6LHJVklXnpgtH9kB113tCHXzlL8NomIHHCpJCsswcxeBlTqLvWsK5xjIBehlrqqTPs++JNB3hRi3sXXZFZiEuBdf5q2D5+L5NQ3UzAfYUA5OwKZ+PmOI8cDUHTNaQ5m1FkqiMhbUCBfhLFehVKaGKV6CfEQ4rz9bqw7y8+LsoAjor56RI8lsDuXmadCmISEpAxP7T/sQv5ArxCdNHA6KhGyrC2kVXsPBo4zmZzCSHvY8AZdd7X4JMgbjCvV+dyd9+6TbtqQcyCNXDs+8Ci2/qeJBCnGgBC27kDrzfPF/u9SdBcSHR1IsnVgQRN/nFu6dAFrKNytbzVAN2fCoAMHqtNZpycefjr8/y8BAV5q9dBtcQMa/MS4MC5kKzvGcwiKENL40Fk4fazGnDJJf65uXnzgM2b6RzPBFalvBHs4CeaOejeTXNWKvqRj3RXR/N/0Z8+EtqEOlPWuxftA6E1TjQA9HkWhCsaAI7I+XHvg9ZtRPA2vS53zmPJi0kZfufcTPQRJTGT8kklQ55MDGJ4O85qd3dNYsDE6mriSitWBP4dP8DDd3tmbx906JMXKJYCsbOTx4D4aNygfY9G89m80D6uAHKGmnci7DFuYNsOqcZSps4LO9oyDS2CnLyJUsEy+dFN8SSRrCKzEfxBQU+W56EpSK3W+vX8wI7An/GWI6YAJW68nsGZWwqLzw70wwHodEUHwP4BH4U0XgByduFQlXdHQnbWeQFGQsFEpM9aEvbFGCSWQn46ZTE6sJwIymTqRwUy0BSCkdboyXhva2D9xeCtWRPcyQ21b4wzvRDjKYHM1ju812kdcwDZzp1o8LJNEaM6CPyZ7E58Tj6ylpw54gueStRlCbnpdvKSthKdYVehPwxVerwx+HdYjQZzO3n/lthgW8CbvTa7t3fsJbCzy6+8pDEaAAYlMZxRbx5UarN9p0wRWZOSkb387BEt2eog1syE5AhJm22E1YxmUrzT8oMvl+ZNkjjHd+JEcHsYcMcK1ViIomliJ8DBT0aIduvwr5xtHjMAB4PHbPz1N6XNM5Oflbv6UrFZTVjOPoG1GROHdRmChsjIUm5IP441q0OPLG8cFAzAUGvl+VlIugEgs8xgW2e6oiCB9U2D3NyxAJDTQW7w2OBWHAbeflsu3zJZ45C/5jKo5vCTnlvEU9FHDl4G2crZ5mZcsbANGy7Vhq0JDbVVf6j9YtzPNBoOwGgIpvdJNtIqRB3AegKpoc1rcB9+RK6EZSKXUDhJJGfDlTx3OIxdhrADvSRtTGrW5jXhglMHhOMebjFvsLWW/FAqLchziyykMu3Gbkl9/aH3fEN0Aex6qxUtUQWwiaSuzocX7f1EgmdJSkXeqguE9I3YaSWO5AyD6KZiAMus9diwsB2rVup++6iF2yoqRi59SnerX4RkrPeLrfUCGLX8lQCQywBrfPQz13G++KLsUO6p544KPLf94sMegrQUoAt3n3MU552tD/u8oGDt3XeJHR8YOYCOmiNuhzqGATSNMYA+z3vYEzUA27plOsjd6miWPPSwNNppM5eJKrFIWg75fjUInp34/rJKfO7ikVsYxoWLlXiLr5qakds/C+lLu9w5gn9dym5EKAAjVa9cVt/TOwYAnmgYCh7bk7iCMiRPmRPxBQrRGRRAjouuWOAc0fmYafIWVCx1w23EFMr+Kd6d4lkMS3nlUKgUZqTq9bA/5/woWgCqbr/HA56DOhKbhKzFq6NygTIiJWoQDmenT3rDeNQ276PDgetnn5VLwy68UPp9w4at+oMng521IoXEGQFhPW32sSUxPgAy7d0XVRvoXvjI4HHIKH8UEZZgjXN508lnPYChu7s7yDa+siMRK1YEfwzdpk0y28/rLHxdhdNPp0E5PJyaDaw+zYSUo0vQ7dfcDjWz0FALvLQIQ2n7Dnne7iIG2hut8f3/AgwAtFuE+1OM1gUAAAAASUVORK5CYII=') - - e_ponder = ('Ponder', - b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RTU4NjgxMkY2RENEMTFFQkJFODNCNEM1OENCQTU5ODEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RTU4NjgxMzA2RENEMTFFQkJFODNCNEM1OENCQTU5ODEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpFNTg2ODEyRDZEQ0QxMUVCQkU4M0I0QzU4Q0JBNTk4MSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpFNTg2ODEyRTZEQ0QxMUVCQkU4M0I0QzU4Q0JBNTk4MSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PmF7/wUAACncSURBVHja7H0HfFzF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') - - e_pray = ('Pray', - b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAKQ2lDQ1BJQ0MgcHJvZmlsZQAAeNqdU3dYk/cWPt/3ZQ9WQtjwsZdsgQAiI6wIyBBZohCSAGGEEBJAxYWIClYUFRGcSFXEgtUKSJ2I4qAouGdBiohai1VcOO4f3Ke1fXrv7e371/u855zn/M55zw+AERImkeaiagA5UoU8Otgfj09IxMm9gAIVSOAEIBDmy8JnBcUAAPADeXh+dLA//AGvbwACAHDVLiQSx+H/g7pQJlcAIJEA4CIS5wsBkFIAyC5UyBQAyBgAsFOzZAoAlAAAbHl8QiIAqg0A7PRJPgUA2KmT3BcA2KIcqQgAjQEAmShHJAJAuwBgVYFSLALAwgCgrEAiLgTArgGAWbYyRwKAvQUAdo5YkA9AYACAmUIszAAgOAIAQx4TzQMgTAOgMNK/4KlfcIW4SAEAwMuVzZdL0jMUuJXQGnfy8ODiIeLCbLFCYRcpEGYJ5CKcl5sjE0jnA0zODAAAGvnRwf44P5Dn5uTh5mbnbO/0xaL+a/BvIj4h8d/+vIwCBAAQTs/v2l/l5dYDcMcBsHW/a6lbANpWAGjf+V0z2wmgWgrQevmLeTj8QB6eoVDIPB0cCgsL7SViob0w44s+/zPhb+CLfvb8QB7+23rwAHGaQJmtwKOD/XFhbnauUo7nywRCMW735yP+x4V//Y4p0eI0sVwsFYrxWIm4UCJNx3m5UpFEIcmV4hLpfzLxH5b9CZN3DQCshk/ATrYHtctswH7uAQKLDljSdgBAfvMtjBoLkQAQZzQyefcAAJO/+Y9AKwEAzZek4wAAvOgYXKiUF0zGCAAARKCBKrBBBwzBFKzADpzBHbzAFwJhBkRADCTAPBBCBuSAHAqhGJZBGVTAOtgEtbADGqARmuEQtMExOA3n4BJcgetwFwZgGJ7CGLyGCQRByAgTYSE6iBFijtgizggXmY4EImFINJKApCDpiBRRIsXIcqQCqUJqkV1II/ItchQ5jVxA+pDbyCAyivyKvEcxlIGyUQPUAnVAuagfGorGoHPRdDQPXYCWomvRGrQePYC2oqfRS+h1dAB9io5jgNExDmaM2WFcjIdFYIlYGibHFmPlWDVWjzVjHVg3dhUbwJ5h7wgkAouAE+wIXoQQwmyCkJBHWExYQ6gl7CO0EroIVwmDhDHCJyKTqE+0JXoS+cR4YjqxkFhGrCbuIR4hniVeJw4TX5NIJA7JkuROCiElkDJJC0lrSNtILaRTpD7SEGmcTCbrkG3J3uQIsoCsIJeRt5APkE+S+8nD5LcUOsWI4kwJoiRSpJQSSjVlP+UEpZ8yQpmgqlHNqZ7UCKqIOp9aSW2gdlAvU4epEzR1miXNmxZDy6Qto9XQmmlnafdoL+l0ugndgx5Fl9CX0mvoB+nn6YP0dwwNhg2Dx0hiKBlrGXsZpxi3GS+ZTKYF05eZyFQw1zIbmWeYD5hvVVgq9ip8FZHKEpU6lVaVfpXnqlRVc1U/1XmqC1SrVQ+rXlZ9pkZVs1DjqQnUFqvVqR1Vu6k2rs5Sd1KPUM9RX6O+X/2C+mMNsoaFRqCGSKNUY7fGGY0hFsYyZfFYQtZyVgPrLGuYTWJbsvnsTHYF+xt2L3tMU0NzqmasZpFmneZxzQEOxrHg8DnZnErOIc4NznstAy0/LbHWaq1mrX6tN9p62r7aYu1y7Rbt69rvdXCdQJ0snfU6bTr3dQm6NrpRuoW623XP6j7TY+t56Qn1yvUO6d3RR/Vt9KP1F+rv1u/RHzcwNAg2kBlsMThj8MyQY+hrmGm40fCE4agRy2i6kcRoo9FJoye4Ju6HZ+M1eBc+ZqxvHGKsNN5l3Gs8YWJpMtukxKTF5L4pzZRrmma60bTTdMzMyCzcrNisyeyOOdWca55hvtm82/yNhaVFnMVKizaLx5balnzLBZZNlvesmFY+VnlW9VbXrEnWXOss623WV2xQG1ebDJs6m8u2qK2brcR2m23fFOIUjynSKfVTbtox7PzsCuya7AbtOfZh9iX2bfbPHcwcEh3WO3Q7fHJ0dcx2bHC866ThNMOpxKnD6VdnG2ehc53zNRemS5DLEpd2lxdTbaeKp26fesuV5RruutK10/Wjm7ub3K3ZbdTdzD3Ffav7TS6bG8ldwz3vQfTw91jicczjnaebp8LzkOcvXnZeWV77vR5Ps5wmntYwbcjbxFvgvct7YDo+PWX6zukDPsY+Ap96n4e+pr4i3z2+I37Wfpl+B/ye+zv6y/2P+L/hefIW8U4FYAHBAeUBvYEagbMDawMfBJkEpQc1BY0FuwYvDD4VQgwJDVkfcpNvwBfyG/ljM9xnLJrRFcoInRVaG/owzCZMHtYRjobPCN8Qfm+m+UzpzLYIiOBHbIi4H2kZmRf5fRQpKjKqLupRtFN0cXT3LNas5Fn7Z72O8Y+pjLk722q2cnZnrGpsUmxj7Ju4gLiquIF4h/hF8ZcSdBMkCe2J5MTYxD2J43MC52yaM5zkmlSWdGOu5dyiuRfm6c7Lnnc8WTVZkHw4hZgSl7I/5YMgQlAvGE/lp25NHRPyhJuFT0W+oo2iUbG3uEo8kuadVpX2ON07fUP6aIZPRnXGMwlPUit5kRmSuSPzTVZE1t6sz9lx2S05lJyUnKNSDWmWtCvXMLcot09mKyuTDeR55m3KG5OHyvfkI/lz89sVbIVM0aO0Uq5QDhZML6greFsYW3i4SL1IWtQz32b+6vkjC4IWfL2QsFC4sLPYuHhZ8eAiv0W7FiOLUxd3LjFdUrpkeGnw0n3LaMuylv1Q4lhSVfJqedzyjlKD0qWlQyuCVzSVqZTJy26u9Fq5YxVhlWRV72qX1VtWfyoXlV+scKyorviwRrjm4ldOX9V89Xlt2treSrfK7etI66Trbqz3Wb+vSr1qQdXQhvANrRvxjeUbX21K3nShemr1js20zcrNAzVhNe1bzLas2/KhNqP2ep1/XctW/a2rt77ZJtrWv913e/MOgx0VO97vlOy8tSt4V2u9RX31btLugt2PGmIbur/mft24R3dPxZ6Pe6V7B/ZF7+tqdG9s3K+/v7IJbVI2jR5IOnDlm4Bv2pvtmne1cFoqDsJB5cEn36Z8e+NQ6KHOw9zDzd+Zf7f1COtIeSvSOr91rC2jbaA9ob3v6IyjnR1eHUe+t/9+7zHjY3XHNY9XnqCdKD3x+eSCk+OnZKeenU4/PdSZ3Hn3TPyZa11RXb1nQ8+ePxd07ky3X/fJ897nj13wvHD0Ivdi2yW3S609rj1HfnD94UivW2/rZffL7Vc8rnT0Tes70e/Tf/pqwNVz1/jXLl2feb3vxuwbt24m3Ry4Jbr1+Hb27Rd3Cu5M3F16j3iv/L7a/eoH+g/qf7T+sWXAbeD4YMBgz8NZD+8OCYee/pT/04fh0kfMR9UjRiONj50fHxsNGr3yZM6T4aeypxPPyn5W/3nrc6vn3/3i+0vPWPzY8Av5i8+/rnmp83Lvq6mvOscjxx+8znk98ab8rc7bfe+477rfx70fmSj8QP5Q89H6Y8en0E/3Pud8/vwv94Tz+4A5JREAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAADJmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NkYzODVGRUY3NjZBMTFFQ0IwRDQ4MUREQUY4Q0EwMEIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NkYzODVGRjA3NjZBMTFFQ0IwRDQ4MUREQUY4Q0EwMEIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo2RjM4NUZFRDc2NkExMUVDQjBENDgxRERBRjhDQTAwQiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo2RjM4NUZFRTc2NkExMUVDQjBENDgxRERBRjhDQTAwQiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PnTHOpwAAChaSURBVHja7F0HeBzVtf5ntmi1q16s5l6w5d6xcQzGxhgwmNj0FkjyyCPkkYTA4yWBEMILSQiEkgCPkLw8SCAESOiYYjAG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') - - e_relief = ('Relief', - b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6M0UyNDM4M0Q3NkRGMTFFQkFCN0FEN0FBQkJCNDI0RDQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6M0UyNDM4M0U3NkRGMTFFQkFCN0FEN0FBQkJCNDI0RDQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDozRTI0MzgzQjc2REYxMUVCQUI3QUQ3QUFCQkI0MjRENCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDozRTI0MzgzQzc2REYxMUVCQUI3QUQ3QUFCQkI0MjRENCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PkcqXg4AACTLSURBVHja7H0HeFzV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') - - e_smile = ('Smile', - b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QURGRTRDNDE3OTk2MTFFQjg5OTlFM0FGNERCNDQ2MDQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QURGRTRDNDI3OTk2MTFFQjg5OTlFM0FGNERCNDQ2MDQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpBREZFNEMzRjc5OTYxMUVCODk5OUUzQUY0REI0NDYwNCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpBREZFNEM0MDc5OTYxMUVCODk5OUUzQUY0REI0NDYwNCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PtdWIMkAACF7SURBVHja7F0JmFxV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') - - e_stare = ('Stare', - b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RDU2RENDRDY3NkRGMTFFQkFDMkZGNEIwRDA4NDUwMEEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RDU2RENDRDc3NkRGMTFFQkFDMkZGNEIwRDA4NDUwMEEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpENTZEQ0NENDc2REYxMUVCQUMyRkY0QjBEMDg0NTAwQSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpENTZEQ0NENTc2REYxMUVCQUMyRkY0QjBEMDg0NTAwQSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PjonYg0AACDcSURBVHja7F0JeFvVsZ57tVqWLFve7cTZ9z2EhCUhJCZsgUAppQVK6Sttacqjr9v3KC1tXxce5fV9bSmU0kehLZRSoA1QQlhSwk421iSELCSxiR3viyRLstb7Zs65kq5s3avNcizT833HV5bucu78Z+bMzJk5R5AkCf5VCrfo0z1REIQx/zLryqEIDyb5XwNWM1a34hTn1h4Y8z02E6YS0j35ZACIgFAHmy7XyVgbsNZjrcRahbUUm1WGr2DFz2L6nRF8BCxe58RjN9YOrJ1YP8LajLUJ634Eu/dfAKYPlg4PS7CuwHoaPo4+z8LmDZMS1mKAmiqQqipAKHcA2Ir59yU2RFHk1Wrl3wWDAD4f/+zBYzCANQzQ2wfQhdzY0QXQ0wtCKJQU6G58/h78uAvrTqxvIKid/wIwDhpx0qVYz8fbN2JT7DLhYPoUgOVLAWZOBaitAXCUAhShQNQbBPwdMWUVMZeQ8pHBnNsSiQD4EVz3AAKLPNl0HGDfAYDtbwJ4vQmgvoftfB4/PoX1tXyI5DENIIJmxMMVWD+LtzwHH68z4GjVuArgrNM5cPYSwgf/mFBamur40ViLo1o5gA5Za/AYwMB7WPcCBNryLtICCGwb8t07yItP/xOk5uMgyGC2YPsfwY/3IpAHxzWACFwFHm7A29yAj6y0oLrxaeS9NSsBqpEPBSPKQsscrLOR1aZxsJTFdxTZAyWZ+x2AUP9JVTL8fuROhOuvm0B6732IEuZZrL9EIJ8fVwAicBY8fAMvvwkfZSuzg3TJBSCctwagvKYaB7BTccDC4c48IUnXxwHKjUOPE2uwE8ZaIbH75rsoSxGyXW8T4dnXL2G9CYHcVfAAInjn4mX34yPqkcukqy8H4ZzVetA7lqOcXMk5bVjrkSoeFI39L+NxP31REPZYcwvAA4/hoLg9BuR9WL+JQLoKDkAEjvTCX2H9osmEwH0ShMs2GMFYuRagDKvenqQ7o4rY/woHLthTkEZ1D0K1HTlyyzMAH37IxshWJO+1COILBQMggjcZT92Mt503dybAf35NgLqZZwJUbEgOXJiAw/frxRrxFrxn5CBqr258jV2ovT61GaRwiImQ7yKIt495ABG8BXjaC6SkXHEJwL9dWwW6+mtRVE5P0sow57aezQiiJ+W93WCDMDMV4yUIBvAIxVkRWod3s0nuYd8XgwfvGswawAEfB5FKJw7hf3oApN5epuj8BuuN6ZgdJwVABG8unvJq2GRxrP36Cjhz7SlQVX0ehEULBNByIGITAPS5HdW4rR0n4GjABINgBh8UseqXvWD9QinXYfBcH/OOjX4RkM4l8vBlplZK3Nak7wh8OzhZq02SH0qhH1vuZ//T74F+PGfQBdaIE0SPC3ZvagbXThrP4W4E8IYxByCCV4M/v4ng1ff+djNMnr4Gzi9Lfu4/0QLYhENc+GPkQ9dLQWi8/3KIPPUP+vd7COJ/jxkAZRfYi3jCKs9dj8CERZ+CxtLk9/gLipSXnfCxLCZU0s6+bbUU2b2b/r0AQXxuJAAUR6Bt38G6SvzmTRCcpQ7epu6PL3jM+BeL4K1vbxIi5ZWknT6IHb98JO6bE4DYiGnYmB/qliyWdqz+CVxZmfy8IziwP98PH/vSbZoAvT+4WyAlD//9nxEZq3MRoQjg4/jDpS0P7IC5U5bDuSrcdxtqZU3+THpVBHVOriHaJSdTKGKaI7iTiyhZidAcW/BOTrAn/Y1ptBDXaH0CV6roey9zJo1cOeeei0B49ml6qVNQlL6TiwjV58B9i/BwqfXCc8BQUgpXlLSDFUJMKzMy/TGANw+Bc+AY3OzdiiTw4u8DUCK52GfS7EhjI7CKJa66pwPCySpK8N0CN2kIWHrTftRD6bNXsOAbWvGtStj/R/vwf6EE3LpSXsVSGMBj72Ubofy5LdgvpR/g7T6Rk4KUw7Vfpz/fP2UrLCkmzfhTaIgnkxu3wdpIU8GLP5ICZC5QKZX61VBONOpd3C5MVu6bxrw1lyAjTEEuPDaqAOJDHShRr2yoB1iygOTcaclP9B4EGBwOHk2y9vbzidYwgj6AdnwY7fpBNLUCQV59g/w7j2zjs+8D/DNNvg4GEu9J3/n9qYYBAMsQaSjSdwpT0ypLUYMRwGjgc5A61LOtFn40m/n3RiP/ja4ttatongZ1AM84gwFI49JXsN402hx4NYpp08Xn4SdjDbZ0YvKz+uIuQCf2xn+g4vzaDoBjH40v5YRApI68fh3AssWJAKqVmTOw36PO4HLCdcgQ5GoLjyaAV1BvpLk8sC1JfkYQ7YaBPezj1pcA7v4DcpMXxmXxIpe9votXAvDbN/AIApNRw5WH+v+ypQAvbGPmxNlYXxgVAMnrgoczqcfZKO6kaHbyE52vs0HhwccAHnx0yFBhMEPEhN1WoAAWHZNtEjuKrEpi9Mh/Y+fIMlASFf5QUb35/B4CCJGw+owUTV1Jkajqx8+VP5OvVqAJP/qM3wvsGIqfJ/HfhFAAxEFP7D40P/gf3wX43x+h2LVp03LOHAYglctHDUAs64mUKyn0SDCoO6qdb8C21xLBC1sdEKqahOAVjxp3jIrHDsHT93eCvqsJhHAIKFDq+z8DuONW7cvqagHKHAD9fbAB/904Wob8GvpzChkR5knJucDzPgw4++E39ymUjIqJEJg4d1TBGzF8/IMQ6mzjtasdQj2dEHb2QWTQxzkUpUWorAb8UxajdOEO+SYc5zdt5kqSllI1exa7RR1KtumjAiA+dC3FsFAF82QV8fkqPPMCj/DinFcGwcpJhWtCmMwg2uwgofosoSosobocGXBDuKeLgUoAR4eGQH18SHl8C0CqSbgpcRKenXcAyWbB3lK7cJ78hTkJKCEncuA+2Pqy4quqyQWvqIhFFhCTDGoS2i/EkREv762RIjTybdzN6XKjLXhI+74T4wr8qtHgwKX0Z3aU2Sncb2hx7YATbREmQtgLmSwFKTaTao4lpdwYTDLQhvt7kTu5IRq2x53Ce/dp35NsSFsJk2zLRgNAZjNQ7CbTGA3VSQF8ZYdCcSmpHD/2AlJZZy1R1ZZoXIwqa1HNmQBMFvWtLA2cC2ejhDPnG8BFNPBOIcmprxiuwPiPYz0B23crAawYVzafWGxNzoWEIY2PxIXYuWncp0IepaMpHGX1dUyRISzm5RVABG9WFeJhJkXLmAQY505mrB84LL+Q0Yy1aFwBSEQQLepDQsTnjXOhXChCTatUxkk5M28AInvTuZPrauQvhkZOkyHr3gV79sfiIiFsKR2XnhexKDWAkeL4u394RPt+9nj4ybR8cuAEBMYQA1A/BEDvAaaBvrNX8TLF4xNAwWBgNWkJh5kYlfRGkEzcc97enpggk0yRkcvUvAJIf6qjOol+iErtfpMd9ryvBNAO47WQbajKhbJdGLbYY565Y03q9yKXpE4fp3G+AKxJ6C26kkTX2cC7bDqn6bhi/NMZxi2AogaAZOhzmzBOo5aWFGKUmxK1+QSQMmKZl50DaE0Un2EPHGniCR+s8WYrjOciGE3qAAb9jBCSOT5WtrZq30+ma3U+AayI9pRhALp4Ik6U+7gBXzyuAaQ0YEGvU7UJpVAQIkZ5xgVLR4rkKhsfkcrzCSCDrrh4CIA0xULJlliaFQAqe9+45UKDUYMLA0wmRmRFxuXiEQdqhSaFyRaUE4PSLplMJ7GWmKOSQyfHJnj388wikvNtI8CB+NK9s06HziXngmvKYgjYykHn94L1xGEo3/ciVL/1LP7vyQsgNNfYvbARuhauBXfDfAiiEqb3usDW8gFU7NkGVe9uBSGsyJvQ0xjvUzXqCQrWkQe5n5RStyeqqCmmuEQmw9mTDwCtcQAVPnb3W7GPMTFBE68avVOt+O1VcPAzPwTX5IWJmjn2YueURaweX/t5mPG328Bx4I0RBc9TM40921s9JeH7kKUE+mauYPX4mmtg1iM/BtvxD/hrqnhkOAdyoCMGUywlp69PHUCjMYHO3flypUGxhQM0VHxS6ZQfK+lNkHoiJbEMOurgva/eMwy8oSWItuX+z90GXYvPHTHw3BPnwJ6v/GYYeMPaWD4B9n7pTnBOXSoDqBEREOYOUJpiipZ+jeDm4rjDSpfXMZBjJ19GmbSy+KQVHgb9UQAzMx8iaPQSKIF0Hd+oGBy6/GYYmDAnZ/B4h7gduTw9kU8c9cE1t4K/tJqvZ6J6Ig+5IIM+xuXpxQTZ8gXg8HMV4tOlCJjO1P5rX3Ep9v7MnBAS9v4jG76eM4DN674IQWtZRteE0ESi6zQBjFrwClp48jB0Z5kbIXDx6dmXFEDQpT+0UvBRy+qrshR9c2PiLFvu61i2PqtrSYQHymrT6GhxiejznlwAmQSPrnrEjPeIL0FiKEFJtwxMmMs0zWxLz9wzs762b9ZpjJOz01hF6J23KjUHCrqkNBpafHETw5kvAFnMXTjaiIG3E370+hLHqHSLa9L8HBWQeSflWtb2Bu22S6BQ+GQ9QQvrqITOF4DuhJ4iB+3mrEQo5s2yKYEcJowDNkeObS+DkSo+fyKd82EHMh5j3gQJbZxw4kIAJmN2DZdyXcJLyD7FMRNRr2b4Z0RsDWr74yJ0MF8cyJZejIYKDi0J02NRYR9OHe5vGOjLiYgGd3fW1xrdvTk+uyeVUyke+U3nawBICT60DObWnnwDqKIKFykiJwTZiI0EUmd12loO5EREa2v2a8xZWz7I6dm25vdTautRWgxxlw0r8oRvxr05EwBZV3eqLBxVWqIEMBjjQPLKa3oHmveCfnAgayKW738t62sdB3fy/IcsS+nelyAlCyqGGotGoi+ZYajIdOYTwHbGhip9hLzp0dkVSvjgdxch4tEGh8Cue/2xrAho6TgGZYezXlMOjK4uqHz3uaw7jrntiKapzJJrQnHVs1jD2YN0laI0zheALFS3U2PIqa6S2x7kYpycvQzAFL28/tVHwNSfcdth6tN3Jujf2ZRJW+/PeHZDRFAmP3sPnzJSw0+2L4VgfBgpU1Fa3TzBVYjSOF8AdmCHCndrjPuxeBk57YrFT+LnsFvbNiUCznnwuxkRcsqWu6H08O6c1XfqOLMf/lHCWKWtekZg5mO3QlFXM58yUlU5uVYnBAZTAqgQUifyBiBqR8RGre0aUnpineLGCAbrheR1wxZKKQhE832LfvtVJIx2JxSxR0/fdDty7cMjZoOVHdwO8+//FopUbY3W4HHCvD99h80NsukiDckSnewVFZ2yUsVkdToTpVy+7EBipoMtrTCRGCyZ+TZ1suIFKOmxuIy9CPXUcH8f6MsrU4xpR2HpHZ9n/snOxevYpGrUVjP3tEDFvpehdvsmMDlHfvFX+9G34ZRffBbaVlwC3YsaYaB2RsyLUtx+FCr2bmPP1vu4nR3xaUsLgU3wSTEAS0rUlZieuDVyKK8AYjkYCsM6Ggerk2AxQzGdJsqapUDRaSwly8cyeESLNaVSU7PzCVZpViNUZAMx4AVdYBDyXUiET3jlL6zSFFfYbGXficHh5pCkBSAlFRtNIPh9MS6tq9NQ7+MAHsibCFX2EGXsi7JMboh7ZEQvlwuiOT6hSVwoBdJf8YfANAz0jgp4yRQVenYy8NiQEApriE8T08B13rhsnKgR8UmBv8jstClJT74BZNPvHzapu4rmzoqaEkEUH14efhd1WaHsDfV0ZQTiWCs09oVd2va2aOZeDdETB3CqynQnMejxFrY409tZdbQMz3+X/hzRyLZZooiIED19PBlEwYXU4lB3JxKhP6ViM9aAiwy4sO0d+A7apotQZOHjn5fHUNBwqMaBvajVY18XorTN6xhIC3ifWwHHDh0B1eCRZQjg/Q/JY4q7B0KOejbuRZTJAdjdIm4XqzzPwAgCqd16HddcKeaSHMWimGdUJB6AKx9pNQqJ/LexY4R5kigLN117k5QXAUWR6OmPmSbTpqpmpEF7R+zj23kHUH7nNzq6YArZgxVJZmOm004r1QBtHTQOurg9aDKzl5KSZDqyvPOghruNVgkgj4a8BEnUwxEjmArIklLFj3GMxOw4KSLJy4TkYewstsmdN26SLNCYNmxujn3cORoilApzPu7T8APTDiwxzc7VlfBiGRcidjjCwCfPB9No/f5Yjfh8SavyHHYdq0GufETyAx6t3kO59NQ5dLJNSZw3RyP26vAR1h+7ULodHi0AX6U/e/arn7BGEeWg7+PRvpQUqRqKPk6KzmrnadgIXlR8zprF11dTc6GRBopS7eWsOT6La/ZjGzt2v6Pho0SDfq6ca0quJBoPmFrtqGKidDwW0VoSW8Ui2mmpnLZc/ZqmY7Ho2X+OGoC0bD72mC20GlHTR4n6gF8xlF10nsIF1XmM9UhSWPRVtSDSsgz5VlBGqZDSoq+sBp2dpxfp+jtAlL01tDXedI3lew7EpzKfGU0OpLKZ/mx/UwEgjYvYoz5sBejD9q86DZWc8qhXxgOmo2+BzslVLlquw1BdB7pSh+xyKjR2E9liBwScvrKG2bokaYytB8HYFh/KVq5M0LcSCi2f+f5+FlGyD5ki6/Ubs5Vnz+KDvdteBcuVl8W8R6w4PbyS8njdtQB33sNnm8mwN544DFLXcbYsVdhexYjAVn1AlT3ilxUPSk8OjTH7kLRgMg9oxSYCK5bcKYFuoI91TJ2rB5Sa0ZLFACs0xOeRoywOhsj2t5yalu2a2evK4c94uPqen8ed2HuxUYHQcD/f3/+O4rY5iYJJqxpZHRCxlkGEpaPxZ0hynjlZuFxz5HVUVq4jG5RsU71sn8p2apSVyL1HHhYdudmwDp2Gotigc9cBnHmGOvdReeQxtNy56T5zqAY6KvtGIIA0yj178bkAN35J7lUnAPoHktvLH6DZ8eJLAC1qmapouIeLSiBiKWEpWZSeFl04LnoTZlzTZkQEMBEuamzLRjg7J2rfsfeSYlFrAlt1TpD3aNVx+5GOpOdjJeUq6kRQeo1oNoFNjQ0OgI7sWn/y8GryQ6w4FWD1WbFkTdVC4RO3/5xZG7ue72ZbzkK2AOaiEm5FTD98/iWYRtvKOcqw4ZbkABL2c+cip84A+PmjRgh1hyHYh4QPKhqKAOg8fazGXkTUczCNRTzn3mBmoEomyr8foQRSpCLNmgsBL4g4jlE0AdOcCbRA6gXYdTYRDA4RViwDOH9peqJ/5y7e37DcmWvzswaQJniRC2/1B+APD/2Nc6EdaXpc4xrPINpIFqwNejA10JyhBMtrAnDkCF8EYKhDRoig5up1xmY2hvYKmm5iofG0pAebPFYsEhv13ERC8r04hxIHkxhklcRyJLOVjmlWfeoUvJVVhEMuA9vKl4ovlF5wVD++yiuvMuWlCZvz15MGoFz+jA351uatMP+c1QBz0PYrMiVEGScUfyhRDNfUAjSejXUNl4YnUAS3nuDGbVs7P6pGLchhG8xV58/PWs4ONANqavgmzLW1fE2zqHg8gm07vF35bundk/YWlJ3X30EmCJ1UAKkByIU0Ar5++69BvOt2NB3syIWdap6mRNleaon/T0MRLb2oWH6RMQxltfb08iNV8t739QMMDPB0La2wlBS6Couko1WzaOkU4iwaBkrLOHAU/qAVx2kvTnwXfRoG2e63UNHjCyE9g7R7dCQ6Wc5uEWzIDgTxJyc64Ic//QXAj25CLhKSz7gYhnjS9DoplfbOiOnQSGEgi4PMlCiYlHxDolipHDJXlsAnm2l6krKMLTluxjL0XQwpKEkL/Tz+BBOdXdgxrxspKTFSfq0fY13w9h647NZfcvuvO0kAMHEc9fzoREEonPvW5uSZo3iTkpLRNQ2DQ4ZOh1V9DGxGM/0Pf0SVWAI/gncpdvoR2zt9RPxZcsTa1Vif2/EmwB13D0k3U4it2tL4i/Z5BCjUMrTt9WXJpcm+9wHuvY/5Jgi8TyKtto+o2TpSN5KTMmj19YdpqunXd4FE3oahZWZtHMAul5DgPy2k0tITJ50JpcCkykQOpFzAJ54CeOgvTNF1IXjnIY22jLjfYSRvhg0MyJx4o8sJwd/fB/DkU3yRm2hZOCnCNr2gQuPVobbCm2Ii5epAq6h4p3Dsnei3/diB77gTpJ185eI38LvFSJtX8uLly9c+8rQhMh5+h/V0PZprZ58FwqnL+Fi1bZ8edhzmwFXYJPhSYwCEApKm+1tEeGI3j7w2IvdtXBcAi0lik7O0kcdHzTxVDElLO0f8LNNtdU76PvIKEOmiz+Clt+JjppBdvXgR9lisLzUZoXeA37NxQQhWTA8XBHgk8u99wQguH2/76tkhEF1heO01vls1ra6F7/og8L1yW7Pj8DECoAJIYjfaJ++bxJFMtbcK0oQ5ohApEsEdFOBTp4dgYnlkzIvOx3YYoKNfAJsQAVd7BNoOR6Imjxt/vxc//hqBa87tOWMMwCFgUuTolXi7T+Oj+S4ZZO9VC9LkOkmgCGbKciLDmgxs3UkcIsm2JKcBOQ/aUPH/qJWc8YIU8EmCDBqJSZqMRVUFns40u7YgARwCZgMdsK7F2y/HpkwfasgjiFJpGQhlpXxvPzLKaTqOjHIyxmk+mKZwlJEa9EpFsvHOjHqldJb4PoM07UV56fSZ8v6pkulDCpcMGk1PCkPa48F7U0oUmQJbyQMlK24jzOkFAmASQCkugXZlIs6kWC5aBLwBH90gSTAqC3Djs8iH04rPo1lyEoUU+EAhXJS3cEC2efMsqgsUwBTgEk9RkAalkVKmXYlcKVvmM1hXhSomqFpG5MOiQGM56eYWrOQNGZArhVDTlHp3NvkJJxPAggkRk8eXVrkOBXc5A9BRr7lOG9/rjwH4EN6vCcZBGR+hYcC3l065bkv893GznH5BiFDkMGKrs0nZAb4BV7lco42ixcLNCSEYyQrtxMmnKSgh3x9Xa5jYpEr5CbSn5kvIoSfNyTcuxkAZtEZg+5sDxb7FlBiKDBP1OWxpQGEZikXuKIAq4nUrZ+dpTNyElZbPeGG0wSxkLTQpaPoiKxRPmApFtQ1gpuhuXW5Ddxjtiq6uLjQdEs02vYiKjm8Agq1HINzXPhRMCv/bhmD6P3YAIjAk2y7BSnvkUXI2Tada9DqmTUIozHo4JSHTvmgmJWhUTY6qvBDKhUZfX19fUoLpEEz9cDADsmnRim03yG2nKCyvXCmTh8Kdn8wF6DEFIHle8GWfwxedhIZ4mAxymxUENLRFMsbJoKYVEClEoquHz65bquuheuX6URFXgUAAuru72VFV92naA+GeduY4qMSR12rljgJyZNO0EbY/4h4AiYV6eECH79uM70vTRwcLGkByZuPLvFlSAotv+QaI8+ca+EqHirK/OR4ERU2hkLsn/wEw8cKrGBeO1phDnOhyJQkjCAyCtPcVuGQDj7SOkoGCt+Ym2YGW5kJ/+kuI4K3eRRCXUS5JPgHMtxlxAb7E0lv+a6U4/wuI1KJnAGbcAVBxMWki7IRJqD9aTHHX2QR5NQfNpM8R974I4HA4oLq6GnRDna9yWCK1KwoetXeSyiY58+cAfO2LINJ70/vnu+15NeSRFjfX1Qjh+Rvu0MH7l+OgM3xlpWIURXOwJ3f282i26Fps+mwTQnMoRUVFUFdXx0SqL7q2tJFHP1G7JlDUHA7HVSmceqefiufVQ/hEO9yM/27JZ5vzxoEoPpegsrdy47fO14H3g6TgKYtR7ko93ajFFBelrWkGQIeG2xT4PXb4P8JieA9qkp5H8ZwLFyLnTNLOWSAOJE4si66LJYqgNxtZu5Tt1OZogMsvBh29P9GhUDnwxmILhJeuu0oHR7+XWrWXXcS0iJAuzX0HCbwtMAM65e2G6P+dUI/qnw6WKzxupyJHXHttfFFaWhnp0UdjySXJXTt2O5hMJmhvbwcJubCzO5DQzlSl8SyA/3sAwh4v3Ij/fqGgOBB7nQN74dUbLrToRM/bAIOp5zcD8pDX1kHh96kBDGHTleApy7vIhbugPgbeddclrihcjprkxo0AV1yhnWdqNpsZR4aNxaxdynamKkZ83oXngI7oQPQoNBH6OXqHC84vAWi5K60LfHJQbmenBAZbaUrwnoXpScFTgviWWA/r16uLzMZGgGuu0RapBkovMxezdlH7fBnM/q3nuwMZZXoUDoBoOly/aB5INfb2YWaDWvEOctFG2WFGuyMleCfS2KHmrUgNfPmOSuVicsPKGWcAbNigwUk0Y4zmDLULdRvWznRLHWqqRAeiR8EAiOLiNFShZ1/QmP7uV9SzKVgoSmiDLfnCmhG85XNpghctm/sa4PpfVYJbYzH/C1DZnzZNnQNB3o2UQiuoneEMpnSJDkQPokuhcOC1liKInLki/QsGZI29s5MyxfSgV1nR8BCUo2piQ8EZhKr0t9iDv3c2wENPGjS1xk98QgNAI46FBh1rn7K96RSiA9GD6DLmASRnNI75V65ZiWZ6BpMFbjk7jLJ3jXb1bXi6+R6UcBFCeSkcgEqIp5XZU7getx3QTp6YMSP5mtaGqPZTZIttZOzOIJuN6ED0QLpcJTvrxzQHnoe2j71xVWYXuWSCHD0mgKFUfR/gUjnoqxOBdKNu4JHpMQuhtacICCs1pR6L7fbkdqGIqmq4qBSONgkJ7U23ED2QLtSDzhvTAOJ7Xl1eBpF5s9O/hla+Il8oZa56PRKYytRX9Z2NQJWDD15Ew/1hWID8Z2Dg+fD4kcYkewWe+ckVLm0p4IaYiBymlFH+vKWEtY/aSe0NZRCHTPQguhB9xiyAJB5wLLno7DNBzMTv3ScrF23yct9GR6WG1yEC61F8OuR9awlQP36rBR6de8uiQ2zlCFUlCsG4916ea6iqiRaXJLSzL4MdjogeJEaJPiMtRkeSA1chIayZKC9Uoosi0Kp95EIzFGuPVWY0JGgMPAXamEnRpBFtSOB9f9FB+Pfrw6q2HoH3u98BHNSY+CEOBJOFudSiy6X0Z7hXyRnL2bNIO1s1VgHcSIG30TXS0jUf3LJGd+gIjn+OurSuM0EYnPj3Qw0HRxS8GxE8tehumrW5/36A997Tfl5UkQlbHHD4CO8J1O5MzAmii5UrSRvHHIAoFkjr3LB8SWZLoPXx7WbYhlptJyQwV6YH4KvQoAleCQrW7y1MDd7jj6NGexHAggXpAQg2B2sntZfl72cgRokuy5cyrXQD0WusceClwRAYF2W4l2OXvKvzMXkJ56KahpTXkLP6AKjvGWhBG/Gm2Qfgxi+nBm/VKr76xPXX43g6Ow0A5b0Ko+3t6s/sfRfNAyA6Eb1GCsD/F2AAhr8aEtdh24AAAAAASUVORK5CYII=') - - e_think = ('Think', - b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MDRFMTMyOTc2RENFMTFFQjlENkFFNDNGMjQ1NDU1REQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MDRFMTMyOTg2RENFMTFFQjlENkFFNDNGMjQ1NDU1REQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDowNEUxMzI5NTZEQ0UxMUVCOUQ2QUU0M0YyNDU0NTVERCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDowNEUxMzI5NjZEQ0UxMUVCOUQ2QUU0M0YyNDU0NTVERCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PmNHEb0AADADSURBVHja7H0HfFzV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') - - e_thumb = ('Thumb', - b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NzlGMEE5Mzc3OTk2MTFFQjgxOTNCMDJBN0NBQTUwNDYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NzlGMEE5Mzg3OTk2MTFFQjgxOTNCMDJBN0NBQTUwNDYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3OUYwQTkzNTc5OTYxMUVCODE5M0IwMkE3Q0FBNTA0NiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3OUYwQTkzNjc5OTYxMUVCODE5M0IwMkE3Q0FBNTA0NiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pk4O+RQAACQYSURBVHja7H0HeFzV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') - - e_weary = ('Weary', - b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RTNEMDY4M0Y2Q0U4MTFFQjkyQzZGQjIyNEUzNDI1NTciIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RTNEMDY4NDA2Q0U4MTFFQjkyQzZGQjIyNEUzNDI1NTciPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpFM0QwNjgzRDZDRTgxMUVCOTJDNkZCMjI0RTM0MjU1NyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpFM0QwNjgzRTZDRTgxMUVCOTJDNkZCMjI0RTM0MjU1NyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Phd5p5MAACVgSURBVHja7H0JnBzV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') - - e_wink = ('Wink', - b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OEU4NTA4QjM3OTk2MTFFQkEwOTNDM0Q1REQ2NURFNjAiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OEU4NTA4QjQ3OTk2MTFFQkEwOTNDM0Q1REQ2NURFNjAiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4RTg1MDhCMTc5OTYxMUVCQTA5M0MzRDVERDY1REU2MCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4RTg1MDhCMjc5OTYxMUVCQTA5M0MzRDVERDY1REU2MCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PmA0NjoAACG+SURBVHja7F0HfBzV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') - - e_zipped_shut = ('Zipped', - b'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UmVhZHlxyWU8AAADJmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NzhCMTU0ODc3NjZBMTFFQzkyNzFGNTJGMzIzQzdGNjIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NzhCMTU0ODg3NjZBMTFFQzkyNzFGNTJGMzIzQzdGNjIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3OEIxNTQ4NTc2NkExMUVDOTI3MUY1MkYzMjNDN0Y2MiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3OEIxNTQ4Njc2NkExMUVDOTI3MUY1MkYzMjNDN0Y2MiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PiFa8hIAACO+SURBVHja7F0JnBxVmf+q72Nmeq7MfSUTckAOQkgi4UiEDaBAAuoCggeyCioKiOwirri7KouyIgoeyyEgGmGNqwQRcEm4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') - - e_not_understand = ('Not Understand', - b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NTE4QUQ1ODQ2Q0U5MTFFQkJFNUJFNkE0MDVDMTU3RkQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NTE4QUQ1ODU2Q0U5MTFFQkJFNUJFNkE0MDVDMTU3RkQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo1MThBRDU4MjZDRTkxMUVCQkU1QkU2QTQwNUMxNTdGRCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo1MThBRDU4MzZDRTkxMUVCQkU1QkU2QTQwNUMxNTdGRCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PvaUPHYAADXuSURBVHja1H0HfBzVtf4326WVVr1LVrXcey8YGww2wQZDgNACCaH8CQmdUAK8JA9eAiGBR02AkAChE8DYgDEYbLCNu+VeZMuSLav3vtoy/3PuzDZpm+SV4V1+w6y8u7Mz97vnnO+Ue6+E/yPtnCSY6DSSjtHqeawkidf5sgzDqVybrtNJ19hEL7fQsYGOr79oRFeE799IpwvpuIz/pMPiek/W6mE3x9ELGdqeDmhsVtdbTjo+oeMRup8tfu/9BwqWlk6j6JhJxzTqYD6PpefTuD6j0wHFhcAIOvKGAempQGI8EBsLmIzK+xp6Oq1W7STuDQdgp6OxCSgrB45WAFU1wJFjwMlq0X8uQK30ehW9fI2Oj6nz7KfwLDF0upWOu+hIlDVadI5fgNaZF6ClaBpa04rQGZvkA4W5vQHJx3Yg9Zu3ELfmNUiyk+/sOTrupnux/uAAVKWLQZpPx5nUgdOpA6Nd72ekQp43G9J4krfsTOqFBMBoiOw91DaQ6O0EDh4G9uwhkBvdYFbRvfyZXv6dOq97gM+1iE4v05Hdm1EoV135O6lyylJ0R8eFfY24pkqM+vstiN38MVTtcD7dR+v3CiA9GEvSNFWVzKdOmkudxCoG0VGE4Gxg+iSgMB9IpsGp056e+2onpXnkJEkqjfeaWmAnAfodKVabTQBZS/f4G/rY69SBchjPeDud/uKIjtMcv+VvODr7MsiSZnAqnn54zEd/QsarD/Cfa/nyLq0gnUbQWJXwiFxGnfEjuqdE/neDHlgwl1Cco6jE2JjvVxu0dpJqrfKo0yZrNFaUjsb+T4/KmtZm7q8v6LiOOrAyyLNeR6d/WHPHoOT3q9EWnxmRexv/1oNIe+dRqDbxoSEHkB6E5AlL6biCQDvPJWWTxwMXLCY2UgzEx+EH08qkAuySJuA76wRst4/DEdM4VBoKiUloEGerx/QPyIy99TpLYxM9y2XUiWv8PDMTq52kMvVbn9gidZkTI3Z/Gqcds++bjajDWx1M5Oj3j0hDBBzbsxvpQS+hB42lMxaeSUieCxTlS9CZmHGRXnJ0fi9AOYgjHZRGokSaiB3SZOyUJomjBfEhvzu17C1YHroJuq52Oz3btdSJb/Z59hV0WrLr6RLUDZsQ8XtPP7Yd4+6Yyi//Qb99vRRhafspgXULPdh4/reZ9DtXXMSqUYI2poiI83QyaARe85dA1+HTApZMSqZUGo6t0jRslmaIM0tZt7jdwbW8thIU3Xu+LFVX8Z83UUe+pPZBAZ2Otsy/Cltv//eQPdPs+2bBfHBTD71M1kUAOB62txBwtxNwyRai8Tf8FJhHMmiKTSYdOU8BTqKfqv+QjMxGldQPTTspZQmQtkjTxZmPVkRWT5dbJqLnr99IY++aL0tVlX+jPqglEJkmXsLv1yy6YUgHZePimxhAZu5n6E4BODOdbiPg7iXgLEX5kG+9nqRtuAZSzDgCjnSmeZSCVcs6oGE50bvuiD5ID3kfrAI3SHPwnTRLSFiVlHl6JFtnQNS9d0n2u++Aw443qT8m0z/PEC5JwdSw2eXwtf9EW+541IT5HW71o8/AMOXlNN0ggGO1ew0B9zj9furIIsj3/IocnSy9hDji/4lk6PTJag8TUat9nc7lEek0BmejNFscDNh2aQps0A8pUBa5FUVdJRjRU4IC6z469qOoZw/Mzjbx/u5LIL31FszUHx9Qf1ht8enoNZrDunZm6XfI/d9fwGEyo/nVGliN4VHwluQ84ZKQg1+gGyB4zLCeZ2c7nZzr/7obKMjXEXDkAySdr9g3EQAiF6WRbHnTajUaNPBmh06QDBdYfD4uDRtSsHLlCkyUSzARJcqZjlxnOfbQOLQFiMWMH0vslczF5k0Yw66kIy4p7N8zdDSJs7anEznbV+LI7MvD+p5To0VvyjAY68pzdQOQOrZzf9FoYLiFvJxz50MyJE4EUi/1SJxL6mr+AVirBqwON0kzsV6ai3WaMwVonTAPGVj58jFMk7diqrwNU+TtmCzvIGPe4jfYmELjsqox8LV+RC7RsTKgro4Yt603/GeOT3O/TtjxObGTy8P+ri27GMb6ijRdGOAlcPSBQzhJCZDvuIkU7wwCLO1qxcbBK+7aRD5uA9lyOXTosA0WIVXfaObhG2meIBu9MAwJWJlylQCLDwZrurwFiWgK+/vJBGB1k8e57ydJpMUvJrb9t7+TNLU1hH3dzoQs9+uo3WsHZoP1JiUmHAK8ApK6z+jGi6eRsP3mVkmKG3YWPdGF5FUavfQd2YNqkrqug4GZE5IEWOukM4WUsd/lhCbiYMWiHTPlTZghbxaATXduQTpqgo9mcklPnKR7JAFkAUqIVwLkUUofQU+9FEfKoKUjiPqlzyclcQy1GfrebtgMod2UtoQM2M3x0HW2wFB/XJAaWQrPs5NsPQqXCgLeDLrWpxzy+ullwNU/iYGUSbrTPMb3g92kO6po6Nlb+kkYS9ZXmrPwlXQWdkvjhU8W6VYsH8Ys+TtxzJY3Yoy8j4ZFYLtr7VUyEZyB4KOUbv/YcXLuHb6f4/jrFPLDL7kAmDBGkcJgAHIbQ5/75hsaADWl5MSPDwcGdI2ZC8uWlSLYGi544v6qjxLa8kldEPDI20bMXTcDi87LAbJuoaGY0GcIbSZ795pQmewYM53/WrMAa6SzsU2aKiIekWxmsoqs/ljC5jg3iHMSAhunHit51QzSMeV8+ChQQSbaGQav4rTT5h3KcdZc8pfIdBiot3qDWIeCPAXAxKPb/ALIobCE2qNIPLYTsQc2wFyyBqYTB8R7HdOXhE9+rJ0w1hxjtMt1fsAbyWqTwXvwTvIUz6ZhlXkj/brJlwmRvdvRUIHPpXvxhfYcQUCsMEacFc6RN4iDJWy8vJuGhMM/M3Mq4Bw4rAB1sFSRLDmMmIGs08NpioHMao/peW8PtJ3NSgKR2lfrgZOkhe/4VXAA8/Opm8gqxG8hHrDgOsS21iDx+B7EHd6MmN1fI2r/Bu9krSe0FxWD0msfDz+cVrqJXQh+uU3qS1gIvC300EW304j70bIJCniSgjOzwkopG8sbNXi8ZbSwa5FsI+RDmCuvx3x5rTjnyYH9x5ZWYP8hOg4rYDFoPdbwHHAGy0mdJvOZgdP5IU8Enq6pCvoGzyjg0OCFFwW//stEBY5U6GCPTYK+pTaEBpXQeublOPTTx9CalBN2P83444WwbP6Yb2pYXwl8kcG7ZCmBd+F4ODNvRjUBxv4XA9dMhHQNmbp3W04dLNL4GCvvxTz5G5wpr8MZzm8Dkg2WrvITKmDqUVUbJlhRsQpIAiyzL1gMDF1ctqtipZFIAFW1T2d7co74vvHEPvHZTdtokI0ERo4K/JtLSRN+8KEdJyprOQjFZRlke0TqiTP82t6UXHRNmI/myYtRM3YBOixpAwtml21j8Pjlck5pSV7SdyWd3siZkoGz/utKxOfejDrtMJ9IxwG6naerBueas+pjX4sB42Ouc31AKt9LrPAQSdUeMg97idjuI8C6Q0XhqMNdYIkzHf4ky6YzoXnYWHQnZoHLG4z1lYjf+aVggi6p0ERFQ2OJg6RVxreu4QT09RUKy40Bbr8NiI4OfjuryaP6WvEMrqKDRgBKaq55BHsu/u2gB72xpwMzb58gG2rKeMSNJQAP61TwLHTfTzktifKqh/ZI+dlJSO3DP3oItVfrBgYe26yz5TU4y/mVUIsx8E/jGJy9BNJeAmz3fkUdMrUPKl1kr5zRFhUsOhuD96idPltxzvWombZEFBH5YG/tQuaK55H5yQuQHHY4uzrh7OmCNj5JgGlPyoa2vQGank600yN8Sgzhkh8Hv7/Jk90Akg3CuTwuzfs3GHDx4MBj12QKqU4Cj4XuTgbP2w+8mzREivW3f8KCFALPj0n4kgZocwj/vEAuE4C5QEtBvX/AehTJ2k3jcucehcoHJRtELFxSpYBmIRDCjwJ2ZgzH/mv/BGtcqueSDpu4Lkshg195yd1onroIxU9eD0NzjaircDQ30EdSIRlNsNE1jMdKxHe3EzOdOQPIzg7i/BM9KCoie3gEZzK/oWOreffaORqyrU7NwNh5bEs1Jjx6gRxVKjjLXwm8Z93uhCp9tyG/SD485jrpCov/i2xo6/9vaagVQLlAC0Q6WCUK6SLAduxRJCwYlWdwhFQxWNFxQi1CGpwP2ZE5HHtufAYONcCceHAjcr5+DbEqfe8kdt2aNx718y5De/E07Pvdcox+9FIY646LTIq9qQH6tExxD3ZyvHXN1eJ7n3wK3HRjCLIxXQDI7Wd0fKfp7Z4T31COptTC8MwODbKitf9C1st3Qdvdzv/0EIH3iI8/SMfVnA6y3XAH5li00Prpp0pid00kfXqyiEzpFztXYZH8OSbIuwQZ6QcA/dNRwnLHbuVgWxZMJQoaz0CJg9VhZGKgtphE7P/ZE27wClY+g8wN7/r6lnbyqTYtR8o376Jl/Hwcv/wBHLzrVYz5wzKyi61ipDlam6BNSIY9ZRh0rXWCoZaTSdxP6n706MC/P3w4+WwG8ew/oT4RFUkJ5bvCBnDKX36CuI0f8kuWjOv9lXAwgNc4TdHYMeIq3BPjPzSV0/kdljuewwLn1+Jvvzkq8qd37FIkjM+t7cEkTAXMHAeHOV7xvyLdSD0euuxB9MYmBgTPRVp0icmw1VUjfvdaxO1bj8qL78SRW57FyD9fSzfrJJvYRbaQDLUpCjZipvo6RdN89jkwalRg5cClj+PHkbO2XahQEeWOLd0KTA/PEFqHkQ+uAMilhPv9RmRY0k0cTtfHIZVsO4ehMlAtnOgc+QTiuASx62UadVv7UXuWrs3bySbQubIqOEN0CMDilSME4YhI7nD2j9EyfJp4nVLyhX/w3LqKNE98IhykLpnE5Lz3ONpGzUL9GZcIyRTOdmszdGQL7YmZQo1K5JA3NJBZoAE7IUjUbJwCILfZ7L6a96yLD/cZ2oqnQ7Xak+gICCA0U6fhFv1HOEc2I0s+CQP6pET6JGTXfAO88qYidYG8PEE4CCyWMH49WBs2mGaNSxGMk5uJOrvooydCfofZphxFzFb1VywHvoOt6oggORKpTPYVnZ0d0MTEEislKaxRjNtXXytSFujx8vJINkgw6OtLSY1uiyrdupBtm0OrDxgmi68/BkvlQcTt+sLNiQLGRPl/j8n3Y5RuIamLS/t/wkHOn01hk+zvPvYMsG6jf1rvcEkYqUZZo8P31coX30x2T5Hywo/+Aq01vGkOGksCuQ89bkqsb/Vl0Y72VmiizbDHp5FveBySvZdzgCg9wqUkgVNNrGZ370Yxj32S8IUJdWVoyBiBqK5WJJ3YA0t5CWIObELU3nUwNPQrN2V34f2gAHLqxJ1N7zecK9zE5JEnSSV7TbHgyIYjPgOOmATIeiN+CI1dhvoJC8XrpH3rkHB4s6/qJ+e+KzUPVgLBHhUDDYFgJKCia45CR36exkyao6MNgUJCDnpPa4kXjNTl3G/YGBhAESIcIQAUY0JkUJ67AaNb6mCsPOTDvHuTh6Fr1Gxo6X6M1UdcA4k7NpeOk34B5EkhIu+lDeA/9Cjf+/BTX/BsaflkD7LwQ2vlXBFG+kyizs77/EWl32lwMaj1E88RLoMcQH3FnDxE9nI1kla+BG1nq38MO9uhjbHAwQA2nBAkp7SUfORmYpgJAfzjfC/Pi7Suee+3Z7nt3IylOHnR3agpmgG7ziMEpu5W5H/7JjJfviuX3I81PM+CiMw3/QDMdhVxaQMU1Nhq0UVm4XUvDmBLLxQj8IfWWvMnoHnELPE6dceniKIOrp16PirOvdHNRoP6jFkjxHH8rJ8ha/nTSF/1D2H/fBGUiZWyLSQQLckkLXVCUNi5X3i2/+ty9Tkne5uacAZ9lqfG7STbmlF27zsom+E/pNMTFYcD596MhjFnYvyd00waa9d7BGKx98QWofYT4jx02r8KrcHaDaSaVDPCDvYPETxuFYtuUh6K1GLWt29j/zWPofTH94UFnm96J5b8wd/i4L1vwhab5FcKBSeIT3f/246dwaNJxcXifWagL9CRceyeNwOC5+OeZY3G8V+LumEmpHf0s9vuuQlSgHoUW52IoLhjij9Q8JqLZ6Atd5yip7Z/ioNX/gFNI2ed0jXbRs3EgfvfUiZfehM2O7HSnm4RdHDVprAKPVEZJMzoUaPnd42YgaOzLgv7Psros7ZEoSp/0Q9Ak8nj+PYfaj2iVKLc68ac0bE/SACPL7xOsQS9PWgnNdiVVhCR63ZnjxBOfV8N5exW5nWwGnW1vXuDpIE8wmpoXHT9wDQCEZzW+Vfwy2xWoz4AmqO9wOoXxKxzjy5P2Mv4g5S+9hwlpmUmNtmRPSqytnXsPHLqL+0DYLfQiY5YD4AHDwW+RlKi4g9y60ovHPA9tBfPcL30+XLwsjBbg9DrLW0eqns6HfJwQ2bli1XbZ7MK6RuKVnnxHb4ZEOoYJ6tRzuyrrLae3MaWAMlu7rbUFK8w1kDjup5ZvYn+AXT4cXbtTQI8t3HWDqyMnR+sJylb+GadNOo4uBzpVjdpkbi+S/oGkmYaSOslG9Q6Zq7v81mVqI0zxuM/qNkHvy1NVaPRNUcG/PuuKm5qPoWnui5XptvpB0BbI3p74eNshgNa9YwLlY7NHC5CUd5NTzfC/lb80R1I2v8tTI0nB92pdlMMjp33/5QHbG+CdYgJVuu4eSLg7X7WHsXscJyX3QnBhI8DUwPMU+H84A5yNxI2vE8+x00D+u24HavET9JR4gNgrzWIBPYBECHmeHdkFuPQ5Q+jOyU3sCogKWRfjY9jP7pFgJm2baUIOHMkZCDt2Pm/ckt11vq3CcxfDimAXdkjfQerg9goZ/CjPUEQBjAgkVEj0zE7v0TKyX3kIowJ63cT6o8h/isx3/Ar8gN9qoE0nd3uQJ+f3m4SydhwWsO4Bdh989/c4PVzgH2eXPZxno9eeBe2PLAchy97UDjj4djZusmLhZMuHOXSrYiuLR9yc2v340/KJAEcB3ZpJ85QBMp9Jnq+Lo96/HLZ1NMe8jejupox7pGl3J9sOO/v50a0uPx6e6tfCZSdoVVozYxlOHjF76DvbEZ0nRo7DVY24AcgDnex2t1z47PYes+7InrCfp2s1fb7bu3UJSi9+F7VBrRh+AePw6kd+uC5JPcnH7KKlqwGz3ls1vuvJIHRqKxjQ4/QaKzYK02/b7aceny3389y6UXB1o8w85ejZGOFcMR5jZit/UJpDU0BAJR7hV10Bq1VkXD87J+jbuI5KFr+V3QQUamZedEpd5Q1IR0nFvxUHJxJiK49Rka8WZSes4R3J2e7WeeoNx6EsaWG/L68IQfQ4M9e2xUAOcep6VLoOi9RkhlgnmkyeR0dHWLK8K3G8r1PTLh1gqG7aAo6Jp8LW3wqdPScxpOliNmyUimjkCR24m4m8PwmNHVNzR6XwVf6FD7sLQCc7PRuTWTHLBV7MGzNv9A2bDSOLLs74p3GaaH2Yf1thaGtASPffIh+X/GeOe451M1c1l9aXDWl3lUF3n5z35ZCAB47JrIS/4FSK3pH1NEdy6KObPdmYHzR9XQsJ5F+mcALOCtDx0lZngeg47lxLHWukJpD+Y7Pikh9VAgXCLkjIedcP2Qdx2oyuq5cqDB9Zwssx0qI+HwKba+nWNTUVEWg1qPXkjJk95G4/fP+AKqzYrwDHG1tga9h8fCdLFUlEvOSf3lOkkjacqyUqW1NuMt76dinrK4BcrJIV1qJCpvUWjm7MoxizIEl0NV6iL63FE4ZOvIQFStUpb6jOSgxStm1BifPuHxI7sFycBOiTvpZWUN1yr3zoa2tga8T40n6+GTZCbCGvj5eOE34BZXVLrXpVdpuV4aRz8pJTv8ANo+YMcTsQXKHyoK1zA3viUxExBsNjpx3Hwvh/3pIVG+QW/Dqz7RI3JoAsMIVrO71BtBjA+PU+LXEBttPzsQVCRnKZo0P/bxGcqaHrflnxH8784t/IubIjpAhPbdGCjLJJsozySs+YgAeKXP98sl+Eihk3SslJtmtfp3zoW7h1thkffMmkvavj5zdO7Aewz78Sxg96WF7wabJG40RBpC0UwvPVFWGuVcYweFR5GlevIDnzvXvXeeQAxhuYRKXUox462ERpjvVlrrzc7K9D7tdhbA1fpCAlc4zDiNSDKshjbiTFz3t6FRdCZV9wuYhDDlepS8aPx1paGsYcgCj68KPtGiow0f9+7fI++x5vxMqQzI78r+G/+cxFL/7iDKHwuEIQ0U4/YHU/9qefEBE8nL8U1y2tYBntk7j8tGeCmUevFdozRtAqbc/gObq0iGWvk7EnDw4YOKR/c1bSNn9FSrnXYH6SYthN5lD2tC0rSuIDL0PXU+HiovDM38wWFTpNGihQACuo+O+PftdAJIajR7pA2CRV5BD093fp0w8tFl5AEkzJDeZUvJlQBcmJLFpqUXhx08h/9PnxJJWHBToScoi18Qi4rU6NfzHAYmYqtJ+QHDpRFB1qUY6JC+QY8ynF0Bexte556CaG+ymh3DM9vlQbo7i0PMKDxqShr5gsQPNNqdxzJmR9yAIuOxv3z51W0FqNf7odnEMRIqd7W0h1IMKoMNjJ82nEUANOZAsajt5RqyoKudlQ+zt/e5xeIHnoTTd/aPouatf9nmISLXsdf+GqbHytKsmThPZm+qDq08GTm/ox84tlsCf7/FwwO5ISSC3VXYHppTsA2ZNpet27ev3wYljlUmZAtDOFjG7qC/JyFv1d5Gji1SLP7JtQH6dwxCFtvwJIvvPQW9bdCwcphiyod0iC55a8oUIjAcFrtcq5kA4u7vCWuJCUgtdJK+wXnwQB8HLyW+LKIB0/HbbTgaQXrX3VzOTxgH/Viv0NRzSog6SSS1JXnUyWevfEQ531ZxLTz10Vb5LMEkpRP0I+6D1E85Gw9j5ZN/Gkr/o3w5zieHJeVehYMVTyNj0oS9o9BwyAcagybYBugwGhUxKXuw8LUjMwWodGgC/IwzaNu+A5ddQmWifNqpYWVGeSzA0xNB4ehXXyDjaWqCN89SEFKx8Wsw14EIjWTO4hX4yNn2E/E+eFnYrUGOwKuddjsbRZ4RNnhjcoxfeKTL/yVs/EaWBTFIGCprb/kSbIal+gbd7lZYa+DstHve6KhIAiicnO+ggbfFpXYMyXz2QAzprmpddbG8Uq9rwwwt14x0N+fYtTHzmF4gv3TKgm4k9sR/jXvw1Cpf/JSB4HLbbc8PT2HXzCwppGgTzPXLBHeju6RUEZbDg8bx5nlMo+qalRhnQUOZHBCMxXqmmiBh2t4gUKgnlyywxpC4DTFhk7cRl9i7W5UjgMitZTEHWmKLclFowU1KzqTtXi7CWlnxHTnjao+N9svFM48215UjZ9QVJ7v8Ke2dq8b9WDOcFy5behiMX/wbWxFMrXpKJeOg6WhB7eOvgRr05BrqEJPEsWnJTDNWeKrOzFigL3wVqm7a4M/a/Les+9e19vGMGn9L9dK3fjOjrrvL/YV6xkNfEbmtX1Cgvu4EoMwHYAkdjPbQpae61Vbyd/Hzh6D8vIvY2cwKcBLTG4RC5vXCYa1vuWBz+ycMibRWp1lE0aRDDXZnJy4OV00j62jL3ogfchhcBc2YHv8SJEwL3+tUNAZbwGIwKVdVoN6nRFZxaOhSgbJEJ18J5Xs/D0sIL45hjRWLT0VDnTnAG8unYZzQ114hzOODVTjmPVOYzEQVv4PqSnjHWAn1qhgBP09UK07EdPuDx/MCfXq1oqUCtoVFJ9lI/b4yYH9jn79cFmOsCf+G8hV7iS+qDQdDGxIplqthncjTUhvSdwm08z730kgeGpFg3ecMH4QFHz6ZLyxSTOnlGrqHyAIwVe3yC+mfSoL72Gk/pfKBW6hGMVUMF4Od0z3Vfrw+MQW62okpd8T9eEI6HHc+XUyg5OcD1Nf2IzUDjmE1F08jm3R75yAWRjdw3/xuJWz8L8iEv4Ihha2iQ6snOmcq2K+TN9TGjhOTxeiw6N7jkqY+ELYrJZRX1UcTixN5/kFF1FkQhk5zNWRw+ywtgjLkwZ/VadZD2dAkyIxmjIHd1KnfKK88Kn6pXRCokbWB3QowU+pyYrtXVIZihvbMT+27/p5jCHRFfqbMVsYc2I33N6yh86S5Y9m8I6JRrLXHQqUtsaW3dYkkRJimang6fYW/M0CGqgNwonYRhyTLizcGd/mPlylqiDB6Zq1ciGQvt2/5Gxx0ff65sSOWv8TZwvO8RL/UoOe1iMTiecq2h0cpLdXgHgu10iGgFqUGJN/RjcLlGlaP8bC/9RDta1BK7sE0UXctUdQTRlYdgbKiEobEKhqZqGJprxWt9e2NwNRlFdi06RrgGzKq17U1Cs7Ct68vCJxP3qSTfr9PhEbnSag3yUpxBpe9z94ITYis7DBmAvIjaOUn4cu8BLCw/HlgKeXeWOx5SL9JcBTtRe2Wpjuh+6lP4WnSEu1+LNTn03Hteqj9h22dI3LZKLAmi7e4YACnhCIpJOOKCURIy7MdpaSB6+3TesWAGjm0dT5XefMSJNXs8AJ5sCl5JvqMEOK7ERj6k/t00pACqjXeLXPifTwBectlfGzMSmDsDWL9ZGWKsZqzDxgqa7eQJF+EkQQM0c8X+wO+V70Hal68hadMKaHoHEA/mhQ+MRgIsWgGNUSHJ5VUImYz1lTbxW6TBp09T1jyL8wr9js5iAD1/17UFNoCN5Lh//LGoSeZtXiNu1AMB+DH94NE161B47U+IsQUoebmeaPPWnWqaiXw6nqHjiEsVTq69sW7QWyTFHt6CxC2foGn6+aoNaxF/p6x7FzFlJeFjRiCxWpSY+rN6ZB3IoHU0C+D4DD9zOLiqes4sMhXj/WfXY6NkpFpkAk6RPK6r5aWYDX0+y8VNb7whAthi3w2SvoBTX9S9OdhosSfJJYef0ee/DkOZBLwgr8X390svUNRloPbex8BLr6uqkuycNX+SqJHkhQAcLc2nNLp6uFyehq2pPozFr1ktkm0SpMlgVIBTe5/pv0aA1igyKf6y57yAKy+Zxaoy2DKS7hG+TY+9JzySd+cSK0x636zDG28Bh5VS0ucIjF8F6Ge+yM9JQzxMz9jXYN1K33tmsAAaSQorDAakvvospMQAKRLWlLc+4Imh8ioW1lxl7Sm2hc721kHHG4NFRBgcAZgATQHOxeWZWGk620gttgjApAAFUaxFR45QQOPFeLQDiL1/tVeHTaVal9eB+5Z57Cavh/r2O27wltPxY443++ljnkFBMGOepNHKMcOGS9GZecjKy0PZmo/lltoq7rgi+u6JsNyIPi6Fg1wKGwF0HoM0bVLg+Ciz0tVfK6qEE5u8gQUvucUdy1EaEbWnkSA6mjdk4PXHtEQcmDwwGO6DQNHroDF4pEhEPuj7HCzgaAg71NrYOMEaRfyVgNTae0gdNonICK+epK89Bm1bvUg894328PKPvPTVgvnKbiu8sm5KSmg/rp9TTsyzqln5Ugqp08kFDne24ZV/ARUKaeEJKVf6K5MX+1BJEtc/jmXQ0ucslmJyi6GnZ9NFmTH77EXS3nWrGZ8uwuKrgdpAV3uBBOnuFZ8j++IlvuWF3o2Lnm67UVlHTVy0sVL4Tfa4NLFuGnQGtzobVCSL62FYDZLPyYlTjoJo1LO6g0nQxvPyigpJ2kYq8UpdBAI7HT0e5TVMdSF4B+z33iN3uEtotqegLI0s+wEvi8D7klRmRsLY6YgfMdH32h0dSC8YDhMB2dPdyWtTPjgoAOnHe+nHHibJeuXF14CH7vJ939twnz1PWdj10y9VyeTtZNSFxHlBVzEJkoAUCwKI0JiyU4kkbJuskAmyTSKBS4Cx5LDtUqrBB1bxxYwxLxcoLFSAC7QE1qm0E40eAAsJwI+JsX+3UVgOpsa8q+e/A5gmlqr/CPDGTOsHnqs1kSjnTZmBg+u/GkXfSafr1QxGArm9Sjf1q283YXLJXqW0wtV4y26ewWsyKPsLXbAU4IjaylUk915mh0GQ7JGvl2G1x/sc8RosWaQFsjKV81AXFZ1o1KDTqgCYbnbinX855fYOwk7CdhqPV7oWJA/QmMzMMGflI35k4IxIc3MzUnOHM4D8J/f64ACkm3HSCOAf3fjMy6RT/6wsoSgCwjTST5C30OmlxSZNoV8jNnfgoBK8PUkg19YOamUNQSoYDC4S4lk9rjXH+OBwHkuW9jTtMe/dthzRIt4kw15tR+k2J0sdl0XfT+A9z/0VhBjy0HqYzUnSpLlBf6O9vR1Jme7NQHjyyZeDlUAG8Tv68ZdOnMQNr77tcSuSqGOruJjb2T/txIugjldWvsLafTps2KchB18W+xbE0cOfPdburtBim8QSzNUJPHeAV4/i2srTWZ4XTuNBuOeAhKoDDlSVCuCYnLxEwP0hkIrr0zjTmmguGAutMXhlfWdnJ9Iz3OHE5MGSGO92N+8F//4KZM+ZDoxm2k0qLIVUWE2IrfiSYmVilxK0ekXtGOnvMaPxf6a1k3zt3QN8uwFycxNZbklskPhvAu5R3st9AJcSkxd740LPtOqh0a03uqcyxZwygHSjbSSFvCDZal749fnHFJWWTgyvvqW/FHq31DjfN1u7JDH3XiP9cEHjJAlvU7djO7B7L1EOp7BxXBDL2xM9Rf0xoAVu1G3a5+kS08khDP3gMv2I5OkgRyQkkEH8gm7kkYZGPPjgH4Enfk/qjlReNrkXFUH2MkqLk2E2ym7Dz/5ifZsk/v2H1Dh6wuu87NsPlOyCbO1x9/QmFbh3qQ8Gm+jkSiOtRADqDaF3KuXRYvfMU+uICIBqe5iO4sNHcdk9vwP++KBCZppobLYHebThGU6UlHsYx9EaDQHo+N5BaybtcfSoslDdocOemWQcC6bTG3S8GYJVhtuU2naTmThC6CXLjEQGulvdC681RAxAdkxJCpnGGA8dwYW/vh/43W+AfKLy+ysU6fLXphY4fADk17OKHad97TyePlBZCbFxB0taba1PwoJzDFxr8dHqBpRE+KdFUY9N0iIxKvTUQAtR7+Y6d+XhoUhKoMvB5+Vm/3qyGrfefA/k666EtHA+2Y0a/3HnVFKXo7Od2F+phJ9ayA5uP6YVwA5lIzKHSrJWx0k1Hj6igOeKjaj0n+k516isItDKh/BW5vMsYxvRgagwAExNTcWuze6NWvZHFEAVRO752wjI7xwOvPDia4j/jH5v2RIaajn+V8s6Z7wdFfV6ty1k94Iz2cmxkbGFTPPr6sm1qSb/9LhSxsCL7kgeCZPpP97cfi0fvI9DuMt5nEpTMztLkT0cZnJopRBqR6PRICc7Gyv2bOeOOUT3WD/gbMQAb5B5MdEascmTxI42J0GLR/SPn1Y2avDmBr1b1VqiZVw91xaypqRvs9mVdcl434baOkWyOIDsvUIEB8jtUcoGWrw9uFrXYlFnZJ2WRn1zD50el+NS5J7MEVJ+fn5ICSwsLEQ++YAv3fFz/vNJut87hxRAr5sdpfqLV3IaT0TqU5RNoDjElZGmxCkbujT4YLMOXb3Kz0cbZFww1Y6CNGc/Ks/79XV0KCXpfNSrEsaS5RMiZfEi59hhsng2gPTa4oerynRK1fdU6pDtpwE4RokXOL8W8QzeSCk+Ph4ZGRkh2ecFF1yAzcvfwnf/EeHUBXS/a08LgF43zzWGbCMvpPuZR2Am9I3UpKRKkKIlkd5xaRQjOZNcTsNEgzfPCjQ5lifi0DV30Us+bnQaogzWgklB50nomk6KNBOU9M5bQwweL9nIU6AmSen56E7MRjjgcSsqKsKkcePw1PUXo7enm4MExf4yGqdsA0M5/XTiiX3/VEsFeKHNWeo5z2ZDXnWVTLxV5mCZkcAwe5EKVq6N9G9cSsYHJzOZenA5Aj9QKZGNGq/OulKS5cSgk1w40yG5GfAy+g6np3liB6t+VvL8JivfCnVQbBpghMUbvHPoQd4lJhcvFU1Cl94MS2xsWODpdDpMmDABm1a+z+DxPz0RDLx+Ekg/zh4m62zewkKjdh5XM66kC1X/kJxuNTDMGe1vZK0u3Z6Sq2Q8HL1q9qPXnZIaVCRd8b2+8zq2Uh90+rkP7kMueeL7Yffqfzj/KY+YJvU4WcMYUFBQIIhJqMbg5aSn4oVfXknmw8Z+6Cj6TdtAAHwZ6t4EEm9P6jEyzNRY7fw3XbD0ewCLa0WWcSiKDo6i8i4MpqAPptFCa4qiIxpangomzlGiKs2qjyZx04i0gVNdT5M7QssV2ZzB72iFvbEKjiYfn8ipaoEG0hS9xI8S6a0MYuAW736Uoi2wkTq3qVV5eXl5iI4Ovd1eLEnpkiVL8Paj96Fsp9jv6Tzq65Al+N67WHPuoiJnzEQpfda5aGhugY0epLvmBNqO7hOvmfxBWTX2r6FEOwKg8ZD9EZT82SI3xTYYoY+J8wHF96z8u0YfPFzFWe+WlhYa6faghELHj9lSC0f5XjiIOvOEXK5A4BXoM1MB3vmGbforb0qwygbYi2e6wWO7lxlo4dA+7eyzz0bNwd1Y+fSj/Oc71L9hrdrnbQMX8D1PXrQM5c1K6I07Sl8UB0vRWLSXH0LTnk16Z6+VN+ObQB38c3+FOhEAjgkPB81vUSUNpuR0xOQUgWtHGJxItBjyx8xmM9ra2tDa2kqS6PQbUOYRK9WWI97iwFVXEpNO95CuIgIyjhTnv97mqdMypNFT3OAx+Ckp4S19yVKqk+1Y9cKf6SJSC/1w2PWj3gCK7F1SVg4O1+7qL+J5IxCdnoPajatgbW5gXc8bKF8VKUmka01QQeNrm8iHkxk0S+FYGOKThkTKuZPjyK9h9cXSyElU2U8Yie3oCHKQMlUewkkCTqNZ1LHEs7kkGlhdssfOJSQkhBXzZBs5ZvRovPX7Ozh4zUPjF2HmFvsBKJKGZku839HIjUd/+hlLUPPtSgbxCpWxPRYmQHxzbMs4u5ylEhCLGuSdp7JC6KJjCbTRNGBGShrD6dklhglGYmKiAJJLGbq6fKPyTlMcDpb24AJ1rI4vVHKh3Hhaej0dmpREMRGGi610zh44T8io3GYXPELL1Xlcr2qKhd6SBGN8MqLSssgcmDB58mSsfuUZNB4XLs4zBN6HA7l3bwAFKdCGKNniG0mbvRgnv3xfdlh7HiVgVgTaoJfe44vdoNPiZ+TiTaDBbfR0GmT2Ac3RSsEaL55AAkAPl4C44gnfC7NlieEYJCdTm5qa0OsK68QmoPl4jSgZ5Byodx7za3VhRGd9JWJMEnIyZWSmKzOZeWlJLj/p7LKjgx6wsqoV5SdOovWwLKQ/Ia8QO2qO4vAGEfPkK9010Hv2RktUpjroprUhCk1YEvWjZkqOkrX8QV6L8Tw/4BnpMqvIJMwvLoI8cSwk3qswJ1OpZ+Gyz0N9ylU3bgRWfHIcts426M2W781FMZlMgnywSmWJdO3MwtOjGUCuxjOq2pELmnkVq8d+z6RFhtWmvJ9JWj/Wj7lmFV1O19mwRcaqNUdxaMMRHsw9pPR+GcplCAWgKIzo6uoUerm7O/jEEV50QJeaA3vdicUE1kT68b7pl58xeL+5LQoLl86UYFTr1Tv3kagpi6emkh1paIV7ZfxsdVLSQGf4ViMGvN+2ibydYvL9TX7i01zMO326QkA4brp1a/ClkV3UngdzHfWu1qBDeYUd48YSg+32AMgsVPAW+rvaq7TE5ggYRUL+MOW44iJZ2M9nX4ax1wmeRjTgnUu8vUtRHN9aVy3YWTj5KjnDvcVbvxXP6bl/VVwIeeGtq8m6XUso0eBq3UDg7XR/Jodo+KThymjl1t3jUtPh79G0AxlYgRE0etKxCdl4D2MIUN8t8ubOBW4nXjd7NjBrFnDppcCjxNYvvDB0ka9J3Z/PaU7EgYOK7mzzcud5MVx/OdBwYges6BafBZCG4rj7oBYd9wZQLKTVWF0p/JdwaHiPA8IQU7u4L6OkUTn2ql+cKQlH+MDPyNq/razD5oe0ulSNaxUjjc4Q1s2XIhHb4OtnEYXAJ8ST9iPFLXlXXeXP3pGTSV7mAw/47Kjil+BwdhyWZDQ3yWKhgtZOj3/vGmu9fZYldQwg+MNmRXJl7E9BhXLdh6Nyf4l2xvjpYTE3zm05Mul3y/dnMGikRl3+xxU0ouSpi6+RcPzxMK7l2wmSLrQE1pDaXIc8/6FP6o71RHgbEI3r51QEnffAWZL77weefBKoCrB2Eqd/rOpGj5xjZKljNept4z5Puhp1NGg6tHHuQRmjUolYuZ3eqUe2XEl3XI48uVyNA6nvxwjA404JQN5cgkDYWV6ybeqSW+4TLEkOMaWLqXdlext0HEiWnU/Q95fSdXqowy6fMl6S9Bbi20c/CXkTrp8R8ww1yqSXYK2NyOxqFAqggrWD5Bkte8WEvzeVYskiZxBzANx6K/A//+N/zwcGsIU0jTY6GocPdWHaFKUGiEHiiVd2czzuS3897E4njxFj5H2YLm/BfHktbLFfUx806k9VhXL7j43EoProobCi5/xgUTGxcBQw7Zd4AZJNBOLVpP9zFy0dQbTtKYQzy9Nmd4W3aESZgqtPK4jaogg9YSZSqpwx+MkHY/Hcq8Gvy1XeV1wR2NnmAe2ITcGBQ8pAa25XyJfYvi9qYMtfdxGEW6VpeE5zCy7VvoePxj4oZuNFAsA3ucd3rP6YbEd425imp6fDEWWBo3gqT/BkJF/jfx+WTmg0LA/rGm4AybYEq1gm7wlfkOS1BI9j++kwPR7YWMylgkEbTzXzZ/4ZPCYzUnwqz7sRapRtXEuHMgfElHxqLo++s5XVfPcpA6hOAf748OZvoZftyMnJCSuHlZubC9kUA9vIWZDS84Ve++VtlXjlTVlZTD0UgCqLY/UlGQLHOsuQgCpimNHkLhWR16MdwKBltbtjb2ipTU0NwkZJVWrJMz+ghi3YBeIdTrVpp7bdj9TcKJbfioQEcvsTG6W1b7yMmTNnhlVBxQ/HdRyWuHh0JWTBOWYu7NFJePtD4JpbJLy/InC5IbceNeDR3i6J1SMCNZfkzUMFzsIxTPTaC3E8vdYHAVRD8huld4a0xYG2jhP9wGrUkopdeyQxK4vrYOuIlSZG9WB091bo5EHOwKooY7fj6KmyUJcUsh1bcWDj10snL7oQZ5xxBr744ouQhIbJB9tNptw1NTXk3I1CVJYTneV78OJr7fiSHNb/ukepi+nbulX22UiOcFRuYB80SS2KLkc8LGQNT6r+HksjS5gtyJ7OkzQ1mDsrOIArVwbeeYztID+jMzED1oaTohh41EilCm5i2jbcWjYddkmP44bhqDCOgJySgwZDFirJN62SMkm8UtBMGqRFihc20Lv1HjjslJ0oiwiAaruVU1QfPfmHqJueflWaOnUqtm4Nb2lGZqZsM6qrq9EtE6PMm4hoazvKjpbgjockPPnfsg+IPC44/MRkoLdXJmYXEzjtQjLIkRZmlwfVCTvp6EAU7NiD1KDfe/SiKgSzCNu2AZ98ElrTdDkTyE4bsGtXr5jty9v3ufxIlsAC635xjE3iGp8AJoN0RSfMaJXiUN9qwP1lZRxe3RspFcpSWM6pnc6WJum9xx5CUUG+KLYJt3EqxZULY8ntNBAoo2fTw8p45K++S8h09yogdqiFfrogAHKbT7c2nWRPEqkMK3l7rUHBS6bx/rszysR6ZgE1WAXw6quhF8JQojKkRslM7KbuPl6pfCfZz+QvfRBzqycI42lQ5coV6D1Y6tqudnvEAFRB/Bednj+xrwQfPf1HTJ82FdnhrL+hNgbQ4rV8O0ujpnCCCP5+usbzOdcevq6liEMByG0iufGLcUTYvb6RGO9mRi/uGlmKq68IjAyrzC1bgMsvDx1Wc/EBKTlLlDTu2OGf+PC083BnXvFC86Sw2IhsjSiAXqr0w/3r1+CTF5/CnDlzaLQlh31xjugbvGbidJu4/sCAD71UVYcKYKO6nJk+Jrw9oWLpmbcgK6Azr6N3fpFeiltvsgecxcuhu88+A5YtAz0bcM89visy+Us3iUwNb7cal4R9+yURnO47Bz96AF7O9l0CwPU8XSHiAKolE1fS8U0J+YYrXngC84jUWCzh+T1s9LOysrwCvE5oM4tQWQVU1/oCyElRoys5GKKxM/85+YO9gVdJwUUxZXjo1z0IVE/Equ9DYslLlyrxTOZdw4YpYbVgsXxXcFtOzUVPN9nz1P5xT3OYAJ44qRzULWsH64KEnGFe1g17YTTeoZcTGk4cy609UYF5Sy7qra6p6bLZxBofLP5W2W4zaCWHZDQ4oNd6jiijRthBXmRcQ3rFaNRB31aFkUUyLPESalt09LaWc4FSly7DZs4u6nBdM9DxFQq0zYjSaHllQT9HPlrsT19X46Sxo+HMlL+DCIt12jRINBalb79F77PPorOuDs4pU6Dr7ETPsWOC8vb7bRqEstVq1UkmM3QNZdL4MTIKi5Q0ER+cqc9I6r/slr/2yZfKXhwE4Djq4zeorwdc8v//BRgAwXg35mbuwIYAAAAASUVORK5CYII=') - - e_blank_stare = ('blank stare', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpkNTJlMTYxMC0xNThlLTlhNDItYTY0Ni0yNjViYjMyYzFkMDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6M0VCODlFNkMyOUM0MTFFREFCQUVDNUFGRTg5RUYwMEMiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6M0VCODlFNkIyOUM0MTFFREFCQUVDNUFGRTg5RUYwMEMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ZDUyZTE2MTAtMTU4ZS05YTQyLWE2NDYtMjY1YmIzMmMxZDA4IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOmQ1MmUxNjEwLTE1OGUtOWE0Mi1hNjQ2LTI2NWJiMzJjMWQwOCIv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') - - e_cool = ('cool', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpkNTJlMTYxMC0xNThlLTlhNDItYTY0Ni0yNjViYjMyYzFkMDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NjAxMTUyM0IyOUM1MTFFRDk4RDdDMzgwQzNCOTA1RjAiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NjAxMTUyM0EyOUM1MTFFRDk4RDdDMzgwQzNCOTA1RjAiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ZDUyZTE2MTAtMTU4ZS05YTQyLWE2NDYtMjY1YmIzMmMxZDA4IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOmQ1MmUxNjEwLTE1OGUtOWE0Mi1hNjQ2LTI2NWJiMzJjMWQwOCIv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') - - e_eye_roll = ('eye roll', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpkNTJlMTYxMC0xNThlLTlhNDItYTY0Ni0yNjViYjMyYzFkMDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MzM4ODc4MTcyOUM1MTFFREE0MUJDMzNDMUNBNDM4NTIiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MzM4ODc4MTYyOUM1MTFFREE0MUJDMzNDMUNBNDM4NTIiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ZDUyZTE2MTAtMTU4ZS05YTQyLWE2NDYtMjY1YmIzMmMxZDA4IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOmQ1MmUxNjEwLTE1OGUtOWE0Mi1hNjQ2LTI2NWJiMzJjMWQwOCIv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') - - e_ok = ('ok', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjRBNkQ4QkZEMkMzNjExRURBNDc3RUQ0NkI0MTM2OTdEIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjRBNkQ4QkZFMkMzNjExRURBNDc3RUQ0NkI0MTM2OTdEIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NEE2RDhCRkIyQzM2MTFFREE0NzdFRDQ2QjQxMzY5N0QiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NEE2RDhCRkMyQzM2MTFFREE0NzdFRDQ2QjQxMzY5N0QiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6AqwGBAAAurklEQVR42ux9CXxb1Znvd6/2xZZteY2T2Nl3kkASSAiEAAmQAqGUaaHThdJOO12ZPh5thzedaaedefPovLbMtJ1uTAvdC20pBQoJS0IWAoFskJAQJ7ETO94tW5ZkrffO/zv3XulKluQlcUrSnh8HycrV1bnf/3z7d86RVFWlv7Tzt8l/IcH53aQL4SHW+cmNFzu6A91lejYn+pD+t4Ie1N8HN/eKv8/rxtJTepsD48XLPPTZ6A3oU9Hr0csliSrw6kcvw3PYxzxzJQFmH77bi9cAOr82o59EP4H+JnoLgFb/AuDowGLuuQx9JfpyEHgFxjc59zpfKVCsJ7WuhiQ/ICz3EXk90AUWIgsUgsetXWezgSXRwxHt72SSKBLV3g+BJwdDQK8fqPUBtVZS2ztI4mtyQI5iDPvxdjf6y+jbAGjLXwDMgDYJL+9C3wBiXYXxsMgjj4fUVctJWrIQbAcIK8FnJR4GRRJUzahuvFdTunQ886bgNtEY2BHAtncSHTlGtOtVUt86RpJh6+Hnm/D+abx9DH0LAE39WQGoc9p70O9Cv5Jp4i8n9ebrSVq+lGgKBKTDYcX/IC2dQM8OjB3o9joiK9gvBTYKgylC6OGDoHr0HBBKA/XNt4g2bSUVoApAAWYPXn+GS74LIA9f0AACuDK8fBYP/Un8rh8iTn3PLSStW0NUUyOT7JoB1ptL5IbKc0DdyVYTa0Q1wIKQYpEjGHnyTyq6hjCcN6Ahf/Yo0aG30h9vRv83APn8BQUggGOx+HcA7j78XkltNanvuomka6+UyOOfBaUGtee9CAqsJFeggcMAVnCnBp4Se1saEsyVj/2RaOtOTQSjPYv+BQD52nkPIMC7AsA9iN+ZBaNDveu9JF15uZuk8itgO0J62iqHfykF62IA1OjfRpToOm9M+uY2ooceIdqxkykrlPI30P8RQEbOOwABHMu//4t+D1uCd95B0i03eshafb0GnOwc/qV4B8xCSKHgrj+5iBw3iHiEQ01ETzxF1HRU6MjjoPFtAHHveQMg6zoM/DHce82cmUSfv1umyfOuhsd2I8SkKz9wPU/Arn9VTN3zuSUw796AB5kC/70Edf3UU6RCrMZBi/cDxEfe9gACvCqAtwX3nX8dMLv7k3VknfJBWJPThl0bSyUp3PsCBftfowEqJR5Kv7BzgCn88oikOXRh8lCCbOLfB8iX93djMGyHJNeoxiirCn4tmPffHLiTSw/clNAgWeAhcC9RB8VnToqKztfwtWVqf9Z3uLX3Ep3u1d63nib68UOkhkOCzp8AiP/1tgUQ4PkA3g5FsizwfOXLNHv5pbSqZja4zikAYRC4JyFd94Zl+inUWzBFF0xjwBlMBtseGyBPaoC8ygDZokGy/uBbqvLKy0zruwDij952AAI8C8DbjNutHfrGQ+RZ8n66NY99wpr9MczOTYHzXViOrblTQVr9lTUq7d/HNL8WIL5wtgA8W9mIf8a91lruvY+ki/KDx+3n4Lpn/szA4xaxlNLev39cUqpqJUz0RzDha8/WveWzwH0r2O9xXruW9q35Kt1eALzn+om2BenPtnU7plDbV38mQUpxAP77bwsAAZ6MGfVfissr7/nYj+j2KiJrnjsGYJ39rpf+7Nub1VeT+pGP89ubQLubzsY9pTME8Ha8/ILu+zIdv/If6XM5uQOrMFmS9PvOfmoKdpEbPi13VvSGleeDbSlBqPLndjZ31Lh4L1PGWjSuNTezdZjb+D5u3X9WcKcg7pTX7IdRFZY8wz43LF9hDeNO4h6Sdg++F/89BNuTrV++li1mfmUrOaI/5QBGHSYvwajLurc3GaBLPzyTLMG+w1A7C84kL8k60HpG6Et0n81K6p2zd0gXlX6TKpSpwhJjAvKr5hN00Qf6/ono7Zo/nSCF3Ie5daIdLo7sokG5jAYtWg/hfeuVHtr7h765uOxm0rIa427WM+C+NZgAi65dQ3Sb7xVMrXfi05488nPTuMDj3BynduJxzUEWnBHO0JsDyqk8boi4PjH8c5EnzCNvXE5ws84kDruWRzSul6EO3K7x0celp5gdypDolcn29L8NzCfa96SYPJ/5kwGIJoT5xhtYxi3Pr05FXHNXxuEGcXcC6/0HiTq7tWRrHMSO6mDw3xzFGBp6ezGp1cIprgzALpcGrtetJZinNxBdDlOucaopKFCkRoC/s/gigLiP1oIR5p5JKso6Tu7zQnzeMm8W0TQedOkl+S/sfxGzLCHyaY8/Q/Twr7RM+PnWkphcyUgmu5/btmGOPoRn43zmJ+8imgQnQQa3Q72kpUduW75MAMjtr9G/eK458EaA4ljNBRAWGAHOhjy6RREAMof96zfAebvz21Aq10Lw00qyqItQOePOn/G/WaxaBl7SuFtcK+lykD+T8hvRqsWSLS+VVCalPiy6kKGwhOvIuE68V/CZomX9OeohZLYqxAUbXuIaU9u9l+gTnwMa9xBdshhcaCsMYANI5naTCmnz7j8FgLfy/67k6hX33PziM/wGpm2A7v/PbPBSvmpKltWQ4vTqQJ3fTUrEyBLqI2tvG95HKQLx/6X7ib7+FQAIERsqoA64fmfJEpJ27qTZZyJG5XGIT/b9rpneSFTNTrt7Tv4LB7bRs5CgL75k/JKFYlMXUnzSbFLcvvMKPDUJNRCPocehEeLa37oFpdoclCyvo+j0iylVUpnW9TxxrSNQd87s9Ntrz6UjfxGkScWSBfpfzsY8SiNAaugN+qkpgRKfNIcUT9n5yWUQ5amBACW7OyjZhd7ZTsmONkq0t5IS0sNLsGri9XhGl1ZZ0NJK9OoIWcApk9OS/qpzCSAXItHSRfzjXHxUn4f7dtC+1xU63aGLTW85ZmfFeSwnJbL4qzS5l6U/FQDbT8neLk134rpEzfSMcbNzBFcD1uzUKeJr15xLAJfx/+bOIq1STMpVo4ooiUiLTgYQOu+813UQ+RZfeX4RCz8oFdBihcyBql1zHrnwKRQuft9pjQL7MqimaecEQMyWi7lOk30ZUe6X2yJNpMR6afvLGd2X8lbQhdBkl4ckW34HTxmKkBLVLJZUaZUe6iI6cKD4PWszeYmlEw6gXtM5b6YxV+x5OCv4Eh2EPTUQzIjPQub+eQliSWnBfzP0YdJXlf7szTdHADBDwsXnggNncg6x0Qha26pzZAmcvsE9tOd1k/j0+ulCarLLnYm95YpSWKrsI7IIVe1a4VZzixYWLNQqMuSZey4AnMH/m1RnAJgDzuA+UYS71wTg+Wp5FiWa21PA32BRqim9lFt7bgavuchqCq7aqygXqmnWuQOwtgCAEJ/syB4+qoPn8JBqtV14ALrchcWorgfNE/doU/H7VVdnaDvRAArhWWOIeIvXJCsHicJvCstLr1C+ILlPGHJsyFjkwmIUBDA/+4kTxe9X5RcGTylsDM9EAyiEZ3mZ/lVzsnJwr3Ahjphmm+HUXohNdrgKi9FYVMRxDXfi9On8qS+jlWbsokkTDWCli/WzjYZblkEt4PnWMROATs8FC6BkL5wvElxoen4Gr7Oz8L28GUFWOaEAQtFWl/v04I+Z+5IDREOa4ms+lfH/jBk4upFYKTRp9riIqeB3BiePwojDpIuXVo3rN1SLjWIm96CQP5gNYAaZ9o4iHJi5rGqiObDM5czz1cHXhOzgLDknag0DZmwoJOnQnffT0dvuI8VqHzVwTbfcQ7u++AS+MwpjSVXo2M1/R53LbtRSU6MErmvpetr76QezviMALFBRpOolAWYAO4us0+FksYHlWAG0jpEDPZ60ASYNE5/mWaY43GOe5VM3/zc13XqvIFhZ06tUs/txqji8k2STIxXzVVPXxTdQ95JraKiqgVRwle/4HvI1vz46K+zFX9D+v/02nVr7fqrd/QSVH95B7q5mLe9nCBSIvsGpC6l3/mrqm38lxUsqaOqzD5Iz0JFFDA6vqfmUGywS/lw10aCvSFWeM7PWxz2hAHISN82BRmI1GSCKamZWh2mWGY7sWFotAOtdcAUF5lxGgdmXii5+Sk+cqiKJmz3tHYF2WvTgPaP+jZKTb1Dj09+j5hs+Ts3XfVR0ORknW7hfcKhic1HCk70Go2rfJpr6/MN5qGctbJ1gzKrgUkkQjlf4FvQF7eMHcKwi1J0JQuhfDb5CRqlRT58JQJtjXLpmwY/vpeo9z5C5XIxFV1Y2Xjf3Kt7cTsv//fasrProuPDnNPO395MlppceQmQzZ8fKarPAs8TCNO3Jb9GcX39VqzDIlUiWImJY52jVpk3kgYHCl1rOIDU6Vg60mEVIRv9pLTCQrTvG22Y/8lWasuUhOnHDJyDKFkCklWgiK5UUnOI7sZ8anvkeOQbGvwC0dvcfyH/oRYjr66l/5iUU9U8BkFayRQbJ2XOSyo7tocoDz5E1WiSdUESP8roySaeDREMUiaQzTkW11IQCOKzFYbFEM3GiAXPpvNV+Rrd2dZ+i+Q///YS6ArbwANVv/5Xo4/MlpKKzXbzoxhX/yUVR3uK2nW+i3YhsgR/ak/UnlxJkxN6Fv4uXVOwZjeIoE5cm4iPeMjahAKJF0lVWPL7BbACj0SwFQRd+GwUHmgIehSrUTEb20ERzYCwWM8WMotlh9iyDTJLoL420CmCDPgUANAEbnlAAMamG4kbZOldd05/5VpWj2apzFNckM0sBEhMtQvtCIRMH5jqkjmw/6MLHb+Q1H5KJDs4CrrGp4rt3ojmwJxjKIMfi1LyOISu+azzchQykooxsoZpANvt7vAgnrhs1QxnboW+i3YjeQW3HBfrJozL97BFVSIiN75DpEx9MUYkpPSilEkDaRUokTLK39MLkwGI5Ih1AyaT43HqcZdOzFtqyRQN29RUS+cuUiefAdX5aS9renPTz30j009/IpM64mGjOCnr8aYn2vUFUakr/GXs3KuHQhcuBycTIxot+Da9q4shbayvRlq0g4uzlRLOW0faXLHTg9TQMl4HO6886gOurrd+SLJZNFqf7agmOKXMfNSwEYn4iDj05PSKMVmWqsOB1AkZEgkvuLkQDphgHGj4ir50QHnppJtghcTLYW0ZUUk7UeBGdaOHyWpsK+n5XslifWF9jfeisiVDMiA1A4W8nXfMuSxx492z9PSkSplNZdVrHqUOD1DhFW+uXC6CEqacMBovWkeS2/pnLaGD6UnJ1nyRn32myB7tF1MQSn/iFg4rNQQl3KcXKaihaMUlkPDgz4jueXSfPaySKWpgAkMWnpMdpjeqzmhqum4lAQoFYHKVhJgADqPGoVLZqg8Nls1Lbs4++F3R/anMv/eqMAMRNSjAjHipfsMxiLy2nntOnRZJWKjfVg/Z3k9tjoRmNSlYoTYoN6QDaSQkNarrQPbocIRPMGhmg5g2fon4W02m9miRbJEhWTBjWsRIMBCMgzcQsGrc0gwTCKXqwPeVwkypbBWhJdHMukscx7alvk6d9eFWSkbQtzIEW0CAzHr9e2yw2r/XZKNTfiT/0+szqBqKuFgrCHC2dPJn8F6209h7Y+f11/tRmgNg3bgAhBj5ndXtLfTMXUTQapXgE+gzEo5mmIuK+NrrxmqTQ2WU+bQtkDmrLsVCaAwWhgv0kO11Zjm2x5j19lBb+8G4RzG698g7qm7da1Jlwbi4+gesseJL439xO9dt+SSUnDxaeBEXUgshS4DnlaEb/myqwadWlCdq8E8xgAMgM0XqEkpFBWPVDVDJ9Hg22HHHG+3u/CMp9dlwAgvuYSvdULLrMzuiEeYF6Xwem0iTYw/rX4hCTwT66cV1GlMyaQfTKHhIiQkrGSTLygtAXqWCALGVjK/RlIs776T9QwltOXUvWiQTrQOOis1vtDU7mhLD/4ItUtX8z2UKB4pfDQFPjhQObkp5iNwOYrqVFW3aJSps2Y5azxHDqG34zmKBvqLySXC4XVSxcYe/Y9tSngMP94ML2UQPI22YRV59J0vtsJWUWd91UsZ0FA6gOdJM02bQesLeNZsy0U01VRpzMmq4BKB4AYlAtrYKCtuChU7BIwwDUAVHqHTONmaj1238tetLto4FpSwR3BmFMRaCnWPyNWvGDsO7OEyK5W3LyEJVBv7HIHrWeDBW/VtIr1uRIMO3/mTmQMxKN0210oqcN9NTqgCQAqGISRSIRuJcKOasmkb28Uon39wBE5Tu4pAtAJooCKLaKtFj3qqlkI+uUkgYNLGZrRSht+CuuDPGlQAe9853ZuoA3KuetiMXAw/1ioYfkhJ4JaXu6pPoDgnvGYtQMGzSI7T+4VfS0Re/0UtRfLzg1ZXNCt8EHtbtJjkdg/ERF1t2OCchGkTU6ftdGjQ4JfV4YPS45dArrU9KNroapmgthbqtWxKnlNx2k6gASg86Ja3yP6e3xeKhk2jx7z2tb78O/3gdc2tb5kxcDxK6CAEqS/Gmb1zep9ooN1LHtSW29OhrPChrsJanCJAdAFC4jX56zpmb+bG2HBk4tyWGtjoB1n6IDyBMj1ddDqreELLxQ5Cyt1GVQvG1HJtA8TQngUsGBoiFgoTLAcvJgZsuVGXlqrmfN1A0hQ4zydzEBaaCHwqVlAkAVvwk8qO6qjdT10qbqWKD782CBewr6gZLV+qHSmQvtFswGZ1W9CBWx+GQAVSjYtOvAbbCP/NUOYbhkiTrYLBfNp7QPxHpA4hmZMwUZ0ERHGyV7OsUiSSaOygWxHAD4U5znxO5QIiHGwGPhlUZiVW5vNyU7T1OivU2Mc6SxyXq4xTKYCarMzrPqgdWkvwYzPWgKvvgqhUsmJJ6e0XfVTCYL6AdcbOCw9xcUobyDHsTkNHftlHSw2urypG+mXZ0xsdVQP61Ymj8/csVKot37dDEa7BHldexCiNmbJY/wXywmer5QlGTRd6KQpPRuFZLxPjfiUSxOqccjBe35vaKKVzX9/ixNGLY8eQ0hLFlLWDOEfJjg9fX5L586KU69zSaasHHIYpTTPqC7BbaCGtDqNBlIqLZK4DQTYrQpnwi9CoBFLU63MBsVsLcNrByMRHR3ILtIScJMmTsjfySCN7154PtaftACJzxR3Uiyx0spOPSjJhZHOniDlpwigLdzAoufUSzHZvGpP+eSxYVToxZZ1dyyLCmoMQkbjeUlZZTS/U0Z/jSMylhisP8q/Nk0TITCd7kGKKdRUnj7DI9Pcx84o2Cu82Ti4oedBcpeOKht6EaxDQfELc8s2XPhrpUQ3Kc/nyWQsfp5R6ZCLcjzmZejmaUFhyZ1Q0bmCI0pGA58nFBF1+TVgZJsWe2oqEnPFRkcNwTnXZwvyP6etyzLgOEfPXW68OBuus400/QHspT6Rh2NOd/As/qrhAMvY2LLekSINzCoq8v/FQ47Hj9B2p7JMVNQgN0h3spEd90gEdP/5KyoweXS6mEA8tJpJZmY5ajIGCkWyPLBQZ29OWZnthbxgxx8fXV/TnA+pakU4axCdEyqMdyJgBClQryU+8WOD8XWFpw3Dc8jw5q21UwS/q0I9XUeT//zZZcV/uqpk2JTPgkiM5IFIMtbuyYIQ6FQFoD2iioCTvUc4szVgRfBhRA6L2Pe2DMFMLklgrEhEYk/0uKgO/+XRNV+lRrr43DoVeIlERfNg4UFSXDbzUT/8QP9x2HipyBKE3C62a3gnrb4eFGkcv4c58crk9hYEdKEjSgumB3oJFtXi4g+iTgqSLloYcaeaoO0amsj6u6RqKvXRu0dMMhsnNFIOKRYTlhOp3c8HieH6Qgim6eUZKstCRB5d8HnzQAut/sqEpKUYbNosghBK2p5xkmsG9sBZHtXjPa1DgmnWQ0HwbASXXOVQlevUejKy4le3GFYpN3CKuU9Y3jLLd4AgU1k/lHhQkBhK2JHpFiGld8OgME3EhzGnV0iPbUuQZVYB7oEeEbayIi0fOB9WgRm6zaZntsiUzIBaQn9xgtyJF61VcZ+hIVVl4WKLISN5ZABUlId6mpblgUgFOPlzsrarIqNRDH6sbnrq8oNQGgWIkzzZKCLnnn+MCUgU2/YkKJqiNI/Pm3UfqjCRxJ+Em9BgsHzNiS8/ZZa4ksrZbGlFftlvK0Vr/YR21slJ9YM5RQQ/FUBGLhAvNpM6gOsJA8FRYRJDvWRHBse0J4PH3jjTdqizee2WOi5raDVlLmCXlxiONZavQSmN0fBZF3lwE6xw6FfA/68PwOgJK+0l2UDMt61DcJvA4fySHe9coSuXZuiSy6BOFlEtPMlzMjt4O5IxnlOg0laFTMDKdbWwwITr7lGDwcX2CoWr4omn1TdrxNcm8evE3a8pL/I6d0RRdJV71Lu2gsGKxYmOdhPEowSDkjIQwUq8fC1eXPgh12lGS5G27Ub5K3HP5zBRkeMA/vhxsR2lFfy86X397RCIdogUxvsZZkUDSPOIaERJzuLDbZIGezc1UjsR5pUJxc8XYV50+e00RuHwVB94NR+ED2Z+RXOYLCItZh2/uVcnepwiUUi/DC86knh96wnAPi4N1HgSEcKz5mMaXHLRDT9KseHhHgcqVm8sD7LYTtUyLThhgRVlmRTjKvQwvnuY9CNaTYSo+DfzVxrL/OzIVOjGzKDzIELOLoBJzEjSUB5K2R9IlGg5mMAFmXHCVUNDcAMkxVwkixEjbtMcI4Ao+cUOatVOnyEaK4pgRGO8TmOsujc1k5PUDSgiK04Tp7Mqe7m+yhJETTIdXizZikvpOE16bKc2WtU56j0HqCKttenyJJzNlwdm9HEzFkFIdXYoMU2d7XbqSecIW04KmUBeOwYuMWK3zndhEka0yQAJ3jDA1o2X7YkMSYr9KJKtY1SIS61QKSznZDmOHcJb76XgDrhjYG2M4DzrZ7SGMRo1npoK744DEB+6JZDpPZ1cKDu6/jgaxhECR7uUJk7Ybvxum5p9/4+gAZilVZQR9JDD/+sjT7wXoXm6iug48lsLbBwtkolrnR8gHohTTs60TuI2tu194FA8QAOZ+eJM/RnSRVynJJLH3gXJfbjOBXE7811nScTCgDMuFZxU8DoGDyJB38sk+qvJ8kLfdHZQpOnWMhXmaKDWo744c3dqQ+KnOtQ6B71xOufk8o6rdS4cFie02YbLmHspeVJ6MF5BoBTYZ4OSwk4Mdqh3M2rT/IeWt09APLyzT1knF3ZhYH8Q2CA7ufinEAQt6quF4rbMGwOHDwNALUndNhUMq8pKHGpWbO8slLrCxdkfpZDcry+jhdJBvoghgPsI2lGEQeKOLvDET/2Q2MFKh3YImRaMDi8qQDHnHlDc37P8UrebKccvax8dBudl+ZcYzcFJQ+DTGo5LPWp87QP2o5SYKANEzLFCZ52TMa7+WOtXCL1f0C/H9Jg3zZqPlhP0xYNw2GYVPX6HACwwTBiai1u7zCvmrPCgUAgK/qi9rZxIeil+OHjOZf/f/Q121+md5AMEbV4Vlb00uXMiCvHOFQWE7+iQus0fXTfMUQxJ0GsVjrrLZfbXTY1S99LJgtCmjSDIvtP8S4sin6eYNZ6Xfx9Yp0/voICnaek2mmyOeeaD0A49zJcGVGPgTdQw5bhT2jHKLLYV9Q3SozEsI2j9MMr7uC5JrFPY94MADrH4848TK6ijyVoQho/N/eJAE9MENO42ait8GaeS2SUzBuksViEzwsN/HvQ6qUCt2yHVZwwrzZmNZYPQC7thNVs7NZDQ2qBJcolJabgM2YFwObrb813LQY2KDtczaq3bJh+cpvi4I1V2cZDb+j8XMVkHnd9hSKOJshIL57qOTMTdJHtzmLy4zqVD50xbY7k9eYvPRFulCQJ/SbDmmlJhkOJQgBajSnMCqqmgWN334HMHlYPwYcdw7paLpX4h4XdfKakb0OlQh5HZrY2dZx/6wjjmO8nezLGxoIpyjDuV6M5Tn6pnzM8i8xxTBPtHJLN/iBVTZEM6WWB3igtzV/nk4qEFDWROGnowB1D3adFclPKsYDYvaiERdHZ2allJWoaYUV0+vmUTsjsB3AJ7+7DXrgH7sRHyOGyiWpjyjjqCgBkB56352Jrji39FTNT9MJBbWK8cUqm1XM1MXS+tIOtFmEwCXGJybhwSiqdYdizl2jTJpArEZdkqA/VUE/uUpJcJTJFww+s8ye/ybFqdJ7tM8AUnySrvU6qy9ReMN3lAsnqSOepJPDaagD4Eoc0Yr2d5Kyso3zWaBUcoO7ubk0tz7wYdlTTcinU/7BIe6QSnDJXRXyvYb5kBt+rxCBXLbGmpqT9gf8kaQGs5MtWEC2bnqJ9zRYKwI/qR99zwiI+Ox9aAsPccTgjNdYuSBHH4nftg02/k9TBoHj0Ntlqc3tTQxUha6k2+UV+CfRpfv1OikbuxIeQZlZFBK69ZTJNmpmuLmB6sxGZl/v7ezjQwgPYkjamrquxPeZtmH2zf8nlUmGrLipATKVGJjQbP37Y5T0vPh5PRkJfwfzgk4K+gAe7jTeMLa8gdc4iSTqZtNFgTCIbhnPX1XHye9/+C0af3GOl/S0WcaRAvTdFameSDsI1ZgsFz9eC54N/TD/AXx+1Ot33V699p70X/k88PvICeea4YuBx63vjFRo8dvD5ZzoT16SPYOWz7GSb/dGGmz5oL7Y0msHr7+8XeSo1j2fN+tIHhcfKt//QazRw9MAp6NjZMHCi+u9wpPBv8BO389nyQrKUSSosZwl+P62clRIOtONtlirkR2Xf81CzTMfaZQp2KtTerIhqDzwLn1L9BC77CfrjxnFyHKIEFx70NsyZWbF4pcQ0CwaDBaNbTLNyOKKWETaNOfnkT2OpaORD+J1fmAF0wITtrVl1vYeLZ0ZqDCRni3lWcaCVgXPD1DRM3mhvB7Vv/QOmp3olfijv5vv4TV708A5+CyKsNI7C42lR6Se1ro4kXu0EbhXOtuF8G8742QKZY+HsM4pDuIa04AAHCThwwFGhrm6xXSQXYpvUA53GePlYNu68CGWgwDMugV3xas3q6y2u6slpScYBkoTI5kp4FocoIbSMYrcfpmvH1icwYRQ/fjOUdQjy+mrL9921Uz9Ufdm6M/KcOBDeuunXcSUe/dqmbuUfRvMd3arlKhpOVDKw8/FsczE+T7HYpMtJagm8G46cmO0vccqY6SkYFLO84GhNmCsltdPTiplPHDk5hXFwAIw7b0u1G8RrHi091lfKn4eF+c+T17/bbo5pjqf1vLZVCbUee3RTZ/I9mmQwHQCpplLfi5xu+bDCVcz28f9Q797tKSUZfxN670uj/Q4Iwjb3Dr2bgeUIL5+PxqKXN0Ot0rufwY0MkRedHc9qqI86Dmob23qkg9iY2cY8FTFTReHn5sMAorolyJ1XAPXoFjXv7MmbZraiN2/qGfveLdniV/kaxrIRxF9es+q6cTOHkkxQ6FSTApy+UzAiBGOmqXzB8hmlMxeKAttoXyclBvspwUWusUh6QSNHbrhWw+opIbuvghxlVSIRGm49Rt27X4gDvAXm2sWJbgD6X/ByH59fpBbZJdHedlikq1hdY3ypczi+yVBRR/xLr3CXNM4RielYoIfiwT5KhkFbPnNCrz4TB4w4XWTzlqKXcQZeZIcGm49Q7/4dp4HLZIxdHcaBmtuW/O/+w3u/HGk7bo32dWkJ03R0QUpvExUMqhSKmyNFkOXl1TyoFG76v88leEbMQZ9ZI5h5FvP1/edqcKBH6zq/8qnevdt+GGo+LMcC3Vm05dhpaYkkfOEQZFEwomb54pzETUaHUmCgnxjgZXEgZgiXo/0Trv0IQLXzcuDlS4iWLNJOp6yv1cJD5saJitZ2opchjI4eIzrwBvRKSOimP0LsbJiAWcyykcuELjXEKAcsDFWDPi9VXpu1M9Iw/CIDRsnfj3geGjaZLjp50QifN3PwTA4mLjL+3+HlFq795WKnmdOJVuC1YfJw2vLRs6fbtd2Pee8Brv7r6RW05WD4z3HJF1kPCyOGCQM1cRjScRYfWnjLBg280azD5JDS68czpvaDPxI7tLc+001TztJDczT9KvR3YfS34Ucm/hQRScIcV3l9FZ+9tuVsidr1ldQyfTpN/fCHMpUbCxqpYHF0rhtz4BB8lKfJONKoF59N39SjBlmErmTw3ncb0QfeM8aIfDzbKtRfQwXAYMvoM1CVt0MITMOYbLoISIJpIngdhFQ5nUyJbAc7Sz7cbD1GLyKpnIn2TGogh78W771k4drJcW7nFY3FKRAK6zU0mpiSOZQYDVGyo9mf6jn9MXz8MfzDwDq/+rwubi1WCzVgrGxMeXG5R9UlgMTjlegYzIZf4M9vG35vtpNOQU7Em4fMmZjRAMjfWbxA6089S/TN7wnpw1Lul1Z9hmuncY6x5QZlONgAEGL5xB8eflNKodXgcmlGY/axC5gIvt5+qgsM0Gz2uzgLz0akDEOJ1yh6Jk8XxtLZanx4sbPERz09PcIvE0vehP/hFbtvWKctIksMvtqJ133KYOCdXHbDGfnqKm0Jub8sO6/JdDh6gi5+dR9dgue6ibdkydVVuGYot1IzkRz72BknXneCIV9jALgUfpM6dfLYKxJySzfZv8KN8xkHfwPOuuJL9/LCxjwTAQ+2/1imbILXFv7yl9ABnVYqX7BsQiQlBx9qa2tFdIQT1+bIUgoPxotE5XiIlsMrvfFm7YgcwUmg0pKZeZlf2rqT6F++QWvw/i70B3Nj0NEhyipHGE/pKxuSdZhM7Z3CXyYrBjK1pqrw1pdxslOHVEunITmipPmHbrhtk/CJRej9uHlGKZSznIhPI4GO/eqKpaQCvLyThLlxBgRTR5925iw74jUwq5rbJ75am1M2HEFibhwWrwSoNbUZ8ErAuXUVhSX3mlVEz24lXnLwr3jun4MLzTUp4XhOFC0JLdImVQvahvWYhQMCrJY64NS2g9r5K+P46KOOLmowAKw1L9LsgkH6lLyBNkvr6DXpEnpLmk1qIea0B6jWspPmqEdoLh2mhPtRDhrmlo99GmK18q6/Lk5In0frR05pILackshaWknnonH1QV1dneBE5shMKsZLzSf76fLLtbHNrB/5Xh96L0mv7BVWPde9/JtZYkYtXvqBfAe9RbPpiDSHTtsuAwKFj4qYoR6jpepeukZ9jt6hPklTVO1QjrJSoar8BoAyxxa3SFfRN+TP0pPyO8BCo0yywq9i7uS+FZJjfQVMpNaA28R9XnDfF9as1Mzl0RmBmkg91QrumFtF56qxIVNRUSFiukbWJeXy0QmxAFMd7e4owu1iPQVr8Qt4/m9xzDItMn1++p78MZMcL14gdEyaIfqjdJuosVmrvkCfUf4DdH+cjOCgGNbhWRtprfUFely+efTgCdmXfa2kyXezXfUpzBTfHe8a/S1ZzECaUSqpkqPs7HsNcS4ULqLuWZzW19cLICVXCXxblYKD2dtJj9Te91eCQ1iufcosZKgkpyBoDPsD8Jifl66mWyyP0a6ln8zMAfxQMBmO1o+LGjkD4DpaE/e5gO+9qy8dPfcx57FpbZwzlFvun69V+aJ07cXQIv4I9Yfs9MK+OjrekV21MGh1096S2dTsqqOobCe7kqDFoSZaGnyrYF6uurqaeuJDNNj8hhgPi61R7DovGj8vr1J+6VW6F3R4QNeFXAQtjRfALDqFozwOUbNhxaD6Ur0BOhsAyl6n2YL5AKRQxXtuGf3tQrrKP3WKzXwPjRS9XzGnh9579TGyWzPGzsUze+mRF6fRlgPaxixvuafQ9vLFcDZNRbiyjXaXzqMem4+u6XtN+IB5DZyqWgrD/2ltTYldJcK8znWUx0HdcasQo+z7fBD9u/rMkIpJsFG3gQADOGCI0ECip189GwDyviy4sU/3+76wZCGpM8dwNvOgXgd09DgMmPK6otdev6yN7lx/NAs8Q4e+e80JuvEyTeHvKluQBZ65nXBNos3+5aQUCL/Z7KLcgVfSZk2w0TTe8Ggxnp/poG+eBKc2p57JMr7khNrbx9Kg1wCwOdXcjEcYh8meI08kOCkMIN7eBL+v8a82js23ZAB599qOdlVEXAq1W1adpJtXnix6rw3LW+mOtcdpQ88uciqFFViLs5Z2li0qaNhIXr9Yt8HOenCMu2a++2aSQAc2928Gs5VJnpz05ji3Cxs6KsKgIojJU6CJdzGqS5ykNlvj8FlICZqqnhS+SaXaQ2Xw010Q6dxLKYhP29MhqWj4BCfTSjHYu+FsKssWj35DWY6rRjiI26ZZQs4CAK6Dvlt/Sduo7nnFQlame0jertLvq1dTQso/4w95GqlhqJ2mRIefBGOvqKah1rfYcRZFwlyNZh2l5Fu2hGhKPSmnO+huENxXHTpGH1W+n578dWodDaolgpoRMOgA5n6v5AdNa+mkNBUeoSMvHnTqJJOoyQBQaPJaKPXO8sl0pfoirVRfosuUXTSfDlGD2gL+LxzPfRMPE9FDQo+FieB7c13h2o03jC1UaXiPLK5sTjsv4MhrsGwswHntfW7x71aLMgzEZGo/hV5x0tOVhRet7/bNzwugo6KGYlBdLc0qTZ5EMJSIKn2jF1Abryf5Ww/SGrxPTokdpVsV7ZxFjoEuKBIm5xWBp6Qp8K7n0ivSCtoprxKuXn30uLGR+lEDQLE/1cad99Lm9S2g/tgMGlbqET36qe9KK0N1KOvWjG1D9X7dWzr8lkSOyvq86F88qxd2wHB1/ei2Rnoe1mdjTYg+9+7hx9CtXdxOe5qa6PBQg7BE8zU2aIJWD5Ums/dBs8OtkErK6MjRAF2+amwAComxhugHPyEFbojVdNDjiMYQqzRmngZqoevUZxhROJRe+uGe+fSUdslbaR3IJmn8tX1jBi93ICV6IfGKpSS7x3B4J7sObCCEwrwRgErO6skFXYZ8rbtfs1Y7Aq6Ci1Jn1w/QpFhP0XHkE7FcIql4K8V6P460sR4cSxCac32XXqJNZvMeEp5xVK14AaG09xXjT7EXlqwnL3e/eTRvpeDIAzSJaWNf6NljPFC7R6/pOn6M9P3B8qcTZSn/AG+HsXId9OLHbzxc0GoKhBwUsRSmGkc6vKlIXgBFWXxKOw9erGEMju35DHr4TJXy7nGWHQEnjgqdMHbylfWY7ZbgIEktp8Z+Q06rGNKuXFdbyTGkQM0EefMwwMNNrGPcT7TcG6eNsExn1eenbGuPh3Ycq6Mj7qkF7zENRoxDSeS1RK2lFWR1OsRqY/OEG20z6OE3ZcSc4yiL5IgQr8FUFG2HijSApG9Zwen78XgSbp0LeZEku4ZjmQgDYU0kcajqjUPQf7WFHUerZewionvASQ/8YQH90XcpDVnyr0d3pWK0sr/wEa6cekqWVNO+/VI6WjQ4BpeC6cF0Ka/ISK3xrAXZfzCdctuSC+AuPthqPAAaaRYt0KCtIT98dPTf7dC39GYdw3upcPK2YNbAOjZflUNrX//dQvqtcxWdduTPbNiVJF3fu4s8qWjRbIVUXktDEZWaT2SPezTtEDh3yuRMErvENT46789s4f1cFoCQp+zpbnntAKnxxPgBFNH4adpJ1sZp1iM57mGdbvv2s/gsg/twdjLvDN6//3YR/dqxWjjreTlLTdH63pepKl68QE0ssYMlymJ0v86oQdPYizWDFjOm56fXWFTNzt2i0PiQeQ9t2XTB72IxkvbsH4d15Mrowen6QHe8PPL32vVZ3A+d8jq43zVl7lkBrwtW6dcA3i9sVxQF7/qeXcLo+U3NVRSyuItyIJs5yfJ6em1P5rCq0XDhDt1oNHbtZTqNB8CmE6IyTQJOv812NzLtMcZxxyvjCIlKGbHA+0OzO/HsiyPrPkOP7N2nxXmNPbrPpHX0uej/PXoR/XIU4HH7I5z7XviAmypXkFLAhjUWuYqNySHFDxzI+K4j6UKmg7dEUy3GZLeMI4K2PcMQ+QEEW3ZidrwEANXkOIptSj0ZPbh8mTZjmk7kv5YNgZN6yohrILfiIXmLZ9lefNObpDKy5v/V1mm0yXnxqMDjyIwR6GZH/ri7viCAYqdgu1Psd/bClswpNS2dhWtbBA2Owy9elinTLB3nXu9bdwrx2QKcso6Q+R8BBgC9pLEFUlBdmAAAAABJRU5ErkJggg==') - - e_question = ('question', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpkNTJlMTYxMC0xNThlLTlhNDItYTY0Ni0yNjViYjMyYzFkMDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OUQyRkMwMzAyOUM0MTFFRDkyQkQ4Mjk4RjE5NUM0MkUiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OUQyRkMwMkYyOUM0MTFFRDkyQkQ4Mjk4RjE5NUM0MkUiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ZDUyZTE2MTAtMTU4ZS05YTQyLWE2NDYtMjY1YmIzMmMxZDA4IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOmQ1MmUxNjEwLTE1OGUtOWE0Mi1hNjQ2LTI2NWJiMzJjMWQwOCIv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') - - e_skeptic = ('skeptic', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpkNTJlMTYxMC0xNThlLTlhNDItYTY0Ni0yNjViYjMyYzFkMDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6Qzk3MUM5QzIyOUM0MTFFRDg0NjRBMEI1RTRDRkE1NzAiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6Qzk3MUM5QzEyOUM0MTFFRDg0NjRBMEI1RTRDRkE1NzAiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ZDUyZTE2MTAtMTU4ZS05YTQyLWE2NDYtMjY1YmIzMmMxZDA4IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOmQ1MmUxNjEwLTE1OGUtOWE0Mi1hNjQ2LTI2NWJiMzJjMWQwOCIv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') - - e_sleeping = ('sleeping', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpkNTJlMTYxMC0xNThlLTlhNDItYTY0Ni0yNjViYjMyYzFkMDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6ODcyQzE0MEUyOUM0MTFFREEzRTc5NzhENTQzNDhBQjIiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6ODcyQzE0MEQyOUM0MTFFREEzRTc5NzhENTQzNDhBQjIiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ZDUyZTE2MTAtMTU4ZS05YTQyLWE2NDYtMjY1YmIzMmMxZDA4IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOmQ1MmUxNjEwLTE1OGUtOWE0Mi1hNjQ2LTI2NWJiMzJjMWQwOCIv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') - - e_tear = ('tear', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpkNTJlMTYxMC0xNThlLTlhNDItYTY0Ni0yNjViYjMyYzFkMDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NDlENTU1RjgyOUM1MTFFRDg1RDE4MDJGOEMyQTQzNkEiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NDlENTU1RjcyOUM1MTFFRDg1RDE4MDJGOEMyQTQzNkEiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ZDUyZTE2MTAtMTU4ZS05YTQyLWE2NDYtMjY1YmIzMmMxZDA4IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOmQ1MmUxNjEwLTE1OGUtOWE0Mi1hNjQ2LTI2NWJiMzJjMWQwOCIv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') - - e_upside_down = ('upside down', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpkNTJlMTYxMC0xNThlLTlhNDItYTY0Ni0yNjViYjMyYzFkMDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MjBBNjk1MDcyOUM1MTFFRDk0OEJBMDM2NDEwQkM3RDQiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MjBBNjk1MDYyOUM1MTFFRDk0OEJBMDM2NDEwQkM3RDQiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ZDUyZTE2MTAtMTU4ZS05YTQyLWE2NDYtMjY1YmIzMmMxZDA4IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOmQ1MmUxNjEwLTE1OGUtOWE0Mi1hNjQ2LTI2NWJiMzJjMWQwOCIv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') - - e_wizard = ('wizard', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpkNTJlMTYxMC0xNThlLTlhNDItYTY0Ni0yNjViYjMyYzFkMDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6ODU2RDE3MTgyOUM1MTFFREI0MDFFNTFCRjJGMTE0MUYiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6ODU2RDE3MTcyOUM1MTFFREI0MDFFNTFCRjJGMTE0MUYiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ZDUyZTE2MTAtMTU4ZS05YTQyLWE2NDYtMjY1YmIzMmMxZDA4IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOmQ1MmUxNjEwLTE1OGUtOWE0Mi1hNjQ2LTI2NWJiMzJjMWQwOCIv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') - - e_wave = ('wave', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkRBNTQ1ODFGMzQwQTExRURCNUJCQ0EwMTFGRDI2NUM1IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkRBNTQ1ODIwMzQwQTExRURCNUJCQ0EwMTFGRDI2NUM1Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6REE1NDU4MUQzNDBBMTFFREI1QkJDQTAxMUZEMjY1QzUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6REE1NDU4MUUzNDBBMTFFREI1QkJDQTAxMUZEMjY1QzUiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7BCSZzAAAtj0lEQVR42ux9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') - - e_crazy = ('crazy', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjY5MUNDMzIwMzQwQjExRUQ5NzAwRjUyRTU4MzA2QjkyIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjY5MUNDMzIxMzQwQjExRUQ5NzAwRjUyRTU4MzA2QjkyIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NjkxQ0MzMUUzNDBCMTFFRDk3MDBGNTJFNTgzMDZCOTIiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NjkxQ0MzMUYzNDBCMTFFRDk3MDBGNTJFNTgzMDZCOTIiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5mF7EvAAApLklEQVR42uxdCXhb1ZX+39NqW7a8r7HjJE5C7CxOyELISggJISRhp+x0oExLS/sBLXTo+tF2aAvtULpQaKGFUjpDWQMEQhaykZCd7CFxNifed1u2bG1vzrlPsmRrsWRLtpnO/b5rydJ7T+/d/55z/nPuufdKiqLAt0iShC9auSINWnopplrqfi3kSo8ymh4vI9zr0PEd9HKWztlPr9upfkr1s3UNcA2H5+yNlbjnLxqABBbfYAnVuVQvZtDolqfQY+g8x2gJzlEFUMaOhlSYD6SnAUmJgCke0NB3sqwe5yJYmpqAYyeBsjNAbT1wvgLosPYAtZqu/Tq9/R8Cctv/Axg5YNzcE6nOp7qQbm8h3XKa5/uRI6DMmQVp4gSgIA9INgN63UAaCdh3FDhyAjhZBhw8DFg7usE8Qt8/RW9fHgqp/MIASKAxQMu40u0so1tM4c9ZcmaTzF02D5gwFkhL9UpTtEt1I1BRr0rpuXJgx07g0CFuRQHkUbqnBwjEjf8PoBe0SfSykupyqrMYL76VWQTYkgUE2DggNUU03qCVygagqkF9b5f02GMvxcZzRWh95U3Itk7++E9UHyQg2/8lASTQxtPL7fSTN9FtjOPP4uOAVVcCC+YI9QiNZmi0QJlUhE+lS7DOegn2ambghLFUgMgl23oapX++D84NGzxqdSWBePpfAkACjawU7qB6J9UZ/FlmOn1wI/0zVZWywS5dMGCfNA3bpLnYIc3GJ/Ic1CIzNGMlXTp/5xPQ/eKHkBVnAzXj5QTigf+zABJw0+jl63T5W+gn40wJhOBNqqSlpBhI1OgDe+OgANZCfYiB2iQvxFZpHvZKFwsQ+1NKL7yD1G/fCm1Xh4Weax6B+Nn/GQDdlJ/JyMNUF/FnCwmw264nxlhggJREBi5hMvH2Y9SqW+kOY0PsGpGKrfI8AdYmaSH2S1OJQkaP/Uyo/Rh531gG2d5VS805g0As/8IDSOBdSZf6GV1+mo5o/b23AUsJwnhzLokcvUmaTsARV6/5O+BoiTpgH8uXYYs0H5ulBTgoTSaFF33NkuRswkWde1Fs3YPR217E1r+eZJu4h555DoFoGwwAtTFQlexcP0P1UqMR+Oa9qtRpEomvpCwhb5pcOqeFePorQNueqPxmB+KF/VovL8ZGaZGwZ9EGTAc7Suz7MaF1ByZZP8VF1r3It5UJWygKuTWO2eRu7AD1TDxN9f7BMAdRk0ACjqgInqB6j1YL6cF/By4n11tOLCGHjbyDuEL1wHZypqpfpqdt7fdNO6jf7ZJmCrAYNLZnNuij2jA5qMKlru24RPkUlyrbMU3ZB62zE4eIa7qUwOfY7MCfXwDOnxf/XkVS+MEXQoUSeNfQac9z3PGGFcDdtwD6xJFABlHL+LHuuBX5TXVvAM1bVW84wnJEKsE66QpskC8XarENiVEFrEQ5grnKNixUNgnACpTAZuxsNdAQou/Vk/P/9DNkzV2opPYoJhBbh60KJeDi6eUPVO/KyYLy8x+Qj5RDbDKDWIp5Nvvibp5eSV7x89RFq8K+djOShXR9KF2Jj6QlOC/lRw0smSjMVGU/5itbRJ3r2kbqoz6sczNTQgOYTnpo6VJIa9Ygj/79KdVvDksVSuCNpkPfotMnl04CHvsWkJxPbl3ml8jgmbwHtu4movI3ksCukNdjVrhHmq4CJi8RajFaTFFPCnaGshsLlM2Y59oqJM0ES9DjOah97gJ5NURD4uJEYFzEWD3lOAlne2fw33MSmf7Ds0BVFWlbBSUkhceHlQol8GbRYWvpVPOt15E/d0sc5ByimUkzfH7NSS3xGonSpuDxRmRjrbxUgLZOvgIN3hh1VCTscmUDLndtEIDFoyNwx6HGPn0WOExNfORz4BB5NI1N/scVjwOuXQ7MJ8XS2Kaq0lDl1Cmyhy+Kt+8RgCuGDYAE3iI65D0iKsZv3w/psstHAHlfI5qW7tMFraQyn1P9O98bIM7GTvN78tV4T7pavI9WuUg5rgJGdYFrMzkSgYMCVpKc4yfdgFE9SqB1doX/O9PIbf0uaZtzdUSmnKGPfZmI9jG1CeYTiFuHHEACbzF9/YFOC81PH4NUeslUomtfpi7vE8WwU/et+C3ZvQqVdCJBSBcD9r68XEhdNEq+ch6LlI1YrKwXr7lKZcDj2knwDlMjHjgCHDyqjvu5XKGDZC5jAhSuGh0kexfkjmZIDnv3EYWkUh96gK7dh6dXRVL6zG/F27UE4JVDCiCBN5W+2mY0IO6JH0Aqnkk+QibRTcnHTjkIvPInUe5IwGpppZC0j6XLokLx2WaxOlyqrMUVyjoUKWV9AsaVAVNCkV5ZA1dcIpzxSfSaJN7zZ71aDprWWuir2YdQxW4KubM3f6nv0ZFXXiVJPyLeTicQ9w4JC+XxObrRd+lt/GMPkj2YdZlKVnxKnUOLVy4oeEX5CPu006IiZVOUA1imfIClrrWYo3winOlAvherwv3kXu47CJw8HRowRauHywMWvxoSvCjQicz/4XSQHErqYCN/R9VpzkKX0QT92UOQXA4cOAxMOED3WBr6GRYs6AbwUao3RZuFhutG/IWeLe++O4FZC1SmyfaMI/ZnpFE4oRTgsepkVLiEBup3Ybu1xPWRkLIrXR+Ssq0OSDoYJAaMK9syu70PwBLMBJaZpCwZit7Y83rtFihdnXDZyBA6nb21KSQ6XpNkpleDANueMwb6is/F129Tlx5ZSAw1OYSqJ2eicBTZzLO4jgQhl6SwclABpB+9i15WsPG+9saxqMp9DKelsQK4DuEGAn+kdq7oR+SP2eJMZZcA60rlQ0H15QCZCg2kmfd8plaWsjZL/wHzuwdjHJwEoB94KusS4DrqOiEnJhGQyXAmZcDZWg9NWwM66bTVBOKdd4R+zkuJuZ49A9bL91H98aD5gTx2R/+WSdk5aWOe/qFUPO526HSmHsdvJ6f2pdrwf9CMFixzfYAVyrsCuEBskSWK6TwDtpfU1JkQsX1F1qqAJVDjEmiKIT60HdFoYckbD5lIiUurQ3sWdcTssUg4tRfm7auhaQ/upbMkyokkjQ4bDKf2CVXK5ct3A+PGhgj90WG/eBJKezt4tCKPpNA5WDbwQTonveM/noSt4DboeiULddH13g5jCI8Jx9XKe1jpWi18skC2rL4B2LWf6j4CjaSsKxi1px7F9stJgDForjhT2Hq7duoSWDNHYeTa57o/Syw/guaxM3D4y09Bc/P3kbnuJeS98ww0nf5ZEs62FkgGkmhSp47MkdBVnxKfv7+GnvGB4Pk5nCU3ayakDRuRRf8uZlYacxVK0meitnpILpmEynG34Y4AoceDpMpaHIFVI5OOFa53haSxj+bfm1QfjEHbuU91poP2PFKDzoQUAiyFXs3+LLGvnkstW3bdo6ibvAizfrrS7/vkk7uRdnQrGkoWoGr5V9FcuggXPXkn9I1VfirV2dQAbWYOHMnZ0DZVQerqQC1poJ27gNmXBL+HicRaN6gpUHcOCoBUbqdGTuy492FcHsRIH/DppEZ04irXGqxS3sFy1/tIQ4Pf8V02VSXu2A18SoS6JZi2ItdESJgpRQDXlx3rq5xa+RBqLr4KCVVl0NisAY9JPH9MACic/bxxOPbdVzHxx6ug6eh5kwrpQ2drCzTmZNhJ/erLVYq5fgNwMZFvfRCPKZtkb8QI4goVuJaFg9SoJdYA3sW9fW/hzbguiFmptLbhNlKL1ypvCfDi4N84DBKDxaAxeF1ByI6iIylLTPVKmRSdOGjjRbNRPWuVaovizUGPs9Fv+5bO7NE4d8v3MfqFR/yZcHsb5IQEt1ZIhtzejA7yP7fvABYuCBHFIYAvXKBmUrMU/hkzAKmHcLjkEtMNK1EQZ0Sc3FPSCpWzyLcfwt2dt4tAsR+wxEo/IZWyY4/qowXzywRTpIYTUtYH+ehvKb/837wawJxBgF6K1OPbe5IM8u/qpiz2O7du/k3Iff9ZGKvP+Ol/Z0sTtGmZsGeMhIEA5LJ1GzDnUvhxBU/xITrXxBRAxlD03unLMNKogjZKOYPRymnkkhsjRqFtHOTrCR6D9to7wLETwTi7LMByJqaRekwVjDCWpZ2kyDLioh6fnbj5hyh68xdIP7xZ5OB0ZI3GiRu+C7spNSBhqp9zHUa88St/jUE+hNJpVaM4pOo1liYhhXvJnl8yK/D9cCJybq4YpVhBQqIjNWqPFYCzheGNP4P7Nb9GiSvJ3z/rquwRIH7q99QDPw3kl+noAQkwIWnJUVON4ZTWUf5hEocxAcdvfRwaIh8aW6ef6uxdLKODh1rYFmrJj3SkjRAActn2iWCcQUNskyaRhqoUo9HzqG6MFYAlTH1/b/oeZN2jIhLpz0gquonJ936mRkS89sygOrxs04jyD1XpSg4eOHeSynaGoba7skcFZ7d2G1wkhSBT4CI1LHda0EDcrawMGBvELxzjvdziaAAoB3G1xmZnuv0aTZCHtKlhrudf9gGPpMuePQadRTNgzywcUvCEjY1GWjdfI0TE2tWmslRHSk73Zzt3B79cbp5gqgpd8spoPKMcgMAYyUbn5Hk6r8YU+Ex7vRi1fnetF/Wu/OIeDxJeLCh2KtXQXDvga+gsjZDjg0uqYusSksgah6NCXI4f7zlFrUd/oMe96CKOgKGU2jo1FipUTIj0prgH6MWKQ2SVvfW+j20hO8CUOpzCxKJizo1oLpouyIPkdJAfdhRZe95D5v61kFzRSfBlv2+gJan8KAGYSK5D8Pkr7FZoktMIxHRom6tFWJVnMrEtDKhGRwMHD4rw0Ryq70ZbhQpnKSGUeeBBW2KiO/d6pc+RmhcerV98Dz67/znUlS7pZn7MRlsLJ+PkDY/h0Fd+C3uYHaHPuOvZA9C3DSxdP/3gekik8yRd8DFNF08gZNfC7J0MfOhw8GuyQ++Jc8fCBgrDFR8KQEeTGBFocOeOsAEPxyW4MP8W8svuDqk2Gcgjd/8yKi4GS3belr/3vwOc3iciNKKhyHEPjqAiQGS/llk3lzPkOnYGSXzKyhK+ouKWwKgDKLqarrv9AgQ77Y1oaunJOvsqnSnZOLfkvjBV7ARUXnpjVKQwd/sbSDp7MHLuYrOi6K2nvA1ljA8ZM1c61aQpl1ursBX4/ERwO1g4Ugz8TCc7qIk2gCrJ9PjoTmtACfQ1CR7jHarUzFgRkVRVzb4uKgBKLicmvPI9JLhHDsIFb8LL30Vc/fkebJQHdYMKIYsbq1GfgEDZqdBqlGdpcYAm2gB29rqzAE5UCyy+WXphANMyeqo/yaBGZdKScmInqTu7n8TakjKiAqKuvRmTn/0qsne+0ydBMl04him/vw/Jp/b5N5YxLoQIKoKRunzirWdCTPnM8ZL10mizUCFy3WkKzrYAEtgmkl4jcQUcPj6h7LBh3D//kwjCBi9gqbk4dscTIvzVramJzOhb66ICIkddit5+CiM2v4LqmStFlIYdfafeSO5GDUyVJwVhSTm5O2jwVowFhvI7uzrpmGSR1SZ3tqOB+FMbNV9igKG4LO/80SlU/xFNAAVta/UMdjiaA8WQIv8hq7cjjPzozz3A42JsrETxS49i78OvipFyjyqLdjE2VaNw7fP9U8fMRDm6EUSKWQIFkHGJAkAulZXA+PH+x6awppUEmZ8QbRUqAOzOOwk0d68fM4vYz1Of0oWs3auDON7VMJ/a43agm2BsuIDhVkLZQcWtthSjN/hRGWQ6CJNEDm4TkRkfVQB5xQW6qL3Zg5G9LioAZu15X82vJFWm7QzuFOvb1IHg7F2rhwSgvohWKH9QSCZ58S6DF8CamhB2UI12jXGvNBVVFnquts4bMuv5hE660Y6Ifyi+5jRR+tdFALnLHHwBAWt6PkleBdmqvw86eGeu+jq2P74e1oyCEBIYOklZIdar+NjKhhBxBJZA6tMMXl5UAaSLnqlrcGfa2XrFE93g9XgOlyOsHxu15nfI2rsGFxbeHsSJnyKiMxP/8u2Y2L9QwYPPvv4nVM26RkSZm4tmBAewL8ZNUshulUeSG0MAaPauyDEimiSGy2nWBgxidiaRGGeHd1TCqao/30hNbxcguE/mwtjXn0BDyXxy1G9A5r4PVHVKjdY4fjY6iIFOfebfINs7YwqYS2ckt6YU9ZMuEyP0Lo0OTqM30tI6ciJydrwR+Bm02j4lUHAT+g3JaRGDvJxWGOg0s5ed5kcbQBFD4NEGHlZCF72JH+cJ/KnxNt9BCqcjoh9NO7JFPc2QINIcZHuXSHPoneoQrWI3pRAok6mTzEIr+aO2RHUam1Mf2K/rMmeF6IVSSCba7YL4SCqDmBRgZC3B24Z50QaQVwVDOeE2i6c58OCtB0CHKoFpKT1jjv3yzbraRY12YZ+S/byGCXMJuBJySwyk0jRC8sIpjvg+pm+HSkN1A+hLhjhjIRCAcd7+kxZtAEUs/cw5T5e84GcD+ccNBjUBl6dgDWVhZ7xlzHTUTl2K5jHT1NwbnUFMD+uXitWGJiocxOxrlr9veNEahPMZvf0pJaoAkitRtSQdjSdPuwccAwDIJTdLTXvnVHOxSM8g5rtwimBD8RzUTL8alhw1f8E1wPxR30hRaDsXxiINPmnawQ73ATA12hLImmBHeQWWW8nkxUkV6iCupFUJjcePyfLOW5CJNYqpWjEs7GLUT14kUgC7krOol2v6lJb+xk5DqsgoDTj7rGtqiDqAVLbTvS7n1WynTSaW2XlBXevF6bVZBUR+t7vzPzjFHFEAkDOoecmDhKrTJGVJZM9y0DRutmCGHGITiUgxlvT4mjMhoi19TMPy5M/4gBwqNYcPp3aOjwWAO/kP53jy1DJYy9wAeiVwTKGPxiB3wBmF0YPTKx8kX0wmNdalShjbMnnw1pxkRmw+vT+4fezsw8Vxdy7JxzeOC6HZ6Tulw9r/KcyhuvIOzpTYf8hD7dy90uWVwNEjfS5kbYtKA5oqjhNoejg4YZakbTDB8zDq5FNBZkKTj8f5L6Hxczepz3xDYwgAHY4BdrhgXxCR6SDR3n70BBSexiwkUNyYN0IyIhdINHkksK2PyejhFQ63aWydGKoS13AB2o7WAKrTDkdDXd/2z60vfYMbcSGGEaltWed2xkICuWygHiLxogFiWIlXWnJZe+jv4vHeEBIntg60pB7dJtTYUBTO1i7Y8Fc/m+dsqoejrop6ct/TkD2hNskdTeJUmmBzJXz6QswAXMd/dnkGpzs+91txqXSiTwNYmgauwkhNFax/YUhA5MHj1OOfiJblufOOuho4aqvJc+oIa3k3EeimXs1q2BPcSAvhIPjkjlpiBeBOnt/xqccktB/jSeM9Dpjhkykhtzd124qBlOxd74jxwMGWvvEvPwZnYx3s1RVwNjd2D9CG1/PoGu7otOSjiVJDAOjDh2pjAiDvjUBm7V2eLsYbYqDjaA83QrgSeUBWhpfIeKIyrg7LAKTQheK/PTZoIxJylxUjXn8ShgPb3NIWoS1n8JLTxGAv2z59tTeheMyY4Kf5JIbVxUoCuYiRVTHzyGVTHfpeZa7PdCpNW726eE5He/cIdX9KQtVJFKx7IeaERibJy9rwN2SvfbGfF5DFPEE5PkF0Xv25Q5Dc95xBHbt0SvBTm7xK5ngsAVxLatSyKcRAwaJ5PgC2qJ1JjosX6mggUYu8bf8jRvJjNbzE0aP8159CwX//rH+awmCANjNbJDvxLF3D2QOiQ3iY5223Bh5G8pQqb7rFoZgBSGrUShrl7bPl6vBSoDJ2NLkUOR53wiJUqRyXIFY9cjCIA3AvRr/7tEjOjaYksso01Jaj+Kc3kuS90C+p0ySnQpueRZxFhq7mDAzlh9WYMPuyxDzv+XKPzLOA5USZ4Dzss5yOpQRyEfkNG7YEP+DqJT7hnaYq8ZByvIk4T9eAQSz88I+Y8Pfvixhlf4euhHbobIeutQGjXv4+Sr+zAAlnI+z41Nq84I8uKxdygolYdyOMp/dC21jRfUhiioT7v0bao48RPk61qK4SzbJ6IPswhQvgBrr3uo82qUuJBSpXLAQM7oCQhug490YNPSxkSUxHdjTUDkidJp/Yiem/vBH5H78sUhQ1XWHk5XASFR9LwJmPbEPRHx7AtAemI33r65FtccDAkUOnJeB4tSbZ1iEkTn/+aI+hNH22BvpxepjCmBZ50Nt33hyQ2xXBaoW/oJdHfvIf7kHeAOU3zwPvr3OHiFJzYc8aDWdrc/ckSIk8Wk1KuniNtCgkeexIi+xnpxPNY2eiccZVsIy9GPbkTJHLIuKQBAwDZqw5h8TPdyLp6CcwndzX5xBR4O4tCS0imxKFg872TVtfTh20Z6KXHCfBWKiFJkGVh1XT7SjJD95BOB7wy6egEOGtp+bPJwkMy18Z6JrZbCwe+WBDcABvvgbg71nQeJ6cmDueaBaMlGODIhxVV029OdEtnXIQsMiPdNhFFMQDmtJrLbPkg5tEjUk8VKMRKpLvU5gCkmJtwwWxPppv4X2eFi8mJ47APXLB+yynauWQAO7eI1wIlpRfhwtesBI2gPRDJ0gKN+/YjQU1dV7fr4cDnqluNbBukxon0tWdgy1nrHBwnY313WrNZWkVQWHhN7ljh4o7p5IlLVrjbZH6cpIhTgVOzIEg9dvWKOy53Gt8kBXI3DnA/HlqoLqm2UEAegcUKhqCW6bmFuCjdUJh1FFT/G6gtx1pQulv6EcXrP4Q+EqQFfp4P6TNn6jreGqaayCn5BKnJkZKvNpltfawT7wSoIKhLazO2eWR2I8jSeKVeTX154UG6Z0qwmDxclpz5vScAJuVrCA5QUFzu2p+muiVFz7XyP6xzzffFiqUD/xWNFZrinRkdDX1nPI166FYg01eJMm8brlPb3VHJThSMWR7yfUGjZwzmZgG+3C87pl4b22FvuI4jGW7hObwBc9kApYSy/7uI8CSKwLPXi7K6qk1Orr8ucRG0kwn1TmDvJ3rf0fjWSKSQF4mkdTo0+0d+DUvbnDTqsDH3XIdHbtZncEr7EdjpSA12pQ0lY0qQ6AeSV2zamQ16SFRfG+ahvOClATKbc0foS7aM3lyaIdcBK0TQz/Unn1E5TcIQnuMlM9XovVo/cnJ/xPdxA/eeBfJq5ZRewQYS+YoxAP3Aj9+0i2FtWfFakagxhP2sDnGgWpijzyHQYBmMKoTUkTuggtyRyuB1iB8uEDZdIztlCmkKmepqyqFW0zGngDG6b3/7yLS8tZb4haqCLxlJAhtQwYg622SwqeaWvAzdhl81aVvuXQmsGguqY1tgqFAf+EYugpLVWZHdN/V1gzF4Ry4ZPH4m1YnpEqAxq9aXY9Yp0z2jImIhslIgJESxnb0KGBqKVBSEnoEPVhx+mhQc7wCrUaNXWzZCny4ths83n7gXDT7an9nxfyBbuiRf7yBpGWXQwqW8/H1e9SVdzlFnxuSo/S23HEi8MuV3QqRJMQ+Hlt4rh5fR/h1bpSIyotUBVE16nue8txrngIPoooRkS53OI/fh4jccLRk8iQ14Jw0wDWJWq1emzcywyWSeZmwHD7UvWny1QTemahbhwFsvfNtenny9huIed4c/DjeZOOhH3g3yeCF7pw8M5anIvdjC2qO8LDqkxxd6p4O5LRzRhwHpvsah2Q7xsM7Ey5Sa1IUF5J6c6cOxyvV57msyI5tH7mUxkbRBd+hekc01GZUdy8jAOPo0JN6HXJffAZSRojk8LfXkMj+xV9v8QQQkYyr0fmkoqvTVsU7lh736LYAjkCLJKbKA+QjR1ItAAoLgYL84OkNAyk2us3frDGIBN50yYGynU5+PBvdKi809xsCLyq0LerbzxGIt9HLK/PIN/rBw97Pu4jQnSeyadSryavEKbCeKPSr/4xsm5tIChOn7Gx1ZVxeh4UZJP8vD0Ky+M6TGhw6JaPqoEPpaFG4CXdRs94VrU2vYgkgH/wx1QU/+x4ww73eAvfEA2X+KeWcQnCAN+cgtVpRCTQ3RxRPFglCrPbMZnUpME5X4O3eGLSkIVhXj6N7Bw7xKI2kNNYI4Di2yUv8/jVaUhdTAN0gFtMpB9NSIT//K0gmd3I2S2BtHwCdqJDx2hatOjDgVKDXKFgx1SFmZrGqY5vFksUkiecjyjKGRWGCcpA64uatUJoaRZO1UjP+lzu22Rqr343JHrp0w0cJxB/VN+Cnf3gReOQB9XPeKLGuJbTJykpRyLmWum2fi9MUix0YrqW6Gti3X6xQzzF2Bq7FHV58mtqheSjuKVprHv+cHmbl+i2YOXUySeUC8tlJgjLMoaWQ/SV2eK02yRMeRXOHhOR4ZdiAxqt1HOftEXaJBcs96pyMAJ6m+32JE6CH8v6iAqA7xHYLPdj+p59DYk4mpIkTgFyyT03UAPYQQlWU7cKhcm+M9EK9jOQC55CC1kqE/wRBdOCAe7ksRYDGA4qvcSSKgNsaCxs3qH5gEHt4BZ2+xmiE5j8fg1RCvlYTNcbpEFvnnqyW8c8dXm4/PteF62fZB70heOcY3nWTR8pPezNUuHE2MdOm+gaB1jKUYMVsF+teIN5Al/gHbxL5MO/wORcoJ0JT1xzspoA/rtOLIRgP2/z6UhuS4mLbwXlU/Fy5ur714aNAo3es1uUG7XV2wqO929iwB9AN4jK6zOs8723pInXssLIx+MbBn1fKeGNnbKWQo3S8atK5c6paPFnmXZvBPUePFKZIG/mIQGsYjiRq0AB0g3gRXeo1uvwkcyKU61dCGkd2UQly+bd26XCswusnXEXuRGlh/20hT9vixYrOnyewTqnjcL5zU3g5LF4a0hWf6Nk+5zUC7mYM4zKoALpBZLF6hC75GEsjO+KzZolFv8XUNN+fshNWf9+qR2WTV5WuuNiBifnhgchZzrxnbTnnr55XgfONY/POMBx/FTue8cq6PoFwo7rc5TECsLjX/XN4gHuVhb5z/MsB6NMQnOL6IF36Xt7Ojj/j1fp48W+OT3Loi5dkNJDT/u5eHU7VeCVxxhgnFpY46EbV2TycH9VCVKKJbGodSVh1jRrV6ersEbWx0+/wNNuZvBy0Lb9YbAzZszVcalCc0+GrT0GyWbkhXoW66A5PXeXVkzz0mHsRpxbwSnzkUIi9cD/jdeX+JQDsJZGcAnwr/cwi+uns3uEynnKsT5K6F0TibMBOi8K73EhBQmwcNOYZjIfcjcuVwWPpqVAMcXpHco4YavIAxtO34QhiY3V6aBJToDGZIfG6MrIsllN2NNeKMUxfswp1TsNO9+/xRhoch+IZk6O0GhRIMrKpn/BYfRzdvMXpwlq618cJ+FNfSAADAMpzd3hx/iJ+aKq8yhzP+TXSbaTQrXErc+IPv3JaG0/D4vX/zkJNRz/lfuUpJFdT5cluxe7rBByl5DFEbUIitHEmeqVKNlAbbxL/O/UGtFisZCsD55DKdFNawo2Hr1ytjXDUXVBcHW2S78JNRgOU3Gwo6WmQU8xq/gxXTi/ZsgMu0iIWOnYigXj+Cw/gAMFnncijIQ9R7Z5mqiE9LADxANOjJkLW972iR3t7O9nUJiJCfZi9qtNQKstw6aVk18cBmWQKzCT340kJm+IC+5pfeQhOayc2ra3D4n9JAHnzRHr5ihu4Edz94/NGwZRfBENqFgEYncV+uF3a2trI3rbA6QxMpKSyPSjJa8Stt3k/i6f+Mb5AHUILVDZuBX7+jHh7S6SZaV9oAAk4Jj8P0A1+k54kmVShkjS6WEoaO4nUX+wWGHKRvmttbRVA9m4r5ewRpCmV+PbD6uejcoicmUJutSQCFw//CMqxE6ijfjE6EiIUk9GIGALGosRLwLOd/AbVa9nEyDq9Yi6ahKQxJVI46nCgRSYJT05OJpaciObmZiGV3Z09KRUNZyrQ2KSOT/YFnoeofeMeSF/7jmDmPGL/w2ETC+0nUOwz8AqrPM93CrG3yXRHY6h3+i0AZ6BGzJq3Epq4hCHrWHa7HY2NjbByljkxWuXgZtx0ozujrVDNQgin/OpZ4KOPBYMuCpfQDDsJJPBmEmCvOJwQq9VlpMFZNAoaXks6iWSPXTceyOU+xT7fa29Y0Hr6KFJKZgzZPet0OvJbs2CxWFBfX09MNh5lpzoEgBwqDBfAL38J2LQNWpsdP6F/7+7v/WiHELx80k4bMzMQd+/t1IMnCbrdPa7UQpahzDtvEtlkX/bvV3CutQnDoZhMJpWpJqTj2PHzZCsVtNI9p4WZ2sEq94aVkF99A3dSWzxJUnikXyp+CNvgq8TU4n773GJ57j2vI2HWO+S9fYe6cKH40kxasngkfZTpnSTCqYnScMmrAKd7xJEdTIe1QxHRIO50kUxEvmGF6LS8zf0T/bbRQ/XwpDpvXzg/Xk68+AVyyx8HDq0Cyp8EOs96G4g4SkYykOxezstml/pedHyQAURiKmTqYTzCwdnZbRGsjMIO/q3XQyaiy5siT/3CAEg3O42kqWDl7QRaw3uAJfTuYnpdbO/HBQmn4vOwJaUUW1OmoFafEr4E8oyrpDQcOaqSv4YIh3xXLKUOaha7xT7+RZLAFSSBrrEzSYdUPBv2SUz8ZG3/0DTqnTDF+UdW2rTxeCtrATakTsfxhJE4llCItzPn45PkyXD2sS4puxgGgwFKUgYqLihobAaaLT3nSfRVeHLQTasgE+u+uj9SOCQAEnirJpdQ55XJqLUfDsOZdlN4R+Q2kIG7e8lJ/Oq+Xfjlvbvx8PWHMSJD9Z07NEaszpiHBp3Z77wjplF4h4DkY/pUo8mZginzmCPnwjZGmFi4/AqxNImLHu3RYQ8gDy2R+iydOzdNQtVLYZ3j6dGcjylFsMSyXufCN685ipnj67sd7DG5bXj0pkO4ckaFaLFQkxXrCdjVGXPRJQeXeiNPZaJ7kpNSRNKyOC9CNcp5r8xIiQDdSO0zYrhLIAdxpdJi0odN68M6wTMxptOqQNaFByDjdfcVJ1GY5T+LWSMrWHlJOX60ahfusXyEgs7gGxy1ahOEXQyqAkmFsip1mbPFtqucbd7RRedFmGy4fLGYcMV4PDLcAbw8NRnOEVnhPyGrTs+cCjnM2SmXlVahdEzoDZDH5LThJ1/ajW/Fr0Vx+9mgx52OyxNAhlSjKdmk3iUccntzNRHuvcyjGDyfkkC8n6QwcdgCqNXiytJJke0by5NlPHPyw5HAnNQOXDvHfx6ltcvfBUkwOvCNFcdwi247Mm3BgwRN2sTQAPIkU3MGdu6ShC/IEmiNcCLPNcvEfAtum+eHJYDUs0Y6HMgVi6iHWdj+sQp17zEMjbHvBd6vmFYp1KRv2fhZDh5+fgb+uaUwoEqdU1yD0dbgGYQ6xREaQLamqXloqFdEXg6Xyghz24pGA4X5IgngBp6+NxwlUGy7PWlCZNInGKPbQdaEsblHXrq/eq5uUtujujE+SEeRhT8YkKi4bMiyBdeJGtJ7ep6MaE6H1mjAp7vUz9mlsES45Om82aqionrlcARwrjkRrpys8E/wqCGLJXwJDBTOun7uOeFO3LXkZADwJGw+ki38wEBlessxaPpYW02wUaK6zrQCwUab3Uy0oj6yBuKYsNttWj7sACT+saBkQmS/2eG2fZyJptVpw7KBTRb/cUKDzinciaR4/2Smdz/Nx3uOaQGJyojO2pAEp7caRfoI4avu2OHueCSBjRFMrvaZ6XwtqdGMYQMgZ6SR/RtfHOGu6R1uCeS8T53JFNY5dS3hp1WUVSThL0dK8Vni2ICqc2HTfnyeUABXH1EZlkAxlkpkxpWWj+07vPsQ81xJuyN8AN1Ld/Jq2weo3czDRQKLefXHolHhn8Cq0COBnBAkx5nDOq8+TADbO7X43bqJ2JhyccDvFxB4J+LzsTllKtakzw4ZWmPw2CcU77MKSQ1K+Phjrx/LE3zC3TOL19hxg5hDXeIzAjGo3RjM0H5JUiKcKUmQ7W2SSydLAR/H5lIkqwOyzalILH2WTp1L1miVNotd1qWkc2Jmn4GqmmajodmiTw8ZnlMkvLx+TP0a/fREGYohwdlz4sbYjvMWg8veedQ0Kp2/a9GacNBU1Da17URrCDWaZLfbE3m3U2dylubokWpp+hQZBdnEom1QztrgGpEORa/tOwjxwC2cE+vSbP4UI8mFepNAZJvol131vwIMAJKLkouM93aFAAAAAElFTkSuQmCC') - - e_glasses = ('glasses', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkE0NDBCM0JFMzQwQjExRURBN0RDQzM2N0I1NkY0OTAxIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkE0NDBCM0JGMzQwQjExRURBN0RDQzM2N0I1NkY0OTAxIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QTQ0MEIzQkMzNDBCMTFFREE3RENDMzY3QjU2RjQ5MDEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QTQ0MEIzQkQzNDBCMTFFREE3RENDMzY3QjU2RjQ5MDEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5EdTqxAAAnZ0lEQVR42ux9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') - - e_head_explode = ('head explode', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjk1NjQyODBEMzQwQzExRURBN0U0QjkyN0FBQTc1MTQ4IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjk1NjQyODBFMzQwQzExRURBN0U0QjkyN0FBQTc1MTQ4Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6OTU2NDI4MEIzNDBDMTFFREE3RTRCOTI3QUFBNzUxNDgiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6OTU2NDI4MEMzNDBDMTFFREE3RTRCOTI3QUFBNzUxNDgiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7E0s7FAAAiwElEQVR42uxd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') - - e_laptop = ('laptop', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjIyRUJDMzFBMzQwQzExRURCQkI2RDUwMEU5QzE0NTQ1IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjIyRUJDMzFCMzQwQzExRURCQkI2RDUwMEU5QzE0NTQ1Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MjJFQkMzMTgzNDBDMTFFREJCQjZENTAwRTlDMTQ1NDUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MjJFQkMzMTkzNDBDMTFFREJCQjZENTAwRTlDMTQ1NDUiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5fLI6QAAAjoUlEQVR42ux9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') - - e_party = ('party', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjFDMzgzRjg5MzQwQjExRURCMjg3OTFDMTJDQzQ4NUNDIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjFDMzgzRjhBMzQwQjExRURCMjg3OTFDMTJDQzQ4NUNDIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MUMzODNGODczNDBCMTFFREIyODc5MUMxMkNDNDg1Q0MiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MUMzODNGODgzNDBCMTFFREIyODc5MUMxMkNDNDg1Q0MiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4KgKfvAAAojklEQVR42ux9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') - - e_rainedon = ('rained on', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjZEREVDMDY0MzQwQzExRUQ4MzJDOEQ0QzJGODk4MzY4IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjZEREVDMDY1MzQwQzExRUQ4MzJDOEQ0QzJGODk4MzY4Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NkRERUMwNjIzNDBDMTFFRDgzMkM4RDRDMkY4OTgzNjgiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NkRERUMwNjMzNDBDMTFFRDgzMkM4RDRDMkY4OTgzNjgiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7rB3aZAAA6X0lEQVR42tx9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') - - e_reading = ('reading', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjAyODk1NEYxMzQwQzExRURBODVFODRDNzMzOUUwRTREIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjAyODk1NEYyMzQwQzExRURBODVFODRDNzMzOUUwRTREIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MDI4OTU0RUYzNDBDMTFFREE4NUU4NEM3MzM5RTBFNEQiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MDI4OTU0RjAzNDBDMTFFREE4NUU4NEM3MzM5RTBFNEQiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6qdxYAAAAgcklEQVR42uxd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') - - e_santa = ('santa', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjNGMTBBRkM2MzQwQjExRURBMTQzRDIwNjlGMEJDMDM4IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjNGMTBBRkM3MzQwQjExRURBMTQzRDIwNjlGMEJDMDM4Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6M0YxMEFGQzQzNDBCMTFFREExNDNEMjA2OUYwQkMwMzgiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6M0YxMEFGQzUzNDBCMTFFREExNDNEMjA2OUYwQkMwMzgiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz57Dg6vAAAm0UlEQVR42ux9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') - - e_search = ('search', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkI2RTlEMEI2MzQwQzExRUQ5NzVEOTcwMkM4NjRENTdDIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkI2RTlEMEI3MzQwQzExRUQ5NzVEOTcwMkM4NjRENTdDIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QjZFOUQwQjQzNDBDMTFFRDk3NUQ5NzAyQzg2NEQ1N0MiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QjZFOUQwQjUzNDBDMTFFRDk3NUQ5NzAyQzg2NEQ1N0MiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5fHY4pAAA3AklEQVR42ux9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') - - e_depressed = ('depressed', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+tpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIyLTA5LTIyVDA4OjEwOjQzKzA3OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMi0wOS0yMlQwODo1Njo1MCswNzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMi0wOS0yMlQwODo1Njo1MCswNzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RDMyOUQ3ODYzQTE5MTFFREFCRDc5QjJCRTEwMkI3MDQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RDMyOUQ3ODczQTE5MTFFREFCRDc5QjJCRTEwMkI3MDQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RS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') - - e_gold_star = ('Gold Star', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkZENjgxMzIzM0VENjExRUQ4MDhBODgzMkUyMzJFQjBFIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkZENjgxMzI0M0VENjExRUQ4MDhBODgzMkUyMzJFQjBFIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6RkQ2ODEzMjEzRUQ2MTFFRDgwOEE4ODMyRTIzMkVCMEUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6RkQ2ODEzMjIzRUQ2MTFFRDgwOEE4ODMyRTIzMkVCMEUiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5xZRiZAAAp3klEQVR42ux9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') - - e_honest = ('Honest', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+tpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIyLTA5LTIyVDA4OjEwOjQzKzA3OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMi0wOS0yMlQwODo1NToxMyswNzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMi0wOS0yMlQwODo1NToxMyswNzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OTk1QUE2RjUzQTE5MTFFREI4MEZEQ0E4MkMxQkZDOTEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OTk1QUE2RjYzQTE5MTFFREI4MEZEQ0E4MkMxQkZDOTEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RS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') - - e_ill2 = ('Ill 2', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjgzNzQ0MDBEMzk1RjExRUQ4NjkzRUE4MzMxQkMwOURFIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjgzNzQ0MDBFMzk1RjExRUQ4NjkzRUE4MzMxQkMwOURFIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ODM3NDQwMEIzOTVGMTFFRDg2OTNFQTgzMzFCQzA5REUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6ODM3NDQwMEMzOTVGMTFFRDg2OTNFQTgzMzFCQzA5REUiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4vuqT+AAAi+klEQVR42ux9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') - - e_ill = ('Ill', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+tpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIyLTA5LTIyVDA4OjEwOjQzKzA3OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMi0wOS0yMlQwODo1NTo1MSswNzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMi0wOS0yMlQwODo1NTo1MSswNzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QUY3RTI3MTMzQTE5MTFFREE2NkRDQ0NBRTIxNTBCQjgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QUY3RTI3MTQzQTE5MTFFREE2NkRDQ0NBRTIxNTBCQjgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RS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') - - e_key = ('Key',b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+tpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIyLTA5LTI0VDA4OjE1OjA5KzA3OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMi0wOS0yNFQxMjowNToxNSswNzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMi0wOS0yNFQxMjowNToxNSswNzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NzlGMzg5RUMzQkM2MTFFREJENjM5NzFDOTY5QkQwQUUiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NzlGMzg5RUQzQkM2MTFFREJENjM5NzFDOTY5QkQwQUUiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3OUYzODlFQTNCQzYxMUVEQkQ2Mzk3MUM5NjlCRDBBRSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3OUYzODlFQjNCQzYxMUVEQkQ2Mzk3MUM5NjlCRDBBRSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PnjYUFkAACqaSURBVHja7H0HfFzVlfd5b3qRZtSrm2y5Yhs3jMEF29jYJjHgQAghhd2Q7KaQzX6bRpb8vpRd8pGwKRCSkEASSAJLSTBgXLHBYLBxQTZykWTJktXraGY0fea9951z3xtN0cxoRpbkAvf3u37j0Zv37r3/e+o991xOkiT4qFy+hf9oCD4C8KPyEYAflY8A/JAWdaIvOY67Yjq4Lg+0eDFizcKqUr7WYTVgDWF1Rd3uwBrY0wfuS7EviRROLuGXlwGACAxNvmlYZ2KtwDoRaxnWQmx+Hl5zseZg9/SZPht/T8Dasdrw93147cfagrVZqTVUEWjXRwCmD9hsvCzHugSbdy1eZ2HTVdH3GJGmJk8EqawEuHyEL8cCkJ3FAAGTCeUFJ1ejMfIbfwAgGJQ/uz0AggjgwavDieghhG0dIDW3AtfXTwM4BOhW/O4QfjyK9V2s7yGogY8AlAEjNrce6xZszk3YzBLG8xGyhfNAWrwAuMopSG75MkhaLQccj0TJhSveKCEygoe6PiptCiJdupG59toAziM9Hj+JqB0BacAFnAKoF9u5Dz9uw/oPBLP7QwcgArcEL1/BJtyOTTNrNPjdKoBV1yG/REaZZcK2aYsB9JNRkpViRVy1WDW5Mk6eOhzl4yjZPsAR7xuXNhMVt7QDHD4G8OoukJBaaQCRluENrL9XwAxdsQAiaPTCW/G138XmXEPfLUMY77wFoBJB05iKkAdehbwPxZ2hElURQ9SviefVAzjfQ9CqkOIurv4hYnM6ugB2vwnwwssghQQ2nJ3Yr1/hn399IXLzkgQQwVuDr3sIm7FYpwVp/WrgbtsEUD6pAMCCoi5rkUxh8SXQiYIKxY7zMOqS/ZekouXCubQLafAf20Dq6WPD2o39/C/8029HQpGXFIAInBUvv8T6eWST0pabgbtjMwfZJVej9rEWqa0yQQ+wz64TqB++hVRXO2qybawLyc7nXwN4GYG029nwvo/D/gUE8fhlCSCCtxpf8Qy+uvg6ZJhfvoeDoqn4Ie9jSG2FCfiSD6ntHVQLdyO12S9Le9SJutSpRoBDyOl37UYsRBCx/w/gnx5CIKXLBkAE7yt4edSgB+5rXwBu3QYUckV3o1JSnhg4+34ZOMEFl3tpQEXHjt3oRBn5wosA7e3sa/wEn0MQvZc8gAje9/Hyo6ICkB78voabMP82ZJerBz16QdCAgKYdXZ3OaujreRtsghr8aFF4OVlxGYAsdo+Iv3FCNvvOh7a6j4u1171gYL9LVugZKvw3WaG/ZeHbYr6TIt8Z8A06fAOVbGwJjy1SI4s3o45iAjdo0Ry0gAP0Emsd++wPSHD6vGxPBlBz/cdWgBMnmPnxJn53M4LouWQBRPC+TezCuGEtiP/yfdg4YSrk6c3YTS0DjCqVPpQXT+EMrfXCFVcIcJPoBGPIya4mwQm5VbuAe/gnBOI+hGJjKkfARQMQwbsdLy9oV6+Cmm/uhC+X6yFLNfS+Gpx/v0fl0i3Ch6qsPPTfoPt/JA7hKQTwnksKQASvAh9XzVdMNZz6+VHuq5OskJPAhU4U9yjKhOCHNEBg3QufB/jb0/TxXgTxyXQBHNPlJDLQEbynRF5jbPrx89zm4sTg9SPbfLzjwwself2feBz4mTMlHK9HcNwmpPu7sV4PvBsnzXLVt+4HTcFCmGdKfNPfez98bHOIX4LXQ/13nuJQOSNX+/+k+7sxY6G0DoePaRBLyssOPFbH/fsEA0zWy9odaWgaRXWxeZ3wUmstamteps2RFmdEZYxqWIOL1ghJm+PQbDJKHvYcqsYEylu0lhhfTJKbvZuKnbMmdolFabkxA41vpNZJ2AoHZ5E9LtjqEKhlbRgrabgDXBbroRt1Uge2mvWIMzIt2imZwR40gpvPApfKCh7ePPj8tc/dA/yzT9HHJchKjw7HQtVjOKnuxPeVb1njhce1t0KJ9jOgFQNDVffex+CLoQ8u2sy3ShfgGBghyyccqhoiy1MipwIXb4EBBLMHmedz8tektX9yuGeNGYBIfV9XqUD69Oo+zmIpZ5bZkOJvw+lbnVaHw2t1Pp+8fkcrAH6/7KYKheTPzL7De7y+uNdErfmllCdxa4VUtBq5MjsQR0uvU9YX8T4VCiADmqcaNS1n4d/08nJXGmMDOnymTzEYeLQvswUbq2VI1MdnANTVwSeQi5UhFbaNO4D44sXknF6zHFmeBVtqnp/4Rtvrg9NYQMJ85zDAQWQa55rkxVQCxuMdupB6qRcClcC1IgcuKQZYhN2/caW8bjloE0YBGF+WXYtaeS3TT76I9QcXgwLvon82rCGBMxenWIKohhDKtIHD7OP7yEF/9Xt5GeZKKF6F2dBqRCtq10eqAP70LMBn7wC4/eM4HLwMYLJSOQ3nvBkktxs+Pe4AKqbDnTkWkObMRElvmp34RscBtrrw6i6AXz8ZR2W8CkQN8SqefSaeI7ErH/WZ4iPUIJG+xUe6If8tzKuU+0ZSxMhqDydEyW1RIM2PXYl7yH9T/i+JwNGCoCRXLhTEKpMZsfgn/gpwpg7gP/8dAdSmYOXYzQVXA/f2AajE8ZyLbLR6PClwIfavbMW1ytiZZiXU8QjAd5EAH30i6luTFYL5E0E0Zl8x5gEX9IHa1gHq/nY2S0lMPPIHgC98LvXvZuO8RwCpbMFaPZ52IHmn4ZpFND1yUMLnD73DXQtuRy/84neRr4IFE8E/8arLDjwJtSOhv0+udhsIDjuI7gGQAjLlSRo9BIumsL4x0sKycx9SYk3q505AvY/WScPjOa4AkvZ5FQX7GaYkYZ9vwXbUXxyKs1/ILoBQ/sTLk8JwlDmDEUSvG4FzgehyIpD9EOrphFB3BwIpq8ei0QKBksgi9fMvp34ujiFMr2Ti6Hpko8ZxARBfxOMLb5gxDftEegsFHg1RXpxsVX3P/ijqK5x0WbNJXm8A3pydkDpDvd0Irmdwoop62R118gxA/zCRIFOnMa5LYm7peFHgNHyhcWZ4omnLht7hPAQtrQI0NcPgzCQ2c7kXVZYFOLU6oRFL7FVSDFHBEok4OH069TNLI6FAC8cLQPaiaWHOqUsQjOQ4CG8djPyXZuWVoa1wwGdZknoiBIdMbkJWRCc4MYwDqrBw/AGcxwCczIQDSuG8OJdIC0CgHd45EgVgVt4Vo3HyRlNiKiQM/T60mkLIbXQgGmSLvqUVGZIzhUMAGVNeHpsbV48XgDPIdCgvhcTaJ1KfExWXhkaFfRrQWlVr4EoqvNGc3LT0yjGrgjl38Lv6+mHYaKls2yuxs2NrByJ4UynUnU3CeOqTBBbDWVUd5cQ15WT8DkGrB/u0xeAtkBUfQ08zWOuPgiowPjEY5GBwTJkP/pwSUPk9YOpoAGPXucgYkDN1wJ7Q0S2RMoNsluxd6DkvA9iA/HFh8vfl5bLxollODuWWsTbkK0uLlU/xAHpQYgsDzG02CIbJmtHsaLv+DmhZ+88Q0scuLKr8bpiw72kof/vZMXOcSioNtKz+HLSt+BSbRNHF3F4HFa/8ErLPVwOnUqP00A7agfFaKbFRxnnoPiHEAExVciPDODURgKPGQpHEzaSBFuQNqmVx2qcs+KrPhAHhsSPpG+1nt3wHGm++bwh4bCLoTNC08ctQd8cDI3edpaI6ZPOn/ulhaF57zxDwmM+zdDpUf/ER6J23Vu6azpB8IviJU3BM+6YygCKlN8UWjigHeOlYy0CmcuaGiUodBaCEs9F1nC0JtXUog0JApDnYnUs+Bl2Lbx72vu4F66Hj2ttGHcDGTV8F+9SFw1CoGifQf4IHbVpen9wsEn0+pf8RWdnamvy55shtRWMNILMHcsJiLWqVGVwnscV+qG+Mkn96U5qsk4fmG/857UY0I4uV+NHrlh/tts6lt6VNqfR+YqGQZG5KARlAKQrAthQrfgbjOAOYZU5AgQMy+2yK4uDRHUhVXCXTIJCBrRg0WWCA/I6jVGyzV2Q0IfpnXsc0ay6Zdi1KKAeDMRO4O8UuQn0kNjl/rAFkLTLq42Sg6B1cdW+OAlDUpQegL788c6qxFo9ap7x5ZRlryUHUrslHmpTdooIjqbWDJlRXd2pbUCnGsQaQSW5T+DW8MnVoo6Uku5E6uqMBNKRnVwV8mZszYmjUOsWJwghUVlGOv0j256CyUqGVx4CM+VAoqfJNa4fSeADISG5QfvPaGO2TKSPdEYHPFmrTKMauxsxZQfvZUeuUsft8RvervQOgcfczcyIpgApaYR8w6QX2FLFVKnmoLOPhiYGIJ0kj70/3RDy2YXVZUuvSfp6+vwOym9KPWjO31YKht2XU+pN75gDwQX/a9+d/sI+tynOqFBNUCAMYGYcB17BykBsXACPTBmfXwDHZAwNyVJgvPA4Zus+mbP81M3rTYXcV2x4Z1W5o3HaY8OZf0qa+ifueUkY2+dBKYQBVkXFwuVJSYFLvxNhGZhOASnEMxHo1MuLNLWdgxnM/Aj6UPIMHATz9hf/OiFrTLRPeeBqKju1IDZ7PDbP+cj9onT3DAkiaqMyJIuPg8YyQ4412ZweFMbFPb12EawhxkjnDkl/9BsqjJrQJvwC2mcvQ5tIqwAUht/YQTNzzJJg6G8ZmIqKQqnzxQbA0HGPeGF9eedTECULe6QMweefvQG9rz6yPHD903BIUVFq58QCQeZMH2SRljJAiqLncsV6LESkUqNDM/NsDzKEcNhV09s6MZNSFlMKqXawSgD5rIajwvcauJuaLHdG8iFLkAinSAwVlcJ1jDaA/htIGjo/ZQBJghp7zcLGKvq+V1Qu3UbjEHCp+YGUKDI21DGRSzh3m5e4PkrX1w1HSWBVhMaRKSRYnSsAq4DrHGkBHKnXYZExgHItX8J6ydPomRe5JZhZ7Isuc9rEGsDcVgDEzTJlSYY/EhxbAKI9RMgr0B2LHd0QyUFnOp0hPigX4YE9fXPqGNADMMkOM5jbokVALqY3ey5WDprJbFXkSbdsak0R+eiMUaMsIQASNYqI247vW8Tx3oyBILJBDxYML/3Yngrg97ifMUdbTl9wdRCASwOH9ArSfi6KYVdnWKw/AFHZBOPCJi7JrTUl8+64IqXSkDSACtArt0B28Sm1YuKRUzDc7+TkVajD4RXj7pM/01jHPn5W9a4O77ig9xvp86Om1QdK1n6ICBcCgTzGDVCC4+1lM5ZWm5UipNiQqZhQXiJg/OUnmcFTUWmvaAKpU3JPrP36V/l++eRMEz23jpaA8uO11Plg+G7g3jngIpOuw7o9TvJq6e9i6VUI0SoqALerSjRyaAsweRFkhuJwyiFcUgMlt0/BSExeU+SMRZFZWEs0wAmBL2koMssupmz91DSfZPsCGRJiwtRhfHJLAauZJQq+Oo1piAl7KyhdKYtOUR0V18H6PLPsQatpPIAnClQMeUZYopQBQyyYx75fHNj8vOQPq62N/o9nQlTaAGjXXfK62HXhtbNiDMUsFag0H184zcGoVt4lSRWL9rw2FcBhfQmbESjJ/3j2cuDFTJ0d1wudiLePIJYadFR22DI1gHtzFUy8aSKneHd4LkbTpWi3wAc+gGVFSmvzeTlny1SVLiMcndt1Iu/dsOyWqrXGbTmhvuFUNMyZqOUGUKLPuXq2Gu3/ONO2Su2428T+8zwp5Vh7+vi1xYyh56+CLfbK6yul0Sqe9IHoySGiHnXeXTIP6Ld8BX4ar5hfkrZg4B05/7ifJ3YE4g0WPO6UCw0IPvZG+lidpPu33J6UQH1mb7HnJtNC9J4613Cvp8mXajvIqmHJUYOkPsa/u/rgJNiw38NFWwNJ5Othz0MvMoHiHPMlASkTej7TKe4hgJbazR1RULdqWxTqnS2+zC/kl3aWVcPQ/noWcs4eh4Pgetn5HKwOjWfzWIuiduxp6rl4PLnzfzGd/wNYdEw76gCOlDcjp5VV4lSdil09Iktant3eQSM9kDKCEbK2ruR3lXRE2qjMKQDWqyD4ozlWD3SlCvAl3VaUGXtvvZcrK9ARcZsFcgH0HZBuIx4EWdSYZabY1WYKQrQdUOfkM2HTKlO2PMd8oBd32T1/K3FNZLafZykFWyykwt9dHlnjSZM3e/AngKpsOTqQ2x9TFLFSQcQ1U+wm8/A/2JmWdJM9TlXC/eLcMIEUwlCVhoT2REJTjGQGI/LZnYxFXW3Wwdsb6NZNjANSbeCYHl803wPGzQ8PZC/NkRLt6kgA4TwaQdcJlY/GRvAGp0K1QDU4coa8HJPyOM+LftLrUa2sI+qTdf4Ds8yfh7JZvsQg256SrWB3spMcJensX6LBSuAPF2aiwUl4rUWuAkN4IQXMe+HKKWci8mGDB2dxaA9NffDA2xAMnC0WYkUeJ4j0l3zDh/TjbibuQ+KD981QqKpJ3rz1i+R3LlAIhFJJ27nzp5LSNWz6vgpZDsX5NlIMVAQm2vhkCh0tCPi1A9dkAnK4PSjWNQaablBQlfu7ShRGurHb2sp25tCFkEMDB2exlbgghbPgSa2VXFbMfqdcsoxRLdsCD9dRbsAjZaMfyT0H79bcjkJEovJAxG1xUSyszZp/Gjnoo2/1HyD+Mgh0HPSTK3mWJOEaGvlzavcRwdEa8YrNmJL//fDPrnn13L5zPGEBio/W1Xf8mUnggO4NBiJGDJkUOfv3HNikoSDSWQRzHw9g38sVsppQh0xLssLaiDJw/Rz5zgUNTgvfLbJRso2TGL/Nq0NasNJb9ip79CRQ+/zNwzF0JtiWbwDH7egjklWY00Ia2OrCcfBvy3nsVzA3HZcXkQgUpzTPF3RIGkMTP7DmJb6f1wcYm9uq3Uj02FYBvUUaP1vrzXJGlDEL25iFycHKJRmrqCL6PX9FxAe/u7AYPmhU0pzbTHgjKVJGorFwmA8g6gWxNLKpgW5RpJ+toFJKv1uP7WGVatSUfPOUzwV9Qjp8LQDBkD2qRJD9VyGK1/Z2g62kBY8sZUHlHP70zj2yaFDRS3sKeqMpK+bSZRKWtfVCBeXtEAKIcdKAcrDp2oHbh5lsmxgAYloNL5xq41p5Qzo4u6XUErhzrHWTgq1Ug7toH/C0bUEAn2KS7ejnA40/LuVNUjm4IFkxi7IX2z0k+36gPnsbRCxbHgYtn2at44C2yr0wdFXaxeFHyn5yL7Fh7I+XESPVHkoPbt54cag8qcnBSoZruqdhYyNw8VP9ckKv6zIrFel6n5eHnv038XFobXLsiQi1qh6xuqXMLkBKzAK4gtygpLer8Ytk8QspTDcgOCwuKklkzk//u9Bkm/4jXVo2UhTL021v6vxcQNdgALYrBQIwc1NtCTIeomKguX3ONHmZP00J+jrw0+co+Lzy3w80Sz4XDw5tQmS3MQbaBiuVmpE5KNcIoRNHsQrRp0pKDsiKLqePMo3E5LvpyMnAqFAthm5b3DoC2PXLWxdJrkmuf/fbBjPavIScUR0yBWA6QcnL+TCOoLbF7FJgcFCSYNUUHxWg6rFyiJ/Bi7EFScj44FeXXQxPpDOpTp1A4k/m3bnXEq6LpbADduSrGUjlkOSprLmiKy0CVmy9rb5f6miGp3mjUqaw5oC4qA3VeoWwyeFG+tp4BXdMJ4JRtAuT7vG5Z8kediZjtW4d7bUoKRPR9Gwrg4KH9NSsqPjubC9rOxcpBLQeLZ+ngtXeGej4ml6nJp4rKigRLF4V9rHKEFWXp60ROcsMalIOoeL79jmxWkEaqba8Dqescy+YgZuUSr2Z7rFSKNkqOYlbR9mJa68VIZUgUpuzEJb8mh7Yq1UGqQCVIhTauytmDoMXahpMmAnzmbpzAKYLTjx5j88GBXdtxQQAq/rg9O7aeWvGZr20YKsuQCsvQuuizC9DVK0BRvgqcLhHONAShui5IPlVojtr7ZtAOhsjJHUWC3bhRVqV37Ua1uTFKLtqR31Klnbxow9FuXoFdUUYaTTEmBhnTZKOxzywKSLleCPsliiKqZ/ancmWgKVvHwssHbFXBDbytj1Eb0zJDQ80hknlrkeMsXpx66ZO0zw7ZgH8OCch/wQCSPWi3uX/s94vYcD0zHwa9EygHnT1BlhvziRddBJ7Y0inwio3Tgw011JwFE8pBlrnJbJCPoIkvNCu/dC9ATQMHz7zCQ6hfiJidyF7J7UQ13FiWqkNvAgn5MNmQkhbbhVSaysGc8LtEI5lsdGm/AyohvN8FnNMjL4f53MqqQnIuoM7mGWgfu0FMSwocivhMfpfOPEsHwCNIKZ76D+qNlcWTINhbGwWgmtkqC2bq4f0zPko6/yoBjnUf2oQ1aFZ8Y8AFv3jpNYBPfwJnIdqx7SlMPbOVA/1kbNIk1G6dIqg9IphFATo7Y8eIFoMpqBYG4pagWJpKvbxpBKmEQvgJVBbCzg6HVFJVMqtaNZgWki0wh9NFUopIitkRKFUkKmkhPwMuEVUlKtnZyCByOLBzKlBbVewsyqwiAcEbnhtQP4++z5q5Z3dvau0zbQDpmLSbCmD/23vPbJj11SVcNIBaAw8aPQ/zK3VQVeNz4yS9PW7d6jfYmH975u8wCW0/5l7T4hsDScJFPIGIjFFbeJg5G2DLNQILrWtqlD0TxF7o7CF3ogUHBIHYGfjH5wxBWlgvwj4VY52IXKRiipyYp7qZh1ePqYb2K0Uhbv/yNqak0ly9P902pBWVhg/fs/e1mg3/ev/QveLERotR1qGsJEuVMjWdiAI/gFT45UAQdjz0CMDDP8QOoizoSNPhkmeW5wJ5Kyh/5uyo3LGU3YFmbHePnDSOVVS/bbZI/uxRscFVcrwK7f1HBZN9LiiQQctLspKenyXG6zzDlgPvypOUJj2O27FRBZBYosft59xOL/A6tNH8AzFs1N4ZBJ2Gk/xBaU00gAqIOxHEX5+ug6/96g8A990ra6CJxEZ8GmK9JrlsoRgSqpUJ/NMEIO3FoB0/nvBVUQbDYXp0DyUqJwDoSkBRcnPSj8wmOcwvXDONt9KoU/crvtTUAezYyd5Ti+Py7UzelS6AH6CiYq+tOmudO20iBLoixp05V83AWDxbDwervevwq18k+P1/YONm79oHa2gP/QZUaG0JIksthljAxBFaCKSiU83LvTgmYfzkzDYk7wil2vrLX1nm6H783ceHO8EsU0M+TEW0vvv6m7vPSPFuNbIFdWgTzp2mo3m6SjnfPf73AWwcnUZ95KXtAM88F2tODK5UmCQwaiOd7Xdfnj41uye23WW5iQGsOg7wp6fZYZBOHJ8NOE4Z7w3nM5hVr+/fc5bjzKUJ5KAaCrJ4kpUUX7wkmXMcn0G+l+370XD/3eMgdXQOva+yJCI/2mz8ZQlgW1+k3UadBKU5sTKRWPpLWwGef4Epvm10PBGOz5ERrXJkcO/eEJKNoxdtMkPOEADp5CqznqOptjYFJZN6uBnr91CbFB99DOD1fbEHdSyYEll37HFy0Dtw+VFhTXtkWBdMFqNtfqg+CfDLR0E6LMP1Mn63AMfl5EjflTaA+JJ6tZrrPHmkFjRxbNRkleM7l803klG/bpjnCFh/gg1fiirz+3vRavzpz0B656BsGpTmSDA9igoP1l1e+yZOt/Jgc8mIkThYWhlie3nIv0kT9plnWbg8GbB0zNytWHsv5H0Z8ahQSNq159VTojonFkCVhgODWQUzJ2k5lJXLUA7q05gQx+h0F/z4WdQIm7ehDfSTh0Da+grArNwQYz1UqptV0NRzebBSH9r6e09GVIBlFSE4iObBQw+D9PRfmdlDCsqD2O+KZGcEZuzxy+T0MgTmM7yK/8urR38E7vefgOikmJ31PuhtD8KPnrJRaH61IEjvEQFhfQkbmzK9NyVLx8stZPRjc1ax2WvhpLIZPCcaeOTOHHxqeRByTJfuGTwUw/nCQQ3YkeXr8T99zaLU2ypyineuEfuF9AdPkC4wcu1WumAAKQS19c+v3QdZrkMguCJxbwO2EDQd90C7SwQ71pqmgHj6nJ+AIX3zf/E1PyQ2PFwj8R10/sCd2IRP4G+WhLlElhXESWXAl5XJhjQZ1OQgNpnGHyzas+ewy44DCn0nZay5FaSeHhxPYdClSqDRctDzWN9L96jxsQawnIzNbzyw3njD8mzwtx6J8mJJ0HLKC0JIAr9HhFBAAk7FQZ9XhK1vuoT23hCdWPMDYiEkB9NpML6PdryQc+B6rNfguxdRTtI4T4mUm8PSXHIUM0ROc4q1pCsdQkVXSfHmDGeQkzJFrlFapSKD34P/9/vkzwPI/BxIO7Z+FvXBxfm/SWifxraRK5o4z17sY+NoT5wLAhAH8xpUUHZOriy0PPj4PbyJt4Pn7K7ksxRBHOgNQV9bAII+EVqdIjy1jXGPN5HD3DoSVqKwWhLAM5VKnymumSYWpa3Ijwd4VOQMx7bRkeLRjc+nbV4UIEQhJOQYplwqtHfBN9aUP2IAceAWInhv37BhluFbD9/LhfobwVO3XTkAari3Ys87Aigj/YyXPvqiXXR5xSoEcZViVoxqwbbSUin5ZYm5UkpgYvvbKNF4KK8sYcYnWqFQ+QZALedF+ynWZ0FOm0LhaQ5spwsugTKiEzxxQKwI3msrbpyh//bP/5UL9pxG8HZmMH2RvZVqma3YdMIDX7/dyv/8uf6F3oD0R5J1o91JZRG0K6r9jNIpM2A4zXEyMlMGowOfcRwukzIsBd5UAE/nF2Xf/ec9D/DgxalY/dyIwxhCaOw3HHWDE+Xiz/7GFNM7cLBeHGUKJC8DZe4Ob1qmONX/DeUUg2AtST4QAS9o29iJVL/B+oeoP1FD+y4FKsyYheJgsOWh3z53L1TMnwMDR5+MWYkYVGBI8KOcC6EiQ+uDenMWqHOnMi1VGIjd2u1DDbX+qAsOnQ1Ie494zqO5UUlrjhcAGO3lpyPabsaGL8dejs2Ge45rw2e/SeyY6sUANGMWyvPw3VnzyoWpCxeofI1vDQHP3R+CzqYAnO8IwpvHPOLZ5gBPGYUnTdBKm9b18Rs/uwn48iWM5YZDEvVmHgom6uBanuN2H3JPxq8+AYPn/qYNWqnyuzsUDZU2SoAupwC0llzgtXp5/8RIBonjwa/WR1RWlPOU51ro7y4L9bTdjWrq3aSjYRsoycNLWF+5ENtuzFgoeVNoY8VDj9+lm79qKTgPPhYTF9p1zg+9rQF45g2XWN8SIG3mGXwU7c3Vocy8hZSUxVcbpO8/fDunyS5G1vvCoOFPpkbNuy545ZBbPHHWv31XD3w8ChxifQZFCSGhRd4Lh/J/orRPKg5zDkGSDEVlnKl8KhhLJgGv0Y7KoAQCAejt7WXXmAlNclIMgtTbBoHWs+GgKdJQdytgblPsVqtyJSWN9pt5RkNLzYiF4kBSGNqObVUP4uvbwVPzakQoIMW1nvHCa+97xRO1vi4Eaw02sCaOSu7Bx/zx5pus3Fcf+j/MZgx0RtJvtdX6oL7RD7950U5LTV9Rq+E+QYCr8HNS0qHgKdoSpi+cAOYJlWAomQj8GB3dQ+Nit9vR9nMk4agcaMQQiJ2NIHY3svW2VEFwyM18PAeHQgL8CMfqjfFgoXMtOSZJa7ZwnvZ3ox4C0NnggwC25v0zPppld8aDp2iDlIpk9vbd9m/efe97nHXq4hgAs/PVkNMVpOcR2TyxEKXt4vmyZ8VkkI1xCjvsdiinWXvkEIrX36B4JB5ME8Z2fzwBlJOTAwaDgVFjKC7vCw1mAImMt7UBORJWrwR2pRV8WpHPRwMmEJR3GVH+uH476N84ACsbm2EvjgvZwa+MRjtTAVgxb1EZzSmV4I44zP1ugXlZGrpCoFZzp3d0Sal2zzyGs/JbVQdr4Mb5m4BT60AKyQErxmy0vZQJtWaVCb77068BaFEfCfayQ7LAvp+x3Fo0l11KGMSUqeR5kWDHG93jJmP0OJNKS0vBZrOBKz6trhAEweeHOz4HMCHKv1+IDHRC4dBn3bEZ+O/+GKSTNfAYydALUd7SARAnn5pJ8ncPdMD2nV3QgApLICAScBQDQ6sTWdgQOpVjKzbGloAKz+PfoatN/hOnNgwCSCsY4bWQ5bd9Cb9A0uv4M6qpTeyMpXCZXo54oiRp65Ujuomj8VodjGfhkRXk5+czauzr60NWqfBKikPl5AArxlWQ+kry5PjXJGwUvvRZ4L7yHXaQFR3V/pcLblsqsy3gF+A3P34B/ueR81DTEATeUgSm8gpQW4vAE2DYkhuLlkV6EKhtWDcq7q6wHGSGl9ksyylJ8MfbzqxozGUAjf8XeU11DHjhe6xmeXCYld1FO10vTmouE/L3srIyRpVy4yisUgc9CoPKtyQHL1ymVbA8AZJaBd9LdqTcaFFg07FDzdyAsxb0+cVQeO16UOn0IAYD0L73H6g8aKFwxXoIuRzgbj3He7pabkbBQLbYyXV50vfx93TM770US7to2WRO9NpikgaR81tQWGhe4K8AaTrr2zpQEyxNH8CpJQMwd0o/NkuC6qYcqG8beuBWpzYXakyToEebgyMqwWRvBywYqEMWP1QrUalUUFxczBQcqqLWBF3d/rDXMK1y+2bgqqqZL5cc9XvHCsDqgQEfp0J2VbRsPbOtmAZ66igEPQNQesMtoMtFRp9XxPYKeDqbwVQ6ha5zJEkglfoUgjdzzQozV1h5Nfjbjg0x6B1eCdkxD5Osw3uugoIcCuh0SlAwffi0XBq1CJ+6oRGWzYrIy3UL2+Gt6mJ4fv9kECUOgpwaDuTMg7PG2DwfNk02tOoLYUPve6AXEweZWq1WJhODCGB7Zz+DL5imRCNlrbgQhO5e+MaFApiKhbL9YVlTrxoET/B5YKDxNGRXzJHBU4qzvho0WVYoXLYOJmy8izNPnE68bw7t4ZlciQBrDOBvjwVpoC8EaAPCVbNUoEnDEvD65aBdmeWmBtBsCMI3bjsdA164rJzbCfdurGMAH8ueMQS8cOlGatxWcB3q/snlrZZ2JumN0N3DAptZG9Nc3YBbN4EKRenNyEYnjRWALDjJPHHa4BeulnqWncEyfW5EUHrd4OvthKwps2QWgx3SWvPkXTvIcp98sgEefeBPMTYMcaa+ziC8XeWBtcuH33NA8aGkwPQqskaTnTMseFOKB5Lec/VUG9x3yxm41l8LucHkeV2IErfnXwsCl3iYNDTzDFmsP7Y+NHUyiAhffwMLzadBuXesAFyuNphiZru3s5W5q9TGSGo9X4/s6zQWR2ayqwnlZkEplK/7JOjzimHnXif8/dWIQUxrhFUNfrBYOLhheXrUx2RVN7nijEk9LnqtwMArzRs+NnZaqRO+vbkKbne8lRLEXq0VjmTPTgGg7DOnU2lokqUbjEzR3yuXoSqhgi8hFapGFUDlgTO1lthjVP32HmSdsQlgAo5eNqDEQsNsNuC0galsMlP3i1dsQoqxwkvbHeBwChDwitByzg8vv+mCf7pLSppqOLqE7cCOdjoULfmp11uuP58QPCJ+knnxZXKRC0E8Dpvt74JRSE4+J81TwKUyJmShgMqcWqdmR8jRe9wZHOW7CXlcSGDO+JtGmwJpdVutjkojSymExYAfKTJWiwu5XTEU6bfLfC4MNG2KtM5YCMGgBO8d80DDCQ88vtXBBPlNq9NrpFNZ9m1s5kBjyU8sj1CmLZ01NKWWbUAH9/9xMXz3yUXQ2W9ICOJdS2phqeNUchaOLLTeWJaYAmls9NnsSHEm2zMA8KpZLH+cgPbh50cbQDbNeW2kw6KSoDzeiBYCXiBWOwiokissTJHR7PXwe274w8sO0OhEuP8b6W0aoVlNFEgBRD6PxFh4wgZn4+RKsAevudsETo8Gn6GBhvbEWVXnVfQz0yFV8aj0Cd1tarUaBIMFzjVyMZMtXWXmxpVorUhwK3K9rNEEkH3PJ1AP453HIp0LE7X1lJQaYqnR9xHopNycQrnX1S9IP/uhFJMEPVWhGU1ypVMJw4/WfmPts8Se5HloA964oB2un9MFi6cn3tfmD6ggwKdWhc2CN6kc5ExW8OLkoklGikwog9y1a1ZA2B9862grMTFZdAmAsrVb2ApAPKD0t2hWm0jJUOkMaLhz0o2rJK44/RNVwa64H+mgYJ3JEPOu9NxgEmxZfh7uXnMOdJrEI7vrWBkz5JM+A9XMZBTK2KhJFivtbcpZgBks9VIipOlTQUIauGM0AQyGwYiRM9Z8WoSLFZbLN0HuvGUxAKZYTOVuuC6zBoYHo/Ysyr8UiV116pElNHj53YmwtWUWVGVPT3rPooFayA65kwOo0YEGJxftII5uc7pl+bW0rAcbkI0aRgvAflm+Db8GyTLQRmWsscxcAAVLVidk+MTz585Ov3Ek+8i7QXGZbW0S6POTJ61T8ZnH6ew6WgZ/Ojkf9uRdA2ISt+R0TwsscNYl93YoYiZozIOaOkUOeuRI7XTLskVsbZge9MnRApAkTog0zEyLBtlJIjlFqUD0OgnUGVg8fYp51nRedjQaCkthtMpuZJu/fX8h7ERDPcQlbtQkbyessqXONaAOnwGRlQt9vRI7SpXYqM2ZflsmoY5XICvX3xoVAJX0To1B1+iFepAJkm1O/36aweFBqEUCMFiyQW3KHpW2bD9cDr85Ngx4vk5YYzsG+3OuhiZDSUoAabkJsvOZVlqvHGHYk+HQLZzLtnjPRjaa0b7i/y/AAI/skfkzCz/SAAAAAElFTkSuQmCC') - - e_mask = ('Mask', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+tpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIyLTA5LTI3VDA4OjI3OjA1KzA3OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMi0wOS0yN1QwOTozMzowOCswNzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMi0wOS0yN1QwOTozMzowOCswNzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QjhFREY5RkMzRTBDMTFFREEyOUJCRjFCOTY3MzMyREUiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QjhFREY5RkQzRTBDMTFFREEyOUJCRjFCOTY3MzMyREUiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpCOEVERjlGQTNFMEMxMUVEQTI5QkJGMUI5NjczMzJERSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpCOEVERjlGQjNFMEMxMUVEQTI5QkJGMUI5NjczMzJERSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PkdNbj4AACZFSURBVHja7F0JfFxV1f+/2ffsbZp039KVlkIXutCP0tJCLUuBSlGUVVE2QUQRBVFx/QQU5UNALaCiAgVklbZqC3ShdE/3pk3TNM0+mUwyyWzvfefc92ZJMjNZmqRJ9f5+t286ee/Nved/z3rPvVdSFAX/Lf23GNq7QZKkftOZRVlw0kWv/deiVS51cbc1rqlBsL/0qT0Gk9q94QwDSKAMpUsB1WFazaOaQzWDKzUvm67p1A1zZ95Lz3noUkPP1dLVTZWvlVRLqB6nWkT1AIHt+y+AHQdrHF1mUp1BdTr99ERqnq31fVbiq7xcKDnZkLIzAZcDMJvV77nYrCRajC2faWgE5DBV6q7XCwSIB2sIsupaKOUVdHVDkuW29KM2nKA27KDPn1DdSnUTgdrwXwBVwBicZVSX0M8soqbkR/7GAF0wHdK40UD+ICCLgLITMEYjt0lH/+i4dVovu0cihglgvx/wEMAVVcAx4sWde4BPdwHBYJRzQ9TOjfRxLdXXCMx9/1EAEmhM+Uuo3kivXsYcpqNvZk4DFs4Hxo8FMtMBnYGwNQ+mShLTTAia6Goiyal3ETWJdRqIKRqIus0k6ZRwj3NCUzNwooxYcDvw9hooxL2SBuhe6sPL9PF5ArPirAWQgCP+wW30urvpJ0cZyHy6fDGx3gJgKOGkM5IctJEEtY8nWTiKwBpIt+tiLwgQS3hJgnmJgv4TZ9y4YJG8jTjzj69COX5CkIk58xX6088JyB1nDYAEHFu6t9JrHqWfGkD6SVm6CNJiBm4YsZpzOtWpBNrIloAJmUb2g5dUT/0WYoFj3J0+ZyX6A6QUaVy98R6w72D061epfoeAPNivASTwzqfHX6CfmOB0QFm5HNLShRKsOQRY+jziuPGaLmstr46S4b+BwPu02/Rbb5TCA8BLxIM7dgvRKlO/f0Jff5+A9PcrAAk4tgF/SI/eT1VavhTS9Vfr4MifS4b/IhKPAxK0NEScRkPZva5PiMiulhJyRLbsBN55F0rZSUG+/UTiGwjEbf0CQAIvhx5ZTa+dO5Rsym/dDYyeQhZK9lXJgfN8TDY9yaCQu99HRsLkihSStPeT4Fi/HlizTtjKAaLHbQTii30aQAJvMN3+bzZSFl4IfO3OdJgGXw84piR+oJ5EZPVqsiprElt+ZPf4Nf/cI6WRBoy1pRkWUZPqJnqOn5foqTThsycv6S0CNaSOlSZ6WpV6/KzUSd1bSa87Ual+PkHC5IWXoDQ2isY/SCD+pE8CqIG3RZb0eRO/tgwXLpqIEYMWQdY7ECSJGoAJYejF59qQgncqa7DHZ4wSul5yQSYjJkQ2TyPsfY6z9NR6h+a/2+CDWfELcBloK/XApdSLz3ZqvVPxormuHtZQPexyPZT6euz74zalec8BSTNuHutTABJ4LrptM4E33v/LF2GafD2uyW5jU4qynWiwikanX8Z/VLGH6zH3p5dA/mQL//cmAnFVdwCo66b2raLfGa889gTMBN6KJOD9g1Tcs+X/eeBxadS7sPGB96AbNYrDc8/SoJ/eHe89bQCpIbfR5SrTjTfixLS7cHV24vs21gOra/qiJ9d7xWvIwL5H/y6FzDYjgfhnLZR45gCkBgykhjyuGz5c+fjKX+GGAYlf6CaL7K/V+G9ho8YxAYFv/5hEI0bTfx8+3fedlg4kAJ+hy5fdv30LzrGfwXU5SeRrBbDJm7ohTngJfFkYCCYlQKZOUBgEiaxINijYUEhUTGQu2RLMALGBVA9XwmeCkrGN4RQxrtjw8oppRkQNLR/9QhDGrhOd+nTxo9Oh27mNw2+jSB+WdFUHGk6D+4YTtrc5phQgnGPDHWkHkUW/xZYYE5EB4GswUIXcupeElcZWnE1034d0pU4FAt5+y00MIgPP7oxPsokB0kC9FD2k/9eE03Ckhj7rnGjQpcGrT49W84qrEdixjen/Xaq3dbUNhtNo/1dpcOjunH8QF9m+SW+6LbGCq/4DJsmbz0pxyIM06kO27rsiWA073OocZFvOAn6ZSz5jBW4gZvgmcWFtrwHIMwvMfRlpwLwL6AvXzMQ3cmSl/pO2ji7pwyqqjSTpQiHA16zOxfH/+drcrE64BgL0mfzpUDj2faTzjQnmyRs6MHduMqq1BRD0f7NJE896wBKZGKYrT3U57LHvI/dazEQ8+s5GZojLKeYvxXetC9/b5E+kmoC5s4HXVotIxa1Uf9abHLiciJi+9BJ6gYl6Z5+Y+C73v4T2ER9Jjb3+DrBuA4FXc/ZxI4M5ZRJw5WXq3GYUQGNiALmcMxl4620owSBu6XUA+Z+LL2QPlVoh6RPICGKhug/Fx/UbSVw8q86hna2FpQTPD3JlAL95t8q55hS2jom489xzIW3ZgrEk1SaTGN3T4wDSDzmI/ZeOGkFig+dceUooWZxT9uHN94Hf/K6VRWh1QjZT73R6URWdliJBV/ZyoTOothrLLf6/NkAUvj9iFEva31qPG32KLskymd0JogicLKMpMZEYIyw/Rf2ePkviKosqhdXZfykcit4jhQLQNXroO3Xqa8t24J6HgMd/kBpALpMm0P0iOIMVVPf0Bgcu5AywuRG1Z08CoOdD7CoEnv597KuwIwPBgSOhmKxnhk14gCTyVONA73KggYhi8FTAWHFMgHriJPDY48BD96d+bPhwwYksRi/XLNIed+QX8D/nncPaP5uGQFrbO/xlkBuL8MRvtcHMIiY9F4EhE88ceKdZ5IZ6BE+WqLWsBKHykwjVVJGQaVA7yTkV1Ef/8HOiUmAnDeBNW9rhILp17Bj2xzGZpFtmjwNI7byY0/bGcAaEZXgS7tuAjVuBsnKt8yQug7mj+rWO0zlc0DldUTZVSJQqzU0Iu2sRqjwFJeCP6+vo6HOr32n/3aNHa/49cFGPAkgjhBNoJ0war5rXsAxLIErI9vdswT8/jFPw2UMS6qv+VvSudEjmtr6CQr5QqLoSMgEqVIUrG4pZDXMWl5DVXZn6vUOGRD/O6WkOPJf/KYgMMHN+gojtLjT5fPhke+QX9Ag7M3G2FH1aJiAl1oFhd7UAUwxaVyyuWLg39TsHDlDtOSrTegXA0SMidnBuAutzM7ZsUx3xiOGSMHGpnxaJPHmdNckkgqxA9tZFuTBSdu1uZ1AQeIPzhZCaRlJO6kkAp0YB1JETY8xq5QzVA7592ByXvhN25Zx1Pp/OkZbc2GnyCXeFjTVZE6MVlWoaf6rCABITc9R8WE8COIpVQA7jZshKID4/Eb7Szj0xiydsTz/rAGQulExJ1tIoGogMpiOmOoqKUr9zQCzfa0yPAUh4jM2PSE1jAgA9m4TSrq2LOewR4X7WcaHNnoIL1ZBT/OA9fCT1+9Jjt47qEQA5AkMsnj1oYBIAyfeDvxTb42IJZyP3RQnHejCJthIuBYlR2eaK6v+jRTGfOFHJ6GkAqQiTMyeim/XOtuKTLa79cSPxLAaQ/SjJaEouRv3NAjwBIhUfeRiVKdwJhyOmDnsKQCGlMyOYGFoByLFPKgcORwUuZIsDZ3ORzMnzUhW/OvcVT4MTKRLOeVrKoAZwsnsKQKH9MtKipljsL03FQLBKTBlVa9aWYraelvvAAW5/+kD4Bo5EyObqdXBCFjt8A4ajOTNPDaInNGZMnQLwZFnq30xTaZvXmXZ2JpgtRkaaKwEHelXuOx43wmRL15Jzm7IH4+S8lag+52JBxOgIrTyOAdvfw6BNq6EPNPUIaIreiIrzl6J8xjI0DBoTjR7pgs3I2rsBgze8DPupmDUimVIAyA4968G4PpS3s3ownUhaW4ucngJQODVWa2sdKAMN26JhoxiAnRSfRKzS+Z/D8YU3C0K2Lr4Bw1C85HaUXrgSo998Atm713UreJ6R03Do2geJ69sGJ2SjBVVTL0HVlIUCxGFrnhfTSRIHrTmmKCdOdFWCAYAlEXOwHEZFOwDarDE694QIFYjZIwDqND+Il4IFVbl5Kq6BisnWKXF56NqHULz4ywnBayHabGk4sPJ7OLb0rm6Lr5bNvhp7bn0yIXgtB5lODLL9n/thtJ2SITkPCAB5AJhVojU1xdJCEhWLVViq9p4CULBUJF+E7OgW4lMAGGdlySZLh19cvOQrqDx3caeIfnLuCgH46ZaK8z+Do8u+1qnBUDt+Dg4v/4YKoD4VgGo8UTHGaOFOsQArklNDLpu9J0SouNcYYRCeEedZam8sblYdFy5SjB3b9aN++BTSede17EjNSdgrjoor6zueEQ8TEYLOLPhyhqIxbwxkg0lwQ3bhejhK93cJvAC9r+iKe9Xu0G/Yy4/CWnkM5vpq6P0+YbzI1A82ZBoHjkBTTizKVTntUvrtDUjb/FZyAMOhNgB6yNAbNCjx/XEq1ditANKIuFaSpJX8+Xd/UnDL54CBBQRQ4wE1/qmVusgqLZH60DHmLptzjZAbruN7kL3nn4IopvqqdowNAxryC1A/7BycTrI+D4Kh61aJAeA6XiiMlVQl6MhAzcQLUU21bvT51PZrkf5Jigm/CIBxXNqQZIOSY8Xqjhi8A4eiyH8jmt+/pga72zUd2sv8vSRbupQu7xrIZHZlZKK2spz8FQlXXH8xPneVD47Qxui9S69Xt+NQSHw2jzq/Q0T0Dp0Eo7caFnd5v/IBmXubSBo492xAuM6d1DAz5g2B3lMJU9kh8dUS0hTzL4zdUkVj9b33gf0HNGd78FBUlpbQ+NfVKbI87oNqpeJ0daBQNL9Z9yle3luGh57/K3LyR+C1F9fiC5/fjFffiu2hErkqnYh/OksK+x14Qtx5a5B2dEdqSRNhjjh6RGjEmw29/gbw5K8kAd7UeQsEjf+48zhu/8HjpJ1kDpms6A4RKpSZk7iP10nMv3IF5lx2Jf7++6fx51/8AM++WIs339dh5VVxprR0dgawTyfsFnWHfMC6fwIbPpQQCCgYNm4Cbn3kp5i5aGnMH8wZ0IL2p8uBvGUG7ls6Dx++9ZpYbGEgbbv89q9h1adFWHHXA3B7jHjyt3ELYc6C9IluDRDEcem2HTqsJRfWkZGLe594Dr9dvysKnr+5CX958sd44t4vKURLzl98szt0IKPxKL3wIbpXN2HGbNz2yM8wcWYsfYNl9qoffQfrXvmjAJiVdoAMjMiEZqf8ebY6OWGIRy29R9FyR88Q6dU8UDmkXrlvJnMLX1X2NSLsTp5qbswfCkPNCZiqSgRtLHY7PnvXN3HNHV8nH1+lD4lLrP3bS/jDYw+h+tRJ1n819N2XyIhZ3W1LrMkq4pzF70e+n/uZ5bj5uz/G4FFjo/cWFe7Esw/fjx0b1qmTuWkDECTTWzGY2qGTTJ0shbGOdKHm/LZph8GomvUsnvWcDGzQkn51UY6PJghrTncL/SSHYu/SEnYjvx1N3uUk3bgacQPaWK9WF/VrqJhtkRu9SY0YfTggNkzQ+TwkRfVY+sUv4fMPPIKMnIHRe7b/ew2efeR+HN27m+6RIMsKzwbnEnheVY12H4CfpctfvvhZNX2cN7XRGwzUqC/jBmpUWlYshLd13ft4/tEHcGzfHlKHegQz8hDMGpyQkzgkZT6xF1KTF+nZAzBryTLk5A1Gg6cOjfWeNtXnrRfXYMDf7fxmdThhd6W1rE71anO6YCAnuKKmEh+9+mcESJkFyTcMGB0I17dcv6ijwWL218EYVGfmZ5PNcOvDP8Hg0QXRe47u3UXAfUMAyCQ+bxpQUiIW/Rz4oBrjY3ZQ9wG4kC5rvnozcCU5Fps+BZ57SUJpmUIddwixcDWLBYs1KhY++MsLWPXj76KGxQK5IYGsISL5NV5HmskH05FFt/j6m3Dnz34Tfb69Eg6F0NTYQEwTRlODFzJxEoPbkaIn0Wy1O2g86QVo3EcGqUNuTziIYz43Xrzti9i99n00ZQ5FMBQhpkzAeWAKqsm+486biS89+r+YNGtuLNhRVoo/kLpZ+9cXBTgFJMCWLCGWI6Z87EdQGhrxMXHfvJ4AkDd72blyOXDTSo2IJHXeW8fbS+ngrpORlTsINz74Q1yy8kaW41HF/NrTj+Ovv/yJIDhILwZIrIbJj9IR15mLd2Ha/IX48asf9Jvdgfc1uRGiAfTw1AI0+prgtebAFPDCQpXF8KDhowTHzV12dbRPLDWYBqufeQIBvx/5eRIuXaJg1KgYLb+jLrh+nQBc3lEAOxMLLWsdLuN0uM9cAqx6SsbnrwHqqsrxi3tuwZfnT8HWte+pHEYcdf19D+HF7Udxxa13Qh8KwERcZz6+Bwa3OkG2kv7en7Z2dpIRo+h1uPaRxyAFm+FqPAVLcx2caWn46o9+id9t3Id5l1+jbmEYCOCN557CF84bib8QgCZjECuuBe74agy8iF8YT+duD2bTqKii9gQSpcfxTrlfIN14wXR1tBQf2IuHrrsM31y+EEf2qDsvso684ydP4flN+4QBxIpd71FDZuOmzehXboFFp7rPQyarO1AZyPi47p5v4QVyq6780t3CzWLO+fDvr+LWORPx9IN3o0GLM952i4xzp7b1tLyxENuJHgEw8vKKFGHK4YNjEQieyGRr9I4F5+GnX7kBFSeOiz/ljxyDh1e9hiff/VgEBwSXWm39CkCTZt3qtKmku372tLDIHWlqvknh5o/wtUtn4wc3X4uy4qNiuZxC+pG1SnaShIk49V3SYwASLkXllaq8TlSGxqXjsIntHzYZYYNZ+Ic3zyrAc997QFiXXNifnDxrXr90zA2twmdpWSoqpUcO4tEvLsd9n5mH/Z9uRtiRieYRU6IuDIOnS0Lx2phkK+5JDjzI4JUnya4SK5YiL25uhGxLg2/gGDRZsxAIyXjl1z/HF0kXrH7mSaEb+m1krNX/2UB56oE7cOvsifj4nddp0FrQ6BiEwODx2kJQteQNSv7Oytg+Ogc6NZg62XYRUufFi/kJGsML/Tnlgmee2cLkSIbObEHQaKdqgznkg9RQj2e+cy/eePZXcGVm9UsA9a0U2JNfvx1BfzMZNiY02TIRMlghWSzQ0X0qHdSSn5/8nZx+T7fXkg/o7kkOFOtsjpYkczmASRFflcxpXVODmoKuU3eY9xvs8GYMRSgzHxWlJTi089N+yoMtAQwGg2i2ZMJrzxXgCcJqaRS89DpShiVZ9cApNWVlwu4pPF1p0F7ZJUJmx5LfMHVy3MsbVX2ni3POZX8QTXobmoZN6dS0U58KTreaRG4yZyBgapnEJVnVBBe9TwWQU1HykyQMVtcAoaAYFTt6FEDejIa4rPhICgCnnRMnahpUzdx6HYFCjmxABID756yF3Mq5VlqJVF4Eyrkyeh7A2qYKI0cmN2DiMra39zQH8qDaxtlndUk2wR05TFu9BFUPSkG/yGCWDPrWVEi9WKAvA9geUa3qgNV7Y5bJ+HEpfLOY5/dpjwNI5SP+Z8/+5Hpw/uw4LtQ6obM5cbaUsJICQmIzIXF4HzJvTTRiNWli8keOHI2e5XSgNwAUq98LUySCXTQ3zsytU1M6dHbSEbqzY6I3lEJyiH4SGnoCL+JCjBkTl47ZqvAM/cmTAu/1pKLk3gBwJ7XPu21X8hvYHxwxVONIv0+EzXhk6l0ZZwWAgSRH/fDCT71DXXtgcJ+Kfn/+ecnfdbwkagls6A6ftCOGTJhGyz9KTiZ36Lksi8vTNdSejI5OfWY2MaIMQ6gJ/XX/Xr/cEkCeuNUTixmyB6oitLlBHbRQF6yk0n+HDkU/vtcrAGrlbf5nc6ujLIrLSSRo86x8kJWW60/ipBbmYzthLimEvbQQDk8pbL6qxNte9YPS1ApAngO0Vx6C9dgOMctiKom5czOmJ7c+2f/bXSiM2ONdPQWtq5vdvcu/v34jdDy5K/QC9WnvQeAfZWIPTJRzdkRIinIZj0qeI+Rg9phzpmH0Oefi43ffwP6tmyJba/aLEqRB528lQi+8cgX8pMyO7N6OmvKWs0GbNutITMrCB+SMbA6nZWaqxh6LT596nsQbXW1PlwDkqaVFWViz9wAW//BxdUem4hMSQqGYSORE4OHjJopTW0ZPPlfUkZOmwBLnE+7d8jEsTpeYIE3Tm0R16I19GszaUNtUjgXLV4q0CS6emioc3rVdTKMVUeXPhw8XkaiM0cZikZCbq8AfSwR/uVcB5BPJJEkaxrGfDZsAq92OgvOmCs4aNWmqAG1YwUSRQ5LUnyT50eRr1Kw6GTWhZlE5zmjXGeHQGQSYPPfWFwBtlEOife5Q6lwcnvc8f8FiUaMit8ErEr6O7N4hgGVOPX5wn0gL0coSqlu6FNTryqbnvFaCLn/jUXeLlpkm6ZKr01AwiJJD+8Ro5FEpOrFnJ5obG2B1peH7hUUpoo4SrDo9VYO4miWqdDX24OZBLCabSc81E2iNWg0l0NfeoiJ8/6KZcLjSMX7GBVFJwwM4d+iIlFkGnJR1cPtWMVdaWXpcJhzyEh0g2VObnousqWU3fQVDxrQ0sZqJqzhFjkcZjzoGrXh/IYEYmz6SyB+UjGrWnyLL7cYdfURAnxxqAyxPrDKQBlElceUZAD39LX7GQGpl77IZLdM3HBIL0ZXB4Rrgypv0dNI6bmzyiBSSSBoJF85ii4DJUomlE9NKr00CG01mkex00fLrONWCRyMnWFT0ighlX5D/+dMvfgAfiYfy40eJswgsAq206FALUMxmCfmDFOSREue69rAJskkSVG0+FkJzjVfstah0MieGiczGhL8Xjl9NVhqq1fQE62gjdKTXzs0NIl0vi7XwZWVeFG7egN0b10fvN5ktGDFhMhlwBOrkqSIz7oOXV3EWdoA4rUtr5LoKIC+Ke6Vw80fXcvpAVP67dJhQIINTRNnaYsCys5QW+R//LpMQ0JjJ4JLEwWVucobSCwr6nTux7rmnodProLepAzI7V8KM0bEhxiqO18WfYkBP8SYHzTha+CkO7tjaciwCd5P4dPcagPRjipboywd/TKJ6M9UpVy+Tcc0y8m2OJo9Tx0fTbDl66Kpk/N9N1+Hb67dCMRr6DXgnN2/Crg/ehWlgbBvo1pFClpa8B9pgbSKX9wx/+hlFcdcK0B7TROY6oueBrraju04v4yN4tvEx4t+4ExhLarE6yWzFc+tMqKpX32k3K1g8KoAXXwKyBg/Frb99AdkTJqop8n3Wi2/G1pdfwt++9yDSMnUIDzdGM/iXzwxiXF5inc7HJ/z+D9GZBz4nokO71Pfm+YET6FYOdGfe9gVgZEFiLnxzqxF7S3Xau4EHLvfjyBE+P0EHr1ftvDUtHeMumIcxs+YgnwDNHDoMZvpOb7VA7mFwRW/Jag4Su/hIx1UcOYwSMv8PfLweJYW7IWum/9ixwJBzDPikODZNdvuiADIdbTvNq3JXvagGran8hsC7s8O6vpdP8JxMt6+hVw6cOwdYuDB2oEak7DquxzvbY6Ly1gUBDEhTxCEfe/eq0Ynqat6eUUJdXdu2Gcxm5JOPmTe2ABmD8pGeOwiO7GzYM7JgslrF3/Wa/2m02UT7w4EgwpoV7BdrnMmydbvRUFuD+qpK1FWcgpuoe4ws5rpTJ9sQjVckc0ZZFunzrCxgAtngw4bSoNtixMEydUC5rAruXNI2UYvXO/zpZXEGJBPyKar3sArqkwBqIA6hR16h186kziorroU0dEicKAlSL94zI6gZj/8zIYTZBYktSQa1WjvlhXd34A0CPPVqDqWnXgefT0E4fPoBcbaUea8yl0sRGxlxAJorg8V7w/FOgq3JwGflPv52rB/cB+5LfNvX/QvYsEE8y2fo3kvAPd3Ztp2pU6zFoU706Hd4XnPKFOLGBbGk1rV7SPQcUUVPhl3Bl0n0dHWqkAkV2X+FrzzRz1IulOD08khqDjMop6xwRjlfuyKVd5fo8fY2zaejrnzlkgAcFkXkzO4gJ+uDtVBooDH5CokGn+vIhgV9BsB4kUqXn1NdzAKEj5qZMYPci3zVmGloVt+9ZGoI00acOX+u04OGBsjz1P46n9r+BZNCmDgojJ27gI0bodTVCbJ5iLTfoz8/TeB1OQn2jAIYBySfNfENLeaHjEwoYybrpJNhA+oJRB7BN18UQJazf8wPsg5nXW4gzs21h6GrDGHffpE9z+SqJpKyrnuqq75dnwMwDkgOwd1Cr7yOXQ4h1lySMmikTnJlAjNHh8U6Oaul74HGZOKFPQeO63CYDBdPhYzyYkJMVhcj09/XcnCK6l9Ph+P6NIBxQLLW4dQnnk1cRJWTDnSRsEQWcWhuLqScHPJJMgCnU90Q1W7nGKJq2ZqM3QtOU7N23F2TerQdG6u8oIhzNiurRDSFd86SYnRBDT23huMaVN8m0Cp7ZuD0QQATAMrLY/lUZ94daBr9JHNqATUtKUyc6cUz/lzt9th3lhQbc3CItkmbg+P9WjihiMBSyMmWUtMAldQWnjHnDaW3avVQV5KQzkoAk4DKZio7IJyQPlj7zBmnvIkK27OcCp1GzXNStVA38qKbHkCb5dD6Jul1iMa71HQInoispT/Xa5/ZOazRKudB8rR6KdSlXsUElOfMie5+CmAnweY5rf2hzDxxOlrSvoRDsBwSx8GynrquPxhM3bnEui8XNWu4nbUW4jxCtZw1m3kb+lNjidM4MDdFE6vxIIgJZt4kSO9pZ05UkhQa1qPpXTe2DllS5WXEu7rTiuzp0udFqHam3lVUOY1jPnsePfyTbObwLOwrUHeMqD2T/e+XOpBAY0NleRxoQvaZM7Jhyc6D0ZkGncks9tbsElGo+siWCcixbzhHVfI3I+w+hWBZcWRVUTgOzNU95Sr0J0eerUde22vTamR3HSZUSPMNGbA5Ef1syc6FPX8EbHkjYLB1r+ryeDzk69W1IRLn1RjkAJTqMgRKD0c2Ned/OP2AU+A/hrqrbkSpspXq0+opArr6rAKQgLvKYMBPQ6H2D3biwLLO4kDa2HMIuJHQW3p2B4sAee9VVVVilW2y/hvlIEJFu6B4ayB3wPOjvh6mvn6LN6vr9wASeJzx+vr4sVAWXwQpl4Sj06Ee0c1gVbjJ+aLx6/eTQ0Ye2YFDJLNojOfMWADHkNG9Jqbcbjfq65Ns1VVbDuXYbrHT7rixauCAT3HLIvkxMENlUE6X4L1eeL3IP/4FZf8h4XheRSC+0ZMA9qgVytNKBj2eLBgjKY///i5JckziEzGop1vJXX5THFfAidqcgc/t5O3yho8Atn4qIejtPd+ZB2lmZiasViuqq6sRbrWPitLcCJtVwpLFSnx0BiPyaTAmEBBLFkC672Eoh47gSaIBh9lCPdX2nvYDV4TCGHbf9z4vSdmXAid/DRTdT1riD9GzJpgAkwi0fG2uMCBCXAr0JjN6uzCA+fn5sNlaosJbXfqalOippNxWbrPTllwN3HI9JO47OrBtcp8FkPzmb48drZOHzLoPOPgVkjO7yVzxtbnPZFBFEZfIzvcGR++fl6QSX4cBAwYgKysrpj60HScibeO2mtqRXZMniHWSMtOgXwJIomM+SaKJt9+3VIfaf5B3Vdyh5yJEMjrSOvxbI3O9uPyCElw+qwTDBibe199rsOGTtAl4Y8CFeGXgAqzPOBeN+uRbWzqdTuTlkcvC0/fa+UfRYxU6Kn6ugI5pwLTod5EYGrz3pLkQnjB9lh7Fj7V7fyS3hHNfeOQbOrCm3mSUcd38o5g1PraB25LpJ/HPnYPw2kfDo1lxO5xjsc1VADnOb3QbnSixDMTimi0YEEg878rgpaeno4osVW6T261E22rqAOXmzATS0xD21OMezZ/sHxxII453RLni8kv1ep37PRKb3nafadIW/fCWG2anPeViGRHMtAbx9asLW4AXKQumnsLNiw/BoFew3z4cW9PGtwAv+pt6M97OmYMyc/Ij+0x8nAqvt7Cao9uBNHVws2DemGPZYuErXqHRpN+I0FuYCS9dQEPV81GHHogQ5VQ56U5H6i240h0B3Lt8L4bkNCa957wxNfjqsv0oCJYiM5h8J9+QpMf72bNQZ3Qm8ekMamqiySna1hkAuVy2UBVIGk36PoA8206K+/aZ50HK6sSeBrw0m0Ve6UlynNOyUnBeSIA3KLP9MwTHDfHgvqW7cbV7A7KCnpQgrsmcnpBLhSNPolSxOlFaKok2+joBINOAacE00TIR+jwHLiLFnXfZxZ17qKFJzfsMBhSYXJlJ77th4RHkpDV3+L1jB3tw79I9uNy9EY5wctBZJx6wD0uqCyWrA8GgItrY0MnzJ5kWTBOo6SN9G0AasJ8nxS1PP7fjzzQHIDYOr9B0jCktMYC5GU2YPNydAHwDfv3meFH5cyIQb5q3Hxe6U29FVmgfkRRAWFURy23ktjZ3YsKJacE0Ydr0aQD53Dtq5DUL5gkx2uFSr7mGZWW8tt6Q1IUYnpvYRdh1NAv7StJF3VGUWPzOHFeFEcEKOEO+pO3wGB3JAbTYoCOrpEzbw8Dr65Q/DKYJ06YzZwOeCQ68QpZhWTC3cw9FiMErd0wZOUmP7rGZE0ekxg+tE2KVjZuCwYl1nV6niHQZfYo8JJMcSg4grwm2u3CitOWg62hhmjBtmEZ91g8ky39F7gDIY0d1fGBwKnx9oxoQLjomwTp8YKd/N9Ppx6NfaEc8FmegWnGizpB8SirfX5kCQNJj1nQUHa3j01XUNisd3z2MaMIb4srllSK09uc+x4EkGizUlyX/M7tz7/Q0qITg3MuAX4ElK7fbraoqjwUvrBsjoi9JxZwi43zPgSR6XVLdCUe6aCO3ldvsaehcO5g2TCOmVV8UoZeGZZgvmN65h9wNMfHJhOIJ3O4sdQ0m/O/qyVhtm41T5uTuyXwycNJDyRERXOjIENI9sj2ku5MAMm2YRlATmvscgA/y0qyxozr+QPwoPlJEdkJGBnRGU7eC9/jqSXjdPAvHLckHxgV1hRjtK035LgEgb+Jqd4q2xkuPDrs0oyCWrzGt+hSAJBKc1L/zZkzr3NGBtfUqAXiaZv9+CeYBw7odvL/pZ+OoNflu4zM8+zDWdwKVpoz2AWSn35HNC1lEm7nttfUdbxPThmnEtGKa9SUOvDoUhG7SuE7qJi26f6IEwkm25Q7tlsaU11rx81cnC/CO2AanBG9cYwneypkjYqKpQIwAKKXniLWHJ0pa9qGjhWnEtGKadUdf/1+AAQCrIkb0EMnrrQAAAABJRU5ErkJggg==') - - e_salute = ('Salute', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+tpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIyLTA5LTI0VDA4OjE1OjA5KzA3OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMi0wOS0yNFQxMjowOTowNSswNzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMi0wOS0yNFQxMjowOTowNSswNzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MDMxRUIwOTUzQkM3MTFFRDlFNTZDOTNFRDVGQ0ZDRTkiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MDMxRUIwOTYzQkM3MTFFRDlFNTZDOTNFRDVGQ0ZDRTkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RS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') - - e_scream = ('Scream', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+tpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIyLTA5LTIyVDA4OjEwOjQzKzA3OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMi0wOS0yMlQwODo1NDozNiswNzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMi0wOS0yMlQwODo1NDozNiswNzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6ODMwM0E4NzEzQTE5MTFFRDlCQTJFQjRDMUVGMzgzMjQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6ODMwM0E4NzIzQTE5MTFFRDlCQTJFQjRDMUVGMzgzMjQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RS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') - - e_smirking = ('Smirking', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkFEMEUwNDhCMzk1RjExRUQ4NTAyQjQ0RkY4QjYzNDMzIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkFEMEUwNDhDMzk1RjExRUQ4NTAyQjQ0RkY4QjYzNDMzIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QUQwRTA0ODkzOTVGMTFFRDg1MDJCNDRGRjhCNjM0MzMiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QUQwRTA0OEEzOTVGMTFFRDg1MDJCNDRGRjhCNjM0MzMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4JM0EHAAAi8UlEQVR42ux9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') - - e_warning2 = ('Warning2', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+tpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIyLTA5LTIyVDA4OjEwOjQzKzA3OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMi0wOS0yMlQwODo1NDoxNiswNzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMi0wOS0yMlQwODo1NDoxNiswNzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NzcxNjY1MDUzQTE5MTFFRDg4MzI4RTQ0MTMxMUQ2NDkiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NzcxNjY1MDYzQTE5MTFFRDg4MzI4RTQ0MTMxMUQ2NDkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RS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') - - e_warning = ('Warning', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+tpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIyLTA5LTIyVDA4OjEwOjQzKzA3OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMi0wOS0yMlQwODo1Mzo1NyswNzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMi0wOS0yMlQwODo1Mzo1NyswNzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NkJCRTI2Q0UzQTE5MTFFREI0MDNDRTQyQzFFM0UzQzIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NkJCRTI2Q0YzQTE5MTFFREI0MDNDRTQyQzFFM0UzQzIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RS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') - - e_python_hearts = ('PyHearts', sg.PYTHON_COLORED_HEARTS_BASE64) - e_psg_hero = ('PySimpleGUI Hero', sg.EMOJI_BASE64_SUPERHERO) - - all_emojis = (e_happy, e_wave, e_search, e_santa, e_reading, e_blank_stare, e_stare, e_party, e_laptop, e_head_explode, e_glasses,e_laugh, e_joy, e_idea, e_cool, e_relief, e_wink, e_thumb, e_love, e_clap, e_fingers_crossed, e_ok, e_pray, e_smile, e_guess, e_crazy, e_eye_roll, e_dream, e_sleeping, e_python_hearts, e_psg_hero, e_wizard, e_grimace, e_weary, e_rainedon, e_upside_down, e_think, e_frust, e_dead, e_gasp, e_tear, e_cry, e_no_speak, e_no_hear, e_no_see, e_zipped_shut, e_ponder, e_skeptic, e_palm, e_eyebrow, e_not_understand, e_question, e_depressed, e_ill, e_ill2, e_mask, e_warning, e_warning2, e_key, e_salute, e_honest, e_gold_star, e_scream, e_smirking) - - - # Build the "all_emojis" data structure. Converts the all_emojis tuple from 1 size to having 3 sizes - # all_emojis = ('Description', smallest size, mid size, large size) - - new_all_emojis = [] - for e in all_emojis: - description = e[0] - base_emoji = e[1] - new_emoji_info = [description, ] - for s in EMOJI_SIZES: - new_encoded = convert_to_bytes(base_emoji, (s, s)) - new_emoji_info.append(new_encoded) - new_all_emojis.append(tuple(new_emoji_info)) - all_emojis = new_all_emojis - - if len(sys.argv) > 1: - location = sys.argv[1] - location = location.split(',') - location = (int(location[0]), int(location[1])) - else: - location = (None, None) - main(location) - diff --git a/DemoPrograms/Demo_Emojis.py b/DemoPrograms/Demo_Emojis.py index 17644c82b..b354c4b7e 100644 --- a/DemoPrograms/Demo_Emojis.py +++ b/DemoPrograms/Demo_Emojis.py @@ -5,11 +5,7 @@ They are used internally when you get an error or as the icon for windows like the SDK help window. - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ diff --git a/DemoPrograms/Demo_Event_Binding.py b/DemoPrograms/Demo_Event_Binding.py index ae3a27eb1..882d21af8 100644 --- a/DemoPrograms/Demo_Event_Binding.py +++ b/DemoPrograms/Demo_Event_Binding.py @@ -12,11 +12,7 @@ Second parameter for windows is an entire key, for elements is something added onto a key. This key or modified key is what is returned when you read the window. If the key modifier is text and the key is text, then the key returned from the read will be the 2 concatenated together. Otherwise your event will be a tuple containing the key_modifier value you pass in and the key belonging to the element the event happened to. - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ sg.theme('Dark Blue 3') diff --git a/DemoPrograms/Demo_Event_Callback_Simulation.py b/DemoPrograms/Demo_Event_Callback_Simulation.py index 4f61814d3..a79f37186 100644 --- a/DemoPrograms/Demo_Event_Callback_Simulation.py +++ b/DemoPrograms/Demo_Event_Callback_Simulation.py @@ -9,12 +9,6 @@ functions as a mechanism for communicating when button presses or other events happen. BUT, should you want to quickly convert some existing code that does use callback functions, then this is one way to do a "quick and dirty" port to PySimpleGUI. - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. ''' # The callback functions diff --git a/DemoPrograms/Demo_Exception_Traceback_Popup.py b/DemoPrograms/Demo_Exception_Traceback_Popup.py deleted file mode 100644 index 76acad3b1..000000000 --- a/DemoPrograms/Demo_Exception_Traceback_Popup.py +++ /dev/null @@ -1,31 +0,0 @@ -import PySimpleGUI as sg - -""" - Demo - Show an error popup with traceback information - - Copyright 2021-2024 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - - -layout = [ [sg.Text('Choose the type of error to generate')], - [sg.Button('Go'), sg.B('Key Error'), sg.B('Div 0'), sg.Button('Exit')] ] - -window = sg.Window('Exception Handling and Error Information Display', layout) - -while True: # Event Loop - try: - event, values = window.read() - if event in (sg.WIN_CLOSED, 'Exit'): - break - # When choice has been made, then fill in the listbox with the choices - if event == 'Key Error': - window['bad key'] - elif event == 'Div 0': - a = 1/0 - except Exception as e: - sg.popup_error_with_traceback('Error in the event loop', e, emoji=sg.EMOJI_BASE64_SCREAM) -window.close() diff --git a/DemoPrograms/Demo_Execute_Py.py b/DemoPrograms/Demo_Execute_Py.py index 226965cac..deb8d6adb 100644 --- a/DemoPrograms/Demo_Execute_Py.py +++ b/DemoPrograms/Demo_Execute_Py.py @@ -17,11 +17,7 @@ version numbers for Python tkinter, PySimpleGUI http://www.PySimpleGUI.org - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ import PySimpleGUI as sg diff --git a/DemoPrograms/Demo_Fill_Form.py b/DemoPrograms/Demo_Fill_Form.py index 22be365f8..3eec8b6c9 100644 --- a/DemoPrograms/Demo_Fill_Form.py +++ b/DemoPrograms/Demo_Fill_Form.py @@ -3,12 +3,6 @@ ''' Example of GUI - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. ''' def main(): diff --git a/DemoPrograms/Demo_Floating_Toolbar.py b/DemoPrograms/Demo_Floating_Toolbar.py index f9431bbc3..b87caeda3 100644 --- a/DemoPrograms/Demo_Floating_Toolbar.py +++ b/DemoPrograms/Demo_Floating_Toolbar.py @@ -3,12 +3,6 @@ ''' Example of borderless floating toolbar. - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. ''' button_names = ('close', 'cookbook', 'cpu', 'github', diff --git a/DemoPrograms/Demo_Focus_Navigation_Using_Arrow_Keys.py b/DemoPrograms/Demo_Focus_Navigation_Using_Arrow_Keys.py deleted file mode 100644 index f46ceeb55..000000000 --- a/DemoPrograms/Demo_Focus_Navigation_Using_Arrow_Keys.py +++ /dev/null @@ -1,64 +0,0 @@ -import PySimpleGUI as sg - - -""" - Demo - Navigating a window's focus using arrow keys - - This Demo Program has 2 features of PySimpleGUI in use: - 1. Binding the arrow keys - 2. Navigating a window's elements using focus - - The first step is to bind the left, right and down arrows to an event. - The call to window.bind will cause events to be generated when these keys are pressed - - The next step is to add the focus navigation to your event loop. - When the right key is pressed, the focus moves to the element that should get focus next - When the left arrow key is pressed, the focus moves to the previous element - And when the down arrow is pressed the program exits - - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - - - -def main(): - layout = [ [sg.Text('My Window')], - [sg.Input(key='-IN-')], - [sg.Input(key='-IN2-')], - [sg.Input(key='-IN3-')], - [sg.Input(key='-IN4-')], - [sg.Input(key='-IN5-')], - [sg.Input(key='-IN6-')], - [sg.Input(key='-IN7-')], - [sg.Button('Go'), sg.Button('Exit')]] - - window = sg.Window('Window Title', layout, finalize=True) - - # Bind the Left, Right and Down arrow keys to events - window.bind('', '-NEXT-') - window.bind('', '-PREV-') - window.bind('', 'Exit') - - while True: # Event Loop - event, values = window.read() - print(event, values) - if event == sg.WIN_CLOSED or event == 'Exit': - break - # Right arrow pressed, so move to the next element that should get focus - if event == '-NEXT-': - next_element = window.find_element_with_focus().get_next_focus() - next_element.set_focus() - - # Left arrow pressed, so move to the previous element that should get focus - if event == '-PREV-': - prev_element = window.find_element_with_focus().get_previous_focus() - prev_element.set_focus() - window.close() - -if __name__ == '__main__': - main() diff --git a/DemoPrograms/Demo_Font_Previewer.py b/DemoPrograms/Demo_Font_Previewer.py index d58af702a..82fd33e15 100644 --- a/DemoPrograms/Demo_Font_Previewer.py +++ b/DemoPrograms/Demo_Font_Previewer.py @@ -1,24 +1,17 @@ #!/usr/bin/env python +import sys import PySimpleGUI as sg +from tkinter import font +import tkinter +root = tkinter.Tk() +fonts = list(font.families()) +fonts.sort() +root.destroy() ''' - Demo Font Previewer - - Gets a list of the installed fonts according to tkinter. - Requires PySimpleGUI version 4.57.0 and newer (that's when sg.Text.fonts_installed_list was added) - - Uses the Text element's class method to get the fonts reported by tkinter. - - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Showing fonts in PSG / tk ''' -fonts = sg.Text.fonts_installed_list() - - sg.theme('Black') layout = [[sg.Text('My Text Element', diff --git a/DemoPrograms/Demo_Font_Sizer.py b/DemoPrograms/Demo_Font_Sizer.py index a1c402efd..716c587e9 100644 --- a/DemoPrograms/Demo_Font_Sizer.py +++ b/DemoPrograms/Demo_Font_Sizer.py @@ -1,13 +1,5 @@ import PySimpleGUI as sg -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - # Testing async form, see if can have a slider # that adjusts the size of text displayed diff --git a/DemoPrograms/Demo_Font_String.py b/DemoPrograms/Demo_Font_String.py index 9cd57cd98..73385a921 100644 --- a/DemoPrograms/Demo_Font_String.py +++ b/DemoPrograms/Demo_Font_String.py @@ -3,12 +3,6 @@ ''' App that shows "how fonts work in PySimpleGUI". - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. ''' layout = [[sg.Text('This is my sample text', size=(20, 1), key='-text-')], diff --git a/DemoPrograms/Demo_Frame_Based_Dashboard.py b/DemoPrograms/Demo_Frame_Based_Dashboard.py index 746a54c1a..7786f1c74 100644 --- a/DemoPrograms/Demo_Frame_Based_Dashboard.py +++ b/DemoPrograms/Demo_Frame_Based_Dashboard.py @@ -11,11 +11,7 @@ Dashboard using blocks of information. - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI.org """ diff --git a/DemoPrograms/Demo_Frame_For_Screen_Captures.py b/DemoPrograms/Demo_Frame_For_Screen_Captures.py deleted file mode 100644 index 9517cbd16..000000000 --- a/DemoPrograms/Demo_Frame_For_Screen_Captures.py +++ /dev/null @@ -1,51 +0,0 @@ -import PySimpleGUI as sg - -""" - Demo Frame For Screen Captures - - This program can be used to help you record videos. - - Because it relies on the "transparent color" feature that's only available on Windows, this Demo is only going - to work the indended way on Windows. - - Some video recorders that record a portion of the screen do not show you, at all times, what portion of the screen - is being recorded. This can make it difficult for you to stay within the bounds being recorded. - This demo program is meant to help the situation by showing a thin line that is 20 pixels larger than the area - being recorded. - - The top edge of the window has the controls. There's an exit button, a solid "bar" for you to grab with your mouse to move - the frame around your window, and 2 inputs with a "resize" button that enables you to set the frame to the size you want to stay - within. - - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - - -def main(): - offset = (20, 20) # Number of extra pixels to add to the recording area - default_size = (1920, 1080) # The default size of the recording - location = (None, None) # A specific location to place the window if you want a specific spot - - window = sg.Window('Window Title', - [[sg.Button('Exit'), sg.T(sg.SYMBOL_SQUARE * 10, grab=True), sg.I(default_size[0], s=4, k='-W-'), sg.I(default_size[1], s=4, k='-H-'), sg.B('Resize')], - [sg.Frame('', [[]], s=(default_size[0] + offset[0], default_size[1] + offset[1]), k='-FRAME-')]], transparent_color=sg.theme_background_color(), - right_click_menu=['', ['Edit Me', 'Exit']], location=location, no_titlebar=True, keep_on_top=True) - - while True: # Event Loop - event, values = window.read() - if event == sg.WIN_CLOSED or event == 'Exit': - break - if event == 'Edit Me': - sg.execute_editor(__file__) - elif event == 'Resize': - window['-FRAME-'].set_size((int(values['-W-']) + offset[0], int(values['-H-']) + offset[1])) - window.close() - - -if __name__ == '__main__': - main() diff --git a/DemoPrograms/Demo_Game_Frontend_Battleship.py b/DemoPrograms/Demo_Game_Frontend_Battleship.py index be850231b..e7e8cc0b1 100644 --- a/DemoPrograms/Demo_Game_Frontend_Battleship.py +++ b/DemoPrograms/Demo_Game_Frontend_Battleship.py @@ -2,14 +2,6 @@ import PySimpleGUI as sg from random import randint -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - def Battleship(): sg.theme('Dark Blue 3') MAX_ROWS = MAX_COL = 10 diff --git a/DemoPrograms/Demo_Game_Frontend_Battleship_No_List_Comprehensions.py b/DemoPrograms/Demo_Game_Frontend_Battleship_No_List_Comprehensions.py index 204a2ddba..933d696d0 100644 --- a/DemoPrograms/Demo_Game_Frontend_Battleship_No_List_Comprehensions.py +++ b/DemoPrograms/Demo_Game_Frontend_Battleship_No_List_Comprehensions.py @@ -2,14 +2,6 @@ import PySimpleGUI as sg from random import randint -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - def Battleship(): sg.theme('Dark Blue 3') MAX_ROWS = MAX_COL = 10 diff --git a/DemoPrograms/Demo_Game_Frontend_Battleship_Single_List_Comprehension.py b/DemoPrograms/Demo_Game_Frontend_Battleship_Single_List_Comprehension.py index 2de885d5b..650dbae6c 100644 --- a/DemoPrograms/Demo_Game_Frontend_Battleship_Single_List_Comprehension.py +++ b/DemoPrograms/Demo_Game_Frontend_Battleship_Single_List_Comprehension.py @@ -2,14 +2,6 @@ import PySimpleGUI as sg from random import randint -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - def Battleship(): sg.theme('Dark Blue 3') MAX_ROWS = MAX_COL = 10 diff --git a/DemoPrograms/Demo_Game_Wordle.py b/DemoPrograms/Demo_Game_Wordle.py deleted file mode 100644 index 5fde54c18..000000000 --- a/DemoPrograms/Demo_Game_Wordle.py +++ /dev/null @@ -1,102 +0,0 @@ -import PySimpleGUI as sg -import copy - -""" - Wordle GUI Demo - - Enter characters for each position - Press enter or click enter to submit a row - - This is a prototype GUI of the front-end for WORDL - It currently: - * Takes input - * Makes sure only characters - * Automatically converts to upper case - * Handles backspace - * Checks for Enter key - * Compares against a word (the constant "answer") - * Color codes the submitted guess - - To complete an application, you'll need to: - * Supply a word to guess from list of words - * Check if user's submission is a word (I think this is how WORDLE works) - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - -# Insert code to generate a word here -answer = 'WORDS' - - -def TextChar(value, key): - return sg.Input(value, key=key, font='Courier 22', size=(1,1), disabled_readonly_background_color='gray', border_width=1, p=1, enable_events=True, disabled=True) - -def main(): - layout = [[sg.Text('Wordle', font='_ 20')], - [[TextChar('', (row, col)) for col in range(5)]for row in range(6)], - [sg.B('Enter', bind_return_key=True)], - [sg.Text('Or press enter', font='_ 10')]] - - window = sg.Window("Wordle", layout, finalize=True, element_justification='c') - - cur_row, correct = 0, False - [window[(cur_row, col)].update(disabled=False) for col in range(5)] - window.bind('', '-BACKSPACE-') - while True: - event, values = window.read() - if event == sg.WIN_CLOSED: - break - if isinstance(event, tuple): - if len(values[event]): - row, col = event - char_input = values[event][-1] - if not char_input.isalpha(): # if not a character input, remove the input - window[event].update('') - else: - window[event].update(char_input.upper()[0]) # convert to uppercase - if col < 4: - window[(row, col+1)].set_focus() # Move to next position - elif event == 'Enter' and cur_row < 5: - guess = ''.join([values[(cur_row, j)] for j in range(5)]) - answer2 = copy.copy(answer) - for i, letter in enumerate(guess): - if letter == answer2[i]: - window[(cur_row, i)].update(background_color='green', text_color='white') - answer2 = answer2.replace(letter, '*') - elif letter in answer2: - window[(cur_row, i)].update(background_color='#C9B359', text_color='white') - answer2 = answer2.replace(letter, '*') - else: - window[(cur_row, i)].update(background_color='gray', text_color='white') - if guess == answer: - correct = True - break - cur_row += 1 # Move to the next row - [window[(cur_row, col)].update(disabled=False) for col in range(5)] # Enable inputs on next row - window[(cur_row, 0)].set_focus() # Move to first position on row - elif event == 'Enter' and cur_row == 5: - correct = False - break - elif event == '-BACKSPACE-': - current_focus = window.find_element_with_focus() - current_key = current_focus.Key - if isinstance(current_key, tuple): - window[current_key].update('') - if current_key[1] > 0: - window[(current_key[0], current_key[1]-1)].set_focus() - window[(current_key[0], current_key[1]-1)].update('') - - - if correct: - sg.popup('You win!') - else: - sg.popup(f'Sorry... the answer was {answer}') - - window.close() - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/DemoPrograms/Demo_GitHub_File_Copier.py b/DemoPrograms/Demo_GitHub_File_Copier.py index 8c6f6eee4..dc09f4ecb 100644 --- a/DemoPrograms/Demo_GitHub_File_Copier.py +++ b/DemoPrograms/Demo_GitHub_File_Copier.py @@ -26,11 +26,7 @@ * Edit this file in PyCharm * Launch GitHub GUI program - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ diff --git a/DemoPrograms/Demo_GoodColors.py b/DemoPrograms/Demo_GoodColors.py index 23e984be7..7132eca74 100644 --- a/DemoPrograms/Demo_GoodColors.py +++ b/DemoPrograms/Demo_GoodColors.py @@ -2,14 +2,6 @@ import sys import PySimpleGUI as sg -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - # Example of colors in PSG def main(): diff --git a/DemoPrograms/Demo_GoodColors_2.py b/DemoPrograms/Demo_GoodColors_2.py index 06fceaa81..5da9f0a08 100644 --- a/DemoPrograms/Demo_GoodColors_2.py +++ b/DemoPrograms/Demo_GoodColors_2.py @@ -3,12 +3,6 @@ ''' Example of colors in PySimpleGUI - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. ''' def main(): diff --git a/DemoPrograms/Demo_Google_TTS.py b/DemoPrograms/Demo_Google_TTS.py index b4c2bbfbb..1c850d73c 100644 --- a/DemoPrograms/Demo_Google_TTS.py +++ b/DemoPrograms/Demo_Google_TTS.py @@ -12,12 +12,6 @@ Play back the speech Note that there are 2 temp files created. The program tries to delete them but will fail on one of them - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. ''' layout = [[sg.Text('What would you like me to say?')], diff --git a/DemoPrograms/Demo_Graph_Ball_Game.py b/DemoPrograms/Demo_Graph_Ball_Game.py index 05e14cb7e..c6187e3f7 100644 --- a/DemoPrograms/Demo_Graph_Ball_Game.py +++ b/DemoPrograms/Demo_Graph_Ball_Game.py @@ -9,12 +9,6 @@ Demo that shows integrating PySimpleGUI with the pymunk library. This combination of PySimpleGUI and pymunk could be used to build games. Note this exact same demo runs with PySimpleGUIWeb by changing the import statement - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ diff --git a/DemoPrograms/Demo_Graph_Bar_Chart_Dual_Axis.py b/DemoPrograms/Demo_Graph_Bar_Chart_Dual_Axis.py deleted file mode 100644 index b0b150c05..000000000 --- a/DemoPrograms/Demo_Graph_Bar_Chart_Dual_Axis.py +++ /dev/null @@ -1,55 +0,0 @@ -import PySimpleGUI as sg -import random - -""" - Bar Chart - Dual Axis Version - - A simple bar chart with a twist - If you've got 2 values to plot, this technique enables you to trivially plot them both. - Simply set your Graph element coordinates to be negative. Make your y=0 line run through the middle - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - -BAR_WIDTH = 25 # width of each bar -BAR_SPACING = 30 # space between each bar -EDGE_OFFSET = 3 # offset from the left edge for first bar -GRAPH_SIZE= (500,500) # size in pixels - -sg.theme('Light brown 1') - -layout = [[sg.Text('Dual-Axis Bar Chart')], - [sg.Graph(GRAPH_SIZE, (0, -GRAPH_SIZE[0]//2), (GRAPH_SIZE[0]//2, GRAPH_SIZE[1]//2), k='-GRAPH-')], - [sg.Button('OK'), sg.T('Click to display more data'), sg.Exit()]] - -window = sg.Window('Bar Graph', layout, finalize=True) - -# get the Graph Element into a variable to make code completion easier -graph:sg.Graph = window['-GRAPH-'] - -while True: - graph.erase() - for i in range(8): - graph_value = random.randint(0, GRAPH_SIZE[1]//2) - graph.draw_rectangle(top_left=(i * BAR_SPACING + EDGE_OFFSET, graph_value), - bottom_right=(i * BAR_SPACING + EDGE_OFFSET + BAR_WIDTH, 0), - fill_color='green', line_width=0) - - # get a second value and draw an inverted bar. Simply set the Y value to be negative and top to be 0 - graph_value = random.randint(0, GRAPH_SIZE[1]//2) - graph.draw_rectangle(top_left=(i * BAR_SPACING + EDGE_OFFSET, 0), - bottom_right=(i * BAR_SPACING + EDGE_OFFSET + BAR_WIDTH, -graph_value), - fill_color='red', line_width=0) - - # Normally at the top of the loop, but because we're drawing the graph first, making it at the bottom - event, values = window.read() - - if event in (sg.WIN_CLOSED, 'Exit'): - break - - -window.close() \ No newline at end of file diff --git a/DemoPrograms/Demo_Graph_Custom_Progress_Meter.py b/DemoPrograms/Demo_Graph_Custom_Progress_Meter.py deleted file mode 100644 index d9fe375bf..000000000 --- a/DemoPrograms/Demo_Graph_Custom_Progress_Meter.py +++ /dev/null @@ -1,72 +0,0 @@ -""" - Demo Graph Custom Progress Meter - - The "Graph Element" is a "Gateway Element" - Looking to create your own custom elements? Then the Graph Element is an excellent - place to start. - - This short demo implements a Circular Progress Meter - - The event loop has a little trick some may like.... - Rather than adding a sleep instead use window.read with a timeout - This has a dual purpose. You get the delay you're after AND your GUI is refreshed - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - - -import PySimpleGUI as sg - -# Settings for you to modify are the size of the element, the circle width & color and the font for the % complete -GRAPH_SIZE = (300 , 300) # this one setting drives the other settings -CIRCLE_LINE_WIDTH, LINE_COLOR = 20, 'yellow' -TEXT_FONT = 'Courier' - - -# Computations based on your settings above -TEXT_HEIGHT = GRAPH_SIZE[0]//4 -TEXT_LOCATION = (GRAPH_SIZE[0]//2, GRAPH_SIZE[1]//2) -TEXT_COLOR = LINE_COLOR - -def update_meter(graph_elem, percent_complete): - """ - Update a circular progress meter - :param graph_elem: The Graph element being drawn in - :type graph_elem: sg.Graph - :param percent_complete: Percentage to show complete from 0 to 100 - :type percent_complete: float | int - """ - graph_elem.erase() - arc_length = percent_complete/100*360+.9 - if arc_length >= 360: - arc_length = 359.9 - graph_elem.draw_arc((CIRCLE_LINE_WIDTH, GRAPH_SIZE[1] - CIRCLE_LINE_WIDTH), (GRAPH_SIZE[0] - CIRCLE_LINE_WIDTH, CIRCLE_LINE_WIDTH), - arc_length, 0, 'arc', arc_color=LINE_COLOR, line_width=CIRCLE_LINE_WIDTH) - percent = percent_complete - graph_elem.draw_text(f'{percent:.0f}%', TEXT_LOCATION, font=(TEXT_FONT, -TEXT_HEIGHT), color=TEXT_COLOR) - - -def main(): - - layout = [ [sg.Graph(GRAPH_SIZE, (0,0), GRAPH_SIZE, key='-GRAPH-')], - [sg.Button('Go')]] - - - window = sg.Window('Circlular Meter', layout, finalize=True) - - while True: - event, values = window.read() - if event == sg.WIN_CLOSED: - break - for i in range(500): - update_meter(window['-GRAPH-'], i/500*100) - window.read(timeout=5) # an easy way to make a loop that acts like it has a "sleep" in it - - window.close() - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/DemoPrograms/Demo_Graph_Drag_Rectangle.py b/DemoPrograms/Demo_Graph_Drag_Rectangle.py index 8e34f9135..6c062f426 100644 --- a/DemoPrograms/Demo_Graph_Drag_Rectangle.py +++ b/DemoPrograms/Demo_Graph_Drag_Rectangle.py @@ -6,17 +6,11 @@ This demo shows how to use a Graph Element to (optionally) display an image and then use the mouse to "drag a rectangle". This is sometimes called a rubber band and is an operation you see in things like editors - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ # image_file = r'Color-names.png' # image_file = None # image is optional -image_file = r'C:\Python\PycharmProjects\PSG\logo200.png' # image is optional +image_file = r'C:\Python\PycharmProjects\GooeyGUI\logo200.png' # image is optional layout = [[sg.Graph( canvas_size=(400, 400), diff --git a/DemoPrograms/Demo_Graph_Drag_Rectangle_Super_Simple.py b/DemoPrograms/Demo_Graph_Drag_Rectangle_Super_Simple.py deleted file mode 100644 index 67cf65d9c..000000000 --- a/DemoPrograms/Demo_Graph_Drag_Rectangle_Super_Simple.py +++ /dev/null @@ -1,48 +0,0 @@ -import PySimpleGUI as sg - -""" - Demo - Drag a rectangle and move - - This demo shows how to use a Graph Element to draw a square and move it with the mouse. - It's a very simple, single element program. Like many Demo Programs, it started as - a "Test Harness" that demonstrated a bug that happened with a timeout of 0 - was added to the window.read() - - Original code comes courtesy of user @davesmivers .... Thanks Dave!! - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - - -GRAPH_SIZE = (400, 400) -START = (200, 200) # We'll assume X and Y are both this value -SQ_SIZE = 40 # Both width and height will be this value - -layout = [[sg.Graph( - canvas_size=GRAPH_SIZE, graph_bottom_left=(0, 0), graph_top_right=GRAPH_SIZE, # Define the graph area - change_submits=True, # mouse click events - drag_submits=True, # mouse move events - background_color='lightblue', - key="-GRAPH-", - pad=0)]] - -window = sg.Window("Simple Square Movement", layout, finalize=True, margins=(0,0)) - -# draw the square we'll move around -square = window["-GRAPH-"].draw_rectangle(START, (START[0]+SQ_SIZE, START[1]+SQ_SIZE), fill_color='black') - -while True: - event, values = window.read() - if event == sg.WIN_CLOSED: - break - print(event, values) if event != sg.TIMEOUT_EVENT else None # our normal debug print, but for this demo, don't spam output with timeouts - - if event == "-GRAPH-": # if there's a "Graph" event, then it's a mouse movement. Move the square - x, y = values["-GRAPH-"] # get mouse position - window["-GRAPH-"].relocate_figure(square, x - SQ_SIZE // 2, y + SQ_SIZE // 2) # Move using center of square to mouse pos - -window.close() diff --git a/DemoPrograms/Demo_Graph_Drawing.py b/DemoPrograms/Demo_Graph_Drawing.py index 036fc9d6b..3778748ef 100644 --- a/DemoPrograms/Demo_Graph_Drawing.py +++ b/DemoPrograms/Demo_Graph_Drawing.py @@ -1,14 +1,6 @@ #!/usr/bin/env python import PySimpleGUI as sg -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - # Usage of Graph element. layout = [[sg.Graph(canvas_size=(400, 400), graph_bottom_left=(0, 0), graph_top_right=(400, 400), background_color='red', enable_events=True, key='graph')], diff --git a/DemoPrograms/Demo_Graph_Drawing_And_Dragging_Figures.py b/DemoPrograms/Demo_Graph_Drawing_And_Dragging_Figures.py index ad0375348..b3c1affee 100644 --- a/DemoPrograms/Demo_Graph_Drawing_And_Dragging_Figures.py +++ b/DemoPrograms/Demo_Graph_Drawing_And_Dragging_Figures.py @@ -7,11 +7,7 @@ This demo shows how to use a Graph Element to (optionally) display an image and then use the mouse to "drag" and draw rectangles and circles. - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ def save_element_as_file(element, filename): diff --git a/DemoPrograms/Demo_Graph_Drawing_And_Dragging_Figures_2_Windows.py b/DemoPrograms/Demo_Graph_Drawing_And_Dragging_Figures_2_Windows.py index e28c180b5..cb8af2880 100644 --- a/DemoPrograms/Demo_Graph_Drawing_And_Dragging_Figures_2_Windows.py +++ b/DemoPrograms/Demo_Graph_Drawing_And_Dragging_Figures_2_Windows.py @@ -11,11 +11,7 @@ difference between the 2 programs is that the "action" portion of the interface is split into a floating toolbar kind of interface in this version. - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ def save_element_as_file(element, filename): diff --git a/DemoPrograms/Demo_Graph_Elem_CPU_Meter.py b/DemoPrograms/Demo_Graph_Elem_CPU_Meter.py deleted file mode 100644 index 5f92cb648..000000000 --- a/DemoPrograms/Demo_Graph_Elem_CPU_Meter.py +++ /dev/null @@ -1,160 +0,0 @@ -import PySimpleGUI as sg -import math -import psutil - -""" - Demo Program - Display CPI Usage as a VU Meter - - Artwork and algorithm for handling of needle positioning generously provided by GitHub user neovich. - - A long-time PySimpleGUI user and brilliant programmer posted a screenshot of an incredibly - complex audio recording mixing application with features like custom sliders and VU meters made - entirely of Graph elements. I asked him to draw us some special artwork for this demo. An ENORMOUS - thank you to him for the encouragement, support, and hard work! - - This demo uses the psutil library to get the CPI utilization. It is then shown on a nicely rendered - VU meter. - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - -# --- VU Meter Parameters ---------------------------------------------- - -x_needle_base = 169 -y_needle_base = 10 -needle_length = 280 -needle_multiply = 2 -needle_width = 2 -needle_color = '#434443' -needle_cutoff = 100 -angle_min = 60 -angle_max = 122 -CANVAS_KEY = 'CANVAS_vu_meter' - -# --- Colours ---------------------------------------------------------- -tick1_color = '#222222' -tick2_color = tick1_color -background = '#626059' -module_background = '#F2E2CA' -win0_background_color = background -tab_inner_colour = 'black' -background_main = background - - -sg.set_options(background_color=background, element_background_color=background) - -# ---------------------- Definitions ----------------------------------- - - -def VU_METER_update(CONT_CANVAS_vu_meter, a): - if a < angle_min : - a = angle_min - if a > angle_max: - a = angle_max - CONT_CANVAS_vu_meter.erase() - OBJ_VU_meter = CONT_CANVAS_vu_meter.draw_image(data=vu_meter_2,location= (0,234)) - x_angle = math.cos(math.radians(180-a)) - y_angle = math.sin(math.radians(180-a)) - x_cur = x_needle_base+(x_angle * needle_length) - y_cur = y_needle_base+int((y_angle * needle_length)*0.7) - x_cur_low = int(x_needle_base+(x_angle * (needle_length/needle_multiply))) - y_cur_low = int(y_needle_base+int((y_angle * (needle_length/needle_multiply))*0.7)) - OBJ_VU_meter_needle = CONT_CANVAS_vu_meter.draw_line( (x_cur_low,y_cur_low),(int(x_cur),int(y_cur)) ,color=needle_color,width=needle_width) - - -def main(): - # ------------------------- Init the VU_Meter -------------------------- - - - VU_METER_cont = [[sg.Graph ( canvas_size = ( 339,234 ), - graph_bottom_left=(0,0), - graph_top_right=(339,234), - background_color=module_background, - drag_submits=True, - enable_events=True, - float_values=True, - key=CANVAS_KEY )]] - - - # ------------------------- Tab Set Ups -------------------------------- - layout = [[sg.Column(VU_METER_cont ,background_color=module_background )]] - - - - location = sg.user_settings_get_entry('-location-', (None, None)) - - # ------------------------ Finalize Windows ---------------------------- - - window = sg.Window('CPU Usage as a VU Meter', layout, - no_titlebar=True, - auto_size_buttons=False, - keep_on_top=True, - grab_anywhere=True, - force_toplevel=False, - finalize=True, - location=location, - right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT, - enable_close_attempted_event=True) - - # ------------------------ Init the VU_Meter --------------------------- - - CONT_CANVAS_vu_meter = window[CANVAS_KEY] - angle = angle_min - x_angle = math.cos(math.radians(180-angle)) - y_angle = math.sin(math.radians(180-angle)) - x_cur = x_needle_base+(x_angle * needle_length) - y_cur = y_needle_base+int((y_angle * needle_length)*0.7) - x_cur_low = int(x_needle_base+(x_angle * (needle_length/needle_multiply))) - y_cur_low = int(y_needle_base+int((y_angle * (needle_length/needle_multiply))*0.7)) - OBJ_VU_meter_needle = CONT_CANVAS_vu_meter.draw_line( (x_cur_low,y_cur_low),(int(x_cur),int(y_cur)) ,color=needle_color,width=needle_width) - window.refresh() - - ######################################################################## - ## MAIN LOOP ## - ######################################################################## - temp_angle = 0 - angle_impulse = 2 - angle_range = angle_max-angle_min - while True: - event, values = window.read(timeout=30) - if event in (sg.WIN_CLOSE_ATTEMPTED_EVENT, 'Exit'): - sg.user_settings_set_entry('-location-', window.current_location()) # The line of code to save the position before exiting - break - if event == 'Edit Me': - sg.execute_editor(__file__) - elif event == 'Version': - sg.popup_scrolled(__file__, sg.get_versions(), location=window.current_location(), keep_on_top=True, non_blocking=True) - - - cpu_percent = psutil.cpu_percent(interval=1) - target_angle = angle_range * cpu_percent/100 + angle_min - if temp_angle == 0: - temp_angle = target_angle - - delta = abs(temp_angle - target_angle) - if temp_angle > target_angle: - temp_angle -= min(angle_impulse, delta) - else: - temp_angle += min(angle_impulse, delta) - VU_METER_update(CONT_CANVAS_vu_meter, temp_angle) - CONT_CANVAS_vu_meter.draw_text(f'{int(cpu_percent)}% CPU USED', (170, 40), color=module_background, font='_ 18') - - - - -if __name__ == '__main__': - - # --------- Images ----------------------------------------------------- - - needle = b'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' - - - vu_meter_2 = b'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' - - dot3 = b'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' - - main() diff --git a/DemoPrograms/Demo_Graph_Elem_Image_Album.py b/DemoPrograms/Demo_Graph_Elem_Image_Album.py index 53e5cf5d5..115f72c58 100644 --- a/DemoPrograms/Demo_Graph_Elem_Image_Album.py +++ b/DemoPrograms/Demo_Graph_Elem_Image_Album.py @@ -17,11 +17,7 @@ Contains a couple of handy PIL-based image functions that resize an image while maintaining correct proportion. One you pass a filename, the other a BASE64 string. - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ G_SIZE = (800,600) # Size of the Graph in pixels. Using a 1 to 1 mapping of pixels to pixels @@ -48,7 +44,7 @@ def convert_to_bytes(file_or_bytes, resize=None): if resize: new_width, new_height = resize scale = min(new_height/cur_height, new_width/cur_width) - img = img.resize((int(cur_width*scale), int(cur_height*scale)), PIL.Image.LANCZOS) + img = img.resize((int(cur_width*scale), int(cur_height*scale)), PIL.Image.ANTIALIAS) bio = io.BytesIO() img.save(bio, format="PNG") del img diff --git a/DemoPrograms/Demo_Graph_Elem_Image_Album_No_PIL.py b/DemoPrograms/Demo_Graph_Elem_Image_Album_No_PIL.py index efd5035cb..99ead0588 100644 --- a/DemoPrograms/Demo_Graph_Elem_Image_Album_No_PIL.py +++ b/DemoPrograms/Demo_Graph_Elem_Image_Album_No_PIL.py @@ -13,11 +13,7 @@ 1. The images are not resized to fit the window 2. The images are limited to PNG and GIF files - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI.org """ G_SIZE = (800, 600) # Size of the Graph in pixels. Using a 1 to 1 mapping of pixels to pixels diff --git a/DemoPrograms/Demo_Graph_Element.py b/DemoPrograms/Demo_Graph_Element.py index 1c1d10f0f..0eeb2bb2c 100644 --- a/DemoPrograms/Demo_Graph_Element.py +++ b/DemoPrograms/Demo_Graph_Element.py @@ -1,103 +1,71 @@ #!/usr/bin/env python import PySimpleGUI as sg -import random +import ping +from threading import Thread import time -import gc -try: - import ping3 -except: - ping3 = None - if sg.popup_yes_no('This version of Python does not have the ping3 module installed. Would you like it to be installed?') == 'Yes': - sg.execute_pip_install_package('ping3') # pip install the ping3 package - sg.execute_restart(__file__) # restart this program so that it'll pick up the new ping3 installation - else: - sg.popup_quick_message('OK... Ping3 not installed so data will be simulated', font='_ 18', text_color='white', background_color='red', auto_close_duration=6) -""" - Use a Graph element to show ping times to a URL using a line graph +STEP_SIZE = 1 +SAMPLES = 1000 +CANVAS_SIZE = (1000, 500) - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. +# globale used to communicate with thread.. yea yea... it's working fine +g_exit = False +g_response_time = None - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - -if ping3: - ping_url = 'google.com' -else: - ping_url = 'simulated data' - - -def ping_thread(window: sg.Window): - while True: - if ping3: - ping_time = int(ping3.ping(ping_url) * 1000) - else: - time.sleep(.001) - ping_time = random.randint(0, 100) - if ping_time: - window.write_event_value('-THREAD-', ping_time) +def ping_thread(args): + global g_exit, g_response_time + while not g_exit: + g_response_time = ping.quiet_ping('google.com', timeout=1000) def main(): - global ping_url + global g_exit, g_response_time - STEP_SIZE = 1 - SAMPLES = 100 - CANVAS_SIZE = (1000, 500) - Y_MAX = 500 - X_MAX = 500 + # start ping measurement thread + thread = Thread(target=ping_thread, args=(None,)) + thread.start() sg.theme('Black') + sg.set_options(element_padding=(0, 0)) layout = [ - sg.vbottom( - [sg.Column([[sg.T('Ping in MS'), sg.T(k='-TIME-', s=4)],[sg.Slider((50, Y_MAX), default_value=Y_MAX, orientation='v', size=(20, 20), k='-Y SLIDER-', expand_y=True, enable_events=True)]], expand_y=True, element_justification='r'), - sg.Column([ - [sg.Graph(CANVAS_SIZE, (0, 0), (SAMPLES, 200), background_color='black', key='-GRAPH-')], - [sg.Text('# Samples:'), sg.Slider((50, X_MAX), default_value=SAMPLES, orientation='h', size=(50, 20), k='-X SLIDER-', expand_x=True, enable_events=True)], - [sg.Text('Ping times to:'), sg.Input(ping_url, size=15, key='-URL-', readonly=not ping3, use_readonly_for_disable=True, disabled_readonly_text_color='black', disabled=not ping3), sg.B('Set', disabled=not ping3)],])], - expand_x=True, expand_y=True) + [sg.Text('Ping times to Google.com', font='Any 12'), + sg.Quit(pad=((100, 0), 0), button_color=('white', 'black'))], + [sg.Graph(CANVAS_SIZE, (0, 0), (SAMPLES, 500), + background_color='black', key='graph')] ] - window = sg.Window('Ping Graph', layout, background_color='black', finalize=True, font='_ 16') + window = sg.Window('Canvas test', layout, + grab_anywhere=True, background_color='black', + no_titlebar=False, use_default_focus=False) - graph = window['-GRAPH-'] - - i = prev_x = prev_y = 0 - fig_list = [] - window.start_thread(lambda : ping_thread(window)) + graph = window['graph'] + prev_response_time = None + i = 0 + prev_x, prev_y = 0, 0 while True: - event, values = window.read() + event, values = window.read(timeout=200) if event == 'Quit' or event == sg.WIN_CLOSED: break - if event == '-THREAD-': - new_x, new_y = i, values[event] - window['-TIME-'].update(values[event]) + if g_response_time is None or prev_response_time == g_response_time: + continue + new_x, new_y = i, g_response_time[0] + prev_response_time = g_response_time if i >= SAMPLES: graph.move(-STEP_SIZE, 0) prev_x = prev_x - STEP_SIZE - fig = fig_list[0] - fig_list.pop(0) - graph.delete_figure(fig) - # gc.collect() # Run garbage collect. Uncomment if you want the space freed immediately - fig = graph.draw_line((prev_x, prev_y), (new_x, new_y), color='white') - fig_list.append(fig) + graph.draw_line((prev_x, prev_y), (new_x, new_y), color='white') + # window['graph'].draw_point((new_x, new_y), color='red') prev_x, prev_y = new_x, new_y i += STEP_SIZE if i < SAMPLES else 0 - if event == '-X SLIDER-' or event == '-Y SLIDER-': - graph.delete_figure(fig_list) - graph.change_coordinates((0,0), (values['-X SLIDER-'], values['-Y SLIDER-'])) - graph.erase() - fig_list = [] - i = 0 - prev_x, prev_y = 0, 0 - SAMPLES = values['-X SLIDER-'] - if event == 'Set': # set a new URL to ping - ping_url = values['-URL-'] + + # tell thread we're done. wait for thread to exit + g_exit = True + thread.join() + window.close() diff --git a/DemoPrograms/Demo_Graph_Element_Sine_Wave.py b/DemoPrograms/Demo_Graph_Element_Sine_Wave.py index da55c665c..0f8daed69 100644 --- a/DemoPrograms/Demo_Graph_Element_Sine_Wave.py +++ b/DemoPrograms/Demo_Graph_Element_Sine_Wave.py @@ -1,34 +1,11 @@ import PySimpleGUI as sg import math -""" - Demo - Graph Element used to plot a mathematical formula - - The Graph element has a flexible coordinate system that you define. - Thie makes is possible for you to work in your coordinates instead of an - arbitrary system. - - For example, in a typical mathematics graph, (0,0) is located at the center - of the graph / page / diagram. - This Demo Program shows a graph with (0,0) being at the center of the Graph - area rather than at one of the corners. - - It graphs the formula: - y = sine(x/x2) * x1 - - The values of x1 and x2 can be changed using 2 sliders - - Copyright 2018-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. - -""" +# Yet another usage of Graph element. SIZE_X = 200 -SIZE_Y = 200 -NUMBER_MARKER_FREQUENCY = SIZE_X//8 # How often to put tick marks on the axis +SIZE_Y = 100 +NUMBER_MARKER_FREQUENCY = 25 def draw_axis(): @@ -36,45 +13,44 @@ def draw_axis(): graph.draw_line((0, -SIZE_Y), (0, SIZE_Y)) for x in range(-SIZE_X, SIZE_X+1, NUMBER_MARKER_FREQUENCY): - graph.draw_line((x, -SIZE_Y/66), (x, SIZE_Y/66)) # tick marks + graph.draw_line((x, -3), (x, 3)) # tick marks if x != 0: # numeric labels - graph.draw_text(str(x), (x, -SIZE_Y/15), color='green', font='courier 10') + graph.draw_text(str(x), (x, -10), color='green') for y in range(-SIZE_Y, SIZE_Y+1, NUMBER_MARKER_FREQUENCY): - graph.draw_line((-SIZE_X/66, y), (SIZE_X/66, y)) + graph.draw_line((-3, y), (3, y)) if y != 0: - graph.draw_text(str(y), (-SIZE_X/11, y), color='blue', font='courier 10') + graph.draw_text(str(y), (-10, y), color='blue') + +sg.theme('DarkAmber') -# Create the graph that will be put into the window. Making outside of layout so have element in a variable -graph = sg.Graph(canvas_size=(500, 500), +# Create the graph that will be put into the window +graph = sg.Graph(canvas_size=(400, 400), graph_bottom_left=(-(SIZE_X+5), -(SIZE_Y+5)), graph_top_right=(SIZE_X+5, SIZE_Y+5), - background_color='white', expand_x=True, expand_y=True, - key='-GRAPH-') + background_color='white', + key='graph') # Window layout -layout = [[sg.Text('Graph Element Combined with Math!', justification='center', relief=sg.RELIEF_SUNKEN, expand_x=True, font='Courier 18')], +layout = [[sg.Text('Example of Using Math with a Graph', justification='center', size=(50, 1), relief=sg.RELIEF_SUNKEN)], [graph], - [sg.Text('y = sin(x / x2) * x1', font='COURIER 18')], - [sg.Text('x1', font='Courier 14'), sg.Slider((0, SIZE_Y), orientation='h', enable_events=True, key='-SLIDER-', expand_x=True)], - [sg.Text('x2', font='Courier 14'), sg.Slider((1, SIZE_Y), orientation='h', enable_events=True, key='-SLIDER2-', expand_x=True)]] - -window = sg.Window('Graph of Sine Function', layout, finalize=True) + [sg.Text('y = sin(x / x2 * x1)', font='COURIER 18')], + [sg.Text('x1'), sg.Slider((0, 200), orientation='h', + enable_events=True, key='-SLIDER-')], + [sg.Text('x2'), sg.Slider((1, 200), orientation='h', enable_events=True, key='-SLIDER2-')]] -draw_axis() # draw the axis (an empty graph) +window = sg.Window('Graph of Sine Function', layout) while True: event, values = window.read() if event == sg.WIN_CLOSED: break - - graph.erase() # erase entire graph every time there's a change to a slider - draw_axis() # redraw the axis - - # plot the function by drawing short line segments + graph.erase() + draw_axis() prev_x = prev_y = None + for x in range(-SIZE_X, SIZE_X): - y = math.sin(x/int(values['-SLIDER2-'])) * int(values['-SLIDER-']) + y = math.sin(x/int(values['-SLIDER2-']))*int(values['-SLIDER-']) if prev_x is not None: graph.draw_line((prev_x, prev_y), (x, y), color='red') prev_x, prev_y = x, y diff --git a/DemoPrograms/Demo_Graph_FourierTransform.py b/DemoPrograms/Demo_Graph_FourierTransform.py new file mode 100644 index 000000000..088005555 --- /dev/null +++ b/DemoPrograms/Demo_Graph_FourierTransform.py @@ -0,0 +1,72 @@ +import math +import numpy as np +import PySimpleGUI as sg +import time + +""" + Fourier Transform Animated Graph + + A fun demonstration of the Graph Element and the drawing primitive draw_lines + Written by Jason Yang, by an innovative PySimpleGUI user that has created a number + of impressive animations using PySimpleGUI. + + Copyright 2020 Jason Yang +""" + +def push(v): + if len(buffer)==size: + del buffer[-1] + buffer[0:0] = [v] + +def update(i): + draw.Erase() + x1 = x0 + r1*math.cos(v1*i*rad) + y1 = y0 + r1*math.sin(v1*i*rad) + x2 = x1 + r2*math.cos(v2*i*rad) + y2 = y1 + r2*math.sin(v2*i*rad) + x3 = x2 + r3*math.cos(v3*i*rad) + y3 = y2 + r3*math.sin(v3*i*rad) + push(y3) + draw.DrawCircle((x0, y0), r1, line_color='blue') + draw.DrawCircle((x1, y1), r2, line_color='yellow') + draw.DrawCircle((x2, y2), r3, line_color='red') + draw.DrawLine((x0, y0), (x1, y1), color='magenta') + draw.DrawLine((x1, y1), (x2, y2), color='white') + draw.DrawLine((x2, y2), (x3, y3), color='white') + draw.DrawLine((x3, y3), (x[0]+xx, buffer[0]), color='ivory') + draw.DrawPoint((x3, y3), size=10, color='red') + lines = ((x[i]+xx, y) for i, y in enumerate(buffer)) + draw.DrawLines(lines, color='green1') + +size = 720 +distance = 100 +r0, r1, r2, r3 = 90, 90, 30, 18 +rad = math.pi/180 +v1, v2, v3 = 1, 3, 5 +x = np.array(list(range(size))) +x0 = y0 = r1+r2+r3 +xx = x0*2 + distance +buffer = [] +win_size = (xx+size, 2*x0) + +layout = [[sg.Graph(canvas_size=win_size, graph_bottom_left=(0, 0), + graph_top_right=win_size, key='-GRAPH-')]] +window = sg.Window('Fourier', layout=layout) +draw = window['-GRAPH-'] + +i = 0 +timeout = refresh_interval = 10 # Target refresh interval = 10 milliseconds + +while True: + start_time = time.time() + + event, values = window.read(timeout=timeout) + if event == None: + break + + update(i) + i = i+1 if i<359 else 0 + + timeout = max(0, (refresh_interval - (time.time()-start_time)*1000)) + +window.close() \ No newline at end of file diff --git a/DemoPrograms/Demo_Graph_Noise.py b/DemoPrograms/Demo_Graph_Noise.py index 2ecf5f599..388c6733d 100644 --- a/DemoPrograms/Demo_Graph_Noise.py +++ b/DemoPrograms/Demo_Graph_Noise.py @@ -5,12 +5,6 @@ ''' Example of random line in Graph element. - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. ''' sg.theme('black') diff --git a/DemoPrograms/Demo_Graph_Window_Resize.py b/DemoPrograms/Demo_Graph_Window_Resize.py deleted file mode 100644 index 7b8d67c53..000000000 --- a/DemoPrograms/Demo_Graph_Window_Resize.py +++ /dev/null @@ -1,49 +0,0 @@ -import PySimpleGUI as sg - -""" - Demo - Graph Element Rescale Figures When Window Resizes - - This demo shows how you can redraw your Graph element's figures so that when - you resize the window, all of the figures on the graph resize. - - There may be a tkinter method to help do this? - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - -gsize = (400,400) - -layout = [ [sg.Text('Rescaling a Graph Element When Window is Resized')], - [sg.Graph(gsize, (0,0),gsize, expand_x=True, expand_y=True, k='-G-', background_color='green')], - [sg.Button('Exit'), sg.Sizegrip()] ] - -window = sg.Window('Graph Element Scale With Window', layout, finalize=True, resizable=True, enable_window_config_events=True) - -graph = window['-G-'] #type: sg.Graph - -orig_win_size = window.current_size_accurate() -# Draw the figure desired (will repeat this code later) -fig = window['-G-'].draw_circle((200, 200), 50, fill_color='blue') - -while True: - event, values = window.read() - if event == sg.WIN_CLOSED or event == 'Exit': - break - if event == sg.WINDOW_CONFIG_EVENT: # if get a window resized event - # Determine how much the window was resized by and tell the Graph element the new size for the Canvas - new_size = window.current_size_accurate() - dx = orig_win_size[0]-new_size[0] - dy = orig_win_size[1]-new_size[1] - gsize = (gsize[0] - dx, gsize[1] - dy) - orig_win_size = new_size - graph.CanvasSize = gsize - # Erase entire Graph and redraw all figures0 - graph.erase() - # Redraw your figures here - fig = window['-G-'].draw_circle((200, 200), 50, fill_color='blue') - -window.close() diff --git a/DemoPrograms/Demo_Graph_pymunk_2D_Graphics.py b/DemoPrograms/Demo_Graph_pymunk_2D_Graphics.py index a7023f1f0..8ee7089d3 100644 --- a/DemoPrograms/Demo_Graph_pymunk_2D_Graphics.py +++ b/DemoPrograms/Demo_Graph_pymunk_2D_Graphics.py @@ -13,12 +13,6 @@ Demo that shows integrating PySimpleGUI with the pymunk library. This combination of PySimpleGUI and pymunk could be used to build games. Note this exact same demo runs with PySimpleGUIWeb by changing the import statement - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ diff --git a/DemoPrograms/Demo_Graph_pymunk_Desktop_Balls.py b/DemoPrograms/Demo_Graph_pymunk_Desktop_Balls.py index f7df9227f..f36fc7351 100644 --- a/DemoPrograms/Demo_Graph_pymunk_Desktop_Balls.py +++ b/DemoPrograms/Demo_Graph_pymunk_Desktop_Balls.py @@ -4,12 +4,6 @@ """ Demo of pymunk physics lib combined with a large Window that is transparent. Result appears like a screensaver type of screen - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ class Ball(): diff --git a/DemoPrograms/Demo_Hello_World.py b/DemoPrograms/Demo_Hello_World.py index 2bfa67f42..ae48f4773 100644 --- a/DemoPrograms/Demo_Hello_World.py +++ b/DemoPrograms/Demo_Hello_World.py @@ -3,12 +3,6 @@ """ Oh yes, the classic "Hello World". The problem is that you can do it so many ways using PySimpleGUI - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ sg.popup_no_buttons('Hello World') # the single line diff --git a/DemoPrograms/Demo_Hotkey.py b/DemoPrograms/Demo_Hotkey.py index 1cd7afa98..07a6b235f 100644 --- a/DemoPrograms/Demo_Hotkey.py +++ b/DemoPrograms/Demo_Hotkey.py @@ -10,11 +10,7 @@ This line binds the F10 keybaord key to the window. It produces a "Go" event: window.bind('', 'Go') - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ layout = [ [sg.Text('Press F10 to get same result as clicking "Go" button')], diff --git a/DemoPrograms/Demo_HowDoI.py b/DemoPrograms/Demo_HowDoI.py index 0e64f05d0..5ebbd3cf8 100644 --- a/DemoPrograms/Demo_HowDoI.py +++ b/DemoPrograms/Demo_HowDoI.py @@ -4,12 +4,6 @@ ''' Famouns howdoi command in PSG - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. ''' diff --git a/DemoPrograms/Demo_IP_Address_Entry.py b/DemoPrograms/Demo_IP_Address_Entry.py index c3bb216ee..9033d2aab 100644 --- a/DemoPrograms/Demo_IP_Address_Entry.py +++ b/DemoPrograms/Demo_IP_Address_Entry.py @@ -6,12 +6,6 @@ . will advance the focus to the next entry On the last input, once it's complete the focus moves to the OK button Pressing spacebar with focus on OK generates an -OK- event - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. ''' # create a short-cut element so don't have to type this in over and over diff --git a/DemoPrograms/Demo_Image_Elem_Image_Viewer_PIL_Based.py b/DemoPrograms/Demo_Image_Elem_Image_Viewer_PIL_Based.py index d44e4f765..715bb3511 100644 --- a/DemoPrograms/Demo_Image_Elem_Image_Viewer_PIL_Based.py +++ b/DemoPrograms/Demo_Image_Elem_Image_Viewer_PIL_Based.py @@ -16,11 +16,7 @@ can then be passed to an Image Element's update method. This function can also optionally resize the image. - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ @@ -49,7 +45,7 @@ def convert_to_bytes(file_or_bytes, resize=None): if resize: new_width, new_height = resize scale = min(new_height/cur_height, new_width/cur_width) - img = img.resize((int(cur_width*scale), int(cur_height*scale)), PIL.Image.LANCZOS) + img = img.resize((int(cur_width*scale), int(cur_height*scale)), PIL.Image.ANTIALIAS) with io.BytesIO() as bio: img.save(bio, format="PNG") del img diff --git a/DemoPrograms/Demo_Image_Elem_Splash_Screen.py b/DemoPrograms/Demo_Image_Elem_Splash_Screen.py index 6cff73ff2..71ace78b0 100644 --- a/DemoPrograms/Demo_Image_Elem_Splash_Screen.py +++ b/DemoPrograms/Demo_Image_Elem_Splash_Screen.py @@ -6,11 +6,7 @@ Displays a PNG image with transparent areas as see-through on the center of the screen for a set amount of time. - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ image = b'iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAACXBIWXMAABcRAAAXEQHKJvM/AAAgAElEQVR4nOzdd3gUVdsG8Hu2pfdCCJCA0qQIiIj0pqJ0EBRUioq919eGouBnQ8XepQsCoih2SkBa6L0TQgrpvW+Z+f6gZZOd3dnsbtrcP6693peZs+c8s8hy58ycGUGSJBARERGRemjqugAiIiIiql0MgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDK6ui6AiOjUudzA5KyCdhsPJnUC0PnI2azmJ1Nz/C/slnq2b5YbFRpwMjYy6EC3K6P2XRUTnuSl14l1WbOsirO+sBTGwJjUBKUHIi5sNSJoaDoEfQYMzVOhCzHXaY1EpHqCJEl1XQMRqVBuUZnvr9uO9/5r16lJZzMLBpUbzc0AGJS8tVlYwL6+nWK+v++Wa34NC/Qt8nStDlmKdchbfR0KN05GxZnBEMuiAfgBECq3AlAAXVg6dKGbEHTDXwgeGgdtSCEELb+IiahWMQASUa3KyCv2Wxp3aNrK/448VFJu6uhKX77e+hPj+3Z4a9KgTgujQvzrZkYwa35v5Cx/CZbCW+D8ZTXn4NvlZwT2+w4hY/ZB480vZCKqFQyARFQryipMhs/X7Bq1avPR2aUVprawnh1zhdgiIvC3h0f2eOLma1ufdVOfjplzfHH2uZdQfvIpQPJ1sbdy6MLXIWLqXAQNiYM2kKeIicijGACJyOOOJWc3eWne+o/OpOfdCg9de6zTao7PuKP/baN6tTvgif6tlO4PQdrc71B+cqybezZB33QNQse+hvBJB92XkYmIrDEAEpFHffxL/PB5/+z7HEBMLQyX8+pdA0aN7d1+q8dGKNwYieRX/gCk7h4bAzDDt+sXiLz7Lfh1T/PgOESkUgyAROQROYVlPv/77t+n95xKe1mS4FNb4+p12nMv3N7ntnF9rtri9s4LNzRF6uwVECv6uL1vWwTtGYSMeRVNHlgOja+xVsYkIlVgACQit9uwPzFq7s/bv0jKLBhTF+MLgpA1864BI0f1ahfvtk4L45og5fVfIJmud1ufSnm1+g3hE59H8PBjtT42ETVKDIBE5DYVJouwYf+Zbq8u2PCDySK2q8tatBpN+ksT+04Y1/eqzS53Vrgh6nz4M/d0Q2k1JOQhsN8riHpsHvRNy+quDiJqDBgAicgtJEnCy/PX3/rnzlNfAIhw+IZaoNdq0l6+o//Y0a7MBBbGNUHqrJ9q7bSvfSK8Yv9E06cegd+1tbfimYgaHQZAInKZ0WzRvbYw7om/dp16C4C+ruupIvu1uwaMGtO7/Tan31m4MRLJM34HxGs9UJcrchA24RFE3r8SGh9LXRdDRA0PAyARuSQhPc/n+W/+fft0Wt7DqKePl6zRwpDCDU2RMnslpIreHizNFUb4X/c1mjzwIrzbFdd1MUTUsDAAElGNnc0s8Lvvw1/nZxWUjoPzT8GoVRpByHztrgGjFC0MKYxrgpQ3foZk7FULpblGG7wF0c9OReDA03VdChE1HAyARFQjp9PyIh759PcfMvJKbqjrWpTSajQZL03qO35cHzsLQwrjopAyczUk83W1WJqLhBRETL4bkfet5c2jiUiJev0TOxHVT0mZBVGPfPL7zw0p/AGARRSbvL1s8/LV247bvpVL4aYIpM5a0bDCHwBIzZG18GdkLZgMycIESEQOMQASkVMS0vJaTP/w1z8y8kvqw6pYp5ksYtOZi+J++2XrseqndzUGC6CpqIOy3MEfmd9+j4R7X4Y5v15ei0lE9Yd25syZdV0DETUQCWl5LR759I+fMvNLPPkYtNrgu/VIyi1hgT7xV8VEJF/aamheBp82v6NwU0/AEouGdz5VA3PuAJTu9kVA/41cIUxEcngNIBEpkpRZEDX9w1//yCoo7VbXtbiLRnNhYcj1VRaGFG0NR/KMlZAqBtRRaa6S4NPuPcS8/zJ0wea6LoaI6h+eAiYih06n5TW9f+5vvzam8AcAoihFvrF44+pVW45an84O6J2NmNm3QuOzro5Kc5WAsuPP4uwT78JSwNPBRFQNAyAR2XU2syDokU9/X5iRX9KjrmvxBIsoNXn7RxsLQ/x75aDFrNsg6Fx/lFzd0KD89JM4+8xTsBTxu56IrPBLgYhknUnP87/vw98WNrTVvs4ymcXomYvifqseAq/PRcxbY6DxWV9HpblKQNmx2chZNq2uCyGi+oWLQIjIprTcIsP9c9d8mJlfcgca3mKImvDdciRpWFigb5WFIS3K4N3mdxRtug6SpWXdlVcTAgBBi9IDgwBpO/y6JKrjj5KIHOEMIBFVI0nAx6t3vJCeV3wvVJQYTGYx+v+W/vfTr9uPW98HMKBXDprPmgDBsLGOSnNAkHld2h2I7PnfoexY8zopj4jqHa4CJiIrFSaL8MaSjXf9ufPUfFT5IVHRt0Uj+E7RaITMVyb1Gze26rODi7eFIfnVHyGWDan9qhzkcEFBTtcG/4lWX94KQ3SZe2oiooaKM4BEZCXuQGKfP3ee+hg2vh/k5pmsXoIAQRDOBxJ7r3pMFKXIt37cUscLQ2Rm8wAnPs8qfVgKhiL948c8WDQRNRCcASSiS+IOnG3+v+/WbjKZxVbV99bed4XDkWrveyv79ckDR4zqVfU+gdvCkPLqcohlg13r3g2zeg7P0FfbX45mL/dE0I0HFHRORI0UZwCJCACQW1Tm99Ev8fNMFrGVzNSezMyTkpdzlM4y2nq5eeYxfPbSTauq3yewVw6av3E7NF5xrh3Rxd1KanX02drZb/1n6I2sbz+GKd1PWe1E1BgxABIRAOCF79e/mJRZcIPT8U3ZeWGPhUWny3EyLJrMYvT/Ldu88tftJ6ouDMm+sDBkr+MKLu5SGkodfS72xrh0oDY+9wtMmf2R8eVd8p8iETV2DIBEhE9/3Tlmz6m0Z+Rm9uR/ORnnnAmL9WimURSlqDcWb/zt563Helt1ENA7G81nTgaEdOsZN1eCnuBgn1Blt9znZHccAcXbX0PJ3mhnPzMiahwYAIlU7nhKTpN5/+7/VAK8rXY4E9bsNKpxWKzKTfXUNCyKkhT59o9bVqzedry71Y6AXocRMuxFCILk1IIMqxoc1Gcr7Nk9DnvHemGbZGqKzM+ehmR0/sMgogaPAZBIxcqMZsMrC+I+BYRmLgUkZ8KZnZm9+j7TaDKL0a8v3rTqt+0nYi+PpQeiX5wPfeRaxxU6qF6uNntBTulYl/qrtLki8X4Ub29T9eMjosaPAZBIxb76Y8/EMxn5Y21lg5pHsUYfHmM+W7Pr25TsIutFFOF3zQBQar8TB8fkVNCzsd+qvypj2e4jANmLn4NkcvIPjYgaOgZAIpXafyaj2bKNh98GoL20UUFash0WbYdHtwZFW5wJjw6rVV5xZn7JkA9XbX/QqpagG3dC3+RPq+OyFfbsHrvCoCf3B+GwDxv7K85MQOHG9jIFEVEjxQBIpEJlRrP2tUWbZpstUtMahzFnwqLs5JTb5u3cUq8TM43C1iPJL8cfS211qX+Nn4iIqR9CEETHYc/eMSkIeoKTfdgPg0HIXfYgiEhVGACJVOj3HaeuTckuusN6q6KEhBqFr6qcCY+yTTwYFhXUa7SIIYvXH3zM6p7UAf12Q9AedHygMvttBj25fpTss3EQtpK4MfkeFG+NUP6BEFFDxwBIpDJFZUbd/H/3vy4IMCi5FZ7tha3OhEUXw5gzYVEm33hqpnHr0ZS7jqdkXw5O2sBy+F//m92Q5vR1ekL1PmTrs/eB2BsD/ija/JDdgyWiRoUBkEhl/th5un9GfulAhWGtPDzQZ/dVLcI/fGRE95d7XdVsTnSY/2ZBQKnaw+OFvRHr9iXebDVm4JC1gGCWDXoOj82VoKd0DBtjFW2ajIqEECc+XSJqwHR1XQAR1a75aw88DAFeVhttPFo3NMBn75QhnZ4e0bPNf0G+XhYAuBtdYDKLmr93n+6+YN3BtxIzCobY7eQC2Vvj2WD/Mb/OhEAXnxfsYKiLu9ftSxz+yMhrF13aYWi+HxpDCSRjkON6lRyP4KCpE33Y2y9ZrkTRxkHwumKVgg6JqIHjDCCRihw4kxmdU1g2WqgaCKpMFIUG+qz7+vFbBt85qFPcxfB3kV6nEUf0bLPzmyeGjbgqJvwb2U5qOLPnzMxifZhpzC0u65mcVehzaYN3m3xofM5c7kfpOO6Y1VMwuyg/3Smg4N/pTh08ETVYDIBEKrJg7cHxuDDzL3dqU6vRpLxxV//psZFB+fb6CvbzLv/w/hue1Os08a5nKveEs5qHxZrXU1xmDMkpLGtW5f2n7NdrK+xdbK70uGsSKB30IRb1QtlBPh6OSAUYAIlUosxoFlJzi25yFMauaxv9Rc920YlK+gwL8Cl9YULvlwQIRvlr5S5QkKd0Os2esECfpRAgyWcfZ8KifEBy40xjAARYr6D17ZZqO4BVDnuuBD3Bep+9ixgd9lGpjSQGoXj7jTaKIKJGhgGQSCWyCkqDEtILrpIPDAIgQBrcJXaFM/32aNt0c4CPIVFuv70VuJV/eel18a/d0Xf0Zw8PvSci0He+AEGs1Ik7Mp/bOqrysWmOJmUHWzUwRFVcfpvC8FWjoFe1K1fGurDTmHQDINpKokTUiDAAEqmEAAQLQFP7/7ILBYO7tMxwpt+mof5GPx/DYUWTWfL2vzqp79ibu1+ZcmXTkPKPHrzx0dAAn0VKw2O1axqtDsmJl13ybzx5Ls+/SuMK52b0bOx3OegpGMvWDwGle6+DWOot/zkQUWPAAEikHnoAPoDdDGRBjZbPCgU2e3N8jxUY9Nr42VMH3HLTNa3SLvbWJjq0dNLADi8AKFBcgQu/KnVSo1eXKyIzq5Tj7TikKZnVcyXoXWin+Fz2pfe1RtmRIHufNRE1fAyARGpS9Z501V8hp9PznLoXnNkiQpKklk5Npl1opdNqd70ysc/4m7pdDn8AsH7/2ajv/t6/AoIQpCiEucjFWUZjbGRQkdWWoi0B1Y63RqdvbVcr207xahe7Y2lgPBcrd7BE1DgwABKpRwWAEgdpSrNhf9JoZzrdm5ARnVlQ0rlqXnGU2fRaze6Zd/QddXP3K1Iqv2/DgbNNXl3836pyk6Wvsp7szHC5OTzKBMNCANYzgFJpjPzqWyWFOCjYuRk9mbHsfZZo4twnQ0QNDQMgkXrkCUCKo+zz156Eh06n5YUp6VCSIKzaeuIeQAi1H8Ssw5hBr42fManPmMqnfQFgw4GzUTMWbfrZZLb0UpLdHOc5z4fHYH/v5OhQ/8vHIZYJkMT2rgW9i7tdCXoO9lfbdLFvAQCqzGASUWPDAEikEpHBfsWtm4XurhwkhIsvXM4BhSUV7Z/4et27SvpcuP5Qz/X7z/4P8nmykkuj7J8xqc+4qjN/Gw8mRcxcsnmFySL1cmXWruZhsQY9CQI6xUbERQb7Xb5Zdun+GIglkcr6q7zbUdBT0IfcftmgJxsY8+Q+FSJqHBgAiVTCS6+V+lzVbJ7NndbBQ8guLLtn+MyVi3aeTIuy1Ty/pELz5Z/7xn3xx941AuCvNGgZdNodsyf3v/mmbq3OVe4v7mBS5P/mx/2h+LSvm075OhMWZboRB3WJXW7VadnhnoDgZzuI2aldUWV29lc7/sp9K+zj8n6rPx8ianz4LGAiFZk8uFPcsk1H91aYLN0ctc0pKrvrya/X9b22TdPF17aJ+rtfh+YJZzIK/E+l5fVYvf3kHdmFZTcAMMgvNLhMAKDTana9fHuvW2/s1jK98r4NB85GzVyyZQUkXCvA1Sf4Oq7lchMFI9lpIgDQazU7+3Vsse9ye6OA0l3DAAhKPpcqBSnfV22zo7GU1HKpTQH8eyUqeAMRNWCCZP/J60TUyHz/78ER3/y9/ycJMNht6MbvBq1G2DPzjr4jbuzW0uqav7iDSZGvLt78s9Fs6e2wEwX11N63mQQAlvF92097blzPxZc2V5wORdITRwHInAKW446gV8PAWfVt2tC/EPPZCGi8LSCiRoungIlUZuqQjn9c1SJsgcPTnJWvEazysr/YwzpRGPTa+Fcn9RldNfxtOJDUZMai/1YrCn+A4zHt1OvEWWGFBIQH+m6d2O+qH6025664FRAi5UeRqUDRqVsHfdiosfopYsHRGBJ8u/3I8EfU+DEAEqmMVqMRX53U+0VAOFDTPpwIj/tfub33uKHXtLJe8HEoOeL1pVtWmETp+pofiTMFOxEcHRwbzv9vwX03d326RUSg6dIYljwflB+5v9Kg1V/VPygbIcyqcJkK7LSpdj2kozEq9SN4nUXwyFV2P0siahQYAIlUqGVkUM4rt/e6XafVnrM/41Tz+TKDTrvjjbv63nJTt5ZWCwo2HkqOfGnBpt8rTJZ+VcKic7OMiq+xc5LjsCj17xzz9Jjr2+yyel/Gp1Ngzu9+OYTBQQirXL+Sz7omQU9BYLzcToTvNbNgiC2sycdGRA0LAyCRSg3vccWxZ8f2uFOn1Vy+5YeiDOg4LOq12l0v3nb9+Bu7VjvtG/Xaks0/iZLUw1F9ykqp9bBo7tAi7K1XJ/aeb7W1/EQ4Sne9CgGC4xBW01k9qwN3vg9H7QzRaxA25Qf7h09EjQVXAROp2OjrW8fptJo73ly+bQUAf0ftrRZZyGQqrUbYO2NSr1FVw1/cweTImUu3/mQ0i72VzSQqX9KhKN7JhEBFo5xfgCJ1io146/3pg1739zGIl/aJ5XpkfvQRgOjLlSgNnILd3yrrx4mxZJsKpxH+wAPQNylX2BkRNXAMgEQqN7zHFX9ZRGni+7/sXGgyi6HVW1yOSI6ihkGnjX9xQvWZv7iDyU1mLNn8i9kiXq+oI3uNHCY259YCKwyPlk6xEbM/mD5odoCP4fICCbFMQPrbT8CYOtF+T4LN/+tEBQrbCQ6a2tgh6E8ifPpY+HRKr76TiBor3gaGiAAAv8afGvHOqh0/SJLMY8AcfFUIAva9Nqn3iJu6tUytvH3joeTI15duXVluNPdTWotbvpWUTe0paSRe1SLsnbn3DZkR6GuwXh2b+dkkFP77LQDfyxvtzerVcdir3uYsIh4cjoDBh5XVRUSNBQMgEV3y+66Em99euWOpRRSDnXmfXqfZ+cptvUbf2DXWauZv46HkyJcXbf5NFKXrHPfinu8iN4dHqXPLiJnv3zvwTauZPwAo/HsUMr/8AYCfx0/d2m1ew7EE7WmEPzgCAQOOKSyEiBoRBkAisrI6/tTID37ZvcBsEUMubpPsxCq9VrPzxQk9b735mlbJlbfHHUyOen3Z1hUVlx7vppD7Zu5c7cHcoUXYu3PvG/xagI/BbLWn8K/RyP5uHiRzSIMIe1X3C7rTCL93LAIGH1RYGBE1MgyARFTN77sSbv6/5fEOF4ZoBGHvq5N6Da8+85cSOfOHrauMZksfe+HR7dwXHqWOMeFvzrl34OtBvl5Vwt/aYcj64kdAsvHZuCPoues0sewYSYh4eCj8OfNHpGYMgERk0287Tg9//5ddC00WWwtDzt/n78Xx142rfs1fSpNXl2y5vODDBXUUHi2dY8Nnz7l34GwbM39jkPXdAkAMdNxhLc3mKerqYjvdKYTdOwYBg3jNH5HKMQASkaxf40+PePfnXT9IkmS1MEQjYN+M23uNuKlbrHX4O5wS+cbSbSvLTcoXfLgr47kpLIpXNQ9958Ppg6sv+ChcOxzZXy+GZLFxfaQ7wp6jdk6GvWo0iQi/byQCBh1SWAwRNWIMgERk1++7ztz87qodyyyiFAQAOq1m58sTetpY8JESOWPJlt8sihZ8AG5Jfu4Nj1Ln2IjX59wzYHb1BR//jkTWl0sBwQ9APZjVU9jHpd9qExB+/3D49+dpXyICwABIRAqsjj898sNfdy8QBJx64dbrbh3araX1go9DyVGzftxebcGHe75e3Jby7DF3aBH2zgfTB86sftr379HImXdhwcdFHr9Oz/k+5Gh0pxB69zgu+CCiyhgAiUiRP3afGWTQaY/d0CXGauZv0+GUyNeXbV9VYbL0Ob/FTbdzqcWbAXaMCXvzvbsHVF/wUbRuGLK+WgZItu+NeIknT90q2C/ItklC+INDOfNHRFUxABJRjW06nBI5Y8nWXy2i1NM9PdZ6eLR0ig2fPefu/jYWfPwzBtmVF3y4eUGG0/tgL+jZqEN3CmH3jIb/gCOOKiIi9eGj4IioRjYdTol848f4lRZJ6nkpj7ic35SeWrU/mMxjf6uytG8W+t57d/efVe2av6J1I5Azbx4gBdquqb6EPbn9mkSEThvL8EdEchgAichpmw6nRr76w7ZfLaLUU8mTzjxzb2dnwmK1waROseGz35tmI/wVrh2J7K+XAvCrlWv0BDf0YdVOk4Dw+4bDvx9P+xKRLAZAInLKxkMpUbOWx6+8fNrXcTi53MJOyhMctrjMtZlGc4cW4e+8N62/rdW+o5E7fx6EC6t95YqUVaPr9Jwcw047QXcKYdPGMfwRkSMMgESk2KYjqZGzVsSvqDBb+tTstK8zYbEqyWEjBaVIHZqHvfPe3f2rr/YtWj8MOd8vAsSA+hP0ZNrYHiMJYfeMgn//owo6JiKVYwAkIkX+O3L+tK8oSj2tgodsjlESx5ypwOXwaOkUEz773Wn9bCz4+Hc0cuYtPL/a92IvblyQ4ZBTQc9GO90phN49muGPiJTS1HUBRFT/bTqSGjlrefxK8cJpX0HR6/wvu60EQVlnLhMs7ZuFvvfutH6zbMz8jUDugkoLPmwMemmzcPlVrZ3SwmXaKRrDVh/aMwidOg7+/a0XfIjF/ig72FruEyEideNtYIjIrk1HUiNnLtu+2myRLjzb190ze650o6gWqVNM2BsXwl+V1b7rRyD7m2UA/GrnGj039GFFcwZh9w6rds2fWBSAzDkLYUzsi7D7h8Gvz06FAxKRSjAAEpGsTYdTo95YvmOl0XzxJs+uqp3wWKkLc4cWoe/MmdbPxjV/a0cjd8E8SJYQ2OT2a/Sc78deG0F3CqFTxsF/gPUTPsTiAGS+vwDGM2MACBB0qQiZchv8+29VWAwRqQADIBHZ9N+Rc5Gzlsf/VPnxbrX7beFyWJSuah761nvT+r0W6Fsl/BXHDUP2t0uV3+TZThunwl4NA2G1twlJCLv3Fvj1q37aN/ODeTAmjLe+TlObhtB7RsOvN2cCiQgAAyAR2bD56LmIGUu3rxFF6TpFb1DwPVLL4VHsFBP2xjtT+r5ZfeZv3WjkzFsk/3i3Ogp61UOezFt0pxA6dbTt8PfeDzAmjbDdsZCBsLvHwq/vNoXFEVEjxgBIRFb+O3KuyewVO5aXmyz9PTKA58OipV2zkPc+uLvfKzav+ctdsBCS+cJp3/oyq6e0D20iQqeMsn3ad+7352f+7HQr6FMRMuVW+PWJVzggETVSDIBEdMnRlLzQR7+JW2O2iL3quhabHH9fSR1iwma9M6XPG4HVwt+G4cj57kcA52/yXCvX6dWkD7l2mkyE3T0cfn13WW0WiwOQ9cECGBPHKhwrG6HTh8GvF08HE6kYbwNDRACA3OJy/zmr93xvEaXrrW5FIveqC/ZrMndoEfbmu1P6zKoe/taNRt6CxRAEP/u3WFF6Lxpbt7OpfEubqmPUZKzK/evPIXTqOKax+cAAACAASURBVNvh78MFMJ4d47CPy69w5C34BSWb62fIJ6JawRlAIkJ+SYXw3IIt75xMy3/O2fcqe3Sb579n2jcLeee9qX1fqb7gY+MtyPl+2eUFHxe5bUGG8304N0Y2Qu8eCb9+2622iiX+yJo77/JpX4XHczG8C9o0hEwdDV/OBBKpEZ8EQkRYtvnk2JNpBY+fDxHOhTVFsUNmxtBd4bFjTNi8dyb3eS3AR1/1Js+jkbtgkfUTPmSLtPNbd50mdhQmq2wUdGkImTwOfn1thL/3l8CYNMpmJw5naAVAEpsid/4aSOJo+PXZ7uANRNTIMAASqdyZzMKgZVtOzoUAr/NbLoQHZenMpbGdCY9yI+m1mr2PD+/yZICPvsJqR/GGEchbPM/2at8arL6114ejfbJN7fWhzUDInROqh7/iAGR9/D2MSSPPd+Fk6LQiRSL/h5WAMBJ+vfc66IiIGhEGQCIVKzOaha/+OfSKALQAqoQsZenM9mYPhEeZkQpeuvXa+9o3Cym02lq8cRhy5p9/wkflR60p6VHpyLb21Sjo2donZJ6/1UuV1bpicQCyP1oAU+LY6sGvhqeiJXMz5C34GbqwXvBql6agEyJqBLgIhEjFthxLbx1/MvOeiwsE5H/ZX7JgM1s5fMktLlE+WrvokM/6d4jeYzV28fr+yF2wCMKFx7u5e0GGzUUfcFC7vTGqlqI7h9Ap46qHvxJ/ZH+00PaCD6XHU3X3pWOJRf4P38CS7VO9ICJqjBgAiVRs05FzdwMIdSqsyTSqcVisSnl4zHxp/LUf6bSay1OJFcfDkLv4a0AMlR/NifBkM+g52Ye9o64egLMRctd4+PXbYtVOLPFD9sffnw9/VTtzKuhV+TOs1NCceQsKVk20XSgRNTYMgEQqdTq9wC/+ZMZdTr/RmbAoExzdMdM4onvLT2MjAjIvbZAsGuT/NBsQ29kv1MaBWNVauakTfciFPYe30rlYgy4NIXePqPakDrHEH1kf/gBj4gTZsZwJevL1alB+aAZMqVVWSxNRY8QASKRS209k9DeZxWjl0UtmFkspRUNUD4tVXwIEaAShsH/H6EVW/Rev64KKk1Mdhh6bQU+uQEcHULWJXMhz1Ic2HcF33Aa/3lVP+wYg+5N5MCWPrN6FvaCnsN6q+yVzS5SsH2ujIRE1MlwEQqRSx87l3QwB2ou/l413ClaGKFvO4cSiDwdZM8jPa9N1rZskWm0sWv8kIFy+hk22D3udKwy5Lq28rdpGyELI5DHVw19xALI/mQ/T2XHy49nark2Ed4efoY/ZA33zUpRuawpz1kCY04cD8Kn+dsF6S8XRiZAqFkPwsr6ZNhE1KgyARCpUVGYy7DiZqexJEAqyjGfDY/UWQzo3X2W1wXg6BpbsYdazefa4I+gpnRG1007QnUPwJFszf/7I/nghTEmjnRirAoYr3kHIlLnQNcm7tNWnKyAZv0D5/o4oXPURLIUD7XZoKewNsSQQWq882TZE1ODxFDCRCkmS5GuySG09esoXDrq2c0a2+klfq9PUFf07RFsvkijdOxCQwmt+KhQOTt8q/WzstKt+6jYbwXdMgF/fKgs+Sv2Q89n3MCWPufzJOBzHBL+BzyHi2ZlW4e9Sc4MInx4HEfrIOGgC/nRQbyDK9rWROUAiaiQYAIlU6K99SeGCgCDHj/hVkODcFR6Vh8WEUH+vc5ffKAFle25SVIfSBRl2j8XBMVcPeqh2nZ6gS0PI1BHw67PVqmuxxB/Zc3+A8cwEu2NVHUMf/SMCbv4MEOxPqOqb5yP8qbsA4dzl47J5HO3t9kNEDR4DIJEKSUC03D57Gcl+WKzWkxMv5do2DU6KCvYtqXQ0Gpgzeyg6EIf1KTkGW7tlgp7NfnTpCJp4G3x7VV/wkfPZPJhSRjoMlNZjGBE46l1og0QbB1CdrkkefHp8ZHuMS69wRX0RUYPFAEikSoLBuYBmOwQ5ExbdNdPopdcmWt37z5yrhyBc4dzpWyVhULCxu+oYldspCbhCNkLuHAO/vputhheL/c+Hv8TxEATByRW+R6CPPVX1E7XLr99vEIQS+VXXTqZyImpwuAiESK2c/Sfe+efE2e3E8QyiDAHnrH5fcTQcEBR+l9kZVFDQRtF+2TbFCL5tgo2ZP3/kfLbo/IIPW0HPwRhebTOgDSxTUFTl96YByEXlR+UpHpeIGgPOABKpkACYbd+G2f6bXD+b6/wso40eTFU2eSsfq+oup2baZOqSaVN9DG8YE262eqtY6ofcL76DKanSgg+bM4d2xtBKNQhsEiDIvE8AgBxnOySihoUzgEQqFOzndc7Wdoch0A7p4uyeK5NHimYZq203ybb1/KyeE2NAh7I9zwMAgifPgGT0Qs4nS2BKGWV9GlnJ0JU2VByLhaXAD9qgkqqt7AgBBH87Q55xoi8iaoAYAIlU6Pq2kZkQUAzA/9JGJ+7TbIsz4VGSG0xZDvOy/r3eaP1eBadNFQxif3ONA6OAsj3PQLLoIRbEwJQ6slo7QfY3cmO0RfnuzvAbvF1BUeeV7+4NASEyA1ugiz6huC8iapB4CphIncoA4aTVKUXZFRtw/HKSvacBO/qFqiuYfa/LgiCUWRejtFCZdlVPDzt9mtju6Vsdyg88DdPZ8ZcOyeYYjk4BX9qvRfH6lyCW6OU/8UoseQaUbnm2+h/upbFOQB/Dm0ATNXIMgEQqFOBtqOjZOnK3spikIAHWYnisMImxZotY+Z0SIByW79RezbAT9JR+DkrGQPWxnA961m0q9yUVD0PeFy9DLLV/VseS7YXcz94DhG6yY3l12AKNd7ndfoiowWMAJFIhQQBaRvqvh8yJXyW5TVl+cyY8KhvsZFpBbHp+2eVT19CI8O60U368yr+1FcCU1u1gX7XNzvZhJ3TaCtXWbbQwpb6CvK/nwpQYWr0fCTCeCEPuV1/Ckvuo7UMWAEEQoW/6j5I/WSJq2HgNIJFK9Wobte6n+MR8iyiFVN/r4ILASrtdiQrWoyjo6XyTVnklFc2ah/kdu7RdH/0Xyg8/AOHiD7VKqnLURmZ/tfDlyhhV2tlt7nAsLUxJjyDn40kwtP4R2pCt0EWcgzmrGczpfWBKvg1AiP3772iz4dXxX4VFE1EDxgBIpFKdWoRkhvp7/ZVVWD6p+l4HYcNqt/Kw6OQoct0Y/juaPqBzTOjlAOjddQuK158DxOY1G8nG/mqb3Bj2HDZ1aaxQGE89BEF4yPottk4lV6EN+hv6lvmOqiOiho+ngIlUbGLvK78WAJPyU7q2KD3Fa+vl4O0yo2w4nDrGaqehVQ682ixz3JFcfZU3VT1FXJPTt/aOXcln58RYDh+1ovR0M0T4Df7O1g4ianwYAIlUbFDH6K1Ngn3jKgcHQe4Fp/KaQjULjwVlpr5xh8+1serKf+jnAPLt91V5k72gp/Qo5eqs2tReXwrHshv03PCnog3dBq+uym8lQ0QNGgMgkYoF+OiNI7vHvKWosYIH/Ho2LF4mSfDfcCRtmtVGQ+tEGK789HytVV/OzrLZ/ABQPezZau6GsZye0XMDQ5tPoPGpcE9nRFTfMQASqdyEXldsCPX3WuXWTp0JizWcadx6PGP61hMZzS6PqZUQMvUtaAx7nJtpq1a8TM2VmzuqzoUZPYezeh5xAH6DVniqcyKqfxgAiVROAPC/0V1e0Wo12Q6DW60UpDg8Ri7579SzVvcE1IaWInDsdAi6DJdm9Wy1cXQa2N5YDj/LWgt6tljgc+1b0IaLtTkoEdUtBkAiQreWYUe7xYa97XD2TWbWTklo84ST6YX3Ldua0M9qo2/fvQicMBXAhWfj2gp5zszqKd0PBcdeq7N6ymiD/4P/aPfOABNRvccASEQAgOdGXf2Fr0G3tSahxGFwhMfCo9/SLae/3p2QHWa11bfX3wiaOBGCLq/64dgLYfaOoHIX9upU2Ef9UAG/wS9B42Os60KIqHYxABIRACDEz1D6wI3tn4SAkguJDbYXT7g32DgTHm2FLpMotfv0nyNfFZebfK069u21BoG33g1oipTP6Nkq0NkZvQZEG7YA3tfG13UZRFT7GACJ6JKbuzTf2btt5FuofN9lZQnNRkhyf3iU6+FcbumtLy7d9VFhmcnL6g2+vVcj6PbbAU1hjWb06mZBRi3RnkPQpJkQDLz2j0iFGACJyMr9Q9p/EhHgvdXl+KY4A7onKJ5IK7hnxo+75xaVm7ytdvj0/BOBt06BoD3/hIv6vSCjtljg2/dF6Fum1XUhRFQ3GACJyErTYJ/CqQPa3A8INmbNqgciZ+b6ZHup6SyjdXjUHDtX8OCM5XvmFNmaCQy89S4IQonjQVVA4/cH/Ab8WNdlEFHdYQAkompu6BR95Norw5+FAFMNw5id12WeCI9HU/MffnHZrk+Ky00Gq8F8rv8dgRPOLwxRS9CzLRMhDzwATSBv+kykYgyARFSNIAAvj+kyv0mQzw/OvVHJq2Zh0YmhhFPphdNnLN/zfnF5lZlAn+vXIGDM3YBQ5NRxNR5G+A16CrponvolUjkGQCKyycegNb0ytssTQT6GHQIc/3Kae077yrwgHE3Nf/TlZburLwzx6bUagRMmAkJhTT6XBk3f/HP4Dlha12UQUd1jACQiWW2iAgseHXrVZEGDVEcZT0lIrHFYrD6YouB4PL3wvleX75lbfSbwuj8QOG4KoM1zvZgGQtDHIWjqq9D4S44bE1Fjp505c2Zd10BE9VhsuH+O0SztO5ySPwYCvF2/aM+5sOhieBSyiyuuPZicH9KnXeQ6L53WcmmPvsVxaAMOo+LIaAAG+S4aAUGbiKC7xkIfm1nXpRBR/cAASEQOdY0NPQMIRw8m548FBF2Nkp9bVnzULDxmF1X02JeYG9WvfZN/DFYhsPkJaAMPoOL4LYDk4+aPrb7IRtCdE+B99cG6LoSI6g8GQCJySBCAzjEhJ0wWMfdoav4QCNApf8yv6ws+ahoWK/eQW1xxzaHzM4Hrq4dA/2OoODYMgJdsDw2TCd7X3AW/Qesg8IofIrqMAZCIFBEAdGsZulMUpaxDKQU3AdBd2iezVsO5x/y6bYpQ7iVkF5VfdyApL7x328i1Xvqqp4ODD6DiyCg0nhBYCu9u9yHojhUQtHVdCxHVMwyAROSUzjEhe0VJyjicWnCj86eDqwe22g6POcUV1xxMyovo2y5yrfVMYLOT0AYcgfHE0EZwOrgU3t0fQOBtSxj+iMgWnhMgIqdoBEGc0u/Kr8dfFzsdQInDN9jk+jldoKZhEZrjaYXDj54rCKnWoU+v1QgYO7Xmx1UvVMC724Xwp+OKXyKySZAkfj8QkfMkCcKSrQn9lm49swRAcwBQ9G1Sa185tgfSaTUJj9zYftTQq6MPy761LH4EClctAizBnqrOQ/Lgfc39CJq00uF1lUSkagyARFRjkgTsTszpOGfN4YVF5eZrKu1x/F5FA9S4NJs0gpD4yI3tRt/StdkBh43Lto5B4S8LADHQvVV4iiYNQZNuh1fnzZz5IyJHGACJyGUn0guDP/772MdnMovvgstTT54JjxpBOPv4ze1vualz9FHFpZTFD0PhymWAFKD4PXVB0G9D0J3T4NXpRF2XQkQNAwMgEbmF0Szq3/nt0MO7zuS+ZhZF6+vr6v607+kHh7Qdd0sXBTN/VZVtG42iX+ZBslS/ZrDumaFrtgDBU5+DNlQ9TzUhIpcxABKRW/17KK373L+OfQegi/UeBd81nvk6Sn58aPthQ6+OPlTjHsq2j0ThyqUA/NxXlsty4TfoefgOmA+Nv8VxcyKiyxgAicjtMgrK/ef8fuSVo+cKHoWC0OSWk742mui0QsIjN7YbdVNnOws+lCqLH47CVYvrwcIQERrf9QgY9zC8u5zkYg8iqgkGQCLyCLMoaVbvTu67ZOuZz4xmsSMk9yQVpWFRqxESHxrSdswtXZrtd8e4AIDSrWNQVJcLQzRZ8Go/GwHjvoE2uKxuaiCixoABkIg8KiGzOGDlzqSnNx3LfBaAf/UW7j81LAhIenxo+5tv7NRU+YIPpc4vDPkRkGwci8eYoA1bjqCJL0Pf6mwtjktEjRQDIBF5nCRB2HQ8s/P3G0+/l1NcMRiVHiPnYs/Vtug0mlMPDm5z681dop1f8KFU7S0MsUDw2gX/YS/Bp/smCN5mD49HRCrBAEhEtSajoNzw54Fzo1ftTJ4lSVI7d3/7RAZ6b7+zd8vJQzpGnXJz19WVbRuJwp8WAPBUCDwN7+6vw2/wT9A1KfXQGESkUgyARFTr8kqM3it2JN0WdzTjyaJycxdUfSylgu+lKi0K2kcHfvz88A5vRQZ61961cWXxV6P47+8hFnZ3U48iBMNOeHf5Cn6Df4A2osJN/RIRWWEAJKI6k11U4ffXgbQBW05mTcsoKL/JZBED4MQzyjUCCto0Cfht/HUx717bKuyQTivU/heaJTsYRb8+BOPxJyFZIuD8slwJ0ORBE/An/AbPh1f7LdCGcYEHEXkUAyAR1QsJmcUROxJy+p9ILxq872xeV5NFbAWgaZVmFQCSmwb7HLymZcja61uH/9Y1JiS5DsqtzpQagdKNt8N4chzEou4A7K0ULgVwAoZ226GLWg/vTmuhb8UbORNRrWEAJKJ6p7DMpBclybeg1OSzMyEnHIDW10tX1rtNeC6Acm+9ttRbrxXruk6bpDIdxOJglB9sDaAVgAgAvgAKAOQAOAvvq89A8C6Exq+c9/EjorrAAEhERESkMoqvtSEiIiKixoEBkIiIiEhlGACJiIiIVIYBkIiIiEhlGACJiIiIVIYBkIiIiEhlGACJiIiIVIYBkIiIiEhlGACJiIiIVIYBkIiIiEhlGACJiIiIVIYBkIiIiEhlGACJiIiIVIYBkIiIiEhlGACJiIiIVIYBkIiIiEhldHVdAFFDUFBm9l6+69xN5Saxk43dxnB/w5rbrm16XKsRpFovjoiIyEkMgEQOnMgoCZr49Z4fs4qMNwEQZJq9djKj5PlXR7b5ojZrIyIiqgmeAiZy4Mllh2dkFRmHQj78AYD/t5uT3lu1J/3q2qqLiIiopjw+A2i2SMLSnedGAoj29FiVZProNXtGd22SrNdqLLU4bqMmScD+lELfg6lF3QF0gP1AVKMhAKR2aR6wpWN0QH59OJ16MqPE62RmyS1K2koS/H4/kHnTuGuiDni6Lmr8UvPLdeuP5QwA0MbJt0oA4sd1izrg56UVPVAauZUEyXjWWyo/1g3nv1f1NejEAsFnp8a/734IWvd9b0pmrVi09kYALQEUCl5t/xS8WuW5/6u/CrFcJxbHDQTQGkAZtEF/a/yuT3ffuJIgFm1sBal8EGr2ebuHYDio8R+wDULd/D31eAA0WkTNS6uOPQlgkKfHqkJ86scj+yf3avb19L4xS66I8C2q5fEblf3JhaHv/HX6mf9O5k4HEOnh4Upjw3xWPzgg9u1br4k66GNw4xeas4UYLYZyk+jtxFv8PVYMqUZqfnnohC92r0jOKx+Emv2rJ67em/7R99O6vBDoozO6uz5yD7EkPkYs/OdxsXTXXQCauNidWchb8oEu+v9eEnThLk98SBWnmpnSXl8MS+HASptTtcGjp2jD7lnvav+y45YfjjSlzV4EsfSmSpvztKGTpmlDJv7q+giiYM764hGx8J93Afi43p9LJCH3h5910bOnCfqoWs8ojfkUsAZAt0XbUj8f+enOTct2nOtlESUP/9jSOC3fldZh3Be71/53MvcleD78AYDv2ZyySS+uOrbpsaWHX8gvNRlqYUw5Ajz+4y7RZWaLJDz6w6H/S84rH4ya/7eniT+T//gba07e487ayE0kk86c+fE0c8b728XSXc/A9fAHADrJlPGsJW/FBJd7koyCOf3/PqgS/gCgmSX/t4WS8WyQy2PIMGfPe7tK+AOAEEvuj9+JJTtiXe1fLPynu1j4z/uo+/AHAIJkzhpnzpjzGiRzrQ/emAPgRUJhmbnrcyuP/vXe3wnj67qYhmbVnvQr/rfy6GqjWexWB8MH/X04a/bAOdu/OXKu2JlZOHfyB+BbR2OTCp3ILAnZlVhwsxu60v6489wk/uBb30iCOfPj18Widd9Aqmjq5s41UkXCHa52IpbujpLMOcNl9kZLFYmDXR3DFsmcqZMqTt0mM264WLR2mKtjWAr/mQCgLicVqpEqTo6TjIkeC9Vy1BAALwr8PC5x3pu/nxonSnV+aVmDkJJX7jPn79PfmkWpdR2WockpNk5+cPHBT0uNlrq4VkO68FKK15ySq/Rw33VJQeAMdv0hmQRz5twHxOJNL8Bzl2AFuqGPYABamX0CPPRDsVR2KAyQ7M3MueMMVIgb+nA3LwC1PsmhpgAISYLflxvPfrk/ucjlaWQ1+GlP2rDkvPKBdV0HAOFMdunU9/9JuL22Bw7zN+SE+OqTFDa3tI703e3RgqjRC/XV54f5G87VdR3kfpb8nweKRXFvw5P/9gqaeI/17Xke/2FF0Dff7+kxnCXom54SDC2ya3tcVQXACyIeW3roneIKixqP3Skrd6VNRf2ZPdB9vSnp7YzCilqdum8e4m28f0DMCwAKHbW9IsL3p2l9WvxdC2VRIxYV5FXx8MDYGQDK6roWch+xJL6NJe/HRTg/K+spx3SRj8/xYP8NnjbktvmCNnhrXddRSaEm4MYXIXjV+tmj+nAjaFPTIK8MwPVbfhSWm7QlFRZfODjtcTanbPiaAxkdJvaIPuTqmI3V3qRCn5S88s52mogCkBcV5F3qjvHSCsq9cP7PzctOs2Z/Hsy6cVqf5r+7Y0ylHh7YMs4iSmOWbD/3EoB2NpoYw/31P3w15eo5TYNq/y8xNT739Yv522SRRi/YmvIC7NwGRoIkpBdURMD+3xuqY5I5K9icMWc+JHMzR00B5ANwZkWABG1AiaAN/lMX8fjbgr5ZVs0rbfwEQ/MSXfTrY83p782AVD4cTuQgSSwLgFgSLLNbFLRBGRD0yv/sBMNBbcj4WZqAwXUya1sfAuCRrS/2uUanEVy+D05CVqkhObcs6ouNZydtOZU3A4CfTFP/Q6lFw9ADDIAyjGYx1CxKsrc0iQn12fDO+PZ39G0dmumO8f47mRt0MLWoy1t/nPoGQFu5dr/uzxhS2wFQI0B6YkirDU8MabWhNscl9RIESI8Miv33kUGx/9prV1Jh0bafEbcWwMDaqYycZinQmdPfmgvJ2NtBy0KNf9/XNQE3LgdQ4swQglfLfEEbzIvbFRIMLTP1MZ89BuAxZ95nyV/9tCXn+/dldufpol68XvC+SuklQ3WuPgRAt7kiwtd4RYRvUr+2oe++tvpEyvytKQsgcyHrT7vTes8eY2syhy4wws5PoSl5ZVdKkvsuWu3XJrSgb5vQTZIkTX/7z9P/Qn5Goy4XpBAROUGC6dyMlyTj2cn22wnl2rApd2qDx66pP1fdUGPXKK+D0wiC9NiQVqu0GuGgXBuzKF1RmzU1NJ2aB+RGB3vnyO0XJbR8fOnhzxOySt22MlcAMKVX863BvvozdprxRstE1ABIsOStGCUZz74E+//WioLXlbO0weMY/qhWNcoACACRAYay/m1C0+w0kTs9TAD8DFpLTKj3P/baZBcbh7395+m3yk2i3O0CnBbgrbP0axP6k50m+9w1FhGRp4iFf3Wz5C75Bg6uzxS82y3WR8/kwg2qdY02AJLrHhnU8jsA9hZ5CH8eynz8meVH7nLnuMM6Ry4EkGtjV9aLw678yJ1jERG5m1Rxqok594eFcHTfOsErXhc27UloAvi4Pqp1DIAkq0/rkKPdYgI/hv0bIev/Ppw197f9Gb3cNe6Qq8JO3tcv5iEBSLgwtsXfSxf3yaSOt/RoGXzWXeMQEbmdWGowpb3+DSyFney2Ewypuqj/TRG8O+TVUmVEVhrVIhByL71WI340sePrt3+199q0gvIb5NpVmMXgR5ce/kEC+o/q0iTZ1XF99Frp1ZFtlv/vlit/xoVFPAJgMug0vMUKISWvPDCvxHQFzv+3kXllpG+Kr0FrdwVkuUnUnMwoaQYgHNY/+FoAZDUJNKRHBvIWPuQisVxrznj/TVgKRzpoWaIJGDhd49v9RK3URWQDAyDZ1Srct/yzOztOH//Fnr9ESWov104UpZaz1pz8pmer4AlNAr2K3DG2l05jAmByR1/U8ImShI/XJd7w3ebkT/JLTW1wIQDe0CH8q2+mXP26TiNYBTiLKGFPUkHwHwczb1t/LGdSQlZpRwBhqB4AcyICDEcndG+6eFjnyKWdmweUaARejE/OM2e8N0Us3fW4g2aiJuCGl3XhD9i9xprI0xgA3eB4ekno91uS7yksM18LQASw8bWRbRZGBXl59E7+R84VB327OWlamVHsCQB6rbB5xog2CyMCDMXuHKdHy+CzM0e1nfLq6uPrAATItUsvqBh6+9d73lv+QPeHIwMMLt/XsbbNXXum3/H0kjvh/LMiK8L99StfHNb6D1+D1pkbuLqdWZQ07/51elRybvkonF/olDqyS+T8YZ0jD1xsU1hm1mxPyOv0896MGwBcDeDiszczmod4b7upY/jaHi2DZW8mG3c858ofd6bdAKAHLv/3kBMT5r3tpg4Rf3ePDXLLvSGrWrI9tfP7/ySswPnnlF4UufZI9oznVx7N/+C2Dh9c3Hguv1z/4dozU5ftODcDQIydbrUAIrOKjJGfx50d8Hnc2ecfGBDzwivD26zyxDGQbWUmizY+Ib/z8l1pQyQJHeD8an8TgGMjro5c3+vKkJ2hfvpa/8FRLIq7Xizd9QkAu08rEnSRC3SRj/FaZqpzDIAuOpRaFHzrF7t/LzVaeuLyGv6JR9OKRi2a3u2OFiHeBZ4Yd8eZ/NA7v937Z7lJ7FF53GPpxcMW39v1zshAL7eOe3ef5jsPphY+smJXmt1VbaczS+/9ZN2ZAzNHtf1Cq3H96S61wSJKwlt/nrr7641Jn0qXw5CzJiblln/wet53BwAAIABJREFU5eROL/notXUSfo1mUTvx671v7kzMfwaV/m7/cTBj8rNDrxz50IDY+MXxqV3n/nvmzZwS4wDYfqD7o9/+l5Te84rgTz+e1GluZIChFABMFglbTuW2/HRD4hu7EgtGWUTJ1uOsHvxmU1J6n9ahn39wW4f3IwIMbv0B6I+DWdNgHf4uWb0v456nb7zi6+Yh3sWHzxU1e3DxoU8Ss0tHw/nrnNt8vSnph/iE/I++nXr1600CvdzypBuyrajcrP39YObgj9aeeSklr7wnav73DwCw5kDGjBBf/eEHB8bOmnRd9JoQ39oJgmLx1pbmrE8WwcHdJQR91H+6pq89XRs1ETnCRSAu+jzu7OOlRsv1sL6Bk3A6q3TY7DUnp3tq3E/XJ75SbhKvqzru0bTi4e/+nfCQJ8Z8bWTbJde1Cv7YQTPd/K0pb7/z1+kBnqjBE+LP5Df9amPSOy6EPwDQrz+W/dSibak93FaYk/48lHXtzsT8J1HlBztRQvg3/yXNenbl0adm/HJ8Q06J8RbYDn8AIJhFqemWU3lvDpqzbVX8mfwIAJix+viEyd/t2xKfkD9ZJvwBgGCySE3jjue8Mfj97av2nC0Idd/RAYfTiiLk9hnNor9FlAzLd6Z1HP7xznWJ2aVjUcPvN0mC177kwucnf7dv0a5E9x4DXbY3qTBw0jd75z634ujvKXnlA+Fi+LvAkFdq6vbWH6eW3zx3x8Lk3DJnZ/OdJplz9JbcxV9BMju6SX2SNuyeaYI+Ot/TNREpwQDooozCikFy++IT8oZ4YszU/HLDvuTCoXL7tyfkyS7YcEWQj078anLnVwO8db86aBqwcFvKoh1n8mUf6VafbE/I64rziwNcZYhPyJf978HTtifk9YPM7GxeiWnIT7vT5sCJB9EXlpmHTv1+36rJ3+17Ysn21MUAohW+VcgvNd1813f7fjqdWVprN+5eEp/a57mVRzZYRMktj/g5mlY87tYvdsf9fjCTjwxys3VHszuM+3zXxv3JhY8CcNvN5CvRncsvnzj+yz3rftx5TvZZyu4gFv4+VTKl2v/OFbRFuoiHp2r8eiZ4shYiZzAAus7eTZDddoPkynJLTF55pSZ715m47RFtVYX7G8q/nXr1dF+D9qi9diUVluZ3z9+/4GBqUUO44bY7r/j32GevgL3PWkANjrOkwtIn7njOB3BwXZMtReXmAa+sPv60RayVKwEivog7u1CUIDtLWBOiJHV+ctnhtR+vSxxqtkhcGeIisyhpXvjp2KSHlxxabxalrp4e71x+ebcXVh37dcHWlKs98l+hpdDXUvDn07D/b6lZ43P1S5rAoXGeKIGophgAyWm9rwzJ+uSOjpMByC4UAIDCMvP1b/1x6pPiCrMnfsJ3m95Xhu6Dg2NRMQE1/54QNp/MfbI2TsPh/Cltm9cHuqrcJDZ/7+/Tqx5beuhBo9l9T71RG4soaZ5ZfuS1JfGpC0uNlia1Na7ZIrV/5ZfjfyzaltLH3X1bitb3g1h6lb02Gp+uX+mavPCVu8cmchUDINXI4Pbhu+/t2+IBOLhNy38nc6dMX3DwqVKjpd7OnvRoGXTuiSGt/icIKKnrWhqhkD8OZg2v6yIAiME++q3P33zl6AX3dI3dPaNf05eGtb56bLeoB/0MWiU3F/ddcyDz4+kLD8w5mlYsd/0kyTCaReH5lUefWrUn/WXUzeLDZq+tPrHq+83Jbr1EQyzeNMZuA43vJm343c9B483bWVG9w1XAVCM6jYBXR7b95URGyTv/ncx9GfKnF7VbTuXO/G5z8r7HBresl/e90moE6dmhV8zz89IePZFRMhF2bgNzNqfMZ2di/ng0nqe2lwPYjvOPrOrg5HvNAOIBNAVwhVyjNQczej48KHZxjSt0gwFtwz6aNabtjFbhvpdC/kMDY9MBHPzvZO5f9y44sLDMaOnvoBvdhmM5jx9KLYpd+WD3266I8K3TW/40JH8dzuq2fFfaDCi7LEYEsNffW5d0c8cIu/cUTc0vN2w7ndcKQHc4+PfMLEqRr/92cnHbKL9r+7a2+5x4ZSyFWljyrrfTokQX+fgzgqGlR28HRlRTDIBUYxoB0vu3dZh1xzd7Wp/KLJ1op6nPe3+fXhTooxsytVfzQ7VWoJMeGhi7HefDkKyVu9Oidibmj4OHru+sTUE+upNTeze/66kbr9iZXWT0uuWjHRuyi432/kGr7OyTN7Sa8sQNrTYfTCmMHv/lnr1Gsyi3kKalm0quCePAdmFvfjf16jflniTTr03o2RUPXDN81pqT78afyX8A9s+MaLKKjGMfWHxw7m+P9njSW69hCFTgmeVHZkHBAqSYUJ+/7unb4pmpvZsfEwDJ0a2kJAmwSJLm3yNZHV746dhnuSWmfrDzw5koSdHv/nX61eseDH7YoNO4dFmgZEoLk8y5sqeyBW3IPsH7qj2ujEHkSY32FHBOidGwIzHf3i0cyj1dQ5lJbHM2p8ztiyCMZjEQdm7IXJuaBnkZv5p89eM6jWD3i06SEDnn74TvEnPKwmqrNpIlBXjr4ubd3eXG54ZeuUOnEaSoIK/yQG/dbiXvDfbVb1s8veuQp25stUmnEcRuMUEpkQGGU3beU1ffM8aB7cJe+PKuzrMdPUawS4vA4nl3d3miR8vg/2k1gsN7/x1LK57+6YbEYe4rtfH661DW1RVm0dGdCUwdowM++v3xHrfe27fFEZ1GEJXcR1QQAJ1GEG/pFHlo0b3dRvRpHfIVzj/dRdbepMLxqfnlkc4cg4wg2Ft4pfXbJ2iDG9wN8Uk9Gm0AXLrj3OCSCks3O01S3DSU7F/wUqMldt6W5LFuGueSzzYkjgdg7yLqWv3SadvEL+v92zrcqdUIGfba5Zearrv9qz1fJeWWcea5DvVrE/rlzw93H9mjZXDVa98czWZJHaMDFiy8p+stA9qGna7yuLR0O++rtQv+K6kY1D7s3q8nd/7Iz0vZjbkDvHWmVQ93n/PK8NbjATh6monXt/8lzcwqMjq9OlptFmxNmSxJdleRFz4yKPb+H+7r9lSwr77GN96+unlA0YJ7uj56U8eIZ2D/2uTwn/emK53ptkcPO2fRBF047/dH9VqjCoC5JSZdQlZp8NPLj0yc83fCAti5dcWYrlG73DFmgLdunZ3dmkXbUx8qKDO77R+JI2nFPhuO5Txpr83VzQN/d9d4So27JurYvX1b3AfYX0hxLr983Jx/El40msVG9d9eA1HU+8qQJ76f1uWxdlH+zj4u0DigbdjLqx+99v5uMYEeebqNuxi0mtwHBsRO/WbK1Ut8DM4/leXevjF/zhjRZlCwr97ujGhJhaXzxhM5fWteaeOXVlDhFX8mf6CdJpaHB8U+/PzNVy4I9dO7fKcWL53G8vmdnT6+qWPEKwBk+zuQUtTd1bEcEXy61uu/J0T1YSam9e1f7YlzR0dJuWVe6QUVYTh/Qbq9i/TN7Zv6/+mOMR8ZFPvN+qPZ/5NkTgUYzeL1645m9x53TVScO8b7Mu7seLMoxdppkvXIoNiF7hjLWc/cdMWaU5mlb6w/lv2OnWbCz3vSX/LSag6/N+EqPm+1Fr0yos2dd1wXvcZbX6Nrn1KfHXrFp146jdzMiuzsYUJWqSExp8zQMszHWINxnZU/e2y7yZOui/6jph0IAnB//5gjA9qG/n979x0fRZ3/D/w9sz27STa9hyS0hCQQehGR5iGBowsCilgAsYGc9zv82uAsZzkroHAgICoKCgcWDgugiCDSIqEaCQlJSC8k2WTbzPz+QE/0MpOyM7uBeT0fD/7JfPh8PoFk9jXzaWNmrD62qazOKXaqjfaz42Wjp/SO2t3Wtq51HC+YXBwvOu3DT68pnjekw2aWke/YSIOWFf46KmntFyfL7yeiuKbKnC6ulzofGkAV2kMANP9wvuZ6bzYYbTXumdQz8qAcdfVNsJb0S7S+d/B8zVyRIuw/v8h9aFRq2N6WDkWJqWlw+R04V72QJMLtsK4h61Kj/T1f4dYGfnqN8Nbs7i9NXHG4W1ZB7e0SRY1bjhavzewefm5Y15AfvdZBlZvSK/Kgv1Gr1K7MFWIXbA7O0ODk9ESkaADUaZjK5yanjJnaJ0qW3+2ukZbSl6Z2mzZrbdYJQWj6pJjTxfU96x2cxmLQSM47g6ZpWObnYLP85/UmR1oqesQGlPxYWNtkACSJlf4AaqHGYTjH7EGxS4JkvOlkpoevJiLRuSsFVY3Dt2eVpHnazsaDF4eX1DpE5zUyDNnGZ0T4dMNRLctwT0/oujDYrJNcTevihMB73sl+9+uzlZHe6htc2wYkBb0gV/j71dCuIaVp0f5fil0vqrGHOlxcu97oXLWulY2aABTSHt4AehM3ISPisblD4g/IWemkXpFHV36Tv6f4kkNsw1vLij3582f0j5nf1jYqbS7Nqr35D5PEba1LhGXz5N5RPj9rskdcQM3qWd1vm/zmkd0kMgRDRNTg5NL+svnUqq/+MmBakJ9O8VXZoCipt3tmunxSR2vnHbZG/X3DEjYpUXGPuIBL2UWi29GZ6BrYEgjaB8F1MVBwFvajyz9XbcJoLGcZY7ezMnYLrlFqCoDOyb0in3/x5m6vtmR7gdaw+un4+UM7vPrE9p8ySSSgFVQ33pZdWPdkeqx/c6sLm/T+waKhVTbXQIkitvuGdVjRlrqV0Cch8OdFNybd8cpXuR8LAomenFBW5xx765qsv2+c03NxoEmLLROuUhMyIquW78kTu8yS8u9jKmODjJKbBgO0XwJx1ZuGcNVb15Dg6EgejM4xhi5LdbEvLpGvb3CtUssQcO34jIg5z09JWarTMIps3DqxZ+S3RCS6alAQyLzi67y72lK3082zq7+9cB9JrGruFG7efVNqWFZb6lcCyzD00I2JuzLTwv+PpPflYo8X1j60bPf5qd7qG8jPIL2wREPqetgEaBXBWRDCVb3/AQmOzqSez2XwsWv5piwQUdHw5JCPHhyR+GLvDoEXlWzM6qdzzOwfs/y9g0VrSeQX+LPjZXMO511a1SchsKo1dX+fW5NSZXONlygi3Dk47gWTvv1NRP/HpOQVBdX2LscLa++VKKZd9c2FNy0GbcHCkYnfea1zICepBysTERm91RG4enC8EHgor+Y6Jeq2OTiLEvUqQbCfGkWXj1QE8Jr2EADL5t3Q4W2WEd+zqQ3KTTrNkXEZEScSQ03lf9iwVjF3DY7buuVo8VK7ixfbpiVhR3bZ+D4JgetaWifHC8xru84/TBJPhQYtuz8zPVzWeY1yCTLr3Gtnd1886Ln9aU43L3XWqnXFnrx1o1LDhqVEWYq81kGQS6WvOwBXnwYn13PSG0f2+bof7UCArzsA6tMeAmDx4tEdF2tZ5qqf/9U5wlw3KjVs9fas0qdFijCbDl98YP7QDu+F+etbtCXGrtMVXX84XzNBogg3d0j8KyFmXbt7+/eriABD3Zsz02bdu/HEboeLTxIrZ3fxnWesPrZu45yeE1KiLG0+EQB8QuoBDm8AAaTl+boDoD6YayCzzPTwd4ioXOx6baM77Z3vC5s7F/O/VuzJn0NEVrHrVj9d9swBMbJsaq2kP6WG5S8ckTibiCR3x6+od974/M5zLzS6uPbwcAItJzUErKX28bAJ0C6xlht2E+u3x9f9AHVBAJTZ8OTQgpQoy4cSRXTrviucb3NwzW4d8W1OVXhWQe2dUmUm9oxcGWM1XhVvy+YOif92Qs/IRdTMWcW7TlfMffD9k3cISm1ZDEoQfeghIsotb8C9BkAMa3Lqoh6bzhg6rSdi6ogYXvoPgOdwU5aZUccKfxvd8VWSWPla0+C66cC56vTm6lr1Tf58XhBE3/4RUe69Qzu835Z++oJey9Ky6alrB3cKXkbSQ4a6nSfKly3bnefVE2JAOYfyasJ93QeAX4VZ9Md93Yc/YoyppbrYl+7Qd9wWoO+4TSP2Rxv1ZBciqvV1f+HqhwCogBHJoTkpUZbPJIpoX9t1/j43J4iuTimotof8cP7SbKl2hnQJXhPmr7/qbgR/H9/lsRirsblha8Pru86v35ZV2tkrnQJP4a0EXBV0GrbggREJa33dDwBfQwBUSGZ6+HIiEj1uLqugdtLOk+WJYtdf++r8tEYXlyB2XcMylQ+NTFqtYa++8446R5jrN9yVcTcR5UiVc7j5pMVbTq8trXX4e6lr0HbNbXCu9P+hkTDPEKS544NNe16emjJ2VGrYeV93BsDXcMNUyC39or9e/13hD5U2p9geV8E7ssvuHNs9/LE/Xjhf0WDZkV32gFT9A5Ks6/okBFbI0lkf6BxhLl46rsvMpz7N+Y+bF0LEytkc3HXT/3Xs1Y1zet4TGWiQ/dB48Bql92QLX/ddQe8l47q0+wVR8Bt/o3bLgUeuu9tb7Rm0jM2o0+A+AkAIgIqJDDC4bu4TtXLlN/mim5zuyC6bc76i4dnEUL/fLeJYv79wfJ3dLTr0yRBdun9Ywlty9leMIBBxgqChX47yYog4OY7SY4jozsFxh3LKbAvf/b5oLRHpxIrmlNlm//OL3OMvTkl5zUtbOkIrMYzkaS9e6cLmw8VP3n19/LexQUZZzxz+6nRFrMRlG0mfdAPSXIEmbY2vOwGgRhgCVtA9Qzv8m4h+ErvO8UL4m1/n337l1wqr7bq1+woWkcQB82kx/lsGdw4+I19Pm3auvMEwbdXRxxMX785PXLzblbh4d2Py419/svenqk5ytfHYmM4bB3YMep6kF4Wwmw5dfOaNr/OGytUuyGtqn+jmhoAVXwRSZ3f3n7LyyOYLVY2BctW5I7sso6zWKbptU2q0f6HFqHXI1Z4KBfu6AwBqhQCoIKtJaxuZErqWJMLNv4+VzM0tb/jv8NiO7LJhRNRTolpuSu+oV2XspqiXvsh9+EBu9RIiivnlS1q7ix8zZ8PxTw7nXRIdtm0Ns0HDr5vd4ymzQfNJc0WX78l/zu7i8TN7dWp22yM5FFXbR89ck/V2fmWj1Or5ZjndPH38Y2n/BR+c3MoLgugm1omhfgcNWslzkNVOIIkFQk433+dEUV2EF/sDAL/Ah6mCNCxDC0Ymvq3TsKJn/9pdfI8tR4uHERHV2d26DQcKH6ZfhlubEm01fnrbwJiTCnT3d86W1Bu/Ol0xm5r4GWlwcsmfZZfOkKsts0HjXDu7xzyLUfujVLl6u7v/9qwSRc4NBVlIBSGDtzqRV9Ew/pZ/HX2vqMZubsvfd/MCs+CDkzff996Jz+wuXnShFhE5xmdENPfgomomvcYWatEXil13uPngW9/Kev3ExTqTN/vlDUJD1lVzFnFrCe5Sr/0+g3IQABWWERdQMrhT0LsSRZiV31zY3O2Jby71eXpfZX5l4wiJss65Q+Jf12lYxbfcqGlwhzc6OdHhme9+rpZtGJiIaFDHoJK3bu9+KxFJLmzZerRkrJztgmycJH3KS5C3OkJEVFhtz5y68ugHeZWNrWq3tNZhePD9k498erzsXSKSfMsdH2z6YmS30GyPOnqNCzHr3P2TrJ9Llamsd9586+qsz77NqZIK2+0RTxJvNwV3cSoJDvlnLfP14STxQMVoLHJMSXCTxAMdbzvUjQSpw3/aRuDr40jiBQgRyTq/V+0QAL0gMz18DUn84DrdvLHO7g5ocHL+JPF/EhFgODS1T9ReJfrYBMkbV3WDq295nVPW8137J1pP3DYg5kGSOFbMxQnJcrYJshFI6gOD9/4o6YWqxrG3rTm2vrDa3qItaM6VN5gyXz+06pMfS5cSkV6qLMNQ9QPDE57UyrAg6lqXmRa+iYjsEkWYSptz2IzVx3Yt2503hOPF90dtZ6qIqE7souAqvZGv2ztA1hb5Rp27fNUikgiArHlAvqfNMNqIYmJ0oqulBcdPM/jGrC6etvM7fL2Bv7RjEYl/9giMLjZP1jZVDgHQC8Z0Dz+VEOontTF0Swgz+8f809+olf+xqwkBJm2FUcfaxK6XXHIMmLrq6PL956oTC6oaZRkOKK11aKKtxp9I+sMiQI62QHaSc70+PFLsk8n+eZWN46asPPJhQVVjmFS5MyX1cVNXHvlPWa3jdmp+dwRhVGrYQ7f0iz4mX0+vXeMyInLjgk3rWlA08YWd57688eWDyzcfLs44duGSbIt5lMDoosoZbbDUXqYB7vLl/+Yq183gG7MjiKtr264bgov4xmx/vv67Xs78uzcSXzdFqjRpgva3qZ0rMIakemL0JySKRLlLXtjBVW2cxDdmhxLf2OYsITh+CuDr9qS7ih5ZL7iKb5Eo2sAYk7Pa2g78L2wD4wX+Ri0/b0j8ike2nplKzbxZE6PXsj+Oz4j4UuauiUqJstgiAwyH8yob40SKMD+X2e6aturo5ACTti7QpPM4mNbZ3WxNgyuQpPeMK/K0naZU21zGRR+eWni2xDZDqn2bw60hiQUN3+ZULRj03P5ZEk25jTr28xUz0p5LibIo8r34iIsuDwGLDZtKvlFTUlG1fdSMNVnbFo/uePeI5NAzRt1vizYanBz79v7Cgcv35L1V2+ju2oLqnL3iA//x8tRuGxTsMglEtP1YSd8Ve/IftTm57qLlBIEhokiJqlKuf37/OWIk31SemXt9/Iuzr4vd09b+Nuf1W1KfunnVkRFuTmjurZE+p8x27182n7pDq2FqogKNUg+DreXuFO63c9GNSU9nxAU0t2q9eZoAgTGmfSTU7x0iUSqCq9m2gWq2VTEaawMxhjZM3+EYwV2hJyIrEflJFmUMh1m/3hda38b/Yi2DP+RrPx8kWkBwdOSqN22m6k0VjDbYTqRr09Qkgas0kOAOJCLJObuMNuQI69cjty1t/E+bzgth7tJ/PkK8fSy1IgcJfIPUQ0mQu+T5fcToW/NZeIYNHPUPjXXSPiLvjyYgAHrJjP7R+x7ZeuYgEbVlSECY0jvqjaQwP9E3ckq4oWvI+rz9hRObKWatbXRbaxu98mKS4oONh+Wus9HJ6aauOvrmmZL62R7X5eKsBVXNrkDtPHPNsRven9NzWNdIS6WnbbYTkkPA5ON7TV5Fw6B73snelxJl2Tg8OfRIWoyl4aMjJWEXKhsH5JTZJhNRSxYh2Cb2jFzw9wld1vobtYrerNfuK+iz5OOfvqDLH/qe0BdU2xOaKZP4+PazQ3RaZsLM/jFfedhek/okBBYvHddl1qP/PvsxtWxLIJObE0wFVY2y9qOgqrFz1oXa/m/fmTG6Z3yA6OK8ltIETfmAr9+7mIiipYoRUZjAKb7dIaexTniFGI0sc8RZ88AP+drPH6bfdoFoioaIIgS3x/+UzeE1QVNfJMbg8e+d4Coyuy8+8bHAVcs7PE/ECly12AsTMYlc5YZBROx4jXXiNzL3p1kYAvYSlmGEO66Le4aIWj1BV6dhCuYNid+oQLckLRiR+LnFoG1PJyvUj04Pf1/uSld/W9D3TEn9bXLXK6W8zpn+2q68+73ZphdI3ZxDvdYLccGni+vvX7Enb938d09s2nW6YnlOme1WakH4YxnmwhN/7jz6tVtS11pNOkXDn93Fs+8dLFpCnoe/1jC/8uX55yptTsVW4942MPbgMxO7DtNqmONKtdES1Q2ufi99mXuXHHUx+vhy1n/449QONgNndNFfsQGjtspVH+uXUaQJHPM4Sf9eewVj6LSZtQyWXEzUUlz15pkKhD9PBHI1W58W3OVef0hGAPSiv93U8T/DkkOeYhmmVcMaY7tHrPL22z8iojB/vWP1rPQFeg3bHoYqheRIyxujUsNK5a7YzfPp5KV96q70U6mtPd2EPOUkolqJ60pP7K/WsMxZJSqOCDD88OzErn+ac338twyj/IdhbkWDKafUJusq+5YorXUk1Ta6FZuryRDRrIGxpz6c1zszxmrcpVQ7LZFTausvT00MaUPv3sAYu71FPg1K7DlNyKx7GG2IjJuSM8QGTXub0cetJ99+b6e1oXPuJ9YiyxF+grOglxz1yIqr7UjcJa8/JCseAFmGEUIteqn3+A0S164pZoOG23BnxjOb5vVMWzY9dfqy6akz+yVa327mrxXPHRK/3hv9a8rgzsE50/pFzyCiEl/1gYgoIsDw5aZ5vZ5SqHp5x5laTnQFYRuVS1yrosvz9ERFBBhEH0z89Bqn1AIkvZZ1W/10UtvAKL19Q+3r01PHBpl1cs6T5cP99Zs2z+s1cuaAGEXCZVPMeg1nMfjkdJFGuhzkFdUnIbDow3t6ZUZbjWvJR2/OIgL0Ur8rrcOa3bqoJxawpvSVstXZug6c1Ybf/2fWPDBP7poZTSCvjX7mXsaQKHmggWIYw2Ft5COjGWOynFNl5L7vysFBPvgcUjwAGnUsPyIldDM1/YvOT+4V+ZGWZRTf1649GZAUdG5Cz8gPhqeEbjpRVCf5pJ8RF7Cxa6T5orf61pSl47rsfeeujNEmveY4ef8mIASbdTufndj1tmCzTpEQ0T02YLdBy3o74HLT+kRtkrPCSb0id2o1TJPfR1Ko32cmvUbqDR1lpodvI5EV2F0jzf/pGOYneoMKMevc0/tFv0NNrwTmpvaJlvV7bUqP2ICqDXdm3GL108nxdskxPiPiqa8WDbg9KczPqx8YHUJM9tQYi2xDeS01sGPQx3HBJsl9OOUSF2xyfr6w3/zp/aLvM+rYIvLufcWRmR4u788ja7JrIx97kDV1f4AYjecLTFrGxeiiNmsjHh7J+o84rVQjjCbQro168j7Wf9hfiJhqpdr5AwdjSFqvjVycyZr7ebytzZVY/xFbyQsPOq3BGDpuY/QJUg/QitAsWbJE8Ub6JlpPHThXHVhS6+hDv4VOoU9C4IbXbkn9u1GnkeXV7tXm5S9yB+8/V/2kRJHG5yYnz+oUbvb6D8aVNCxDCaF+JX/qFvpBvYOrOl1c34m8s7Fv6U1pYc++c1fGQ+mxAYr9GySF+dUW1ThysovqRlHLFgN4yj2ld9RT/290x9Ws9OrMVomxGquDzbqzu8+C0rKQAAAIZ0lEQVRUjqQrVtTpNOz+56ckz0uJskgGwNQYy8X8ysbqMyW2YUSk++XLQlSg4dO1s3sstPrpJKcuJEdaTuw+U2mtsrmu/D3nb+gS8vJzk5Nf12tZj972vPlN/kS7i+8hcvnSnYPjViVHWqoGJFl37DxR3sXu4tu6Z+Slsd0j5rw6rdsbFi9tu/RHgzoGH9p5sjy5zu5OIeWHz6lDiGn3+jt6zA0wauVcdSvJqNNwN3YLOzKyW9i7TjefX1LrtDY6uRhS9vttzEwP/+v/ZXb6SPY9HBktz/oP/4ExpmwVXKUucpcnkfSOBm3lIMbwhSZo0l81oXOfZ43Jin8+MKyJY80DvmcM8dsFV6lAXFUHUuZ7s5MmYLsm6OZFmtC7XmUNibJPfWKNnYoErvKS4MgdSr/d53xFYLShn2qjHl/IaAK99rv3K0YQvPPg5eIE9stT5d3Lap0D6fKHw+HJvSMP+xu1Pp886wsOF68Zs+zQ5rMl9ZPEyqTH+K/9+P6+d2s17WezWUEgsrs4/ZajJd3dnNCDlAlMPBGd75sYuK9blH8d44VtYTleoAO51ZE/lzbcRMrc2H7lNurYfTf3iTqpUWATYYGIdp2uCC+sst9El/dMzBudHrYrIsDQouEFjheYH87XJJ4tsY0gIoNRx56Y1Ctyn17LtigIuTie3ZFdnlZtcw3+5UvfT+8fnWXQen56TfelezdU21xii3Xy9/1tUK8OIaYqossrux/afGrBlycrFjg5PraFTdijAo2fLxnX+dFRqWEnNaxv9yN2unnNtqzSQQ0OTiz0yiVnVFrY11GBBl8MO/+Xw81rD+bWhOeWN/Qn6ZWnbeXqFOG3e2BS0M9K/O79Hk+Cu8bE2w4kE1E6ybN/KUdEuawp/RCji6whRu+bkTOBYwR3mR/fcDSNiLpRM9u3tBBHROcYXdQR1pRWrfz3xjN83Z5OAm8fTj4MgQxjOMX637CXGM+3UWtT+94KgPB7nx4v6z7/3ezvSCRsMAw1rJiRNvTPPSIOeblrAO1SawLgr34srI3+6EjxuC1HSv7s5oUe9L9vrm1EdGZcj4hvkiPNH0/qFXU02KxT5UMpAKgL9gH0kRV78u4liTdNkQGGXQh/AJ7pERtwsUdswMqnxnf10QR9AID2CdvA+MCeM5Uxpy7WTZUowk3rG/2K1zoEAAAAqoIA6AM7T5TdyQviiyjC/PX77rguzuPzHAEAAACaggDoZTmltuAPDhXfLVGEn94v+rVgs86nE7IBAADg2oUA6GXL9+RN4gUhXuy6Sa/5ae6QDp96s08AAACgLgiAXpRTZvP7/GS51Pmvws29o14ONGlVuS8iAAAAeAdWAcsgp9Rm2Z5VOpaIUqXKFdXYI20OTrSMTsPmTukduUX2DgIAAABcAQHQQ/mVjUHTVx/7pLTWMYg83MF+RErIWz3jA6uaLwkAAADQdgiAHnC4eZr/bvbTpbWO62SoruL+YQlrZKgHAAAAQBLmAHrgYo3dP7uobrgcdY1ICd2QHuvvlYPYAQAAQN0QAD2jIXnOEay9fVDsmyzTfs78BWiHpI5o43/5AwAALYAA6IEgP11tbJDxuKf1JIT6bbmuY9DPcvQJ4Fo1vkfEASJq8iEpLth0wuqnq/NylwAArloIgB6w+un4R8d0XsoQXfKgmgsPDk94Rq/FfwWAlGl9o98Pseh3/PHrDEOXHh3T6YlAk1bqDSEAAFyBEQSMOnrq0+Nlyf/am/8wEaW14q8JLMNk3zcs4dkbu4XmKdQ1gGtKTpnNsHx33oPnKxrGEJGRiE7MG9LhxTHdw8/6um8AAFcTBEAAAAAAlcG4IwAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqMz/B7LJu0uHjbFxAAAAAElFTkSuQmCC' diff --git a/DemoPrograms/Demo_Image_From_URL.py b/DemoPrograms/Demo_Image_From_URL.py deleted file mode 100644 index 423ea8932..000000000 --- a/DemoPrograms/Demo_Image_From_URL.py +++ /dev/null @@ -1,36 +0,0 @@ -import PySimpleGUI as sg -import urllib.request - -""" - Display an Image Located at a URL - - Downloads and displays a PNG (or GIF) image given a URL - - NOTE: - Early versions of tkinter (for example 8.6.6 found in Python 3.6) have trouble with some PNG formats. - Moving to Python 3.7 fixes this or you can use a tool to re-encode the image (e.g. psgresizer) save it and - it will then work OK in Python 3.6. - Example of one of these images - https://www.python.org/static/community_logos/python-logo-master-v3-TM.png - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - - -image_URL = r'https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png' - -layout = [[sg.Image(urllib.request.urlopen(image_URL).read())]] - -window = sg.Window('Image From URL', layout) - -while True: - event, values = window.read() - if event == sg.WIN_CLOSED or event == 'Exit': - break - -window.close() - - diff --git a/DemoPrograms/Demo_Image_Resize_and_Base64_Encode.pyw b/DemoPrograms/Demo_Image_Resize_and_Base64_Encode.pyw new file mode 100644 index 000000000..7775f61b2 --- /dev/null +++ b/DemoPrograms/Demo_Image_Resize_and_Base64_Encode.pyw @@ -0,0 +1,197 @@ +import PySimpleGUI as sg +from PIL import Image +import PIL +import os +import base64 +import io +import webbrowser + +""" + Demo Image Resize and Base64 Encode + + This demo has been released to PyPI as the commnand `psgresizer`. It is also in in this repo: + https://github.com/PySimpleGUI/psgresizer + A quick little utility that will resize an image, convert between formats, and also Base64 Encode it. + + Base64 is particularly good to use to make icons or other images that you include in your sourcecode. + + Use this Demo to help you code your PySimpleGUI programs. Here's how: + 1. Select PNG as the output format + 2. Set "Encode to Base64" checkbox to True + 2. Click resize button + 2. Paste the base64 encoded byte-string left on the clipboard into your code as a variable + 3. Use your variable for things like an icon, an image for buttons, etc. + + Copyright 2021 PySimpleGUI +""" + +version = '1.3.1' +__version__ = version.split()[0] + +''' +Change log + + 1.3.1 16-Nov-2021 + Added correct readme to PyPI + 1.3.0 16-Nov-2021 + Fixed bug - MUST always include the icon in the main function for these psg commands + 1.2.0 16-Nov-2021 + Somewhat extensive reworking of the functionality + Added a drop-down list of formats to convert to + Automatically save all the settings + And more I'm sure! +''' + + +def resize(input_file, size, output_file=None, encode_format='PNG'): + image = Image.open(input_file) + width, height = image.size + new_width, new_height = size + if new_width != width or new_height != height: # if the requested size is different than original size + scale = min(new_height / height, new_width / width) + resized_image = image.resize((int(width * scale), int(height * scale)), Image.ANTIALIAS) + else: + resized_image = image + + if output_file is not None: + resized_image.save(output_file) + + # encode a PNG formatted version of image into BASE64 + with io.BytesIO() as bio: + resized_image.save(bio, format=encode_format) + contents = bio.getvalue() + encoded = base64.b64encode(contents) + return encoded + + +def main(): + image_resize_icon = b'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' + + def update_outfilename(): + infile = values['-IN-'] + if os.path.isfile(infile): + + image = Image.open(infile) + width, height = image.size + window['-ORIG WIDTH-'].update(image.size[0]) + if not values['-WIDTH-']: + window['-WIDTH-'].update(image.size[0]) + if not values['-HEIGHT-']: + window['-HEIGHT-'].update(image.size[1]) + window['-ORIG HEIGHT-'].update(image.size[1]) + + infilename = os.path.basename(infile) + infilenameonly, infileext = os.path.splitext(infilename) + if values['-NEW FORMAT-']: + outfileext = values['-NEW FORMAT-'].lower() + if outfileext == 'jpeg': + outfileext = 'jpg' + else: + outfileext = infileext[1:] # strip off the . + outfile = f'{infilenameonly}{width}x{height}.{outfileext}' + outfullfilename = os.path.join(os.path.dirname(infile), outfile) + + if values['-DO NOT SAVE-']: + window['-NEW FILENAME-'].update('') + window['-BASE64-'].update(True) + else: + window['-NEW FILENAME-'].update(outfullfilename) + else: + window['-NEW FILENAME-'].update('') + window['-ORIG WIDTH-'].update('') + # window['-WIDTH-'].update('') + window['-ORIG HEIGHT-'].update('') + # window['-HEIGHT-'].update('') + window['-NEW FILENAME-'].update() + + format_list = ('', 'PNG', 'JPEG', 'BMP', 'ICO', 'GIF', 'TIFF') + new_format_layout = [ + [sg.Combo(format_list, default_value=sg.user_settings_get_entry('-new format-', ''), readonly=True, enable_events=True, key='-NEW FORMAT-')]] + + layout = [[sg.Text('Image Resizer')], + [sg.Frame('Input Filename', [[sg.Input(key='-IN-', enable_events=True, s=80), sg.FileBrowse(), ], + [sg.T('Original size'), sg.T(k='-ORIG WIDTH-'), sg.T('X'), sg.T(k='-ORIG HEIGHT-')]])], + [sg.Frame('Output Filename', [[sg.In(k='-NEW FILENAME-', s=80), sg.FileBrowse(), ], + [sg.In(default_text=sg.user_settings_get_entry('-width-', ''), s=4, k='-WIDTH-'), sg.T('X'), + sg.In(default_text=sg.user_settings_get_entry('-height-', ''), s=4, k='-HEIGHT-')]])], + [sg.Frame('Convert To New Format', new_format_layout)], + [sg.CBox('Encode to Base64 and leave on Clipboard', k='-BASE64-', default=sg.user_settings_get_entry('-base64-', True))], + # [sg.CBox('Use PNG for all Base64 Encoding', default=True, k='-PNG CONVERT-')], + [sg.CBox('Do not save file - Only convert and Base64 Encode', k='-DO NOT SAVE-', enable_events=True, + default=sg.user_settings_get_entry('-do not save-', False))], + [sg.CBox('Autoclose Immediately When Done', default=sg.user_settings_get_entry('-autoclose-', True if sg.running_windows() else False), + k='-AUTOCLOSE-')], + [sg.Button('Resize', bind_return_key=True), sg.Button('Exit')], + [sg.T('Note - on some systems, autoclose cannot be used because the clipboard is cleared by tkinter')], + [sg.T('Your settings are automatically saved between runs')], + [sg.T(f'Version {version}'), sg.T('Go to psgresizer GitHub Repo', font='_ 8', enable_events=True, k='-PSGRESIZER-'), + sg.T('A PySimpleGUI Application - Go to PySimpleGUI home', font='_ 8', enable_events=True, k='-PYSIMPLEGUI-')], + ] + + window = sg.Window('Resize Image', layout, icon=image_resize_icon, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_LOC_EXIT, + enable_close_attempted_event=True, finalize=True) + window['-PSGRESIZER-'].set_cursor('hand1') + window['-PYSIMPLEGUI-'].set_cursor('hand1') + while True: + event, values = window.read() + # print(event, values) + if event in (sg.WIN_CLOSED, sg.WIN_CLOSE_ATTEMPTED_EVENT, 'Exit'): + break + infile = values['-IN-'] + update_outfilename() + + if event == '-DO NOT SAVE-': + if values['-DO NOT SAVE-']: + window['-NEW FILENAME-'].update('') + window['-BASE64-'].update(True) + if event == 'Resize': + try: + if os.path.isfile(infile): + update_outfilename() + infilename = os.path.basename(infile) + infilenameonly, infileext = os.path.splitext(infilename) + if values['-NEW FORMAT-']: + encode_format = values['-NEW FORMAT-'].upper() + else: + encode_format = infileext[1:].upper() # strip off the . + if encode_format == 'JPG': + encode_format = 'JPEG' + outfullfilename = values['-NEW FILENAME-'] + width, height = int(values['-WIDTH-']), int(values['-HEIGHT-']) + if values['-DO NOT SAVE-']: + encoded = resize(input_file=infile, size=(width, height), output_file=None, encode_format=encode_format) + else: + encoded = resize(input_file=infile, size=(width, height), output_file=outfullfilename, encode_format=encode_format) + + if values['-BASE64-']: + sg.clipboard_set(encoded) + + sg.popup_quick_message('DONE!', font='_ 40', background_color='red', text_color='white') + + except Exception as e: + sg.popup_error_with_traceback('Error resizing or converting', 'Error encountered during the resize or Base64 encoding', e) + if values['-AUTOCLOSE-']: + break + elif event == 'Version': + sg.popup_scrolled(sg.get_versions(), non_blocking=True) + elif event == 'Edit Me': + sg.execute_editor(__file__) + elif event == 'File Location': + sg.popup_scrolled('This Python file is:', __file__) + elif event == '-PYSIMPLEGUI-': + webbrowser.open_new_tab(r'http://www.PySimpleGUI.com') + elif event == '-PSGRESIZER-': + webbrowser.open_new_tab(r'https://github.com/PySimpleGUI/psgresizer') + + if event != sg.WIN_CLOSED: + sg.user_settings_set_entry('-autoclose-', values['-AUTOCLOSE-']) + sg.user_settings_set_entry('-new format-', values['-NEW FORMAT-']) + sg.user_settings_set_entry('-do not save-', values['-DO NOT SAVE-']) + sg.user_settings_set_entry('-base64-', values['-BASE64-']) + sg.user_settings_set_entry('-width-', values['-WIDTH-']) + sg.user_settings_set_entry('-height-', values['-HEIGHT-']) + window.close() + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/DemoPrograms/Demo_Image_Viewer_Thumbnails.py b/DemoPrograms/Demo_Image_Viewer_Thumbnails.py index ae3225a44..c766fed2e 100644 --- a/DemoPrograms/Demo_Image_Viewer_Thumbnails.py +++ b/DemoPrograms/Demo_Image_Viewer_Thumbnails.py @@ -11,11 +11,7 @@ This image viewer uses both a thumbnail creation function and an image resizing function that you may find handy to include in your code. - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ THUMBNAIL_SIZE = (200,200) @@ -60,7 +56,7 @@ def convert_to_bytes(file_or_bytes, resize=None, fill=False): if resize: new_width, new_height = resize scale = min(new_height / cur_height, new_width / cur_width) - img = img.resize((int(cur_width * scale), int(cur_height * scale)), PIL.Image.LANCZOS) + img = img.resize((int(cur_width * scale), int(cur_height * scale)), PIL.Image.ANTIALIAS) if fill: img = make_square(img, THUMBNAIL_SIZE[0]) with io.BytesIO() as bio: diff --git a/DemoPrograms/Demo_Img_Viewer.py b/DemoPrograms/Demo_Img_Viewer.py index 213ee6b59..9df35c409 100644 --- a/DemoPrograms/Demo_Img_Viewer.py +++ b/DemoPrograms/Demo_Img_Viewer.py @@ -18,12 +18,6 @@ ------------ Python3 PIL - -Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - -Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - -You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ # Get the folder containin:g the images from the user diff --git a/DemoPrograms/Demo_Input_Auto_Complete.py b/DemoPrograms/Demo_Input_Auto_Complete.py index 5648f9326..ab0ed90a9 100644 --- a/DemoPrograms/Demo_Input_Auto_Complete.py +++ b/DemoPrograms/Demo_Input_Auto_Complete.py @@ -19,11 +19,7 @@ The selection wraps around from the end to the start (and vicea versa). You can change this behavior to make it stay at the beignning or the end - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ diff --git a/DemoPrograms/Demo_Input_Save_Last_Used_Entry_In_User_Settings.py b/DemoPrograms/Demo_Input_Save_Last_Used_Entry_In_User_Settings.py deleted file mode 100644 index f1971af7d..000000000 --- a/DemoPrograms/Demo_Input_Save_Last_Used_Entry_In_User_Settings.py +++ /dev/null @@ -1,35 +0,0 @@ -import PySimpleGUI as sg - -""" - Demo - Save previously entered value in Input element by using user_settings calls - - Tired of typing in the same value or entering the same filename into an Input element? - If so, this may be exactly what you need. - - It simply saves the last value you entered so that the next time you start your program, that will be the default - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - - -def main(): - sg.user_settings_filename(path='.') # The settings file will be in the same folder as this program - - layout = [[sg.T('This is your layout')], - [sg.T('Remembers last value for this:'), sg.In(sg.user_settings_get_entry('-input-', ''), k='-INPUT-')], - [sg.OK(), sg.Button('Exit')]] - - # make a window, read it, and automatically close after 1 event happens (button or X to close window) - event, values = sg.Window('Save Input Element Last Value', layout).read(close=True) - - # only save the value if OK was clicked - if event == 'OK': - sg.user_settings_set_entry('-input-', values['-INPUT-']) - -if __name__ == '__main__': - main() - diff --git a/DemoPrograms/Demo_Input_Validation.py b/DemoPrograms/Demo_Input_Validation.py index fbd9c824f..35ba89264 100644 --- a/DemoPrograms/Demo_Input_Validation.py +++ b/DemoPrograms/Demo_Input_Validation.py @@ -2,14 +2,8 @@ """ Simple field validation - Input field should only accept digits 0-9. + Input field should only accept digits. If non-digit entered, it is deleted from the field - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ layout = [[sg.Text('Enter digits:')], @@ -20,12 +14,11 @@ while True: # Event Loop event, values = window.read() - print(event, values) - if event == sg.WIN_CLOSED or event == 'Exit': + if event in (sg.WIN_CLOSED, 'Exit'): break # if last char entered not a digit - if event == '-INPUT-' and len(values['-INPUT-']) and values['-INPUT-'][-1] not in ('0123456789'): + if len(values['-INPUT-']) and values['-INPUT-'][-1] not in ('0123456789'): # delete last char from input window['-INPUT-'].update(values['-INPUT-'][:-1]) -window.close() \ No newline at end of file +window.close() diff --git a/DemoPrograms/Demo_Invisible_Elements.py b/DemoPrograms/Demo_Invisible_Elements.py index 098cef8de..c41acf8e3 100644 --- a/DemoPrograms/Demo_Invisible_Elements.py +++ b/DemoPrograms/Demo_Invisible_Elements.py @@ -6,12 +6,7 @@ were made invisible and then visible, then tkinter puts EACH ELEMENT on a separate row when it is made visible again. This means a row of 6 elements will become a column of 6 elements if you make each of them visible one at a time. - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + """ layout = [[sg.Col([[sg.Text('My Window')], [sg.Input(key='-IN-'), sg.Button('My button', key='-OUT-')]], key='-COL-'), sg.Canvas(size=(0,0), pad=(0,0))], diff --git a/DemoPrograms/Demo_Invisible_Elements_Pinning.py b/DemoPrograms/Demo_Invisible_Elements_Pinning.py index 3b95074e5..8e4fae74c 100644 --- a/DemoPrograms/Demo_Invisible_Elements_Pinning.py +++ b/DemoPrograms/Demo_Invisible_Elements_Pinning.py @@ -2,39 +2,36 @@ """ Demo - "Pinning" an element into a location in a layout - + Requires PySimpleGUI version 4.28.0 and greater - + When using the tkinter port of PySimpleGUI, if you make an element invisible and then visible again, rather than the element appearing where it was originally located, it will be moved to the bottom of whatever it was contained within (a window or a container element (column, frame, tab)) This demo uses a new "pin" function which will place the element inside of a Column element. This will reserve a location for the element to be returned. - + Additionally, there will be a 1 pixel Canvas element inside the "pin". This will cause the area to shrink when the element is made invisible. It's a weird tkinter thing. Not sure exactly why it works, but it works. - + For other ports of PySimpleGUI such as the Qt port, the position is remembered by Qt and as a result this technique using "pin" is not needed. - - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ -layout = [[sg.Text('Hide Button or Multiline. Buttons 1 & 2 hide Button 2')], - [sg.pin(sg.Multiline(size=(60, 10), key='-MLINE-'))], - [sg.pin(sg.Button('Button1')), sg.pin(sg.Button('Button2'), shrink=False), sg.B('Toggle Multiline')], - ] + +layout = [ [sg.Text('Hide Button or Input. Button3 hides Input. Buttons 1 & 2 hide Button 2')], + [sg.pin(sg.Input(key='-IN-'))], + [sg.pin(sg.Button('Button1')), sg.pin(sg.Button('Button2')), sg.B('Button3')], + ] window = sg.Window('Visible / Invisible Element Demo', layout) toggle = toggle_in = False -while True: # Event Loop +while True: # Event Loop event, values = window.read() print(event, values) if event == sg.WIN_CLOSED or event == 'Exit': @@ -43,6 +40,7 @@ if event in ('Button1', 'Button2'): window['Button2'].update(visible=toggle) toggle = not toggle - elif event == 'Toggle Multiline': - window['-MLINE-'].update(visible=not window['-MLINE-'].visible) + if event == 'Button3': + window['-IN-'].update(visible=toggle_in) + toggle_in = not toggle_in window.close() diff --git a/DemoPrograms/Demo_Justification_Columns.py b/DemoPrograms/Demo_Justification_Columns.py index a2d9a54c5..8ec3d6e46 100644 --- a/DemoPrograms/Demo_Justification_Columns.py +++ b/DemoPrograms/Demo_Justification_Columns.py @@ -5,11 +5,7 @@ Using Column elements to justify one or more elements within a window - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ col1 = [[sg.T('Left side')],[sg.T('Still left')]] diff --git a/DemoPrograms/Demo_Justification_Using_Stretch_Elements.py b/DemoPrograms/Demo_Justification_Using_Stretch_Elements.py index 29d129391..1acab1c9a 100644 --- a/DemoPrograms/Demo_Justification_Using_Stretch_Elements.py +++ b/DemoPrograms/Demo_Justification_Using_Stretch_Elements.py @@ -13,11 +13,7 @@ If you want a third button that is centered, then add TWO Stretch elements, one on each side of the middle one - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ diff --git a/DemoPrograms/Demo_Keyboard.py b/DemoPrograms/Demo_Keyboard.py index 77a09c501..f1acb3be4 100644 --- a/DemoPrograms/Demo_Keyboard.py +++ b/DemoPrograms/Demo_Keyboard.py @@ -2,14 +2,6 @@ import sys import PySimpleGUI as sg -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - # Recipe for getting keys, one at a time as they are released # If want to use the space bar, then be sure and disable the "default focus" diff --git a/DemoPrograms/Demo_Keyboard_ENTER_Presses_Button.py b/DemoPrograms/Demo_Keyboard_ENTER_Presses_Button.py index 919148a3c..2e7e5fc76 100644 --- a/DemoPrograms/Demo_Keyboard_ENTER_Presses_Button.py +++ b/DemoPrograms/Demo_Keyboard_ENTER_Presses_Button.py @@ -14,11 +14,6 @@ 3. Find the Element that currently has focus 4. Click the Button if the Element with focus is a button - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ QT_ENTER_KEY1 = 'special 16777220' diff --git a/DemoPrograms/Demo_Keyboard_Realtime.py b/DemoPrograms/Demo_Keyboard_Realtime.py index b858c4529..dd76c5e87 100644 --- a/DemoPrograms/Demo_Keyboard_Realtime.py +++ b/DemoPrograms/Demo_Keyboard_Realtime.py @@ -1,14 +1,6 @@ #!/usr/bin/env python import PySimpleGUI as sg -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - layout = [[sg.Text("Hold down a key")], [sg.Button("OK")]] diff --git a/DemoPrograms/Demo_Keypad.py b/DemoPrograms/Demo_Keypad.py index f4011135b..dc9c3751d 100644 --- a/DemoPrograms/Demo_Keypad.py +++ b/DemoPrograms/Demo_Keypad.py @@ -1,14 +1,6 @@ #!/usr/bin/env python import PySimpleGUI as sg -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - # Demonstrates a number of PySimpleGUI features including: # Default element size diff --git a/DemoPrograms/Demo_LED_Clock_Weather.py b/DemoPrograms/Demo_LED_Clock_Weather.py new file mode 100644 index 000000000..59686011a --- /dev/null +++ b/DemoPrograms/Demo_LED_Clock_Weather.py @@ -0,0 +1,165 @@ +#!/usr/bin/env python +import PySimpleGUI as sg +import datetime +import calendar +import forecastio + +''' + Example of a weather App, using: + - DARKSKY + - google maps coordinates +''' + + + +##### CHANGE these settings to match your location... check Google Maps ##### +MY_LOCATION_LAT = 35.0 +MY_LOCATION_LON = -79.0 + +##### You need a free dark-sky key. You get 1000 calls a month for free ##### +# *** INSERT YOUR DARKSKY KEY HERE ** +DARKSKY_KEY = "INSERT YOUR DARKSKY KEY HERE!" + + +# Changes number of days in forecast +NUM_COLS = 5 + + +class GUI(): + def __init__(self): + self.api_key = DARKSKY_KEY + self.lat = MY_LOCATION_LAT + self.lng = MY_LOCATION_LON + self.blink_count = 0 + + sg.set_options(border_width=0, text_color='white', + background_color='black', text_element_background_color='black') + + # Create clock layout + clock = [ + [sg.Text('', pad=((120, 0), 0)), + sg.Image(data=ledblank[22:], key='-hour1-'), + sg.Image(data=ledblank[22:], key='-hour2-'), + sg.Image(data=ledblank[22:], key='-colon-'), + sg.Image(data=ledblank[22:], key='-min1-'), + sg.Image(data=ledblank[22:], key='-min2-')], ] + + # Create the weather columns layout + weather_cols = [] + for i in range(NUM_COLS): + weather_cols.append( + [[sg.Text('', size=(4, 1), font='Any 20', + justification='center', key='-DAY-' + str(i)), ], + [sg.Image(data=w1[22:], background_color='black', + key='-icon-'+str(i), pad=((4, 0), 3)), ], + [sg.Text('--', size=(3, 1), justification='center', + font='Any 20', key='-high-' + str(i), pad=((10, 0), 3))], + [sg.Text('--', size=(3, 1), justification='center', + font='Any 20', key='-low-' + str(i), pad=((10, 0), 3))]]) + + # Create the overall layout + layout = [[sg.Col(clock, background_color='black')], + [sg.Col(weather_cols[x], background_color='black') + for x in range(NUM_COLS)], + + [sg.Button('Exit', button_color=('black', 'black'), + image_data=orangeround[22:], + tooltip='close window', pad=((450, 0), (10, 0)))]] + + # Create the window + self.window = sg.Window('My new window', layout, finalize=True, + background_color='black', grab_anywhere=True, + use_default_focus=False, no_titlebar=True, + alpha_channel=.8) + + self.colon_elem = self.window['-colon-'] + self.hour1 = self.window['-hour1-'] + self.hour2 = self.window['-hour2-'] + self.min1 = self.window['-min1-'] + self.min2 = self.window['-min2-'] + + def update_clock(self): + # update the clock + now = datetime.datetime.now() + real_hour = now.hour - 12 if now.hour > 12 else now.hour + hour1_digit = led_digits[real_hour // 10] + self.hour1.update(data=hour1_digit[22:]) + self.hour2.update(data=led_digits[real_hour % 10][22:]) + self.min2.update(data=led_digits[int(now.minute) % 10][22:]) + self.min1.update(data=led_digits[int(now.minute) // 10][22:]) + # Blink the : + if self.blink_count % 2: + self.colon_elem.update(data=ledcolon[22:]) + else: + self.colon_elem.update(data=ledblank[22:]) + self.blink_count += 1 + + def update_weather(self): + forecast = forecastio.load_forecast(self.api_key, self.lat, self.lng) + daily = forecast.daily() + today_weekday = datetime.datetime.today().weekday() + + max_temps = [] + min_temps = [] + daily_icons = [] + for daily_data in daily.data: + daily_icons.append(daily_data.d['icon']) + max_temps.append(int(daily_data.d['temperatureMax'])) + min_temps.append(int(daily_data.d['temperatureMin'])) + + for i in range(NUM_COLS): + day_element = self.window['-DAY-' + str(i)] + max_element = self.window['-high-' + str(i)] + min_element = self.window['-low-' + str(i)] + icon_element = self.window['-icon-' + str(i)] + day_element.update(calendar.day_abbr[(today_weekday + i) % 7]) + max_element.update(max_temps[i]) + min_element.update(min_temps[i]) + icon_element.update(data=weather_icon_dict[daily_icons[i]][22:]) + + +def led_clock(): + + # Get the GUI object that is used to update the window + gui = GUI() + + # ---------- EVENT LOOP ---------- + last_update_time = 0 + while True: + # Wake up once a second to update the clock and weather + event, values = gui.window.read(timeout=1000) + if event in (sg.WIN_CLOSED, 'Exit'): + break + # update clock + gui.update_clock() + # update weather once ever 6 hours + now = datetime.datetime.now() + if last_update_time == 0 or (now-last_update_time).seconds >= 60*60*6: + print('*** Updating Weather ***') + last_update_time = now + gui.update_weather() + + +led0 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAAEb0lEQVRoge2Zz4scRRTHP/WqunsDSQjiBvFHSBC8eRJRFAXFgCIYRVBPgrkoiBgU9U/w4iEgHjwEBT2IKHiIiBfBg4oB8SJ4CgHjIXpSE5Ls9HR9PUz1ZGa6dnZ2dmdnlXzh0TPV1a+/9erVq/eqHSB2GWzZBHK4TmpW7EpSIdfokuwE4jrv12QDk40LhNElNmapluFNZtws8bdEsQCCrb69zvEL0FP3DQLk0nUf6P6y1A8hSKAeKG6jNEmnQG8Xhe5cWZE5p5ZHy3mM1GHQz2Z6YGVF33ovgeqkZDukn65vVpVeDUFfr6wIM9k0UgdBa6DfvNc9VaWvErFeGuW80h8Z3Imi0PGqkkCny1KYyY+Q6qw+A64AtzUNn0k8GwI9M56oayLzxxABzjleCgFvxqleb3DDddd5NiT4dL01Rr6oa54pS9aKgqMSl+YgFoG9wFtm7JE42evRkyjJh54sqRZ9YFXi07rmLjMuJEWbXY0B+Ac4Dpysa2qmD6xDavSFnsEoVyVWm4bzEg35gLcRKYA7wuDXRsE561M28R8GVptFYQ5t/yYTj6aSagPnJKlJDNfsJtD2n3Uw3fdnVsNOo0PKwdKJ/YcstSDM71ObeHhR6FpqN04fsHS/2lGfmhU76lNbcvRF5eez7pkbOnpcr+McaPe03KCV6TdsvApccY4KqIESOGvG7yOb6bzT+6MEZvgYqRlkIRdTojypc5iGtnnysbLUFTMJ9Kv3OhLCIGV1Tm5O8c4JMz1fluon3WdC0KrZWDre2kc5Yk+GoJ+KQoeKQjg3mdjPJQGE9zpeFPq+KHRDCDlC6hSjMJjT6BzmPcSIYqSZc8omUQDRDOccagZaJ3V3/NcYJHT3ec8nzrHfORqzbXP02jke854PzSicoyHvo52pu9d7/ZlKq++81w1FIcw6Zt6MeBBmejQEXUw+ddp7VdN8qm280XtdSISupjrtTAja5/3At+Zw8uCccE5Hi0I9M8UR3aeqSjg3VvcNZ6U14T7nOJCWf8lgvu9uGm4fqXO1SWmfe9iMIkb6XItFtwA4N+bYHVfRxBy3NeCsSf809JOOUf2tk4+2zey/25HSWEZHTuvST/Jy9l86qRyWTuq6pWaFMqt6+aQybUsnlcPSSf3/LLUdxUTOqXN6px4vAsPD17bjVg7NQtpmRvfX4YY9K6kmdTjrPefSg3FiR58FbUV0JkZwDpOm6lj3g5HSzfPe82JR8EFdc8iMNTZvqQjsBz4GXi5L3kunw7C+W4xlnYdDGFYyfzinB8tS36Skr2H614Rp0j77elXpRDrYF+jzVJhkk7xRhgG45BzPlSWvNQ0PNQ29dK+ZU8Qg939nbY3LMfJGOinuzxLRA3DZjKfKkhdi5FjTcJVryd5WUQPv1zXnvOfdEDiwTr+xHP1ICHp6zx59lKasv4UpmyrO6ZWq0uNV1Skcxuq+9s9BMx6Jkb+20UKjiAzy/55zfAmdkJAtRrONC8KGX0ZHsQgL5ZCrvHfSKDNjV27I/wIpihClbBNQxAAAAABJRU5ErkJggg==' +led1 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAACD0lEQVRoge2Yv27UQBCHv9kkRCAhXgAkSh6AmoKCFFBENLwBFQ0PQIPES0BJky4NDR0lJT28A4ICQc7nH4V3FccZ+9zcrAv/pJVP3jntp525+XMGiIUp1QbwtELN1Qo1V1WhLK+hqkEVIC8fVYFKdDB3gLvW3ZUN9qsAmRlnKfEoQ6WBTShQCxybcW7Gk7blt2N3GAVkGegmcA6ctC0AB45tyE2VgL5txifgROLfhH0YFMBH4DGwYdpFIVBtft5XlwA8l/UVGujtbhMgGMrL3p7W2rcrlor2DtV32dHM7+wdSiOfp7TG1FytUHO1Qnllpko7bL3n3N4pJE+VFvhLftf09n/Kz16KXO/NJJBAr8wEKF23i4GxvDDTh5T0OqUxII2NXntRiavGDJM4pOtChwqfZhrgDfDCjA3jnUOY+zDT2xxTf0Gnea9KTJVD36UkgS5ALWgDeugEe+jg8DTPegnY0k009/JetbF92wMoEFu73rmHB/oVOUCuXbS2zrvqUF6RrgIlLmPKy9zrTXlaJNQi3bc8KGmBUCwgphYzOPRVeqdd/1OFQJVDvuVa1y8tcgaHEKhy7EvgsxlHXE401dxXysqFxHO6UevGhH1YTCkf9kfiFPiaXdk4tuG/vgT8Ap4B31PilmMXOmIVHdAF+wMzGuCHdAWkClQ5mJHDq2X0/q0MVe2mplS99nlaJNR/DW4BrSasyZkAAAAASUVORK5CYII=' +led2 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAADmElEQVRoge2Zz4scRRiGn7d6NlHJQaKoKHgwxGgiIpiTegrI4kEUkdwEQcRF8pdI0INIrorkoqB48SB4EhQUvSoIIkjixaiExdnNTtfrYaqyPZmamZ6e7GQC88JHM71dVU999ev7tgSYFVO41QAlraHaaiWheqWXSrYMxQnt39LVVwLolT64T+Jem22gOgAQM5w3hyV+8bhPisN3GPhU4qTNf5M+WgBIwCFgS+KqxKU4Oohj3ssvHpL4UuLJGKm5OR7LDQl4NQQeBp4A3oiRCqjT38dWX3btJZszwA8SFbCXCnW1AfteerGqOCLxboz00/A1F1ZxS4gMPXMlRjaB7yQ2UsGqgwWGU0DACxKPxMiHdT0GkzVxutSpsn9sNiU+riqetulP6skM9YA303Q4b7MD3DEvFAw9JmDb5pU07l3UA/rAOeC8zd6MhmcurDwPSJV1UZ7gpwrzpxNUrvQ6XAflcqXdu6S5tqCuW39zK2ijlTyQ11BttYZqq6VCSe3W39pTbbWSUK139EWSidzz0jFTOiVaQYVUuO3ZdaNyuRxlNM/RuUOXDBSBu4GjDOOseT3WA/4CvgbeSnA5fPl3QhlPspCexyX/KjmC++DdOa0PNnhL8supHoM/l3xIMmCNtl0GqtLz8RD8u2SD61RZF8sgWyH4tRB8MQRXZaAyVAaS5O8T0G6quKvVqQ6DXwrBgDfKQONQecjOSH5P8mnJlxue6go1SEDvSw6pnQlAo1AZ6JkQfCVV8kEIfqyqfDkEW3KU7DmtTs93koemwBjw9dWXV9mDEl/YHAV2gbdj5M4QOC1xXOoUpwu4BvwUY+uVO+KlU8kb2e0Gb4MfyPNsRi+n2YwhG/dUVt7omvl8c2+qGu/nVT37E6CweZaOkyZIvQBUW63kgbyGaqvbG+qgJ3dTt7enlqk1VFu1guoam3dVq8Qh/wMW9pOILhLtzr+pUANgA/hR4k8Am7gAFOyHSJ2g6gbQuRD4LEbuSfHUvNlMBI4AH0lciJEeww5P00g8dVLyIIW/P4NPhOBvQlg4ccj2eoo+e9NjqlGoEyl0/U3yoyH4q0biMFjA9nKnJJ9NWcwUsFGopyT/EYKPVZU/SUA7qcJFbS8BXgNvJo+FaVA5TD0m+bmq8sU0ZDkLuVmWQ+wdyc9PABu5xco/7geeZZhSH8R9Xw3cBfwt8a09dpVWvFrjxpdLVvG6Vizn/DEreodc0koeyP8DbP/uIBO2okgAAAAASUVORK5CYII=' +led3 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAADoUlEQVRoge2ZzascRRTFf6d7TCLBaALiImAIRoObJzqu3JiVCzH/QEACLlyI4sdCiArqwp2gG/8BcavgB7gRsgquRRBc+lwEBTExEMzLdB8XVTWv01090zPznPcgc6FopvtO1al7q+qee0uAOWBS7DeAnGxADZUDCWrU92EdaE1+l6nn/dokB2CUUzguccLmJlD+D0Aq4BBQS/zurk267pM4AnwFbAH/ZJVWB1QB54GbwF/cabGO9UqJSuJUXfMDcAao2Zs15jjgBHgWeA44DFwiTHwS9TpjVTalzW8S54Cfo9JOnN2y7XYEdAN4WuIJ4H2CJ/omMG2KzxKM5OOSr4ANruJz0VbH5zXwGcmvN769G8cbNTB0lksycQWUNn9LvAB8ATwK/Jsz7wxx1K+AF4ELwIexnyNxrLmWarcCXEgzdea1ZIV3onV2YjP4vYyl5k66js9VFnraSY8r2EX0WwgG7va+k3eoJACTmVq7stbYV2YOypwcyIB894Jqho8hcvdaalHZgBoqG1BDpRNmJOHWyZuYw9At3ZaSwBLqzLfcGT8o9pXxz7lOh0g1Y7BcDpAF1bRWmuWx2JYBNgL+BL6XuGBP+RrA1dz4ZCyoRDFsaomzwNc2pwm0eBE3JtePgOcljgLfxAl/ArzVAyJLzErJFIXH4KstWrssHTb4PPhl8Gct+t1q3ZdJ8RD4p9jZrdj5sm3SaFux/8M9oLJHggmp1k5R8ApwjZCrrUr0SuAl4KTEm8At+s+krqUkSwoulPwM+PoKLkz/uQg+1+Dnr0XuX3Q9lV/o090nUQEPAw8SKO2i59UI+APYsvmOsIMr4B7gIvA5u7s86fcCgpicxpx/e0EwTVAT4CMJ7OngAKfTuC39uVKz2ome1k1KHJr93M7oD65dLHuaN/+bW9RD3+27bEANlQ2oobJWUEPD1MZSQ2XjvlxUyL0bFGYSF1qWT5WEuJcb7Ebm3VxLNYPpsuXqFIh/zBTNFk6xSqCSeMTmYylcXbA4W6iB+4APbN4APiVUh2cN3mGdsFtHPwn+lb2po++An5J8SZp+e5UhdXQ71L0l7ge+BR4jpFYFy1MYE5jmZZuxxAPA2+SLsx1QhUQtcW9d8yXwZAS0F5dGE0JCe8VmDJwCTsyYxG5qVRQ+Kvnyii6b58pt8FjyWe5M62gnDunHQ8AYuM7e3/eJQIGPAdvAL3Qz5H29GU27uA0gX+BgfXfIuY2z73fIOTmQLOE/hw5ngBNVOEQAAAAASUVORK5CYII=' +led4 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAADdElEQVRoge2Zu4tkRRSHv3OqukdFxd0FUQRdxESMFgQDBWFBQ/P1LzBREHSNzAwNRPwbVkMDQUMVdIKNfIAYimAgsivjY3fsufUzmKrZftSdvn3t7tvC/OBw+z6q6runHufUbQPEjsmHBqjpDKqrzqC6qgq1TdJaW9X21XZjzXIgtVyf0f3uXAyBBIQtAF0ajYhmC/cFyPLxwRD0/Xisp0MQoJivr9MiCDO9HqO+Go+F2Un72WahHghBN0PQgbueyWCjNQKVul4JQTLT5zEKM/lpUOdD0K8xSqDfzfScmQCFNQCF7KHX3CWQQF+MRsuhLoSgGxlKoD/MdDlGAfMFVzLPQFdz3Ye5/i+7eOpCCLoRggSa5IIH7nrcvTdY8fKV3GWTqbprUAuzz7gzJQPHM+S+lDif0sn9VVXKPJL9ryX1VKFq5+vIb8qatOzFqlC1Qn081LeOzlDbVDWabAqqa71xoaA2mB1XwklN/5/UZWgtQm2y+zqq7qkNgfVeEnZBOwm1sCQox6Y2TcfGrirP1+qtXVuAcmb7vqTF0zGwllefpvJ8Sa81BeqVtWsB6hbwpxn3SkyAMfCDGb+Z8URKOKsH5wAcANeBf8wYSxwCe8DNlkk1m4iBLrvrwEwCfWemSzHq63w+ATUrWsmd3nPXCyHo73z+jbseypltNUefB3vRXfsx6vnRSPs56WtyZX2slH0/Rr0co/Zj1MM5cZwDWoQqYA7CXZ9loNug9B/tVgZ7KwThrj3quX91IiXyQEyJqynxszt7QFN7g47WAHcB10LgW+AaMDKjob6onp7sg550108xSu5q3KUVrZT5MEY9Ox7rl7yb+dRdd1e60Eoftinkt3w0BJ5yZ9LyZqfJgb8Al/g4Jc6lxO3suY9i5ErT4NLMUtNpe1QZjJ2t7LLfyB46nBr4+3k3Y7PPL1cZY31jUgCOuLOITq91TT5Od1knqALWVzZ3XKbBA3KnT0Hbliqxb3ioyrXBoXaz+yrXzqBq2kmoszFVU80rg0PVdjXlt1We26hKwz+agdlMQB7MU01u6JOUeNXsJEcbFAry/lHig5R40529HPMGH1MNx7nSuxJvx+Os6aiy7+ucT61LDRAl3jk64mIIPNbyda93mtvXSup7D+il/DfI3P21fCLvpc7/921TagEY1FNtGjz21bSTUP8C1hqqTm9IJgsAAAAASUVORK5CYII=' +led5 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAADyUlEQVRoge2Zv4tcVRTHP99zZ6NEggg2iYgWpghKEGNlYaGNYifBgAGbNFaCkCJ/haAiiGDAgOkFKxtttrGKFlaCbJFlwVVEo+5m5t2vxdy3+3bmzcybmXVnA/uFw5v35r37Pu/cX+fcK8AcM8WqAdp0AtVVxxKqN+mPo6I14z1NLdfaLx6hWj0VwLMS/9iYIeRhawCcAbYkfrXHHFF70CrHsxG+npIN3gX3wYNDtB2wwXcifDalA+8uv/cBE1ABNyXuSPwlcbOqyMVbh+GxqrznB4nXgC2bkMje99OB9ly/dAB8mDODnHlHIoBcCsxLWL8ArUfwisSWTYIDQGNQo3C3bE5LvJUSSSKV/2IBA1gDvpV4Hfg9572aGa2BiQ0dYBf4NGfeS4nLEXxs829LIbOUgdPA9zZXgb9zJgoQjPf0ieNUDdcHPqoqrqXEuVL4YE6oWgPApaflKfdNhWr2gvMSVBX3l4Cqa2DWGNgKJWnYaWk0/sb5or2wbfTuDNWm5lf+36P91N63Kh3LKOHBgTqpvhaNQ0lDW6FOqq+rjqWnOo/o9QTaDEXm1ULTTP2AGscaJjXgps3w0xQjZXaCEoDNn+V8wDAwQ2IdeBx4jP04qKvM8KO2Jf6w9yLZWc8cCN7PSP4mwgbfB7+Rkm+U8zqRmMd2S6Lwk+SnSqIQjfe22MELNdjDEf46wlcjfEOywVUpfBGrn/05whckA+51harB1sBIfrukWjvgvKTVHluXjGRN9lg7bUhOkk9F+PMC1i9fvIj1C9AG+MUIf5KSX4qYVJXtUCpfApgIfxZhS64ke07L5XhX8nOSb5fmsBnhF1rA2tcSJDwSDq9JXIqg1/ZAB/WAX2w+sHnTZhd4CNiUuAj8NpK6T+sFe20slca5iNVeOM8wbW+2sz74mZH7Oo3oZjiupFk3TlA9Lpn9tN3s18Jced+o5h00azWrZHSKaptnH5woYdU6geqqlUNVjK9NrByqLT5bOVSbTqC66sihDn19atF1qXru63Usp5On6kXTRZeq6zlzA/hRQkyfR2d6KgGVxPUIruTMva5f0pCBU8AmcC2CL3PmQtlimfZMq/VKnP5+yWQyyycO30m+mJI3SvR5D/zkSDzVDiXtAb1bgOp0aZk9mTpx+CrCz0d4G7wr+VwJIKdCpQJ0OSVn6VCARjeLvpB8KcJ3I/z0LKgoQFfqwH/JamuzQTneivDLvZ6fKFB1ojJxv/FV4BFgh8XD4GmqgEcZ7tVsjyQNq94E3Ru3mhBT95CPYp2qTiiaWrmn2nQsJ+T/AHYfURS2h8j3AAAAAElFTkSuQmCC' +led6 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAAEBUlEQVRoge2ZP4gdVRTGf9+Z3c1qZJFUChJWLBQigmLQiJYhIkQLwcLWwkYrGy1s0sRC0gQUIljYWCRaaKONJoKNIoJKwEgaBcEuJuwmu/vefBZz7+68P/N23p91X7EfHGbmzsy935x777nfuSPAzBlivwkMwwGptphLUgvDCv8vpmVDueibfQMF+4BtT2UyhyUeBP61Kfao0RK4B7gO3Gl4xtkOgY8WhT+RbPAaeGPGtg42+EKEkVxvv2ZY6WJJ8jcRfjrCFxKxTqpkFpbr+qAojGTV2m4kheRrEb4l+VhR+FyEnb6wM6VtJkLnJCM5mgn1kpLk3xKRG5KPR/i95LHuFB4q0/Fs6rJiNCEPhIQ8uFdsrticjGBD4nXgJuOHizyoz0ucLUsWbLrZHQ1Q8hQGQuKqxMNlSYdqaq5LHAeuAodoji27YQsIu9X7g8HT1TcE0AHutllNpDpAd0JSxRjvDpBS7Tx3Vad2T0yGcTzcQ2q3Rrenxh5jLhfkHlKyJ+6eWWLQU97v5XgIqbnz1DSza5aY/4E+Lzgg1RY9EX23iB273B+FcVaDgWWmft5NRPJDJZOrhNwlbYj1kNoCbkpgs0klVf4Erkk8YLPYstJ+CPhbYiOtGG3qMOBIx2OS/0pK8XfJj0T4UlKft0ckBE12O9X1qeQiJQp1pQsNcrif2GMpgXiiKHwxyeNp5HB+91KElyNcgKOZUC8pKn3sJaok4sOah8opLXvsTNLpi6N1+qCnjkr+WPLjki/XUq1JCeXU6mKEn4zwR5KP9HXlUFL55n0R/il12ffg1Qh/G2FL7kr2mJbf+SzCq0XhX9NHXpa80kBsYDJ8J/GczR1gGfhR4hWJ+6WJ4pSoZvUtmy9tHqrV/XkEL9tDE4qdDBl8nZ1cbSudP5/uF81jYFQOZ8CvJu9v1gb+D2l89XuqJ07Vg6PZCXi5bJINj4Iq8cgernu7KRAPRPRRi2GX8VMs9R09pKwfc7kg7yuppklzQKotDjzVFgeeaou58FR/EG1Faha7C3lJaZOBD/0NUq8ogKV0PYlKyF+dG6ovM2OTKtPNfyR+AUgbqONmM3kX8GdgDThMJWUKmj+wkdQCcEPixQjeKkueklhjst3hFeAL4KUIvirLVnVs65lF8B9J66yDT0T4fNJB0/x5yPrp3Qifiti+vpL0VJbh2XpI1/v7lMRp4I2yZDOVdSc0U3XZmbLkUZvTRaXM3LBBF/0XAl4oCk4A75QlG1RdqSktgE3gfZsjNq9FcJe07YyB7st2L/jZovDbM8j1mqwEW/KbEX4mokrndkscliVOJnHfZvqOC1PNvAL4muFKdoBUMPkmxrhoamvofsNe/RHtR5Pen4dfxgOYS5XwH7eZhqnTFNxUAAAAAElFTkSuQmCC' +led7 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAACtElEQVRoge2ZwWoUQRCGv+ruFRPx4iOIGPEuETyLGDH4AqII4tN49KQg+AB6jAjiOeBFg5gHEA+KHiQmJpme38P0hN3ZSZysm949zA9NQ2/t9LfdtV1V0waIOZObNUCbeqiumkuocNgHuWjF+D/NWsayylI/DHHoSi2ZUUgUTH/VDNgHzgK/zPgijazOGJQDSmDZjOdAlIhTBiuARWATuG/GjsQPRrdNzeZSfy8ERTMJVII0hRZTv2mmJee0Brqe5vNDLjYGBSikftVMuwlqPz100raXgDa81+XBQK+9l0BXukIBGqT+pnPadu6/VqxeoXXQee/1Lj1PoKsNqEMdHSpnDMBaWXInBJ46R6DyOTvqiw2VwAKwIfGwLHkRI9fS8wct9kdCAQf/vjdFwUXvCUx2hhjwR+ItHAAdNvk/oaD6pQ7Yi5HdCYEEnAEupDF/hH0nqBrMON62NaFKIHaw7wwF0zn6u/youQzIPVRX9VBd1UN1VQ/VVVmh6lDTNj6srFCO0UCsofGm3YlLVDFvG1i3KvoVaUxm/E5janznxJul/pSZXqU0OIIemAmzg7qgZssCNQLmnF6GoEdmI4XKkF3eYtSlFp0DiSCx32KTTXUuVQCPgVWqtLgtC822fYAw05NUS26Z6XYIbVuY0Z/M9Cw5+S5VebXjnC41fOtY6fCkqh13UeJGrLL0ulQ7XZacG7KDzD7VLBxqiGYxkd3R2yZsFhN9QO6qHqqreqiu6qG6aj6gbPT4zF44dEneshcOYxPa+Bur7IXDR1dNORKEZ7l9AHfNeO89A6oMtE3ZoJQm+xkjKxIfzFpfV2eFgiqf8sD3smRF4nMaj7PevpjAvgK3nOOb9yw0bGZ23+epAJdDYAv4VBQHN2gzvYRsu4CEGZ/o9VHRPKlmfl3bpvmIfQ3NJdRfFS/ZxKoPEs0AAAAASUVORK5CYII=' +led8 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAAEi0lEQVRoge2ZT4gcRRTGf+9Vd/VkIRjxIqggJF5E8JSDF/EQjKAICflDQjAnUdGD6EEQDHrRmwdBD6IIweQkiiIevOTgKSAiiiAiBDxpomhiJLvTVf08TPVkZqdmMz272Z2FfPCoobrr1dev/r1vSgBjwaBbTSCHW6RmxUKSKnKVkuxmw8ivMlld35LZjCU5ra8JUgD3qyJNQ5+bM74R2AGsqPJL02RJGGCSyru9t5NVZf+JmIEFsGYDrQYzsL9U7diOHXavc2P9AzYMhEvlURH2x8iBsuSaKi69KRtgxmAS/y3CwbLkZAg8FuNY/5AZncvAsRA41DQ86T1XRFAgAM06LKTOflflibLkuRjZX9f8I/klZYAVqXy2qsxSiM+UpT3ivV1KQ9mk+q7WtvvNOXuoquwL54bPToiM9Z9+57EMHK9ryqLgcFnyoRlLZkS6bRcGlMCfwDPO8XoIPBojy0BvSpsJUjLyoAYOh0C/LNltxs5EqisUuAp8mQjVieg0TI0UXJ9896lCCFyNsfP+1U5wBfaM+G26kBodmpZAYzbxrCuxBmaO8pqRGnUK04+FWTHrR01sCZtx5t0IC5klbI9ILSSpjYZM+b0WNi1Syvihe6N3Fw6bOqcWbvi6YKYdvT2nlO47envEqMjAj417yPmbIJWbZC4lYs2cpNrjKec7NzITpK6YgQiNGcJgxZwz43Yz7mSQQXZFAfwhwjlV9oRw/WAW4V8RMMsLh6GJ2HtFYZayzTe9tyPeDwVEAIsdLKQM85qqPV5V9s5I1vmW94bImGhgICImdZ+J8EFR0Ae+UeVMv4+kr5lnIbTtVkQ4WhQcEuFi0/ByjEO/uTajLM2DoWoPem8rqhY2QGq17a+o2p6qMkTMr5JWUyOlQCPCKeeIqlw04/0QhonePGgnuQAnvOcBMy4Bb4eAmmWz0LEoIWKnynIw7iL2Qlna096bqVqjatbRRtsc895e837gW9WeL8tWfOYj5Rikq8erijN1TZ3kdAG8UpZ8JcI9ZvTprmYq4IIZJ0R4NQTqtLILVfaL8HWMw/7HItXqrpeS7qtHVs557w3nsuN/I5OR8ufkL3Jdvj+VZPuaui83d9ovaCX8PDDye1yuv0k1k5HR7U4c10Fq1M8YMqS2R+qy2YiLFKl2kuQE6pZHKre9zERqs68ktjxSOdwiNSu2L6mNmuhr/VE2ipnUjKajZ56sc6hmpnRmKUcf628th+2XnY8RzBARrKM1IgN5pcq3xYDW6hRlNaZGKjD49/Z0UXBOle+ahmWRucWqA153jiXgQAgspzoykZpKqgd8UpacLQo+XVlhqWnWLRxO9/scLAp2Ose+GEFktki1Oc/nzvGuCJ8tL7NkRpiTUIsGuMOMszFy1Hs88HCMBJ2cQRM1twHfO8cbzvFxXbPLjHqdhNqO+sBdTcNHdc2LZcmvRcHOKe+PJe/7ej070uvZhSQa5736mGYxlT+q2sFez/YWxYR4GJNYrRDdC+w24zIz7hkdIAxuMnYBP6nyQ+a+b/vcjLbC8WbDyO/yWVJbjYU8kP8HKX/sOnQ6GT4AAAAASUVORK5CYII=' +led9 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAAEYklEQVRoge2ZT2gkRRTGf+91VXeQJcp6kAVBEFn/ggh7ET0IggjBGBNW1+Bpc1E8uDfPIgqC4OLNu6IL4oJ48+RR0LMXvQgii4d1E4PZdFc9D1M9yWRqJjPpbGbAfFBM0l3d7+tXr+q9r0oAY86gsyaQwympSTGXpFzuoqR2p2HkZ5kcvN6SOYkpOcrWECmAh1XxMbIDFHeATAQqIKjyS4zZPgaYpN9zInapquymqhlYDRaPsTVgBrYlYm+UpT1YlgP2AesHeuuRJTPWQ2CtLLklgks95RiaJTvbqqyWJa/EyEXVAfuQmX03gZeaho0QWPaev0RQoEluP2prkrFbIiyXJZdCYLVp+Nvy0WuAufT7WnKvgV0vCnumLO2PojBL7rcjtPa5G6r2bFnaV973771dVQP209957AArIbAAvO49n4lwFqiZbrkweuvOlggbIlwJgbUQ2AEWRjwzRKp1pk8EXgyBWoRHzThDbyimRQFsAdeAtRCoc4bHkWqDrA1KgIdiRMz4xyy/hkwCVc471yc57uOGSDmR3mjvQ2BvBsL0q70kEmFEUB9KKmew6yrfPjdpoh3uJyeR9cZjiNTsKZ16anLMZZE37Kl5HL55wGlMTYrhvJiJqTZPdfmCtq46iFyWGJmQc50iI4r6CZGrDDTjhH6/1tAmgAhmRkgkf1DlbIzcZ0ZzRDI3gO9FeJJegifZ2RwnHGiLdxH7uCzNRMzArjpny2VpO0lINGBhitakyrMWsVXv7aOy7FWdIvap94bIgGhIPIZ1n6nySVGwKMJ3wLW6xpsNlC/ToH0uAutVxfNmRDPeDAGJMRsOB1n26+XHqsq2i6IvjbpKqwD2r6o9UVWGqpUHpNVIT7XecqrUIrxTFFyta+IxeEpF2PCe+4EmRj5sGpTRs3KgFUVhImIKhnP2lvdmqhZVzTq0y1VlV1olI2LvOme0dsZ5SpM4jGlWFCIEVS6IcK8IzZTeMqAEfhfhZeCD3V3qdM+LcNF7vt7dpWBvVmZFRdw3TYMZzoyfY8QmrLGzUOXzJBw0kcWMc8kJ+z90nNLZI0a31VzoKeQmfdT+4cmJiYlItdO56/bQ0YXDHGAiUp1i6bB3Z67N3FNzSSqHmZOaS0/NjNTYDJCZRP9fT/UxoaY8UVIxM1QTCYccNNXsXVFkPHWk4VMgivRyn8iRWrsV8GP6sLDfwKQJuc3iDmhUWSoK3gd20p7ntDB6xx7vqbLoPet1zU56/yj/D1R9qrq3r61qz3lv20nJdN1H31K1FxYW7Bvn+vcuO3f4PrrR24xtRLjgHNebhrtinLrizL33TIx8efs2K95TqrIUY78K3Y8hUgXQiPCIc3wbAvfEyC7dT7ME2AXOmvFF07DiPQ80DYvjjkFo5Y6qPe6c/dlxyA4byt+Kwl5dWLCnve+FzSjh0P7zlCrnY2ST3snDcVZTQu8k427gVxF+yhwYdNmv6IxR+/PZJUE5mc0zIy9EZ+qpUZh5lZDDfw9J5SDpQQEIAAAAAElFTkSuQmCC' +ledcolon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAABdklEQVRoge2YQU7DMBBFn9MEVVBYcADEmiVH4BScD3EL7gIcAYEEFSQdFrZRCJGYeBa1qnlSZSuVJz8/k/EkARAqo9m3gDlclBYXpcVFaXFRWlyUFhelpUpRrWVxAFaTYwIMlqApbnX9VJFT+UpOgRugA3ZE195C4EHE7JYs/TVpvAJ5BxGQPo1PTSObEASQUBA7xS/nE/hI8+yMEJ20YBK1G81zwnfWoKXr85MxAF9p3o/+24tT45N2k/EYOLIoovDpy069AvfAOdGxDngR+cmzUg6nTv0XoJ85toQqnapyQ3ZRWlyUFhelpUpR5oo+1xFYq3GVFd3Uo18Cd8CGuN+tgcem4VaErUjxFZtErYFr4ITY8K2AM2ILsy0JnDD36Pnk49a4mh49B2qtQUvX5zzZ8TdnVqVBR5jWD/x2C6Ko6av8UkwloQUuiImd32J64Bnb94TDqVNj5u7/9JYupUqnqtyQXZQWF6XFRWlxUVpclBYXpeUbS+1qOYf8HRgAAAAASUVORK5CYII=' +ledblank = 'data:image/png;base64,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/GMzLdsAADpEaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzE0NSA3OS4xNjIzMTksIDIwMTgvMDIvMTUtMjA6Mjk6NDMgICAgICAgICI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgICAgICAgICB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgICAgICAgICB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8eG1wOkNyZWF0b3JUb29sPkFkb2JlIFBob3Rvc2hvcCBFbGVtZW50cyAxNy4wIChXaW5kb3dzKTwveG1wOkNyZWF0b3JUb29sPgogICAgICAgICA8eG1wOkNyZWF0ZURhdGU+MjAxOC0xMC0yMFQxNjowOToyNS0wNDowMDwveG1wOkNyZWF0ZURhdGU+CiAgICAgICAgIDx4bXA6TW9kaWZ5RGF0ZT4yMDE4LTEwLTIwVDE2OjM2OjMyLTA0OjAwPC94bXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhtcDpNZXRhZGF0YURhdGU+MjAxOC0xMC0yMFQxNjozNjozMi0wNDowMDwveG1wOk1ldGFkYXRhRGF0ZT4KICAgICAgICAgPGRjOmZvcm1hdD5pbWFnZS9wbmc8L2RjOmZvcm1hdD4KICAgICAgICAgPHBob3Rvc2hvcDpDb2xvck1vZGU+MzwvcGhvdG9zaG9wOkNvbG9yTW9kZT4KICAgICAgICAgPHBob3Rvc2hvcDpJQ0NQcm9maWxlPnNSR0IgSUVDNjE5NjYtMi4xPC9waG90b3Nob3A6SUNDUHJvZmlsZT4KICAgICAgICAgPHhtcE1NOkluc3RhbmNlSUQ+eG1wLmlpZDoxYTc5NDQ5ZC05ZmM0LWZiNGItOTNjYy0xNTcyMjU1MGU5OTk8L3htcE1NOkluc3RhbmNlSUQ+CiAgICAgICAgIDx4bXBNTTpEb2N1bWVudElEPmFkb2JlOmRvY2lkOnBob3Rvc2hvcDpkMGIzZGFmNS1kNGE3LTExZTgtOGI3ZC1jYmQxMWFlODBkMGE8L3htcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ+eG1wLmRpZDowZDlkYjE1OS1lYThmLWQxNDEtYWE4MS04YTY4NzFkNTI4YTc8L3htcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOkhpc3Rvcnk+CiAgICAgICAgICAgIDxyZGY6U2VxPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5jcmVhdGVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6MGQ5ZGIxNTktZWE4Zi1kMTQxLWFhODEtOGE2ODcxZDUyOGE3PC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE4LTEwLTIwVDE2OjA5OjI1LTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgRWxlbWVudHMgMTcuMCAoV2luZG93cyk8L3N0RXZ0OnNvZnR3YXJlQWdlbnQ+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOjFhNzk0NDlkLTlmYzQtZmI0Yi05M2NjLTE1NzIyNTUwZTk5OTwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAxOC0xMC0yMFQxNjozNjozMi0wNDowMDwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIEVsZW1lbnRzIDE3LjAgKFdpbmRvd3MpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICAgICA8c3RFdnQ6Y2hhbmdlZD4vPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgPC9yZGY6U2VxPgogICAgICAgICA8L3htcE1NOkhpc3Rvcnk+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjMxNDAwMDAvMTAwMDA8L3RpZmY6WFJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOllSZXNvbHV0aW9uPjMxNDAwMDAvMTAwMDA8L3RpZmY6WVJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDxleGlmOkNvbG9yU3BhY2U+MTwvZXhpZjpDb2xvclNwYWNlPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+Mzc8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFlEaW1lbnNpb24+NjA8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAKPD94cGFja2V0IGVuZD0idyI/PvnJsBAAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAEZJREFUeNrszkEBACAMAKHT/p1nDPeABJxqWua2kJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSU1G8PAAD//wMAGdkBdyV2S1QAAAAASUVORK5CYII=' +w1 = 'data:image/png;base64,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' +w2 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEYAAABGCAYAAABxLuKEAAAACXBIWXMAAAsSAAALEgHS3X78AAAUwElEQVR4nO1ceZQV1Zn/3Xur3toLvTe0dAPKIgk0YZuMOhk1JKiZxATUicswyclINCPq6MzJiZPVWYxbMpnEUWMyw9FoopkomkRxXCBAAwICBqHZl17pbrr7db+tXlXd75s/XtXjdUMj3bSG5PCdU+edrqp3l9/9fd/3+27Va8HMOGcnmvxDD+BstXPADGHngBnCzgEzhJ1NwAjvOCvMeL87YGYFQAghkJcBSQhBAIR3HXl/C2ZmKaV+v8d2KhOjla6ZWeL4ijMACCE4e4lBRBBCQErp3688MJiZYds2pJQwTTO/PR+wD9xGhTHMLAdNQADgRCIROHLkyCLLsi4mooiU0jIMY3d1dfWKqqqq5r6+vuKmpqarM5nMx7TWlUIIxzCMfZFIZFVtbe2bkUjEISJDCEH57Xug+WGAALC3CKNmo8EYqbWmI0eOzOru7l7AzMExY8asj0aju3bu3Pk/kUjkykgkwkII4TMjHo83h0Kh+zKZzA3hcPiSSCTCUkoBZOmTTCZFIpF4bcaMGV8YN25cG7JAS2ZmIQSQBWPwPIQPnrdQDI+5I7ERAUNEEoCUUmoi4nXr1t3R1dX1/eLiYgEA6XQ6bVlWR2VlZW0oFBKu6+bihQeAisViKCwshGEYpLXW8NzQsiwIIWQ6nZaWZb01Y8aMh4qKit6urKw8JKWE4ziiq6vrfMuypjCzaZpmS2lp6Y6CggLbc89cX178opGwadjAeCsDrbXQWosDBw7M3rBhw5u1tbVRx3E0soFWIMskZuYTMg1nZ0Su6wpmloZhwHEcWJaFkpISFBcXIxgMklJKpFIpTqfTvaFQ6AcVFRW/am5uvldKealpmoXMrJg5aVnW3pqamjsmT568PpFIjLEsqzgUCvUWFBT0ewvx/gLjgcLt7e3jGxoavnLs2LHLXde9oKioqFRKSX7A5GyjLISQg7JRttOsO8C/Zts2iAhTp05FYWEhtNZ+sNZewFbxeFz39/ejoqJCBQIBsGdCCEFEorOz84hS6tdE9HEhxAQiaolGoz+ZN2/e9yKRCHvtnTZ7ThsYH5Rjx46VPfHEEy8S0cWFhYUkhJBExDgNDSKEgBACruuCiKC1hmmaCAaDGDt2LEpLS5HJZHKZK69vUkpBKSVd19VE5LPSZwNJKaVlWSIcDvv9cGdnpygvL7/nsssuu89zM2bm08p0pw2M1tpQSrmrV6/+mxUrVjxZUVFh2bZtMrP03cs/mPmkLCEiOI6D4uJilJSUIBgMorCwEEqpXLpWSsEb/GBwTno+/xYppdZa+7JBK6WMWCx2pKKi4vHKysq906ZNe6OoqCjmL/Kp5jvsdJ3JZERLSwuYWTiOo3wwAMC2bWitEQ6Hc2D4QLmui0AggPnz52PatGkoKCiAUgpaa6RSKXR1daG5uRlEBD/mEFEOYB80KeUJoHsmmNnw+xNC+HOrPXTo0L/t2bNHNDQ0rF20aNGNdXV1zSeRGCc0dlqAEJGUUlJra+t5S5cu/V0ymZxUUVFhE5EiIqm1FslkEo7jIBKJIBgM5iaglEIoFMLnP/95TJ8+PRdTfAb4k+7p6cGWLVuQSCRQUlKCsrIyhEIhaK2RTCbR3d2NVCqVE4FDTmpgXGMppTYMg2OxmFldXf2TpUuX3vxewJw2Y6SURESypqam5Z577vnyvffe+0RjY+OEYDDIgUBAaK1RU1ODuXPnYty4cVBKIRaLobGxEVu2bMHVV1+NyZMno6enB/ksywMeBQUFuOCCC9DT04OpU6fCNM0BrplKpbBnzx7s27cvX0EPAAQAMpkMgsGg/10BwJBSatu20draOs2795SMGHZWIiJDKeUcPXr0vJdeeun6hoaGvzp48OCUKVOmVFx33XWqrKxswEAdx8H69etRW1uL2tpaWJZ1QnDNax+GYUBKmQvQ+aaUgmma2Lx5M7Zu3YpgMDjgu8yMRCKBWCyGcDiMcDjsux8BcPft2xe45ppr/nXZsmXfICJ1qnpsOFkppya11n6QNIQQ7qZNmz7d1NT0QnV1tUylUkBehvIn4zjOULFhSJBOFoD9uLR8+XK0tbUhEonkAPW1kJQSQgjtJ4ZMJsOJRELMmTNnzUMPPfS50tLSnlGJMX4U7+rqKtu1a9f1fX19FxFRhVLqYE1Nzc9bWlq+xMw3KaVcDHJPv/1TZJNhmQ/Cjh07EI/HoZTC/v37sXfvXgBAMBgkZqZ4PG4IITgajVrjx49/d+HChc8sXrx4+elmpfcExpfZ27dv/9jGjRuXh8PhiYFAwBdWSCaTHAwGRUFBwQnUf7/MB8c0zVzGe/vtt/Hyyy8jmUzCsiwsWbLkiSuuuOKZqqqq1rq6uoOmaWpPgJ5WwXlKYHy6HTx4cMqKFStWVVVVjZNSutnSJqv9ZTYqiw8KlLyxDWBjJBLBypUredu2bQeWLVv28JIlS37sxRYAEEQkh6N8T5mViEgppWjz5s1LDcMYl8lkHNu2zfzgOdquMhJjZrZtW0yZMqVn2bJl19fX12/RWiuttRJCsJSShrvxNSQwzCyUUi4RoaOjY7bjOIjH48q7lrvPB+RkzDtZnXQqy7//ZCnd72fwYgghfPUcEkJE/ea8mDciGxIYIuI1a9Ysfuedd26IxWKzQ6EQbNv+QPaI89XyYGC9mglAFiRfKEopEY/H04ZhdHtt+Hsz7xloTzqGwR37+f3pp5/+2tq1a/+9tLSUTdPM3Tcc15FSQmv9nvf6adgHxHEcCCFQUlKCkpIShEKhnEbp6upCKpWClBJEhEgkglAoBKUU9fT0yMLCwidvu+22myORiGbmXEwZ7t7MAMZ4sl8fPnz4/A0bNtxSUlICrbWbyWTMk1S8A0DKB1gpBdd1kUqlUFhYmLv/ZOaXBIlEAo7jIBwOo7S0FHPnzsV5552XU7AAoLVGIpHA9u3b0d7ejvr6eowdOxaBQAAAJBHpxsbGJdu3b//dRRdd9N/pdDqQSqUioVDIikaj1qCK/JQ2gDF+PdTS0jLxrrvuWhUIBOpKSkocr1Phuq6Mx+MwDCM34ZOZ1ho9PT1IJpOIRqMoKiqCaZq+8MrvD0SEeDyO7u5uBINBVFRUYNGiRaipqUEmkzlBApimCdd1kU6nUVxcnL93AwAcDAZFe3t7HMCPmfkSIpoEoDccDv98zpw5DxUVFaW8DKVPxZ4hXemZZ5657bHHHvs+AMMrAtkwDLJtWwkhEAwGfQrnaK21huM4SKfTIKIBruTrDh8cZobWGrZtw3EczJ8/H/X19QiFQohGo/mTHRDg/Xjilw0nMVZKCb9e8lVwT0+PUkr98Kqrrro9LzTI/K3QUwKTbzt37py5bt26z/T29o7dvHnz5S0tLdPKysocx3GU1lr6sj3flfLPDRitFyjzTUoJ27YxYcIELF68OCf3TzcuneoeKaVLRNIrIikQCMhjx471lJeXP15TU7O+rq5uQ3l5ec9QwXlIYHy38j8PHTo0+Z577nny3Xff/WhRURF70pv9eiR/zIN36JlZedljwEyEELBtG3V1dbjyyisHZBh/8v59+YDkn/MBGiwhBp/3J59Op2HbtiCiXQsWLFhaX1/fcLK66T2VL2efDEqllBOLxUqWL19+54oVK77c0dFRJYTgYDAoDMMYMFDbtmHbNpgZpmkiFArBMAwtpeRcv+RIIRRDKAIYs2fPlpMmTZL5rDpd1gzFHh/kvDZZSkmGYVA6nTa11m/feuutHxszZkxqMHOGtVEFZPdl2traal57/fVrtm7e9NG9+/ZP643FxluWFWJmhEKhVGlpafucOXPeKiws7N+0adNFTU1NU2KxWFlWlxCkABAsY6EtQW4KrkuIRMJYsGABV1ZW5soLPzgbhnGCG/qADHXd3+lLJpO57Ye83UACIPr6+prvuOOOyydMmHDA94xhA+OtgGBmASEhBWhXP83q7+8prM7EOhJWJiqyWcEuKytrLykp6QWAZDIZaWtrq2tpaak9fPjQlKNHO8bGUtq09jx9C0frDhaOm/9mdeWYo4lUpqqhoeH28vJyYRiG9L4L13VRVlZ2wq4dEaG/vx/pdBqlpaUn7M1ordHf3494PI5oNErRaJR8Yai15qamJrO+vv7XDzzwwGeQfapJ+awbyQM3CWZqSrj1Tx22X7h8bPDOPy83XmJAirwnhFprg5mFYRguAAZYAB5Vd977z2hd8Vlc/spVfaIqHlQQia6u6PU33rg7Y1llBQUFLjEJwSQBwcQCpmkIf2JeBuS87VFWSinDMPy+fdVMhmEgHo/LTCaTA00ppadPn77u61//+s0TJ07cd7IYM6zNcH/yB9P4i9+n1dO2CIwvMcVRMIEIygfcq11cbyCCyTVZKA22gtzwpZ/SwRc/G7h649yErIot39X384vKzcfmVVe8fvfdd//dA/ff/3hrW1ulIIfZKIaSkEGTIKUBKQV7rIVt28J1XZim6StgFkK43qoLANK2bZFIJMSsWbM219bW7lRKUXV1ddOFF164ef78+asjkUhqsAv5NjxXAgww3N908hsdNi5nLVquPw+zCwx0cZaOLAarSnYNCMNF5mglrb/pZ3TkjU8YV7x0ZU/Vp1et77BWbTomZn2hzpg1qVDuBQSOHm0fu3bN6qvauu1idL36qQMHmqe+21qU7OtpHWu7ZAgA4XA4VVFR0XnFFVc8/ZGPfGTDI4888q1t27Zd7DiOyg4TQimlq6urO6+55prHvvjFL36voKAgkR9g+T3ephguMFIA1GrhxpYMbh0fxKPjQnjaOy8ADBRLPih922fSW0ue4qM7Zso/++7X3Klf/e6rR53VXa75l70pbrt5kriw0EA/ESspGBBSo2/VRdj/1Qcw8xc3dPaW9jc3778wkUhGpJRcVlZ2rK6ubm80GrUAwLKs0MYNGy5t3L17Zm9v75iCgoJ0XV3dvnnz5q0ZN25cGx9/QpoDREp5SuWbU5PDPAQzB5gZ5FE7aevwwT67zssUgrVtMjO4881L9W9rmvWzYHpn2Q+zVXPGXH1Mv/ZcG/PWPr7Pa0cya0nMcDtXLnRWlne4Xesu1sxgyorJwWPQWitXa4OZhhyr1loRkRjuHEf0fgxn2eEAUAJgYvArbfY3wEQTi8yvE9hU0rS55Wc38va/fwQcL0ZhQUqMmfEOdCqsVCR9SSkWZ5hmRCRtBgwI1gJCafS+epX4/VW/VeHSLqRf/zgShf0UnrwXIuD65PaUNQkpIQF3Q4f1ybDi9KyywFrb5YAUYGRLAz3iN7NGyBifNUi5HFjXo//jX3ZleGVr5s7sKtlharzrQf0iWK8M2vq1qK1XGqR/A9ZrZrxD+779TUrun5jPOGZvVdMHzueWB+/i7fXbeB2YGpTDXU/dyMxgcpXfPzFLIsbufnfBd3akurcesz/DzNDExhnM6Xg9NiI0s6yRALC1j5cdSss7TGXa46LGfgAApYMwIklRNn2nALNwk6ZQgAiFHZF6dwb2ffs72DBrB+246Slx7JWFcLpLs6mcBUITD6LmH7+HD6++FNEJh0XVtf+L0sUvMENAZJUzZ5lKjQm+7p2kfAUyoIqDRuvxoZ25jfiNKm9wek8Ct+xM8KMVAfF/88bg6pCEBX/Pw+0rRPerC7n9Zzeh97WF7FohYZgEaTLYlpxxhQgU94v5ay9BdMYOgCTIVZABhw9/5VHhHivGBb+44fgjrePB0iYEX+nil7oy4pNhie2fHYtLowp9DIgTMuOIJnjmtDMyxNM0c9GA8+SqnHuwK7l/20zad+fDen11J60JMK0Jkl5bFOPulZ/gXID1XKXrsVv4wKJfMtlKM0tmQlvCKe1Ou6XHAzWj3eLPbe/nX/c4/HE/44yGGzHzmQPjxwgaEC/8gwSTYzB7WcXuLOctUxt5nWRaF7So69lrKQeid09y43xu+sp/sttbnG2P0JHW4x7eGX9+b8yp9+LIqAEw1HHGb216tJXe5yAKC4ZQGkwSAsChWx5DZs80loCY9KM7uPy6XwpoCSEJEAy3sxLprTMx9jvfZjWmX4C5I8MXrO3lFxNkFhYGZA+Q9RXPpJchWZz4wuKZ2fuNPJOnZ44+eiuvB/MGwdT64N3MjJTjhHf2WB8iYsFMgtPbZ7LTUZn9rkbc4ejz7bTpx03E/7WfNlqaTWYWJzJz9I/RaETooXzbT6+JLbN5c0mM14O5+VvfzF5z8FKz9c0n9iR+yswgcg2mjOm5oGRmWJqjr3fxW79qZ26M8z94LqtGYczvLzCUXb0h/J2yLNCJCO26ZC01gKnproeZGWnHVRt73Qfv32Pzs4edb2WBYZVVsOTHLMXMcInLLeJZHwQYowKMD0i/rYs3dVoXO5oGCitysn83/9P93ADmw19+XJMTYiZs6dW3PNnK/MBe4k3dfMNgJnhtS6JsUPcX4Y8CGGYWjiY835z5waO7k88OmJzvQn2/+RRtBPP+v36OyVZEboCZ0JrmhS93cPvaHl6Vcrncb4+ZoTmrXA/2OR9qaE8vHAza2QyMYGYkHAqu7XV/cP9eh39x2Hno+KS8tOscreJtlV28+9JVTOnAAMCY4RDXauLi/Db9z640Vf5ob3rL84fT9zIzNH3wwAy7JGBAAcD+pLh2f0LebgoD5xcZe72LApzdG8bhv30SgYpOXPDCIoiQDWgFobTXhjAEmoRAHF669fdzWlI8dXOC3+h2jDnlYbNxlJLvsG0kOoYAYHwY7/ZrvB0t4oPTC8SvAEDCFRCGg477vgZr93RM2zgXakwvQBJQuSr3ZNrHr38OpHFbuyU/XBYWzvlFYg8ACDE69c+wbKTxxfP9Ivb2ZXJuEn/zUt41eR9bjdOy553TrXYlM6Pb5ovfitHvDqX5dhroZmd9jMmfiCBmSayzoDjt1bT/sjUcf+Oy7D3uSGODGPT5gR9n+nulvKdcDLTf/TAiF29E8eLnctuaw2Xw8R9oCU/mf/BuhFH5IZf3WKTvuWsBIVF87bMjBeVssjMsIj1Q7P3nQ43pRsEn3wRI/rGDAowGY9iVcNoqYVb3QATs0RnWH95G7Ve0AInsLsCfho3Sy4b8JwUKMGrAjO5Pe88GO5v+hcFZZeeAGcLOATOEnQNmCDsHzBB2Dpgh7P8B+QrwZW3eDSIAAAAASUVORK5CYII=' +w3 = 'data:image/png;base64,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' +w4 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEYAAABGCAYAAABxLuKEAAAACXBIWXMAAAsSAAALEgHS3X78AAAUt0lEQVR4nO2ce5TdV3XfP/v8Hvc1d+48LI1GoweSZVvGsuWHsOLK0NjEJBTbgbQYcFoSQ9oVAmQloXFqFoUmNMkioV0JDU1CWroocZPlOLGpsSl+Fdu4ED+IZWzLlrHQ+zGa152Z+/g9ztn94/e7M6PHMDOSLJO1tNe6msf53XP2+Z79+O595kpUlXNyopg3WoEfVzkHzDzyBgOjZh4dBNQ729oco8A/whgjwOuu9Fm0GJUTvk8PbSA9uj7/5ey4a3UR774SnH+SOc7KSZ4lYGy+6Q44+YaT/dfReupX8zEDLgAgHb6U9jO3g3HgZBYLUTTxUfu66/06L6DZ/O0Xr6f9wk+BKDgv+wqKTmn7hRsAD8QCFoB45/WkIz7gsrHcmlxzGY3HfguRE5c6w/I6AKNyrNsApjtl8v7P4Zo1MBbX7AEQRCTedSHJvstx45dp/NQnAbT93M2qreVAAGmKxiGANh76JHb8gtyS5gRnPeP7OLMTalxB02JmEWo6lkEw9Bx2eC2T934GgOSZO0ie+n2cXY6d9Gm/+G7S7/+KJN+9nejlfyPxvk2iUsKOXEzz7nsgGiA9cplMPfhRwvMfzhbL50YNqKBJcCa34i/8yGJEDYjDNZdp48lflK7rP48pTWcKR2WkMEV40QM6+fVfp7ztTtHJDRo9czNpeT9SgtZ3bhezSqDgafv//JnYSNRNDEn7G1/BHrgcO3y31r/x86IuIDz/W2CLqPMQvwniaHzng/i9r1G4+MkZXU5TzpDFSGbaXs9u0bbo0T+8B9ccAFHiZ28jevgv8PsjsS1k9L9+HTv6T0W6kMCskuIQ4hPi6j52UkQS1UIvUqgOQmMz/nkw/fU/ovH0O/EHd+P2v4fmXY+gjZUgqlMPfFqbj3+U8IJncmXOSNY6TR6jAkh+QlkqVVvQAx95TUzXUVb8znWkr95C694/R2qW9ohBY6HYB/FhxdbBJYKqgopiEDTbmwSKV1SCAYOUIKorxWUgVjDVI3R96Bomv/khrf/1J2XZ7T9H6cqvZXHH2OP0eiOAycFR5yHGZop5KY2//wCHP/m/KF7xNLWfeAm39xcwJUe839B4UdXFYGoiXh+YCkgIksdSdaAp0ELtFGLHQduqxUGR8iYFXyAc0YTvyeSD76Cy7W6W/cZ7MzCEPOvZ2Rj0RgATvbwV0z1KsPIHgKCxR/TtT0HoMX7vv6KxfS1db1ZKQ0L9cUim0MI6xF9GloVdBgSdg1WyzQlgUDEIgroGxHvBTiDVS6GwDiaecxhj6Hv/FzFBhL/mUYIL7wfAxTXiHW8lXP8kpjqeg7akjZ5i8O0sVEg4+sd/oqUrH5XaTX+OKddxjVXafvDDlJZbSm930twpDN8N/iCUNiPqIJ2cA8L8ko0qIgbCdeCmYfI58F5Fqz8BftURP/tRhDEJL/sqAK1nbtGJr/0GXdvuleLm+7Npls57TsNinAHjaO+4jn0f+wZB3zC9t32K0rqAxt99Sb2KMP2cyOR2KG4ErwKula+61JivmWWZAAjRaBdChPa/04lg8NY+ib/pD7V+zx00vrtV+n/x0/R84LOnk6FOM8akPvgp7ZevYv+v30M6vJrC+WP0Xt3D1HOGyX9AK5sQ8rgxA8iprCm52wmYEsSHwE7BwLshnoiZ3mEg8bX/Q5+Rnvf9TnZwojmnWrIrnQowgtqMpouXYEcHSfdeTvPpm5h8+CN4RYezhsnnoLQOsKDKGaXx6sAUIR5GJYDaFSrphBCs3kntpk9hug4Rvvn/gTMoihj3OgOj+SYNM6egSY2JLzyk9shb8M6zYhtGD94lUugH482e8hkXB14RmgehchHaf62STjvcqCfVf/lhild/eQ7x7EL8NhKmi519CcDkHKHx1JXU//fHKV7yPOXLv0u4/nu4kW3Uv/wAIgWOPKCaDIsUzgMX8/qAMkfEQOswDLwnpdDtE26+h66bbyPeu5HolS20nn8r3sBr9L3vP2K6WouedskWgwu0/sDPc+Q//weiH66lcP4wwdpdUuq5DNso64G/Velakc/7erdOFEyAtEYhHFIGf0ZoDu/GTvnEu1ZBME3/B79Ezy2fw+seXkqsOYUYk0/umt0c/W//lrEv34Fr+3RtQif3IK0fQGUI3KKt9jRFssDeGEVX3ojYUSWti1bedr8s++XbCde8dLZ4TE7922UqF5SUf9YScV04i0w8JBTLYBNQewpTn6KIB0kTaeyDFW9X4lGV4vkl3NgGdOVOxJubshcF0CkUkfm8UnCa7N6MTlbVFNHp10TjSVQlA0XdWXop2DTLC5O70LQhKr4heulKNBXET3Oll+Tbi7cYTQLUCqaQgBYxpRGp3fZ+nfjqA+J2baVxwOEwxG3wgkzhsyEiGTBWkPYYxBNCWLPa9Z6PS/HKh9B2D2qaaLsKWLzqxGISwiJiTJ7y2jsvZPxvbqX54jXYsSHVNEs5dmo9lTXdcmi7Mvma4BWh0gWef3bAMQKNBiRtwKFr3wWmZUkao2KkpjAhpjpKeP4otZ/+U7p/5q8QzzBboJ1UFmExOaUurN1D3y13Udyxg6n/+3Ya39tGvPsiCgOeSBmiSQEDzkFjGsrlLJWqnmbGnudiQMlAaUUQtbO1bILE09C9zBAdXo45b4+Ur/gWXdc+QemSpwlXvZpX8QuWCaeelZpP3arjf/kF8f1+0lh5+U4haeTtAwVjoFTMvi5pjayyzpiy6yCQvWYqccnIYxxDFIEIikGSaRh6Gwxts0QjHuVr7qb27l/D9BxYamZaQlZSAIM6g7Z8ohfeIUT9WAcuFpzO6AyAtWCbEAYQZMz8+B75nGsROtW2IKBT4ByKj+IjJAgWTAH1Kkg6Ba0YTZipncVIdgCq4FJRfIhe3irRD6+guPkAoj54yWJ3uzSLUWfymicrzqJXr9WxL31FkpH1vHKfI5owGH9mkzOW4hkIJGvBnIBL3lwQg5DibExUfitp/01I5c3gVdC0DpPPEo78NYWpV4iCC0h63wnVjeAVIDqMN/YtiqMPIedvs/Sv9vA33cd5//o2vOWjs8po1hE448AAaOzTfGELU9/+aSaf+Ema/3ClVtZ1s+8Vlan9glfIdjy33aKa/eiRgWPyohfp1F2gMVaL1If+gGDdxygWBDEzpAmrQmtsH3b3X+K/6YMU+4YQ0ayRpRDFkO74PEV9VNPuq0Q575CEtWdLBX3Yr27+e4qXb0fMmSwJct9s71rL2L23Un/oZ2luv5B0tBcJobweereiux6Ho6+AX8xjwbzzZWAYg0gKmuAkIPb6mTzvlwgv+SxlaWCdRdXMgCs4MCUSAgKSvLeTX1KKIl5AlAjx9FHCriGMgE0bGo08IT3t/3S40LXq21q9+UFq77hLvGqdBe7AFw9MvH850d7LUNsHtoEyTuOJ9xO//HEKfU4PPGvY/R0Iwh8dbMUgzkKS4oxPHKxieOUdsOImCsUSxcDh8nB2ojgMDlVB5Ti/VIcIGC/EuRhAjQni2BYK8dSuv+vr5TNhsdo0wcBu8Bcke6eSlTJeY0f7dPjzX5No17UEPZbWuOeev5eZLCKGWV/KWaoYjI1ITR/t1b+EDL4Lrb4JDdcgtkG71SBOUjzPQzuBGKWjo0in2TmvbvmhSJbVNIOwHbvJ1MprIu5Ab638hd7e3oc4fYs5ZtF8twouChHxiPdcpwd/73/ijvbw2ovqJvaL+D4mTWbZggHnF5G0TVTaSPstd1EevBS/s31NUc0S29TUFBP1OmBwzmEEjOdlSzqLc2A8syA1mhvi8nyhzqlMTk41V61aeXNfX98jqmpETt76XEK6FhBxeVdM8Motbe3cyL7f/bCM3tdN9wbVgYvEO7qPhIBm99twpTXgYrzpFyhNb8eaCo3L/wfdg5dCu0kqGWqa3WIDUK1WsdYyMjJKrdZNpVLB931UFWstzWaTyckprHUYEfT4proq4nmICKouz+CqIuI8z0uCICiPjo69r6+v7xFmripOCxjI4o1x2HpND37ht9j3uU9gG6GW11gpX2iENpOrbqG9+hMEA5fjeSGqlnYS0X7tq6STOykt24JtTeMwyMyfu8xabZqmlMtlVqzwKRQKiIBziogQhgFh2EOpVOLAgYO0ogTP91HnZtzN8zxa01OMjY3R29uXzyGiqp6i9vChQwwNrTy6oBkswZWy2DL51NUc+Pxvk+7vpnrN43RtfYb4e79M+5mfqttrbLP333ndXSU0mZ6jrE8sJaLmNOWw0xpdQDERnDtRN1XF933a7Rbbtz+PAsViEWM8UGV6epqxsaNEUYTvh7ZYLKgxRpxzMjU5aXw/OHLjTTfeUKvVvn+mXMmhzhB2H3Fr/v1vts0GE9lSTZPx9YXW9qs8uZC6/3Om6gtxYwSV2amT1CK0KPgeSQqLKFXgeBeZI2maEoYhvu9z+PAhSqUSExN1ms3mTM/d933XbNbNyEgsAJ7vucEVK57atu3aT9Rqte8D84ICS7AYVYwIrtmya44eHf0srvkBz5MAwKohTR3FQkihEJz0pBfa7FJFREjTFGMEVaFeH+f555/nwIEDhIGnjWZbli9f/v0VKwZ/UKt171q5cuWDQ0NDj3meF/0oS5mZf5HACKCtVnPd3r17H66Uy+uDoDB3+6Lq5EzfkixOrUx8PyCO2zzyyKPu1V37zSUXrX3gXTfedFu1Wh3OYq+oanbZvxAosEhXUlVfRJKDBw/d4fvF9Ygft6M4nKX85FmAM2UQS5Z2u02xVLUXXzDobVpX/9Mr3nrrrwhqVNXLAVERsSyyi7cgMKrqiYhN05R2O9paKpWJougM/cHR4kRg1hTzuusEUaXdappS9xDrWr93o4wPPKq9771bxBkRs+QG9EIbFBGx9Xr90sOHj9wcx/HKIAhRdYu+KNfcvxZrSKo6w2k64pw7pkFhzIlZTVXVUyetVhK79X/2EZJHLqS9byPF1S9zCnfY8wLTCVB79uz+F/v3HfjvxXKlOwxDjeI402+BDWv+r8m7eG5OADppVyYHxJiM8UIGiBghDEJ8PyNtSZoSR3EOoIdzaed94tQ4a1vh3iPFyy65+CO/j6aFbDlxzHS7WNS9zkmDbweUqamp87dvf/5b3bWeVagmqU19MivCGIOq4qxlplt0LCp4vkccxYgxhEGItWnesDoOFhE842Odpd1qUipXUFV6e7rp7++nUCjieWYGrFarzfDwUaanp+nr66VWqxIEPqqi1jo5sH9fOjg0+LO9PX0PWGuLgCcibWNMruzCcWY+YDwRsSMjI9c8/vgT3x5YscIWCgWRrE1m0sRKvT5GqdJFuVTBOTtbUUtG70WEdrvN3r27EWDFikHKla6MiAnHPI8qcRxxYP9+6vUJent72bz5ctauXYOqzryyx7NDSZKEVqtJtdqdB/6ZcSciZmKi/kMR7gSuBJar6r4wDO+sVqv3zqSoLDudFKT50rXkvu49/PDDX9nx0ku3Vms1FwaBCYJAo3ZEs9WUQqFIb29vVs8EYcZW1ZHEcVYMjo9h7WzcK5VKlEsVwkIhLwyVJE1ot9tM1sfp6qpy6aWXUi6X6e3txfd9nLN5zJlNgZpnwYwdnxg6cqA0SRIJggCRrOicbkwThuHH+vv7v5hPeGJNsgAwdN5krS2/9NJLv7B37553NZvNoeHh4fWqdBcKBZumqXHWivE8jDEYMTh12DTFqeIZg+QuB8yANDfAat7U8v2A66+/nsHBlaRpmj/7IxoMWWA6IVDPjCMqSApqFBVRsWIkqNcndnR3Vz9TLJZ2VyqVZ405eatzIYI325zM4o7s2LHjvQ8++OBfxHHcVSwWnTHGqqpnbefzAlkMyhV2IuKccyZf66S7cM4RhiE33PAOKpUqaZock3kWIo4Lj2vHxdU5SxzHYtO0bYz527Vr1/xaoVAY4bjYsyDzzce9/HtnjNFDhw5teeyxx3579+7dNyRJEvi+j5dZjcv9F+cc1lpJ0yxrBEGA53l27gkrSIcuW2v1ggsuYNOlm71juUre1yVvVOnMO5l1K2bca7bfLDOWaUSwuctJTvSMMTQaDb9UKvyXDRs2/Gonri4amOPE5Is5a62/Z8+et73yyivv27t379UTExOroyjq7/h8EASuVqu9unr16qfr9fENBw8evqzZbJY77iQiSMcq8uCapglbtrxFN226TNI0naED1lmM8fJ4MnsDIcZk8cRZpDM+BynjZb9rt1uUy5UcWO1U6EkURUEUtb951VVX3uR5XueO+5SAyfeRfaghj+oSRVFPs9nsbTQay6MoUs/zpFKpxF1dXftLpdJwkiS16enpgaNHj1505MjwFePjY0ONRrMnbk+tszZ1fthlisXCzq5KxRsbH39PtbsW1LprxjOGqcYU01OTDAyspFKpHOMz1lrGx8eYmqwzMDBIuVxmhjooxEnM0eHDTNQn6OnpdV1dVc2aXmgctfXgwQPB5s2bP3vFFVd8+nQt5hhxzvmA5vxgXhBFZJ7m8wyf7fh3eN99931z586dP9nT05OoqnHOdeKVlEolCcMCYgSbpLSjSJMkUlWMMcYVi0UThKEApHFCq91S55wzxkir1TIda85TNRdddNGd11133ccKhUK9U2ieEWDmSCewHk/zNF9sZnxORlIk7+Fl5u0bY5KRkZGr7r///q8ePnz4Yub0KXzfn5PJMp1d3rkzxqiqiu/7zpic+iuIMZIkiZemKWvXrv1uuVze5ft+2Nvbu3fNmjVfHxwcfMIYc1Im/GP1mcjOqSVJUtu5c+c/HxkZ2aiq8dTU1Jv27Nlz9fR0YyBNEwEIgkCr1eqhjRs33r169epnnnzyyd/cs2fPP7HWHtPm7O/v/8HWrVu/uGXLlj85CQj5bd/SeMwbIvO5XqPRGJiYmFgbx1lHrlAo0NfX92qxWBwDiKKotm/fvq2HDh16S7vd7g/DsDEwMPDcqlWrnuzq6jp8nEXnBfvSme8bLdLhPvnP88WxznOdUuCEzaiqqKrJidyiN/vjCswJoqpmLkHsxKlONy4H4ITPaouIPRlgC8k/GmDOtpz7LwzmkXPAzCPngJlHzgEzj5wDZh45B8w8cg6YeeQcMPPIOWDmkf8P1g4l0uBhGEEAAAAASUVORK5CYII=' +w5 = 'data:image/png;base64,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' +orangeround = 'data:image/png;base64,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' +weather_icon_dict = {'clear-day': w1, 'clear-night': w1, 'rain': w3, 'snow': w3, 'sleet': w3, 'wind': w3, 'fog': w3, + 'cloudy': w4, 'partly-cloudy-day': w5, 'partly-cloudy-night': w5} +led_digits = [led0, led1, led2, led3, led4, led5, led6, led7, led8, led9] +if __name__ == '__main__': + led_clock() diff --git a/DemoPrograms/Demo_LED_Indicators.py b/DemoPrograms/Demo_LED_Indicators.py index d35ee4ab9..2aba8150c 100644 --- a/DemoPrograms/Demo_LED_Indicators.py +++ b/DemoPrograms/Demo_LED_Indicators.py @@ -7,12 +7,6 @@ Demo program showing how to create your own "LED Indicators" The LEDIndicator function acts like a new Element that is directly placed in a window's layout After the Window is created, use the SetLED function to access the LED and set the color - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ diff --git a/DemoPrograms/Demo_LED_Indicators_Text_Based.py b/DemoPrograms/Demo_LED_Indicators_Text_Based.py index 4692d606a..43e60a716 100644 --- a/DemoPrograms/Demo_LED_Indicators_Text_Based.py +++ b/DemoPrograms/Demo_LED_Indicators_Text_Based.py @@ -7,11 +7,7 @@ A simple example of how you can use UNICODE characters as LED indicators in a window - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ sg.theme('Light Brown 4') diff --git a/DemoPrograms/Demo_Layout_Add_and_Delete_Rows.py b/DemoPrograms/Demo_Layout_Add_and_Delete_Rows.py deleted file mode 100644 index 1e29d950b..000000000 --- a/DemoPrograms/Demo_Layout_Add_and_Delete_Rows.py +++ /dev/null @@ -1,69 +0,0 @@ -import PySimpleGUI as sg - -""" - Demo - Add and "Delete" Rows from a window - - This is cut-down version of the Fed-Ex package tracking demo - - The purpose is to show a technique for making windows that grow by clicking an "Add Row" button - Each row can be individually "deleted". - - The reason for using the quotes are "deleted" is that the elements are simply hidden. The effect is the same as deleting them. - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - - -def item_row(item_num): - """ - A "Row" in this case is a Button with an "X", an Input element and a Text element showing the current counter - :param item_num: The number to use in the tuple for each element - :type: int - :return: List - """ - row = [sg.pin(sg.Col([[sg.B(sg.SYMBOL_X, border_width=0, button_color=(sg.theme_text_color(), sg.theme_background_color()), k=('-DEL-', item_num), tooltip='Delete this item'), - sg.In(size=(20,1), k=('-DESC-', item_num)), - sg.T(f'Key number {item_num}', k=('-STATUS-', item_num))]], k=('-ROW-', item_num)))] - return row - - -def make_window(): - - layout = [ [sg.Text('Add and "Delete" Rows From a Window', font='_ 15')], - [sg.Col([item_row(0)], k='-TRACKING SECTION-')], - [sg.pin(sg.Text(size=(35,1), font='_ 8', k='-REFRESHED-',))], - [sg.T(sg.SYMBOL_X, enable_events=True, k='Exit', tooltip='Exit Application'), sg.T('↻', enable_events=True, k='Refresh', tooltip='Save Changes & Refresh'), sg.T('+', enable_events=True, k='Add Item', tooltip='Add Another Item')]] - - right_click_menu = [[''], ['Add Item', 'Edit Me', 'Version']] - - window = sg.Window('Window Title', layout, right_click_menu=right_click_menu, use_default_focus=False, font='_ 15', metadata=0) - - return window - - -def main(): - - window = make_window() - while True: - event, values = window.read() # wake every hour - print(event, values) - if event == sg.WIN_CLOSED or event == 'Exit': - break - if event == 'Add Item': - window.metadata += 1 - window.extend_layout(window['-TRACKING SECTION-'], [item_row(window.metadata)]) - elif event == 'Edit Me': - sg.execute_editor(__file__) - elif event == 'Version': - sg.popup_scrolled(__file__, sg.get_versions(), location=window.current_location(), keep_on_top=True, non_blocking=True) - elif event[0] == '-DEL-': - window[('-ROW-', event[1])].update(visible=False) - window.close() - - -if __name__ == '__main__': - main() diff --git a/DemoPrograms/Demo_Layout_Extend.py b/DemoPrograms/Demo_Layout_Extend.py index eeda9f8d4..bacbfa624 100644 --- a/DemoPrograms/Demo_Layout_Extend.py +++ b/DemoPrograms/Demo_Layout_Extend.py @@ -7,43 +7,27 @@ Note that while you can extend, add to, a layout, you cannot delete items from a layout. Of course you can make them invisible after adding them. - When using scrollable Columns be sure and call Column.visibility_changed so that the scrollbars will - be correctly reposititioned - - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI """ layout = [ [sg.Text('My Window')], - [sg.Text('Click to add a row inside the Frame'), sg.B('+', key='-ADD FRAME-')], - [sg.Text('Click to add a row inside the Column'), sg.B('+', key='-ADD COL-')], - [sg.Text('Click to add a row inside the Window'), sg.B('+', key='-ADD WIN-')], - [sg.Frame('Frame',[[sg.T('Frame')]], key='-FRAME-')], - [sg.Col([[sg.T('Column')]], scrollable=True, key='-COL-', s=(400,400))], + [sg.Text('Click to add a row inside the frame'), sg.B('+', key='-B1-')], + [sg.Text('Click to add a row inside the Window'), sg.B('+', key='-B2-')], + [sg.Frame('Frame',[[sg.T('Frame')]], key='-COL1-')], [sg.Input(key='-IN-'), sg.Text(size=(12,1), key='-OUT-')], [sg.Button('Button'), sg.Button('Exit')] ] window = sg.Window('Window Title', layout) - i = 0 - while True: # Event Loop event, values = window.read() print(event, values) if event in (sg.WIN_CLOSED, 'Exit'): break - if event == '-ADD FRAME-': - window.extend_layout(window['-FRAME-'], [[sg.T('A New Input Line'), sg.I(key=f'-IN-{i}-')]]) - i += 1 - elif event == '-ADD COL-': - window.extend_layout(window['-COL-'], [[sg.T('A New Input Line'), sg.I(key=f'-IN-{i}-')]]) - window.visibility_changed() - window['-COL-'].contents_changed() + if event == '-B1-': + window.extend_layout(window['-COL1-'], [[sg.T('A New Input Line'), sg.I(key=f'-IN-{i}-')]]) i += 1 - elif event == '-ADD WIN-': + if event == '-B2-': window.extend_layout(window, [[sg.T('A New Input Line'), sg.I(key=f'-IN-{i}-')]]) i += 1 window.close() \ No newline at end of file diff --git a/DemoPrograms/Demo_Layout_Generation.py b/DemoPrograms/Demo_Layout_Generation.py index 538303d54..f794f874a 100644 --- a/DemoPrograms/Demo_Layout_Generation.py +++ b/DemoPrograms/Demo_Layout_Generation.py @@ -19,15 +19,8 @@ 6 - Questionnaire - Unwinding the comprehensions into 2 for loops instead 7 - Using the * operator to unpack generated items onto a single row 8 - Multiple Choice Test - a practical use showing list comprehension and concatenated layout - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ - """ Construct #0 - List comprehension to generate a row of Buttons diff --git a/DemoPrograms/Demo_Layout_Reuse_Effect.py b/DemoPrograms/Demo_Layout_Reuse_Effect.py index 56f86e1a9..11b5b720e 100644 --- a/DemoPrograms/Demo_Layout_Reuse_Effect.py +++ b/DemoPrograms/Demo_Layout_Reuse_Effect.py @@ -13,11 +13,7 @@ Solution - create the layout and window in a function and return it - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ diff --git a/DemoPrograms/Demo_Layout_Vertical.py b/DemoPrograms/Demo_Layout_Vertical.py index bb1afc8f0..c882614c8 100644 --- a/DemoPrograms/Demo_Layout_Vertical.py +++ b/DemoPrograms/Demo_Layout_Vertical.py @@ -10,11 +10,7 @@ There is also a funciton provided that will convert an entire layout into a top aligned layout. - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ def top_align_layout(layout): diff --git a/DemoPrograms/Demo_Layout_Vertical_Centered.py b/DemoPrograms/Demo_Layout_Vertical_Centered.py index de02befbf..9b5141ee2 100644 --- a/DemoPrograms/Demo_Layout_Vertical_Centered.py +++ b/DemoPrograms/Demo_Layout_Vertical_Centered.py @@ -11,11 +11,7 @@ This expanding Text element is what will cause the Column element to be centered - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ def main(): diff --git a/DemoPrograms/Demo_Layout_Vertical_Centered_Using_Sizer_Element.py b/DemoPrograms/Demo_Layout_Vertical_Centered_Using_Sizer_Element.py index 29a000549..65d0499ad 100644 --- a/DemoPrograms/Demo_Layout_Vertical_Centered_Using_Sizer_Element.py +++ b/DemoPrograms/Demo_Layout_Vertical_Centered_Using_Sizer_Element.py @@ -16,11 +16,7 @@ This demo shows how you can make a 500x500 pixel window without hardcoding the size and while also centering the contents of your layout. - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ diff --git a/DemoPrograms/Demo_Layout_Vertical_Centered_Using_VPush_Element.py b/DemoPrograms/Demo_Layout_Vertical_Centered_Using_VPush_Element.py deleted file mode 100644 index d071a8bfc..000000000 --- a/DemoPrograms/Demo_Layout_Vertical_Centered_Using_VPush_Element.py +++ /dev/null @@ -1,37 +0,0 @@ -import PySimpleGUI as sg - -""" - VPush Element - - In version 4.49.0 a new VPush Element was added. - It is not "True Element" but rather a "User Defined Element" because it's a function - that returns elements versus a class based on the Element class. - It's not an important detail in the use of it. - - Use a VPush to "Push" your elements vertically away from it. - * If you put one at the top of your layout, then your layout will be "pushed" to the bottom of the window. - * If you put a VPush at the top and bottom of your layout, then your layout will be centered - - This Demo Program shows the "centered" use case. - - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - - -layout = [ [sg.VPush()], - [sg.Text('Resize me to see that I am vertically centered')], - [sg.In()], - [sg.In()], - [sg.Button('Go'), sg.Button('Exit'), sg.Cancel(), sg.Ok()], - [sg.VPush(), sg.Sizegrip()] ] # toss a Sizegrip onto the bottom corner to make it easier - - -window = sg.Window('Window Title', layout, resizable=True) - -window.read(close=True) - diff --git a/DemoPrograms/Demo_Layouts_Using_Walrus_Operator.py b/DemoPrograms/Demo_Layouts_Using_Walrus_Operator.py deleted file mode 100644 index 2d7883b9e..000000000 --- a/DemoPrograms/Demo_Layouts_Using_Walrus_Operator.py +++ /dev/null @@ -1,34 +0,0 @@ -import PySimpleGUI as sg -import random - -""" - Using Python's Walrus Operator in Layouts - - Some elements you call many different memeber functions for. Rather than looking up the element by the key and storing - into a variable, you can use the walrus operator to store the element, right from the layout itself. - - Copyright 2024 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - -layout = [[sg.Text('Using Walrus Operator In Layouts', font='_ 16')], - [graph_elem := sg.Graph((500, 500), (0, 0), (100, 100), key='-GRAPH-')], - [sg.Button('Draw'), sg.Button('Exit')]] - -window = sg.Window('Walrus Operator In Layouts', layout, auto_save_location=True) - -# graph_elem = window['-GRAPH-'] # This is the way elements are normally looked up and stored in a variable - -while True: - event, values = window.read() - if event == sg.WIN_CLOSED or event == 'Exit': - break - if event == 'Draw': - emoji = random.choice(sg.EMOJI_BASE64_HAPPY_LIST) - location = random.randint(0, 100), random.randint(0, 100) - graph_elem.draw_image(data=emoji, location=location) - -window.close() diff --git a/DemoPrograms/Demo_Listbox_Search_Filter.py b/DemoPrograms/Demo_Listbox_Search_Filter.py index 96a27c37d..6504e749d 100644 --- a/DemoPrograms/Demo_Listbox_Search_Filter.py +++ b/DemoPrograms/Demo_Listbox_Search_Filter.py @@ -1,13 +1,5 @@ import PySimpleGUI as sg -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - names = ['Roberta', 'Kylie', 'Jenny', 'Helen', 'Andrea', 'Meredith', 'Deborah', 'Pauline', 'Belinda', 'Wendy'] diff --git a/DemoPrograms/Demo_Listbox_Using_Objects.py b/DemoPrograms/Demo_Listbox_Using_Objects.py deleted file mode 100644 index 3b33ca071..000000000 --- a/DemoPrograms/Demo_Listbox_Using_Objects.py +++ /dev/null @@ -1,47 +0,0 @@ -import PySimpleGUI as sg - -""" - Demo - Listbox Using Objects - - Several elements can take not just strings, but objects. The Listsbox is one of them. - This demo show how you can use objects directly in a Listbox in a way that you can access - information about each object that is different than what is shown in the Window. - - The important part of this design pattern is the use of the __str__ method in your item objects. - This method is what determines what is shown in the window. - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - -class Item(): - def __init__(self, internal, shown): - self.internal = internal - self.shown = shown - - def __str__(self): - return self.shown - -# make list of some objects -my_item_list = [Item(f'Internal {i}', f'shown {i}') for i in range(100)] - -layout = [ [sg.Text('Select 1 or more items and click "Go"')], - [sg.Listbox(my_item_list, key='-LB-', s=(20,20), select_mode=sg.LISTBOX_SELECT_MODE_EXTENDED)], - [sg.Output(s=(40,10))], - [sg.Button('Go'), sg.Button('Exit')] ] - -window = sg.Window('Listbox Using Objects', layout) - -while True: - event, values = window.read() - # print(event, values) - if event == sg.WIN_CLOSED or event == 'Exit': - break - elif event == 'Go': - print('You selected:') - for item in values['-LB-']: - print(item.internal) -window.close() diff --git a/DemoPrograms/Demo_Long_Operations.py b/DemoPrograms/Demo_Long_Operations.py index 375151cf0..a194c19ef 100644 --- a/DemoPrograms/Demo_Long_Operations.py +++ b/DemoPrograms/Demo_Long_Operations.py @@ -22,11 +22,7 @@ When you function completes, you will receive an event when calling window.read() that matches the key provided. - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ diff --git a/DemoPrograms/Demo_Look_And_Feel_Theme_Browser.py b/DemoPrograms/Demo_Look_And_Feel_Theme_Browser.py index 159c17f46..1665f3627 100644 --- a/DemoPrograms/Demo_Look_And_Feel_Theme_Browser.py +++ b/DemoPrograms/Demo_Look_And_Feel_Theme_Browser.py @@ -5,12 +5,6 @@ Popup window using the color scheme you chose. It's a simply little program that demonstrates how snappy a GUI can feel if you enable an element's events rather than waiting on a button click. In this program, as soon as a listbox entry is clicked, the read returns. - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ sg.change_look_and_feel('GreenTan') diff --git a/DemoPrograms/Demo_Look_And_Feel_Theme_Dump.py b/DemoPrograms/Demo_Look_And_Feel_Theme_Dump.py index cf613089f..0c5d60fe2 100644 --- a/DemoPrograms/Demo_Look_And_Feel_Theme_Dump.py +++ b/DemoPrograms/Demo_Look_And_Feel_Theme_Dump.py @@ -5,12 +5,6 @@ """ If you're using the PySimpleGUI color themes, then your code will a line that looks something like this: sg.change_look_and_feel('Light Green 1') or sg.change_look_and_feel('LightGreen1') - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ # Use the built-in Theme Viewer to show all of the themes and their names diff --git a/DemoPrograms/Demo_MIDI_Player.py b/DemoPrograms/Demo_MIDI_Player.py index 93f2c8110..a66c41d54 100644 --- a/DemoPrograms/Demo_MIDI_Player.py +++ b/DemoPrograms/Demo_MIDI_Player.py @@ -4,14 +4,6 @@ import mido import time -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - PLAYER_COMMAND_NONE = 0 PLAYER_COMMAND_EXIT = 1 PLAYER_COMMAND_PAUSE = 2 diff --git a/DemoPrograms/Demo_Machine_Learning.py b/DemoPrograms/Demo_Machine_Learning.py index c39c3be45..a21c2f39d 100644 --- a/DemoPrograms/Demo_Machine_Learning.py +++ b/DemoPrograms/Demo_Machine_Learning.py @@ -2,14 +2,6 @@ import sys import PySimpleGUI as sg -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - def MachineLearningGUI(): sg.set_options(text_justification='right') diff --git a/DemoPrograms/Demo_Main_Control_Test_Panel.py b/DemoPrograms/Demo_Main_Control_Test_Panel.py index bbac4226a..bc4e09875 100644 --- a/DemoPrograms/Demo_Main_Control_Test_Panel.py +++ b/DemoPrograms/Demo_Main_Control_Test_Panel.py @@ -3,12 +3,6 @@ """ This is a simple as it gets. Calls the "main" function which is the PySimpleGUI Test Harness or Control Panel of sorts. Use it to view themes, upgrade your PySimpleGUI to the GitHub version, etc. - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ sg.main() diff --git a/DemoPrograms/Demo_Make_Windows_Shortcut.ico b/DemoPrograms/Demo_Make_Windows_Shortcut.ico new file mode 100644 index 000000000..2b86085e5 Binary files /dev/null and b/DemoPrograms/Demo_Make_Windows_Shortcut.ico differ diff --git a/DemoPrograms/Demo_Make_Windows_Shortcut.pyw b/DemoPrograms/Demo_Make_Windows_Shortcut.pyw new file mode 100644 index 000000000..4b2c4fdc7 --- /dev/null +++ b/DemoPrograms/Demo_Make_Windows_Shortcut.pyw @@ -0,0 +1,203 @@ +import PySimpleGUI as sg +from win32com.client import Dispatch +import os + +""" + Demo Program = Make Windows Shortcut + + Creates a shortcut to your python file (or EXE file or anything that you want to make a shortcut to) + + Input just the .PY or .PYW file + or... + Optionally Add: + - The interpreter to use + - An icon for your shortcut + - A new name for the shortcut + + Copyright 2021 PySimpleGUI +""" + +''' +MM""""""""`M +MM mmmmmmmM +M' MMMM .d8888b. 88d888b. 88d888b. dP dP +MM MMMMMMMM 88' `88 88' `88 88' `88 88 88 +MM MMMMMMMM 88. .88 88 88. .88 88. .88 +MM MMMMMMMM `88888P' dP 88Y888P' `8888P88 +MMMMMMMMMMMM 88 .88 + dP d8888P +.8888b oo dP +88 " 88 +88aaa dP 88 .d8888b. .d8888b. +88 88 88 88ooood8 Y8ooooo. +88 88 88 88. ... 88 +dP dP dP `88888P' `88888P' +''' + + +def create_shortcut_for_python_file(arguments='', target='', icon='', new_name=''): + """ + Create a shortcut for a given target filename + :param arguments str: full arguments and filename to make link to + :param target str: what to launch (e.g. python) + :param icon str: .ICO file + :return: filename of the created shortcut file + :rtype: str + """ + filename, ext = os.path.splitext(arguments) + working_dir = os.path.dirname(target) + shell = Dispatch('WScript.Shell') + if new_name: + shortcut_filename = new_name + ".lnk" + else: + shortcut_filename = filename + ".lnk" + shortcut_filename = os.path.join(os.path.dirname(arguments), shortcut_filename) + shortcut = shell.CreateShortCut(f'{shortcut_filename}') + shortcut.Targetpath = str(target) + shortcut.Arguments = f'"{arguments}"' + shortcut.WorkingDirectory = working_dir + if icon == '': + pass + else: + shortcut.IconLocation = icon + shortcut.save() + return shortcut_filename + + +''' +MM""""""""`M dP dP +MM mmmmmmmM 88 88 +M' MMMM .d8888b. 88d888b. .d8888b. d8888P 88d888b. .d8888b. 88d888b. +MM MMMMMMMM 88' `88 88' `88 88' `88 88 88' `88 88ooood8 88' `88 +MM MMMMMMMM 88. .88 88 88. .88 88 88 88 88. ... 88 +MM MMMMMMMM `88888P' dP `88888P' dP dP dP `88888P' dP +MMMMMMMMMMMM + +.8888b oo dP +88 " 88 +88aaa dP 88 .d8888b. .d8888b. +88 88 88 88ooood8 Y8ooooo. +88 88 88 88. ... 88 +dP dP dP `88888P' `88888P' +''' + + +def create_shortcut_exe_or_other(arguments='', target='', icon='', new_name=''): + """ + Create a shortcut for a given target filename + :param arguments str: full arguments and filename to make link to + :param target str: what to launch (e.g. python) + :param icon str: .ICO file + :return: filename of the created shortcut file + :rtype: str + """ + filename, ext = os.path.splitext(target) + working_dir = os.path.dirname(target) + shell = Dispatch('WScript.Shell') + if new_name: + shortcut_filename = new_name + ".lnk" + else: + shortcut_filename = filename + ".lnk" + shortcut_filename = os.path.join(os.path.dirname(target), shortcut_filename) + shortcut = shell.CreateShortCut(shortcut_filename) + shortcut.Targetpath = str(target) + shortcut.Arguments = f'"{arguments}"' + shortcut.WorkingDirectory = working_dir + if icon == '': + pass + else: + shortcut.IconLocation = icon + shortcut.save() + return shortcut_filename + + +def shortcut_exists(target, new_name=''): + filename, ext = os.path.splitext(target) + filename = new_name if new_name != '' else filename + shortcut_filename = filename + ".lnk" + shortcut_filename = os.path.join(os.path.dirname(target), shortcut_filename) + print('looking for exists filename', shortcut_filename) + return os.path.exists(shortcut_filename) + + +def shortcut_delete(target, new_name=''): + filename, ext = os.path.splitext(target) + filename = new_name if new_name != '' else filename + shortcut_filename = filename + ".lnk" + shortcut_filename = os.path.join(os.path.dirname(target), shortcut_filename) + os.remove(shortcut_filename) + + +''' + oo + +88d8b.d8b. .d8888b. dP 88d888b. +88'`88'`88 88' `88 88 88' `88 +88 88 88 88. .88 88 88 88 +dP dP dP `88888P8 dP dP dP +''' + + +def main(): + main_icon = b'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAACWElEQVRYR7WXO2tVQRSFv7QWRmMIIggKAUW0SKNFGvMjFLsUooWPNIqVoqI2ShpFQbCwFNME/QMWggqCj0pQJIiSIkSSQgVRkHWZCTs7Z85rxg2Xe8+ZuXuts2ftNXOG+D+xE9gL7AH+AB+Aj8A3DzdUGH8CuAAcS+R9CpwLZAZTShK4HMA3tXioK8DVkgQErqQ2VoEvwF9gF7DFjYvorxIVqAJfe0ID+hg4Yq5vABdzCbQFj7h+/lgOga7gkcQKMBwupvoS6Asu3PfAgUDgdB8COeDZBMaBV8CIEVOV4Oo6MWsJbgNnM8CzRDgKLBnwOeBoC9OJU24B5838O8BMFw1MAs9DApVxq0n2ANgGvI0O54gJ7Iy59x04BHzqQuAkcD8kEZB8X3EKuGuS7wAWzfU1GY4j1MuKUwT0JC8NwKwptcS6nALX/VQFZJn7gHfAfEhQtwRenGNBL/L7H3WirSJglboA7A4JvAgHIjLJ17UX8CyMxYd5AzzxovUEfJt8BXS4iCENaCliTBmgdQ4H3GvTIZZAlcNdAq6bRCKjLTbGCUAdoMgiUOVwKq/K7ENEDwKfnSmllqC2ELECXkQyDKm5bWxwOGdayTwikOtwHtyLs7ECde3VVAEPvuZwTX+M46pAymCacuRuy4P8fQkUAY8Eui5BMfBIoIsIi4JHAvp+CEybRW9zrNb0rqehDbqKPrAZ0IuEDdnwi7CZHA4vF3Y8G9xWQL+rylvVCT+Bm4mDR1PnJCsQB7YH7z+eyPQogGtnKxKp88B+QN2hz++w470Or9lFgGOSf3MNjp/Wcz63AAAAAElFTkSuQmCC' + sg.set_options(keep_on_top=True) + python_command = sg.execute_py_get_interpreter() + if not python_command: + python_command = sys.executable + sg.theme('dark grey 13') + txt_size = 45 + + layout = [[sg.Text('Create Windows shortcut (Click Create Shortcut or return key to start)', font='_ 15')], + [sg.T('Python (.PY/.PYW), EXE or other file - (absolute path)', s=txt_size), sg.Input(key='-IN FILE-'), + sg.FileBrowse(file_types=(("Python Files", "*.py *.pyw *.PY *.PYW"),), )], + [sg.T('Icon file (optional)', s=txt_size), sg.Input(key='-ICON-'), sg.FileBrowse(file_types=(("Icon Files", "*.ico *.ICO",),), )], + [sg.T('Shortcut Name (optional)', s=txt_size), sg.Input(key='-SHORTCUT NAME-')], + [sg.T('Python Command (optional, required for pinning to taskbar)', s=txt_size), sg.Input(python_command, key='-PYTHON COMMAND-')], + [sg.T('Arguments (optional)', s=txt_size), sg.Input(key='-ARGUMENTS-')], + [sg.Button('Create Shortcut', bind_return_key=True), sg.Button('Exit')]] + + window = sg.Window('Create Windows Shortcut', layout, icon=main_icon, right_click_menu=['', ['Edit Me', 'Version', 'File Location', 'Exit']]) + + while True: + event, values = window.read() + # print(event, values) + if event in (sg.WIN_CLOSED, 'Exit'): + break + if event == 'Create Shortcut': + infile = values['-IN FILE-'].lower() + py_cmd = values['-PYTHON COMMAND-'] + if shortcut_exists(infile, values['-SHORTCUT NAME-']): + if sg.popup_yes_no('The shortcut already exists. Do you want to overwrite it?') == 'Yes': + shortcut_delete(infile, values['-SHORTCUT NAME-']) + else: + continue + try: + if '.pyw' in infile or '.py' in infile: + if values['-PYTHON COMMAND-']: + if '.pyw' in values['-IN FILE-'].lower(): # if a .pyw file specified, use pythonw to launch it + if 'pythonw' not in py_cmd: + py_cmd = py_cmd.replace('python.exe', 'pythonw.exe') + if py_cmd: + shortcut_name = create_shortcut_for_python_file(target=fr'{py_cmd}', arguments=values['-IN FILE-'], icon=values['-ICON-'], + new_name=values['-SHORTCUT NAME-']) + else: + shortcut_name = create_shortcut_exe_or_other(target=values['-IN FILE-'], icon=values['-ICON-'], new_name=values['-SHORTCUT NAME-']) + else: + shortcut_name = create_shortcut_exe_or_other(target=infile, arguments=values['-ARGUMENTS-'], icon=values['-ICON-'], + new_name=values['-SHORTCUT NAME-']) + choice = sg.popup('Done!', 'Created shortcut:', shortcut_name, custom_text=('Take me there', 'Close')) + if choice == 'Take me there': + sg.execute_command_subprocess(r'explorer.exe', os.path.dirname(shortcut_name)) + except Exception as e: + sg.popup_error('Error encountered', e) + elif event == 'Edit Me': + sg.execute_editor(__file__) + elif event == 'Version': + sg.popup_scrolled(sg.get_versions(), keep_on_top=True) + elif event == 'File Location': + sg.popup_scrolled('This Python file is:', __file__) + window.close() + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/DemoPrograms/Demo_Matplotlib.py b/DemoPrograms/Demo_Matplotlib.py new file mode 100644 index 000000000..4a281a4d0 --- /dev/null +++ b/DemoPrograms/Demo_Matplotlib.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python +from matplotlib.ticker import NullFormatter # useful for `logit` scale +import matplotlib.pyplot as plt +import numpy as np +from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg +import PySimpleGUI as sg +import matplotlib +matplotlib.use('TkAgg') + +""" +Demonstrates one way of embedding Matplotlib figures into a PySimpleGUI window. + +Basic steps are: + * Create a Canvas Element + * Layout form + * Display form (NON BLOCKING) + * Draw plots onto convas + * Display form (BLOCKING) + + Based on information from: https://matplotlib.org/3.1.0/gallery/user_interfaces/embedding_in_tk_sgskip.html + (Thank you Em-Bo & dirck) +""" + + +# ------------------------------- PASTE YOUR MATPLOTLIB CODE HERE ------------------------------- +# +# # Goal is to have your plot contained in the variable "fig" +# +# # Fixing random state for reproducibility +# np.random.seed(19680801) +# +# # make up some data in the interval ]0, 1[ +# y = np.random.normal(loc=0.5, scale=0.4, size=1000) +# y = y[(y > 0) & (y < 1)] +# y.sort() +# x = np.arange(len(y)) +# +# # plot with various axes scales +# plt.figure(1) +# +# # linear +# plt.subplot(221) +# plt.plot(x, y) +# plt.yscale('linear') +# plt.title('linear') +# plt.grid(True) +# +# # log +# plt.subplot(222) +# plt.plot(x, y) +# plt.yscale('log') +# plt.title('log') +# plt.grid(True) +# +# # symmetric log +# plt.subplot(223) +# plt.plot(x, y - y.mean()) +# plt.yscale('symlog', linthreshy=0.01) +# plt.title('symlog') +# plt.grid(True) +# +# # logit +# plt.subplot(224) +# plt.plot(x, y) +# plt.yscale('logit') +# plt.title('logit') +# plt.grid(True) +# plt.gca().yaxis.set_minor_formatter(NullFormatter()) +# plt.subplots_adjust(top=0.92, bottom=0.08, left=0.10, right=0.95, hspace=0.25, +# wspace=0.35) +# fig = plt.gcf() +# + + +fig = matplotlib.figure.Figure(figsize=(5, 4), dpi=100) +t = np.arange(0, 3, .01) +fig.add_subplot(111).plot(t, 2 * np.sin(2 * np.pi * t)) + +# ------------------------------- END OF YOUR MATPLOTLIB CODE ------------------------------- + +# ------------------------------- Beginning of Matplotlib helper code ----------------------- + +def draw_figure(canvas, figure): + figure_canvas_agg = FigureCanvasTkAgg(figure, canvas) + figure_canvas_agg.draw() + figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1) + return figure_canvas_agg + +# ------------------------------- Beginning of GUI CODE ------------------------------- + +# define the window layout +layout = [[sg.Text('Plot test')], + [sg.Canvas(key='-CANVAS-')], + [sg.Button('Ok')]] + +# create the form and show it without the plot +window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI', layout, finalize=True, element_justification='center', font='Helvetica 18') + +# add the plot to the window +fig_canvas_agg = draw_figure(window['-CANVAS-'].TKCanvas, fig) + +event, values = window.read() + +window.close() diff --git a/DemoPrograms/Demo_Matplotlib_Animated.py b/DemoPrograms/Demo_Matplotlib_Animated.py index 4a6bd8acb..9311613bc 100644 --- a/DemoPrograms/Demo_Matplotlib_Animated.py +++ b/DemoPrograms/Demo_Matplotlib_Animated.py @@ -4,14 +4,6 @@ from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, FigureCanvasAgg from matplotlib.figure import Figure -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - # Yet another usage of MatPlotLib with animations. def draw_figure(canvas, figure, loc=(0, 0)): diff --git a/DemoPrograms/Demo_Matplotlib_Animated_Scatter.py b/DemoPrograms/Demo_Matplotlib_Animated_Scatter.py index 746791bb4..e1dcd0810 100644 --- a/DemoPrograms/Demo_Matplotlib_Animated_Scatter.py +++ b/DemoPrograms/Demo_Matplotlib_Animated_Scatter.py @@ -4,14 +4,6 @@ import matplotlib.pyplot as plt from numpy.random import rand -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - def draw_figure(canvas, figure): figure_canvas_agg = FigureCanvasTkAgg(figure, canvas) figure_canvas_agg.draw() diff --git a/DemoPrograms/Demo_Matplotlib_Browser.py b/DemoPrograms/Demo_Matplotlib_Browser.py index df2163e0c..85c51c48d 100644 --- a/DemoPrograms/Demo_Matplotlib_Browser.py +++ b/DemoPrograms/Demo_Matplotlib_Browser.py @@ -16,13 +16,7 @@ * Draw plots onto convas * Display form (BLOCKING) -Each plotting function, complete with imports, was copied directly from Matplot examples page - -Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - -Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - -You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. +Each plotting function, complete with imports, was copied directly from Matplot examples page """ import numpy as np @@ -830,26 +824,15 @@ def get_rgb(): # The magic function that makes it possible.... glues together tkinter and pyplot using Canvas Widget def draw_figure(canvas, figure): - if not hasattr(draw_figure, 'canvas_packed'): - draw_figure.canvas_packed = {} figure_canvas_agg = FigureCanvasTkAgg(figure, canvas) figure_canvas_agg.draw() - widget = figure_canvas_agg.get_tk_widget() - if widget not in draw_figure.canvas_packed: - draw_figure.canvas_packed[widget] = figure - widget.pack(side='top', fill='both', expand=1) + figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1) return figure_canvas_agg - def delete_figure_agg(figure_agg): figure_agg.get_tk_widget().forget() - try: - draw_figure.canvas_packed.pop(figure_agg.get_tk_widget()) - except Exception as e: - print(f'Error removing {figure_agg} from list', e) plt.close('all') - # -------------------------------- GUI Starts Here -------------------------------# # fig = your figure you want to display. Assumption is that 'fig' holds the # # information to display. # @@ -890,9 +873,6 @@ def delete_figure_agg(figure_agg): choice = values['-LISTBOX-'][0] # get first listbox item chosen (returned as a list) func = fig_dict[choice] # get function to call from the dictionary window['-MULTILINE-'].update(inspect.getsource(func)) # show source code to function in multiline - try: - fig = func() # call function to get the figure - figure_agg = draw_figure(window['-CANVAS-'].TKCanvas, fig) # draw the figure - except Exception as e: - print('Exception in fucntion', e) + fig = func() # call function to get the figure + figure_agg = draw_figure(window['-CANVAS-'].TKCanvas, fig) # draw the figure window.close() \ No newline at end of file diff --git a/DemoPrograms/Demo_Matplotlib_Browser_Paned.py b/DemoPrograms/Demo_Matplotlib_Browser_Paned.py index dc49c0ae0..6344e89d6 100644 --- a/DemoPrograms/Demo_Matplotlib_Browser_Paned.py +++ b/DemoPrograms/Demo_Matplotlib_Browser_Paned.py @@ -17,12 +17,6 @@ * Display form (NON BLOCKING) * Draw plots onto convas * Display form (BLOCKING) - -Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - -Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - -You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ @@ -843,23 +837,14 @@ def get_rgb(): def draw_figure(canvas, figure): - if not hasattr(draw_figure, 'canvas_packed'): - draw_figure.canvas_packed = {} figure_canvas_agg = FigureCanvasTkAgg(figure, canvas) figure_canvas_agg.draw() - widget = figure_canvas_agg.get_tk_widget() - if widget not in draw_figure.canvas_packed: - draw_figure.canvas_packed[widget] = figure - widget.pack(side='top', fill='both', expand=1) + figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1) return figure_canvas_agg def delete_figure_agg(figure_agg): figure_agg.get_tk_widget().forget() - try: - draw_figure.canvas_packed.pop(figure_agg.get_tk_widget()) - except Exception as e: - print(f'Error removing {figure_agg} from list', e) plt.close('all') @@ -896,11 +881,13 @@ def delete_figure_agg(figure_agg): [sg.Col(col_listbox), col_instructions], ] # create the form and show it without the plot -window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI', layout, resizable=True, finalize=True) +window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI', + layout, resizable=True, finalize=True) canvas_elem = window['-CANVAS-'] multiline_elem = window['-MULTILINE-'] figure_agg = None + while True: event, values = window.read() if event in (sg.WIN_CLOSED, 'Exit'): @@ -915,8 +902,6 @@ def delete_figure_agg(figure_agg): func = fig_dict[choice] # show source code to function in multiline window['-MULTILINE-'].update(inspect.getsource(func)) - try: - fig = func() # call function to get the figure - figure_agg = draw_figure(window['-CANVAS-'].TKCanvas, fig) # draw the figure - except Exception as e: - print('Error in plotting', e) + fig = func() # call function to get the figure + figure_agg = draw_figure( + window['-CANVAS-'].TKCanvas, fig) # draw the figure diff --git a/DemoPrograms/Demo_Matplotlib_Embedded_TEMPLATE.py b/DemoPrograms/Demo_Matplotlib_Embedded_TEMPLATE.py index d7f097c75..9e336cb40 100644 --- a/DemoPrograms/Demo_Matplotlib_Embedded_TEMPLATE.py +++ b/DemoPrograms/Demo_Matplotlib_Embedded_TEMPLATE.py @@ -20,11 +20,7 @@ PySimpleGUI ports by only changing the import statement. tk, Qt, Web(Remi) all run this same code and produce identical results. - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ diff --git a/DemoPrograms/Demo_Matplotlib_Embedded_Toolbar.py b/DemoPrograms/Demo_Matplotlib_Embedded_Toolbar.py index cf16d24ae..2ba9f2b75 100644 --- a/DemoPrograms/Demo_Matplotlib_Embedded_Toolbar.py +++ b/DemoPrograms/Demo_Matplotlib_Embedded_Toolbar.py @@ -3,12 +3,7 @@ """ Embedding the Matplotlib toolbar into your application - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + """ # ------------------------------- This is to include a matplotlib figure in a Tkinter canvas diff --git a/DemoPrograms/Demo_Matplotlib_Grid_of_Graphs_Using_PIL.py b/DemoPrograms/Demo_Matplotlib_Grid_of_Graphs_Using_PIL.py index b91f80011..f42f26eec 100644 --- a/DemoPrograms/Demo_Matplotlib_Grid_of_Graphs_Using_PIL.py +++ b/DemoPrograms/Demo_Matplotlib_Grid_of_Graphs_Using_PIL.py @@ -26,13 +26,7 @@ * Draw plots onto convas * Display form (BLOCKING) -Each plotting function, complete with imports, was copied directly from Matplot examples page - -Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - -Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - -You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. +Each plotting function, complete with imports, was copied directly from Matplot examples page """ import numpy as np @@ -896,7 +890,7 @@ def convert_to_bytes(file_or_bytes, resize=None): if resize: new_width, new_height = resize scale = min(new_height/cur_height, new_width/cur_width) - img = img.resize((int(cur_width*scale), int(cur_height*scale)), PIL.Image.LANCZOS) + img = img.resize((int(cur_width*scale), int(cur_height*scale)), PIL.Image.ANTIALIAS) with io.BytesIO() as bio: img.save(bio, format="PNG") del img diff --git a/DemoPrograms/Demo_Matplotlib_Image_Elem.py b/DemoPrograms/Demo_Matplotlib_Image_Elem.py index 52980b374..2cf93fe59 100644 --- a/DemoPrograms/Demo_Matplotlib_Image_Elem.py +++ b/DemoPrograms/Demo_Matplotlib_Image_Elem.py @@ -15,11 +15,7 @@ The example graph can be found in the matplotlib gallery: https://matplotlib.org/stable/gallery/images_contours_and_fields/specgram_demo.html - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ diff --git a/DemoPrograms/Demo_Matplotlib_Image_Elem_Spetrogram_Animated.py b/DemoPrograms/Demo_Matplotlib_Image_Elem_Spetrogram_Animated.py index 41acd4c1c..f45b8c983 100644 --- a/DemoPrograms/Demo_Matplotlib_Image_Elem_Spetrogram_Animated.py +++ b/DemoPrograms/Demo_Matplotlib_Image_Elem_Spetrogram_Animated.py @@ -18,11 +18,7 @@ The example static graph can be found in the matplotlib gallery: https://matplotlib.org/stable/gallery/images_contours_and_fields/specgram_demo.html - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ np.random.seed(19801) diff --git a/DemoPrograms/Demo_Matplotlib_Image_Elem_Spetrogram_Animated_Threaded.py b/DemoPrograms/Demo_Matplotlib_Image_Elem_Spetrogram_Animated_Threaded.py index d2c807ad1..fca7102eb 100644 --- a/DemoPrograms/Demo_Matplotlib_Image_Elem_Spetrogram_Animated_Threaded.py +++ b/DemoPrograms/Demo_Matplotlib_Image_Elem_Spetrogram_Animated_Threaded.py @@ -3,6 +3,7 @@ from matplotlib.backends.backend_tkagg import FigureCanvasAgg import matplotlib.pyplot as plt import io +import threading import time """ @@ -24,11 +25,7 @@ The example static graph can be found in the matplotlib gallery: https://matplotlib.org/stable/gallery/images_contours_and_fields/specgram_demo.html - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ np.random.seed(19801) @@ -144,7 +141,7 @@ def main(): # define the window layout layout = [[sg.Text('Spectrogram Animated - Threaded', font='Helvetica 24')], [sg.pin(sg.Image(key='-IMAGE-'))], - [sg.T(k='-STATS-')], + [sg.T(size=(50, 1), k='-STATS-')], [sg.B('Animate', focus=True, k='-ANIMATE-')]] # create the form and show it without the plot @@ -159,7 +156,7 @@ def main(): if event == '-ANIMATE-': window['-IMAGE-'].update(visible=True) start_time = time.time() - window.start_thread(lambda: the_thread(window), '-THEAD FINISHED-') + threading.Thread(target=the_thread, args=(window,), daemon=True).start() elif event == '-THREAD-': plt.close('all') # close all plots... unclear if this is required window['-IMAGE-'].update(data=values[event].read()) @@ -173,7 +170,4 @@ def main(): if __name__ == '__main__': - # Newer versions of PySimpleGUI have an alias for this method that's called "start_thread" so that it's clearer what's happening - # In case you don't have that version installed this line of code creates the alias for you - sg.Window.start_thread = sg.Window.perform_long_operation main() \ No newline at end of file diff --git a/DemoPrograms/Demo_Matplotlib_Ping_Graph.py b/DemoPrograms/Demo_Matplotlib_Ping_Graph.py new file mode 100644 index 000000000..457464c9f --- /dev/null +++ b/DemoPrograms/Demo_Matplotlib_Ping_Graph.py @@ -0,0 +1,673 @@ +#!/usr/bin/env python +from matplotlib.backends.backend_tkagg import FigureCanvasAgg +import matplotlib.backends.tkagg as tkagg +import matplotlib.pyplot as plt +import PySimpleGUI as sg +import tkinter as tk + +""" +A graph of time to ping Google.com +Demonstrates Matploylib used in an animated way. + +Note this file contains a copy of ping.py. It is contained in the first part of this file + +""" + + +""" + A pure python ping implementation using raw sockets. + + (This is Python 3 port of https://github.com/jedie/python-ping) + (Tested and working with python 2.7, should work with 2.6+) + + Note that ICMP messages can only be sent from processes running as root + (in Windows, you must run this script as 'Administrator'). + + Derived from ping.c distributed in Linux's netkit. That code is + copyright (c) 1989 by The Regents of the University of California. + That code is in turn derived from code written by Mike Muuss of the + US Army Ballistic Research Laboratory in December, 1983 and + placed in the public domain. They have my thanks. + + Bugs are naturally mine. I'd be glad to hear about them. There are + certainly word - size dependencies here. + + Copyright (c) Matthew Dixon Cowles, . + Distributable under the terms of the GNU General Public License + version 2. Provided with no warranties of any sort. + + Original Version from Matthew Dixon Cowles: + -> ftp://ftp.visi.com/users/mdc/ping.py + + Rewrite by Jens Diemer: + -> http://www.python-forum.de/post-69122.html#69122 + + Rewrite by George Notaras: + -> http://www.g-loaded.eu/2009/10/30/python-ping/ + + Enhancements by Martin Falatic: + -> http://www.falatic.com/index.php/39/pinging-with-python + + Enhancements and fixes by Georgi Kolev: + -> http://github.com/jedie/python-ping/ + + Bug fix by Andrejs Rozitis: + -> http://github.com/rozitis/python-ping/ + + Revision history + ~~~~~~~~~~~~~~~~ + May 1, 2014 + ----------- + Little modifications by Mohammad Emami + - Added Python 3 support. For now this project will just support + python 3.x + - Tested with python 3.3 + - version was upped to 0.6 + + March 19, 2013 + -------------- + * Fixing bug to prevent divide by 0 during run-time. + + January 26, 2012 + ---------------- + * Fixing BUG #4 - competability with python 2.x [tested with 2.7] + - Packet data building is different for 2.x and 3.x. + 'cose of the string/bytes difference. + * Fixing BUG #10 - the multiple resolv issue. + - When pinging domain names insted of hosts (for exmaple google.com) + you can get different IP every time you try to resolv it, we should + resolv the host only once and stick to that IP. + * Fixing BUGs #3 #10 - Doing hostname resolv only once. + * Fixing BUG #14 - Removing all 'global' stuff. + - You should not use globul! Its bad for you...and its not thread safe! + * Fix - forcing the use of different times on linux/windows for + more accurate mesurments. (time.time - linux/ time.clock - windows) + * Adding quiet_ping function - This way we'll be able to use this script + as external lib. + * Changing default timeout to 3s. (1second is not enought) + * Switching data syze to packet size. It's easyer for the user to ignore the + fact that the packet headr is 8b and the datasize 64 will make packet with + size 72. + + October 12, 2011 + -------------- + Merged updates from the main project + -> https://github.com/jedie/python-ping + + September 12, 2011 + -------------- + Bugfixes + cleanup by Jens Diemer + Tested with Ubuntu + Windows 7 + + September 6, 2011 + -------------- + Cleanup by Martin Falatic. Restored lost comments and docs. Improved + functionality: constant time between pings, internal times consistently + use milliseconds. Clarified annotations (e.g., in the checksum routine). + Using unsigned data in IP & ICMP header pack/unpack unless otherwise + necessary. Signal handling. Ping-style output formatting and stats. + + August 3, 2011 + -------------- + Ported to py3k by Zach Ware. Mostly done by 2to3; also minor changes to + deal with bytes vs. string changes (no more ord() in checksum() because + >source_string< is actually bytes, added .encode() to data in + send_one_ping()). That's about it. + + March 11, 2010 + -------------- + changes by Samuel Stauffer: + - replaced time.clock with default_timer which is set to + time.clock on windows and time.time on other systems. + + November 8, 2009 + ---------------- + Improved compatibility with GNU/Linux systems. + + Fixes by: + * George Notaras -- http://www.g-loaded.eu + Reported by: + * Chris Hallman -- http://cdhallman.blogspot.com + + Changes in this release: + - Re-use time.time() instead of time.clock(). The 2007 implementation + worked only under Microsoft Windows. Failed on GNU/Linux. + time.clock() behaves differently under the two OSes[1]. + + [1] http://docs.python.org/library/time.html#time.clock + + May 30, 2007 + ------------ + little rewrite by Jens Diemer: + - change socket asterisk import to a normal import + - replace time.time() with time.clock() + - delete "return None" (or change to "return" only) + - in checksum() rename "str" to "source_string" + + December 4, 2000 + ---------------- + Changed the struct.pack() calls to pack the checksum and ID as + unsigned. My thanks to Jerome Poincheval for the fix. + + November 22, 1997 + ----------------- + Initial hack. Doesn't do much, but rather than try to guess + what features I (or others) will want in the future, I've only + put in what I need now. + + December 16, 1997 + ----------------- + For some reason, the checksum bytes are in the wrong order when + this is run under Solaris 2.X for SPARC but it works right under + Linux x86. Since I don't know just what's wrong, I'll swap the + bytes always and then do an htons(). + + =========================================================================== + IP header info from RFC791 + -> http://tools.ietf.org/html/rfc791) + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |Version| IHL |Type of Service| Total Length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Identification |Flags| Fragment Offset | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Time to Live | Protocol | Header Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Source Address | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Destination Address | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Options | Padding | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + =========================================================================== + ICMP Echo / Echo Reply Message header info from RFC792 + -> http://tools.ietf.org/html/rfc792 + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Identifier | Sequence Number | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Data ... + +-+-+-+-+- + + =========================================================================== + ICMP parameter info: + -> http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xml + + =========================================================================== + An example of ping's typical output: + + PING heise.de (193.99.144.80): 56 data bytes + 64 bytes from 193.99.144.80: icmp_seq=0 ttl=240 time=127 ms + 64 bytes from 193.99.144.80: icmp_seq=1 ttl=240 time=127 ms + 64 bytes from 193.99.144.80: icmp_seq=2 ttl=240 time=126 ms + 64 bytes from 193.99.144.80: icmp_seq=3 ttl=240 time=126 ms + 64 bytes from 193.99.144.80: icmp_seq=4 ttl=240 time=127 ms + + ----heise.de PING Statistics---- + 5 packets transmitted, 5 packets received, 0.0% packet loss + round-trip (ms) min/avg/max/med = 126/127/127/127 + + =========================================================================== +""" + +# =============================================================================# +import argparse +import os, sys, socket, struct, select, time, signal + +__description__ = 'A pure python ICMP ping implementation using raw sockets.' + +if sys.platform == "win32": + # On Windows, the best timer is time.clock() + default_timer = time.clock +else: + # On most other platforms the best timer is time.time() + default_timer = time.time + +NUM_PACKETS = 3 +PACKET_SIZE = 64 +WAIT_TIMEOUT = 3.0 + +# =============================================================================# +# ICMP parameters + +ICMP_ECHOREPLY = 0 # Echo reply (per RFC792) +ICMP_ECHO = 8 # Echo request (per RFC792) +ICMP_MAX_RECV = 2048 # Max size of incoming buffer + +MAX_SLEEP = 1000 + + +class MyStats: + thisIP = "0.0.0.0" + pktsSent = 0 + pktsRcvd = 0 + minTime = 999999999 + maxTime = 0 + totTime = 0 + avrgTime = 0 + fracLoss = 1.0 + + +myStats = MyStats # NOT Used globally anymore. + + +# =============================================================================# +def checksum(source_string): + """ + A port of the functionality of in_cksum() from ping.c + Ideally this would act on the string as a series of 16-bit ints (host + packed), but this works. + Network data is big-endian, hosts are typically little-endian + """ + countTo = (int(len(source_string) / 2)) * 2 + sum = 0 + count = 0 + + # Handle bytes in pairs (decoding as short ints) + loByte = 0 + hiByte = 0 + while count < countTo: + if (sys.byteorder == "little"): + loByte = source_string[count] + hiByte = source_string[count + 1] + else: + loByte = source_string[count + 1] + hiByte = source_string[count] + try: # For Python3 + sum = sum + (hiByte * 256 + loByte) + except: # For Python2 + sum = sum + (ord(hiByte) * 256 + ord(loByte)) + count += 2 + + # Handle last byte if applicable (odd-number of bytes) + # Endianness should be irrelevant in this case + if countTo < len(source_string): # Check for odd length + loByte = source_string[len(source_string) - 1] + try: # For Python3 + sum += loByte + except: # For Python2 + sum += ord(loByte) + + sum &= 0xffffffff # Truncate sum to 32 bits (a variance from ping.c, which + # uses signed ints, but overflow is unlikely in ping) + + sum = (sum >> 16) + (sum & 0xffff) # Add high 16 bits to low 16 bits + sum += (sum >> 16) # Add carry from above (if any) + answer = ~sum & 0xffff # Invert and truncate to 16 bits + answer = socket.htons(answer) + + return answer + + +# =============================================================================# +def do_one(myStats, destIP, hostname, timeout, mySeqNumber, packet_size, quiet=False): + """ + Returns either the delay (in ms) or None on timeout. + """ + delay = None + + try: # One could use UDP here, but it's obscure + mySocket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.getprotobyname("icmp")) + except socket.error as e: + print("failed. (socket error: '%s')" % e.args[1]) + raise # raise the original error + + my_ID = os.getpid() & 0xFFFF + + sentTime = send_one_ping(mySocket, destIP, my_ID, mySeqNumber, packet_size) + if sentTime == None: + mySocket.close() + return delay + + myStats.pktsSent += 1 + + recvTime, dataSize, iphSrcIP, icmpSeqNumber, iphTTL = receive_one_ping(mySocket, my_ID, timeout) + + mySocket.close() + + if recvTime: + delay = (recvTime - sentTime) * 1000 + if not quiet: + print("%d bytes from %s: icmp_seq=%d ttl=%d time=%d ms" % ( + dataSize, socket.inet_ntoa(struct.pack("!I", iphSrcIP)), icmpSeqNumber, iphTTL, delay) + ) + myStats.pktsRcvd += 1 + myStats.totTime += delay + if myStats.minTime > delay: + myStats.minTime = delay + if myStats.maxTime < delay: + myStats.maxTime = delay + else: + delay = None + print("Request timed out.") + + return delay + + +# =============================================================================# +def send_one_ping(mySocket, destIP, myID, mySeqNumber, packet_size): + """ + Send one ping to the given >destIP<. + """ + # destIP = socket.gethostbyname(destIP) + + # Header is type (8), code (8), checksum (16), id (16), sequence (16) + # (packet_size - 8) - Remove header size from packet size + myChecksum = 0 + + # Make a dummy heder with a 0 checksum. + header = struct.pack( + "!BBHHH", ICMP_ECHO, 0, myChecksum, myID, mySeqNumber + ) + + padBytes = [] + startVal = 0x42 + # 'cose of the string/byte changes in python 2/3 we have + # to build the data differnely for different version + # or it will make packets with unexpected size. + if sys.version[:1] == '2': + bytes = struct.calcsize("d") + data = ((packet_size - 8) - bytes) * "Q" + data = struct.pack("d", default_timer()) + data + else: + for i in range(startVal, startVal + (packet_size - 8)): + padBytes += [(i & 0xff)] # Keep chars in the 0-255 range + # data = bytes(padBytes) + data = bytearray(padBytes) + + # Calculate the checksum on the data and the dummy header. + myChecksum = checksum(header + data) # Checksum is in network order + + # Now that we have the right checksum, we put that in. It's just easier + # to make up a new header than to stuff it into the dummy. + header = struct.pack( + "!BBHHH", ICMP_ECHO, 0, myChecksum, myID, mySeqNumber + ) + + packet = header + data + + sendTime = default_timer() + + try: + mySocket.sendto(packet, (destIP, 1)) # Port number is irrelevant for ICMP + except socket.error as e: + print("General failure (%s)" % (e.args[1])) + return + + return sendTime + + +# =============================================================================# +def receive_one_ping(mySocket, myID, timeout): + """ + Receive the ping from the socket. Timeout = in ms + """ + timeLeft = timeout / 1000 + + while True: # Loop while waiting for packet or timeout + startedSelect = default_timer() + whatReady = select.select([mySocket], [], [], timeLeft) + howLongInSelect = (default_timer() - startedSelect) + if whatReady[0] == []: # Timeout + return None, 0, 0, 0, 0 + + timeReceived = default_timer() + + recPacket, addr = mySocket.recvfrom(ICMP_MAX_RECV) + + ipHeader = recPacket[:20] + iphVersion, iphTypeOfSvc, iphLength, \ + iphID, iphFlags, iphTTL, iphProtocol, \ + iphChecksum, iphSrcIP, iphDestIP = struct.unpack( + "!BBHHHBBHII", ipHeader + ) + + icmpHeader = recPacket[20:28] + icmpType, icmpCode, icmpChecksum, \ + icmpPacketID, icmpSeqNumber = struct.unpack( + "!BBHHH", icmpHeader + ) + + if icmpPacketID == myID: # Our packet + dataSize = len(recPacket) - 28 + # print (len(recPacket.encode())) + return timeReceived, (dataSize + 8), iphSrcIP, icmpSeqNumber, iphTTL + + timeLeft = timeLeft - howLongInSelect + if timeLeft <= 0: + return None, 0, 0, 0, 0 + + +# =============================================================================# +def dump_stats(myStats): + """ + Show stats when pings are done + """ + print("\n----%s PYTHON PING Statistics----" % (myStats.thisIP)) + + if myStats.pktsSent > 0: + myStats.fracLoss = (myStats.pktsSent - myStats.pktsRcvd) / myStats.pktsSent + + print("%d packets transmitted, %d packets received, %0.1f%% packet loss" % ( + myStats.pktsSent, myStats.pktsRcvd, 100.0 * myStats.fracLoss + )) + + if myStats.pktsRcvd > 0: + print("round-trip (ms) min/avg/max = %d/%0.1f/%d" % ( + myStats.minTime, myStats.totTime / myStats.pktsRcvd, myStats.maxTime + )) + + print("") + return + + +# =============================================================================# +def signal_handler(signum, frame): + """ + Handle exit via signals + """ + dump_stats() + print("\n(Terminated with signal %d)\n" % (signum)) + sys.exit(0) + + +# =============================================================================# +def verbose_ping(hostname, timeout=WAIT_TIMEOUT, count=NUM_PACKETS, + packet_size=PACKET_SIZE, path_finder=False): + """ + Send >count< ping to >destIP< with the given >timeout< and display + the result. + """ + signal.signal(signal.SIGINT, signal_handler) # Handle Ctrl-C + if hasattr(signal, "SIGBREAK"): + # Handle Ctrl-Break e.g. under Windows + signal.signal(signal.SIGBREAK, signal_handler) + + myStats = MyStats() # Reset the stats + + mySeqNumber = 0 # Starting value + + try: + destIP = socket.gethostbyname(hostname) + print("\nPYTHON PING %s (%s): %d data bytes" % (hostname, destIP, packet_size)) + except socket.gaierror as e: + print("\nPYTHON PING: Unknown host: %s (%s)" % (hostname, e.args[1])) + print() + return + + myStats.thisIP = destIP + + for i in range(count): + delay = do_one(myStats, destIP, hostname, timeout, mySeqNumber, packet_size) + + if delay == None: + delay = 0 + + mySeqNumber += 1 + + # Pause for the remainder of the MAX_SLEEP period (if applicable) + if (MAX_SLEEP > delay): + time.sleep((MAX_SLEEP - delay) / 1000) + + dump_stats(myStats) + +#=============================================================================# +def quiet_ping(hostname, timeout=WAIT_TIMEOUT, count=NUM_PACKETS, + packet_size=PACKET_SIZE, path_finder=False): + """ + Same as verbose_ping, but the results are returned as tuple + """ + myStats = MyStats() # Reset the stats + mySeqNumber = 0 # Starting value + + try: + destIP = socket.gethostbyname(hostname) + except socket.gaierror as e: + return 0,0,0,0 + + myStats.thisIP = destIP + + # This will send packet that we dont care about 0.5 seconds before it starts + # acrutally pinging. This is needed in big MAN/LAN networks where you sometimes + # loose the first packet. (while the switches find the way... :/ ) + if path_finder: + fakeStats = MyStats() + do_one(fakeStats, destIP, hostname, timeout, + mySeqNumber, packet_size, quiet=True) + time.sleep(0.5) + + for i in range(count): + delay = do_one(myStats, destIP, hostname, timeout, + mySeqNumber, packet_size, quiet=True) + + if delay == None: + delay = 0 + + mySeqNumber += 1 + + # Pause for the remainder of the MAX_SLEEP period (if applicable) + if (MAX_SLEEP > delay): + time.sleep((MAX_SLEEP - delay)/1000) + + if myStats.pktsSent > 0: + myStats.fracLoss = (myStats.pktsSent - myStats.pktsRcvd)/myStats.pktsSent + if myStats.pktsRcvd > 0: + myStats.avrgTime = myStats.totTime / myStats.pktsRcvd + + # return tuple(max_rtt, min_rtt, avrg_rtt, percent_lost) + return myStats.maxTime, myStats.minTime, myStats.avrgTime, myStats.fracLoss + +# =============================================================================# + + + +#================================================================================ +# Globals +# These are needed because callback functions are used. +# Need to retain state across calls +#================================================================================ +SIZE=(320,240) + +class MyGlobals: + axis_pings = None + ping_x_array = [] + ping_y_array = [] + +g_my_globals = MyGlobals() + +#================================================================================ +# Performs *** PING! *** +#================================================================================ +def run_a_ping_and_graph(): + global g_my_globals # graphs are global so that can be retained across multiple calls to this callback + + #===================== Do the ping =====================# + response = quiet_ping('google.com',timeout=1000) + if response[0] == 0: + ping_time = 1000 + else: + ping_time = response[0] + #===================== Store current ping in historical array =====================# + g_my_globals.ping_x_array.append(len(g_my_globals.ping_x_array)) + g_my_globals.ping_y_array.append(ping_time) + # ===================== Only graph last 100 items =====================# + if len(g_my_globals.ping_x_array) > 100: + x_array = g_my_globals.ping_x_array[-100:] + y_array = g_my_globals.ping_y_array[-100:] + else: + x_array = g_my_globals.ping_x_array + y_array = g_my_globals.ping_y_array + + # ===================== Call graphinc functions =====================# + g_my_globals.axis_ping.clear() # clear before graphing + set_chart_labels() + g_my_globals.axis_ping.plot(x_array,y_array) # graph the ping values + +#================================================================================ +# Function: Set graph titles and Axis labels +# Sets the text for the subplots +# Have to do this in 2 places... initially when creating and when updating +# So, putting into a function so don't have to duplicate code +#================================================================================ +def set_chart_labels(): + global g_my_globals + + g_my_globals.axis_ping.set_xlabel('Time', fontsize=8) + g_my_globals.axis_ping.set_ylabel('Ping (ms)', fontsize=8) + g_my_globals.axis_ping.set_title('Current Ping Duration', fontsize = 8) + +def draw(fig, canvas): + # Magic code that draws the figure onto the Canvas Element's canvas + figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds + figure_w, figure_h = int(figure_w), int(figure_h) + photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h) + canvas.create_image(SIZE[0] / 2, SIZE[1] / 2, image=photo) + figure_canvas_agg = FigureCanvasAgg(fig) + figure_canvas_agg.draw() + tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2) + return photo + +#================================================================================ +# Function: MAIN +#================================================================================ +def main(): + global g_my_globals + + # define the form layout + layout = [ + [ sg.Canvas(size=SIZE, background_color='white',key='canvas'), + sg.Button('Exit', pad=(0, (210, 0)))] + ] + + # create the form and show it without the plot + window = sg.Window('Ping Graph', layout, background_color='white', grab_anywhere=True, finalize=True) + + canvas_elem = window['canvas'] + canvas = canvas_elem.TKCanvas + + fig = plt.figure(figsize=(3.1, 2.25), tight_layout={'pad':0}) + g_my_globals.axis_ping = fig.add_subplot(1,1,1) + plt.rcParams['xtick.labelsize'] = 8 + plt.rcParams['ytick.labelsize'] = 8 + set_chart_labels() + plt.tight_layout() + + while True: + event, values = window.read(timeout=0) + if event in ('Exit', None): + break + + run_a_ping_and_graph() + photo = draw(fig, canvas) + + window.close() + +if __name__ == '__main__': + main() diff --git a/DemoPrograms/Demo_Matplotlib_Ping_Graph_Large.py b/DemoPrograms/Demo_Matplotlib_Ping_Graph_Large.py index 9794db4ad..c1f85fa77 100644 --- a/DemoPrograms/Demo_Matplotlib_Ping_Graph_Large.py +++ b/DemoPrograms/Demo_Matplotlib_Ping_Graph_Large.py @@ -1,23 +1,10 @@ #!/usr/bin/env python -from matplotlib.backends.backend_tkagg import FigureCanvasAgg +from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, FigureCanvasAgg +import matplotlib.backends.tkagg as tkagg import matplotlib.pyplot as plt import PySimpleGUI as sg -import io -import random -import time -import ping3 - -""" - Shows ping time to google.com using Matplotlib and ping3 module. - - Note that you will need to pip install ping3 for this demo program. - - Copyright 2023-2024 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" +import tkinter as tk +import ping # ================================================================================ # Globals @@ -39,13 +26,16 @@ class MyGlobals: # ================================================================================ -def graph_a_ping(ping_time): +def run_a_ping_and_graph(): # graphs are global so that can be retained across multiple calls to this callback global g_my_globals #===================== Do the ping =====================# - # Insert your code to run a ping - # ping_time = random.randint(0, 100) + response = ping.quiet_ping('google.com', timeout=1000) + if response[0] == 0: + ping_time = 1000 + else: + ping_time = response[0] #===================== Store current ping in historical array =====================# g_my_globals.ping_x_array.append(len(g_my_globals.ping_x_array)) g_my_globals.ping_y_array.append(ping_time) @@ -71,14 +61,6 @@ def graph_a_ping(ping_time): # ================================================================================ -def ping_thread(window: sg.Window): - while True: - # time.sleep(.1) - # ping_time = random.randint(0, 100) - ping_time = ping3.ping('google.com') - window.write_event_value('-THREAD-', ping_time) - - def set_chart_labels(): global g_my_globals @@ -87,25 +69,16 @@ def set_chart_labels(): g_my_globals.axis_ping.set_title('Current Ping Duration', fontsize=12) -def draw(element, figure): - """ - Draws the previously created "figure" in the supplied Image Element - - :param element: an Image Element - :param figure: a Matplotlib figure - :return: The figure canvas - """ - - # plt.close('all') # erases previously drawn plots - canv = FigureCanvasAgg(figure) - buf = io.BytesIO() - canv.print_figure(buf, format='png') - if buf is not None: - buf.seek(0) - element.update(data=buf.read()) - return canv - else: - return None +def draw(fig, canvas): + # Magic code that draws the figure onto the Canvas Element's canvas + figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds + figure_w, figure_h = int(figure_w), int(figure_h) + photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h) + canvas.create_image(640 / 2, 480 / 2, image=photo) + figure_canvas_agg = FigureCanvasAgg(fig) + figure_canvas_agg.draw() + tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2) + return photo # ================================================================================ # Function: MAIN @@ -118,28 +91,28 @@ def main(): # define the form layout layout = [[sg.Text('Animated Ping', size=(40, 1), justification='center', font='Helvetica 20')], - [sg.Image(size=(640, 480), key='-IMAGE-')], + [sg.Canvas(size=(640, 480), key='canvas')], [sg.Button('Exit', size=(10, 2), pad=((280, 0), 3), font='Helvetica 14')]] # create the form and show it without the plot window = sg.Window( 'Demo Application - Embedding Matplotlib In PySimpleGUI', layout, finalize=True) - image_elem = window['-IMAGE-'] + canvas_elem = window['canvas'] + canvas = canvas_elem.TKCanvas fig = plt.figure() g_my_globals.axis_ping = fig.add_subplot(1, 1, 1) set_chart_labels() plt.tight_layout() - window.start_thread(lambda: ping_thread(window)) + while True: event, values = window.read(timeout=0) if event in ('Exit', None): break - if event == '-THREAD-': - graph_a_ping(values[event]) - draw(image_elem, fig) + run_a_ping_and_graph() + photo = draw(fig, canvas) if __name__ == '__main__': diff --git a/DemoPrograms/Demo_Matplotlib_PyLab.py b/DemoPrograms/Demo_Matplotlib_PyLab.py index 9c2531efd..f12e17af3 100644 --- a/DemoPrograms/Demo_Matplotlib_PyLab.py +++ b/DemoPrograms/Demo_Matplotlib_PyLab.py @@ -7,12 +7,6 @@ """ Demonstrates one way of embedding PyLab figures into a PySimpleGUI window. - -Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - -Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - -You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ diff --git a/DemoPrograms/Demo_Matplotlib_Styles.py b/DemoPrograms/Demo_Matplotlib_Styles.py index 441e8de5c..12a72710f 100644 --- a/DemoPrograms/Demo_Matplotlib_Styles.py +++ b/DemoPrograms/Demo_Matplotlib_Styles.py @@ -20,11 +20,7 @@ This demo adds the ability to change the Window's "Theme" and the Matplotlib's "Style". It gives you a way to quickly see how well a theme is going to match a particular Matplotlib Style. - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ diff --git a/DemoPrograms/Demo_Matplotlib_Two_Windows.py b/DemoPrograms/Demo_Matplotlib_Two_Windows.py index cf20cc9ee..ffb71c147 100644 --- a/DemoPrograms/Demo_Matplotlib_Two_Windows.py +++ b/DemoPrograms/Demo_Matplotlib_Two_Windows.py @@ -8,12 +8,6 @@ A number of people have requested the ability to run a normal PySimpleGUI window that launches a MatplotLib window that is interactive with the usual Matplotlib controls. It turns out to be a rather simple thing to do. The secret is to add parameter block=False to plt.show() - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ def draw_plot(): diff --git a/DemoPrograms/Demo_Media_Player.py b/DemoPrograms/Demo_Media_Player.py index 758cf537c..cfd845c6f 100644 --- a/DemoPrograms/Demo_Media_Player.py +++ b/DemoPrograms/Demo_Media_Player.py @@ -1,14 +1,6 @@ #!/usr/bin/env python import PySimpleGUI as sg -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - # # An Async Demonstration of a media player # Uses button images for a super snazzy look diff --git a/DemoPrograms/Demo_Media_Player_VLC_Based.py b/DemoPrograms/Demo_Media_Player_VLC_Based.py new file mode 100644 index 000000000..9fa5aec80 --- /dev/null +++ b/DemoPrograms/Demo_Media_Player_VLC_Based.py @@ -0,0 +1,73 @@ +""" + Bare Bones Media Player Demo with Playlist. Adapeted from media player located at https://github.com/israel-dryer/Media-Player + Original Author : Israel Dryer + Modified to be a PySimpleGUI Demo Program + A very simple media player ready for you to customize. Uses the VLC player to playback local files and YouTube streams. You will need to install the Python bindings for VLC as well as the VLC player itself. + You will need to pip install: + pip install python-vlc + pip install youtube-dl +""" +import PySimpleGUI as sg +import vlc +from sys import platform as PLATFORM + +#------- GUI definition & setup --------# + +sg.theme('DarkBlue') + +def btn(name): # a PySimpleGUI "User Defined Element" (see docs) + return sg.Button(name, size=(6, 1), pad=(1, 1)) + +layout = [[sg.Input(default_text='Video URL or Local Path:', size=(30, 1), key='-VIDEO_LOCATION-'), sg.Button('load')], + [sg.Image('', size=(300, 170), key='-VID_OUT-')], + [btn('previous'), btn('play'), btn('next'), btn('pause'), btn('stop')], + [sg.Text('Load media to start', key='-MESSAGE_AREA-')]] + +window = sg.Window('Mini Player', layout, element_justification='center', finalize=True, resizable=True) + +window['-VID_OUT-'].expand(True, True) # type: sg.Element +#------------ Media Player Setup ---------# + +inst = vlc.Instance() +list_player = inst.media_list_player_new() +media_list = inst.media_list_new([]) +list_player.set_media_list(media_list) +player = list_player.get_media_player() +if PLATFORM.startswith('linux'): + player.set_xwindow(window['-VID_OUT-'].Widget.winfo_id()) +else: + player.set_hwnd(window['-VID_OUT-'].Widget.winfo_id()) + +#------------ The Event Loop ------------# +while True: + event, values = window.read(timeout=1000) # run with a timeout so that current location can be updated + if event == sg.WIN_CLOSED: + break + + if event == 'play': + list_player.play() + if event == 'pause': + list_player.pause() + if event == 'stop': + list_player.stop() + if event == 'next': + list_player.next() + list_player.play() + if event == 'previous': + list_player.previous() # first call causes current video to start over + list_player.previous() # second call moves back 1 video from current + list_player.play() + if event == 'load': + if values['-VIDEO_LOCATION-'] and not 'Video URL' in values['-VIDEO_LOCATION-']: + media_list.add_media(values['-VIDEO_LOCATION-']) + list_player.set_media_list(media_list) + window['-VIDEO_LOCATION-'].update('Video URL or Local Path:') # only add a legit submit + + # update elapsed time if there is a video loaded and the player is playing + if player.is_playing(): + window['-MESSAGE_AREA-'].update("{:02d}:{:02d} / {:02d}:{:02d}".format(*divmod(player.get_time()//1000, 60), + *divmod(player.get_length()//1000, 60))) + else: + window['-MESSAGE_AREA-'].update('Load media to start' if media_list.count() == 0 else 'Ready to play media' ) + +window.close() diff --git a/DemoPrograms/Demo_Menu_With_Toolbar.py b/DemoPrograms/Demo_Menu_With_Toolbar.py index e361c860d..3ab552aac 100644 --- a/DemoPrograms/Demo_Menu_With_Toolbar.py +++ b/DemoPrograms/Demo_Menu_With_Toolbar.py @@ -2,14 +2,6 @@ import sys import PySimpleGUI as sg -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - # Usage of icons as base64 string and toolbar house64 = 'data:image/png;base64,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' diff --git a/DemoPrograms/Demo_Menubar_Custom.py b/DemoPrograms/Demo_Menubar_Custom.py index af3d4fd37..e905e86e9 100644 --- a/DemoPrograms/Demo_Menubar_Custom.py +++ b/DemoPrograms/Demo_Menubar_Custom.py @@ -29,11 +29,7 @@ The color choice for the menubar background and text use the theme's button colors. You can change these color choices by changing the Menubar in the layout. - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ def main(): @@ -43,7 +39,7 @@ def main(): # sg.theme('black') menu_def = [['&File', ['&Open Ctrl-O', '&Save Ctrl-S', '&Properties', 'E&xit']], - ['&Edit', ['Edit Me', 'Special', 'Normal',['Normal1', 'Normal2'] , 'Undo']], + ['&Edit', ['Me', 'Special', 'Normal',['Normal1', 'Normal2'] , 'Undo']], ['!Disabled', ['Special', 'Normal',['Normal1', 'Normal2'], 'Undo']], ['&Toolbar', ['---', 'Command &1::Command_Key', 'Command &2', '---', 'Command &3', 'Command &4']], ['&Help', ['&About...']], ] @@ -51,7 +47,7 @@ def main(): layout = [[sg.MenubarCustom(menu_def, pad=(0,0), k='-CUST MENUBAR-')], [sg.Multiline(size=(70, 20), reroute_cprint=True, write_only=True, no_scrollbar=True, k='-MLINE-')]] - window = sg.Window("Custom Titlebar with Custom (Simulated) Menubar", layout, use_custom_titlebar=True, keep_on_top=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT) + window = sg.Window("Custom Titlebar with Custom (Simulated) Menubar", layout, use_custom_titlebar=True, keep_on_top=True) # ------ Event Loop ------ # while True: @@ -70,10 +66,8 @@ def main(): sg.popup('About this program', 'Simulated Menubar to accompany a simulated Titlebar', 'PySimpleGUI Version', sg.get_versions(), grab_anywhere=True, keep_on_top=True) window.reappear() - elif event == 'Edit Me': + elif event == 'Me': sg.execute_editor(__file__) - elif event == 'Version': - sg.popup_scrolled(__file__, sg.get_versions(), keep_on_top=True, non_blocking=True) elif event.startswith('Open'): filename = sg.popup_get_file('file to open', no_window=True) print(filename) diff --git a/DemoPrograms/Demo_Menubar_Custom_and_Traditional.py b/DemoPrograms/Demo_Menubar_Custom_and_Traditional.py index 782f21a2f..b188c48a1 100644 --- a/DemoPrograms/Demo_Menubar_Custom_and_Traditional.py +++ b/DemoPrograms/Demo_Menubar_Custom_and_Traditional.py @@ -15,11 +15,7 @@ The color choice for the menubar background and text use the theme's button colors. You can change these color choices by changing the Menubar in the layout. - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ sg.MENU_SHORTCUT_CHARACTER = '&' @@ -55,8 +51,10 @@ def Menubar(menu_def, text_color, background_color, pad=(0, 0)): def main(): sg.theme('dark green 7') + sg.theme('dark amber') + # sg.theme('dark purple 3') - menu_def = [['&File', ['&Open & Ctrl-O', '&Save & Ctrl-S', '&Properties', 'E&xit']], + menu_def = [['&File', ['&Open Ctrl-O', '&Save Ctrl-S', '&Properties', 'E&xit']], ['&Edit', [['Special', 'Normal',['Normal1', 'Normal2'] ], 'Undo'], ], ['!Disabled', [['Special', 'Normal',['Normal1', 'Normal2'] ], 'Undo'], ], ['&Toolbar', ['---', 'Command &1::Command_Key', 'Command &2', '---', 'Command &3', 'Command &4']], @@ -80,13 +78,13 @@ def main(): layout3 = [[sg.Multiline(size=(70, 20), reroute_stdout=True, reroute_cprint=True, write_only=True)],] - window = sg.Window("Custom Titlebar and Menu", layout, use_custom_titlebar=True, finalize=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT) + window = sg.Window("Custom Titlebar and Menu", layout, use_custom_titlebar=True, finalize=True) win_loc = window.current_location() - window2 = sg.Window("Traditional Titlebar and Menu", layout2, finalize=True, location=(win_loc[0]-window.size[0]-40, win_loc[1]), right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT) + window2 = sg.Window("Traditional Titlebar and Menu", layout2, finalize=True, location=(win_loc[0]-window.size[0]-40, win_loc[1])) - window3 = sg.Window("Output Window", layout3, finalize=True, location=(int(win_loc[0]-window.size[0]//1.5), int(win_loc[1]+window.size[1]+30)), use_custom_titlebar=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT) + window3 = sg.Window("Output Window", layout3, finalize=True, location=(win_loc[0]-window.size[0]//1.5, win_loc[1]+window.size[1]+30), use_custom_titlebar=True) # ------ Event Loop ------ # @@ -99,10 +97,6 @@ def main(): if event in (sg.WIN_CLOSED, 'Exit'): break - elif event == 'Edit Me': - sg.execute_editor(__file__) - elif event == 'Version': - sg.popup_scrolled(__file__, sg.get_versions(), keep_on_top=True, non_blocking=True) sg.cprint(f'event = {event}', c='white on red') sg.cprint(f'values = {values}', c='white on green') diff --git a/DemoPrograms/Demo_Menus.py b/DemoPrograms/Demo_Menus.py index ae28d203c..cc545376d 100644 --- a/DemoPrograms/Demo_Menus.py +++ b/DemoPrograms/Demo_Menus.py @@ -1,17 +1,10 @@ #!/usr/bin/env python import PySimpleGUI as sg - """ - Demo of Menu element, ButtonMenu element and right-click menus - - The same basic structure is used for all menus in PySimpleGUI. - Each entry is a list of items to display. If any of those items is a list, then a cancade menu is added. - - Copyright 2018-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Demonstration of MENUS! + How do menus work? Like buttons is how. + Check out the variable menu_def for a hint on how to + define menus """ @@ -31,22 +24,20 @@ def test_menus(): sg.set_options(element_padding=(0, 0)) # ------ Menu Definition ------ # - menu_def = [ - ['&File', ['&Open Ctrl-O', '&Save Ctrl-S', '&Properties', 'E&xit']], - ['&Edit', ['&Paste', ['Special', 'Normal', ], 'Undo', 'Options::this_is_a_menu_key'], ], + menu_def = [['&File', ['&Open Ctrl-O', '&Save Ctrl-S', '&Properties', 'E&xit']], + ['&Edit', ['&Paste', ['Special', 'Normal', ], 'Undo'], ], ['&Toolbar', ['---', 'Command &1', 'Command &2', '---', 'Command &3', 'Command &4']], - ['&Help', ['&About...']] - ] + ['&Help', '&About...'], ] right_click_menu = ['Unused', ['Right', '!&Click', '&Menu', 'E&xit', 'Properties']] # ------ GUI Defintion ------ # layout = [ - [sg.Menu(menu_def, tearoff=True, font='_ 12', key='-MENUBAR-')], + [sg.Menu(menu_def, tearoff=False, pad=(200, 1))], [sg.Text('Right click me for a right click menu example')], [sg.Output(size=(60, 20))], - [sg.ButtonMenu('ButtonMenu', right_click_menu, key='-BMENU-', text_color='red', disabled_text_color='green'), sg.Button('Plain Button')], + [sg.ButtonMenu('ButtonMenu', right_click_menu, key='-BMENU-'), sg.Button('Plain Button')], ] window = sg.Window("Windows-like program", @@ -64,7 +55,8 @@ def test_menus(): # ------ Process menu choices ------ # if event == 'About...': window.disappear() - sg.popup('About this program', 'Version 1.0', 'PySimpleGUI Version', sg.get_versions()) + sg.popup('About this program', 'Version 1.0', + 'PySimpleGUI Version', sg.version, grab_anywhere=True) window.reappear() elif event == 'Open': filename = sg.popup_get_file('file to open', no_window=True) diff --git a/DemoPrograms/Demo_Multi_Window_read_all_windows.py b/DemoPrograms/Demo_Multi_Window_read_all_windows.py deleted file mode 100644 index 930da0a57..000000000 --- a/DemoPrograms/Demo_Multi_Window_read_all_windows.py +++ /dev/null @@ -1,50 +0,0 @@ -import PySimpleGUI as sg - -""" - Read all windows example - The input elements are shown as output on the other window when "Go" is pressed - The checkboxes on window 1 are mirrored on window 2 if "mirror" checkbox is set - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" -layout1 = [ [sg.Text('My Window')], - [sg.Input(k='-IN-'), sg.Text(k='-OUT-')], - [sg.CB('Check 1', k='-CB1-', enable_events=True), sg.CB('Check 2', k='-CB2-', enable_events=True), sg.CB('Mirror on Window 2', enable_events=True, k='-CB3-')], - [sg.Button('Go'), sg.Button('Exit')] ] - -window1 = sg.Window('Window 1 Title', layout1, finalize=True, grab_anywhere=True, relative_location=(-600, 0)) - -layout2 = [ [sg.Text('My Window')], - [sg.Input(k='-IN-'), sg.Text(k='-OUT-')], - [sg.CB('Check 1', k='-CB1-'), sg.CB('Check 2', k='-CB2-')], - [sg.Button('Go'), sg.Button('Exit')] ] - -window2 = sg.Window('Window 2 Title', layout2, finalize=True, grab_anywhere=True) - -while True: # Event Loop - window, event, values = sg.read_all_windows() - if window is None: - print('exiting because no windows are left') - break - print(window.Title, event, values) if window is not None else None - if event == sg.WIN_CLOSED or event == 'Exit': - window.close() - if event == 'Go': - # Output the input element to the other windwow - try: # try to update the other window - if window == window1: - window2['-OUT-'].update(values['-IN-']) - else: - window1['-OUT-'].update(values['-IN-']) - except: - pass - try: - if window == window1 and values['-CB3-']: - window2['-CB1-'].update(values['-CB1-']) - window2['-CB2-'].update(values['-CB2-']) - except: - pass diff --git a/DemoPrograms/Demo_Multiline_Elem_Input_Justification.py b/DemoPrograms/Demo_Multiline_Elem_Input_Justification.py index 309b94974..7eebf14c6 100644 --- a/DemoPrograms/Demo_Multiline_Elem_Input_Justification.py +++ b/DemoPrograms/Demo_Multiline_Elem_Input_Justification.py @@ -13,11 +13,7 @@ * If get mline element event * Set the contents of the multline to be the correct justificaiton - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ import PySimpleGUI as sg diff --git a/DemoPrograms/Demo_Multiline_Multicolored_Text.py b/DemoPrograms/Demo_Multiline_Multicolored_Text.py index 9593f7bae..b32671928 100644 --- a/DemoPrograms/Demo_Multiline_Multicolored_Text.py +++ b/DemoPrograms/Demo_Multiline_Multicolored_Text.py @@ -4,11 +4,7 @@ """ Demonstration of how to work with multiple colors and fonts when outputting text to a multiline element or with Debug Print - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ MLINE_KEY = '-MLINE-' diff --git a/DemoPrograms/Demo_Multiline_Right_Click_Menu_Clipboard.py b/DemoPrograms/Demo_Multiline_Right_Click_Menu_Clipboard.py index 739b51907..d667dfb4a 100644 --- a/DemoPrograms/Demo_Multiline_Right_Click_Menu_Clipboard.py +++ b/DemoPrograms/Demo_Multiline_Right_Click_Menu_Clipboard.py @@ -19,11 +19,7 @@ running in order to access the clipboard. Upon exit, your clipboard will be deleted. You can get around this by using other clipboard packages. - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ right_click_menu = ['', ['Copy', 'Paste', 'Select All', 'Cut']] diff --git a/DemoPrograms/Demo_Multiline_cprint_Printing.py b/DemoPrograms/Demo_Multiline_cprint_Printing.py index 2890a23f2..db2b3248f 100644 --- a/DemoPrograms/Demo_Multiline_cprint_Printing.py +++ b/DemoPrograms/Demo_Multiline_cprint_Printing.py @@ -15,11 +15,7 @@ 3. Specify c/colors parameter a tuple with (text color, background color) 4. Specify c/colors parameter as a string "text on background" e.g. "white on red" - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ def main(): diff --git a/DemoPrograms/Demo_Multiple_Windows_Experimental.py b/DemoPrograms/Demo_Multiple_Windows_Experimental.py index 8e2cd6ccf..43f931b74 100644 --- a/DemoPrograms/Demo_Multiple_Windows_Experimental.py +++ b/DemoPrograms/Demo_Multiple_Windows_Experimental.py @@ -3,12 +3,6 @@ ''' Parallel windows executing. - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. ''' layout1 = [[ sg.Text('Window 1') ], diff --git a/DemoPrograms/Demo_Multiple_Windows_read_all_windows_25_lines.py b/DemoPrograms/Demo_Multiple_Windows_read_all_windows_25_lines.py index 9aae4b4ba..ff22a4a93 100644 --- a/DemoPrograms/Demo_Multiple_Windows_read_all_windows_25_lines.py +++ b/DemoPrograms/Demo_Multiple_Windows_read_all_windows_25_lines.py @@ -5,11 +5,7 @@ Super-simple, 25 lines of code. - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ import PySimpleGUI as sg diff --git a/DemoPrograms/Demo_Multithreaded_Animated_Shell_Command.py b/DemoPrograms/Demo_Multithreaded_Animated_Shell_Command.py index 1e58f5883..b31d20f57 100644 --- a/DemoPrograms/Demo_Multithreaded_Animated_Shell_Command.py +++ b/DemoPrograms/Demo_Multithreaded_Animated_Shell_Command.py @@ -14,12 +14,6 @@ waiting for the thread to complete running. The output from the subprocess is saved and displayed in a scrolled popup. - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ diff --git a/DemoPrograms/Demo_Multithreaded_Calling_Popup.py b/DemoPrograms/Demo_Multithreaded_Calling_Popup.py index 18d63dd87..a16fbecc5 100644 --- a/DemoPrograms/Demo_Multithreaded_Calling_Popup.py +++ b/DemoPrograms/Demo_Multithreaded_Calling_Popup.py @@ -12,11 +12,7 @@ except for Window.write_event_value() Cuation - This method still has a risk of tkinter crashing - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ diff --git a/DemoPrograms/Demo_Multithreaded_DataPump.py b/DemoPrograms/Demo_Multithreaded_DataPump.py deleted file mode 100644 index 3f0cf8759..000000000 --- a/DemoPrograms/Demo_Multithreaded_DataPump.py +++ /dev/null @@ -1,146 +0,0 @@ -import PySimpleGUI as sg -import random -import time -import queue - -""" - Demo - Multi-threaded "Data Pump" Design Pattern - - Send data to your PySimpleGUI program through a Python Queue, enabling integration with many - different types of data sources. - - A thread gets data from a queue object and passes it over to the main event loop. - The external_thread is only used here to generaate random data. It's not part of the - overall "Design Pattern". - - The thread the_thread IS part of the design pattern. It reads data from the thread_queue and sends that - data over to the PySimpleGUI event loop. - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - -gsize = (400, 400) # size of the graph - -THREAD_KEY = '-THREAD-' -THREAD_INCOMING_DATA = '-INCOMING DATA-' -THREAD_EXITNG = '-THREAD EXITING-' -THREAD_EXTERNAL_EXITNG = '-EXTERNAL THREAD EXITING-' - -# This queue is where you will send your data that you want to eventually arrive as an event -thread_queue = queue.Queue() - -# M""""""""M dP dP -# Mmmm mmmM 88 88 -# MMMM MMMM 88d888b. 88d888b. .d8888b. .d8888b. .d888b88 -# MMMM MMMM 88' `88 88' `88 88ooood8 88' `88 88' `88 -# MMMM MMMM 88 88 88 88. ... 88. .88 88. .88 -# MMMM MMMM dP dP dP `88888P' `88888P8 `88888P8 -# MMMMMMMMMM -# -# MP""""""`MM oo dP dP oo -# M mmmmm..M 88 88 -# M. `YM dP 88d8b.d8b. dP dP 88 .d8888b. d8888P dP 88d888b. .d8888b. -# MMMMMMM. M 88 88'`88'`88 88 88 88 88' `88 88 88 88' `88 88' `88 -# M. .MMM' M 88 88 88 88 88. .88 88 88. .88 88 88 88 88 88. .88 -# Mb. .dM dP dP dP dP `88888P' dP `88888P8 dP dP dP dP `8888P88 -# MMMMMMMMMMM .88 -# d8888P -# M""""""'YMM dP MP""""""`MM -# M mmmm. `M 88 M mmmmm..M -# M MMMMM M .d8888b. d8888P .d8888b. M. `YM .d8888b. dP dP 88d888b. .d8888b. .d8888b. -# M MMMMM M 88' `88 88 88' `88 MMMMMMM. M 88' `88 88 88 88' `88 88' `"" 88ooood8 -# M MMMM' .M 88. .88 88 88. .88 M. .MMM' M 88. .88 88. .88 88 88. ... 88. ... -# M .MM `88888P8 dP `88888P8 Mb. .dM `88888P' `88888P' dP `88888P' `88888P' -# MMMMMMMMMMM MMMMMMMMMMM -# - -def external_thread(thread_queue:queue.Queue): - """ - Represents some external source of data. - You would not include this code as a starting point with this Demo Program. Your data is assumed to - come from somewhere else. The important part is that you add data to the thread_queue - :param thread_queue: - :return: - """ - i = 0 - while True: - time.sleep(.01) - point = (random.randint(0,gsize[0]), random.randint(0,gsize[1])) - radius = random.randint(10, 40) - thread_queue.put((point, radius)) - i += 1 - - -# M""""""""M dP dP MM""""""""`M -# Mmmm mmmM 88 88 MM mmmmmmmM -# MMMM MMMM 88d888b. 88d888b. .d8888b. .d8888b. .d888b88 M' MMMM .d8888b. 88d888b. -# MMMM MMMM 88' `88 88' `88 88ooood8 88' `88 88' `88 MM MMMMMMMM 88' `88 88' `88 -# MMMM MMMM 88 88 88 88. ... 88. .88 88. .88 MM MMMMMMMM 88. .88 88 -# MMMM MMMM dP dP dP `88888P' `88888P8 `88888P8 MM MMMMMMMM `88888P' dP -# MMMMMMMMMM MMMMMMMMMMMM -# -# MM"""""""`YM MP""""""`MM MM'"""""`MM MM""""""""`M dP -# MM mmmmm M M mmmmm..M M' .mmm. `M MM mmmmmmmM 88 -# M' .M M. `YM M MMMMMMMM M` MMMM dP .dP .d8888b. 88d888b. d8888P .d8888b. -# MM MMMMMMMM MMMMMMM. M M MMM `M MM MMMMMMMM 88 d8' 88ooood8 88' `88 88 Y8ooooo. -# MM MMMMMMMM M. .MMM' M M. `MMM' .M MM MMMMMMMM 88 .88' 88. ... 88 88 88 88 -# MM MMMMMMMM Mb. .dM MM. .MM MM .M 8888P' `88888P' dP dP dP `88888P' -# MMMMMMMMMMMM MMMMMMMMMMM MMMMMMMMMMM MMMMMMMMMMMM - - -def the_thread(window:sg.Window, thread_queue:queue.Queue): - """ - The thread that communicates with the application through the window's events. - Waits for data from a queue and sends that data on to the event loop - :param window: - :param thread_queue: - :return: - """ - - while True: - data = thread_queue.get() - window.write_event_value((THREAD_KEY, THREAD_INCOMING_DATA), data) # Data sent is a tuple of thread name and counter - - -def main(): - - layout = [ [sg.Text('My Simulated Data Pump')], - [sg.Multiline(size=(60, 20), k='-MLINE-')], - [sg.Graph(gsize, (0, 0), gsize, k='-G-', background_color='gray')], - [sg.Button('Go'), sg.Button('Exit')] ] - - window = sg.Window('Simulated Data Pump', layout, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT) - - graph = window['-G-'] # type: sg.Graph - - while True: # Event Loop - event, values = window.read() - # print(event, values) - if event == sg.WIN_CLOSED or event == 'Exit': - break - if event == 'Go': - window.start_thread(lambda: the_thread(window, thread_queue), (THREAD_KEY, THREAD_EXITNG)) - window.start_thread(lambda: external_thread(thread_queue), (THREAD_KEY, THREAD_EXTERNAL_EXITNG)) - # Events coming from the Thread - elif event[0] == THREAD_KEY: - if event[1] == THREAD_INCOMING_DATA: - point, radius = values[event] - graph.draw_circle(point, radius=radius, fill_color='green') - window['-MLINE-'].print(f'Drawing at {point} radius {radius}', c='white on red') - elif event[1] == THREAD_EXITNG: - window['-MLINE-'].print('Thread has exited') - elif event[1] == THREAD_EXTERNAL_EXITNG: - window['-MLINE-'].print('Data Pump thread has exited') - if event == 'Edit Me': - sg.execute_editor(__file__) - elif event == 'Version': - sg.popup_scrolled(__file__, sg.get_versions(), location=window.current_location(), keep_on_top=True, non_blocking=True) - - window.close() - -if __name__ == '__main__': - main() diff --git a/DemoPrograms/Demo_Multithreaded_Delegate_Appear_To_Make_PSG_Calls_From_Thread.py b/DemoPrograms/Demo_Multithreaded_Delegate_Appear_To_Make_PSG_Calls_From_Thread.py deleted file mode 100644 index 2d34bb2f3..000000000 --- a/DemoPrograms/Demo_Multithreaded_Delegate_Appear_To_Make_PSG_Calls_From_Thread.py +++ /dev/null @@ -1,155 +0,0 @@ -import PySimpleGUI as sg -import time -import threading - -""" - Demo - Multi-threaded - Show Windows and perform other PySimpleGUI calls in what appread to be from a thread - - Just so that it's clear, you CANNOT make PySimpleGUI calls directly from a thread. There is ONE exception to this - rule. A thread may call window.write_event_values which enables it to communicate to a window through the window.read calls. - - The main GUI will not be visible on your screen nor on your taskbar despite running in the background. The calls you - make, such as popup, or even Window.read will create windows that your user will see. - - The basic function that you'll use in your thread has this format: - make_delegate_call(lambda: sg.popup('This is a popup', i, auto_close=True, auto_close_duration=2, keep_on_top=True, non_blocking=True)) - - Everything after the "lambda" looks exactly like a PySimpleGUI call. - If you want to display an entire window, then the suggestion is to put it into a function and pass the function to make_delegate_call - - Note - the behavior of variables may be a bit of a surprise as they are not evaluated until the mainthread processes the event. This means - in the example below that the counter variable being passed to the popup will not appear to be counting correctly. This is because the - value shown will be the value at the time the popup is DISPLAYED, not the value when the make_delegate_call was made. - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - - -# Design decision was to make the window a global. You can just as easily pass it to your function after initizing your window -# But there becomes a problem then of wheere do you place the thread startup code. Using this global decouples them so that -# the thread is not started in the function that makes and executes the GUI - -window:sg.Window = None - -# M""MMMM""M -# M. `MM' .M -# MM. .MM .d8888b. dP dP 88d888b. -# MMMb dMMM 88' `88 88 88 88' `88 -# MMMM MMMM 88. .88 88. .88 88 -# MMMM MMMM `88888P' `88888P' dP -# MMMMMMMMMM -# -# M""""""""M dP dP -# Mmmm mmmM 88 88 -# MMMM MMMM 88d888b. 88d888b. .d8888b. .d8888b. .d888b88 -# MMMM MMMM 88' `88 88' `88 88ooood8 88' `88 88' `88 -# MMMM MMMM 88 88 88 88. ... 88. .88 88. .88 -# MMMM MMMM dP dP dP `88888P' `88888P8 `88888P8 -# MMMMMMMMMM - -def the_thread(): - """ - This is code that is unique to your application. It wants to "make calls to PySimpleGUI", but it cannot directly do so. - Instead it will send the request to make the call to the mainthread that is running the GUI. - - :return: - """ - - # Wait for the GUI to start running - while window is None: - time.sleep(.2) - - for i in range(5): - time.sleep(.2) - make_delegate_call(lambda: sg.popup('This is a popup', i, relative_location=(0, -300), auto_close=True, auto_close_duration=2, keep_on_top=True, non_blocking=True)) - make_delegate_call(lambda: sg.popup_scrolled(__file__, sg.get_versions(), auto_close=True, auto_close_duration=1.5, non_blocking=True)) - - make_delegate_call(lambda: sg.popup('One last popup before exiting...', relative_location=(-200, -200))) - - # when finished and ready to stop, tell the main GUI to exit - window.write_event_value('-THREAD EXIT-', None) - - -# -------------------------------------------------------------------------------------------------------- # - -# The remainder of the code is part of the overall design pattern. You should copy this code -# and use it as the basis for creating this time of delegated PySimpleGUI calls - - -# M""""""'YMM oo -# M mmmm. `M -# M MMMMM M .d8888b. .d8888b. dP .d8888b. 88d888b. -# M MMMMM M 88ooood8 Y8ooooo. 88 88' `88 88' `88 -# M MMMM' .M 88. ... 88 88 88. .88 88 88 -# M .MM `88888P' `88888P' dP `8888P88 dP dP -# MMMMMMMMMMM .88 -# d8888P -# MM"""""""`YM dP dP -# MM mmmmm M 88 88 -# M' .M .d8888b. d8888P d8888P .d8888b. 88d888b. 88d888b. -# MM MMMMMMMM 88' `88 88 88 88ooood8 88' `88 88' `88 -# MM MMMMMMMM 88. .88 88 88 88. ... 88 88 88 -# MM MMMMMMMM `88888P8 dP dP `88888P' dP dP dP -# MMMMMMMMMMMM - -def make_delegate_call(func): - """ - Make a delegate call to PySimpleGUI. - - :param func: A lambda expression most likely. It's a function that will be called by the mainthread that's executing the GUI - :return: - """ - if window is not None: - window.write_event_value('-THREAD DELEGATE-', func) - - -# oo -# -# 88d8b.d8b. .d8888b. dP 88d888b. -# 88'`88'`88 88' `88 88 88' `88 -# 88 88 88 88. .88 88 88 88 -# dP dP dP `88888P8 dP dP dP - -def main(): - global window - - # create a window. A key is needed so that the values dictionary will return the thread's value as a key - layout = [[sg.Text('', k='-T-')]] - - # set the window to be both invisible and have no taskbar icon - window = sg.Window('Invisible window', layout, no_titlebar=True, alpha_channel=0, finalize=True, font='_ 1', margins=(0,0), element_padding=(0,0)) - window.hide() - - while True: - event, values = window.read() - if event in ('Exit', sg.WIN_CLOSED): - break - # if the event is from the thread, then the value is the function that should be called - if event == '-THREAD DELEGATE-': - try: - values[event]() - except Exception as e: - sg.popup_error_with_traceback('Error calling your function passed to GUI', event, values, e) - elif event == '-THREAD EXIT-': - break - window.close() - - -# MP""""""`MM dP dP -# M mmmmm..M 88 88 -# M. `YM d8888P .d8888b. 88d888b. d8888P dP dP 88d888b. -# MMMMMMM. M 88 88' `88 88' `88 88 88 88 88' `88 -# M. .MMM' M 88 88. .88 88 88 88. .88 88. .88 -# Mb. .dM dP `88888P8 dP dP `88888P' 88Y888P' -# MMMMMMMMMMM 88 -# dP - -if __name__ == '__main__': - # first your thread will be started - threading.Thread(target=the_thread, daemon=True).start() - # then startup the main GUI - main() diff --git a/DemoPrograms/Demo_Multithreaded_Different_Threads.py b/DemoPrograms/Demo_Multithreaded_Different_Threads.py index b74dc5e7a..3ba464a0f 100644 --- a/DemoPrograms/Demo_Multithreaded_Different_Threads.py +++ b/DemoPrograms/Demo_Multithreaded_Different_Threads.py @@ -1,4 +1,5 @@ #!/usr/bin/python3 +import threading import time import itertools import PySimpleGUI as sg @@ -14,11 +15,7 @@ The PySimpleGUI code is structured just like a typical PySimpleGUI program. A layout defined, a Window is created, and an event loop is executed. - Copyright 2020-2024 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ @@ -95,7 +92,7 @@ def worker_thread3(thread_name, run_freq, window): # ###### ####### #### -def main(): +def the_gui(): """ Starts and executes the GUI Reads data from a Queue and displays the data to the window @@ -107,16 +104,16 @@ def main(): layout = [[sg.Text('Multithreaded Window Example')], [sg.Text('', size=(15, 1), key='-OUTPUT-')], [sg.Multiline(size=(40, 26), key='-ML-', autoscroll=True)], - [sg.Push(), sg.Button('Exit')], ] + [sg.Button('Exit')], ] window = sg.Window('Multithreaded Window', layout, finalize=True) # -- Create a Queue to communicate with GUI -- # queue used to communicate between the gui and the threads # -- Start worker threads, each taking a different amount of time - window.start_thread(lambda: worker_thread1('Thread 1', 500, window)) - window.start_thread(lambda: worker_thread2('Thread 2', 200, window)) - window.start_thread(lambda: worker_thread3('Thread 3', 1000, window)) + threading.Thread(target=worker_thread1, args=('Thread 1', 500, window,), daemon=True).start() + threading.Thread(target=worker_thread2, args=('Thread 2', 200, window,), daemon=True).start() + threading.Thread(target=worker_thread3, args=('Thread 3', 1000, window,), daemon=True).start() # -- Start the GUI passing in the Queue -- sg.cprint_set_output_destination(window, '-ML-') @@ -134,6 +131,14 @@ def main(): window.close() +## ## ### #### ## ## +### ### ## ## ## ### ## +#### #### ## ## ## #### ## +## ### ## ## ## ## ## ## ## +## ## ######### ## ## #### +## ## ## ## ## ## ### +## ## ## ## #### ## ## + if __name__ == '__main__': - main() + the_gui() diff --git a/DemoPrograms/Demo_Multithreaded_Logging.py b/DemoPrograms/Demo_Multithreaded_Logging.py new file mode 100644 index 000000000..ca0ca53a1 --- /dev/null +++ b/DemoPrograms/Demo_Multithreaded_Logging.py @@ -0,0 +1,94 @@ +import PySimpleGUI as sg +import queue +import logging +import threading +import time + +""" + This code originated in this project: + https://github.com/john144/MultiThreading + Thanks to John for writing this in the early days of PySimpleGUI + Demo program showing one way that a threaded application can function with PySimpleGUI + Events are sent from the ThreadedApp thread to the main thread, the GUI, by using a queue +""" + +logger = logging.getLogger('mymain') + + +def externalFunction(): + logger.info('Hello from external app') + logger.info('External app sleeping 5 seconds') + time.sleep(5) + logger.info('External app waking up and exiting') + + +class ThreadedApp(threading.Thread): + def __init__(self): + super().__init__() + self._stop_event = threading.Event() + + def run(self): + externalFunction() + + def stop(self): + self._stop_event.set() + + +class QueueHandler(logging.Handler): + def __init__(self, log_queue): + super().__init__() + self.log_queue = log_queue + + def emit(self, record): + self.log_queue.put(record) + + +def main(): + + layout = [ + [sg.Multiline(size=(50, 15), key='-LOG-')], + [sg.Button('Start', bind_return_key=True, key='-START-'), sg.Button('Exit')] + ] + + window = sg.Window('Log window', layout, + default_element_size=(30, 2), + font=('Helvetica', ' 10'), + default_button_element_size=(8, 2),) + + appStarted = False + + # Setup logging and start app + logging.basicConfig(level=logging.DEBUG) + log_queue = queue.Queue() + queue_handler = QueueHandler(log_queue) + logger.addHandler(queue_handler) + threadedApp = ThreadedApp() + + # Loop taking in user input and querying queue + while True: + # Wake every 100ms and look for work + event, values = window.read(timeout=100) + + if event == '-START-': + if appStarted is False: + threadedApp.start() + logger.debug('App started') + window['-START-'].update(disabled=True) + appStarted = True + elif event in (None, 'Exit'): + break + + # Poll queue + try: + record = log_queue.get(block=False) + except queue.Empty: + pass + else: + msg = queue_handler.format(record) + window['-LOG-'].update(msg+'\n', append=True) + + window.close() + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/DemoPrograms/Demo_Multithreaded_Long_Shell_Operation_Animated.py b/DemoPrograms/Demo_Multithreaded_Long_Shell_Operation_Animated.py index 51a51986e..4146d9d13 100644 --- a/DemoPrograms/Demo_Multithreaded_Long_Shell_Operation_Animated.py +++ b/DemoPrograms/Demo_Multithreaded_Long_Shell_Operation_Animated.py @@ -8,12 +8,6 @@ more external tools like ffmpeg. The shell_with_animation function allows users to easily start a long-operation without fearing that the GUI will appear to be frozen. It offers a wide range of parameters to help create a custom animation window. - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ # Here we're running a simple "pip list" command and using the built-in animated GIF. diff --git a/DemoPrograms/Demo_Multithreaded_Long_Task_Simple.py b/DemoPrograms/Demo_Multithreaded_Long_Task_Simple.py index b90a489f5..906e2c6e4 100644 --- a/DemoPrograms/Demo_Multithreaded_Long_Task_Simple.py +++ b/DemoPrograms/Demo_Multithreaded_Long_Task_Simple.py @@ -15,12 +15,6 @@ 1. If a the amount of time is known ahead of time or the work can be broken down into countable units, then a progress bar is used. 2. If a task is one long chunk of time that cannot be broken down into smaller units, then an animated GIF is shown that spins as long as the task is running. - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ diff --git a/DemoPrograms/Demo_Multithreaded_Long_Tasks.py b/DemoPrograms/Demo_Multithreaded_Long_Tasks.py index 2d99583ac..0ec1a2f95 100644 --- a/DemoPrograms/Demo_Multithreaded_Long_Tasks.py +++ b/DemoPrograms/Demo_Multithreaded_Long_Tasks.py @@ -1,27 +1,25 @@ #!/usr/bin/python3 +import threading import time import PySimpleGUI as sg """ - Demo Program - Multithreaded Long Tasks GUI - + DESIGN PATTERN - Multithreaded Long Tasks GUI Presents one method for running long-running operations in a PySimpleGUI environment. - The PySimpleGUI code, and thus the underlying GUI framework, runs as the primary, main thread The "long work" is contained in the thread that is being started. - So that you don't have to import and understand the threading module, this program uses window.start_thread to run a thread. - - The thread is using TUPLES for its keys. This enables you to easily find the thread events by looking at event[0]. - The Thread Keys look something like this: ('-THREAD-', message) - If event [0] == '-THREAD-' then you know it's one of these tuple keys. - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. + July 2020 - Note that this program has been updated to use the new Window.write_event_value method. + This method has not yet been ported to the other PySimpleGUI ports and is thus limited to the tkinter ports for now. - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Internally to PySimpleGUI, a queue.Queue is used by the threads to communicate with main GUI code + The PySimpleGUI code is structured just like a typical PySimpleGUI program. A layout defined, + a Window is created, and an event loop is executed. + + + This design pattern works for all of the flavors of PySimpleGUI including the Web and also repl.it + You'll find a repl.it version here: https://repl.it/@PySimpleGUI/Async-With-Queue-Communicationspy """ @@ -30,12 +28,12 @@ def long_operation_thread(seconds, window): A worker thread that communicates with the GUI through a queue This thread can block for as long as it wants and the GUI will not be affected :param seconds: (int) How long to sleep, the ultimate blocking call - :param window: (sg.Window) the window to communicate with + :param gui_queue: (queue.Queue) Queue to communicate back to GUI that task is completed :return: """ - window.write_event_value(('-THREAD-', 'Starting thread - will sleep for {} seconds'.format(seconds)), None) + print('Starting thread - will sleep for {} seconds'.format(seconds)) time.sleep(seconds) # sleep for a while - window.write_event_value(('-THREAD-', '** DONE **'), 'Done!') # put a message into queue for GUI + window.write_event_value('-THREAD-', '** DONE **') # put a message into queue for GUI def the_gui(): @@ -49,7 +47,7 @@ def the_gui(): layout = [[sg.Text('Long task to perform example')], [sg.Output(size=(70, 12))], [sg.Text('Number of seconds your task will take'), - sg.Input(default_text=5, key='-SECONDS-', size=(5, 1)), + sg.Input(key='-SECONDS-', size=(5, 1)), sg.Button('Do Long Task', bind_return_key=True)], [sg.Button('Click Me'), sg.Button('Exit')], ] @@ -60,14 +58,14 @@ def the_gui(): event, values = window.read() if event in (sg.WIN_CLOSED, 'Exit'): break - elif event == 'Do Long Task': + elif event.startswith('Do'): seconds = int(values['-SECONDS-']) print('Thread ALIVE! Long work....sending value of {} seconds'.format(seconds)) - window.start_thread(lambda: long_operation_thread(seconds, window), ('-THREAD-', '-THEAD ENDED-')) + threading.Thread(target=long_operation_thread, args=(seconds, window,), daemon=True).start() elif event == 'Click Me': print('Your GUI is alive and well') - elif event[0] == '-THREAD-': - print('Got a message back from the thread: ', event[1]) + elif event == '-THREAD-': + print('Got a message back from the thread: ', values[event]) # if user exits the window, then close the window and exit the GUI func window.close() diff --git a/DemoPrograms/Demo_Multithreaded_Multiple_Threads.py b/DemoPrograms/Demo_Multithreaded_Multiple_Threads.py index bb64c04e4..059b3e677 100644 --- a/DemoPrograms/Demo_Multithreaded_Multiple_Threads.py +++ b/DemoPrograms/Demo_Multithreaded_Multiple_Threads.py @@ -30,13 +30,7 @@ You can hard code these IDs to make your code more readable. For example, maybe you have a function named "update_user_list()". You can call the work ID "user list". Then check for the message coming back later from the work task to see if it starts - with "user list". If so, then that long-running task is over. - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + with "user list". If so, then that long-running task is over. """ diff --git a/DemoPrograms/Demo_Multithreaded_ProgressBar.py b/DemoPrograms/Demo_Multithreaded_ProgressBar.py index 54839460c..f9e418342 100644 --- a/DemoPrograms/Demo_Multithreaded_ProgressBar.py +++ b/DemoPrograms/Demo_Multithreaded_ProgressBar.py @@ -1,4 +1,5 @@ import PySimpleGUI as sg +import threading import random import time @@ -13,50 +14,37 @@ have implemented your own progress meter in your window. Using the write_event_value method enables you to easily do either of these. - - In this demo, all thread events are a TUPLE with the first item in tuple being THREAD_KEY ---> '-THEAD-' - This allows easy separation of all of the thread-based keys into 1 if statment: - elif event[0] == THREAD_KEY: - Example - (THREAD_KEY, DL_START_KEY) indicates the download is starting and provices the Max value - (THREAD_KEY, DL_END_KEY) indicates the downloading has completed - - The main window uses a relative location when making the window so that the one-line-progress-meter has room - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ -THREAD_KEY = '-THREAD-' DL_START_KEY = '-START DOWNLOAD-' DL_COUNT_KEY = '-COUNT-' DL_END_KEY = '-END DOWNLOAD-' -DL_THREAD_EXITNG = '-THREAD EXITING-' + def the_thread(window:sg.Window): """ The thread that communicates with the application through the window's events. - Simulates downloading a random number of chinks from 50 to 100- + Once a second wakes and sends a new event and associated value to the window """ max_value = random.randint(50, 100) - window.write_event_value((THREAD_KEY, DL_START_KEY), max_value) # Data sent is a tuple of thread name and counter + window.write_event_value(DL_START_KEY, max_value) # Data sent is a tuple of thread name and counter for i in range(max_value): time.sleep(.1) - window.write_event_value((THREAD_KEY, DL_COUNT_KEY), i) # Data sent is a tuple of thread name and counter - window.write_event_value((THREAD_KEY, DL_END_KEY), max_value) # Data sent is a tuple of thread name and counter + window.write_event_value(DL_COUNT_KEY, i) # Data sent is a tuple of thread name and counter + window.write_event_value(DL_END_KEY, max_value) # Data sent is a tuple of thread name and counter def main(): - layout = [ [sg.Text('My Multi-threaded PySimpleGUI Program')], - [sg.ProgressBar(100, 'h', size=(30,20), k='-PROGRESS-', expand_x=True)], - [sg.Text(key='-STATUS-')], + layout = [ [sg.Text('My Window')], + [sg.ProgressBar(100, 'h', size=(30,20), k='-PROGRESS-')], [sg.Button('Go'), sg.Button('Exit')] ] - window = sg.Window('Window Title', layout, finalize=True, relative_location=(0, -300)) + window = sg.Window('Window Title', layout, finalize=True) + window.read(timeout=0) + window.move(window.current_location()[0], window.current_location()[1]-300) downloading, max_value = False, 0 while True: # Event Loop @@ -65,24 +53,17 @@ def main(): if event == sg.WIN_CLOSED or event == 'Exit': break if event == 'Go' and not downloading: - window.start_thread(lambda: the_thread(window), (THREAD_KEY, DL_THREAD_EXITNG)) - # Events coming from the Thread - elif event[0] == THREAD_KEY: - if event[1] == DL_START_KEY: - max_value = values[event] - downloading = True - window['-STATUS-'].update('Starting download') - sg.one_line_progress_meter(f'Downloading {max_value} segments', 0, max_value, 1, f'Downloading {max_value} segments', ) - window['-PROGRESS-'].update(0, max_value) - elif event[1] == DL_COUNT_KEY: - sg.one_line_progress_meter(f'Downloading {max_value} segments', values[event]+1, max_value, 1, f'Downloading {max_value} segments') - window['-STATUS-'].update(f'Got a new current count update {values[event]}') - window['-PROGRESS-'].update(values[event]+1, max_value) - elif event[1] == DL_END_KEY: - downloading = False - window['-STATUS-'].update('Download finished') - elif event[1] == DL_THREAD_EXITNG: - window['-STATUS-'].update('Last step - Thread has exited') + threading.Thread(target=the_thread, args=(window,), daemon=True).start() + elif event == DL_START_KEY: + max_value = values[event] + downloading = True + sg.one_line_progress_meter(f'Downloading {max_value} segments', 0, max_value, 1, f'Downloading {max_value} segments', ) + window['-PROGRESS-'].update(0, max_value) + elif event == DL_COUNT_KEY: + sg.one_line_progress_meter(f'Downloading {max_value} segments', values[event]+1, max_value, 1, f'Downloading {max_value} segments') + window['-PROGRESS-'].update(values[event]+1, max_value) + elif event == DL_END_KEY: + downloading = False window.close() diff --git a/DemoPrograms/Demo_Multithreaded_Signal_Thread_To_End.py b/DemoPrograms/Demo_Multithreaded_Signal_Thread_To_End.py deleted file mode 100644 index 9b7989599..000000000 --- a/DemoPrograms/Demo_Multithreaded_Signal_Thread_To_End.py +++ /dev/null @@ -1,86 +0,0 @@ -import time -import datetime -import PySimpleGUI as sg - -""" - Multithreading with signaling to thread when to stop. - If exiting the program, waits for the thread to finish. - - In this example, the thread runs at a rate of twice a second. It sends the time as a string - The main GUI checks the value sent by the thread to see if it differs from what is displayed. - If the display is different, then the GUI is updated with the new time. - - Copyright 2020-2024 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. - -""" - - -# dP dP dP -# 88 88 88 -# d8888P 88d888b. 88d888b. .d8888b. .d8888b. .d888b88 -# 88 88' `88 88' `88 88ooood8 88' `88 88' `88 -# 88 88 88 88 88. ... 88. .88 88. .88 -# dP dP dP dP `88888P' `88888P8 `88888P8 -# - -def the_thread(window): - - while window.job_running: - window.write_event_value('-THREAD-', datetime.datetime.now().strftime('%H:%M:%S')) - time.sleep(0.5) - - -# oo -# -# 88d8b.d8b. .d8888b. dP 88d888b. -# 88'`88'`88 88' `88 88 88' `88 -# 88 88 88 88. .88 88 88 88 -# dP dP dP `88888P8 dP dP dP - -def main(): - - layout = [ - [sg.Text('00:00:00', font=('Courier New', 20, 'bold'), justification='center', expand_x=True, key='-TIME-')], - [sg.Push(), sg.Button('Start'), sg.Button('Stop')]] - - window = sg.Window('Threading', layout, enable_close_attempted_event=True, - print_event_values=True, # enable to watch the events and values print out - ) - - window.job_running = False # Create a member variable to signal to the thread when to stop - exiting = False # Used when X is clicked - - while True: - - event, values = window.read() - - if event == sg.WINDOW_CLOSE_ATTEMPTED_EVENT: - if window.job_running: # if thread running, tell it to exit - window.job_running = False - exiting = True - else: - break # if thread not running then OK to exit - - if exiting and event == '-THREAD ENDED-': # If exiting and thread is finished then OK to exit - break - - elif event == 'Start': - window['Start'].update(disabled=True) - window.job_running = True - window.start_thread(lambda: the_thread(window), '-THREAD ENDED-') - - elif event == 'Stop': - window.job_running = False - window['Start'].update(disabled=False) - - elif event == '-THREAD-' and values[event] != window['-TIME-'].get(): - window['-TIME-'].update(values[event]) - - window.close() - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/DemoPrograms/Demo_Multithreaded_Write_Event_Value.py b/DemoPrograms/Demo_Multithreaded_Write_Event_Value.py index e3629282e..1ffedfd4a 100644 --- a/DemoPrograms/Demo_Multithreaded_Write_Event_Value.py +++ b/DemoPrograms/Demo_Multithreaded_Write_Event_Value.py @@ -1,3 +1,4 @@ +import threading import time import PySimpleGUI as sg @@ -5,17 +6,20 @@ """ Threaded Demo - Uses Window.write_event_value communications - The only PySimpleGUI call allowed from a thread is write_event_value. - Using a tuple for thread events makes processing them easier to see and understand. - + Requires PySimpleGUI.py version 4.25.0 and later - Copyright 2020-2024 PySimpleSoft, Inc. and/or its licensors. All rights reserved. + This is a really important demo to understand if you're going to be using multithreading in PySimpleGUI. - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. + Older mechanisms for multi-threading in PySimpleGUI relied on polling of a queue. The management of a communications + queue is now performed internally to PySimpleGUI. + + The importance of using the new window.write_event_value call cannot be emphasized enough. It will hav a HUGE impact, in + a positive way, on your code to move to this mechanism as your code will simply "pend" waiting for an event rather than polling. - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ +THREAD_EVENT = '-THREAD-' def the_thread(window): """ @@ -23,13 +27,12 @@ def the_thread(window): Once a second wakes and sends a new event and associated value to the window """ - - window.write_event_value(('-THREAD-', '-STARTED-'), None) # Tell the GUI the thread started - - for i in range(5): + i = 0 + while True: time.sleep(1) - window.write_event_value(('-THREAD-', '-PRINT-'), i) # Data sent is a tuple of thread name and counter - # Note that the thread ended event is sent automatically by PySimpleGUI if you started the thread using window.start_thread + window.write_event_value('-THREAD-', (threading.current_thread().name, i)) # Data sent is a tuple of thread name and counter + i += 1 + def main(): """ @@ -43,26 +46,20 @@ def main(): [sg.Multiline(size=(65,20), key='-ML-', autoscroll=True, reroute_stdout=True, write_only=True, reroute_cprint=True)], [sg.T('Input so you can see data in your dictionary')], [sg.Input(key='-IN-', size=(30,1))], - [sg.B('Start A Thread', key='-START-'), sg.B('Dummy'), sg.Button('Exit')] ] + [sg.B('Start A Thread'), sg.B('Dummy'), sg.Button('Exit')] ] - window = sg.Window('Multithreading + Tuple Events', layout) + window = sg.Window('Window Title', layout) while True: # Event Loop event, values = window.read() sg.cprint(event, values) if event == sg.WIN_CLOSED or event == 'Exit': break - if event == '-START-': - window.start_thread(lambda : the_thread(window), ('-THREAD-', '-ENDED-')) - if event[0] == '-THREAD-': - if event[1] == '-PRINT-': - sg.cprint(f'Data from the thread ', colors='white on purple', end='') - sg.cprint(f'{values[event]}', colors='white on red') - elif event[1] == '-ENDED-': - sg.cprint('Thread has ended', colors='white on blue') - elif event[1] == '-STARTED-': - sg.cprint('Thread has started', colors='white on green') - + if event.startswith('Start'): + threading.Thread(target=the_thread, args=(window,), daemon=True).start() + if event == THREAD_EVENT: + sg.cprint(f'Data from the thread ', colors='white on purple', end='') + sg.cprint(f'{values[THREAD_EVENT]}', colors='white on red') window.close() diff --git a/DemoPrograms/Demo_Multithreaded_Write_Event_Value_MultiWindow.py b/DemoPrograms/Demo_Multithreaded_Write_Event_Value_MultiWindow.py index 222429517..395df6c9b 100644 --- a/DemoPrograms/Demo_Multithreaded_Write_Event_Value_MultiWindow.py +++ b/DemoPrograms/Demo_Multithreaded_Write_Event_Value_MultiWindow.py @@ -8,11 +8,7 @@ This demo uses the write_event_value method in a multi-window environment. Instead of window.read() returning the event to the user, the call to read_all_windows is used which will return both the window that had the event along with the event. - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ THREAD_EVENT = '-THREAD-' diff --git a/DemoPrograms/Demo_Multithreaded_popup.py b/DemoPrograms/Demo_Multithreaded_popup.py index 1672f0324..7eff381c2 100644 --- a/DemoPrograms/Demo_Multithreaded_popup.py +++ b/DemoPrograms/Demo_Multithreaded_popup.py @@ -19,11 +19,7 @@ When a messages is received from the queue, sg.popup is called using the parms passed through the queue - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI.org """ mainthread_queue:queue.Queue = None diff --git a/DemoPrograms/Demo_Net_API_Download_Image.py b/DemoPrograms/Demo_Net_API_Download_Image.py deleted file mode 100644 index 055e84984..000000000 --- a/DemoPrograms/Demo_Net_API_Download_Image.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python -import PySimpleGUI as sg - - -""" - Demo of Net API - Download a PNG Image using net_download_file_binary & Display in a Window - - This Demo Program shows how to download a binary file (an image) and display it in a window. - - - Copyright 2018-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - - -sg.theme('black') - -# First the easy case.... display a PNG image - -sg.Window('PNG Download', [[sg.Image(sg.net_download_file_binary(r'https://pysimplegui.net/images/tests/powered-by-pysimplegui-5.png'))]]).read(close=True) - diff --git a/DemoPrograms/Demo_Net_API_Download_Image_jpg.py b/DemoPrograms/Demo_Net_API_Download_Image_jpg.py deleted file mode 100644 index 0736f884d..000000000 --- a/DemoPrograms/Demo_Net_API_Download_Image_jpg.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env python -import PySimpleGUI as sg - -# Only need these imports if using JPGs -from PIL import Image -from io import BytesIO - - -""" - Demo of Net API - Download JPG Image using net_download_file_binary and display in a window - - The download is the easiest part. It's the displaying of a JPG that's tricky. - - - Copyright 2018-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - - - -# Download the binary file (into a variable, not a local file) -jpg_data = sg.net_download_file_binary(r'https://pysimplegui.net/images/tests/powered-by-pysimplegui-5.jpg') - -# Now display a JPG image. It requires converting the image to PNG before using with PySimpleGUI -# Note a commented out version below of this same code. Here the context manager was removed for simplicity. -jpg_image = Image.open(BytesIO(jpg_data)) -bio = BytesIO() -jpg_image.save(bio, format='PNG') - -sg.Window('Download JPG', [[sg.Image(data=bio.getvalue())]]).read(close=True) - -del bio # delete the BytesIO object since done with it - - - - -# This is another implementation using the io module with a context manager -# The "with" statement makes understanding what's going on a little more difficult -# but is perhaps the "preferred" method to use. -""" -jpg_image = Image.open(BytesIO(jpg_data)) - -with BytesIO() as bio: - jpg_image.save(bio, format='PNG') - data = bio.getvalue() - -sg.Window('Download JPG', [[sg.Image(data=data)]]).read(close=True) -""" \ No newline at end of file diff --git a/DemoPrograms/Demo_Nice_Buttons.py b/DemoPrograms/Demo_Nice_Buttons.py index f3e02fc47..a1cefe13a 100644 --- a/DemoPrograms/Demo_Nice_Buttons.py +++ b/DemoPrograms/Demo_Nice_Buttons.py @@ -6,14 +6,6 @@ import subprocess import sys -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - orange64 = 'iVBORw0KGgoAAAANSUhEUgAAAiIAAADLCAMAAABkvgh7AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAANtvJ99sId5tIt5uI91tJNxuJNxuJttvKN90NN91Ntt3PN52ONx3Otx3PNt4Pdp4Ptx4PepfD+pfEOtgD+piD+tkD+ttD+dnFOdoE+doFOVoFuNqG+JrHOFrHuFsHuRpGORpGuRqGORqGupgEOpiEOpkEOlmEOhnEupoEOpoEupqFettEetsF+tuFOxqFetrGOtsGetvHOxrGOxsGOxtGuxuG+xuHexxFutwH+xxGOxyGOxyGuxxHuBsIOJvJ+NvKORvKONwKeNwKuJxLONyLeJyLuRwKeRwKuRxLOtxIexyIexzJOx0JOx1Ju11KOx2KOx2Kux5Iux4Kux5Le1/LeFyMOFzMuB0NOB1Nux7MOx8MOx8Mu19NO1+NO1+Ntd7RdV8RtN+S9J/TdF/TtV9SNR9Stl5QNl6Qdh6Qth7RK+Tfa+Tfq6Ufr+JZb+JZr+KZ7uMbr6KaL6LaryMbLyNb7yOb7WPdLuNcLqOcLmOcrmPdLOQd7SQdrKReLKRerGSerCTfLCTfrmQde2AN+2AOO2BOu2COu6DPO6EPe6EPsWDV8OFXcOFXsOGXcOGXsaDWMSEWsqCVs+AUM2AUs6CU82CVMqDWMmEWtCAT9CAUMKHYMCIYsCIZMCKZu6FQO6GQe6GQu6HRO6IRe6JRu6KR+6KSO+LSu+MS++MTO+OTe+OTu+OUO+RUu+TVfCNTvCOTvCPUPCQUfCQUvCSU/CRVPCSVPCSVvCUV/CUWPCVWvGWWvGXXPGYXvCWYPGaYfGcYvGcZPKdZvKeZ/GdavKeaPKebfKebvKgavKhbPKibfGibvKjcPGkcfKmdPKiePOod/OpePSpePSqevSrfPSsfPSsfvSqg/SugfWwgvWwhPWyhfWyhvWxi/Wyj/W0ifW2jfa4j/a1kPW2kva2lfW2lvW4kPa6kfa7kva5lvW7lPa8lPW8lve+l/a4mva5nPa6nPa7nva+mPa+mva/nPa8oPa9ovbAm/bAnfXAnvbCofbEo/XGp/bGqPbIqQAAAC/NnaUAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjFjKpxLAAAJXElEQVR4Xu3de3zVdR3H8Xb9/sJh60LlOTtubdIZEyckSdedMzkdZyRGIePmZdqki8s0KllJmtGCTAXRlUAyrireUeZga2JRkooYRWR0JbXMLsIqZ5fT7/L5nRvj9/md0/fhw/Px/fyHP+D33fb4vPj+LvsxXpMA8IREgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgJF7Ih1Xf3bVsuu/AYXu+mUrL+u8iqbqIcdErvhme0V8SjQCIpwWe+0nli+k2R5NTolc0jYzqpQBcigV+UDltZ57SQ6JfLqyRRXRyiCIis7u7qAhj8B3Ip1tLdg/pFLR0Z+hOR/JbyIrWxGIZCp289E2Ep+J3HzEFqLKy0qhUJUfeUkZnf8lGnYWX4l0tDfTOg5VEqoJNNTXh6EgmaMLBKuaymmcJFLRSfPO5CuRtgitYisPBehDQUFrqC3O2EtUxRdo4Bn8JHJhlNawlNZh85Aj2JQeiRp9JY08nY9Euk+nFUwq1ECLgww1ZTRaS+R8mnk6PpEF8dTDkNIgLQxiHFdNw7U0d9PU07CJdLw+tRUVpy5Cxo19+bz9lYI+n5cNfdhcjWGZf2jsCTTJcDiUmnBR/HKaewqbSHfqQqSJrkLGvuuctZu3jOgBD1u99B7Fg6a+Vwrrk8kNfRX+0XE2+qg527adsc38M723d01yK3lbqhH1SZp7CpfIolnJw4udQk44ddPOn/3q6b+M6K8+/c2vF+jXVw29X/ALI7N+Z3jome+f/QZ7pOG6VCMtl9Dkk7hElifvd0uPs1cb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' green_pill64 = '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' red_pill64 = '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' @@ -23,7 +15,7 @@ def image_file_to_bytes(image64, size): image_file = io.BytesIO(base64.b64decode(image64)) img = Image.open(image_file) - img.thumbnail(size, Image.LANCZOS) + img.thumbnail(size, Image.ANTIALIAS) bio = io.BytesIO() img.save(bio, format='PNG') imgbytes = bio.getvalue() diff --git a/DemoPrograms/Demo_NonBlocking_Form.py b/DemoPrograms/Demo_NonBlocking_Form.py index 701a9c440..22efe0ed2 100644 --- a/DemoPrograms/Demo_NonBlocking_Form.py +++ b/DemoPrograms/Demo_NonBlocking_Form.py @@ -5,12 +5,6 @@ ''' Window that doesn't block good for applications with an loop that polls hardware - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. ''' def StatusOutputExample(): diff --git a/DemoPrograms/Demo_Notification_Window_Alpha_Channel.py b/DemoPrograms/Demo_Notification_Window_Alpha_Channel.py index 4eb00f286..0e99a53f6 100644 --- a/DemoPrograms/Demo_Notification_Window_Alpha_Channel.py +++ b/DemoPrograms/Demo_Notification_Window_Alpha_Channel.py @@ -2,14 +2,6 @@ import PySimpleGUI as sg import time -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - # Demonstrates a notification window that's partially transparent # The window slowly fades-in # Includes a small red-X button to close the window diff --git a/DemoPrograms/Demo_Notification_Window_Fade_In_Out.py b/DemoPrograms/Demo_Notification_Window_Fade_In_Out.py index d7bb24cec..95c4f01d4 100644 --- a/DemoPrograms/Demo_Notification_Window_Fade_In_Out.py +++ b/DemoPrograms/Demo_Notification_Window_Fade_In_Out.py @@ -10,12 +10,6 @@ You can click on the notification window to speed things along. The idea is that if you click while fading in, you should immediately see the info. If you click while info is displaying or while fading out, the window closes immediately. - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. ''' # ------------------------------------------------------------------- diff --git a/DemoPrograms/Demo_Notification_Window_Multiprocessing.py b/DemoPrograms/Demo_Notification_Window_Multiprocessing.py index 5d09f8f23..e70ebef0f 100644 --- a/DemoPrograms/Demo_Notification_Window_Multiprocessing.py +++ b/DemoPrograms/Demo_Notification_Window_Multiprocessing.py @@ -14,11 +14,7 @@ Note - In order to import and use these calls, you must make the call from a "main program". - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI ''' diff --git a/DemoPrograms/Demo_Notify_Integration.py b/DemoPrograms/Demo_Notify_Integration.py index c110a4ae6..d00adcd18 100644 --- a/DemoPrograms/Demo_Notify_Integration.py +++ b/DemoPrograms/Demo_Notify_Integration.py @@ -24,11 +24,7 @@ temp files (an optional step), then include this line of code when you close the window: [os.remove(file) for file in notify_popout.temp_files] if hasattr(notify_popout, 'temp_files') else None - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ diff --git a/DemoPrograms/Demo_OpenCV.py b/DemoPrograms/Demo_OpenCV.py index 9f77dedf8..ea5cf72d7 100644 --- a/DemoPrograms/Demo_OpenCV.py +++ b/DemoPrograms/Demo_OpenCV.py @@ -1,22 +1,16 @@ #!/usr/bin/env python import PySimpleGUI as sg +from PIL import Image import cv2 as cv -# from PIL import Image -# import io +import io """ - Demo program to open and play a file using OpenCV - It's main purpose is to show you: - 1. How to get a frame at a time from a video file using OpenCV - 2. How to display an image in a PySimpleGUI Window - - For added fun, you can reposition the video using the slider. - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. +Demo program to open and play a file using OpenCV +It's main purpose is to show you: +1. How to get a frame at a time from a video file using OpenCV +2. How to display an image in a PySimpleGUI Window + +For added fun, you can reposition the video using the slider. """ @@ -34,39 +28,37 @@ def main(): # ---===--- define the window layout --- # layout = [[sg.Text('OpenCV Demo', size=(15, 1), font='Helvetica 20')], - [sg.Image(key='-IMAGE-')], - [sg.Slider(range=(0, num_frames), size=(60, 10), orientation='h', key='-SLIDER-')], - [sg.Push(), sg.Button('Exit', font='Helvetica 14')]] + [sg.Image(filename='', key='-image-')], + [sg.Slider(range=(0, num_frames), + size=(60, 10), orientation='h', key='-slider-')], + [sg.Button('Exit', size=(7, 1), pad=((600, 0), 3), font='Helvetica 14')]] # create the window and show it without the plot window = sg.Window('Demo Application - OpenCV Integration', layout, no_titlebar=False, location=(0, 0)) # locate the elements we'll be updating. Does the search only 1 time - image_elem = window['-IMAGE-'] - slider_elem = window['-SLIDER-'] - timeout = 1000//fps # time in ms to use for window reads - + image_elem = window['-image-'] + slider_elem = window['-slider-'] + # ---===--- LOOP through video file by frame --- # cur_frame = 0 while vidFile.isOpened(): - event, values = window.read(timeout=timeout) + event, values = window.read(timeout=0) if event in ('Exit', None): break ret, frame = vidFile.read() if not ret: # if out of data stop looping break # if someone moved the slider manually, the jump to that frame - if int(values['-SLIDER-']) != cur_frame-1: - cur_frame = int(values['-SLIDER-']) + if int(values['-slider-']) != cur_frame-1: + cur_frame = int(values['-slider-']) vidFile.set(cv.CAP_PROP_POS_FRAMES, cur_frame) slider_elem.update(cur_frame) cur_frame += 1 - imgbytes = cv.imencode('.ppm', frame)[1].tobytes() # can also use png. ppm found to be more efficient + imgbytes = cv.imencode('.png', frame)[1].tobytes() # ditto image_elem.update(data=imgbytes) -main() - ############# # | | # # | | # @@ -82,4 +74,6 @@ def main(): img.save(bio, format= 'PNG') # save image as png to it imgbytes = bio.getvalue() # this can be used by OpenCV hopefully image_elem.update(data=imgbytes) -""" \ No newline at end of file +""" + +main() diff --git a/DemoPrograms/Demo_OpenCV_4_Line_Program.py b/DemoPrograms/Demo_OpenCV_4_Line_Program.py index d6991f893..96f715bb9 100644 --- a/DemoPrograms/Demo_OpenCV_4_Line_Program.py +++ b/DemoPrograms/Demo_OpenCV_4_Line_Program.py @@ -1,13 +1,4 @@ import cv2, PySimpleGUI as sg - -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - window, cap = sg.Window('Demo Application - OpenCV Integration', [[sg.Image(key='-IMAGE-')], ], location=(800, 400)), cv2.VideoCapture(0) while window(timeout=20)[0] is not None: window['-IMAGE-'](data=cv2.imencode('.png', cap.read()[1])[1].tobytes()) diff --git a/DemoPrograms/Demo_OpenCV_7_Line_Program.py b/DemoPrograms/Demo_OpenCV_7_Line_Program.py index 75db03fd3..765c8fe6b 100644 --- a/DemoPrograms/Demo_OpenCV_7_Line_Program.py +++ b/DemoPrograms/Demo_OpenCV_7_Line_Program.py @@ -1,24 +1,14 @@ import cv2, PySimpleGUI as sg -window = sg.Window('Demo Application - OpenCV Integration', [[sg.Image(key='-I-')], ], location=(800, 400)) +window = sg.Window('Demo Application - OpenCV Integration', [[sg.Image(filename='', key='image')], ], location=(800, 400)) cap = cv2.VideoCapture(0) # Setup the camera as a capture device while True: # The PSG "Event Loop" - event, values = window.read(timeout=20) # get events for the window with 20ms max wait + event, values = window.read(timeout=20, timeout_key='timeout') # get events for the window with 20ms max wait if event == sg.WIN_CLOSED: break # if user closed window, quit - window['-I-'].update(data=cv2.imencode('.ppm', cap.read()[1])[1].tobytes()) # Update image in window + window['image'].update(data=cv2.imencode('.png', cap.read()[1])[1].tobytes()) # Update image in window """ - Putting the comment at the bottom so that you can see that the code is indeed 7 lines long. And, there is nothing - done out of the ordinary to make it 7 lines long. There are no ; for example. OK, so the if statement is on one line - but that's the only place that you would traditionally see one more line. So, call it 8 if you want. - - NOTE - the encoding format PPM has been shown to be significantly less CPU intensive than using PNG (thank you reporting PySimpleGUI user!) - - In some cases however, PPM may not be supported. If you have problems with PPM encoding, then change ".ppm" to ".png" on line 8. - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" \ No newline at end of file +Putting the comment at the bottom so that you can see that the code is indeed 7 lines long. And, there is nothing +done out of the ordinary to make it 7 lines long. There are no ; for example. OK, so the if statement is on one line +but that's the only place that you would traditionally see one more line. So, call it 8 if you want. +""" diff --git a/DemoPrograms/Demo_OpenCV_Draw_On_Webcam_Image.py b/DemoPrograms/Demo_OpenCV_Draw_On_Webcam_Image.py index e055a77db..fff2a93b5 100644 --- a/DemoPrograms/Demo_OpenCV_Draw_On_Webcam_Image.py +++ b/DemoPrograms/Demo_OpenCV_Draw_On_Webcam_Image.py @@ -11,11 +11,7 @@ Note also that this demo is using ppm as the image format. This worked fine on all PySimpleGUI ports except the web port. If you have trouble with the imencode statement, change "ppm" to "png" - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ def main(): diff --git a/DemoPrograms/Demo_OpenCV_Simple_GUI.py b/DemoPrograms/Demo_OpenCV_Simple_GUI.py index 73ee10b79..a9758f5a9 100644 --- a/DemoPrograms/Demo_OpenCV_Simple_GUI.py +++ b/DemoPrograms/Demo_OpenCV_Simple_GUI.py @@ -12,12 +12,6 @@ blur: simple Gaussian blur, slider sets the sigma, i.e. the amount of blur smear hue: moves the image hue values by the amount selected on the slider enhance: applies local contrast enhancement on the luma channel to make the image fancier - slider controls fanciness. - -Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - -Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - -You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ diff --git a/DemoPrograms/Demo_OpenCV_Webcam.py b/DemoPrograms/Demo_OpenCV_Webcam.py index 25c3c7bf7..cc9995697 100644 --- a/DemoPrograms/Demo_OpenCV_Webcam.py +++ b/DemoPrograms/Demo_OpenCV_Webcam.py @@ -5,12 +5,6 @@ """ Demo program that displays a webcam using OpenCV - -Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - -Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - -You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ diff --git a/DemoPrograms/Demo_OpenCV_Webcam_ASCII.py b/DemoPrograms/Demo_OpenCV_Webcam_ASCII.py index cd41e870c..4798c5d7a 100644 --- a/DemoPrograms/Demo_OpenCV_Webcam_ASCII.py +++ b/DemoPrograms/Demo_OpenCV_Webcam_ASCII.py @@ -2,6 +2,8 @@ from PIL import Image import numpy as np import PySimpleGUI as sg +font_size = 6 +USING_QT = False """ Interesting program that shows your webcam's image as ASCII text. Runs in realtime, producing a stream of @@ -20,38 +22,40 @@ pip install opencv-python On Linux / Mac use pip3 instead of pip - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ # The magic bits that make the ASCII stuff work shamelessly taken from https://gist.github.com/cdiener/10491632 chars = np.asarray(list(' .,:;irsXA253hMHGS#9B&@')) SC, GCF, WCF = .1, 1, 7/4 -sg.theme('Black') # make it look cool with white chars on black background -font_size = 6 +sg.theme('Black') # make it look cool # define the window layout # number of lines of text elements. Depends on cameras image size and the variable SC (scaller) NUM_LINES = 48 +if USING_QT: + layout = [[sg.Text(i, size_px=(800, 12), + font=('Courier', font_size), + key='-OUT-' + str(i))] for i in range(NUM_LINES)] +else: + layout = [[sg.Text(i, size=(120, 1), font=('Courier', font_size), + pad=(0, 0), key='-OUT-'+str(i))] for i in range(NUM_LINES)] -layout = [[[sg.Text(i, font=('Courier', font_size), pad=(0, 0), key=('-OUT-', i))] for i in range(NUM_LINES)], - [sg.Text('GCF', s=9, justification='r'), sg.Slider((0.1, 20), resolution=.05, default_value=1, orientation='h', key='-SPIN-GCF-', size=(15, 15))], - [sg.Text('Font Size', s=9, justification='r'), sg.Slider((4, 20), resolution=1, default_value=font_size, orientation='h', key='-FONT SIZE-', size=(15, 15)), - sg.Push(), sg.Button('Exit')]] +layout += [[sg.Button('Exit', size=(5, 1)), + sg.Text('GCF', size=(4, 1)), + sg.Spin([round(i, 2) for i in np.arange(0.1, 20.0, 0.1)], + initial_value=1, key='-SPIN-GCF-', size=(5, 1)), + sg.Text('WCF', size=(4, 1)), + sg.Slider((1, 4), resolution=.05, default_value=1.75, + orientation='h', key='-SLIDER-WCF-', size=(15, 15))]] # create the window and show it without the plot -window = sg.Window('Demo Application - OpenCV - ASCII Chars Output', layout, font='Any 18', resizable=True) +window = sg.Window('Demo Application - OpenCV Integration', layout, + location=(800, 400), font='Any 18') # ---===--- Event LOOP Read and display frames, operate the GUI --- # # Setup the OpenCV capture device (webcam) - cap = cv2.VideoCapture(0) - while True: event, values = window.read(timeout=0) @@ -62,7 +66,7 @@ img = Image.fromarray(frame) # create PIL image from frame GCF = float(values['-SPIN-GCF-']) - WCF = 1.75 + WCF = values['-SLIDER-WCF-'] # More magic that coverts the image to ascii S = (round(img.size[0] * SC * WCF), round(img.size[1] * SC)) img = np.sum(np.asarray(img.resize(S)), axis=2) @@ -70,8 +74,7 @@ img = (1.0 - img / img.max()) ** GCF * (chars.size - 1) # "Draw" the image in the window, one line of text at a time! - font_size = int(values['-FONT SIZE-']) for i, r in enumerate(chars[img.astype(int)]): - window[('-OUT-', i)].update("".join(r), font=('Courier', font_size)) + window['-OUT-'+str(i)].update("".join(r)) window.close() diff --git a/DemoPrograms/Demo_OpenCV_Webcam_Minimal.py b/DemoPrograms/Demo_OpenCV_Webcam_Minimal.py index 7083153fa..1cfc35e20 100644 --- a/DemoPrograms/Demo_OpenCV_Webcam_Minimal.py +++ b/DemoPrograms/Demo_OpenCV_Webcam_Minimal.py @@ -6,12 +6,6 @@ This demo will run on tkinter, Qt, and Web(Remi). The web version flickers at the moment though To exit, right click and choose exit. If on Qt, you'll have to kill the program as there are no right click menus in PySimpleGUIQt (yet). - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ sg.theme('Black') diff --git a/DemoPrograms/Demo_PIL_Color_Picker.py b/DemoPrograms/Demo_PIL_Color_Picker.py deleted file mode 100644 index 3601e2f46..000000000 --- a/DemoPrograms/Demo_PIL_Color_Picker.py +++ /dev/null @@ -1,72 +0,0 @@ -import PySimpleGUI as sg -import PIL.ImageGrab - -""" - Color Picker Using Mouse - - Move your mouse anywhere on the screen and the window will show you to - location of the mouse and a square containing the color being shown. - You're also shown the RGB hex value for the color. - - Requires PIL package (and thus only picks colors on primary monitor at the moment) - - You can move the window by grabbing it anywhere and dragging it - - Pressing the F1 key puts the RBG hex value on the clipboard - Pressing the F2 key exits - Clicking moves the window to that location - - If you accidently do something that causes the window to lose focus (e.g. click the mouse) - then the window will move to where your mouse is and force focus back to the window - - As always, there is a right click menu with handy options - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - -layout = [ [sg.Graph((100,100), (0,100), (100,0), key='-GRAPH-')], - [sg.T(k='-OUT-')], - [sg.T(k='-OUT LOC-')], - [sg.T('F1 copy F2 Exit')]] - -window = sg.Window('Color Picker', layout, no_titlebar=False, keep_on_top=True, grab_anywhere=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT, finalize=True) - -window.bind('', '-COPY-') -window.bind('', 'Exit') -window.bind('', '-MOVE-') - -while True: - event, values = window.read(timeout=30) - # print(event, values) - if event == sg.WIN_CLOSED or event == 'Exit': - sg.popup_quick_message(f'Exiting', background_color='red', text_color='white', keep_on_top=True, font='_ 20', non_blocking=False) - - break - if event == 'Edit Me': - sp = sg.execute_editor(__file__) - elif event == 'Version': - sg.popup_scrolled(__file__, sg.get_versions(), keep_on_top=True, location=window.current_location(), non_blocking=True) - - window['-GRAPH-'].erase() - x, y = window.mouse_location() - rgb = PIL.ImageGrab.grab().load()[x, y] - hex_color = sg.rgb(*rgb) - window['-OUT-'].update(f'{hex_color}') - window['-OUT LOC-'].update(f'{window.mouse_location()}') - window['-GRAPH-'].draw_rectangle((0,0), (100,100), hex_color) - - if event == '-COPY-': - sg.clipboard_set(hex_color) - sg.popup_quick_message(f'{hex_color} copied to clipboard', keep_on_top=True, font='_ 20', non_blocking=True, auto_close_duration=1) - elif event == '-MOVE-': - window.move(x,y) - window.force_focus() - - -window.close() - - diff --git a/DemoPrograms/Demo_PIL_Rounded_Rectangle_Buttons.py b/DemoPrograms/Demo_PIL_Rounded_Rectangle_Buttons.py new file mode 100644 index 000000000..de615b5e3 --- /dev/null +++ b/DemoPrograms/Demo_PIL_Rounded_Rectangle_Buttons.py @@ -0,0 +1,90 @@ +from io import BytesIO +from PIL import Image, ImageDraw, ImageFont +import PySimpleGUI as sg + +""" + Demo Rounded Rectangle Buttons created using PIL + + A BIG thank you to @jason990420 for his talented work creating this demo. + + Demonstrates how you can draw buttons rather than using the built-in buttons + with the help of the PIL module. + + One advantage is that the buttons will match your window's theme. + + You'll find more PySimpleGUI programs featured in + Mike Driscoll's PIL book - "Pillow: Image Processing with Python" + + Copyright 2021 PySimpleGUI, @jason990420 +""" + + +def im_to_data(im): + """ + Convert a PIL.Image.Image to a bytes image + :param im: Image + :type: PIL.Image.Image object + :return image in bytes + :type: bytes + """ + with BytesIO() as buffer: + im.save(buffer, format='PNG') + data = buffer.getvalue() + return data + + +def rounded_rectangle(text, font=('arial.ttf', 14), button_color=None,): + """ + Generate rounded image with text aligned center. + :param text: text to show on image, '\n' to split lines. + :type text: str + :param font: font for text + :type font: Tuple + :return image in bytes + :type: bytes + """ + pad, radius, spacing = 5, 10, 5 + ttf_font = ImageFont.truetype(font=font[0], size=font[1]) + if not text: + text = ' ' + paragraph = text.split('\n') + w = max(map(lambda x: ttf_font.getsize(x)[0], paragraph)) + 2 * pad + h = sum(map(lambda x: ttf_font.getsize(x)[1], paragraph)) + 2 * pad + len(paragraph) * spacing + c0, c1 = button_color if button_color else sg.theme_button_color() + c0 = c0 if c0 != sg.COLOR_SYSTEM_DEFAULT else 'white' + c1 = c1 if c1 != sg.COLOR_SYSTEM_DEFAULT else 'white' + im = Image.new("RGBA", (w, h), (255, 255, 255, 0)) + draw = ImageDraw.Draw(im) + draw.rounded_rectangle((0, 0, w-1, h-1), fill=c1, width=0, radius=radius) + draw.multiline_text((pad, pad), text, align='center', font=ttf_font, fill=c0, spacing=spacing) + return im_to_data(im) + + +# sg.theme("dark red") +sg.theme("dark green 7") +# sg.set_options(font=("Arial", 16)) +layout = [[sg.Button('Normal Button')], + [sg.Button('', image_data=sg.EMOJI_BASE64_HAPPY_THUMBS_UP, border_width=0, button_color=(sg.theme_background_color(), sg.theme_background_color()))], + [sg.Button(image_data=rounded_rectangle('Button text\nwith 2 lines', font=('arial.ttf', 25)), button_color=(sg.theme_background_color(), sg.theme_background_color()), border_width=0)]] + +layout += [ + [sg.Button( + image_data=rounded_rectangle(text, font=('cour.ttf', 25)), + button_color=(sg.theme_button_color()[0], sg.theme_background_color()), + border_width=0)] + for text in ( + "My button", + "Button with\n2 lines", + "A long long ..................long line", + "123\n2\n3") + ] + +window = sg.Window('Image and Rounded Button', layout, finalize=True, keep_on_top=True, use_custom_titlebar=True) + +while True: + + event, values = window.read() + if event in (sg.WINDOW_CLOSED, "Exit"): + break + +window.close() diff --git a/DemoPrograms/Demo_PIL_Toggle_Button.py b/DemoPrograms/Demo_PIL_Toggle_Button.py new file mode 100644 index 000000000..7ba97db8b --- /dev/null +++ b/DemoPrograms/Demo_PIL_Toggle_Button.py @@ -0,0 +1,78 @@ +from io import BytesIO +from PIL import Image, ImageDraw, ImageFont +import PySimpleGUI as sg + +""" + Demo Toggle Buttons created using PIL + + A BIG thank you to @jason990420 for his talented work creating this demo. + + Demonstrates how you can draw buttons rather than using the built-in buttons + with the help of the PIL module. + + One advantage is that the buttons will match your window's theme. + + You'll find more PySimpleGUI programs featured in + Mike Driscoll's PIL book - "Pillow: Image Processing with Python" + + Copyright 2021 PySimpleGUI, @jason990420 +""" + + +def im_to_data(im): + """ + Convert a PIL.Image.Image to a bytes image + :param im: Image + :type: PIL.Image.Image object + :return image in bytes + :type: bytes + """ + with BytesIO() as buffer: + im.save(buffer, format='PNG') + data = buffer.getvalue() + return data + + +def toggle_button(button_color=None, size=(100, 40), on=True): + """ + + :return image in bytes + :type: bytes + """ + pad, radius, spacing = 5, 10, 5 + w, h = size + c1, c2 = button_color if button_color else (sg.theme_input_background_color(), sg.theme_background_color()) + im = Image.new("RGBA", (w, h), (255, 255, 255, 0)) + draw = ImageDraw.Draw(im) + draw.rounded_rectangle((0, 0, w - 1, h - 1), fill=c1, width=3, radius=radius) + if on: + draw.rounded_rectangle((2, 2, w - size[1], h - 3), fill=c2, width=3, radius=radius) + else: + draw.rounded_rectangle((size[1], 2, w - 2, h - 3), fill=c2, width=3, radius=radius) + + return im_to_data(im) + + + + +sg.theme("dark red") +# sg.theme("dark green 7") +# sg.theme("dark gray 13") +button_on = toggle_button() +button_off = toggle_button(on=False) +layout = [[sg.T('PIL Made Toggle Buttons')], + [sg.T('On'), sg.Button(image_data=button_on, button_color=(sg.theme_background_color(), sg.theme_background_color()), border_width=0, k='-B1-', metadata=True), sg.T('Off')], + [sg.Button(image_data=button_off, button_color=(sg.theme_background_color(), sg.theme_background_color()), border_width=0, k='-B2-', metadata=False)]] + + +window = sg.Window('PIL Buttons', layout, finalize=True, element_justification='c', use_custom_titlebar=True, font='_ 18', keep_on_top=True) + +while True: + + event, values = window.read() + if event in (sg.WINDOW_CLOSED, "Exit"): + break + window[event].metadata = not window[event].metadata + window[event].update(image_data=button_on if window[event].metadata else button_off) + +window.close() diff --git a/DemoPrograms/Demo_PIL_Use.py b/DemoPrograms/Demo_PIL_Use.py index c0d8b1ec9..bffd98579 100644 --- a/DemoPrograms/Demo_PIL_Use.py +++ b/DemoPrograms/Demo_PIL_Use.py @@ -13,69 +13,51 @@ This function is your gateway to using any format of image (not just PNG & GIF) and to resize / convert it so that it can be used with the Button and Image elements. - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ -def make_square(im, fill_color=(0, 0, 0, 0)): +def make_square(im, min_size=256, fill_color=(0, 0, 0, 0)): x, y = im.size - size = max(x, y) + size = max(min_size, x, y) new_im = Image.new('RGBA', (size, size), fill_color) new_im.paste(im, (int((size - x) / 2), int((size - y) / 2))) return new_im - -def convert_to_bytes(source, size=(None, None), subsample=None, zoom=None, fill=False): +def convert_to_bytes(file_or_bytes, resize=None, fill=False): """ Will convert into bytes and optionally resize an image that is a file or a base64 bytes object. Turns into PNG format in the process so that can be displayed by tkinter - :param source: either a string filename or a bytes base64 image object - :type source: (Union[str, bytes]) - :param size: optional new size (width, height) - :type size: (Tuple[int, int] or None) - :param subsample: change the size by multiplying width and height by 1/subsample - :type subsample: (int) - :param zoom: change the size by multiplying width and height by zoom - :type zoom: (int) - :param fill: If True then the image is filled/padded so that the image is square + :param file_or_bytes: either a string filename or a bytes base64 image object + :type file_or_bytes: (Union[str, bytes]) + :param resize: optional new size + :type resize: (Tuple[int, int] or None) + :param fill: If True then the image is filled/padded so that the image is not distorted :type fill: (bool) :return: (bytes) a byte-string object :rtype: (bytes) """ - if isinstance(source, str): - image = Image.open(source) - elif isinstance(source, bytes): - image = Image.open(io.BytesIO(base64.b64decode(source))) + if isinstance(file_or_bytes, str): + img = PIL.Image.open(file_or_bytes) else: - image = PIL.Image.open(io.BytesIO(source)) - - width, height = image.size - - scale = None - if size != (None, None): - new_width, new_height = size - scale = min(new_height/height, new_width/width) - elif subsample is not None: - scale = 1/subsample - elif zoom is not None: - scale = zoom - - resized_image = image.resize((int(width * scale), int(height * scale)), Image.LANCZOS) if scale is not None else image - if fill and scale is not None: - resized_image = make_square(resized_image) - # encode a PNG formatted version of image into BASE64 + try: + img = PIL.Image.open(io.BytesIO(base64.b64decode(file_or_bytes))) + except Exception as e: + dataBytesIO = io.BytesIO(file_or_bytes) + img = PIL.Image.open(dataBytesIO) + + cur_width, cur_height = img.size + if resize: + new_width, new_height = resize + scale = min(new_height / cur_height, new_width / cur_width) + img = img.resize((int(cur_width * scale), int(cur_height * scale)), PIL.Image.ANTIALIAS) + if fill: + if resize is not None: + img = make_square(img, resize[0]) with io.BytesIO() as bio: - resized_image.save(bio, format="PNG") - contents = bio.getvalue() - encoded = base64.b64encode(contents) - return encoded - - - + img.save(bio, format="PNG") + del img + return bio.getvalue() def random_image(): return random.choice(sg.EMOJI_BASE64_LIST) diff --git a/DemoPrograms/Demo_PNG_Thumbnail_Viewer.py b/DemoPrograms/Demo_PNG_Thumbnail_Viewer.py index fa7dd3e18..36e1d8c6d 100644 --- a/DemoPrograms/Demo_PNG_Thumbnail_Viewer.py +++ b/DemoPrograms/Demo_PNG_Thumbnail_Viewer.py @@ -16,11 +16,7 @@ demos in the repo. There are likely better ones to use. The convert_to_bytes function is the best thing in this demo. - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI.org """ @@ -63,7 +59,7 @@ def convert_to_bytes(file_or_bytes, resize=None): if resize: new_width, new_height = resize scale = min(new_height / cur_height, new_width / cur_width) - img = img.resize((int(cur_width * scale), int(cur_height * scale)), PIL.Image.LANCZOS) + img = img.resize((int(cur_width * scale), int(cur_height * scale)), PIL.Image.ANTIALIAS) with io.BytesIO() as bio: img.save(bio, format="PNG") del img @@ -73,7 +69,7 @@ def convert_to_bytes(file_or_bytes, resize=None): # def image_file_to_bytes(filename, size): # try: # image = Image.open(filename) -# image.thumbnail(size, Image.LANCZOS) +# image.thumbnail(size, Image.ANTIALIAS) # bio = io.BytesIO() # a binary memory resident stream # image.save(bio, format='PNG') # save image as png to it # imgbytes = bio.getvalue() @@ -84,7 +80,7 @@ def convert_to_bytes(file_or_bytes, resize=None): def set_image_to_blank(key): img = PIL.Image.new('RGB', (100, 100), (255, 255, 255)) - img.thumbnail((1, 1), PIL.Image.LANCZOS) + img.thumbnail((1, 1), PIL.Image.ANTIALIAS) bio = io.BytesIO() img.save(bio, format='PNG') imgbytes = bio.getvalue() diff --git a/DemoPrograms/Demo_PNG_Viewer.py b/DemoPrograms/Demo_PNG_Viewer.py index 4e7e19b45..3604ec6e9 100644 --- a/DemoPrograms/Demo_PNG_Viewer.py +++ b/DemoPrograms/Demo_PNG_Viewer.py @@ -3,15 +3,7 @@ import os ''' - Simple Image Browser - - This is an early demo program, so perhaps not quite as sophisticated as later ones. - - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Simple Image Browser based on PySimpleGUI ''' @@ -24,8 +16,8 @@ def main(): return # get list of PNG files in folder - png_files = [os.path.join(folder, f) for f in os.listdir(folder) if f.lower().endswith('.png')] - filenames_only = [f for f in os.listdir(folder) if f.lower().endswith('.png')] + png_files = [folder + '\\' + f for f in os.listdir(folder) if '.png' in f] + filenames_only = [f for f in os.listdir(folder) if '.png' in f] if len(png_files) == 0: sg.popup('No PNG images in folder') @@ -35,39 +27,39 @@ def main(): menu = [['File', ['Open Folder', 'Exit']], ['Help', ['About', ]]] # define layout, show and read the window - col = [[sg.Text(png_files[0], size=(80, 3), key='-FILENAME-')], - [sg.Image(filename=png_files[0], key='-IMAGE-', expand_x=True, expand_y=True)], + col = [[sg.Text(png_files[0], size=(80, 3), key='filename')], + [sg.Image(filename=png_files[0], key='image')], [sg.Button('Next', size=(8, 2)), sg.Button('Prev', size=(8, 2)), - sg.Text('File 1 of {}'.format(len(png_files)), size=(15, 1), key='-FILENUM-')]] + sg.Text('File 1 of {}'.format(len(png_files)), size=(15, 1), key='filenum')]] - col_files = [[sg.Listbox(values=filenames_only, size=(60, 30), key='-LISTBOX-', enable_events=True)], - [sg.Text('Select a file. Use scrollwheel or arrow keys on keyboard to scroll through files one by one.')]] - - layout = [[sg.Menu(menu)], [sg.Col(col_files), sg.Col(col, expand_x=True, expand_y=True)]] - - window = sg.Window('Image Browser', layout, return_keyboard_events=True, use_default_focus=False) + col_files = [[sg.Listbox(values=filenames_only, size=(60, 30), key='listbox')], + [sg.Button('Read')]] + layout = [[sg.Menu(menu)], [sg.Col(col_files), sg.Col(col)]] + window = sg.Window('Image Browser', layout, + return_keyboard_events=True, + location=(0, 0), + use_default_focus=False) # loop reading the user input and displaying image, filename - filenum, filename = 0, png_files[0] + i = 0 while True: event, values = window.read() # --------------------- Button & Keyboard --------------------- if event == sg.WIN_CLOSED: break - elif event in ('Next', 'MouseWheel:Down', 'Down:40', 'Next:34') and filenum < len(png_files)-1: - filenum += 1 - filename = os.path.join(folder, filenames_only[filenum]) - window['-LISTBOX-'].update(set_to_index=filenum, scroll_to_index=filenum) - elif event in ('Prev', 'MouseWheel:Up', 'Up:38', 'Prior:33') and filenum > 0: - filenum -= 1 - filename = os.path.join(folder, filenames_only[filenum]) - window['-LISTBOX-'].update(set_to_index=filenum, scroll_to_index=filenum) + elif event in ('Next', 'MouseWheel:Down', 'Down:40', 'Next:34') and i < len(png_files)-1: + i += 1 + elif event in ('Prev', 'MouseWheel:Up', 'Up:38', 'Prior:33') and i > 0: + i -= 1 elif event == 'Exit': break - elif event == '-LISTBOX-': - filename = os.path.join(folder, values['-LISTBOX-'][0]) - filenum = png_files.index(filename) + + if event == 'Read': + filename = folder + '/' + values['listbox'][0] + else: + filename = png_files[i] + # ----------------- Menu choices ----------------- if event == 'Open Folder': newfolder = sg.popup_get_folder('New folder', no_window=True) @@ -75,23 +67,24 @@ def main(): continue folder = newfolder - png_files = [os.path.join(folder, f) for f in os.listdir(folder) if f.lower().endswith('.png')] - filenames_only = [f for f in os.listdir(folder) if f.lower().endswith('.png')] + png_files = [folder + '/' + + f for f in os.listdir(folder) if '.png' in f] + filenames_only = [f for f in os.listdir(folder) if '.png' in f] - window['-LISTBOX-'].update(values=filenames_only) + window['listbox'].update(values=filenames_only) window.refresh() - filenum = 0 + i = 0 elif event == 'About': sg.popup('Demo PNG Viewer Program', 'Please give PySimpleGUI a try!') # update window with new image - window['-IMAGE-'].update(filename=filename) + window['image'].update(filename=filename) # update window with filename - window['-FILENAME-'].update(filename) + window['filename'].update(filename) # update page display - window['-FILENUM-'].update('File {} of {}'.format(filenum + 1, len(png_files))) + window['filenum'].update('File {} of {}'.format(i+1, len(png_files))) window.close() diff --git a/DemoPrograms/Demo_Paned_Window.py b/DemoPrograms/Demo_Paned_Window.py index 2a1e6ef08..13b8b005a 100644 --- a/DemoPrograms/Demo_Paned_Window.py +++ b/DemoPrograms/Demo_Paned_Window.py @@ -1,13 +1,5 @@ import PySimpleGUI as sg -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - sg.theme('GreenTan') col1 = sg.Col([[sg.Text('in pane1', text_color='blue')], diff --git a/DemoPrograms/Demo_Password_Login.py b/DemoPrograms/Demo_Password_Login.py index b170b985b..ec66c7796 100644 --- a/DemoPrograms/Demo_Password_Login.py +++ b/DemoPrograms/Demo_Password_Login.py @@ -12,12 +12,6 @@ 5. Run program again and test your login! 6. Are you paying attention? The first person that can post an issue on GitHub with the matching password to the hash code in this example gets a $5 PayPal payment - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ diff --git a/DemoPrograms/Demo_Pi_LEDs.py b/DemoPrograms/Demo_Pi_LEDs.py index aabe8cf60..b516d8063 100644 --- a/DemoPrograms/Demo_Pi_LEDs.py +++ b/DemoPrograms/Demo_Pi_LEDs.py @@ -3,14 +3,6 @@ import PySimpleGUI as sg import time -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - # App for Raspberry Pi. if sys.platform == 'win32': diff --git a/DemoPrograms/Demo_Ping_Line_Graph.py b/DemoPrograms/Demo_Ping_Line_Graph.py new file mode 100644 index 000000000..732a2d59d --- /dev/null +++ b/DemoPrograms/Demo_Ping_Line_Graph.py @@ -0,0 +1,670 @@ +# !/usr/bin/env python3 +# -*- coding: utf-8 -*- + +from sys import exit as exit +from threading import Thread +import PySimpleGUI as sg +import time + +""" + A pure python ping implementation using raw sockets. + + (This is Python 3 port of https://github.com/jedie/python-ping) + (Tested and working with python 2.7, should work with 2.6+) + + Note that ICMP messages can only be sent from processes running as root + (in Windows, you must run this script as 'Administrator'). + + Derived from ping.c distributed in Linux's netkit. That code is + copyright (c) 1989 by The Regents of the University of California. + That code is in turn derived from code written by Mike Muuss of the + US Army Ballistic Research Laboratory in December, 1983 and + placed in the public domain. They have my thanks. + + Bugs are naturally mine. I'd be glad to hear about them. There are + certainly word - size dependencies here. + + Copyright (c) Matthew Dixon Cowles, . + Distributable under the terms of the GNU General Public License + version 2. Provided with no warranties of any sort. + + Original Version from Matthew Dixon Cowles: + -> ftp://ftp.visi.com/users/mdc/ping.py + + Rewrite by Jens Diemer: + -> http://www.python-forum.de/post-69122.html#69122 + + Rewrite by George Notaras: + -> http://www.g-loaded.eu/2009/10/30/python-ping/ + + Enhancements by Martin Falatic: + -> http://www.falatic.com/index.php/39/pinging-with-python + + Enhancements and fixes by Georgi Kolev: + -> http://github.com/jedie/python-ping/ + + Bug fix by Andrejs Rozitis: + -> http://github.com/rozitis/python-ping/ + + Revision history + ~~~~~~~~~~~~~~~~ + May 1, 2014 + ----------- + Little modifications by Mohammad Emami + - Added Python 3 support. For now this project will just support + python 3.x + - Tested with python 3.3 + - version was upped to 0.6 + + March 19, 2013 + -------------- + * Fixing bug to prevent divide by 0 during run-time. + + January 26, 2012 + ---------------- + * Fixing BUG #4 - competability with python 2.x [tested with 2.7] + - Packet data building is different for 2.x and 3.x. + 'cose of the string/bytes difference. + * Fixing BUG #10 - the multiple resolv issue. + - When pinging domain names insted of hosts (for exmaple google.com) + you can get different IP every time you try to resolv it, we should + resolv the host only once and stick to that IP. + * Fixing BUGs #3 #10 - Doing hostname resolv only once. + * Fixing BUG #14 - Removing all 'global' stuff. + - You should not use globul! Its bad for you...and its not thread safe! + * Fix - forcing the use of different times on linux/windows for + more accurate mesurments. (time.time - linux/ time.clock - windows) + * Adding quiet_ping function - This way we'll be able to use this script + as external lib. + * Changing default timeout to 3s. (1second is not enought) + * Switching data syze to packet size. It's easyer for the user to ignore the + fact that the packet headr is 8b and the datasize 64 will make packet with + size 72. + + October 12, 2011 + -------------- + Merged updates from the main project + -> https://github.com/jedie/python-ping + + September 12, 2011 + -------------- + Bugfixes + cleanup by Jens Diemer + Tested with Ubuntu + Windows 7 + + September 6, 2011 + -------------- + Cleanup by Martin Falatic. Restored lost comments and docs. Improved + functionality: constant time between pings, internal times consistently + use milliseconds. Clarified annotations (e.g., in the checksum routine). + Using unsigned data in IP & ICMP header pack/unpack unless otherwise + necessary. Signal handling. Ping-style output formatting and stats. + + August 3, 2011 + -------------- + Ported to py3k by Zach Ware. Mostly done by 2to3; also minor changes to + deal with bytes vs. string changes (no more ord() in checksum() because + >source_string< is actually bytes, added .encode() to data in + send_one_ping()). That's about it. + + March 11, 2010 + -------------- + changes by Samuel Stauffer: + - replaced time.clock with default_timer which is set to + time.clock on windows and time.time on other systems. + + November 8, 2009 + ---------------- + Improved compatibility with GNU/Linux systems. + + Fixes by: + * George Notaras -- http://www.g-loaded.eu + Reported by: + * Chris Hallman -- http://cdhallman.blogspot.com + + Changes in this release: + - Re-use time.time() instead of time.clock(). The 2007 implementation + worked only under Microsoft Windows. Failed on GNU/Linux. + time.clock() behaves differently under the two OSes[1]. + + [1] http://docs.python.org/library/time.html#time.clock + + May 30, 2007 + ------------ + little rewrite by Jens Diemer: + - change socket asterisk import to a normal import + - replace time.time() with time.clock() + - delete "return None" (or change to "return" only) + - in checksum() rename "str" to "source_string" + + December 4, 2000 + ---------------- + Changed the struct.pack() calls to pack the checksum and ID as + unsigned. My thanks to Jerome Poincheval for the fix. + + November 22, 1997 + ----------------- + Initial hack. Doesn't do much, but rather than try to guess + what features I (or others) will want in the future, I've only + put in what I need now. + + December 16, 1997 + ----------------- + For some reason, the checksum bytes are in the wrong order when + this is run under Solaris 2.X for SPARC but it works right under + Linux x86. Since I don't know just what's wrong, I'll swap the + bytes always and then do an htons(). + + =========================================================================== + IP header info from RFC791 + -> http://tools.ietf.org/html/rfc791) + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |Version| IHL |Type of Service| Total Length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Identification |Flags| Fragment Offset | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Time to Live | Protocol | Header Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Source Address | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Destination Address | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Options | Padding | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + =========================================================================== + ICMP Echo / Echo Reply Message header info from RFC792 + -> http://tools.ietf.org/html/rfc792 + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Identifier | Sequence Number | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Data ... + +-+-+-+-+- + + =========================================================================== + ICMP parameter info: + -> http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xml + + =========================================================================== + An example of ping's typical output: + + PING heise.de (193.99.144.80): 56 data bytes + 64 bytes from 193.99.144.80: icmp_seq=0 ttl=240 time=127 ms + 64 bytes from 193.99.144.80: icmp_seq=1 ttl=240 time=127 ms + 64 bytes from 193.99.144.80: icmp_seq=2 ttl=240 time=126 ms + 64 bytes from 193.99.144.80: icmp_seq=3 ttl=240 time=126 ms + 64 bytes from 193.99.144.80: icmp_seq=4 ttl=240 time=127 ms + + ----heise.de PING Statistics---- + 5 packets transmitted, 5 packets received, 0.0% packet loss + round-trip (ms) min/avg/max/med = 126/127/127/127 + + =========================================================================== +""" + +# =============================================================================# +import argparse +import os +import sys +import socket +import struct +import select +import time +import signal + +__description__ = 'A pure python ICMP ping implementation using raw sockets.' + +if sys.platform == "win32": + # On Windows, the best timer is time.clock() + default_timer = time.clock +else: + # On most other platforms the best timer is time.time() + default_timer = time.time + +NUM_PACKETS = 3 +PACKET_SIZE = 64 +WAIT_TIMEOUT = 3.0 + +# =============================================================================# +# ICMP parameters + +ICMP_ECHOREPLY = 0 # Echo reply (per RFC792) +ICMP_ECHO = 8 # Echo request (per RFC792) +ICMP_MAX_RECV = 2048 # Max size of incoming buffer + +MAX_SLEEP = 1000 + + +class MyStats: + thisIP = "0.0.0.0" + pktsSent = 0 + pktsRcvd = 0 + minTime = 999999999 + maxTime = 0 + totTime = 0 + avrgTime = 0 + fracLoss = 1.0 + + +myStats = MyStats # NOT Used globally anymore. + + +# =============================================================================# +def checksum(source_string): + """ + A port of the functionality of in_cksum() from ping.c + Ideally this would act on the string as a series of 16-bit ints (host + packed), but this works. + Network data is big-endian, hosts are typically little-endian + """ + countTo = (int(len(source_string) / 2)) * 2 + sum_val = 0 + count = 0 + + # Handle bytes in pairs (decoding as short ints) + loByte = 0 + hiByte = 0 + while count < countTo: + if (sys.byteorder == "little"): + loByte = source_string[count] + hiByte = source_string[count + 1] + else: + loByte = source_string[count + 1] + hiByte = source_string[count] + try: # For Python3 + sum_val = sum_val + (hiByte * 256 + loByte) + except: # For Python2 + sum_val = sum_val + (ord(hiByte) * 256 + ord(loByte)) + count += 2 + + # Handle last byte if applicable (odd-number of bytes) + # Endianness should be irrelevant in this case + if countTo < len(source_string): # Check for odd length + loByte = source_string[len(source_string) - 1] + try: # For Python3 + sum_val += loByte + except: # For Python2 + sum_val += ord(loByte) + + sum_val &= 0xffffffff # Truncate sum_val to 32 bits (a variance from ping.c, which + # uses signed ints, but overflow is unlikely in ping) + + sum_val = (sum_val >> 16) + (sum_val & 0xffff) # Add high 16 bits to low 16 bits + sum_val += (sum_val >> 16) # Add carry from above (if any) + answer = ~sum_val & 0xffff # Invert and truncate to 16 bits + answer = socket.htons(answer) + + return answer + + +# =============================================================================# +def do_one(myStats, destIP, hostname, timeout, mySeqNumber, packet_size, quiet=False): + """ + Returns either the delay (in ms) or None on timeout. + """ + delay = None + + try: # One could use UDP here, but it's obscure + mySocket = socket.socket( + socket.AF_INET, socket.SOCK_RAW, socket.getprotobyname("icmp")) + except socket.error as e: + print("failed. (socket error: '%s')" % e.args[1]) + raise # raise the original error + + my_ID = os.getpid() & 0xFFFF + + sentTime = send_one_ping(mySocket, destIP, my_ID, mySeqNumber, packet_size) + if sentTime == None: + mySocket.close() + return delay + + myStats.pktsSent += 1 + + recvTime, dataSize, iphSrcIP, icmpSeqNumber, iphTTL = receive_one_ping( + mySocket, my_ID, timeout) + + mySocket.close() + + if recvTime: + delay = (recvTime - sentTime) * 1000 + if not quiet: + print("%d bytes from %s: icmp_seq=%d ttl=%d time=%d ms" % ( + dataSize, socket.inet_ntoa(struct.pack("!I", iphSrcIP)), icmpSeqNumber, iphTTL, delay) + ) + myStats.pktsRcvd += 1 + myStats.totTime += delay + if myStats.minTime > delay: + myStats.minTime = delay + if myStats.maxTime < delay: + myStats.maxTime = delay + else: + delay = None + print("Request timed out.") + + return delay + + +# =============================================================================# +def send_one_ping(mySocket, destIP, myID, mySeqNumber, packet_size): + """ + Send one ping to the given >destIP<. + """ + # destIP = socket.gethostbyname(destIP) + + # Header is type (8), code (8), checksum (16), id (16), sequence (16) + # (packet_size - 8) - Remove header size from packet size + myChecksum = 0 + + # Make a dummy heder with a 0 checksum. + header = struct.pack("!BBHHH", ICMP_ECHO, 0, myChecksum, myID, mySeqNumber ) + + padBytes = [] + startVal = 0x42 + # 'cose of the string/byte changes in python 2/3 we have + # to build the data differnely for different version + # or it will make packets with unexpected size. + if sys.version[:1] == '2': + bytes = struct.calcsize("d") + data = ((packet_size - 8) - bytes) * "Q" + data = struct.pack("d", default_timer()) + data + else: + for i in range(startVal, startVal + (packet_size - 8)): + padBytes += [(i & 0xff)] # Keep chars in the 0-255 range + # data = bytes(padBytes) + data = bytearray(padBytes) + + # Calculate the checksum on the data and the dummy header. + myChecksum = checksum(header + data) # Checksum is in network order + + # Now that we have the right checksum, we put that in. It's just easier + # to make up a new header than to stuff it into the dummy. + header = struct.pack("!BBHHH", ICMP_ECHO, 0, myChecksum, myID, mySeqNumber ) + + packet = header + data + + sendTime = default_timer() + + try: + # Port number is irrelevant for ICMP + mySocket.sendto(packet, (destIP, 1)) + except socket.error as e: + print("General failure (%s)" % (e.args[1])) + return + + return sendTime + + +# =============================================================================# +def receive_one_ping(mySocket, myID, timeout): + """ + Receive the ping from the socket. Timeout = in ms + """ + timeLeft = timeout / 1000 + + while True: # Loop while waiting for packet or timeout + startedSelect = default_timer() + whatReady = select.select([mySocket], [], [], timeLeft) + howLongInSelect = (default_timer() - startedSelect) + if whatReady[0] == []: # Timeout + return None, 0, 0, 0, 0 + + timeReceived = default_timer() + + recPacket, addr = mySocket.recvfrom(ICMP_MAX_RECV) + + ipHeader = recPacket[:20] + iphVersion, iphTypeOfSvc, iphLength, \ + iphID, iphFlags, iphTTL, iphProtocol, \ + iphChecksum, iphSrcIP, iphDestIP = struct.unpack( + "!BBHHHBBHII", ipHeader + ) + + icmpHeader = recPacket[20:28] + icmpType, icmpCode, icmpChecksum, \ + icmpPacketID, icmpSeqNumber = struct.unpack("!BBHHH", icmpHeader) + + if icmpPacketID == myID: # Our packet + dataSize = len(recPacket) - 28 + # print (len(recPacket.encode())) + return timeReceived, (dataSize + 8), iphSrcIP, icmpSeqNumber, iphTTL + + timeLeft = timeLeft - howLongInSelect + if timeLeft <= 0: + return None, 0, 0, 0, 0 + + +# =============================================================================# +def dump_stats(myStats): + """ + Show stats when pings are done + """ + print("\n----%s PYTHON PING Statistics----" % (myStats.thisIP)) + + if myStats.pktsSent > 0: + myStats.fracLoss = (myStats.pktsSent - + myStats.pktsRcvd) / myStats.pktsSent + + print("%d packets transmitted, %d packets received, %0.1f%% packet loss" % ( + myStats.pktsSent, myStats.pktsRcvd, 100.0 * myStats.fracLoss + )) + + if myStats.pktsRcvd > 0: + print("round-trip (ms) min/avg/max = %d/%0.1f/%d" % ( + myStats.minTime, myStats.totTime / myStats.pktsRcvd, myStats.maxTime + )) + + print("") + return + + +# =============================================================================# +def signal_handler(signum, frame): + """ + Handle exit via signals + """ + dump_stats() + print("\n(Terminated with signal %d)\n" % (signum)) + sys.exit(0) + + +# =============================================================================# +def verbose_ping(hostname, timeout=WAIT_TIMEOUT, count=NUM_PACKETS, + packet_size=PACKET_SIZE, path_finder=False): + """ + Send >count< ping to >destIP< with the given >timeout< and display + the result. + """ + signal.signal(signal.SIGINT, signal_handler) # Handle Ctrl-C + if hasattr(signal, "SIGBREAK"): + # Handle Ctrl-Break e.g. under Windows + signal.signal(signal.SIGBREAK, signal_handler) + + myStats = MyStats() # Reset the stats + + mySeqNumber = 0 # Starting value + + try: + destIP = socket.gethostbyname(hostname) + print("\nPYTHON PING %s (%s): %d data bytes" % + (hostname, destIP, packet_size)) + except socket.gaierror as e: + print("\nPYTHON PING: Unknown host: %s (%s)" % (hostname, e.args[1])) + print() + return + + myStats.thisIP = destIP + + for i in range(count): + delay = do_one(myStats, destIP, hostname, + timeout, mySeqNumber, packet_size) + + if delay == None: + delay = 0 + + mySeqNumber += 1 + + # Pause for the remainder of the MAX_SLEEP period (if applicable) + if (MAX_SLEEP > delay): + time.sleep((MAX_SLEEP - delay) / 1000) + + dump_stats(myStats) + + +# =============================================================================# +def quiet_ping(hostname, timeout=WAIT_TIMEOUT, count=NUM_PACKETS, + packet_size=PACKET_SIZE, path_finder=False): + """ + Same as verbose_ping, but the results are returned as tuple + """ + myStats = MyStats() # Reset the stats + mySeqNumber = 0 # Starting value + + try: + destIP = socket.gethostbyname(hostname) + except socket.gaierror as e: + return False + + myStats.thisIP = destIP + + # This will send packet that we dont care about 0.5 seconds before it starts + # acrutally pinging. This is needed in big MAN/LAN networks where you sometimes + # loose the first packet. (while the switches find the way... :/ ) + if path_finder: + fakeStats = MyStats() + do_one(fakeStats, destIP, hostname, timeout, + mySeqNumber, packet_size, quiet=True) + time.sleep(0.5) + + for i in range(count): + delay = do_one(myStats, destIP, hostname, timeout, + mySeqNumber, packet_size, quiet=True) + + if delay == None: + delay = 0 + + mySeqNumber += 1 + + # Pause for the remainder of the MAX_SLEEP period (if applicable) + if (MAX_SLEEP > delay): + time.sleep((MAX_SLEEP - delay) / 1000) + + if myStats.pktsSent > 0: + myStats.fracLoss = (myStats.pktsSent - + myStats.pktsRcvd) / myStats.pktsSent + if myStats.pktsRcvd > 0: + myStats.avrgTime = myStats.totTime / myStats.pktsRcvd + + # return tuple(max_rtt, min_rtt, avrg_rtt, percent_lost) + return myStats.maxTime, myStats.minTime, myStats.avrgTime, myStats.fracLoss + + +# =============================================================================# +def main(): + parser = argparse.ArgumentParser(description=__description__) + parser.add_argument('-q', '--quiet', action='store_true', + help='quiet output') + parser.add_argument('-c', '--count', type=int, default=NUM_PACKETS, + help=('number of packets to be sent ' + '(default: %(default)s)')) + parser.add_argument('-W', '--timeout', type=float, default=WAIT_TIMEOUT, + help=('time to wait for a response in seoncds ' + '(default: %(default)s)')) + parser.add_argument('-s', '--packet-size', type=int, default=PACKET_SIZE, + help=('number of data bytes to be sent ' + '(default: %(default)s)')) + parser.add_argument('destination') + # args = parser.parse_args() + + ping = verbose_ping + # if args.quiet: + # ping = quiet_ping + ping('Google.com', timeout=1000) + # ping(args.destination, timeout=args.timeout*1000, count=args.count, + # packet_size=args.packet_size) + + +# set coordinate system +canvas_right = 300 +canvas_left = 0 +canvas_top = 0 +canvas_bottom = 300 +# define the coordinates you'll use for your graph +x_right = 100 +x_left = 0 +y_bottom = 0 +y_top = 500 + +# globale used to communicate with thread.. yea yea... it's working fine +g_exit = False +g_response_time = None + + +def ping_thread(args): + global g_exit, g_response_time + + while not g_exit: + g_response_time = quiet_ping('google.com', timeout=1000) + + +def convert_xy_to_canvas_xy(x_in, y_in): + scale_x = (canvas_right - canvas_left) / (x_right - x_left) + scale_y = (canvas_top - canvas_bottom) / (y_top - y_bottom) + new_x = canvas_left + scale_x * (x_in - x_left) + new_y = canvas_bottom + scale_y * (y_in - y_bottom) + return new_x, new_y + + +# start ping measurement thread +thread = Thread(target=ping_thread, args=(None,)) +thread.start() + +layout = [[sg.Text('Ping times to Google.com', font='Any 18')], + [sg.Canvas(size=(canvas_right, canvas_bottom), + background_color='white', key='canvas')], + [sg.Quit()]] + +window = sg.Window('Ping Times To Google.com', + layout, grab_anywhere=True, finalize=True) + +canvas = window['canvas'].TKCanvas + +prev_response_time = None +i = 0 +prev_x, prev_y = canvas_left, canvas_bottom +while True: + time.sleep(.2) + + event, values = window.read(timeout=0) + if event == 'Quit' or event == sg.WIN_CLOSED: + break + + if g_response_time is None or prev_response_time == g_response_time: + continue + try: + new_x, new_y = convert_xy_to_canvas_xy(i, g_response_time[0]) + except: + continue + + prev_response_time = g_response_time + canvas.create_line(prev_x, prev_y, new_x, new_y, width=1, fill='black') + prev_x, prev_y = new_x, new_y + if i >= x_right: + i = 0 + prev_x = prev_y = last_x = last_y = 0 + canvas.delete('all') + else: + i += 1 + +# tell thread we're done. wait for thread to exit +g_exit = True +thread.join() + +window.close() +exit(0) diff --git a/DemoPrograms/Demo_Pip_Installs.py b/DemoPrograms/Demo_Pip_Installs.py deleted file mode 100644 index c5a58d17b..000000000 --- a/DemoPrograms/Demo_Pip_Installs.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env python -""" - Obtain the version number for a package installed on any versions of Python on your system by uysing - the sg.execute_pip_get_local_package_version() call. - - Copyright 2024 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - -import PySimpleGUI as sg - - -layout = [ [sg.T('Package Name:'), sg.In(s=15, setting='', k='-PACKAGE-')], - [sg.T('Full path to interpreter'), sg.In(setting='', k='-INT-')], - [sg.CB('Use threading', setting=False, k='-THREADED-')], - [sg.MLine(s=(80,20), reroute_cprint=True, k='-ML-')], - [sg.Button('Show', bind_return_key=True), sg.Button('Exit')] ] - -window = sg.Window('Get PIP Installed Versions', layout, print_event_values=False, enable_close_attempted_event=True, auto_save_location=True) - -while True: # Event Loop - event, values = window.read() - if event == sg.WINDOW_CLOSE_ATTEMPTED_EVENT: - window.settings_save(values) - break - if event in (None, 'Exit'): - break - if event == 'Show': - package = values['-PACKAGE-'] - if not package: - continue - - win = window if values['-THREADED-'] else None - - out = sg.execute_pip_get_local_package_version(package, interpreter=values['-INT-'] if values['-INT-'] else None, window=win, key='-PIP VER-') - if win is None: - if not out: - out = 'Not Installed' - sg.cprint(f'Not threaded {package} ', end='', c='white on green') - sg.cprint(f'version = {out}', end='', c='white on red') - sg.cprint('') - elif event == '-PIP VER-': - out = values[event] if values[event] else 'Not Installed' - sg.cprint(f'{package} ', end='', c='white on blue') - sg.cprint(f'version = {out}', end='', c='white on red') - sg.cprint('') - -window.close() diff --git a/DemoPrograms/Demo_Pong.py b/DemoPrograms/Demo_Pong.py new file mode 100644 index 000000000..2f9f38f4e --- /dev/null +++ b/DemoPrograms/Demo_Pong.py @@ -0,0 +1,309 @@ +# !/usr/bin/env python + +""" + Pong + + One of the most important video games. + Pong was created by Al Alcorn and it did not use a microprocessor + + This demo is based on some initial code by Siddharth Natamai + + In 2021, it was reworked by Jay Nabaonne into this version you see today. + + A big + + ###### ## ## ###### ## ## ## ## ## ## ###### ## ## ## + ## ## ## ## ## ### ## ## ## ## ## ## ## ## ## ## + ## ###### ## ## ###### #### ## ## ## ## ## ## ## + ## ## ## ###### ## ### #### ###### ## ## ## ## ## + ## ## ## ## ## ## ## ## ## ## ## ## ## ## + ## ## ## ## ## ## ## ## ## #### ###### ###### ## + + to Jay for making it a smooth playing game. + @jaynabonne https://github.com/jaynabonne + + Copyright 2021 PySimpleGUI, Jay Nabonne +""" + +import PySimpleGUI as sg +import random +import datetime + + +GAMEPLAY_SIZE = (700, 400) +BAT_SIZE = (20, 110) +STARTING_BALL_POSITION = (327, 200) +BALL_RADIUS = 12 +BACKGROUND_COLOR = 'black' +BALL_COLOR = 'green1' +BALL_SPEED = 300 +BAT_SPEED = 400 + +UP_ARROW = 38 +DOWN_ARROW = 40 + +player1_up_keycode = ord('W') +player1_down_keycode = ord('S') +player2_up_keycode = UP_ARROW +player2_down_keycode = DOWN_ARROW + +num_rounds = 10 + + +class Bat: + def __init__(self, graph: sg.Graph, colour, x, field_height): + self.graph = graph + self.field_height = field_height + self.width = BAT_SIZE[0] + self.height = BAT_SIZE[1] + self.current_x = x + self.current_y = self.field_height / 2 - self.height / 2 + self.id = graph.draw_rectangle( + (self.current_x, self.current_y), + (self.current_x + self.width, self.current_y + self.height), + fill_color=colour + ) + self.vy = 0 + + def stop(self): + self.vy = 0 + + def up(self): + self.vy = -BAT_SPEED + + def down(self): + self.vy = BAT_SPEED + + def is_hit_by(self, pos): + bat_p0 = (self.current_x, self.current_y) + bat_p1 = (bat_p0[0] + self.width, bat_p0[1] + self.height) + return bat_p0[0] <= pos[0] <= bat_p1[0] and bat_p0[1] <= pos[1] <= bat_p1[1] + + def update(self, delta: float): + new_y = self.current_y + self.vy * delta + if new_y <= 0: + new_y = 0 + self.stop() + if new_y + self.height >= self.field_height: + new_y = self.field_height - self.height + self.stop() + self.current_y = new_y + + self.graph.relocate_figure(self.id, self.current_x, self.current_y) + + +class Ball: + def __init__(self, graph: sg.Graph, bat_1: Bat, bat_2: Bat, colour): + self.graph = graph # type: sg.Graph + self.bat_1 = bat_1 + self.bat_2 = bat_2 + self.id = self.graph.draw_circle( + STARTING_BALL_POSITION, BALL_RADIUS, line_color=colour, fill_color=colour) + self.current_x, self.current_y = STARTING_BALL_POSITION + self.vx = random.choice([-BALL_SPEED, BALL_SPEED]) + self.vy = -BALL_SPEED + + def hit_left_bat(self): + return self.bat_1.is_hit_by((self.current_x - BALL_RADIUS, self.current_y)) + + def hit_right_bat(self): + return self.bat_2.is_hit_by((self.current_x + BALL_RADIUS, self.current_y)) + + def update(self, delta: float): + self.current_x += self.vx * delta + self.current_y += self.vy * delta + if self.current_y <= BALL_RADIUS: # see if hit top or bottom of play area. If so, reverse y direction + self.vy = -self.vy + self.current_y = BALL_RADIUS + if self.current_y >= GAMEPLAY_SIZE[1] - BALL_RADIUS: + self.vy = -self.vy + self.current_y = GAMEPLAY_SIZE[1] - BALL_RADIUS + if self.hit_left_bat(): + self.vx = abs(self.vx) + if self.hit_right_bat(): + self.vx = -abs(self.vx) + + self.position_to_current() + + def position_to_current(self): + self.graph.relocate_figure(self.id, self.current_x - BALL_RADIUS, self.current_y - BALL_RADIUS) + + def restart(self): + self.current_x, self.current_y = STARTING_BALL_POSITION + self.position_to_current() + + +class Scores: + def __init__(self, graph: sg.Graph): + self.player_1_score = 0 + self.player_2_score = 0 + self.score_1_element = None + self.score_2_element = None + self.graph = graph + + self.draw_player1_score() + self.draw_player2_score() + + def draw_player1_score(self): + if self.score_1_element: + self.graph.delete_figure(self.score_1_element) + self.score_1_element = self.graph.draw_text( + str(self.player_1_score), (170, 50), font='Courier 40', color='white') + + def draw_player2_score(self): + if self.score_2_element: + self.graph.delete_figure(self.score_2_element) + self.score_2_element = self.graph.draw_text( + str(self.player_2_score), (550, 50), font='Courier 40', color='white') + + def win_loss_check(self): + if self.player_1_score >= num_rounds: + return 'Left player' + if self.player_2_score >= num_rounds: + return 'Right player' + return None + + def increment_player_1(self): + self.player_1_score += 1 + self.draw_player1_score() + + def increment_player_2(self): + self.player_2_score += 1 + self.draw_player2_score() + + def reset(self): + self.player_1_score = 0 + self.player_2_score = 0 + self.draw_player1_score() + self.draw_player2_score() + + +def check_ball_exit(ball: Ball, scores: Scores): + if ball.current_x <= 0: + scores.increment_player_2() + ball.restart() + if ball.current_x >= GAMEPLAY_SIZE[0]: + scores.increment_player_1() + ball.restart() + + +def goto_menu(window): + window['-MAIN_MENU-'].update(visible=True) + window['-GAME-'].update(visible=False) + + +def pong(): + sleep_time = 10 + + inner_layout = [[sg.Graph(GAMEPLAY_SIZE, + (0, GAMEPLAY_SIZE[1]), + (GAMEPLAY_SIZE[0], 0), + background_color=BACKGROUND_COLOR, + key='-GRAPH-')], + [sg.Button('Back to Menu', key="-MENU-")]] + + main_menu_layout = [[sg.Text("Pong", font="Courier 40", justification="center", size=(None, 1))], + [sg.Text("-- Instructions --", font="Courier 16")], + [sg.Text("Left player controls: W and S", font="Courier 12")], + [sg.Text("Right player controls: \u2191 and \u2193", font="Courier 12")], + [sg.Text("Escape to pause game", font="Courier 12")], + [sg.Text("", font="Courier 8")], + [sg.Text("Winner is first to 10 points", font="Courier 12")], + [sg.Text("", font="Courier 8")], + [sg.Button("Start", key='-START-', font="Courier 24"), + sg.Button("Quit", key='-QUIT-', font="Courier 24")]] + + layout = [[sg.pin(sg.Column(main_menu_layout, key='-MAIN_MENU-', size=GAMEPLAY_SIZE)), + sg.pin(sg.Column(inner_layout, key='-GAME-', visible=False))]] + + window = sg.Window('Pong', layout, finalize=True, use_default_focus=False) + + window.bind("", "+KEY+") + window.bind("", "-KEY-") + + graph_elem = window['-GRAPH-'] # type: sg.Graph + + scores = Scores(graph_elem) + bat_1 = Bat(graph_elem, 'red', 30, GAMEPLAY_SIZE[1]) + bat_2 = Bat(graph_elem, 'blue', GAMEPLAY_SIZE[0] - 30 - BAT_SIZE[0], GAMEPLAY_SIZE[1]) + ball_1 = Ball(graph_elem, bat_1, bat_2, 'green1') + + start = datetime.datetime.now() + last_post_read_time = start + + game_playing = False + + while True: + pre_read_time = datetime.datetime.now() + processing_time = (pre_read_time - last_post_read_time).total_seconds() + time_to_sleep = sleep_time - int(processing_time*1000) + time_to_sleep = max(time_to_sleep, 0) + + event, values = window.read(time_to_sleep) + now = datetime.datetime.now() + delta = (now-last_post_read_time).total_seconds() + # read_delta = (now-pre_read_time).total_seconds() + last_post_read_time = now + # print("**", event, delta, time_to_sleep, processing_time, read_delta) + if event in (sg.WIN_CLOSED, "-QUIT-"): + break + elif event == "-START-": + scores.reset() + ball_1.restart() + window['-MAIN_MENU-'].update(visible=False) + window['-GAME-'].update(visible=True) + sg.popup('\nPress a key to begin.\n', + no_titlebar=True, + font="Courier 12", + text_color=sg.BLUES[0], + background_color=sg.YELLOWS[1], + any_key_closes=True, + button_type=sg.POPUP_BUTTONS_NO_BUTTONS) + last_post_read_time = datetime.datetime.now() + game_playing = True + elif event == "-MENU-": + game_playing = False + goto_menu(window) + elif game_playing: + if event == "+KEY+": + if window.user_bind_event.keycode == player1_up_keycode: + bat_1.up() + elif window.user_bind_event.keycode == player1_down_keycode: + bat_1.down() + elif window.user_bind_event.keycode == player2_up_keycode: + bat_2.up() + elif window.user_bind_event.keycode == player2_down_keycode: + bat_2.down() + elif event == "-KEY-": + if window.user_bind_event.keycode in [player1_up_keycode, player1_down_keycode]: + bat_1.stop() + elif window.user_bind_event.keycode in [player2_up_keycode, player2_down_keycode]: + bat_2.stop() + elif window.user_bind_event.keycode == 27: + sg.popup('\nPaused. Press a key to resume.\n', + no_titlebar=True, + font="Courier 12", + text_color=sg.BLUES[0], + background_color=sg.YELLOWS[1], + any_key_closes=True, + button_type=sg.POPUP_BUTTONS_NO_BUTTONS) + last_post_read_time = datetime.datetime.now() + + if game_playing: + ball_1.update(delta) + bat_1.update(delta) + bat_2.update(delta) + + check_ball_exit(ball_1, scores) + + winner = scores.win_loss_check() + if winner is not None: + sg.popup('Game Over', winner + ' won!!', no_titlebar=True) + game_playing = False + goto_menu(window) + + window.close() + + +if __name__ == '__main__': + pong() diff --git a/DemoPrograms/Demo_Pong_Multiple_Platforms.py b/DemoPrograms/Demo_Pong_Multiple_Platforms.py index 0ab567bfc..1be3ec7ae 100644 --- a/DemoPrograms/Demo_Pong_Multiple_Platforms.py +++ b/DemoPrograms/Demo_Pong_Multiple_Platforms.py @@ -4,14 +4,6 @@ import PySimpleGUI as sg import random -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - GAMEPLAY_SIZE = (700, 400) BAT_SIZE = (20, 110) STARTING_BALL_POSITION = (327, 200) diff --git a/DemoPrograms/Demo_Popup_Custom.py b/DemoPrograms/Demo_Popup_Custom.py index 725caba05..32bc6a353 100644 --- a/DemoPrograms/Demo_Popup_Custom.py +++ b/DemoPrograms/Demo_Popup_Custom.py @@ -11,12 +11,6 @@ This example is for a DropDown / Combobox Popup. You provide it with a title, a message and the list of values to choose from. It mimics the return values of existing Popup calls (None if nothing was input) - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. ''' diff --git a/DemoPrograms/Demo_Popups.py b/DemoPrograms/Demo_Popups.py index 8a44569ef..6ba21181d 100644 --- a/DemoPrograms/Demo_Popups.py +++ b/DemoPrograms/Demo_Popups.py @@ -1,29 +1,28 @@ #!/usr/bin/env python import PySimpleGUI as sg -import sys + ''' - Usage of Popups in PSG - - While this is an older demo, it is a good instroduction to a FEW of the popups available to you. - Check out the System Call Reference for the full list: http://www.PySimpleGUI.org - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. - + Usage of all Popups in PSG ''' + +sg.Print('test') +sg.popup_get_file('Get file', save_as=True, + file_types=(("ALL Files", "*.jpg"),)) + # Here, have some windows on me.... -[sg.popup_no_wait('No-wait Popup', relative_location=(-500+100*x, -500)) for x in range(10)] -answer = sg.popup_yes_no('Do not worry about all those open windows... they will disappear at the end', 'Are you OK with that?') +[sg.popup_no_wait('No-wait Popup', location=(500+100*x, 500)) + for x in range(10)] +answer = sg.popup_yes_no( + 'Do not worry about all those open windows... they will disappear at the end', 'Are you OK with that?') if answer == 'No': - sg.popup_cancel('OK, we will destroy those windows as soon as you close this window') + sg.popup_cancel( + 'OK, we will destroy those windows as soon as you close this window') sys.exit() -sg.popup_no_buttons('Your answer was', answer, relative_location=(0, -200), non_blocking=True) -text = sg.popup_get_text('This is a call to PopopGetText') +sg.popup_non_blocking('Your answer was', answer, location=(1000, 600)) +text = sg.popup_get_text( + 'This is a call to PopopGetText', location=(1000, 200)) sg.popup_get_file('Get file') sg.popup_get_folder('Get folder') sg.popup('Simple popup') @@ -31,4 +30,5 @@ sg.popup_no_border('No border') sg.popup_no_frame('No frame') sg.popup_cancel('Cancel') -sg.popup_auto_close('This window will Autoclose and then everything else will close too....') +sg.popup_okCancel('OK Cancel') +sg.popup_auto_close('Autoclose') diff --git a/DemoPrograms/Demo_Post_An_Issue.py b/DemoPrograms/Demo_Post_An_Issue.py index 88ac9fde3..8af8cbe24 100644 --- a/DemoPrograms/Demo_Post_An_Issue.py +++ b/DemoPrograms/Demo_Post_An_Issue.py @@ -7,19 +7,15 @@ This program is going to be inside of PySimpleGUI itself. - It produces Markdown code that + It produces Markdown code that - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ -def _github_issue_post_make_markdown(issue_type, operating_system, os_ver, psg_port, psg_ver, gui_ver, python_ver, - python_exp, prog_exp, used_gui, gui_notes, - cb_docs, cb_demos, cb_demo_port, cb_readme_other, cb_command_line, cb_issues, cb_github, - detailed_desc, code, ): +def make_markdown(issue_type, operating_system, os_ver, psg_port, psg_ver, gui_ver, python_ver, + python_exp, prog_exp, used_gui, gui_notes, + cb_docs, cb_demos, cb_demo_port, cb_readme_other, cb_command_line, cb_issues, cb_github, + detailed_desc, code,): body = \ """ ### Type of Issue (Enhancement, Error, Bug, Question) @@ -112,7 +108,7 @@ def _github_issue_post_make_markdown(issue_type, operating_system, os_ver, psg_p -def _github_issue_post_make_github_link(title, body): +def make_github_link(title, body): pysimplegui_url = "https://github.com/PySimpleGUI/PySimpleGUI" pysimplegui_issues = f"{pysimplegui_url}/issues/new?" @@ -123,7 +119,7 @@ def _github_issue_post_make_github_link(title, body): ######################################################################################################### -def _github_issue_post_validate(values, checklist, issue_types): +def validate(values, checklist, issue_types): issue_type = None for itype in issue_types: if values[itype]: @@ -307,12 +303,9 @@ def main_open_github_issue(): # [sg.Frame('Details',frame_details, font=font_frame, k='-FRAME DETAILS-')], # [sg.Frame('Minimum Code to Duplicate',frame_code, font=font_frame, k='-FRAME CODE-')], [sg.Text(size=(12,1), key='-OUT-')], - ] - - layout_pane = sg.Pane([sg.Col(top_layout), sg.Col(bottom_layout)], key='-PANE-') + [sg.B('Post Issue'), sg.B('Create Markdown Only'), sg.B('Quit')]] - layout = [[layout_pane], - [sg.Col([[sg.B('Post Issue'), sg.B('Create Markdown Only'), sg.B('Quit')]], expand_x=False, expand_y=False)]] + layout = [[sg.Pane([sg.Col(top_layout), sg.Col(bottom_layout)])]] window = sg.Window('Open A GitHub Issue', layout, finalize=True, resizable=True, enable_close_attempted_event=False) for i in range(len(checklist)): @@ -321,7 +314,6 @@ def main_open_github_issue(): window['-ML CODE-'].expand(True, True, True) window['-ML DETAILS-'].expand(True, True, True) window['-ML MARKDOWN-'].expand(True, True, True) - window['-PANE-'].expand(True, True, True) # window['-FRAME CODE-'].expand(True, True, True) # window['-FRAME DETAILS-'].expand(True, True, True) @@ -373,13 +365,13 @@ def main_open_github_issue(): continue checkboxes = ['X' if values[('-CB-', i)] else ' ' for i in range(len(checklist))] - if not _github_issue_post_validate(values, checklist, issue_types): + if not validate(values, checklist, issue_types): continue - markdown = _github_issue_post_make_markdown(issue_type, operating_system, os_ver, 'tkinter', values['-VER PSG-'], values['-VER TK-'], values['-VER PYTHON-'], - values['-EXP PYTHON-'], values['-EXP PROG-'], 'Yes' if values['-CB PRIOR GUI-'] else 'No', values['-EXP NOTES-'], *checkboxes, values['-ML DETAILS-'], values['-ML CODE-']) + markdown = make_markdown(issue_type, operating_system, os_ver, 'tkinter', values['-VER PSG-'], values['-VER TK-'], values['-VER PYTHON-'], + values['-EXP PROG-'], values['-EXP PYTHON-'], 'Yes' if values['-CB PRIOR GUI-'] else 'No', values['-EXP NOTES-'], *checkboxes, values['-ML DETAILS-'], values['-ML CODE-'] ) window['-ML MARKDOWN-'].update(markdown) - link = _github_issue_post_make_github_link(values['-TITLE-'], window['-ML MARKDOWN-'].get()) + link = make_github_link(values['-TITLE-'], window['-ML MARKDOWN-'].get()) if event == 'Post Issue': webbrowser.open_new_tab(link) else: diff --git a/DemoPrograms/Demo_Program_Desktop_Widget_LED_Clock_Weather.py b/DemoPrograms/Demo_Program_Desktop_Widget_LED_Clock_Weather.py deleted file mode 100644 index 246cbac5c..000000000 --- a/DemoPrograms/Demo_Program_Desktop_Widget_LED_Clock_Weather.py +++ /dev/null @@ -1,251 +0,0 @@ -#!/usr/bin/env python -import PySimpleGUI as sg -import datetime -import calendar -import requests -import webbrowser - -''' - Example of a weather App, using: - - openweathermap.org - - - - Copyright 2023-2024 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -''' - - - -NUM_COLS = 5 # Changes number of days in forecast (don't change this) - - -def settings_window(location=(None, None)): - tsize = 15 - layout = [[sg.Text('Settings')], - [sg.T('API Key', s=tsize, justification='r'), sg.I(s=35, setting='', k='-api key-')], - [sg.T('Latitude', s=tsize, justification='r'), sg.I(s=12, setting='', k='-lat-')], - [sg.T('Longitude', s=tsize, justification='r'), sg.I(s=12, setting='', k='-lon-')], - [sg.CB('Use F Degrees', s=tsize, setting=True, k='-faren-')], - [sg.OK(), sg.B('Register with openweathermap.org for API key', k='-register-'), sg.Cancel()], - ] - - window = sg.Window('Settings', layout, location=location) - - while True: - event, values = window.read() - if event == sg.WIN_CLOSED or event == 'Cancel': - break - if event == 'OK': - window.settings_save(values) - break - if event == '-register-': - webbrowser.open(r'https://home.openweathermap.org/users/sign_up') - - window.close() - - return event == 'OK' - - -class GUI(): - lat = 0 - lon = 0 - api_key = '' - faren = True - def __init__(self): - self.blink_count = 0 - sg.theme('black') - sg.set_options(border_width=0) - - # Create clock layout - clock = [ - [ - sg.Image(data=ledblank, key='-HOUR1-'), - sg.Image(data=ledblank, key='-HOUR2-'), - sg.Image(data=ledblank, key='-COLON-'), - sg.Image(data=ledblank, key='-MIN1-'), - sg.Image(data=ledblank, key='-MIN2-')]] - - # Create the weather columns layout - weather_cols = [] - for i in range(NUM_COLS): - weather_cols.append( - [[sg.T('', size=(4, 1), font='Any 20', justification='center', key='_DAY_' + str(i)), ], - [sg.Image(data=w1, background_color='black', key='-ICON-' + str(i), pad=((4, 0), 3)), ], - [sg.T('--', size=(3, 1), justification='center', font='Any 20', key='_high_' + str(i), pad=((10, 0), 3))], - # [sg.T('--', size=(3, 1), justification='center', font='Any 20', key='_low_' + str(i), pad=((10, 0), 3))], - ]) - - # Create the overall layout - layout = [[sg.Column(clock, background_color='black', justification='c')], - [sg.Column(weather_cols[x], background_color='black') for x in range(NUM_COLS)] + [sg.T('×', enable_events=True, key='Exit')] + [ - sg.T('C' if GUI.faren else 'F', enable_events=True, key='-CELCIUS-')], - ] - - right_click = sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT - right_click[1].append('Settings') - # Create the window - self.window = sg.Window('DarkSky Weather Forecast Widget', layout, - background_color='black', - grab_anywhere=True, - use_default_focus=False, - no_titlebar=True, - alpha_channel=.8, # set an alpha channel if want transparent - right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT, - enable_close_attempted_event=True, - auto_save_location=True, - finalize=True) - - self.colon_elem = self.window.find_element('-COLON-') - self.hour1 = self.window.find_element('-HOUR1-') - self.hour2 = self.window.find_element('-HOUR2-') - self.min1 = self.window.find_element('-MIN1-') - self.min2 = self.window.find_element('-MIN2-') - - self.window['Exit'].set_cursor('hand1') - self.window['-CELCIUS-'].set_cursor('hand1') - - def update_clock(self): - # update the clock - now = datetime.datetime.now() - real_hour = now.hour - 12 if now.hour > 12 else now.hour - hour1_digit = led_digits[real_hour // 10] - self.hour1.Update(data=hour1_digit) - self.hour2.Update(data=led_digits[real_hour % 10]) - self.min2.Update(data=led_digits[int(now.minute) % 10]) - self.min1.Update(data=led_digits[int(now.minute) // 10]) - # Blink the : - self.colon_elem.Update(data=ledcolon if self.blink_count % 2 else ledblank) - self.blink_count += 1 - - def update_weather(self): - today_weekday = datetime.datetime.today().weekday() - - try: - # Make the API - units = 'imperial' if GUI.faren else 'metric' - api_url = f'http://api.openweathermap.org/data/2.5/forecast?lat={GUI.lat}&lon={GUI.lon}&units={units}&appid={GUI.api_key}' - - response = requests.get(api_url) - data = response.json() - # print(data) - # Extract relevant information (e.g., temperature, weather conditions) - i = 0 - for forecast in data["list"]: - date_time = forecast["dt_txt"] - if not '12:00:00' in date_time: - continue - # print(forecast) - temp = forecast["main"]["temp"] - weather_desc = forecast["weather"][0]["description"] - - print(f"{date_time}: {temp}°F, {weather_desc}") - day_element = self.window.find_element('_DAY_' + str(i)) - max_element = self.window.find_element('_high_' + str(i)) - icon_element = self.window.find_element('-ICON-' + str(i)) - day_element.Update(calendar.day_abbr[(today_weekday + i) % 7]) - # sg.Print(icon_data, wait=True) - try: - icon_data = weather_icon_dict[weather_desc] - icon_element.update(icon_data) - except: - sg.Print(f'Missing icon data for description: "{weather_desc}"') - max_element.update(int(temp)) - i += 1 - except requests.RequestException as e: - print(f"Error fetching data: {e}") - - -def main(): - if not sg.user_settings_get_entry('-api key-', None): - if not settings_window(): - sg.popup_error('Cancelling setup and exiting') - exit() - GUI.lat = sg.user_settings_get_entry('-lat-', 0) - GUI.lon = sg.user_settings_get_entry('-lon-', 0) - GUI.api_key = sg.user_settings_get_entry('-api key-', '') - GUI.faren = sg.user_settings_get_entry('-faren-', True) - - # Get the GUI object that is used to update the window - # location = sg.user_settings_get_entry('-location-', (None, None)) - - gui = GUI() - - # ---------- EVENT LOOP ---------- - last_update_time = 0 - while True: - # Wake up once a second to update the clock and weather - event, values = gui.window.read(timeout=1000) - if event in (None, 'Exit', sg.WIN_CLOSE_ATTEMPTED_EVENT): - break - elif event == '-CELCIUS-': - GUI.faren = not GUI.faren - sg.user_settings_set_entry('-faren-', GUI.faren) - gui.window['-CELCIUS-'].update('C' if GUI.faren else 'F') - elif event == 'Edit Me': - sg.execute_editor(__file__) - elif event == 'Version': - sg.main_get_debug_data() - elif event == 'Settings': - if settings_window(gui.window.current_location()): # if settings changed - GUI.lat = sg.user_settings_get_entry('-lat-', 0) - GUI.lon = sg.user_settings_get_entry('-lon-', 0) - GUI.api_key = sg.user_settings_get_entry('-api key-', '') - GUI.faren = sg.user_settings_get_entry('-faren-', True) - gui.window['-CELCIUS-'].update('C' if GUI.faren else 'F') - gui.update_weather() - - gui.update_clock() - # update weather once ever 6 hours - now = datetime.datetime.now() - if last_update_time == 0 or (now - last_update_time).seconds >= 60 * 60 * 6 or event == '-CELCIUS-': - print('*** Updating Weather ***') - last_update_time = now - gui.update_weather() - - -led0 = b'iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAAEb0lEQVRoge2Zz4scRRTHP/WqunsDSQjiBvFHSBC8eRJRFAXFgCIYRVBPgrkoiBgU9U/w4iEgHjwEBT2IKHiIiBfBg4oB8SJ4CgHjIXpSE5Ls9HR9PUz1ZGa6dnZ2dmdnlXzh0TPV1a+/9erVq/eqHSB2GWzZBHK4TmpW7EpSIdfokuwE4jrv12QDk40LhNElNmapluFNZtws8bdEsQCCrb69zvEL0FP3DQLk0nUf6P6y1A8hSKAeKG6jNEmnQG8Xhe5cWZE5p5ZHy3mM1GHQz2Z6YGVF33ovgeqkZDukn65vVpVeDUFfr6wIM9k0UgdBa6DfvNc9VaWvErFeGuW80h8Z3Imi0PGqkkCny1KYyY+Q6qw+A64AtzUNn0k8GwI9M56oayLzxxABzjleCgFvxqleb3DDddd5NiT4dL01Rr6oa54pS9aKgqMSl+YgFoG9wFtm7JE42evRkyjJh54sqRZ9YFXi07rmLjMuJEWbXY0B+Ac4Dpysa2qmD6xDavSFnsEoVyVWm4bzEg35gLcRKYA7wuDXRsE561M28R8GVptFYQ5t/yYTj6aSagPnJKlJDNfsJtD2n3Uw3fdnVsNOo0PKwdKJ/YcstSDM71ObeHhR6FpqN04fsHS/2lGfmhU76lNbcvRF5eez7pkbOnpcr+McaPe03KCV6TdsvApccY4KqIESOGvG7yOb6bzT+6MEZvgYqRlkIRdTojypc5iGtnnysbLUFTMJ9Kv3OhLCIGV1Tm5O8c4JMz1fluon3WdC0KrZWDre2kc5Yk+GoJ+KQoeKQjg3mdjPJQGE9zpeFPq+KHRDCDlC6hSjMJjT6BzmPcSIYqSZc8omUQDRDOccagZaJ3V3/NcYJHT3ec8nzrHfORqzbXP02jke854PzSicoyHvo52pu9d7/ZlKq++81w1FIcw6Zt6MeBBmejQEXUw+ddp7VdN8qm280XtdSISupjrtTAja5/3At+Zw8uCccE5Hi0I9M8UR3aeqSjg3VvcNZ6U14T7nOJCWf8lgvu9uGm4fqXO1SWmfe9iMIkb6XItFtwA4N+bYHVfRxBy3NeCsSf809JOOUf2tk4+2zey/25HSWEZHTuvST/Jy9l86qRyWTuq6pWaFMqt6+aQybUsnlcPSSf3/LLUdxUTOqXN6px4vAsPD17bjVg7NQtpmRvfX4YY9K6kmdTjrPefSg3FiR58FbUV0JkZwDpOm6lj3g5HSzfPe82JR8EFdc8iMNTZvqQjsBz4GXi5L3kunw7C+W4xlnYdDGFYyfzinB8tS36Skr2H614Rp0j77elXpRDrYF+jzVJhkk7xRhgG45BzPlSWvNQ0PNQ29dK+ZU8Qg939nbY3LMfJGOinuzxLRA3DZjKfKkhdi5FjTcJVryd5WUQPv1zXnvOfdEDiwTr+xHP1ICHp6zx59lKasv4UpmyrO6ZWq0uNV1Skcxuq+9s9BMx6Jkb+20UKjiAzy/55zfAmdkJAtRrONC8KGX0ZHsQgL5ZCrvHfSKDNjV27I/wIpihClbBNQxAAAAABJRU5ErkJggg==' - -led1 = b'iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAACD0lEQVRoge2Yv27UQBCHv9kkRCAhXgAkSh6AmoKCFFBENLwBFQ0PQIPES0BJky4NDR0lJT28A4ICQc7nH4V3FccZ+9zcrAv/pJVP3jntp525+XMGiIUp1QbwtELN1Qo1V1WhLK+hqkEVIC8fVYFKdDB3gLvW3ZUN9qsAmRlnKfEoQ6WBTShQCxybcW7Gk7blt2N3GAVkGegmcA6ctC0AB45tyE2VgL5txifgROLfhH0YFMBH4DGwYdpFIVBtft5XlwA8l/UVGujtbhMgGMrL3p7W2rcrlor2DtV32dHM7+wdSiOfp7TG1FytUHO1Qnllpko7bL3n3N4pJE+VFvhLftf09n/Kz16KXO/NJJBAr8wEKF23i4GxvDDTh5T0OqUxII2NXntRiavGDJM4pOtChwqfZhrgDfDCjA3jnUOY+zDT2xxTf0Gnea9KTJVD36UkgS5ALWgDeugEe+jg8DTPegnY0k009/JetbF92wMoEFu73rmHB/oVOUCuXbS2zrvqUF6RrgIlLmPKy9zrTXlaJNQi3bc8KGmBUCwgphYzOPRVeqdd/1OFQJVDvuVa1y8tcgaHEKhy7EvgsxlHXE401dxXysqFxHO6UevGhH1YTCkf9kfiFPiaXdk4tuG/vgT8Ap4B31PilmMXOmIVHdAF+wMzGuCHdAWkClQ5mJHDq2X0/q0MVe2mplS99nlaJNR/DW4BrSasyZkAAAAASUVORK5CYII=' - -led2 = b'iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAADmElEQVRoge2Zz4scRRiGn7d6NlHJQaKoKHgwxGgiIpiTegrI4kEUkdwEQcRF8pdI0INIrorkoqB48SB4EhQUvSoIIkjixaiExdnNTtfrYaqyPZmamZ6e7GQC88JHM71dVU999ev7tgSYFVO41QAlraHaaiWheqWXSrYMxQnt39LVVwLolT64T+Jem22gOgAQM5w3hyV+8bhPisN3GPhU4qTNf5M+WgBIwCFgS+KqxKU4Oohj3ssvHpL4UuLJGKm5OR7LDQl4NQQeBp4A3oiRCqjT38dWX3btJZszwA8SFbCXCnW1AfteerGqOCLxboz00/A1F1ZxS4gMPXMlRjaB7yQ2UsGqgwWGU0DACxKPxMiHdT0GkzVxutSpsn9sNiU+riqetulP6skM9YA303Q4b7MD3DEvFAw9JmDb5pU07l3UA/rAOeC8zd6MhmcurDwPSJV1UZ7gpwrzpxNUrvQ6XAflcqXdu6S5tqCuW39zK2ijlTyQ11BttYZqq6VCSe3W39pTbbWSUK139EWSidzz0jFTOiVaQYVUuO3ZdaNyuRxlNM/RuUOXDBSBu4GjDOOseT3WA/4CvgbeSnA5fPl3QhlPspCexyX/KjmC++DdOa0PNnhL8supHoM/l3xIMmCNtl0GqtLz8RD8u2SD61RZF8sgWyH4tRB8MQRXZaAyVAaS5O8T0G6quKvVqQ6DXwrBgDfKQONQecjOSH5P8mnJlxue6go1SEDvSw6pnQlAo1AZ6JkQfCVV8kEIfqyqfDkEW3KU7DmtTs93koemwBjw9dWXV9mDEl/YHAV2gbdj5M4QOC1xXOoUpwu4BvwUY+uVO+KlU8kb2e0Gb4MfyPNsRi+n2YwhG/dUVt7omvl8c2+qGu/nVT37E6CweZaOkyZIvQBUW63kgbyGaqvbG+qgJ3dTt7enlqk1VFu1guoam3dVq8Qh/wMW9pOILhLtzr+pUANgA/hR4k8Am7gAFOyHSJ2g6gbQuRD4LEbuSfHUvNlMBI4AH0lciJEeww5P00g8dVLyIIW/P4NPhOBvQlg4ccj2eoo+e9NjqlGoEyl0/U3yoyH4q0biMFjA9nKnJJ9NWcwUsFGopyT/EYKPVZU/SUA7qcJFbS8BXgNvJo+FaVA5TD0m+bmq8sU0ZDkLuVmWQ+wdyc9PABu5xco/7geeZZhSH8R9Xw3cBfwt8a09dpVWvFrjxpdLVvG6Vizn/DEreodc0koeyP8DbP/uIBO2okgAAAAASUVORK5CYII=' - -led3 = b'iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAADoUlEQVRoge2ZzascRRTFf6d7TCLBaALiImAIRoObJzqu3JiVCzH/QEACLlyI4sdCiArqwp2gG/8BcavgB7gRsgquRRBc+lwEBTExEMzLdB8XVTWv01090zPznPcgc6FopvtO1al7q+qee0uAOWBS7DeAnGxADZUDCWrU92EdaE1+l6nn/dokB2CUUzguccLmJlD+D0Aq4BBQS/zurk267pM4AnwFbAH/ZJVWB1QB54GbwF/cabGO9UqJSuJUXfMDcAao2Zs15jjgBHgWeA44DFwiTHwS9TpjVTalzW8S54Cfo9JOnN2y7XYEdAN4WuIJ4H2CJ/omMG2KzxKM5OOSr4ANruJz0VbH5zXwGcmvN769G8cbNTB0lksycQWUNn9LvAB8ATwK/Jsz7wxx1K+AF4ELwIexnyNxrLmWarcCXEgzdea1ZIV3onV2YjP4vYyl5k66js9VFnraSY8r2EX0WwgG7va+k3eoJACTmVq7stbYV2YOypwcyIB894Jqho8hcvdaalHZgBoqG1BDpRNmJOHWyZuYw9At3ZaSwBLqzLfcGT8o9pXxz7lOh0g1Y7BcDpAF1bRWmuWx2JYBNgL+BL6XuGBP+RrA1dz4ZCyoRDFsaomzwNc2pwm0eBE3JtePgOcljgLfxAl/ArzVAyJLzErJFIXH4KstWrssHTb4PPhl8Gct+t1q3ZdJ8RD4p9jZrdj5sm3SaFux/8M9oLJHggmp1k5R8ApwjZCrrUr0SuAl4KTEm8At+s+krqUkSwoulPwM+PoKLkz/uQg+1+Dnr0XuX3Q9lV/o090nUQEPAw8SKO2i59UI+APYsvmOsIMr4B7gIvA5u7s86fcCgpicxpx/e0EwTVAT4CMJ7OngAKfTuC39uVKz2ome1k1KHJr93M7oD65dLHuaN/+bW9RD3+27bEANlQ2oobJWUEPD1MZSQ2XjvlxUyL0bFGYSF1qWT5WEuJcb7Ebm3VxLNYPpsuXqFIh/zBTNFk6xSqCSeMTmYylcXbA4W6iB+4APbN4APiVUh2cN3mGdsFtHPwn+lb2po++An5J8SZp+e5UhdXQ71L0l7ge+BR4jpFYFy1MYE5jmZZuxxAPA2+SLsx1QhUQtcW9d8yXwZAS0F5dGE0JCe8VmDJwCTsyYxG5qVRQ+Kvnyii6b58pt8FjyWe5M62gnDunHQ8AYuM7e3/eJQIGPAdvAL3Qz5H29GU27uA0gX+BgfXfIuY2z73fIOTmQLOE/hw5ngBNVOEQAAAAASUVORK5CYII=' - -led4 = b'iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAADdElEQVRoge2Zu4tkRRSHv3OqukdFxd0FUQRdxESMFgQDBWFBQ/P1LzBREHSNzAwNRPwbVkMDQUMVdIKNfIAYimAgsivjY3fsufUzmKrZftSdvn3t7tvC/OBw+z6q6runHufUbQPEjsmHBqjpDKqrzqC6qgq1TdJaW9X21XZjzXIgtVyf0f3uXAyBBIQtAF0ajYhmC/cFyPLxwRD0/Xisp0MQoJivr9MiCDO9HqO+Go+F2Un72WahHghBN0PQgbueyWCjNQKVul4JQTLT5zEKM/lpUOdD0K8xSqDfzfScmQCFNQCF7KHX3CWQQF+MRsuhLoSgGxlKoD/MdDlGAfMFVzLPQFdz3Ye5/i+7eOpCCLoRggSa5IIH7nrcvTdY8fKV3GWTqbprUAuzz7gzJQPHM+S+lDif0sn9VVXKPJL9ryX1VKFq5+vIb8qatOzFqlC1Qn081LeOzlDbVDWabAqqa71xoaA2mB1XwklN/5/UZWgtQm2y+zqq7qkNgfVeEnZBOwm1sCQox6Y2TcfGrirP1+qtXVuAcmb7vqTF0zGwllefpvJ8Sa81BeqVtWsB6hbwpxn3SkyAMfCDGb+Z8URKOKsH5wAcANeBf8wYSxwCe8DNlkk1m4iBLrvrwEwCfWemSzHq63w+ATUrWsmd3nPXCyHo73z+jbseypltNUefB3vRXfsx6vnRSPs56WtyZX2slH0/Rr0co/Zj1MM5cZwDWoQqYA7CXZ9loNug9B/tVgZ7KwThrj3quX91IiXyQEyJqynxszt7QFN7g47WAHcB10LgW+AaMDKjob6onp7sg550108xSu5q3KUVrZT5MEY9Ox7rl7yb+dRdd1e60Eoftinkt3w0BJ5yZ9LyZqfJgb8Al/g4Jc6lxO3suY9i5ErT4NLMUtNpe1QZjJ2t7LLfyB46nBr4+3k3Y7PPL1cZY31jUgCOuLOITq91TT5Od1knqALWVzZ3XKbBA3KnT0Hbliqxb3ioyrXBoXaz+yrXzqBq2kmoszFVU80rg0PVdjXlt1We26hKwz+agdlMQB7MU01u6JOUeNXsJEcbFAry/lHig5R40529HPMGH1MNx7nSuxJvx+Os6aiy7+ucT61LDRAl3jk64mIIPNbyda93mtvXSup7D+il/DfI3P21fCLvpc7/921TagEY1FNtGjz21bSTUP8C1hqqTm9IJgsAAAAASUVORK5CYII=' - -led5 = b'iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAADyUlEQVRoge2Zv4tcVRTHP99zZ6NEggg2iYgWpghKEGNlYaGNYifBgAGbNFaCkCJ/haAiiGDAgOkFKxtttrGKFlaCbJFlwVVEo+5m5t2vxdy3+3bmzcybmXVnA/uFw5v35r37Pu/cX+fcK8AcM8WqAdp0AtVVxxKqN+mPo6I14z1NLdfaLx6hWj0VwLMS/9iYIeRhawCcAbYkfrXHHFF70CrHsxG+npIN3gX3wYNDtB2wwXcifDalA+8uv/cBE1ABNyXuSPwlcbOqyMVbh+GxqrznB4nXgC2bkMje99OB9ly/dAB8mDODnHlHIoBcCsxLWL8ArUfwisSWTYIDQGNQo3C3bE5LvJUSSSKV/2IBA1gDvpV4Hfg9572aGa2BiQ0dYBf4NGfeS4nLEXxs829LIbOUgdPA9zZXgb9zJgoQjPf0ieNUDdcHPqoqrqXEuVL4YE6oWgPApaflKfdNhWr2gvMSVBX3l4Cqa2DWGNgKJWnYaWk0/sb5or2wbfTuDNWm5lf+36P91N63Kh3LKOHBgTqpvhaNQ0lDW6FOqq+rjqWnOo/o9QTaDEXm1ULTTP2AGscaJjXgps3w0xQjZXaCEoDNn+V8wDAwQ2IdeBx4jP04qKvM8KO2Jf6w9yLZWc8cCN7PSP4mwgbfB7+Rkm+U8zqRmMd2S6Lwk+SnSqIQjfe22MELNdjDEf46wlcjfEOywVUpfBGrn/05whckA+51harB1sBIfrukWjvgvKTVHluXjGRN9lg7bUhOkk9F+PMC1i9fvIj1C9AG+MUIf5KSX4qYVJXtUCpfApgIfxZhS64ke07L5XhX8nOSb5fmsBnhF1rA2tcSJDwSDq9JXIqg1/ZAB/WAX2w+sHnTZhd4CNiUuAj8NpK6T+sFe20slca5iNVeOM8wbW+2sz74mZH7Oo3oZjiupFk3TlA9Lpn9tN3s18Jced+o5h00azWrZHSKaptnH5woYdU6geqqlUNVjK9NrByqLT5bOVSbTqC66sihDn19atF1qXru63Usp5On6kXTRZeq6zlzA/hRQkyfR2d6KgGVxPUIruTMva5f0pCBU8AmcC2CL3PmQtlimfZMq/VKnP5+yWQyyycO30m+mJI3SvR5D/zkSDzVDiXtAb1bgOp0aZk9mTpx+CrCz0d4G7wr+VwJIKdCpQJ0OSVn6VCARjeLvpB8KcJ3I/z0LKgoQFfqwH/JamuzQTneivDLvZ6fKFB1ojJxv/FV4BFgh8XD4GmqgEcZ7tVsjyQNq94E3Ru3mhBT95CPYp2qTiiaWrmn2nQsJ+T/AHYfURS2h8j3AAAAAElFTkSuQmCC' - -led6 = b'iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAAEBUlEQVRoge2ZP4gdVRTGf9+Z3c1qZJFUChJWLBQigmLQiJYhIkQLwcLWwkYrGy1s0sRC0gQUIljYWCRaaKONJoKNIoJKwEgaBcEuJuwmu/vefBZz7+68P/N23p91X7EfHGbmzsy935x777nfuSPAzBlivwkMwwGptphLUgvDCv8vpmVDueibfQMF+4BtT2UyhyUeBP61Kfao0RK4B7gO3Gl4xtkOgY8WhT+RbPAaeGPGtg42+EKEkVxvv2ZY6WJJ8jcRfjrCFxKxTqpkFpbr+qAojGTV2m4kheRrEb4l+VhR+FyEnb6wM6VtJkLnJCM5mgn1kpLk3xKRG5KPR/i95LHuFB4q0/Fs6rJiNCEPhIQ8uFdsrticjGBD4nXgJuOHizyoz0ucLUsWbLrZHQ1Q8hQGQuKqxMNlSYdqaq5LHAeuAodoji27YQsIu9X7g8HT1TcE0AHutllNpDpAd0JSxRjvDpBS7Tx3Vad2T0yGcTzcQ2q3Rrenxh5jLhfkHlKyJ+6eWWLQU97v5XgIqbnz1DSza5aY/4E+Lzgg1RY9EX23iB273B+FcVaDgWWmft5NRPJDJZOrhNwlbYj1kNoCbkpgs0klVf4Erkk8YLPYstJ+CPhbYiOtGG3qMOBIx2OS/0pK8XfJj0T4UlKft0ckBE12O9X1qeQiJQp1pQsNcrif2GMpgXiiKHwxyeNp5HB+91KElyNcgKOZUC8pKn3sJaok4sOah8opLXvsTNLpi6N1+qCnjkr+WPLjki/XUq1JCeXU6mKEn4zwR5KP9HXlUFL55n0R/il12ffg1Qh/G2FL7kr2mJbf+SzCq0XhX9NHXpa80kBsYDJ8J/GczR1gGfhR4hWJ+6WJ4pSoZvUtmy9tHqrV/XkEL9tDE4qdDBl8nZ1cbSudP5/uF81jYFQOZ8CvJu9v1gb+D2l89XuqJ07Vg6PZCXi5bJINj4Iq8cgernu7KRAPRPRRi2GX8VMs9R09pKwfc7kg7yuppklzQKotDjzVFgeeaou58FR/EG1Faha7C3lJaZOBD/0NUq8ogKV0PYlKyF+dG6ovM2OTKtPNfyR+AUgbqONmM3kX8GdgDThMJWUKmj+wkdQCcEPixQjeKkueklhjst3hFeAL4KUIvirLVnVs65lF8B9J66yDT0T4fNJB0/x5yPrp3Qifiti+vpL0VJbh2XpI1/v7lMRp4I2yZDOVdSc0U3XZmbLkUZvTRaXM3LBBF/0XAl4oCk4A75QlG1RdqSktgE3gfZsjNq9FcJe07YyB7st2L/jZovDbM8j1mqwEW/KbEX4mokrndkscliVOJnHfZvqOC1PNvAL4muFKdoBUMPkmxrhoamvofsNe/RHtR5Pen4dfxgOYS5XwH7eZhqnTFNxUAAAAAElFTkSuQmCC' - -led7 = b'iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAACtElEQVRoge2ZwWoUQRCGv+ruFRPx4iOIGPEuETyLGDH4AqII4tN49KQg+AB6jAjiOeBFg5gHEA+KHiQmJpme38P0hN3ZSZysm949zA9NQ2/t9LfdtV1V0waIOZObNUCbeqiumkuocNgHuWjF+D/NWsayylI/DHHoSi2ZUUgUTH/VDNgHzgK/zPgijazOGJQDSmDZjOdAlIhTBiuARWATuG/GjsQPRrdNzeZSfy8ERTMJVII0hRZTv2mmJee0Brqe5vNDLjYGBSikftVMuwlqPz100raXgDa81+XBQK+9l0BXukIBGqT+pnPadu6/VqxeoXXQee/1Lj1PoKsNqEMdHSpnDMBaWXInBJ46R6DyOTvqiw2VwAKwIfGwLHkRI9fS8wct9kdCAQf/vjdFwUXvCUx2hhjwR+ItHAAdNvk/oaD6pQ7Yi5HdCYEEnAEupDF/hH0nqBrMON62NaFKIHaw7wwF0zn6u/youQzIPVRX9VBd1UN1VQ/VVVmh6lDTNj6srFCO0UCsofGm3YlLVDFvG1i3KvoVaUxm/E5janznxJul/pSZXqU0OIIemAmzg7qgZssCNQLmnF6GoEdmI4XKkF3eYtSlFp0DiSCx32KTTXUuVQCPgVWqtLgtC822fYAw05NUS26Z6XYIbVuY0Z/M9Cw5+S5VebXjnC41fOtY6fCkqh13UeJGrLL0ulQ7XZacG7KDzD7VLBxqiGYxkd3R2yZsFhN9QO6qHqqreqiu6qG6aj6gbPT4zF44dEneshcOYxPa+Bur7IXDR1dNORKEZ7l9AHfNeO89A6oMtE3ZoJQm+xkjKxIfzFpfV2eFgiqf8sD3smRF4nMaj7PevpjAvgK3nOOb9yw0bGZ23+epAJdDYAv4VBQHN2gzvYRsu4CEGZ/o9VHRPKlmfl3bpvmIfQ3NJdRfFS/ZxKoPEs0AAAAASUVORK5CYII=' - -led8 = b'iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAAEi0lEQVRoge2ZT4gcRRTGf+9Vd/VkIRjxIqggJF5E8JSDF/EQjKAICflDQjAnUdGD6EEQDHrRmwdBD6IIweQkiiIevOTgKSAiiiAiBDxpomhiJLvTVf08TPVkZqdmMz272Z2FfPCoobrr1dev/r1vSgBjwaBbTSCHW6RmxUKSKnKVkuxmw8ivMlld35LZjCU5ra8JUgD3qyJNQ5+bM74R2AGsqPJL02RJGGCSyru9t5NVZf+JmIEFsGYDrQYzsL9U7diOHXavc2P9AzYMhEvlURH2x8iBsuSaKi69KRtgxmAS/y3CwbLkZAg8FuNY/5AZncvAsRA41DQ86T1XRFAgAM06LKTOflflibLkuRjZX9f8I/klZYAVqXy2qsxSiM+UpT3ivV1KQ9mk+q7WtvvNOXuoquwL54bPToiM9Z9+57EMHK9ryqLgcFnyoRlLZkS6bRcGlMCfwDPO8XoIPBojy0BvSpsJUjLyoAYOh0C/LNltxs5EqisUuAp8mQjVieg0TI0UXJ9896lCCFyNsfP+1U5wBfaM+G26kBodmpZAYzbxrCuxBmaO8pqRGnUK04+FWTHrR01sCZtx5t0IC5klbI9ILSSpjYZM+b0WNi1Syvihe6N3Fw6bOqcWbvi6YKYdvT2nlO47envEqMjAj417yPmbIJWbZC4lYs2cpNrjKec7NzITpK6YgQiNGcJgxZwz43Yz7mSQQXZFAfwhwjlV9oRw/WAW4V8RMMsLh6GJ2HtFYZayzTe9tyPeDwVEAIsdLKQM85qqPV5V9s5I1vmW94bImGhgICImdZ+J8EFR0Ae+UeVMv4+kr5lnIbTtVkQ4WhQcEuFi0/ByjEO/uTajLM2DoWoPem8rqhY2QGq17a+o2p6qMkTMr5JWUyOlQCPCKeeIqlw04/0QhonePGgnuQAnvOcBMy4Bb4eAmmWz0LEoIWKnynIw7iL2Qlna096bqVqjatbRRtsc895e837gW9WeL8tWfOYj5Rikq8erijN1TZ3kdAG8UpZ8JcI9ZvTprmYq4IIZJ0R4NQTqtLILVfaL8HWMw/7HItXqrpeS7qtHVs557w3nsuN/I5OR8ufkL3Jdvj+VZPuaui83d9ovaCX8PDDye1yuv0k1k5HR7U4c10Fq1M8YMqS2R+qy2YiLFKl2kuQE6pZHKre9zERqs68ktjxSOdwiNSu2L6mNmuhr/VE2ipnUjKajZ56sc6hmpnRmKUcf628th+2XnY8RzBARrKM1IgN5pcq3xYDW6hRlNaZGKjD49/Z0UXBOle+ahmWRucWqA153jiXgQAgspzoykZpKqgd8UpacLQo+XVlhqWnWLRxO9/scLAp2Ose+GEFktki1Oc/nzvGuCJ8tL7NkRpiTUIsGuMOMszFy1Hs88HCMBJ2cQRM1twHfO8cbzvFxXbPLjHqdhNqO+sBdTcNHdc2LZcmvRcHOKe+PJe/7ej070uvZhSQa5736mGYxlT+q2sFez/YWxYR4GJNYrRDdC+w24zIz7hkdIAxuMnYBP6nyQ+a+b/vcjLbC8WbDyO/yWVJbjYU8kP8HKX/sOnQ6GT4AAAAASUVORK5CYII=' - -led9 = b'iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAAEYklEQVRoge2ZT2gkRRTGf+91VXeQJcp6kAVBEFn/ggh7ET0IggjBGBNW1+Bpc1E8uDfPIgqC4OLNu6IL4oJ48+RR0LMXvQgii4d1E4PZdFc9D1M9yWRqJjPpbGbAfFBM0l3d7+tXr+q9r0oAY86gsyaQwympSTGXpFzuoqR2p2HkZ5kcvN6SOYkpOcrWECmAh1XxMbIDFHeATAQqIKjyS4zZPgaYpN9zInapquymqhlYDRaPsTVgBrYlYm+UpT1YlgP2AesHeuuRJTPWQ2CtLLklgks95RiaJTvbqqyWJa/EyEXVAfuQmX03gZeaho0QWPaev0RQoEluP2prkrFbIiyXJZdCYLVp+Nvy0WuAufT7WnKvgV0vCnumLO2PojBL7rcjtPa5G6r2bFnaV973771dVQP209957AArIbAAvO49n4lwFqiZbrkweuvOlggbIlwJgbUQ2AEWRjwzRKp1pk8EXgyBWoRHzThDbyimRQFsAdeAtRCoc4bHkWqDrA1KgIdiRMz4xyy/hkwCVc471yc57uOGSDmR3mjvQ2BvBsL0q70kEmFEUB9KKmew6yrfPjdpoh3uJyeR9cZjiNTsKZ16anLMZZE37Kl5HL55wGlMTYrhvJiJqTZPdfmCtq46iFyWGJmQc50iI4r6CZGrDDTjhH6/1tAmgAhmRkgkf1DlbIzcZ0ZzRDI3gO9FeJJegifZ2RwnHGiLdxH7uCzNRMzArjpny2VpO0lINGBhitakyrMWsVXv7aOy7FWdIvap94bIgGhIPIZ1n6nySVGwKMJ3wLW6xpsNlC/ToH0uAutVxfNmRDPeDAGJMRsOB1n26+XHqsq2i6IvjbpKqwD2r6o9UVWGqpUHpNVIT7XecqrUIrxTFFyta+IxeEpF2PCe+4EmRj5sGpTRs3KgFUVhImIKhnP2lvdmqhZVzTq0y1VlV1olI2LvOme0dsZ5SpM4jGlWFCIEVS6IcK8IzZTeMqAEfhfhZeCD3V3qdM+LcNF7vt7dpWBvVmZFRdw3TYMZzoyfY8QmrLGzUOXzJBw0kcWMc8kJ+z90nNLZI0a31VzoKeQmfdT+4cmJiYlItdO56/bQ0YXDHGAiUp1i6bB3Z67N3FNzSSqHmZOaS0/NjNTYDJCZRP9fT/UxoaY8UVIxM1QTCYccNNXsXVFkPHWk4VMgivRyn8iRWrsV8GP6sLDfwKQJuc3iDmhUWSoK3gd20p7ntDB6xx7vqbLoPet1zU56/yj/D1R9qrq3r61qz3lv20nJdN1H31K1FxYW7Bvn+vcuO3f4PrrR24xtRLjgHNebhrtinLrizL33TIx8efs2K95TqrIUY78K3Y8hUgXQiPCIc3wbAvfEyC7dT7ME2AXOmvFF07DiPQ80DYvjjkFo5Y6qPe6c/dlxyA4byt+Kwl5dWLCnve+FzSjh0P7zlCrnY2ST3snDcVZTQu8k427gVxF+yhwYdNmv6IxR+/PZJUE5mc0zIy9EZ+qpUZh5lZDDfw9J5SDpQQEIAAAAAElFTkSuQmCC' - -ledcolon = b'iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAABdklEQVRoge2YQU7DMBBFn9MEVVBYcADEmiVH4BScD3EL7gIcAYEEFSQdFrZRCJGYeBa1qnlSZSuVJz8/k/EkARAqo9m3gDlclBYXpcVFaXFRWlyUFhelpUpRrWVxAFaTYwIMlqApbnX9VJFT+UpOgRugA3ZE195C4EHE7JYs/TVpvAJ5BxGQPo1PTSObEASQUBA7xS/nE/hI8+yMEJ20YBK1G81zwnfWoKXr85MxAF9p3o/+24tT45N2k/EYOLIoovDpy069AvfAOdGxDngR+cmzUg6nTv0XoJ85toQqnapyQ3ZRWlyUFhelpUpR5oo+1xFYq3GVFd3Uo18Cd8CGuN+tgcem4VaErUjxFZtErYFr4ITY8K2AM2ILsy0JnDD36Pnk49a4mh49B2qtQUvX5zzZ8TdnVqVBR5jWD/x2C6Ko6av8UkwloQUuiImd32J64Bnb94TDqVNj5u7/9JYupUqnqtyQXZQWF6XFRWlxUVpclBYXpeUbS+1qOYf8HRgAAAAASUVORK5CYII=' - -ledblank = b'iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAADpEaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzE0NSA3OS4xNjIzMTksIDIwMTgvMDIvMTUtMjA6Mjk6NDMgICAgICAgICI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgICAgICAgICB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgICAgICAgICB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8eG1wOkNyZWF0b3JUb29sPkFkb2JlIFBob3Rvc2hvcCBFbGVtZW50cyAxNy4wIChXaW5kb3dzKTwveG1wOkNyZWF0b3JUb29sPgogICAgICAgICA8eG1wOkNyZWF0ZURhdGU+MjAxOC0xMC0yMFQxNjowOToyNS0wNDowMDwveG1wOkNyZWF0ZURhdGU+CiAgICAgICAgIDx4bXA6TW9kaWZ5RGF0ZT4yMDE4LTEwLTIwVDE2OjM2OjMyLTA0OjAwPC94bXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhtcDpNZXRhZGF0YURhdGU+MjAxOC0xMC0yMFQxNjozNjozMi0wNDowMDwveG1wOk1ldGFkYXRhRGF0ZT4KICAgICAgICAgPGRjOmZvcm1hdD5pbWFnZS9wbmc8L2RjOmZvcm1hdD4KICAgICAgICAgPHBob3Rvc2hvcDpDb2xvck1vZGU+MzwvcGhvdG9zaG9wOkNvbG9yTW9kZT4KICAgICAgICAgPHBob3Rvc2hvcDpJQ0NQcm9maWxlPnNSR0IgSUVDNjE5NjYtMi4xPC9waG90b3Nob3A6SUNDUHJvZmlsZT4KICAgICAgICAgPHhtcE1NOkluc3RhbmNlSUQ+eG1wLmlpZDoxYTc5NDQ5ZC05ZmM0LWZiNGItOTNjYy0xNTcyMjU1MGU5OTk8L3htcE1NOkluc3RhbmNlSUQ+CiAgICAgICAgIDx4bXBNTTpEb2N1bWVudElEPmFkb2JlOmRvY2lkOnBob3Rvc2hvcDpkMGIzZGFmNS1kNGE3LTExZTgtOGI3ZC1jYmQxMWFlODBkMGE8L3htcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ+eG1wLmRpZDowZDlkYjE1OS1lYThmLWQxNDEtYWE4MS04YTY4NzFkNTI4YTc8L3htcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOkhpc3Rvcnk+CiAgICAgICAgICAgIDxyZGY6U2VxPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5jcmVhdGVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6MGQ5ZGIxNTktZWE4Zi1kMTQxLWFhODEtOGE2ODcxZDUyOGE3PC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE4LTEwLTIwVDE2OjA5OjI1LTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgRWxlbWVudHMgMTcuMCAoV2luZG93cyk8L3N0RXZ0OnNvZnR3YXJlQWdlbnQ+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOjFhNzk0NDlkLTlmYzQtZmI0Yi05M2NjLTE1NzIyNTUwZTk5OTwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAxOC0xMC0yMFQxNjozNjozMi0wNDowMDwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIEVsZW1lbnRzIDE3LjAgKFdpbmRvd3MpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICAgICA8c3RFdnQ6Y2hhbmdlZD4vPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgPC9yZGY6U2VxPgogICAgICAgICA8L3htcE1NOkhpc3Rvcnk+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjMxNDAwMDAvMTAwMDA8L3RpZmY6WFJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOllSZXNvbHV0aW9uPjMxNDAwMDAvMTAwMDA8L3RpZmY6WVJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDxleGlmOkNvbG9yU3BhY2U+MTwvZXhpZjpDb2xvclNwYWNlPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+Mzc8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFlEaW1lbnNpb24+NjA8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAKPD94cGFja2V0IGVuZD0idyI/PvnJsBAAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAEZJREFUeNrszkEBACAMAKHT/p1nDPeABJxqWua2kJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSU1G8PAAD//wMAGdkBdyV2S1QAAAAASUVORK5CYII=' - -w1 = b'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' - -w2 = b'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' - -w3 = b'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' - -w4 = b'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' - -w5 = b'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' -orangeround = b'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' - -weather_icon_dict = {'clear sky': w1, 'rain': w3, 'light rain':w3, 'shower rain':w3, 'thunderstorm':w3, 'snow': w3, 'sleet': w3, 'wind': w3, 'mist': w3, - 'cloudy': w4, 'scattered clouds': w5, 'few clouds': w5,'broken clouds': w5, 'overcast clouds': w5, 'partly-cloudy-night': w5} - -led_digits = [led0, led1, led2, led3, led4, led5, led6, led7, led8, led9] - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/DemoPrograms/Demo_Progress_Meter_Simulated.py b/DemoPrograms/Demo_Progress_Meter_Simulated.py index 9cf76303a..00fc5dfde 100644 --- a/DemoPrograms/Demo_Progress_Meter_Simulated.py +++ b/DemoPrograms/Demo_Progress_Meter_Simulated.py @@ -6,18 +6,14 @@ This is a clever use of a Text Element to create the same look and feel of a progress bar in PySimpleGUI using only a Text Element. - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ import PySimpleGUI as sg sg.theme('DarkBlue') -layout = [[sg.Text('', size=(50, 1), relief='sunken', +layout = [[sg.Text('', size=(50, 1), relief='sunken', font=('Courier', 11), text_color='yellow', background_color='black',key='-TEXT-', metadata=0)]] window = sg.Window('Title', layout, finalize=True) @@ -31,6 +27,6 @@ if event == sg.WINDOW_CLOSED: break text.metadata = (text.metadata + 1) % 51 - text.update(sg.SYMBOL_SQUARE * text.metadata) + text.update('█' * text.metadata) window.close() \ No newline at end of file diff --git a/DemoPrograms/Demo_Progress_Meters.py b/DemoPrograms/Demo_Progress_Meters.py index 58404b580..2a9d6c6ea 100644 --- a/DemoPrograms/Demo_Progress_Meters.py +++ b/DemoPrograms/Demo_Progress_Meters.py @@ -15,12 +15,6 @@ If the software determined that a meter should be cancelled early, calling OneLineProgresMeterCancel(key) will cancel the meter with the matching key - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ diff --git a/DemoPrograms/Demo_PyCharm_Diff_2_Files.py b/DemoPrograms/Demo_PyCharm_Diff_2_Files.py index 286f5a366..7bcd66a95 100644 --- a/DemoPrograms/Demo_PyCharm_Diff_2_Files.py +++ b/DemoPrograms/Demo_PyCharm_Diff_2_Files.py @@ -4,11 +4,7 @@ Compare 2 .py files using PyCharm's compare utility If you use PyCharm, then you've likely used their awesome - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ @@ -17,16 +13,16 @@ def main(): layout = [[sg.T('Choose 2 files to compare using PyCharm\'s compare utility', font='_ 18')], [sg.Text('Filename:'), sg.Combo(values=sorted(sg.user_settings_get_entry('-filenames1-', [])), default_value=sg.user_settings_get_entry('-last filename chosen1-', None), - size=(90,30), auto_size_text=False, k='-COMBO1-'), sg.FileBrowse(), sg.B('Clear History', k='-CLEAR1-')], + size=(90,1), auto_size_text=False, k='-COMBO1-'), sg.FileBrowse(), sg.B('Clear History', k='-CLEAR1-')], [sg.Text('Filename:'),sg.Combo(values=sorted(sg.user_settings_get_entry('-filenames2-', [])), default_value=sg.user_settings_get_entry('-last filename chosen2-', None), - size=(90,30), auto_size_text=False, k='-COMBO2-'), sg.FileBrowse(), sg.B('Clear History', k='-CLEAR2-')], + size=(90,1), auto_size_text=False, k='-COMBO2-'), sg.FileBrowse(), sg.B('Clear History', k='-CLEAR2-')], [sg.Button('Compare'), sg.Button('Exit'), sg.T('PySimpleGUI ver ' + sg.version.split(' ')[0] + ' tkinter ver ' + sg.tclversion_detailed + 'Python ver ' + sys.version, font='Default 8', pad=(0,0))], [sg.Text('Note - You must setup the PyCharm information using PySimpleGUI global settings')], [sg.Button('Global Settings')] ] - window = sg.Window('Compare 2 files using PyCharm', layout, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT) + window = sg.Window('Compare 2 files using PyCharm', layout) while True: event, values = window.read() print(event, values) @@ -49,10 +45,6 @@ def main(): window['-COMBO2-'].update(values=[], value='') elif event == 'Global Settings': sg.main_global_pysimplegui_settings() - if event == 'Edit Me': - sg.execute_editor(__file__) - elif event == 'Version': - sg.popup_scrolled(__file__, sg.get_versions(), non_blocking=True, keep_on_top=True) window.close() if __name__ == '__main__': diff --git a/DemoPrograms/Demo_PyCharm_Launcher.py b/DemoPrograms/Demo_PyCharm_Launcher.py index 1de927bb2..e7e6861da 100644 --- a/DemoPrograms/Demo_PyCharm_Launcher.py +++ b/DemoPrograms/Demo_PyCharm_Launcher.py @@ -5,11 +5,7 @@ Demo mini-PyCharm "favorites" launcher Open a python file for editing using a small window that sits in the corner of your desktop - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ # ---------------------------- Items for you to edit specific to your setup -------------------- diff --git a/DemoPrograms/Demo_PyCharm_Self_Edit.py b/DemoPrograms/Demo_PyCharm_Self_Edit.py index 40b3846e7..af8601b68 100644 --- a/DemoPrograms/Demo_PyCharm_Self_Edit.py +++ b/DemoPrograms/Demo_PyCharm_Self_Edit.py @@ -9,11 +9,7 @@ Note that this is a Windows version. You'll need a slightly different path for Linux. - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ # Change this variable to match the location of your PyCharm folder. It should already have the batch file. diff --git a/DemoPrograms/Demo_PyGame_Integration.py b/DemoPrograms/Demo_PyGame_Integration.py index 6ff4d94b8..7b689940b 100644 --- a/DemoPrograms/Demo_PyGame_Integration.py +++ b/DemoPrograms/Demo_PyGame_Integration.py @@ -8,12 +8,6 @@ To make it work on Linux, set SDL_VIDEODRIVER like specified in http://www.pygame.org/docs/ref/display.html, in the pygame.display.init() section. - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ # --------------------- PySimpleGUI window layout and creation -------------------- layout = [[sg.Text('Test of PySimpleGUI with PyGame')], diff --git a/DemoPrograms/Demo_PyGame_Snake_Game.py b/DemoPrograms/Demo_PyGame_Snake_Game.py index a2dde4ba5..80b723abb 100644 --- a/DemoPrograms/Demo_PyGame_Snake_Game.py +++ b/DemoPrograms/Demo_PyGame_Snake_Game.py @@ -9,12 +9,6 @@ The purpose of the demo is to show one way of adding a PyGame window into your PySimpleGUI window Note, you must click on the game area in order for PyGame to get keyboard strokes, etc. Tried using set_focus to switch to the PyGame canvas but still needed to click on game area - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ # --- Globals --- diff --git a/DemoPrograms/Demo_Pyplot_Bar_Chart.py b/DemoPrograms/Demo_Pyplot_Bar_Chart.py index ad0fb9b9b..e647ff8f9 100644 --- a/DemoPrograms/Demo_Pyplot_Bar_Chart.py +++ b/DemoPrograms/Demo_Pyplot_Bar_Chart.py @@ -16,12 +16,6 @@ The remainder of the program will convert your plot and display it in the GUI. If you want to change the GUI, make changes to the GUI portion marked below. -Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - -Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - -You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. - """ # ------------------------------- PASTE YOUR MATPLOTLIB CODE HERE ------------------------------- diff --git a/DemoPrograms/Demo_Pyplot_Bar_Chart2.py b/DemoPrograms/Demo_Pyplot_Bar_Chart2.py index 0e19967e0..09e9cfb90 100644 --- a/DemoPrograms/Demo_Pyplot_Bar_Chart2.py +++ b/DemoPrograms/Demo_Pyplot_Bar_Chart2.py @@ -16,11 +16,6 @@ The remainder of the program will convert your plot and display it in the GUI. If you want to change the GUI, make changes to the GUI portion marked below. -Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - -Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - -You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ # ------------------------------- PASTE YOUR MATPLOTLIB CODE HERE ------------------------------- diff --git a/DemoPrograms/Demo_Radio_Buttons_Simulated.py b/DemoPrograms/Demo_Radio_Buttons_Simulated.py index c7907504b..660332954 100644 --- a/DemoPrograms/Demo_Radio_Buttons_Simulated.py +++ b/DemoPrograms/Demo_Radio_Buttons_Simulated.py @@ -7,11 +7,7 @@ 1. Uses Buttons and changes the color of the button to show which is selected 2. Uses an Image Element and a Text Element together - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020, 2021 PySimpleGUI """ def using_buttons(): diff --git a/DemoPrograms/Demo_Reddit_Search.py b/DemoPrograms/Demo_Reddit_Search.py index f7987731e..4f48080f3 100644 --- a/DemoPrograms/Demo_Reddit_Search.py +++ b/DemoPrograms/Demo_Reddit_Search.py @@ -14,11 +14,7 @@ NOTE - you must register with Reddit as a developer. https://www.reddit.com/prefs/apps/ You can set these credentials using the "Settings Window". - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI """ settings = sg.UserSettings() diff --git a/DemoPrograms/Demo_SDK_Help_Func_Parms.py b/DemoPrograms/Demo_SDK_Help_Func_Parms.py deleted file mode 100644 index 4042b8d25..000000000 --- a/DemoPrograms/Demo_SDK_Help_Func_Parms.py +++ /dev/null @@ -1,112 +0,0 @@ -import PySimpleGUI as sg -import inspect -import sys - -""" - Demo SDK Help - Function Parms - - This is the tool that was used in the Udemy course to display the function parameters - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - -def main(): - """ - Display a window that will display the docstrings for each PySimpleGUI Element and the Window object - - """ - - sg.set_options(font='courier 12') - - functions = [m for m in inspect.getmembers(sys.modules['PySimpleGUI'], inspect.isfunction)] - functions_names_lower = [f for f in functions if f[0][0].islower()] - functions_names_upper = [f for f in functions if f[0][0].isupper()] - # functions_names = sorted(functions_names_lower) + sorted(functions_names_upper) - # func_names_str = [f[0] for f in functions if f[0][0].islower()] - func_names_str = [f[0] for f in functions] - - func_parm_dict = {} - - # for func_str, func in functions_names_lower: - for func_str, func in functions: - # Build info about init method - args = inspect.signature(func) - params = args.parameters - func_parm_list = [] - for a in params.values(): - func_def = str(a).split('=') - if len(func_def) == 1: - name, default = func_def[0], '*Required*' - if name[0] == '*': - default = '*Optional*' - elif len(func_def) == 2: - name, default = func_def[0], func_def[1] - elif len(func_def) == 0: - name, default = '', '' - else: - name, default = func_def[0], '*Object*' - func_parm_list.append((name, default)) - func_parm_dict[func_str] = func_parm_list - - sg.theme('black') - sg.theme_background_color('#131314') - sg.theme_text_element_background_color('#131314') - sg.theme_input_background_color('#131314') - ml = sg.Multiline(size=(35, 20), key='-ML-', write_only=True, reroute_stdout=False, expand_y=True, expand_x=True) - - layout = [ - [sg.Titlebar('Func Parm Viewer', background_color='#131314', text_color='white')], - # [sg.Combo([e for e in sorted(func_names_str)],background_color='#131314', size=(25,30), enable_events=True, key='-COMBO-'), sg.T(' '*6, grab=True)], - [sg.Combo([e for e in sorted([f[0] for f in functions if f[0][0].islower()])],background_color='#131314', size=(25,30), enable_events=True, readonly=True, expand_x=True, key='-COMBO-')], - sg.vtop([ml], expand_x=True, expand_y=True)] + [[sg.Sizegrip()]] - - window = sg.Window('Func Parms', layout, use_default_focus=False, keep_on_top=True, no_titlebar=True, margins=(0,0), right_click_menu=[[],['Edit Me', 'Upper Case Too', 'Lower Case Only', 'Exit']], resizable=True) - while True: # Event Loop - event, values = window.read() - if event in (sg.WIN_CLOSED, 'Exit'): - break - if event == 'Edit Me': - sg.execute_editor(__file__) - continue - elif event.startswith('Upper'): - window['-COMBO-'].update(values=[f[0] for f in functions if not f[0][0].startswith('_')]) - elif event.startswith('Lower'): - window['-COMBO-'].update(values=[f[0] for f in functions if f[0][0].islower()]) - else: - # ml.print(event, values) - if event == '-COMBO-': - func_chosen = values[event] - else: - func_chosen = None - window['-ML-'].update('') - - ml.print(f'= {func_chosen} =', background_color='#FFFF00', text_color='black') - func_parms = func_parm_dict[func_chosen] - # print(func_parms) - for parm, default in func_parms: - ml.print(f'{parm:18}', text_color='green yellow', end=' = ') - if default != inspect._empty: - if isinstance(default, str): - if default in ('None', '(None, None)', '(None,None)'): - color = 'pink' - elif default in ('False', 'True'): - color = '#00FF7F' - else: - color = None - ml.print(f'{default}', end='\n', text_color=color) - else: - ml.print(default, end='\n') - else: - ml.print(f'{default}', end='\n') - ml.set_vscroll_position(0) - - window.close() - - - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/DemoPrograms/Demo_SDK_Help_Init_Update_Parms.py b/DemoPrograms/Demo_SDK_Help_Init_Update_Parms.py deleted file mode 100644 index a73fc47a6..000000000 --- a/DemoPrograms/Demo_SDK_Help_Init_Update_Parms.py +++ /dev/null @@ -1,97 +0,0 @@ -import PySimpleGUI as sg -import inspect - - -""" - Demo SDK Help - Init and Update Parms - - This is the tool that was used in the Udemy course to display the init and update parameters. - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - -def main(): - """ - Display a window that displays the parms for the init and update methods for each element - - """ - - common_parms = ['key','k','font','pad','p', 'visible','size','s', 'change_submits', 'enable_events','right_click_menu','tooltip','metadata', 'expand_x', 'expand_y'] - element_classes = sg.Element.__subclasses__() - element_names = {element.__name__: element for element in element_classes} - element_names['Window'] = sg.Window - element_names['SystemTray'] = sg.SystemTray - # vars3 = [m for m in inspect.getmembers(sys.modules[__name__])] - element_arg_default_dict = {} - element_arg_default_dict_update = {} - for element in element_classes: - # Build info about init method - args = inspect.getargspec(element.__init__).args[1:] - defaults = inspect.getargspec(element.__init__).defaults - if len(args) != len(defaults): - diff = len(args) - len(defaults) - defaults = ('NO DEFAULT',)*diff + defaults - args_defaults = [] - for i, a in enumerate(args): - args_defaults.append((a, defaults[i])) - element_arg_default_dict[element.__name__] = args_defaults - - # Build info about update method - args = inspect.getargspec(element.update).args[1:] - defaults = inspect.getargspec(element.update).defaults - if args is None or defaults is None: - element_arg_default_dict_update[element.__name__] = (('',''),) - continue - if len(args) != len(defaults): - diff = len(args) - len(defaults) - defaults = ('NO DEFAULT',)*diff + defaults - args_defaults = [] - for i, a in enumerate(args): - args_defaults.append((a, defaults[i])) - element_arg_default_dict_update[element.__name__] = args_defaults if len(args_defaults) else (('',''),) - - sg.theme('black') - sg.theme_background_color('#131314') - sg.theme_text_element_background_color('#131314') - sg.theme_input_background_color('#131314') - ml = sg.Multiline(size=(40, 30), key='-ML-', write_only=True, reroute_stdout=True, expand_y=True, expand_x=True) - layout = [ [sg.Titlebar('Element Init & Update Parm Viewer', background_color='#131314', text_color='white')], - [sg.Combo([e for e in sorted(element_names.keys())],background_color='#131314', size=(25,30), enable_events=True, readonly=True, expand_x=True, key='-COMBO-')], - sg.vtop([ml], expand_y=True, expand_x=True) ] + [[sg.Sizegrip()]] - # layout += [[Button('Exit', size=(15, 1))]] - - window = sg.Window('Init & Update Parms', layout, use_default_focus=False, keep_on_top=True, no_titlebar=True, margins=(0,0),font='Courier 12', right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_EXIT, resizable=True) - # ml = window['-ML-'] # type: sg.MLine - while True: # Event Loop - event, values = window.read() - if event in (sg.WIN_CLOSED, 'Exit'): - break - # ml.print(event, values) - if event == '-COMBO-': - element_chosen = values[event] - else: - element_chosen = None - if element_chosen in element_arg_default_dict: - window['-ML-'].update('') - ml.print('========== Init Parms ==========', background_color='#FFFF00', text_color='black') - for parm, default in element_arg_default_dict[element_chosen]: - ml.print(f'{parm:18}', text_color='hot pink' if parm in common_parms else 'green yellow', end=' = ') - ml.print(default, text_color='hot pink' if parm in common_parms else 'white', end = ',\n') - ml.print('========== Update Parms ==========', background_color='#FFFF00', text_color='black') - # print(element_arg_default_dict_update[element_chosen]) - for parm, default in element_arg_default_dict_update[element_chosen]: - ml.print(f'{parm:18}', text_color='hot pink' if parm in common_parms else 'green yellow', end=' = ') - ml.print(default, text_color='hot pink' if parm in common_parms else 'white', end = ',\n') - elif event == 'Edit Me': - sg.execute_editor(__file__) - - window.close() - - - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/DemoPrograms/Demo_Save_Any_Window_As_Image.py b/DemoPrograms/Demo_Save_Any_Window_As_Image.py index b5af97965..0aac965fc 100644 --- a/DemoPrograms/Demo_Save_Any_Window_As_Image.py +++ b/DemoPrograms/Demo_Save_Any_Window_As_Image.py @@ -1,6 +1,8 @@ import PySimpleGUI as sg import win32gui +import cv2 from PIL import ImageGrab +import numpy as np """ Demo - Save Window screenshot @@ -8,11 +10,7 @@ Saves a window as an image file. Tested saving as PNG and JPG. Input the title of the Window and it will be saved in the format indicated by the filename. - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ # --------------------------------- Function to Save Window as JPG --------------------------------- @@ -43,8 +41,9 @@ def save_win(filename=None, title=None): fceuxHWND = win32gui.FindWindow(None, title) rect = win32gui.GetWindowRect(fceuxHWND) rect_cropped = (rect[0]+C, rect[1], rect[2]-C, rect[3]-C) - grab = ImageGrab.grab(bbox=rect_cropped) - grab.save(filename) + frame = np.array(ImageGrab.grab(bbox=rect_cropped), dtype=np.uint8) + frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) + cv2.imwrite(filename, frame) sg.popup('Wrote image to file:',filename) except Exception as e: sg.popup('Error trying to save screenshot file', e) diff --git a/DemoPrograms/Demo_Save_Window_As_Image.py b/DemoPrograms/Demo_Save_Window_As_Image.py index a2073e0f2..38c31f30d 100644 --- a/DemoPrograms/Demo_Save_Window_As_Image.py +++ b/DemoPrograms/Demo_Save_Window_As_Image.py @@ -11,12 +11,6 @@ us to save an image of the Column which saves the entire window layout Portions of windows can be saved, such as a Graph Element, by specifying the Graph Element instead of the Column - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ def save_element_as_file(element, filename): diff --git a/DemoPrograms/Demo_Save_Windows_As_Images.py b/DemoPrograms/Demo_Save_Windows_As_Images.py index 2bf237a59..40c4c82fc 100644 --- a/DemoPrograms/Demo_Save_Windows_As_Images.py +++ b/DemoPrograms/Demo_Save_Windows_As_Images.py @@ -6,23 +6,10 @@ import win32con import win32gui import win32process +import cv2 from PIL import ImageGrab +import numpy as np -""" - Demo - Save Windows as Images - - Works on WINDOWS only. - Saves a window as an image file. Tested saving as PNG and JPG. - saved in the format indicated by the filename. - The window needs to be on the primary display. - 2022 update was to remove OpenCV requirement. - - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" def convert_string_to_tuple(string): """ @@ -80,6 +67,7 @@ def enumProcWnds(pid=None): titles = sorted(titles, key=lambda x: x[0].lower()) return titles + def save_win(filename=None, title=None, crop=True): """ Saves a window with the title provided as a file using the provided filename. @@ -94,8 +82,9 @@ def save_win(filename=None, title=None, crop=True): fceuxHWND = win32gui.FindWindow(None, title) rect = win32gui.GetWindowRect(fceuxHWND) rect_cropped = (rect[0] + C, rect[1], rect[2] - C, rect[3] - C) - grab = ImageGrab.grab(bbox=rect_cropped) - grab.save(filename) + frame = np.array(ImageGrab.grab(bbox=rect_cropped), dtype=np.uint8) + frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) + cv2.imwrite(filename, frame) sg.cprint('Wrote image to file:') sg.cprint(filename, c='white on purple') except Exception as e: diff --git a/DemoPrograms/Demo_Script_Launcher.py b/DemoPrograms/Demo_Script_Launcher.py index c25ae3f68..662c26532 100644 --- a/DemoPrograms/Demo_Script_Launcher.py +++ b/DemoPrograms/Demo_Script_Launcher.py @@ -4,14 +4,6 @@ import ntpath import subprocess -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - LOCATION_OF_YOUR_SCRIPTS = '' # Execute the command. Will not see the output from the command until it completes. diff --git a/DemoPrograms/Demo_Script_Launcher_ANSI_Color_Output.py b/DemoPrograms/Demo_Script_Launcher_ANSI_Color_Output.py index 8660a1b42..352fddbf1 100644 --- a/DemoPrograms/Demo_Script_Launcher_ANSI_Color_Output.py +++ b/DemoPrograms/Demo_Script_Launcher_ANSI_Color_Output.py @@ -1,18 +1,12 @@ +import subprocess +import sys import PySimpleGUI as sg import re """ Demo Program - Realtime output of a shell command in the window using ANSI color codes Shows how you can run a long-running subprocess and have the output - be displayed in realtime in the window. The output is assumed to have color codes embedded in it. - - The commands you enter will be run as shell commands. The output is then shown with the ANSI strings parsed. - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + be displayed in realtime in the window. The output is assumed to have color codes embedded in it """ @@ -84,38 +78,50 @@ def cut_ansi_string_into_parts(string_with_ansi_codes): for x in range(0, len(tuple_list)): if tuple_list[x][0]: - new_tuple_list += [[tuple_list[x][0], tuple_list[x][1], tuple_list[x][2], tuple_list[x][3]]] + new_tuple_list += [(tuple_list[x][0], tuple_list[x][1], tuple_list[x][2], tuple_list[x][3])] return new_tuple_list def main(): layout = [ - [sg.Multiline(size=(110, 30), font='courier 10', background_color='black', text_color='white', key='-MLINE-', expand_x=True, expand_y=True)], + [sg.Multiline(size=(110, 30), font='courier 10', background_color='black', text_color='white', key='-MLINE-')], [sg.T('Promt> '), sg.Input(key='-IN-', focus=True, do_not_clear=False)], - [sg.Button('Run', bind_return_key=True), sg.Button('Exit'), sg.Sizegrip()]] + [sg.Button('Run', bind_return_key=True), sg.Button('Exit')]] - window = sg.Window('Realtime Shell Command Output', layout, resizable=True) + window = sg.Window('Realtime Shell Command Output', layout) while True: # Event Loop event, values = window.read() + # print(event, values) if event in (sg.WIN_CLOSED, 'Exit'): break elif event == 'Run': - args = values['-IN-'].split(' ') - p = sg.execute_command_subprocess(args[0], *args[1:], wait=False, pipe_output=True, merge_stderr_with_stdout=True ) - lines = sg.execute_get_results(p) - - for line in lines: - if line is None: - continue - ansi_list = cut_ansi_string_into_parts(line) - for ansi_item in ansi_list: - if ansi_item[1] == 'Reset': - ansi_item[1] = None - window['-MLINE-'].update(ansi_item[0] , text_color_for_value=ansi_item[1], background_color_for_value=ansi_item[2], append=True, autoscroll=True) - window.refresh() - + runCommand(cmd=values['-IN-'], window=window) window.close() + +def runCommand(cmd, timeout=None, window=None): + """ run shell command + @param cmd: command to execute + @param timeout: timeout for command execution + @param window: the PySimpleGUI window that the output is going to (needed to do refresh on) + @return: (return code from command, command output) + """ + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + for line in p.stdout: + line = line.decode(errors='replace' if (sys.version_info) < (3, 5) else 'backslashreplace').rstrip() + ansi_list = cut_ansi_string_into_parts(line) + for ansi_item in ansi_list: + if ansi_item[1] == 'Reset': + ansi_item[1] = None + window['-MLINE-'].update(ansi_item[0] + '\n', text_color_for_value=ansi_item[1], background_color_for_value=ansi_item[2], append=True, + autoscroll=True) + window.refresh() + + retval = p.wait(timeout) + return retval + + +sg.theme('Dark Blue 3') main() diff --git a/DemoPrograms/Demo_Script_Launcher_Realtime_Output.py b/DemoPrograms/Demo_Script_Launcher_Realtime_Output.py index 3c686bbeb..cd6d547c8 100644 --- a/DemoPrograms/Demo_Script_Launcher_Realtime_Output.py +++ b/DemoPrograms/Demo_Script_Launcher_Realtime_Output.py @@ -1,36 +1,51 @@ +import subprocess +import sys import PySimpleGUI as sg """ Demo Program - Realtime output of a shell command in the window Shows how you can run a long-running subprocess and have the output be displayed in realtime in the window. - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ +sg.theme('Dark Blue 3') def main(): - layout = [ - [sg.Multiline(size=(110, 30), echo_stdout_stderr=True, reroute_stdout=True, autoscroll=True, background_color='black', text_color='white', key='-MLINE-')], - [sg.T('Promt> '), sg.Input(key='-IN-', focus=True, do_not_clear=False)], - [sg.Button('Run', bind_return_key=True), sg.Button('Exit')]] - - window = sg.Window('Realtime Shell Command Output', layout) - while True: # Event Loop - event, values = window.read() - if event in (sg.WIN_CLOSED, 'Exit'): - break - elif event == 'Run': - cmd_list = values['-IN-'].split(' ') - sp = sg.execute_command_subprocess(cmd_list[0], *cmd_list[1:], pipe_output=True, wait=False) - results = sg.execute_get_results(sp, timeout=1) - print(results[0]) - - window.close() + layout = [ + [sg.Output(size=(110,30), background_color='black', text_color='white')], + [sg.T('Promt> '), sg.Input(key='-IN-', do_not_clear=False)], + [sg.Button('Run', bind_return_key=True), sg.Button('Exit')] ] + + window = sg.Window('Realtime Shell Command Output', layout) + + while True: # Event Loop + event, values = window.read() + # print(event, values) + if event in (sg.WIN_CLOSED, 'Exit'): + break + elif event == 'Run': + runCommand(cmd=values['-IN-'], window=window) + window.close() + + +def runCommand(cmd, timeout=None, window=None): + nop = None + """ run shell command + @param cmd: command to execute + @param timeout: timeout for command execution + @param window: the PySimpleGUI window that the output is going to (needed to do refresh on) + @return: (return code from command, command output) + """ + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + output = '' + for line in p.stdout: + line = line.decode(errors='replace' if (sys.version_info) < (3, 5) else 'backslashreplace').rstrip() + output += line + print(line) + window.refresh() if window else nop # yes, a 1-line if, so shoot me + + retval = p.wait(timeout) + return (retval, output) main() diff --git a/DemoPrograms/Demo_Script_Parameters.py b/DemoPrograms/Demo_Script_Parameters.py index effdbd403..1b42f2839 100644 --- a/DemoPrograms/Demo_Script_Parameters.py +++ b/DemoPrograms/Demo_Script_Parameters.py @@ -11,12 +11,6 @@ The 1-line-GUI shows a form that allows the user to browse to find the filename. The GUI stores the result in the variable fname, just like the command line parsing did. - -Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - -Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - -You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. ''' fname = '' diff --git a/DemoPrograms/Demo_Separator_Elements.py b/DemoPrograms/Demo_Separator_Elements.py index c332fab03..d12102f3a 100644 --- a/DemoPrograms/Demo_Separator_Elements.py +++ b/DemoPrograms/Demo_Separator_Elements.py @@ -11,11 +11,7 @@ are located on. If that row is constrained within a container, then it will spand the widget of the container. - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ diff --git a/DemoPrograms/Demo_Settings_Save_Load.py b/DemoPrograms/Demo_Settings_Save_Load.py index 2d3b1a9a7..c67fa72b8 100644 --- a/DemoPrograms/Demo_Settings_Save_Load.py +++ b/DemoPrograms/Demo_Settings_Save_Load.py @@ -10,11 +10,7 @@ Note that it attempts to use a lookup dictionary to convert from the settings file to keys used in your settings window. Some element's "update" methods may not work correctly for some elements. - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.com Licensed under LGPL-3 """ diff --git a/DemoPrograms/Demo_Simple_Material_Feel.py b/DemoPrograms/Demo_Simple_Material_Feel.py index 6454f0330..ea9d59c2c 100644 --- a/DemoPrograms/Demo_Simple_Material_Feel.py +++ b/DemoPrograms/Demo_Simple_Material_Feel.py @@ -8,11 +8,7 @@ * The 2 toggle buttons * The large spinning animation - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ def make_window(light_mode): diff --git a/DemoPrograms/Demo_Smart_Desktop_Icon.pyw b/DemoPrograms/Demo_Smart_Desktop_Icon.pyw deleted file mode 100644 index 380b6890f..000000000 --- a/DemoPrograms/Demo_Smart_Desktop_Icon.pyw +++ /dev/null @@ -1,59 +0,0 @@ -""" - -Creates what appears to be an icon on your desktop, but is in reality a PySimpleGUI program. - -Copyright 2024 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - -Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - -You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - - - -import PySimpleGUI as sg -import random - -def main(): - - PROGRAM_TO_LAUNCH_WHEN_DOUBLE_CLICKED = 'explorer' # This will be run when icon is double-clicked. Change to any program you want. - - # Set to your own custom icon. This is dislayed on the desktop - # For fun, the icon is changed every 5 minutes to a random PSG Emoji - icon=sg.EMOJI_BASE64_COOL - - #------- GUI definition & setup --------# - - sg.theme('black') - - - layout = [[sg.Image(source=icon, key='-IMAGE-', p=0, enable_events=True)]] - - window = sg.Window('Desktop Icon Demo', layout, element_justification='center', finalize=True, resizable=True, no_titlebar=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT, margins=(0,0), grab_anywhere=True, auto_save_location=True) - - window['-IMAGE-'].bind('', '+DOUBLE_CLICK+') - - window.timer_start(5*60*1000) # every 5 minutes, change the icon (totally optional... just for fun) - - #------------ The Event Loop ------------# - while True: - event, values = window.read() - if event == sg.WIN_CLOSED or event == 'Exit': - break - # Add your double-click action here... such as launching another program - if event == '-IMAGE-+DOUBLE_CLICK+': - sg.popup_quick_message('Double Clicked', location=window.current_location(), font='_ 20', background_color='red', text_color='white') - # Example of launch when the icon is double-clicked. Of course you can do some other action than launching a program - sg.execute_command_subprocess(PROGRAM_TO_LAUNCH_WHEN_DOUBLE_CLICKED, wait=False) - elif event == sg.TIMER_KEY: # Change the icon shown every TIMER event - window['-IMAGE-'].update(random.choice(sg.EMOJI_BASE64_HAPPY_LIST)) - elif event == 'Version': - sg.popup_scrolled(sg.get_versions(), f'This Program: {__file__}' ,keep_on_top=True, non_blocking=True, location=window.current_location()) - elif event == 'Edit Me': - sg.execute_editor(__file__) - - window.close() - -if __name__ == '__main__': - - main() \ No newline at end of file diff --git a/DemoPrograms/Demo_Sort_Visualizer.py b/DemoPrograms/Demo_Sort_Visualizer.py index c6bbd914c..ff1f69557 100644 --- a/DemoPrograms/Demo_Sort_Visualizer.py +++ b/DemoPrograms/Demo_Sort_Visualizer.py @@ -1,13 +1,5 @@ import PySimpleGUI as sg import random - -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" # ------- Sort visualizer. Displays bar chart representing list items ------- BAR_SPACING, BAR_WIDTH, EDGE_OFFSET = 11, 10, 3 DATA_SIZE = GRAPH_SIZE = (700, 500) # width, height of the graph portion diff --git a/DemoPrograms/Demo_Spin_Element_Wraps_Around.py b/DemoPrograms/Demo_Spin_Element_Wraps_Around.py deleted file mode 100644 index ff242a9dc..000000000 --- a/DemoPrograms/Demo_Spin_Element_Wraps_Around.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python -import PySimpleGUI as sg - -""" - - Demo Spin Element - Wraps around - - This is a nice touch for the Spin Element that is yet another jason990420 creation - - This Spin element will wrap around going in either direction. When getting to the end then - it will go back to the beginning. - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - - -lower, upper = 0, 10 -data = [i for i in range(lower - 1, upper + 2)] - -layout = [[sg.Text('This Spin element wraps around in both directions')], - [sg.Spin(data, initial_value=lower, readonly=True, size=3, enable_events=True, key='-SPIN-')]] - -window = sg.Window('Wrapping Spin Element', layout, font='_ 18', keep_on_top=True) - -while True: - - event, values = window.read() - - if event == sg.WIN_CLOSED: - break - - # code to make the Spin do the wrap around. Do this prior to using the Spin's value in your code - if event == '-SPIN-': - value = values['-SPIN-'] - if value == lower - 1: - window['-SPIN-'].update(value=upper) - values['-SPIN-'] = upper # Change the values dictionary too so it'll be correct if used - elif value == upper + 1: - window['-SPIN-'].update(value=lower) - values['-SPIN-'] = lower # Change the values dictionary too so it'll be correct if used - - sg.Print('Spin Value:', values['-SPIN-'], relative_location=(-400, 0)) - -window.close() \ No newline at end of file diff --git a/DemoPrograms/Demo_Spinner_Compound_Element.py b/DemoPrograms/Demo_Spinner_Compound_Element.py index 38c35ae9c..1669aa324 100644 --- a/DemoPrograms/Demo_Spinner_Compound_Element.py +++ b/DemoPrograms/Demo_Spinner_Compound_Element.py @@ -3,12 +3,6 @@ """ Demo of how to combine elements into your own custom element - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ sg.set_options(element_padding=(0, 0)) diff --git a/DemoPrograms/Demo_Status_Bar.py b/DemoPrograms/Demo_Status_Bar.py index 5d061a5d3..bdf496875 100644 --- a/DemoPrograms/Demo_Status_Bar.py +++ b/DemoPrograms/Demo_Status_Bar.py @@ -9,11 +9,7 @@ It's possible to also "simulate" a statusbar (i.e. use a text element or something else) by also configuring that element with the correct expand setting (X direction = True, expand row=True) - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ def main(): diff --git a/DemoPrograms/Demo_Stdout.py b/DemoPrograms/Demo_Stdout.py index 6160bcefd..811657dd5 100644 --- a/DemoPrograms/Demo_Stdout.py +++ b/DemoPrograms/Demo_Stdout.py @@ -8,12 +8,6 @@ Use the Output Element in your window layout to reroute stdout You will see the output of the print in the Output Element in the center of the window - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. - """ diff --git a/DemoPrograms/Demo_Sudoku.py b/DemoPrograms/Demo_Sudoku.py index 82e13c3fb..7e6ba67b2 100644 --- a/DemoPrograms/Demo_Sudoku.py +++ b/DemoPrograms/Demo_Sudoku.py @@ -12,11 +12,7 @@ Code to generate a playable puzzle was supplied from: https://github.com/MorvanZhou/sudoku - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.com """ diff --git a/DemoPrograms/Demo_Sudoku_1_Line.py b/DemoPrograms/Demo_Sudoku_1_Line.py index b2760108c..a66bd4f35 100644 --- a/DemoPrograms/Demo_Sudoku_1_Line.py +++ b/DemoPrograms/Demo_Sudoku_1_Line.py @@ -7,11 +7,7 @@ utilizing the power of Python. The power isn't a PySimpleGUI trick. The power is Python List Comprehensions and using them in your layout. - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ sg.Window('Sudoku', [[sg.Frame('', [[sg.Input(justification='r', size=(3,1)) diff --git a/DemoPrograms/Demo_Super_Simple_Form.py b/DemoPrograms/Demo_Super_Simple_Form.py index 661b7f20c..d6c1ec858 100644 --- a/DemoPrograms/Demo_Super_Simple_Form.py +++ b/DemoPrograms/Demo_Super_Simple_Form.py @@ -3,12 +3,6 @@ """ Simple Form (a one-shot data entry window) Use this design pattern to show a form one time to a user that is "submitted" - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ layout = [[sg.Text('Please enter your Name, Address, Phone')], diff --git a/DemoPrograms/Demo_System_Tray_GUI_Window_Design_Pattern.py b/DemoPrograms/Demo_System_Tray_GUI_Window_Design_Pattern.py index 95f3495c8..7fcefa1af 100644 --- a/DemoPrograms/Demo_System_Tray_GUI_Window_Design_Pattern.py +++ b/DemoPrograms/Demo_System_Tray_GUI_Window_Design_Pattern.py @@ -23,11 +23,7 @@ To exit the entire program, you will need to do this from the System tray by choosing "Exit" - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ icon = sg.DEFAULT_BASE64_ICON diff --git a/DemoPrograms/Demo_System_Tray_Icon.py b/DemoPrograms/Demo_System_Tray_Icon.py index 6deb01141..c01723e62 100644 --- a/DemoPrograms/Demo_System_Tray_Icon.py +++ b/DemoPrograms/Demo_System_Tray_Icon.py @@ -1,42 +1,29 @@ -import PySimpleGUI as sg -# import PySimpleGUIWx as sg +# import PySimpleGUI as sg +import PySimpleGUIWx as sg # import PySimpleGUIQt as sg + """ System Tray Icon - Your very own peronsal status monitor in your system tray + Your very own personsal status monitor in your system tray Super easy to use. 1. Find an icon file or use this default - 2. Create your menu defintion + 2. Create your menu definition 3. Add if statements to take action based on your input Note from the imports that this code works on all PySimpleGUI ports (except Web). For the tkinter port, however, the icon isn't located in the system tray. Instead it's located just above the system tray in the form of what looks like an "icon" on your desktop. It's actually a very small window. - - In June 2021 a new package was added to the PySimpleGUI family - psgtray - With this package, you can get a real system tray icon while using tkinter rather than a desktop-icon that this - demo is demonstrating. The Demo Program - Demo_psgtray_Tray_Icon_Tkinter - shows how to integrate it with PySimpleGUI - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ - - -menu_def = ['UNUSED', ['My', '&Simple::my key', 'Has Sub', ['1','2'], '---', 'Menu', 'E&xit']] +menu_def = ['UNUSED', ['My', 'Simple', '---', 'Menu', 'Exit']] tray = sg.SystemTray(menu=menu_def, data_base64=sg.DEFAULT_BASE64_ICON) while True: event = tray.read() - print(event) if event == 'Exit': break elif event == 'Menu': - tray.show_message('Title', 'Hey, you clicked Menu!') -tray.close() \ No newline at end of file + tray.show_message('Title', 'Hey, you clicked Menu!') \ No newline at end of file diff --git a/DemoPrograms/Demo_System_Tray_Icon_psgtray_No_Window.py b/DemoPrograms/Demo_System_Tray_Icon_psgtray_No_Window.py deleted file mode 100644 index 238e51dcf..000000000 --- a/DemoPrograms/Demo_System_Tray_Icon_psgtray_No_Window.py +++ /dev/null @@ -1,73 +0,0 @@ -import PySimpleGUI as sg -from psgtray import SystemTray - -""" - A System Tray Icon using pystray - No visible window version - - Import the SystemTray object with this line of code: - from psgtray import SystemTray - - Key for the system tray icon is: - tray = SystemTray() - tray.key - - values[key] contains the menu item chosen. - - One trick employed here is to change the window's event to be the event from the System Tray. - - This demo program keeps the Window hidden all the time so that it's a pure "System Tray" application. - Because the PySimpleGUI architecture implemented the tray icon using the psgtray package combined with the - overall window event loop, a Window object is still required. The point of this demo is to show that this - window does not need to ever appear to the user. - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - - -def main(): - menu = ['', ['---', '!Disabled Item', 'Change Icon', ['Happy', 'Sad', 'Plain'], 'Exit']] - tooltip = 'Tooltip' - - layout = [[sg.T('Empty Window', key='-T-')]] - - window = sg.Window('Window Title', layout, finalize=True, enable_close_attempted_event=True, alpha_channel=0) - window.hide() - - tray = SystemTray(menu, single_click_events=False, window=window, tooltip=tooltip, icon=sg.DEFAULT_BASE64_ICON, key='-TRAY-') - tray.show_message('System Tray', 'System Tray Icon Started!') - print(sg.get_versions()) - while True: - event, values = window.read() - # IMPORTANT step. It's not required, but convenient. Set event to value from tray - # if it's a tray event, change the event variable to be whatever the tray sent - if event == tray.key: - event = values[event] # use the System Tray's event as if was from the window - - if event in (sg.WIN_CLOSED, 'Exit'): - break - - tray.show_message(title=event, message=values) - - if event == 'Happy': - tray.change_icon(sg.EMOJI_BASE64_HAPPY_JOY) - elif event == 'Sad': - tray.change_icon(sg.EMOJI_BASE64_FRUSTRATED) - elif event == 'Plain': - tray.change_icon(sg.DEFAULT_BASE64_ICON) - elif event == 'Hide Icon': - tray.hide_icon() - elif event == 'Show Icon': - tray.show_icon() - elif event == 'Change Tooltip': - tray.set_tooltip(values['-IN-']) - - tray.close() # optional but without a close, the icon may "linger" until moused over - window.close() - - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/DemoPrograms/Demo_System_Tray_Reminder.py b/DemoPrograms/Demo_System_Tray_Reminder.py index 020f54277..b93d883eb 100644 --- a/DemoPrograms/Demo_System_Tray_Reminder.py +++ b/DemoPrograms/Demo_System_Tray_Reminder.py @@ -9,12 +9,6 @@ A periodic reminder that uses the System Tray. Will show a popup window every X minutes Should work with 3 of the PySimpleGUI ports - tkinter, WxPython, Qt - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ ONE_HOUR_IN_SECONDS = 60*60 @@ -35,7 +29,7 @@ def resize_base64_image(image64, size): """ image_file = io.BytesIO(base64.b64decode(image64)) img = Image.open(image_file) - img.thumbnail(size, Image.LANCZOS) + img.thumbnail(size, Image.ANTIALIAS) bio = io.BytesIO() img.save(bio, format='PNG') imgbytes = bio.getvalue() diff --git a/DemoPrograms/Demo_TTK_Scrollbars.py b/DemoPrograms/Demo_TTK_Scrollbars.py deleted file mode 100644 index 2936e37e2..000000000 --- a/DemoPrograms/Demo_TTK_Scrollbars.py +++ /dev/null @@ -1,114 +0,0 @@ -import PySimpleGUI as sg - -""" - Demo - TTK Scrollbars - - Beginning in release 4.60.0 (May 2022), all scrollbars in the tkinter port use TTK Scrollbars - - This feature impacts all elements that have scrollbars including: - Multiline - Output - Listbox - Table - Tree - Column - - Not all elements in PySimpleGUI use TTK Widgets. Some of the Widgets are TK Widgets. Regardless of the - underlying widget, if it has a scrollbar that's visible normally (one of the above elements... unlike the Combo), - then it will use a TTK scrollbar. - - There are many options available to you to set for these scrollbars. - - TTK Theme - - While the TTK Theme has been available for you to set, most users have likely not experimented much with this feature. - This may change with these new scrollbars because the TTK Theme will impact how the scrollbars look. Be aware that - the TTK Theme will also impact elements that use TTK Widgets. - - You can see what tkinter widgets are used for all of the elements in the documenation located here: - https://pysimplegui.readthedocs.io/en/latest/#table-of-elements-in-tkinter-port - - Hierarchy of settings - - The scrollbar settings used for an element are picked up from one of these 4 locations. The priority order for - the settings is: - 1. The Element's parms in the layout (you can change individual element's scrollbars) - 2. Window parms - 3. set_options parms - 4. The Global Settings (changable by calling sg.main()) - - The TTK Theme follows a similar hierarchy. The order of priority to determine the theme is: - 1. Window parm - 2. set_options parm - 3. The Global Settings - - More detailed information is available in the documenation about these scrollbars. The docstrings also tell you about - each parm. The parm names are identical for the elements, the Window and the set_options call - sbar_trough_color: - Scrollbar color of the trough - sbar_background_color: - Scrollbar color of the background of the arrow buttons at the ends AND the color of the "thumb" (the thing you grab and slide). Switches to arrow color when mouse is over - sbar_arrow_color: - Scrollbar color of the arrow at the ends of the scrollbar (it looks like a button). Switches to background color when mouse is over - sbar_width: - Scrollbar width in pixels - sbar_arrow_width: - Scrollbar width of the arrow on the scrollbar. It will potentially impact the overall width of the scrollbar - sbar_frame_color: - Scrollbar Color of frame around scrollbar (available only on some ttk themes) - sbar_relief: - Scrollbar relief that will be used for the "thumb" of the scrollbar (the thing you grab that slides). Should be a constant that is defined at starting with "RELIEF_" - RELIEF_RAISED, RELIEF_SUNKEN, RELIEF_FLAT, RELIEF_RIDGE, RELIEF_GROOVE, RELIEF_SOLID - - Note that some parms can impact others. For example, setting the relief to Ridge negates the frame color setting - - This Demo shows 2 different windows to demonstrate the parms in the Window object and set_options. - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - - -# Our first window uses your global defaults with the Listbox element directly overriding the settings - -layout = [[sg.T('Fun with TTK Scrollbars')], - [sg.Multiline('\n'.join([str(x) for x in range(50)]), size=(40,20), expand_x=True, expand_y=True), - sg.Listbox(list(range(40)), s=(10,15), - sbar_background_color='green', sbar_trough_color='red', sbar_relief='ridge', sbar_arrow_color='purple', sbar_frame_color='yellow',)], - [sg.Button('Exit'), sg.Sizegrip()]] - - -window = sg.Window('TTK Scrollbars 1', layout, resizable=True) - -while True: - event, values = window.read() - print(event, values) - if event == sg.WIN_CLOSED or event == 'Exit': - break - -window.close() - -# Our second window uses both set_options and the Window object to change the scrollbars - - -sg.set_options(sbar_width=30, sbar_arrow_width=30) - -layout = [[sg.T('Fun with TTK Scrollbars 2')], - [sg.Multiline('\n'.join([str(x) for x in range(50)]), size=(40,20), expand_x=True, expand_y=True), - sg.Listbox(list(range(40)), s=(10,15), - sbar_background_color='green', sbar_trough_color='red', sbar_arrow_color='purple', sbar_frame_color='yellow',)], - [sg.Button('Exit'), sg.Sizegrip()]] - - -window = sg.Window('TTK Scrollbars 2', layout, sbar_relief=sg.RELIEF_SOLID, resizable=True) - -while True: - event, values = window.read() - print(event, values) - if event == sg.WIN_CLOSED or event == 'Exit': - break - -window.close() - diff --git a/DemoPrograms/Demo_Table_CSV.py b/DemoPrograms/Demo_Table_CSV.py index ea5a3f9f3..47649c918 100644 --- a/DemoPrograms/Demo_Table_CSV.py +++ b/DemoPrograms/Demo_Table_CSV.py @@ -2,14 +2,6 @@ import PySimpleGUI as sg import csv -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - # Show CSV data in Table sg.theme('Dark Red') diff --git a/DemoPrograms/Demo_Table_Checkmark.py b/DemoPrograms/Demo_Table_Checkmark.py deleted file mode 100644 index f2e580d82..000000000 --- a/DemoPrograms/Demo_Table_Checkmark.py +++ /dev/null @@ -1,89 +0,0 @@ -#!/usr/bin/env python -import PySimpleGUI as sg -import random -import string - -""" - Demo Program - Table with checkboxes - - This clever solution was sugged by GitHub user robochopbg. - The beauty of the simplicity is that the checkbox is simply another column in the table. When the checkbox changes - state, then the data in the table is changed and the table is updated in the Table element. - A big thank you again to user robochopbg! - -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣿⣿⠆⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⣿⡿⠁⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⠟⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⣿⣿⡿⠃⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣾⣿⣿⠟⠁⠀⠀⠀⠀⠀⠀ -⠀⢀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⠏⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠺⣿⣷⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠈⠻⣿⣿⣦⣄⠀⠀⠀⠀⠀⠀⣠⣿⣿⣿⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠈⠻⣿⣿⣷⣤⡀⠀⠀⣰⣿⣿⣿⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠙⢿⣿⣿⣿⣦⣼⣿⣿⣿⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⣿⣿⣿⣿⣿⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠻⣿⣿⣿⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢿⡟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - -# Characters used for the checked and unchecked checkboxes. Feel free to change -BLANK_BOX = '☐' -CHECKED_BOX = '☑' - -# ------ Some functions to help generate data for the table ------ -def word(): - return ''.join(random.choice(string.ascii_lowercase) for i in range(10)) -def number(max_val=1000): - return random.randint(0, max_val) - -def make_table(num_rows, num_cols): - data = [[j for j in range(num_cols)] for i in range(num_rows)] - data[0] = [word() for __ in range(num_cols)] - for i in range(1, num_rows): - data[i] = [BLANK_BOX if random.randint(0,2) % 2 else CHECKED_BOX] + [word(), *[number() for i in range(num_cols - 1)]] - return data - -# ------ Make the Table Data ------ -data = make_table(num_rows=15, num_cols=6) -headings = [str(data[0][x])+' ..' for x in range(len(data[0]))] -headings[0] = 'Checkbox' -# The selected rows is stored in a set -selected = {i for i, row in enumerate(data[1:][:]) if row[0] == CHECKED_BOX} - -# ------ Window Layout ------ -layout = [[sg.Table(values=data[1:][:], headings=headings, max_col_width=25, auto_size_columns=False, col_widths=[10, 10, 20, 20 ,30, 5], - display_row_numbers=True, justification='center', num_rows=20, key='-TABLE-', selected_row_colors='red on yellow', - expand_x=False, expand_y=True, vertical_scroll_only=False, enable_click_events=True, select_mode=sg.TABLE_SELECT_MODE_NONE, font='_ 14'), - sg.Sizegrip()]] - -# ------ Create Window ------ -window = sg.Window('Table with Checkbox', layout, resizable=True, finalize=True) - -# Highlight the rows (select) that have checkboxes checked -window['-TABLE-'].update(values=data[1:][:], select_rows=list(selected)) - -# ------ Event Loop ------ -while True: - event, values = window.read() - if event == sg.WIN_CLOSED: - break - elif event[0] == '-TABLE-' and event[2][0] not in (None, -1): # if clicked a data row rather than header or outside table - row = event[2][0]+1 - if data[row][0] == CHECKED_BOX: # Going from Checked to Unchecked - selected.remove(row-1) - data[row][0] = BLANK_BOX - else: # Going from Unchecked to Checked - selected.add(row-1) - data[row ][0] = CHECKED_BOX - window['-TABLE-'].update(values=data[1:][:], select_rows=list(selected)) # Update the table and the selected rows - -window.close() - diff --git a/DemoPrograms/Demo_Table_Element.py b/DemoPrograms/Demo_Table_Element.py index d6e9fdec0..54b8add27 100644 --- a/DemoPrograms/Demo_Table_Element.py +++ b/DemoPrograms/Demo_Table_Element.py @@ -5,14 +5,9 @@ """ Basic use of the Table Element - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ +sg.theme('Dark Red') # ------ Some functions to help generate data for the table ------ def word(): @@ -29,34 +24,27 @@ def make_table(num_rows, num_cols): # ------ Make the Table Data ------ data = make_table(num_rows=15, num_cols=6) -headings = [str(data[0][x])+' ..' for x in range(len(data[0]))] +headings = [str(data[0][x])+' ..' for x in range(len(data[0]))] # ------ Window Layout ------ layout = [[sg.Table(values=data[1:][:], headings=headings, max_col_width=25, + # background_color='light blue', auto_size_columns=True, - # cols_justification=('left','center','right','c', 'l', 'bad'), # Added on GitHub only as of June 2022 display_row_numbers=True, - justification='center', + justification='right', num_rows=20, - alternating_row_color='lightblue', + alternating_row_color='lightyellow', key='-TABLE-', - selected_row_colors='red on yellow', - enable_events=True, - expand_x=False, - expand_y=True, - vertical_scroll_only=False, - enable_click_events=True, # Comment out to not enable header and other clicks + row_height=35, tooltip='This is a table')], [sg.Button('Read'), sg.Button('Double'), sg.Button('Change Colors')], [sg.Text('Read = read which rows are selected')], [sg.Text('Double = double the amount of data in the table')], - [sg.Text('Change Colors = Changes the colors of rows 8 and 9'), sg.Sizegrip()]] + [sg.Text('Change Colors = Changes the colors of rows 8 and 9')]] # ------ Create Window ------ window = sg.Window('The Table Element', layout, - # ttk_theme='clam', # font='Helvetica 25', - resizable=True ) # ------ Event Loop ------ @@ -66,11 +54,10 @@ def make_table(num_rows, num_cols): if event == sg.WIN_CLOSED: break if event == 'Double': - for i in range(1,len(data)): + for i in range(len(data)): data.append(data[i]) - window['-TABLE-'].update(values=data[1:][:]) + window['-TABLE-'].update(values=data) elif event == 'Change Colors': window['-TABLE-'].update(row_colors=((8, 'white', 'red'), (9, 'green'))) window.close() - diff --git a/DemoPrograms/Demo_Table_Element_Header_or_Cell_Clicks.py b/DemoPrograms/Demo_Table_Element_Header_or_Cell_Clicks.py index ef5061c57..01fa231a7 100644 --- a/DemoPrograms/Demo_Table_Element_Header_or_Cell_Clicks.py +++ b/DemoPrograms/Demo_Table_Element_Header_or_Cell_Clicks.py @@ -5,46 +5,36 @@ import operator """ - Table Element Demo With Sorting and Cell Editing - NOTE: release 5.0.6.5 needed in order to use the Cell Editing features. Comment out the parameters that contain cell_edit to remove from demo - + Table Element Demo With Sorting + The data for the table is assumed to have HEADERS across the first row. This is often the case for CSV files or spreadsheets - This demo shows how you can use these click events to sort your table by columns - - Copyright 2022-2024 PySimpleSoft, Inc. and/or its licensors. All rights reserved. + In release 4.48.0 a new enable_click_events parameter was added to the Table Element + This enables you to click on Column Headers and individual cells as well as the standard Row selection - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. + This demo shows how you can use these click events to sort your table by columns - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ sg.theme('Light green 6') - - # ------ Some functions to help generate data for the table ------ def word(): return ''.join(random.choice(string.ascii_lowercase) for i in range(10)) - - def number(max_val=1000): return random.randint(0, max_val) - def make_table(num_rows, num_cols): data = [[j for j in range(num_cols)] for i in range(num_rows)] - data[0] = [word() for _ in range(num_cols)] + data[0] = [word() for __ in range(num_cols)] for i in range(1, num_rows): - data[i] = [i, word(), *[number() for i in range(num_cols - 2)]] + data[i] = [i, word(), *[number() for i in range(num_cols - 1)]] return data - # ------ Make the Table Data ------ data = make_table(num_rows=15, num_cols=6) # headings = [str(data[0][x])+' ..' for x in range(len(data[0]))] -headings = [f'Col {col}' for col in range(1, len(data[0]) + 1)] - +headings = [f'Col {col}' for col in range(len(data[0]))] def sort_table(table, cols): """ sort a table by multiple columns @@ -60,13 +50,11 @@ def sort_table(table, cols): sg.popup_error('Error in sort_table', 'Exception in sort_table', e) return table - # ------ Window Layout ------ -layout = [[sg.Table(values=data[1:][:], headings=headings + ['Extra'], max_col_width=25, +layout = [[sg.Table(values=data[1:][:], headings=headings, max_col_width=25, auto_size_columns=True, - display_row_numbers=False, + display_row_numbers=True, justification='right', - right_click_selects=True, num_rows=20, alternating_row_color='lightyellow', key='-TABLE-', @@ -74,10 +62,7 @@ def sort_table(table, cols): enable_events=True, expand_x=True, expand_y=True, - enable_click_events=True, # Comment out to not enable header and other clicks - enable_cell_editing=True, # Comment out to if your PSG version does not support cell edint - cell_edit_colors='white on blue', # Comment out to if your PSG version does not support cell edint - cell_edit_select_colors='yellow on red', # Comment out to if your PSG version does not support cell edint + enable_click_events=True, # Comment out to not enable header and other clicks tooltip='This is a table')], [sg.Button('Read'), sg.Button('Double'), sg.Button('Change Colors')], [sg.Text('Cell clicked:'), sg.T(k='-CLICKED-')], @@ -86,33 +71,29 @@ def sort_table(table, cols): [sg.Text('Change Colors = Changes the colors of rows 8 and 9'), sg.Sizegrip()]] # ------ Create Window ------ -window = sg.Window('The Table Element', layout, resizable=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT, finalize=True, print_event_values=True) - +window = sg.Window('The Table Element', layout, + ttk_theme='clam', + resizable=True) # ------ Event Loop ------ while True: event, values = window.read() - if event == sg.WIN_CLOSED or event == 'Exit': + print(event, values) + if event == sg.WIN_CLOSED: break - if event == 'Edit Me': - sg.execute_editor(__file__) - elif event == 'Version': - sg.popup_scrolled(__file__, sg.get_versions(), location=window.current_location(), keep_on_top=True, non_blocking=True) - if event == 'Read': - [print(row) for row in window['-TABLE-'].values] if event == 'Double': for i in range(1, len(data)): - data.append(data[i].copy()) + data.append(data[i]) window['-TABLE-'].update(values=data[1:][:]) elif event == 'Change Colors': window['-TABLE-'].update(row_colors=((8, 'white', 'red'), (9, 'green'))) - - # See if was a table clicked or edited event by checking event[0] for table's key - if event[0] == '-TABLE-': # TABLE CELL Event has value in format ('-TABLE=', '+type of event+', (row,col)) - if event[2][0] == -1 and event[2][1] != -1: # Header was clicked and wasn't the "row" column - col_num_clicked = event[2][1] - new_table = sort_table(data[1:][:], (col_num_clicked, 0)) - window['-TABLE-'].update(new_table) - data = [data[0]] + new_table - window['-CLICKED-'].update(f'{event[2][0]},{event[2][1]}') + if isinstance(event, tuple): + # TABLE CLICKED Event has value in format ('-TABLE=', '+CLICKED+', (row,col)) + if event[0] == '-TABLE-': + if event[2][0] == -1 and event[2][1] != -1: # Header was clicked and wasn't the "row" column + col_num_clicked = event[2][1] + new_table = sort_table(data[1:][:],(col_num_clicked, 0)) + window['-TABLE-'].update(new_table) + data = [data[0]] + new_table + window['-CLICKED-'].update(f'{event[2][0]},{event[2][1]}') window.close() diff --git a/DemoPrograms/Demo_Table_Pandas.py b/DemoPrograms/Demo_Table_Pandas.py index 8bcd1e788..32f9f5449 100644 --- a/DemoPrograms/Demo_Table_Pandas.py +++ b/DemoPrograms/Demo_Table_Pandas.py @@ -2,17 +2,8 @@ import PySimpleGUI as sg import pandas as pd -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - # Yet another example of showing CSV data in Table - def table_example(): sg.set_options(auto_size_buttons=True) diff --git a/DemoPrograms/Demo_Table_Simulation.py b/DemoPrograms/Demo_Table_Simulation.py index a730ff723..19930e9bc 100644 --- a/DemoPrograms/Demo_Table_Simulation.py +++ b/DemoPrograms/Demo_Table_Simulation.py @@ -2,14 +2,6 @@ import PySimpleGUI as sg import csv -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - def TableSimulation(): """ @@ -36,9 +28,9 @@ def TableSimulation(): sg.Input(key='inputrow', justification='right', size=(8, 1), pad=(1, 1)), sg.Input(key='inputcol', size=(8, 1), pad=(1, 1), justification='right'), sg.Input(key='value', size=(8, 1), pad=(1, 1), justification='right')], - [sg.Col(columm_layout, size=(800, 600), scrollable=True)]] + [sg.Col(columm_layout, size=(800, 600), scrollable=True,)]] - window = sg.Window('Table', layout, return_keyboard_events=True, resizable=True) + window = sg.Window('Table', layout, return_keyboard_events=True) while True: event, values = window.read() diff --git a/DemoPrograms/Demo_Table_Simulation_Arrow_Keys.py b/DemoPrograms/Demo_Table_Simulation_Arrow_Keys.py index 33e501945..0e7aaba46 100644 --- a/DemoPrograms/Demo_Table_Simulation_Arrow_Keys.py +++ b/DemoPrograms/Demo_Table_Simulation_Arrow_Keys.py @@ -5,12 +5,6 @@ """ Another simple table created from Input Text Elements. This demo adds the ability to "navigate" around the drawing using the arrow keys. The tab key works automatically, but the arrow keys are done in the code below. - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ sg.theme('Dark Brown 2') # No excuse for gray windows diff --git a/DemoPrograms/Demo_Tabs.py b/DemoPrograms/Demo_Tabs.py index ad1684d44..87b8b96ae 100644 --- a/DemoPrograms/Demo_Tabs.py +++ b/DemoPrograms/Demo_Tabs.py @@ -3,14 +3,6 @@ import PySimpleGUI as sg # import PySimpleGUIWeb as sg -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - # Usage of Tabs in PSG # # sg.set_options(background_color='cornsilk4', diff --git a/DemoPrograms/Demo_Tabs_Nested.py b/DemoPrograms/Demo_Tabs_Nested.py index 0372307f2..f8e00eb99 100644 --- a/DemoPrograms/Demo_Tabs_Nested.py +++ b/DemoPrograms/Demo_Tabs_Nested.py @@ -1,25 +1,7 @@ +#!/usr/bin/env python import PySimpleGUI as sg -""" - Demo - Yet another example of TabGroup element - - These are simple tabs and tab groups. This example simply shows groups within groups. - Be careful with tabs to make sure you don't re-use a layout. If you used a layout in one tab - you cannot use it again in another tab. - - There was an error in this demo for quite some time that makes for a great example of this error. - - See how tab_layout is in both Tab elements? That's a no-go and you'll get an error poup - - tab_group = sg.TabGroup([[sg.Tab('Tab 7', tab_layout), sg.Tab('Tab 8', tab_layout)]]) - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - +# Yet another example of TabGroup element sg.theme('GreenTan') tab2_layout = [[sg.Text('This is inside tab 2')], @@ -30,12 +12,11 @@ tab3_layout = [[sg.Text('This is inside tab 3')]] tab4_layout = [[sg.Text('This is inside tab 4')]] -tab_layout7 = [[sg.Text('This is inside of a tab')]] -tab_layout8 = [[sg.Text('This is inside of a tab')]] -tab_group = sg.TabGroup([[sg.Tab('Tab 7', tab_layout7), sg.Tab('Tab 8', tab_layout8)]]) +tab_layout = [[sg.Text('This is inside of a tab')]] +tab_group = sg.TabGroup([[sg.Tab('Tab 7', tab_layout), sg.Tab('Tab 8', tab_layout)]]) tab5_layout = [[sg.Text('Watch this window')], - [sg.Output(size=(40,5))]] # generally better to use a Multline, but for super-simple examples, Output is OK + [sg.Output(size=(40,5))]] tab6_layout = [[sg.Text('This is inside tab 6')], [sg.Text('How about a second row of stuff in tab 6?'), tab_group]] diff --git a/DemoPrograms/Demo_Tabs_Simple.py b/DemoPrograms/Demo_Tabs_Simple.py index dd68c81c1..ac7a843a6 100644 --- a/DemoPrograms/Demo_Tabs_Simple.py +++ b/DemoPrograms/Demo_Tabs_Simple.py @@ -1,20 +1,9 @@ #!/usr/bin/env python - -""" - Demo - Simple Tabs - - How to use the Tab Element and the TabGroup Element - - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - import PySimpleGUI as sg # Simple example of TabGroup element and the options available to it + sg.theme('Dark Red') # Please always add color to your window + # The tab 1, 2, 3 layouts - what goes inside the tab tab1_layout = [[sg.Text('Tab 1')], [sg.Text('Put your layout in here')], @@ -25,16 +14,17 @@ tab4_layout = [[sg.Text('Tab 3')]] # The TabgGroup layout - it must contain only Tabs -tab_group_layout = [[sg.Tab('Tab 1', tab1_layout, key='-TAB1-'), +tab_group_layout = [[sg.Tab('Tab 1', tab1_layout, font='Courier 15', key='-TAB1-'), sg.Tab('Tab 2', tab2_layout, visible=False, key='-TAB2-'), sg.Tab('Tab 3', tab3_layout, key='-TAB3-'), - sg.Tab('Tab 4', tab4_layout, visible=False, key='-TAB4-')]] + sg.Tab('Tab 4', tab4_layout, visible=False, key='-TAB4-'), + ]] # The window layout - defines the entire window layout = [[sg.TabGroup(tab_group_layout, enable_events=True, key='-TABGROUP-')], - [sg.Text('Make tab number'), sg.Input(key='-IN-', size=(3,1)), sg.Button('Invisible'), sg.Button('Visible'), sg.Button('Select'), sg.Button('Disable')]] + [sg.Text('Make tab number'), sg.Input(key='-IN-', size=(3,1)), sg.Button('Invisible'), sg.Button('Visible'), sg.Button('Select')]] window = sg.Window('My window with tabs', layout, no_titlebar=False) @@ -51,6 +41,5 @@ window[tab_keys[int(values['-IN-'])-1]].update(visible=True) if event == 'Select': window[tab_keys[int(values['-IN-'])-1]].select() - if event == 'Disable': - window[tab_keys[int(values['-IN-']) - 1]].update(disabled=True) + window.close() diff --git a/DemoPrograms/Demo_Text_Element_Autosize.py b/DemoPrograms/Demo_Text_Element_Autosize.py index 69ceb6d80..93f1ef1ef 100644 --- a/DemoPrograms/Demo_Text_Element_Autosize.py +++ b/DemoPrograms/Demo_Text_Element_Autosize.py @@ -17,11 +17,7 @@ By default autosize is enabled, but setting a size parameter will disable unless None is specified in one of the directions. - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ layout = [[sg.Text('Starting string', size=(None, None), k='-T-'), sg.Text('Also on first row')], diff --git a/DemoPrograms/Demo_Theme_Add_Your_Own.py b/DemoPrograms/Demo_Theme_Add_Your_Own.py index f2f2ab31b..3a27eb29d 100644 --- a/DemoPrograms/Demo_Theme_Add_Your_Own.py +++ b/DemoPrograms/Demo_Theme_Add_Your_Own.py @@ -5,11 +5,7 @@ There are functions to make the job quick and easy. - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI.org """ # First make a dictionary with the required keys. diff --git a/DemoPrograms/Demo_Theme_Browser.py b/DemoPrograms/Demo_Theme_Browser.py index cd8961481..f9336b37d 100644 --- a/DemoPrograms/Demo_Theme_Browser.py +++ b/DemoPrograms/Demo_Theme_Browser.py @@ -5,12 +5,6 @@ Popup window using the color scheme you chose. It's a simply little program that demonstrates how snappy a GUI can feel if you enable an element's events rather than waiting on a button click. In this program, as soon as a listbox entry is clicked, the read returns. - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ sg.theme('Dark Green 5') diff --git a/DemoPrograms/Demo_Theme_Change_Your_Windows_Theme.py b/DemoPrograms/Demo_Theme_Change_Your_Windows_Theme.py index 94515043a..4f8963f6c 100644 --- a/DemoPrograms/Demo_Theme_Change_Your_Windows_Theme.py +++ b/DemoPrograms/Demo_Theme_Change_Your_Windows_Theme.py @@ -5,11 +5,7 @@ * Create your window using a "window create function" * When your window's theme changes, close the window, call the "window create function" - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ diff --git a/DemoPrograms/Demo_Theme_Color_Swatches.py b/DemoPrograms/Demo_Theme_Color_Swatches.py index 19b336e15..31f24179a 100644 --- a/DemoPrograms/Demo_Theme_Color_Swatches.py +++ b/DemoPrograms/Demo_Theme_Color_Swatches.py @@ -23,11 +23,7 @@ * Have a "create_window' function where the layout and Window is defined * Use a "main" program function where the event loop also lives - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ # Try and import pyperclip. Save if can be used or not. diff --git a/DemoPrograms/Demo_Theme_Custom_Saved_In_UserSettings.py b/DemoPrograms/Demo_Theme_Custom_Saved_In_UserSettings.py deleted file mode 100644 index 6c52190f2..000000000 --- a/DemoPrograms/Demo_Theme_Custom_Saved_In_UserSettings.py +++ /dev/null @@ -1,86 +0,0 @@ -import PySimpleGUI as sg - -""" - Demo of using User Settings to create and store your own personal PySimpleGUI themes - - There are 2 operations - 1. Initialize your settings file. You would normally only do this once and perhaps - write a simple program to administer it or you can also edit the JSON file directly - 2. Use your settings file. Add the code to the top of all of your applications that you want - to have access to your selection of custom themes - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - -MY_APPS_SETTING_FILENAME = 'my_awesome_apps.json' - - -def init_your_settings(): - DarkGrey20 = {'BACKGROUND': '#19232D', - 'TEXT': '#ffffff', - 'INPUT': '#32414B', - 'TEXT_INPUT': '#ffffff', - 'SCROLL': '#505F69', - 'BUTTON': ('#ffffff', '#32414B'), - 'PROGRESS': ('#505F69', '#32414B'), - 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - } - - DarkGrey21 = {'BACKGROUND': '#121212', - 'TEXT': '#dddddd', - 'INPUT': '#1e1e1e', - 'TEXT_INPUT': '#dbdcd9', - 'SCROLL': '#272727', - 'BUTTON': ('#69b1ef', '#2e2e2e'), - 'PROGRESS': ('#69b1ef', '#2e2e2e'), - 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - } - # Set up my app settings file... start with an empty one to be sure - sg.user_settings_delete_filename(MY_APPS_SETTING_FILENAME) - sg.user_settings_filename(MY_APPS_SETTING_FILENAME) - # Add the theme dictionaries - sg.user_settings_set_entry('Dark Gray 20', DarkGrey20) - sg.user_settings_set_entry('Dark Gray 21', DarkGrey21) - sg.user_settings_set_entry('-theme list-', ('Dark Gray 20', 'Dark Gray 21')) - sg.popup_quick_message('Your settings file has been created and is ready to be used', background_color='#1c1e23', text_color='white', keep_on_top=True, font='_ 30', non_blocking=False) - - -def use_your_settings(): - sg.user_settings_filename(MY_APPS_SETTING_FILENAME) - - default_theme_name = sg.user_settings_get_entry('-theme default-', None) - - # Only need this section is you want this app to allow user to select the default theme - # Could also auto-choose the first theme in the list for them - if default_theme_name is None: - default_theme_list = sg.user_settings_get_entry('-theme list-', None) - event, values = sg.Window('Choose a theme', [[sg.T('Your settings do not have a default theme chosen so please choose one')],[sg.Combo(default_theme_list, key='-THEME-', readonly=True, enable_events=True)]]).read( - close=True) - if event == sg.WIN_CLOSED: - sg.popup_error('No theme chosen so exiting') - exit() - default_theme_name = values[event] - sg.user_settings_set_entry('-theme default-', default_theme_name) - - my_theme = sg.user_settings_get_entry(default_theme_name, None) - sg.theme_add_new(default_theme_name, my_theme) - - # Switch your theme to use the newly added one - sg.theme(default_theme_name) - - # Test out the theme - sg.popup_get_text(f'My theme is {default_theme_name} looks like this.', image=sg.EMOJI_BASE64_HAPPY_THUMBS_UP) - -if __name__ == '__main__': - operations = ('Initialize your settings (must do first)', 'Use your settings') - event, values = sg.Window('Choose an operation', [[sg.T('Choose an operation to perform')],[sg.Combo(operations, key='-OPERATION-', readonly=True, enable_events=True)]]).read(close=True) - if event == sg.WIN_CLOSED: - sg.popup_error('No operation chosen so exiting') - elif values[event] == operations[0]: - init_your_settings() - elif values[event] == operations[1]: - use_your_settings() diff --git a/DemoPrograms/Demo_Theme_Dark_Custom_Elements_Check_Toggle_Buttons.py b/DemoPrograms/Demo_Theme_Dark_Custom_Elements_Check_Toggle_Buttons.py deleted file mode 100644 index d6cad33a5..000000000 --- a/DemoPrograms/Demo_Theme_Dark_Custom_Elements_Check_Toggle_Buttons.py +++ /dev/null @@ -1,104 +0,0 @@ - -import PySimpleGUI as sg - -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - - -DarkGreyFig = {'BACKGROUND': '#232429', - 'TEXT': '#828692', - 'INPUT': '#333742', - 'TEXT_INPUT': '#f7fbff', - 'SCROLL': '#505F69', - 'BUTTON': ('#fafdff', '#1d5ffe'), - 'PROGRESS': ('#505F69', '#32414B'), - 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - } - -# Add your dictionary to the PySimpleGUI themes -sg.theme_add_new('DarkGreyFig', DarkGreyFig) - -# Switch your theme to use the newly added one -sg.theme('Dark GreyFig') - - -def Check(state=None, key=None): - return sg.Image(state, key=key, metadata=state, enable_events=True) - -def Toggle(state=None, key=None): - return sg.Image(state, key=key, metadata=state, enable_events=True) - -def DarkButton(state=None, key=None): - return sg.Image(state, key=key, metadata=state, enable_events=True) - -def main(): - gray_bg= '#333742' - - col_cb_layout = [ [Check(cb_blank, ('-CB-', 0)), sg.Text('Label')], - [Check(cb_check, ('-CB-', 1)), sg.Text('Label')], - [Check(cb_minus, ('-CB-', 2)), sg.Text('Label')], - [sg.Text(s=(1,2))], - [Toggle(toggle_light, ('-TOGGLE-', 0)), sg.Text('Light')], - [Toggle(toggle_dark, ('-TOGGLE-', 1)), sg.Text('Dark')], - ] - - col_left_layout = [ [sg.Text('Label')], - [sg.Input(key='-IN-', border_width=0, s=30)], - [sg.Frame('Tags', [[sg.Image(button_green_keyword, background_color=gray_bg), sg.Image(button_orange_keyword,background_color=gray_bg)]], background_color=gray_bg, border_width=0)], - [sg.Frame('', [[DarkButton(button_dark, key=('-DARK BUTTON-', 0)), DarkButton(button_darker, key=('-DARK BUTTON-', 1)), DarkButton(button_darker, key=('-DARK BUTTON-', 2))]])], - [sg.Image(submit_button) ] ] - - - layout = [[sg.Column(col_left_layout), sg.Col(col_cb_layout)]] - window = sg.Window('Dark Custom Mockup', layout, font='_ 16', border_depth=0, element_padding=(10,10),use_custom_titlebar=True, titlebar_background_color=sg.theme_input_background_color()) - - while True: # Event Loop - event, values = window.read() - print(event, values) - if event == sg.WIN_CLOSED or event == 'Exit': - break - - if event[0].startswith('-CB-'): - if window[event].metadata == cb_blank: - window[event].update(cb_check) - window[event].metadata = cb_check - elif window[event].metadata == cb_check: - window[event].update(cb_minus) - window[event].metadata = cb_minus - elif window[event].metadata == cb_minus: - window[event].update(cb_blank) - window[event].metadata = cb_blank - elif event[0].startswith('-TOGGLE-'): - if window[event].metadata == toggle_dark: - window[event].update(toggle_light) - window[event].metadata = toggle_light - elif window[event].metadata == toggle_light: - window[event].update(toggle_dark) - window[event].metadata = toggle_dark - elif event[0].startswith('-DARK BUTTON-'): - [window[('-DARK BUTTON-', i)].update(button_darker) for i in range(3)] - window[event].update(button_dark) - - window.close() - -if __name__ == '__main__': - button_green_keyword = b'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' - button_orange_keyword = b'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' - - cb_blank = b'iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAD+UlEQVR4nM2Y328bRRDHP7O354tTXYpLfsG/UMkIUNWWIiHEG38w4oEn0qoIgdqo/RPSR5vgNBfbt7vDw96eL46bGBqsfKWVvXt3u9+ZnZ2ZHeEDePToe83zDGt7FEWOtT1UPdb2gACYK78BMMYAoKqEEGJTRwgBVaWqKqbTKa//fC6r1r00+HD4WPf3DimKgiyzOFfjfQCUEBTnaozJAG0+Xf4F7z0qICKICAbBGFn0jaHX6+Gc4/TvMb+9+EVWEhp++UT39w+xWY/pdEZVVYQQEImvJGlvgmQGVV30NZGL/SzLEBF6vR5lWeK95927d7w5fiEANn24v39InueMxn/hfVSviKBoS8z28htJJQG6pACUON/c1YgI0/mManrB7u4uh59/xpvj+J4BePrtD7q9vc1oNKKu65ZMUnGSynt/o4ZU9QqZNO69J89zVJWiKHDOMR6PyfOcZ9/9qAD24fCxPniwy+npKSGE1ihBm8m70sfx/4IkoHOOLMuo6xprLc7Nef9+wmBwP2rIWouq4pxbKdn/BRFptelcPIXDr5+qLYoiDtYBDYJkNxvux6GxTV2sU9c13nu2t7cxRVEQQsB73xik+fBct0mr2Q0Radcven1snucEDyEo1mYE9CNJLWv48lwioCqoCiIGY6RxKWCtxWRmcZRFNqed5B66YyaeatMSuh2jNkttmQyANMJLVGgAUUHIMMnab4/QeuhGgO66JvkdEZCV4e62iUD0cTFGGmvAgNfoNDdjNGtCJdwtQrApp7MGkh3dGUIJd4ZQOnV3hlDC3SOU0g9jzEYcY3LEXceYciVVxayTJ98mluNYN1KISCTUHdwksUSiC5PyoE0RWhXpu8+M9x5jTLuPm8Klq1Kztvce45xrCW0aXQM3xlDXdSS0Se0sn7L0P8synHObP2XL6Bq39x5zcX7OvX4fo3IlhU3XlH9j8KoeCIho2yCg6lH1bXaa7oCqSp7nAFRVhXn16kicc5RlyWw2g7DY09TSzXUdYinhaysfDYEsy7DWkuc51tr2thFCaJ+9/uNILMBkcsrOzicU57Eq4ZtLY7KtbrtZQ0LMmbtaBu+VmCn6lnhSRFmWjMfjOA4wGo24uLjg08GgZZ8MLfW70l9PaGETaY5V2oZ47dnZ2QHg5dHPi+rH27e/i7Xf6N7eHgcHB1RVRVVVsfDgA9JsQV27NUg1FRMNl0OCWWg4z+LWDQYD5vM5Jycnna87GA6f6L3yPmVZsrW1hXOO2Wy2KM00VbHrEMJlDS1afG6Mod/v45xjMpnw/NefVheslvHFV8+0KAr6/T5FUQCxOra1tXUtIaMLDSYBnHN47/He49ycs7Mzjo9frlz7HzLiWEBTYnmBAAAAAElFTkSuQmCC' - - cb_check = b'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' - cb_minus = b'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' - toggle_light = b'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' - toggle_dark = b'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' - submit_button = b'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' - - button_dark = b'iVBORw0KGgoAAAANSUhEUgAAAGsAAAA2CAYAAADAr2clAAAQRUlEQVR4nO2ceYxcVXbGf/e+pV5V716wG0yDM60xNgbHrAHjDGYwAZOYAGacDAhMRkocIhmYEBgnBAyMUUYgIQUQQooipIQJMMYxi4QDzIwRGsK+ZWJsHLYZjLdu91LVVfW2e/PHq/uquuhuG7rahqE/qdRV9V6/u5xz7j3nO+eW4CBwzO8dr13XxbZtLMtCCJG+LMsadq8QYszP3zQopdBaA6C1Tj8nr5goiojj5O/HH2wdc7JGvTi7+3jteR65XDNCCKSUo3YAhgvlmy6gWph5M/Nk3pvPlmWlQgvDkCAICIJgRMGNOKtz55+sm5ubkVISKwA5rIHROjGJz0MpBZCuRHVXieMYy7KwLAspJUopgrBMPp/ng23vDvuHzwnrxIVnas9zieMYkAhpjykQ04H6e0ayuG8mzPj1iHNlWQKlEqFprbFtGyklQRBQKg+x/ddvivonAfD7J5+lbctF6QjLtitaIZnE4YIiP9jP+++9LaBGEt3fPknblguAFPawfWkShw+ZTJau2cdpqBFWS0sLUkq0AKSYFNRXBJlMBs/zgIqwZnefoB3HSTdDI6haD3AShwMSKeVwYXmeh9aaOI4RYtKqvkpQSuG6Hl2zj9MSwHXdEa1pUmiHH0oppJQ4jpNYlmEhjJ8vpZwU1FcExt23bRt57LfmJ56GlAghiKIoDeAm96zDD2M4QojEsoQQ6X5lWVbiaFiSUMXjbkxr/TmLNdpiHJrxPr82AB9O44x/dTCKG0VROje17SmlsG07VfLa8TUKWmtc10XWPrh+cI1o1AzACMy0Y1kWtm035PmO4yClJIqidIXwfb8h/Y+iCEiEH8cxUsp0xVFKYVkWvu+TyWQAUmE1QhFrUVnpksFpQfJq8F5lmGaj6SZECMOwQmmND1JKyuVy2obRfMO3jRdGocyqYMZRu1K4rpuy56YPmUymoXM5TFj1aFRDZkC+72PbNsViMZ3ERkxmLREKVc0WQhCGYUOeb55nlMzMl7lWKpWQUqZCU0oRRVHD5tCMya6ywckXMTp535BmqkueEIIgCMhkMqkAG7FUmOXJ932Ahi9BUkriOB62Oph2zDiy2WzClgcBQggymQxhGDbUQUuFVf9lI803iqI0AjfabzS+EYMxS6nZM2odAmjMCuE4TsqKm2c7joPruoRhmLZVb9G1+/R4kXqDE4lcLkc+n2fFihX84hfPcfbZZw9bqsYLo8l9fX0sWLCAxx57jOuvv56BgYGGPd/3/dSypJQUi0WWLVvGxo0bWblyJeVyOXWYlFKpwhshNgJVYWlZd0GTMFHjl6Xv+1iWRXt7K54HU6a0D3Nzvxyq2mrCDkiYmJkz25gxYzpax1iWQKAQGsQXbCq5P2nHspIlz4wliiKy2SxTpmRw3ST3Z9z3WoE1Yk+uQiITQQnATF5jXU5bWkih0SoCDSoO0wlMoAhViLAtlACFQAuZXrMkWJI05R2GPrYj0TquKJXAsuyK0EKkhLJfAB0jhSbyy6AidBxiWyJpV2ksy0ZrUEojpQVKIxFYEuIoIA59BArbEkihsSQIFKBwHIs4DtEa0DG2JYjDKN0vtRQoQWX/Hx+0EtXwZ+w7GxncKRAgNUhdSXWjKsuYQxiGlXjMTgNdKSWl0hD5fJ6pU6fS2dlJW1sbxWIRPyil5HMcx2Sz2Rp+U2BZgv37e2hra2P69Kk0NTXR37s/jcPiOAKSzGwYBjiOg+/7BKUyU9ramTXrSHIZj76+XsrlMqASSxWCYrGIbduMtcqaUKghqKx8449KD9SOYEz9Ukqhgxgp3XR/yGYzxGEZPwg45ZRTOPfc85g3dz7Tpk2jUMyzbftWnnrqKd54/S2am1vx/YBSqYRt22gFYRBg2zZr1qxh8ZmLaW9vZ+fOXbz9P+/y8MMPs3v3btrb2xM3XCdWM5jvZ86cOVy8/CJOOukkZsyYzt69e3nzzTd58skn+fV7W+no6MA3Hq0QDfOYDxaHnfwzbj0knlsul0srfC677DLuvfdeVq5czszOI9j52W/JeA7nn7+Ue+/9ZxYtWsS+fftST9Agm81y8803c9VVV5LJZfntZztZeMo8rr76z7jjjjvo6uqqWAtIC/L5PIsWLeLBBx/k8ssvZebMmezatYtp06bx/e+v4L777uMPF53F0NAQdiXoTWKpQztXE25ZB0IURUhLgOEnlUZFEV1dXaxevRrXFdxyy3o2b362QikFrFhxCTfc+Lf8xQ9W8eqrrxPHMY5lI1AoBaeddhqlYpnVq/+at956B9vJ0N7ezjXXXMNFy5dy3XVr+Me//wdcS1IuDjGn+1usvfHvyGVc1q37JzZv3oywLeIg5MILL2DdurXcdNNN/PkVlyfppJQlObRzdWgta4T1sN5jCsOQTCbD4OAg99xzD3fccSebNm3Cdd1KIs7loYce4uOPf0N3dzezZs3C98sgVCUcgCAIuPPOO/nVr/4bN5NFCMHu3bu5++672bHjNyxd+h3mzZtHqVQCYOnSpRx7bCd33XUXGzZsSK1dCdjws5+x8fGnOeaYTv7o3KXs2bMHz/Mawmt+URxCYY3clCFfYThxXMjn2bTxP3nkpz/FFonbbNiEjo4O0ArXtmhpzhH6yR6VUE8wMDDAiy+8wJQpUxJPSlrkcjn27dvH888/j9ZwxpmnE8UBWc9l+Z9cSE9Pnpdeegk36+FHIeVSkPZp8+bNACxYsADP8wjDsEI7TfCU1eGwL4PJJEcoklhGoInjhAiN45A58+fT3d3Nt4+bz6xZR9LR0cGCBSfgODAwUExZdz8oVbw86OnpoVgs0tKWSfi8WJF1HSzLYseOHUgJXV1dSdzU1s7RRx9J/0CRG2+8kaIfJAyFncGyBWHZZ9rUDrSG6dOn09rayuDgYIXmqo7jUCRrJ1xYQkiUqg7GFDIKIVAmFyXAQoDSCCGRMomZVq26kquvuor29ibCGPr68uzdu5fHH3+c7557Ds1NLWlqxFillImwUspJJMyCYU0Sng+am5uTvrgOCmhuzrFw4UKUSKzXkg6aZA+N45A9e/bT398/jOuUsr64KHkfqxiRUk2NM79DYlmO41QmK7Ek3/extUXGc4iVQqOxLUmp5OM4LuVymWUXLOXaa69hoK/Aj3/8E95+dyuFwiBhGLJt21aefOoJFpx4ApDse1EQVGIomDplGpZ0cJwMYYUF1zIR3tSpUwHo7e1NCddyOaC/b5C1a9eye18PruuClkmxa0UAnufRnx8EahWvSiRHUYQiifvsjEtcSaEQN87iJlxYJmitrY13XRcvlyMIy0jLwg98bMtNckCxxnMzLF68GIBbb7uNZ555hubmdiBxMDo7O8k1NSEkhFFEGEe4joeuRKFHHXUUR3TOpLe3j4znoXwf202cgq6uLqSErdveJ1IQRIoPK87KULnERx99RGtra5ohgIRNN5RWR8dUpGURhCGaagLScRy0SBwky7KIo8YyQXAIHAxjVYlzkHhqQ0NDCQvh+5RKCRORz+cpFgtpaiGhbqC/vx8p7UTAXo6enh5OPfVUOjs7yReSWMl13dQBKRRCZsyYwrJlf0xfX1+aa+rt7WX27NlccMEFBAG8/PLLeJ5HoVDg2WefxbLg0ksvxRxt8jwvJW1XrVrF+vXrOf2MP2Awn0+zxVJWq4+UUsRhlObuJgITbllBZXlKUgmKuXPnsmTJElyvGU2M0hqEwrEzFAoFdmz/gP37e3nj1dc479xzWLPmOm6//Xb27eslDEOW/+lF/PCH19HSnGV/Xx4hLIRIKomjOMZxHHbt6mHlypUEQcDTTz8JwDFdx7N27VqOmNHOI488wac7d+G4HkLabP6v5zj//GV873sX09razv3338/evbtpamrioouv4C9X/xVZT/LMc88So5GOXclQJ95iuVzGdTyEEIniRCFiAirEJlxYhnvr6OjAdSXLl1/IJZdciB+C4yZbskryncQxXHnFD9i9exdbtmzhjDNPZ8l3z2bTpkcZHIhxXAsnAxs2bGTx4rM4svOIlPXOZDLYto1tw6effsZzz/2cH/3oem644W8oFmNyOQutYfPmF3jggQfS5KHreuzZs4dbb72V9evXc955S1i2bAmlkiKblShgaCjkltt+wosvvkhLSxu7du3CcRw8L0kBZbPZlHWPogipQcVmGfwaORgmkN2yZQv5/ABSJxonbY8oDhAmJtaSQqHA4OAgLa1N5AsDrFu3jtfeSLi66UccSU/PXl5/41UeffQ/2LbtImbNOpqdO3dWJt7ik08+4V8f+jc++ugjnnriaYIg4LSTT6K1tZWevn5eeeUVtrzwIkEQ4HgeJd9HIMk2t7Bt+w7WXHs95yz5DnPmzGHGtKkU/TLb3t/Oz3/5S7Zu3UpTUxNCCJqamnjr3Xd48F/+nTdfex1VU81MmkFu/MEOMWfeybqttYNIxZWo3WiEBC2Q46T5ldJYlqRULDA0lAfAshxUDEJqFEnKXJC42E3ZZrK5DFEUIISmv3+Q1tZ2vGwTAwN9hJFPS0sL+fwAvh/S0T4d23bQOql76O/fj+d5NGWbGRoaIpvL4DgO5XIZ3/dpbmnDtm1KfpCWjZfLZZqyXnImqljAcRxyuRxKRfQP5PGaPCzLSd12U4sxODhILuPR0tICqlJeV5kvLSuhxDjlZVJJmhgxZ95C3dbWkcY8MZWyMZLcz3gbg2q6W0rDUlTXcyHM+VpRc9a2mldLNu9q/aG531yL4+GH9uqzw6Md8hurn+Y+rWOktAGV9q/+vkaXnH0OyiRYI2zTKeMYTkQkbgRQHVc19K9Orq5r2/QnKeap9k1g9oHaeTJB71j9/+Jjk2mb9WeCDyXSEupUmzFaYwES0aAODdfUzxeRjqSZIxWe1j5nNKGMdxJHEshozzxUAqsdtz1S6fFEN1z/fizUFteY2ob6a+b9F322uXcsqxmrHHoiSqVHRqLodm1hjBDVtG6jOlJrOQeymNEw2n400j3jUbiRxnwwbR4KKKWqljVRHRhLK2v/jnbvSMX+9Rv9l7Wqg2n/qwJNjDQp6tTDapAHaGAmtPZV+33tfWN2dhSt/90/R1aTrTCCEhgnYLQf2PiSTR3Agg7mpOVYlvXV2FMmGEIlYcQnH/6viOOY5JB+NXawhUSoxp6CGEkJhsdWo/+vubf2WQcSxtdNUCN6vjIZYxAEiWdhUhjG2zL12pMnHyceozlGtQpp6uklQOSX03yNKftt5FI4iYNDfUxqVg7zw1sSYPv2d0QQBOmRltpDYZOYWNQKpdaaapfEMEzyY+k6VyoNoXWMQBFHAVTquicxsagP7GsFZ47AmmRmKqz/2/6uMKcSHcf5hrjFhx9jEQVxHFIoFPjkw/cE1OWzCoUCUiYpbeMdTopr4jES5RUEAb5f4oP33xn5J+wMjj/xdG2qTuNIN/YwySSGoT78SDjQiHx+iB3vvT72j0MadHfP13bGI5dtTgtEaje/evZ7LKrom4zacGikGFNIkz5KEpq+71MuF9OlrxYHtJmjj52rzRFM84PGRnBmE4SvXwB6qJAyOEqgiVPBGOYo+UmGJI4aSUC1+H+1v2tgSQm5egAAAABJRU5ErkJggg==' - - button_darker = b'iVBORw0KGgoAAAANSUhEUgAAAGsAAAA2CAMAAAD3cZcXAAACuFBMVEUfIiscHSEkJy4gIyohJCsjKC4kJjIeISghJC0jJi0gIywjJi9FSVRKTllMUFt8f4tydIBzdoJrbnl6fIh4e4Z9gIuDhpB8f4pucXwiJjF7fop/go2ChY97fodsb3p4eoV6fYh/gYyChY58fYdRVWBWWWROUlxsb3mFiJFVVmBcXWdUVWBSUl1aW2ROT1gdISp8foloa3R7fYhpbHVucXt1d4NWWWNdYGp7fYlgYWokKDF8f4l3eoR3eoVfYm1sbnlhY207PURSVF1tbngiJi9ZXGZhY24+P0YmJy0nKC4lJyxAQUdHSlVucXpiY246O0IoKS8pKzEyMzlMTVYvMDZJS1R7foh1eYI/QUc9PkVdYGtvcXs8PkMkJSpoaXN6fIZBQkl3eIJ9f4oeHyMfICQpKi9maHJtcHl2eINLS1MrLDI2Nz2Fh5EkJzBPUVc9PkNGR05BQ0pmaXNucHo7PUNNTVVoaXRISVBnaHOHiJOChI55e4VAQUhnanQ+QEc6PEJRUlqGh5J+f4lzdX8xMjgsLjQhIic8PURGR09MTlVnaHJTVmBYW2VYWmZXWWRZWmNfX2lHSlIiJS6Ago19foiFh5I6O0FkZ3IjJCl1d4JIS1NdYGmDho96e4UnJy81Nz0sLTJvcnwnKS55e4Z7fol9f4liZ21+gYyBhI5sbHZvcX1tcXttcXpwdH5pbHd4eYMwMjdlaHRtcHssLjNJTVdWWGNNUFhqb3iHiZNeYGx6fIdvcn1zdYFhZG50eIIcIyuBhI9maXGDhY6EhY+DhI+EhpJKTFh5e4d5fIZ2eoGAg4xLT1pTV2B/goxzd4B0doFOUV1VWGOHiZSGiZNdYmpfZm5/g41kZ3EhIy8gJSseIykfIywjJzBMT1ofJCpKTVdOUVtISlQdJCwlKC8fIikkJCwdICkAAACsCdXOAAAA6HRSTlP///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8Asi2gugAAAwJJREFUeJzdmAdTE1EQx7OJSonlrxRRo2KvWFAsIAqWE1tERQRRQcWKWLGhYhcVFAWxgdjF3rBi7xV7x240X8P37iCEGaIzN8kbx525293bffebN2/fldWYi0VDjhGtzkJQVDkHgYpEZ8VyLIlJeQvL4SgmRSwRKA5jrApiWE6cJQbFJqYxOwtkiUKRk0CWi0AWaVz/U5awMmQsvUCWONQ/w6poK1DJ9pjK6lhVULXsQDW42RrjDg9VLE9ULzvgBdgYUqMmaqliGVC77EAd1LU1xhv1VLHqo0Epv2GjxorRBE2JmjVvURJq6dNK1q3b2IXV1heAdztutmcsP+b5dVBCHTsxx7czs/wD7MHqAkW8ZFZgoOJ15aFuCAruHhyEHkQ97TGvXpB6h/Tp209Cf6IBgHFg6KDBRmAIkQ+CwlhGWBCGknO4PeY1LEJWkRhOFAWM4M5II0YRRSNSDsVgNNEYlSxDqfUay47YcRLGE02AMVa+FoGJNAmYLDtxmELxvnZhTZ02fYbElmgm0ayimVAC22izgTlzuczDfHJVu16J1qwFvBSkhRIWcVaScnExYy2BRZaSXm0dJmKZxV7OamPFylWUzFlRxfOKAFavAdampK5bn5a2YSOlByBDFcuATRY7E5tlnYwtvOaNW2UvCdtoO5BleQf6q31uZGNHTglrJ1e7JM7aDcRwb48RWUR7sU9O2Z95gCgcuapYB5Fx6HDUkaPHjhOdgHQyNCSBFccpotNsfyXl5cWx/XWGKAVwO0vn2GY/T6S2Ni5YFv0iUb5suAMMfAm4rARSed6VoqyrRNc8cF0V68bNW7fvGLKzPXPvMi86H/fu04OHj4geFzyhp/zuz5TE576ZL14WvOLm6zdvVbFIp9O/S3//ofAjd7T0iavP/FTIji9fv5U15vsf7vevfG/YnfVDIEsrkBUvkCXyG1vkv4PAQhT4X6kVyNJpzDl/z7KPCO6lmAXtZpO43pde6bOZRLDE9SrJqgf707Ekk3W/12z+5eqgp7CLqRjxG7LsF9Z68qMOAAAAAElFTkSuQmCC' - main() diff --git a/DemoPrograms/Demo_Theme_Previewer_Dark.py b/DemoPrograms/Demo_Theme_Previewer_Dark.py index bd782fde4..905df3491 100644 --- a/DemoPrograms/Demo_Theme_Previewer_Dark.py +++ b/DemoPrograms/Demo_Theme_Previewer_Dark.py @@ -8,11 +8,7 @@ This demo shows how to access the list of all "dark themes" as an example of how you can build your own previewer - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ # Use the built-in Theme Viewer to show all of the themes and their names diff --git a/DemoPrograms/Demo_Time_Chooser.py b/DemoPrograms/Demo_Time_Chooser.py deleted file mode 100644 index 942543ec2..000000000 --- a/DemoPrograms/Demo_Time_Chooser.py +++ /dev/null @@ -1,83 +0,0 @@ -import PySimpleGUI as sg - -""" - Demo Time Chooser - - A sample window for choosing a time. - - This particular implementation uses a Spin element. Numerous possibilities exist for entering a time of day. Instead - of Spin elements, Input or Combo Elements could be used. - - If you do not want your user to be able to manually enter values using the keyboard, then set readonly=True in - the Spin elements. - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - - - -def popup_get_time(title='Time Entry', starting_hour=1, starting_minute=0, allow_manual_input=True, font=None): - """ - Shows a window that will gather a time of day. - - :param title: The title that is shown on the window - :type title: str - :param starting_hour: Value to initially show in the hour field - :type starting_hour: int - :param starting_minute: Value to initially show in the minute field - :type starting_minute: int - :param allow_manual_input: If True, then the Spin elements can be manually edited - :type allow_manual_input: bool - :param font: Font to use for the window - :type font: str | tuple - :return: Tuple with format: (hour, minute, am-pm string) - :type: (int, int, str) - """ - - max_value_dict = {'-HOUR-':(1, 12), '-MIN-':(0, 59)} - hour_list = [i for i in range(0, 15)] - minute_list = [i for i in range(-1, 62)] - - layout = [[sg.Spin(hour_list, initial_value=starting_hour, key='-HOUR-', s=3, enable_events=True, readonly=not allow_manual_input), - sg.Text(':'), - sg.Spin(minute_list, initial_value=starting_minute, key='-MIN-', s=3, enable_events=True, readonly=not allow_manual_input), - sg.Combo(['AM', 'PM'], 'AM', readonly=True, key='-AMPM-')], - [sg.Button('Ok'), sg.Button('Cancel')]] - - window = sg.Window(title, layout, font=font) - - while True: - event, values = window.read() - # print(event, values) - if event == sg.WIN_CLOSED or event == 'Cancel': - hours = minutes = ampm = None - break - - if event == '-HOUR-' or event == '-MIN-': - spin_value = values[event] - if spin_value > max_value_dict[event][1]: - values[event] = max_value_dict[event][0] - window[event].update(values[event]) - elif spin_value < max_value_dict[event][0]: - values[event] = max_value_dict[event][1] - window[event].update(values[event]) - if event == 'Ok': - # Do validation on the input values to ensure they're valid - try: - hours = int(values["-HOUR-"]) - minutes = int(values["-MIN-"]) - ampm = values["-AMPM-"] - except: - continue # if not valid, then don't allow exiting the window using OK. - if 1 <= hours <= 12 and 0 <= minutes < 60: # make sure the hour and minute values are in a valid range - break - - window.close() - - return hours, minutes, ampm - -print(popup_get_time(font='_ 15')) \ No newline at end of file diff --git a/DemoPrograms/Demo_Timer_API_State_Machine.py b/DemoPrograms/Demo_Timer_API_State_Machine.py deleted file mode 100644 index 676972026..000000000 --- a/DemoPrograms/Demo_Timer_API_State_Machine.py +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/env python -import PySimpleGUI as sg - -""" - Demo - State Machine using timers - - State Machines are very useful when you need to perform a series of operations that you - cannot do all at once due to a time constraint. Particularly problematic are operations - where you would normally use "sleeps" as part of the sequence. - - In this Demo Program, we're going to use the PySimpleGUI Timer API calls to provide our - sleep-like behavior. - - The sequence of operations we're going to run are: - User clicks a "Send" Button to start the sequence: - 1. A "Status Window" is shown that says "Sending" and Disable SEND button - 2. Sleep for 3 seconds - 3. Close the "Status Window" - 4. Sleep for 2 seconds - 5. Enable SEND button and Go to state 1 - - Control of the state machine will be through the PySimpleGUI events. This will enable you to use threads - for any of these states and have the threads communicate the state transitions using the same write_event_value used - in this example. - - Copyright 2024 PySimpleSoft Inc. -""" - - -class State: - stopped = 'stopped' - start = 'start' - delay_3_sec = 'delay 3 seconds' - close_win = 'close win' - delay_2_sec = 'delay 2 seconds' - enable_send = 'enable send' - - -TIMER1 = 3000 -TIMER2 = 2000 -NEXT_STATE = '-NEXT-' - - -def make_send_window(): - layout = [[sg.Text('Send Window')], - [sg.Text('State:'), sg.Text(key='-STATE-')]] - - # Create window a little lower on screen so windows don't overlap - window = sg.Window('Send Window', layout, finalize=True, relative_location=(0, 150)) - return window - - -def main(): - layout = [[sg.Text('State Machine Example', font='_ 14')], - [sg.Text('Click Send to begin sequence')], - [sg.Text('State:'), sg.Text(key='-STATE-')], - [sg.Button('Send', key='-SEND-'), sg.Button('Exit')]] - - window = sg.Window('State Machine Example', layout, font='Any 12') - - window_send = None - state = State.stopped - - while True: - event, values = window.read() - if event == sg.WIN_CLOSED or event == 'Exit': - break - - if event == '-SEND-': - state = State.start - elif event == NEXT_STATE: - state = values[event] - - window['-STATE-'].update(state) - if window_send: - window_send.refresh() - - # ----- STATE MACHINE PROCESSING ----- - if state == State.start: - window['-SEND-'].update(disabled=True) - window_send = make_send_window() - window.write_event_value(NEXT_STATE, State.delay_3_sec) - elif event == sg.TIMER_KEY and state == State.delay_3_sec: # be sure the if with the timer check AND state is above if with only state - window.write_event_value(NEXT_STATE, State.close_win) - elif state == State.delay_3_sec: - window.timer_start(TIMER1, repeating=False) - elif state == State.close_win: - window_send.close() - window_send = None - window.write_event_value(NEXT_STATE, State.delay_2_sec) - elif event == sg.TIMER_KEY and state == State.delay_2_sec: - window.write_event_value(NEXT_STATE, State.enable_send) - elif state == State.delay_2_sec: - window.timer_start(TIMER2, repeating=False) - elif state == State.enable_send: - window['-SEND-'].update(disabled=False) - window.write_event_value(NEXT_STATE, State.stopped) - - window.close() - - -if __name__ == '__main__': - main() diff --git a/DemoPrograms/Demo_Timer_Periodic.py b/DemoPrograms/Demo_Timer_Periodic.py deleted file mode 100644 index ccd9d1109..000000000 --- a/DemoPrograms/Demo_Timer_Periodic.py +++ /dev/null @@ -1,115 +0,0 @@ -import PySimpleGUI as sg -import time - -""" - Demo Program - Periodic Timer Event - - How to use a thread to generate an event every x seconds - - One method of getting periodic timer event that's more predictable than using window.read(timeout=x) - The problem with using a timeout with window.read is that if any event happens prior to the timer - expiring, the timer event will not happen. The timeout parameter is not designed to provide a "heartbeat" - type of timer but rather to guarantee you will get an event within that amount of time, be it a - user-caused event or a timeout. - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - -timer_running = {} - - -def timer_status_change(timer_id, start=None, stop=None, delete=None): - """ - Encapsulates/manages the timers dictionary - - :param timer_id: ID of timer to change status - :type timer_id: int - :param start: Set to True when timer is started - :type start: bool - :param stop: Set to True when timer is stopped - :type stop: bool - :param delete: Set to True to delete a timer - :type delete bool - """ - global timer_running - - if start: - timer_running[timer_id] = True - if stop: - timer_running[timer_id] = False - if delete: - del timer_running[timer_id] - - -def timer_is_running(timer_id): - """ - - :param timer_id: The timer ID to check - :type timer_id: int - :return: True if the timer is running - :rtype: bool - """ - if timer_running[timer_id]: - return True - return False - - - -def periodic_timer_thread(window, interval, timer_id): - """ - Thread that sends messages to the GUI after some interval of time - - :param window: Window the events will be sent to - :type window: sg.Window - :param interval: How frequently to send an event - :type interval: float - :param timer_id: A timer identifier - :type timer_id: int - """ - - - while True: - time.sleep(interval) # sleep until time to send a timer event - window.write_event_value(('-THREAD-', '-TIMER EVENT-'), timer_id) - if not timer_is_running(timer_id): # If timer has been stopped, delete it and return from thread - timer_status_change(timer_id, delete=True) - return - - -def main(): - layout = [[sg.Text('Window with periodic time events')], - [sg.Text(key='-MESSAGE-')], - [sg.Text('Timer Status:'), sg.Text(key='-TIMER STATUS-')], - [sg.Text('Duration:'), sg.In(s=3, key='-DURATION-'), sg.Button('Start')], - [sg.Text('Timer ID:'), sg.In(s=3, key='-STOP ID-'), sg.Button('Stop'),], - [ sg.Button('Dummy'), sg.Button('Exit')], ] - - window = sg.Window('Blinking LED Window', layout) - - timer_counter = 0 - # --------------------- EVENT LOOP --------------------- - while True: - event, values = window.read() - if event in (sg.WIN_CLOSED, 'Exit'): - break - window['-MESSAGE-'].update(f'{event} {values}') - window['-TIMER STATUS-'].update(f'{timer_running}') - if event == 'Start': - if values['-DURATION-']: - timer_status_change(timer_counter, start=True) - window.start_thread(lambda: periodic_timer_thread(window, float(values['-DURATION-']), timer_counter), ('-THREAD-', '-THREAD ENDED-')) - timer_counter += 1 - else: - window['-MESSAGE-'].update('Please enter a numeric duration') - elif event == 'Stop': - if values['-STOP ID-']: - timer_status_change(int(values['-STOP ID-']), stop=True) - - window.close() - -if __name__ == '__main__': - main() diff --git a/DemoPrograms/Demo_Titlebar_Custom_Async.py b/DemoPrograms/Demo_Titlebar_Custom_Async.py index 496b35ed3..dd19211c6 100644 --- a/DemoPrograms/Demo_Titlebar_Custom_Async.py +++ b/DemoPrograms/Demo_Titlebar_Custom_Async.py @@ -24,11 +24,7 @@ Additionally, if you right click and choose "close" on the minimized window on your taskbar, now the program will exist rather than restoring the window like the other demo does. - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ diff --git a/DemoPrograms/Demo_Titlebar_Custom_Dark_Theme.py b/DemoPrograms/Demo_Titlebar_Custom_Dark_Theme.py index 79d669392..c85e34c9f 100644 --- a/DemoPrograms/Demo_Titlebar_Custom_Dark_Theme.py +++ b/DemoPrograms/Demo_Titlebar_Custom_Dark_Theme.py @@ -13,11 +13,7 @@ This code eventually grew into the internal implementation of the Titlebar element. It's a good example of how user code is just as powerful as internal PySimpleGUI code. - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ diff --git a/DemoPrograms/Demo_Titlebar_Custom_Multiple_Combinations.py b/DemoPrograms/Demo_Titlebar_Custom_Multiple_Combinations.py index c5f68f421..a1fdfc8b7 100644 --- a/DemoPrograms/Demo_Titlebar_Custom_Multiple_Combinations.py +++ b/DemoPrograms/Demo_Titlebar_Custom_Multiple_Combinations.py @@ -20,11 +20,7 @@ ['6 - Button Background & Slider', sg.theme_button_color()[1], sg.theme_slider_color()], ['7 - Slider & Button Text', sg.theme_slider_color(), sg.theme_button_color()[0]], - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ diff --git a/DemoPrograms/Demo_Titlebar_Element.py b/DemoPrograms/Demo_Titlebar_Element.py index e11d6a661..05112e868 100644 --- a/DemoPrograms/Demo_Titlebar_Element.py +++ b/DemoPrograms/Demo_Titlebar_Element.py @@ -6,13 +6,6 @@ 1. set_options - will create a titlebar that every window will have based on theme 2. Titlebar element - Adds custom titlebar to your window 3. use_custom_titlebar parameter - Add to your Window object - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. - """ # sg.set_options(use_custom_titlebar=True) diff --git a/DemoPrograms/Demo_Tooltips.py b/DemoPrograms/Demo_Tooltips.py deleted file mode 100644 index 1e8df8086..000000000 --- a/DemoPrograms/Demo_Tooltips.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env python -""" - Example tooltip operations. - Removal of tooltips feature added in version 5.0.2.11 - You disable a tooltip by using the remove_tooltip method or set the tooltip to the value None - - - Copyright 2024 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - -import PySimpleGUI as sg - -layout = [ [sg.Text('Tooltip Operations')], - [sg.Input(key='-IN-', tooltip='My default tooltip')], - [sg.Text(key='-OUT-')], - [sg.Button('Remove'), sg.B('Add'), sg.B('Set None'), sg.Button('Exit')] ] - -window = sg.Window('Tooltip Test', layout, print_event_values=True) - -while True: - event, values = window.read() - if event == sg.WIN_CLOSED or event == 'Exit': - break - if event == 'Remove': - window['-IN-'].remove_tooltip() - window['-OUT-'].update('Tooltip removed') - elif event == 'Add': - window['-IN-'].set_tooltip(values['-IN-']) - window['-OUT-'].update(f"Added tooltip {values['-IN-']}") - elif event == 'Set None': - window['-IN-'].set_tooltip(None) - window['-OUT-'].update('Tooltip set to None') - -window.close() diff --git a/DemoPrograms/Demo_Touch_Keyboard.py b/DemoPrograms/Demo_Touch_Keyboard.py index 063690936..1426e66bc 100644 --- a/DemoPrograms/Demo_Touch_Keyboard.py +++ b/DemoPrograms/Demo_Touch_Keyboard.py @@ -2,12 +2,6 @@ ''' Example of on-screen keyboard. - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. ''' class keyboard(): diff --git a/DemoPrograms/Demo_Tree_Element.py b/DemoPrograms/Demo_Tree_Element.py index 85532cf6f..4875d7d2b 100644 --- a/DemoPrograms/Demo_Tree_Element.py +++ b/DemoPrograms/Demo_Tree_Element.py @@ -3,19 +3,11 @@ import os import PySimpleGUI as sg -sg.theme('light brown 8') - - """ - Demo program that will display a folder hierarchy with icons for the folders and files. - Note that if you are scanning a large folder then tkinter will eventually complain about too many bitmaps. - This can be fixed easily enough by reusing the images within PySimpleGUI (enhancement request can be opened if you hit this problem) - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + A PySimpleGUI or PySimpleGUIQt demo program that will display a folder heirarchy with icons for the folders and files. + Note that if you are scanning a large folder then tkinter will eventually complain abouit too many bitmaps and crash + Getting events back from clicks on the entries works for PySimpleGUI, but appears to not be implemented in PySimpleGUIQt + If you need tree events using PySimpleGUIQt then post an Issue on the GitHub http://www.PySimpleGUI.com """ # Base64 versions of images of a folder and a file. PNG files (may not work with PySimpleGUI27, swap with GIFs) @@ -39,27 +31,28 @@ def add_files_in_folder(parent, dirname): treedata.Insert(parent, fullname, f, values=[], icon=folder_icon) add_files_in_folder(fullname, fullname) else: - treedata.Insert(parent, fullname, f, values=[os.stat(fullname).st_size], icon=file_icon) + + treedata.Insert(parent, fullname, f, values=[ + os.stat(fullname).st_size], icon=file_icon) + add_files_in_folder('', starting_path) + layout = [[sg.Text('File and folder browser Test')], [sg.Tree(data=treedata, headings=['Size', ], auto_size_columns=True, - select_mode=sg.TABLE_SELECT_MODE_EXTENDED, num_rows=20, col0_width=40, - col0_heading='Files & Folders', key='-TREE-', show_expanded=False, - enable_events=True, - expand_x=True, - expand_y=True, - ),], + enable_events=True), + ], [sg.Button('Ok'), sg.Button('Cancel')]] -window = sg.Window('Tree Element Test', layout, resizable=True, finalize=True) +window = sg.Window('Tree Element Test', layout) + while True: # Event Loop event, values = window.read() diff --git a/DemoPrograms/Demo_Turtle.py b/DemoPrograms/Demo_Turtle.py index 8475852ee..d982a8c05 100644 --- a/DemoPrograms/Demo_Turtle.py +++ b/DemoPrograms/Demo_Turtle.py @@ -9,12 +9,6 @@ Get the tkinter Canvas from the Canvas element Draw on the tkinter Canvas using turtle commands. Results are shown on the canvas immiedately after button press / drawing command - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ diff --git a/DemoPrograms/Demo_Unicode_Characters.py b/DemoPrograms/Demo_Unicode_Characters.py index fb438ad31..3a3af78a3 100644 --- a/DemoPrograms/Demo_Unicode_Characters.py +++ b/DemoPrograms/Demo_Unicode_Characters.py @@ -7,12 +7,6 @@ You can directly copy and paste characters from the site into your strings. Unicode characters make it possible to add simple graphics to your windows by using text. No Base64 required. They're plain chars. They're good for a quick status display / dashboard, for use on buttons (arrows), or as "simple clipart" to name a few uses - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ sg.theme('Light Brown 4') diff --git a/DemoPrograms/Demo_Uno_Card_Game.py b/DemoPrograms/Demo_Uno_Card_Game.py new file mode 100644 index 000000000..874c3b194 --- /dev/null +++ b/DemoPrograms/Demo_Uno_Card_Game.py @@ -0,0 +1,3053 @@ +import os +import sys +import random +import math +import time +import PySimpleGUI as sg + + +#-------------------------------------------------------------------------------# +# Works on Python 3 # +# Uno card game using a GUI interface provided by PySimpleGUI # +# Based on this excellent text based version: # +# http://code.activestate.com/recipes/580811-uno-text-based/ # +# Contains all of the graphics inside the source file as base64 images # +# Cards were obtained from Wikipedia # +# https://en.wikipedia.org/wiki/Uno_(card_game) # +# Up to 4 players... any number can be computer controlled # +# Still needs some work but close enough for fun # +#-------------------------------------------------------------------------------# + +yellow_color = '#FFAA00' +blue_color = '#5555FF' +red_color = '#FF5555' +green_color = '#55AA55' + + + +wildblue = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAABQUFCQkJDQ0NERERFRUVGRkZHR0dICAgJSUlKysrMTExNTU1OTk5PT09QUFBRUVFSUlJTU1NUVFRVVVVWlpaXV1dYWFhZWVlaWlpbm5ucXFxdXV1eXl5fX19R13JWlvZWVrcS13gU07kVE3jUE/sW07gU1DtU1frU1ftVFDuUVzsXlnvUlL3UlL5VVX+U1rwXFz1Wlr9TXTDU2ffVGvcVW3aVH3AWnXWXHbWXXTYXnnVUmPjUWLlUmTiVmHlXWLjak7PbE/PZV/VY13aZF3aal/Zal/dYFHmY13tbV7obl/vYVfzY1jzZ1rxalzwaWPaYHHaYX3UZH/Ud2bCdmbEc2TOemnJcmPQeGPcaGHoZWL6amH1a2f5amr/bm7/cGflcmLudmXtc2rjdWzieW/hemntfWztfHLhcnL/e3v/W4TAYorBZo7CaITUbIjUbJLEcY3VdJjHepzJd5LWfJbXf6HMgGq7hWTdiW/Xi2vejW/fiHbKjXvKgG/tgnLuhnfvg3nhi33wk3Xglnnhl3zimX/kgYGBhYWFiYmJjIyMkJCQlZWVmZmZnZ2doaGhoaOlpaWloqWqqampra2tsbGxtbW1urq6vLy8gZnZhp7alYTNmIjPmorQm4zRnY/Un5HVi4LjhIT/jYHxlY3om4HlnIPmnofokoj0lo31k5P/mZP4mJj/haXOjaLdi6nRkazUmrLYlqnhoJLWopXYpJfaoZjYpprcpJzYp5zdoo7qpJLspZXtoJvyqJrwq5/zoLbdq6LjrqbooaH/pKT/q6L1rab3qqr/r6n5rq7/oLDlp7XpprrgqrzisKnqs63vtK/xsa37tbHzt7T3srL+ubf6urr+scHmucXrvsjv3Zi53py8wcHBxcXFysrKzc3N0dHR1dXV2NjY3d3dw8P/wcrxycn/y9D20NL60dH/1dX+3Nz+3unt4eHh5eXl6enp7e3t5eX+5+306eTz6ef46en+7O/57Oz/8fHx9fX18vL+9PT++fn5+Pj+/v7+AAAAP81AhwAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABapSURBVHhe3Z15YB3HXcff02mrPmRZdnxIogVaDkMEjhPSug6Uoy03xPQAQwPldJJSk0ALuNBCaSzbcozxIZUAaQMhHA1JablCcNOkdh2gARfVdsCWLKk5cJD0FioqUWXN7zfz293Z672Z2d97+zafP7y23r7VfLyz353dnZ0pXa2B21RQoWpRw4o21lxQ2apQ1Yq20pxQGROpYkXfbnKosGFSrehLBYAKrJJiRV8oBlRmhUQrWrswULEDEqxo1UJBRfeIWdFqRYNKT0StaKXiQeWXRKxolSJCBoKwFa1QTMgBCVnRx0WFLADVij4sLKQBKFb0WYEhEdWKPikyZKJY0Qdxpi+NjjQVo5emqGgxyMW3oh9HmB7obis1Ia2r+yepiGHIpprVyBraSFPSfZyKqUI2ZEU/VJnroa83Ld0zVFQFqSOt6Ecqx5qy6oVpO0yFDRA6qVaH6ItNzgEqboDwEVb0A4WCSCVoVbE6Tt+pTrm9c1nu9fQIFdkn1Wqunb6SRtuagaMTFbnusbX0w3xojUZGqlUvfSOZl+2boPWIyVX0SS6soVL4pFhdpPWTaOtLOv1tpk9z4QQVwoOs6F8+6buqc3hRruKMnXn0j3/r3//6iSeviH/nqdUtSqCQaDVDa8doO7iEnztjp+76/kHkdfjHLf+JP8yzEsaahUlW+2nlKBtEPDhnflYYIa+UizH48WVaKQ/6sVwqSVbJmdY5ip85n/huaYK8ipaDuLdyTMJ4FQQr+qtPJ60cogd3lHNKcRocvJaWg7vhs6O0Yg60iWIrJFjN0bohBuADZ+xnyELyFbQEIDISv9YgYgdW3GqSVlUoYyvS+RNSIN5ISwSPrFZa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' +wildgreen = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAABQUFCQkJDQ0NERERFRUVGRkZHR0dICAgJSUlKysrMTExNTU1OTk5PT09QUFBRUVFSUlJTU1NUVFRVVVVWlpaXV1dYWFhZWVlaWlpbm5ucXFxdXV1eXl5fX19Ap0AC5UADp8LD5kUCpwYCZ4cFZoAGpcUCp4gDpksEZImEZgzAKMABKQNAKoABKkABasEBqwGCqYPDqkACqwKC6YWCKAZFaYKEqoCG6EAHKALGaoAHKwKFKQUEa8QGKMQH6YRHa8RE7ASGbAUGrIaE6chFackHaguJ5oNL5sANJYRIKcMIa0KLKoAKa8PIqcTJqcXK6gcLrATK7IZMaoAOaQYMbEVN7IaO7MeIaEiIaM6IaoyJao2La4+I7UjKbcpLLgsMakgN6smOqwpPa0sMroyNrs2O707K6hBL6RQNqNINqZWOKdYPKpbP6tdNLBETbIZR6olRKouSaEoQa8wRLcnSLgsRLAzRbE1TrU3SrM6VKY1Wac5XKs+VLQgWrcnX7gtUbs2VL06aaoAYroyab08Sp9yQq1fQLZPQb9BS7tXX6xCUbdDVLlHV7tLVb9fXL5RSrBlUbRqVbdtXbtyYq5FZ7JMabNPbb9Ca7VSbrhXcrhNYL10db1hRcBFTcNNVMVUWMdYXchdWsNiYMJJb8FFYsJZc8JLd8VSesdYfMhbZsZgY8pja81raMF5cctkecFofcVvcsd/cM9wddB1fNJ8c5+YeMuCrKlxgMpihM1sgcl1gsx4hc99idB1jdN9gYGBhYWFiYmJjIyMkJCQlZWVmZmZnZ2doaGhpaWlqampra2tsbGxtbW1urq6vLy8gNCFgtWCh9GBhdOIitSFiNeIi9iLjNiMkdaGk9iLk9qTl9qSmNyYo+CjquKqsuWyuOe4vOi8wcHBxcXFysrKzc3N0dHR1dXV2NjY3d3dwurCzevHy+3L0e/R1Oza3u/S1vDW2/Lb3vPe4eHh5eXl6enp7e3t5PXk6ffp7Pjs8fHx9fX19Pv0+fn5+fz5/v7+AAAAeLMFJAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABaXSURBVHhe3Z15fBznWcd3ddqqbcmyfEviKlfJQkCBQIoB1dz3faXCHMGUlFLuI9yEpuXoQSENxbH9CUc46pCkNgU3DpJtOZZlS7HjopI4dmtLlmQKZCXtupaqvuZ53nlm5p1r931nnt3ZyfcPr6yd2X2/et/5zTsz78ybu10F0VBQoapRxYo+rLGgslWgohV9SmNCZQylghWt3eBQYb1EWtFKGYAKrBJhRStkAyqzQqgVLZ0ZqNguIVa0aKagotsErGixrEGlJ/xWtFD2oPJb+KxokSxCBhKvFS2QTcgB8VjR21mFLADVit7MLKQBKFb0XoYhEdWK3skyZKJY0RtB5q9NTjQUk9fmqGgByMWxol/7mO/vask1IM2dfbNURC9kU8lqYiN9SEPSdZaKqUI2ZEW/VCl10+oNS9ciFVXB0rGs6Fcq4w3Z9Ly0nKbCukidSKtTtGKDc4KK6yJ9pBX9QiEjUiFaFazO0jqVybe2r0m9nY5RkR0irUqttEoULRv7z8yUrWXHN9Ev06HZHxmRVj20RjivGZ6h5YjZDfROKmykUjhEWF2l5cNo6Q3b/e2kd1PhHBXChqzofw7RVdU+umItUpy68ORf/eW//ez9b9k3VYT/p6nVZRXJJdRqkZYO0HJyFd8vTj3z8HcWkM+T/74dtdJshIFuYZjVcVrYzzYZD8ULPyVdkNdaL/eC1nVaKA36ZLEVwqzCM619Et8rfvi7LBPks+lV1laKSRhsgmBFPzq008IeurGiis8oTk5VAVNCnKEFU6DFKrdLiFWJlvXQD28Up36SJCw+h16BfRGr1YnAhhW0mqVFFfLYiyy+mxSIz6JX5CF4v5kWToFrsuAK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' +wildred = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAABQUFCQkJDQ0NERERFRUVGRkZHR0dICAgJSUlKysrMTExNTU1OTk5PT09QUFBRUVFSUlJTU1NUVFRVVVVWlpaXV1dYWFhZWVlaWlpbm5ucXFxdXV1eXl5fX19tEx6tEx8y19C3ltJ3lRx3VR0w3RNwH1U32dT2m1V3GtU1nVa1nZc1Xle2HFYxHF32Gx01H1h1H9k415D5V5E4FxK5FpJ7VpJ4lBd5lBZ7VFY7FJc7FxR9lFS91dT9Vdf81tT+VJT/VRU+llS/VhS/l1T+Fpf/1tb/l1e71Ri7ltr8lZh8lpl8F1r+Fpg42NS4mRS5WJR4W5b/mFT/mNU/mdX/mpZ/mxa/m9d/nZU/nJf/ntZ4mBm5WN87WR17Wd47Wt8/2Ji/2ho/21t/nVn/nhl/ntp/3Jy/nZ2/3t73WyC2myP3mqK3m6O3nCP3HCT3HKU3XWW3nqZ6m2B7nKC4HSS4niU432Y8HuJq7F7wIRbwYtjxJJrx5h0yZ161IRo1Ihs1Y1x1pJ315Z8zKF//oBe5YFn5YNq94Nk/oNj/oZm/ohp/ops/oxv/oFw/oRz/o9z/o1+/pF1/pJ4/pV8gYGBhYWFiYmJjIyMkJCQlZWVmZmZnZ2dsbOBoaGhpaWlqampra2tsbGxtbW1urq6vLy82ZmB2p6GzqWF0amL3aKN1KyR2LKa3bag5YOb8oOP/4KC/4yM9YyV/pqE/pyH/5CQ/5WV/puT/5ub/p2d44Wg5Ymi6o6h6ZGm7ZWl7Jiq8Zyp4amW/qCM/qOS/qWV/qaY/qmc5bCg4Lqm4ryq6bWn9KGr/qOj/q2j+Kit+qyv/6mp/62t+Kyy/rGq/rSv+rG0/rKy/ra1/rm5/76+5sGx68W578i+wcHBxcXFysrKzc3N0dHR1dXV2NjY3d3d8crB/8LC/8XF/8vL9tDL/dTT/9nZ/tzc7ene/uTd4eHh5eXl6enp7e3t9O3n/+Pj/ubm+e/s/ujo/+3t8fHx9fX1/vHx//X1+fn5//n5/v7+AAAA1zju8QAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABZTSURBVHhe3Z17YBzHWcDv9LRV2ZZl2ZatB7QQnKQGYmhLqXnkgPJoSuMChfJoEwqkLaWFAgGStJS2vAqFQCvZloJfkUpCGkh4BBfSECgJFNyEUvAztmRJcRzFIOtQOOthj/t9s9++d+9mZr+73c3vD691t7uan2bmm9nd2ZnC1RqITEGJqkUNKzpZtqC0VaGqFZ0lm1AaI6liRUdnHEqsn1grOigHUIK9xFjRAfmA0uwh0or2zg2UbJcIK9o1V1DSbUJWtFveoNQTQSvaKX9Q+i0CVrRLHiEDid+Kdsgn5ID4rOjrvEIWgNeKvswtpAF4rOi7HEMiXiv6Js+QiceKvggzc2Z8LFOMn5mmpIUgF8eKPg4wM9jVUsggzesGpiiJfsimmtXYejpJJuk6RMn0QjZkRR96me+mwzNL1xwl1YOlY1nRR14OZrLo+WnZR4l1kTqxVqN0YMbZQ8l1kT7Sij7wkBOpCK0qVofomOoUW9tXpV5O91OSHWKt5lvpkDha1g8emCxb+x7cQB+mQ3MwZMRa9dAR0bxsaJL2I6bW0jepsJ5S4RBjdZr2j6KlP6r566NvU+FeSoQNWdFPDvFZ1T6yRPuIlQvPHfvMu9/3/s9W8Kc0tbpkejxEWs3R3iFa9l629rh04pF3lIDX4j9vkF5pFsJQtzDKajftHKTXCg8rx9+FMsCNtP1F0DpLO6XBgEyXhyir6JjWPi6/rBz+bnIplV5H29JnY49qCOEiCFb0X4d22tlHt8yoSx6n0jfTFgohZNYB2jEFWmSyPURYzdO+PgblV8c8Tj4gsyIPaxChihW2mqJdPRRlL3LBrk8WMlQQ74evm2nnFDiDyfNSCBXA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' +wildyellow = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAABQUFCQkJDQ0NERERFRUVGRkZHR0dICAgJSUlKysrMTExNTU1OTk5PT09QUFBRUVFSUlJTU1NUVFRVVVVWlpaXV1dYWFhZWVlaWlpbm5ucXFxdXV1eXl5fX1915U1xa4Ny6oAw68SwrEVwLMe364N3K8Q1rMc1rQf2rAT2LEY2rMdz6Q3wLYnwLgtyLgtwbozw7062ag31LUj1Lgr1Loy1Lw41b8/5pgW5pwW5ZoZ554e6pUW7J8R858L5p4i4qEA56IA5asG4KwK6KIA6aQA66oD5aYd4K8Q47AU9KYA9aEI9KwI+qYD+KYF/KYD+6YI/qYK/qYO/qoA/6wJ86YW8qMa/qYR/qcX/aQa/q4Q/qgc/7AU/7Md6aEl76ck7agu7aoy7ao27a4+5bUi8Kch/qEo/qkh/qsm/qwp/q0s/qUx/qc2/q8w/qs+/7Uj/7cp/7gr/rAz/rE1/rM6/7oz/749xL9C3qNI3qVK3qRQ3qZW3qdY4Kpb4Ktd4q1f7rBE/qxC/q5F/q9I8LZP/rdD/rJN/rlH/rtL8rtX9L9f/rVS/rhX/r5R47Bl5bRq57dt6bty6710/qpp/qlx/qt2/r1hxcBEx8JKycVSzMdZ1sFH18RO2cZV2shczsphycFz0sxq3Mlg3sxo1c9z2NJ6/8BD/8NM/8VU/sJZ4c9x7cF55dN998Ni/sZg/sFo/sVv/8pj/81r8cd//sl1/89w/sx4/s99/9By/9J7gYGBhYWFiYmJjIyMkJCQlZWVmZmZnZ2doaGhpaWlqampra2tsbGxtbW1urq6vLy83dWC4NeJ4tiO6daF5tyW9MuC+NCF/tGB/9WD/tSG+tOI/9eI/tiM/9uU/92c696g/9+g7+Cm8eKq/+Cl/+Kr9ua1/+Sx+ue6/ui8wcHBxcXFysrKzc3N0dHR1dXV2NjY3d3d7fHX/urC/+7N/+/R//DV/vLa4eHh5eXl6enp7e3t9PTg/fXj//fo/vjs8fHx9fX1//ry+fn5//z4/v7+AAAAA7tHUwAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABaESURBVHhe3Z0LfBzHXcfv9LRV2ZJl2bGtB7TgpAFaCDblDa1NDJQ3R3gUAjQFysM8CqWFpjQ8WvNooMFASAslNVAIBIihxaaSZSuWH1Iopq6DapM0qWtJlkRKVtYRIlkZ9/+f/d/u7OtuZvZ/t7f5fj7JSbq9vfl6Z387uzs7U7hRA9FUUKFqUcOKVtZcUNmqUNWK1tKcUBljqWJFn25yqLBBEq3oQzmACqySYEUfyAdUZoVYK1o6N1CxfWKsaNFcQUWvELGixfIGlZ4IW9FC+YPK7xKyokXyCBlIgla0QD4hByRgRW/nFbIAVCt6M7eQBqBY0Xs5hkRUK3onz5CJYkVvRFmcmZpsKqZmFqhoEcjFs6I/h1gc7m0rNCGtPUPzVMQgZFPNanITraQp6T1DxVQhG7KiP6os99HHm5beJSqqgqvjWtGfVE43ZdUL0naSCusjdRKtxumDTc4YFddH+kgr+oNCTqRitKpYnaHPVKfY3rku83o6QUX2SLRabqePJNG2afjUXNld9vRm+mM2tIYjI9Gqnz4Rz0tG5mg5Yn4jvZMJm6gUHglWV2j5ONoG4w5/A/RuJpylQlQgK/rNI3lTdZ5YdRdxps8/8u7f/ONfufsdB6cd+D1LrV63SD6xVku0dIS242v4vjN95MD3lZBvkf9/J2plWQkjzcI4q2O0cJhtMh6c8z8tXRTuAq2rtFAWDMliK8RZxWda5xS+53z4+0kF+DZ6lVsrwySMVkGwoh89OmnhAH24oZwjilPpO+gVmBbiFC2YAW1uuX1irJZp2QDD8IYz/VMk4fLt9AocTPhYg4jsWFGreVpUoYitSOf3SYHw6h9wD7zfSgtnwIws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' + + +plusfour = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAAwQKBwgHCgQDCAcJDAgACwsLBwgZDxEPFggGGxMAFBQUFxQaFxgZGBUXHBwcDQ0qDw8yEQ8uFxkhExQ8JQsNLw8SKBgEIB8eNxMTOCUAJCQkKCYnKScoLCwsMigpMS8yMTExODU2Ojo6FxVEHB5XICBfPz5AJiZvJiZ0PkA+RRcZVBweXx8gQSsASjIBWTsAXyAgZyEidycnQEA+aUcAcksAe1EBZFk4Q0NDSEdIS0tLT09QT1FPUE5RUVBPVVVVVlZYW1tbYF5hY2NjaGZoa2trc3NzeHd1ent6LSyHMC2SMTSaOjipOzuzPkDAQD+8VliDfn6PQ0LISEjcTU3rT1T4UE7sVFX+XWH+YF78aWnkZGT9Z2n7a2v+d3f9TqtQValUXq5gXrBgYK1eY65kaLNobrZwdrp2fMF7gSsrjjAyky8ymTMyqDg3uDw8tj1AhFcAmGUBvEA9p24ArXQBt3oAgm1AyEA/xkJD10dH5ExM709Q9U5S91JO/lRU/Wdn/25w/HZ1gX/+v4EAgIJ/woMB0Y0A2pIB6poA7qMA/qkA/q4R/bIY/rYl/ro0/YB9/r5B/cJK/cZY/stl/s5y/tBr/dF5goKCh4iGi4uLjIyQkI+Rk5OTl5iXmZeWmJaZm5ubnZ+ggr+CpoaGoJ+eoaKeoqKiq6urr7CvsK+wtLS0ura7u7u7hIT+iYf+ion8lpX9oZ/+vb7Bp6j8sq//tbP7ubX9vLv+icSJj8aRmMuYmNCYoM+gp9OnvsC+sNetu9y7vd/E0JeX/YmJ/ZGP/Zua/aOi/q2w/bu7wb/Bwd+//NeH/duV/eGn/ea3w8PDx8nHycnGysrKw97C0c/O09PT19jW29nX3NzbyMn90tP819j729v9xuLG1+rX3+Hg/cTF/djY4N/74PDf/evG/u/R/fLa5OTk5Ovk6Ofo6Onn6urq5eT+5uj76Of76+v+6PPn7fbw7vD+/eno8e/3/PXm8/Pz8vP99Pn09vn5/PTz+vb6+/r1/v7+AAAADa/O5QAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABkUSURBVHhe7Z1/kCTlWceHutBh6ehQBak76MokaxM1IUELJDqMWsOymc2eIf4gKEYDOZXLJQokaFBAsxopA7kAGrCYTDKlq8aZchwiBiNHDIpSKprjVoeMGfDuvLPwOpdBOT22uSM7Z3e/z/t29/u+T/fbPT2/tu5zf9xM9zs773ee98fzPu+Pzp3ajESq6g2mmB5kUgauCj481UBWBRBVNnxs6rEhw2GkquATMwJkOohE1czYiSLaS1DVgaQzRRcyT+FVzZyhCJy5OFWQaAYBAYSwKkgxk4AEj5AquD+jgAiXoCq4O7OADIeAKrg3w4CQoCq4M9OAFF8VXJ9xQAxVZcHlGadP1FBVcHXmIWpAFVwTsZrLiwvlqWJhcamJj/w8OURVFy5xWMv53JSiLyHCvMEkUQVXwvTK8BemlJJcF1Mlvb2qwaenlzpkNYRFVcH7IHYJPjnVFGVDDFyVXYTPTTnzElkdogreBZgVUXJZmKoKfGYGWIAsB0BUteETM0ELMu3TdVXBax87eS9ltCk6XBkbeh+y7SNVVYf0CWjARwcNuDBGavDVPlJVBUiujgGfTPPZocnDV/vIVKWoVavw0UETLoyVJnw5w1El+IBLkFgd/9eagKlyuUX4coaVEyOAJiRWh3kuEzFVbh6+3ScnVqvE/p9vqnm4MmYEw4iqepBUHdYIteDCuBGi6KKqLiRVRocPTsxUuTX4foaoqgNJlWGmmphL0oYMMIZXpbNSnbyZyYgRqKrC5yboPWavyjfV5EYv2atiplqDCxMgc1Ua85gnONDMXNUyfCpxdcySrFX5pppk9CZrVVNhqsSqGhYgd8Z9U5Wd1hCSWmNv4pOqYkEBuTO0BHc9N4t5Tol9rmHJVpXG5ofc4DVz3WdcVQVuEh2bxVbMVAvuu01iK2YqMiTbJLYKm2qT2IoFQWD0vDlsxWa9Fsn7qbfVqj0g/4KQKwb5Q4GwvQUXpt5WLMAswlQxU9EJlKm3lYIqwVSbwlYs5MvmujaBrcrwdtBnQdFNYCtmKj8qP/u2KsG7gKk2ga1YDHjZe+sx9bZ61AbgmtNZUbzZVWYqO68x2NRc13vrphsTiqoYiG/BwmURjHEq67Qql9OqOE6rGpLTqlxOq+KYYlWrPSCcxyW4GsJfPO69HV6Vput5Bz22Q0+qKgnZ+IF5s1ypNtrd4Joru10r0xGQjFGqGs4P1IvLq2EtHP32EraebSptpRWjFqgHsFflxXrabKWZSw0lQZQ12XL0qbJVsY7sDojEEqdqp8ZWWrkhrD5SRVhpPx22yi+yfjAVPc5cU2CrwnIGW5LrIXON1FYdIGLtrVFN1DbgrAVljVJVPMXhCl6IoKwJqtIqGZkJCMiamKpCPXWTh9Fhsiakqix8bxYwa01Clb40qq2gq/AN41elLWde9HxgmdHYVS2Oyk4eFvHix6yqnG2zJ0K6xrGqMoW1y9njlcExqjKE7RujwJuTGZuqPNsQM2Lcqc5xqRplwxfGdaXHo6qQZjSYFmdUMhZVbIHnWGiORVVh3Cc65cegamlsNYpSG7kqA+mijlrdzr/+C4wqMbq9iHAgTnfUqipyQ/1bbcGM33GrGWallcbS2khVIYbqfdrUy8v1Rhz1SumsVMMwc5SqyvIMWYa+2FEqWnZ/NS/+7vEsjVAV0p73coZ6tMKu6yxSpU5jZKo0xOtrnzufxG+3y/6UmTK9UanKI53UN8rGf8BLNapKM34cI1JlYmPDli7uko+kpkWsNsIYxW7NXG4Ba7j6C/MJXcKauP88HoWdtclV4ebo6aHy9PL/vSjy8jfhrseiv55cnRGo0iKq95oWGGbt/+JD110r8N7rH34OEjj0iynawBGoMqKK2ILv6r74yPWgQ+C6R1+GRINWPo3Dn7kqI7LAaKxn3v8QSJBx3bOQyqlWaYZmWauKFtXU6GkKJ1FDeTwCxrLK0hOW4shYlRHtCS3moc19OVrUtde9QNJ1CmyfWhKyVRVtqcFgmwG//COQe4zrXyTp2ml6q4z7qxhLDboarA9/QdL2hXgIVNWocZORpao4Sw2q9Jd/9ich9xgPk3plm6UUvVWmquIs5UZ/4MXDkHmUvyTp+ikDOdmpirXUYK0AO7T+M6atuPa6fycJa9tSTbHamXm38ZYaNHTI47M/DbnHoNXKTDRqYWQ2Eom3lDuogESPQuZRHibpBmcVN+BVItYyUqUpeABW2STt+stx1eo9UK3aacZWDs2MVAl/RsJaHnrU/46tVvtJwrKWql0f1LNRpTQSbNA8PguZR7mepOsbBfIiKdlEY4QTuOxOq17lWDaLUPWjCuA1V79r+/YfJZ9Y1ObJC556ox3ZiixkoQqqC8NulwtGYKUKpQLNJF4Ar7nqwnPPgdQRaLpRivKkihmoynNteqes6cutnncGRIAuq/ogQeRd553xumrbso5+3bL6favvvDp6tG8578J0amXNiCj1heFVaZyDvJYzqrLRQy0PvRXWrv/49i2FPyBJYrHrekQLlUFEOhwssRu5BWEc4GGYUBd+E1Rw/MQPJVldYtfkZ9u62MPPHnA9yqpekWetS0/0eAFU8Hznqz4d75742EYeM1ZvaFVs6ymhZ5pI1qo0SPNFUMHxw69GwvIYZVqiBb4wrCo6CqSsovFjUwcb/hnI4Ph2f2+4GgvY1NigMawq7g9blxeRqmHn6S5Hebt+9TlCpxdD2ZDXX3dtwnCq+KBCVwu2t+uHDz1F+aM5qIDPvRd0hHln6CTDYwcPPMFz4MDBY3DbQy9gJdYcTpXg0DS+xW8Rv3noyY/9+grlElrAHgEZHG8KOP0nntiz8+d2iLx/zwFI4dAVPRrKluFUCUWgaDLf/fCTvqSVldvPL5LLL8qr1bvPWWCtzIFdPwsyBHb+LaRxt5Bj8Xcnv8OoEkff/u93KKhpZeVDr/0Mub5fHoe5mu2zPvEEqslhJyuEJo0WCKwOpUp0qOs6zdvh3wA5wI3Uroi//qYCtfsTN4AAOU9AsrbBjt7hWRxKlThQLNEY+/GwpVZWLs1DtfkLkMFxXhnuH4wWtWMXSTao4/PF88OokgxTWbP0JIih3L5t4SXvxkufBxkcZzhF1xvM74LcY+zx/oxbrXB/aQhV4vm/jl8LpeIwb6pfyX2O3PkfUMFxlQ4TQAcg8yhfIums0pvJCxE3u6lVSTyBCnUsngIxjEtfD9UGK4C0R/0ryDwK1Kt2Ho1ouMeup1Ul+aO2CRNor/AFcOV8Wm3kjsU19MyF9ZhateMGaAM/qwu9CsU9NimlKtkEYNuApv7wx0AM5aNbKifJLZDB8U568nlsAdxzwkvXL2OeGdnAm1KVbHxdo9EWrq9aWbmZVpvnQAbHG2l7+jhkHuVxks7KoyvZ3MYipSpp7AeapQ2xWl1E3es/Bxkc59EedQ9kHgVcpp78KS8u3rmS6VQJn3LoFUvk9zsuVKvc5d6Nwcn3gIwwP/Lqt5P7B6Pb9fft2HWQJFw2ZDnw8M5NSqUKfLowbR1+P6ELvpH+sohjsf2MfyL3/zmusXjsf0lCA69W3oEvqVRJ258qXeQjFMC3al8ld+T++jVvhAJ94kuQeRRo1zsaOgFEMptGleTpKk6zVKITaGK7voXcGHz+2ndftf3C88JceN4ZMEw7FudY7KQFkE6uiJAjhtKokg7FLZ0uWecL4G1z4Mnv/6ntZ8CfCNMiMx8Hd0LuMXate+kGBT4E6UP2eqdQJZ9V79LKcxzEMD64hfyy1o+dmy83e8LcTZ1GFON7K5LO1iTuGgHOY0yuyj+oN0SFtt7/CGIov/YW0mX3r8wvCt/m0C9B1T+pWq1WQ3GEEDWSx+SqEAdMvxzUciOrldu2esbt/YDxOShAYb5Gi+6JuAK4A9ylBTwcBaf3J1aVl3fqLQ3UHgYxjJvmvKG4qbXAa+Ko07ieagHsFthJXTx9yGRiVYipKjoUwH8AMYwbPXeoocur42Dw/TTWEetYPEPSNfOoY0G3WydWhbQ+rFni2/U73uJWG7tEg5wC+hVg/dgCCAW4hhdAenp6UlXSvspt18HfEByL2+fcatNEx0PdV0GPegzyjvJ+km797XzAmGGn3VmLDGtq2u+TF4K/fqNXbeq5r5H7Hs/vfeB+yvd9K1SrWH/9y16yk18tLGKq2KNmEqrCOopyDorH34MYxlvdatNfMPusnzrywD27fc42YNFcnGOxAxyLFr4UnB3fn1AVMm/ZKUDJPM4PGFfm3JXFHYNtGNnYC3IIt26BAhgXXNrxAdKun6ig65H9BwolU+U/KyRM8zUgV4jD3OG5Ik22Fnf9AZADfG/uC+TG43GqIA7z0rwf5eXwTwRNpgpzlVmzdAjEMC71qtUCbb3Xf/eTIAf4LhoBU3Us+qi/ztqKpKqQ1rm/ME9+v1eEajVXcO7YBv19nwYxlLsu+B5y41hcb7UThsFNFh/mCTzTL5EqbmKRwarN8d8GMZSbiS/MPGIQw7hlDnrUeH8d3KUii13zBI5mSqRKSAy06B3BXbo096fO5Voe5i/CLYXD2zRoO2PbdahWNvrTBh+EkUQVuv5mkVYbwV26KOdGogsFqHb3gxjKXRdfQdp15QJYDy7zDxE8bSqJKsz9sgu02vDt+h3nux0cm0A7AmIYd54NE0DH4gogneIp60i7zs7kdkmiCvPk/HWkIIZx22vdfqxKJ9CEAvgRr4A6HITMo9C5EIMd8sQROD04kSp0AFqn1UZo12+eu9K5XKKPGeEL4O7LaI+qGt5c05FpKzu0+TOBKsw/HczTvAlxmJvmvs12CiiNX/8OiKHcvXXhG+TOH0LmUcBdWsLcpfCRTwlUIQXacVSg2ggRi5U7LnJ8rKYOBfT5e0EN5U7t98gdVX+9X/IfsBomfKCmuirs7/m72YRAoGOsXKFRoY6HUK0uK8BQU7kAYhssuGd4qqvCxrJOtYFcC46FY6xLcvpZ4D6sC9VqaxHaTtWIxSo2b8o9AFldFfysIqxZEvx1l1+coxXy+ftADIP1qJB3HBjGYMNg/gHIyqqwFnXQotVG8NcJv7AFvmMfaGHcQnvUZyDvKBCHsUowQcERbgAdlFWxlRQ8S3R8LKlWDh/9YB6rVhe8Bu6o+utrek2qKtRXuSirwgagdhH6sXWhXfe4/fzyUXKfr1Yfn4MCGO9YfJ0krMuXBFrCGl9VVRoyXnT8dRoIlFarldupo7UOYhi3nPnH5M6BOFWPQWNRoqusw8ADdAKoqsI85UFD+2vyQojDEC6lrfdXQAzjMuqCfRkyjwLtuq1L4zCSkyRVVWFDtUFVh99PXq1WLirCDvVPgRjKJy4Gl0N52qpH48NhJEfDqqrCPFvbLMMwWF6tVrZcCa0yN7TffSuJv8fOmzqeLbhLFem8qezBpIqq0Ha9Q3eVCuFNwofo/IXYrtO2U3U5wkCHOEIY2eN+FVWh8foqneDBCuA2uP8giKHc/d1vJnlULoAtqX8tfd65oirUXy+WoFpJ3CWXnElubwQjmy4f3wpLJtZjh8FQAN8hZtbxd6XHzyiqQsOl2iKcBSCvVjflPktuP81Xq9/aAgu2YmeD6TIzk8Y4gpAn2PEoqpIVaJcOm/aT91aX0MojtOu30B41ThUd2/cMMHsQ5Hn7aqpky5Y8yqy3l9eri+iqF8Ffv4D2qDH16meg/Dn+uhg3kZc/VVVoH+wP+6WuBYlbOBzh/fVP5N5B7ji+rcy1eB/8TyuV60HAiwDY037VVGGNRTOwS07mW/z8FohoPM03Fh/e9ifkjmOsiDHjHiaqa4pTZ+hJzmqqhFRAJTjqOvQkb65fvQSK7gbfru+++A2+S3fibz4gM9cNux57HOqUQ0ucN4WjRSWoqcIaCzO4+nXj+OFDT/m7DRz+7vWw7OoIH4fZfeZ3BD55UrbX4JkDB4Ne36o4IYiVP0VVWMiia6C9s0eLRvqf5wvgnUm3olt0VYYPPbJXgpIqrLFYM5BpYqABBXTjeRDD+IjatlWfDl3uyRBHVT5KqrActPJo4+jSX6CtNzcV5zqBqLcixTbpTjtG1IPplVRBQybQzkduVLd0mADa4AOBjqor/IYgnn4lz5uqCgKkKKnCZozscmRBatBIteCv7757a5617PF0yvpqsOVwQJwKQEkVapB2TpfuNyWwc7KEAuhWrG1YCeCx6wb9eRj+UexSlFTBC5GjnzlbK9ZafRmWladxLr4FdLjrbWfqP1hfg7QoVq+1nNfoanhGn4tq8qioQoeMDp3LDbQvpBsshDiMxy9dsHUO0kWgGUapLRQH2UgxiIoqdIrHxWo3YHc8T0GHciMEAgl33XrLhwm/TD6wqJvL5JXPamtNLOJiUIlDRVV0V4ti0AVbgmPBs4+ka6Ozo2FgaWMEKqrQsG0kbQ0KoOBY8Nx3hCRcRqfnQwSntRFUVCV0boAaHUDv5YfBPA+QMa5tCq2CjG508+ehokqtXPCUqU8s+Os8XyHpbGx2NEQ/6hllFBVVaNAiCsuk8Xc+vMlzz9MkoVq1inKUGCqqlEo7D1vnKMyb8tz3XyRhicauo8BHH0FUVKmUdoEqLYBIu+5zP0k3kG8/CaNkKTVV8H8ienQCTZw35aAFsIHvPmKoWUpJFWxdSQabAIqvVtCuL/KHmogoWkpJFbYiIZI2Hb4I0SWeB0m6wTw6RUZRtdToVLEe9UhMY3EfTJl08tHj6gSWGpmq/utojyqGl0Lc+wpJNqhiB09T1C01MlWBgy72RRnrfqhUzgA0amTgkMBSI1NFNx46xWtjLyrrngepqEGnEO1YJLHUyFS9IXA89sa+B2Qtxr2f2rvPn+Ro0mGLlH4iS41MVXgab+OVdRlw16MedVpvT8X3CzIaVc0zE4b7evgqdddBhMwqMxpVjaRBTHa4pYT4QaLAaFQlPQC/Z+BDq9jhvAQFVSn8wFYu0Tm1vfl5IR9APy7wIkVFVQpjmegOAQktAz0GqxsTIkNQUZViLNzStLqF138fu99dys9jopqJ2wmCiiqVgTdHv17QzUoVHuKCU6+W8yYa/o2MpUehoioyHojRrpgKvUy+WKxhBVzyjGdVVFRp8CIZ/V4XHo0UQddCWxXhAc8JUFGFzomMECuZ48ehpCphl5oBDTx4r4KSKnQRyYjoy54GnwQlVfgyppHQHM5QDmqqFGJamdGXL7hKhJqqqGFCxjTTeRNhFFWl6IhTsZbK7RNQVIUc1ZExvWFbCYqiKuxUgSyx0ow55KiqQtdcZIW9PIQvwaOsSh9tGawP3ZoHUVaFr3zMgGbScEsM6qpGVwYb4e17GZBAFbZTdzis5UzLHiGBqlHIWsuqLQ+TRFXWsuzVwIEAmZJIVaayeksjKHpAMlWZybJbEaPCZQhqpB9kJVSViwzyK9JvlCN7XBZxSt3eJ1Xl+E7DdcdWPTbIMglVOfR5A/F0qypd00RU5XLoMU9R2O0lxaHThFTl9OUkYXTnT6wuJvAfJqXKoSx8Uk53tZLUIZqgqlyuUOeXmIfprTWWzDTDi4mqctCLy02uLFqdZn15sVgYooudtCoPvWCaxaJpzs8XhtHiordcWNex5r3lCI+Y83C1FZqRzEBVhqiEU8OnPrCNOaFtw9OlCj3vJEB4mpidETXFqk7binDaViFO22pITtuKMAu2ys27sPF22XtLYF2z9wgADeaV/bUgNlzouKqnTJWHzGNicX5yol7EEkn30NtZUcVsQg5KjVDl7g2cEVUsHA6nem8OW7G1EXCm7aawFVsZ2ofx2qawFTMVPftrM9hKMNWmsBW7wBahbQJbsdUegZOijTz5x+514IK30XcWVImm8pkFP5DAqWJH+wiHHzrMhB/owaliWQz7tYRZtVWkqWbWVmyuQmaqWbUVW/RrS+ceZtRWzFT86a+E2bSVvz5bPk00O7bSKM5rNmErN1U4MWMaVQVgpiAthypTroqZKuJIKQnTrcqPOSUy1ZSrYhuD0NPn5Ey1qrSmmm5VbItUQlNNtSrfVElXcU2zKmaq6OO/JCiokpw+PRb8pw0mXnDHvBOKqMp/WNZ4YYd4sAerKSNsrRJVDSDpmPFNlXxZrrAiSaIq88W+SrBNX8lN5TczlNwpYcWLN7cybvyHvSXfOiJslOjnTgnGStwEZQEzlcIBYDzCXuVTElXI0GakDGMq8Zl+UlWp9+2mh+3jD40G1RDPZZOqwg6hHh1a1wKSbxqmz6UK4KoSN9Im9cMminhYVc9VJRpL9hyIaUWyB7OGqFI6324qkJ3AW8u7qiR7uWdFliFZX9o75dlKYqyBNao9HZkiEzWogCrZCmjbf3jq1MKejBuk7wjyVMmM5XQdU26ugjCs8qgyVchy9RFtl8qEklyTZypQJTeWQ79dLZuwtGhqMEtVfwkyj1OrmCpU1qzR8dRQVbJ6N4PYi54aqmqTGMsrfwFVm0JWE7T4qjaBLFKpHAKqMtyaORkcVwkIqJp1Wb6okCqZmzs7dK8EFQ5hVTNct9qgwSOkygHSzBw1yD+BV4W5hNMN5J0hqOrOoLkg6z6CKhdIPCOs6ZBtH6mqWdLVzkOWgyCqZqR+QV4FUFUu8NkpBTIpI1IVEPX5aeTUqf8HHRhC11FdSQQAAAAASUVORK5CYII=' +plusfourblue = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAAwQDBQUFBwgHCQkJDQ0NDxEPERERFRUVGRkZHh4eDAwmDg4sDxAuFBQuFhY2FxU4GxgzFyE0ISEhJiYmKSkpLS0tMDAwMjQyNDQ0OTk5Ojw5PT09KipNJzFFMTJRPTtcPkA+Qj9hQUFBREZDRUVFSUlJTU1NT1FPUE5QUVFRU1RTVlZWVlVYWVlZXFxaXV1dRkdqSUptUVF0U1N4WFl9YF5hYWFhY2RmZWVlaWlpbW1tcXFxdXVzdXV1eHl4fX19LCuAMjKXMzOYNDmROD2WOzyiPD2pPj+8PUOiXVyEQEanQUepQkirQECwRkyySE21Sk+5RVK1SFS3SVW7Sli/ZGOJZ2iMbGyUcnKXRkjOSUrERknQSEvWS0zcTlTDTVjBTFTXTFTZUFbHUFrFUFbfTU7iUFTjUlbsUljrUlP0VFX+U1jwWVzzWl74XmXuXWH0XGD4Y27bZnLbaXfcbHvccHHfYmvtYmX2ZWr1aGv0a3bpbHD1c3TrdH7qcHT0dXn2en72cIDedYDqeYPrf4ntfID3fID4gIJ/goKCg4OEgoSAhIOEhYWFh4iGiYmJi42KjY2LjY2NjIyQkZGRlJOUlJWSlZWVl5iXmJaZmZmZnZ2djo+1oaGhpaWlqampqqysra2tr7CvsLCxs7G0s7S1tLKztbW1ura7ubm5u726vbu9vLy8hofQiInRgoPug4zuhofwgoP5hozwh4j7i43yi5Hvi5Hyj5D5kZXzkpL9lpr1mZz2m574m6LunKPwnqH5pab9pqj9qKf+qKn+trbvtrb+v7/+vsC+wcHBxMTEx8nHysrKzMvLzc3Lzc3N0c/O0tLS09TT1NPU1dXS1dXV19jW29nX2dnZ3d3dzc7rzNnl1dby3d303Nz43+Hg3uD54eHh5OTj5eXl5+jn6Ofo6Onn6Ojo7e3t4+P95uj86Of96Oj98O/w8fHt8fHx8/Ty9PP09fX19/j29vj4+vf6+Pr3+fn5+vr8+v76+v38/fr9/f36/v7+AAAAAAAAOABVigAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABpySURBVHhe7Z0JfCvHXcdVIaGj5ZRs18JQwNgGYYwplIcPbPN6UI5wPMJVQgiBNq9xWwoh0KQkJCQfwBRjakwNNrYxBozB0JRSwkuaJnYfh12Ba8BgccYVRVL6qIKAqs/Rfh5z/Hf2mJndWWklS/68b94n8q52pflpjv3Pf/4zE7hxHnFUday1MFlIpAi5Kri5pYGkckhUleC2lqcMCbYiVFWBW9qCCiTajEBV2+STDp9fnKoMXNpWHELideyqynBdm2HLLpsquKgNAQEUqyq4oi0BCQSLKni/TQERGLMqeLdtARkIkyp4r40BIWZV8E5bA1IMVXC+zQExuqocnG5zClSNrgrOtj1UDaiCczwn65MXhgZbiqELE2tZSB4PkUNVHcIpGyeTsUCLEp2QCCOdSaoKzljJDgbhI1qTAXFXnakSvr0UhrtbltA8JNVCTlcFx2bK/XBrS9Mr6gvKVZV74b4Wp1sgK0NVwZGJdhElliVTNQr3tAHDkGQTElXbcEdbsAGJNjjEqjiPUjkON6iT3Aa2InCmaUQLkGwDrAr+NFiE6z2wArdqq3CiiczBVxsIVXXC5eokWH53wJkmEoevNhCpqqFWLcGt2hqcaCrr8OUMpOoI/mSMw8XqxFlWec9mHxiBL2ecBHgPYA9crM4i3Kmtw4nm0gnfbhDgq1UILlYmxn6YLjjTXIJcxvCqjuFadRbgTm0TTjSbA/h+Bq/qEC5VJsp+qm4402z24PsZvKoMXKoM6w9swYmmsw0JYNSvysiqFJxpOg1QNQv3naH16L+qCOsKnF3vxX9VM3CbtgcnzgDfVYWZxdwHZ84A31VNwV2eq6Of+K3KyKqz9N74rWoSbtIO4MSZ4FXVSg4QG+OhPNykpdGDCy7NNb2J96pqE05KjKFxeJeYWVH427vNVS/+qgqx8aFBdBSDv9td1Ri8qR3ho3OSV8ETeFMbwofnJK9G4T3okp2PvDKyapgcn4+8ugBvaVk6znU+8ooN9o3Q45bPq+UKAOc0DY4rlQT9IJPb/gSGJFs+r5iDmYepYgOU+gBKy+eVgqohONZy+ujxecgr5vIdgxPnIa8G4VDLMafoOcgr5licoMeI9s+rATjS8ob/uv3zimXVJDkktHxe/WUJYA8sOC6ViKp+OKuVYmFGAs5pR+QQX9ckFFUxJLYFc5c50MShrJuqMDdV2bipqk5uqsLcVGWjhVUtZwFrGsfhrAXmxqiQwyRcWzPBUCQai8djEdegAq+qvOCLHRiMp9JjsytbR+aYq9L23CBY1UIaqao+OzDSN7m8dcj89jyFrXFZPFtL5lW41ylA3UR5WVxZWy2vQqnxVU9zrfdE4eitlFfBvsVDLuLSnRN+qLZl8io8uMrHYCqyZG8UWyOvYiObNWSSQdYWBNECedUx6cOU5AVLdjVSVSQDOMTeJmZ9Wodh39zXbqQqd/r4KO2aMcs6Q1XhMZ+yCTDJOjNVHYu+L1pgyDojVWnue/1gX28yzkJVZIJZ8z6zDN/QfFWhKd+LngGEGTVd1UhDp+zmqBXfZFVpf5s9nhXyNU1VldqHj2wgA/iLmqgqyU3faARkTKZpqmJLddmv6uBR6SapCk5xkxwaBQ6hao6qTslc8YaAeiVNUTXVpMJHWW+Kqo5mr+gUb4KqiabVKJ3ZhqtKCh9R1Ur+5DDzoQ9Br1LCwVG2UEvZPWq0qjFhRlWO3znU6z7jNpxIjW7UYDRWQg1VleDmQRGycz3RL51aXHFjcXQg0rlQQwHuaaSqtPh3zsWjwwd5hcRWSvmleIRLoTvjDVTF5lZYyQYSbLjIlfJilHmq1FltmKrQGtxuYzve7cVu/++0YF69G8eNUhXnJkwSqv85mFAaF2DMBFVG/Gw0SFVK1jfciJBZj6TBrqL/eGzn5oMO0UYyuMeJL6qGZW1BYajrH/BrlaS9uLuzs2sHnSriN4F5WVF2grNm/FDFL1qgk43M6M/V4s7uw9NiHjbJGg7U4BJogKqwQ/XeCy3DX0WZJMxDTFahl18BwR2FWdAeVSW41QlMDHfCz+goyiRrM85mdHnAd1VJxwIThieziyijEM4FnX4kGX6XQGdRa2G6moKrqOnpq+TCXFq4wpIbPqtyFqVdiO1XX1ASBaoOOidrsdr9VeUiSksk0C9fre5Cyp3YITdsh1bJq0d8fV65iToKk/jw6lVIuRMfxFdW5uM1uRD9VOUmSpsJrWinagVwehffUOrpr2mgwUdVrqK0vgD+v1JW0TawIDP8XfBvfQt3UfsddJkaFVUkq7S5uHqnxUTZN+uWF8WZrisR6pPegZQ7QVX1dHsz8IGsX6oSrjmFOxXoouseqpUW/qL/Ia8e2fdJVVihJ5gbTBFTXr1abdXSt0Ks+aRqC651Yj8+QZ6oKqro02owzCVPiQV/VAnXw7RRWaFpVCqAT+CO1pXP7SB3embCF1Vs8qlO6WBzYcZOqpdUfRXDAnhN9y/+wuws3G5iYXX7xMmQGvZDVcr2Dc//frozIYiNHSWGqnsBvDx928WLr7x48eJL4EY7oWii38mS6vVBVdwWRXowGI5Obh7DKhCMQxpIfeqm6m3v+/Mr/5TL5dG/jyLQnf9BP8AgMz8YTsg73FpH/apC1i5aZS+YmHkeDszAE9WlWj1xVe8vOlJeiPLOdAbfyHhWZR3tLa0GBsVOs2TKvVo9bHHEOFGaD/TIel6l+kcPbE+Upcio+Hl8GKQrejip+mNVTYhSIi57nBzXrYpNPaUc96YkcaYz1EnjVAD/pCjyD8oYism8Pnv1qkraHH/LUv9xT4Q0Kh8EBTy3m/1l7lSGE7Ku10q9qmwfnOuz9Yeu/QXwr/EkOeFg2V7Fvk/13BpMiOsvnoZdn6oJuETnKPzL5NmF03bt6Xvv+bE3Q4qn3/xZ78BvOBTA+4ysKj752KOPPPgI/kd4EPHIo48+9qQ5NyOdstYiVZ+qDrvjeSWqt4jFp38SUgt8HbF/HR5W70PmPKH4zFvhFMf9z9JLEIe8RQNUQvWp4opAXwoCK557HNKhc/kryHmHFvD95AKtWrwfToi4j8maCMj87wf1RSZwve+K/vtds4uavuNX8Hmnzv0OrVPPSjOK8JRe8VLEWyBiuS5VnZyBuRil1hkvavoSddHJ8+ptRaKqeB8cS3grVK3tBFslyc5IPaqCfBRPf+LvyOsHIAkmbkHP5qpWfAgOea6QTCj+FBxKoT0vbTEs7dJ11aNK0E2NoOYDJa76M5ACg8uv+C/cajtUqx3cWCi4n2jXH1UrWQtYDtahqpvv4OwFUalAqp7jq8YlMmDoZFgQVe5ZNb1L8vSk/wvwiwic3FpViYYqRoPIsEBpexoSYOLb/xpf4JAT95P64u59QtUPsxWTejTwsuu1qmILpRqUUhBEcC+kwODyV34EZ6JjAcS8H47kPEmuqyxEZIaFdgGlrkZVxqLeBlsJMoBW1e6BFBjcOva/uOA4qCJDIG4NIOIZfJ1WSMs91XhOYI2qROPqC2FiFVavMTOJ8Z1LOKvk1eq2d5OC5d5WvIUWwJP4hLSxwMmrTRW/VDiCNkvVqqBafSvW6zDA81qS2FP3avUovg73oNgC3HbIKs+1qRI9K457B1CxRI0FX63ufDl6v+qUFbRa/SkcyXmcXKdNJbl065B1k2pS1QfvWNiKLpDK9jFBu07GTeUF8PsfwHl1qlCtnsIfpGnJXmm1Ittp1KRK1P5U5miQj6gAvvrD+B15Vn0fbkpOFdp1sJcOQtIBILp0ay2q2NpfZgr9A/T3ExgWn44y0SHRt38PebK+cAWO5TymvYAvnYhKB4CmSAprUBUUjr7kojTA9pRXdevXkCtoXt12kfBKAnVmftoGSir69xi5wIln0FWnqPG2uyAN6FzvGlSx1V8tHAZps/TPfLv+6t/GSdGoIf+eT5DLDD65SDyKyPR16lhRUKOCdJXCXfRWnixNondVYfHvNJqkw5Z8Vk2/BidFy3/j7dP3X7U6/HAe5Qf6aNFVNpeWQ1K/7TxNo3dVAlsJE+0jLrPnbB17xOXvxm9kvzjxG0+hVOFcI3J0/jECsy2eguvlUHNJGzJWlbQDm4R4VmXsqmFhM/RL5FXQtbqV+DJ6wvz0bRJP9y4Y+1Vo12kv5KiLrdRlJw+J9KxKklVjEWkBvIS7l6thYXWsate/JPX3JOvczSXshXpB09ZjbBMWO3ROmXdVQUnr0xmjPluBqh9C3eBSf9TiqGYlsKpFv4zmvnu1An/NXFA6XJuGVHpVJdgJDHMS6SWv134EUmDw+u9Fqd6IG3lcvHr1ytsZD34mhMq5P62IXX/68VEcNiSkXOvMWi7uiTIf+nX8UhVUqzt+F78fIIGpOI+KPwdvAN/yO+Sd4o/CsRwasPXhzhFx1TbtCuRRVTecs5MOfJy8CgrgD6Bec344lSfPqdMiF5Z617+RZtGh7wVAJOTmi36LvApgy/d7VCWJVz7ohJL545ACg9e/ApWXg8TY88QzK7Jwqb3ubljQdr089tK/JX/wGBsKeVNlbOtiZS1G5Qo6jJewL349DK23rfQhbkP2Oi6X7gWQqi90D8nMJWOfLm+qZDGwerMkqFbftIFHZVLEefOCoJi99l/Ine4FEOz1fFgWB1mqdc0ESa+mcKGrgH7w64IO410vQy1+OTlM231RO0cfrU/CkZzHqFWyHpVF7S9BIhGeVKXhjJ1McpQUzSLfrpMCWAaLuPgWOGuGqKq6V6sr5CMqvZ0y75JpXz5PqsTTqdDTKEitIUEBfNXvofPzMWI0VQVZ9YY/IwVLoVrRPC3bx2wZ5o0wvKiSxd9URlC1wU0c366/6cW46HV0omp3Ks4q2ga4F0AYtFtkYf528P4ROl5UycyvUidUG17VD78UnT6ETfmELQJWVYW+lxNgrw9GJPHtJ5BIghdV4pADpCpIR1KLfC/kji9H52eDZABNVAB1B5+7KpqnWjIqaQFNqwd7UiWzK7RFWm2EvRCsqh9HO0rainfjd8RvWaGq9iJsxwgr5SikkuBBlaQPomldXbRUCMyluz6/rJU6qP9dWABpy+beC/lpmqcTQYkfRu+DUDyokhRoLUvHTavP8e06agNXrv9mlPq5hKp2iWHxs3Akh7aAhX62irMN68aQ6qpovISAeZgfIHAETk/f+bLVUWp4CJNOPRHuhgWufugpvNdhj4UAbNutqquSfB6qNmHsRrguKoCIH/y8T6UDaHUVQPBEL0vGTY0tJSjqqmTxNVoyQl/Fqqbf+Nm0QgpVkXkTCt1g3Fagzv2cxA+zQJPIUFbFls2zsxGhNu81WUjBJfodkmqFUPDD0BbwpH+APhhtlCwNIEJZFbe7rc54kBpmgnad8s20Wgl6VnfTgCz3agWOwExkVvi0om5oE8qqZJ7tch88x3h7nXL5q0h/SFjKaJ/d3WOBqhVqKivzcaElauwfoaOqKiTzFRwkYdyZHzelXPpVVCEkGaI6bkq9S5WBPmG1gg10TKiqklnK2nLor8jrc3w3mPJt5PcVFcDXPU4KlnsLCNWqEhX6YcgOYlZUVcm6ato7IvT3k1Wryy//d60qnh53O60t7i0g2OvHQaF5Q9aVsqKqSja2V+pN02ZJVq2+46s/gV2a8hZQwbJ9L7lOG02Inlb7RIcVRVXSdj0TouOmAvcm5dZ50rXi3TDTt1PbTjkcQYt2i9ybou1+FVWxTVDszMAAj9Bcwtyyh0RVhaWMGhbPwJEc8MNsktApe9Mu3JpeUZU0vqavL0uaOIlhMX3nF+LyJ24RaBvgHg8D5tLXBrnEIns3RnVYUVQli3zWwiP/R15lqi69kzxqhNVqh3iN3FXR6qf1fIrAsDD36w0UVckci5kwDPvJVL3qb7TrVWG1QgYDyUZXlwVEhGeTn0NeLQjLn6oq6boFg3H4AEm9euOLST0QVqv3aFXswnGrV9Bf1BbD76J/mMhLlj9SUyVzBGqs2y+xbe8g/ndxMCOtVtqzzm3gQ/qEhBFBoK0+XmVHTZWsc79mLNAhfgrfuo7bEqFlO72Dk3td0j7qsCUhDlN8mId0JWc1VbIY11Gj18XFehNuIW2JMKv0CRTV4o7cF2PMh9nkx01haVEBaqqEvRpET8AwzD72gXvvsduCb/quT+IMEebGDhn6IS3ks1fwXAMCenkE/w9PNnjvU6Y4huUgNyAo321aSZXEBVI9TNqezmxaCOHx6W+g5qNwygtt1904hVqVG+ACsvQlewUoqRIGLiH2E5JhYsq1n3gJKaDiYDN4CimSCdg90SfmpcttKKmShaJsxKQdFExhqIfY86JH8GXoMSpSSvXYB+6dNqZXUmWd5GewFXecqH4SHSfmqNCw0OMMlMiPxpfgT50ZECBESZVk4F4rpR2WXkINb5ROUBH24O/+I/KeEgdD0SWbuc6G64UoqZJ1rrTtQEQ435Qy1E0nXbwdhFh5wx/uKM43XUzE1mym+oFgOrIJJVVCxw4mPxcJ981t5kXkcrEB8gPLhgbunp5+AK6Vc7w5GQsP2n/WPIlDlaOiStplRGT6E3ZnHONFdPzCwXZ4HQ2BvAjxj4K53OFEMv0Hdm9FRdRTNKOiShpjiKicbK/A7Hg7HRFSrcTtupCvT03BvTqzv7a5x3eA8fQCR1RUSQPXnEnEiUkin3Vq8MTO7s7u7gOfIRsdtQKhjQ6oqJK6bR3ZDtN5X+J23Qp6Ile1ymSHbHjewiYk3QEVVbWtszOHZ/gg3D2zyHrCdlG5Jy1tbE0cOdgUOiqq7A9ANQapTawwOIrMd6SqWoqMSxtbg4LKRm4qqqROCydOUqSRUVr9i5qE27C0myMV2z5DYlRUKZV2O2uxWdzJUKpWtFc8gJfRdsmtirz3YUZFlZOtJ2WGFMCqwpCvPjQinn5iQVGUkip49US2nxoWKu067RWvBF0LoKooFVU1FcBMgi4r6uiUAGi1uhBy+/mURamoqml1/60gDchSyCsIj+kKy4bIAHVRjVJVmUrSX16hsaDu9kzMsV/tSVSjVJU60qiNQW2ge16Br2nGZbVeL6IapepIn6DiatuCqHLaqWfgUVSjVE3CxMOqmyzdK5jplIRdUbyJUlEli19yoossj00WTHGUpYvS1mBtQTEFJ9eLgAapMjbId5D18K7hxVyUBn8hjr1u4tuYErimVytsM2nFq7j3ZOXqVZMklO6uIZl/GD0lFKx0K41RtRpUWXvPxEpEbkK7dxI5GqPq5z0t0ljVssn0R+HATsW1Oy9AQVVGoddjYyPQ58UkPu7q4tIB5N0cL0JUVHlvLiqpiDTshGczkdiX/HKHLi4yCSqq1HwkFrbC4YVcSSGTy/mj8Zh0Z7Z1Z2emFBVVjs9HMbmFzkhqZBY2cZGzOJOOpWZlzZ+jL90JFVXSkG8HKtujKadd0CnBeG/f/JEkSwV7PKuioirovblAFLJHsDeSA4cn0mVDlz0/pQxUVAnXSGgwOW+Gnw0lVU7DOY1h1X0fKSeUVMlC4xtFXhZHoYqSqho2AKqHNekoiypqqtx9Wv5RGIKk1YGaKqdugs+sC0PjPKKoSrqsnc/s12T2cSiqCst7Pz5yXG8roaOoSraqgJ/k8L6s/qCqShpz4RelqRotWRHKqmKycE5fqCzU3ZqbUVYln33gA2vuhrAn1FVJV2Ktl8qqdfqeD3hQJZupWx8nU76WPYoHVYGo/7L2BoPw4b7iRZXfsspLdP0u//GkyldZ2fH6ehtOeFPlm6zyhkOvcAqcGis11ziPqgJsUe86KKykHXvvzOPk1b3O8KoqEHBwiKtwsuAaMXEWqgIx6ZKErhzOqDyazkRVIHCBD25zp7w9puiIPSNVgcikShwVo3KwNNKl/mA6K1WINHenmMPl0W6PT9ozVBUIdCyIJ8UDlez+yniqlu7FmapCRPom161lsXKSWV+cvNDXWccj9qxVEaKd3T19vT2p7q7Ojjot1egmhj069sihDetM7hic3ZyDEwQfVPmIyl7C1lUf2GpKlmnD7a6KrZByUxXmpqo6uamKclOVhZuq6iTYjWHBOGlySGFOVuK3DsO4coZdW4ITGfw4bi1VFLbkjcliYhNGc8RUhiWgRGygt1tRlcgOZHlCF0p1CPxsI1VsIYA87QScj7xisRET9Phc5BWbQg5ZdT7yis1K0NepPA95xYJ4C7of8TzkFTvBlmk7B3lFF7RHlAy3QRxg72XgRBx3x9tBFXsqz9JjM+1gMVFsqnrgyJxVjLZVxZJocbgA7aoqBQe2hXqBdlXFxiqE0fptqooF/ZaFYVttqoqFJlp7izrtqYqt11ARDxO1j6qQDvqbDdiadjWwAJeSixmtqMoE20JRklUSWlwVizJyWFJKQGurYrXGvvy1C62tik0Msi4q70pLqzLi6E17hajQ0qrYFCnpQoESWllVgk2M8ZhVLa2KrezivPyXAAVVdGvR5mPszOw54I5b8JxXZWyW1VzYFsLYE+ENbqUMXlWlIeGWrsRYVnXDGXW4iKTADW7ymvdP9QM2j1phVSkb7OHNCNywL6pIx1aajbHZm/epI9xEiXzgBlcEPTdBfsDm55n3tVKEm6t8Q6DKm73sDxFWNWDDVg9EuAVoRKpEfrhGw1ZD3oMTHuD39BOqKjQumllC6OgEUFoBzELoI5BsA6yKn0jr1Q47U/jFqrJYFZ9Z0sW1WxDBHMx5iao8cc21A6IVeOfiWJVgaa5cm8hKCOJLj2+QvBJklpZr1JwOX0mKgmbHQJVoIZGysXlqyzIqCkkvIEFElSiz0KOjxbOrQ7w4/gxTJQlX3xNvdNESDEgW/M9jPVSVOLMQha3ZdKqrxUgNzGxKJ5OOYjmgSiqr3cgQNbqqWqaCtCDlEaJGV3VOMgu16him6lzIWgMthqpzIItWKoRJVQ0LnLUWyFQCTKpuNGTac/PIggyEWZWgp9VGHA2DCoRFVaaN69Y2aCBYVCHgmrZjHtJPsauSmYStDaSdwak6asPsgqQbcKowcHGbsBeBZBsIVbWTru0YJNmMRJW4f9xyQFo5pKowsrX+WoIKJFKEoypA+pO0KDdu/D83QSf4+vAyWwAAAABJRU5ErkJggg==' +plusfourgreen = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAABwgHCQcKCwsLDBYMCxgMDRsTEQ0NERkNFBQUEh0RER4bGBUXHBwcFiwWHSkcHygiIB8eJCQkIi4jKCYnLCwsJDEkLTosMS8yMD4vMTExMT0wODU2Ojo6Pz5AI0UjJkslJ00oKkskKU4pL1AmK1EqLlg1NEM0PkA+MVMmNFYsN1knN1kvOlsrM1syMFw6PV0yP2AsNWU0OWU3OGY8PG05NWRDOGhHOmtLQEA+Q2UrRGQ2S2s5THEvSnc0U3c2Q0NDSEdIS0tLT09QQ1JDR1dIT1FPUE5RUVBPVVVVVlZYW1tbR3FAQn5MQHZUVnZBW3xDYF5heHlEY2NjaGZoa2tra35rc3NzeHd1ent6ToE6YpE8Q4FORYJQSo5WTJFWT5dYT5hYUYVFU4dIVIxJW4xKV5BLWJRDWJRMWZlGWZlNUZxYWZ1QTqtQWqJNVKZTU6FYValUVqpYWKpVW6xbXapiXrBgYp9hfZB8Y6tcaa9bbLBdY61kY6xqbK1jY7FjZbJqaLJnbLRsbLJycq1xcrNidrJueLVnebZpfbhucbVzdLl0eLNwerl2e717fMF7dIiBe7OLfLqBgIJ/k456ha9yiLF1jLR8iL98kL1zlMB6goKCh4iGi4uLjIyQkI+Rk5OTl5iXmZeWmJaZm5ubnZ+gg76BhbqRir6UkbqDlL2JoJ+eoaKeoqKiq6urr7CvsK+wtLS0ura7u7u7vb7Bv7/+hcGGh8eLi8ODisOKjMiLjsOUksaNmsSCm8WKnsiMk8SblMqTm8WSmceem8mXmsqdmNCYnsygoMmPo8yVo8yaoc6hpNGjqdGjrNSrvsC+sNetsdextNm0vd28vd/Ewb/BwMy/wd+/w8PDx8nHycnGysrKw97C0c/O09PT19jW29nX3NzbxOHEy+PL0+bS1OnT1uvY2OnW2+zb3OTg3uvg4+3e4fDe5OTk4u3i6Ofo6Onn6urq4/Dj6/Tq7fbw8O/w8PTt8fjv8/Pz9Pn09vn4+Pb3+vf6+Pn2/v7+AAAARX10/QAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABlESURBVHhe7Z0LlCRXWccbayOpaBvT0AkMtkl2zxgSTQCVoCQkzQBqM77i2A6Db3wlm8DauxsUCaxuRCUr4BMkY0sfHYGIPce2MSREMAFizCZZhfgY6dDSmwSXbHpi92qoRam1qu6/bj3u/apuVVf3dM/ZX87JTFfd2rn//u7ju999VO7UdiRSVc+cYnrIpAxaFR6eapBVAUKVgcemHgMZDiJVhSdmBGTaj0TVzNjJRbSXoKqDpDNFF5l3CauaOUMxQuYKqUKiGQQCGEFVSDGTQIJDQBXuzygQYeNXhbszC2RY+FTh3gwDIX5VuDPTQIqnCtdnHIhxVfVxecYZMDWuKlydeZgaqMI1kf76ytJiZapYXFpep0d+jhymqotLIfor+dyUoi8TwpzBJFOFK0F6FfwLU8qCXBdXJb29puHp6aWBrAbou6rw2Y+xgCenmrJsiEGrMsp4bsqZk8jqMFX45GNWRMllUaqqeGYGWESWfRCq2nhiJmgh0x5dWxV+9zCS91KFtouOKxNDHyDbHlJVDaRPQBOPmk1cmCB1/GkPqaoikqtTwJNpnh2ZPP60h0xVilq1hkfNdVyYKOv44xxLleADLiOxOt63tQWmyuWW8Mc5/ZwYASwhsTrcc9kSU+Xm8Nc9cmK1Suz/eaaaw5UJIxhGVNVDUnV4I9TChUkjRNFFVV0kVUbHg1tmqtwG/j5HVNVBUmW4qbbMJWkjA5zRVem8VCdvZjJiDKpW8dwWeo/Zq/JMtXWjl+xVcVNt4MIWkLkqjXvMWzjQzFzVCp5KXB2zJGtVnqm2MnqTtaqpMFViVc0+kDvjnqkqVmuIpP2JN/FJVfGggNwZWsZdx83inlNi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' +plusfourred = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAAgQJBwgHCgQECQcKCwsLCgoeDxEPGQkJFBQUFxQaFxgZGBUXHBwcFxkhJQwLJA4SJA8aLw8SKxELJhISJhEdIB8eLhkZOhwKNxMTKBQlLhYvMhgzJCQkKCYnKScoLCwsMyYnMS8yMTExODU2Ojo6Pz5APkA+RRcZVBweXx8gXyAgYiIeZiMidycnezAifi9CQEA+fVg8Q0NDSEdIS0tLT09QT1FPUE5RUVBPVVVVVlZYW1tbYF5hdld6Y2NjaGZoa2trc3NzeHd1ent6fn6PgSsrhDMkjjAyky8ylz0nmTMyqDg3uDw8gjFEhjNIiDRJlDpUmDxXmz1Ztj1An0EpqEYquU4uvEA9mGhDpUFhrURmsEVpuElsyEA/wVAvylQx1lc25F45xkJDxEhc10dHw01w1Exg2U9h3Xxs5ExM709Q6VdD7FJe9U5S9lZL81FQ8VNc9VtX815Y/lRU/VVY/l1T/Vpa41Bg719u9Vdg81hj8F5s7mZe+GRY/nhW7Wxj7mNy7HFo7Hlx/Wdn/25w/npo/HZ1i2TD3mSF3muK7nCB4XWT4nqVgIJ/3oV14ol7/Yhq/opz/pN6goKCh4iGi4uLjIyQkI+Rk5OTl5iXmZeWmJaZm5ubnZ+gpoaGoJ+eoaKeoqKiq6urr7CvsK+wtLS0ura7u7u7vb7Bv7/+vsC+0JeX442A5oOb6Ied6Iuf5pOI7JyT+omH/ZqG/pWW+5yb6o6g7ZOj8Jel8pyn8p2o7qGZ/qGM+aWa86ei9aGq9Kmk9q2q/aCg+Kat/qyi+ayt/q2w/rKr/bSz/ra7/Lm3/by8wb/Bw8PDx8nHycnGysrK0c/O09PT19jW29nX3Nzb3t/+3+Hg6NnP7t3V/cPC/8DJ/snK/d7M8N7W/dPT/tfZ/tjX/Nrb7dTj89rl+eLa5OTk5+jn6Ofo6Onn6urq9+Li++Xk/ebo/ejm/enp8O/w+fPs8/Pz8fL+9fj09vj4/PPz/PX5+vr2/v7+AAAAAAAAAAAAAAAAAAAAHYHLzAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABlASURBVHhe7Z17lCTVXcfbrCVTxg7xgAmr1qHDWAY87h616ajNYKcnoyjPqDFqiMoGMUIWJwkzm5cuhJBgYghgOm366PjoPrYddZVlMaKJq4kGxeCYTptWdwWJwJZLM+yGMpDtf9aqur97q+re+6u6VV39mrMfOGe7q27N3O/87uN3f/dRudPbkUhV/eEM04dMysBVwcMzDWRVAFFlw2Mzjw0ZDiNVBU/MCZDpIBJVc2MnimgvQVUXks4VPcg8hVc1d4YicObiVEGiOQQEEMKqIMVcAhI8Qqrg/pwCIlyCquDu3AIyHAKq4N4cA0KCquDOXANSfFVwfc4BMVSVBZfnnAFRQ1XB1bmHqAFVcE3Eaq1UlsozxVJluYWP/Dw5RFUPLnFYK/ncjKIvI8K8wSRRBVfC9MvwE2aUklwXUyW9vaHB07NLA7IawqKq4HsQuwRPzjRF2RADV2UX4bkZZ1Eiq0tUwbcA8yJKLgtTVYVn5oAlyHIARFUHnpgL2pBpn56rCj772Ml7KaND0eHKxNAHkG0fqaoGpE9AEx4dNuHCBKnDr/aRqipAcnUMeDLNsyOTh1/tI1OVolZtwKPDFlyYKC345QxHleADLkNidfy/1hRMlctV4JczrJwYATQhsTrMc5mKqXKL8Nt9cmK1Suz/+aZahCsTRjCMqKoPSdVhjVAbLkwaIYouqupBUmV0eHBqpsptwu9niKq6kFQZZqqpuSQdyABjdFU6K9XJm5mMGIOqGjw3Re8xe1W+qaY3esleFTPVJlyYApmr0pjHPMWBZuaqVuCpxNUxS7JW5ZtqmtGbrFXNhKkSq2pagNwZ901VdlpDSGpNvIlPqooFBeTO0DLc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' +plusfouryellow = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAAgQJBwgHCgQCCQcKDAgACwsLCgoeDxEPFAoFHBMBFBQUFxQaGBUXHBwcFxkhIRUCJBkEIxkNKxsCLB8MJhwTIB8eKB8aNhwHLiQOLyQQOCUANisUJCQkKyQlKCcoLCwsMiQnMC0vMS8yMTExODU2Ojo6Pz5APkA+QiUGSjIBWTsAUjceSDojQEA+ZkQCdUoCe1EBflYbZFk4Q0NDSEdIS0tLT09QT1FPUE5RUVBPVVVVVlZYW1tbYF5hY2NjaGZoa2tqdmdqc3NzeHd1ent6fn6PhVcBhFsdiF4fmFwKhl0giF4gmGUBjWEjkmcomWsqp2YKrXQBtmsOvW8Qt3oApXMvpnQwrXgysHs0gm1AynYQ134Ri3ewv4EAuIE1gIJ/t41rwoMBxIYe1YgG24AS2pIB1JAe2ZQcw4g23bU054cR65gD5ZsX4pkY654T9ZsH7qMA7aAS764X7q8Y7bAe9KQA8aIO86sM/KUB/qYM/qkA/a0L9KYU86YY8K0S/qYR/q4R/qga/bIY76gq76My7qkw7LMl6bg48Kcj/qMv/qol/qwp/qc2/rYl/rg03qBH3qJM36dV3rpA7q9B4atd4r5M5L9Q/q1G/bNK/rVU4q1h5LFl57Vr6Ldu6blv671z/b5j48BP5cFV+8FK/cZY68hn7cB278N578xw/cNr/stj/Mtq8cV88c508sh+/sdy/cx0/c15/tBr+NF6goKCh4iGi4uLjIyQkI+Rk5OTl5iXmZeWmJaZm5ubnZ+goJ+eoaKeoqKiq6urr7CvsK+wtLS0ura7u7u7vb7Bv7/+vsC+wb/B9cuB+M+E9tOC+NKE+9WI+9iH/diL/dqT/eGn/ea3w8PDx8nHycnGysrK0c/O09PT19jW29nX3Nzc3t/+3+Hg7N/Z7OnI7eLU7uLY++nI8+XZ9e7T9erZ/OzT+u7Z9/DW+vDV/fLb/Pje5OTk5+jn6Ofo6Onn6urq8O/w/fXl8/Pz8fL+9fj09vj4+/X1+vf6/Pr1/v7+AAAAeSzGFgAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABkISURBVHhe7Z17lCTVXcc7Z0MJW0nL48ghYpn2ZKyTTdRBbSZ6OsOknUzAXVazCEoE8ahIlGDccExkMyDqRkN8gM9FwAdhYGMCEqP06djqGLu1bZ/Bw7JDOi2tEjcEsmNl004Z4vRaVfd3b1Xde39Vt6qrHzVnP/vHdlfd7rnf/t3H7/7uowqndyKRqvrDGaYPmZSBq4IPzzSQVQFElQ0fm3lsyHAYqSr4RE6ATAeRqMqNnSiivQRVXUiaK3qQeQqvKneGInDm4lRBohwCAghhVZAil4AEj5AquJ9TQIRLUBXczS0gwyGgCu7lGBASVAV3cg1I8VXB9ZwDYqgqCy7nnAFRQ1XB1dxD1IAquCZitVaWFiszxeLScgsf+XlyiKoeXOKwVoqFGUVfRoR5g0miCq6E6VfgG2aUBbkupkp6e12DT88uDchqCIuqgvdB7AX45ExTlg0xcFV2GT4348xJZHWJKngXIC+i5LIwVVX4TA5YhCwHQFR14BO5oA2Z9um5quC1j528lzI6FB2uTAx9ANn2kapqQPoENOGjwyZcmCB1+NM+UlUlSK6OAZ9M89mRKcKf9pGpSlGr1uGjwxZcmCgt+OMMR5XgAy5DYnX8X2sKpioUluCPM6yCGAE0IbE6zHOZiqkKc/DXfQpitUrs//mmmoMrE0YwjKiqD0nVYY1QGy5MGiGKLqrqQVJldPjg1ExV2IC/zxBVdSGpMsxUU3NJOpABxuiqdFaqkzczGTEGVTX43BS9x+xV+aaa3ugle1XMVBtwYQpkrkpjHvMUB5qZq1qBTyWujlmStSrfVNOM3mStaiZMlVhV0wLkzrhvqorTGkJSa+JNfFJVLCggd4aW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' + + +bluebutton = b'iVBORw0KGgoAAAANSUhEUgAAAGMAAAAnCAMAAAAsLAbdAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAAE5a71VV/kZq1ICN7pal7QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJIhjsUAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAAzElEQVRYR+2X0Q6EIAwEgaP//8lYoLVgcomJ3T4Y59EYJrtGKKldIAdkKWVzEP1ycaDumsVBVV7xoC4Wc3gaOlXWNQe5lLSRNYo4vENMJMp0YBQqGQ6UopRRV3eQPACQ1YGLMdtiBzAGw22xAxljBEngGD1IjANbVS8roWNwkM9xm89xnxhHxD/4mv0qYm8POaMiztrW/Oc35ZwZgG2dsw+urWWGg4y7zFSoA/JNRGEO977sBmKOiDsOQ06a/PeuNpBb4zNkLeXq8Ke1A1yYxppnbkkqAAAAAElFTkSuQmCC' +greenbutton = b'iVBORw0KGgoAAAANSUhEUgAAAGMAAAAnCAMAAAAsLAbdAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAAAGmCwCqAAyjKU/AWXHLfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFeD53sAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAAzElEQVRYR+2X0Q6EIAwEgaP//8lYoLVgcomJ3T4Y59EYJrtGKKldIAdkKWVzEP1ycaDumsVBVV7xoC4Wc3gaOlXWNQe5lLSRNYo4vENMJMp0YBQqGQ6UopRRV3eQPACQ1YGLMdtiBzAGw22xAxljBEngGD1IjANbVS8roWNwkM9xm89xnxhHxD/4mv0qYm8POaMiztrW/Oc35ZwZgG2dsw+urWWGg4y7zFSoA/JNRGEO977sBmKOiDsOQ06a/PeuNpBb4zNkLeXq8Ke1A1yYxppnbkkqAAAAAElFTkSuQmCC' +redbutton = b'iVBORw0KGgoAAAANSUhEUgAAAGMAAAAnCAMAAAAsLAbdAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAALhqYuVaWP5VVeSNi+KlogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPXdpGwAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAAzElEQVRYR+2X0Q6EIAwEEej/fzIWaC2YXGJy3T4Y59EYJrtGKKndIAdkKWVzEB25OFB3zeKgKq94UBeLOTwNnSrrmoNcStrIGkUc3iEmEmU6MAqVDAdKUcqoqztIHgDI6sDFmG2xAxiD4bbYgYwxgiRwjB4kxoGtqpeV0DE4yOd4zOd4Towj4h98zX4VsbeHnFERZ21r/vObcs0MwLau2QfX1jLDQcZdZirUAfkmojCHe192AzFHxB2HISdN/nlXG8it8T9kLeXu8Ke1E2qb0ylAVTgZAAAAAElFTkSuQmCC' + + +blank = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAszD0iAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAAAFbSURBVHhe7c8BDQAwEMSg+Td908GnOODtolaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5Wjour7QMC20VI3QCuyAAAAABJRU5ErkJggg==' + +plusfour = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAAwQKBwgHCgQDCAcJDAgACwsLBwgZDxEPFggGGxMAFBQUFxQaFxgZGBUXHBwcDQ0qDw8yEQ8uFxkhExQ8JQsNLw8SKBgEIB8eNxMTOCUAJCQkKCYnKScoLCwsMigpMS8yMTExODU2Ojo6FxVEHB5XICBfPz5AJiZvJiZ0PkA+RRcZVBweXx8gQSsASjIBWTsAXyAgZyEidycnQEA+aUcAcksAe1EBZFk4Q0NDSEdIS0tLT09QT1FPUE5RUVBPVVVVVlZYW1tbYF5hY2NjaGZoa2trc3NzeHd1ent6LSyHMC2SMTSaOjipOzuzPkDAQD+8VliDfn6PQ0LISEjcTU3rT1T4UE7sVFX+XWH+YF78aWnkZGT9Z2n7a2v+d3f9TqtQValUXq5gXrBgYK1eY65kaLNobrZwdrp2fMF7gSsrjjAyky8ymTMyqDg3uDw8tj1AhFcAmGUBvEA9p24ArXQBt3oAgm1AyEA/xkJD10dH5ExM709Q9U5S91JO/lRU/Wdn/25w/HZ1gX/+v4EAgIJ/woMB0Y0A2pIB6poA7qMA/qkA/q4R/bIY/rYl/ro0/YB9/r5B/cJK/cZY/stl/s5y/tBr/dF5goKCh4iGi4uLjIyQkI+Rk5OTl5iXmZeWmJaZm5ubnZ+ggr+CpoaGoJ+eoaKeoqKiq6urr7CvsK+wtLS0ura7u7u7hIT+iYf+ion8lpX9oZ/+vb7Bp6j8sq//tbP7ubX9vLv+icSJj8aRmMuYmNCYoM+gp9OnvsC+sNetu9y7vd/E0JeX/YmJ/ZGP/Zua/aOi/q2w/bu7wb/Bwd+//NeH/duV/eGn/ea3w8PDx8nHycnGysrKw97C0c/O09PT19jW29nX3NzbyMn90tP819j729v9xuLG1+rX3+Hg/cTF/djY4N/74PDf/evG/u/R/fLa5OTk5Ovk6Ofo6Onn6urq5eT+5uj76Of76+v+6PPn7fbw7vD+/eno8e/3/PXm8/Pz8vP99Pn09vn5/PTz+vb6+/r1/v7+AAAADa/O5QAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABkUSURBVHhe7Z1/kCTlWceHutBh6ehQBak76MokaxM1IUELJDqMWsOymc2eIf4gKEYDOZXLJQokaFBAsxopA7kAGrCYTDKlq8aZchwiBiNHDIpSKprjVoeMGfDuvLPwOpdBOT22uSM7Z3e/z/t29/u+T/fbPT2/tu5zf9xM9zs773ee98fzPu+Pzp3ajESq6g2mmB5kUgauCj481UBWBRBVNnxs6rEhw2GkquATMwJkOohE1czYiSLaS1DVgaQzRRcyT+FVzZyhCJy5OFWQaAYBAYSwKkgxk4AEj5AquD+jgAiXoCq4O7OADIeAKrg3w4CQoCq4M9OAFF8VXJ9xQAxVZcHlGadP1FBVcHXmIWpAFVwTsZrLiwvlqWJhcamJj/w8OURVFy5xWMv53JSiLyHCvMEkUQVXwvTK8BemlJJcF1Mlvb2qwaenlzpkNYRFVcH7IHYJPjnVFGVDDFyVXYTPTTnzElkdogreBZgVUXJZmKoKfGYGWIAsB0BUteETM0ELMu3TdVXBax87eS9ltCk6XBkbeh+y7SNVVYf0CWjARwcNuDBGavDVPlJVBUiujgGfTPPZocnDV/vIVKWoVavw0UETLoyVJnw5w1El+IBLkFgd/9eagKlyuUX4coaVEyOAJiRWh3kuEzFVbh6+3ScnVqvE/p9vqnm4MmYEw4iqepBUHdYIteDCuBGi6KKqLiRVRocPTsxUuTX4foaoqgNJlWGmmphL0oYMMIZXpbNSnbyZyYgRqKrC5yboPWavyjfV5EYv2atiplqDCxMgc1Ua85gnONDMXNUyfCpxdcySrFX5pppk9CZrVVNhqsSqGhYgd8Z9U5Wd1hCSWmNv4pOqYkEB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' + +wild = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAABQUFCQkJDQ0NERERFRUVGRkZHR0dICAgJSUlKCgoLS0tMTExNTU1OTk5PT09Pn4AQn4AQUFBRUVFSUlJTU1NUVFRVVVVWlpaXV1dYWFhZWVlaWlpbm5ucXFxdXV1eXl5fX19az+RUUGvU0G0UkK4TUrcUVH0U1P6VVX+XV30Wlr+YmH9amr/bm7/cnL/eXH2e3v/BJUAFYUAGIQAAKMAAKoAC60LEa8QE7ASGrIaI7UjKbcpK7grM7cpNbgqMroyPL08e4UAZb48Qb9BRMBETMNMVMVUWcdZXchdY8pja81rcM9wddB1fNN8Z5a2cJuqlkJ0mkNyzktfykpg81FS+lNT/lVV/1tb819p/l9g82Bs/2Ji/2ho/21t/3Jy/3t7vHy+gXn2mn3hvH3A3W+Q3XCSgYYAl749mL08vZUAwpYAyrcpyLgq7aMA7K8Q8KQA/qoA/6wJ/68Q/7AU/7Md/7Uj/7cp/7gr/7oz/7499Zhr/5ZnzsBD/8BD/8NM/8VU/8pj/81r/89w/9By/9J7gYGBhYWFiYmJjIyMkJCQlZWVmZmZnZ2doaGhpaWlqampra2tsbGxtbW1urq6vLy8hIT/k5P/mJj/gKfCoZjYpJzYoaH/pKT/qqr/rq7/s7P/u7v/gtWCiNeIi9iLk9qTm92bo+Cjq+OrsuWyuOe4vOi8/4KC/4yM/5CQ/5WV/5ub/6qF/qOj/6mp/62t/7Ky/7W1/7m5/76+wcSDwcaJ/9WD/9eI/9mO/9uU/92c/9+g/+Cl/+Kr/+Sx/+e5/+i8wcHBxcXFysrKzc3N0dHR1dXV2NjY3d3dw8P/ycn/0dH/1dX/3Nz/w+rDy+3L0e/R1fDV3PPc/8LC/8XF/8vL/9TU/9nZ/9zc/+vE/+7N/+/R//DV//La4eHh5eXl6enp7e3t5eX/7Oz/5PXk6ffp7Pjs/+Pj/+np/+3t//Xj//fo//js8fHx9fX19PT+9Pv0//Hx//X1//ry+fn5+Pj++fz5//n5//z4/v7+AAAAwISkTAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABclSURBVHhe3Z15YBXHfcff0wkoQIsQAnNIpGlcFWLqtEGA6tYkMTS2oadLDzdO77vp5TZNL/cIt7ksuWnrxA6JDxK7pooP2rShcVqQkKjrJG0wmKa20GsOgRspAeTgob/fzG/v3fdmZn/v7Vt//rCl92af5sPb/e7szuxM4WoFRF1BlapEBSv6sPqC6laGslb0KfUJ1TGWMla0dZ1DlQ2SaEUb5QCqsJ8EK9ogH1CdfcRaUencQNX2iLGiormCqu4QsaJieYNqT4StqFD+oPorQlZUJI+QgSRoRQXyCTkgASt6O6+QBeC3ojdzC2kAPit6L8eQiN+K3skzZOKzojeinDw+0F9XDBwfpapFIBfXil4OcXJ5e1OhDmmc1z1CVQxCNuWs+ufTh9Ql7Qeomn7IhqzoRT/jHbR53dI+RlX1oXSUFb3kZ39d7npBmvZQZT2kTqLVbtqwztlB1fWQPtKKXvCRE6kYrTJWB2ib8hSbW2dkvp/upSq7JFqNN9MmSTTNX75vuKTK7l9AL2ZDYzgyEq06aYt4Xrd1mMoRI3PpnUyYT7VwSbA6RuXjaOqKO/0to3cz4R6qhANZ0W8uyV9V664pKiMunX3+qY//zX33Pyd/y1KrXdbAR6zVGJWO0LRzWpW4cOTxd24BfrAHuO4/8KUsd8JIszDOajsVDrNYxcOlp9+FRsBtb0Srnp4H4NUTVCgLumW9fMRZxWda64B88/zhHyOnLVter6R6evDbyjAJo7sgWNGPLq1UOECH/KIu+Jy2/Mi1JNWzCt7aRwUzoAmr5ifGapzKBlgu33rK57Rly7eSEwCREbtZjYgcWFGrESrqoyhbkRPO8aSQUUHgkdVI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' + + +b0 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX/Vlb/WFj/Wlr/XFz/Xl7/YGD/YmL/ZGT/Zmb/aGj/amr/bGz/bm7/cHD/cnL/dHT/dnb/eHj/enr/fHz/fn7/gID/goL/hIT/hob/iIj/ior/jIz/jo7/kJD/kpL/lJT/lpb/mJj/mpr/nJz/np7/oKD/oqL/pKT/pqb/qKj/qqr/rKz/rq7/sbH/srL/tLT/trb/uLj/urr/vLz/vr7/xMTExcXFxsbGx8fHyMjIycnJy8vLzMzMzs7Oz8/P0NDQ0tLS1NTU1dXV1tbW19fX2NjY2dnZ2tra3d3d3t7ewMD/wsL/xMT/xsb/yMj/ysr/zMz/zs7/0ND/0tL/1NT/1tb/2Nj/2tr/3Nz/3t7/4uLi4+Pj5OTk5eXl5+fn6Ojo6enp6+vr7Ozs7u7u7+/v4OD/4uL/5OT/5ub/6Oj/6ur/7Oz/7u7/8fHx8vLy8/Pz9PT09fX19/f38PD/8vL/9PT/9vb/+Pj4+fn5+vr6+/v7+Pj/+vr//Pz8/f39/Pz//v7+/v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAV9lm+wAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABGoSURBVHhe7Z3nf9vGGYBNUpRESZa1t+RYw5qWrdnldKRO26TWHrakNt21ZI2kaTSahLRp/uEsSLw4HHAD7x1ADP/4fLF4OMh4BBC337tX/hiRWX36QynGfP9zuEwOQqu/wcmx5iu4WDcCqw9wWux5DxfshGsFZyQEuGgajlVi7pPFO7hwG8YqEd8nN3+Gi7dwWyXuRpm4vl4uK8iUQEDAxGH1AnIkkl+CRAXa6ks4nlBegIYBZfUFHE0sn4EIbfUpHEswYEJbwZFEAyq2FaQnmw8gY1l9B+kJ5xvTBqyeQ2riMXXACtIYbvYWhnu6OmNFV8/Ik/0buECGqo5p9Q9IcrE/nE7FlPToIVykiz/ZVpDiZP8B/IaY0vkKLtQJsfo3JNDcTcLJ8SU9k4eLpfmrZQWfac7vw6mxpuMKLpcGrH4PHynO2+C8mPOAo/XctIJPFJcJkUql2q/hkm2MophrVRyAcxLAKFwzRdWKbYCswBmJYAMu2uZXFSv42eYyCydQdIyvvH578fZoZbwDUuJCE1Mgv+dazUJ+QsPEGzhU4c0kxzpCFuG6bHhW+SbIbvHY/de4nY5TnaO1CJdF4FmtQ26g7QDSaQ7j9JLchosiGFZ/hx8Jn0Bmk75bSHZy1w/HY8AUXBPhi3tsD2A7ZK7SdwepbmKk1Q2XRPjuHvMA3kLeKt0iKUOrB/JETqYAl0RgrY4gb4XsW0jkcR6bV+EZXBGBtTqErBWWIY1PbArrE7ggAmt1AFkNuql3ZmGzL5fN9W3Qd7sX8kXNMVwPQWq1CUkGyy2QlnsGKQZbkBY1SlYt9n1ZgKQKc5Bm1IJbISlilKzmIcUpRWs50yNDyYpUKt5A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' +b1 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX/Vlb/WFj/Wlr/XFz/Xl7/YGD/YmL/ZGT/Zmb/aGj/amr/bGz/bm7/cHD/cnL/dHT/dnb/eHj/enr/fHz/fn7/gID/goL/hIT/hob/iIj/ior/jIz/jo7/kJD/kpL/lJT/lpb/mJj/mpr/nJz/np7/oKD/oqL/pKT/pqb/qKj/qqr/rKz/rq7/sLD/srL/tLT/trb/uLj/urr/vLz/v7//xMTExcXFyMjIycnJy8vLzc3Nzs7Oz8/P0NDQ0dHR09PT1NTU1dXV1tbW19fX2NjY2dnZ2tra29vb3Nzc3d3d39/fwMD/wsL/xMT/xsb/yMj/ysr/zMz/zs7/0ND/0tL/1NT/1tb/2Nj/2tr/3Nz/3t7/4ODg4uLi4+Pj5ubm5+fn6enp6+vr7Ozs7e3t7u7u4OD/4uL/5OT/5ub/6en/6ur/7Oz/7u7/8PDw8fHx8vLy9PT09fX19vb28PD/8vL/9fX/9vb/+Pj4+fn5+vr6+/v7+Pj/+vr//Pz8/f39/Pz//v7+/v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqB9+GQAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAAA0jSURBVHhe7d35XxNJGsdxkgAiioiI4sUI3iKisLizs8fs7LrXzIrKeONezs4oLLDrjGhGBzTmD8/28U1fVZ081fVUH3n15xdD6DT9NpCrq6v7Wr1YR9WrZo57/1tspaRY1Ve4ca77DhsbLUb1E26W/36BLQ4lVX3ELYrR59jqQBLVWyxdmD5iw/0E1R+xaKH6Lza+XVRVuDsKYfNRRIVlCtivIXAKq7BEIfs7DHZB1af4fkF7BoZVUIXvFrZ/wRFS4XsF7i+QBFT4TqEDxVd9wDeKHTBt1T9xdcF772raKlxb+L50NFDFvZ6tP5yfmjg0lq8OH59d2cIGCjkcV/U5roq0Ol2r5LXJuw1sZbhXvgrXhHs6gRXktP23saHhPNUXuCJYYy6/91O7qdfY2GBv2yp8HexNzu8ot73PsbnB4lVvDuN2OW9IwvrGVb3Dl371gqAs1gtsciBXhS8CncNtCtDYLrbZL0b1ALcoRLPYaL//2arv8YXXzj7cwK26tIkWcU2uqop/WrYKF/1uYHm36i1c3WzewVX5ahpb5ydVHcLiTgFUTlW1bWyel0z1BEs7BVE5VVWuYvO8vpKo5rCwXQiVV9VRbJ7X+77WX3HR6yQWtgqj8qoaFF7n9rV+cC/4DWNhAZVXVWUN2+fVJ7y1qmNREZVb1Qq2z6tP+LPaxqIiKrcq4S2JqNrEopWDuMIvryrhv5+i8l5p9ZJq6ywu9JJq64D3fNA7qq0D/rNcz6gsVO+pbFTPqRxUr6lcVI+pgOot1T6gekvlVaoyqVR5lapMKlVepSqTSpVXqcqkUuVVqjKpVHmVqkwqVV6lKpNKlVepyqRS5ZWJamh07ND4xJHJ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' +b10 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX9Vlb9WFj9Wlr9XFz9Xl79YGD9YmL9ZGT9Zmb9aGj9amr9bGz9bm79cHD9cnL9dHT9dnb9eHj9enr9fHz9fn79vb29gID9goL9hIT9hob9iIj9ior9jIz9jo79kJD9kpL9lJT9lpb9mJj9mpr9nJz9np79oKD9oqL9pKT9pqb9qKj9qqr9qqr+rKz9rKz+r6/9rq7+sLD+srL+tLT+trb+uLj9uLj+urr+vLz+vr7+wcH9wMD+wsL+xMT9xMT+xsb+yMj+ysr+zMz+zs7+0ND+0tL+1NT+1tb+2Nj+2tr+3Nz+3t7+7+/v4OD+4uL+5OT+5ub+6Oj+6ur+7Oz+7u7+9/f38PD+8vL+9PT+9vb++Pj++vr+/Pz+/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHJ0rWgAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABVmSURBVHhe3Z1pQ9u8loAnCRC2t5R1WFrKTgtcLkOBoTBwoSwt20BfoMOSBP//P9FxkhNZ8jmSj2THce7zBZAd8IM3LUdH//Enmv+Er+1DtJWXTeDoaExW8PnsAseJ0VrBB7MOHG0IjRV8ph2AI1agrGD3tgEOWwJbwa7tBBx5ALKCHdsMOPgGYSvYq+2AwwdCVrBPGwICdVQr2KMtAYUaihVsb1NAoopsBVvbFtDwkaxgWxsDIv9mVkIrsIINbQ2oBFZQ3uaATMMKSkNU7g6WxocHs8Xw2MLeTQWOMEzdBqygTOV5669cVuld/w1HGaKmo7cqfemE35BNCgsvcKQKNZ26FZTIXL2DT2eXvnM4VgWT1W4ePppp1t7gcCWEFfwssQMfyzqrWEtv9Q0+lH3W4IglwAp+CrgtwGfaAHxv1a3gh4DyIHyiHejDT0LaagM+QNA5urx/9ev+/tf1weexLihsLYtw1AGkVakb9g/TvXKnvNIrv9Z6YVML6XiCwxGQVvuwe4jxozLsIFE+noDNrWMDjkVAWg3D3gpDN7AVcUvunyJ9qE5IWL3AzjKFDeI8Nah87YDdWsQdHIjAt4LvBOewr8QI+pzKrxHYsTUcwGEICKtN2DdgXlftF1QWYdeWsARHISCs5mBfwedIKZ8V2LkVTMAxCAirT7Bvg2Uoj+AL7N4CRuEQBITVR9gXmFPP1MPe0mh3Z2fP4OfTVygCFuAD6TMMRyCItHovP/wqJ1NSA6Uwdiwbl4egPHWsrfLXUFrl+j2UCj7AlhotqxNbW61CoU9pBTUke/+GbXXWoThtbK0GguvvZRTKAkJSXhmdy3SwtfoJZb4UvmvCUp53CVtS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' +b11 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX9Vlb9WFj9Wlr9XFz9Xl79YGD9YmL9ZGT9Zmb9aGj9amr9bGz9bm79cHD9cnL9dHT9dnb9eHj9enr9fHz9fn79gID9goL9hIT9hob9iIj9ior9jIz9jo79kJD9kpL9lJT9lpb9mJj9mpr9nJz9np79oKD9oqL9pKT9pqb9qKj9qqr+rKz+rq7+sLD9sLD+srL+tLT+trb+uLj+urr9urr+vLz+vr7+19fXwcH9wMD+w8P9wsL+xMT+xsb+ycn9yMj+y8v9ysr+zMz9zMz+zs79zs7+0ND90ND+0tL+1NT+1tb+2Nj+2tr+3Nz+39/+4OD+4uL+5OT+5ub+6Oj+6ur+7Oz+7u7+8PD+8vL+9PT+9vb++Pj++vr+/f39/Pz+/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5tFg+wAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAAA+7SURBVHhe3d15Q9NcFoDxSQtlE0VBQUVBXhdAZFwYZYZRX8dxGFFRVJB9Yr7/d3CS3JM0yV1yzrlJmuvzT7FNSn4CbZrl5i+/fscwqqBtwXLpM6rgSdoZLKMygwrmbm+wnIq0Kpiz5cHCFtOoYCYHggXOp1TBDI4EC51NoYKJHQoWvJ+sgindCpY9SVLBZK4FSw8VVTCRgwEgrqCCKZwMCFF5FTzuaIAIy6rgQXcDR04FDzkcQLIqeMTpgNJXwf2OBxiz6uf+q+W56cvt6srVO892z2AJCwEmUcG9uc42r3htrffgOyxlPqEBFdyXzX8yCs/QzjrzB7Ck2QRHqOCubN+vwdztrbf5ExY2U+yJVXBHtu1hmLXVLfiwuP1S1f/gjkzbXZiv5d2WWKkK/p3pvSMoHStU/R3+2e+o3a8TuTZgmdNAJf3J/bwFc7jQcPEVHlTwr36vYQap6wc/CrXghzoLS52mUU3D9HKLxd/iMXhgkO3CsiSpVbswtaoiqw2qRViWJLVqEaZWVmC1QdU9goVJUqrGYWp1j2EqURtU3htYmKRIBV+m/YBp1c3mV5ZboVqBhUlTqN7AtMoKqHao5mBh0hSqdZhWVRHVDtU4LEyaQvUQplUkodqhGoGFSVOoVmFaORnVDlUPFiaNolKg3FepUM6rlCjXVTLqQ7SW4bZKRr2IV56cVqlQ8Tqhyyo1KmI5rNKhQlYrNgWwVGrU6MfL4uHBx1FpUHvBXls2RDFUWlQQrIgpBh5dZUAFhx0xzaAjq64ZUEFwXUw06KiqiRO4My2LCp6JqQYdVVXcIpBHBR/EVIOOqLoGd6XlUcGhmGzQEVWbcFdSARWciMkGHU3V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' +b12 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAAQEBAgICBAQEBgYGAwMKBAQMCAgICgoKDAwMDg4OEREREhISFRUVFhYWGBgYHBwcHh4eDw8sICAgIyMjJCQkJiYmKioqLCwsLi4uMzMzNDQ0ODg4Ojo6PDw8Pj4+GRlLGhpQHR1WHx9cIyNoJSVuJyd0LS10QUFBQkJCRERERkZGSEhISkpKTExMUFBQVFRUWlpaXFxcX19fYGBgYmJiZGRkZWVlZmZmaGhoampqaGhvbGxsbm5ub29vcnJyc3NzdHR0dnZ2enp6f39/MzOYNTWfPT23Pz+8RkbSSEjWSEjYSkrcS0vgUFDuU1P3VVX9Vlb9WFj9Wlr9XFz9Xl79YGD9YmL9ZGT9Zmb9aGj9amr9bGz9bm79cHD9cnL9dHT9dnb9eHj9enr9fHz9fn79gICAhYWFhoaGh4eHi4uLjIyMjo6OkJCQkpKSmpqam5ubnJycoKCgo6OjpaWlp6enqampqqqqrKysrq6usLCwsrKytbW1tra2ubm5vLy8vr6+gID9goL9hIT9hob9iIj9ior9jIz9jo79kJD9kpL9lJT9lpb9mJj9mpr9nJz9np79oKD9oqL9pKT9pqb9qKj9qqr+rKz+rq7+sLD+srL+tLT+trb+uLj+urr+vLz+vr7+wMDAwcHBwsLCxsbGyMjIysrKzMzMzs7O0tLS1NTU1tbW2NjY2tra3Nzc3d3d3t7ewMD+wsL+xMT+xsb+yMj+ysr+zMz+zs7+0ND+0tL+1NT+1tb+2Nj+2tr+3Nz+3t7+4ODg4uLi5eXl5ubm6Ojo6+vr7Ozs7+/v4OD+4uL+5OT+5ub+6Oj+6ur+7Oz+7u7+8vLy8/Pz9PT09vb28PD+8vL+9PT+9vb++Pj4+vr6+Pj++vr+/Pz8/f39/Pz+/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA47wMlAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABQYSURBVHhe3Z35Yx5HfYc3xuCYkoQU2pCkCRRoS5NACKRHWrcQWtrSlqL79KXDJUBaWo42TeqCfMiyJVu+FFk+YlEITUvSxrIl+bZJaRNZliyIdQS95dX+Je6++352d2Z3dvY7++7su8vzi0ezs8fj932/Ozs7h3FLytfxb5b4Pv6VILcyMwsuMIS8WpXARQqQWWHnLIMr9RNuhf2yDq6WJ8QKu+QCXDKL0ArFcwMu20NkhbJ5AlfuELRCuZyBiwcBK5TKH7h+G78ViuQRGJTwWaFAPoGDBW+FzXkFFj4rbMwt0OCssCnPwISxwoZ8AxfXCtl5pyzjWCHTz9zE0I6uzdmio7tv5MISLtDPim0DK+TxFMd7arJKff8VXKWPV0o6EqvT7ThCRum+igvlKemUrZDBMt+HnbNL3XARF8viWuFvlqkW7JppuhdxuSzhVlPN2C/jdAm0Qq2u5UTK0goGQ1jhL4/CZuyTAwZxzQwhVoexRy44j4v2EFtdrcUOJOq3HDw9NTM7fe7IrlZkpUrbMi7bxbZC2qMf5SmsP7qAvSyKE9uRnSancHYXodV8HYpH0zzmv2Nc24JN6dG5gnM7CK2GUTqaXfPYhaF4rB5bU+MyTu0gtCJX/kawg4+rad8WhnFiB5FVsRGFoziKHQKkfQvvxXldBFbTKBuF/3+IYaoBZdKhFad1EVhNoGwEPaKapcMLKJQS/vqFZYWUyxiKymmYQXEx6Ub4QNAKWp1CUTnsj2pueGNTY9seNhTN0u8OCXADZ3WJadXofeiLexyDzovIstiNvFRIysqrUy52Isui4QIyTfMSslIhKaspFOakOK1NyEqDhKyaUDZQvV/vRsZB5KRBQlbbUdYs+G+4k9hgjiIjDRKyOoyywcI7sMG8how0SMjqJMoGQ12t8xVcRkYaqFrVNwD8DcZQVnC3dR+3lB49K0PVyq1B8FXeM8gV1O/dRh/8nQYJWQ2dB4Fmmw0oby4iIw0SsgpnP8qnehvWbuXenk8gIw10W21DcdMcQE4aaLaqu4biZqEJWWmg2cp7PjmDnFTQalV3HIUtdiAvFYhWLe1gFpnmJmS0lY8joo15bDyHvHQgWvlb2DwK5eMI2ME04i6vR2Y6aLOqPcK2zuxFbkrosmr1HhdNs7gPuWmhyWof+8pvaSdyU0OL1aZL2Ggzxz3zp4IGq/rhArbZTFehP0PyVj3XsaXMxTTrFA5JWzX7XokdT7V104FoNXoZuF+uK8jgHzB2823Bc6nWKDyIVi7SGlOz+0hcZrJa/RmStPK9aVxOswWQJzmrptPYAq5uxIYqkJhV7xw2lCkerUqYAAlZNflC32x1OxImZOW2B5YZZbZenAYpfngJWXHBb74XuTbuGfJtNcn3JMyD1ehZwHcNYazGt/O4z46VWdW2btzc0dXds237ls5NUbUwVasQfLdfIXGsals6dux9/oWJK3N8D4GZ0wd7+G8LR2atGnsOnb58g6v9+yhOj4Q9DmTRqqH7wNi0rPeGS1iftoxZ1XUOjk6RhBym9wu+iVmy2njokuwbF8YcdyOxyYpVbffINMqpM+aPiZmwqt9xkq9FqnLD9xxXfaumPWfCRq4ocJJ7pZuQ1eCpaETvhev6zsX5KQm4xGolZBWPlqHA6ePDalXRqmssoY8JMFrVsqofCBkuVQGeVnWs2o4IOlNXziWnyl0Nqy3jSrUHBY7iDOlbbT6H42qg2F0+R9pW7ad0fU4218s/rXStmo4GRqYkzHH7PGla1R8Sjc9LlqLduJWeVW2/+6ZcJzOlKkxqVjvcrj+a2WWdLCWr9cEBbLo4b50uHavBBGrlZDamY9WW3gdV4kQqVnv1Rz6OpUb9Vq1ncZj02K/dqp/p9pMWE5qtWiZwjFSZ02vVp+V5I5pWjVZ1L+AAqdOrz6qZ7Z+VLsParDa5b7rS56wuq51p1ib8zGuyOqz12TASLVb1vpffqaPDqjW8L5eYt773x8YXI3ny7qe2/hh7RBBota/cqjPwPyXne4/dblBZ/Vs/wl5SkrfqU2uaePVjxtsefurx3/mXSL72FfPjbzPu+DfsKCNxq361OPEPa1c/SfrvL/Pqg8ad/4O0hKStFKX+xrj3B0jSuHm/sQ5JCQlHC0WprxsfIf7+XV403vUzJMNJ1kpR6uU196hKmSt3G68hGU6iVopS5sOrXkJKgY8YLyMVSjFJK1WpF41HkFLhPiPy8y0kaKUqZa4y/ggpBW4a70MqnBvJWSlLme8ybiJlszS2b3dvgD0H+VkBtxqfQSqcK4lZqUu9xn0BL+xmX1dzbGGf1NYZ30YqnImkrHYrS1mnwr8WhQM4jpAG5uN679qfIhXOiYSsumK8wXnUeAUpczpizrs2twHkFeNRpCQEuwbEsmqN0bXlrbW/hJS5IBlGWGYUJa3KyFeRkjCQiFV9nPfx33arPsXocRfuCPFHCPdgc0ciVr7++TSeNLYiNYLDSOhB0ZtrouO6aW5OwmoIBdV43xrE9SJhHtM95aKkuG6azQlY9cYIf2xcpwy6PYGylLhuFhJou90crzWpxqhBaj8OJMNphqPEdXO2cqvmmG97vbi+AUeS4EySQYrr5uWKreqY6bFU8OL6dRxJxgGUJcV1c7xiK3caHEW8uF7uISHH6U5DiuvWESu06kcZZby4Thgk2ICaCy2umwcqtGqN/XLUjevLhFk7nTmdaHHd7K7QKvbbUS+un8WhZDgTSpDiullsqMxqL0qoozGum1OVvcNvp9ypfvjVJ4xffsTPnfriemlCtUqsortRrDz7fjQl+9EX10uT31VgJZhc28fL7zd+4fee+88f3fSzVWNcNzsrsVof+f37p9tv/9KbSPPojOsFK6jGtqqNrFR87bZ73IddHzrj+hVrl9hWzpc9lG+tuu8NJP3ojOv21LpxrTZGNVS8cdedoe86dMZ1e4qauFbcbCMiPmN8E6kgGuvr1oOwtU9Mq13YFsqbhhH66kJnfd1cLg0dimdVx883IuDLxlqkguisr5cn9ItnFX2resL4LlI2M8Nd7c0Ov6ExrptHSjvFsmqIbP5bec87mZ/2JD/Lzy9qjOtmV2mnWFbPY0s4PzA+jpR17b5A93mdcX3OHrsWx6olulb7tPH3SJmz/qmWP6szrpcngo9j5TRjSXjI+G+kCh3Yy+VXdcb18i81htWG6CFub66+F6ng9NFfeIfGuL5UHhIaw2oc+RKec48yiZ08/kxnXMeMkupWXciW4cX1YOz+dZ1xHRM+q1sRGgC9uL4YHCQcM64/iZSUAsbkK1u5c3hL8OJ6cI5RrXHdabJXtqKMjvDienCS288af4ttGuK6E5pUrTYiU4ob11eCS0VpjevOO0tVK8K9ionrU9jLQ2tcLz0G2yhaMQtshOPFdbuqyaE1rrtrLihaue9nZXhxPbj2lc64XnBfWipaUWbWqFpc95beUbNyl6KQUbW4bj+E2KhZkYboyOO6vvr6ZexloWTVTnqvXa24zqzpp2QVssIaT7Xi+jzzQ1WxqieNe6tWXGfPpmJFe11VpbheZPtCqViRBkpUK66PYy8bBavAGnRCqhXXuSkzFayiGwFLVCmu82sbKVg5P145VYrr/AzwdKtG0jxDVYrr83ynXbrVbvwpp0px3deSRbeidW2kxXXCgoDN+GqQ4vp1X7glW9WRusHQ4rqJqXhkOOuPkuK6f1F7shWlFYYa1wlLVrjrj1LiOlOvLUO2og3Ulsd1bCL8rlrcty6UuB74spOtaH27aXHdnI2YsHa92y2fEteD7cNUK0qLLTWuW5yXLjI34LWOEOJ6Mbi+JdXqCP6QQ4vrJc6Ezt5eu41tyCfE9ZPYkYFq5a5jJUUW1z/sxnWb4tk927sDbNt1nPuq3zTuRiqU5eB3nWrVjLQcaVw3+HFJNG4ZzBAZMcFvBdmK1Awjjet/FX19Ah4yvoNUGAui6aSJVu6KoFJkcf1zxsPYpsB/rPpNpEIRLhlBtKLN/yKL639h3FPepsDN+1b/O5JhXMDheYhWgWIiZHG95gtvN9TGO5vmWx+L/NIuiWf9plm1IClHFtdraj5kPER4+mN47QHjr5EMJWRhLZrVTiTlyOJ6Tc1fvsN49HVsJ/DjL61dHXkDDhs4Q7OK7jZiIY3rFn/6duOd65557rsvRfLMd/7usbXGA1G/KXMxbIwdzcpd0FmGLK7b/PkH0JWYwKpH/nkFRwsnGGkBzYo0W5QsroPP/8mHjQ/+ms3v/2GZ29f8AVIu96/+4rOU72qwVutAsmpDSo4srgfoKBc1XzI+gZQyC+Fj7EhWkX0cS0jjegDntv6U8Q2klJE0E5CsSBV2eVz34/TaePA2hbjIEfLjtSFZkVoC5XHdRxMe4N9Y9SvlhDLzshXDSFaR/VEtouI6T1+5qPmP0TdaMQXpfx3JivLiPjKuczhjtR83vo+UIvL2HIpVIxJSCHGdAY+GK3fdET0JjIiI5hyKVcX9YQJUGtfPRaytT7Hy1t4Ox4vr/NsJMc5o8Jhx/XoSayo5w8VleHFd0DgSwOm2ES+uL0a+UaFYHUJChhfXj+HIEpz/pnhxvShecYiFYnUMCQleXLfncZaz0Ymp8eK6dNqSMhQrwsIuXlw3F3DkUBrcVrhYcX0Uh5FBsYocv8PG9cj/yw3uFB+x4vpFwj2eZOW8oJXgxnUL+fd+r3dLjxPXpwmTYdCslPqvWywdCbtlNe9j+yLHiOvThJuhBcGK8JLxG8YTSJUpjB85fMjP0Mgk//9zm6Ea14lSFCvC471hPI2UAv+r3JpLlaJYEZ5D3muEDcyU8LTxFaSIkKUSsnqPIR4XLOP1O96t9jqBLkWxIvRgv9egzAHK8X8fNZ5DkoaCVEJWv829caPw1mOK0+ypSFGsCHN3v2is+haSNP7rAeNT0e19DEpSCVmZv2usMemt6D/89Oo1SBJRk6JYUWbx+eknDOOuxz/JvG0Kq9g8/Ml19xvGRyPn1uS4RKpReCRkZa48+yDakqO56wnF2DJKqfuxJPQNLPH6v94yn4nim+u2vqr0g7LqlQdxrXQIVumu3BJgkdBF1w/BitbbURfX4yyrT7CqypogDuejGl6EEKxOpbzODsvxiCayEChWVVtCoxDd404MxYo0kEID84TXEGIoVk5Tf8qMK956GShW65FIlYU9uMI4UKxqqrDa06Raxc8HyeoUUqmxSHmvIoFk1YlUWpyLnKs4ApIVbTRPUiyFdONRgGZFeSuSFBfW49IqgGZVl9qiYwv749UmeGhW7kgAzSyPxKr2BSBatVJeeFdKcbTSKOFAtCIOKauIyWC/9LhQrUjzWlTCZW4IX4WQrdq0Po9c94/KqQyyVc0A/tTA/KBqc0sEdCta18cYTA+GrrkRFwWrFtqoCjWKE9tw+CRRsNKgtTAi7rldKSpWSWtdGSCM8I6FklWSWoUxwuDGuKhZJaZ19bDw8b3rcjS9KCtD0aqmqfInyOL5/WG/JsrQIcpziqpVTU0vbYRjCEvj/ZIKbPWsappjLfVSYv7kTnl8qKJVvDWeC1dGuiMfnapqVVM/wC8gJqc4Nbqvk1Qnqq6VRfcYZQ6F4vTY/m56hajqVlaUHzofXo8vzl2dfOFgj2jQoYQMWJXYsOfYRfYxeWHq7OjwYG9nW7xKeEasbOqbWttbW5obG+oqbUlxrcbbObqnkG/BW22bAdwwjiSsksO14s+5m20S5616kct3Ys6BVRN/f8yfVcckYHq5bvddIt8WkAerIPW+KTPnfJXbXFp1+KZhPO2vRObQqvYQf6ef34UNHvmzavO9Zj8jGEiWO6s+/hXngnAcY86sGnyPp/y7765F4C5rUkDG4vPW5qxadfCjDmd9oa8b+QJKlYyMWu3k3sEUj/mr/bm0GuSmNb3KL3FRIo9WR3Fmm6WDgjpz/qzquZFRZ4XtUbmzamR7xC6HPE3lzaqWHe01E1i2A+TN6iDOWmIitIGgq+CAomYRfxeGrc1Zs2JWSyxQehHno27hrRZL6x2YC6sG96MKroQjJBdW3hq4Q8iJIBdW7iR7c8Smt1xYucNdiR9VLqyacEpvZZAo8mDlzpM5jQyPg7OA74+bByt3zonTyPBwp+/i61Dbb4ARZNhky6oHp+RnW7dx6/GULrkZ/QZeRIaH+8BPmK05q9Gi4O/47a25UFoRNIpsWXlzJJXqqCxu37BlynuXjFm5Lwr8d2H3ja29ImgUGbPyuuud4T4TbzqUUsNYJBmzYpYsYbU8qSJppEXGrNiGmHPOo0gH8wKLMjFX9qza3cZYi6nBno4tA+wjf9FbN0kGwSp4n9eJfN0wwrRIJQK9XIxbfq3wiSK1IBtvOE3sUMh+4CVWglYzKJoSbbM4b5AFyh3YIjAM7s2g1Yps/kENtIdpLdAe+gWLhNyyrPxaMQZXV0S7eBbGOaoU36JdQmRFWdMkURpOCBZFO03/ygTW9BNZLSn2RkqAHn+fNpXBCcGZAUVWpBWQkobt01acjJ6GjiE4xF5oNZP44AAK9V2DoxPnJk8d2KJ2+s2Br+8toZV5AjvkgTqmJxcIsVrRMexBE4Iph8tWQa05wjJc2aAvGD4tIbFVbrT6BP1mHSuRFvkeWE36BVIrEiuzMFRpT03tNAvn2iz5lK1EWuaVbMeM+gHhqAhbR2Jlmtf2JTOeVwPtR0KGDtg6UivrNj89dqC/L1vsHhiaCB28UtaBVahWzoCNY/Vz4gUXz+rnQQsmrFX+tUq3KhvWKvda0PBZ5VwLEha8Va61oFDCZ5VjLQjY+K3yqvUzXH6ZgFU+tX6CiwdBqzx64cJdRFZ508JVMwitcuWFK+YIsSqBvbINrtWHxApg9yyCKwwSbWWDw2QIXJgYolWuuHXr/wH2EmDI9i42XgAAAABJRU5ErkJggg==' +b2 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX/Vlb/WFj/Wlr/XFz/Xl7/YGD/YmL/ZGT/Zmb/aGj/amr/bGz/bm7/cHD/cnL/dHT/dnb/eHj/enr/fHz/fn7/gID/goL/hIT/hob/iIj/ior/jIz/jo7/kJD/kpL/lJT/lpb/mJj/mpr/nJz/np7/oKD/oqL/pKT/pqb/qKj/qqr/rKz/rq7/sLD/srL/tLT/trb/uLj/urr/vLz/vr7/xMTExcXFx8fHycnJzMzMz8/P0NDQ0dHR1NTU1dXV1tbW19fX2NjY2dnZ2tra29vb3Nzc3d3d3t7e39/fwMD/wsL/xMT/xsb/yMj/ysr/zMz/zs7/0ND/0tL/1NT/1tb/2Nj/2tr/3Nz/3t7/4ODg4eHh4uLi5OTk5eXl5+fn6Ojo6enp6urq6+vr7Ozs7u7u4OD/4uL/5OT/5ub/6Oj/6ur/7Oz/7u7/8PDw8fHx8vLy8/Pz9PT09fX19vb29/f38PD/8vL/9PT/9vb/+Pj4+fn5+vr6+/v7+Pj/+vr//Pz8/f39/Pz//v7+/v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/IkxoQAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABI6SURBVHhe3Z1pQxRHGoBhZhgmIIcgAh6IqAiIiCBmc+2VZLNZRUUO0exu9gxyyF5JYFizg47zu2f7eLu6uuvouvoony/MVPeM9dg9XfdbHe33Ea7VP1oF5t2XkEsKTKtP38Gni8z3kNk4DKsf4GPF5wvIcQSq1U/wCTv4BnKNQbEq9K+JykeQcwRpBWdaxWvIe0Dcyr4L5QPZB2JWb+Ek+/gDGHhEreAMK/knOLhErOC4pfwAFg64FRy1llALs4JjFvMdmGBWNtSQkgiqhsjq33DAbkAmsPoEkm3HtwmsINF6/Oc7WLHq6I3tpasjQ2eLxfDYzOo+ZJDA0wErSIqxd7PaWVSG7jcgl1HeuTq+FfX5d3AJvqCg1O42IacRQitIiHC/uNcp4Dz1Pgys3sB7jOYV+GSh6XoK2cUJrOAtRnMCPldwKhStN77VH+FtiC1SnZ3ldcgyhm8FbzCW4DMWUDuCPId8Rrfa64KP2MBlyHTIO9fq5/AmZBQ+gNFzeWF992B/Z3VmtAJJReER5DrEtSJa9dtwesj4E6xoOF48A8nFYBjyFeJawcuQSTg94PxLOBDQfFiDQ4VgG7KF+JxidVSGs30qtCL86DIcLQJXIVOINxSrR3CyT+0FJMe4A8cLQA9kKYRiNQsne9R2IJVgEc4oAK8gS4gOsr2IPwG7mFKt1m04J3+eQI4QHe2v4BWiB851uQdpNJqUAiAfFiBHiI721/AK0Q3nOoxDEp39ohTW85AhREf7t/AKEbZAygeQ5LI92VvtHpg/hLcuRflpzUF+EB3tb+EVIrS6AikOW8OQVp6sQ1KrVS/IxZKzegYprdYmlv/hUOsGJOWMlNUgJESl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' +b3 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX/Vlb/WFj/Wlr/XFz/Xl7/YGD/YmL/ZGT/Zmb/aGj/amr/bGz/bm7/cHD/cnL/dHT/dnb/eHj/enr/fHz/fn7/gID/goL/hIT/hob/iIj/ior/jIz/jo7/kJD/kpL/lJT/lpb/mJj/mpr/nJz/np7/oKD/oqL/pKT/pqb/qKj/qqr/rKz/rq7/sLD/srL/tLT/trb/uLj/urr/vLz/vr7/w8PDxMTExcXFx8fHyMjIycnJy8vLzs7Oz8/P0NDQ0dHR0tLS09PT1NTU1dXV19fX2NjY2dnZ2tra3d3d3t7e39/fwMD/wsL/xMT/xsb/yMj/ysr/zMz/zs7/0ND/0tL/1NT/1tb/2Nj/2tr/3Nz/3t7/4eHh4+Pj5OTk5eXl5ubm5+fn6Ojo6enp6urq7Ozs7e3t7u7u4OD/4uL/5OT/5ub/6Oj/6ur/7Oz/7u7/8PDw8fHx8vLy8/Pz9fX19vb29/f38PD/8vL/9PT/9vb/+Pj4+fn5+vr6+/v7+Pj/+vr//Pz8/f39/Pz//v7+/v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEN6WYAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABLjSURBVHhe3Z37Q9RGHsCbfYE8RUBARUBQFBEBxbZ3vWvv0bve9RQRxQW37fXaayvKo71rC2x7Ze26//beJvvdySTfSfKdx24SP78Ak2TJZ/OazHznO2/V30TCrL6sJZlPYS9FBFr9ChsnmV9gXxFiq69hs+TzOeyxF5HVf2GLdPA17DUPtvoM1k4PH/0Gdp2BrGDNVPEa9p3hs/oE1ksbH8L+A16rn2Cl9PEdGDTxWL2GVdKI5y7PW8HylPIrWNhwVrA0tXBarlWaT78m//sGVFyrH2FRmvnmbyDTskrrLd3L+2DTsoLitAM2YAWFqedV87nVtPoUCv1US2uz54eHksXw2NX7u1XYQz8fOD5NKyjycbjYYyWV/uUT2Esfjo9jJXz1OJnNwickk/z1U9hTD5+93bKCAg9PemHr5DK4A/vqwRayrb6Cv3luwpaJJnMH9pbnI7CCP3kWYLukswr7y/MqyCoVR8rhLuwxR/NYvYK/XJ7AJikg+xz22eW7D2wr+MPlJPk3CpehCuy1i3Os4HeXOdiAp3durbS392xtNnGPsFuw1y621b/gd8YRfk4NP2TP8sr6OShMCN3osfW7hhX86nILVmfklj31k+pSsh7P92C/GD//FVtV/edYVwmWMHYKsCgRDMNeubzCVruwcgsslTQtVCMUnIH3YN0Wj6HcwwYsTARbsFMMgdVVWBeYhWIf07A4CSzBPjEEVuOwbpPcMRT7OEzQHWMG9okhsBqFdZsEHKpEHazLsEsMgdUwrNvErezvXC50TT2DP2q1p7BCArgEu8SIssqxJ9Wmc8rlnsCftdPknILSVqNQWDvtahacYdWuoWZBApC2mobC2gMo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' +b4 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX/Vlb/WFj/Wlr/XFz/Xl7/YGD/YmL/ZGT/Zmb/aGj/amr/bGz/bm7/cHD/cnL/dHT/dnb/eHj/enr/fHz/fn7/qKioqampqqqqq6urrKysra2trq6ur6+vsLCwsbGxsrKytLS0tbW1tra2uLi4urq6u7u7vb29vr6+gID/goL/hIT/hob/iIj/ior/jIz/jo7/kJD/kpL/lJT/lpb/mJj/mpr/nJz/np7/oKD/oqL/pKT/pqb/qKj/qqr/rKz/rq7/sLD/srL/tLT/trb/uLj/urr/vLz/vr7/wMDAwcHBw8PDxMTExcXFxsbGycnJysrKy8vLzc3Nzs7Oz8/P0NDQ1NTU1tbW19fX2NjY2dnZ2tra29vb3Nzc3t7e39/fwMD/wsL/xMT/xsb/yMj/ysr/zMz/zs7/0ND/0tL/1NT/1tb/2Nj/2tr/3Nz/3t7/4eHh4uLi4+Pj5eXl5+fn6enp6urq6+vr7Ozs7u7u7+/v4OD/4uL/5OT/5ub/6Oj/6ur/7Oz/7u7/8PDw8fHx8vLy8/Pz9vb29/f38PD/8vL/9PT/9vb/+Pj4+fn5+vr6+/v7+Pj/+vr//Pz8/f39/Pz//v7+/v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1va/bwAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABBfSURBVHhe7Z35X9zGGYfNch82YGzSpk2TNGma+Ai+MLZjYzAG47Q52qZJm54QGxuDgaZN0iQ2tnFzEUgccNb736qS9qvRMaPd95VGWg0fnl+8Gh3MY2lX0sw77+yx6vGiZf2mSDz11K9+gqrFUsvqX08qBebTZ1FNBXFWz3+PnYvMkzdR2yhqqw+xW/H5H2ocRmX1MfYwg69R6yCy1XvY2hw+Rs19JKsfsalRPI/Ke0Ss3sFmpvHRKxCoErb6FBuZxyMYVAlZfYdNTOQJHFyCVo+xgaHAwiFg9QPWGgs8bHyrb7DOXPyLUFiZdetV8+ivkPGs3sIKs/nomaqNZ4Vi03mhagOrRyg1nqpO1Sr2+ludPXtooL9YDAwOX1neRgWjfPK0b4WiCBuT+5qKSufoGmoZwfVxrf6GkhDbo604QjEpnfoWNQ3xzW89KxSEWOnH3sWlcw51DeEIOVaqB/WZZuxaaM6htkG+eq5qhcUgV0vYr+CcRX2D4FxhKcCsIVLKs/V710p+VrrXgn0M4Drq7PPkXccKCz7lA9jDBDrXUWsf91zhs89l7BDlxho4i4JCcBK19nnRtnoFnwXlbmwf4RDWVzbbUVIISg9QLcEXttWX+Cy4hs2j3ML6yjgKCsJ5VMvn/T3yBXgIW0c4iNWVzQ6UFIQO6ZnwsWy1FXP/ncf6ygQKCsMSKiawr0B8Eixh2wgHsLqy1YmSwjCJmgkUVpPYNsINrI79hWwcp1AzgcLqDLYNsx9rK9tdKCkO4jLyUFgNY9sw4hY+hYIC0Y+qCRRWp7BtiL4y1m7H3MwaSS/qJqBaXcPKyjQKikRSq17vVJX3oqRIJLWaxbrKDAoKRUKr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' +b5 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX/Vlb/WFj/Wlr/XFz/Xl7/YGD/YmL/ZGT/Zmb/aGj/amr/bGz/bm7/cHD/cnL/dHT/dnb/eHj/enr/fHz/fn7/t7e3ubm5urq6u7u7vr6+v7+/gID/goL/hIT/hob/iIj/ior/jIz/jo7/kJD/kpL/lJT/lpb/mJj/mpr/nJz/np7/oKD/oqL/pKT/pqb/qKj/qqr/rKz/rq7/sLD/srL/tLT/trb/uLj/urr/vLz/vr7/wMDAwcHBwsLCw8PDxMTExcXFycnJysrKy8vLz8/P0NDQ0tLS1NTU1dXV1tbW19fX2NjY2dnZ2tra29vb3Nzc3d3d3t7e39/fwMD/wsL/xMT/xsb/yMj/ysr/zMz/zs7/0ND/0tL/1NT/1tb/2Nj/2tr/3Nz/3t7/4ODg4uLi4+Pj5eXl5+fn6Ojo6enp6+vr7e3t7u7u4OD/4uL/5OT/5ub/6Oj/6ur/7Oz/7u7/8fHx8vLy8/Pz9vb29/f38PD/8vL/9PT/9vb/+Pj4+fn5+vr6+/v7+Pj/+vr//Pz8/f39/Pz//v7+/v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3CowtwAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABLMSURBVHhe7Z35X9RIGodNQ4MCcgnuzO4K3gLKCIojqLM7s9esu7Ozp6jgBbjjXjOOAq4zgzAH7bb9T/cmnW+/qaTeqlSuTvL5+PxCUlWd1EOnk0qdB5oG/KxINJvvIltqdFafvGkUmJcaOaXVV/hwobmJzAbhrW7iU8XnW+TYD2f1J3yiHLxGrkVkqw+Qujx8hZx7SFbfIGmp+BUy3yZohWRl46ufIP8ufqs/I1H5eAMDF5/V50hSSuDQQrQqxSNKDSwcBKuXiC0t8LDxrP6NuBIDE8Hqt4gpM3TLICtElJtvINO2QnDZ+Z1rA6v/ILT0uDqwQpjE1p2Lk2MjxWJ0/OzVtX1kMMj3LR3X6n8I81O7dcQqKtXzXyKXAVo+rhVC/CwdwhEKyuRzZNTHmw/bVtyb/NYEPlxcqkvIq4932lbYF3nYg48WmpM1ZFfAeWg5Vt9hX+BhFZ8rOMcZLVhhT+BRSaRsrTqy7PF5y+oj7Hns9uMzJWABeRb42LF6jR2Pc/hEGeh6ikx7tL4rbHvcc9PPbYdx0k2YL0eQa4+/slbH3ORXsKvmrJswZx4gN8Qb2+rX2Ca+ROqyWJ1Ebjz+cKD5NTaJ80hdFqvKFrJD2N8VtjwGkbosVtYNZIdgrHaRtjxW55Ed4kPZ6gHSlsdKugt+KlstIW15rHqQHeKJbHUFactj1YXsEJ/JVgtI61lNdyuoIGXeIJ+EkVXhC1DIJ/GPt1aFBfkk3loVF+STeGtVXJBPwshqugoK84AKgHwSRlYCL1YvTRZPDZkjolo5bM8XrVIXGSPiWDUa+3PF+r6QLSKeVaOxPoREhQCZIuJaNfbGkaoIIE9EbKtCaSFLRHyr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' +b6 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX/Vlb/WFj/Wlr/XFz/Xl7/YGD/YmL/ZGT/Zmb/aGj/amr/bGz/bm7/cHD/cnL/dHT/dnb/eHj/enr/fHz/fn7/gID/goL/hIT/hob/iIj/ior/jIz/jo7/kJD/kpL/lJT/lpb/mJj/mpr/nJz/np7/oKD/oqL/pKT/pqb/qKj/qqr/rKz/rq7/sLD/srL/tLT/trb/uLj/urr/vLz/vr7/wMD/wsL/xMT/xsb/yMj/ysr/zMz/zs7/0ND/0tL/1NT/1tb/2Nj/2tr/3Nz/3t7/4OD/4uL/5OT/5ub/6Oj/6ur/7Oz/7u7/8PD/8vL/9PT/9vb/+Pj/+vr//Pz8/f39/Pz//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACfdmegAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABMCSURBVHhe3Z3nQtuwFoCvk7DLDLNQoGxoWQXKLrusQAPkXvv9X6TXTo5l2Ro+Gknsfn9KFcf4I7GscXT0n7//InIrzyM/ZIDoSuo/SRBb1d+eaeBCOYis4I0ZBy6WgW8Fb8oDcMVxeFZwfE6Ai47BWsHBOQIunIKxgiPzBVw7IWkFh+UNuPqQuBUck0NAAIhZwRG5BBQa0Fbwek4BiTqUFbyaW0AjILKC13IMiPj8S1aRFrGCF/INuPxjVqFWaAWlSf6cf58eHRnOFCNjX7Yu3+ACkzRswArK4rjnU05WKc7dwFXGaehIrM764QwZpXwLF0rT0GlYQRHN21d4c3YpbNTgYinqPnUrKKB57IO3ZppyFS43Qmb12AvvyzjDjJbE6jknUr4WUxmGVvDfCHcU3pMDvsI1E4RWW/COXHAGFx0isnoqwhsohhf3b58qD7eHs51QkhV63uGyQwRWy3A8oWP5AV7yqV2tdUB5NvgBFxbSsIL/EN4SF11YS96RlWl4KRMMwlURuFY/4GhggNc0Oc1SJXkJFxXCtYp/EFMfUBznLUPV5DpcUwjXKvYxCKQ8rzoIR7SfSbgkgm8FPxFe4Ng64yIp/+bKTJuq04VLCvkfa3UJxwZ0VqCQx0MXHNV2XuGKCKzVORwa8BPK+CSqlfbxDBdEYK1O4VCfCSgKqB2O9XR0zxxQtXxtAI5rN49wQQSp1TkU+Wx3Q1kvaaG8rJSgrN0oWfVHd+EqFAV8r5dkx0nRahtK4lKOs58tJ0UrMi5wAwVA8TpTTmpWRTIqMAclWUXFagQKvFdOzyRTqFjNQoF3CAWZRcWK9J13oaBQKsBPGUPFagEKgg5/cXzzNuhz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' +b7 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX/Vlb/WFj/Wlr/XFz/Xl7/YGD/YmL/ZGT/Zmb/aGj/amr/bGz/bm7/cHD/cnL/dHT/dnb/eHj/enr/fHz/fn7/gID/goL/hIT/hob/iIj/ior/jIz/jo7/kJD/kpL/lJT/lpb/mJj/mpr/nJz/np7/oKD/oqL/pKT/pqb/qKj/qqr/ra3/rq7/sLD/srL/tLT/trb/uLj/u7v/vLz/vr7/wMD/wsL/xMT/xsb/yMj/ysr/zMz/zs7/0ND/0tL/1NT/1tb/2Nj/2tr/3d3/3t7/4eH/4uL/5OT/5ub/6Oj/6ur/7Oz/7u7/9vb28PD/8vL/9PT/9vb/+Pj/+vr//Pz//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYmWdhQAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAAA2DSURBVHhe3Z39Q9M6G4bPGN+ICA6Rj6PgJyKichT1KIKCeJCPF5Ct//9f4ru197q2SdsnyZM24frFrUtKLrfdzdok/evPTYRoFTgEmlREgRV24iRoYh65VqjuLminlBwr1HQcNFZEaoVKHoAGZ5FZoYYnoNEpRCsU9gg0PIFghZJ+gbbHZK1QzDfQ+j4ZKxTyEAhEpKxQwFMg0SNphVe9BRpdElZ4zWMgkrTCKz4DkxtmFWvFVtjuOZDpW2Frlqv9rb/n52adYq61vLl7gQZmiWwKrQ4eNhuusrjbQSvThDawwqYUh3exA0eZ/oKGpgh1IitsSdLeGEJtd1m7QmOTFFldzKGm00wdo7kJCqwuZlHPcSZFrdgKzwdceSLV1TpBkwfkWq2hjge0hCjMs/qCGl7wGo0eEFnhSczvibD43Fk5T8KStdL8hWbHyK22o+LzeFrEelS0Vp6iLTGhFR7HdG5HpX2xGhGOWjKrPZT2xaqxjcbEyKxeoLA3VitoTIzMagGFvbGaRGMGiFadURT2xqpxhtbEiFbnKOqR1T5aE/OX8AH8haIeWe2iNTGi1TGKDqy+DGf5hFeC+yhbL5/RmhiSFTbEjF/jlfh9rRceq+d4IT4I1AyPVf9HTTvqMNYOi9U9bA/+xYa6YbH6iO2OZAWPlWtZwWPlWlaoWbV+g0/YAFzLCjWrHJzLChYr57KCw8q9rOCwci8rOKzcywoGKwezgsHKwawwtxpvo5RDWWFutY5CLmWFuZWLWWFs5WRWGFs5mRWmVm5mhamVm1lhauVmVhhaLaCEY1lhaOVoVphZuZoVZlauZoWZlatZYWTlbFYYWTmbFSZW7maFiZW7WWFi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' +b8 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX/Vlb/WFj/Wlr/XFz/Xl7/YGD/YmL/ZGT/Zmb/aGj/amr/bGz/bm7/cHD/cnL/dHT/dnb/eHj/enr/fHz/fn7/i4uLgID/goL/hIT/hob/iIj/ior/jIz/jo7/kJD/kpL/lJT/lpb/mJj/mpr/nJz/np7/oKD/oqL/pKT/pqb/qKj/qqr/rKz/rq7/sLD/srL/tLT/trb/uLj/urr/vLz/vr7/xcXFwMD/wsL/xMT/xsb/yMj/ysr/zMz/zs7/0ND/0tL/1NT/1tb/2Nj/2tr/3Nz/3t7/6urq6+vr7u7u7+/v4OD/4uL/5OT/5ub/6Oj/6ur/7Oz/7u7/8vLy8/Pz9PT08PD/8vL/9PT/9vb/+fn5+Pj/+vr//Pz8/Pz//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbZCRbQAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABOaSURBVHhe7Z17X9NMFoDtjbYgyE1WkFduioIIAgLLRXhFeHEvgoC7C+Vtt/n+H4Jt05OZSeZMcs4kbRN/+/wjnaSYh6aTuZw58+Qxmr/Av9mBYOWkDrgwM2Yr+A3pBa4Tw2gFb003cK0aJit4W+qByw2AW8FbMgFcsg/MCk7PCnDVKroVnJsl4MolmhWcmC3g2gVBKzgta8DVe/it4JwsAgYdfFZwQjYBBxfVCg5nFbBo8wtZKVqKFRzLMCCiWsGRTAMqv5iVpyWsoDhA/Xxr4fn4WLqYnFk9uoELDNKR8ayg0M/lcimXVib3G3CVflwbsIIiHz9m4BeklOonuFA/bR2z1af0fk4e09h92NbpWEGBQuM3eGeqGfgKl6sQYtV4Ce9LOSVcC7dqZkSqpXUGlywxWm3AezLAUA2uWeBZwUvB9wK8JQsswkVLDFbj8AaVsZXDy5vrs6351FWNX+CqBR0reCE4hdMVXsnbt7Y9BIUpYRouTIBbzcLpguoxHOlQW4LylHAJ1yVoW8GPgps8nO0xegdHBHvBU/rKMlyV4E/Eag9O9tClHGc/TVojcFESxGoZTgZK11DuYxWOpgKtckesJuBcYAeK/TRG4XAaOIWLEiBWA3Buh1EoDfIFjqcBrfGOWPkfwfhH1WpUjcAJKWATrkmAWMGpHYoPUOo4n6dK1bey7f8RzkgBG3BJgieP/4GfBHBqh+dQ6LUNh37AS+fcfZ0KEKt/wU8COLXDWyh0vkPBDLx26ump3NlW21DovIWCnLgH09NwYluJyuIVFOTOocAZhoL+w7YS1cs7KMjfQoFThZL+w7Z6D4XOJRS8hNdOswgl/YdtNQGFXk3+VLSf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' +b9 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX/Vlb/WFj/Wlr/XFz/Xl7/YGD/YmL/ZGT/Zmb/aGj/amr/bGz/bm7/cHD/cnL/dHT/dnb/eHj/enr/fHz/fn7/gID/goL/hIT/hob/iIj/ior/jIz/jo7/kJD/kpL/lJT/lpb/mJj/mpr/nJz/np7/oKD/oqL/pKT/pqb/qKj/qqr/rKz/rq7/sLD/srL/tLT/trb/uLj/urr/vLz/vr7/ysrKy8vLzMzM0tLS2NjY2dnZ3Nzc3t7ewMD/wsL/xMT/xsb/yMj/ysr/zMz/zs7/0ND/0tL/1NT/1tb/2Nj/2tr/3Nz/3t7/4eHh4OD/4uL/5OT/5ub/6Oj/6ur/7Oz/7u7/8PD/8vL/9PT/9vb/+Pj/+vr//Pz//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQLQ3wAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABNHSURBVHhe3Z1pQ9s8EoA3CQQKFMp9lqaQQqFQyrm77x4c5aaw5Sbk+v+/ouskE1m2RvJIchKL50uDbKd+EsfWMRr97c9bhG5VTQ5wRnIirOBtEgicII7cCo5OMHCiCDIrODDpwNmGkVjBQQ4AJxwEs4L9nQFOm0O0gl1dAs7cR7CCHR0DTr5J2Ar2cg44fSBkBfu4CBjUCVrBDm4CDjUCVrDZVcDCg7eCje4CHgEr2OQyYMJZwQa3ARdmBcWOAzIRVuXrnYWJ0eFkMTq5dHAHJximIdO0gsIgT6u9qaQyuPUKZxmkbqOwevmchndIJtlvZTjTADUbsIISnuN3cHRyGb6Bc+Wp6UitluHIRJPZh7PlYVbwN8cSHJdw0ntwvhxyKye+qRrpAzhjDrCCv3x+wjEO0H0P5+wjsXpJ7g1dZLwCZ81oWMEfPjk4gKNnZu3k9uHh9ufKVDcUJYVNOGsf1OpReE6NHXCPhuL2EBQng37xy8KsVmD3Jh+uYAPjuA82JYKfcFYMzKrcA3s3SK8gj/DXz7A1CUzCSfl4VvCK8Qt2btB1BsUhdpNTncoIHztitQU715FJVat7ydH6BafEQKz4iystlfK+Ldin82zBGTEQqzHYt8YqlKHMw04d5wucEAOx+gD7enxA6/pNXpJSq1+AE2IgVtzTiL9gb/MD2Z7BlUf4s8YB7NZpPsP5MJRW41DicTsJZem5ZyiqViv9UNhhEKv/wSuGb3UIJZ4UVzMc9LXWoajDIFZ/wSsGs+plvypeitd6ScbdHbH6B7xiMKs5KKhWJ6AE8H+d3J2lgyBWf4dXDGa1DgXV31DQpKsAG6oLUNJZtKzYE3gRChgbsKG6DQWdRcuKtTKFGvoEbKieQUFn0bJ6goJqFxQwPsCG6iUUdBYzK6H1OwwbqldQ0FnMrkDhYctaNA5anUCB2DnIKskOWq1BQfUeCppki7DBRasZKKhWp6EE8Gv+Dlr1lKCk+jgARXVG/TEWB61Sfic2r8VJOWk1AiUej58yjbLuPD8a5qJV6hyKajyvjQ0OTWwGR/ictBpgNzsJTlql8lAmw00rrjmM4qhVWq3lqBU6mOfjqpV3DB7YUMddq1Tfz9AIUfkIXrhs5d3hN1hPRbV6szHwHl66bZVKZUYWd86vLk/3crVu6LdiFYRVpS6goLPEZMXaKCdQ0FlismJ3++9Q0FnMrLJQX2/yjnVVf4SSzmJilf1WCHVcsKZ/NdCa7Bj6Vp5TtVoKdLR/9EcVoKTD6FrVnTxeuWFVX6qah6IOo2m1yh6+lR/Q1Tm45Uu9JiT4R9NqF4pqFI/zsx8Xz/jK0xrs1gqy7z+MjI5NTE5PjY8MRgyTaVq9U7aFb0K3xhjoej8xv7xxcHEX/I9LV5u5Ibma7u9qVoh88ikPw06xMJjbPLtVtA686/1sXvIx6lqJg/6MSmwjcgPzG+dKH8bTGhoMoW0ljSOJR6pvbv30Bd6RRPmAD3IB9K1Sa+hFWLIPOuua22NjSTocCZGmBlapkWvYwHE1CBtN6f38M6pXTsrLHLxJExOrVHo5dAJPy3YRCQPLF4q7EIGDYAijkZX3yS4csZ9z+fyjldPI2m94JwueZuDd6hhaeWQm1zZ3d7e+jAqDxDoMbPBxUBZU+Ihnc6s4mDq2u/B4eK0OWmWXZHOmzOC0OmY1JJkuZYGv1Rmr9Bw/ZBQblWYwaSessisP8M5xU4SmePutMstaNSI9oOOu7VafWvU9NWh0qLTZagqpbMVK8X3tv2mr1bAiGD4uLmv1nDZaDezH98hVUOsQaptVzw8WgtJa7rz/rF1WeW5kqMVMtcuqvyUPXQnHbbJajL1ypKIy0A6rvlN4n3ax0QarXPt+UUAh02qrd8fwJu1krMVW8y2s88lZaqlVb0R4UKvYb6XViFHvXgzcttBqvk2VCZHKIrxgxGbFpsp0gO/wLyMmq25hfnU7EQLI4rEaiKHj0gI2naBJLFbjHbmh+wjtuDisFvyR4s4gVKbtrdJifgmB0tXWt69L+aWVtd2bFrQlL+FfhrVVNqIZX77eXhjmhxu6xpb2b2FjTFzAvwxbq6wwsz+ALPvWYCgu3o64r0C1lGpMqDsf3xcW891CJVXZjZp2OxlXS0x4HysrldT9OOykQhWorEGszyuV1BYtGKg/lq8rTiuF1GMzF0E0i8aD3j5Cdc3cSiF1lIV9KAzY91oLOdyMrRRSB3qj4T3WWkiGFTOr+KRi0PJjSwFDqy4h8RRDW8peaxn+ZRhayXsoDKRstSpI3hgTq2+wq8ipiZSnZTN49xJPv8WctN5dME2AJmb1onMTi9Ww/BGD5OgjQmjPyDiNw6pXHrRjkSMSydlIZTcGq4zQRmNYpZ0SczZSWYvBio+bDiGfX9E7vXp0dnG6vzQurx+ytC265O2thGeDj2wyViA0pnwoq8x3m1bg56ytphXXySfYJ8Tn8O/wOpQIqckP2K7LqK3VoOLzfEbjsvuEZoLHJhpkyGbgadJnaZXBEjc3QWcijOODdLdohjTsA4immLa0UnWml7EH8Ljs0XaPaflpQnS4tBxBHVXdfLG0e2Py5/U98iGkjZ5ZP+ysupS9QlOwF0dWFWR7CjvxKFNLyvhkZ6V8oFSQB9EObMMR8oxxObl0GLSyUj/8kWlzETXWongNZg3qF69WUSRd6ot+D3bjiOo/Qm6aBj2f51ZWQudAkC+wm88gbJGCPOCw3PgRfLexmoy4OMSpNtFtC7EysgRbNPAqn8ZW3RGN1bJYW4gefxTzAI/BFg0GLKzUtzPsZtEd/csP55D0DoItdF68o0ytIhvgwZTaNbi0sjIq4hcMW+jUHnumVpF9QGLyBPncQR9xZqR20EbtRmpo9Qk2yRFrCpQfvniL0Y5Ym/UOMrPKRPdrxWWlGw1Qqc0vM7NStH+biFegEIaDIF6Bft5jGt4z2NAqS/gAxbvFFGxRIY6d6FrVJx8YWQlhQgjiTboHtiioRW2H0LWqz38xseqj3JdKYu0nurGENMk0rW7qB5lYKbrKOMSfSPRxSCIJTatGBdnAaojWOhCneo/CFilFZEhS06rxWRpYEeODkYzSisHwOoHFMAA9q4fGQfpW1ObpNezPEfHsrmDzw/WsNhsH6VvJBxWDlJHeQHWzEe1p07OCUAFtq8gfBwPJZdCnqv/gOT+0rAowBKhtRW+cYr+Sj/I7zSseD6RltQ8H6Vr5Sx9Egt3RUjmZ1usI7BFCy6o5BqNrpdNBhy6wJ9EqSKS0rIrNzjpNq7RO4P0dOtA9inUbnUoXItGxYg8TTauPUEQjlEMb6NoIX8UFpH+ziY4VO1FNKyH0U8kxHBWmd5X/ym8WVLkkNKzqjZA6elZseQMaFWlIYHp86eD26eXxemcxIt2RhpWfZ0XPKqpjKcy9fYYwuhW3pp+WlZ8ynwrUYCygW63CER5aVoSGfRh6tKMEslWJC77WsTIZI3uwvQbJVvxohY4VpeNBYAcONoVsxT/Gday24W890Jo4HapVILZDx8pwQp+dFtUqEAamYUVvg4Sw0iJaPQeaMRpW5lP6bLSIVtxt3UPDymIax7pZQGcNmtVz8FZLtzINv6lzWU98YgLNKlQ9plt9hb/MKH4x/LpIVuE2D91KHttI49wsbTHJyjh/YC+tb1NBcTlqXkX/nljJp1gJC6SRrSgjhVGol8Ie3SuFV0z0oFgJnwXZKqaMDudz+O+rO1fv2DWyEkOWqVbdsU2qf9pfGgs2ftMjqxfQ6DexQrp8qVb+sppxULnZzc/PTk1MziysH/7iwkFFq+gBQKT+TLUyDYHVZLRxVhyREcVFJLqcaqXXDWOM2H8b2auKVceIVukYpuUREEcc0rBFyhPWLCVaDcHLFiMOkUcOJqN9jkQrYbfWIA44REUW4eu6E60iYgHjIpCKt05E7fMRr64QrahDcXbci09odZagiqQLi2aVjucZHBUntAwnxaE+BBsiq0GzYkvS2nAy2qMOtXoSL6de2IQj7RqmWVFCkCI4qT1g/ZVFMcRfVWoaNqHIu/FpVrr96wJ1J+/poxp/xW5nyr6SH7CTCM3KcvouOHlk5KP4l8jllFHVbe/kA0Qkq4xVdhvfyaNb9gFdYvdoVYBGRawzMkhW3PKn2gScPN7hNcpT9MGjeqCo1qQiWemNm/KEnTzSSD7LIr6+j+rTPFf17pCsDELl69zgF0lfqF1dPpB01PgL/wrcBxc6CEGyokQ5YjzKfs/Dq36g1gO+0IlHr/zZ/+rVdxSQrAwmazRAKgtN3i2sb+5sfpvGExnVkS/iWcGjAxgkK+Nsta9mfYANFJ0KX2EXGSQr8x525W9aTa+8xwKZBBWEZGU6G9kDjfohwRYhFbhEg9N4KFY2j6uS6Uo38gfwY/TkfoqVsooZxZ3idqDgvbR6X4wIO6lBscrBv2b8MhnFfy+drFqhrAhJsTIIs+A5jfwZCMilqiuwixKKlXFGBuBQV0shFRwplUGxUlRcaFzo/baspUhWZnP8ee7VFZwg4/IICKIUycp2lNHjtTbXi0TXD/nwH1WKZBVLt9khLYXMmGKdJbIUySpqIgSNwkJ07SnzXTFOS5ciWakyc+hwJRlnbNKdVy2IpSFFsoove/JdXt6DEpFFVUeKZGURFCPwsj2DiWVmI7LkakmRrOJdKK1aOvkyzt060h8Wtn9FdGKVNdctpliZp+aS83p9uLO1ub13eEnowi/oxrm2+wo04VY7CIpiZdlza8tJVEiNCMWqPYNXMr4bdBJQrGJK9r+ZiUaonJWMEhBSrGJal0E+hOET7q5+VnSmK6BYRSdIIGFgdW2Y/5JiNWw1JMLQtzqQ10TUUKyG4qkI6loVzHN6kqxoU9Sj0LQ6Nc2+6kGyysMLO7SsXq3WNidZ9VtHp9Yo3EXTrD6dS+c5kiBZpdq8PI1kkI4OzcpoNo8xF8bB701oVjbzDnQpWa7XXoNopQ7/iJNz24X1axCtjFPPanITMYhIhGhlnidYh8ec/cVXh2rVFXMzH6HwVX+YQQLVKjUWyzNLTmlDGWugB9mqtddgZc/usRuCbpVp4d39JGoFH03oVqmReBokAuUDJBeLHRpWqXwrflpP32jDClroWLVA62I+pnt5EC2rmLWKO4TheCP0rOLUul+O8VYeQtMqLq3i0YzNpZcZze+dX12c7H3CPxldq9S0/UK0zzszVrWIwS2/Vlq5XEWedNpWqR7juLo6d98t7+PvT0OXS2lF+Nr1rVKpOcoMSozK1Yp1O+MLMmdKiBk1sTJb4/n5eNH+yZTBJ41WQhEzRlap1NC2zjSzwtn6XCz1PHk4fHDKuqFVKpVdIrVNXi825q27IZqk5TH+lcD0bmMrj+n9W/l9vnR/cbiRG4q16qBKslbip6/aWHlkJ74e8gOs5Yero82V3NSQ/khaNOr+fj4g29KqTrq7t7+/r7enu6sllToGP+b5tDo2ODS7w9+NuWH+OKzaBNcped9cJbbLD6Y5456DDln5N/U77hEx0ejEPgvMxXLHyu/s56VSqVmvPOjkkpUf/RuqSfwIO7lkxSb3hqdKI7cod6xYfARhCNIdKxbgTogkd8eqOWBXgr9VuGPVvAUWvNfds1s3j4XC4+n6HNoYdtAqnWvmY6lR2kW6dNyzKgl9yGKyXPesEIQB/zdhJcwLfyNWIa23YhVckODNWNXX52nisFWo4Jl7crlqdf4xm870LfO9C1wOLTetLppjk+kZv43PJSd20uqc63gZ8rX8rk4XrS4CIZ6+FiyR4uGgVTiznp/RgdWcHLQKr4Lm51dn/bcOWgmTCVl+63UocNFKGNFjyRXY8lnuWRXhbx+2HhJL0OmOlbyFz/LWOWjFemOEgYl52MCW6cGs/gmvGMmwYhNjhJhwlgmDjR8gVn/BK0YyrNg6vo0F8Xz8rmoWCIpY/QteMZJh5fdIhzqg/SlHrNaOWP0HXjGSYdXHOpYeAjl2Zlm5v+YbYvVfeMVIhhWXSIbX8qW4H5xDVtwyfY/NBYverflSL36lF7FK6D0wmMvtZWN6dHzukOvurH6D3TwQq3/DK0ar4t10GVROLeYX2xNyU/7tzx94xZAmimw3qgQ2Zf6zF3ZErBQribWXtDzzVCVwksI0OMQKz//bCaRaleDcJiHLA2IVfph3kDSep64cvJy6WG2jiWcV1qrEGkFvSQ5JqvU7dD8Ts9khVsoUmG2n7zD0TRTWwu1IITPgH8yKe74lgf51LtDnZlE4OXFNP9RKlbOxMwzmNn+enh6tzWKBlEJM5p+6laBlnC+vE4gZXyVW1avWRpPFSa+YIxKsRC1ZzvDE0RVKUODh+UisXNFCpHwrRGsntvl5LaQXl5JbVX/LlgBODmikfU0HrDCt8nf7gPRWMoRWp+o2CivPa38sqTdDafatuk3TCteqVosXG4u5+WSRy29f861inoZMlJVjgAyzehNaoMJZvQUtMOGt3NcCj6CV61pg4RGwclsLHGoErRzWAoEGIStnteD0gbCVo1pw8k0EKye14NQZopV7XnDaHJiVW15wygFwK3e84HRDyKw84LgkA2cqoLDygIOTCZwjhtqqDrxJUoCzUkKwco4/f/4Pv1V3CjSDb48AAAAASUVORK5CYII=' +g0 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0dbp1drp2eLt4ebx5erx6fL18fb59fr5+gL+AgcCBgsCChMGEhcKFhsKGiMOIicSJisSKjMWMjcaNjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cnc6dns6eoM+godChotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatrtausNewsdixstiytNm0tdq1ttq2uNu4udy5uty6vN28vd69vt6+wN/A0NDQ0tLS3t7eweDBwuDCxOHExeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e5+fn4O/g6Ojo6enp6urq4fDh4vDi5PHk5fLl5vLm6PPo6fTp6vTq7PXs7fbt7vbu8PDw8Pfw8fjx8vjy9Pn09fr19vr2+fn5+Pv4+vr6+fz5+vz6/Pz8/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiD0LYAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABGuSURBVHhe7Z39XxNHHsebYKiI2uJD42FV1BYLRcUHUHwAaVEK9YHenVQtLRWxoJ53Jz6gcBXhOGLIH+1tsp/Mzu487MzsZDfrK++fYHY2mTchu7Mz3/nOJx+UKNUNaJAcJav//Puf9cM//v4vNEtMiBX+QHUIGshHZoXz6xY0k4PQCmfWOWhsEIEVTkoBaLAfrhVOSAloNA3HCpVTBBruwVqhZqpA0wlBK1RLG2h9lYAVKqUQCLj4rVAjlUChgs8Kx1MKJMrQVjiaWqDh4FnhUJqByUdvhQPpBi7ECsVpBzawQmGQzfmxk3u2NefqiuZtX/SOP95EE/24NrD6Lwr9rI3vydQt+RvraKaPig6sUOSjOL4VL1CntEzwPq+KT8XqfyiheX0EJ9cxx5bRWArPCgU083X+Qbm0PkNzKSRW6ZDialWt8CvFs5RIOVov0WSC0KqwD+ekgINFNJogshrEGQGyuSx+qieuodEEgdUC2/hc98jMinPo3czV7maU1QlbXrutJgis+lCf0DZaNqqyMroL5fXBJbSrimuFXwgrgQ+jeTz4r1u8Xk+f17YNNKsK12oMtcEh5irj8KoDR+uBn9CoKlyrblR2OclcYyoUe3G8DjiNNlXhWn2OyhUEUnWltQ9NIjhW+InwJ+pW+EYk5Wh1oU7iZJneO2s1h7plWt+ikMfKdtRKnOdoEYG1eoCqZe6hzGV1aRU/uUyhVuI8QYMIrNUMqjp0oqjM8vBOp2T7lSX8XuaYWy1xHqE9BKnVNIqcL1F/E8qa+t6jzFc1UbSs9pBLRfEEisr0eFp7UZQwWlZXUVIqnUSJSw9KS6VRlCSMltUfKCnNoqDKDMpL8yhI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' +g1 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0dbp1drp2eLt4ebx5erx6fL18fb59fr5+gL+AgcCBgsCChMGEhcKFhsKGiMOIicSJisSKjMWMjcaNjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cnc6dns6eoM+gotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatrtausNewsdixtNm0tdq1t9u3uNu4udy5uty6vN28vd69vt6+wN/A1NTU39/fweDBwuDCxeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e4eHh4uLi5eXl5ubm4O/g6Ojo6enp4fDh4vDi5PHk5fLl5vLm6PPo6fTp6vTq7PXs7fbt7vbu8PDw8Pfw8fjx8vjy9Pn09fr19vr2+Pj4+Pv4+/v7+fz5+vz6/Pz8/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAl8giSgAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAAAy2SURBVHhe7d35QxTnHcdxFlwUQZCq0WokGK0GxaLUqxqNFVHj1RZCRaNEq8YetlhUAhWKpawLfzWdmf3sXM8c32ee7zPHZt6/uMfMw/OKcdnjmdm2TUIbeQpzioyi+sM//5Gn/vj3v/wVMwsrWoX/PHkMMwwuQoXdcxumGVSoCrvmOkxVLESF3fIeZisUpMIuhQhT9hWgwvZFCbP2JKqwcXHCvN0JKmxaqDB1J58KmxUuTL+ZV4VtChgAyK3CBgUNCCuXCvcWNjDMHBXuK3CAGLWSymHZKtxR7GD5eapm74zu6+6s5quuXcPjT+uYoTdgmirc6qk2ebCS23aOLWOanhqaCNWDXgyQ06pXa5ipO0sDFW5ytTyCnXPcgTeYrCuL01DhFlfz/dgz11W/x3SdLE+IqhioUFaw6kNBUAbrKaZsZ6tw3W59CPsUoL4VTNouTDWBPVB7J9qCG3LVKCZtF6Ja6cIOjTrtv+Qp3JKvfsDsmoWobmDzRg4qp6qvMDu7hgpXmtV3YXMrFyqnqvb3mF6zQNUTbG3lRuVUVfka07MzVbhodwUbm3lQeVUNYHp26wGqI9jYyIvKq6r6CfOza9v8Hy41W9+OjQVUXlWVV5ifXZvwV7WCTUVUblUPMD87UbWITQOejORVNYn52YmqBWxa2YsbnPKqmsD87Cgq+5lWK6leD+NCK6ledx9qXGgl1evuSuupDFTrqUxUy6ksVKupGqgWUwHVWqpuoFpLZVeqMqlU2ZWqTCpVdqUqk0qVXanKpFJlV6oyqVTZlapMKlV2pSqTSpVdqcqkUmWXgaraPzA0fHJk9My5C2dPDR92lhUElm9VR9/BoXPX7j+eFRYK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' +g10 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0dbp1drp2eLt4ebx5erx6fL18fb59fr5+gL+ArKyssLCwt7e3uLi4ubm5urq6vb29gcCBgsCChMGEhcKFhsKGiMOIicSJisSKjMWMjcaNjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cnc6dns6eoM+godChotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatrtausNewsdixstiytNm0tdq1ttq2uNu4udy5uty6vN28vd69vt6+wMDAwsLCw8PDxMTEyMjIysrKy8vLzMzMz8/PwN/A0NDQ09PT1NTU1dXV2NjY2dnZ2tra29vb3d3d39/fweDBwuDCxOHExeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e4ODg4+Pj7fbt7vbu8/Pz8Pfw9vb29/f38fjx8vjy9Pn09fr19vr2+Pj4+fn5+Pv4+vr6+/v7+fz5+vz6/Pz8/f39/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAji4xRwAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABaPSURBVHhe3Z37QxRHnsDTg4P4QlEUJUFh77EXjFl8EUEIPoKiRAxrlN175zZ3t7cn4iMajc94BzEnj102jBn6j62bnvlOVXV/v1VdVd3T07OfX4CqmqE/0z3d9fzWeyw7fArIS5csrbJDZ/UOPs58svk/cJgESit4bb6BY0UorOBV+efdX8ERh6Cs8n3lRdmEo5YhrKB06/AjHLggavWPULK1+BqOvk7Y6u9b70TV+AEEgLDVT1Co9Qh/u0JWm1CkJQGHKrIVZLcqYBEgWUFm6wIeFYRVS19+NcBEsvoj5LQyP/8JZLgVZLQ24MKtILnV+c+aDVhBYutT09FbrdyfHOzsKOaLjp39FxaW4Aij1HRqVpAUgY0WvbzSdvoFfdOu+qitln4Fb5BX+snD/olbQYLM5vw2eHF+aZ8tw9HKaKw2z8Er880pooH7f2AFf0psTsDL8s5JQqtm9Vv4S+IivCj/DON7xv9Wrf4EfwmewEtagdtwzIJKU6tiBX8IVvfAK1Rs2QK/5IAOfPy0lfpL1dY7Mvt8tXLnKa+9vDHamwu543DUgsDqv+B3zmo7lI/ywa01KAJs3D4MWU2kgE5LYIXuIteheJitY68hPwQb74ACTeMCHIqgYgW/CbqhdIgTqoqX//Y0FGkW20pwJBzCagkKy+y8C5kkD3ZBsSaBLiLC6hsoK3HqLeQpWB6Ggs3hSzgMDmF1GcoKpiFHwwwUbQqjcBAcwgp97jcgQ8utApRuAh/CMXAIqxNQts4spAuW2WLwzArzJRRvAn1wCBzCagjKAlOQDDy5MLgjSG4/NhN55XS1eDP4AI6AE2s1IJ+U5Wuhu/6uqdBT+SNIzhxrq3Y5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' +g11 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAW1tbVapVVqpWV6tXWKtYWaxZWqxaW61bXK1cXa5dXq5eX69fYK9gYa9hYbBhYrBiY7FjZLFkZbJlZrJmZ7NnaLNoabRparRqa7VrbLVsbbZtbrZub7dvcLdwcbhxcrhyc7lzdLl0dbp1drp2d7t3eLt4ebx5erx6e717fL18fb59fr5+f79/l5eXmJiYmZmZm5ubnZ2dgL+AoKCgoqKipaWlqqqqq6urra2tsbGxtLS0t7e3urq6u7u7vb29vr6+v7+/gcCBgsCChMGEhsKGh8OHiMOIicSJisSKi8WLjMWMjcaNjsaOj8ePkMeQkciRksiSk8mTlMmUlcqVlsqWl8uXmMuYmcyZmsyam82bnM2cnc6dns6eoM+godChotCipNGkpdKlptKmp9OnqNOoqdSpqtSqq9WrrNWsrdatrtausNewsdixstiytNm0tdq1ttq2uNu4udy5uty6u927vN28vd69vt6+v96/wMDAwcHBwsLCxMTExcXFx8fHyMjIycnJysrKy8vLzMzMzc3Nz8/PwN/A0tLS1NTU1dXV1tbW2dnZ2tra29vb3d3d3t7e39/fweDBwuDCw+HDxOHExeLFxuLGx+PHyOPIyeTJyuTKzOXMzebNzubOz+fP0OfQ0ejR0ujS1OnU1erV1urW1+vX2OvY2ezZ2uza2+3b3O3c3e7d3u7e4ODg4+Pj5eXl5+fn4O/g6Ojo6+vr7u7u7+/v4fDh4vDi5PHk5fLl5vLm5/Ln6PPo6fTp6vTq6/Xr7PXs7fbt7vbu7/fv8PDw8vLy8Pfw9PT09fX19vb28fjx8vjy8/nz9Pn09fr19vr29/v3+Pj4+fn5+Pv4+vr6+/v7+fz5+vz6+/37/Pz8/f39/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8fCpXwAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABEwSURBVHhe3d2LnxV1Gcdxm2Vb1oW4qHhDXE0NCTOjzEqzBCVDRDJQFBAhBC+gYIpkVl7SzLJENPKGICCoWFEKiCAgSoqKm5eFbXf+lW0u3zNnZn6/mXmeZ2bOmV+f18vXOWfOzGHe7tmzc+Z6RP//Y1mq79736P0P/7NK/f3VV3934TcxewmlqO7+xK5yfX/+OmZULUn1YB8mrnSvn43ZjaVXvYupql/fDzHLkXSq9zCFIWlcqupvGNmcejDn9eKqbxnx+xTvMcx9rZjqjxjNtD7H/KOoypxPCaVzQfCKqD7HGEZ2IRBuYdV/8byh/QoMp5DKcFT4p1VXVXv5iFTwuxWo/oVnjA6WQPVrDDe72gd8TYXBpoc/x1D9H/xS+fkcX3U3hsXrXr1w4rGDBlarI4eNnvnQLsxhPH+Z0FdhUKy3rh9iVbaLn+vFbEb7QaB6GEMifTyjBS9Q0U7eiDmNFqjwONILx2Hi6tYy9xBmNpz7w3JVv8TjcLdjymp35kHMbqg+qDRfqZZisqo3WsOCCo9C3YWJqt+Z6pvwNU/1Jzyqt2MgpjGgeZjnUJ4K9+v1jsEU8dra4+GJJtayCXNd72taVeInxdgujBF0FJ5pYp3K361HHdV5uB/UOxLjqymsCqis5zEvQX2O6lXcD1qNsXXFWVVQTcS81HNUyuf6pRhbW4xVBVXLbsxMkKPCvaC+9IW/RRjNrwoqayVmJugbqupNjKtvWvR3sxKq2ZiZoAtU1RMYV1sMVQ3VGMxM0L2q6iaMqyuOqobqaMxM0AOqaj7G1aSgqqEajJkJukdVzcO4aiqqGqoOzEzQfQyVBlVR1W/pKh3KeJUWZbpKRd3hLmWY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' +g12 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAAgICBAQEBAkEBw8HCAgICgoKDQ0NCBEIEhISFBQUFhYWGBgYGhoaHBwcFSoVFi0WICAgJCQkJiYmKSkpLi4uMTExMjIyNTU1ODg4Ozs7PT09IUMhIkUiJUolLVotL14vMmQyNGU0OXM5QEBARUVFSUlJTExMUFBQVlZWWFhYWlpaXFxcXl5eYGBgYmJiZGRkampqbGxsb29vcHBwcnJydHR0d3d3eHh4enp6fX19QoRCRIpESJBITJlMTp1OUKBQUqVSVKlUVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0dbp1drp2eLt4ebx5erx6fL18fb59fr5+gICAgoKChISEhoaGiIiIioqKkJCQkpKSkZSRlpaWmJiYnJycnp6egL+AoKCgoqKipKSkpamlqKiora2trq6usbGxtra2uLi4urq6vLy8vr6+gcCBgsCChMGEhcKFhsKGiMOIicSJisSKjMWMjcaNjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cnc6dns6eoM+godChotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatrtausNewsdixstiytNm0tdq1ttq2uNu4udy5uty6vN28vd69vt6+wMDAwsLCxsbGyMjIzMzMzs7OwN/A0NDQ0tLS1NTU1tbW2NjY2tra3Nzc3t7eweDBwuDCxOHExeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e4ODg4eHh4uLi5OTk5eXl5ubm5+fn4O/g6Ojo6urq7Ozs7u7u4fDh4vDi5PHk5fLl5vLm6PPo6fTp6vTq7PXs7fbt7vbu8PDw8/Pz8Pfw9PT09fX19vb28fjx8vjy9Pn09fr19vr2+Pj4+Pv4+vr6+fz5+vz6/Pz8/f39/f79/v7+AAAAAAAAGpDFhgAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABSPSURBVHhe3Z19nBXVeccPJMRohcZEIybpS1pN1JgUm5im1jZJ770s7nZZBFmyuBuIbU1iW0NtE1NSA6gIiK4soiDrxpUVRNEk9aU1CStvYtEVxLVpTKQBWRcWqw3LbnDv9s6HzNz7m9czc+Y5c+fMvcP3H849c+bly937zMw5Z55hJyj87Oc/QykdCK20qgYH6Ueg1f9j3aoGx8oRYIW1qh8crwc/q7exRjrAQbvgrX6O1ukBB+6AsxpF0zSBQ7fxWqFd2sDRm5wkVh4tjxXapBEYFHFboUE6gYOB0wpLUws0dBxWWJZiIHKSWVlathUWpBu4WFaoTjmQMa1Qm3pKNrBCnZfRnnVLZ9bVVBdT6me3PrwfR8hR1ClZ+d9MDXZOz1Qtc7rzOEw3RZ+SFWpc5DtqsIEqZdp2HKkby8rvqzrQjJWrmOWDOFgnlhU+O3muyr+oEjMO4XCdwOpX+OggHVL+WrDCJwc9KZHStd7CIdsEWQ1dgXVSwGIcs4Oi1Tv4YNOKNejkKvflduOgbYpWKNu8gPY0Zqx4pFc/dRQObVt7NaoSpW4Ih23hb3Uz2lNY+GwBaxm8vqoW9QmyHju38bN6I4vm4TS9jHUsjsn/9ZbLTOf/axHd6k0ULdagdSjZtX4XLTunYXFi7MKeLXQrlGzmoHEYuW1YwcNAIxokRTt2bOFjlSeGsyCp5LUWYb8W+/jfVS/ahsFHVIuBBrRJhnrs1uJXvNU2tA3hNjT35Vk0SggutvN/gd1oKmaa63J59OiRERRL3IFmyXAEe7XgrTajqZjNaG2wZ/lkvablCYfY4OWlZskwgL1aRLSaasf0/hbUZeodP7WVqEuEuKzsYNo/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' +g2 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0dbp1drp2eLt4ebx5erx6fL18fb59fr5+gL6AgcCBgsCChMGEhcKFhsKGiMOIicSJisSKjMWMjsWOjcaNjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cns2enc6dns6eoM+godChotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatrtausNewsdixstiytNm0tdq1ttq2uNu4utu6udy5uty6vN28vd69vt6+y8vLwN/AweDBwuDCxOHExeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ufS0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e4ODg5eXl5ubm4O/g6Ojo6enp6urq6+vr7Ozs7e3t7+/v4fDh4vDi5PHk5fLl5vLm6PPo6fTp6vTq7PXs7fbt7vbu8PDw8vLy8Pfw9PT09vb29/f38fjx8vjy9Pn09fr19vr2+Pj4+fn5+Pv4+vr6+/v7+fz5+vz6/Pz8/f39/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHWJ+1wAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABiESURBVHhe3Z39Q9tGf8DL+QWDeS8UmjxJYdBQWKGhUFjhMSUhbzTJCmEpjISErFDaELaHPu2zBcKrN54VG3d+Zrk6/lkmWd/T60m+k2Rb3ucncTqb+1h3p7vT3em9SwYuAgMkqBgsVv/0Uzn4sy0/6/nl3yFVThSz+vXX3/72W97M77ZgW+DX9gdInR1OVnl/U+IzkEgqdla//Q4fDjaQWjM2VoG+SkYgxQboVvCB6gDSrIdmBbGrB0i3BsUKolYTkHIVqxVErC4g7QSzFcSqPiD9CiYriFKNgEEBoxVEqE7AQcZgBaerFbCQ0FvByeoFPP6fWalaOis4U82Aic4KTpQajEWZfF5QyMlksxmFc5m0RErh7OzsVCKpcHJyciyTPDsX6C1VcHG2Enaf/rGvq739fYm2trZWhRaJ5ubmJoVGmQaJuEJ9fX2dREyhtrY2KhHxk1hb/8zzg/M8JNKA4qJaQagOnFoeaKqPhlBNAEHv33qTplwvRcbeKvP8ejwM3xFI4tMHAqRVR0GGWEGYCj6YbAjkRdIR/mgtA8nVKNjYWInbvVH4bJBpXqBrgRWEEMTt7kBnPpXmhSwkWUXWoVrht38Xgo8FnZanlqpQtYK/CcnJ6rhSEujKjrkmtLHKLsXgMyaCWMlHb55DsgnECv4E8O4V+IRGtCex9OYoefxudXYgDmEBoXnRerEoVpl5U6FCzYkfz85zIpaaO0I2vTdnta4g4X5zhUG12u+D+ED91Dt96wSL2eOFFjgXBN7/DlJGUKzgD0BYi0D0AqErz9MinCLg3NYQnA4AsUlTFsQUq9Q9iF0g3LtLaZZg8ehWYGoO1GNOIbZaHd+E2DKSlPlC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' +g3 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0dbp1drp2eLt4ebx5erx6fL18fb59fr5+kpKSmZmZm5ubgL+AoqKio6Ojp6enqamptLS0ubm5gcCBgsCChMGEhcKFhsKGiMOIicSJisSKjMWMjcaNjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cnc6dns6eoM+godChotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatrtausNewsdixstiytNm0tdq1ttq2uNu4udy5uty6vN28vd69vt6+z8/PwN/A1dXV19fX2NjY3t7e39/fweDBwuDCxOHExeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e4eHh4+Pj5+fn4O/g6Ojo6enp7u7u7+/v4fDh4vDi5PHk5fLl5vLm6PPo6fTp6vTq7PXs7fbt7vbu8PDw8vLy8Pfw9PT09vb29/f38fjx8vjy9Pn09fr19vr2+fn5+Pv4+vr6+/v7+fz5+vz6/Pz8/f39/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8DgQ0gAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABMISURBVHhe3Z39QxTHHYfdQxBEfAHjCwmGtvZVDAqiKIqiEAxqRIlGm75pUBGiETHSNm0jgYjQpg0XqSlHjv1P6b18bvZlZnbnbe92eX65u5m5u31gb3Z2Xr6zaT2YP/zjRztO4LBCCLH6xfpv/7j+l7/FiT//7e84OD58q5//bg1/n3iCw2TCs/on3htvcLAUHCu8K/78FwfshWmFdySD/+Gg3TCsUDo54LhdUFYomSxw7AS/FYolDRx9CZ8VCiUPHD/wWqFIEoFBEY8VCiQTOBRwWyE7qcAij8sKmckFHjkcK2QlGZg4Vv9BRqKBC7H6PdITTlGGWCE18RRtYPUVEv0sjva3bqutjhe129sGH3yPI/RRsIHVb5DmZW3qeJUVV2rOvMBheig4weoHpHmYa8UHxJWjizhSNwWpohVS3GRHqvHm+FJ3l+6DKEjxrFa78M54c56jlbfCaxcJkbKsPkqLb7XWjTfFnwEcsgPX6hO8JQk8xjETYIVXDq9q8Q4fmzfjSZzY+RpHTeBYdeINblqvTy7b9vLk8LtIiA19OGpCwepfeEH4JoXyDt2uS950zGqSGv8/q2CF5w79KE5oeIgc8KAeGfHgOg6LwLLK1KF0iaYF5BDmdyErFuzGURFYVs9RuEQjJRU3rW9xVIT1TT/BM8JNlAVVz5Hu4Sn926sc4zgowvqmX+IZoQdlwRCSfVA/vgpCHeL6pl/jGeEgyhbZuoJkH6+3oEAM6MYxEdY3/RTPCC0oW6QfqXkW3SfwWRSIAcdwSA6bfoUnhHdQtsgMUm17dJ9lNT/AC9v+AgViQAcOyYGuAz1WtVmk2jcKr1O38dLOxOf+i7Ji1Oweq4NI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' +g4 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0dbp1drp2eLt4ebx5erx6fL18fb59fr5+gL+AgcCBgsCChMGEhsKGiMOIicSJisSKjMWMjcaNjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cnc6dns6eoM+godChotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatrtausNewsdixstiytNm0tdq1ttq2uNu4udy5uty6vN28vd69vt6+wN/A3d3dweDBwuDCxOHExeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e4O/g4fDh4vDi5PHk5fLl5vLm6PPo6fTp6vTq7PXs7fbt7vbu8PDw8fHx8vLy8Pfw8fjx8vjy9Pn09fr19vr2+Pv4+fz5+vz6/Pz8/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzAkGwwAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAAA/HSURBVHhe7Z39f9TEFofvbtlSbAWBcgtoeRORNylF3q6VF+0tWqnFaxUpIAiCIO9Ir0rpQin5v3E3+e5kkjPZnpNMspn99Plld2cy23m6bTaZOXPmX2+7kbRWf/35/yZ//oXX5WI5K08GWpF2KC2KZCv0p8ygp5REKzQsOehsnAQrNHIAdDiK0QoNHAGd1jFZ4Wh3QL9DqBWOdAp0XUGscJxjoPMt4lY4yj3Q/4CYFQ5xERj4RK1wgJvAoUnECtWuAosG3W+FSneBR8QKVS4DE80KFW4Dl/ZWC7Ond6/tq5WLvoHtJ2eeoYcx4KKsUKzz4NjqSlmp7r/5Bt2MEMgkWz0/gDcoK8P30dMIvkzLCmUhl/rRuLzUJpbQWQ3fJsHqzWm0LDd7FtFfjaYNrFDSwhEpo1ZTJ7BCgeJLNCo/e+kfYcsKLxW3qmjjAN+gzyEJVi8H0SJGTy9YhYIy0PsIvVbACq8Up9AgjjqTnkBBKdiNToUYrV69g+Nj7Ee9N1dDSTm4h24pfCs8V0zj6Dh3Ue99hoKScBTdUhittuLoGHtR7T3vRUlJ6K2jYy1MVvWEE+Ad1Cf+23WMG+iYwmB1A8fG+AjV3nwfSkrDOfRM0bDCM8UEjo1xC9XeGRSUhwPomcJgdRTHRvkQtd5C6T6qyvvomsJgNYpjo9xErfcFCkrEELqmMFiN4NgIO1Hp1RO+zDrJJvRNwbW6jkpvHAVlIq3VNtR59TLeS6a1uoo67xwKSkVKK3WSefUuSkpFSqvLqPImUVAu0lltRY23uBYl5SKd1SXUeFMoKBmprIZaQwOL6yuV9VtBiS4xUln9iAr/xmsGz73dQWUZSGO1qfVRvd7Q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' +g5 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0dbp1drp2eLt4ebx5erx6fL18fb59fr5+gL+Avb29gcCBgsCChMGEhcKFhsKGiMOIicSJisSKjMWMjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cnc6dns6eoM+godChotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatr9evsNewsdixstiytNm0tdq1ttq2uNu4udy5uty6vN28vd69vt6+y8vLwN/A09PT19fX29vb39/fweDBwuDCxOHExeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e4eHh4uLi5OTk5eXl4O/g6Ojo6enp6urq6+vr7e3t7u7u4fDh4vDi5PHk5fLl5vLm6PPo6fTp6vTq7PXs7fbt7vbu8PDw8vLy8Pfw9fX19vb29/f38fjx8vjy9Pn09fr19vr2+Pj4+fn5+Pv4+/v7+fz5+vz6/Pz8/f39/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo18IGgAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABKcSURBVHhe7Z35f9TGGYejNb6AQAzmjhNTIAQwGOwApgYbFzAEnEDTA2ICiYMbg7GblLRNoTg20NLWJrQuS5f9a+keX7065p3RaCStJD5+ftnVOyPtPPaupNFcb71+E8mS1d//8uc/fi/hTz/8Dbl0UFn9uxwA8oUEO0cBR5Iit8IBMgwKyiCxwn6ZB8X1w1n9C7vkApTZi2j1A7LnBRTbg2D1CplzBEruwmf1PTLmDJSe8Fr9A7lyB8pv47H6L/LkEBgAt9VL5MglcKjjssrxf6oKLGo4Vv9Eam6BRxWy+g5pOQYmFWyrnyEl18DFsUI850DGtsr9jwrUbWwrBP0Ub53Z39HenC1a1uw4emUOJfRT11FZPR5ea2WW3TdLKKaHuk7dCiEPywNNOEBG2fgNSuqh5iO1utOJnTPMwDIK60Zl9VkBe2aa7UsorguFVT6kLGsbr1WzwqbDeE6kKlrPUWSH/0isFtqwTw4YQJld8FavdtfyN7UEkYn/6CRK7VC3wgZxtZ59FJtyeusZ06VDqBayVq+217PnxMq6jtIQNSu8J6aQOy9W3SiNA2dllzUvVtYDFIeoWOGdwzvInBurT1AcgrF6irz5sepDcYhfilZfIW9+rLaiOMRvRKuLyJsfq1YUh/hWtBpFXsdqcUHCfuRMmQLKSfxetDqLvI7VYQQyC8pJfPdGWv1hxSqzoJzEilV2QTmJFavsgnISWlant4Otm7JZ9Uc5CS0rN3OfD6xBenZA2YjQVhVeXN2BHFkBBSNMrCpcydY3EaUiDK3Kj+qPoTICCkWYWpVfHkSuLIAyEcZWmdJCkQhzq/LLXciXPigREcEqQ8+tUSBCZdU/4Wdy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' +g6 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0dbp1drp2eLt4ebx5erx6fL18fb59fr5+gL+AgcCBgsCChMGEhcKFhsKGiMOIicSJisSKjMWMjcaNjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cnc6dns6eoM+godChotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatrtausNewsdixstiytNm0tdq1ttq2uNu4udy5uty6vN28vd69vt6+yMjIzMzMzs7OwN/A0dHR2dnZ29vb39/fweDBwuDCxOHExeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e4ODg4uLi4+Pj5OTk5eXl5ubm5+fn4O/g6Ojo6enp6urq6+vr7Ozs7e3t7u7u7+/v4fDh4vDi5PHk5fLl5vLm6PPo6fTp6vTq7PXs7fbt7vbu8PDw8/Pz8Pfw9fX19vb28fjx8vjy9Pn09fr19vr2+fn5+Pv4+vr6+fz5+vz6/Pz8/f39/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzLH1jAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABQfSURBVHhe3Z39QxRHnoe3B3kxKBoXg0FREaOLwaAiBoNCSFASBXV3c7cr51tEDZwc3Nte9jZxT5R1lKx3mTBHGHfsf9Xtnv5MdXXXS1dV98x0+/ziTHXNUI/TXd319q1fvFHArhf4e7FRsvrzH+vEn6p899133z969Oh/Avzw6HuH7/7jv/71dyiYCKkV/gdTCgrJQ2j1Cp9NNT+jsGEEVvhUBkCBg3Ct8IGM8AeUmoJjhcwZAgX3YawycT2FQdkJIat/RLasgeJXCVr9OzJlEBh4BKz+jByZBA4VaKu/4nhGgYULZfUDjmaWP0GEtvoDjmWY30PFt/oHHMk0v4FM1erXSM84sKlavUZyxvk/z6ZqhdTM89uKDayQFqa8MHW8c2tLc6poae86Nb0sOrkqOjKrn6Z2Waml+9omihnkj66OZ4WUAOWLLfiClNI+y/29pFar+/HhFPPhjygszaOqFd7TzKf8h/LoWEVxacRW2ZDia/2byGoxI1KOVh5F9nntWeGdz0YnPpMB+tgqQ2A1gk+EyDXjRaqYRqF9KlZ47bOI/BQtAxe/WXdq+/WH491ISgstL1FsAt/qI+QndF5yjAgvrryL9HTwGcrlw7Naa0J20Ha1jCNVNs7lcCwNdJRQLIJj9d94SfgcuUEfW8vY9vJeHE0Dt1EogmP1M14SDiOzx+nwD+VR/hDHU8BZlIngWOEV4fU7yFxBIGXbpV7kaDz7USQCx2oVeSscF0nZ9vr7yNNwmkP9zW4diJeE+8jrsoOu+8Ks7UCuhvMCJSKwVneQ1eUe0jzWn/+EVx43kKvhMA+DrNVtZHUYQJLL87F2J+W9c/Q3pOUcfIryEKRW/4wk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' +g7 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0drp2eLt4ebx5erx6fL18fb59fr5+gL+AgcCBgsCChMGEhcKFhsKGiMOIicSJisSKjMWMjcaNjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cnc6dns6eoM+godChotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatrtausNewsdixstiytNm0tdq1ttq2uNu4udy5uty6vN28vd69vt6+wN/A2NjY2dnZ29vb3Nzc3t7e39/fweDBwuDCxOHExeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e4eHh4+Pj4O/g6Ojo6enp7Ozs7u7u4fDh4vDi5PHk5fLl5vLm6PPo6fTp6vTq7PXs7fbt7vbu8PDw8/Pz8Pfw9/f38fjx8vjy9Pn09fr19vr2+Pj4+Pv4+/v7+fz5+vz6/Pz8/f39/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAurfsHQAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAAA4VSURBVHhe3Z39QxTHHcZzKChijPieRONbNBgploZEY6PFUGkUG9r0LYkRYzVGiPY9VCJC2opSy5lj/2F7t/fsy93M7n5n5ju7M35+YW93Zm8+cPcwuzuz+9LzYgLXeIaGZUKx+u3f/uoSv/vzJ79Gy7LItcKvxlH+g1ZKyLZCXaf5AW3tJssK1dznH2hwB3Ir1PCD79HoFDIrlPaHP6HhMRIrFPWJ/6HpEaIVCnoGGg8EK5TyDjS/TbcVyngIBEI6rVDAT+DQosMKm30FFk3SVtjoLdBokrLCNo+BSNoKW7wGKokV1nsOZCIrrPUd2MAKK7tZvzc1unegr9cp+vp3DU9+3UATu2jr5FmtTb9ac5Ydk4/RzA7aOm0rrOpg/dMB7MBR+i7K/l6hT6bVoxOo7DAHFtDYNLEVXqe5vw01nabvNpqbIsfKD6lMLbnVoidSTa05NDkBVniVsH4EdTxg11M0OiHDaios39NXzIawZKWcRqMTQqsf8CJmuS8sfgAv8zgblqyWb9CWhJYVFhPG26V9sRpBWxJkVnVEhS9WG5bRmBiZ1Rco7YtV7UM0JkZmdRqFvbE6isbE/FdidQCFvbHaso7WxIhWz3pR2Bur2ndoTcxLwp/qIYp6ZHUTrYkRrRZQNLF6uthNfGjjhtUMWhMjWt1H0cRqBisSvsSW4DWsqJZraE2MltX26HDtHlZUDI/VODYEY1hRMSxWPUvYsLoZayqGxWoI64NfYkXVsFg5lhU8Vq5lBY+Va1mhZrXvLpjEijbOZYWaVQbOZQWLlXNZwWHlXlZwWLmXFQxWDmYFg5WDWcFg5WBWmFu5mBXmVi5mhbGVk1lhbOVkVhhb3UAZ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' +g8 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0dbp1drp2eLt4ebx5erx6fL18fb59fr5+gL+AgcCBgsCChMGEhcKFhsKGiMOIicSJisSKjMWMjcaNjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cnc6dns6eoM+godChotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatrtausNewsdixstiytNm0tdq1ttq2uNu4udy5uty6vN28vd69vt6+wN/AweDBwuDCxOHExeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e4O/g6enp7e3t7u7u7+/v4fDh4vDi5PHk5fLl5vLm6PPo6fTp6vTq7PXs7fbt7vbu8PDw8fHx8vLy8/Pz8Pfw9PT09fX18fjx8vjy9Pn09fr19vr2+fn5+Pv4+vr6+/v7+fz5+vz6/Pz8/f39/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB03dHgAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABRlSURBVHhe3Z2NWxPH2odNIDRURKlYv0pLi9WqWBA/itJqqaIt1eqpPR6t+EXlyHl7rEpFrOfwlkiO5yU07p/Mu0l+Ozu7M7v7PLObZLf3dbWE2dmwt0k28/HMM5s2yFguKEktDCuVl4/+iUdc/vVvPKDw8rdHP//88z8fPXr028uXv/32P9F/NNQKr0w6wTVqCbbCyanmDa7VT5AVTks/uF4veiuckQ1wzTI6K9TODrhuF9UKNTMFLl2gWKFe1sDVA78VKmWPlxCo47NClSzyHyjU8FqhQjZZh4SNxwqHs8r/QcNjhWMZBiKyFY5kGqi4Vn/gQKaBi2uF8owDGccKpVkHNhFWC1dP7N3cVUgX3X0Hz92p4Ap9NGxghTIv1ZtDudTSc3YJl+mlrhNidW87niCldIy/xpV6qOk0rFAg83ocJ6eY/ge4WJkwq9IenJlq8t/jcmUcK/wqUdqN81KOTuuPIKtyRqRsreu4ZIkgq89wTgYoPsc1u9hW9n/4xeUuzvBT6MCDNLHvDa5a8Kb+WuEXwXofTpDoGP5u3v7iW5mZ7EdJariGy3bRWl1HdZeOM+5XXvX2AEpTwh7lxdJaDaK6YPc/cKRB9UInDqSDn3BdgpoVHgoeo7Jg3xqOCO534VAqGMFVCf6rsbqEyg6qlK1VwME00IeLctFYjaEy6C2h3MM0jqaCFVyUQGO1E3XBLRR7qX6Ew2lAuUSNlfczM4hSP3M4ngamcU2CTRu/45Egj7oNpBbJ+tIrPKrxHiqkgAu4JMGmjf/FIwGqNiiKPmd1qjeX+/ghflNvKm3kPC5JsGnj33gkQNUGH6HQuYkU5/CrNV//PRVorP6FRwJUbfA5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' +g9 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0dbp1drp2eLt4ebx5erx6fL18fb59fr5+gL+AgcCBgsCChMGEhcKFhsKGiMOIicSJisSKjMWMjcaNjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cnc6dns6eoM+godChotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatrtausNewsdixstiytNm0tdq1ttq2uNu4udy5uty6vN28vd69vt6+ysrKy8vLzMzMzc3Nzs7Oz8/PwN/A0NDQ0dHR0tLS09PT1dXV1tbW19fX2NjY2dnZ2tra29vb3Nzc3d3d39/fweDBwuDCxOHExeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e4ODg4eHh4+Pj4O/g4fDh4vDi5PHk5fLl5vLm6PPo6fTp6vTq7PXs7fbt7vbu8fHx8Pfw8fjx8vjy9Pn09fr19vr2+Pv4+/v7+fz5+vz6/Pz8/f39/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHWfsaAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABSfSURBVHhe3Z39QxRHmsd3BlAMqDE7vqxGxagQFIKBlYioiBIJGFbubbN3t7f3vixGIqKgBvdOjSiBE3Rchh36j/V6Zr5TXd31VHVVdQ/T7ecXmuoa6A/MdNfLU0/94r0xTl3BRaixsEoBSqst/H2SCS6SQm6F1yYaXKqAxOqveFniwfUGIK2S/c4LgovmoaxQOzXgsjlEK1RNFbh0hmCFeikDF18laIVa6QPXXyFghSppBAZl/FaokFIg4eKzwtm0AgsX3gon0ws8fFY4lWZgwlnhRLqBywduheK0U5GpWqEwyMrUwPHW5qZk0bzn1NDMW1xhkLINrFDkZ2v+bDaTVHb2/4TLDFDSUVg9P4ofkFS61nClPko6FSsU8BRvNOLFyaX1Di7Wh8Kq0IFXJpshooMrt0qJFKlVtcK3HsVOvCj5XMclc8isxvGSFJB9hGv2kFgt7cBLAjQ24CBJ5N7hqhkVK3zjcRIv4Dh8cWqp6H7enk/251CUFIZw1R6k1TNUZzSee4xTZe53Jurh/NEGrotRssKhx69RvUr7Ck4wnn+KU4ngFq6KQVnl/Z+q5kmU82yOJOgjdgQX5UFYzaNyhdbnKA5wvwkV6k82j2tiEFY3ULmMTCpRWvO4JAZh1YW6JXY8QyHBXGLuGaO4IgZhdQR1S4yjjGQAlepOPy6IQVgdRF2Xz9xHlEdh9XUBh2U2kvLk6sUFMQir/ajrfgyXUOSyeeezUknnfXxf4l6lWt05h+thuFZBLc+qAyUucx+jLHPgKYpcvKp1hbLCEcO71FmUuFLcDa/F07qJojpjZPUx+1T57+It7G6fT0Z/2ciqGwW+G0iJThT775f1w8iKPQb8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' +p4 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAAQEBAgICAwMDBAQEBQUFBgYGBwcHCAgICQkJCgoKCwsLDAwMDQ0NDg4ODw8PEBAQEREREhISExMTFBQUFRUVFhYWFxcXGBgYGRkZGhoaGxsbHBwcHR0dHh4eHx8fICAgISEhIiIiIyMjJCQkJSUlJiYmJycnKCgoKSkpKioqKysrLCwsLS0tLi4uLy8vMDAwMTExMjIyMzMzNDQ0NTU1NjY2Nzc3ODg4OTk5Ojo6Ozs7PDw8PT09Pj4+QEBAQUFBQkJCQ0NDRERERUVFRkZGR0dHSEhISUlJSkpKS0tLTU1NTk5OT09PUFBQUVFRUlJSU1NTVFRUVVVVVlZWV1dXWFhYWVlZWlpaW1tbXFxcXV1dXl5eX19fYGBgYWFhYmJiY2NjZGRkZWVlZmZmZ2dnaGhoaWlpampqa2trbGxsbW1tbm5ub29vcHBwcnJyc3NzdHR0dXV1dnZ2d3d3eHh4eXl5enp6e3t7fHx8fX19fn5+f39/gICAgYGBgoKCg4ODhISEhYWFhoaGh4eHiIiIiYmJioqKi4uLjIyMjY2Njo6Oj4+PkJCQkZGRkpKSk5OTlJSUlZWVlpaWl5eXmJiYmZmZm5ubnJycnZ2dnp6en5+foKCgoaGhoqKio6OjpKSkpaWlpqamp6enqKioqampqqqqq6urrKysra2trq6ur6+vsLCwsbGxsrKys7OztLS0tbW1tra2t7e3uLi4ubm5urq6u7u7vLy8vb29vr6+v7+/v7/+wMDAwcHBwsLCw8PDxMTExcXFxsbGx8fHyMjIycnJysrKy8vLzMzMzc3Nzs7Oz8/P0NDQ0dHR0tLS09PT1NTU1dXV1tbW19fX2NjY2dnZ2tra29vb3Nzc3d3d3t7e39/f4ODg4eHh4uLi4+Pj5OTk5eXl5ubm5+fn6Ojo6enp6urq6+vr7Ozs7e3t7u7u7+/v8PDw8fHx8vLy8/Pz9PT09fX19vb29/f3+Pj4+fn5+vr6+/v7/Pz8/f39/v7+////AAAAAAAAAAAALXB5YwAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAAA7sSURBVHhe7Z15mBTFGYdnl0MEQbkWMMKiqEAUQYOokBBQMNEoiAoxJqIxXhFFg0GCxhuNiaiIEY8IHhEUUaPigRoPJC6ooLgKBJC4gCCIAgvsAjv1PJM+flPTPd09W9VH9dfz7PvPVH1d1f29zNLTR3V1KlOMFLT6b5qRJb0aSbrhbbUX3QlTh1QdeFhtRT/yVCNhO65WteiSCPYgaSsuVon5nrI4vy+H1QdomiiWIPks+VbVaJcwdiF9kGdFeFdeDxAwsVuhRSKBgoHNCssTCiR0rFZYmligoWGxwrIEAxGrFZYkGqjkrBJw2Fc/achkrdYhnnA2mzZZK0QTj2kDK69f3/SaZ8aPHjWSFKNGj5u52vNwwdAxrZYilEfVhE4porT/w2okmYdxMmlaIWJn9VmNsAqSlJy2DIna4VYrELCSnrYfupOl2eQ6JGtlbdYKdSvVp6IraQZ9j3SteFtV/xT9iNPPRavCtHJ+jzsSIqVpOc/ctZ9i3Qo1C79HnwTwG6RswcNqHnokgueQdI5PdKs9qHCqu6CDOIfNA68egIgyyrYgbU5at0I5x9/RXoJH0ZU9gYBC7sCmc7hZpY9Ac3EO3o2+dT0RUUi543TDzeoNtJbgQXRlsxBQyhxsnKNZVaLIuQqNxemSvdhb1wsRpVyIrXOqUs4rgD9BY3HuR082BwG19MbWOXUpxx/g3hZoLMyBu9CVHYOIWhrtwOY5TquVaCvOPejJXkRANR9j+xyn1RI0FabDTvRkxyGimnexfY7TahGaCvNXdGSvIqCceUiAE9yqHd/dDEBEORFYTUI/9iYC6gnfqvU29GODEFFP+FY3oRt7D4EYCN2q1XfoxoYi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' +r0 = b'iVBORw0KGgoAAAANSUhEUgAAANQAAAE/CAMAAAAJ9B3fAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAA/1VV/1ZW/1dX/1hY/1lZ/1pa/1tb/1xc/11d/15e/19f/2Bg/2Fh/2Ji/2Nj/2Rk/2Vl/2Zm/2dn/2ho/2lp/2pq/2tr/2xs/21t/25u/29v/3Bw/3Fx/3Jy/3Nz/3R0/3V1/3Z2/3d3/3h4/3l5/3p6/3t7/3x8/319/35+/39/iYmJi4uLj4+PkZGRk5OTlJSUmJiYmpqanJycnZ2dnp6en5+foKCgoaGho6OjpKSkpqamqKioqqqqq6urrKysrq6usLCwsrKys7OztLS0tbW1urq6u7u7v7+//4CA/4GB/4KC/4OD/4SE/4WF/4aG/4eH/4iI/4mJ/4qK/4uL/4yM/42N/46O/4+P/5CQ/5GR/5KS/5OT/5SU/5WV/5aW/5eX/5iY/5mZ/5qa/5ub/5yc/52d/56e/5+f/6Cg/6Gh/6Ki/6Oj/6Sk/6Wl/6am/6en/6io/6mp/6qq/6ur/6ys/62t/66u/6+v/7Cw/7Gx/7Ky/7Oz/7S0/7W1/7a2/7e3/7i4/7m5/7q6/7u7/7y8/729/76+/7+/w8PDxMTExcXFxsbG09PT1dXV2dnZ/8DA/8HB/8LC/8PD/8TE/8XF/8bG/8fH/8jI/8nJ/8rK/8vL/8zM/83N/87O/8/P/9DQ/9HR/9LS/9PT/9TU/9XV/9bW/9fX/9jY/9nZ/9ra/9vb/9zc/93d/97e/9/f4ODg4eHh4uLi5eXl5ubm5+fn6Ojo6enp6urq6+vr7Ozs7e3t7u7u/+Dg/+Hh/+Li/+Pj/+Tk/+Xl/+bm/+fn/+jo/+np/+rq/+vr/+zs/+3t/+7u/+/v8PDw8fHx8/Pz9PT09fX19vb29/f3//Dw//Hx//Ly//Pz//T0//X1//b2//f3+fn5+vr6//j4//n5//r6//v7/fz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATF6XsQAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABMBSURBVHhe7Z39gxTFnYd3ZndhBeQtKIuuBgVxs7lL7uLlXvRyMYl3ueNNBEUgQNDjEoKKCL5tFiSAHHAvSdwAIhAQFnFVRO5yl/PuEszyqq4kxgRB2Mi6zM6/Mdfd85mq6qmXrqru6Z7OzfPL9lRV99SzM93TXS/fqiso+PIPfpuvSj74/pdQRSFSqbs+wAGqlve/gqpyiKX+vOqNirx/GyrsRyT19UHskwIG70KlWXipO1Ok5JK7AxWncFK/RtkU8StUnVAm9XcolzL+BtUHfqn/QqHU8RMIFPFJ/a5YIo38BgoerFQOBVLJFUi4MFIpu+qVk4OGA5VK9efkQj8rIpXi86nEB1AhUqm97rH8O2QgldLfp3K+VrSBFBJTT9GmKCW/N8qd6O46UFV0dZ+SX6d/7ul4UnciqZzjK6cNz1QhI2asPoUqlvNFIiU0H9wzA8eoRrL37BfW2ruuu1J/iwQf78zE7lXLvWdRVR93Qkqk3FmV3zs/I19AZVncGwtH6i/wkqUD+1U5m1Bdls97Ur/BK4aUOAmtnAugI4UXDD/CLilgD6rM4ErdhW3Kuyk4n0qM/hCVptzhSHGtYYPC695VrXPmzfnMVXhVPcxDrSn/60hhk/JjFGeYubWn+GSSO/7cLKRVC91exVhEUuUf1JBlJ5BT5OTyocipCviPqlD3ZWwRTqBwiSl+JZeTrcirBup7USvCF+t+gC3CShQukm0XPRHnOrLIrwI6UCnCv9Zxv1LTUdYj24nUcrZXj9VcVInwZh02CDn2ei51qiara1AjQo6TOomiHu1IFFE9dx3nUCMCJ/UKSrpMUbUw5armatGDGhE4qYMo6TDEd9073Lmx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' +r1 = b'iVBORw0KGgoAAAANSUhEUgAAANQAAAE/CAMAAAAJ9B3fAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAA/1VV/1ZW/1dX/1hY/1lZ/1pa/1tb/1xc/11d/15e/19f/2Bg/2Fh/2Ji/2Nj/2Rk/2Vl/2Zm/2ho/2lp/2pq/2xs/21t/25u/29v/3Bw/3Fx/3Jy/3Nz/3R0/3Z2/3h4/3l5/3p6/3t7/3x8/319/35+/39/s7Oztra2urq6u7u7vLy8vr6+/4CA/4GB/4KC/4SE/4aG/4eH/4iI/4qK/4uL/4yM/42N/46O/4+P/5CQ/5KS/5SU/5WV/5aW/5eX/5iY/5qa/5yc/52d/56e/5+f/6Cg/6Ki/6Oj/6Sk/6am/6io/6qq/6ys/62t/66u/7Cw/7Gx/7Ky/7S0/7W1/7a2/7e3/7m5/7q6/7u7/7y8/729/76+wMDAwsLCxcXFx8fHyMjIysrKzMzMzc3Nz8/P0dHR0tLS09PT1dXV1tbW2dnZ2tra29vb/8DA/8HB/8LC/8PD/8TE/8XF/8bG/8fH/8jI/8nJ/8rK/8vL/8zM/83N/87O/8/P/9DQ/9HR/9LS/9PT/9TU/9XV/9bW/9fX/9jY/9nZ/9ra/9vb/9zc/93d/97e4ODg4eHh4uLi5ubm6Ojo6enp6urq7Ozs7e3t7u7u7+/v/+Dg/+Hh/+Li/+Pj/+Tk/+Xl/+bm/+jo/+vr/+zs/+3t/+7u/+/v8PDw8fHx8vLy8/Pz9PT09fX19vb29/f3//Dw//Hx//Ly//Pz//T0//X1//b2//f3+Pj4+fn5+vr6+/v7//j4//n5//r6//v7/vz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiWNr1QAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAAA2QSURBVHhe7d35fxR3Hcfx7HIfclquJlAoh2cEGkRKSpsgEKCUcmMErVhatWrDjUq5WsNRsFWxVUiBCCjaFoQQEULY5C9bZ2fe+53jO7Pz/c73852d2ce8fpnZ2ZnZeT5ybXZnvltXrNRbtwcT2cNf4gD9C0Z9ih0ktv9+E0fKFYD6BBsmvIc4XE++qKfYJg39BMfszAf1CKunpW/guO041J+xaorivgm9KKyXsvbi6JEb9Q5WSl3/BMDKhUr8b/HgCiCYOVFfYoV0BkQpB+oh7k1rYBjZqC9wX3oDxIH6C+5Jceznqox6G3ekun8BU0Zhccr7mYUBagBL056lsVAfYRnfQPeZ0yeTVWdXAQfH98jkWCgs8nZj4+LxuQQ2cn7bBRyitzcY6nMscXdm2VDsJInNPeD/DxJD4barnhXYOrHNuYpDdfVzoPy+UKcnY9MEN3yb3+83oHDL2dEkf+fZtfmojP8ZDdSvcctRSky+KuN5hYHCDUdn02LK5TbjkB35ox5PwxYpaNhlHLTdXgP1C8zbrcIGaOqL6HksSFSz+nHUrAEDxX1XXsXqqOEulg8ewpJk1Y6jszNQmLNzf6FsU0JRDdxXxQf1YDTWNnOYEorKfYDDY73BozqwrpnTlFTUyzg81l/r3sIc6/tYt5TLlFTUszg8u7pLmGHNwbpGblNSUfkHOD5WnfeV86fDsS5nSiqK/6Gqw5R1D2vypsSiDuP4WBzqJtbMTfCaEovqwPGxONQNrJlrwAK7WkKdx7SWUDu/g5kaQu3MNVozNYTamas9lGGqOVTJVGso01RjKMtUWyiYagrFntjWEoqVoapRhkIZqhplKJShqlGGQhmqGmUo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' +r10 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAALi4uMDAwPz8/S0tL/1VV/1ZW/1dX/1hY/1lZ/1pa/1xc/11d/15e/2Bg/2Ji/2Nj/2Rk/2Vl/2Zm/2ho/2lp/2pq/2xs/21t/25u/29v/3Bw/3Jy/3Nz/3R0/3Z2/3d3/3h4/3p6/3x8/319/35+/39//4CA/4GB/4KC/4SE/4WF/4aG/4eH/4iI/4mJ/4qK/4yM/42N/46O/5CQ/5GR/5KS/5OT/5SU/5aW/5eX/5iY/5qa/5yc/56e/5+f/6Cg/6Ki/6Sk/6am/6en/6io/6qq/6ur/6ys/62t/66u/7Cw/7Gx/7Ky/7S0/7a2/7i4/7q6/7u7/7y8/76+x8fHyMjIysrKy8vLzMzMzc3Nzs7O0dHR0tLS09PT1NTU1dXV1tbW19fX2NjY2dnZ2tra29vb3d3d39/f/8DA/8HB/8LC/8TE/8bG/8fH/8jI/8rK/8vL/8zM/83N/87O/9DQ/9HR/9LS/9PT/9TU/9XV/9bW/9jY/9ra/9vb/9zc/93d/97e4ODg4eHh4uLi4+Pj5OTk5eXl5ubm5+fn6Ojo6enp7e3t7u7u7+/v/+Dg/+Hh/+Li/+Tk/+Xl/+bm/+jo/+rq/+vr/+zs/+3t/+7u8PDw8fHx8vLy8/Pz9PT09fX19vb29/f3//Dw//Hx//Ly//Pz//T0//X1//b2//f3+fn5+vr6+/v7//j4//n5//r6/vz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF6KyZgAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABdwSURBVHhe1Z35QxRZfsDNUQ2CgIDiAQNB1wPHcfAcHG/wGHQQD7K7ySabTTbZrIqiI+LFKOwms9kkG0FhPLJJZkYHHWZXm6b+P1LHt1+9V9/vq3qvqrq6+vOD0u8V3fWhql+98/uWLQXyRcHMIov/DucnQW7100V4i8zyCzhTjMTqx5lXcvl7OF8fpNW/we9UAr+DcxYgrH4Fx1cK/wHnzYGt4NhKAs7cw2/1X3BgZfE1nH0Rn1WFFBIYOH9AtIJDKpEfgoIDb/WXcEBl8nOwsOGsfgTZlQr3UOasILNy+VsQ4a0gq5IBE84KMiobcClamd9DemVT+MrVca3+8DNIrnR+82PHx7H614D7b37i3li2uPvgDZwbgSPlWplfQ5qPhWv723JGBlm379I7OEcfhf8pWi3Sl+pV/yp4kyzS0PcMzlPElrKtfmEuQIrA1Qb4/axSe56stX7vWpnUpZrbA7+bZbY9h7Plca/Vb81v4DXHXAf8YrZZ8xTOl2Px97YVdakqRIrWsq/Vz8y/glcehR/AL2Wf9W/hnD1+Y1lZlwxeeZyBX6kEDsM5cyxYVvgGnFoOv0HSsHnHzp07tjTCy7JzB87aw75W2Op9OB5Rtf3kDXYjP//s1I5A/ZR4D91rttUX8DPjCRzup6X/BRzBeHlmDWSWkXtwMozv/8H6Xvk5DEeLdI2SXe6FW9Irmxa74FQ8CtiqUA9H89RfhlyC4TJXQqpwZdd6XvmgbsBudO/xvNwFh5UJVF7YT2Efl+FYj9phyJJytQ4OLQtn4CwYhNUROJZR/znkBDBRzrsQfbEIq71wbJGGKcgIZLqMz68tcA4Mu27hYyccC9RNQHqR+fGhc+cuj83DyyKPqEImHTbAKTCIa9UNx7rkxK/i9NH10Diu3tz/ABJd7le5GenTCWfACLU6BqkOo5sgFei8DRkOxyE1dbSt1nHdA9/ug0QPoWqZb4XUtNG1yt2HRIsxXB746ssPytRzo2t1BNIsrlZDmgdqBByDjJTRtFr+CtJM8zouC3DL5k0tZKWLptU+SDLNGXy+RHPN/Bjy0kXTin2r8p2Q4kFJmQ8gM130rNogxTQ/hRQPXurtCPxgmmXpxdGzGoQU8+1KSGEIUltrWZX+POSnip7VNKSYZyGBIUht4WrNM3BAqmhZ1bCO6vcgpQgvNW9JGevhhVkoR5NEy4pVGp9CQhEkZRisCuyrU6WCltVBSDAvQAJASBnn4DVunaWAltUFSDAPQYILJWXshwRzCBLSRMvqGiSYOyDBQZDaDIne3foZJKRJNKt2SLChpYx2SKogK+7RKkhxJcNaSDNvQEKaRLPaCAlyKaMVEivIajskyKWM9yE1+1aswtQLCXIp6VMgFbSsWGl9zX0dIGVchHTzICSkiZYVK9eeOy13Xuo7/2AkG3bGTZbSo2VVnYcUs8t6FSjVARlmvgZS0kTLyqvcDfukvEIRYDfgFCSkip7VKUgx8y3BUqvZVS3LiLKe1So2DvcE/rfBUt6lKpRl6FHPyvgMknjeYKkPIMs0RyElXTStvNNlEFKNLyFP+N0U0bTKfQlpjDcbIMtjhTeI8Kw8AwiaVkY3pBUhpOrGIc+iTDO6dK0MceyUkOpgXTamOQJpaaNttdLrk7ZKOPtpLFDVy8p005wr13CjtpWxB1Idnh0SBhRrDs5ChsNHkJw6+lbGECS7vLuyd62b3rB7yCv7bK646WUgglWV190MzE0/uDeNZm7cxCNBUVnZvv3jE+cuXRkeuTE6duvG8FDv1sBuxghWxvKbkBHIWOxqbVVrV0/f4Mj4U+6ryig8uXIUPymBKFZGdegkEqsJFutK5Vp7BsclU7k5Zo7SlyySlZHro/58HPmT0cdO1+4ZuPcdvE8o8+fb4Nd4olkZRps4CcHHBN+1psGK7tNjc/AeytzFs2ejWhm5XukNku+LVE9qOjAacgdIKAz4v8KRrQyj5Qz/QGZ8OxCl8dHaOx5jgf9jXxUnhpVVGO7l5im43N+nX/TlNp7hm2tRWDgtTI2NZWWxemf/KDx7X46e3t0CyepUf3AxcKqhKo+a4Q1t4lo51Dc2NjVFmjnXfCoRJZsZTisRq6hsGo5WPNBwWuWzqjkwCe+fFJ5WuaxaBrSfS+EwrfJYbfusNHFapqAALofVnrjluByY3JK+VZd/gmuSFNxqfNpW7aPwpiVixrkH07VafbnkcY8G7c9J06p+ILzFFJuCPTUiPaua3hKU5QTj1melZtVDrDcsDR2pWbWgJVGlYygtq4P+dQml5F1DKlarxuCNUqI3Dav9AQENSsJsruRWzUqdh8mytdRW+9IpzkX6SmvViDqvU2GkpFYfkp1QpedpKa1OlLzSJ4NNDSuSmFWNQmd8qTgK/zOSsmouZTMqDDbdo0hCVhsS6xGLAnrsJ2P1UQptjgBQl3ISVjm0Cjll0IBNAlZ11LwgTH7+zXy+NKEkUU9jfKs13IQLirk7Awe7N7S4nVzVzZ07DvTfTPhb+Aj+Z8S26vwWfo3i8UA3PcDQtP3Ug+SuW+LXqlNa8cvfOhw8stW0fyShdljS3yup1EyvykSZFQcT6XznZlK5xLOSSBWudSmPfm8Yiv9USLZkp6UWr+qt8W4+T4ZZ0wD1ksSxoqVu6i/YXHslXsmhEotE1YqUeuIt89GhHX01dEDt7+hWlFThtP7gt0vuWIyv1yX4nxHZipKairPwYH30yzUA/zOiWlFSg/EiaeWOR2129sL/jIhWLbgxn4+/Bn+H8nwmkY/hf0Y0qxU4QM4LPCVXn9YZeDc9/HOeo1nlbsChHhP8rI7o1OMAcwr8AP5nRLI6DUd6jCe1pLsG/8FCmUukj8mLelHk3grIik+1fp/iVBJWnejJMp6clKWlfbVuJWDVjJp8kwq3X3XL+vbOjjaV2U81umMqQ/Gtah7CYYyXIRGMV2w8dHGyOINp/tHIpx+EXNp6zZKwP74V6szMS6cu2zT2TuNna/7eicBqfaveYNGh2FbH4SCPA5BDkOu6Jp1ldmdnwKzqHVq1jO64VvjjnAkPJHW9wXfS8z55nKM+OEaJzphWDeIaCosn0kr69vBR/OfFOBKInMZw+UJtTCu2hr1IQVZPqheXl9Dclxcba9UbJlMxx4WF9T0OA5DjJziOJxAgZRhonEPKUDyrJtT1506OQtQpjfoEShk55ebWoXhW+KG/DXJEGpRGfYKlDKNNtRzsjGXVA/kedyBHZNVjyA4kTMq/8EtKfnkcq+bXkO9BFhXNwvo5GeFSRovajOoJq2YKPzLUrfD8xeuQI7AyoStlweJrBHIhjtUByPUoUIuGahL5Trk04YDyBFbdJrJVC+5SIFenn4XMQNSkDOM8HB9IewwrouUtRGkCtql0wqpKeVEzAnhnVSejWu2FPI6nxKqrhtgPX5HAtWwuMeZyLifKtROQx3Md8oLQkPIi18ixa9cRrYjqS4HoVMI1KoxUqt4X6dmmNryhZS+9jmZVR0xQug95HLmQEWIbudTEayIQ9RX4NSkFOwplNCvcU+bFaOJAnY2YACkioiTVneXD+eNGsmqmnhvEwyr8USWXskdS3+JenYawyqATNziSFZomZDELeRzbIEtOsBTZWYAGR304A+pRrFqpAc5zkMlxF7KkhEmZn8NrjpCm/rRzUBQrstcRR31oDHsAS6Ua2EA+vq1RmHyRfuegCFabIFkEfz5uqIgoSBFN63rIkeAOA0awItuk73DFIqT9qyJlvoA0jsB2zTP3GH0rvLGKjV1PEanGzS8eJSnTXA2pHoGDCfDt1rdCM58ccGFB36hF5FLi++P6xQnIIYEeBm2rzZDoAz+Dcacuh6qUeRrSPYh6NeM1dP9qW6EeQJceyPagHmpFlKXM25DhsRVyKIqRanStmiV9B7hzKWB45r6s53klGl5+jeY/sTCmBLvhGF2rTyDNjz9ctmHI+9Q1pEwTDXAFFO1zxTfWtFqO+tUBFK89J+0Q0pIy8ViYvKeJPd00raRVZnSmzZCB0JMy10Ouh/SJ4cUq1LSSbqaETnUNZPiRS9GNMTxhTWp1Ew7QtUJHM9C5NkGGD6lUo6SFiUPdSJvDLLawphWay8VAJ1sHGSLaUkThKrPi9iLQsmqQjyGhs62GDAF9KaKTW2Z1FPIttKwC2jZ4qjBRVEWQMpvgEA9JGTjPNZx1rHIBQ6A4rBSeWRdF6h16CjdAjh9+iw8dq6AGG779UYNFKtUklyL2H/R2ahHhG3g6VkFd5rge6D/6XhQpcwwO8uiCHB93IdtBxyqovYbr7B9BDiCXChwJwnHQJU1socmiYcUiflPgTxdroRGlWH3Vg25fiZ38GlYn4SXJQ/cYjhy/5kMuFRxDhtislG4Li31sGlZCy9tPHk/X4ZoiUqnmkMA4RDc3WRA/FrtN1K1a4JUE3BTxvliRpYivK12wF7/6gLoVH7qcABeCbPwiuhTxtyKLQP8lVbcKmdZLbNoAG+DEkHJ7YgXIwsI/d0/Zqj5knQ30xPG4m9rEkDLxfpDkaCMK7Kxs5Xv8YIhQnPbjVS4VPkFzFnedUt3cC6hlqWwVOlO5z3k/gb3xpKghEWoIFW/ypmpVE7riEPfeGrmJWFLPiGUmxB93HlfrVa0ktS+OArG4tC2OlG+XLYc64o97CvI4VK0Ce2JdPnHfUYVVKlJ3iKWQbJ8cj5dEj6mqlcICgBfKMZaVpOao+eNEJz9xRZWt2AY1ARAzCUiUpExqm3a0x7NpPiDmrqhaSXqMRG7Be4agJkVuR4d7g96R8+AVrXbAj4Es/gW8aSCrlKYLTlOLMrwdZRj0Vr+KVmwrm0BUtkRRk5olV2/hYZZxenG1opViqCjfHlgEq5WknpMhCFrRXIu36yDLh6KVbNDAB9EcElGTmqXjKuChs8OQ40fNajX8FAo1RZBDTWqaXjzYiaqAQg8Mj5rVTvgplKeBK69alKQu0gOR1agt/p00FreaFTUbi4aYIsNQknpl3e8kuGEl37FOzUp9sdqidP2KmtQorqq6vIdK9YDHo5oVFTZAwqysQmu0h02ssn55PxyLqEbz114HrMhTsloFPyhxGd6ZoFs6qOcwtZeq/bjg70DQdk1KVkT1KwBuxAXRdlYaK2f8w4BwJXiqK56IwaFkpTAnk6NAL4EBlu++gcW+GzmAp/ZwdKCBsxsBfwJFq0PwgyJzsB2RlDV7Bu6/ck80P3v38qktIW2YxmfOsRxTsmkoLkpW/fCDKk+U9r2qqmte1xT4Jwdq0aDRK+mTykXJSnGJkMcjYnZzZGpQT2Re/vhwUbLSXVttmhPJadXcgvf0CN0wVskqaNhMwiSaLBORFXj2rnztbhElK42HMOOJpJGgSRN+xN2WP9WKqFjthv/1eB1YwCvSiftLZhRubhUrortKhULQ41gNImTkG5U4XCpWWqvFeS5J64RKVKMAROROsgQqVsSbKzK7FT4mCh1E55+alJKV9uPKY/GcQgAPkpp+YmhJUUrJSqHfVs7TD+GT9NhEPU1UpZSsYsYiHw+rCWA68KpdC2UpJSvyI3S4pdT9yWi9Sq4wUZdSstKvMCHu7FIdWshtG6GXWGlIKVlFCl/l50V/SD3bobFP1rmhI6VkFbqOSo3Fz08Eb+PYeuyOdP6zlpSSVXgvijLPLvS0U/dirnXP2aChkjktKSWr6NEJSd49uNDbs619ZW1tbU1NQ1vXvmOD4yGjzrpV5TJY6TOq+yhPrbSIwYBKN4CAilXs51Us8tKeTzkqViqL6UvGS71ywkXFSi0ESGmYDOwnlKFidQT+LwMj0VpoKlY7lQKblAJi2osSKlbdCT6GdXilOoEDoWSlFPslca4r9QCTKFmFhl8oAXN4Cbw6SlayFWIlZDRWuFwlq9DwC0nzJmawZjWraP2ckbkd6SHFoWZVpTLlLCnmqblxeqhZBS9+T5b7UTae96Fo1ShtpCbMlx9pV9AJFK3CIwYlwtyxqBsKiKharUloV5Yg3p1JaixP1crQHPHWpzAUEqhZA2WrsHUicRnFC12io27VEh5iLDoP9Xutg1C3IoI7JsU0XucXDw0r1WmqmiyMJHudbHSsahPqxOV5dTq5MsJDxyp5rQc98fZRkaFllaxW/nKc/W4C0bNKUOvZ8SjzTHJrOjZs7GgNu8KaVkZtIkXGl2e3hE8F8dO6f/A+1HDykxcPbQioMOpaWQV83OfW5MngAR+S2v1oQeNsr/Rq61sZq2PUMhbuHFEZnPOzbpD8U+aHJTHuI1hZdcJoVd35kZ5I1deqPnkMlIvkcEkkK2PNZd321vOR49sitjLaA8N7Pn0fDuOJZmUYK4+jWaMyXt48tUM2Sz2c3MmwP+AQ7rWOamXdF7vCt42YGzu9M17PSrVCc3Uc3dfRrSxa9gwUy1qBb6dGh/oPdW+IXxmqVtr+dspfGMayssm19Xx6bmh4+Mqli+cHz54+vGsj7EabBDm0OOnZ2PXrY5P+GRn+7Y5iW5UUMR773GAXRKir33VBnJdxX5wYkGmrD+EEHKZ7xHugS3gsiwHHs2xVzwV3z59C0zS28fdhXohMm2Urbh3tY1zJ2iY+mh/yFcsMW30AH2/xEG9p5pMSg7Fk2Mqb9ziJK1pISggQnl0rL14usX4MSwkL8rNr5VUq8PoxSsqcgkyLzFo1sOofigojSBW8dpE33ySzVsfgw80C6tQVpA7WsGq2t/Yws1ZsWuwNSGCIUlyksldwQIat2C4YXgxRF7+UsZo9jVmpklUrtkb+ra+ujKQMg7WI2Hr5rFqxBaJeEFsHQQoiG7FVt6wymFUrFlBDjLFDSXlRAlhpmVWrc/DZYqQpUspYDyleSKjMW/Fr02gpL2R15Vh1QYKFRMqLbZ55K9YK9pYECVL8lCAWKLFyrFiwPamUt4NZ5q1YGViMIiBIidOm2VOAVUOyasXOFML4Bkh5VSY2oTWrViy26ZzTXxEkZbAtttmJZtXKC39if7og5Y9r2lg59UBv0or1ZQmU8ubDVUCdvRc+3MyvDZaqZUFAhiElw1YrWVv4YaCUp29uhpQMW5EbTRFSbcyZC46bXSsixn0Bzwav8TYhOQJJFtm1MlCQX0Iq513Rt1ynYYathLEDiwKOVFx1GfIsTkKaTYatfLNiCalGLvjKJD+6kGWrBiFqIV4y183tW5oXhheybCUuDpjZ5xu/EiYfiWuaMm3l21V9brALRghynSfFaIKfh441wg8ekZdBxabKv+Fl4cmdG1dGp/1D7FO+QRMcmA1fq71wbBkggjERPPEvAELPOuIOjB/VJjrLFUKGTKAxO7Rah7Aq7qxXFnKnQ4L4m8N4KhOKdENYcRtLlYNOcme2Ii+osgzN2iFKi0U8Kpsq1Z/IpzJdpmaxVeMJO8tMFN+EDtacIm0Xybl7C9fpyEh4+82FZeav4UfGbBKrh+JRdwjdh09PyNY+oiAP3/x0mYm+WGV8DnN0HLw4AbdiYfrKsS3SPzUOYrxkfa+w1Uy80F7JUd3aYdEeeDo5HI/DtjJxkJ3wkH3ZgQjL9gfbCl+s4LiomaIdF5i/cq4VtjLn8W6Q2aSNCLq+5FiZ/+e+4qkQLUqq8DvXirhY5nxojM8MsJsKfWxdqqVlP7F++KP7WmSsFIuKkqSB3NZ98Wvbyr5Q1MWyLtc5lfCR5aLlUzoqqn2pLCu7bvG/boqfxdtHN2Xl2cVTs+HQDfw8cvjjf7pW8ovlUJh59DBbTM7Iq7/upbKt/s568dduWsXzS2a1ZFekvnJTK5yF33tWIfdgBeEoWThW/2wnuOkVjWNk41gtfWMnuTkVzA8dFxvXyvlqVbrW37gqNmDlGFW21k/AxKZoVfFaoOHCrFwtyRM78yyCBOBZuUa/dQ6qNP77X8AB4KyWnNqgU3BUGEtLfwIKAG+1ZLdKTNOuQVUSv+TLCRfBamnpe+e4f3L+rQy+WFr6Uzh5D5+VW2hUTLFhFxJ/7p63ALJiXktkCzlDFH5kneyfuefsg7ByK1A2VitF0p4sM1/93DpL8x/ds0UsLf0/wi0yyTeHp4gAAAAASUVORK5CYII=' +r11 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAALi4uMDAwPz8/S0tL/1VV/1ZW/1dX/1hY/1lZ/1pa/1tb/1xc/11d/15e/19f/2Bg/2Fh/2Ji/2Nj/2Rk/2Vl/2Zm/2ho/2lp/2pq/2xs/21t/25u/3Bw/3Fx/3Jy/3R0/3V1/3Z2/3d3/3h4/3l5/3p6/3x8/35+l5eXmZmZmpqanJycnZ2dnp6eoKCgoqKio6OjpKSkpqamqKioqqqqq6urrKysra2trq6usbGxsrKys7OztLS0tbW1tra2t7e3uLi4urq6u7u7vLy8vr6+v7+//4CA/4KC/4SE/4WF/4aG/4iI/4qK/4uL/4yM/42N/46O/4+P/5CQ/5KS/5SU/5aW/5eX/5iY/5qa/5ub/5yc/56e/6Cg/6Gh/6Ki/6Oj/6Sk/6am/6io/6mp/6qq/6ys/66u/7Cw/7Ky/7S0/7a2/7e3/7i4/7m5/7q6/7u7/7y8/76+wMDAwcHBwsLCxMTEx8fHyMjIysrKy8vLzMzMzs7Oz8/P09PT1NTU1dXV1tbW19fX2NjY2dnZ2tra29vb3d3d3t7e39/f/8DA/8LC/8TE/8bG/8jI/8rK/8vL/8zM/87O/9DQ/9HR/9LS/9PT/9TU/9XV/9bW/9fX/9jY/9nZ/9ra/9zc/93d/97e/9/f4ODg4eHh4+Pj5OTk5ubm5+fn6enp6urq6+vr7Ozs7e3t7u7u7+/v/+Dg/+Hh/+Li/+Pj/+Tk/+bm/+jo/+rq/+zs/+3t/+7u8PDw8fHx8vLy8/Pz9PT09vb29/f3//Dw//Hx//Ly//T0//X1//b2//f3+Pj4+vr6+/v7//j4//n5//r6//v7/vz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeyflvwAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABGPSURBVHhe1Z2Lf9XUHcC7R9oCBWqHIKgrAkK3idvUTbe5qduUIiDyUhk4R3lIsQNB3eZrvqcrpVrAjjkQcT7mhMlAimxzSktXkNKW/EN3Sc4vuUnOSfL7/ZLcm/P9fPDmJuek52tukvM+NaU4bv3jF2YRuXjkd9dAEpVEW/12FE5RWN77FiRVIsLqZ2MQs+C8A+kNobR6AeLowGeQ5gCy1Y1PQ3hd+C8k3Idkdc1FCKwRL/4AEu8SsrrjbQioF6OQfJeQ1TkIph2PgIAgaAVBdOSVG8HBxm/1fQigJx/cARoWPqub4LCuHH4MRHxW354PB/Xl/Z+Ai2f1HZ3vKZfnQaZ8rTTJIsXzQ5ABK/MD2K85wgaszt0Me3Xn8yccH8fqnZib6sKhfXuLRe/+05A2BeI5aFtdb74L+0JcfP0Xc8YZBeSypR1nII1h/uNaXVRfqvNbvw4nKSINq49BOoO8/Q1h9QfzCOwJ8MYMiF9U6taPQFIDwLUyVZdq5IFaiFxgrjoKqfXzimP1vqkofYwsgYjFpvEgpNfPv20r1aXSREqt9WPL6lnzu/DNxz0Qqfg0noQklzl3e6nGNP8F38q8ClF0YKFcI2FdK8UPsH8KxAgza3mY8XCkimyDVJe5UWl1P4SXaPoIQnhcCkeqyOQhSIvH4fk15s9h22NoEoSXkbQKYKW4WM/XmIdh02MrhFYR1iqCVbN0Z41ZT4swcyG0kpBWEawM6eluv69CjMTmZ+t2QTBBIax+DYnxuF62OghhldR1QSigEFarIDEej8hW2yCsirBUMayaITEej8tWmyCsAkmqGFZTIDEeT8pPizYIKyNLFcNqEiTG41H5WkVaKaQKavUk3kolpb2VUkp3K7WU5lay1OBiO5ehtZVCaq6TedLZSinl5Ak1toqQsrX0tYqQmmf9a2pwQlQZjlWE1KqxDeJ49WFYRUqZF64QIaoO3SpayjR7RJCqQ7aKkzJHC/GsYFjtgJ0ePqmYyqjKQrVaAfs8AlJmlwhVbYhWk07BPpeglHlUBKs2RKs1sMslJGUOimDVhmh1AHYBYSk9rZpgD+BI3eOTMgdEuGpDs1oAewSyVHwlW+WgWa2GPQ4KKbNThKs2NKv7YY+NSqoojXdsK6XUcHTjSUWhWZVrepVS5g4RrOrQrK6GPRFSA1FNkpWGZtUAvTTUUuYqEar60KyM15wdEVLrRJgCQLS62/4+eLW1VWQpqlXtQR2kqFbGnDENpGhW9da/ezWQolltahafRZeiWW3rd7QKL0W0Mm2t4ktRrSwtDaTIVuaZakg1Nreuantox86u7td279372q4dGxd9DQ4pIVtJ5Cg1Y8HKX23peuPEMPypAH3dba32Q1lFaqucpKYv29w7CH8imlMbp0L4IGmtcpCaumTTngE4fSIjXXZLTJiUVhlLjWvd0BOucUzk0FKIXSadVaZSk1fsSv7NKelqglO4pLLKUGramr3KHvY4ToV6cKexykyqeb2qFzqJzkY4l0MKq4ykWtpPwAlT8cksOJ8N32poJuxNw+T7P4bTpWbAp5XiWvWn1mreJvVmToFPK819lU6rbumf4DxZUdZKY5VGq6mtD06SIZ4WyeqezhBbmCMNru5UZu1S0w/t0iSrjGjdDyfOHuhEUHmrmXvgtLkgKlorbTW9UyqfZcrgNPuvVNaqsT2f+8nHHvvvVNJq/Dp0ASMFq62/VDmr2lU5PMsVnLIKyBWzWqQaHZoLKypmdYnU+yk/9lfKajG5gJuG2RWxmtwJJ6oQOyphtVAe6povw025W018GM5SQdbkbbUgk4Iukc58rRo68s0fRXAsV6s5mRXfaYxNhQ2PDK1W5p7pi2IRfHpkZlX7IESvAm3w6ZGV1UTRNSOW8xvbEgn1s8TRDZ8eGVlNR2X7epJn1tkKQUn8Ez49srFa0A9xE0jWYllJr5NMrFaj68wTtVhWUrYzA6s6acB4DElaLCupdJreqvF1iIcjQYtlJU04ldpqGvXVG6/FspLu6rRWZKkErULcVwypeC2WlVT2SWfFkortBMqyyvbJzpR6EKKrYFlJyUhjNY1XmIqT4llJk9OlsMpDimclNTPzrXKR4ln1wKcH2yofKZ7Vdvj04FrlJMWz2gSfHkyrSerZI5NIlOJZhYf0Ma1qpV8yimQpnpXT7d4Pz6odgtJASPGs5sGnB8tKmtUJBUaKZzUDPj04VnMvQEgSKCmW1UgW9YHTWC0eOCmWVV8GVg1vQTgSSCmW1YEMrIJz0iHBSrGsutNbbYRQJNBSLKuO1FZLOe0DeCmWVVtaq2ZOXziCFMtqVUqr+kMQhgJCasJGt98Xx+qqlFacmwoj1Wv2gBbDarg+ndVsRr9mnJRVRhJaDKv96Vq7x0m19MlgpVwthlVHOqvNEIAAXgq0GFarUlnNpT/UKVJCi2H19TRWE47DcTw0KUeLbjVUm8ZqCxzGQ5WytehW+9L0Y2oh//7oUpaWNP9TIu0prBrItS8UqTNr3fZ/+r2bpicd+ZdBkppjLGb3P7mcbzWb+keJUtyqENOZZohrFf79J0GWMiYyu6rtteIyre6EQ1joUlYZB74TsWe95lnVhtcFSIAjZRi8OkZ79CbPilhTxpMy5sIuEqfsdXdYVuNpfbiZUobBaePbbkdkWT0AB3CwpYz1sJfCYjsix6qRNIRgC8SKoUEtZUynrys75BRfOFakAkhn8vpSUVKGQR/StMuJx7CaRunM2Jc8q2+0lNEBR/CsdOIxrEj5TednHkuMVHAOPAwjYtgw3WomJa+UvBZTnJQhtdgk0Svi0a0oFdDnL4NIkcRKGY1wEM1aEY9sNZVSreS8POKIlzIMZOdJD/i/SLaSGpLjaIFIUSRJGZ/AcSRvQTSqVT2lraov4ameKEW12gjRqFYrYR+KmEVjbJKliFZj7oKSVCtSR+z4od8IKaLVbohFtZoDu1BcqINYSjBSxKfFIohFtSK9gQ9BJCUoKdqT/WOIRbVqIo382AmxVKCkiG/h8jTqNCtp/EUs/vsxBE6KlmMamgyxiFa1tNLiMogmg5QyHoJgKHyLj5GsiPUjd0E0CawUrSQCkxvakKzcxCCJskJLkUqN+yCSDcVqKrFmM8IKLUUr4ftn0KJYUUs7aiu8lEFpSurzvxwpVrvhO5YVEC8AQcqb3xmDd5vYEKwmUZu23bymn7LUbNgTDWK0ncdwYJZEgtVy+IpG1IwEoEgtgaAo2iGSgGBFnvbgmIjngyLVQHk5nrkEYgnwVvXkafBGw4NaKFK0+rnQnGt4q4XwjYA9NbgPktTiUQiM4aToceKBt2J0EXjIiehCkmoh5aPDyy3grYiFbZt+/xynDe60Zhipef+DwCiOhmsS0Fak8qKLr44zR6lyadEFbUWqW3IpL7GUp5Q/ByhAW7FGTIy6NRd5Spn23OpBsFbTYJvIfvGLz1VK8bLHWjGbns377D/iSQ3kIDVyOUT0gbXiTuswYOXPcpUyOyCiH6wVbby2j97x+Up9EpgSFsBaSWPAE3Fz+N25SslPdRuk1RWwSWBxKHeQj5R6ZSCklbT0XzL1CwNa+Uj1qRdxQloxukrVG36tfKTMVogaAmn1Z9gkYOUBy1o5SW2FqGFwVrWMcRN2ztbVyknqRFQHAZxVM2xRcPLrQisnqbHIpkycFWfcoiiF2Fo5ScX0usFZ0XtzuFaWVl5SxydAZBmcFWeqJ7AyFuYkNRaqP/CDs+IMsnKtEHCklLWNLiirybBBAm/FkuqGyEpQVlfCBgm0FUvqo9heXyirVtgggbViSZ2eDrHVoKxInSxckFYsqRHVgi8+UFbrYIMEzoolZd4LsaNAWdFH71igrHhSiZ1eUVas0dsYK57UnsROryirv8AGCYQVT+p4uQdCFCgr1pQwyVY8qYErIHoMKCvW9BWJVjyp0YiCYgCMFasyOtGKKaVsbA6DsWI9ApOs8pRCWdGHFtrEW+UqhbJiPdjjrfKVQlm9Cp804qxylkJZUfo9lImxylsKZcUbsxZt1UDtpe5AkEJZUXv6CGKulb/6EwtFCmXFWy4o7r6ia5GkUFa8Vp44K7LWCEkKZeX2k6ARa0XUOp1QSgxTpWtF0zqUODQoRFWeFg54re7k8XYhMFZZP9kBrFbCaBMVGCtpvn0UiVY4rfPLITQFjBWjX5ZF++ZEEB27TyLqs2UwVhsYsy5lxAFYqpAIxqqNM+1XJnSG+v1hQVlJk+JWhmEYe0kHZUUetpsJBxDVLhGgrGbBRiW5sC55qHskKKv6LBfMxXHQN5aFDsrKqPTKXCMbYgcPJoKz4rThp+DoVZA6LjgrYx9sVoLRTcnZkgSQVtJ00/lxTO5wSgZpVVepdfwGHohfCgYH0oo1hQud4c2qPox0sFaTKrA069gOZ3HgDMBaGawWbxI9qV5RAdBWnHEiFA4scP5KNuCt6BMGEviYUzaMBm/FmNwRS9/a1G+oIAQr9ox+CfQuZeZj7+4J456IYlXLa8iKZWhrimeEVO5zLznFKnut42vVfZyxhLVYVtlqjfXcCaflE9LiWWWoNdDuTvKSimA7KNPKqOV0VpXo37GYWc8SYmawKYxrZRiLGAMcA3zc3pKi8B4gJJXCymhMs7j4m23Z5YskqTRWhrGEtxD8yN41WWVfHSSpdFZG0xbqQO/+3ZuWJPeqIiFLpbQyjIlr0MM3B3s3L4vvUMpCIZXaymJBd+Kg8qE3tqzk11XGopLKwsowLr1r017VzKODx3s7N69dNm96Vs86GaVUNlYOM5Y/2LF9566dndsf7tiy+ZcrWi4nNw3SkaWc9012VtVAluoZb2eetLZSSI1z8oQ6W6mlbC2NraKkLC19rdRSDQ/7axK1s4qQ2uebdUI/q0gp01wIQSw0s4qRMvdDGAu9rJpjpJwlNwCtrKZIJSC/lG9SJq2sdkKCPAJSvnlAdbKS5h4NSvnmbNXJKly/FZIyT0A4razGh/qLh6X0tAotLyJJmUchoFZW90JyBLKUbwojjawCa0MqpMz1EFArK/8wMJWUb4pxPa9Vj1XkkKQ+gnAWGlndB8mJkPJP2aqRlfcMVEvZq3m5aGQ1AfrzOVLS9Dx9/spujawM0WqhljoZaA3TyarFTgxGSisru2ERJaWX1dR+nJRGVnYrxJU4KY2susSkFhgpjax2jdlaKCmdrExLCyellZU5thYnpZeVjFpKc6sIKb2toqS0toqUkq2eqIGNMgW1ipaSrW6VrxVjEGgOhK1ipIwpEMbjCdkqcSW/ihCyipMyZkIgj8dlq9jVuSpG0CpWKlTJZnG7bDWSTV++lASs+mOljG0QzOM6+WmRuOxiRQhYjTkzpEciDZot1Zh/h02PQtxYwV9grNYsaYWp0RrzNtj0GG6C4NUk9LSI05I7B/++xpRurPDSKlUhZBWjJa/p97dvqqwGM+2DyWPmwhCtUT3a5B60N1j3lfkhfCnjr0IsOnfJ67ads63mwxcf7MHjFefS05DkMmdvs63kn6A5JhbELj5TFD1nbyrZVuZL4psfTbRUUuYRYaW4WOZY+mG8+dOiGvr2Qsmyetra+EB8D3IofmXd6jO+XTnwzZIqOflA1cWyMoRdxHmRKkpTm3qc7EvC6q/W5stij8TBttZshvRmS93M+zqj5tY5LKycixW9WOfFvqNvFou3jp+HtCm4zZayrZ6xvtwg9mnPp4+5Vs6Felfs1R3HSVhdY389J3brzXVCyrEq2Q8L9XNQL55ylCwcq9Ln1i79td6+wZGxEFbOrXWtOKYt790iXCzAyrlQ9v2lL+/8CFQsXCtHK+a1VXiemQ8iNp6V0PrMCaEhN4OFoGxVcvKKzzlhdOMsKLj4rEqf2gFKXzjhtOKpa78ECoDfqmSXSkzzUee/+vAhpN5HwKpUOuuEe9z5rx78o/TolyHxZUJWpZ+KsN8TeoXn2VLpq5ByP2GrUuk3InzplqI/Dy8+Z6X2KyLRIWSrUuk6OwNlU7r+6SOFfIWdfdkqR5kvQnrDlEr/B4IwRFAYphQqAAAAAElFTkSuQmCC' +r12 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAAQEBAgICBAICBAQEBgYGCAgICgoKDAwMDg4OEQYGFgcHHAoKEBAQEhISFBQUFhYWGRkZGhoaHBwcHx8fNxISISEhIiIiJCQkJycnKCgoKioqLCwsLi4uMDAwMjIyNDQ0NjY2ODg4PDw8Pz8/QBUVTBkZUhsbZSEhQEBAQkJCRUVFR0dHSEhISkpKTU1NUFBQUlJSVFRUVlZWWFhYWlpaXFxcXl5eYGBgYWFhYmJiZGRkZmZmaGhoaWlpampqbGxsgysrii4urjo6tz09wEBAzURE00ZG1kdH2EhI5ExM7k9P5F1d8VBQ9VFR+FJS/lRU/1ZW/1hY/1pa/1xc/15e/2Bg/2Ji/2Rk/2Zm/2ho/2pq/2xs/25u/3Bw/3Jy/3R0/3Z2/3h4/3p6/3x8/35+qampqqqqq6urrKysrq6ur6+vsLCwsrKytLS0tra2ubm5urq6u7u7vb29vr6+/4CA/4KC/4SE/4aG/4iI/4qK/4yM/46O/5CQ/5KS/5SU/5aW/5iY/5qa/5yc/56e/6Cg/6Ki/6Sk/6am/6io/6qq/6ys/66u/7Cw/7Ky/7S0/7a2/7i4/7q6/7y8/76+wMDAwsLCxMTExsbGyMjIysrKzMzMzs7Oz8/P0dHR0tLS1NTU1tbW2dnZ2tra3d3d3t7e/8DA/8LC/8TE/8bG/8jI/8rK/8zM/87O/9DQ/9LS/9TU/9bW/9jY/9ra/9zc/97e4ODg4uLi5OPj5OTk5ubm6Ojo6urq7Ozs7e3t7u7u7+/v/+Dg/+Li/+Tk/+bm/+jo/+rq/+zs/+7u8PDw8vLy8/Pz9PT09vb2//Dw//Ly//T0//b2+Pj4+fn5+vr6//j4//r6/fz8/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfVCjXAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABVDSURBVHhe3Z35Y9XGncAnbCjp7qZpmt2w2zSEdrNH98g2zZY2QAN7H93DzzYGbGzsgMvSpkma5XLAnMEEGxsMhjSwaa4t2OAYAwaWhCSLsY1DOewGW9Zfo9Xx1UijGY2+oyfpPfXzQyLrjd7TB0lfjUYz3yGGjB+/97leltx8C/ZQTJjV95575VfwDWXLp7CvPGKrZ/+zTI9RkE9ghwMIrX4G2+QBzXgO9toHb7X+FSifF+7BjvvgrXJy7vn56Eew7y4Bqw0noGDOgN13Ya2Wfgalcse7YODgt1pgaFAmh3y6HiwsmGMFBfLJ7Q1gYeK3go/zyufHwIOxgg/zy+0XwcRnleNryuVjUPGsfgmf5JqfL3RkHKul+tuwPufYNq7VvfxfVA4zx20f2+qy5KLShs8NlBdnz4/NwM7xXPKs9DdgXZChtubqijJkxZaOG7CLQajVjPj803rXwpeUI5XbzsN+stwCq/fFoeL687B92bJzAnaVAax00aGaOVgF25YxtWdhb/1YB4sYH+o/hb99zOyFDcubytOwv35sK10QAHMiJdZ6caFB3hGdgJ2wUflTKYgZGwyi6/zj77VK2CYH1E/BTnuYx0p/jrulTTfBFlhqN7+6tWV1Af7KmNdgrz3Wm1b8CXgYyqNYtqd/3Nls6nxnPazMlBHn5z0+EVnNrIbiCFZ1T8JWDgMt8EGG8AfrXcLXls5C6WgKbfxJfXoFfJgZy9h/WBON6P8Hi5QdUDqS2nOwBcOdV+HjzDgJv0wxyEJY8miAwlHUjcIGAbTtUCAr9sAPU6y7cIAJZCwLk8peaw38LuUoWQxLlEEoG0HVdSgvQGuGQtlQFawcHSfPwRKl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' +back = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAABQUFCQkJDQ0NERERFRUVGRkZHR0dICAgJSUlKCgoLS0tMTExNTU1OTk5PT09Pn4AQn4AQUFBRUVFSUlJTU1NUVFRVVVVWlpaXV1dYWFhZWVlaWlpbm5ucXFxdXV1eXl5fX19az+RUUGvU0G0UkK4TUrcUVH0U1P6VVX+XV30Wlr+YmH9amr/bm7/cnL/eXH2e3v/BJUAFYUAGIQAAKMAAKoAC60LEa8QE7ASGrIaI7UjKbcpK7grM7cpNbgqMroyPL08e4UAZb48Qb9BRMBETMNMVMVUWcdZXchdY8pja81rcM9wddB1fNN8Z5a2cJuqlkJ0mkNyzktfykpg81FS+lNT/lVV/1tb819p/l9g82Bs/2Ji/2ho/21t/3Jy/3t7vHy+gXn2mn3hvH3A3W+Q3XCSgYYAl749mL08vZUAwpYAyrcpyLgq7aMA7K8Q8KQA/qoA/6wJ/68Q/7AU/7Md/7Uj/7cp/7gr/7oz/7499Zhr/5ZnzsBD/8BD/8NM/8VU/8pj/81r/89w/9By/9J7gYGBhYWFiYmJjIyMkJCQlZWVmZmZnZ2doaGhpaWlqampra2tsbGxtbW1urq6vLy8hIT/k5P/mJj/gKfCoZjYpJzYoaH/pKT/qqr/rq7/s7P/u7v/gtWCiNeIi9iLk9qTm92bo+Cjq+OrsuWyuOe4vOi8/4KC/4yM/5CQ/5WV/5ub/6qF/qOj/6mp/62t/7Ky/7W1/7m5/76+wcSDwcaJ/9WD/9eI/9mO/9uU/92c/9+g/+Cl/+Kr/+Sx/+e5/+i8wcHBxcXFysrKzc3N0dHR1dXV2NjY3d3dw8P/ycn/0dH/1dX/3Nz/w+rDy+3L0e/R1fDV3PPc/8LC/8XF/8vL/9TU/9nZ/9zc/+vE/+7N/+/R//DV//La4eHh5eXl6enp7e3t5eX/7Oz/5PXk6ffp7Pjs/+Pj/+np/+3t//Xj//fo//js8fHx9fX19PT+9Pv0//Hx//X1//ry+fn5+Pj++fz5//n5//z4/v7+AAAAwISkTAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABclSURBVHhe3Z15YBXHfcff0wkoQIsQAnNIpGlcFWLqtEGA6tYkMTS2oadLDzdO77vp5TZNL/cIt7ksuWnrxA6JDxK7pooP2rShcVqQkKjrJG0wmKa20GsOgRspAeTgob/fzG/v3fdmZn/v7Vt//rCl92af5sPb/e7szuxM4WoFRF1BlapEBSv6sPqC6laGslb0KfUJ1TGWMla0dZ1DlQ2SaEUb5QCqsJ8EK9ogH1CdfcRaUencQNX2iLGiormCqu4QsaJieYNqT4StqFD+oPorQlZUJI+QgSRoRQXyCTkgASt6O6+QBeC3ojdzC2kAPit6L8eQiN+K3skzZOKzojeinDw+0F9XDBwfpapFIBfXil4OcXJ5e1OhDmmc1z1CVQxCNuWs+ufTh9Ql7Qeomn7IhqzoRT/jHbR53dI+RlX1oXSUFb3kZ39d7npBmvZQZT2kTqLVbtqwztlB1fWQPtKKXvCRE6kYrTJWB2ib8hSbW2dkvp/upSq7JFqNN9MmSTTNX75vuKTK7l9AL2ZDYzgyEq06aYt4Xrd1mMoRI3PpnUyYT7VwSbA6RuXjaOqKO/0to3cz4R6qhANZ0W8uyV9V664pKiMunX3+qY//zX33Pyd/y1KrXdbAR6zVGJWO0LRzWpW4cOTxd24BfrAHuO4/8KUsd8JIszDOajsVDrNYxcOlp9+FRsBtb0Srnp4H4NUTVCgLumW9fMRZxWda64B88/zhHyOnLVter6R6evDbyjAJo7sgWNGPLq1UOECH/KIu+Jy2/Mi1JNWzCt7aRwUzoAmr5ifGapzKBlgu33rK57Rly7eSEwCREbtZjYgcWFGrESrqoyhbkRPO8aSQUUHgkdVI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' +r2 = b'iVBORw0KGgoAAAANSUhEUgAAANQAAAE/CAMAAAAJ9B3fAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAA/1VV/1ZW/1dX/1hY/1lZ/1pa/1xc/11d/15e/19f/2Bg/2Fh/2Ji/2Rk/2Vl/2Zm/2ho/2lp/2pq/2xs/21t/25u/29v/3Bw/3Fx/3Jy/3Nz/3R0/3V1/3Z2/3h4/3l5/3p6/3x8/35+/4CA/4KC/4OD/4SE/4WF/4aG/4iI/4mJ/4qK/4uL/4yM/42N/46O/5CQ/5KS/5SU/5aW/5eX/5iY/5qa/5ub/5yc/56e/6Cg/6Ki/6Oj/6Sk/6am/6io/6mp/6qq/6ys/66u/7Cw/7Gx/7Ky/7S0/7a2/7e3/7i4/7m5/7q6/7y8/76+09PT1NTU1dXV1tbW19fX2NjY2tra3d3d3t7e39/f/8DA/8LC/8TE/8bG/8jI/8rK/8vL/8zM/83N/87O/9DQ/9HR/9LS/9PT/9TU/9XV/9bW/9fX/9jY/9nZ/9ra/9zc/93d/97e/9/f4ODg4+Pj5OTk5ubm5+fn6Ojo6enp6urq6+vr7Ozs7e3t7u7u7+/v/+Dg/+Hh/+Li/+Pj/+Tk/+bm/+jo/+rq/+vr/+zs/+7u/+/v8/Pz9PT09fX19vb29/f3//Dw//Hx//Ly//T0//X1//b2//f3+Pj4+fn5+vr6+/v7//j4//n5//r6//v7/vz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0cgG7QAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABLQSURBVHhe3Z15QxRHGocdBgcEQVwSNR6wKsR4xIsENBohaASNQI5NdhfwjjEuKxpybJJNNsEbybEehDURYegPOtvT/aP6qGOqqqtnun3+mZnq6qYeeqa7uo63lhVEvP9fyypY+JAMrCK/vItPbPhSvxRl/rPoHCRp/PF3u2w/OcVkwZH6pVD4CgdILAtcL6bUYuEL7Jhw8ihwCIbUYuFX7JMGPkSp/VBSPxd+Rva0gIL7oKQ+QtYUsYiiE4JSXxcWkDFdfI7yg4DUE/cukEJ+h4GLXyr/N2RJI3Bw8Et9i+3pBBJFfFLfY2tagYYNkXryL2xLLzDxpL7+C7akGbh4ZwrpqcauDTosSSE55XzryrhSP9vPTc8Fjs3SmUIagwdXL19KFlcmnqFsDBwbVwopYR6f3P2nTAJZ3nrgE87T6xdE6nOkBLnZVYODJJGXTj1FOYMQKXwOMN+Txe5J5YUxFDXAfyDFqvJNbsSuCabq8DxK6wdS+OTnWj12TDa7GFb2YwhbKiVObCtH6nd88LiXFqdM5jUU2Ycjhfceiy9jjzRwDoX2+IEpdQr5A2Q37Njz6rbV+JQcGh+i1B62FPUYNVuH/B5rj1+dczdOXzi4AokJ4ZBbMB+2FN55UCdqxyVscfntnRewIRHUzaJcBIbU4nrkBo1nscFj7nAVNiaBAZSK8D0tdQ15wS76O2szlqA64WaUyYOWOom8LvvzSA5xpxkZKk+OulfRUh3I68BzSpTVdRSJsOw9vCH4f1JbuU6WdSuHTBWH+lEtox47GpHVpuY20pj0IVfFOYoCEZZ9iDcE323oJJIcpkYHBi/gbuWQ34JslaYbBSIs+xJvCJ5Us+/L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' +r3 = b'iVBORw0KGgoAAAANSUhEUgAAANQAAAE/CAMAAAAJ9B3fAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAALi4uMDAwNDQ0/1VV/1ZW/1dX/1hY/1lZ/1pa/1xc/11d/15e/2Bg/2Fh/2Ji/2Nj/2Rk/2Vl/2Zm/2ho/2lp/2pq/2tr/2xs/21t/25u/29v/3Bw/3Jy/3Nz/3R0/3Z2/3d3/3h4/3p6/3x8/319/35+/39/gICAgoKChISEhYWFiYmJioqKi4uLjIyMjo6Oj4+PkZGRlJSUlZWVlpaW/4CA/4GB/4KC/4SE/4WF/4aG/4eH/4iI/4qK/4uL/4yM/42N/46O/5CQ/5GR/5KS/5OT/5SU/5aW/5eX/5iY/5qa/5yc/56e/5+f/6Cg/6Ki/6Sk/6am/6en/6io/6qq/6ys/62t/66u/6+v/7Cw/7Gx/7Ky/7Oz/7S0/7a2/7i4/7m5/7q6/7y8/76+/8DA/8HB/8LC/8PD/8TE/8XF/8bG/8fH/8jI/8nJ/8rK/8zM/87O/9DQ/9HR/9LS/9PT/9TU/9XV/9bW/9jY/9ra/9vb/9zc/93d/97e4+Pj5OTk5eXl5ubm5+fn6Ojo6enp7Ozs7u7u7+/v/+Dg/+Li/+Pj/+Tk/+Xl/+bm/+fn/+jo/+np/+rq/+vr/+zs/+3t/+7u/+/v8PDw8/Pz9PT09vb29/f3//Dw//Hx//Ly//Pz//T0//X1//b2//f3+fn5+vr6//j4//n5//r6//v7/vz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA75ob3AAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABOtSURBVHhe3Z39QxTHHYdteweCUDSgUYMBJS9N39JXI7EYojEq+IJGQo0GCvgWNSI10RASmqavhhhjlNA2DVU0CZ7H/ovXvb3Pzc7uzM7O293t+vxyx8zs3T7s3u7O23dWFAT8pvDXZSeJ5D8q/BL7yCNS6vkCPiCxLBd+jH0NEyWFDRPOMvY2BFfqH9gmDXyMfabhSP0NxdMCdpuClULRNIE9J4SlvkK5dPEP7D0ISaFQ6lj+BQQ8glIokkZg4BGQQn46gUMRWgq5aQUWLpQU8tILPGgp5KQZmBCpnyE93UCmLJVHcrr5piQDqY+RmnZKNpBCGofF6SuXk8XVD+9j3zj8qGhTkoo4+ZZO7d6YSSDZTXsvPMQ+hvjKl0JKkNtHWvAhSaRtaAH7GYRI4e8Ay6ON2DyptFzArgZ4KJCa68amSWbXXewtDaQ4jSu31mO7ZNN5B/tL8V9P6uf4iyIlTnwrT+rP+MPn/hPYJvk8zV64PSm8pziALdLAceyzz7Ir9WO893kX5YM0v9Dbu7UZfySHlZ9gr314R2r5SZSnWH/i81LmZ2+sQ1JS2F7aMQpX6hu8JVxBaZ/V56gzN38mYffkz7BjhI9WsD+pXhQm7Ajdu+e3IyMZHMRuEZZZqcU6FC7zCnOByb2MrETQzOwfKxW+TLzEedrNJepYXcdeEVipYygKHuPc3twzMEm/qzPYKQIrFTq1LiI5xFlkJwHmR8VKPYuiJdqRGiafoAep3dgnwgqmxaULRUuMItXl87HxL/DW5QQKJIBe7BKBPVJbULTEPFKd3KtZt8q5j1Q4b6JAAngJu0SIkWpDouPsKiXsxZ+Ok5xLharUDiQ6s0jI3kSC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' +r4 = b'iVBORw0KGgoAAAANSUhEUgAAANQAAAE/CAMAAAAJ9B3fAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAALi4uMDAwNDQ0PDw8Pz8/QUFBSUlJS0tLTU1NUlJSV1dXWlpaXFxcXV1dYGBgYWFhYmJiZGRkZmZmbGxsbW1tbm5u/1VV/1ZW/1dX/1hY/1pa/1tb/1xc/11d/15e/19f/2Bg/2Fh/2Ji/2Rk/2Vl/2Zm/2ho/2lp/2pq/2tr/2xs/21t/25u/3Bw/3Jy/3R0/3V1/3Z2/3h4/3l5/3p6/3t7/3x8/319/35+/39/urq6u7u7vr6+v7+//4CA/4KC/4SE/4WF/4aG/4eH/4iI/4mJ/4qK/4yM/42N/46O/4+P/5CQ/5GR/5KS/5SU/5aW/5eX/5iY/5mZ/5qa/5yc/56e/5+f/6Cg/6Ki/6Oj/6Sk/6am/6en/6io/6mp/6qq/6ys/66u/7Cw/7Gx/7Ky/7S0/7W1/7a2/7i4/7m5/7q6/7y8/729/76+wcHBwsLCw8PDxMTExcXFxsbGycnJysrKy8vLzc3Nzs7Oz8/P0dHR0tLS09PT1NTU1tbW19fX2NjY2tra29vb3t7e39/f/8DA/8LC/8TE/8bG/8jI/8rK/8vL/8zM/83N/87O/9DQ/9HR/9LS/9TU/9XV/9bW/9jY/9ra/9vb/9zc/93d/97e/9/f4ODg4eHh4uLi4+Pj5OTk5ubm6urq7Ozs7e3t7u7u/+Dg/+Li/+Pj/+Tk/+bm/+fn/+jo/+np/+rq/+vr/+zs/+3t/+7u/+/v8fHx8vLy8/Pz9fX19vb2//Dw//Hx//Ly//Pz//T0//X1//b2//f3+Pj4+fn5+vr6//j4//n5//r6/vz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASP4oJQAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABDtSURBVHhe7Z39YxTFGcdTa99b+4oJgTRAIFERkqooUAtBSoiABBEsIUIJIK+GWvtisa1W25KAsWmAIFparW/QiIQ3a0F5qybhsn/U9Xb3ezO7O3N3z+zO7u2k+fxytzM7y3643N7uzDPPVGSL8eCbGSuNjL39DM5QSiGpb2afG8MRUsufca4CcqlJv0y9kctLOGE/Uqk30MQEPsQ5e5FI/RG7m8K7k3DiDFEKu5rEb3DqeQJSi97GfmbxX5w+CEil8wpOAOfv4pW6zcQ/vTzPQcLGK7UI9WbyJ1jk8Eg9jVpT+Qc8PFLfMPlvz4X9EvNPCjUmk78hZFIoNxu4QGrRf1BsNmOuDaSeRanpvOPYQAplEoZfP9qfLo68egXnJsGxcaX+jaIAmd61TZMrU8jsVV3DOMcAzh+gK4USP1e334ljpJHp7Wdwnn6ehdSDn6LAR+8sNE8rU3ZK71QhJfugrq9B0zSzcAhn6+UXrpTkG3X9AbRLNw2ncb4ect8qWwpbHgxxklvZUt8Sb87HlqBN+rnzGs6Z8679Sd3EBmcPWpjAGpyzB1sKbzmna9AgwP0rwb0oSAW9OGuOVGoFdg9Qy37Il6IkFcwWLuy/r8j+AW8Z5wrcRDyBeus1FKSEV3BajEyF2NeyCTsHqPkY9VYLSlLCEpwWp+LreMNpwM4B2lFtnUBBariAE2NUCF+p89g1wJSLqLceRklqEC4VotTL2DXAT1BtnUJBetiMM2OIUpuxq58p51FtrUJJehC+VKLUOuzqZz1qrcEqlKSHe3BqDFGqDbv6qD6LWnl1eZmLU2MQpdai0jqdwifhkFKT2VPmoyhJEyGl2lBnnalGSZoIJ1X1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' +r5 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAALi4uMDAwPDw8Pz8/QUFB/1VV/1ZW/1dX/1hY/1lZ/1pa/1tb/1xc/11d/15e/19f/2Bg/2Ji/2Nj/2Rk/2Vl/2Zm/2dn/2ho/2lp/2pq/2tr/2xs/25u/3Bw/3Fx/3Jy/3R0/3V1/3Z2/3d3/3h4/3l5/3p6/3t7/3x8/319/35+k5OTlJSUlpaWmZmZnJycnp6en5+foKCgoqKipKSkpqamrKysr6+vsbGxs7OztLS0tbW1tra2ubm5urq6vb29v7+//4CA/4GB/4KC/4OD/4SE/4aG/4iI/4qK/4uL/4yM/42N/46O/4+P/5CQ/5GR/5KS/5OT/5SU/5WV/5aW/5eX/5iY/5qa/5ub/5yc/52d/56e/5+f/6Cg/6Ki/6Oj/6Sk/6Wl/6am/6en/6io/6mp/6qq/6ur/6ys/62t/66u/6+v/7Cw/7Gx/7Ky/7Oz/7S0/7W1/7a2/7e3/7i4/7q6/7y8/729/76+wcHBw8PDxMTEx8fHycnJysrKzMzMzc3Nzs7Oz8/P09PT1NTU1dXV1tbW2dnZ2tra29vb3d3d3t7e39/f/8DA/8HB/8LC/8PD/8TE/8XF/8bG/8fH/8jI/8nJ/8rK/8vL/8zM/87O/9DQ/9HR/9LS/9PT/9TU/9XV/9bW/9fX/9jY/9nZ/9ra/9vb/9zc/93d/97e/9/f4ODg4eHh4uLi4+Pj5OTk5eXl5ubm5+fn6Ojo6enp7Ozs7e3t7+/v/+Dg/+Hh/+Li/+Pj/+Tk/+Xl/+bm/+fn/+jo/+np/+rq/+vr/+zs/+7u/+/v8PDw8vLy8/Pz9PT09fX19vb29/f3//Dw//Hx//Ly//Pz//T0//X1//b2//f3+Pj4+fn5+vr6+/v7//j4//n5//r6//v7/vz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+TpPMwAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABPrSURBVHhe7Z35n9bEHcftld2VZZeVQ0SWywPQ3vdtixUXqaJSClK5u4iwImXtutvb3pcgRURcFxTkUNrS1l4CUhTQ2kvAhday7D7kH3ma4/N8kzxzZDJJniSv8v6BJ5n5ZjJvsrkmk8klZRmf+Nl/zVzy52+/H1XkIrb6ek6FPP7wPlSVQWD1qSEsmXN+h/pWwbX6PpYpAv9+Dyrth7X6yLcQXxT+iYr7YKzeVUJwgXgYdSeqrD77UwQWixKqXyFo9a5/I6xwfBMGLkGrC4gpIAeg4OC3+gACismfYWHjs/ogsovKa/CwIKsPlJFZXP4EFc/qg8WXMs2fQ4aszDeRU2g+AxtYmQeQXnBcG1i9+WGkFp03HR3X6oApPlENHtzZly927H4FdePwEFl92BRcJ114+ktThxk55PJZ606hjtWQ1QX+8W/gwckoJI8Mm/cC6hnk97D6qfk8UgLsnYDl80rdkgFUNQCsMBdkqL0eC+eYCc+itn6ed6yeN3+IeR9Dt2PBfNO0C/X141hhOkBBpPhaX7Osfmi+G3M+7sZC+afpKKrsYd1CXmL9IWLOYzsWKQLT2RYJx4qh/wonfvJtYbhxGbMWtfb4tGXF7ljtovBq7nADs6XxNGpD/MOy+iimifOj3PCCWHHqaVn9CpPEI8LoavJhNY7Zsywr5sL2JkQXxcp4CtUhOEeL0ggEF8aqA9UhPs5aHUFscaxmozrEd1mrTYgtjtUVqA7xS9ZqPWKLYzUc1SF+w1p1INaz6usUcA0iM6YO9SQ424q1mouE3IJ6Er9lr9kvWuUE1JO4aJVfUE/iolV+QT2J/2OrrfeA9mV3TqhDbp5APQklqwBntt9x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' +r6 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAALi4uMDAwPT09Pz8//1VV/1ZW/1dX/1hY/1lZ/1pa/1tb/1xc/11d/15e/19f/2Bg/2Ji/2Nj/2Rk/2Vl/2Zm/2ho/2lp/2pq/2xs/25u/29v/3Bw/3Fx/3Jy/3Nz/3R0/3Z2/3d3/3h4/3l5/3p6/3t7/3x8/319/35+/39/kpKSlJSUlZWVl5eXmpqanJycnZ2dn5+foKCgoqKio6OjpaWlpqamq6urrKysra2tsLCws7OztbW1t7e3uLi4ubm5urq6v7+//4CA/4GB/4KC/4SE/4WF/4aG/4eH/4iI/4mJ/4qK/4uL/4yM/42N/46O/5CQ/5GR/5KS/5SU/5WV/5aW/5eX/5iY/5mZ/5qa/5ub/5yc/52d/56e/5+f/6Cg/6Ki/6Oj/6Sk/6Wl/6am/6en/6io/6mp/6qq/6ur/6ys/66u/6+v/7Cw/7Gx/7Ky/7S0/7W1/7a2/7e3/7i4/7m5/7q6/7u7/7y8/76+wMDAwcHBxMTExsbGx8fHyMjIycnJz8/P0dHR09PT1NTU1dXV1tbW19fX2dnZ2tra29vb3Nzc3d3d/8DA/8HB/8LC/8PD/8TE/8bG/8fH/8jI/8nJ/8rK/8vL/8zM/83N/87O/8/P/9DQ/9HR/9LS/9PT/9TU/9XV/9bW/9fX/9jY/9nZ/9ra/9vb/9zc/93d/97e/9/f4ODg4uLi4+Pj5OTk5ubm5+fn6Ojo6+vr7Ozs7e3t7u7u/+Dg/+Hh/+Li/+Tk/+Xl/+bm/+fn/+jo/+np/+rq/+vr/+zs/+7u/+/v8PDw8fHx8vLy8/Pz9PT09fX19vb29/f3//Dw//Hx//Ly//Pz//T0//X1//b2//f3+Pj4+fn5+vr6+/v7//j4//n5//r6//v7/vz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6r+4xAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABV+SURBVHhe3Z35YxbHfYfpsa9eBAhhECABsjC2MaRO3LS1G6dN0nIYsMCACSaAwQILDOJQOAzI6Zkmbdo6AgFCxpj7MiaOU7dukA2YK04b21yWnVhIr/YvebvH592d3ZnZnZnd9313+/xg7zs772of3j3m/M6gfBBP/svneiL53x8+gVNkwrf61ic4QmL56M9xqhQcq8cTr2Tzq0dxwl6YVj/Ad9JA7kmcNAlt9Y2/GMAXUkL/YzhzF9oqJdceyXs4dQef1V//LTKmjG/g/IHX6o/eQ67U8SoMbLxWv0OeFPJrKFh4rFL2mPDyW0iYkFbYnVZ+Bw0Dx+pP0v1LmXwBFdfqT9N8TxX4CDKOlf7f2JNqfgIbWOn/gPSU87itY1v9Nu1PCgdLx7b6uf4FEmly7588cjhRHD31If/B9q5j9YT+HaT5ubB66jAtgYx4av1VnKIfx2qAff3l9k3DQZJIZu4xnKcX6/FuWP2b/vdI8XB5Cr6fWBbcwql6+LpthU8+dg7FdxPMqIM4WRKz5DQo/x/6k/hMsg5fTDaZ3ThdEsvKsMNHgnRIsbV+YVj9WGdcgi/jS8kncwSnTGBY6for+OByKQX3VIExd3HSLl81rahibW4yvuGhakrjM7OmjMSn5LAYZ+3ytmFFX4B7kN8lM6f9g5y1L3d23SQkJoW3rBMjYVo9jOwFhjZdxh6b60uwIxnQP5Zh9W1sOpxD7gJTP8QOlxPjsS8JVFIvY8PqbWw6rEBum+wW+9Lzcm9dBvsTwMs4KYfvDNKpk34QmS2y+5HqZwcyJIDv4pQc/t14BvroG4zMJlwpXV+PLOWnHmfk8DFt5bmttiGRxTLkKTuZHpyRA211CHlNprPuqQK56chVdqi6Fm11AFkNqq4gzeJ0+/afXsK2xYWkPDE+wAk50FadyGrQjCSDnp33W0njX3Z/vpv1VlL5oa2ol7BrVeH+spfHIE3TpiD1ZnNiKv9SVvOQ4pEyfi7zrZcgJ0mrfUjRPyOljF8rlygnSSvnAtyGhAKNCWt4krEaiQRdH4eUpCJjNRMJ+jEkJBYZqwVI0HciIbHIWDn1lk3mp+yUZavWrn5uYtbalyyUrDZqY5Z3FZoHek8vT1wjtZJV+65+bNnc3Zqw1gslK5pbC5AnGcRkpesdlciVBGKz0o8kSCs+qyRpxWiVoNdYnFb6TGQsOxGsetqaV6zdcw+fTK5VIWe5Uba6/MJwK/G+5mtIMVhlJZUfVatT7s9y3wWk6fqHCWm4ULQipDxac5BUZtSsbnhvoJFO+1sbUsqMmpW/mXYH0vULSCgzSlZ9NUgp4DQB55LRKalkdRAJLmexR38ICeVFyYru+3Zan2YgobzIWDkdKK1IcPkp9uizkFBeZKycdotdSHDpwh49GR0IMlbTkKC/hQSHjNOrMAEp5UXGqsrpJ/B3fzciXe9JRuFCxsrN7B+qcBjp+gkklBkpK+eZ0OfpKnabP/XNSCkzUlbOjaXfIbVm9CI1KbeVnJXWjSRDyx0COceVOoqkciNntRRJJicXmK22lYvP4bPJXDtb2ZGzypIK+q23jp+/g22Lw8gWN0Prpi1sam1r79h34OAbhw/ua980fyx2sZGz0urJCr2fu6ORKyZqJs9fuXn30Q8+w/E93DrU0mjXxhlIWmlNSGSxCHliYOTsda/dwGH59OzgdK/LWmkbkUrThBwRqZ7RvJ83Np3m2LwKfI9E2oqrFYfUg00dngEcIlx9gfaSt9KWsK7zW/OxV5nBs3Zex8EkOUsN41Ow0sYexR6XrohdPcOf3ct8JojR2+QrfqpYadpTB8nxTP37piJdjdHPH+nDoVQ5WYtj2ahZaVrti7ilL3c0RXqg16/1vANV6fHcAapWJiNqJ9RWY1uN7MLT+COR6Se1olhFpWZ9+CtJHFKrfFZTOqLeTD4IrTJZDVlyHkePEVerLFZjN9/GseOlv1A9KoPV+M6gYa6RKMxnKblVjW+sRrxst/9Iia2qWr7EUYtDzm47LqlVduVNHLNoXLX6oEpptcA7Z6Y4WO3KpbOaHkvJKJRcnfG3SmV1/yEcrehsMf5aaayyLTGXIwK4YzzdS2LVUISCBJ+lJbGqWFu6H8qkuxRWE97EcUrGtKJbZVa77dWloq3YVnWx1QoleL/IViuLWz7ikBtWTKua4zhCqZlaRKsHFZv3otNUPKtnS/+YKNBRLKvMJny7HFwuktWw1/Dl8lAcq1q3q7UsXMT/HeKwmsaMSlNCqI6VGKyWiZX7cj09xSogUtXTyFYV2/E9LrnutuUPVVsznLK1s1ZsPRz70zJ2q8o38DUOF5qmUBObhsx+Wbx3UYS4rSoZwWhc+vdyI1VN2hNji1rM91Wg1Kct/pGtHsa0RuiY8xKvVZBU7yoyogST6m0xterG+mQPkqI7b1k85A6Nj0KcVgFSfWtYAwgYZJvjeNrHaBUgdb4BeQSYGv0VnouvxBQgdTD0jiKpfR9fU+Z6bFaxSRkPDWdoqCLn4rKKUco4WMRKdFdcVp3ITCMvpWnDf4kvq7EjJqsW5KVRkdK0Gjo8lwTr4rGaj6w0HyrOZq+j4+WJsyQWqwe4DWQDylFX3WlR8syOw2oUMbPRx1ZkUSBCG8HEGKwqzyAjzcUI07FGqb+NR8Zg1Y58NOwYkWDohAcaarkjZw0W4ijS9GWiW61GNgZmtx+ToYvbuq3i+cDZtdzCVEa1y/Va9Hb2OfzKQ44zxK621TNe/NpazsOfHD0vw9nIVvUBT+D9yOOlYg1VKu/2zxEyqe9QrWx1RrUaHjT4l/lUH+dMgSTIbfW/1tSdzGhREa3akIcFc5ZtA+fJdnoIMlhEcTJewhGt5iALk6XIRMKTMkqkbrUympPxuopmVR00FvMu411VEzDipxAdI6qT3puNZtWBHEz2IRPJ69jHZLWZI7KTrp+J1of/DDKwsU7Sy3PYxaZ3dBxOVmi5CFb3BQ8go+fYDgkZwflaHE7WJJwIVvyKoskAPSY8SjFcgvooViHFtIvIRkBHrS4G5uReZauakMuJjhN+P/YUGXNyr7IVa90EkheQz2UJ9hQZM0iAqlXoPfIMMrrsxJ4is9D4U4pWw0OrdLOR06U0Yzn1CGM5+fMAC9CBLvjtAHFyx/xTalY14X2edDXY83rrOd/V0b57/8ETcc9CsGb3qlntwq4A6CpT4aK9s2/pQ8TUutr5rcepGN3qWE8pJat6gTIAx+rK+ocZfT6Zhq1x9TNa06OVrEQatVhWA288zY1/UbU8cleIyS+tg6lYTcGOQGirm+3m4ymAGQeirzpoR4pSseK3/xHQVgJdqNMiNa+bTLSOo2AVXAEpQFuJUBXxVX3VPoy8VZbqdGWiZqVpMyO91hC2W95qOZJDULXShrOWsBIF735pq2GC80aVrTRtKw4hz228NaStgkJBkESwUtfajQPIWmVEn1JRrJS1ChUFWavAFkCSSFaKWr2FxjpZq5Bxci7RrNQqY04EQEmrOuFWoIhWlSojd50Q3ZJW4ldGRCvtQflWtOtOAHw5q2HiPetRrQIGO/BwV1+UsxJ8A5tEthosO5KkbxS+KWslcbGHWGXqFqxpaWmeGxDxo0FyTF0HvmcgZTUDKSIEWWVmdTl9qDd2c3N+H1kEIdoUpKyC26C98K0qVvg6KM95oqO41Eo9MMjFx2Ssxsj8Fa7VOEb1rJMdIiisJdXDYnzJRMYqvLmMgGe1hNk8dZMZ2v0p7BXhFhnJX8ZKaiQ9x2oFdvu5R7eKGvefWFXOwlq5pYCE1UR8FoNtxZMynsssrZXYGU7OE3pPwmo9PovBtJoe0NzS4w0UZTFceAZJF75hI2ElN9ScZeVdbM/PcUar2insC8XbAC5uNRYfBWFZOQHP2axENoIt2BXGSeQH4lYv4KMgDKvRIW+GG/R4pmexKwzfXxO3khy3zLAKLa8+i4wu47AnhMJNUkDYaoTkRCLaqjI0aMwZ5HTJCDW/9/tXhBO2otaBDYG2cmMAc3FL3QWOYU8g1HK5wlYH8EkU2moV9gRAv7NasSeIHqq8JWo1RDZOAG0VOD7Ihl51fw32BEEvASxq5cQqF4W2ov4UjX1ZkAg0P35KD5kXtQoaCMiEthIINnAEWV0Eat/LkZVA1Eo6fuEj1uFJBOJmHUdWl/BBGhcZixAKWo3Gtjh0H75AkZ9coNmGXxwuwKpyClrNxbY49Io9rAG3PugFcQLGlducRUYPglYbsC0O/U9IredO8zyyuqzDHh59dueiD0Er+dlrdABmgYF09MoxYU8p+l1gImglP9aDaMcC47GHTy+93l5I9ecce71SMatabEpwGX+AIDSKEX1bDQ0u5t+LFMmcP2uMDz2WM7RaQd8jk7GHQzOy+RGzEimN+aFbjQaHvPROIR9BcKXuDG9MipiVypxQxr+js9APk37G4yyw57uXuyS1kJVYLceH+ZDxsxf7mLAeZ9TpkdDDRQsIWYU/vRj0MBZvHBEwmOIs43EWOFT3BHdMlJiVaOuBlxX4EyR1XK3zI5CFJKj5htXSVkDISq3v+SLr35KnxZSqDho3yCiqOwhZ0SsCCMFsOx/NnNrexpzgGPQEpNe2IxCyojKJ8Rr+hpfMcuoXuPE09nnJBExZ62bctS5CVorjLHOcK3/kWs9l2L2cc4azkIHB7YCbykDEqgob0nAXHM42tp60GkJuH97Anf2dOWEdhEUfXXvzIGIl2NRIMxD0xytqascGrtcRUGGkayxeRKymY0MeO1a1GnX8Vq3QRadFrNReVxb0GoiiZPjdIcfZ1Q8CEavQWnYArL42IfhNZpdZrzYvIlai3S0srisuODKe2x93l1OnIhGxCiyThnFcKWxCDXVeBXIiCzOLWJ3EhhoqWnwp/UVkCUTEKuIgc3mtACmxBSFFrKIGLZTViiwlYiU1QoWJnFZ0KRErfvwoYS4GBSXx8Qy/PV54PVIBK8V6iIdcK93Ux2REQC+X+CKrAlZCnZihdHsXhOXwdEAzlLiUiFVMkbtzG0ILhSOdRXEZSEiJWPErBJJ8ti1wstLDe4IGb8pIiVhFewl7OdLIifnoXSWWRkpKxEp4LJEQVzY0UpFUa+dvCZl/vBE5BRGwin/pgutda2eNHVk1uLJ6VN28DYdDO1zukeM0RSiLlSSfSrztbEp8X6lwfgzOVRwBq3KtyQA6Fcr8AlYxlJgsdnw/FEZNjh74IoCA1YGYoqgL1IqpTrgvOUPdQxCw6oxpRSQFq2sPYIckIlYCsQREkLc6TY+sE0PE6nvYiIisVW67YDmfRsRKbiA7F0mrqyGtzkGIWGWjVvFt5Kx2RWj2FbLS4nkPL5wTitOeem0Wzk8NIasSxRxyaRf4XYMQsgoLUBYzNxpxcsoIWWmbsVkS9oa3o4chZjVWfpqrKjfVShNexKy0LmwXm74t0X8oA0GrmdguLrkOzywqdQStFIY9ynNEsdRHI2o1Okq8dCHOM4dnqCFqVexAjVcX8UclySNsFSVeeii3m5QLskzErUYV7VV8d1PEogSFuJXSMFUBupcpNEyEIGElMA9Amv79ygsjBCFjFbvWzQ0BIROiIGUVr9bZRUpLjYggZxWf1r12ep6BDJm6SZMf4P7Sklba0ntIjUJP56JIT73JrSfsMYafvr6OOaRO1kqrjxoK9eauOZFeToO9fUK5g09hB4G0lVbxUoRWz0utj0QsQ0yio7wcpLqO5K00rUFx8bc31wgMQQqmooU1bfm2GbmXRMVKy66WDfLXc7J1YeCyhmJU8Hr4fQP2layMw88T7inpPbPtu/XxFF25Un4tRSuD+h2hUWr73tr5vYmhQxTF2YbjsnCigZmoW2la1czmTtal+OWlEx2tTQun1cVbEA8OnHSbvMCjWFmMmvPS1l3te/e0t+3cvqX1xUUzJsRdAC9Q5ZnEeunwgWOeISfksP3IVqWDiPDSt2+qmZJdQLYqE3Xp9Fhl3V/mqhsOeLbbB0CEjkmPlTtS+yrZEjXT0SLC/KTH6hBOR7/tbV5zY2quQUqarJwGBv/gH2c8iHsJpsbKmdzrjSdl4Fya15GQIiun1YSaeJV1Bn86r6zUWD2Ps2EM1HIe784SdamxcmZY0DN2neHOTvU6NVZO20ILElycgrYziis1VotwNoylcpxZBOmzasDZ6L3+cqbbC5U+qwpnkpl/uTC3xzB9Vm7QvSveSEXEMiAptHInD58ktchp1Sm0Gu5WvQktz1zxFFqR0XSuNtud4uO2eaYyp9FqDNmJ27t380ut/lGmabQKH3iUSiu3isUhnVbVIW386bQK00qplVYdOB0xrVaatjhgOEt6rbTRW71et1Y5q4Gk2ErThi0/VhC7tP3poW4g1FRbGWTGL1j6/OL5dsOMU2hPX104gBS3W/Bxm6qdPv3/B1ZOm9oNJKTRqnYeNgo4F6DbUpg2q9q2vl7v/Fy3r+4lpKTNynAyTugK2a041alMEuGf0mRlOxl8MAkpmjbdrSG/jiQD2gr/d0mKVaM7eiW35X4zJdNI1huJqSUCVgeQtdx4Vx+80tlxyNNR/AaymQhY0WGQy0RgXKg75AA0KrgzbXUeWctP0Iomi5DHxG0RLUBb9cU8bCIC/DX0PD0lTut1gd8M0qnxT3So9XKR4a1V5e3+eQ6pDv86SP8ZNh34sUpLTuUm1jC+u77oA9Sk2W8N0v8Smw4XkDkRNNAB0Y/6JuoPparL+UE69RrWizI6W5XMCu/YqaNzscNhGfa4MK0SVr7VGppP2R0hd49tnIA0Anq0p2Glf4Fth8CYjeWhumHyjEfGMYcd0uO4XzWt/gofXKLEbCw1jBiRXzGt6EtQb8dXkk+WEeYmb1rpn9sfSFrxpaSTZczA/Jlt9YT9yUM6tFhSxk9lWems5d86ijVGM0ZqWXPrPzGt/tHYeMX+7IUTFzlB0LGcTb5qWlnPCuZafQNH58Y5+TBmKhezY6aYP5VhZZYDv2mnUFzZSEe+SgK1C7byom+ZUoaV9WP9xkphcqP73JuJ4lx3wJTLtwtWPzI+MN5ZqWTAkjKt8uZdxXxgpI+vuVaPmZ/ftVJTzg9tKcsq/6qZQhVy08d//oHlBKv8J0ZSvnRBLYrEx5aLiW1l3VrWf1LM57aKCaysZ2C6f62Pvw4Vg4LVV8wd1pWYUv7rMZiYFKzsX0t/x/pvCvknWNi4Vvb1920rT9oYIH8oA8Iq/z9mhvxHVr5U8c4//x4UAGmVN2sluv5nKXtoEM++Ah6rfN5+FX8zRV5f/PEPfh8n7+KzyqPB6dFf2f9POr/AafvwW+Xzf4MvPPEeNhLLO1/7df4PcdZeaKt8/vHCayv/2N+9m8iLsf/nrzyq6z/B+frJ5/8PFFlxzjSCFB4AAAAASUVORK5CYII=' +r7 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAALi4uMDAwPT09Pz8//1VV/1ZW/1dX/1hY/1pa/1tb/1xc/11d/15e/19f/2Bg/2Fh/2Ji/2Nj/2Rk/2Vl/2Zm/2dn/2ho/2lp/2pq/2xs/21t/25u/29v/3Bw/3Fx/3Jy/3Nz/3R0/3Z2/3h4/3p6/3t7/3x8/319/35+/39/k5OTlJSUlZWVl5eXmJiYmpqanJycn5+foKCgoqKio6OjpaWlpqamq6urrKysra2tsLCws7OztbW1t7e3uLi4ubm5urq6v7+//4CA/4GB/4KC/4SE/4WF/4aG/4eH/4iI/4qK/4uL/4yM/46O/4+P/5CQ/5GR/5KS/5SU/5aW/5eX/5iY/5qa/5yc/52d/56e/5+f/6Cg/6Gh/6Ki/6Oj/6Sk/6Wl/6am/6io/6mp/6qq/6ur/6ys/62t/66u/7Gx/7Ky/7Oz/7S0/7W1/7a2/7e3/7i4/7m5/7q6/7u7/7y8/729/76+/7+/wMDAwcHBxMTExsbGx8fHycnJz8/P0dHR09PT1NTU1dXV19fX2dnZ2tra29vb3Nzc3d3d3t7e/8DA/8HB/8LC/8PD/8TE/8XF/8bG/8fH/8jI/8nJ/8rK/8vL/8zM/83N/87O/8/P/9DQ/9HR/9LS/9PT/9TU/9XV/9bW/9fX/9jY/9nZ/9ra/9zc/93d/97e/9/f4ODg4uLi4+Pj5OTk5ubm5+fn6Ojo6+vr7Ozs7e3t7u7u7+/v/+Dg/+Hh/+Li/+Pj/+Tk/+Xl/+bm/+fn/+jo/+np/+rq/+vr/+zs/+7u8PDw8fHx8vLy8/Pz9PT09fX19vb29/f3//Dw//Ly//Pz//T0//X1//b2//f3+Pj4+fn5+vr6+/v7//j4//n5//r6//v7/vz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA46UD8AAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAAA93SURBVHhe1Z35YxTlHcbTY0NCFBpbClgExFCO1lZ6SIutRxWJKIqAQhURzxpEsIh4tLb2sK01giJQpAERRcSrVlsNKEeg2iqCIXhA2My/Mt2ZefadnX3neI/vHO/nB3aO9528H3b32dmd932nwY5j6sP/swrJsT9OQxNDibb60Xs4QmE5dD6ayhFhdfZ/ULPgHDoXDQ4SajWtjEom8CAaXQtv9eMpJ1HeEAZ+gpb78FZvorBBHELTGXVWP5uGgobxa7QfBK2+/ShKGccbMPAIWr2PMgbyGRRcAlafooSRDEDCodbqM+w3FWhUYFbftz/BTmPxn62q1Q/swp8gJcPeW1Ur6xHsMZp/wQZW1rnYbji/8XQ8q09tbDUeV8ezesV6HRt5BvY9t6WrUGzetjv67PsYs5pqRT1V+2+f0VoqIKdMXvw2mljPhVWrgYhQf+aKRhyliFz8VPgzBqs/W9/DhgCHr0L1wjJ5H5oa4CHPyrLCzpQ2fg11C0zLSjQ2gGv1j9B31eNFfvH53Ibm1jLNsbKs17BagyFSoVqfVqz+EPZUbTZFqlRagSbXULGyrO9ixad3OKoYQMseNNrnAcfqZaz4zHPLt16VzBluyVyZyAX8ZxUr/gX4old8AlbjuNErmitr0BafUCvvqTLGim9nmNXh5qjSPEWwKu1AYxgXNFgXYpGxAoWNsboOjWG83GD9BYuMuShsjNV4NIZRbrA+xCJjDAobY9Xcj9YwKsleR1/1E9gYK/6NxVv1oKhBVn9Haxi81Tso6lvtXV4P+89ZgLL5sh6tYYhYrccGn27s6R+GDfmyDs1hOOfsQQSs2J512JAzNFaPYYfVjg05Q2I19Dh2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' +r8 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAALi4uMDAwPT09Pz8//1VV/1ZW/1dX/1hY/1lZ/1pa/1tb/1xc/11d/15e/2Bg/2Fh/2Ji/2Nj/2Rk/2Vl/2Zm/2dn/2ho/2lp/2pq/2tr/2xs/21t/25u/3Bw/3Fx/3Jy/3Nz/3R0/3V1/3Z2/3h4/3p6/3t7/3x8/319/35+/39/k5OTlJSUlpaWmZmZm5ubnJycnp6en5+foKCgoqKipKSkpqamq6urrKysr6+vsrKys7OztLS0tbW1tra2urq6u7u7vb29v7+//4CA/4KC/4SE/4WF/4aG/4iI/4qK/4uL/4yM/42N/46O/4+P/5CQ/5GR/5KS/5SU/5WV/5aW/5eX/5iY/5qa/5yc/52d/56e/5+f/6Cg/6Gh/6Ki/6Oj/6Sk/6Wl/6am/6en/6io/6mp/6qq/6ys/62t/66u/6+v/7Cw/7Gx/7Ky/7Oz/7S0/7W1/7a2/7e3/7i4/7m5/7q6/7u7/7y8/729/76+wcHBw8PDxMTEyMjIycnJysrKzMzMzc3Nzs7Oz8/P09PT1NTU1dXV1tbW2dnZ2tra29vb3d3d3t7e39/f/8DA/8HB/8LC/8PD/8TE/8bG/8fH/8jI/8rK/8zM/83N/87O/8/P/9DQ/9HR/9LS/9PT/9TU/9bW/9fX/9jY/9nZ/9ra/9vb/9zc/93d/97e/9/f4ODg4eHh4uLi4+Pj5OTk5ubm5+fn6Ojo6enp7Ozs7e3t7u7u7+/v/+Dg/+Hh/+Li/+Tk/+bm/+fn/+jo/+np/+rq/+vr/+zs/+3t/+7u/+/v8PDw8vLy8/Pz9PT09fX19vb29/f3//Dw//Hx//Ly//Pz//T0//X1//b2//f3+Pj4+fn5+vr6+/v7//j4//n5//r6//v7/vz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXn6cBAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABYNSURBVHhe1Z35YxTnfYfVYxdJyAghQMiYw0KSFTvpmTg90tZtJTCYOBibIB8EsCorHAoGQznSNG2aJo3jxLLAXEYGc1t13bqpU4SMxaUmbW0QshobHav5T6ZzfPadd+Z9Z+Z935ndnXl+2d33fWc1j2Z39j2/b5kexO//3X9qieSzV/4Ep8jF3+r3foZ3SCyf/Q1OlcHP6t9wZMKZ+jOcrxuu1W//Hw5KA/+Ik6Zhrf5Q/1+UTwvfxZk7sFY/RdkUkfsCzj2Px+ov9WmUTBcv4/yB2+oLf4tSqeMjGNi4rf4VZVLINBQsXFYJ/ckV5IuwMKCtfoHstPIleFBWX9TfR2Z6gYpj9SX9J8hKM5AhVtpfICPVfAobWGk60lPOu7aObfWp/imS086XLR/L6l3te0jkcPPsyb5k8dbAJM6Nxf7ZMq2+7Pv5u71j1fxMAqlsfuYtn6rdj/NW0/q/I8nNpXWVeJck0rBvHOfpBlY/5l+q8Y1ZHJ9UFp/Hqbp4z7YyniCB5uJiHJtgZnRO4WxpLKv3uJfqdBWOTDZPcLR+aFpp2rfxkiIlUnwtw+qHmp7DK4cP7sFByedZnDLFb+llhhpeOORacEgaOImTdnjPtHoELxy6cYCbuhVffaw5eff6BaM4awfDSv8fPCeMzMQBFM09w1be5NvfqEZSUnjBOjEa0wpPHdhLtfQsskzGvlmO5GRQy9Sf/ohjlatHccLmCWSB/iXISAa9OC3COxyrkyhM2IEMh1v3IysRLMdZEabLtK/gKWEbCufZgnSaWwuRmQSqmYpumfYPeEZYjcLgQfbnzOB0kiqJH+CkCGXaO3hGWICyNhUfItnDBuQnAeaLVaYxXUvu+/qTSPVyI0E3wp04J0KZ9nM8I7g/WxeQanB+T88dPDX4GgokgG04JUKZxvRtoqhNHRI1bdisRlV9C6807ZBdIAmwVmyPLYrarEaiNoHfqD14rQ3Zr5OAtBW5rfcgYT75JU9OzUnailyaNUjIXESClpyfLGmrl5Do3BzI7YOpWJUMaautSNT2ImEOqRPORkrpkbb6OhK1MVyabrzWbiendiFtNZvcHIbMm+CMDrxyLl4CkLbKHEWq0UJ5Y8vO63hu8BAKJAB5qyeQ6uV6gqq38lZV15DsoQP5SUDeKtPGbYmcn4HsJKBg9Ryv11cbSFKzUd5qF1K9jCxDgQQgbbURiSzX56FI6ZG1WsX9UtlcTExfvKTVfWNI49KLUiVH0oruELh7sKN984s38MqiEcVKjZzVUufzN7FrrpVU/vhppBgct5JKj5zVYaRo2s1FSDIgjRNNS8jYiZTVHCRo2mgDkiwcrQNIKTFSVl9Fgqa1IQW8geSk9F1IWZFrch4JeZyObXePaKmQshpAgrYeCYRBZGhrkVBapKzyd8BJZpT4eeRo25FQWmSsZuK1dhMJDmuRo72EhNIiYzULr7UPkeCwCjnaPiSUFhmrSrzWRpDgsA45KbxWmfzgODukSponnUgoLVJWZCaD955QRSYDrEBKaZGy2o4E7bZnlkU70jWtBimlRcrqMSRo2gtIsam5gmTOfaQkSFlV3kKKpm1CkkkN+XX22JYMKSu6dAfp/qtzpCZrkVZi5KzqqO6lax3Wd+jBQ9RMlKQ0huWs3FMtxgfeOu/q8hwtUN22fEHz6me27uvpff3w0Tf63jjcu3t9Y+DYuqRVufNp48BUeqMxq3Fle9e+Y/0f83qAxs/vfsq3C1LSKtPIn4dscQxlYmBmy7M9gwHdWaBvJb9zX9Yqs9xX6xRnvp0C5U3t+y9xu4d5DG3ijUZLW/lqxSFVv27PBc90tlDu7mNvvPJWmSbSRKTI7Yo8qXNZVz/eTJLbzPwVBatM5Q7mEz/UijxFZrTuHMJbqXDIU1FTscpkFu/+BHkW/esjXaiq1T0jeCdVhlfhvWzUrIy77vr9A9ZXeqRva6ROwJr1xwJuq+Lspe+GqlYmM+9dsijiOEjza7I3B196KK0oVlGpfJKavxYdSqt0VnXbnBZAPDhapbJqPSz8QysO0SqJVVX7Zbx1zOQn3pfAatYWdslDTOTXsxTdqvy5uL9ONFfsQdxiW63xmWEdF3Z/ZHGt2sgMyUKRs6puxbRqIMNcBeSqObJRPKsFPeGtwDgwe7+KZVXdHUttT4Ah40erSFYrb+K9isDKIlnNOoB3KgonimO1nJrwWQRyi4pgdc9evE3R2FV4q9YoLXc17mQLbDVzV3Fu524WF9aqhVm0VhTWFtJqxvZSXCiDnQW0qu7D8UXnTOGsFpXm02dylwz15onLakXBmoYC7McjISarjSX6StkcwSMhFquKolaRWI7hkRCHVe0ZHFkqTuCREIPVMp+VJB6mx8cK0Htm8SYeCdGtVgfODjeZHnxtQ8sss/OufOHXuk+FlpeGCUcS2Sr0PjH4jGd4MNvS6x/RS4nYr9UmHORD7kib0x3uMLfTNS8+KnF/r0KkzlATxt2Ub4ptdETTmG6faFbBUsExxZbEN0JyHI+ESFbBUudDYoqVd8b19XLWXoIoVsFSh8NDRbTF1BEVZ90islRsWs7KD6BuFYNUXFqv4pGgbBUsdUw0UklbHPWN3XgkqFoFSw2Lr9HvwiERyMXVvvKLJgNWopgA5W/jGHU+jqkt/EDw10FqAdP9ke/v/fFY1dmR3Py4PgvlxHACFihyPBarmSEfmqdRThBq0rIa+2OxOoSCPozKBorkhRyToSsOq7C71i6UE6YuYqdHewxWq0POYdqnnl6zpLHeJyQBUzeQY2V0q2VhTdk3UdBFdsUx859xrWMOEly02Ueq0hTZqja0k+J5lKRZSOaDTvDiYlREu7nPi2pVEd6d5FmvarKQ/ld0IZEmUlMrF3mkh+klZWEnMc93X9/NSKYgsaxUuBF1VI6s/PPnCopSeCJg3mW9ydo7FY5HtKoJrlNYHERZhyoqPJ8FG1CxATlKdEW0OogSQbBhZdcjh3CF6c6oRo4SK6NZPY4CgbA3A3b4m2mnkIWhKsyLZFUrVF9j79yvI8eBWcaSRYYKN6LNt2D6PLiwq1J7kOPAzLQuR4YKRyJZkfXcwWxBcQcS1i7PODPJvwo5Khj/RnWreYLrBdgW4yJvkF1OEeSosCKKFdM/6oM3aoSBdxicDTdDon8qUBPBisQRDOMu2wu9AlngFJIp2GDkwpiBQ1StOKHd/eCs03sOWRYDnGp7SDs0iNeNw1Wt2LuzL7xAHpQWTypzFZkKmLVKRatmZIlg3GlZWo/Ybc2rm3kr+B6w8tQwpxMrWp1ClgiT/B7O+o5de7et4g/9ULGQZMmZ/VlqViuRI4b0gtsZH+NIBd4y30DJKiu3zINzbw/GiWIgzzfMN1Cykm39PIbjBJkRZW2MdcdVsaqUnUc7KDogYsO0VCQYsN5BxYqEKRJG6ps1M8pw/jett1Cwmu1tyoZzW2b5I7sDhgR25UvBSuWvHsaxAjRH2ST3mv0e8lb1CvMiBnynWbBkuyJoIXCSvBWz/0M4J+VGetao93Gi71Ha6j75nv0jsiu/H1Ud8r6Dm620FbOpRSi9cvd1kwddC+LFyUd4kbVi+vJC6ZOXMq6W2ljP4zhc1sqJJyXIZbnvVJ6ncbgUE/nhP1mrwLgxHG7diwNl8QvsHATpJpa0akWSMBJTEtyoTFB4EMfKWskOAkaIqdogfX/vx5GyVnSUKRFuqH2pbP4KbyKMU9uUs2L6J0Pw7JxFkW1u37Jja+e6+/2D1ZdLNkioPf2krCokJ0JcxHEMj75K3unuqbV+P9JOeF0hqMEXKauQyUoMPiESV3jGR29t4U/IyErF/MlRd1spK8nR2jM4zE01M33UN0SQVPfIURxkImPVhNei5H/pXTRy1zlOd/M6m7Ik2qIAy3GQiYyV5A/jCO/78pBfxdUVoydPJzIFGMQhFjJWkh2qu3EYTYN/RzZPq168qfUsDrGQsGrES1GacBxFbdDCdd7MNHb/WR8+cf0ySlhJTh3lbbH0GvK4jHGGGYLnvVK4PxgSVpKx1ThdFSHTk06jGIXoDWq8DgfYiFvV45Uoz9mH0VxClh/s3KBywVVMnukP4lYb8EoUdgAxdCCFc3nFwpeMeAZWxK1khkEMptn7euicJzY+tWA33UaUziNsNVuyuj5sHUWTDR+eZG+DnL3FWa56/4PCVrJ1wHPWUTQC4/Jsc0xg+hdnNFPYSra9yE7KWoOcAOy+f5plyAmin/kNEbWqlF1SyYafF2ic5Zj+qPnICYKuAdqIWsmNLhrssN6ehlmSwoFpO9ciIwDOvF5RK+nJlayVSKQVZgi5Bhn+5DhbHolaSYfyYj+BIr2+zA5azsa/fvAicgtayU9a3m+/P4XA8o9R5nsfeuOc4HU4ClrJNhh5/0KBSerMHvXhU1W5ce4FraQ7ojlV1dnICYCdzRp2l7rI7aMStJKP7HCX/XPhwUnYnraQ5s/EUpRzI2gl271ucL/9ByhCv1i32LojE6nCDWcqvImY1UyFJZTr8BccnJ2IfdiKghTBs2TO8jo7DMSsWvBMBk63RcjneIrdYCD4xn7Xb7hZzMo1n08Qzjyf+cFDeuwM3ZC5P+zsfiBmFdjf4MMEZ4wxsOJ/qQKlKAJXzZ3y+fyJWvHizIfiDi5uE1DzH+ftoxr0h8f8B/yErGYpjdL24U/QVDLxNPKMcxY0Bf9wt6MQByEr6RFGG17gBz8trlRgo473T8sjZCXUzGbh7vBV2c278Je5e40uCPiM3HL3lbkRsmIKieHuTyWw4fdy2/hDWAHtzEkyBsxDyIpd2CGGz+rnirXnUMBi9EWfn52g1dDBc/OErJhAQIJc4V8Cg6auo9aCtMkLe5703ZU4YM7FThTxQchKecbot/BXuNTUL5zP+Yki1Pt3lZzw/aWyEbJSDpqX+xz+jAJZ/27VQd4ceBoRqwjLhhAvXQX/G+9I6GxDEasoy4ak1+DnWXQX78AwxfaUeRGxegiPKkwrbnWTpXaY9uBbp3UQsRLodPVnOCS0FJ+sf08d283DImLlvwW+CCpaWf8e0dMi0w1FrCJNxVbRCpC6EHb7sxCxElnrHISsVmQpISvJ8TgWOa3oUkJWSm1GF59ILKm41/+fKColZCUWPDSYE0ENB4psu389SVhKyCqWPQtG2Z40DnUBsafFpYSsooZHAkfZsWwP5esDapwSUkJW8mt4+PhEGs0z94WgJUoyUkJWsoOnAQw+6zcTNyQ6rJSUkFWMwU2Nf9HetYu9V6y67fmQed7npKSErNRWNwQwdmrHmsXzqivLZ9XWt248GD63sde3Uc1HxCpacKTo5HgRnQIRsVJuCsfDJ/LrF0SsBAL5FJAP+QNvgYhYFXh7sWBOqexFL2IlFh+mMOxVWb0lZBUhhEZEJp/BaUoiYvUoHovOCHdIQQARqzl4LDbnfHcbD0PEKhNHU0SaiY6QDtoAhKwkwqnExtvszAZxhKyidTKpMNmldO/LI2Q1t9h1pgHuIJ04QlYqq9QjMLU1aKhEBDErlVkkygw249zUEbOSn/SoTG6HZKuDh6BVpDiZMrwZ8RtlI2hVeRvPC0t/+CCOEIJWauviJbn6pPrvrhtRK+URb2FGNsbwhQLCVhJB6FQY75brbwlG2Eo8YKACuQOCHdaCiFuFTRZVJ3ckSp2Ph4TVvJh6pj2MdKuGwPBHwirTUACt/q/Hd49wkLGKXWvyYIRZJkFIWcWrNdwlEydMCjmrGLXOrInUgsrUNbU0L/F7C0mrTEOEOKCE3NnnlWZh5FnQac9Y08bPvbScVx+RtcrM2odUVSaOt8/Fe6nRetg1nMEbPJK2ymQejRDf707v47JbpniYw3aiXGM62BSsMtWKczuvv9QW7btksIr7xd7jhIyxULEyLpfsRqe5gQNPx9Fy8qu2nXTP2FOzymQa94vGjcsN9m74nPo0QRf+dVG3lqpVJjN7c/ie8EOHNrf6DQQrENQ17lrDr26VyWSbnj4wwFnDNHXj/JE9netWNMTZuDCoDpz4QS/wjmJlUdWy4cW/fvXgwdcO7Nuza0fX+pWNc+Nq0XpxrcEZOXWkzzXL+Q5VU4lsVTzoFaMXn7IqxU2vUvML9lqlLFJk5axJyz2BJKN55FwvaguZ9FjVkMuSowM91TpazoTc9Fg5vVxPIcXG2apKNdJeKSEfwA88dyMSByhHahjpsSKfNG+YndmkPvAAUtJjVZWvqI8zP+vkKpL4WamxImtsXQHNLMigIdnoKDVWC3Ey2gUkOJB47tuRkB4rEmrlMhIcSKSo9F0rss/XKNPVRsKBkFX5qbFypkc4FQsbZxSKjBOlx4o0wL3b+jyFdG2KdB6kx8rZ48G9+KmCxMpzVv6nx+o+nI3xzWpAkkmFE7zUiWSSHquMsyr8ptObSElNOdOeUmRFta+m9tqhMKo3UDOR09m+cu3ON3lse8f2Xnqm/QQ1sJcmq6WB3VrbUMokTVaBgaWP0TGFUmUVsJfOJVdNPl1WvkHkhlRjqCYD/opv7/TwtFnxJ1Sd9jT6U2Y112cui2e9d8qs/ObKehrIKbNy5imO92zaQg1fuIeR0mXlRG+4WGu8zDrbWLjjg6TLilgMo/eZbOyI7bxAuqxIwNJ8D0U9Gfh23QXTZUUiApDxbfLVSnHdgmxlS/b0IJssukYA02VF4g7sQQLZtWDCFTAzXVakZjFmt4ZnkJawOxg3a6Ul2MqJEztsdsnMczZXdsdU41j9HM8IhRrnVYAKSnH54Alq+Yo77BnH6n08I3gmnpQSvwnol5APmODOZdo/4xkh/hmkytzjs8DNs3kOExOmTPt7PCNw99spEctxTm4OITcPsxa4TPtjPCOwcZBLSDdOiuaKp9FYw2yEU6bpeEbg7F5SQtiA6Fe8k+GZmUE5jlVOYm/WIrDJE5mij5m+y0wh/AnHKiwGYbFZQkcBGmZDqbJ7+v2BYfVLPCeMxjhvLBaW7bV7ou+ceEIo9K9epml/iucOvK2sSkx1S1vrIm79gBOjz7T6PJ475FSXjpeA7FmctMO7ppXOzvm7xmwekVg4m1fqppX25/YLmosxz2AsGO2cKDe2FXsXTI0WT+r7tpX2L9YrN4OcfeKSRuUOjpRxqfSy75uP9ks3U1siz0YvME3c6HnvmFaW0bvWay9DG5P8MWw9zN+dwZAyrN4xn9kJDGMH1i1NUCOSULOi028bjR/YVpbRd6wULmODb19IFgPX/HernDalTKsfGC/0j+zE1PM7eSvdNPf7DKaMVywpy+p3zddM4zGNfGRLWVb6K2bKP1npqWb6NywnWFnfKv09OyvFWC4mtpX91foPOy+1fN52MYCVdbPQf2ZlphWYmOStrEaW/rKVnUpyELHIW9lXi9coSQe/hIWNY6Vb9V/9M6tQ2jBaHzSUld0tY1U1Usav9F+DAqCtdLNVYnj9l/WQHh7B6Tu4rHT9V1YxdqQuwXzn27+Ok3fwWOmP2EX1H9mPSeejh3HebrxWup5vlOgvi+9OXxr++yu/0H8TZ+2GtdL1h/PNEuPS/dT+TCaM6fe/97Cu/Qjn60XX/x9qP8CeI4O3vwAAAABJRU5ErkJggg==' +r9 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAALi4uMDAwPz8//1VV/1ZW/1dX/1hY/1lZ/1pa/1tb/1xc/11d/15e/2Bg/2Fh/2Ji/2Rk/2Vl/2Zm/2ho/2lp/2pq/2tr/2xs/21t/25u/29v/3Bw/3Fx/3Jy/3Nz/3R0/3V1/3Z2/3h4/3p6/3x8/319/35+/39/kpKSlJSUlZWVl5eXmJiYmZmZnJycnZ2dnp6eoKCgoqKipKSkpqamqKioqampqqqqrKysra2trq6usrKytLS0tbW1tra2uLi4ubm5urq6u7u7vr6+v7+//4CA/4KC/4OD/4SE/4WF/4aG/4iI/4qK/4yM/42N/46O/4+P/5CQ/5GR/5KS/5SU/5WV/5aW/5eX/5iY/5mZ/5qa/5yc/56e/6Cg/6Ki/6Oj/6Sk/6am/6en/6io/6mp/6qq/6ur/6ys/66u/7Cw/7Gx/7Ky/7Oz/7S0/7a2/7i4/7m5/7q6/7u7/7y8/729/76+/7+/wcHBwsLCw8PDxMTExsbGyMjIysrKy8vLzc3Nzs7Oz8/P0NDQ0dHR0tLS09PT1NTU1dXV1tbW19fX2dnZ2tra29vb3d3d3t7e39/f/8DA/8LC/8TE/8bG/8jI/8nJ/8rK/8vL/8zM/83N/87O/9DQ/9HR/9LS/9TU/9XV/9bW/9jY/9ra/9vb/9zc/93d/97e/9/f4eHh4uLi4+Pj5OTk5+fn6Ojo6urq7Ozs7e3t7u7u/+Dg/+Li/+Tk/+bm/+fn/+jo/+np/+rq/+vr/+zs/+3t/+7u/+/v8fHx8vLy8/Pz9fX19vb2//Dw//Hx//Ly//Pz//T0//X1//b2//f3+Pj4+fn5+vr6+/v7//j4//n5//r6//v7/vz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI8jCgAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABVhSURBVHhe3Z39YxTHfYfV9g4hhGSwZMybsSwJk7Zum7R22/QlTdNaMkaigDHYCCTABgvzHgQ0tZu3NmlaN22RMAgkMCK8JWnqJiBj8WK5bRAKqE4R0mn/m+2+fG52dmdmd2Z272V5frm92dnTPrrb3Xn9ToUZxnPvfDhjlCO5H/8FTpFLiNW/4RPKlplv40wZRFb/jCPLnJl3cb5++Faf4qA08COcMw1r9UXzp8ifFr6PM/dgrb6JvGnij3HueQJWL5r/i4zp4kOcP/Bb/cYfIVfqyMHAxW/1d8iTRr4IBxuf1b8iQzp5ERYWtNUPsTutfA0elNXvpuXBG8KX4EKsfs98B7vSzG/CJm9lPIcdqWYGNrAyzPIsm6vyP66Oa/VL8z+RnHa+4fg4Vj82fh+JHMZ/8MGZ8uLcpQc4Nw7E6gXh72/i8LqFmTJkVsPr/TmcY4D/ylvNmN9Akp+Rrlp8SjmyYPcvcJ5+nnOtvm+YSPCR21uF48uVx0/hVH185loZxrtIoLmxAseWMxvv42xpHKufcL+q6/U4sLxZztH61LYyjN/CW4qUSPG1LKvvGebP8M7j3gIcVP6sZG/ff2lWWGp4Q7EBh6SBgzhnj2m+VT8O8JFdumr16pefxLvyofo6ztrDsjK/i21Cjn3y1u88d8/deXew6zEklglr3BOj+LxlxTykma9q+fvT2OUweWQZdpQFs27jvAj/ZFlh02MlsoO5h5DuMfVWJXaWA2/irAg5jtUnyAyWjyDdx+Wl2F0G1OOcPDhWJ5HZpVVQPr5TRr/CT3BOhArjBWwR3kBeB5FUWWn145QIFcaXsUWgL6vFE0jkcLtsSvTMhVVhMK0wjchr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' +y0 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABUVFRYWFhgYGBkZGR0dHR4eHiIiIiUlJSYmJigoKCsrKywsLC4uLjAwMDExMTIyMjMzMzQ0NDk5OTw8PD09PT8/P0BAQEpKSktLS0xMTE5OTk9PT1BQUFJSUlNTU1ZWVllZWVtbW11dXWBgYGFhYWJiYmRkZGhoaGpqam1tbW5ubnBwcHFxcXJycnNzc3V1dXZ2dnl5eXp6en19fX5+fv+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2JP+2Jv+3KP+4Kv+4LP+5Lv+6MP+6Mv+7NP+8Nv+8OP+9Ov++PP++Pv+/QP/AQv/ARP/BRv/CSP/CSv/DTP/ETv/EUP/FUv/GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/LZP/MZv/MaP/Nav/ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/TfP/UfoCAgIKCgoODg4SEhIWFhYeHh4iIiIuLi4yMjI+Pj5CQkJKSkpOTk5WVlZaWlpiYmJqampycnKCgoKKioqSkpKampqioqKqqqqysrK6urq+vr7CwsLa2trm5ubq6ur+/v//UgP/Vgv/WhP/Whv/XiP/Yiv/YjP/Zjv/akP/akv/blP/clv/cmP/dmv/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/mtP/mtv/nuP/ouv/ovP/pvsDAwMLCwsTExMbGxsjIyMrKyszMzM7Ozs/Pz9DQ0NHR0dLS0tTU1NbW1tjY2NnZ2dvb293d3f/qwP/qwv/rxP/rx//sxv/syP/syv/tzP/uzP/uzv/u0P/v0v/w0v/w1P/x1v/y2P/y2v/z3P/03uHh4eLi4uTk5Ofn5+jo6Orq6uvr6+zs7O7u7v/04P/14v/25P/25v/36P/46v/47P/57vDw8PLy8vPz8/T09Pb29vf39//68P/68v/79P/89vj4+Pr6+v/8+P/9+vz8/P39/f/+/P7+/v///wAAAHrYiUMAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAATyUlEQVR4Xu2df5wUZ33Ht9ra2lh/tNa21ljbmBil0Vp1j+M4OCCQu3CQAwnhVwg/EjgCgUDANqaNqVVr1bRqld+EI/y4C+EgEEitabVaf8AVKFACAY0xNhwcKDX3I9yS3Vnnx2efeWaeZ2ae55nZmZ3Xa99/hNnneXZ33rnd2Wee5/t8n0zRm7e/+8F//s+XXtMqjqs//dY//dW73oHT5OBl9d4/e/i/CniRCqXwnYfei7N1w7e65i9/iKdWON/70Ftwyg54Vm/99C/xpBRw+eHfw2lTsFav/2SKnAwuf/QNOHWC2+qmP/wRGqeIH9yEsy/hsvr65yr8EsHntU/9OgQsnFa/+x00Sx3P/j4UTGir6679GdqkkJ9cBwsDymrIO1N2mXByeQg8dGyrv/3jV1GfUn5paxGrz1/7CmpTy2XyISxZ/ePb/g91KebF0iUDVo8M+R5qUs1/4AJvWX1A+wLKU85nTB1YXXkPStNOweplmFY//rWfopTDYM+5CqMnh1Pj8GOzT2hYfVH7DMrc9O64t2VotuKonbSkox+n6OahklXhTVdQ5OT0kuF4mQpkxLIzOE0nrxg3JrrVD7QvocRB/xI8v1KpWT6IU3XwWdNqiPZbV1FA09WIJ1cw44/hZGlefath9RPtETym2VWBXyeW2n04XZpPGFban3N6FemQ4mu9cEMx813tT/CIYn9KpHStIzhliuuLGY1zrei9Gc9JAU3sJf6zutWN7AdwAZ7hpKFpQlMDjiuIpThpmxd0qzfj2KYL7SnGreg8Z9Z1737gFpRVCifNE6P5g4x2Ew5t5qI5YfqePKoM8k/NQHllsAjnZXND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' +y1 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABUVFRYWFhgYGBkZGR0dHR4eHiUlJSYmJigoKCsrKywsLC4uLjAwMDExMTIyMjMzMzQ0NDk5OTw8PD09PT8/P0pKSktLS0xMTE5OTlBQUFFRUVNTU1RUVFZWVlhYWFtbW1xcXF1dXV5eXmBgYGFhYWJiYmRkZGhoaGlpaWpqam1tbW5ubm9vb3BwcHFxcXNzc3V1dXp6enx8fH19fX9/f/+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wE/+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2JP+2Jv+3Kf+4Kv+4LP+5Lv+6MP+6Mv+7NP+8Nv+8OP+9Ov++PP++Pv+/QP/AQv/ARP/BRv/CSP/DS//DTf/ETv/EUP/FU//GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/LZP/MZv/MaP/Nav/ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/TfP/Uf4CAgIGBgYKCgoSEhIeHh4iIiImJiYuLi4yMjJGRkZKSkpSUlJWVlZiYmJqampycnKCgoKKioqWlpaampqioqKmpqaqqqqysrLCwsLKysrm5ubq6ur29vb6+vr+/v//UgP/Vgv/WhP/Whv/XiP/Yiv/YjP/Zjv/akP/akv/blP/clv/dmf/dmv/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/mtP/mtv/nuP/ouv/ovP/pvsHBwcLCwsTExMbGxsnJycrKysvLy8zMzM7Ozs/Pz9DQ0NHR0dLS0tTU1NXV1dnZ2dra2tvb29zc3N3d3d7e3v/qwP/qwv/rxP/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03uHh4eLi4uTk5OXl5ebm5ujo6Onp6erq6uzs7O3t7e7u7u/v7//04P/14v/25P/25v/36P/46v/47P/57vLy8vT09Pb29v/68P/68v/79P/89vj4+Pr6+vv7+//8+P/9+vz8/P39/f/+/P7+/v///wAAAAvkMikAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAOwklEQVR4Xu3deZwT5R3H8VRbe1hrLw+0WouKWrS2FrMHLHLIscqxIqJsC4qC3LgqWM9aa7WltbbaCgIKVASRywXU3traVi2Iq4Cg1Wq1FhfZ9YAFFskmneObZ45nknlm5vdkZvKazz87mUyenfcLkp0kc6RyhfvS4d1++qc39mYj1/63n/rFjV89DKvpUCHVCced+cf9GCSqPXvLCVhbe86qz5z8Zzwy4r123eewypacVIde8188KAbtuf2LWG1TvOrAU9/CA2LSnlsOwqqz7KrTD38SC8eoN4/D2uezqX7dbQ+WjFc//zgAelbVF+7CUrHrn18GQcus6nz001gmhr3fCQo1k+q0I9/EErFs74lwKBmqmzq9jftj2v6TIDGpbj8q1v9Sah8dAwtT/fjzMX5O5fsg/5IB1c2nxfbVz9zreIHXVV2z3TA/5t2tcaDac2w8//jyna55NNWrHyuymZRpaX4nWu1ox6o59L62TaiqZmZPxTx77cunDe+ejlwVgyc8sAOraO/OvKrjYOet9ObpvTFMBKu+/EWsprUO9Y2Jono6eybmWMrMqcIAUe2yVqyqpcc11anZTzq9SdwyDI+NcH0ewcpaOlRVvZ49GTfNNdXgkdFuIVbX3B2qKvsNh88oYoJyZO3ukkv9LfuVDtw02hIXVDq9FKtsqmsulXV4rcjE4DmVr+YdrLTRY4rqlD/ghtEcPAL1HIL6YUakGsn9V9urqA75CDdY260v6X22YH52GeZEq+VYO6NOqezpmDSagcX1DFREVcOxdkY3pbLfxiSrvQ8W1zKhIqpKb8TqsX6Vys7EJGsFFtYyo6KqmozVY/0n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' +y10 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABkZGR4eHi4uLjAwMDExMTk5OTw8PD09PT8/P0pKSktLS0xMTE1NTU5OTlFRUVJSUlVVVVZWVldXV1hYWFtbW11dXV5eXl9fX2BgYGFhYWNjY2RkZGVlZWhoaGtra2xsbG1tbW5ubm9vb3FxcXJycnV1dXZ2dnh4eHp6enx8fH5+fn9/f/+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2JP+2Jv+3KP+4Kv+4LP+5Lv+6MP+6Mv+7NP+8Nv+8OP+9Ov++PP++Pv+/QP/AQv/ARP/BRv/CSP/CSv/DTP/ETv/EUP/FUv/GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/LZP/MZv/MaP/Nav/ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/Tff/UfoCAgIKCgoODg4SEhIaGhoiIiIqKiouLi4yMjI6Ojo+Pj5GRkZKSkpOTk5SUlJaWlpeXl5qampubm5ycnKCgoKGhoaKioqOjo6SkpKWlpaampqmpqaqqqqurq6ysrK+vr7CwsLKysrS0tLW1tbi4uLq6ury8vL29vb6+vv/UgP/Vgv/WhP/Whv/XiP/Yiv/YjP/Zjv/akP/akv/blP/clv/cmP/dmv/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/mtP/mtv/nuP/ouv/ovP/pvsHBwcPDw8TExMbGxsfHx8jIyMrKys3Nzc7Ozs/Pz9LS0tPT09TU1NbW1tjY2Nra2tvb29zc3N3d3d7e3v/qwP/qwv/rxP/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03uDg4OHh4ePj4+Tk5OXl5efn5+jo6Ovr6+zs7O/v7//04P/14v/25P/25v/36P/46v/47P/57vLy8vT09Pb29vf39//68P/68v/79P/89vj4+Pn5+fr6+vv7+//8+P/9+vz8/P39/f/+/P7+/v///wAAAM9q+HsAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAYc0lEQVR4XtWdeWAc1XnAt3dpKGkbSppSjkDTxAmj2xK2ZRnjU7Z8gPGJMTbCJ24hJJSkaQu5ILQpadPEt3yCjeVDtrGTNqVtCm5DsC2f8tHmaKkl2VYJtkWJRFazmePbN2/m+97MezOzs7O/fzz73ux6ftrZmTfvfe97mZyYX7v5L77x+lsDeur4yX9+66nbbrgGDpNAZPWhG/76f+Ez0spbX7vpfXC0Xmira7/8E3hrunn3q0/+ChyyC8rqg9+BN5UC3/3Ar8Jhc2Cra74F+5cK//KlX4RDZ3it/vDJ92Dn0mHgCx+Go8/jsbr232HP0uJH3/gFELBxW938DuxWarz3iV8HBQve6obPwj6lyFf+ACxMOKvbn4MdSpNvDgIPA8fq01+F6lLl258AE87q81+EytLl67eBC7P64p9AVSnz9HVgA1af+a0UNmLVuRUu8LbVh/W0N2XleOe7lg5YvVtqrSQRrz5h+VhWP7gZCimudHemi+7LPr+WR602oWn1rP4mlHk5uWZGvZY+hkxb2S4we+eVvNXAk1Dkpn9HE3xKGhm7tReO081z19tW/6G/DSUujt0N708r9fvhSF387KBldZv+BBTw9C8vgzenmOarcLQ8z/6OafVj6qreNw3emG4mXIbj5Xj3H00r/ffhJUeJSNFaH78xl3lV/ya8chiYBW9KP01ZOGaHg4/nMsYTF7xy2AZvKQXWwDFzfM+w+iBsO3TVwDtohowYNWrEEHhRdCpOwlE7fMyw+gJsO8yBN2AaZq99+aK9U8+BdXNGQHFRabKPh+Pvb8no34NtRlc57O+h4v7DsAfj6LxKqCwiJ+BgGG89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' +y11 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABkZGR4eHi4uLjAwMDExMTk5OTw8PD09PT8/P0tLS0xMTE1NTU5OTk9PT1BQUFJSUlRUVFZWVldXV1hYWFpaWl1dXV5eXl9fX2BgYGFhYWNjY2RkZGVlZWZmZmhoaGlpaWtra2xsbG1tbW5ubm9vb3FxcXJycnNzc3R0dHV1dXZ2dnl5eXp6ent7e35+fn9/f/+qAP+qAv+rBP+sB/+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2JP+2Jv+3KP+4Kv+4LP+5Lv+6MP+6Mv+7NP+8OP+9Ov++PP++Pv+/QP/AQv/ARP/BRv/CSP/CSv/DTP/ETv/EUP/FUv/GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/LZP/MZv/MaP/Na//ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/TfP/UfoCAgIODg4SEhIeHh4iIiIuLi4yMjJCQkJGRkZOTk5SUlJWVlZmZmZycnJ6enqCgoKGhoaKioqSkpKampqmpqaqqqqurq6ysrK+vr7CwsLKysrOzs7S0tLa2tri4uLq6ury8vL+/v//UgP/Ugv/WhP/Whv/XiP/Yiv/YjP/Zjv/akP/akv/blP/clv/cmP/dmv/dnf/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/ltP/mtP/mtv/nuP/ouv/ovP/pvsDAwMHBwcLCwsTExMXFxcbGxsfHx8rKyszMzM7OztHR0dLS0tTU1NfX19jY2NnZ2dvb29zc3N3d3d/f3//qwP/rw//rxP/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03uDg4OHh4ePj4+Tk5OXl5ebm5ufn5+jo6Ovr6+zs7O7u7v/04P/14v/25P/25v/36P/46v/47P/57vDw8PHx8fLy8vPz8/T09PX19fb29v/68P/68v/79P/89vn5+fr6+v/8+P/9+vz8/P39/f/+/P7+/v///wAAAD9msOwAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAASQElEQVR4XtWdCZgUxRWAJ3c8IsYzhnjFMwfRnnUXkJtFVEAUxGNFFBYUVI7EK0ZDjFcukmhYCTdEblwSRIkxQQ1JTFROLyRqojHcq0YFVlnd7Ukfb3q6u6q733vdPdP1fx92dXfVTP3uTE91ddWrXCGYzx313V/+9e02PXN88Nqf7vjGEftBNSUEWR110O2vw2tklQ9Wnro/1NaP3OqAW/8LRbPNx7869DNQZQ8yqyMnZfBTF8Qrx38Wqu1CtNrvHoWcTJ4+5JNQdQe/1clffw8yK8S9J0Dti/isDngMMqrFO1/6BAjYeK2OVeMiIeEHnwcFC7fVESd9BHkU5LGvgIWJy+qkGyCDmvylA3gYlKxuuglOq8rfTwMTl9Xt34KT6rL6RHBxrO44XLFfKRkrDwIbsLrl4PfhjNLcBhd42+oE/Sk4rjZtX7R0wOrD78Nh1XnzZsvHsnr12JAv1d4dW7PFtqaQ2v7YahOaVnfpq+GYny0zhvXRskfnweNWtEIVfbStKlq1HQOHvLQ9fGkeXiaD1E7fDfX08uRhttVT+qtwxMPmC6B8Vum8QPpJPNSyOlFvD/tu2uZ2hMIZ5tIdUFs3TxxiWr2u/xn2XbSNgYLZptcWqK+bP5pW+pdhz4UiUnKtO9sXcqv122DPxQQolH16N0GVS7x3YyGn62IP2doMX/v8DIc6uzjEsDoS0iX2Bv1G9TzXTwb0G6HWJe4wrL4J6RINkF+gz3bI4dANzlSQHi1QF4fXjs/pkyDtsC+4qoJWBqy0xVCXEnflxK/VIsgtw6+VBavzoC4lDs6JP8GDILcUn1YWrLQXoTIOp+WEi0VrDWSW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' +y12 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAAAICAgYGBg4KAAkJCQ0NDRIMABcPABERERUVFRgYGBoaGh0dHR4eHiUZAC4eACEhISUlJSkpKS0tLTAwMDY2Njk5OTo6Ojw8PD4+PlI3AHZOAEFBQURERElJSUpKSkxMTE5OTlBQUFJSUlRUVFZWVlhYWFpaWlxcXF5eXmBgYGNjY2RkZGdnZ2hoaGtra2xsbG5ubnFxcXJycnV1dXh4eHp6enx8fH5+fo5eAJNiAJxoALx9AL2BC5yQecCAAMSCAMaEANaOANmQAOGWAOSYAOucAPGgAPqmAPyoAP+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2JP+2Jv+3KP+4Kv+4LP+5Lv+6MP+6Mv+7NP+8Nv+8OP+9Ov++PP++Pv+/QP/AQv/ARP/BRv/CSf/DTP/ETv/EUf/GVP/GVv/HWP/IWv/IXv/KYP/KYv/LZP/MZv/MaP/Nav/ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/TfP/UfoCAgIKCgoSEhIaGhoiIiIuLi4yMjI6OjpCQkJOTk5SUlJaWlpmZmZycnKCgoKKioqWlpaampqioqKqqqqysrLCwsLKysrS0tLi4uLq6ur27ury8vL6+vv/UgP/Vgv/Whf/XiP/Yiv/YjP/Zjv/akf/blP/clv/cmP/dmv/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/mtP/mtv/nuP/ouv/ovP/pvsDAwMLCwsXFxcjIyMrKyszMzM7OztDQ0NPT09TU1NbW1tnZ2dra2tzc3N7e3v/qwP/qwv/rxP/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03uHh4eLi4uTk5Obm5ujo6Orq6uzs7O7u7v/04P/14v/25P/25v/36P/46v/47P/57vLy8vT09Pb29v/68P/68v/79P/89vj4+Pr6+v/8+P/9+vz8/P/+/P7+/gAAAHdvKjQAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAWDklEQVR4Xt2deYAVxZ3HCxZ2PbIbDMGV3RDBA1BchEjQva9k152BgUFAUA4PRETkkkPwQCLHGrMSF3Q1GuO6yDWAUUBAcBSTJRIP5D5UJHiCyKAwMwww/dLd79vVR3VX/6pfd7/X+fwB9epVv+7PvNe/rq6ug+WCOa/9Qz9/8/PTWsnR8Mlvnrjy/NY4TB+CrC5t98hmfEapcnrjVefjaL34W7V98CNsWuK80fnbOGQXflaXPNqAjTLAZ7PPxWE7EK1aP5IhJ4PPuv4pDp3jtfpeh09ROENs6oKjt/BYtX0SBbNFw5VnQSCP26rzuyiWOZ45DwomTquO7b5GmQzyzmWwMHBYdb20BC+4dD7tDg8d2+onl2VaStM+vwomDqtHL8q4lP5tdYULt3qswzG8l2HeaQcbWM258GO8k2meQYDPW3XRnkV+xrnS1IFVw/eQm3Ua/sv0Ma0OdJZcqE4eOVRafFHTiEPzYZNZJzSsHteeQp6XI89PubG8rOToNWLampM4RC9mHDSstL9Cjofdk3viY0qQfjO/wGG6+ax93uod7VfIcVEzEduXKj0X+v4SjWsxy3XVOuG1i/X9sXEJM/wDHKyTzy42rD7WfobXTpZhw9KmcicO10lnw0q79AReOsiGlL/Wbzrl2JtaF7xysAoblT6V+3DIDh7KMc0nVhyqxDYZYLgYMq7SrS4RG1/uwBZkrht6w+BeSKfNQhy0zUbd6gKkbVajPI1Ri7fWGls1vvfilN7IS5Oeh82DdnD6cqb9BGmbEShPoPd9ruB6fOkQvJEi87Fzm8eZ9n9IcnajNIExwt+pcWHq9ZH+QuWpO+sktP/d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' +y2 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABUVFRYWFhgYGBkZGR0dHR4eHiUlJSYmJigoKCsrKywsLC4uLjAwMDExMTIyMjMzMzQ0NDk5OTw8PD09PT8/P0pKSktLS0xMTE5OTk9PT1BQUFNTU1RUVFZWVldXV1lZWVpaWltbW11dXV5eXmBgYGFhYWJiYmRkZGZmZmhoaGpqamtra21tbW5ubnBwcHJycnNzc3V1dXZ2dnh4eHp6en19fX5+fv+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+zHv+0Hv+0IP+1Iv+2JP+2Jv+3KP+4Kv+4LP+5Lv+6MP+6Mv+7NP+8Nv+8OP+9Ov++PP++Pv+/QP/AQv/ARP/BRv/CSP/CSv/DTP/ET//EUP/FUv/GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/LZP/MZv/MaP/Nav/ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/TfP/UfoCAgIODg4SEhIeHh4iIiIuLi4yMjJCQkJGRkZKSkpSUlJWVlZmZmZycnJ6enqCgoKKioqWlpaampqmpqaqqqqysrK+vr7CwsLKysrOzs7i4uLq6ury8vL6+vr+/v//UgP/Vgv/VhP/WhP/Whv/XiP/Yiv/YjP/Zjv/akP/akv/blP/clv/cmP/dmv/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/ltP/mtP/mtv/nuP/ou//ovP/pvsDAwMHBwcPDw8TExMfHx83Nzc7OztHR0dLS0tTU1NbW1tjY2NnZ2dvb29zc3N/f3//qwP/qwv/rxP/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03uDg4OHh4ePj4+Tk5OXl5ebm5ufn5+jo6Ovr6+3t7e7u7v/04P/14v/25P/25v/36P/46v/47P/57vDw8PHx8fLy8vT09Pb29v/68P/68v/79P/89vn5+fr6+v/8+P/9+vz8/P39/f/+/P7+/v///wAAAB2rsOgAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAUOUlEQVR4Xt2de2AUx33Hr2mbPtL0ncQ1bmiTOI7dBjduXd8dQpKFRAUIyYBlEMQ4CIwBY4wskGnjJE2cunEa9+EmDRQLxMM2CGSCa2TLrds4zsOxEGAeAjdJQ9MIS7ZqOwglUnzay+3eV7OPmdmbmZ292/Xnn9ubmV32g253Z+fxm0SWz++8+0/v/8/v/diIHBOvfeOf//ryd+E0GfCsLn/fR56OoI+Lc5+7FGfrhW31q1O//CZ2jTY/vPfXccouWFa/8cffwU4xYOLB38ZpO6Ctfv6938YOMWHigbfj1Aleq6vf/UUUjhFvXIOzn8Rj9eXLX0fJePHML0Agj9vqt/4WpWLHD38XChZOq/dPeQZlYshPp8HCxGE17ZKvo0Q8uQceOWyrT/7e88iOK5+EicPqc1OeQ2Z8uRYuxOr+33waWTFm4g9hA6tPT/sscmLNj3CDz1t92Pj9CWTEm29ZOrD6ydT/Q3Lc+RvLx7L67s/9PRIZTAy/fD5aDF3EqTGYsOqEptXfGdM4v79Md9vSymT0qFu1cwCn6OW5SauJdzyLJDfDHXNwlAiSWv4U+09xZd7qW8ZUJLiY6IziX8lJ00s4VRfftaymGb/0VSQ4GVqOfSNM+SOsP9cVptU54yp8dTIwG3tGmxaG1tdMK+Pqz+Org5hIsbWuyCaeMy57A99shiN8m/CwGafs4LPZhMG6V6zGLjEgdRTnbHMuZ3XV/fhicwh7uJlR11AfwR9m3SjO2iZn9c7vYZswXoMdbMpv33cqY+aN9HYsRVpU2GqdtJM/SxhXY9PmAIoT5u2+gCyL/g3lyIgENeM4L8KDCeMybNrchOJg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' +y3 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABkZGR4eHi4uLjAwMDExMTk5OTw8PD09PT8/P0BAQEJCQkREREZGRklJSUtLS0xMTE9PT1FRUVJSUlZWVldXV1hYWFpaWl1dXV5eXmBgYGFhYWNjY2RkZGVlZWZmZmhoaGtra2xsbG5ubm9vb3FxcXJycnV1dXd3d3h4eHp6enx8fH5+fv+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2JP+2Jv+3KP+4Kv+4LP+5Lv+6MP+6Mv+7NP+8Nv+8OP+9Ov++PP++Pv+/QP/AQv/ARP/BRv/CSP/CSv/DTP/ETv/EUP/FUv/GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/LZP/MZv/MaP/Nav/ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/TfP/UfoCAgIKCgoSEhIaGhoiIiIuLi4yMjI+Pj5CQkJKSkpSUlJWVlZeXl5mZmZqampubm5ycnJ6enqCgoKGhoaKioqSkpKWlpaampqmpqaqqqqurq6ysrK2tra+vr7KysrS0tLa2tri4uLq6ury8vL29vb6+vv/UgP/Vgv/WhP/Whv/XiP/Yiv/YjP/Zjv/akP/akv/blP/clv/cmP/dmv/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/mtP/mtv/nuP/ouv/ovP/pvsDAwMHBwcPDw8TExMXFxcbGxsfHx8jIyMrKyszMzM7Ozs/Pz9LS0tPT09TU1NbW1tjY2Nra2tvb29zc3N3d3d7e3v/qwP/qwv/rxP/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03uDg4OHh4ePj4+Tk5OXl5ebm5ujo6Ovr6+3t7e7u7u/v7//04P/14v/25P/25v/36P/46v/47P/57vHx8fLy8vT09Pb29vf39//68P/68v/79P/89vj4+Pr6+vv7+//8+P/9+vz8/P39/f/+/P7+/v///wAAAJQ+NvAAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAU6ElEQVR4Xt2deWAc1X3Ht3dJL9IcjSkFktCkJKwky5J8yadsfFs+hLGNbXziM4SQENI2bUoh0JomLbGx5QtjG98HQiW9krZxSRowNr4tt2mcUIwPqRB04Ep0Nds5vvtmZt+bmXft7ow//+zse29G89Huzrx5x++lssH8yie/+tJ//MyIHb3v/PDpP7ztphtwmgyCrG665a/ewUHiypt/8bEP4mzzYVv9xupr2DXe/OzPH/klnLIPltVHvoedksA//uYv47Q90FY3/DPKJ4WXnvx5nDoh3+r3/6wXhZPD+1/6NM4+R57Vr/8YJZPF9//+5yDg4Le6830USxrv3farULDxWn3s6yiTRL58OywsPFa3fwsFkskTD8LDxLV66NvITiqrH4KJx+pr30Rmcnn0M3AhVo/+KbKSzAO/AxtYPfwJZCSa3g/hAu9YfcJ4DxnJ5s0f2DqwunYYyUnnpT+yfWyrHz2ARAa97ZffiheXO3BqLG6z64SW1eNB37/eo2unD0zHj9oZ60/hFPN543DOqvdJJPnp2n4XjhJHJu7twXn6+dKtjtUPDGY1/cVa7B9XRh7Hmfp490e21SeNx5HgpXMR9o0x5atYH9dDN1tWFwzG03z7OOwZb6Z343w9vPmvlpXxWbz1kBApttbv3pxNHTa+j3cuPROxU/yZSV8TvvWVbAqbPtZhlySwE+fs8v4F0+oOvHE5VY49/AyqqxuEzRhRfQln7dLHtHoa2y6M71/l/ENXrawrB+f1RVJcmG2fs5ev3ZEyqCbakyjuUrG2DXkmrSvZH2WpKL+MEyP8+1OM39U8FCeMzquenKhDRjxYhdMi9F5I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' +y4 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABkZGR4eHi4uLjAwMDExMTk5OTw8PD09PT8/P0BAQEREREZGRktLS0xMTE1NTU9PT1FRUVNTU1RUVFZWVldXV1hYWFlZWVpaWl1dXV5eXl9fX2BgYGFhYWJiYmRkZGZmZmpqamtra2xsbG5ubnBwcHFxcXJycnV1dXh4eHp6en9/f/+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2JP+2Jv+3KP+3Kv+4Kv+4LP+5Lv+6MP+6Mv+7NP+8Nv+8OP+9Ov+9Pf++PP++Pv++QP/AQv/ARP/BRv/CSP/CSv/DTP/ETv/EUP/FUv/GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/LZP/MZv/MaP/Nav/ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/TfP/Tfv/UfoCAgIKCgoSEhIaGhoeHh4iIiIuLi4yMjI6OjpCQkJOTk5SUlJWVlZaWlpiYmJqampycnJ2dnZ6enp+fn6CgoKKioqSkpKampqioqKmpqaqqqqurq62tra+vr7GxsbKysrS0tLW1tbe3t7i4uLq6ury8vL29vb6+vv/UgP/Vgv/WhP/Whv/XiP/Xiv/Yiv/YjP/Zjv/akf/akv/blP/clv/cmP/dmv/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/ltP/mtP/mtv/nuP/ouv/ovP/pvsDAwMHBwcPDw8TExMbGxsnJyczMzM7OztDQ0NLS0tTU1NXV1dbW1tfX19jY2Nra2tvb29zc3N7e3v/qwP/qwv/rxP/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03uHh4ePj4+Tk5Obm5ujo6Orq6u3t7e/v7//04P/14v/25P/25v/36P/46v/47P/57vDw8PLy8vPz8/T09Pb29vf39//68P/68v/79P/89vj4+Pr6+vv7+//8+P/9+vz8/P/+/P7+/v///wAAAGcqjO8AAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAASDklEQVR4Xu2deZzWxBnH397Vth5tvVqLtNjisRcILCBUuxwrVAW5VHRFUXAFuopASyse9a5t1VZbri6KyKnAUhFQa6vV1mJVEN1yqWjLcnoDCstu3r5Jfu/kmMn7PpNM8ib72e8/bzJHNt99d5PJZOaZVNqbL7W97v7V7zdrseOjN5666fvHH4LTFOBldfwxd/wXx4grH/7+u0fgbN2Irb568weoGm/233PYF3DKDkRWRz0Zw786L/75rS/itG3wVofch/JJ4bm7PotTZ7itfjDhUxRODs13noSzz+Ky+spzKJks3jnsMxAwcVod9yGKJY3miV+GgoHd6rgJCbpKuLn7RFjo2KxOvBkFksnTE+CRwbKadBuyk8rfJsHEZnXLFGQml6dOgQuzuvUkZCWZO4+FDawmtzuInERzMi7wplU77R2kJ5v9qw0dWH16L5KTzr+vN3wMqzePRaKIPdsb4sX23Tluq5ONNqFudbu2BWlu1tde2KMofpQPrnnZw2z/c1mr5muQ5KSpbiCOEkd6z92L83Tyu7am1WrtPaQ4qO+D+nGl23KcqYPmNw2rE7VTkWCnaWYpKseYSz/G2dq5p41utUV7G/s2GoejYrzpswvna+Pg33Ur7RvYtZEQKbHWxDbp1PPab7Fn41JUij+VB3DKFm9dl05p2ifYs1iKKklgLM7ZxpaM1ZHYtthZjhouuvcBpyMhDhSvxVlbXJux+gW2LS5DBRclDcjXLkZKLOjL3Y//enJKewbbjF1lKO/iMuRrG4uREg9ewWkxPr07pXE9ZbUo7aJkM/K1EUiJCRfitCy2pL6JLYszUNrFJcjWNpcgJSaU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' +y5 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABkZGR4eHi4uLjAwMDExMTk5OTw8PD09PT8/P0BAQEREREZGRkpKSktLS0xMTE9PT1FRUVJSUlRUVFZWVldXV1hYWFpaWlxcXF1dXV5eXl9fX2BgYGFhYWJiYmRkZGVlZWZmZmlpaWtra2xsbG1tbW5ubm9vb3FxcXJycnNzc3V1dXZ2dnd3d3h4eHp6ent7e35+fn9/f/+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2JP+2Jv+3KP+4K/+4LP+5Lv+6MP+6Mv+7NP+8Nv+8OP+9Ov++PP++Pv+/QP/AQv/ARP/BRv/CSP/CSv/DTP/ETv/EUP/FUv/GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/LZP/MZv/MaP/Nav/ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/TfP/UfoCAgIODg4SEhIeHh4iIiIuLi4yMjI6Ojo+Pj5CQkJOTk5SUlJmZmZqampycnJ6enqCgoKKioqOjo6SkpKWlpaampqenp6qqqq2tra6urrKysrS0tLa2tri4uLq6ury8vL6+vv/UgP/Vgv/WhP/Whv/XiP/Yiv/YjP/Zjv/akP/akv/blP/clv/cmP/dmv/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/mtP/mtv/nuP/ouv/ovP/pvsDAwMHBwcPDw8TExMbGxsjIyMnJycrKyszMzM3Nzc/Pz9DQ0NLS0tTU1NfX19jY2Nra2tzc3N7e3t/f3//qwP/qwv/rxP/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03uHh4eLi4uTk5OXl5ebm5ufn5+jo6Onp6evr6+zs7O/v7//04P/14v/25P/25v/36P/46v/47P/57vDw8PLy8vPz8/T09PX19fb29v/68P/68v/79P/89vj4+Pr6+vv7+//8+P/9+vz8/P39/f/+/P7+/v///wAAAIAkMWMAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAUiElEQVR4Xu2deYAW5X3H3941bdWkidbGkFpjUptWbWfZw11YUETlEEGR+wjIIcppo6a1qWnSNDFqeiD3ERCX+xCSpo29kpAUkFsEj6aNgZVlm7TCrpaV3Xk7x/f9zfE8z8wzz8y8M5Py+eed+T3PzDyfffed45nnKJXF/NJVf/zV7/xXj5473n3jH754w9WXoJgcRFZXX/q517GPvPK/f/f7l6O0fvhWv/onP8Sm+abnm1f9AorsgWf1oa9cwFYF4N+v/0UU2wVrdclfFMjJ5PXf/FkUnfBb/c51P0bmAvGNT6L0FXxWv/K3yFgs/ue3fwYCNl6rq/4T2QrHl38ZChZuq6s++i7yFJB/+gQsTFxWn7gphxdceb7/CDwMHKvH/gDJReW1x2Disvr8xwv9TZl87ya4kNUXLi/YVYrHt66EDawe/1gBL1MsX8AJ3ra6Tv9XxAvORywdWL37GUSLzo//zPKxrF678j1EOXSePpUvWs90o2gc/sq6JzStvqS/iJifUyun3K7lj5vvnbNNZPaBilXPlYh46dk7oQa7ySG3LDmDcnrZfY1ttVvfjYiH1lHYPq80rOFeYT9qWX1c/yDW3fS0NGLjHDOqFaV1s7uXafUD/e+x7qJnPjbMN/1eQXndXGZa6b/OfpEFkeJrPd2rXPq2/ijWXCzDRvmnXxuK7PDuZ8sl46YQaw6He2ObAjCe/U8zviv9/Vh2OD/Iyt88OIxcnFBaUGqHpwyrj2HZYYWdfSlWxXzKzpgtTR0oDfGjG0r6l7FMdA+wsxfESluD0jg8XWIvwduQuyhWg5hf1tWlDzI3tuOQuyhW2n4Uh3isxJws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' +y6 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABkZGR4eHi4uLjAwMDExMTk5OTw8PD09PT8/P0BAQEREREZGRkpKSktLS0xMTE1NTU5OTk9PT1FRUVJSUlNTU1RUVFVVVVZWVldXV1hYWFlZWVpaWlxcXF1dXV9fX2BgYGFhYWJiYmRkZGVlZWZmZmlpaWtra2xsbG5ubm9vb3FxcXJycnV1dXZ2dnh4eHp6ent7e3x8fH5+fn9/f/+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2JP+2Jv+3KP+4Kv+4LP+5Lv+6MP+6Mv+7NP+8Nv+8OP+9Ov++PP++Pv+/QP/AQv/ARP/BRv/CSP/CSv/DTP/ETv/EUP/FUv/GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/LZP/MZv/MaP/Nav/ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/TfP/UfoODg4SEhIaGhoeHh4iIiIqKiouLi4yMjI2NjY6OjpCQkJGRkZKSkpWVlZmZmZqampycnJ6enqCgoKKioqOjo6Wlpaampqqqqqurq7CwsLGxsbKysrW1tba2trq6ury8vP/UgP/Vgv/WhP/Whv/XiP/Yiv/YjP/Zjv/akP/akv/blP/clv/cmP/dmv/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/mtP/mtv/nuP/ouv/ovP/pvsDAwMPDw8TExMbGxsnJyc3Nzc/Pz9HR0dLS0tPT09TU1NbW1tfX19jY2NnZ2dra2tvb293d3d7e3v/pwP/qwP/qwv/rxP/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03uDg4OHh4eLi4ubm5ufn5+np6evr6+3t7e/v7//04P/14v/25P/25v/36P/46v/47P/57vDw8PHx8fLy8vPz8/T09Pb29v/68P/68v/79P/89vj4+Pn5+fr6+vv7+//8+P/9+vz8/P39/f/+/P7+/v///wAAAKxo9DAAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAV8UlEQVR4Xt2deWAU133Ht3fdNnZrpy2mbpripnFSu2mOkYQEAmQQt5A5TEAgwGAhwOauY9duHbdNmqRp67TmPmQjJAtzI8dpk7ZJmjStzI0wUDtOYw4BbhxLyHF2YTXbOb775nhv3rw3M7s7488/zL55u5oPu/v2Hb/3m1TOm1/67Uf//t9+eEONHdd/8PUvf+qWm3CZDLysPnjzk98dwIvElBvfeORWXK0bttWvffJVPDXm/PtHfgGX7IBldftfv4MnJYA3P/OLuGwbtNVNTyTISefNP/5ZXDrBbfVH7/8+KieIb92Dq8/jsvrVL8a8iWBz/TM/AwETp9UH/gPVEsdLvwwFA7vVB+78P9RJIK9+FBY6NquP3v4T1EgkbzwKDw3L6vHB13E+ofzocZjYrP7mfe/ibGJ54+NwIVZfuPUtnEswr90BG1h99q7/wZlE8zU08KbVXerTKE84jxk6sHr3TpQmnRt/ZfgYVq/d8SZKGaQvX4gXF69kcGkMvmP0CXWrv1W/iDI3V1ubJ5crsWPo1Id29eMS3RjtoG41cAd7vHuquRIvE0OqV53HZTr50YdMq/9Uv4ISB71NeH5cKV/L/CQ+YVh9RB3E6qd3jsaTY0zdKVysnbeG6Favq5/DYzvteGK8qXwZl2tHG2ylcupv/RgPbSRDiq313SG51DfVD+KRjX14UvypPIlLtvGXuZTKaCsuj8BzEsCkNC7a4nHN6ra38YAw0IhnOBk5fmLtSBzHiDW4aotva1Z34djiIOrbGLtm70Xj3OX2BcNRFhPKzhoXZmPgYyn1kzi2mIX6hIaDWZzSyXRNR3k8WI7rshiUUv8B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' +y7 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABkZGR4eHi4uLjAwMDExMTk5OTw8PD09PT8/P0BAQEREREZGRkpKSktLS0xMTE1NTU5OTk9PT1FRUVJSUlNTU1RUVFVVVVZWVldXV1hYWFlZWVpaWltbW1xcXF1dXV9fX2BgYGFhYWJiYmRkZGVlZWZmZmlpaWtra2xsbG5ubm9vb3FxcXJycnV1dXh4eHp6enx8fH5+fn9/f/+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2Jf+2Jv+3KP+4Kv+4LP+5Lv+6MP+6Mv+7NP+8Nv+8OP+9Ov++Pf++Pv+/QP/AQv/ARP/BR//CSP/CSv/DTP/ETv/EUP/FUv/GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/LZP/MZv/MaP/Nav/ObP/Obv/PcP/Qcv/Rdf/Rdv/SeP/Sev/TfP/UfoODg4SEhIaGhoeHh4iIiIqKiouLi4yMjI2NjY6OjpCQkJGRkZKSkpSUlJqampycnJ6enqCgoKKioqOjo6Wlpaampqqqqqurq7CwsLGxsbOzs7S0tLa2trq6ury8vP/UgP/Vgv/WhP/Whv/XiP/Yiv/YjP/Zjv/akP/akv/blP/clv/cmP/dmv/enf/env/foP/go//gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/mtP/mtv/nuP/ouv/ovP/pvsDAwMPDw8TExMfHx8nJyc3Nzc/Pz9HR0dLS0tPT09TU1NbW1tfX19jY2NnZ2dra2tvb29zc3N/f3//pwP/qwP/qwv/rxP/rxv/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03+Hh4eLi4uPj4+Xl5ebm5ufn5+jo6Onp6evr6+3t7e/v7//04P/14v/25P/25v/36P/46v/47P/57vDw8PLy8vPz8/T09Pb29v/68P/68v/79P/89vj4+Pn5+fr6+vv7+//8+P/9+vz8/P39/f/+/P7+/v///wAAACsZAT0AAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAQLUlEQVR4Xt2de4BUVR3Hp3dWvoAKVs0MKtFE090FBEFeCriISBAqkgjyCAmENDVTy8qyBwXiIg9BFHkoIqilFZamLQQIqKBZZro8NRUWH7uwe6f7+M6ZO3Pu3DmP332cPv/sufeec+d8dma+c+fOuedmsqX5xJFn3PbYqwet1HHotT/+8nufPwzdDKCU1QlHXP34IewkpbQ8dWMr9LaYYKvPnPQnNE05L53+MXS5gCCrdte8iUYG8O6PPo5u++CtDuv0OhoYwrs3fBhdZxRbfa3NE6hsEP9qg97nKLL69DUpjLzytNz6IQh4FFod/wiqGcdfPgkFF7/V8R1eQh0DefNkWDj4rE5uZ1hMFPJeO3jY5K2ur/gvthvKwQqY+Kx+crjRz5TD+4fDhVn9tNU/sM1g3joWNrC6qeOj2GI0zyDgPauO1nVYbzi/cnVg9X6HlB+fC9PB9XGtXj7uSawMoGnvzh3pYk8juhbAm+4xoWP1c+s0rCvmwNJJQ7pUpo7qmvF3v4EuFnNrzqrl2OBPqvopZ2E3KaTr+K3oZiGHvuJZ/dX6PtYU0DS9GjtIK+P2oasFzHCtTrLavoUVfrbWoG2K6bManfXT0t6xesXqhGU/dV3RMt3ci+76ucWxsj73FBZ9GCIVqPV2+2xmrXUClnxsMUWqsvIBdNnHCdmMFZAVjeehiQH03INO55lhW7X+MxbyXOXW71pTnh5uzUQZ1YJeM96xrTpya7dXudWHYDGM77g1k2UV+pLn1IzVFsU8k73aplhdhL7kOT1jXYsio6G7V9sUq8pt6AzjV5m2M1Bk3IPKxlhNRWcYT2f4sBiPysZYDUVnGB9kOnKHS4NQ2RirM5vRG0amAgXGgdxBrTFWlc+hN4xMexQYO1DVIKuH0BtG5kYUGNtQNW+1e1Ux27HFuhJ1k+V+9IaRORUFxguomre6HyvyrMcW6xysSJYV6A0j0xEFhoDVAGyw1mBFwtBYzcMG6zKsSBgSqy65MyF7OmNNwpBYjcF6aw5WJA2JVcqygsYqbVlBYzUfq9OSFXJW5ywBhR+1qcsKOasSpC4rSKxSlxUUVunLCgqr9GUFgVUKs4LAKoVZQWCVwqzQt0pjVuhbpTErtK1SmRXaVqnMCm2rVGaFrtVAVElXVuhapTMrNK1SmhWaVinNCk2rlGaFnlVas0LPKq1ZoWWV2qzQskptVmhZpTYrdKzSmxU6VunNCg2rFGeFhlWKs0LDagO2xpMVPc4bccWUabNm1945b8HcO6ZNGBz+AlG1iiUrug8YPmbq/OUb6vmR3Y2bF42r8QaNBaBqFXVW9B45e9VePERJdt/eC9WLULSKMit6XDT9gV3YfTmall2IVgUoWkWUFV2HT11ejz2LsmUsGvtQtIoiK3qOW3kAe5Wjri/2wFCzos+Kc6ds4IZUCbN/AvaSQ82KOCsuqH0e+1Plod7YlYeSFWVWdL5ooWg0hLHvUuzPRcnqrFHgAqxQpt/c3D9Ilyb/y0YxLWgYsVL9vcTh10rOqtuV3KBfPXxaSVkNXLgfu6cjr5WIVdWlddg3LU0j8AAJWHWevAN7JmcnRt7HbzVG9pBIhiXeY8RtNWIL9hoRI91Hidfq/DXYZ2Tsdi8qitOq31LCj6dSLHMeKT6rHvNDrlUmZIj9WHFZdZ0WeNVrBCy1Hy0mq2FRBl8hTWfHZNV1QQxvKMaseKwuZNdbxMKu6hisusyN84lyuCx6q8EvYDfxsSZqq861TdhLjDRURWs1KHhyhqgZGKVV1awEniiHsRFadeOvRo6JBdFZnRN/TOTYGJnVcKqTRwo08lcA0lhNSugt5cFNSUJiVb0IbRPib/jLoLDqEc3JFnHW4S+DwGrgi2iZGH/HX4a+1SX5M33retIge1KK/RCVQ9tqsu9gdjXW6SL75LNhOzl0raaglcv/i1WBVGJWxGlRKJWYFZfBWlZFUolZkX5eFUslZsWdTNWw4qQSsyI8YuKlErNaib8MZasAqaSsGsm+iQRJJWX1IpXVeFQuJCGr9URWQ4O/TiVktYzGqi8/u51LQlbzSKzOLHWCLCGrKSRWAdMreiRkdTmF1R2oyJOQ1TACq9GoFwBv1blbefhpdSV//eqvbzU4ZKgibzUBW0Jo5GbB7C35q0o3bateYePglKzuQ9U8s7BFkAbt30S6bEKtQJSsvoGqjCrJ0xbbtK2WoFIwKlb8w12MLaLU6VpdjjolULHC1KY+Sn5wlGCBplWvMifTFaz0s8Iaq2n1IKqUQsFKOyssa6Ce1TjUKImClXZWWA1VWlZ9yg53kbfiH0w2K6z1euMtgqZ4L0TeSj8rrLlaVhOxPQRpK4KssEbrWPVrwPYQpK0IssI6V8eKO+sbgLSVflZY++xWylaTsTUUWSv+oaSzwr0gR9Wqv9BFRbJWBFnhXhGmaiU2gFbSiiIrrFF2M0UrfmL3QCStKLLCci4xU7QSHJ+06YJi5mBLIHxW7MQWcfY47dSsxmITLfwDyWeFN05fyapLNJdEUGSF+7ZSswo8p65NI3fDJoWsaDzTaahi1T2aIUokWfGg21DF6k5sIIYiK3CPBgWrPmpX9ZaDf6ErZEXz2W5LBaugmzERwGcF94theTZ4LeWtauTfwiKQZIU1xWsqbxXRuFOSrHC+hThIW7EpsokZiv0zVLLiebSVtlqKtcQUv3mVssKqRVtZq7MjGnlKkhVW7lpzWSuVF7sANFmxC21lraopZgIIgCYr5qGtrFXIL3BakGRFM5tCRNKKG/pJQ8GL3EUlK1ahrazVIKyihiYrLkZbWavFWEUMTVZsR1sbKauzojmuzV1n7kMlK3xPuJRVNN8WibIid08/Bxmrqoguj/W9xIFKVixCWwcZq5FYQQ1NVvhvaipjxdWlgSYr1qGti4RVF4EfQVSgyQr33FIOCatLsEwNSVbsLJh1T8Iqog8r9gJnqPz7pqGth7hVVYmRjbqQZMUbvli3Ebe6EIvEkJ6vyCFuFdFZQJKs2FE035q4VUQTH5BkRfHEiMJWbMpAWvAv86GQFVvRlCFsdRWWiCHJityUWQxhq9BxgMrwWdFHPiv4CSdFrXphgRiKrGg+H03ziFoJDIRRgSIrnEl9ihC1UjmKLo/34vYjnxWN/dDUh6hV2XmClaDIivlo6UfQqh/KtFBkxT5ujIaNoNW3UKaFIismoWUBglahwySUIciKOrQsRNAqkhnycr/L5JHOiv3cZMsuglaRTL3G37lcOiuKp1oGYlbnokgKQVY8hIbFiFmVGYyvhn5W7CucPTqPmBW72zgl+llxBRpyiFlxMysQoJ8VK9GOR8iqKopzZtpZsdcbMRKEkFUU3xj1s2I02gUgZHUFSpRoZ8UKNAtCyCqKsNDNil1Bx385hKyWo0SIblYcGIxmgQhZRfBrsG5WhLypbISs6H+30s2K3CCYEghZ0U8qrJkVD6BRKUSseqBAiF5WbHUH14YgYnUeCnToZcWe4K8fPkSsRqBAh1ZWNHJPNIeIFfmHsF5WeAOGQxGxmoYCGXxW3I4tAixAkzBErO5CgQydrFhd8gZlPkSsuLk7NdHJik3d0CQUESvqHw40skJMSshK+nRWOBpZISglZEU81FY9K0SlhKzwlwru/naiWSEsJWJFfOsj5awQl0rASjUrJKTit1LNChkpESvaIQmKWSElFb+VWlZslJKK3UotK5Z1QWVB4rbat62Y8hdJNk9HZ4WJ/RUoT0PBrRiFELAiTnZZ6v0DagURsEru/gUO68POZpZCxCqaK7nFuJufoE4AESuuTmw08QciQohYRTTcrDxvfBO9lEXEajgKcbMFV5TKI2LVHYV4aZqt9JZyEbGKanBqKM/z4+PEEbK6D6X4aJ6jdT9mISuVS2y02ObcnlADIauYX4LN8yUPZjnErISmlKLiRW6iC2nErLpHdDlPEAvL/YwjgJhVZWx3E3pW/4myEbSi/wkrkO0099cXtYriZ3yOPZPUP3cLEbXqEdF1SnkaZhO8oYCoVeWlWIqIpkWlRyXJI2wV7QHG/f29ByFC3Kp7RJNA2KzTPJTgELeK6rjpwD06x7HBSFhFcq1I/VSV8xLlkLGi11o9UuRXXnmkrGi19t81ALslR86KUOuFSXKnznm64lZ6PfkjfEmryokkP6fWzyc43GNDC3LzFeWRtao8/zmsVmbLrBrsS4teuf/vFqzwIW1V2XmO5KhfP01rriw7tEqQ6dil9W2s8CFvVVk5RPHMe8OKMdwPjcqwKUQaAt6fKlaVXWqlr4bZt6b2Yt3v7QWwGXcXY4UfJSs7fyaIv70a1s0drXy+siQhWaFsZTNsRfk4PLBxwdiBkXzQhmWFjlVlZe9xC58NNtu7ddXi2RNH1lB9C+RhWTERKwrQsXLoPHji4lV1G7ds3rS+bvWqlffWTho1pK/WGUohQrNC3yohQrPCWKvQrDDVKjwrTLUKzwpDrcpkhaFWZbLCUCs2bXtwVphpVS4rzLQqlxVGWpXNCiOtymaFkVZls8JEq/JZYaJV+aww0EogKwy0EsgKA60EssI8K5GsMM9KJCuMs2K3mQvLCuOs2O+dYVlhnJVQVphmJZYVplmJZYVhVoJZYZiVYFYYZsWyonB6lcETAPvlxSSr3iWyohar83NpmWRVKiuMtiqZFUZblcwKo61KZIXZVqWywmyr0scVIlYVKDDSYRVyXCFidS0KjHRYDUVvrG3TimF3EGdW3OwpmdYoMOpRNVlERpIyK+7ui5kvoMBwblqePFJW3JwwmcPfRYnBbmyWJDJW1dwdrTIVz6DECJ/VLiZkrLhbqrVkvjgTRQa7tV6SyFhxtzz/Z8b6IYqMndEN3BFHxoqFYo6ZGas9inmIrrTRQsKqpgXLjOszVhsU86z3aieKhNXdWMzT2n6u/o0yo0V+LgZy+k4qj3exSQ03NeXBbMb61I+xkGd3FBcIRET1VnQ6z+9sK+soLPhYjiYGcAe67KOTY3Xif7DkIxXpLsIELiqsg60cK+sH3lIBhmgFSFm/ybpWpxz0Fgu4h+4Cvciovj1AyjrDtnrcso68DcsF1A9D29QycDO6WsAfsrZV1i60CXqyrOal1Ne0kTLgruDZhlu7Vi9ZQeHusXnioDQcPvH0H7s66MVn86gtZVs5T1bF696qAA5sXHHfknSxvG4/Osdz8MuwWmsvdPDWmc8NjpRjlbWfy4oZWGs4a10p1+oWe/GIl73VZvN2u7xV9ml7Rbt3vA0m0wIpzyrrGLU95G0ymK+7MjaelfPWsr5aIiuN4SbPxQZW33XWnmj2s5WXylllb3bWH8edRTOHFvbys8lZZW9yNh3zqlvDQN4+Bh4uzCp7mvP6+9LDXiXTeOIoWHjkrbLZt5ztnQxM+IM3fgQKwG+Vtb+V2N9Lfm1aFv7+s+g/o8Aqe/V7Tq22j7iVDWFt24+i93kKrbLZ37o1j/7F++7f1HNo5tFHoOd+iq2y2Ufd6kd2fPgDt5BiWh477drD0OtCeKts9mcIjFbXzXwlre+x1x65ueLJU9DhIrLZ/wFcdNTRL+2QrwAAAABJRU5ErkJggg==' +y8 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABkZGR4eHi4uLjAwMDExMTk5OTw8PD09PT8/P0BAQEREREZGRkpKSktLS0xMTE1NTU5OTk9PT1FRUVJSUlRUVFZWVldXV1hYWFlZWVpaWlxcXF1dXV5eXl9fX2BgYGFhYWJiYmRkZGVlZWlpaWtra2xsbG1tbW5ubm9vb3FxcXJycnNzc3V1dXZ2dnd3d3h4eHp6en5+fn9/f/+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2JP+2Jv+3KP+4Kv+4LP+5Lv+6MP+7M/+7NP+8Nv+8OP+9Ov++PP++Pv+/QP/AQv/ARP/BRv/CSP/CSv/DTP/ETv/EUP/FUv/GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/LZP/MZv/MaP/Nav/ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/TfP/UfoGBgYKCgoSEhIiIiIuLi4yMjI6Ojo+Pj5CQkJOTk5WVlZqampycnJ2dnaCgoKKioqOjo6SkpKWlpaampqenp6urq62tra+vr7KysrS0tLa2trm5ubq6ur29vf/UgP/Vgv/WhP/Whv/XiP/Yiv/YjP/Zjv/akP/akv/blP/clv/cmP/dmv/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/mtP/mtv/nuP/ouv/ovP/pvsDAwMHBwcPDw8TExMbGxsjIyMnJycrKyszMzM3Nzc/Pz9DQ0NLS0tTU1NfX19jY2Nra2tzc3N3d3d7e3t/f3//qwP/qwv/rxP/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03uHh4eLi4uPj4+Tk5OXl5ebm5ufn5+jo6Onp6evr6+zs7O7u7v/04P/14v/25P/25v/36P/46v/47P/57vDw8PLy8vPz8/T09PX19fb29v/68P/68v/79P/89vj4+Pr6+vv7+//8+P/9+vz8/P39/f/+/P7+/v///wAAABfKiGAAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAWaklEQVR4XtWdeWAdx13HH2dJoXFJg+OG0DSmTgrhaGB1WbJs+YyP+IitxLcdK/J9xDYQAoGUltJCkxZ8yld83zdQIFxt0oJvy7YslxoKTX1ICikgWwQpedrHHt83O7szuzszu++93c8/fm9m9mk/fm935/xNJufPh/p85gt//a/v6Ymj9z+/8ZXfeegenCYHP6uH7/3Vv/w/fEhSuf7Ze3G2XvhWP/XQ13pxaLL53u/+GE7ZBc/qgcf/DQelgA/+5Mdx2hSs1T0/dx0HpIQP/vCHceoEr9Uv3v8XKJwi3n0MZ5/HY/WTn/pvlEwXf/ZDELBxWz30JZRKHf/xE1CwoK0e6v93KJNC3usPCxPK6hce+CeUSCW9T8DDwLH67X7/gvy08mswoaw+95FvIjO19H4aLsTq8/e9gbwU8/59sIHVy49+Hjmp5l3c4G2rx/RPIj3l/KOlA6v3+r+L5LTzkuVjWX3nwa8ikUO249bNZNHWhVPj8L5VJzStvqjfjzQv2SMr6qu15PFkw5ZbOEUvb+Steh98C0luOjYMw6ckkLLZp/lNwI/bVm/p/ZHgonf7QHxAUpnK/b7etKw+rfflfVW3puLYBFOzh/d19TWtvqv3wVuaq3U4Mtms5mj9lWml/8yreEuREimuVu8juczX9YfZvrG2tEhpWhNOmeLFXEbn3Ct6Z+GQFFB+CSft8E3D6mNfxhuHPTjCw/Axo2vwMkGM68ZZOxhWj34frwl3B+EAisGrTt8x867tm46UxLDZOmmaARm9L146bEdxh9pd1H9I6zykJoSRWZwY4UsZ/WG8JPSOQXHCzDZkgUO1yEgGR3BahDcz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' +y9 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABkZGR4eHi4uLjAwMDExMTk5OTw8PD09PT8/P0pKSktLS0xMTE1NTU5OTlBQUFNTU1RUVFZWVlhYWFlZWVtbW11dXV5eXmBgYGFhYWJiYmRkZGZmZmpqamtra2xsbG1tbW5ubnBwcHFxcXJycnV1dXh4eHp6en5+fv+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2JP+2Jv+3KP+3Kv+4Kv+4LP+5Lv+6MP+6Mv+7NP+8Nv+8OP+9Ov++PP++Pv+/QP/AQv/ARP/BRv/CSP/CSv/CTP/DTv/ETv/EUP/FUv/GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/KZP/MZv/MaP/Nav/NbP/ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/TfP/UfoCAgIKCgoSEhIaGhoeHh4iIiImJiYqKioyMjI6Ojo+Pj5CQkJOTk5WVlZaWlpiYmJqampycnJ2dnZ+fn6CgoKKioqOjo6SkpKampqioqKmpqaurq62trbGxsbKysrS0tLW1tba2tri4uLq6ury8vL29vb6+vv/UgP/Vgv/WhP/Whv/XiP/Yiv/YjP/Zjv/ZkP/akP/akv/blP/clv/cmP/dmv/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/ltP/mtP/mtv/nuP/nuv/ouv/ovP/pvsHBwcPDw8TExMbGxsnJycrKyszMzM7OztDQ0NLS0tTU1NXV1dbW1tfX19nZ2dra2tvb29zc3N7e3v/qwP/qwv/rxP/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03uHh4ePj4+Tk5Ofn5+jo6Orq6uvr6+zs7O3t7e/v7//04P/14v/25P/25v/36P/46v/47P/57vDw8PLy8vPz8/T09PX19fb29vf39//68P/68v/79P/89vj4+Pr6+vv7+//8+P/9+vz8/P/+/P7+/v///wAAAJqY7cUAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAV7ElEQVR4Xt2deWAVx33HX++6ce06dd3Ubp24dWM/ISEkLiFQOQRGnKKY+zCUSxxNGidtnaZuYsd2mto52iIQUC6Jw8hABQXiuKldp3XtIsRtjtRxmhQkJOqkNgg7T0j7usf3zR4zszszu+9Yf/5A+2Znn/aD9pjzN4k0n1/63S+++L33tIKj78ev/+1f/PZdt+A0GfCsPvY733gXX1Ko/OiZOz+Cs/XCtrr1uZ/i0MLmJ1/681/AKbtgWf3mv+OgGND3ra/+Ik7bAW11y6s4IC5888s/i1MneK1+7yt9yBwfPvjMJ3D2GTxWt/4AOePFq3/3MxCwcFs9Gr8/lMX/3fXLUDBxWt31LPLEkL7P3AMLA4fVfS8hRzz50gPw0LGtPvcv2B1XnnoQJg6rJ17EzvjyhfvgQqye/Ap2xZnfvw02sHrsk9gRa26+gwe8ZfUJLR7lviB+8K+mDqw++E8kx52v/anpY1r912NIZNB3teNyYdFxHafG4jfMMqFh9TTv+utrXVM7KFl4DJu14U2copfvfydj1fcNJLnpbhyFbylEJu/rxXm6+dSdltXrGrP01zIYxxcq1Wdwpi7eec20uk97DglOri3EsQVMcQPrz/XgRw2r72s38dlB1xgcWdjM7sH5Onj7JcNK+xw+OoiJFFvrjrvTie9qb+GTTWosDip8FuKUHfzNo+kENl2swiFxYB/O2eb9N3SrP8EHm+NFOMJFceWokcOYe/LKoE6ctc3tutV3sE3oq8YBNsWzt59MGfu627ZMKzCzReZJO/n8vQntA2wTWpGdMHSd6//jYl05dhQE/a/ivAgvP824r2Yhe4blN7CD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' + + + +Update = lambda elem, value: window.Element(elem).Update(value) + +class BadInputError(Exception): + pass + + +class Player(): + + def __init__(self, name): + self.id = None + self.name = name + self.type = 'Human' + self.hand = Hand() + self.legalCards = [] + self.wildCards = [] + self.valueChangeCards = [] + self.zeroCards = [] + self.canSkip = False + self.canReverse = False + self.canDrawTwo = False + self.canDrawFour = False + self.canValueChange = False + self.drew = False + self.scrollMax = 0 + self.points = 0 + self.forceDraw = 0 + + def addCard(self, card): + self.drew = True + if self.forceDraw > 0: + self.forceDraw -= 1 + self.drew = False + self.hand.addCard(card) + + def beginTurn(self): + self.drew = False + + def didDraw(self): + return self.drew + + def getLegalCards(self, color, value, zeroChange=False): + self.canSkip = False + self.canReverse = False + self.canDrawTwo = False + self.canDrawFour = False + self.canValueChange = False + self.canZeroChange = False + self.legalCards = [] + self.wildCards = [] + self.valueChangeCards = [] + self.zeroCards = [] + plusFours = [] + for card in self.hand: + if card.isWild(): + if card.getValue() == '+4': + plusFours.append(card) + else: + self.wildCards.append(card) + elif zeroChange and card.isZero(): + self.canZero = True + self.zeroCards.append(card) + elif card.getColor() == color or card.getValue() == value: + if card.getColor() != color: + self.canValueChange = True + self.valueChangeCards.append(card) + if card.getValue() == "+2": + self.canDrawTwo = True + elif card.getValue() == 'R': + self.canReverse = True + elif card.getValue() == 'X': + self.canSkip = True + self.legalCards.append(card) + if len(self.legalCards) == 0 and len(plusFours) > 0: + self.canDrawFour = True + self.wildCards += plusFours + + def getValidCards(self): + return self.legalCards + + def getAllValidCards(self): + return self.legalCards + self.wildCards + self.zeroCards + + def hasLegalCard(self): + return len(self.legalCards) > 0 + + def addPoints(self, amount): + if (self.points + amount) <= 999999999999999999999: + self.points += amount + + def removeCard(self, index): + return self.hand.removeCard(index) + + def assignID(self, identity): + self.id = identity + + def getName(self): + return self.name + + def getID(self): + return self.id + + def getPoints(self): + return self.points + + def getType(self): + return self.type + + def getCardNum(self): + return len(self.hand) + + def getHand(self, scrollNum=0, hide=False): + return self.hand.show(scrollNum, hide) + + def getForceDraws(self): + return self.forceDraw + + def addForceDraw(self, num): + self.forceDraw += num + + def decreaseForceDraw(self): + self.forceDraw -= 1 + + def removeForceDraw(self): + self.forceDraw = 0 + + def checkCard(self, index): + return self.hand.getCard(int(index)) + + def discardHand(self): + self.hand.discard() + + def __str__(self): + return self.name + + def __repr__(self): + return '({},{})'.format(self.name, self.points) + + +class Hand(): + ''''deck' (Deck) : Card's Color (rgby) + 'numberOfCards' (int) : Card's Value (0-9, R, X, W, +2, +4)''' + + def __init__(self, deck=None, numberOfCards=0): + self.hand = [] + if deck != None: + self.draw(deck, numberOfCards) + + def __iter__(self): + return iter(self.hand) + + def __len__(self): + return len(self.hand) + + def __getitem__(self, item): + try: + return self.hand[item] + except: + return '' + + def addCard(self, card): + self.hand.append(card) + + def removeCard(self, index): + index = int(index) + if (0 <= index < len(self)): + return self.hand.pop(index) + + def discard(self): + self.hand = [] + + def show(self, scrollNum=0, hide=False): + return '' + + def getCard(self, index): + return self.hand[index] + + def indexCard(self, card): + return self.hand.index(card) + + +class GameSettings(): + playerIdentities = ('play1', 'play2', 'play3', 'play4') + computerNames = ('Watson', 'SkyNet', 'Hal', 'Metal Gear') + + def __init__(self): + self.playerStaging = [] # Where Player Objs Are Stored Before Game Starts + self.players = {} # ID : Player Obj + self.numPlayers = 0 + self.useColor = True + self.displayEffects = True + self.hideComputerHands = True + self.zeroChange = False + self.computerSimulation = False + self.mainMenuError = '' + self.computerSpeed = 'normal' + + def canAddPlayer(self): + return (self.numPlayers < 4) + + def canRemovePlayer(self): + return (self.numPlayers > 0) + + def canBegin(self): + return (self.numPlayers > 1) + + def addPlayer(self, player): + self.playerStaging.append(player) + self.numPlayers += 1 + + def removePlayer(self, number): + number -= 1 + del self.playerStaging[number] + self.numPlayers -= 1 + + def clearStaging(self): + self.numPlayers = 0 + self.playerStaging = [] + + def finalizePlayers(self): + self.players.clear() + identity = 0 + for player in self.playerStaging: + playerID = GameSettings.playerIdentities[identity] + player.assignID(playerID) + self.players[playerID] = player + identity += 1 + + def getPlayerNum(self): + return self.numPlayers + + def getComputerName(self): + complete = False + index = self.numPlayers + while not complete: + name = self.computerNames[index] + complete = True + for player in self.playerStaging: + if player.getName() == name: + index += 1 + if index >= len(self.computerNames): + index = 0 + complete = False + + return self.computerNames[index] + + def getRandomIdentity(self): + '''For Getting a Random Player for First Turn.''' + return random.choice(self.players.keys()) + + + def changeComputerSpeed(self): + return + + + +class Deck(): + ''''shuffle' (bool) : shuffle deck.''' + + colors = ('red', 'yellow', 'green', 'blue') + values = ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'X', 'R', '+2') + + def __init__(self, populate): + '''Initializes proper deck of 108 Uno Cards.''' + self.deck = [] + if populate: + self.populate(True) + + def __getitem__(self, index): + return self.deck[index] + + def populate(self, shuffle=True): + for color in self.colors: + for value in self.values: + self.deck.append(Card(color, value)) + if value != '0': + self.deck.append(Card(color, value)) + for i in range(4): + self.deck.append(Card('wild', '+4')) + self.deck.append(Card('wild', 'W')) + if shuffle: + self.shuffle() + + def __iter__(self): + return iter(self.deck) + + def __len__(self): + return len(self.deck) + + def draw(self): + return self.deck.pop() + + def place(self, card): + return self.deck.append(card) + + def insert(self, card): + self.deck.insert(0, card) + + def shuffle(self): + random.shuffle(self.deck) + + +class ComputerPlayer(Player): + + def __init__(self, name): + super().__init__(name) + self.type = 'Computer' + self.begun = False + self.colorsInHand = {'red': 0, 'blue': 0, 'green': 0, 'yellow': 0, 'wild': 0} + self.colorsOutHand = {} + self.currentColor = "" + + def addCard(self, card): + Player.addCard(self, card) + color = card.getColor() + self.colorsInHand[color] += 1 + + def indexCard(self, cardColor, cardValue): + for card in self.hand: + if card.getValue() == cardValue: + if cardValue in ('+4', 'W'): + return self.hand.indexCard(card) + else: + if card.getColor() == cardColor: + return self.hand.indexCard(card) + raise ValueError("Card Cannot Be Found") + + def think(self, match): + card = None + self.currentColor = match.currentColor + currentValue = match.currentValue + zeroChangeRule = match.zeroChange + twoPlayers = False + previousTurnID = match.getNextTurn(True) + nextTurnID = match.getNextTurn(False) + previousPlayer = match.getPlayer(previousTurnID) + # nextPlayer = match.getPlayer(nextTurnID) + if previousTurnID == nextTurnID: + twoPlayers = True + if self.canSkip == False and self.canReverse == True: + self.canSkip = True + self.canReverse = False + + self.getLegalCards(self.currentColor, currentValue, zeroChangeRule) + + ### DRAW CASE ### + + if len(self.legalCards) == 0 and len(self.wildCards) == 0: + return "d" + + else: + + ### NO LEGAL CARD, USE WILD CARD ### + + if len(self.legalCards) == 0: + + if zeroChangeRule and self.canZeroChange: + bestZeroColor = self.getBestColor(self.zeroCards) + card = self.getCardByColor(self.zeroCards, bestZeroColor) + + else: + + if self.canDrawFour: + card = self.getCardByValue(self.wildCards, "+4") + # print(card) + + else: + card = random.choice(self.wildCards) + + else: + + ### HAS LEGAL CARD ### + + if twoPlayers and self.canSkip: # Always play a skip card in a two player game + # print("Shed Skip Strategy") + card = self.getCardByValue(self.legalCards, "R", "X") + + if self.canReverse and previousPlayer.didDraw(): + # print("Reverse Strategy") + reverseCards = self.getAllCardsByValue(self.legalCards, "R") + for reverseCard in reverseCards: + if reverseCard.getColor() == self.currentColor: + card = reverseCard + + if self.canValueChange: + # Computer Can Value Change, However, Should it? + # Computer Checks to See if Value Change Color is Better Than Current + currentColorNum = self.colorsInHand[self.currentColor] + bestValueChangeColor = self.getBestColor(self.valueChangeCards) + if self.colorsInHand[bestValueChangeColor] > currentColorNum or len(self.valueChangeCards) == len( + self.legalCards): + card = self.getCardByColor(self.valueChangeCards, bestValueChangeColor) + + if card == None: + # print("Random Strategy") + card = random.choice(list(set(self.legalCards) - set(self.valueChangeCards))) + + color = card.getColor() + self.colorsInHand[color] -= 1 + return str(self.indexCard(card.getColor(), card.getValue())) + + def getWildColor(self): + maxKey = max(self.colorsInHand, key=self.colorsInHand.get) + if maxKey == 'wild': + return random.choice(('r', 'g', 'b', 'y')) + else: + return maxKey + + def getCardByValue(self, cardList, *values): + for card in cardList: + if card.getValue() in values: + return card + + def getAllCardsByValue(self, cardList, *values): + cards = [] + for card in cardList: + if card.getValue() in values: + cards.append(card) + return cards + + def getCardByColor(self, cardList, *colors): + for card in cardList: + if card.getColor() in colors: + return card + + def getBestColor(self, cardList): + bestColor = None + bestColorNum = 0 + for card in cardList: + color = card.getColor() + if self.colorsInHand[color] > bestColorNum: + bestColor = color + bestColorNum = self.colorsInHand[color] + return bestColor + + +class Card(): + ''' + 'suit' (string) : Card's Color (rgby) + 'rank' (string) : Card's Value (0-9, R, X, W, +2, +4) + ''' + # 11 = reverse, 12 = +2 + # 0-9, X, R, W, +2, +4 + # '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'X', 'R', '+2', '+4', 'W' + green_dict = {'0':g0, '1':g1, '2':g2, '3':g3, '4':g4, '5':g5, '6':g6, '7':g7, '8':g8, '9':g9, 'X':g10, 'R':g11, '+2':g12, '+4':plusfourgreen, 'W':wildgreen} + red_dict = {'0':r0, '1':r1, '2':r2, '3':r3, '4':r4, '5':r5, '6':r6, '7':r7, '8':r8, '9':r9, 'X':r10, 'R':r11, '+2':r12, '+4':plusfourred, 'W':wildred} + blue_dict = {'0':b0, '1':b1, '2':b2, '3':b3, '4':b4, '5':b5, '6':b6, '7':b7, '8':b8, '9':b9, 'X':b10, 'R':b11, '+2':b12, '+4':plusfourblue, 'W':wildblue} + yellow_dict = {'0':y0, '1':y1, '2':y2, '3':y3, '4':y4, '5':y5, '6':y6, '7':y7, '8':y8, '9':y9, 'X':y10, 'R':y11, '+2':y12, '+4':plusfouryellow, 'W':wildyellow} + green_cards = [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9, g10, g11, g12 ] + red_cards = [r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12 ] + blue_cards = [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12 ] + yellow_cards = [y0, y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, y11, y12 ] + wild_card = wild + + + colors = { + 'red': '\033[91m', + 'green': '\033[92m', + 'yellow': '\033[93m', + 'blue': '\033[94m', + 'purple': '\033[95m', + 'cyan': '\033[96m', + 'white': '\033[97m', + 'wild': '', + 'dwild': '', + 'dred': '\033[31m', + 'dgreen': '\033[32m', + 'dyellow': '\033[33m', + 'dblue': '\033[34m', + 'dpurple': '\033[35m', + 'dcyan': '\033[36m', + 'dwhite': '\033[37m', + } + + idMap = { + 'red': 'R', 'blue': 'B', 'green': 'G', 'yellow': 'Y', 'wild': 'W', + '0': '0', '1': '1', '2': '2', '3': '3', '4': '4', '5': '5', '6': '6', '7': '7', '8': '8', '9': '9', + '+2': '+', 'R': 'R', 'W': 'W', '+4': '$', 'X': 'X' + } + + + def __init__(self, color, value): + '''Initializes Uno Card w/ Color and Value.''' + self.wild = False # Is wild card? + self.zero = False + self.cardID = '{}{}'.format(self.idMap[color], self.idMap[value]) + self.setColor(color) + self.setValue(value) + self.setPoints(value) + + ############################################# + + ### -\/- Retrieve Card Information -\/- ### + + def __repr__(self): + return "{},{}".format(self.color, self.value) + + def getBigNum(self, reverse, reverseSeed=0): + '''Returns list of strings to draw card's value on the pile.''' + return '' + + def getColor(self): + '''Returns card's color.''' + return self.color + + def getColorCode(self): + '''Returns card's color code.''' + return self.colorCode + + def getValue(self): + '''Returns card's value.''' + return self.value + + def getPoints(self): + '''Returns card's point value.''' + return self.points + + def getRow(self, rowNum, hide=False): + return + + ############################################# + + ### -\/- Set Card Information -\/- ### + + def setColor(self, color): + '''Sets Card's color and escape code.''' + if color == 'blue': + self.color = 'blue' + self.colorCode = self.colors['blue'] + self.colorCodeDark = self.colors['dblue'] + elif color == 'red': + self.color = 'red' + self.colorCode = self.colors['red'] + self.colorCodeDark = self.colors['dred'] + elif color == 'yellow': + self.color = 'yellow' + self.colorCode = self.colors['yellow'] + self.colorCodeDark = self.colors['dyellow'] + elif color == 'green': + self.color = 'green' + self.colorCode = self.colors['green'] + self.colorCodeDark = self.colors['dgreen'] + elif color == 'wild': # No color modification + self.wild = True + self.color = 'wild' + self.colorCodeDark = self.colors['dwild'] + self.colorCode = self.colors['wild'] + + def setValue(self, value): + if value in ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'X', 'R', '+2', '+4', 'W'): + self.value = value + self.displaySpace = ' ' + if len(value) == 2: + self.displaySpace = '' + if value == '0': + self.zero = True + + def setPoints(self, value): + if value in ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'): + self.points = int(value) + elif value in ("W", "+4"): + self.points = 50 + else: + self.points = 20 + + ############################################# + + ### -\/- Wild Card Methods -\/- ### + + def changeColor(self, color): + '''Changes Card's Color, Intended for Wild Cards.''' + self.setColor(color) + + def isWild(self): + '''Returns if card is a wild card.''' + return self.wild + + def isZero(self): + return self.zero + + +class Match(): + elementsInit = { + ### Names (final) ### + 'P1Name': ' ', 'P2Name': ' ', 'P3Name': ' ', 'P4Name': ' ', + ### Card Values ### + 'P1Cards': ' ', 'P2Cards': ' ', 'P3Cards': ' ', 'P4Cards': ' ', + ### Turn Colors / Hand### + 'P1Turn': '', 'P2Turn': '', 'P3Turn': '', 'P4Turn': '', + 'HName': '\t\t', 'HVisual': '', 'Hand': '', + ### Deck ### + 'DNum': '', 'Deck': ['', '', '', '', '', '', '', '', ''], + 'PostDNum': '', + ### Pile ### + 'uHeader': '\t\t\t\t', 'uMiddle': ' ', 'uLower': ' ', + 'oHeader': '\t\t\t', + 'oMiddle': ['\t\t\t', '\t\t\t', '\t\t\t', '\t\t\t', '\t\t\t', '\t\t\t', '\t\t\t', '\t\t\t'], + ### Messages ### + 'Console': '', 'Error': '' + } + + speeds = {'slow': 2, 'normal': 1, 'fast': 0} + + window = None + + def __init__(self, gs): + ### Decks ### + self.deck = Deck(True) + self.pile = Deck(False) + + ### Player Information ### + self.players = gs.players + self.turnList = [] + self.handTitles = {'play1': '', 'play2': '', 'play3': '', 'play4': ''} + + ### Carry Information ### + self.displayEffects = gs.displayEffects + self.hideComputerHands = gs.hideComputerHands + self.zeroChange = gs.zeroChange + self.computerSpeed = self.speeds[gs.computerSpeed] + self.simulation = gs.computerSimulation + + ### Data ### + self.handPosition = 0 # For hand displays + self.drawAmount = 0 # Used for force draws + self.passes = 0 # Keep track of consecutive passes for emergency color change + self.passMax = 0 # Max passes before color change + self.turn = '' # Current turn + self.event = '' # Wild, Reverse, Skip, etc + self.wildColorChange = '' # Specifies color to change wild card to + self.currentColor = '' # Current color + self.currentValue = '' # Current value + self.winnerID = '' # ID of Player who Won + self.reverse = False # Is turn order reversed + self.turnComplete = False # Is turn complete + self.matchComplete = False # Is the Game over? + self.matchAbort = False # Did the match conclude without a winner? + self.forcedWild = False # Force change wild + + self.max_cards_displayed = 0 + self.previous_card = None + ### Initialize Names / Cards / Deck (Assuming New Game) ### + self.elements = dict(self.elementsInit) + + keyStringName = 'P{}Name' + keyStringCards = 'P{}Cards' + + for i in self.players: + self.elements[keyStringName.format(i[-1])] = self.players[i].getName() + ( + ' ' * (11 - len(self.players[i].getName()))) + self.elements[keyStringCards.format(i[-1])] = ' ' + ( + ' ' * (3 - len(str(self.players[i].getCardNum())))) + str( + self.players[i].getCardNum()) + ' Cards' + + self.elements['DNum'] = len(self.deck) + + if len(str(len(self.deck))) < 2: + self.elements['PostDNum'] = '\t' + + j = 8 + for i in range(int(math.ceil(len(self.deck) / 12))): + self.elements['Deck'][j] = '=' + j -= 1 + + for key in GameSettings.playerIdentities: + try: + self.buildHandString(key) + self.turnList += [key] + except KeyError: + pass + + self.passMax = len(self.turnList) + # ----------------------------------------- Create the GUI window ----------------------------------------- + sg.SetOptions(background_color='black', element_background_color='black', text_color='white', border_width=0) + Card = lambda image_data, key: sg.B('', image_data=image_data, image_subsample=4, image_size=(60, 80), button_color=('white', 'black'), key=key) + CardBig = lambda image_data: sg.B(button_text='', image_data=image_data, image_subsample=1, image_size=(200, 300), + button_color=('white', 'black'), pad=(0, 0)) + CardBig2 = lambda image_data: sg.Image(data=image_data, size=(100, 300), pad=(0, 0), background_color='black') + + Elem = lambda key: Match.window.Element(key) + T = lambda text, key=None, font='Helvetica 16', **kwargs: sg.T(text, key=key, font=font, **kwargs ) + + MyButton = lambda text, size=(6, 1), font='Helvetica 14', **kwargs: sg.B(text, size=size, font=font, button_color=('white', 'green3'), **kwargs) + OvalButton = lambda text, image_data, **kwargs: sg.B(text, image_data=image_data, font='Helvetica 14', button_color=('white', 'black'), **kwargs) + + col_players = [ + [OvalButton('Quit', greenbutton, key='_QUIT_', visible=False)], + [T('Player', '_P1_', text_color=yellow_color)], + [T('Cards', '_C1_', text_color=yellow_color)], + [T(' ' * 15)], + [T('Player', '_P2_', text_color=red_color)], + [T('Cards', '_C2_', text_color=red_color)], + [T(' ' * 15,'_S3_', visible=False,)], + [T('Player', '_P3_', visible=False)], + [T('Cards', '_C3_', visible=False)], + [T(' ' * 15, '_S4_', visible=False,)], + [T('Player', '_P4_', visible=False)], + [T('Cards', '_C4_', visible=False)],] + + col_cards_left = [ + [OvalButton('Draw', redbutton, key='_DRAW_')], + [T(' '), Card(back, '_DRAW_')], + [T('0 Cards Left', font='Helvetica 14', key='_CARDS_LEFT_')], + [OvalButton('Pass', bluebutton, key='_PASS_')],] + + NUM_COLS = 10 # how many cards shown across bottom in 1 row + NUM_ROWS = 4 + cards = [] + for j in range(NUM_ROWS): + cards.append([sg.T(' ' * 5,font=('Any 5'))] + [Card(None, j*NUM_COLS+i) for i in range(NUM_COLS)]) + + layout = [ + [sg.Column(col_cards_left), + sg.Graph((400, 360), (0, 300), (400, 0), key='_GRAPH_', ), + sg.Column(col_players)], + [T(' ')], + [T(' ')], + [sg.T('', justification='center', size=(55, 2), font='Helvetica 18', key='_MESSAGES_')], + [sg.T('', justification='center', size=(55, 2), font='Helvetica 18', key='_MESSAGES2_')], + ] + layout += cards + + Match.window = sg.Window('Uno', layout, + background_color='black', + use_default_focus=False, + disable_close=True, + finalize=True) + + def clearShell(self): + os.system('cls' if os.name == 'nt' else 'clear') + + def begin(self): + self.elements['Console'] = 'Beginning Game, Click Draw to Deal.' + self.drawScreen() + self.enterBreak() + self.eventDealCards() + self.turn = random.choice(self.turnList) + self.elements['Console'] = 'First turn will be {}. Click Draw'.format(self.players[self.turn].getName()) + self.drawScreen(True) + self.enterBreak() + self.placeCard() + self.elements['P{}Turn'.format(self.turn[-1])] = '\033[93m' + if self.event == 'wild': + self.eventWildCard() + elif self.event == 'reverse': + self.eventReverse() + + def end(self, gs): + if not self.matchAbort: + points = 0 + self.elements['P{}Turn'.format(self.turn[-1])] = '' + self.elements['Console'] = '{} Wins! Click Draw to Begin Point Tally'.format( + self.players[self.winnerID].getName()) + self.drawScreen() + self.enterBreak() + + for identity in self.turnList: + if identity != self.winnerID: + self.turn = identity + self.elements['HName'] = self.handTitles[self.turn] + self.elements['P{}Turn'.format(self.turn[-1])] = '\033[93m' + while self.players[identity].getCardNum() > 0: + card = self.players[identity].removeCard(0) + points += card.getPoints() + self.elements['Console'] = '{} Won {} Points!'.format(self.players[self.winnerID].getName(), + points) + + keyStringCards = 'P{}Cards' + self.elements[keyStringCards.format(identity[-1])] = ' ' + ( + ' ' * (3 - len(str(self.players[identity].getCardNum())))) + str( + self.players[identity].getCardNum()) + ' Cards' + self.players[identity].maxScroll = math.ceil((self.players[identity].getCardNum() / 10) - 1) + if self.handPosition > self.players[identity].maxScroll: + self.handPosition -= 1 + self.buildHandVisual(identity) + + if self.displayEffects and not self.simulation: + self.drawScreen() + time.sleep(.1) + self.elements['P{}Turn'.format(self.turn[-1])] = '' + + self.players[self.winnerID].addPoints(points) + self.elements['Console'] = '{} Won {} Points! Click Draw'.format(self.players[self.winnerID].getName(), + points) + self.drawScreen() + self.enterBreak() + + gs.clearStaging() + for identity in self.turnList: + self.players[identity].discardHand() + gs.addPlayer(self.players[identity]) + return gs + + def adjustCardAmount(self, playerID): + keyStringCards = 'P{}Cards' + self.elements[keyStringCards.format(playerID[-1])] = ' ' + ( + ' ' * (3 - len(str(self.players[playerID].getCardNum())))) + str( + self.players[playerID].getCardNum()) + ' Cards' + self.players[playerID].maxScroll = math.ceil((self.players[playerID].getCardNum() / 10) - 1) + if self.handPosition > self.players[playerID].maxScroll: + self.handPosition -= 1 + self.buildHandVisual(playerID) + + def buildHandString(self, playerID): + playerName = self.players[playerID].getName() + if len(playerName) < 9: + self.handTitles[playerID] = "{}'s Hand\t".format(self.players[playerID].getName()) + else: + self.handTitles[playerID] = "{}'s Hand".format(self.players[playerID].getName()) + + def buildHandVisual(self, playerID): + string = '[' + for i in range(self.players[playerID].maxScroll + 1): + if i == self.handPosition: + string += '|' + else: + string += '-' + string += ']' + self.elements['HVisual'] = string + + def checkInput(self, playerInput): + if playerInput == '': + return {'valid': False, 'entry': playerInput} + if playerInput.isnumeric(): + if int(playerInput) + (10 * self.handPosition) < self.players[self.turn].getCardNum(): + return {'valid': True, 'entry': str(int(playerInput) + (10 * self.handPosition)), 'type': 'card'} + else: + self.elements['Error'] = '{} is not a card.'.format(playerInput) + return {'valid': False, 'entry': playerInput} + else: + playerInput = playerInput.lower()[0] + if playerInput in ['<', '>', 'u', 'd', 'p', 'q', 's']: + return {'valid': True, 'entry': playerInput} + else: + self.elements['Error'] = '{} is not a valid selection.'.format(playerInput) + return {'valid': False, 'entry': playerInput} + + def checkColorInput(self, playerInput): + if playerInput == '': + return {'valid': False, 'entry': playerInput} + playerInput = str(playerInput).lower()[0] + if playerInput[0] == 'b': + return {'valid': True, 'entry': 'blue'} + elif playerInput[0] == 'r': + return {'valid': True, 'entry': 'red'} + elif playerInput[0] == 'g': + return {'valid': True, 'entry': 'green'} + elif playerInput[0] == 'y': + return {'valid': True, 'entry': 'yellow'} + return {'valid': False, 'entry': playerInput} + + def eventDealCards(self): + if self.displayEffects and not self.simulation: + self.elements['Console'] = 'Dealing Cards...' + for i in ('play1', 'play2', 'play3', 'play4'): + if i in self.players: + for j in range(7): + self.dealCard(i) + + def eventReverse(self): + if self.displayEffects and not self.simulation: + hide = False + if self.players[self.turn].getType() == "Computer": + hide = self.hideComputerHands + self.elements['Console'] = "Reverse Card Played! Reversing Turn Order.".format( + self.players[self.turn].getName()) + self.drawScreen(hide) + time.sleep(1) + for i in range(10): + cardBigNums = self.pile[0].getBigNum(self.reverse, i) + self.elements['oMiddle'] = cardBigNums + self.drawScreen(hide) + if self.displayEffects and not self.simulation: + time.sleep(.1) + cardBigNums = self.pile[0].getBigNum(self.reverse, 9) + self.elements['oMiddle'] = cardBigNums + self.reverse = not self.reverse + self.event = '' + + def eventSkip(self): + if self.displayEffects and not self.simulation: + hide = False + if self.players[self.turn].getType() == "Computer": + hide = self.hideComputerHands + self.elements['Console'] = "Skip Card Placed! Skipping {}'s Turn.".format(self.players[self.turn].getName()) + self.drawScreen(hide) + time.sleep(1) + for i in range(2): + self.elements['P{}Turn'.format(self.turn[-1])] = '\033[91m' + self.drawScreen(hide) + time.sleep(.3) + self.elements['P{}Turn'.format(self.turn[-1])] = '' + self.drawScreen(hide) + time.sleep(.3) + self.turnComplete = True + self.event = '' + + def eventWildCard(self): + hide = False + if not self.forcedWild: + if self.players[self.turn].getType() == 'Human': + self.elements['Console'] = 'Wild Card! Specifiy a Color' + self.elements['Error'] = 'Specifiy A Color' + self.drawScreen() + while True: + layout=[[sg.T('Wild Card! Specify a Color')], + [sg.Combo(('Blue', 'Red', 'Green', 'Yellow'))], + [sg.OK()]] + window = sg.Window('Wild Card', layout) + + event, values = window.read() + try: + playerInput = values[0].lower()[0] + except: + playerInput = ' ' + # playerInput = str(input("Color Change: ")) + checked = self.checkColorInput(playerInput) + if checked['valid']: + window.close() + break + else: + hide = self.hideComputerHands + checked = self.checkColorInput(self.players[self.turn].getWildColor()) + self.wildColorChange = checked['entry'] + else: + self.wildColorChange = self.checkColorInput(random.choice(('r', 'b', 'g', 'y')))['entry'] + self.forcedWild = False + self.currentColor = self.wildColorChange + self.elements['Error'] = "" + if self.displayEffects and not self.simulation: + self.elements['Console'] = 'Wild Card! Changing Color.' + seed = 1 + for i in range(10): + if seed > 4: + seed = 1 + self.drawScreen(hide, wildSeed=seed) + time.sleep(.1) + seed += 1 + self.pile[0].changeColor(self.wildColorChange) + self.wildColorChange = '' + cardBigNums = self.pile[0].getBigNum(self.reverse) + self.elements['oHeader'] = '{}\u2666\u2666\u2666=========\u2666\u2666\u2666\033[0m\t'.format( + self.pile[0].getColorCode()) + self.elements['oMiddle'] = cardBigNums + self.event = '' + + def eventDraw(self): + self.players[self.turn].addForceDraw(self.drawAmount) + self.drawAmount = 0 + self.event = '' + + def dealCard(self, playerID): + + card = self.deck.draw() + self.players[playerID].addCard(card) + + ### Adjust Hand Visual ### + self.players[playerID].maxScroll = math.ceil((self.players[playerID].getCardNum() / 10) - 1) + self.handPosition = self.players[playerID].maxScroll + self.buildHandVisual(playerID) + + ### Adjust Player Tile ### + keyStringCards = 'P{}Cards' + self.elements[keyStringCards.format(playerID[-1])] = ' ' + ( + ' ' * (3 - len(str(self.players[playerID].getCardNum())))) + str( + self.players[playerID].getCardNum()) + ' Cards' + + ### Adjust Deck ### + self.elements['DNum'] = len(self.deck) + if len(str(len(self.deck))) < 2: + self.elements['PostDNum'] = '\t' + j = 8 + self.elements['Deck'] = [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '] + for i in range(math.ceil(len(self.deck) / 12)): + self.elements['Deck'][j] = '=' + j -= 1 + + def placeCard(self, card=None): + if card == None: + ### Used At Beginning For First Card ### + card = self.deck.draw() + self.elements['DNum'] = len(self.deck) + + cardColor = card.getColorCode() + cardBigNums = card.getBigNum(self.reverse) + + self.currentColor = card.getColor() + self.currentValue = card.getValue() + + self.pile.insert(card) + self.elements['oHeader'] = '{}\u2666\u2666\u2666=========\u2666\u2666\u2666\033[0m\t'.format(cardColor) + self.elements['oMiddle'] = cardBigNums + + if len(self.pile) > 1: + previousCard = self.pile[1] + previousCardColor = previousCard.getColorCode() + self.elements['uHeader'] = '{} \u2666\u2666\u2666=========\u2666\u2666\u2666\033[0m\t\t'.format( + previousCardColor) + self.elements['uMiddle'] = '{}| |\033[0m'.format(previousCardColor) + self.elements['uLower'] = '{}\u2666\u2666\u2666\033[0m'.format(previousCardColor) + + if self.currentColor == 'wild': + self.event = 'wild' + + if self.currentValue == 'X': + self.event = 'skip' + elif self.currentValue == 'R': + if len(self.players) > 2: + self.event = 'reverse' + else: + self.event = 'skip' + elif self.currentValue == '+4': + self.drawAmount = 4 + elif self.currentValue == '+2': + self.drawAmount = 2 + self.passes = 0 + + def extractCard(self, playerID, index): + card = self.players[playerID].removeCard(index) + if self.players[playerID].getCardNum() == 0: + self.matchComplete = True + self.winnerID = self.turn + self.adjustCardAmount(playerID) + return card + + def enterBreak(self): + if not self.simulation: + while True: + if Match.window is None: + break + event, values = Match.window.read() + if event == '_DRAW_': + break + if event == '_QUIT_': + if sg.PopupYesNo('Do you really want to quit?') == 'Yes': + self.matchAbort = True + self.matchComplete = True + + def nextTurn(self): + self.turnComplete = False + self.handPosition = 0 + turnType = self.players[self.turn].getType() + self.players[self.turn].beginTurn() + ### Prepare Hand Visuals ### + + self.elements['HName'] = self.handTitles[self.turn] + self.buildHandVisual(self.turn) + + if self.event == 'skip': + self.eventSkip() + elif self.drawAmount > 0: + self.eventDraw() + #-------------- Main GUI event loop --------------- + while not self.turnComplete: + if turnType == 'Human': + self.players[self.turn].getLegalCards(self.currentColor, self.currentValue, self.zeroChange) + if len(self.deck) > 0: + self.elements['Console'] = 'Select a card or Draw' + else: + self.players[self.turn].removeForceDraw() + self.elements['Console'] = 'Select a card, Draw, or Pass' + if self.players[self.turn].getForceDraws() > 0: + self.elements['Error'] = 'Draw Card Played! Draw {} cards.'.format( + self.players[self.turn].getForceDraws()) + self.drawScreen() + ## GUI INPUT + event, values = Match.window.read() + + playerInput = str(event) + if event == '_DRAW_': + playerInput = 'd' + elif event == '_PASS_': + playerInput = 's' + elif event == '_QUIT_': + if sg.PopupYesNo('Do you really want to quit?') == 'Yes': + self.matchAbort = True + self.matchComplete = True + break + + if playerInput == '<': + self.handPosition -= 1 + if self.handPosition == -1: + self.handPosition = self.players[self.turn].maxScroll + self.buildHandVisual(self.turn) + elif playerInput == '>': + self.handPosition += 1 + if self.handPosition > self.players[self.turn].maxScroll: + self.handPosition = 0 + self.buildHandVisual(self.turn) + elif playerInput == 'd': + if len(self.deck) > 0: + self.elements['Error'] = '' + self.dealCard(self.turn) + else: + self.elements['Error'] = "Cannot Draw. Deck is Empty" + elif playerInput == 'p': + pauseOutput = self.pauseScreen() + if pauseOutput == 'quit': + self.matchComplete = True + self.turnComplete = True + self.winnerID = 'play1' + self.matchAbort = True + elif playerInput == 's': + if len(self.deck) > 0: + self.elements['Error'] = "Cannot pass until Deck is empty." + elif len(self.players[self.turn].getAllValidCards()) > 0: + self.elements['Error'] = "Cannot pass while having playable cards." + else: + self.turnComplete = True + self.passes += 1 + if self.passes == self.passMax: + self.forcedWild = True + self.event = 'wild' + self.passes = 0 + elif playerInput.isnumeric(): + if self.players[self.turn].getForceDraws() == 0: + cardCheck = self.players[self.turn].checkCard(playerInput) + if cardCheck in self.players[self.turn].getAllValidCards(): + card = self.extractCard(self.turn, playerInput) + self.placeCard(card) + self.elements['Error'] = "" + self.turnComplete = True + else: + self.elements['Error'] = "Card Doesn't Match The Color {} or Value {}!".format( + self.currentColor, self.currentValue) + else: + pass + + elif turnType == 'Computer': + event, values = Match.window.read(timeout=0) + if event == '_QUIT_': + if sg.PopupYesNo('Do you really want to quit?') == 'Yes': + self.matchAbort = True + self.matchComplete = True + break + + self.elements['Console'] = '{}\'s Turn'.format(self.players[self.turn].getName()) + self.drawScreen(self.hideComputerHands) + if not self.simulation: + time.sleep(self.computerSpeed) + # str(input()) + while (True): + if self.displayEffects and not self.simulation: + time.sleep(.2) + if self.players[self.turn].getForceDraws() > 0 and len(self.deck) > 0: + cardIndex = 'd' + else: + cardIndex = self.players[self.turn].think(self) + if cardIndex.isnumeric(): + card = self.extractCard(self.turn, int(cardIndex)) + if card.getColor() != self.currentColor: + self.resetDrawBool() + self.placeCard(card) + self.turnComplete = True + break + else: + if cardIndex == 'd': + if len(self.deck) > 0: + self.dealCard(self.turn) + self.drawScreen(self.hideComputerHands) + else: + self.turnComplete = True + self.players[self.turn].removeForceDraw() + self.passes += 1 + if self.passes == self.passMax: + self.forcedWild = True + self.event = 'wild' + self.passes = 0 + break + + ### DECODE INPUT ### + if self.event == 'reverse': + self.eventReverse() + elif self.event == 'wild': + self.eventWildCard() + + # Clear Current Turn + self.elements['P{}Turn'.format(self.turn[-1])] = '' + # Prepare Next Turn + self.turn = self.getNextTurn() + self.elements['P{}Turn'.format(self.turn[-1])] = '\033[93m' + + # --------------------------------------- drawScreen --------------------------------------- + def drawScreen(self, hide=False, wildSeed=0): + if Match.window is None: + return + def get_card_graphic(color, value): + dict = Card.red_dict + if color == 'red': + dict = Card.red_dict + if color == 'blue': + dict = Card.blue_dict + if color == 'green': + dict = Card.green_dict + if color == 'yellow': + dict = Card.yellow_dict + card_graphic = dict[value] if value != '' else Card.wild_card + return card_graphic + + Update = lambda key, value, **kwargs: Match.window.Element(key).Update(value, **kwargs) + elem = lambda key: self.elements[key] + if self.simulation: + return + + currentTurn = self.turn + if currentTurn == '': + currentTurn = self.turnList[-1] + hide = True + + Update('_MESSAGES_', elem('Console')) + Update('_MESSAGES2_', elem('Error')) + Update('_P1_', elem('P1Name')) + Update('_C1_', elem('P1Cards')) + Update('_P2_', elem('P2Name')) + Update('_C2_', elem('P2Cards')) + if elem('P3Name') != ' ': + Update('_P3_', elem('P3Name'), visible=True) + Update('_C3_', elem('P3Cards'), visible=True) + Update('_S3_', None, visible=True) + if elem('P4Name') != ' ': + Update('_P4_', elem('P4Name'), visible=True) + Update('_C4_', elem('P4Cards'), visible=True) + Update('_S4_',None, visible=True) + Update('_CARDS_LEFT_', '{} Cards Left'.format(elem('DNum'))) + # hand = self.players[currentTurn].hand + hand = self.players[currentTurn].hand.hand + i=0 + for i, card in enumerate(hand): + if card.value == 'W': + card_graphic = wild + elif card.value == '+4': + card_graphic = plusfour + else: + card_graphic = get_card_graphic(card.color, card.value) + if hide: + card_graphic = back + + Update(i, '', image_data=card_graphic, image_subsample=4, image_size=(60, 80), visible=True) + else: + for x in range(i+1, self.max_cards_displayed+1): + Update(x, '', image_data=blank, image_subsample=4, image_size=(60, 80), visible=True) + self.max_cards_displayed = max(i, self.max_cards_displayed) + + card_graphic = get_card_graphic(self.currentColor, self.currentValue) + + if self.previous_card is not None: + Match.window['_GRAPH_'].draw_image(data=self.previous_card, location=(0,0)) + Match.window['_GRAPH_'].draw_image(data=card_graphic, location=(100,40)) + + self.previous_card = card_graphic + + Match.window.Refresh() + + return '' + + def pauseScreen(self): + return + + def isComplete(self): + return self.matchComplete + + def next(self): + self.turn = self.getNextTurn() + + def getNextTurn(self, forceReverse=False): + if forceReverse: + reverse = not self.reverse + else: + reverse = self.reverse + currentIndex = self.turnList.index(self.turn) + if not reverse: + if (currentIndex + 1) == len(self.turnList): + return self.turnList[0] + else: + return self.turnList[currentIndex + 1] + else: + if currentIndex == 0: + return self.turnList[len(self.turnList) - 1] + else: + return self.turnList[currentIndex - 1] + + def getPlayer(self, playerID): + return self.players[playerID] + + def resetDrawBool(self): + for identity in self.players: + self.players[identity].drew = False + +def clearShell(): + os.system('cls' if os.name == 'nt' else 'clear') + +def mainMenu(): + gs = GameSettings() + + PLAYER_TYPE_HUMAN = 'HUMAN' + PLAYER_TYPE_COMPUTER = 'COMPUTER' + computer_names = ('Watson', 'SkyNet', 'Hal', 'Metal Gear') + layout = [ + [sg.B('1 - No Player', size=(20,5), key=0, pad=(1,1)), + sg.B('2 - No Player', size=(20, 5), key=1, pad=(1,1), disabled=True)], + [sg.B('3 - No Player', size=(20, 5), key=2, pad=(1,1), disabled=True), + sg.B('4 - No Player', size=(20, 5), key=3, pad=(1,1), disabled=True)], + [sg.T('Enter player 1 (none) name', key='_TXT_'), sg.I(key='_IN_', do_not_clear=True, size=(22,1)), sg.B('Set name')], + [sg.B('Begin'), sg.B('Settings')],] + + Elem = lambda key: window.Element(key) + + button_states = [0] * 4 + player_names = [''] * 4 + player_types = [None] * 4 + + window = sg.Window('Uno Setup', border_depth=0, layout=layout) + + current_player = 0 + while True: # Event Loop + event, values = window.read() + # print(event, values) + if event == sg.WIN_CLOSED or event == 'Exit': + break + if event == 'Begin': + window.Hide() + gs.finalizePlayers() + # ---------------------- START THE MATCH ---------------------- + gs = playMatch(gs) + for i, id in enumerate(gs.players): + player = gs.players[id] + window.Element(i).Update('{} - {}\n{} points'.format(i+1, player.name, player.points)) + window.UnHide() + window.Refresh() + elif event == 'Settings': + layout2 = [[sg.Checkbox('Hide computer hands', key='_HIDE_', default=True)], + [sg.T('Computer speed')], + [sg.Radio('Fast', 1, key='_FAST_')], + [sg.Radio('Normal', 1, key='_NORMAL_', default=True)], + [sg.Radio('Slow', 1, key='_SLOW_')], + [sg.OK(), sg.Cancel()] + ] + win2 = sg.Window('Settings').Layout(layout2) + ev, vals = win2.read() + win2.Close() + if ev == 'OK': + if vals['_NORMAL_']: + gs.computerspeed = 'normal' + if vals['_FAST_']: + gs.computerspeed = 'slow' + if vals['_SLOW_']: + gs.computerspeed = 'slow' + gs.hideComputerHands = vals['_HIDE_'] + elif event == 'Set name': + if values['_IN_'] in player_names: + sg.Popup('Duplicate - Cannot set to same as other players name') + else: + Elem(current_player).Update(str(current_player+1) + ' - '+values['_IN_']) + player_names[current_player] = values['_IN_'] + Elem(current_player + (current_player < 3)).Update(disabled=False) + if player_types[current_player] == PLAYER_TYPE_HUMAN: + addPlayer(gs, values['_IN_']) + else: + addComputer(gs, values['_IN_']) + elif 0 <= event <= 3: + current_player = event + state = button_states[event] = button_states[event]+1 if button_states[event] < 2 else 0 + Elem('_TXT_').Update('Enter Player %s (%s) Name'%(str(current_player+1), ('human', 'computer', 'none')[state-1])) + if state == 1: + Elem('_IN_').SetFocus() + Elem('_IN_').Update('Player name', select=True) + Elem(event).Update(str(event+1) +' - Player') + player_types[event] = PLAYER_TYPE_HUMAN + elif state == 2: + Elem('_IN_').SetFocus() + Elem('_IN_').Update(computer_names[event], select=True) + Elem(event).Update(str(event+1) + ' - ' + computer_names[event]) + player_types[event] = PLAYER_TYPE_COMPUTER + elif state == 0: + Elem(event).Update(str(event+1) +' - No Player') + Elem('_IN_').SetFocus() + Elem('_IN_').Update('', select=True) + for i in range(event): + pass + player_types[event] = None + player_names[event] = '' + for i in range(event+1,4): + Elem(i).Update(text='%s - No player'%i, disabled=True) + player_names[i] = '' + try: + gs.removePlayer(i) + except: + pass + window.close() + return player_names + + +def playMatch(gs): + m = Match(gs) + m.begin() + Match.window['_QUIT_'].Update(visible=True) + while (not m.isComplete()): + m.nextTurn() + gs = m.end(gs) + Match.window.close() + Match.window = None + return gs + + +def addPlayer(gs, name): + p = Player(name) + gs.addPlayer(p) + gs.mainMenuError = "" + + return gs + + +def addComputer(gs, name): + c = ComputerPlayer(name) + gs.addPlayer(c) + + return gs + + + +if __name__ == "__main__": + mainMenu() + +#-------------------------------------------------------------------------------# +# Works on Python 3 # +# Uno card game using a GUI interface provided by PySimpleGUI # +# Based on this excellent text based version: # +# http://code.activestate.com/recipes/580811-uno-text-based/ # +# Contains all of the graphics inside the source file as base64 images # +# Cards were obtained from Wikipedia # +# https://en.wikipedia.org/wiki/Uno_(card_game) # +# Up to 4 players... any number can be computer controlled # +# Still needs some work but close enough for fun # +#-------------------------------------------------------------------------------# + +yellow_color = '#FFAA00' +blue_color = '#5555FF' +red_color = '#FF5555' +green_color = '#55AA55' + + + +wildblue = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAABQUFCQkJDQ0NERERFRUVGRkZHR0dICAgJSUlKysrMTExNTU1OTk5PT09QUFBRUVFSUlJTU1NUVFRVVVVWlpaXV1dYWFhZWVlaWlpbm5ucXFxdXV1eXl5fX19R13JWlvZWVrcS13gU07kVE3jUE/sW07gU1DtU1frU1ftVFDuUVzsXlnvUlL3UlL5VVX+U1rwXFz1Wlr9TXTDU2ffVGvcVW3aVH3AWnXWXHbWXXTYXnnVUmPjUWLlUmTiVmHlXWLjak7PbE/PZV/VY13aZF3aal/Zal/dYFHmY13tbV7obl/vYVfzY1jzZ1rxalzwaWPaYHHaYX3UZH/Ud2bCdmbEc2TOemnJcmPQeGPcaGHoZWL6amH1a2f5amr/bm7/cGflcmLudmXtc2rjdWzieW/hemntfWztfHLhcnL/e3v/W4TAYorBZo7CaITUbIjUbJLEcY3VdJjHepzJd5LWfJbXf6HMgGq7hWTdiW/Xi2vejW/fiHbKjXvKgG/tgnLuhnfvg3nhi33wk3Xglnnhl3zimX/kgYGBhYWFiYmJjIyMkJCQlZWVmZmZnZ2doaGhoaOlpaWloqWqqampra2tsbGxtbW1urq6vLy8gZnZhp7alYTNmIjPmorQm4zRnY/Un5HVi4LjhIT/jYHxlY3om4HlnIPmnofokoj0lo31k5P/mZP4mJj/haXOjaLdi6nRkazUmrLYlqnhoJLWopXYpJfaoZjYpprcpJzYp5zdoo7qpJLspZXtoJvyqJrwq5/zoLbdq6LjrqbooaH/pKT/q6L1rab3qqr/r6n5rq7/oLDlp7XpprrgqrzisKnqs63vtK/xsa37tbHzt7T3srL+ubf6urr+scHmucXrvsjv3Zi53py8wcHBxcXFysrKzc3N0dHR1dXV2NjY3d3dw8P/wcrxycn/y9D20NL60dH/1dX+3Nz+3unt4eHh5eXl6enp7e3t5eX+5+306eTz6ef46en+7O/57Oz/8fHx9fX18vL+9PT++fn5+Pj+/v7+AAAAP81AhwAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABapSURBVHhe3Z15YB3HXcff02mrPmRZdnxIogVaDkMEjhPSug6Uoy03xPQAQwPldJJSk0ALuNBCaSzbcozxIZUAaQMhHA1JablCcNOkdh2gARfVdsCWLKk5cJD0FioqUWXN7zfz293Z672Z2d97+zafP7y23r7VfLyz353dnZ0pXa2B21RQoWpRw4o21lxQ2apQ1Yq20pxQGROpYkXfbnKosGFSrehLBYAKrJJiRV8oBlRmhUQrWrswULEDEqxo1UJBRfeIWdFqRYNKT0StaKXiQeWXRKxolSJCBoKwFa1QTMgBCVnRx0WFLADVij4sLKQBKFb0WYEhEdWKPikyZKJY0Qdxpi+NjjQVo5emqGgxyMW3oh9HmB7obis1Ia2r+yepiGHIpprVyBraSFPSfZyKqUI2ZEU/VJnroa83Ld0zVFQFqSOt6Ecqx5qy6oVpO0yFDRA6qVaH6ItNzgEqboDwEVb0A4WCSCVoVbE6Tt+pTrm9c1nu9fQIFdkn1Wqunb6SRtuagaMTFbnusbX0w3xojUZGqlUvfSOZl+2boPWIyVX0SS6soVL4pFhdpPWTaOtLOv1tpk9z4QQVwoOs6F8+6buqc3hRruKMnXn0j3/r3//6iSeviH/nqdUtSqCQaDVDa8doO7iEnztjp+76/kHkdfjHLf+JP8yzEsaahUlW+2nlKBtEPDhnflYYIa+UizH48WVaKQ/6sVwqSVbJmdY5ip85n/huaYK8ipaDuLdyTMJ4FQQr+qtPJ60cogd3lHNKcRocvJaWg7vhs6O0Yg60iWIrJFjN0bohBuADZ+xnyELyFbQEIDISv9YgYgdW3GqSVlUoYyvS+RNSIN5ISwSPrFZa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' +wildgreen = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAABQUFCQkJDQ0NERERFRUVGRkZHR0dICAgJSUlKysrMTExNTU1OTk5PT09QUFBRUVFSUlJTU1NUVFRVVVVWlpaXV1dYWFhZWVlaWlpbm5ucXFxdXV1eXl5fX19Ap0AC5UADp8LD5kUCpwYCZ4cFZoAGpcUCp4gDpksEZImEZgzAKMABKQNAKoABKkABasEBqwGCqYPDqkACqwKC6YWCKAZFaYKEqoCG6EAHKALGaoAHKwKFKQUEa8QGKMQH6YRHa8RE7ASGbAUGrIaE6chFackHaguJ5oNL5sANJYRIKcMIa0KLKoAKa8PIqcTJqcXK6gcLrATK7IZMaoAOaQYMbEVN7IaO7MeIaEiIaM6IaoyJao2La4+I7UjKbcpLLgsMakgN6smOqwpPa0sMroyNrs2O707K6hBL6RQNqNINqZWOKdYPKpbP6tdNLBETbIZR6olRKouSaEoQa8wRLcnSLgsRLAzRbE1TrU3SrM6VKY1Wac5XKs+VLQgWrcnX7gtUbs2VL06aaoAYroyab08Sp9yQq1fQLZPQb9BS7tXX6xCUbdDVLlHV7tLVb9fXL5RSrBlUbRqVbdtXbtyYq5FZ7JMabNPbb9Ca7VSbrhXcrhNYL10db1hRcBFTcNNVMVUWMdYXchdWsNiYMJJb8FFYsJZc8JLd8VSesdYfMhbZsZgY8pja81raMF5cctkecFofcVvcsd/cM9wddB1fNJ8c5+YeMuCrKlxgMpihM1sgcl1gsx4hc99idB1jdN9gYGBhYWFiYmJjIyMkJCQlZWVmZmZnZ2doaGhpaWlqampra2tsbGxtbW1urq6vLy8gNCFgtWCh9GBhdOIitSFiNeIi9iLjNiMkdaGk9iLk9qTl9qSmNyYo+CjquKqsuWyuOe4vOi8wcHBxcXFysrKzc3N0dHR1dXV2NjY3d3dwurCzevHy+3L0e/R1Oza3u/S1vDW2/Lb3vPe4eHh5eXl6enp7e3t5PXk6ffp7Pjs8fHx9fX19Pv0+fn5+fz5/v7+AAAAeLMFJAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABaXSURBVHhe3Z15fBznWcd3ddqqbcmyfEviKlfJQkCBQIoB1dz3faXCHMGUlFLuI9yEpuXoQSENxbH9CUc46pCkNgU3DpJtOZZlS7HjopI4dmtLlmQKZCXtupaqvuZ53nlm5p1r931nnt3ZyfcPr6yd2X2/et/5zTsz78ybu10F0VBQoapRxYo+rLGgslWgohV9SmNCZQylghWt3eBQYb1EWtFKGYAKrBJhRStkAyqzQqgVLZ0ZqNguIVa0aKagotsErGixrEGlJ/xWtFD2oPJb+KxokSxCBhKvFS2QTcgB8VjR21mFLADVit7MLKQBKFb0XoYhEdWK3skyZKJY0RtB5q9NTjQUk9fmqGgByMWxol/7mO/vask1IM2dfbNURC9kU8lqYiN9SEPSdZaKqUI2ZEW/VCl10+oNS9ciFVXB0rGs6Fcq4w3Z9Ly0nKbCukidSKtTtGKDc4KK6yJ9pBX9QiEjUiFaFazO0jqVybe2r0m9nY5RkR0irUqttEoULRv7z8yUrWXHN9Ev06HZHxmRVj20RjivGZ6h5YjZDfROKmykUjhEWF2l5cNo6Q3b/e2kd1PhHBXChqzofw7RVdU+umItUpy68ORf/eW//ez9b9k3VYT/p6nVZRXJJdRqkZYO0HJyFd8vTj3z8HcWkM+T/74dtdJshIFuYZjVcVrYzzYZD8ULPyVdkNdaL/eC1nVaKA36ZLEVwqzCM619Et8rfvi7LBPks+lV1laKSRhsgmBFPzq008IeurGiis8oTk5VAVNCnKEFU6DFKrdLiFWJlvXQD28Up36SJCw+h16BfRGr1YnAhhW0mqVFFfLYiyy+mxSIz6JX5CF4v5kWToFrsuAK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' +wildred = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAABQUFCQkJDQ0NERERFRUVGRkZHR0dICAgJSUlKysrMTExNTU1OTk5PT09QUFBRUVFSUlJTU1NUVFRVVVVWlpaXV1dYWFhZWVlaWlpbm5ucXFxdXV1eXl5fX19tEx6tEx8y19C3ltJ3lRx3VR0w3RNwH1U32dT2m1V3GtU1nVa1nZc1Xle2HFYxHF32Gx01H1h1H9k415D5V5E4FxK5FpJ7VpJ4lBd5lBZ7VFY7FJc7FxR9lFS91dT9Vdf81tT+VJT/VRU+llS/VhS/l1T+Fpf/1tb/l1e71Ri7ltr8lZh8lpl8F1r+Fpg42NS4mRS5WJR4W5b/mFT/mNU/mdX/mpZ/mxa/m9d/nZU/nJf/ntZ4mBm5WN87WR17Wd47Wt8/2Ji/2ho/21t/nVn/nhl/ntp/3Jy/nZ2/3t73WyC2myP3mqK3m6O3nCP3HCT3HKU3XWW3nqZ6m2B7nKC4HSS4niU432Y8HuJq7F7wIRbwYtjxJJrx5h0yZ161IRo1Ihs1Y1x1pJ315Z8zKF//oBe5YFn5YNq94Nk/oNj/oZm/ohp/ops/oxv/oFw/oRz/o9z/o1+/pF1/pJ4/pV8gYGBhYWFiYmJjIyMkJCQlZWVmZmZnZ2dsbOBoaGhpaWlqampra2tsbGxtbW1urq6vLy82ZmB2p6GzqWF0amL3aKN1KyR2LKa3bag5YOb8oOP/4KC/4yM9YyV/pqE/pyH/5CQ/5WV/puT/5ub/p2d44Wg5Ymi6o6h6ZGm7ZWl7Jiq8Zyp4amW/qCM/qOS/qWV/qaY/qmc5bCg4Lqm4ryq6bWn9KGr/qOj/q2j+Kit+qyv/6mp/62t+Kyy/rGq/rSv+rG0/rKy/ra1/rm5/76+5sGx68W578i+wcHBxcXFysrKzc3N0dHR1dXV2NjY3d3d8crB/8LC/8XF/8vL9tDL/dTT/9nZ/tzc7ene/uTd4eHh5eXl6enp7e3t9O3n/+Pj/ubm+e/s/ujo/+3t8fHx9fX1/vHx//X1+fn5//n5/v7+AAAA1zju8QAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABZTSURBVHhe3Z17YBzHWcDv9LRV2ZZl2ZatB7QQnKQGYmhLqXnkgPJoSuMChfJoEwqkLaWFAgGStJS2vAqFQCvZloJfkUpCGkh4BBfSECgJFNyEUvAztmRJcRzFIOtQOOthj/t9s9++d+9mZr+73c3vD691t7uan2bmm9nd2ZnC1RqITEGJqkUNKzpZtqC0VaGqFZ0lm1AaI6liRUdnHEqsn1grOigHUIK9xFjRAfmA0uwh0or2zg2UbJcIK9o1V1DSbUJWtFveoNQTQSvaKX9Q+i0CVrRLHiEDid+Kdsgn5ID4rOjrvEIWgNeKvswtpAF4rOi7HEMiXiv6Js+QiceKvggzc2Z8LFOMn5mmpIUgF8eKPg4wM9jVUsggzesGpiiJfsimmtXYejpJJuk6RMn0QjZkRR96me+mwzNL1xwl1YOlY1nRR14OZrLo+WnZR4l1kTqxVqN0YMbZQ8l1kT7Sij7wkBOpCK0qVofomOoUW9tXpV5O91OSHWKt5lvpkDha1g8emCxb+x7cQB+mQ3MwZMRa9dAR0bxsaJL2I6bW0jepsJ5S4RBjdZr2j6KlP6r566NvU+FeSoQNWdFPDvFZ1T6yRPuIlQvPHfvMu9/3/s9W8Kc0tbpkejxEWs3R3iFa9l629rh04pF3lIDX4j9vkF5pFsJQtzDKajftHKTXCg8rx9+FMsCNtP1F0DpLO6XBgEyXhyir6JjWPi6/rBz+bnIplV5H29JnY49qCOEiCFb0X4d22tlHt8yoSx6n0jfTFgohZNYB2jEFWmSyPURYzdO+PgblV8c8Tj4gsyIPaxChihW2mqJdPRRlL3LBrk8WMlQQ74evm2nnFDiDyfNSCBXA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' +wildyellow = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAABQUFCQkJDQ0NERERFRUVGRkZHR0dICAgJSUlKysrMTExNTU1OTk5PT09QUFBRUVFSUlJTU1NUVFRVVVVWlpaXV1dYWFhZWVlaWlpbm5ucXFxdXV1eXl5fX1915U1xa4Ny6oAw68SwrEVwLMe364N3K8Q1rMc1rQf2rAT2LEY2rMdz6Q3wLYnwLgtyLgtwbozw7062ag31LUj1Lgr1Loy1Lw41b8/5pgW5pwW5ZoZ554e6pUW7J8R858L5p4i4qEA56IA5asG4KwK6KIA6aQA66oD5aYd4K8Q47AU9KYA9aEI9KwI+qYD+KYF/KYD+6YI/qYK/qYO/qoA/6wJ86YW8qMa/qYR/qcX/aQa/q4Q/qgc/7AU/7Md6aEl76ck7agu7aoy7ao27a4+5bUi8Kch/qEo/qkh/qsm/qwp/q0s/qUx/qc2/q8w/qs+/7Uj/7cp/7gr/rAz/rE1/rM6/7oz/749xL9C3qNI3qVK3qRQ3qZW3qdY4Kpb4Ktd4q1f7rBE/qxC/q5F/q9I8LZP/rdD/rJN/rlH/rtL8rtX9L9f/rVS/rhX/r5R47Bl5bRq57dt6bty6710/qpp/qlx/qt2/r1hxcBEx8JKycVSzMdZ1sFH18RO2cZV2shczsphycFz0sxq3Mlg3sxo1c9z2NJ6/8BD/8NM/8VU/sJZ4c9x7cF55dN998Ni/sZg/sFo/sVv/8pj/81r8cd//sl1/89w/sx4/s99/9By/9J7gYGBhYWFiYmJjIyMkJCQlZWVmZmZnZ2doaGhpaWlqampra2tsbGxtbW1urq6vLy83dWC4NeJ4tiO6daF5tyW9MuC+NCF/tGB/9WD/tSG+tOI/9eI/tiM/9uU/92c696g/9+g7+Cm8eKq/+Cl/+Kr9ua1/+Sx+ue6/ui8wcHBxcXFysrKzc3N0dHR1dXV2NjY3d3d7fHX/urC/+7N/+/R//DV/vLa4eHh5eXl6enp7e3t9PTg/fXj//fo/vjs8fHx9fX1//ry+fn5//z4/v7+AAAAA7tHUwAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABaESURBVHhe3Z0LfBzHXcfv9LRV2ZJl2bGtB7TgpAFaCDblDa1NDJQ3R3gUAjQFysM8CqWFpjQ8WvNooMFASAslNVAIBIihxaaSZSuWH1Iopq6DapM0qWtJlkRKVtYRIlkZ9/+f/d/u7OtuZvZ/t7f5fj7JSbq9vfl6Z387uzs7U7hRA9FUUKFqUcOKVtZcUNmqUNWK1tKcUBljqWJFn25yqLBBEq3oQzmACqySYEUfyAdUZoVYK1o6N1CxfWKsaNFcQUWvELGixfIGlZ4IW9FC+YPK7xKyokXyCBlIgla0QD4hByRgRW/nFbIAVCt6M7eQBqBY0Xs5hkRUK3onz5CJYkVvRFmcmZpsKqZmFqhoEcjFs6I/h1gc7m0rNCGtPUPzVMQgZFPNanITraQp6T1DxVQhG7KiP6os99HHm5beJSqqgqvjWtGfVE43ZdUL0naSCusjdRKtxumDTc4YFddH+kgr+oNCTqRitKpYnaHPVKfY3rku83o6QUX2SLRabqePJNG2afjUXNld9vRm+mM2tIYjI9Gqnz4Rz0tG5mg5Yn4jvZMJm6gUHglWV2j5ONoG4w5/A/RuJpylQlQgK/rNI3lTdZ5YdRdxps8/8u7f/ONfufsdB6cd+D1LrV63SD6xVku0dIS242v4vjN95MD3lZBvkf9/J2plWQkjzcI4q2O0cJhtMh6c8z8tXRTuAq2rtFAWDMliK8RZxWda5xS+53z4+0kF+DZ6lVsrwySMVkGwoh89OmnhAH24oZwjilPpO+gVmBbiFC2YAW1uuX1irJZp2QDD8IYz/VMk4fLt9AocTPhYg4jsWFGreVpUoYitSOf3SYHw6h9wD7zfSgtnwIws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' + + +plusfour = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAAwQKBwgHCgQDCAcJDAgACwsLBwgZDxEPFggGGxMAFBQUFxQaFxgZGBUXHBwcDQ0qDw8yEQ8uFxkhExQ8JQsNLw8SKBgEIB8eNxMTOCUAJCQkKCYnKScoLCwsMigpMS8yMTExODU2Ojo6FxVEHB5XICBfPz5AJiZvJiZ0PkA+RRcZVBweXx8gQSsASjIBWTsAXyAgZyEidycnQEA+aUcAcksAe1EBZFk4Q0NDSEdIS0tLT09QT1FPUE5RUVBPVVVVVlZYW1tbYF5hY2NjaGZoa2trc3NzeHd1ent6LSyHMC2SMTSaOjipOzuzPkDAQD+8VliDfn6PQ0LISEjcTU3rT1T4UE7sVFX+XWH+YF78aWnkZGT9Z2n7a2v+d3f9TqtQValUXq5gXrBgYK1eY65kaLNobrZwdrp2fMF7gSsrjjAyky8ymTMyqDg3uDw8tj1AhFcAmGUBvEA9p24ArXQBt3oAgm1AyEA/xkJD10dH5ExM709Q9U5S91JO/lRU/Wdn/25w/HZ1gX/+v4EAgIJ/woMB0Y0A2pIB6poA7qMA/qkA/q4R/bIY/rYl/ro0/YB9/r5B/cJK/cZY/stl/s5y/tBr/dF5goKCh4iGi4uLjIyQkI+Rk5OTl5iXmZeWmJaZm5ubnZ+ggr+CpoaGoJ+eoaKeoqKiq6urr7CvsK+wtLS0ura7u7u7hIT+iYf+ion8lpX9oZ/+vb7Bp6j8sq//tbP7ubX9vLv+icSJj8aRmMuYmNCYoM+gp9OnvsC+sNetu9y7vd/E0JeX/YmJ/ZGP/Zua/aOi/q2w/bu7wb/Bwd+//NeH/duV/eGn/ea3w8PDx8nHycnGysrKw97C0c/O09PT19jW29nX3NzbyMn90tP819j729v9xuLG1+rX3+Hg/cTF/djY4N/74PDf/evG/u/R/fLa5OTk5Ovk6Ofo6Onn6urq5eT+5uj76Of76+v+6PPn7fbw7vD+/eno8e/3/PXm8/Pz8vP99Pn09vn5/PTz+vb6+/r1/v7+AAAADa/O5QAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABkUSURBVHhe7Z1/kCTlWceHutBh6ehQBak76MokaxM1IUELJDqMWsOymc2eIf4gKEYDOZXLJQokaFBAsxopA7kAGrCYTDKlq8aZchwiBiNHDIpSKprjVoeMGfDuvLPwOpdBOT22uSM7Z3e/z/t29/u+T/fbPT2/tu5zf9xM9zs773ee98fzPu+Pzp3ajESq6g2mmB5kUgauCj481UBWBRBVNnxs6rEhw2GkquATMwJkOohE1czYiSLaS1DVgaQzRRcyT+FVzZyhCJy5OFWQaAYBAYSwKkgxk4AEj5AquD+jgAiXoCq4O7OADIeAKrg3w4CQoCq4M9OAFF8VXJ9xQAxVZcHlGadP1FBVcHXmIWpAFVwTsZrLiwvlqWJhcamJj/w8OURVFy5xWMv53JSiLyHCvMEkUQVXwvTK8BemlJJcF1Mlvb2qwaenlzpkNYRFVcH7IHYJPjnVFGVDDFyVXYTPTTnzElkdogreBZgVUXJZmKoKfGYGWIAsB0BUteETM0ELMu3TdVXBax87eS9ltCk6XBkbeh+y7SNVVYf0CWjARwcNuDBGavDVPlJVBUiujgGfTPPZocnDV/vIVKWoVavw0UETLoyVJnw5w1El+IBLkFgd/9eagKlyuUX4coaVEyOAJiRWh3kuEzFVbh6+3ScnVqvE/p9vqnm4MmYEw4iqepBUHdYIteDCuBGi6KKqLiRVRocPTsxUuTX4foaoqgNJlWGmmphL0oYMMIZXpbNSnbyZyYgRqKrC5yboPWavyjfV5EYv2atiplqDCxMgc1Ua85gnONDMXNUyfCpxdcySrFX5pppk9CZrVVNhqsSqGhYgd8Z9U5Wd1hCSWmNv4pOqYkEB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' +plusfourblue = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAAwQDBQUFBwgHCQkJDQ0NDxEPERERFRUVGRkZHh4eDAwmDg4sDxAuFBQuFhY2FxU4GxgzFyE0ISEhJiYmKSkpLS0tMDAwMjQyNDQ0OTk5Ojw5PT09KipNJzFFMTJRPTtcPkA+Qj9hQUFBREZDRUVFSUlJTU1NT1FPUE5QUVFRU1RTVlZWVlVYWVlZXFxaXV1dRkdqSUptUVF0U1N4WFl9YF5hYWFhY2RmZWVlaWlpbW1tcXFxdXVzdXV1eHl4fX19LCuAMjKXMzOYNDmROD2WOzyiPD2pPj+8PUOiXVyEQEanQUepQkirQECwRkyySE21Sk+5RVK1SFS3SVW7Sli/ZGOJZ2iMbGyUcnKXRkjOSUrERknQSEvWS0zcTlTDTVjBTFTXTFTZUFbHUFrFUFbfTU7iUFTjUlbsUljrUlP0VFX+U1jwWVzzWl74XmXuXWH0XGD4Y27bZnLbaXfcbHvccHHfYmvtYmX2ZWr1aGv0a3bpbHD1c3TrdH7qcHT0dXn2en72cIDedYDqeYPrf4ntfID3fID4gIJ/goKCg4OEgoSAhIOEhYWFh4iGiYmJi42KjY2LjY2NjIyQkZGRlJOUlJWSlZWVl5iXmJaZmZmZnZ2djo+1oaGhpaWlqampqqysra2tr7CvsLCxs7G0s7S1tLKztbW1ura7ubm5u726vbu9vLy8hofQiInRgoPug4zuhofwgoP5hozwh4j7i43yi5Hvi5Hyj5D5kZXzkpL9lpr1mZz2m574m6LunKPwnqH5pab9pqj9qKf+qKn+trbvtrb+v7/+vsC+wcHBxMTEx8nHysrKzMvLzc3Lzc3N0c/O0tLS09TT1NPU1dXS1dXV19jW29nX2dnZ3d3dzc7rzNnl1dby3d303Nz43+Hg3uD54eHh5OTj5eXl5+jn6Ofo6Onn6Ojo7e3t4+P95uj86Of96Oj98O/w8fHt8fHx8/Ty9PP09fX19/j29vj4+vf6+Pr3+fn5+vr8+v76+v38/fr9/f36/v7+AAAAAAAAOABVigAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABpySURBVHhe7Z0JfCvHXcdVIaGj5ZRs18JQwNgGYYwplIcPbPN6UI5wPMJVQgiBNq9xWwoh0KQkJCQfwBRjakwNNrYxBozB0JRSwkuaJnYfh12Ba8BgccYVRVL6qIKAqs/Rfh5z/Hf2mJndWWklS/68b94n8q52pflpjv3Pf/4zE7hxHnFUday1MFlIpAi5Kri5pYGkckhUleC2lqcMCbYiVFWBW9qCCiTajEBV2+STDp9fnKoMXNpWHELideyqynBdm2HLLpsquKgNAQEUqyq4oi0BCQSLKni/TQERGLMqeLdtARkIkyp4r40BIWZV8E5bA1IMVXC+zQExuqocnG5zClSNrgrOtj1UDaiCczwn65MXhgZbiqELE2tZSB4PkUNVHcIpGyeTsUCLEp2QCCOdSaoKzljJDgbhI1qTAXFXnakSvr0UhrtbltA8JNVCTlcFx2bK/XBrS9Mr6gvKVZV74b4Wp1sgK0NVwZGJdhElliVTNQr3tAHDkGQTElXbcEdbsAGJNjjEqjiPUjkON6iT3Aa2InCmaUQLkGwDrAr+NFiE6z2wArdqq3CiiczBVxsIVXXC5eokWH53wJkmEoevNhCpqqFWLcGt2hqcaCrr8OUMpOoI/mSMw8XqxFlWec9mHxiBL2ecBHgPYA9crM4i3Kmtw4nm0gnfbhDgq1UILlYmxn6YLjjTXIJcxvCqjuFadRbgTm0TTjSbA/h+Bq/qEC5VJsp+qm4402z24PsZvKoMXKoM6w9swYmmsw0JYNSvysiqFJxpOg1QNQv3naH16L+qCOsKnF3vxX9VM3CbtgcnzgDfVYWZxdwHZ84A31VNwV2eq6Of+K3KyKqz9N74rWoS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' +plusfourgreen = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAABwgHCQcKCwsLDBYMCxgMDRsTEQ0NERkNFBQUEh0RER4bGBUXHBwcFiwWHSkcHygiIB8eJCQkIi4jKCYnLCwsJDEkLTosMS8yMD4vMTExMT0wODU2Ojo6Pz5AI0UjJkslJ00oKkskKU4pL1AmK1EqLlg1NEM0PkA+MVMmNFYsN1knN1kvOlsrM1syMFw6PV0yP2AsNWU0OWU3OGY8PG05NWRDOGhHOmtLQEA+Q2UrRGQ2S2s5THEvSnc0U3c2Q0NDSEdIS0tLT09QQ1JDR1dIT1FPUE5RUVBPVVVVVlZYW1tbR3FAQn5MQHZUVnZBW3xDYF5heHlEY2NjaGZoa2tra35rc3NzeHd1ent6ToE6YpE8Q4FORYJQSo5WTJFWT5dYT5hYUYVFU4dIVIxJW4xKV5BLWJRDWJRMWZlGWZlNUZxYWZ1QTqtQWqJNVKZTU6FYValUVqpYWKpVW6xbXapiXrBgYp9hfZB8Y6tcaa9bbLBdY61kY6xqbK1jY7FjZbJqaLJnbLRsbLJycq1xcrNidrJueLVnebZpfbhucbVzdLl0eLNwerl2e717fMF7dIiBe7OLfLqBgIJ/k456ha9yiLF1jLR8iL98kL1zlMB6goKCh4iGi4uLjIyQkI+Rk5OTl5iXmZeWmJaZm5ubnZ+gg76BhbqRir6UkbqDlL2JoJ+eoaKeoqKiq6urr7CvsK+wtLS0ura7u7u7vb7Bv7/+hcGGh8eLi8ODisOKjMiLjsOUksaNmsSCm8WKnsiMk8SblMqTm8WSmceem8mXmsqdmNCYnsygoMmPo8yVo8yaoc6hpNGjqdGjrNSrvsC+sNetsdextNm0vd28vd/Ewb/BwMy/wd+/w8PDx8nHycnGysrKw97C0c/O09PT19jW29nX3NzbxOHEy+PL0+bS1OnT1uvY2OnW2+zb3OTg3uvg4+3e4fDe5OTk4u3i6Ofo6Onn6urq4/Dj6/Tq7fbw8O/w8PTt8fjv8/Pz9Pn09vn4+Pb3+vf6+Pn2/v7+AAAARX10/QAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABlESURBVHhe7Z0LlCRXWccbayOpaBvT0AkMtkl2zxgSTQCVoCQkzQBqM77i2A6Db3wlm8DauxsUCaxuRCUr4BMkY0sfHYGIPce2MSREMAFizCZZhfgY6dDSmwSXbHpi92qoRam1qu6/bj3u/apuVVf3dM/ZX87JTFfd2rn//u7ju999VO7UdiRSVc+cYnrIpAxaFR6eapBVAUKVgcemHgMZDiJVhSdmBGTaj0TVzNjJRbSXoKqDpDNFF5l3CauaOUMxQuYKqUKiGQQCGEFVSDGTQIJDQBXuzygQYeNXhbszC2RY+FTh3gwDIX5VuDPTQIqnCtdnHIhxVfVxecYZMDWuKlydeZgaqMI1kf76ytJiZapYXFpep0d+jhymqotLIfor+dyUoi8TwpzBJFOFK0F6FfwLU8qCXBdXJb29puHp6aWBrAbou6rw2Y+xgCenmrJsiEGrMsp4bsqZk8jqMFX45GNWRMllUaqqeGYGWESWfRCq2nhiJmgh0x5dWxV+9zCS91KFtouOKxNDHyDbHlJVDaRPQBOPmk1cmCB1/GkPqaoikqtTwJNpnh2ZPP60h0xVilq1hkfNdVyYKOv44xxLleADLiOxOt63tQWmyuWW8Mc5/ZwYASwhsTrcc9kSU+Xm8Nc9cmK1Suz/eaaaw5UJIxhGVNVDUnV4I9TChUkjRNFFVV0kVUbHg1tmqtwG/j5HVNVBUmW4qbbMJWkjA5zRVem8VCdvZjJiDKpW8dwWeo/Zq/JMtXWjl+xVcVNt4MIWkLkqjXvMWzjQzFzVCp5KXB2zJGtVnqm2MnqTtaqpMFViVc0+kDvjnqkqVmuIpP2JN/FJVfGggNwZWsZdx83inlNi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' +plusfourred = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAAgQJBwgHCgQECQcKCwsLCgoeDxEPGQkJFBQUFxQaFxgZGBUXHBwcFxkhJQwLJA4SJA8aLw8SKxELJhISJhEdIB8eLhkZOhwKNxMTKBQlLhYvMhgzJCQkKCYnKScoLCwsMyYnMS8yMTExODU2Ojo6Pz5APkA+RRcZVBweXx8gXyAgYiIeZiMidycnezAifi9CQEA+fVg8Q0NDSEdIS0tLT09QT1FPUE5RUVBPVVVVVlZYW1tbYF5hdld6Y2NjaGZoa2trc3NzeHd1ent6fn6PgSsrhDMkjjAyky8ylz0nmTMyqDg3uDw8gjFEhjNIiDRJlDpUmDxXmz1Ztj1An0EpqEYquU4uvEA9mGhDpUFhrURmsEVpuElsyEA/wVAvylQx1lc25F45xkJDxEhc10dHw01w1Exg2U9h3Xxs5ExM709Q6VdD7FJe9U5S9lZL81FQ8VNc9VtX815Y/lRU/VVY/l1T/Vpa41Bg719u9Vdg81hj8F5s7mZe+GRY/nhW7Wxj7mNy7HFo7Hlx/Wdn/25w/npo/HZ1i2TD3mSF3muK7nCB4XWT4nqVgIJ/3oV14ol7/Yhq/opz/pN6goKCh4iGi4uLjIyQkI+Rk5OTl5iXmZeWmJaZm5ubnZ+gpoaGoJ+eoaKeoqKiq6urr7CvsK+wtLS0ura7u7u7vb7Bv7/+vsC+0JeX442A5oOb6Ied6Iuf5pOI7JyT+omH/ZqG/pWW+5yb6o6g7ZOj8Jel8pyn8p2o7qGZ/qGM+aWa86ei9aGq9Kmk9q2q/aCg+Kat/qyi+ayt/q2w/rKr/bSz/ra7/Lm3/by8wb/Bw8PDx8nHycnGysrK0c/O09PT19jW29nX3Nzb3t/+3+Hg6NnP7t3V/cPC/8DJ/snK/d7M8N7W/dPT/tfZ/tjX/Nrb7dTj89rl+eLa5OTk5+jn6Ofo6Onn6urq9+Li++Xk/ebo/ejm/enp8O/w+fPs8/Pz8fL+9fj09vj4/PPz/PX5+vr2/v7+AAAAAAAAAAAAAAAAAAAAHYHLzAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABlASURBVHhe7Z17lCTVXcfbrCVTxg7xgAmr1qHDWAY87h616ajNYKcnoyjPqDFqiMoGMUIWJwkzm5cuhJBgYghgOm366PjoPrYddZVlMaKJq4kGxeCYTptWdwWJwJZLM+yGMpDtf9aqur97q+re+6u6VV39mrMfOGe7q27N3O/87uN3f/dRudPbkUhV/eEM04dMysBVwcMzDWRVAFFlw2Mzjw0ZDiNVBU/MCZDpIBJVc2MnimgvQVUXks4VPcg8hVc1d4YicObiVEGiOQQEEMKqIMVcAhI8Qqrg/pwCIlyCquDu3AIyHAKq4N4cA0KCquDOXANSfFVwfc4BMVSVBZfnnAFRQ1XB1bmHqAFVcE3Eaq1UlsozxVJluYWP/Dw5RFUPLnFYK/ncjKIvI8K8wSRRBVfC9MvwE2aUklwXUyW9vaHB07NLA7IawqKq4HsQuwRPzjRF2RADV2UX4bkZZ1Eiq0tUwbcA8yJKLgtTVYVn5oAlyHIARFUHnpgL2pBpn56rCj772Ml7KaND0eHKxNAHkG0fqaoGpE9AEx4dNuHCBKnDr/aRqipAcnUMeDLNsyOTh1/tI1OVolZtwKPDFlyYKC345QxHleADLkNidfy/1hRMlctV4JczrJwYATQhsTrMc5mKqXKL8Nt9cmK1Suz/+aZahCsTRjCMqKoPSdVhjVAbLkwaIYouqupBUmV0eHBqpsptwu9niKq6kFQZZqqpuSQdyABjdFU6K9XJm5mMGIOqGjw3Re8xe1W+qaY3esleFTPVJlyYApmr0pjHPMWBZuaqVuCpxNUxS7JW5ZtqmtGbrFXNhKkSq2pagNwZ901VdlpDSGpNvIlPqooFBeTO0DLc9dws5jkl9rlGJVtVGpsfcoPXzHWfc1VVuEl0bBdbMVMtud+2ia2YqciQbJvYKmyqbWIrFgSB0fP2sBWb9aqQ7zNvqw17SP4LQq4Y5AcFwvYWXJh5W7EAswhTxUxFJ1Bm3lYKqgRTbQtbsZAvm+vaBrYqw9fhgAVFt4GtmKn8qPz826oE3wKm2ga2YjHgFe+rx8zb6o9tAK45nRXFm11lprLzGoNNzfW8r266CaGoioH4FixcFsEEp7LOqHI5o4rjjKoROaPK5YwqjhlWtdEHwnlchqsh/MXj3tfRVWm6nnfQYzv0pKqSkI0fmDfL1Vqz0wuuubI79TIdAckYp6rR/EC9uLIR1sIx6Cxj69lm0lZaMWqBegB7Q16sZ81WmrncVBJE2ZQtR58pWxUbyO6ASCxxqnZmbKWVm8LqI1WElfazYat8hfWDqehz5poBWxVWMtiS3AiZa6y26gIRa2+NWqK2AWczKGucquIpjlbwQgRlTVGVVs3ITEBA1tRUFRqpmzyMLpM1JVVl4fdmAbPWNFTpy+PaCroBv2HyqrSVzIueDywzmriqyrjs5GERL37CqsrZNnsipGucqCpTWLucPV4ZnKAqQ9i+MQ68OZmJqcqzDTFjxp3qnJSqcTZ8YVxXejKqCmlGg2lxRiUTUcUWeE6E1kRUFSZ9olN+AqqWJ1ajKPWxqzKQLuq41et+4V9hVInR60eEA3F641ZVlRvq3+pLZvyOW80wq+00ltbGqgoxVP9jpl5eaTTjaFRLZ6UahpnjVFWWZ8gy9EpXqWjZg428+HePZ3mMqpD2vJ8z1KMVdkNnkSp1mmNTpSFeX+cli0n8drvsT5kp0x+XqjzSST1dNo48D5+VqCnN+HGMSZWJjQ3burhLPpK6FrHaCGMcuzVzuSWs4RosLSZ0Cevi/vN4FHbWJleFm6Ovh8rTU38n4R+24K5HxV9Prs4YVGkR1XtT84dZWw/e9Z41Ge+6z9c1KKZoA8egyogqYku+q/vke0GEhN94ChIN2/k0Dn/mqozIAqPRnnnrQbmdgPtIKrdapRmaZa0qWlRLg9MUtj4J2Ud47zMknVWWnrAUR8aqjGhPqJKHNvchyD3Kp0i6boHtU0tCtqqiLTUcvswgf/mtiDpFAFWdNL1Vxv1VjKWGPQ3Wh38K8o7ynidJwjo1bjKyVBVnqWGN/uX/DDKP8sH/89LZZilFb5WpqjhLudEf8u/Wr0LmUe4iCQcpAznZqYq11HCzADu0/gryjvMgSVh/WaopVjsz7zbeUsOmDnn8c8g7Cq1WZqJRCyOzkUi8pdxBBSS6CzKP8iGSbnhW8RR8SsRmRqo0BQ/AKpukXX/qtnXIPQZUq06asZVDKyNVwo+RsJmHHjW2XafVqqylateHjWxUKY0EmzSP90HeUd5NfPaBUfD+TUw20Ri2+ZRid9uNGseKWSRVf+tdkHkpb/ulN177Q+SJirZIPvA0mp3IVmQpC1VQXRh2p1wwAitVKFXSTD4M+Zfxztd++zdA6gg03ShFeVLFDFTluTa9W9b0lXYfToFg9GjVx1XdfPVLz691rOPW05Y1GFgDyzp+/PjA+l/4CYxuvawZEaW+MLoqjXOQN3NGTTZ6qOeht0Lb9Te/tPC7JEksdkOPaKEyiEiHgyV2M7ckjAM8DBOqFTZcfPPLE6wusevys21d7NFnD7geZUOvyrPWoyd6/DWI4PnFc+vx7omPbeQxY/VHVsW2nhL6polkrUaDNB8GFRw3fwsSlsco0xIt8IlRVcEokLGBxo9NndgQK4A/6e8NV2MJmxobNkdVxf1g6+IiUjXsPOxyRMb2N3+b0OnFUDbk9dddmzCaKj6o0NOC7e1z//PoI5TfW4AK+Jcgg+PnQicZHjl48MA9Bxj3OBw4cPD+I3DbQy9gJdYcTZXg0DRf7LeIXzt66M479nlZdpzZXbSAIdXqDb7T/+xDd++Hq5R3kH/2H/TDnz3Ro6HsGE2VUASKJvPdnzh0B8mKy/oNO4vk8pNItfqeJdrKbN0Dl2S8j8laRuPvTn5HUSWOvv2/36O+pvW1fWuvO/u3yPUH4SLH286mHtDW7XBJzmcgmVPM4IPAxkiqRIe6odO8PXEHFBrgCmpXJA7zhsIXyP2t28MP8tz+LEnXMdjROzyVkVSJA8USjbGfCJQ+l7fuzkO1QarV1a8i9589ABdQHvbSDRv4fPHiKKokw1TWLB2CLFBu2Ln0Fe/GU0i12vVq73akP++x/yRJuCyeaQvYTt5SqxLP/3X8WigVT/Cmup4eT4AMg9/58o3h0A1RHIQLKDeSn2OVXkk+iLjZTa1K4glUqWPxMF83dl8A1QopgNdAj/rsbXAB5R4v3bCTRyMa7rHraVVJfqhtwgTaC3wBXNv5g+AuvRsucOyCMxc+A99xoA38uC70KpSKk7uUqmQTgB0Dmvon7oQsUFZ3VJ/37iDV5pcXYAYytgDuP+alG5Qxz4xs4E2pSja+rtNoy1G+AF6lQ64Rd+knaHt6I1xAuZuks/LoSja3sUipShr7gWbplGMRLt53IbjX2ATP1TT+zntKAgdJwr78LS8uHTd/6VQJTzn0iyXy9zvJV6u35i72bqD++rdCu/5puIBzP0m4Yshy4OGdm5RKFfh0YTo6nR29gzPVFbnfJncQx+Lar/sXcj+2C97/3yShgVcr78CXVKqk7U+NLvJ5hI8373rRF8mdD8EFjh+HAv3VuGq1DtWqq6ETQCSzaVRJ3q7iNEslOoEmtusauTH8oNPfXvtan2uucf+/+pthmPafb4cHUGgBpJMrIuSIoTSqpENxS6dL1jnHYu3nF8CT//dff+OuBfgZIdpk5uN+eADns166YYEPQfqQvd4pVMln1Xu0WToJOWD8yA7yl7V++CX5cqsvzN00aEQxvrcioytbk7hrBDiPMbkq/6DeEFUaHPlHyALlLReRLntwab4i/DaHQQmq/jOx7foBL91wIxRHCFEneUyuCnHA9ItB7fu9Eb3P9ed4Pm//+43ff85LwPElWnQ/Cw/g/K2XbriEh6Pg9P7EqvLyTr2tgdrHIQeMKxe8obiptZ/3EvA0aFwvvgCe8NL1CuykLp4BZDKxKsRUVR0KoNPTrkIuPNav8Nyhpi6vjsPhqyDWcVK1ALbyqGNBt1snVoW0PqxZ4tv1my5yq41dgiCniH4JsX7sgJH663W8ANLT05OqkvZVbrsO/sZJvl2/YcGtNi10PNT7euhRD8MDOGRw/9yr+YAxw067sxYZ1tS13yEfArElwhUvdqtNI/clct9l6/C9tzK+75tItToRHVtyuI0M7r9YqGCq2KtmEqrCOopyDtq3T/L++ne51WawZA5oP3XicKgC7TpftQCCY9HGl4Kz4/sTqkLmLbsFKJlbd7px1qCwBXdlcddgG0aOfYDEcwn7Vs+GAhjrWNxC4tF2FV2P7L9QKJkq/10hYVo0EPg4XwBv8lyRFluL+xjX0l2X+wS5cTdcQLnxq146e5FFeXn8E0GTqcJcZdYsHX0HVwB3e73REo1UH+Ob79fTCFjsMBjiMAPUX2dtRVJVSOs8WFokf78XuIWn62sLBeeObcDf96RT/IIFcG3tsu/1bgyPxPrrMAxmxUIg8E6/RKq4iUUGqzZf+U3IAuUq4gtTj/gRuMzYew70qLGOxdthmqeIbigMHM2USJWQGGjTO1+GLDB25/7IuVzPw/wFL3rtOg0K4D1hE4pAeNNG/7RewAJIogpdf1Oh1ebvIQuMC3NuJLpQINXuhOAUXX7JC96dI7fABRQogI3AMv8wwdOmkqjC3C+7QJslPhB40063g2MTaIL7sHoeTADFx2EOk4RlHWnX2ZncLklUYZ6cv46UDwRef7bbj9XoBNq9cJnxJq+AOsQPg2EuxGCHPHEETg9OpAodgDZotfkvyAHjqgVXVYm+ZuRWuMy4jvaoUfOLHreReatNHZm2skObPxOowvzT4SLNmxCHuXLhO2yngEL8eotvEfbtXnqa3FGNwyxj7lL4yKcEqpAC7TgqUG1O8gVwbe+Fjo/V0qGAPgBXGavnQqBQ1V8flPwXrIYJH6iprgr7ef5uNiEQ6BgrV2hWqeMhVKtfKJCh5onYCZ7bib++iW2w4N7hqa4KG8s61QZy/ReQhQA37crpZ4H7IHhLa5cVSdsZ769/2ks33MDmTbkXIKurghG8CGuW+Hbdc95/ZoFWSLGYXQQ9arwqaAGxYTD/AmRlVViLOmzTavNl3l93WV/7sR3wO4Rqtfdc6FHj4+skEGiVYIKCI9wAOiirghZBZJmOjz8vNBYuq7vzWLW6/BvJHeU4zKZel6oK9VUuyqqwAahdhH7suQfW+XGww/oNO8vHvftitdoFBfCw5LkwUK0a8iWBlrDGV1UV9UIFugZUG3feVMjd+toN1NH6HFxi7D3nD8id+EAg+OslWGXNUfGUBFFVhXnKw6b2J+TDo/yA0WV9dTe03mIB/GnqgqkOGG1dGoeRnCSpqgobqg1rOvz93LGTRNeFxf/wbov++k+By/HMr8EFFFDVp/HhMJKjYVVVYZ6tbZZhGHzIkSRRteNSElz6PHxnrJ4HPaDyvGlVOm8qezGpoiq0Xe/SXaVCeJPwOjp/IbTre3YoT/DAhlQd4ghhZK/7VVSFxutrdILnnyELYVbZ9P1+3rV9/StJHmPnTWkBbEv9a+n7zhVVSQu0S7EE1cqNw4gF8FdyJrktFMC1y2DJxLHYYTAUwNeImXX8XenxM4qq0HCpVvka+SCMQjyuzH2c3P4oXGCsngOORewqH7rMzNQk81/kDXY8iqpkBdqly6b9RCfQZRd1PPh2fd8e2qPGqoIuuG+A2YMg79tXUyVbtuRRZr293EO9kKx6OSWJw9Ae9VhMw36IzMU5/roYN5GXP1VVaB/sD/ufeL/bHHA1i8QtHCT++mvInTjflopyPAj4EAB726+aKqyxaAV2yR11mna+ufjRHRDREKrV3lf8Ibnj9MIRY8Zb7odKNeyZ4tQZepKzmiohFVANjrqOHuKWEK+9ZRcU3VOiv36B79Khy6L33+2vy2+L86ZwtKgENVVYY2GGVr+efPwo7DQA/vQVsOzqsdBUsct3f2fgya3D4b0GDt5eA1i15LEhTghi5U9RFRay6Blo7+zRppH+vwEtlH2rC9jMBoJVEhZk0SN7JSipwhqLTUMs60GaUEBPCe7Sm9S2rfp0c3wkWhxV+SipwnLQzqONo8tgCVpvsV3fk/uYd0cV24Sddj5RL6ZXUgUNmUAnH7lR3dJhAuhhbtLKaQIXLsHqqoxBVTiCtQYCpCipwmaM7HJkQWrSSLVQAB0vEN3pJqFb1je48SLiVABKqlCDdHK6dL8pgZ6TJYu27F2gkmOxG4aQ1j+KXYqSKvggMqifpRXr7YEMy8pDnEuYYXRY33OO/gONTUiLYvXbK3mtzP9ZB1xUk0dFFTpkdOiWDLQvpBsshDiMx97Lz5MugQyjGUapIxQH2UgxiIoqdIrHxeo0YXc8T0GHciM4FsDqnusIP0seqOjmCvnks9HeFIt4BTKPoqIquqtFMWDB1om4Kd+1B7x0ww46OxoGljZGoKIKDdtG0tGgAPKOhQjMjq6onfcbnNZGUFGV0LkB6nQALUzc88DmD9sUWgUZvejmz0NFlVq54ClTn1iYN+W5l8TWbGx2NMQg6h1lFBVVCfpLH8uERubY/n2SMGGQj5KEatUqylFiqKhSKu08bJ2jxLHggGpVorHrKPDRRxAVVSqlXaBGC2B8tYIxvHz7SRglS6mpgn8T0acTaM/FVisogE189xFDzVJKqmDrSjLYBBC/IFAECmCFP9RERNFSSqqwFQmRdOjwJW7RwfqtEG9ZRKfIKKqWGp8q1qPGLqX4J5Kum48eVyew1NhUDc6nPeqxmHp1GNqKGnbwNEXdUmNTFTjoIrJl338Yyp9djhoZOCSw1NhUBTYebn0AFIjs2/8YJBp2C9GORRJLjU3VBYHjsY89IMxdeey79wHiALq06LBFyiCRpcamKjyNd+yhz0nwJTk0ok7r7av4fkHGo6r1ooThvj6+St11ECGzyoxHVTNpEJMdbikhfpAoMB5VH8GnXKX0DXxoVYGcJkFBVQo/sJ1LdE5tf3FRyAcwiAu8SFFRlcJYJrpDQELbQI/B6sWEyBBUVKUYC7c1rWGpxJztQW85v4iJaiVuJwgqqlQG3hyDRkE3qzV4iQtOo1bOm2j4NzKWHoWKqsh4IEanair0MvlisY4VcMk7nlVRUUW30Sdj0O/Bq5Ei6FloqyK84DkBKqrQOZExYiVz/DiUVCXsUjOgiQfvVVBShS4iGRMD2dvgk6CkCl/GNBZaoxnKQU2VQkwrMwbyBVeJUFMVNUzImFY6byKMoqoUHXEqNlO5fQKKqpCjOjKmP2orQVFUhZ0qkCVWxctRFqiqQtdcZIW9MoIvwaOsSh9vGWyM3JoHUVaFr3zMgFbScEsM6qrGVwab4e17GZBAFbZTdzSslUzLHiGBqnHI2syqLQ+TRFXWsuyNwIEAmZJIVaay+stjKHpAMlWZybLbEaPCFQhqpB9kJVSViwzyKzJoliN7XBZxSt3eJ1Xl+E6jdcdWIzbIMg1VuSSrMDl6NZWuaSqqcjn0mKco7M6y4tBpSqpy+kqSMLrzIzYqCfyHaalyKAtPyultVJM6RFNUlcsVGvwS8zD9zeaymWZ4MVVVDnpxpcWVRavbaqxUioURuthpq/LQC6ZZLJrm4mJhFC0uetuFdR2b3leOCqQl5OFqOzQjmYGqDFEJp4ZPfWAbc0LbhmdLFXreSYDwNDE7I2qGVZ2xFeGMrUKcsdWInLEVYR5slVt0YePtsveVwLpm7xUAGswr+2tBbLjQdVXPmCoPmcfE4vzkRL2IJZLuobfzoorZhByUGqHK3Rs4J6pYOBxO9d4etmJrI+BM221hK7YydADjtW1hK2YqevbXdrCVYKptYSt2gS1C2wa2Yqs9AidFG3nyH7vXhQveRt95UCWaymce/EACp4od7SMcfugwF36gB6eKZTHs1xLm1VaRpppbW7G5Cpmp5tVWbNGvLZ17mFNbMVPxp78S5tNW/vps+TTR/NhKozif2YSt3FThxIxZVBWAmYK0HKrMuCpmqogjpSTMtio/5pTIVDOuim0MQk+fkzPTqtKaarZVsS1SCU0106p8UyVdxTXLqpipoo//kqCgSnL69ETw3zaYeMEd804ooir/ZVmThR3i4cZXkiFsrRJVDSHphPFNlXxZrrAiSaIq88W+SrBNX8lN5TczlNxpYcWLN7cyafyXvSXfOiJslBjkTgvGStwEZQEzlcIBYDzCXuXTElXI0GasjGIq8Z1+UlWp9+2mh+3jD40G1RDPZZOqwg6hHh9azwKSbxqm76UK4KoSN9Im9cOminhYVd9VJRpL9h6IWUWyB7OOqFI6324mkJ3AW8+7qiR7uedFliFZX9o/7dlKYqyhNa49HZkiEzWsgirZCmjbf3nqzMLejBtk4AjyVMmM5XQdM26ugjCs8qgxVchy9TFtl8qEklyTZypQJTeWw6BTK5uwtGhmMEs1fwkyj1OrmCpU1rzR9dRQVbJ6N4fYFU8NVbVNjOWVv4CqbSGrBVp8VdtAFqlUDgFVGW7NnA6OqwQEVM27LF9USJXMzZ0fepeCCoewqjmuWx3Q4BFS5QBp5o465J/Aq8JcwtkG8s4QVPXm0FyQdR9BlQsknhM2dci2j1TVPOnq5CHLQRBVc1K/IK8CqCoXeHZGgUzKiFQFRD0/i5w+/f+SOEzoxTWx8gAAAABJRU5ErkJggg==' +plusfouryellow = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAAgQJBwgHCgQCCQcKDAgACwsLCgoeDxEPFAoFHBMBFBQUFxQaGBUXHBwcFxkhIRUCJBkEIxkNKxsCLB8MJhwTIB8eKB8aNhwHLiQOLyQQOCUANisUJCQkKyQlKCcoLCwsMiQnMC0vMS8yMTExODU2Ojo6Pz5APkA+QiUGSjIBWTsAUjceSDojQEA+ZkQCdUoCe1EBflYbZFk4Q0NDSEdIS0tLT09QT1FPUE5RUVBPVVVVVlZYW1tbYF5hY2NjaGZoa2tqdmdqc3NzeHd1ent6fn6PhVcBhFsdiF4fmFwKhl0giF4gmGUBjWEjkmcomWsqp2YKrXQBtmsOvW8Qt3oApXMvpnQwrXgysHs0gm1AynYQ134Ri3ewv4EAuIE1gIJ/t41rwoMBxIYe1YgG24AS2pIB1JAe2ZQcw4g23bU054cR65gD5ZsX4pkY654T9ZsH7qMA7aAS764X7q8Y7bAe9KQA8aIO86sM/KUB/qYM/qkA/a0L9KYU86YY8K0S/qYR/q4R/qga/bIY76gq76My7qkw7LMl6bg48Kcj/qMv/qol/qwp/qc2/rYl/rg03qBH3qJM36dV3rpA7q9B4atd4r5M5L9Q/q1G/bNK/rVU4q1h5LFl57Vr6Ldu6blv671z/b5j48BP5cFV+8FK/cZY68hn7cB278N578xw/cNr/stj/Mtq8cV88c508sh+/sdy/cx0/c15/tBr+NF6goKCh4iGi4uLjIyQkI+Rk5OTl5iXmZeWmJaZm5ubnZ+goJ+eoaKeoqKiq6urr7CvsK+wtLS0ura7u7u7vb7Bv7/+vsC+wb/B9cuB+M+E9tOC+NKE+9WI+9iH/diL/dqT/eGn/ea3w8PDx8nHycnGysrK0c/O09PT19jW29nX3Nzc3t/+3+Hg7N/Z7OnI7eLU7uLY++nI8+XZ9e7T9erZ/OzT+u7Z9/DW+vDV/fLb/Pje5OTk5+jn6Ofo6Onn6urq8O/w/fXl8/Pz8fL+9fj09vj4+/X1+vf6/Pr1/v7+AAAAeSzGFgAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABkISURBVHhe7Z17lCTVXcc7Z0MJW0nL48ghYpn2ZKyTTdRBbSZ6OsOknUzAXVazCEoE8ahIlGDccExkMyDqRkN8gM9FwAdhYGMCEqP06djqGLu1bZ/Bw7JDOi2tEjcEsmNl004Z4vRaVfd3b1Xde39Vt6qrHzVnP/vHdlfd7rnf/t3H7/7uowqndyKRqvrDGaYPmZSBq4IPzzSQVQFElQ0fm3lsyHAYqSr4RE6ATAeRqMqNnSiivQRVXUiaK3qQeQqvKneGInDm4lRBohwCAghhVZAil4AEj5AquJ9TQIRLUBXczS0gwyGgCu7lGBASVAV3cg1I8VXB9ZwDYqgqCy7nnAFRQ1XB1dxD1IAquCZitVaWFiszxeLScgsf+XlyiKoeXOKwVoqFGUVfRoR5g0miCq6E6VfgG2aUBbkupkp6e12DT88uDchqCIuqgvdB7AX45ExTlg0xcFV2GT4348xJZHWJKngXIC+i5LIwVVX4TA5YhCwHQFR14BO5oA2Z9um5quC1j528lzI6FB2uTAx9ANn2kapqQPoENOGjwyZcmCB1+NM+UlUlSK6OAZ9M89mRKcKf9pGpSlGr1uGjwxZcmCgt+OMMR5XgAy5DYnX8X2sKpioUluCPM6yCGAE0IbE6zHOZiqkKc/DXfQpitUrs//mmmoMrE0YwjKiqD0nVYY1QGy5MGiGKLqrqQVJldPjg1ExV2IC/zxBVdSGpMsxUU3NJOpABxuiqdFaqkzczGTEGVTX43BS9x+xV+aaa3ugle1XMVBtwYQpkrkpjHvMUB5qZq1qBTyWujlmStSrfVNOM3mStaiZMlVhV0wLkzrhvqorTGkJSa+JNfFJVLCggd4aW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' + + +bluebutton = b'iVBORw0KGgoAAAANSUhEUgAAAGMAAAAnCAMAAAAsLAbdAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAAE5a71VV/kZq1ICN7pal7QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJIhjsUAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAAzElEQVRYR+2X0Q6EIAwEgaP//8lYoLVgcomJ3T4Y59EYJrtGKKldIAdkKWVzEP1ycaDumsVBVV7xoC4Wc3gaOlXWNQe5lLSRNYo4vENMJMp0YBQqGQ6UopRRV3eQPACQ1YGLMdtiBzAGw22xAxljBEngGD1IjANbVS8roWNwkM9xm89xnxhHxD/4mv0qYm8POaMiztrW/Oc35ZwZgG2dsw+urWWGg4y7zFSoA/JNRGEO977sBmKOiDsOQ06a/PeuNpBb4zNkLeXq8Ke1A1yYxppnbkkqAAAAAElFTkSuQmCC' +greenbutton = b'iVBORw0KGgoAAAANSUhEUgAAAGMAAAAnCAMAAAAsLAbdAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAAAGmCwCqAAyjKU/AWXHLfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFeD53sAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAAzElEQVRYR+2X0Q6EIAwEgaP//8lYoLVgcomJ3T4Y59EYJrtGKKldIAdkKWVzEP1ycaDumsVBVV7xoC4Wc3gaOlXWNQe5lLSRNYo4vENMJMp0YBQqGQ6UopRRV3eQPACQ1YGLMdtiBzAGw22xAxljBEngGD1IjANbVS8roWNwkM9xm89xnxhHxD/4mv0qYm8POaMiztrW/Oc35ZwZgG2dsw+urWWGg4y7zFSoA/JNRGEO977sBmKOiDsOQ06a/PeuNpBb4zNkLeXq8Ke1A1yYxppnbkkqAAAAAElFTkSuQmCC' +redbutton = b'iVBORw0KGgoAAAANSUhEUgAAAGMAAAAnCAMAAAAsLAbdAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAALhqYuVaWP5VVeSNi+KlogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPXdpGwAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAAzElEQVRYR+2X0Q6EIAwEEej/fzIWaC2YXGJy3T4Y59EYJrtGKKndIAdkKWVzEB25OFB3zeKgKq94UBeLOTwNnSrrmoNcStrIGkUc3iEmEmU6MAqVDAdKUcqoqztIHgDI6sDFmG2xAxiD4bbYgYwxgiRwjB4kxoGtqpeV0DE4yOd4zOd4Towj4h98zX4VsbeHnFERZ21r/vObcs0MwLau2QfX1jLDQcZdZirUAfkmojCHe192AzFHxB2HISdN/nlXG8it8T9kLeXu8Ke1E2qb0ylAVTgZAAAAAElFTkSuQmCC' + + +blank = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAszD0iAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAAAFbSURBVHhe7c8BDQAwEMSg+Td908GnOODtolaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5Wjour7QMC20VI3QCuyAAAAABJRU5ErkJggg==' + +plusfour = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAAwQKBwgHCgQDCAcJDAgACwsLBwgZDxEPFggGGxMAFBQUFxQaFxgZGBUXHBwcDQ0qDw8yEQ8uFxkhExQ8JQsNLw8SKBgEIB8eNxMTOCUAJCQkKCYnKScoLCwsMigpMS8yMTExODU2Ojo6FxVEHB5XICBfPz5AJiZvJiZ0PkA+RRcZVBweXx8gQSsASjIBWTsAXyAgZyEidycnQEA+aUcAcksAe1EBZFk4Q0NDSEdIS0tLT09QT1FPUE5RUVBPVVVVVlZYW1tbYF5hY2NjaGZoa2trc3NzeHd1ent6LSyHMC2SMTSaOjipOzuzPkDAQD+8VliDfn6PQ0LISEjcTU3rT1T4UE7sVFX+XWH+YF78aWnkZGT9Z2n7a2v+d3f9TqtQValUXq5gXrBgYK1eY65kaLNobrZwdrp2fMF7gSsrjjAyky8ymTMyqDg3uDw8tj1AhFcAmGUBvEA9p24ArXQBt3oAgm1AyEA/xkJD10dH5ExM709Q9U5S91JO/lRU/Wdn/25w/HZ1gX/+v4EAgIJ/woMB0Y0A2pIB6poA7qMA/qkA/q4R/bIY/rYl/ro0/YB9/r5B/cJK/cZY/stl/s5y/tBr/dF5goKCh4iGi4uLjIyQkI+Rk5OTl5iXmZeWmJaZm5ubnZ+ggr+CpoaGoJ+eoaKeoqKiq6urr7CvsK+wtLS0ura7u7u7hIT+iYf+ion8lpX9oZ/+vb7Bp6j8sq//tbP7ubX9vLv+icSJj8aRmMuYmNCYoM+gp9OnvsC+sNetu9y7vd/E0JeX/YmJ/ZGP/Zua/aOi/q2w/bu7wb/Bwd+//NeH/duV/eGn/ea3w8PDx8nHycnGysrKw97C0c/O09PT19jW29nX3NzbyMn90tP819j729v9xuLG1+rX3+Hg/cTF/djY4N/74PDf/evG/u/R/fLa5OTk5Ovk6Ofo6Onn6urq5eT+5uj76Of76+v+6PPn7fbw7vD+/eno8e/3/PXm8/Pz8vP99Pn09vn5/PTz+vb6+/r1/v7+AAAADa/O5QAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABkUSURBVHhe7Z1/kCTlWceHutBh6ehQBak76MokaxM1IUELJDqMWsOymc2eIf4gKEYDOZXLJQokaFBAsxopA7kAGrCYTDKlq8aZchwiBiNHDIpSKprjVoeMGfDuvLPwOpdBOT22uSM7Z3e/z/t29/u+T/fbPT2/tu5zf9xM9zs773ee98fzPu+Pzp3ajESq6g2mmB5kUgauCj481UBWBRBVNnxs6rEhw2GkquATMwJkOohE1czYiSLaS1DVgaQzRRcyT+FVzZyhCJy5OFWQaAYBAYSwKkgxk4AEj5AquD+jgAiXoCq4O7OADIeAKrg3w4CQoCq4M9OAFF8VXJ9xQAxVZcHlGadP1FBVcHXmIWpAFVwTsZrLiwvlqWJhcamJj/w8OURVFy5xWMv53JSiLyHCvMEkUQVXwvTK8BemlJJcF1Mlvb2qwaenlzpkNYRFVcH7IHYJPjnVFGVDDFyVXYTPTTnzElkdogreBZgVUXJZmKoKfGYGWIAsB0BUteETM0ELMu3TdVXBax87eS9ltCk6XBkbeh+y7SNVVYf0CWjARwcNuDBGavDVPlJVBUiujgGfTPPZocnDV/vIVKWoVavw0UETLoyVJnw5w1El+IBLkFgd/9eagKlyuUX4coaVEyOAJiRWh3kuEzFVbh6+3ScnVqvE/p9vqnm4MmYEw4iqepBUHdYIteDCuBGi6KKqLiRVRocPTsxUuTX4foaoqgNJlWGmmphL0oYMMIZXpbNSnbyZyYgRqKrC5yboPWavyjfV5EYv2atiplqDCxMgc1Ua85gnONDMXNUyfCpxdcySrFX5pppk9CZrVVNhqsSqGhYgd8Z9U5Wd1hCSWmNv4pOqYkEBuTO0BHc9N4t5Tol9rmHJVpXG5ofc4DVz3WdcVQVuEh2bxVbMVAvuu01iK2YqMiTbJLYKm2qT2IoFQWD0vDlsxWa9Fsn7qbfVqj0g/4KQKwb5Q4GwvQUXpt5WLMAswlQxU9EJlKm3lYIqwVSbwlYs5MvmujaBrcrwdtBnQdFNYCtmKj8qP/u2KsG7gKk2ga1YDHjZe+sx9bZ61AbgmtNZUbzZVWYqO68x2NRc13vrphsTiqoYiG/BwmURjHEq67Qql9OqOE6rGpLTqlxOq+KYYlWrPSCcxyW4GsJfPO69HV6Vput5Bz22Q0+qKgnZ+IF5s1ypNtrd4Joru10r0xGQjFGqGs4P1IvLq2EtHP32EraebSptpRWjFqgHsFflxXrabKWZSw0lQZQ12XL0qbJVsY7sDojEEqdqp8ZWWrkhrD5SRVhpPx22yi+yfjAVPc5cU2CrwnIGW5LrIXON1FYdIGLtrVFN1DbgrAVljVJVPMXhCl6IoKwJqtIqGZkJCMiamKpCPXWTh9Fhsiakqix8bxYwa01Clb40qq2gq/AN41elLWde9HxgmdHYVS2Oyk4eFvHix6yqnG2zJ0K6xrGqMoW1y9njlcExqjKE7RujwJuTGZuqPNsQM2Lcqc5xqRplwxfGdaXHo6qQZjSYFmdUMhZVbIHnWGiORVVh3Cc65cegamlsNYpSG7kqA+mijlrdzr/+C4wqMbq9iHAgTnfUqipyQ/1bbcGM33GrGWallcbS2khVIYbqfdrUy8v1Rhz1SumsVMMwc5SqyvIMWYa+2FEqWnZ/NS/+7vEsjVAV0p73coZ6tMKu6yxSpU5jZKo0xOtrnzufxG+3y/6UmTK9UanKI53UN8rGf8BLNapKM34cI1JlYmPDli7uko+kpkWsNsIYxW7NXG4Ba7j6C/MJXcKauP88HoWdtclV4ebo6aHy9PL/vSjy8jfhrseiv55cnRGo0iKq95oWGGbt/+JD110r8N7rH34OEjj0iynawBGoMqKK2ILv6r74yPWgQ+C6R1+GRINWPo3Dn7kqI7LAaKxn3v8QSJBx3bOQyqlWaYZmWauKFtXU6GkKJ1FDeTwCxrLK0hOW4shYlRHtCS3moc19OVrUtde9QNJ1CmyfWhKyVRVtqcFgmwG//COQe4zrXyTp2ml6q4z7qxhLDboarA9/QdL2hXgIVNWocZORpao4Sw2q9Jd/9ich9xgPk3plm6UUvVWmquIs5UZ/4MXDkHmUvyTp+ikDOdmpirXUYK0AO7T+M6atuPa6fycJa9tSTbHamXm38ZYaNHTI47M/DbnHoNXKTDRqYWQ2Eom3lDuogESPQuZRHibpBmcVN+BVItYyUqUpeABW2STt+stx1eo9UK3aacZWDs2MVAl/RsJaHnrU/46tVvtJwrKWql0f1LNRpTQSbNA8PguZR7mepOsbBfIiKdlEY4QTuOxOq17lWDaLUPWjCuA1V79r+/YfJZ9Y1ObJC556ox3ZiixkoQqqC8NulwtGYKUKpQLNJF4Ar7nqwnPPgdQRaLpRivKkihmoynNteqes6cutnncGRIAuq/ogQeRd553xumrbso5+3bL6favvvDp6tG8578J0amXNiCj1heFVaZyDvJYzqrLRQy0PvRXWrv/49i2FPyBJYrHrekQLlUFEOhwssRu5BWEc4GGYUBd+E1Rw/MQPJVldYtfkZ9u62MPPHnA9yqpekWetS0/0eAFU8Hznqz4d75742EYeM1ZvaFVs6ymhZ5pI1qo0SPNFUMHxw69GwvIYZVqiBb4wrCo6CqSsovFjUwcb/hnI4Ph2f2+4GgvY1NigMawq7g9blxeRqmHn6S5Hebt+9TlCpxdD2ZDXX3dtwnCq+KBCVwu2t+uHDz1F+aM5qIDPvRd0hHln6CTDYwcPPMFz4MDBY3DbQy9gJdYcTpXg0DS+xW8Rv3noyY/9+grlElrAHgEZHG8KOP0nntiz8+d2iLx/zwFI4dAVPRrKluFUCUWgaDLf/fCTvqSVldvPL5LLL8qr1bvPWWCtzIFdPwsyBHb+LaRxt5Bj8Xcnv8OoEkff/u93KKhpZeVDr/0Mub5fHoe5mu2zPvEEqslhJyuEJo0WCKwOpUp0qOs6zdvh3wA5wI3Uroi//qYCtfsTN4AAOU9AsrbBjt7hWRxKlThQLNEY+/GwpVZWLs1DtfkLkMFxXhnuH4wWtWMXSTao4/PF88OokgxTWbP0JIih3L5t4SXvxkufBxkcZzhF1xvM74LcY+zx/oxbrXB/aQhV4vm/jl8LpeIwb6pfyX2O3PkfUMFxlQ4TQAcg8yhfIums0pvJCxE3u6lVSTyBCnUsngIxjEtfD9UGK4C0R/0ryDwK1Kt2Ho1ouMeup1Ul+aO2CRNor/AFcOV8Wm3kjsU19MyF9ZhateMGaAM/qwu9CsU9NimlKtkEYNuApv7wx0AM5aNbKifJLZDB8U568nlsAdxzwkvXL2OeGdnAm1KVbHxdo9EWrq9aWbmZVpvnQAbHG2l7+jhkHuVxks7KoyvZ3MYipSpp7AeapQ2xWl1E3es/Bxkc59EedQ9kHgVcpp78KS8u3rmS6VQJn3LoFUvk9zsuVKvc5d6Nwcn3gIwwP/Lqt5P7B6Pb9fft2HWQJFw2ZDnw8M5NSqUKfLowbR1+P6ELvpH+sohjsf2MfyL3/zmusXjsf0lCA69W3oEvqVRJ258qXeQjFMC3al8ld+T++jVvhAJ94kuQeRRo1zsaOgFEMptGleTpKk6zVKITaGK7voXcGHz+2ndftf3C88JceN4ZMEw7FudY7KQFkE6uiJAjhtKokg7FLZ0uWecL4G1z4Mnv/6ntZ8CfCNMiMx8Hd0LuMXate+kGBT4E6UP2eqdQJZ9V79LKcxzEMD64hfyy1o+dmy83e8LcTZ1GFON7K5LO1iTuGgHOY0yuyj+oN0SFtt7/CGIov/YW0mX3r8wvCt/m0C9B1T+pWq1WQ3GEEDWSx+SqEAdMvxzUciOrldu2esbt/YDxOShAYb5Gi+6JuAK4A9ylBTwcBaf3J1aVl3fqLQ3UHgYxjJvmvKG4qbXAa+Ko07ieagHsFthJXTx9yGRiVYipKjoUwH8AMYwbPXeoocur42Dw/TTWEetYPEPSNfOoY0G3WydWhbQ+rFni2/U73uJWG7tEg5wC+hVg/dgCCAW4hhdAenp6UlXSvspt18HfEByL2+fcatNEx0PdV0GPegzyjvJ+km797XzAmGGn3VmLDGtq2u+TF4K/fqNXbeq5r5H7Hs/vfeB+yvd9K1SrWH/9y16yk18tLGKq2KNmEqrCOopyDorH34MYxlvdatNfMPusnzrywD27fc42YNFcnGOxAxyLFr4UnB3fn1AVMm/ZKUDJPM4PGFfm3JXFHYNtGNnYC3IIt26BAhgXXNrxAdKun6ig65H9BwolU+U/KyRM8zUgV4jD3OG5Ik22Fnf9AZADfG/uC+TG43GqIA7z0rwf5eXwTwRNpgpzlVmzdAjEMC71qtUCbb3Xf/eTIAf4LhoBU3Us+qi/ztqKpKqQ1rm/ME9+v1eEajVXcO7YBv19nwYxlLsu+B5y41hcb7UThsFNFh/mCTzTL5EqbmKRwarN8d8GMZSbiS/MPGIQw7hlDnrUeH8d3KUii13zBI5mSqRKSAy06B3BXbo096fO5Voe5i/CLYXD2zRoO2PbdahWNvrTBh+EkUQVuv5mkVYbwV26KOdGogsFqHb3gxjKXRdfQdp15QJYDy7zDxE8bSqJKsz9sgu02vDt+h3nux0cm0A7AmIYd54NE0DH4gogneIp60i7zs7kdkmiCvPk/HWkIIZx22vdfqxKJ9CEAvgRr4A6HITMo9C5EIMd8sQROD04kSp0AFqn1UZo12+eu9K5XKKPGeEL4O7LaI+qGt5c05FpKzu0+TOBKsw/HczTvAlxmJvmvs12CiiNX/8OiKHcvXXhG+TOH0LmUcBdWsLcpfCRTwlUIQXacVSg2ggRi5U7LnJ8rKYOBfT5e0EN5U7t98gdVX+9X/IfsBomfKCmuirs7/m72YRAoGOsXKFRoY6HUK0uK8BQU7kAYhssuGd4qqvCxrJOtYFcC46FY6xLcvpZ4D6sC9VqaxHaTtWIxSo2b8o9AFldFfysIqxZEvx1l1+coxXy+ftADIP1qJB3HBjGYMNg/gHIyqqwFnXQotVG8NcJv7AFvmMfaGHcQnvUZyDvKBCHsUowQcERbgAdlFWxlRQ8S3R8LKlWDh/9YB6rVhe8Bu6o+utrek2qKtRXuSirwgagdhH6sXWhXfe4/fzyUXKfr1Yfn4MCGO9YfJ0krMuXBFrCGl9VVRoyXnT8dRoIlFarldupo7UOYhi3nPnH5M6BOFWPQWNRoqusw8ADdAKoqsI85UFD+2vyQojDEC6lrfdXQAzjMuqCfRkyjwLtuq1L4zCSkyRVVWFDtUFVh99PXq1WLirCDvVPgRjKJy4Gl0N52qpH48NhJEfDqqrCPFvbLMMwWF6tVrZcCa0yN7TffSuJv8fOmzqeLbhLFem8qezBpIqq0Ha9Q3eVCuFNwofo/IXYrtO2U3U5wkCHOEIY2eN+FVWh8foqneDBCuA2uP8giKHc/d1vJnlULoAtqX8tfd65oirUXy+WoFpJ3CWXnElubwQjmy4f3wpLJtZjh8FQAN8hZtbxd6XHzyiqQsOl2iKcBSCvVjflPktuP81Xq9/aAgu2YmeD6TIzk8Y4gpAn2PEoqpIVaJcOm/aT91aX0MojtOu30B41ThUd2/cMMHsQ5Hn7aqpky5Y8yqy3l9eri+iqF8Ffv4D2qDH16meg/Dn+uhg3kZc/VVVoH+wP+6WuBYlbOBzh/fVP5N5B7ji+rcy1eB/8TyuV60HAiwDY037VVGGNRTOwS07mW/z8FohoPM03Fh/e9ifkjmOsiDHjHiaqa4pTZ+hJzmqqhFRAJTjqOvQkb65fvQSK7gbfru+++A2+S3fibz4gM9cNux57HOqUQ0ucN4WjRSWoqcIaCzO4+nXj+OFDT/m7DRz+7vWw7OoIH4fZfeZ3BD55UrbX4JkDB4Ne36o4IYiVP0VVWMiia6C9s0eLRvqf5wvgnUm3olt0VYYPPbJXgpIqrLFYM5BpYqABBXTjeRDD+IjatlWfDl3uyRBHVT5KqrActPJo4+jSX6CtNzcV5zqBqLcixTbpTjtG1IPplVRBQybQzkduVLd0mADa4AOBjqor/IYgnn4lz5uqCgKkKKnCZozscmRBatBIteCv7757a5617PF0yvpqsOVwQJwKQEkVapB2TpfuNyWwc7KEAuhWrG1YCeCx6wb9eRj+UexSlFTBC5GjnzlbK9ZafRmWladxLr4FdLjrbWfqP1hfg7QoVq+1nNfoanhGn4tq8qioQoeMDp3LDbQvpBsshDiMxy9dsHUO0kWgGUapLRQH2UgxiIoqdIrHxWo3YHc8T0GHciMEAgl33XrLhwm/TD6wqJvL5JXPamtNLOJiUIlDRVV0V4ti0AVbgmPBs4+ka6Ozo2FgaWMEKqrQsG0kbQ0KoOBY8Nx3hCRcRqfnQwSntRFUVCV0boAaHUDv5YfBPA+QMa5tCq2CjG508+ehokqtXPCUqU8s+Os8XyHpbGx2NEQ/6hllFBVVaNAiCsuk8Xc+vMlzz9MkoVq1inKUGCqqlEo7D1vnKMyb8tz3XyRhicauo8BHH0FUVKmUdoEqLYBIu+5zP0k3kG8/CaNkKTVV8H8ienQCTZw35aAFsIHvPmKoWUpJFWxdSQabAIqvVtCuL/KHmogoWkpJFbYiIZI2Hb4I0SWeB0m6wTw6RUZRtdToVLEe9UhMY3EfTJl08tHj6gSWGpmq/utojyqGl0Lc+wpJNqhiB09T1C01MlWBgy72RRnrfqhUzgA0amTgkMBSI1NFNx46xWtjLyrrngepqEGnEO1YJLHUyFS9IXA89sa+B2Qtxr2f2rvPn+Ro0mGLlH4iS41MVXgab+OVdRlw16MedVpvT8X3CzIaVc0zE4b7evgqdddBhMwqMxpVjaRBTHa4pYT4QaLAaFQlPQC/Z+BDq9jhvAQFVSn8wFYu0Tm1vfl5IR9APy7wIkVFVQpjmegOAQktAz0GqxsTIkNQUZViLNzStLqF138fu99dys9jopqJ2wmCiiqVgTdHv17QzUoVHuKCU6+W8yYa/o2MpUehoioyHojRrpgKvUy+WKxhBVzyjGdVVFRp8CIZ/V4XHo0UQddCWxXhAc8JUFGFzomMECuZ48ehpCphl5oBDTx4r4KSKnQRyYjoy54GnwQlVfgyppHQHM5QDmqqFGJamdGXL7hKhJqqqGFCxjTTeRNhFFWl6IhTsZbK7RNQVIUc1ZExvWFbCYqiKuxUgSyx0ow55KiqQtdcZIW9PIQvwaOsSh9tGawP3ZoHUVaFr3zMgGbScEsM6qpGVwYb4e17GZBAFbZTdzis5UzLHiGBqlHIWsuqLQ+TRFXWsuzVwIEAmZJIVaayeksjKHpAMlWZybJbEaPCZQhqpB9kJVSViwzyK9JvlCN7XBZxSt3eJ1Xl+E7DdcdWPTbIMglVOfR5A/F0qypd00RU5XLoMU9R2O0lxaHThFTl9OUkYXTnT6wuJvAfJqXKoSx8Uk53tZLUIZqgqlyuUOeXmIfprTWWzDTDi4mqctCLy02uLFqdZn15sVgYooudtCoPvWCaxaJpzs8XhtHiordcWNex5r3lCI+Y83C1FZqRzEBVhqiEU8OnPrCNOaFtw9OlCj3vJEB4mpidETXFqk7binDaViFO22pITtuKMAu2ys27sPF22XtLYF2z9wgADeaV/bUgNlzouKqnTJWHzGNicX5yol7EEkn30NtZUcVsQg5KjVDl7g2cEVUsHA6nem8OW7G1EXCm7aawFVsZ2ofx2qawFTMVPftrM9hKMNWmsBW7wBahbQJbsdUegZOijTz5x+514IK30XcWVImm8pkFP5DAqWJH+wiHHzrMhB/owaliWQz7tYRZtVWkqWbWVmyuQmaqWbUVW/RrS+ceZtRWzFT86a+E2bSVvz5bPk00O7bSKM5rNmErN1U4MWMaVQVgpiAthypTroqZKuJIKQnTrcqPOSUy1ZSrYhuD0NPn5Ey1qrSmmm5VbItUQlNNtSrfVElXcU2zKmaq6OO/JCiokpw+PRb8pw0mXnDHvBOKqMp/WNZ4YYd4sAerKSNsrRJVDSDpmPFNlXxZrrAiSaIq88W+SrBNX8lN5TczlNwpYcWLN7cybvyHvSXfOiJslOjnTgnGStwEZQEzlcIBYDzCXuVTElXI0GakDGMq8Zl+UlWp9+2mh+3jD40G1RDPZZOqwg6hHh1a1wKSbxqmz6UK4KoSN9Im9cMminhYVc9VJRpL9hyIaUWyB7OGqFI6324qkJ3AW8u7qiR7uWdFliFZX9o75dlKYqyBNao9HZkiEzWogCrZCmjbf3jq1MKejBuk7wjyVMmM5XQdU26ugjCs8qgyVchy9RFtl8qEklyTZypQJTeWQ79dLZuwtGhqMEtVfwkyj1OrmCpU1qzR8dRQVbJ6N4PYi54aqmqTGMsrfwFVm0JWE7T4qjaBLFKpHAKqMtyaORkcVwkIqJp1Wb6okCqZmzs7dK8EFQ5hVTNct9qgwSOkygHSzBw1yD+BV4W5hNMN5J0hqOrOoLkg6z6CKhdIPCOs6ZBtH6mqWdLVzkOWgyCqZqR+QV4FUFUu8NkpBTIpI1IVEPX5aeTUqf8HHRhC11FdSQQAAAAASUVORK5CYII=' + +wild = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAABQUFCQkJDQ0NERERFRUVGRkZHR0dICAgJSUlKCgoLS0tMTExNTU1OTk5PT09Pn4AQn4AQUFBRUVFSUlJTU1NUVFRVVVVWlpaXV1dYWFhZWVlaWlpbm5ucXFxdXV1eXl5fX19az+RUUGvU0G0UkK4TUrcUVH0U1P6VVX+XV30Wlr+YmH9amr/bm7/cnL/eXH2e3v/BJUAFYUAGIQAAKMAAKoAC60LEa8QE7ASGrIaI7UjKbcpK7grM7cpNbgqMroyPL08e4UAZb48Qb9BRMBETMNMVMVUWcdZXchdY8pja81rcM9wddB1fNN8Z5a2cJuqlkJ0mkNyzktfykpg81FS+lNT/lVV/1tb819p/l9g82Bs/2Ji/2ho/21t/3Jy/3t7vHy+gXn2mn3hvH3A3W+Q3XCSgYYAl749mL08vZUAwpYAyrcpyLgq7aMA7K8Q8KQA/qoA/6wJ/68Q/7AU/7Md/7Uj/7cp/7gr/7oz/7499Zhr/5ZnzsBD/8BD/8NM/8VU/8pj/81r/89w/9By/9J7gYGBhYWFiYmJjIyMkJCQlZWVmZmZnZ2doaGhpaWlqampra2tsbGxtbW1urq6vLy8hIT/k5P/mJj/gKfCoZjYpJzYoaH/pKT/qqr/rq7/s7P/u7v/gtWCiNeIi9iLk9qTm92bo+Cjq+OrsuWyuOe4vOi8/4KC/4yM/5CQ/5WV/5ub/6qF/qOj/6mp/62t/7Ky/7W1/7m5/76+wcSDwcaJ/9WD/9eI/9mO/9uU/92c/9+g/+Cl/+Kr/+Sx/+e5/+i8wcHBxcXFysrKzc3N0dHR1dXV2NjY3d3dw8P/ycn/0dH/1dX/3Nz/w+rDy+3L0e/R1fDV3PPc/8LC/8XF/8vL/9TU/9nZ/9zc/+vE/+7N/+/R//DV//La4eHh5eXl6enp7e3t5eX/7Oz/5PXk6ffp7Pjs/+Pj/+np/+3t//Xj//fo//js8fHx9fX19PT+9Pv0//Hx//X1//ry+fn5+Pj++fz5//n5//z4/v7+AAAAwISkTAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABclSURBVHhe3Z15YBXHfcff0wkoQIsQAnNIpGlcFWLqtEGA6tYkMTS2oadLDzdO77vp5TZNL/cIt7ksuWnrxA6JDxK7pooP2rShcVqQkKjrJG0wmKa20GsOgRspAeTgob/fzG/v3fdmZn/v7Vt//rCl92af5sPb/e7szuxM4WoFRF1BlapEBSv6sPqC6laGslb0KfUJ1TGWMla0dZ1DlQ2SaEUb5QCqsJ8EK9ogH1CdfcRaUencQNX2iLGiormCqu4QsaJieYNqT4StqFD+oPorQlZUJI+QgSRoRQXyCTkgASt6O6+QBeC3ojdzC2kAPit6L8eQiN+K3skzZOKzojeinDw+0F9XDBwfpapFIBfXil4OcXJ5e1OhDmmc1z1CVQxCNuWs+ufTh9Ql7Qeomn7IhqzoRT/jHbR53dI+RlX1oXSUFb3kZ39d7npBmvZQZT2kTqLVbtqwztlB1fWQPtKKXvCRE6kYrTJWB2ib8hSbW2dkvp/upSq7JFqNN9MmSTTNX75vuKTK7l9AL2ZDYzgyEq06aYt4Xrd1mMoRI3PpnUyYT7VwSbA6RuXjaOqKO/0to3cz4R6qhANZ0W8uyV9V664pKiMunX3+qY//zX33Pyd/y1KrXdbAR6zVGJWO0LRzWpW4cOTxd24BfrAHuO4/8KUsd8JIszDOajsVDrNYxcOlp9+FRsBtb0Srnp4H4NUTVCgLumW9fMRZxWda64B88/zhHyOnLVter6R6evDbyjAJo7sgWNGPLq1UOECH/KIu+Jy2/Mi1JNWzCt7aRwUzoAmr5ifGapzKBlgu33rK57Rly7eSEwCREbtZjYgcWFGrESrqoyhbkRPO8aSQUUHgkdVI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' + + +b0 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX/Vlb/WFj/Wlr/XFz/Xl7/YGD/YmL/ZGT/Zmb/aGj/amr/bGz/bm7/cHD/cnL/dHT/dnb/eHj/enr/fHz/fn7/gID/goL/hIT/hob/iIj/ior/jIz/jo7/kJD/kpL/lJT/lpb/mJj/mpr/nJz/np7/oKD/oqL/pKT/pqb/qKj/qqr/rKz/rq7/sbH/srL/tLT/trb/uLj/urr/vLz/vr7/xMTExcXFxsbGx8fHyMjIycnJy8vLzMzMzs7Oz8/P0NDQ0tLS1NTU1dXV1tbW19fX2NjY2dnZ2tra3d3d3t7ewMD/wsL/xMT/xsb/yMj/ysr/zMz/zs7/0ND/0tL/1NT/1tb/2Nj/2tr/3Nz/3t7/4uLi4+Pj5OTk5eXl5+fn6Ojo6enp6+vr7Ozs7u7u7+/v4OD/4uL/5OT/5ub/6Oj/6ur/7Oz/7u7/8fHx8vLy8/Pz9PT09fX19/f38PD/8vL/9PT/9vb/+Pj4+fn5+vr6+/v7+Pj/+vr//Pz8/f39/Pz//v7+/v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAV9lm+wAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABGoSURBVHhe7Z3nf9vGGYBNUpRESZa1t+RYw5qWrdnldKRO26TWHrakNt21ZI2kaTSahLRp/uEsSLw4HHAD7x1ADP/4fLF4OMh4BBC337tX/hiRWX36QynGfP9zuEwOQqu/wcmx5iu4WDcCqw9wWux5DxfshGsFZyQEuGgajlVi7pPFO7hwG8YqEd8nN3+Gi7dwWyXuRpm4vl4uK8iUQEDAxGH1AnIkkl+CRAXa6ks4nlBegIYBZfUFHE0sn4EIbfUpHEswYEJbwZFEAyq2FaQnmw8gY1l9B+kJ5xvTBqyeQ2riMXXACtIYbvYWhnu6OmNFV8/Ik/0buECGqo5p9Q9IcrE/nE7FlPToIVykiz/ZVpDiZP8B/IaY0vkKLtQJsfo3JNDcTcLJ8SU9k4eLpfmrZQWfac7vw6mxpuMKLpcGrH4PHynO2+C8mPOAo/XctIJPFJcJkUql2q/hkm2MophrVRyAcxLAKFwzRdWKbYCswBmJYAMu2uZXFSv42eYyCydQdIyvvH578fZoZbwDUuJCE1Mgv+dazUJ+QsPEGzhU4c0kxzpCFuG6bHhW+SbIbvHY/de4nY5TnaO1CJdF4FmtQ26g7QDSaQ7j9JLchosiGFZ/hx8Jn0Bmk75bSHZy1w/HY8AUXBPhi3tsD2A7ZK7SdwepbmKk1Q2XRPjuHvMA3kLeKt0iKUOrB/JETqYAl0RgrY4gb4XsW0jkcR6bV+EZXBGBtTqErBWWIY1PbArrE7ggAmt1AFkNuql3ZmGzL5fN9W3Qd7sX8kXNMVwPQWq1CUkGyy2QlnsGKQZbkBY1SlYt9n1ZgKQKc5Bm1IJbISlilKzmIcUpRWs50yNDyYpUKt5A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' +b1 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX/Vlb/WFj/Wlr/XFz/Xl7/YGD/YmL/ZGT/Zmb/aGj/amr/bGz/bm7/cHD/cnL/dHT/dnb/eHj/enr/fHz/fn7/gID/goL/hIT/hob/iIj/ior/jIz/jo7/kJD/kpL/lJT/lpb/mJj/mpr/nJz/np7/oKD/oqL/pKT/pqb/qKj/qqr/rKz/rq7/sLD/srL/tLT/trb/uLj/urr/vLz/v7//xMTExcXFyMjIycnJy8vLzc3Nzs7Oz8/P0NDQ0dHR09PT1NTU1dXV1tbW19fX2NjY2dnZ2tra29vb3Nzc3d3d39/fwMD/wsL/xMT/xsb/yMj/ysr/zMz/zs7/0ND/0tL/1NT/1tb/2Nj/2tr/3Nz/3t7/4ODg4uLi4+Pj5ubm5+fn6enp6+vr7Ozs7e3t7u7u4OD/4uL/5OT/5ub/6en/6ur/7Oz/7u7/8PDw8fHx8vLy9PT09fX19vb28PD/8vL/9fX/9vb/+Pj4+fn5+vr6+/v7+Pj/+vr//Pz8/f39/Pz//v7+/v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqB9+GQAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAAA0jSURBVHhe7d35XxNJGsdxkgAiioiI4sUI3iKisLizs8fs7LrXzIrKeONezs4oLLDrjGhGBzTmD8/28U1fVZ081fVUH3n15xdD6DT9NpCrq6v7Wr1YR9WrZo57/1tspaRY1Ve4ca77DhsbLUb1E26W/36BLQ4lVX3ELYrR59jqQBLVWyxdmD5iw/0E1R+xaKH6Lza+XVRVuDsKYfNRRIVlCtivIXAKq7BEIfs7DHZB1af4fkF7BoZVUIXvFrZ/wRFS4XsF7i+QBFT4TqEDxVd9wDeKHTBt1T9xdcF772raKlxb+L50NFDFvZ6tP5yfmjg0lq8OH59d2cIGCjkcV/U5roq0Ol2r5LXJuw1sZbhXvgrXhHs6gRXktP23saHhPNUXuCJYYy6/91O7qdfY2GBv2yp8HexNzu8ot73PsbnB4lVvDuN2OW9IwvrGVb3Dl371gqAs1gtsciBXhS8CncNtCtDYLrbZL0b1ALcoRLPYaL//2arv8YXXzj7cwK26tIkWcU2uqop/WrYKF/1uYHm36i1c3WzewVX5ahpb5ydVHcLiTgFUTlW1bWyel0z1BEs7BVE5VVWuYvO8vpKo5rCwXQiVV9VRbJ7X+77WX3HR6yQWtgqj8qoaFF7n9rV+cC/4DWNhAZVXVWUN2+fVJ7y1qmNREZVb1Qq2z6tP+LPaxqIiKrcq4S2JqNrEopWDuMIvryrhv5+i8l5p9ZJq6ywu9JJq64D3fNA7qq0D/rNcz6gsVO+pbFTPqRxUr6lcVI+pgOot1T6gekvlVaoyqVR5lapMKlVepSqTSpVXqcqkUuVVqjKpVHmVqkwqVV6lKpNKlVepyqRS5ZWJamh07ND4xJHJ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' +b10 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX9Vlb9WFj9Wlr9XFz9Xl79YGD9YmL9ZGT9Zmb9aGj9amr9bGz9bm79cHD9cnL9dHT9dnb9eHj9enr9fHz9fn79vb29gID9goL9hIT9hob9iIj9ior9jIz9jo79kJD9kpL9lJT9lpb9mJj9mpr9nJz9np79oKD9oqL9pKT9pqb9qKj9qqr9qqr+rKz9rKz+r6/9rq7+sLD+srL+tLT+trb+uLj9uLj+urr+vLz+vr7+wcH9wMD+wsL+xMT9xMT+xsb+yMj+ysr+zMz+zs7+0ND+0tL+1NT+1tb+2Nj+2tr+3Nz+3t7+7+/v4OD+4uL+5OT+5ub+6Oj+6ur+7Oz+7u7+9/f38PD+8vL+9PT+9vb++Pj++vr+/Pz+/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHJ0rWgAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABVmSURBVHhe3Z1pQ9u8loAnCRC2t5R1WFrKTgtcLkOBoTBwoSwt20BfoMOSBP//P9FxkhNZ8jmSj2THce7zBZAd8IM3LUdH//Enmv+Er+1DtJWXTeDoaExW8PnsAseJ0VrBB7MOHG0IjRV8ph2AI1agrGD3tgEOWwJbwa7tBBx5ALKCHdsMOPgGYSvYq+2AwwdCVrBPGwICdVQr2KMtAYUaihVsb1NAoopsBVvbFtDwkaxgWxsDIv9mVkIrsIINbQ2oBFZQ3uaATMMKSkNU7g6WxocHs8Xw2MLeTQWOMEzdBqygTOV5669cVuld/w1HGaKmo7cqfemE35BNCgsvcKQKNZ26FZTIXL2DT2eXvnM4VgWT1W4ePppp1t7gcCWEFfwssQMfyzqrWEtv9Q0+lH3W4IglwAp+CrgtwGfaAHxv1a3gh4DyIHyiHejDT0LaagM+QNA5urx/9ev+/tf1weexLihsLYtw1AGkVakb9g/TvXKnvNIrv9Z6YVML6XiCwxGQVvuwe4jxozLsIFE+noDNrWMDjkVAWg3D3gpDN7AVcUvunyJ9qE5IWL3AzjKFDeI8Nah87YDdWsQdHIjAt4LvBOewr8QI+pzKrxHYsTUcwGEICKtN2DdgXlftF1QWYdeWsARHISCs5mBfwedIKZ8V2LkVTMAxCAirT7Bvg2Uoj+AL7N4CRuEQBITVR9gXmFPP1MPe0mh3Z2fP4OfTVygCFuAD6TMMRyCItHovP/wqJ1NSA6Uwdiwbl4egPHWsrfLXUFrl+j2UCj7AlhotqxNbW61CoU9pBTUke/+GbXXWoThtbK0GguvvZRTKAkJSXhmdy3SwtfoJZb4UvmvCUp53CVtS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' +b11 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX9Vlb9WFj9Wlr9XFz9Xl79YGD9YmL9ZGT9Zmb9aGj9amr9bGz9bm79cHD9cnL9dHT9dnb9eHj9enr9fHz9fn79gID9goL9hIT9hob9iIj9ior9jIz9jo79kJD9kpL9lJT9lpb9mJj9mpr9nJz9np79oKD9oqL9pKT9pqb9qKj9qqr+rKz+rq7+sLD9sLD+srL+tLT+trb+uLj+urr9urr+vLz+vr7+19fXwcH9wMD+w8P9wsL+xMT+xsb+ycn9yMj+y8v9ysr+zMz9zMz+zs79zs7+0ND90ND+0tL+1NT+1tb+2Nj+2tr+3Nz+39/+4OD+4uL+5OT+5ub+6Oj+6ur+7Oz+7u7+8PD+8vL+9PT+9vb++Pj++vr+/f39/Pz+/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5tFg+wAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAAA+7SURBVHhe3d15Q9NcFoDxSQtlE0VBQUVBXhdAZFwYZYZRX8dxGFFRVJB9Yr7/d3CS3JM0yV1yzrlJmuvzT7FNSn4CbZrl5i+/fscwqqBtwXLpM6rgSdoZLKMygwrmbm+wnIq0Kpiz5cHCFtOoYCYHggXOp1TBDI4EC51NoYKJHQoWvJ+sgindCpY9SVLBZK4FSw8VVTCRgwEgrqCCKZwMCFF5FTzuaIAIy6rgQXcDR04FDzkcQLIqeMTpgNJXwf2OBxiz6uf+q+W56cvt6srVO892z2AJCwEmUcG9uc42r3htrffgOyxlPqEBFdyXzX8yCs/QzjrzB7Ck2QRHqOCubN+vwdztrbf5ExY2U+yJVXBHtu1hmLXVLfiwuP1S1f/gjkzbXZiv5d2WWKkK/p3pvSMoHStU/R3+2e+o3a8TuTZgmdNAJf3J/bwFc7jQcPEVHlTwr36vYQap6wc/CrXghzoLS52mUU3D9HKLxd/iMXhgkO3CsiSpVbswtaoiqw2qRViWJLVqEaZWVmC1QdU9goVJUqrGYWp1j2EqURtU3htYmKRIBV+m/YBp1c3mV5ZboVqBhUlTqN7AtMoKqHao5mBh0hSqdZhWVRHVDtU4LEyaQvUQplUkodqhGoGFSVOoVmFaORnVDlUPFiaNolKg3FepUM6rlCjXVTLqQ7SW4bZKRr2IV56cVqlQ8Tqhyyo1KmI5rNKhQlYrNgWwVGrU6MfL4uHBx1FpUHvBXls2RDFUWlQQrIgpBh5dZUAFhx0xzaAjq64ZUEFwXUw06KiqiRO4My2LCp6JqQYdVVXcIpBHBR/EVIOOqLoGd6XlUcGhmGzQEVWbcFdSARWciMkGHU3V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' +b12 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAAQEBAgICBAQEBgYGAwMKBAQMCAgICgoKDAwMDg4OEREREhISFRUVFhYWGBgYHBwcHh4eDw8sICAgIyMjJCQkJiYmKioqLCwsLi4uMzMzNDQ0ODg4Ojo6PDw8Pj4+GRlLGhpQHR1WHx9cIyNoJSVuJyd0LS10QUFBQkJCRERERkZGSEhISkpKTExMUFBQVFRUWlpaXFxcX19fYGBgYmJiZGRkZWVlZmZmaGhoampqaGhvbGxsbm5ub29vcnJyc3NzdHR0dnZ2enp6f39/MzOYNTWfPT23Pz+8RkbSSEjWSEjYSkrcS0vgUFDuU1P3VVX9Vlb9WFj9Wlr9XFz9Xl79YGD9YmL9ZGT9Zmb9aGj9amr9bGz9bm79cHD9cnL9dHT9dnb9eHj9enr9fHz9fn79gICAhYWFhoaGh4eHi4uLjIyMjo6OkJCQkpKSmpqam5ubnJycoKCgo6OjpaWlp6enqampqqqqrKysrq6usLCwsrKytbW1tra2ubm5vLy8vr6+gID9goL9hIT9hob9iIj9ior9jIz9jo79kJD9kpL9lJT9lpb9mJj9mpr9nJz9np79oKD9oqL9pKT9pqb9qKj9qqr+rKz+rq7+sLD+srL+tLT+trb+uLj+urr+vLz+vr7+wMDAwcHBwsLCxsbGyMjIysrKzMzMzs7O0tLS1NTU1tbW2NjY2tra3Nzc3d3d3t7ewMD+wsL+xMT+xsb+yMj+ysr+zMz+zs7+0ND+0tL+1NT+1tb+2Nj+2tr+3Nz+3t7+4ODg4uLi5eXl5ubm6Ojo6+vr7Ozs7+/v4OD+4uL+5OT+5ub+6Oj+6ur+7Oz+7u7+8vLy8/Pz9PT09vb28PD+8vL+9PT+9vb++Pj4+vr6+Pj++vr+/Pz8/f39/Pz+/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA47wMlAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABQYSURBVHhe3Z35Yx5HfYc3xuCYkoQU2pCkCRRoS5NACKRHWrcQWtrSlqL79KXDJUBaWo42TeqCfMiyJVu+FFk+YlEITUvSxrIl+bZJaRNZliyIdQS95dX+Je6++352d2Z3dvY7++7su8vzi0ezs8fj932/Ozs7h3FLytfxb5b4Pv6VILcyMwsuMIS8WpXARQqQWWHnLIMr9RNuhf2yDq6WJ8QKu+QCXDKL0ArFcwMu20NkhbJ5AlfuELRCuZyBiwcBK5TKH7h+G78ViuQRGJTwWaFAPoGDBW+FzXkFFj4rbMwt0OCssCnPwISxwoZ8AxfXCtl5pyzjWCHTz9zE0I6uzdmio7tv5MISLtDPim0DK+TxFMd7arJKff8VXKWPV0o6EqvT7ThCRum+igvlKemUrZDBMt+HnbNL3XARF8viWuFvlqkW7JppuhdxuSzhVlPN2C/jdAm0Qq2u5UTK0goGQ1jhL4/CZuyTAwZxzQwhVoexRy44j4v2EFtdrcUOJOq3HDw9NTM7fe7IrlZkpUrbMi7bxbZC2qMf5SmsP7qAvSyKE9uRnSancHYXodV8HYpH0zzmv2Nc24JN6dG5gnM7CK2GUTqaXfPYhaF4rB5bU+MyTu0gtCJX/kawg4+rad8WhnFiB5FVsRGFoziKHQKkfQvvxXldBFbTKBuF/3+IYaoBZdKhFad1EVhNoGwEPaKapcMLKJQS/vqFZYWUyxiKymmYQXEx6Ub4QNAKWp1CUTnsj2pueGNTY9seNhTN0u8OCXADZ3WJadXofeiLexyDzovIstiNvFRIysqrUy52Isui4QIyTfMSslIhKaspFOakOK1NyEqDhKyaUDZQvV/vRsZB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' +b2 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX/Vlb/WFj/Wlr/XFz/Xl7/YGD/YmL/ZGT/Zmb/aGj/amr/bGz/bm7/cHD/cnL/dHT/dnb/eHj/enr/fHz/fn7/gID/goL/hIT/hob/iIj/ior/jIz/jo7/kJD/kpL/lJT/lpb/mJj/mpr/nJz/np7/oKD/oqL/pKT/pqb/qKj/qqr/rKz/rq7/sLD/srL/tLT/trb/uLj/urr/vLz/vr7/xMTExcXFx8fHycnJzMzMz8/P0NDQ0dHR1NTU1dXV1tbW19fX2NjY2dnZ2tra29vb3Nzc3d3d3t7e39/fwMD/wsL/xMT/xsb/yMj/ysr/zMz/zs7/0ND/0tL/1NT/1tb/2Nj/2tr/3Nz/3t7/4ODg4eHh4uLi5OTk5eXl5+fn6Ojo6enp6urq6+vr7Ozs7u7u4OD/4uL/5OT/5ub/6Oj/6ur/7Oz/7u7/8PDw8fHx8vLy8/Pz9PT09fX19vb29/f38PD/8vL/9PT/9vb/+Pj4+fn5+vr6+/v7+Pj/+vr//Pz8/f39/Pz//v7+/v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/IkxoQAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABI6SURBVHhe3Z1pQxRHGoBhZhgmIIcgAh6IqAiIiCBmc+2VZLNZRUUO0exu9gxyyF5JYFizg47zu2f7eLu6uuvouvoony/MVPeM9dg9XfdbHe33Ea7VP1oF5t2XkEsKTKtP38Gni8z3kNk4DKsf4GPF5wvIcQSq1U/wCTv4BnKNQbEq9K+JykeQcwRpBWdaxWvIe0Dcyr4L5QPZB2JWb+Ek+/gDGHhEreAMK/knOLhErOC4pfwAFg64FRy1llALs4JjFvMdmGBWNtSQkgiqhsjq33DAbkAmsPoEkm3HtwmsINF6/Oc7WLHq6I3tpasjQ2eLxfDYzOo+ZJDA0wErSIqxd7PaWVSG7jcgl1HeuTq+FfX5d3AJvqCg1O42IacRQitIiHC/uNcp4Dz1Pgys3sB7jOYV+GSh6XoK2cUJrOAtRnMCPldwKhStN77VH+FtiC1SnZ3ldcgyhm8FbzCW4DMWUDuCPId8Rrfa64KP2MBlyHTIO9fq5/AmZBQ+gNFzeWF992B/Z3VmtAJJReER5DrEtSJa9dtwesj4E6xoOF48A8nFYBjyFeJawcuQSTg94PxLOBDQfFiDQ4VgG7KF+JxidVSGs30qtCL86DIcLQJXIVOINxSrR3CyT+0FJMe4A8cLQA9kKYRiNQsne9R2IJVgEc4oAK8gS4gOsr2IPwG7mFKt1m04J3+eQI4QHe2v4BWiB851uQdpNJqUAiAfFiBHiI721/AK0Q3nOoxDEp39ohTW85AhREf7t/AKEbZAygeQ5LI92VvtHpg/hLcuRflpzUF+EB3tb+EVIrS6AikOW8OQVp6sQ1KrVS/IxZKzegYprdYmlv/hUOsGJOWMlNUgJESl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' +b3 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX/Vlb/WFj/Wlr/XFz/Xl7/YGD/YmL/ZGT/Zmb/aGj/amr/bGz/bm7/cHD/cnL/dHT/dnb/eHj/enr/fHz/fn7/gID/goL/hIT/hob/iIj/ior/jIz/jo7/kJD/kpL/lJT/lpb/mJj/mpr/nJz/np7/oKD/oqL/pKT/pqb/qKj/qqr/rKz/rq7/sLD/srL/tLT/trb/uLj/urr/vLz/vr7/w8PDxMTExcXFx8fHyMjIycnJy8vLzs7Oz8/P0NDQ0dHR0tLS09PT1NTU1dXV19fX2NjY2dnZ2tra3d3d3t7e39/fwMD/wsL/xMT/xsb/yMj/ysr/zMz/zs7/0ND/0tL/1NT/1tb/2Nj/2tr/3Nz/3t7/4eHh4+Pj5OTk5eXl5ubm5+fn6Ojo6enp6urq7Ozs7e3t7u7u4OD/4uL/5OT/5ub/6Oj/6ur/7Oz/7u7/8PDw8fHx8vLy8/Pz9fX19vb29/f38PD/8vL/9PT/9vb/+Pj4+fn5+vr6+/v7+Pj/+vr//Pz8/f39/Pz//v7+/v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEN6WYAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABLjSURBVHhe3Z37Q9RGHsCbfYE8RUBARUBQFBEBxbZ3vWvv0bve9RQRxQW37fXaayvKo71rC2x7Ze26//beJvvdySTfSfKdx24SP78Ak2TJZ/OazHznO2/V30TCrL6sJZlPYS9FBFr9ChsnmV9gXxFiq69hs+TzOeyxF5HVf2GLdPA17DUPtvoM1k4PH/0Gdp2BrGDNVPEa9p3hs/oE1ksbH8L+A16rn2Cl9PEdGDTxWL2GVdKI5y7PW8HylPIrWNhwVrA0tXBarlWaT78m//sGVFyrH2FRmvnmbyDTskrrLd3L+2DTsoLitAM2YAWFqedV87nVtPoUCv1US2uz54eHksXw2NX7u1XYQz8fOD5NKyjycbjYYyWV/uUT2Esfjo9jJXz1OJnNwickk/z1U9hTD5+93bKCAg9PemHr5DK4A/vqwRayrb6Cv3luwpaJJnMH9pbnI7CCP3kWYLukswr7y/MqyCoVR8rhLuwxR/NYvYK/XJ7AJikg+xz22eW7D2wr+MPlJPk3CpehCuy1i3Os4HeXOdiAp3durbS392xtNnGPsFuw1y621b/gd8YRfk4NP2TP8sr6OShMCN3osfW7hhX86nILVmfklj31k+pSsh7P92C/GD//FVtV/edYVwmWMHYKsCgRDMNeubzCVruwcgsslTQtVCMUnIH3YN0Wj6HcwwYsTARbsFMMgdVVWBeYhWIf07A4CSzBPjEEVuOwbpPcMRT7OEzQHWMG9okhsBqFdZsEHKpEHazLsEsMgdUwrNvErezvXC50TT2DP2q1p7BCArgEu8SIssqxJ9Wmc8rlnsCftdPknILSVqNQWDvtahacYdWuoWZBApC2mobC2gMo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' +b4 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX/Vlb/WFj/Wlr/XFz/Xl7/YGD/YmL/ZGT/Zmb/aGj/amr/bGz/bm7/cHD/cnL/dHT/dnb/eHj/enr/fHz/fn7/qKioqampqqqqq6urrKysra2trq6ur6+vsLCwsbGxsrKytLS0tbW1tra2uLi4urq6u7u7vb29vr6+gID/goL/hIT/hob/iIj/ior/jIz/jo7/kJD/kpL/lJT/lpb/mJj/mpr/nJz/np7/oKD/oqL/pKT/pqb/qKj/qqr/rKz/rq7/sLD/srL/tLT/trb/uLj/urr/vLz/vr7/wMDAwcHBw8PDxMTExcXFxsbGycnJysrKy8vLzc3Nzs7Oz8/P0NDQ1NTU1tbW19fX2NjY2dnZ2tra29vb3Nzc3t7e39/fwMD/wsL/xMT/xsb/yMj/ysr/zMz/zs7/0ND/0tL/1NT/1tb/2Nj/2tr/3Nz/3t7/4eHh4uLi4+Pj5eXl5+fn6enp6urq6+vr7Ozs7u7u7+/v4OD/4uL/5OT/5ub/6Oj/6ur/7Oz/7u7/8PDw8fHx8vLy8/Pz9vb29/f38PD/8vL/9PT/9vb/+Pj4+fn5+vr6+/v7+Pj/+vr//Pz8/f39/Pz//v7+/v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1va/bwAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABBfSURBVHhe7Z35X9zGGYfNch82YGzSpk2TNGma+Ai+MLZjYzAG47Q52qZJm54QGxuDgaZN0iQ2tnFzEUgccNb736qS9qvRMaPd95VGWg0fnl+8Gh3MY2lX0sw77+yx6vGiZf2mSDz11K9+gqrFUsvqX08qBebTZ1FNBXFWz3+PnYvMkzdR2yhqqw+xW/H5H2ocRmX1MfYwg69R6yCy1XvY2hw+Rs19JKsfsalRPI/Ke0Ss3sFmpvHRKxCoErb6FBuZxyMYVAlZfYdNTOQJHFyCVo+xgaHAwiFg9QPWGgs8bHyrb7DOXPyLUFiZdetV8+ivkPGs3sIKs/nomaqNZ4Vi03mhagOrRyg1nqpO1Sr2+ludPXtooL9YDAwOX1neRgWjfPK0b4WiCBuT+5qKSufoGmoZwfVxrf6GkhDbo604QjEpnfoWNQ3xzW89KxSEWOnH3sWlcw51DeEIOVaqB/WZZuxaaM6htkG+eq5qhcUgV0vYr+CcRX2D4FxhKcCsIVLKs/V710p+VrrXgn0M4Drq7PPkXccKCz7lA9jDBDrXUWsf91zhs89l7BDlxho4i4JCcBK19nnRtnoFnwXlbmwf4RDWVzbbUVIISg9QLcEXttWX+Cy4hs2j3ML6yjgKCsJ5VMvn/T3yBXgIW0c4iNWVzQ6UFIQO6ZnwsWy1FXP/ncf6ygQKCsMSKiawr0B8Eixh2wgHsLqy1YmSwjCJmgkUVpPYNsINrI79hWwcp1AzgcLqDLYNsx9rK9tdKCkO4jLyUFgNY9sw4hY+hYIC0Y+qCRRWp7BtiL4y1m7H3MwaSS/qJqBaXcPKyjQKikRSq17vVJX3oqRIJLWaxbrKDAoKRUKr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' +b5 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX/Vlb/WFj/Wlr/XFz/Xl7/YGD/YmL/ZGT/Zmb/aGj/amr/bGz/bm7/cHD/cnL/dHT/dnb/eHj/enr/fHz/fn7/t7e3ubm5urq6u7u7vr6+v7+/gID/goL/hIT/hob/iIj/ior/jIz/jo7/kJD/kpL/lJT/lpb/mJj/mpr/nJz/np7/oKD/oqL/pKT/pqb/qKj/qqr/rKz/rq7/sLD/srL/tLT/trb/uLj/urr/vLz/vr7/wMDAwcHBwsLCw8PDxMTExcXFycnJysrKy8vLz8/P0NDQ0tLS1NTU1dXV1tbW19fX2NjY2dnZ2tra29vb3Nzc3d3d3t7e39/fwMD/wsL/xMT/xsb/yMj/ysr/zMz/zs7/0ND/0tL/1NT/1tb/2Nj/2tr/3Nz/3t7/4ODg4uLi4+Pj5eXl5+fn6Ojo6enp6+vr7e3t7u7u4OD/4uL/5OT/5ub/6Oj/6ur/7Oz/7u7/8fHx8vLy8/Pz9vb29/f38PD/8vL/9PT/9vb/+Pj4+fn5+vr6+/v7+Pj/+vr//Pz8/f39/Pz//v7+/v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3CowtwAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABLMSURBVHhe7Z35X9RIGodNQ4MCcgnuzO4K3gLKCIojqLM7s9esu7Ozp6jgBbjjXjOOAq4zgzAH7bb9T/cmnW+/qaTeqlSuTvL5+PxCUlWd1EOnk0qdB5oG/KxINJvvIltqdFafvGkUmJcaOaXVV/hwobmJzAbhrW7iU8XnW+TYD2f1J3yiHLxGrkVkqw+Qujx8hZx7SFbfIGmp+BUy3yZohWRl46ufIP8ufqs/I1H5eAMDF5/V50hSSuDQQrQqxSNKDSwcBKuXiC0t8LDxrP6NuBIDE8Hqt4gpM3TLICtElJtvINO2QnDZ+Z1rA6v/ILT0uDqwQpjE1p2Lk2MjxWJ0/OzVtX1kMMj3LR3X6n8I81O7dcQqKtXzXyKXAVo+rhVC/CwdwhEKyuRzZNTHmw/bVtyb/NYEPlxcqkvIq4932lbYF3nYg48WmpM1ZFfAeWg5Vt9hX+BhFZ8rOMcZLVhhT+BRSaRsrTqy7PF5y+oj7Hns9uMzJWABeRb42LF6jR2Pc/hEGeh6ikx7tL4rbHvcc9PPbYdx0k2YL0eQa4+/slbH3ORXsKvmrJswZx4gN8Qb2+rX2Ca+ROqyWJ1Ebjz+cKD5NTaJ80hdFqvKFrJD2N8VtjwGkbosVtYNZIdgrHaRtjxW55Ed4kPZ6gHSlsdKugt+KlstIW15rHqQHeKJbHUFactj1YXsEJ/JVgtI61lNdyuoIGXeIJ+EkVXhC1DIJ/GPt1aFBfkk3loVF+STeGtVXJBPwshqugoK84AKgHwSRlYCL1YvTRZPDZkjolo5bM8XrVIXGSPiWDUa+3PF+r6QLSKeVaOxPoREhQCZIuJaNfbGkaoIIE9EbKtCaSFLRHyr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' +b6 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX/Vlb/WFj/Wlr/XFz/Xl7/YGD/YmL/ZGT/Zmb/aGj/amr/bGz/bm7/cHD/cnL/dHT/dnb/eHj/enr/fHz/fn7/gID/goL/hIT/hob/iIj/ior/jIz/jo7/kJD/kpL/lJT/lpb/mJj/mpr/nJz/np7/oKD/oqL/pKT/pqb/qKj/qqr/rKz/rq7/sLD/srL/tLT/trb/uLj/urr/vLz/vr7/wMD/wsL/xMT/xsb/yMj/ysr/zMz/zs7/0ND/0tL/1NT/1tb/2Nj/2tr/3Nz/3t7/4OD/4uL/5OT/5ub/6Oj/6ur/7Oz/7u7/8PD/8vL/9PT/9vb/+Pj/+vr//Pz8/f39/Pz//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACfdmegAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABMCSURBVHhe3Z3nQtuwFoCvk7DLDLNQoGxoWQXKLrusQAPkXvv9X6TXTo5l2Ro+Gknsfn9KFcf4I7GscXT0n7//InIrzyM/ZIDoSuo/SRBb1d+eaeBCOYis4I0ZBy6WgW8Fb8oDcMVxeFZwfE6Ai47BWsHBOQIunIKxgiPzBVw7IWkFh+UNuPqQuBUck0NAAIhZwRG5BBQa0Fbwek4BiTqUFbyaW0AjILKC13IMiPj8S1aRFrGCF/INuPxjVqFWaAWlSf6cf58eHRnOFCNjX7Yu3+ACkzRswArK4rjnU05WKc7dwFXGaehIrM764QwZpXwLF0rT0GlYQRHN21d4c3YpbNTgYinqPnUrKKB57IO3ZppyFS43Qmb12AvvyzjDjJbE6jknUr4WUxmGVvDfCHcU3pMDvsI1E4RWW/COXHAGFx0isnoqwhsohhf3b58qD7eHs51QkhV63uGyQwRWy3A8oWP5AV7yqV2tdUB5NvgBFxbSsIL/EN4SF11YS96RlWl4KRMMwlURuFY/4GhggNc0Oc1SJXkJFxXCtYp/EFMfUBznLUPV5DpcUwjXKvYxCKQ8rzoIR7SfSbgkgm8FPxFe4Ng64yIp/+bKTJuq04VLCvkfa3UJxwZ0VqCQx0MXHNV2XuGKCKzVORwa8BPK+CSqlfbxDBdEYK1O4VCfCSgKqB2O9XR0zxxQtXxtAI5rN49wQQSp1TkU+Wx3Q1kvaaG8rJSgrN0oWfVHd+EqFAV8r5dkx0nRahtK4lKOs58tJ0UrMi5wAwVA8TpTTmpWRTIqMAclWUXFagQKvFdOzyRTqFjNQoF3CAWZRcWK9J13oaBQKsBPGUPFagEKgg5/cXzzNuhz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' +b7 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX/Vlb/WFj/Wlr/XFz/Xl7/YGD/YmL/ZGT/Zmb/aGj/amr/bGz/bm7/cHD/cnL/dHT/dnb/eHj/enr/fHz/fn7/gID/goL/hIT/hob/iIj/ior/jIz/jo7/kJD/kpL/lJT/lpb/mJj/mpr/nJz/np7/oKD/oqL/pKT/pqb/qKj/qqr/ra3/rq7/sLD/srL/tLT/trb/uLj/u7v/vLz/vr7/wMD/wsL/xMT/xsb/yMj/ysr/zMz/zs7/0ND/0tL/1NT/1tb/2Nj/2tr/3d3/3t7/4eH/4uL/5OT/5ub/6Oj/6ur/7Oz/7u7/9vb28PD/8vL/9PT/9vb/+Pj/+vr//Pz//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYmWdhQAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAAA2DSURBVHhe3Z39Q9M6G4bPGN+ICA6Rj6PgJyKichT1KIKCeJCPF5Ct//9f4ru197q2SdsnyZM24frFrUtKLrfdzdok/evPTYRoFTgEmlREgRV24iRoYh65VqjuLminlBwr1HQcNFZEaoVKHoAGZ5FZoYYnoNEpRCsU9gg0PIFghZJ+gbbHZK1QzDfQ+j4ZKxTyEAhEpKxQwFMg0SNphVe9BRpdElZ4zWMgkrTCKz4DkxtmFWvFVtjuOZDpW2Frlqv9rb/n52adYq61vLl7gQZmiWwKrQ4eNhuusrjbQSvThDawwqYUh3exA0eZ/oKGpgh1IitsSdLeGEJtd1m7QmOTFFldzKGm00wdo7kJCqwuZlHPcSZFrdgKzwdceSLV1TpBkwfkWq2hjge0hCjMs/qCGl7wGo0eEFnhSczvibD43Fk5T8KStdL8hWbHyK22o+LzeFrEelS0Vp6iLTGhFR7HdG5HpX2xGhGOWjKrPZT2xaqxjcbEyKxeoLA3VitoTIzMagGFvbGaRGMGiFadURT2xqpxhtbEiFbnKOqR1T5aE/OX8AH8haIeWe2iNTGi1TGKDqy+DGf5hFeC+yhbL5/RmhiSFTbEjF/jlfh9rRceq+d4IT4I1AyPVf9HTTvqMNYOi9U9bA/+xYa6YbH6iO2OZAWPlWtZwWPlWlaoWbV+g0/YAFzLCjWrHJzLChYr57KCw8q9rOCwci8rOKzcywoGKwezgsHKwawwtxpvo5RDWWFutY5CLmWFuZWLWWFs5WRWGFs5mRWmVm5mhamVm1lhauVmVhhaLaCEY1lhaOVoVphZuZoVZlauZoWZlatZYWTlbFYYWTmbFSZW7maFiZW7WWFi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' +b8 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX/Vlb/WFj/Wlr/XFz/Xl7/YGD/YmL/ZGT/Zmb/aGj/amr/bGz/bm7/cHD/cnL/dHT/dnb/eHj/enr/fHz/fn7/i4uLgID/goL/hIT/hob/iIj/ior/jIz/jo7/kJD/kpL/lJT/lpb/mJj/mpr/nJz/np7/oKD/oqL/pKT/pqb/qKj/qqr/rKz/rq7/sLD/srL/tLT/trb/uLj/urr/vLz/vr7/xcXFwMD/wsL/xMT/xsb/yMj/ysr/zMz/zs7/0ND/0tL/1NT/1tb/2Nj/2tr/3Nz/3t7/6urq6+vr7u7u7+/v4OD/4uL/5OT/5ub/6Oj/6ur/7Oz/7u7/8vLy8/Pz9PT08PD/8vL/9PT/9vb/+fn5+Pj/+vr//Pz8/Pz//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbZCRbQAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABOaSURBVHhe7Z17X9NMFoDtjbYgyE1WkFduioIIAgLLRXhFeHEvgoC7C+Vtt/n+H4Jt05OZSeZMcs4kbRN/+/wjnaSYh6aTuZw58+Qxmr/Av9mBYOWkDrgwM2Yr+A3pBa4Tw2gFb003cK0aJit4W+qByw2AW8FbMgFcsg/MCk7PCnDVKroVnJsl4MolmhWcmC3g2gVBKzgta8DVe/it4JwsAgYdfFZwQjYBBxfVCg5nFbBo8wtZKVqKFRzLMCCiWsGRTAMqv5iVpyWsoDhA/Xxr4fn4WLqYnFk9uoELDNKR8ayg0M/lcimXVib3G3CVflwbsIIiHz9m4BeklOonuFA/bR2z1af0fk4e09h92NbpWEGBQuM3eGeqGfgKl6sQYtV4Ce9LOSVcC7dqZkSqpXUGlywxWm3AezLAUA2uWeBZwUvB9wK8JQsswkVLDFbj8AaVsZXDy5vrs6351FWNX+CqBR0reCE4hdMVXsnbt7Y9BIUpYRouTIBbzcLpguoxHOlQW4LylHAJ1yVoW8GPgps8nO0xegdHBHvBU/rKMlyV4E/Eag9O9tClHGc/TVojcFESxGoZTgZK11DuYxWOpgKtckesJuBcYAeK/TRG4XAaOIWLEiBWA3Buh1EoDfIFjqcBrfGOWPkfwfhH1WpUjcAJKWATrkmAWMGpHYoPUOo4n6dK1bey7f8RzkgBG3BJgieP/4GfBHBqh+dQ6LUNh37AS+fcfZ0KEKt/wU8COLXDWyh0vkPBDLx26ump3NlW21DovIWCnLgH09NwYluJyuIVFOTOocAZhoL+w7YS1cs7KMjfQoFThZL+w7Z6D4XOJRS8hNdOswgl/YdtNQGFXk3+VLSfvrqvUwHbKidqcudkujy0Iu4/5w2ckAL4VutQGqRRgRNSAN/qWROKA5zA8TTAt5JPLB/1FDUDbayeoqP0h3A0FfCtxg1zKrspGl1jWw0j3fsOu3BGCuBala+gECE9nXymVUHrOys0UzNtwrTyj0ndX9/5qvm7tAzj8qyKsiXhPKwPtksWL+B1m/ed0/oOz+odlLTYFk2JSal67x+46Rssq7ys/9RBimGplZIPi2U1CQWOsw8lHYZ/QrFzBiV9hmW1CgXOfaArJQ400tHHYlmdQIGzDQUelToccF5ASX9hWYnh6zEoEOzBgZR8sThWBXjt3EOBZAmOOFtQ0F84VgPw2rmGAslvcMTZgYL+wrEqwWvnFgok83DE+QQF/YVjlfeaR3Wt0yEez+kYbGfVFmK+dR4KBKLZtAgF/YVltQ8F2sNWPp7TMTfHshIzB8EAjAModh7SMYPAshoW/Y7rp1DksgKljvMZSvoMyyr3O5T4taSUMw1FfYZnNQslLW7fQa9jQtx+cuy93/Cs8t+gqM3DzuLs3Ns/4JXLApzXDcojo+MTz6emZ15MjvnufwSeVW4Uj9gFjuGsBBkYebGwsnV4di3azy61041XIWpMKznRg3Cf5ARWfmzp0+mVnFpHuPtsCm/mWuU/Q6FOPamqIv9sYfvc/9mYuHqLjilwrXIFk1Y9kbjw4bnNr1q8ThgPn57BWxXYVrmCaGH4uI//SQ0sHN3Db+PQ3NI64HyrXG4OGZQ+ifudGlo+Da2JwriahF/iYWOVq+4G7vqrmFX62Jo6qsin+dHfi7Cyaj08VuV4e/041s2Xn9pEQ/N4XPpappZWLSoz7z/t7W4tjcVq0I7tGOdYeDw8h9/Yxt4qAQpzeki9NapWH62qa8qofQIoWn2zmjywrvJMSK3+WPlnUhLjwavh+2E1uJFQDaFxDRNovbca2KA18ayA4cheWxXedetz6tBpjPbYaj6BB24oN24bvqdW012pI/y4CyV6aDUmx3K6SXuuqWdWQ/uGqK6kaQ8z9MiqsN7Fis9Pc6hXVuPf4Vf1go3eWBU+JN44CuOu2Aur0R7UfD6Wum+VX+3pB9XmoutWIyKGv4eUu2uVf9ezqk9luqtWwwl2dTm876bVLGu4MkE+d9FqtUeNCZ2brlkVlWmtnqMFpydkNeib1+o1h/CvIBmriWSHj7iIMDKPRKzm+1KhS7Q+TxJWpgUyPUPLBRHfquRPqIBze/xhZfnNu/c7F91oUCFru2NaDUX2Oq7XZ9vh1UBx4s1x0s+AxK3k2jkDX2b16YahhEcIk74Do6R2DAuaiotJjj4lbBUhdT0F5yGUTAv8LUi2DoyQisgpNpPYQy7R51W4VC1ykn/AHPbAI0mrCKnglDRC4QhOjon2bLG3ii+VmFZy7cAkpJLS2oV/BbZWERUFOftbIYkRqS34V2BpNRguxVjz+Cx+E+ohoV5jMbw71Zl/ISKW0ljzIyGriI4vK8wkH3uw7WsyVhF/Xv9qrUiewdusOUzEajaiza0tAYog7kTXZhJWo6ERlxYL6EQiEEtWErCqhFd/jjMHJ5LJyxwaVszHtyogWUt9/MQX6E/tnpwevSvDKz/KWlcbpuJbRXYggssFXZagx1zfwUKdq52DtozEttIyEGpgEZHKw/8W60fG65OU4lpNRw85IFfta9FgWrG6JA9x568q0eMNNX2YQqys6+DlFlMIC5uP5FtcK8LfFEnAGmxe6ctxtTSoHHZiWgX+6Ch6ZSFTOgFHcEAyCEeseB3PapASfr4OJ0u0nIV61i2xMNSG8XhW2vAAxhqcLNGbwlo2O7E02YJ6IZaVWPocir7aW+t/69ns8nDAhj9iRZHoybVRPsDpEv25rbUwinDAhtYXOYaVNkCKswmnS+bgiOAbHJBU4IgNi3Gs3sDRKH6H8yUFkQ4D0NNQT8ERG0ZjWD2N6H4IbuANCmtwCAhmy2gR3Q4z0l7ca20V1VKX6GMWZXV5pNNEGor4Hhok2r05Wyvq/ddCXcABVBStJrbIPUb4Sft7bGlVYsw3YQkHKuJR91Nb09+iEmOarv37LK0+wCEKWnp3l5GtVsOkeTaHdiljfK3cLoKdVZVaVbggt6BLccC0yCnGDejm3rCz4k2gsTN5PIU32uD+Z1ZWI7zbvs5NWhxn1tGdJLOy4vZUmZkFTZk/KdTc76mNlUz7TaSJLOkNIU73vpNI08aK/13WW00hxGktQe4XCyuRpYgBI8Nv2bSXGoVGpyHDt8pre5AQ0DvERp7FsYKbgm/1GkoZNFhj0hV6E1MD7gm2VYE/APnATOlWJI0cYDQhPoptpe/DFMU9caJbUtDHAGi0OvcubCv2ZPQDd/aqRd5Syxsj4VrJfFJE7PZuK9rNonrPRa4VntwiBLHpA49q1KQYhkgxxLSqcsMGgvsxkQnPu4Mj/oJMq8CIQySskAQ//ACFB/Gf8azkfhREYmS+4AcoyB4Pz+oVlFAJzfxYrpZDM66OcO9B2YbmWTGf+g/GrRBGV8/c7vT9l/VZfNq4hRaNFI4ypcSyMm19ZcLQ+svP+ZqSt2uGTDpVXqy/knGcZcXso9bwCfoXWmh4YxUfwNAuLgx10IdjVWaNwRg+qvwa1tM9R0OnK5xvlprznmPFHc/CdiMytVxrgc3rOjAaTnX1O8yxCsujj4DtcJM3rrZAtRihP77HPcOqzKxpsZFmLXRUUkNuQsbz0TYf0wK8JNJEmhWhv+IcqTLwHVkQ/Nu/MayYcb5eX0ehHD46j+xxQX7siz3GXOhWyuZ/JPQ5xqj5m4b+3KLOOQb+hHQrbtCettFt9BdTn+7Xt5/FCaw/oVuFfNFR9D+8TAJs4FZvPNH+1+B+TmSrfHAyN4K6+y4f0Uku9M+X1PVpBvM8k624w9B66tsyHAlB3/ScVPFq4/hkq4/wgoo+CP0CjoSg7xBLGZ6uK+sJO5CtuKGw+jyIkpjZhL71AGUqS/+EqVbsGHN9AwRKd0nrRhJiVe/0xz3Vij2KoD+uKP0Yre9CeGB522EqUK3Yg8T6Z0WJodD+7NGf1TXSl6ZaMet1bMiCUN80tSuM/l5hkQ1EqyH4kY6+NoRQSeuPg8jvM9LcJFtxB5ew/N+ECkf/U0SNgNfRyVmilXZaJHpQVj66eawPX0dFFq3AeX6IVsRYQBW9HRjdldE7jhHtwDPiMA5uZZG1Wp8LiWwnIJPi4W3HB8NGzTSrYfiJA9KtiGre6n+IYnjoxTKcFoRmpcWUEkC2C4j4NRf67RReWSALADrQrLQIdAI/4X9QCf1mNZB9Y0K7ZDXjzgc0K6tZdeSeD11Wgm3NGfpneA0n6ZCsCHUyAhbtOGUeOj9CqrPQScCQgBuSld2iUCRIuNXJMmkdYVMjYT3he61XJSFZMUcCPfSA7hZT+E24h0mFxnaEpe8nWXHnTQE9+L5NBfmu3OH7wobVmaGhlCQr2zhsQ2jqXOC59fDJMHsXUkmdYp+tgGRFSbCEYdz1eupQ1j+XhnWoudwYnIHww/SeDiQr6+QM5uQ3+WcLH7d3tlZemCf58+Y4xFpEGCXJynpFqJcv3QrzouGmPm7oh2Il9v7jE2OjwxHzoy1yK22KVZxFhtYBF3lzxozoFAwUq3H41wbr4BjzoNYfoVEaLhQrZd81Pgd4vy6KCWNb6ZawIxDFirF+B2HHRmvcuLqwHthUEYVixVnqgmChZZZq+icVDVCsuDNXQdhaIVK0uGSKlXVwrwdTK7YUycq3Xs+KA05NOGsc+qFKkaxsgkUD3JCfWwNis2wNshTJyrrBpLJDazyF5BCkS5GsGGsYQ7gmxOoPhMwGMaRIVjYb82EcmpYCAuWVkLuCI0WyshqLQfn22nwfjge34PPBkiJZ8UIqw7nfRCMBi/PhscM8KZIVM9Ysip8nH2aVtlxh/M3ut4i+To25gIFiFWOZoZHbk4Pd7a2d/SNKxuUfvBWEvb8DbTgNH6RAoFglVQdass1vHVOsEnkK29JgLIkUUKz6mez/LiRHsxmKVYxkE3H5HrVDNw7FipbLpxscW468Uay4CymSorlhMzjQhmKV70/VfsNcuqpAsYqTbsKeXdsxtxYkK+aSoSS4tVrk6UGyipX3zop9dnPCB8mKGn+dFD/xSTo6NKs42Wn4HBqX2FGhWZVoidoS4Y7XlUKhWdFXocSleUAYRo+EaMXMf2PNKWUUPRqilfXUMItvkbtYEKFaDXb/m3WzYNtA0qBaWeS14HG/Ej3ZRoZs1d17sP4x3mM3AN2q2r2OfnOPm10rAroVKWWvDbVtdIgwDgyr7jRyr5bjxGQY4Fglr9U8jpEqIgSWVcJa9x/tRiWi4VklqXWxlGBVHoBplZTW3W7ErE84pamVw6/nZycbr/BPm2uVW4rfyPix+TxWK+L5gTI2/x2bPGJb5YaYSQYCXLxHArw5PA/G9dXeaxGQfKtc7o3tNF3jy3JICDCJ4kek93ARnDOxscoN28S33xzMxxg1Aqr4ooxg0jsrq8CtHcnt8dpM7F57m6ppACUwF2lp1foPPpCmSu5+/6BuDxqPinlUyB/fZG2VyxXmjkLiS2pXp/vrhorXlrCEKzW1gRzDqk1lZu1Y/czqP74ebq7MT410oXEXsSRIXRce08qlMFAdGhqslEvFxDqzGANqNMvl8sTI2MsjtUJUMrokYdUjlFVL597EwqBy/coC1uxYKZtinSr3tzK5JudQsmMlB/tVKVVLbiGTHStxpY3Ao0/UjDLjQnasRPMzmD5S5hMRz5HMWOVFX0FLsiViTUUDIzNWInmCmyzfh1geJhbzZsZKJE/Q16qJeHuRlOT/Vn1F3IF62gKxXVv27sCCCI/Q+tIixEAsD82MlVzkGMzdIhcKinXX2bESq1XuA/0BseBDrpHPjpVMUnXs6xq8FL1yuTg0O1ZF2RFRM1hJKSUvTnas1NWbn71BpdKylLqUH2GGrIpKp7u5P1UpVMa21CFXZeQiQ1YRmXHUnB9ZssqHLQTzLYzOklWuZF4J1vQFNWTKKjdkTEzmj6TOllVuBB/nDIaHZ8zKkEw9uC9uxqzy+LxFMD1QxqxMSXcDyZ8yZqVs4tu8U0K3G/7QmmxZlcR8YHN9MFeYu4JXwcw72bIS8wcwX1UVWv7kYNmyEiGl3vdIpHNoQEGHbFmJXYK8lmxehIz5gjeyZSVSOYmJAjGl4KsuMvpZeW2JAVEP+rr92bISY2Tfodsh5rT842nZspqBK/KSS8hccHKWp41u9dd/wE8CODUFyBvOuVicmN6T3Xt/Lkvks/on/CQITSnWW0xpUeTWVy5absonj3+HnwSJBvrGw5T6LJDNSku98OTxb/CTwGoZaJfAl3b8DPzhtUX9Tx4f4ScBkiq8b5TQ7PeBvGf6kkXEypgwrx8MI4FGwUTN2n36iFjddS+U1ILhYJhRU8vlKx5rHm0rTQvbR6h/lPx1waU2T5zXdr1FrS7g9LQwIeP4viExyXraddQKSfDcZyq/rX/+crLzGttjNa+npsStbuNHYfYO7Vvl/Ola6VrRiQhTw5hsRnk8GqxsN2ntPYNyLENgtDKmQk8ZmNS/weq/8FolMsVnGhhGpFofVccK+7Cc04SXfnWBZSzSvu3TsUK1am+7EU2bHJP4qoi2DlihWk5ti5sZqWeUFg0ZlF0bzwrXageory/Nz6WLxbd7303LtDsyUVYZA2SE1S+hBSqK1S+gBSI+q8x7gUULn1W2tcChjd8qy1pg4BKwyqwWXD4QtMqoFly8h2aVRS+4cAlilTktuGwFzCpjXnDNKrhVhrTggv0YrDLjBVcbwGiVCS+4Uo0QKxd4ezqBa9SJsnKBX5Ia4LLMkKwyxuPj/wAMTgGEBmcXmgAAAABJRU5ErkJggg==' +b9 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX/Vlb/WFj/Wlr/XFz/Xl7/YGD/YmL/ZGT/Zmb/aGj/amr/bGz/bm7/cHD/cnL/dHT/dnb/eHj/enr/fHz/fn7/gID/goL/hIT/hob/iIj/ior/jIz/jo7/kJD/kpL/lJT/lpb/mJj/mpr/nJz/np7/oKD/oqL/pKT/pqb/qKj/qqr/rKz/rq7/sLD/srL/tLT/trb/uLj/urr/vLz/vr7/ysrKy8vLzMzM0tLS2NjY2dnZ3Nzc3t7ewMD/wsL/xMT/xsb/yMj/ysr/zMz/zs7/0ND/0tL/1NT/1tb/2Nj/2tr/3Nz/3t7/4eHh4OD/4uL/5OT/5ub/6Oj/6ur/7Oz/7u7/8PD/8vL/9PT/9vb/+Pj/+vr//Pz//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQLQ3wAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABNHSURBVHhe3Z1pQ9s8EoA3CQQKFMp9lqaQQqFQyrm77x4c5aaw5Sbk+v+/ouskE1m2RvJIchKL50uDbKd+EsfWMRr97c9bhG5VTQ5wRnIirOBtEgicII7cCo5OMHCiCDIrODDpwNmGkVjBQQ4AJxwEs4L9nQFOm0O0gl1dAs7cR7CCHR0DTr5J2Ar2cg44fSBkBfu4CBjUCVrBDm4CDjUCVrDZVcDCg7eCje4CHgEr2OQyYMJZwQa3ARdmBcWOAzIRVuXrnYWJ0eFkMTq5dHAHJximIdO0gsIgT6u9qaQyuPUKZxmkbqOwevmchndIJtlvZTjTADUbsIISnuN3cHRyGb6Bc+Wp6UitluHIRJPZh7PlYVbwN8cSHJdw0ntwvhxyKye+qRrpAzhjDrCCv3x+wjEO0H0P5+wjsXpJ7g1dZLwCZ81oWMEfPjk4gKNnZu3k9uHh9ufKVDcUJYVNOGsf1OpReE6NHXCPhuL2EBQng37xy8KsVmD3Jh+uYAPjuA82JYKfcFYMzKrcA3s3SK8gj/DXz7A1CUzCSfl4VvCK8Qt2btB1BsUhdpNTncoIHztitQU715FJVat7ydH6BafEQKz4iystlfK+Ldin82zBGTEQqzHYt8YqlKHMw04d5wucEAOx+gD7enxA6/pNXpJSq1+AE2IgVtzTiL9gb/MD2Z7BlUf4s8YB7NZpPsP5MJRW41DicTsJZem5ZyiqViv9UNhhEKv/wSuGb3UIJZ4UVzMc9LXWoajDIFZ/wSsGs+plvypeitd6ScbdHbH6B7xiMKs5KKhWJ6AE8H+d3J2lgyBWf4dXDGa1DgXV31DQpKsAG6oLUNJZtKzYE3gRChgbsKG6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' +g0 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0dbp1drp2eLt4ebx5erx6fL18fb59fr5+gL+AgcCBgsCChMGEhcKFhsKGiMOIicSJisSKjMWMjcaNjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cnc6dns6eoM+godChotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatrtausNewsdixstiytNm0tdq1ttq2uNu4udy5uty6vN28vd69vt6+wN/A0NDQ0tLS3t7eweDBwuDCxOHExeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e5+fn4O/g6Ojo6enp6urq4fDh4vDi5PHk5fLl5vLm6PPo6fTp6vTq7PXs7fbt7vbu8PDw8Pfw8fjx8vjy9Pn09fr19vr2+fn5+Pv4+vr6+fz5+vz6/Pz8/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiD0LYAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABGuSURBVHhe7Z39XxNHHsebYKiI2uJD42FV1BYLRcUHUHwAaVEK9YHenVQtLRWxoJ53Jz6gcBXhOGLIH+1tsp/Mzu487MzsZDfrK++fYHY2mTchu7Mz3/nOJx+UKNUNaJAcJav//Puf9cM//v4vNEtMiBX+QHUIGshHZoXz6xY0k4PQCmfWOWhsEIEVTkoBaLAfrhVOSAloNA3HCpVTBBruwVqhZqpA0wlBK1RLG2h9lYAVKqUQCLj4rVAjlUChgs8Kx1MKJMrQVjiaWqDh4FnhUJqByUdvhQPpBi7ECsVpBzawQmGQzfmxk3u2NefqiuZtX/SOP95EE/24NrD6Lwr9rI3vydQt+RvraKaPig6sUOSjOL4VL1CntEzwPq+KT8XqfyiheX0EJ9cxx5bRWArPCgU083X+Qbm0PkNzKSRW6ZDialWt8CvFs5RIOVov0WSC0KqwD+ekgINFNJogshrEGQGyuSx+qieuodEEgdUC2/hc98jMinPo3czV7maU1QlbXrutJgis+lCf0DZaNqqyMroL5fXBJbSrimuFXwgrgQ+jeTz4r1u8Xk+f17YNNKsK12oMtcEh5irj8KoDR+uBn9CoKlyrblR2OclcYyoUe3G8DjiNNlXhWn2OyhUEUnWltQ9NIjhW+InwJ+pW+EYk5Wh1oU7iZJneO2s1h7plWt+ikMfKdtRKnOdoEYG1eoCqZe6hzGV1aRU/uUyhVuI8QYMIrNUMqjp0oqjM8vBOp2T7lSX8XuaYWy1xHqE9BKnVNIqcL1F/E8qa+t6jzFc1UbSs9pBLRfEEisr0eFp7UZQwWlZXUVIqnUSJSw9KS6VRlCSMltUfKCnNoqDKDMpL8yhI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' +g1 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0dbp1drp2eLt4ebx5erx6fL18fb59fr5+gL+AgcCBgsCChMGEhcKFhsKGiMOIicSJisSKjMWMjcaNjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cnc6dns6eoM+gotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatrtausNewsdixtNm0tdq1t9u3uNu4udy5uty6vN28vd69vt6+wN/A1NTU39/fweDBwuDCxeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e4eHh4uLi5eXl5ubm4O/g6Ojo6enp4fDh4vDi5PHk5fLl5vLm6PPo6fTp6vTq7PXs7fbt7vbu8PDw8Pfw8fjx8vjy9Pn09fr19vr2+Pj4+Pv4+/v7+fz5+vz6/Pz8/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAl8giSgAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAAAy2SURBVHhe7d35QxTnHcdxFlwUQZCq0WokGK0GxaLUqxqNFVHj1RZCRaNEq8YetlhUAhWKpawLfzWdmf3sXM8c32ee7zPHZt6/uMfMw/OKcdnjmdm2TUIbeQpzioyi+sM//5Gn/vj3v/wVMwsrWoX/PHkMMwwuQoXdcxumGVSoCrvmOkxVLESF3fIeZisUpMIuhQhT9hWgwvZFCbP2JKqwcXHCvN0JKmxaqDB1J58KmxUuTL+ZV4VtChgAyK3CBgUNCCuXCvcWNjDMHBXuK3CAGLWSymHZKtxR7GD5eapm74zu6+6s5quuXcPjT+uYoTdgmirc6qk2ebCS23aOLWOanhqaCNWDXgyQ06pXa5ipO0sDFW5ytTyCnXPcgTeYrCuL01DhFlfz/dgz11W/x3SdLE+IqhioUFaw6kNBUAbrKaZsZ6tw3W59CPsUoL4VTNouTDWBPVB7J9qCG3LVKCZtF6Ja6cIOjTrtv+Qp3JKvfsDsmoWobmDzRg4qp6qvMDu7hgpXmtV3YXMrFyqnqvb3mF6zQNUTbG3lRuVUVfka07MzVbhodwUbm3lQeVUNYHp26wGqI9jYyIvKq6r6CfOza9v8Hy41W9+OjQVUXlWVV5ifXZvwV7WCTUVUblUPMD87UbWITQOejORVNYn52YmqBWxa2YsbnPKqmsD87Cgq+5lWK6leD+NCK6ledx9qXGgl1evuSuupDFTrqUxUy6ksVKupGqgWUwHVWqpuoFpLZVeqMqlU2ZWqTCpVdqUqk0qVXanKpFJlV6oyqVTZlapMKlV2pSqTSpVdqcqkUmWXgaraPzA0fHJk9My5C2dPDR92lhUElm9VR9/BoXPX7j+eFRYK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' +g10 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0dbp1drp2eLt4ebx5erx6fL18fb59fr5+gL+ArKyssLCwt7e3uLi4ubm5urq6vb29gcCBgsCChMGEhcKFhsKGiMOIicSJisSKjMWMjcaNjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cnc6dns6eoM+godChotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatrtausNewsdixstiytNm0tdq1ttq2uNu4udy5uty6vN28vd69vt6+wMDAwsLCw8PDxMTEyMjIysrKy8vLzMzMz8/PwN/A0NDQ09PT1NTU1dXV2NjY2dnZ2tra29vb3d3d39/fweDBwuDCxOHExeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e4ODg4+Pj7fbt7vbu8/Pz8Pfw9vb29/f38fjx8vjy9Pn09fr19vr2+Pj4+fn5+Pv4+vr6+/v7+fz5+vz6/Pz8/f39/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAji4xRwAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABaPSURBVHhe3Z37QxRHnsDTg4P4QlEUJUFh77EXjFl8EUEIPoKiRAxrlN175zZ3t7cn4iMajc94BzEnj102jBn6j62bnvlOVXV/v1VdVd3T07OfX4CqmqE/0z3d9fzWeyw7fArIS5csrbJDZ/UOPs58svk/cJgESit4bb6BY0UorOBV+efdX8ERh6Cs8n3lRdmEo5YhrKB06/AjHLggavWPULK1+BqOvk7Y6u9b70TV+AEEgLDVT1Co9Qh/u0JWm1CkJQGHKrIVZLcqYBEgWUFm6wIeFYRVS19+NcBEsvoj5LQyP/8JZLgVZLQ24MKtILnV+c+aDVhBYutT09FbrdyfHOzsKOaLjp39FxaW4Aij1HRqVpAUgY0WvbzSdvoFfdOu+qitln4Fb5BX+snD/olbQYLM5vw2eHF+aZ8tw9HKaKw2z8Er880pooH7f2AFf0psTsDL8s5JQqtm9Vv4S+IivCj/DON7xv9Wrf4EfwmewEtagdtwzIJKU6tiBX8IVvfAK1Rs2QK/5IAOfPy0lfpL1dY7Mvt8tXLnKa+9vDHamwu543DUgsDqv+B3zmo7lI/ywa01KAJs3D4MWU2kgE5LYIXuIteheJitY68hPwQb74ACTeMCHIqgYgW/CbqhdIgTqoqX//Y0FGkW20pwJBzCagkKy+y8C5kkD3ZBsSaBLiLC6hsoK3HqLeQpWB6Ggs3hSzgMDmF1GcoKpiFHwwwUbQqjcBAcwgp97jcgQ8utApRuAh/CMXAIqxNQts4spAuW2WLwzArzJRRvAn1wCBzCagjKAlOQDDy5MLgjSG4/NhN55XS1eDP4AI6AE2s1IJ+U5Wuhu/6uqdBT+SNIzhxrq3Y5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' +g11 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAW1tbVapVVqpWV6tXWKtYWaxZWqxaW61bXK1cXa5dXq5eX69fYK9gYa9hYbBhYrBiY7FjZLFkZbJlZrJmZ7NnaLNoabRparRqa7VrbLVsbbZtbrZub7dvcLdwcbhxcrhyc7lzdLl0dbp1drp2d7t3eLt4ebx5erx6e717fL18fb59fr5+f79/l5eXmJiYmZmZm5ubnZ2dgL+AoKCgoqKipaWlqqqqq6urra2tsbGxtLS0t7e3urq6u7u7vb29vr6+v7+/gcCBgsCChMGEhsKGh8OHiMOIicSJisSKi8WLjMWMjcaNjsaOj8ePkMeQkciRksiSk8mTlMmUlcqVlsqWl8uXmMuYmcyZmsyam82bnM2cnc6dns6eoM+godChotCipNGkpdKlptKmp9OnqNOoqdSpqtSqq9WrrNWsrdatrtausNewsdixstiytNm0tdq1ttq2uNu4udy5uty6u927vN28vd69vt6+v96/wMDAwcHBwsLCxMTExcXFx8fHyMjIycnJysrKy8vLzMzMzc3Nz8/PwN/A0tLS1NTU1dXV1tbW2dnZ2tra29vb3d3d3t7e39/fweDBwuDCw+HDxOHExeLFxuLGx+PHyOPIyeTJyuTKzOXMzebNzubOz+fP0OfQ0ejR0ujS1OnU1erV1urW1+vX2OvY2ezZ2uza2+3b3O3c3e7d3u7e4ODg4+Pj5eXl5+fn4O/g6Ojo6+vr7u7u7+/v4fDh4vDi5PHk5fLl5vLm5/Ln6PPo6fTp6vTq6/Xr7PXs7fbt7vbu7/fv8PDw8vLy8Pfw9PT09fX19vb28fjx8vjy8/nz9Pn09fr19vr29/v3+Pj4+fn5+Pv4+vr6+/v7+fz5+vz6+/37/Pz8/f39/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8fCpXwAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABEwSURBVHhe3d2LnxV1Gcdxm2Vb1oW4qHhDXE0NCTOjzEqzBCVDRDJQFBAhBC+gYIpkVl7SzLJENPKGICCoWFEKiCAgSoqKm5eFbXf+lW0u3zNnZn6/mXmeZ2bOmV+f18vXOWfOzGHe7tmzc+Z6RP//Y1mq79736P0P/7NK/f3VV3934TcxewmlqO7+xK5yfX/+OmZULUn1YB8mrnSvn43ZjaVXvYupql/fDzHLkXSq9zCFIWlcqupvGNmcejDn9eKqbxnx+xTvMcx9rZjqjxjNtD7H/KOoypxPCaVzQfCKqD7HGEZ2IRBuYdV/8byh/QoMp5DKcFT4p1VXVXv5iFTwuxWo/oVnjA6WQPVrDDe72gd8TYXBpoc/x1D9H/xS+fkcX3U3hsXrXr1w4rGDBlarI4eNnvnQLsxhPH+Z0FdhUKy3rh9iVbaLn+vFbEb7QaB6GEMifTyjBS9Q0U7eiDmNFqjwONILx2Hi6tYy9xBmNpz7w3JVv8TjcLdjymp35kHMbqg+qDRfqZZisqo3WsOCCo9C3YWJqt+Z6pvwNU/1Jzyqt2MgpjGgeZjnUJ4K9+v1jsEU8dra4+GJJtayCXNd72taVeInxdgujBF0FJ5pYp3K361HHdV5uB/UOxLjqymsCqis5zEvQX2O6lXcD1qNsXXFWVVQTcS81HNUyuf6pRhbW4xVBVXLbsxMkKPCvaC+9IW/RRjNrwoqayVmJugbqupNjKtvWvR3sxKq2ZiZoAtU1RMYV1sMVQ3VGMxM0L2q6iaMqyuOqobqaMxM0AOqaj7G1aSgqqEajJkJukdVzcO4aiqqGqoOzEzQfQyVBlVR1W/pKh3KeJUWZbpKRd3hLmWY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' +g12 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAAgICBAQEBAkEBw8HCAgICgoKDQ0NCBEIEhISFBQUFhYWGBgYGhoaHBwcFSoVFi0WICAgJCQkJiYmKSkpLi4uMTExMjIyNTU1ODg4Ozs7PT09IUMhIkUiJUolLVotL14vMmQyNGU0OXM5QEBARUVFSUlJTExMUFBQVlZWWFhYWlpaXFxcXl5eYGBgYmJiZGRkampqbGxsb29vcHBwcnJydHR0d3d3eHh4enp6fX19QoRCRIpESJBITJlMTp1OUKBQUqVSVKlUVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0dbp1drp2eLt4ebx5erx6fL18fb59fr5+gICAgoKChISEhoaGiIiIioqKkJCQkpKSkZSRlpaWmJiYnJycnp6egL+AoKCgoqKipKSkpamlqKiora2trq6usbGxtra2uLi4urq6vLy8vr6+gcCBgsCChMGEhcKFhsKGiMOIicSJisSKjMWMjcaNjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cnc6dns6eoM+godChotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatrtausNewsdixstiytNm0tdq1ttq2uNu4udy5uty6vN28vd69vt6+wMDAwsLCxsbGyMjIzMzMzs7OwN/A0NDQ0tLS1NTU1tbW2NjY2tra3Nzc3t7eweDBwuDCxOHExeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e4ODg4eHh4uLi5OTk5eXl5ubm5+fn4O/g6Ojo6urq7Ozs7u7u4fDh4vDi5PHk5fLl5vLm6PPo6fTp6vTq7PXs7fbt7vbu8PDw8/Pz8Pfw9PT09fX19vb28fjx8vjy9Pn09fr19vr2+Pj4+Pv4+vr6+fz5+vz6/Pz8/f39/f79/v7+AAAAAAAAGpDFhgAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABSPSURBVHhe3Z19nBXVeccPJMRohcZEIybpS1pN1JgUm5im1jZJ770s7nZZBFmyuBuIbU1iW0NtE1NSA6gIiK4soiDrxpUVRNEk9aU1CStvYtEVxLVpTKQBWRcWqw3LbnDv9s6HzNz7m9czc+Y5c+fMvcP3H849c+bly937zMw5Z55hJyj87Oc/QykdCK20qgYH6Ueg1f9j3aoGx8oRYIW1qh8crwc/q7exRjrAQbvgrX6O1ukBB+6AsxpF0zSBQ7fxWqFd2sDRm5wkVh4tjxXapBEYFHFboUE6gYOB0wpLUws0dBxWWJZiIHKSWVlathUWpBu4WFaoTjmQMa1Qm3pKNrBCnZfRnnVLZ9bVVBdT6me3PrwfR8hR1ClZ+d9MDXZOz1Qtc7rzOEw3RZ+SFWpc5DtqsIEqZdp2HKkby8rvqzrQjJWrmOWDOFgnlhU+O3muyr+oEjMO4XCdwOpX+OggHVL+WrDCJwc9KZHStd7CIdsEWQ1dgXVSwGIcs4Oi1Tv4YNOKNejkKvflduOgbYpWKNu8gPY0Zqx4pFc/dRQObVt7NaoSpW4Ih23hb3Uz2lNY+GwBaxm8vqoW9QmyHju38bN6I4vm4TS9jHUsjsn/9ZbLTOf/axHd6k0ULdagdSjZtX4XLTunYXFi7MKeLXQrlGzmoHEYuW1YwcNAIxokRTt2bOFjlSeGsyCp5LUWYb8W+/jfVS/ahsFHVIuBBrRJhnrs1uJXvNU2tA3hNjT35Vk0SggutvN/gd1oKmaa63J59OiRERRL3IFmyXAEe7XgrTajqZjNaG2wZ/lkvablCYfY4OWlZskwgL1aRLSaasf0/hbUZeodP7WVqEuEuKzsYNo/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' +g2 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0dbp1drp2eLt4ebx5erx6fL18fb59fr5+gL6AgcCBgsCChMGEhcKFhsKGiMOIicSJisSKjMWMjsWOjcaNjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cns2enc6dns6eoM+godChotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatrtausNewsdixstiytNm0tdq1ttq2uNu4utu6udy5uty6vN28vd69vt6+y8vLwN/AweDBwuDCxOHExeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ufS0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e4ODg5eXl5ubm4O/g6Ojo6enp6urq6+vr7Ozs7e3t7+/v4fDh4vDi5PHk5fLl5vLm6PPo6fTp6vTq7PXs7fbt7vbu8PDw8vLy8Pfw9PT09vb29/f38fjx8vjy9Pn09fr19vr2+Pj4+fn5+Pv4+vr6+/v7+fz5+vz6/Pz8/f39/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHWJ+1wAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABiESURBVHhe3Z39Q9tGf8DL+QWDeS8UmjxJYdBQWKGhUFjhMSUhbzTJCmEpjISErFDaELaHPu2zBcKrN54VG3d+Zrk6/lkmWd/T60m+k2Rb3ucncTqb+1h3p7vT3em9SwYuAgMkqBgsVv/0Uzn4sy0/6/nl3yFVThSz+vXX3/72W97M77ZgW+DX9gdInR1OVnl/U+IzkEgqdla//Q4fDjaQWjM2VoG+SkYgxQboVvCB6gDSrIdmBbGrB0i3BsUKolYTkHIVqxVErC4g7QSzFcSqPiD9CiYriFKNgEEBoxVEqE7AQcZgBaerFbCQ0FvByeoFPP6fWalaOis4U82Aic4KTpQajEWZfF5QyMlksxmFc5m0RErh7OzsVCKpcHJyciyTPDsX6C1VcHG2Enaf/rGvq739fYm2trZWhRaJ5ubmJoVGmQaJuEJ9fX2dREyhtrY2KhHxk1hb/8zzg/M8JNKA4qJaQagOnFoeaKqPhlBNAEHv33qTplwvRcbeKvP8ejwM3xFI4tMHAqRVR0GGWEGYCj6YbAjkRdIR/mgtA8nVKNjYWInbvVH4bJBpXqBrgRWEEMTt7kBnPpXmhSwkWUXWoVrht38Xgo8FnZanlqpQtYK/CcnJ6rhSEujKjrkmtLHKLsXgMyaCWMlHb55DsgnECv4E8O4V+IRGtCex9OYoefxudXYgDmEBoXnRerEoVpl5U6FCzYkfz85zIpaaO0I2vTdnta4g4X5zhUG12u+D+ED91Dt96wSL2eOFFjgXBN7/DlJGUKzgD0BYi0D0AqErz9MinCLg3NYQnA4AsUlTFsQUq9Q9iF0g3LtLaZZg8ehWYGoO1GNOIbZaHd+E2DKSlPlC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' +g3 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0dbp1drp2eLt4ebx5erx6fL18fb59fr5+kpKSmZmZm5ubgL+AoqKio6Ojp6enqamptLS0ubm5gcCBgsCChMGEhcKFhsKGiMOIicSJisSKjMWMjcaNjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cnc6dns6eoM+godChotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatrtausNewsdixstiytNm0tdq1ttq2uNu4udy5uty6vN28vd69vt6+z8/PwN/A1dXV19fX2NjY3t7e39/fweDBwuDCxOHExeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e4eHh4+Pj5+fn4O/g6Ojo6enp7u7u7+/v4fDh4vDi5PHk5fLl5vLm6PPo6fTp6vTq7PXs7fbt7vbu8PDw8vLy8Pfw9PT09vb29/f38fjx8vjy9Pn09fr19vr2+fn5+Pv4+vr6+/v7+fz5+vz6/Pz8/f39/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8DgQ0gAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABMISURBVHhe3Z39QxTHHYfdQxBEfAHjCwmGtvZVDAqiKIqiEAxqRIlGm75pUBGiETHSNm0jgYjQpg0XqSlHjv1P6b18bvZlZnbnbe92eX65u5m5u31gb3Z2Xr6zaT2YP/zjRztO4LBCCLH6xfpv/7j+l7/FiT//7e84OD58q5//bg1/n3iCw2TCs/on3htvcLAUHCu8K/78FwfshWmFdySD/+Gg3TCsUDo54LhdUFYomSxw7AS/FYolDRx9CZ8VCiUPHD/wWqFIEoFBEY8VCiQTOBRwWyE7qcAij8sKmckFHjkcK2QlGZg4Vv9BRqKBC7H6PdITTlGGWCE18RRtYPUVEv0sjva3bqutjhe129sGH3yPI/RRsIHVb5DmZW3qeJUVV2rOvMBheig4weoHpHmYa8UHxJWjizhSNwWpohVS3GRHqvHm+FJ3l+6DKEjxrFa78M54c56jlbfCaxcJkbKsPkqLb7XWjTfFnwEcsgPX6hO8JQk8xjETYIVXDq9q8Q4fmzfjSZzY+RpHTeBYdeINblqvTy7b9vLk8LtIiA19OGpCwepfeEH4JoXyDt2uS950zGqSGv8/q2CF5w79KE5oeIgc8KAeGfHgOg6LwLLK1KF0iaYF5BDmdyErFuzGURFYVs9RuEQjJRU3rW9xVIT1TT/BM8JNlAVVz5Hu4Sn926sc4zgowvqmX+IZoQdlwRCSfVA/vgpCHeL6pl/jGeEgyhbZuoJkH6+3oEAM6MYxEdY3/RTPCC0oW6QfqXkW3SfwWRSIAcdwSA6bfoUnhHdQtsgMUm17dJ9lNT/AC9v+AgViQAcOyYGuAz1WtVmk2jcKr1O38dLOxOf+i7Ji1Oweq4NI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' +g4 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0dbp1drp2eLt4ebx5erx6fL18fb59fr5+gL+AgcCBgsCChMGEhsKGiMOIicSJisSKjMWMjcaNjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cnc6dns6eoM+godChotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatrtausNewsdixstiytNm0tdq1ttq2uNu4udy5uty6vN28vd69vt6+wN/A3d3dweDBwuDCxOHExeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e4O/g4fDh4vDi5PHk5fLl5vLm6PPo6fTp6vTq7PXs7fbt7vbu8PDw8fHx8vLy8Pfw8fjx8vjy9Pn09fr19vr2+Pv4+fz5+vz6/Pz8/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzAkGwwAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAAA/HSURBVHhe7Z39f9TEFofvbtlSbAWBcgtoeRORNylF3q6VF+0tWqnFaxUpIAiCIO9Ir0rpQin5v3E3+e5kkjPZnpNMspn99Plld2cy23m6bTaZOXPmX2+7kbRWf/35/yZ//oXX5WI5K08GWpF2KC2KZCv0p8ygp5REKzQsOehsnAQrNHIAdDiK0QoNHAGd1jFZ4Wh3QL9DqBWOdAp0XUGscJxjoPMt4lY4yj3Q/4CYFQ5xERj4RK1wgJvAoUnECtWuAosG3W+FSneBR8QKVS4DE80KFW4Dl/ZWC7Ond6/tq5WLvoHtJ2eeoYcx4KKsUKzz4NjqSlmp7r/5Bt2MEMgkWz0/gDcoK8P30dMIvkzLCmUhl/rRuLzUJpbQWQ3fJsHqzWm0LDd7FtFfjaYNrFDSwhEpo1ZTJ7BCgeJLNCo/e+kfYcsKLxW3qmjjAN+gzyEJVi8H0SJGTy9YhYIy0PsIvVbACq8Up9AgjjqTnkBBKdiNToUYrV69g+Nj7Ee9N1dDSTm4h24pfCs8V0zj6Dh3Ue99hoKScBTdUhittuLoGHtR7T3vRUlJ6K2jYy1MVvWEE+Ad1Cf+23WMG+iYwmB1A8fG+AjV3nwfSkrDOfRM0bDCM8UEjo1xC9XeGRSUhwPomcJgdRTHRvkQtd5C6T6qyvvomsJgNYpjo9xErfcFCkrEELqmMFiN4NgIO1Hp1RO+zDrJJvRNwbW6jkpvHAVlIq3VNtR59TLeS6a1uoo67xwKSkVKK3WSefUuSkpFSqvLqPImUVAu0lltRY23uBYl5SKd1SXUeFMoKBmprIZaQwOL6yuV9VtBiS4xUln9iAr/xmsGz73dQWUZSGO1qfVRvd7Q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' +g5 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0dbp1drp2eLt4ebx5erx6fL18fb59fr5+gL+Avb29gcCBgsCChMGEhcKFhsKGiMOIicSJisSKjMWMjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cnc6dns6eoM+godChotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatr9evsNewsdixstiytNm0tdq1ttq2uNu4udy5uty6vN28vd69vt6+y8vLwN/A09PT19fX29vb39/fweDBwuDCxOHExeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e4eHh4uLi5OTk5eXl4O/g6Ojo6enp6urq6+vr7e3t7u7u4fDh4vDi5PHk5fLl5vLm6PPo6fTp6vTq7PXs7fbt7vbu8PDw8vLy8Pfw9fX19vb29/f38fjx8vjy9Pn09fr19vr2+Pj4+fn5+Pv4+/v7+fz5+vz6/Pz8/f39/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo18IGgAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABKcSURBVHhe7Z35f9TGGYejNb6AQAzmjhNTIAQwGOwApgYbFzAEnEDTA2ICiYMbg7GblLRNoTg20NLWJrQuS5f9a+keX7065p3RaCStJD5+ftnVOyPtPPaupNFcb71+E8mS1d//8uc/fi/hTz/8Dbl0UFn9uxwA8oUEO0cBR5Iit8IBMgwKyiCxwn6ZB8X1w1n9C7vkApTZi2j1A7LnBRTbg2D1CplzBEruwmf1PTLmDJSe8Fr9A7lyB8pv47H6L/LkEBgAt9VL5MglcKjjssrxf6oKLGo4Vv9Eam6BRxWy+g5pOQYmFWyrnyEl18DFsUI850DGtsr9jwrUbWwrBP0Ub53Z39HenC1a1uw4emUOJfRT11FZPR5ea2WW3TdLKKaHuk7dCiEPywNNOEBG2fgNSuqh5iO1utOJnTPMwDIK60Zl9VkBe2aa7UsorguFVT6kLGsbr1WzwqbDeE6kKlrPUWSH/0isFtqwTw4YQJld8FavdtfyN7UEkYn/6CRK7VC3wgZxtZ59FJtyeusZ06VDqBayVq+217PnxMq6jtIQNSu8J6aQOy9W3SiNA2dllzUvVtYDFIeoWOGdwzvInBurT1AcgrF6irz5sepDcYhfilZfIW9+rLaiOMRvRKuLyJsfq1YUh/hWtBpFXsdqcUHCfuRMmQLKSfxetDqLvI7VYQQyC8pJfPdGWv1hxSqzoJzEilV2QTmJFavsgnISWlant4Otm7JZ9Uc5CS0rN3OfD6xBenZA2YjQVhVeXN2BHFkBBSNMrCpcydY3EaUiDK3Kj+qPoTICCkWYWpVfHkSuLIAyEcZWmdJCkQhzq/LLXciXPigREcEqQ8+tUSBCZdU/4Wdy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' +g6 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0dbp1drp2eLt4ebx5erx6fL18fb59fr5+gL+AgcCBgsCChMGEhcKFhsKGiMOIicSJisSKjMWMjcaNjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cnc6dns6eoM+godChotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatrtausNewsdixstiytNm0tdq1ttq2uNu4udy5uty6vN28vd69vt6+yMjIzMzMzs7OwN/A0dHR2dnZ29vb39/fweDBwuDCxOHExeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e4ODg4uLi4+Pj5OTk5eXl5ubm5+fn4O/g6Ojo6enp6urq6+vr7Ozs7e3t7u7u7+/v4fDh4vDi5PHk5fLl5vLm6PPo6fTp6vTq7PXs7fbt7vbu8PDw8/Pz8Pfw9fX19vb28fjx8vjy9Pn09fr19vr2+fn5+Pv4+vr6+fz5+vz6/Pz8/f39/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzLH1jAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABQfSURBVHhe3Z39QxRHnoe3B3kxKBoXg0FREaOLwaAiBoNCSFASBXV3c7cr51tEDZwc3Nte9jZxT5R1lKx3mTBHGHfsf9Xtnv5MdXXXS1dV98x0+/ziTHXNUI/TXd319q1fvFHArhf4e7FRsvrzH+vEn6p899133z969Oh/Avzw6HuH7/7jv/71dyiYCKkV/gdTCgrJQ2j1Cp9NNT+jsGEEVvhUBkCBg3Ct8IGM8AeUmoJjhcwZAgX3YawycT2FQdkJIat/RLasgeJXCVr9OzJlEBh4BKz+jByZBA4VaKu/4nhGgYULZfUDjmaWP0GEtvoDjmWY30PFt/oHHMk0v4FM1erXSM84sKlavUZyxvk/z6ZqhdTM89uKDayQFqa8MHW8c2tLc6poae86Nb0sOrkqOjKrn6Z2Waml+9omihnkj66OZ4WUAOWLLfiClNI+y/29pFar+/HhFPPhjygszaOqFd7TzKf8h/LoWEVxacRW2ZDia/2byGoxI1KOVh5F9nntWeGdz0YnPpMB+tgqQ2A1gk+EyDXjRaqYRqF9KlZ47bOI/BQtAxe/WXdq+/WH491ISgstL1FsAt/qI+QndF5yjAgvrryL9HTwGcrlw7Naa0J20Ha1jCNVNs7lcCwNdJRQLIJj9d94SfgcuUEfW8vY9vJeHE0Dt1EogmP1M14SDiOzx+nwD+VR/hDHU8BZlIngWOEV4fU7yFxBIGXbpV7kaDz7USQCx2oVeSscF0nZ9vr7yNNwmkP9zW4diJeE+8jrsoOu+8Ks7UCuhvMCJSKwVneQ1eUe0jzWn/+EVx43kKvhMA+DrNVtZHUYQJLL87F2J+W9c/Q3pOUcfIryEKRW/4wkp244Vb1DNV+onsUPg5VlA9Gy6kaKI9WPJJfBSg2SHidNK/LcWKalLOt8upw0rb5Fin0XCSB3NVVOelb+beADpKQVHaseJATvy2lEx4rU69eQkFp0rE4gwZ6qvM11dO7Z7d6z0oeO1Skk2JPOo9OpG4XK6+e3x9LVZnQxszq6hFcVynf6kCMtGFlt4F+fuQ7kSQdGVhwKg8iUCpKysu3zyJUGkrNKk1aCVvYp5Gs8SVoVU1PFx7FaW3yw6N20wANkbDjmVg+Oue3GLYOLeO9yzMvYcEytCj1ItKwPikiz7XkkNRpDqwI9ZNDra3UhqcGYWZWC4yCHSCfhRaQ0GDOr60ipQjrUFpDQYMys/IvK4yjS7WI6xkaMrJaQQMg9w5GUXFhGVleQ4HMHR+xDSGgsRlZeW5jmOo7YR5DQWHSsBpFgTyPB5yaO2OloP+pYkToh1B3o8C84Yu9DQmPRsdqBBPtVeEhnDw7Yr9IxV0HHylpDSnik2JpBuv0YCQ1Gy+ouUuyXbUjx2E46Mq4ipcFoWfm34UVaa9sKUtNSBepZNfutKUqLklpNybQLLSvrApIc8ue8of3tE+Rqs+3RSlLj0bPaRjd9N2cnRidu0vNQ8sHLLUlaOnv7Bz46cWr4zMjpwYH9ERP79Kys40jjk/gtuHnXgYGzF2cfPPVbcB6vHl87s28LcrFoWvkPERzYRw5zmrpPX1kKdIqwlOaOCK5jXau2h0hlmUvoDpzrOnl5kT+Lm2H1E+5Jr2sl1kpEqnPwi4Xw2SanOLMbn6XQtrLavkZ6kNnYUs1Hr1DVqTqlidBMPxMr52bMTvt5GbfPbOvgLb3fiGYp3FY1sbJ2TAdLUJiKN+S4c+QBM1FRi9JYsNowsnJOw5GH1eu5OD8U6+R7f2IZ3xSHxUBvuKGVQ27PqU/Onx3sivWQ1H7+L/grccnTC3PMrRJAtAzHCFqrcVZNg+JbnxGUVqOsOuiH4oTwtRpjdTDwUJwY+eqYewOscieTqPS4VLuJ6m911G9kJg8Gcett1bOAb60N617vV32tOmUNmUTwJnTX02rbdE3qiCDD7l+qn1XLhPnjqwZFt8FVL6umM8nfn/i4K+DqZNXzBF9We546f64uVlsuiFeXJM8H9bHaW8s7FItzK669VdNndaj5aMq7am+1p2aPR0Ima22VG6/zD+XysMZWu+lJTnVjs6mWVrnRBJu6OrxfQ6tWMl2h3gzVzmpXfetzmpmaWfXyAmjUiaVaWQ03oO4jlGpjlbuMzzYIvdWaimx9gI82ilpY7eZEOakvTIdwfKsjspXSHoX7n584duRQ7+H+T6Yf5JMPPpa81Vl5q6O8cHEgFKuq5VczzGLseCRudR6f4lMQRd/a81mSd4Kkryup1LdDkhkFzcPJXY4JW8mk5g8ik4hcf1JeyVpJpDZHFAa6mhNqYSZqJZF6qBjRqctf6h+DJK3EUqVR5RHJ3CQ+E4cEn5jEUs+15oOfiH0WFpKzkkj9ElkUORi3kl9JzCo5KcvqZKJf6XE/KasRZGbRl7Ks7nhd8tcSsuoTRnE3kXK+L9a1NZmMVadwztvme8iiiXwiYgQfJ2LVxnwLwXjOKhsvT51jSVjlgvGMaBaMZ860xHh66knC6ktkZNkwuqg8DpiPo+xMwMqf5c7wMbIYcRFfok8CfbcHxNXVN8Lzb9uxyfurL/Ir8+N7kMLSanoz/jF+P/u7kjumKO7vwZvUjSA/LQqByQTMU+Tb2FYtJJoRC7NQ0KM7EPLDoTzFa0zmBpmyKTIX24oJq0jBjTbQNMG5YT9jZsKbO7lLcGJanUEeHgXeFM/WeRwNEVz7FMfJvUfGs9ole16bRCaaVuGEHyqkbjwn2+6NZ5WTTUoqc+JCNAl+KYfyAPLEdbLLbfGsPkEOLrywEBM4xsOL6xnbqTLhIo7VbulQIucE7BY+2bvkm5Nwsu3ZWFY5+aAvZ95+xHD+WBJOlSs0htUYjgvYiWw+vThSY5x7v7lVl7xh9yOyUdzCodryyrmlG1s1RZxO7ErpjvpMZnIX9xpbyaozlwnk8/kQR2qMGwbQ1Ko7qmPhODL6UEs9a8kZ508ZWuUiZyf9Cjl96jSs6gYfN7Qi4ROEsCs3eQHQk6fkruE0s9oSXUJ2WCfUECtvrBeld2UzKs0fM6tRHJIQDi1jWaR3rXh3cqh3Z6WdnNt68OzsapIDwxfcrzWy2hqx5NVFZLU82cus8916aJwEnolL5e8aWanUZlyrzSui+Nm5o3OJ/GJrlVPAxGqHygQ5jtXa6Fa85NL5ZfSUhkhmKl9lYnUNB6SwViORu+K0TsV+/PBCURhYdSn9adZKhQMxx7uLXq+CgRWJSCLFzMpquRTr8rrpfYu+lWJ7wtDKsg7FuVsjkqu+FQlSJMfYynrHfK54CdWRtlU/UqMwt4qhVe0r0bYS9xIFiWFlrlUdrdC16kJiJHGsjLWq0a90rUg8qShiWRlqkY59Tas25cH1eFbWuyaj+OfwYV0r9cGXmFbWML5Hg00Sj0LPKqd+649rFdo8RwV/4wI9qyNIUiC2lXSjIy7+6J6e1RySFIi0auvat7dLFu/jJL5JFWpPPy2rXRqP1FKr1qHrTyrPe6XlmQEmlk0Vjf9DFyruvZbVFFJUkFj9MtiQWpvYhgMh9Hqw6T39dKxagrtdyRFaNX3KdCWuCyK7a60K+gwfctGx0qpsRVa7w2PdFe5ux+EAOn+wRO8noWOltZxPYNUt6MhZ5W1y0aJRDaJl5aFh1YH3avCtRFICLfFcIoZA/6OGlWy8noVr1SHpclvh1PKdyg3jb/EJDw2r+3ivBtdKWlezEY816oshfMBD3apNb3olz2oIx/iUOWsTlLqzHF4Ef2h1K83ZlRwrKlgpl2Xko/gYh6II3RrUrW7grSIcK8mUOw92NhfZSEzOSmhym7JVk+bDJscqsiU4i4w+4b0/BRxF9irKVh/gnSqsFQk2LaTE9u4qtYmZfQmUrXRn97JW8rqiAnsKKvUoMH9L2Up3jR5rpVDAs8jq8ymOyAg8VlRQtVK8bH1YK+4DYBD2wlIY/yuxi6BUrbTXD7FWz3FEwj1k9RGv1CBcRlYKVavHeKMMe4koTA5md8SJvhiLnNaZolWb9sASu9+1wpVJb9DsEf3wyU5XUbY6hNfqsJHaFZ7p2Os+8rpa4431KVqdw2t12Il0szgiYRxZfcZxRMhJZAygaKUfS+609/0UCj2k7Na3US2sr5EviKKV/sQBb9iZ5gCOSGCDAUeEGyxwewYUrdrxUgN2in5TZHXxDXL65CK62z9CvhBqVofxUoMS27SNvEbYazFiYOkWsoVRs4osDwd2F5htEe3OPLtYRt5/+6MofLWalUkMIneeXoiItUecXsFLOMRHGGhczcok/ARna+Vm6S2LndMa0VnHPjVWUbLS6zMDnPPJ2id5RClwus7aZefsmnj+kJIV2UxJi3AD1cXbOp9HkRcnQnrz530/ULKKmjnMh32ocxBpcaVysgklss3Dlaz4Ox1E8ZqzzYJlfcgdgsizDRcH2dwO6Y4sSlaS9XAyLuFvBOngdHXO8IsomX9cFE00rKBkZbhsshJ6lsPxYM32ek6wxd57yMChLN89QsVqC15ow3ZDgL3XqsPm5cdfCKOUSDo6eI0qChWrd/FCm3V2BQzhnb7hsyNDByUzISXLoNl2WBAVq/14oc99zj1LFcmS9WXZILmLilWMBR6VWNVmiB+W1sKb9TGoWCn084gw3/S6Vzh0VeLeBQKoWMWJujNveA62idupJ5BFgooV2Q7UhIjaSkBOPALDG7wLo2IVbzEO28MSTU78H3lX5cdXsYoZDFVfSyIV2FJRiIpV3CUBulqxpVSs4gfj1dOKL6VipT9Rj2GmFX9OgQ7xKgBVKRWrJFbuPeM1n7h8JB4SV5ZSsfoG/8bi9ZdRTzkV2iVritWlVKxUZ7BHsCqKt0JxTNLm0ZBSsUpqD5ryncPSe03TgOwv6UjV08rh6YiwbBEbYmlJqVglElOySvFyD+cCa+2blffr6kmpWCW8UZpdWpoZ2kOmkzb3fPzVStRI5u3IZXZBGmBVYfPx4vzcvYXFJyqTX+jJp0rU97oyYoNd0h+FglVCNbspL0ShtSQoWCUVFSD/l0g4oxSL/NFEOQpWaqszo/H2+ZbC9vtcV3okCaNgdTuh1eQGVmWy9kgPFauENoPTt1qXDHtIUbHSn2zBRdvqqVZIYxoVK/2JMVw0rcpqT/lcVKz0JzFx0bNSb5FxULFiMxmhZTWt+YwURMnqc7yKyetIkNHOs1FntFCy2lGD+C4yruo9obMoWRlMzorBC3YSni5qVnWKu1ZhVhqwRA01K/0JqqY8ZaNTGaBoZbAm2YS14RjDeBSKVi31CHxVnIhVnVMoWll9eFM7SpcFS1ENULWKFS9dhZuKG44ooWzVwuxTlCTz0aOiOihbWQeTeRrksWLa4hChbmV9gfcJU547kkzFR6FhtcVskpacn6ZihNsXomFVA63Hw0nV5UF0rBLWenWTXUuSEFpWSWq9/Dxyhos5elZJaRVvHWdCI2rQ1Dt64+laYW356jC/C1TTKondddeuHDXvkXDYHhgT4l6aulZxd0Jevbg/Xj3ePBUeEyqwU8D0razcmN7adUJ5ccxw1x4fdlsXh3vhS9TAymzzt9Ubw7xYD5qc4j/gFEKXl5GVZe39SuPyyt8e60uggesgkGK0DK0sq31Mpcm19vXEkeQaGMfFj6KFwLltbOVcX/2XFkW/2Mbqwo2p0f5kb0nSuFNLdACkGFYuTd1DM0v5l+ul4nph7fmz1Yc3L50/0fdeMudbmFDYkNAPR09EjGlVT+iI3IWp3c1W23565J9e4p0hK3/F+6uR6m18OzXn/UukOWTHyu+Df1XdUMXFj+e17j9kZMfqKxTH3yXGw9fyI+Jkx4qM44YWHuRI1ILrSMmQlb+4N9wqI0tJnyAhQ1Ykwou7s0YAsrS1TIZSMmNF+sTZ+eykEUHGkTNjRVbxjyHBhyxTI0uUs2fFLmYgzxxktmhmrE6jNJx1hSS6UfasDqI09otwW7qTPBBmz6qVlD14E6ZDYGTPyg/QEoqU1eq3TzJo5XfzB6Z2NlMLdTNo5V8+tBYtlUUrOlDk9er99nBg+mwWrQLTI+YHD7zfO/IE70AWraLDv2XSqjVqUmkmrayeiFV72bSy9su1Mmpl9UjDN2TVytomW2WZWSvLGgzXGQskqEiGrazc0Xv+Y0b+6mE/WlSWrRzaes/N3r13+/pIJTQNsSITbLJpFYQsZCHDPW+DFXEgPe1vgdU+lNPeIK3kDFqFB2LJAne/OZk5q/7lZ8F5DR1ktMcfFMmYVb/bn3SH7o9p9yc6+1P7M2VVcXL4yv+1KKkVJDlwrMJaabHq8aOar+JnaRuhHjSoMIwZsuqkJ688u3Ty+PA0HYs0T838UbDixWBsCNLYt2V6wQzTvGStmEj1jaJZtsY3EPmbiZHBWhUTnxZrSps45N8DurrfiUTCz6yVzY1u2BA6RD0XASnrGFIJP3CsFIJV1YtO/q91O3hjZoJ9veFY3UHmNNB0np1k9FP4v52pAnlWZeMQbLVgV2jiz+a18GwpdpMQnpVSaLE60j2+WG0Ml1fOsVGX2SX2rhWjJYvZ2BjaB8cvXLo42stbALnfb/+DN1wrssNtFuDEiPSsWC1OqOu0wokRKbLajL8utE6cYWNEOkJ8q8xocaQqVv8p0KK2rkwtuXGO1GvXypXiWNn2LVHk+tTQyQ1H5Pr84s33Aiv75dm4K8lrSsfEBgoawP2p8FvxteziNC/yVRpo6/snwYqIig6sxNFml2YmPx1PFROTkuhb/1/RgZXgx8oenk3V6i3Rggyxeiu0/hcuvtVboPU3mNBW2deCx1tlBQsX2irbWnCoELDKshYMPIJWb/6GPFkDxa8SsnrzV2TLFCi7T9gqg2chyk3DWmXLC0UOwbPKjheKy8C3csDn0gxKykFo5YAPpxQUkovMygHfkD5QPi5v3vwdWLHEBE97yvwAAAAASUVORK5CYII=' +g7 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0drp2eLt4ebx5erx6fL18fb59fr5+gL+AgcCBgsCChMGEhcKFhsKGiMOIicSJisSKjMWMjcaNjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cnc6dns6eoM+godChotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatrtausNewsdixstiytNm0tdq1ttq2uNu4udy5uty6vN28vd69vt6+wN/A2NjY2dnZ29vb3Nzc3t7e39/fweDBwuDCxOHExeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e4eHh4+Pj4O/g6Ojo6enp7Ozs7u7u4fDh4vDi5PHk5fLl5vLm6PPo6fTp6vTq7PXs7fbt7vbu8PDw8/Pz8Pfw9/f38fjx8vjy9Pn09fr19vr2+Pj4+Pv4+/v7+fz5+vz6/Pz8/f39/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAurfsHQAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAAA4VSURBVHhe3Z39QxTHHcZzKChijPieRONbNBgploZEY6PFUGkUG9r0LYkRYzVGiPY9VCJC2opSy5lj/2F7t/fsy93M7n5n5ju7M35+YW93Zm8+cPcwuzuz+9LzYgLXeIaGZUKx+u3f/uoSv/vzJ79Gy7LItcKvxlH+g1ZKyLZCXaf5AW3tJssK1dznH2hwB3Ir1PCD79HoFDIrlPaHP6HhMRIrFPWJ/6HpEaIVCnoGGg8EK5TyDjS/TbcVyngIBEI6rVDAT+DQosMKm30FFk3SVtjoLdBokrLCNo+BSNoKW7wGKokV1nsOZCIrrPUd2MAKK7tZvzc1unegr9cp+vp3DU9+3UATu2jr5FmtTb9ac5Ydk4/RzA7aOm0rrOpg/dMB7MBR+i7K/l6hT6bVoxOo7DAHFtDYNLEVXqe5vw01nabvNpqbIsfKD6lMLbnVoidSTa05NDkBVniVsH4EdTxg11M0OiHDaios39NXzIawZKWcRqMTQqsf8CJmuS8sfgAv8zgblqyWb9CWhJYVFhPG26V9sRpBWxJkVnVEhS9WG5bRmBiZ1Rco7YtV7UM0JkZmdRqFvbE6isbE/FdidQCFvbHaso7WxIhWz3pR2Bur2ndoTcxLwp/qIYp6ZHUTrYkRrRZQNLF6uthNfGjjhtUMWhMjWt1H0cRqBisSvsSW4DWsqJZraE2MltX26HDtHlZUDI/VODYEY1hRMSxWPUvYsLoZayqGxWoI64NfYkXVsFg5lhU8Vq5lBY+Va1mhZrXvLpjEijbOZYWaVQbOZQWLlXNZwWHlXlZwWLmXFQxWDmYFg5WDWcFg5WBWmFu5mBXmVi5mhbGVk1lhbOVkVhhb3UAZ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' +g8 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0dbp1drp2eLt4ebx5erx6fL18fb59fr5+gL+AgcCBgsCChMGEhcKFhsKGiMOIicSJisSKjMWMjcaNjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cnc6dns6eoM+godChotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatrtausNewsdixstiytNm0tdq1ttq2uNu4udy5uty6vN28vd69vt6+wN/AweDBwuDCxOHExeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e4O/g6enp7e3t7u7u7+/v4fDh4vDi5PHk5fLl5vLm6PPo6fTp6vTq7PXs7fbt7vbu8PDw8fHx8vLy8/Pz8Pfw9PT09fX18fjx8vjy9Pn09fr19vr2+fn5+Pv4+vr6+/v7+fz5+vz6/Pz8/f39/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB03dHgAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABRlSURBVHhe3Z2NWxPH2odNIDRURKlYv0pLi9WqWBA/itJqqaIt1eqpPR6t+EXlyHl7rEpFrOfwlkiO5yU07p/Mu0l+Ozu7M7v7PLObZLf3dbWE2dmwt0k28/HMM5s2yFguKEktDCuVl4/+iUdc/vVvPKDw8rdHP//88z8fPXr028uXv/32P9F/NNQKr0w6wTVqCbbCyanmDa7VT5AVTks/uF4veiuckQ1wzTI6K9TODrhuF9UKNTMFLl2gWKFe1sDVA78VKmWPlxCo47NClSzyHyjU8FqhQjZZh4SNxwqHs8r/QcNjhWMZBiKyFY5kGqi4Vn/gQKaBi2uF8owDGccKpVkHNhFWC1dP7N3cVUgX3X0Hz92p4Ap9NGxghTIv1ZtDudTSc3YJl+mlrhNidW87niCldIy/xpV6qOk0rFAg83ocJ6eY/ge4WJkwq9IenJlq8t/jcmUcK/wqUdqN81KOTuuPIKtyRqRsreu4ZIkgq89wTgYoPsc1u9hW9n/4xeUuzvBT6MCDNLHvDa5a8Kb+WuEXwXofTpDoGP5u3v7iW5mZ7EdJariGy3bRWl1HdZeOM+5XXvX2AEpTwh7lxdJaDaK6YPc/cKRB9UInDqSDn3BdgpoVHgoeo7Jg3xqOCO534VAqGMFVCf6rsbqEyg6qlK1VwME00IeLctFYjaEy6C2h3MM0jqaCFVyUQGO1E3XBLRR7qX6Ew2lAuUSNlfczM4hSP3M4ngamcU2CTRu/45Egj7oNpBbJ+tIrPKrxHiqkgAu4JMGmjf/FIwGqNiiKPmd1qjeX+/ghflNvKm3kPC5JsGnj33gkQNUGH6HQuYkU5/CrNV//PRVorP6FRwJUbfA5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' +g9 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0dbp1drp2eLt4ebx5erx6fL18fb59fr5+gL+AgcCBgsCChMGEhcKFhsKGiMOIicSJisSKjMWMjcaNjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cnc6dns6eoM+godChotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatrtausNewsdixstiytNm0tdq1ttq2uNu4udy5uty6vN28vd69vt6+ysrKy8vLzMzMzc3Nzs7Oz8/PwN/A0NDQ0dHR0tLS09PT1dXV1tbW19fX2NjY2dnZ2tra29vb3Nzc3d3d39/fweDBwuDCxOHExeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e4ODg4eHh4+Pj4O/g4fDh4vDi5PHk5fLl5vLm6PPo6fTp6vTq7PXs7fbt7vbu8fHx8Pfw8fjx8vjy9Pn09fr19vr2+Pv4+/v7+fz5+vz6/Pz8/f39/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHWfsaAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABSfSURBVHhe3Z39QxRHmsd3BlAMqDE7vqxGxagQFIKBlYioiBIJGFbubbN3t7f3vixGIqKgBvdOjSiBE3Rchh36j/V6Zr5TXd31VHVVdQ/T7ecXmuoa6A/MdNfLU0/94r0xTl3BRaixsEoBSqst/H2SCS6SQm6F1yYaXKqAxOqveFniwfUGIK2S/c4LgovmoaxQOzXgsjlEK1RNFbh0hmCFeikDF18laIVa6QPXXyFghSppBAZl/FaokFIg4eKzwtm0AgsX3gon0ws8fFY4lWZgwlnhRLqBywduheK0U5GpWqEwyMrUwPHW5qZk0bzn1NDMW1xhkLINrFDkZ2v+bDaTVHb2/4TLDFDSUVg9P4ofkFS61nClPko6FSsU8BRvNOLFyaX1Di7Wh8Kq0IFXJpshooMrt0qJFKlVtcK3HsVOvCj5XMclc8isxvGSFJB9hGv2kFgt7cBLAjQ24CBJ5N7hqhkVK3zjcRIv4Dh8cWqp6H7enk/251CUFIZw1R6k1TNUZzSee4xTZe53Jurh/NEGrotRssKhx69RvUr7Ck4wnn+KU4ngFq6KQVnl/Z+q5kmU82yOJOgjdgQX5UFYzaNyhdbnKA5wvwkV6k82j2tiEFY3ULmMTCpRWvO4JAZh1YW6JXY8QyHBXGLuGaO4IgZhdQR1S4yjjGQAlepOPy6IQVgdRF2Xz9xHlEdh9XUBh2U2kvLk6sUFMQir/ajrfgyXUOSyeeezUknnfXxf4l6lWt05h+thuFZBLc+qAyUucx+jLHPgKYpcvKp1hbLCEcO71FmUuFLcDa/F07qJojpjZPUx+1T57+It7G6fT0Z/2ciqGwW+G0iJThT775f1w8iKPQb8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' +p4 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAAQEBAgICAwMDBAQEBQUFBgYGBwcHCAgICQkJCgoKCwsLDAwMDQ0NDg4ODw8PEBAQEREREhISExMTFBQUFRUVFhYWFxcXGBgYGRkZGhoaGxsbHBwcHR0dHh4eHx8fICAgISEhIiIiIyMjJCQkJSUlJiYmJycnKCgoKSkpKioqKysrLCwsLS0tLi4uLy8vMDAwMTExMjIyMzMzNDQ0NTU1NjY2Nzc3ODg4OTk5Ojo6Ozs7PDw8PT09Pj4+QEBAQUFBQkJCQ0NDRERERUVFRkZGR0dHSEhISUlJSkpKS0tLTU1NTk5OT09PUFBQUVFRUlJSU1NTVFRUVVVVVlZWV1dXWFhYWVlZWlpaW1tbXFxcXV1dXl5eX19fYGBgYWFhYmJiY2NjZGRkZWVlZmZmZ2dnaGhoaWlpampqa2trbGxsbW1tbm5ub29vcHBwcnJyc3NzdHR0dXV1dnZ2d3d3eHh4eXl5enp6e3t7fHx8fX19fn5+f39/gICAgYGBgoKCg4ODhISEhYWFhoaGh4eHiIiIiYmJioqKi4uLjIyMjY2Njo6Oj4+PkJCQkZGRkpKSk5OTlJSUlZWVlpaWl5eXmJiYmZmZm5ubnJycnZ2dnp6en5+foKCgoaGhoqKio6OjpKSkpaWlpqamp6enqKioqampqqqqq6urrKysra2trq6ur6+vsLCwsbGxsrKys7OztLS0tbW1tra2t7e3uLi4ubm5urq6u7u7vLy8vb29vr6+v7+/v7/+wMDAwcHBwsLCw8PDxMTExcXFxsbGx8fHyMjIycnJysrKy8vLzMzMzc3Nzs7Oz8/P0NDQ0dHR0tLS09PT1NTU1dXV1tbW19fX2NjY2dnZ2tra29vb3Nzc3d3d3t7e39/f4ODg4eHh4uLi4+Pj5OTk5eXl5ubm5+fn6Ojo6enp6urq6+vr7Ozs7e3t7u7u7+/v8PDw8fHx8vLy8/Pz9PT09fX19vb29/f3+Pj4+fn5+vr6+/v7/Pz8/f39/v7+////AAAAAAAAAAAALXB5YwAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAAA7sSURBVHhe7Z15mBTFGYdnl0MEQbkWMMKiqEAUQYOokBBQMNEoiAoxJqIxXhFFg0GCxhuNiaiIEY8IHhEUUaPigRoPJC6ooLgKBJC4gCCIAgvsAjv1PJM+flPTPd09W9VH9dfz7PvPVH1d1f29zNLTR3V1KlOMFLT6b5qRJb0aSbrhbbUX3QlTh1QdeFhtRT/yVCNhO65WteiSCPYgaSsuVon5nrI4vy+H1QdomiiWIPks+VbVaJcwdiF9kGdFeFdeDxAwsVuhRSKBgoHNCssTCiR0rFZYmligoWGxwrIEAxGrFZYkGqjkrBJw2Fc/achkrdYhnnA2mzZZK0QTj2kDK69f3/SaZ8aPHjWSFKNGj5u52vNwwdAxrZYilEfVhE4porT/w2okmYdxMmlaIWJn9VmNsAqSlJy2DIna4VYrELCSnrYfupOl2eQ6JGtlbdYKdSvVp6IraQZ9j3SteFtV/xT9iNPPRavCtHJ+jzsSIqVpOc/ctZ9i3Qo1C79HnwTwG6RswcNqHnokgueQdI5PdKs9qHCqu6CDOIfNA68egIgyyrYgbU5at0I5x9/RXoJH0ZU9gYBC7sCmc7hZpY9Ac3EO3o2+dT0RUUi543TDzeoNtJbgQXRlsxBQyhxsnKNZVaLIuQqNxemSvdhb1wsRpVyIrXOqUs4rgD9BY3HuR082BwG19MbWOXUpxx/g3hZoLMyBu9CVHYOIWhrtwOY5TquVaCvOPejJXkRANR9j+xyn1RI0FabDTvRkxyGimnexfY7TahGaCvNXdGSvIqCceUiAE9yqHd/dDEBEORFYTUI/9iYC6gnfqvU29GODEFFP+FY3oRt7D4EYCN2q1XfoxoYi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' +r0 = b'iVBORw0KGgoAAAANSUhEUgAAANQAAAE/CAMAAAAJ9B3fAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAA/1VV/1ZW/1dX/1hY/1lZ/1pa/1tb/1xc/11d/15e/19f/2Bg/2Fh/2Ji/2Nj/2Rk/2Vl/2Zm/2dn/2ho/2lp/2pq/2tr/2xs/21t/25u/29v/3Bw/3Fx/3Jy/3Nz/3R0/3V1/3Z2/3d3/3h4/3l5/3p6/3t7/3x8/319/35+/39/iYmJi4uLj4+PkZGRk5OTlJSUmJiYmpqanJycnZ2dnp6en5+foKCgoaGho6OjpKSkpqamqKioqqqqq6urrKysrq6usLCwsrKys7OztLS0tbW1urq6u7u7v7+//4CA/4GB/4KC/4OD/4SE/4WF/4aG/4eH/4iI/4mJ/4qK/4uL/4yM/42N/46O/4+P/5CQ/5GR/5KS/5OT/5SU/5WV/5aW/5eX/5iY/5mZ/5qa/5ub/5yc/52d/56e/5+f/6Cg/6Gh/6Ki/6Oj/6Sk/6Wl/6am/6en/6io/6mp/6qq/6ur/6ys/62t/66u/6+v/7Cw/7Gx/7Ky/7Oz/7S0/7W1/7a2/7e3/7i4/7m5/7q6/7u7/7y8/729/76+/7+/w8PDxMTExcXFxsbG09PT1dXV2dnZ/8DA/8HB/8LC/8PD/8TE/8XF/8bG/8fH/8jI/8nJ/8rK/8vL/8zM/83N/87O/8/P/9DQ/9HR/9LS/9PT/9TU/9XV/9bW/9fX/9jY/9nZ/9ra/9vb/9zc/93d/97e/9/f4ODg4eHh4uLi5eXl5ubm5+fn6Ojo6enp6urq6+vr7Ozs7e3t7u7u/+Dg/+Hh/+Li/+Pj/+Tk/+Xl/+bm/+fn/+jo/+np/+rq/+vr/+zs/+3t/+7u/+/v8PDw8fHx8/Pz9PT09fX19vb29/f3//Dw//Hx//Ly//Pz//T0//X1//b2//f3+fn5+vr6//j4//n5//r6//v7/fz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATF6XsQAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABMBSURBVHhe7Z39gxTFnYd3ZndhBeQtKIuuBgVxs7lL7uLlXvRyMYl3ueNNBEUgQNDjEoKKCL5tFiSAHHAvSdwAIhAQFnFVRO5yl/PuEszyqq4kxgRB2Mi6zM6/Mdfd85mq6qmXrqru6Z7OzfPL9lRV99SzM93TXS/fqiso+PIPfpuvSj74/pdQRSFSqbs+wAGqlve/gqpyiKX+vOqNirx/GyrsRyT19UHskwIG70KlWXipO1Ok5JK7AxWncFK/RtkU8StUnVAm9XcolzL+BtUHfqn/QqHU8RMIFPFJ/a5YIo38BgoerFQOBVLJFUi4MFIpu+qVk4OGA5VK9efkQj8rIpXi86nEB1AhUqm97rH8O2QgldLfp3K+VrSBFBJTT9GmKCW/N8qd6O46UFV0dZ+SX6d/7ul4UnciqZzjK6cNz1QhI2asPoUqlvNFIiU0H9wzA8eoRrL37BfW2ruuu1J/iwQf78zE7lXLvWdRVR93Qkqk3FmV3zs/I19AZVncGwtH6i/wkqUD+1U5m1Bdls97Ur/BK4aUOAmtnAugI4UXDD/CLilgD6rM4ErdhW3Kuyk4n0qM/hCVptzhSHGtYYPC695VrXPmzfnMVXhVPcxDrSn/60hhk/JjFGeYubWn+GSSO/7cLKRVC91exVhEUuUf1JBlJ5BT5OTyocipCviPqlD3ZWwRTqBwiSl+JZeTrcirBup7USvCF+t+gC3CShQukm0XPRHnOrLIrwI6UCnCv9Zxv1LTUdYj24nUcrZXj9VcVInwZh02CDn2ei51qiara1AjQo6TOomiHu1IFFE9dx3nUCMCJ/UKSrpMUbUw5armatGDGhE4qYMo6TDEd9073Lmx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' +r1 = b'iVBORw0KGgoAAAANSUhEUgAAANQAAAE/CAMAAAAJ9B3fAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAA/1VV/1ZW/1dX/1hY/1lZ/1pa/1tb/1xc/11d/15e/19f/2Bg/2Fh/2Ji/2Nj/2Rk/2Vl/2Zm/2ho/2lp/2pq/2xs/21t/25u/29v/3Bw/3Fx/3Jy/3Nz/3R0/3Z2/3h4/3l5/3p6/3t7/3x8/319/35+/39/s7Oztra2urq6u7u7vLy8vr6+/4CA/4GB/4KC/4SE/4aG/4eH/4iI/4qK/4uL/4yM/42N/46O/4+P/5CQ/5KS/5SU/5WV/5aW/5eX/5iY/5qa/5yc/52d/56e/5+f/6Cg/6Ki/6Oj/6Sk/6am/6io/6qq/6ys/62t/66u/7Cw/7Gx/7Ky/7S0/7W1/7a2/7e3/7m5/7q6/7u7/7y8/729/76+wMDAwsLCxcXFx8fHyMjIysrKzMzMzc3Nz8/P0dHR0tLS09PT1dXV1tbW2dnZ2tra29vb/8DA/8HB/8LC/8PD/8TE/8XF/8bG/8fH/8jI/8nJ/8rK/8vL/8zM/83N/87O/8/P/9DQ/9HR/9LS/9PT/9TU/9XV/9bW/9fX/9jY/9nZ/9ra/9vb/9zc/93d/97e4ODg4eHh4uLi5ubm6Ojo6enp6urq7Ozs7e3t7u7u7+/v/+Dg/+Hh/+Li/+Pj/+Tk/+Xl/+bm/+jo/+vr/+zs/+3t/+7u/+/v8PDw8fHx8vLy8/Pz9PT09fX19vb29/f3//Dw//Hx//Ly//Pz//T0//X1//b2//f3+Pj4+fn5+vr6+/v7//j4//n5//r6//v7/vz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiWNr1QAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAAA2QSURBVHhe7d35fxR3Hcfx7HIfclquJlAoh2cEGkRKSpsgEKCUcmMErVhatWrDjUq5WsNRsFWxVUiBCCjaFoQQEULY5C9bZ2fe+53jO7Pz/c73852d2ce8fpnZ2ZnZeT5ybXZnvltXrNRbtwcT2cNf4gD9C0Z9ih0ktv9+E0fKFYD6BBsmvIc4XE++qKfYJg39BMfszAf1CKunpW/guO041J+xaorivgm9KKyXsvbi6JEb9Q5WSl3/BMDKhUr8b/HgCiCYOVFfYoV0BkQpB+oh7k1rYBjZqC9wX3oDxIH6C+5Jceznqox6G3ekun8BU0Zhccr7mYUBagBL056lsVAfYRnfQPeZ0yeTVWdXAQfH98jkWCgs8nZj4+LxuQQ2cn7bBRyitzcY6nMscXdm2VDsJInNPeD/DxJD4barnhXYOrHNuYpDdfVzoPy+UKcnY9MEN3yb3+83oHDL2dEkf+fZtfmojP8ZDdSvcctRSky+KuN5hYHCDUdn02LK5TbjkB35ox5PwxYpaNhlHLTdXgP1C8zbrcIGaOqL6HksSFSz+nHUrAEDxX1XXsXqqOEulg8ewpJk1Y6jszNQmLNzf6FsU0JRDdxXxQf1YDTWNnOYEorKfYDDY73BozqwrpnTlFTUyzg81l/r3sIc6/tYt5TLlFTUszg8u7pLmGHNwbpGblNSUfkHOD5WnfeV86fDsS5nSiqK/6Gqw5R1D2vypsSiDuP4WBzqJtbMTfCaEovqwPGxONQNrJlrwAK7WkKdx7SWUDu/g5kaQu3MNVozNYTamas9lGGqOVTJVGso01RjKMtUWyiYagrFntjWEoqVoapRhkIZqhplKJShqlGGQhmqGmUo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' +r10 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAALi4uMDAwPz8/S0tL/1VV/1ZW/1dX/1hY/1lZ/1pa/1xc/11d/15e/2Bg/2Ji/2Nj/2Rk/2Vl/2Zm/2ho/2lp/2pq/2xs/21t/25u/29v/3Bw/3Jy/3Nz/3R0/3Z2/3d3/3h4/3p6/3x8/319/35+/39//4CA/4GB/4KC/4SE/4WF/4aG/4eH/4iI/4mJ/4qK/4yM/42N/46O/5CQ/5GR/5KS/5OT/5SU/5aW/5eX/5iY/5qa/5yc/56e/5+f/6Cg/6Ki/6Sk/6am/6en/6io/6qq/6ur/6ys/62t/66u/7Cw/7Gx/7Ky/7S0/7a2/7i4/7q6/7u7/7y8/76+x8fHyMjIysrKy8vLzMzMzc3Nzs7O0dHR0tLS09PT1NTU1dXV1tbW19fX2NjY2dnZ2tra29vb3d3d39/f/8DA/8HB/8LC/8TE/8bG/8fH/8jI/8rK/8vL/8zM/83N/87O/9DQ/9HR/9LS/9PT/9TU/9XV/9bW/9jY/9ra/9vb/9zc/93d/97e4ODg4eHh4uLi4+Pj5OTk5eXl5ubm5+fn6Ojo6enp7e3t7u7u7+/v/+Dg/+Hh/+Li/+Tk/+Xl/+bm/+jo/+rq/+vr/+zs/+3t/+7u8PDw8fHx8vLy8/Pz9PT09fX19vb29/f3//Dw//Hx//Ly//Pz//T0//X1//b2//f3+fn5+vr6+/v7//j4//n5//r6/vz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF6KyZgAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABdwSURBVHhe1Z35QxRZfsDNUQ2CgIDiAQNB1wPHcfAcHG/wGHQQD7K7ySabTTbZrIqiI+LFKOwms9kkG0FhPLJJZkYHHWZXm6b+P1LHt1+9V9/vq3qvqrq6+vOD0u8V3fWhql+98/uWLQXyRcHMIov/DucnQW7100V4i8zyCzhTjMTqx5lXcvl7OF8fpNW/we9UAr+DcxYgrH4Fx1cK/wHnzYGt4NhKAs7cw2/1X3BgZfE1nH0Rn1WFFBIYOH9AtIJDKpEfgoIDb/WXcEBl8nOwsOGsfgTZlQr3UOasILNy+VsQ4a0gq5IBE84KMiobcClamd9DemVT+MrVca3+8DNIrnR+82PHx7H614D7b37i3li2uPvgDZwbgSPlWplfQ5qPhWv723JGBlm379I7OEcfhf8pWi3Sl+pV/yp4kyzS0PcMzlPElrKtfmEuQIrA1Qb4/axSe56stX7vWpnUpZrbA7+bZbY9h7Plca/Vb81v4DXHXAf8YrZZ8xTOl2Px97YVdakqRIrWsq/Vz8y/glcehR/AL2Wf9W/hnD1+Y1lZlwxeeZyBX6kEDsM5cyxYVvgGnFoOv0HSsHnHzp07tjTCy7JzB87aw75W2Op9OB5Rtf3kDXYjP//s1I5A/ZR4D91rttUX8DPjCRzup6X/BRzBeHlmDWSWkXtwMozv/8H6Xvk5DEeLdI2SXe6FW9Irmxa74FQ8CtiqUA9H89RfhlyC4TJXQqpwZdd6XvmgbsBudO/xvNwFh5UJVF7YT2Efl+FYj9phyJJytQ4OLQtn4CwYhNUROJZR/znkBDBRzrsQfbEIq71wbJGGKcgIZLqMz68tcA4Mu27hYyccC9RNQHqR+fGh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' +r11 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAALi4uMDAwPz8/S0tL/1VV/1ZW/1dX/1hY/1lZ/1pa/1tb/1xc/11d/15e/19f/2Bg/2Fh/2Ji/2Nj/2Rk/2Vl/2Zm/2ho/2lp/2pq/2xs/21t/25u/3Bw/3Fx/3Jy/3R0/3V1/3Z2/3d3/3h4/3l5/3p6/3x8/35+l5eXmZmZmpqanJycnZ2dnp6eoKCgoqKio6OjpKSkpqamqKioqqqqq6urrKysra2trq6usbGxsrKys7OztLS0tbW1tra2t7e3uLi4urq6u7u7vLy8vr6+v7+//4CA/4KC/4SE/4WF/4aG/4iI/4qK/4uL/4yM/42N/46O/4+P/5CQ/5KS/5SU/5aW/5eX/5iY/5qa/5ub/5yc/56e/6Cg/6Gh/6Ki/6Oj/6Sk/6am/6io/6mp/6qq/6ys/66u/7Cw/7Ky/7S0/7a2/7e3/7i4/7m5/7q6/7u7/7y8/76+wMDAwcHBwsLCxMTEx8fHyMjIysrKy8vLzMzMzs7Oz8/P09PT1NTU1dXV1tbW19fX2NjY2dnZ2tra29vb3d3d3t7e39/f/8DA/8LC/8TE/8bG/8jI/8rK/8vL/8zM/87O/9DQ/9HR/9LS/9PT/9TU/9XV/9bW/9fX/9jY/9nZ/9ra/9zc/93d/97e/9/f4ODg4eHh4+Pj5OTk5ubm5+fn6enp6urq6+vr7Ozs7e3t7u7u7+/v/+Dg/+Hh/+Li/+Pj/+Tk/+bm/+jo/+rq/+zs/+3t/+7u8PDw8fHx8vLy8/Pz9PT09vb29/f3//Dw//Hx//Ly//T0//X1//b2//f3+Pj4+vr6+/v7//j4//n5//r6//v7/vz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeyflvwAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABGPSURBVHhe1Z2Lf9XUHcC7R9oCBWqHIKgrAkK3idvUTbe5qduUIiDyUhk4R3lIsQNB3eZrvqcrpVrAjjkQcT7mhMlAimxzSktXkNKW/EN3Sc4vuUnOSfL7/ZLcm/P9fPDmJuek52tukvM+NaU4bv3jF2YRuXjkd9dAEpVEW/12FE5RWN77FiRVIsLqZ2MQs+C8A+kNobR6AeLowGeQ5gCy1Y1PQ3hd+C8k3Idkdc1FCKwRL/4AEu8SsrrjbQioF6OQfJeQ1TkIph2PgIAgaAVBdOSVG8HBxm/1fQigJx/cARoWPqub4LCuHH4MRHxW354PB/Xl/Z+Ai2f1HZ3vKZfnQaZ8rTTJIsXzQ5ABK/MD2K85wgaszt0Me3Xn8yccH8fqnZib6sKhfXuLRe/+05A2BeI5aFtdb74L+0JcfP0Xc8YZBeSypR1nII1h/uNaXVRfqvNbvw4nKSINq49BOoO8/Q1h9QfzCOwJ8MYMiF9U6taPQFIDwLUyVZdq5IFaiFxgrjoKqfXzimP1vqkofYwsgYjFpvEgpNfPv20r1aXSREqt9WPL6lnzu/DNxz0Qqfg0noQklzl3e6nGNP8F38q8ClF0YKFcI2FdK8UPsH8KxAgza3mY8XCkimyDVJe5UWl1P4SXaPoIQnhcCkeqyOQhSIvH4fk15s9h22NoEoSXkbQKYKW4WM/XmIdh02MrhFYR1iqCVbN0Z41ZT4swcyG0kpBWEawM6eluv69CjMTmZ+t2QTBBIax+DYnxuF62OghhldR1QSigEFarIDEej8hW2yCsirBUMayaITEej8tWmyCsAkmqGFZTIDEeT8pPizYIKyNLFcNqEiTG41H5WkVaKaQK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' +r12 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAAQEBAgICBAICBAQEBgYGCAgICgoKDAwMDg4OEQYGFgcHHAoKEBAQEhISFBQUFhYWGRkZGhoaHBwcHx8fNxISISEhIiIiJCQkJycnKCgoKioqLCwsLi4uMDAwMjIyNDQ0NjY2ODg4PDw8Pz8/QBUVTBkZUhsbZSEhQEBAQkJCRUVFR0dHSEhISkpKTU1NUFBQUlJSVFRUVlZWWFhYWlpaXFxcXl5eYGBgYWFhYmJiZGRkZmZmaGhoaWlpampqbGxsgysrii4urjo6tz09wEBAzURE00ZG1kdH2EhI5ExM7k9P5F1d8VBQ9VFR+FJS/lRU/1ZW/1hY/1pa/1xc/15e/2Bg/2Ji/2Rk/2Zm/2ho/2pq/2xs/25u/3Bw/3Jy/3R0/3Z2/3h4/3p6/3x8/35+qampqqqqq6urrKysrq6ur6+vsLCwsrKytLS0tra2ubm5urq6u7u7vb29vr6+/4CA/4KC/4SE/4aG/4iI/4qK/4yM/46O/5CQ/5KS/5SU/5aW/5iY/5qa/5yc/56e/6Cg/6Ki/6Sk/6am/6io/6qq/6ys/66u/7Cw/7Ky/7S0/7a2/7i4/7q6/7y8/76+wMDAwsLCxMTExsbGyMjIysrKzMzMzs7Oz8/P0dHR0tLS1NTU1tbW2dnZ2tra3d3d3t7e/8DA/8LC/8TE/8bG/8jI/8rK/8zM/87O/9DQ/9LS/9TU/9bW/9jY/9ra/9zc/97e4ODg4uLi5OPj5OTk5ubm6Ojo6urq7Ozs7e3t7u7u7+/v/+Dg/+Li/+Tk/+bm/+jo/+rq/+zs/+7u8PDw8vLy8/Pz9PT09vb2//Dw//Ly//T0//b2+Pj4+fn5+vr6//j4//r6/fz8/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfVCjXAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABVDSURBVHhe3Z35Y9XGncAnbCjp7qZpmt2w2zSEdrNH98g2zZY2QAN7H93DzzYGbGzsgMvSpkma5XLAnMEEGxsMhjSwaa4t2OAYAwaWhCSLsY1DOewGW9Zfo9Xx1UijGY2+oyfpPfXzQyLrjd7TB0lfjUYz3yGGjB+/97leltx8C/ZQTJjV95575VfwDWXLp7CvPGKrZ/+zTI9RkE9ghwMIrX4G2+QBzXgO9toHb7X+FSifF+7BjvvgrXJy7vn56Eew7y4Bqw0noGDOgN13Ya2Wfgalcse7YODgt1pgaFAmh3y6HiwsmGMFBfLJ7Q1gYeK3go/zyufHwIOxgg/zy+0XwcRnleNryuVjUPGsfgmf5JqfL3RkHKul+tuwPufYNq7VvfxfVA4zx20f2+qy5KLShs8NlBdnz4/NwM7xXPKs9DdgXZChtubqijJkxZaOG7CLQajVjPj803rXwpeUI5XbzsN+stwCq/fFoeL687B92bJzAnaVAax00aGaOVgF25YxtWdhb/1YB4sYH+o/hb99zOyFDcubytOwv35sK10QAHMiJdZ6caFB3hGdgJ2wUflTKYgZGwyi6/zj77VK2CYH1E/BTnuYx0p/jrulTTfBFlhqN7+6tWV1Af7KmNdgrz3Wm1b8CXgYyqNYtqd/3Nls6nxnPazMlBHn5z0+EVnNrIbiCFZ1T8JWDgMt8EGG8AfrXcLXls5C6WgKbfxJfXoFfJgZy9h/WBON6P8Hi5QdUDqS2nOwBcOdV+HjzDgJv0wxyEJY8miAwlHUjcIGAbTtUCAr9sAPU6y7cIAJZCwLk8peaw38LuUoWQxLlEEoG0HVdSgvQGuGQtlQFawcHSfPwRKlD8pG0AXFhYxk+1QWrLufMOsWAU5CUTnN/n+fqf4jh3uZx7hDUCwb4IZJOUqehSUKzspX/Rp7fbm1prB1EFaYaHV2qYwIPhef4KMFyqoJCpv0eZXGVu8AZlo/TsrqCBRmpPxad7N86EzIqkBv54Ns9d67dWR5L07IqgHK6voWWANU0gu3A9ZkQUJWO6CsPhK8ZXfAB/oHsCILErI6CGX1fbCCUgsf6HdgRRYkZEXrk/zV49biNfg7C1StXmsH2KDQC2X1jbDC4w58omf4aKxqRWuwy2CFQx+s5a2qpuGTcj5WIVaNm4EaWEHZDOX1MViRBQlZhdMN5fXTsCIL0raqobfndliTBWlbtUNxURxJj5StGt1YoY/CmkxI16rWez7O8gRM12ozvVfpkythXSYgrdoOAfTZ+TCsOOh8j4BCu+/xONt3KkirC7DMM+18D8/yAShhMZRtm3tqVmv93zyS6fmXmlXlfhr8TIaybpROx6p5GD61OZN5Z4Y0rGoOM62M3dm/x0rBqpVpjdPaYHWWJG5V9wF84DC1DdZnSsJWhTb23dEQ9n1KsiCtNm0DaG1hB6zY6nyPQwNrr3WW6C050ooiqzEF3zTeyLKazpCgVX2gp0Mf91ycGYlZFfayB2pyJ3xQCpKyWuV7/2FxfhV8UBISsmplQ9/0696dd1MLAH9nQUJWtOXMZtjfl4b+QobxMAUrrYt5qfPrYTUWeLOdB6s1GwG2yuqzGjrLQh9J4lstq9+4ve1gz6nevjP9AwP9fScPbK2Fj8SoWoXAXldilK1qm7ft7Tw1eJ3rwGNx54P2ltAnnDK1WtHS/oHXlBPGxKGQPm3lZ7V88/4zwb0KRRtoET29lZVVYe2+PhqOsIzu4b3Kx6qq5Uj0OSfkHFePKROrmh2nhTEBx+Qe+BqXcrCq2zvINHTE4Cwb6Utu1dh+DT4vigmmmpmQVe3qaKCon6odQ/AjRTPt10rIKha1B2KGByF+rdJZbTxd7MUUwKdVIqvq3UzrbjJ4WiWxqj8oHChVNHSMRAmsGvsTPvU8hiHOZm5VezI1JxPoW5mxVU0XPzghSbQ19s9kalW17y58Z2pct1sXMrQq7BiDb0wT+z11dlZbEqkZRTJtvazNyqpJNDo0FayesNlYVXWlGfhYxs3ononV8ylUJMLZnolVZUd2B8riQhZWTdlECR/Pp25V2e7veJENh9K2Wp3YU6ECF9K1KuzL/kCZTFemaVUnTjiRPk0pWjUn+fyuxO70rHaV5OyzOZKWVeEQbF0KLqZkVZNZtU/EdDpWDdwA/2xJxWpLOo0teNKwalOs9/3C+EtCHoyEkNl/ZlyFbeQER9YWb1XZA9shOf4UIfcT8ngkphUhDxjhabI8EreqFuZNCOXWEjLn+0eRaVq1Y98i/P4JSNqqWq0+cWUe+e5HsIzCIASRUjjh60pR6sO5szH/9H6WkG/BkoRkrRSl7n1j1ouwiOYymRMdjBK1UpQSJdOIZi75GJbCSdJKVerjOY/FePb/GonMraklaKUqpT8d51BpDzwCS+FMJmelLKUT8j4sAZNjIxzjgar/cT5VBcf1xKzUpT67fz4s2Yx0iNM+Ve1kmnMMsg6WwhlMykpdSv+R/6dGZf2pd/vqE9+YxWVW4jiVkFXBP9gKySLf/bQ30I03gJeT5pNZfwBLEjoTsqLZBfDMPPIlGgFfg68Jo0Abf1E3g73JWO2Eoiq8Tf4KlvQe+JpwaKqTBeQtWJLQmojV2jhNFN6/+rXo5CtuShPtoYcRdfbmJKzqYjUmfZO41VpEbtZtUBQT13V9VQJW1bEa0r24PgzfI+MAlMXEdV2vTsBKlLY0Gi+uYxLKuGOFMHFdn0igRZomhlHDi+uIhMfLIVqi4rp58Iu2aoVSinhx/S5i2KP7I7hK/tmirZpi9p/w4novfJMMNy0NKq6bO1yk1fLg9li8f3VEJskCBFlcXNcPFGsVL1KY0LiuIUZIP+8URcZ1vbVIq5gXlT+uD8FXyXBTf+Diur6qOKuVsTvwpBjX9btFvu3uhxJyPjNOvBPk23Hi+seouK4PFGeFqNPOHF38KBGRXlw3g0UxVrXR7wg2PEHI1x4kS4I8k2Jc17cWZRX5oHhrEXnIuAJ/MKQZ1/XaYqx2w8ehXJ1PFodMn5VmXLdy38W2qosa13Fz3izuq4BU43q/uUlsq8D4YI6Zb/Pf5JJmXLdTJMW14rOFB/gxWQRLPLHq68i4rlud2mNarYg6/2bmzg59LZhmfV3XrSs1plVkv4N1hE9y7JJmfV2/YW0Tz2pVZPPLs4HvmR7s63FJNa7bCf3iWUUPt/r6/b6grg3s9GeF+MMU47q+y9oolpX7S+Fcve9JWDIZdbrOu/zbb6QY151/qFhWUVGdvbRPBlqb/5Z+lkJcP2dvFMdqC3wg4TuETstkVjZZ/iRWXL8PF9edPEkxrArR7X/al77iXtpnueD922nGdWeQbQwrxAPIm/QWPM4FhH9UiuunoOwC8t+wJAVaTNWtqoKbCDDIelgKjuStqPgb+gspxHU43dWt9sFqGTSuT9tZ9RlSjevQZK9sVYPoT+bFdX5+i1Tjul2xMFG28lK9huNd2lwK8HTjejdspmrlZZGX4MX1RtjMI9W4vhm2U7XCtAB6cd09I3woxfXtTlFsXJ9wB8WrWmFe1Xtx/Qhs5ZFqXKdfqWjlm2AjHC+uMwnrbFKN63TOBUUrVD9NL67z/Q3SjOvenAtqVssx73VKFte9TMFqVpg7cMni+qT3DKdkVUANjS1VXPfN6adk9SqskVKyuO7r3KVkhRomUaq47r+IVay8aWtklCqu+1PQqljhhumUKK7f8J/SClYF1JvFUsX1/bCVjYJVM/wtp0RxfZo5+ApWuD6AJYrrp2ArBwUrVF61UsV1tskRb9UIf8opUVwPTK6Ft9oPf8rBxXW72VhOJcQmVFzXAmc73uoi/ClnPiauCy45jhYoiorr7kXigraic45JwcX1wFUgYpk7MhIT16eCuUfRVpEvF21wcV3fDavCoW9dMHGdmwsSbYUbKouL64JIEmAvFETF9btccnGsVQ2qGzQurpsXnTxze/URGiAwcZ2fWQFr5d495ODiusldWUrwJt+cvoi4PsZ3HMdaYZI5YuO6xWRYqtrlu/3pLDFxXVD9R1oVcOOaZXGd0LjuoF0cOMMxMMSe6S+T34elUC4K6ilIK9yjlSyu/7vkpX44c/ndCeK21/pBWtEZQaXI4vo/kGfgMwVuf+WhX8FiGMJp7ZFWuAdGWVz/e/I0fKZAdAScEk5YgrRCjRmTxvV/Ir8TXZ8L8OKsb/oihxDxfDk4q0pUr3VZXK+o+C3yAnyKZf3s32MDDM858SMNzgr3FCKL6xUVf02+/B58jOKmQR67DMthTIbc9nBWu2BRjiyuV1T8x++SLxq3nALRXDIeIgtuwh+h8G+dHXBWh2FRiiyuW/zgjwj5wnzy8HeimE++PpeQJ16GbwtHGP8scFaoDFiyuO7wd3/8m9BFOorHlh6Lji0TobPRo6zobLpSZHGd8oN//hebf/3fKzbHyZPOgo9fXLoHXyQn/IkaZRXdG8tEGtc53CsVUycPQTIROMrKm/5dws+kcT2IO2zm6eCodTQTktkSUVaoN4zyuB6gEmrL974411lQR9ZSj7JCBQt5XA+w0SmqHyVLYUkVaeMbygrTxyIqrrN0QlmDKCcjcRiSjjHGWBWiKmMW0XHdj9sZ7/HZ6Psyw3jxM9qshAUpqLjuUgvR8gr5c2dBkemIpjeMFSawZxvXo97pYawwr4O9uM6+nRDjzlQZM65z7X9BMFaRo3dMvLiOuKxq4UKNGdf7I9+oYKwwo7dpXNcPwTeHU3CThsWL68PRdw6MFU0uEY4X16HvtQw3rMeL69KmRABjxc7XKsR32U9ETT65g9bG48T1iGZfB4wVItODF9d1fUB62lf3UKkr5C9gSYGwB0UGjBX0e5DgxXWLbsl9f6Mvt2WcuI6bVh9h5b7KlODFdZs7HcJbf6Gxk+kIFSOu46QwVoix9k9wW03f5ZgIVLxuq7fmIqUwVohgQYhwAK2c9eRRWMKClcJYIRJIfXkOLCgw86ezFE9AtFRCVg/OimoO5zHIElhCgpfCWCHenc4jr8ASmje+8NXIPIAMClIJWRnkScwzmI8X5jz8P7CIQ0UKYxU9Mk7/8AGyGNfa5fDRIvLVFKUwVpgEti/MIo8bqKEcuv7LVxbPIQsjW5sZXofdRZKQlb7BSWPxSBSzrVL3PfUmbIZjqhX2FktSVvrnP/zuPEIejcJ0esa4BNsgueGfWhpFMtdVqlxA9GYNgLAqaQJ5sxoanYePA2GFqDGlh4Zph+NAWPXC/0vBpH/GTDwIq5OlS/c/Kk4WGwnGqmQHa5AfwYoDY9UGCxmjdYXO3RsFxgrXkT1pRhC9w8PAWFUr1lyTQDsUOi08AowVfYORHdIEzNGgrGh/0aw4XMyBMkFZLStipvAY3BB1jlMCZYXrRZIUwdwlMcBZrYbFDBiPV5tgwVkhMsUkw1RnVCs9CqTVVlhOF61H/roXDdKqoJ4qX53+mLU+HqRVRX26sx2bXCjuFsWAtUKOE4nNiH8IadGgrVINGHdei12RFYK3ikzuGJu77cXfoVjwVshuqspc3BmjYSICBauK12FFgkz3FvG8EY6KVeJa4+2SPn7FoGSVrNb51mRDhA81q+S0po6IGmRrmqPBtHkqWlW0xZk6JMhkX6s46m2GAjKix0SqWxU/YfX44S2hZ17JrCoqDxTRjHH9wBpZH5PSWVVUrPGNO1RAO78vZNQfpZRWFVX7MT1x/UwOdm1DXOYltTJPw1b0o8nU+YPbGyJ79DmU2MqkqSfy4WR6qHtnI1LIpvRW5t1ly/4zolNxcmSwt6uttble+S5bDlY2K1vaDx051XfqZM/h7oOd+7ZvaiiiAk6txvpYfPGJtVqxFWBu6kVbJQq1Yn+zsN9372etaE9nZnBKHqzq3bw4Nr8mVnvYqJQ/K1q79W7XKwOdw66xd/I8WPFsY1NbaQcCcTWPVsvcRPrAMDexXg6t1rApoLROvoUjd1aFdvbh4LpoIE/erOrYmqZ20H+gVuwCuuFj/Rys2GWdpGVrtYPNEzLMtkWthdUCrLTfZWpVyY5NmdofCH25tFrG3qTOcgNe8mi1kmkbuSMYGZdDq0Zmp3pE3X7yZ7XZHyfGxG+1cmf1qr/FsT/kNXHerPwvNbXQrtF5s/L1hx1vhnU8tR0Azel1EVZ0WF1Qys3Kl09tENOino8ak/fY24NqnMqFlZd57BqugSoXVu783Kgpyi1yYUXr6QOwIoo8WBVoPwFsH608WNXDT+pT3FPv6m0AW9PNgxXtt8znj6Iz6eSv5WwT/KQgKwxNccBmYVq1F9gEK2zK9FhZk5my0Ed5RBb+MrOifUZHYYUH7UZFJ3iRUF5WBVq1DXYo9m7PafRMSBl6vwqegjSFJiYtTblZ0Xz9Gtv4V0efJO0ZQaMoMytvzqYJf5Wpzsu1gEg3VnZWvjr7hHe0VnlSY6iafLlZ+Z6vtH4nZKzt9T3z4wYOB62O8zknMrUqMO8VR/t7+4dh2WYUN4Ak+A7+JT6ZUB8UzYYGWX8HDdmPOpj1+jhZDEuU6FREiSIbQBSd68mmKtjT6h5/XU2q9ANJgC74XZ5e5J5wLVAfCaaESGxIAJIwLawUf7hPEP0TWKQgZv9Ilr2ia0s7gD5nuEGz64h+DBYp56FwdjQwkdBG+KZRTA33j2IQnbuwZpRzFhRNIdCn7dpuhU7v/Jx+bwussr1juTR1nXNaMaYuHApvxBVQ4KZJmjGP1SKuB2qgqpkZhYbmTc2Nqj3X+H7cPzetdD5RyEjygx5So5HvxW1YVvwpSCfuLX+qBLMkvWxZLRF0glbLsVM6qgQ5sd61j5X+E+cvhnxoiaTME9C2EpyCut6T9CCpFBDc56ypBkyrt8yFE87fLGNMk1sZUmgT1vdNKSf/ovBg6TMDWzKu6KpQvZt5EqNYh8q0srIl/ZezhmOko0U9j1AG1G/vDj5TuVhSppV9sD53VgmYGR8eKjOGw4xM3v8+WL1j/iE+B/OHdsw9VoaVD/W4szbv2E6OlXWgFn7qrM43b9pOYGXl9luqkhCwTLliK5nYVsZtc9ViX2LefHLzh7aMiWNlX1r2f3LMrZccFxOwsmNgvrVu/gRUTFwrW2thjq+tD8HDhlo5R+uqXSKHnAALB8/KsB+zjtpl8saMsQAkHHxWhp1mFz8TV/lwyXgcFAC/lWE9lej6upwFjduw9z4YKwNquS/lyOu2cXQe7LxHwMr4qVPWUMu6WzIuG8ZTsOd+glaG8YZTfvE6d26NsuWSubdPOjsdgLcysSpQFobx5tWyPBnvXd5gfE9/D3Y3iGH8P1hheAf04wkrAAAAAElFTkSuQmCC' +back = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAABQUFCQkJDQ0NERERFRUVGRkZHR0dICAgJSUlKCgoLS0tMTExNTU1OTk5PT09Pn4AQn4AQUFBRUVFSUlJTU1NUVFRVVVVWlpaXV1dYWFhZWVlaWlpbm5ucXFxdXV1eXl5fX19az+RUUGvU0G0UkK4TUrcUVH0U1P6VVX+XV30Wlr+YmH9amr/bm7/cnL/eXH2e3v/BJUAFYUAGIQAAKMAAKoAC60LEa8QE7ASGrIaI7UjKbcpK7grM7cpNbgqMroyPL08e4UAZb48Qb9BRMBETMNMVMVUWcdZXchdY8pja81rcM9wddB1fNN8Z5a2cJuqlkJ0mkNyzktfykpg81FS+lNT/lVV/1tb819p/l9g82Bs/2Ji/2ho/21t/3Jy/3t7vHy+gXn2mn3hvH3A3W+Q3XCSgYYAl749mL08vZUAwpYAyrcpyLgq7aMA7K8Q8KQA/qoA/6wJ/68Q/7AU/7Md/7Uj/7cp/7gr/7oz/7499Zhr/5ZnzsBD/8BD/8NM/8VU/8pj/81r/89w/9By/9J7gYGBhYWFiYmJjIyMkJCQlZWVmZmZnZ2doaGhpaWlqampra2tsbGxtbW1urq6vLy8hIT/k5P/mJj/gKfCoZjYpJzYoaH/pKT/qqr/rq7/s7P/u7v/gtWCiNeIi9iLk9qTm92bo+Cjq+OrsuWyuOe4vOi8/4KC/4yM/5CQ/5WV/5ub/6qF/qOj/6mp/62t/7Ky/7W1/7m5/76+wcSDwcaJ/9WD/9eI/9mO/9uU/92c/9+g/+Cl/+Kr/+Sx/+e5/+i8wcHBxcXFysrKzc3N0dHR1dXV2NjY3d3dw8P/ycn/0dH/1dX/3Nz/w+rDy+3L0e/R1fDV3PPc/8LC/8XF/8vL/9TU/9nZ/9zc/+vE/+7N/+/R//DV//La4eHh5eXl6enp7e3t5eX/7Oz/5PXk6ffp7Pjs/+Pj/+np/+3t//Xj//fo//js8fHx9fX19PT+9Pv0//Hx//X1//ry+fn5+Pj++fz5//n5//z4/v7+AAAAwISkTAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABclSURBVHhe3Z15YBXHfcff0wkoQIsQAnNIpGlcFWLqtEGA6tYkMTS2oadLDzdO77vp5TZNL/cIt7ksuWnrxA6JDxK7pooP2rShcVqQkKjrJG0wmKa20GsOgRspAeTgob/fzG/v3fdmZn/v7Vt//rCl92af5sPb/e7szuxM4WoFRF1BlapEBSv6sPqC6laGslb0KfUJ1TGWMla0dZ1DlQ2SaEUb5QCqsJ8EK9ogH1CdfcRaUencQNX2iLGiormCqu4QsaJieYNqT4StqFD+oPorQlZUJI+QgSRoRQXyCTkgASt6O6+QBeC3ojdzC2kAPit6L8eQiN+K3skzZOKzojeinDw+0F9XDBwfpapFIBfXil4OcXJ5e1OhDmmc1z1CVQxCNuWs+ufTh9Ql7Qeomn7IhqzoRT/jHbR53dI+RlX1oXSUFb3kZ39d7npBmvZQZT2kTqLVbtqwztlB1fWQPtKKXvCRE6kYrTJWB2ib8hSbW2dkvp/upSq7JFqNN9MmSTTNX75vuKTK7l9AL2ZDYzgyEq06aYt4Xrd1mMoRI3PpnUyYT7VwSbA6RuXjaOqKO/0to3cz4R6qhANZ0W8uyV9V664pKiMunX3+qY//zX33Pyd/y1KrXdbAR6zVGJWO0LRzWpW4cOTxd24BfrAHuO4/8KUsd8JIszDOajsVDrNYxcOlp9+FRsBtb0Srnp4H4NUTVCgLumW9fMRZxWda64B88/zhHyOnLVter6R6evDbyjAJo7sgWNGPLq1UOECH/KIu+Jy2/Mi1JNWzCt7aRwUzoAmr5ifGapzKBlgu33rK57Rly7eSEwCREbtZjYgcWFGrESrqoyhbkRPO8aSQUUHgkdVI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' +r2 = b'iVBORw0KGgoAAAANSUhEUgAAANQAAAE/CAMAAAAJ9B3fAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAA/1VV/1ZW/1dX/1hY/1lZ/1pa/1xc/11d/15e/19f/2Bg/2Fh/2Ji/2Rk/2Vl/2Zm/2ho/2lp/2pq/2xs/21t/25u/29v/3Bw/3Fx/3Jy/3Nz/3R0/3V1/3Z2/3h4/3l5/3p6/3x8/35+/4CA/4KC/4OD/4SE/4WF/4aG/4iI/4mJ/4qK/4uL/4yM/42N/46O/5CQ/5KS/5SU/5aW/5eX/5iY/5qa/5ub/5yc/56e/6Cg/6Ki/6Oj/6Sk/6am/6io/6mp/6qq/6ys/66u/7Cw/7Gx/7Ky/7S0/7a2/7e3/7i4/7m5/7q6/7y8/76+09PT1NTU1dXV1tbW19fX2NjY2tra3d3d3t7e39/f/8DA/8LC/8TE/8bG/8jI/8rK/8vL/8zM/83N/87O/9DQ/9HR/9LS/9PT/9TU/9XV/9bW/9fX/9jY/9nZ/9ra/9zc/93d/97e/9/f4ODg4+Pj5OTk5ubm5+fn6Ojo6enp6urq6+vr7Ozs7e3t7u7u7+/v/+Dg/+Hh/+Li/+Pj/+Tk/+bm/+jo/+rq/+vr/+zs/+7u/+/v8/Pz9PT09fX19vb29/f3//Dw//Hx//Ly//T0//X1//b2//f3+Pj4+fn5+vr6+/v7//j4//n5//r6//v7/vz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0cgG7QAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABLQSURBVHhe3Z15QxRHGocdBgcEQVwSNR6wKsR4xIsENBohaASNQI5NdhfwjjEuKxpybJJNNsEbybEehDURYegPOtvT/aP6qGOqqqtnun3+mZnq6qYeeqa7uo63lhVEvP9fyypY+JAMrCK/vItPbPhSvxRl/rPoHCRp/PF3u2w/OcVkwZH6pVD4CgdILAtcL6bUYuEL7Jhw8ihwCIbUYuFX7JMGPkSp/VBSPxd+Rva0gIL7oKQ+QtYUsYiiE4JSXxcWkDFdfI7yg4DUE/cukEJ+h4GLXyr/N2RJI3Bw8Et9i+3pBBJFfFLfY2tagYYNkXryL2xLLzDxpL7+C7akGbh4ZwrpqcauDTosSSE55XzryrhSP9vPTc8Fjs3SmUIagwdXL19KFlcmnqFsDBwbVwopYR6f3P2nTAJZ3nrgE87T6xdE6nOkBLnZVYODJJGXTj1FOYMQKXwOMN+Txe5J5YUxFDXAfyDFqvJNbsSuCabq8DxK6wdS+OTnWj12TDa7GFb2YwhbKiVObCtH6nd88LiXFqdM5jUU2Ycjhfceiy9jjzRwDoX2+IEpdQr5A2Q37Njz6rbV+JQcGh+i1B62FPUYNVuH/B5rj1+dczdOXzi4AokJ4ZBbMB+2FN55UCdqxyVscfntnRewIRHUzaJcBIbU4nrkBo1nscFj7nAVNiaBAZSK8D0tdQ15wS76O2szlqA64WaUyYOWOom8LvvzSA5xpxkZKk+OulfRUh3I68BzSpTVdRSJsOw9vCH4f1JbuU6WdSuHTBWH+lEtox47GpHVpuY20pj0IVfFOYoCEZZ9iDcE323oJJIcpkYHBi/gbuWQ34JslaYbBSIs+xJvCJ5Us+/L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' +r3 = b'iVBORw0KGgoAAAANSUhEUgAAANQAAAE/CAMAAAAJ9B3fAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAALi4uMDAwNDQ0/1VV/1ZW/1dX/1hY/1lZ/1pa/1xc/11d/15e/2Bg/2Fh/2Ji/2Nj/2Rk/2Vl/2Zm/2ho/2lp/2pq/2tr/2xs/21t/25u/29v/3Bw/3Jy/3Nz/3R0/3Z2/3d3/3h4/3p6/3x8/319/35+/39/gICAgoKChISEhYWFiYmJioqKi4uLjIyMjo6Oj4+PkZGRlJSUlZWVlpaW/4CA/4GB/4KC/4SE/4WF/4aG/4eH/4iI/4qK/4uL/4yM/42N/46O/5CQ/5GR/5KS/5OT/5SU/5aW/5eX/5iY/5qa/5yc/56e/5+f/6Cg/6Ki/6Sk/6am/6en/6io/6qq/6ys/62t/66u/6+v/7Cw/7Gx/7Ky/7Oz/7S0/7a2/7i4/7m5/7q6/7y8/76+/8DA/8HB/8LC/8PD/8TE/8XF/8bG/8fH/8jI/8nJ/8rK/8zM/87O/9DQ/9HR/9LS/9PT/9TU/9XV/9bW/9jY/9ra/9vb/9zc/93d/97e4+Pj5OTk5eXl5ubm5+fn6Ojo6enp7Ozs7u7u7+/v/+Dg/+Li/+Pj/+Tk/+Xl/+bm/+fn/+jo/+np/+rq/+vr/+zs/+3t/+7u/+/v8PDw8/Pz9PT09vb29/f3//Dw//Hx//Ly//Pz//T0//X1//b2//f3+fn5+vr6//j4//n5//r6//v7/vz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA75ob3AAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABOtSURBVHhe3Z39QxTHHYdteweCUDSgUYMBJS9N39JXI7EYojEq+IJGQo0GCvgWNSI10RASmqavhhhjlNA2DVU0CZ7H/ovXvb3Pzc7uzM7O293t+vxyx8zs3T7s3u7O23dWFAT8pvDXZSeJ5D8q/BL7yCNS6vkCPiCxLBd+jH0NEyWFDRPOMvY2BFfqH9gmDXyMfabhSP0NxdMCdpuClULRNIE9J4SlvkK5dPEP7D0ISaFQ6lj+BQQ8glIokkZg4BGQQn46gUMRWgq5aQUWLpQU8tILPGgp5KQZmBCpnyE93UCmLJVHcrr5piQDqY+RmnZKNpBCGofF6SuXk8XVD+9j3zj8qGhTkoo4+ZZO7d6YSSDZTXsvPMQ+hvjKl0JKkNtHWvAhSaRtaAH7GYRI4e8Ay6ON2DyptFzArgZ4KJCa68amSWbXXewtDaQ4jSu31mO7ZNN5B/tL8V9P6uf4iyIlTnwrT+rP+MPn/hPYJvk8zV64PSm8pziALdLAceyzz7Ir9WO893kX5YM0v9Dbu7UZfySHlZ9gr314R2r5SZSnWH/i81LmZ2+sQ1JS2F7aMQpX6hu8JVxBaZ/V56gzN38mYffkz7BjhI9WsD+pXhQm7Ajdu+e3IyMZHMRuEZZZqcU6FC7zCnOByb2MrETQzOwfKxW+TLzEedrNJepYXcdeEVipYygKHuPc3twzMEm/qzPYKQIrFTq1LiI5xFlkJwHmR8VKPYuiJdqRGiafoAep3dgnwgqmxaULRUuMItXl87HxL/DW5QQKJIBe7BKBPVJbULTEPFKd3KtZt8q5j1Q4b6JAAngJu0SIkWpDouPsKiXsxZ+Ok5xLharUDiQ6s0jI3kSC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' +r4 = b'iVBORw0KGgoAAAANSUhEUgAAANQAAAE/CAMAAAAJ9B3fAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAALi4uMDAwNDQ0PDw8Pz8/QUFBSUlJS0tLTU1NUlJSV1dXWlpaXFxcXV1dYGBgYWFhYmJiZGRkZmZmbGxsbW1tbm5u/1VV/1ZW/1dX/1hY/1pa/1tb/1xc/11d/15e/19f/2Bg/2Fh/2Ji/2Rk/2Vl/2Zm/2ho/2lp/2pq/2tr/2xs/21t/25u/3Bw/3Jy/3R0/3V1/3Z2/3h4/3l5/3p6/3t7/3x8/319/35+/39/urq6u7u7vr6+v7+//4CA/4KC/4SE/4WF/4aG/4eH/4iI/4mJ/4qK/4yM/42N/46O/4+P/5CQ/5GR/5KS/5SU/5aW/5eX/5iY/5mZ/5qa/5yc/56e/5+f/6Cg/6Ki/6Oj/6Sk/6am/6en/6io/6mp/6qq/6ys/66u/7Cw/7Gx/7Ky/7S0/7W1/7a2/7i4/7m5/7q6/7y8/729/76+wcHBwsLCw8PDxMTExcXFxsbGycnJysrKy8vLzc3Nzs7Oz8/P0dHR0tLS09PT1NTU1tbW19fX2NjY2tra29vb3t7e39/f/8DA/8LC/8TE/8bG/8jI/8rK/8vL/8zM/83N/87O/9DQ/9HR/9LS/9TU/9XV/9bW/9jY/9ra/9vb/9zc/93d/97e/9/f4ODg4eHh4uLi4+Pj5OTk5ubm6urq7Ozs7e3t7u7u/+Dg/+Li/+Pj/+Tk/+bm/+fn/+jo/+np/+rq/+vr/+zs/+3t/+7u/+/v8fHx8vLy8/Pz9fX19vb2//Dw//Hx//Ly//Pz//T0//X1//b2//f3+Pj4+fn5+vr6//j4//n5//r6/vz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASP4oJQAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABDtSURBVHhe7Z39YxTFGcdTa99b+4oJgTRAIFERkqooUAtBSoiABBEsIUIJIK+GWvtisa1W25KAsWmAIFparW/QiIQ3a0F5qybhsn/U9Xb3ezO7O3N3z+zO7u2k+fxytzM7y3643N7uzDPPVGSL8eCbGSuNjL39DM5QSiGpb2afG8MRUsufca4CcqlJv0y9kctLOGE/Uqk30MQEPsQ5e5FI/RG7m8K7k3DiDFEKu5rEb3DqeQJSi97GfmbxX5w+CEil8wpOAOfv4pW6zcQ/vTzPQcLGK7UI9WbyJ1jk8Eg9jVpT+Qc8PFLfMPlvz4X9EvNPCjUmk78hZFIoNxu4QGrRf1BsNmOuDaSeRanpvOPYQAplEoZfP9qfLo68egXnJsGxcaX+jaIAmd61TZMrU8jsVV3DOMcAzh+gK4USP1e334ljpJHp7Wdwnn6ehdSDn6LAR+8sNE8rU3ZK71QhJfugrq9B0zSzcAhn6+UXrpTkG3X9AbRLNw2ncb4ect8qWwpbHgxxklvZUt8Sb87HlqBN+rnzGs6Z8679Sd3EBmcPWpjAGpyzB1sKbzmna9AgwP0rwb0oSAW9OGuOVGoFdg9Qy37Il6IkFcwWLuy/r8j+AW8Z5wrcRDyBeus1FKSEV3BajEyF2NeyCTsHqPkY9VYLSlLCEpwWp+LreMNpwM4B2lFtnUBBariAE2NUCF+p89g1wJSLqLceRklqEC4VotTL2DXAT1BtnUJBetiMM2OIUpuxq58p51FtrUJJehC+VKLUOuzqZz1qrcEqlKSHe3BqDFGqDbv6qD6LWnl1eZmLU2MQpdai0jqdwifhkFKT2VPmoyhJEyGl2lBnnalGSZoIJ1X1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' +r5 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAALi4uMDAwPDw8Pz8/QUFB/1VV/1ZW/1dX/1hY/1lZ/1pa/1tb/1xc/11d/15e/19f/2Bg/2Ji/2Nj/2Rk/2Vl/2Zm/2dn/2ho/2lp/2pq/2tr/2xs/25u/3Bw/3Fx/3Jy/3R0/3V1/3Z2/3d3/3h4/3l5/3p6/3t7/3x8/319/35+k5OTlJSUlpaWmZmZnJycnp6en5+foKCgoqKipKSkpqamrKysr6+vsbGxs7OztLS0tbW1tra2ubm5urq6vb29v7+//4CA/4GB/4KC/4OD/4SE/4aG/4iI/4qK/4uL/4yM/42N/46O/4+P/5CQ/5GR/5KS/5OT/5SU/5WV/5aW/5eX/5iY/5qa/5ub/5yc/52d/56e/5+f/6Cg/6Ki/6Oj/6Sk/6Wl/6am/6en/6io/6mp/6qq/6ur/6ys/62t/66u/6+v/7Cw/7Gx/7Ky/7Oz/7S0/7W1/7a2/7e3/7i4/7q6/7y8/729/76+wcHBw8PDxMTEx8fHycnJysrKzMzMzc3Nzs7Oz8/P09PT1NTU1dXV1tbW2dnZ2tra29vb3d3d3t7e39/f/8DA/8HB/8LC/8PD/8TE/8XF/8bG/8fH/8jI/8nJ/8rK/8vL/8zM/87O/9DQ/9HR/9LS/9PT/9TU/9XV/9bW/9fX/9jY/9nZ/9ra/9vb/9zc/93d/97e/9/f4ODg4eHh4uLi4+Pj5OTk5eXl5ubm5+fn6Ojo6enp7Ozs7e3t7+/v/+Dg/+Hh/+Li/+Pj/+Tk/+Xl/+bm/+fn/+jo/+np/+rq/+vr/+zs/+7u/+/v8PDw8vLy8/Pz9PT09fX19vb29/f3//Dw//Hx//Ly//Pz//T0//X1//b2//f3+Pj4+fn5+vr6+/v7//j4//n5//r6//v7/vz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+TpPMwAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABPrSURBVHhe7Z35n9bEHcftld2VZZeVQ0SWywPQ3vdtixUXqaJSClK5u4iwImXtutvb3pcgRURcFxTkUNrS1l4CUhTQ2kvAhday7D7kH3ma4/N8kzxzZDJJniSv8v6BJ5n5ZjJvsrkmk8klZRmf+Nl/zVzy52+/H1XkIrb6ek6FPP7wPlSVQWD1qSEsmXN+h/pWwbX6PpYpAv9+Dyrth7X6yLcQXxT+iYr7YKzeVUJwgXgYdSeqrD77UwQWixKqXyFo9a5/I6xwfBMGLkGrC4gpIAeg4OC3+gACismfYWHjs/ogsovKa/CwIKsPlJFZXP4EFc/qg8WXMs2fQ4aszDeRU2g+AxtYmQeQXnBcG1i9+WGkFp03HR3X6oApPlENHtzZly927H4FdePwEFl92BRcJ114+ktThxk55PJZ606hjtWQ1QX+8W/gwckoJI8Mm/cC6hnk97D6qfk8UgLsnYDl80rdkgFUNQCsMBdkqL0eC+eYCc+itn6ed6yeN3+IeR9Dt2PBfNO0C/X141hhOkBBpPhaX7Osfmi+G3M+7sZC+afpKKrsYd1CXmL9IWLOYzsWKQLT2RYJx4qh/wonfvJtYbhxGbMWtfb4tGXF7ljtovBq7nADs6XxNGpD/MOy+iimifOj3PCCWHHqaVn9CpPEI8LoavJhNY7Zsywr5sL2JkQXxcp4CtUhOEeL0ggEF8aqA9UhPs5aHUFscaxmozrEd1mrTYgtjtUVqA7xS9ZqPWKLYzUc1SF+w1p1INaz6usUcA0iM6YO9SQ424q1mouE3IJ6Er9lr9kvWuUE1JO4aJVfUE/iolV+QT2J/2OrrfeA9mV3TqhDbp5APQklqwBntt9x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' +r6 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAALi4uMDAwPT09Pz8//1VV/1ZW/1dX/1hY/1lZ/1pa/1tb/1xc/11d/15e/19f/2Bg/2Ji/2Nj/2Rk/2Vl/2Zm/2ho/2lp/2pq/2xs/25u/29v/3Bw/3Fx/3Jy/3Nz/3R0/3Z2/3d3/3h4/3l5/3p6/3t7/3x8/319/35+/39/kpKSlJSUlZWVl5eXmpqanJycnZ2dn5+foKCgoqKio6OjpaWlpqamq6urrKysra2tsLCws7OztbW1t7e3uLi4ubm5urq6v7+//4CA/4GB/4KC/4SE/4WF/4aG/4eH/4iI/4mJ/4qK/4uL/4yM/42N/46O/5CQ/5GR/5KS/5SU/5WV/5aW/5eX/5iY/5mZ/5qa/5ub/5yc/52d/56e/5+f/6Cg/6Ki/6Oj/6Sk/6Wl/6am/6en/6io/6mp/6qq/6ur/6ys/66u/6+v/7Cw/7Gx/7Ky/7S0/7W1/7a2/7e3/7i4/7m5/7q6/7u7/7y8/76+wMDAwcHBxMTExsbGx8fHyMjIycnJz8/P0dHR09PT1NTU1dXV1tbW19fX2dnZ2tra29vb3Nzc3d3d/8DA/8HB/8LC/8PD/8TE/8bG/8fH/8jI/8nJ/8rK/8vL/8zM/83N/87O/8/P/9DQ/9HR/9LS/9PT/9TU/9XV/9bW/9fX/9jY/9nZ/9ra/9vb/9zc/93d/97e/9/f4ODg4uLi4+Pj5OTk5ubm5+fn6Ojo6+vr7Ozs7e3t7u7u/+Dg/+Hh/+Li/+Tk/+Xl/+bm/+fn/+jo/+np/+rq/+vr/+zs/+7u/+/v8PDw8fHx8vLy8/Pz9PT09fX19vb29/f3//Dw//Hx//Ly//Pz//T0//X1//b2//f3+Pj4+fn5+vr6+/v7//j4//n5//r6//v7/vz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6r+4xAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABV+SURBVHhe3Z35YxbHfYfpsa9eBAhhECABsjC2MaRO3LS1G6dN0nIYsMCACSaAwQILDOJQOAzI6Zkmbdo6AgFCxpj7MiaOU7dukA2YK04b21yWnVhIr/YvebvH592d3ZnZnZnd9313+/xg7zs772of3j3m/M6gfBBP/svneiL53x8+gVNkwrf61ic4QmL56M9xqhQcq8cTr2Tzq0dxwl6YVj/Ad9JA7kmcNAlt9Y2/GMAXUkL/YzhzF9oqJdceyXs4dQef1V//LTKmjG/g/IHX6o/eQ67U8SoMbLxWv0OeFPJrKFh4rFL2mPDyW0iYkFbYnVZ+Bw0Dx+pP0v1LmXwBFdfqT9N8TxX4CDKOlf7f2JNqfgIbWOn/gPSU87itY1v9Nu1PCgdLx7b6uf4FEmly7588cjhRHD31If/B9q5j9YT+HaT5ubB66jAtgYx4av1VnKIfx2qAff3l9k3DQZJIZu4xnKcX6/FuWP2b/vdI8XB5Cr6fWBbcwql6+LpthU8+dg7FdxPMqIM4WRKz5DQo/x/6k/hMsg5fTDaZ3ThdEsvKsMNHgnRIsbV+YVj9WGdcgi/jS8kncwSnTGBY6for+OByKQX3VIExd3HSLl81rahibW4yvuGhakrjM7OmjMSn5LAYZ+3ytmFFX4B7kN8lM6f9g5y1L3d23SQkJoW3rBMjYVo9jOwFhjZdxh6b60uwIxnQP5Zh9W1sOpxD7gJTP8QOlxPjsS8JVFIvY8PqbWw6rEBum+wW+9Lzcm9dBvsTwMs4KYfvDNKpk34QmS2y+5HqZwcyJIDv4pQc/t14BvroG4zMJlwpXV+PLOWnHmfk8DFt5bmttiGRxTLkKTuZHpyR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' +r7 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAALi4uMDAwPT09Pz8//1VV/1ZW/1dX/1hY/1pa/1tb/1xc/11d/15e/19f/2Bg/2Fh/2Ji/2Nj/2Rk/2Vl/2Zm/2dn/2ho/2lp/2pq/2xs/21t/25u/29v/3Bw/3Fx/3Jy/3Nz/3R0/3Z2/3h4/3p6/3t7/3x8/319/35+/39/k5OTlJSUlZWVl5eXmJiYmpqanJycn5+foKCgoqKio6OjpaWlpqamq6urrKysra2tsLCws7OztbW1t7e3uLi4ubm5urq6v7+//4CA/4GB/4KC/4SE/4WF/4aG/4eH/4iI/4qK/4uL/4yM/46O/4+P/5CQ/5GR/5KS/5SU/5aW/5eX/5iY/5qa/5yc/52d/56e/5+f/6Cg/6Gh/6Ki/6Oj/6Sk/6Wl/6am/6io/6mp/6qq/6ur/6ys/62t/66u/7Gx/7Ky/7Oz/7S0/7W1/7a2/7e3/7i4/7m5/7q6/7u7/7y8/729/76+/7+/wMDAwcHBxMTExsbGx8fHycnJz8/P0dHR09PT1NTU1dXV19fX2dnZ2tra29vb3Nzc3d3d3t7e/8DA/8HB/8LC/8PD/8TE/8XF/8bG/8fH/8jI/8nJ/8rK/8vL/8zM/83N/87O/8/P/9DQ/9HR/9LS/9PT/9TU/9XV/9bW/9fX/9jY/9nZ/9ra/9zc/93d/97e/9/f4ODg4uLi4+Pj5OTk5ubm5+fn6Ojo6+vr7Ozs7e3t7u7u7+/v/+Dg/+Hh/+Li/+Pj/+Tk/+Xl/+bm/+fn/+jo/+np/+rq/+vr/+zs/+7u8PDw8fHx8vLy8/Pz9PT09fX19vb29/f3//Dw//Ly//Pz//T0//X1//b2//f3+Pj4+fn5+vr6+/v7//j4//n5//r6//v7/vz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA46UD8AAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAAA93SURBVHhe1Z35YxTlHcbTY0NCFBpbClgExFCO1lZ6SIutRxWJKIqAQhURzxpEsIh4tLb2sK01giJQpAERRcSrVlsNKEeg2iqCIXhA2My/Mt2ZefadnX3neI/vHO/nB3aO9528H3b32dmd932nwY5j6sP/swrJsT9OQxNDibb60Xs4QmE5dD6ayhFhdfZ/ULPgHDoXDQ4SajWtjEom8CAaXQtv9eMpJ1HeEAZ+gpb78FZvorBBHELTGXVWP5uGgobxa7QfBK2+/ShKGccbMPAIWr2PMgbyGRRcAlafooSRDEDCodbqM+w3FWhUYFbftz/BTmPxn62q1Q/swp8gJcPeW1Ur6xHsMZp/wQZW1rnYbji/8XQ8q09tbDUeV8ezesV6HRt5BvY9t6WrUGzetjv67PsYs5pqRT1V+2+f0VoqIKdMXvw2mljPhVWrgYhQf+aKRhyliFz8VPgzBqs/W9/DhgCHr0L1wjJ5H5oa4CHPyrLCzpQ2fg11C0zLSjQ2gGv1j9B31eNFfvH53Ibm1jLNsbKs17BagyFSoVqfVqz+EPZUbTZFqlRagSbXULGyrO9ixad3OKoYQMseNNrnAcfqZaz4zHPLt16VzBluyVyZyAX8ZxUr/gX4old8AlbjuNErmitr0BafUCvvqTLGim9nmNXh5qjSPEWwKu1AYxgXNFgXYpGxAoWNsboOjWG83GD9BYuMuShsjNV4NIZRbrA+xCJjDAobY9Xcj9YwKsleR1/1E9gYK/6NxVv1oKhBVn9Haxi81Tso6lvtXV4P+89ZgLL5sh6tYYhYrccGn27s6R+GDfmyDs1hOOfsQQSs2J512JAzNFaPYYfVjg05Q2I19Dh27CvIFxYSK/ZZfgs25A2JVcGygsaKbS9IVtBYFS0r5KyG3wquxAaPwmWFnFUEhcsKEqvCZQWFVfGygsKqeFlBYFXArCCwKmBWEFgVMCv0rYqYFfpWRcwKbatCZoW2VSGzQtuqkFmha1XMrNC16kQRawY2FAQtq4JmhaZVQbNC06qgWaFnVdSs0LMqalZoWRU2K7Ssrsf+wmWFllVhs0LHqrhZoWNV3KzQsCpwVmhYFTgrNKx2YW8WWdF8+sQrFy5Z1blm7fqNm7o2PvX4srmjY18hqlYTsTPNrGgdf8WCO+7v6j6CPxXg6NY7Z0f2mVW1SjkrhlyyeG1o1+AA/U9MQvk6FK1SzIqWiQtXvys85nXntYNRrxZFq5SyYuyC+7tlB/Ee6WhBbR9FqxSyonHSnXzfUiH2cq9DNSvyrGieed9HOKQC5bvQg7GKmhVtVrTOXdeH46nyzngcy0PJijIrRi7cSjF0vLwYx3NRsmo5E2h3CG/fKBsOkdTmlmJakDBk4bv4EyTUaOVnNfYe3TdTPb5WTlaDZj2Do1PCtHKxar25B8cmBh3v87AatrIaoeT0jvD+ROZWp3Z8juOmwRbvj2Rs1bRQ4xRCBK/fb7ZWs/fimKnRd7rzd7K0ms51M0+Bbc7pTnZW4zbheCkzs/K3srIa3kl2apTApspfy8hqPvV5RDTlURlZDe/CoTJhWTZW83pxpGzobcnAathGHCczFqRvNSf017xU2Z621Wnc8TPgRFO6VrNSPj+KoC1Nq1NW4whZMz9Fq5FRs4Okzqr0rCbn8+pzeCs1q/ncONDsOLkBCwwaq0F3o3I+bMEjg8Rq6GbUzYmteGRQWI1WvAxAxjY8Mgis2tl5X7mXhgEcT5Tn8MjQt1rkf5PajE26JF92DPI8HhnaVvegmkNeVuTP1b2o5ZKXFfX7KiCVm9WzeGToWQWlcrOiTfY6qdysuEsTOlb1UrlZUZ5brEIFn7ysuF9/1K14qdys/oZHhrJViFReVn1k30TCpPKy2kNl1YHCQXKy2kpkNQdl68jJag2NVVvENdGcrJaSWA07iKL15GS1iMKq+QWU5MjJajaFVfTPfjlZTSawuhnlQuCtvtqWzCko6yPZPWOUvtXlMRcReav52BPDUa5v5hjsEaVF2+rMuKuISlbV6Qp97sIeQXq1r4m0xr7klazOQlFGs+TFot26Vo3c97MAKlbbUdIn4iM+ki5dq8UoE4GK1bUo6cP9CpHAUk2rsSdQJgIFK/2ssGbrWQ1K6uyiYKWdFZVg17O6FSUiUbAah4IM2aywPtbrmTAu8WKOvJV+Vjh/VMOqKflaoryVflZYHVpWd2B/DNJWBFlhzdKxahPoXC9txWfFMuwRZ6SGVXN1AEwc0lb6WWF9VKmlbHUn9sYia0WQFdbTlVqqVhOEuvvJWl2DUj7SWWHdXqmlaNX4FnbGI2lFkRU6fTnnYl8CklYUWWE549zUrJoFv5zumlsPG7kVBkFWWAecempWN2IXLRRZYa106ilZDU2nzx9FVngzkylZLcEeWnopsuJok1NRxWpEOqNXSLLiSbeiihWbh44WiqywrnZrKliNS6e/PUlW9A9xaypYpTQygiQrurya8laXYDMxJFlRvUGBvFVKA3NIssLCUF9pq5nYSg1JVuxAXWkr7qYWNJBkBRuEKms1KqUBRyRZYY1FXVkrlRe7ADRZsQd1Za1aUhqeQ5MVt6GurNUCbKOGJCv62ew4klYiP8EoQJMVa1BX1iqlT2CirJiAurJWXGkaaLIC9/RzkLIaQTFrSAg0WVGdWqCClFV4ZyV9SLKiek8/Bxmr5pRG6dBkxRLUdZCxEvy5TJqalw5QyIrySNR1kLFKadQvTVZsQF0XCashKY2oosmK6ajrImF1NdapIcmK3ajrIWH1JNaJocmKn6Ouh7hV01GsE0OSFT3Bic7ErdqxSgyfFWOxR4a6/xpxq9Dbl+vzS+/oNShkxdt1862JW0X1QtWEJCsuQ90qwlbcfWBpIMmKZ1CVIWyV0jkgSVa0oSpD2Go31mghyYonUNVH1OoMrBBDkRX97hRMAUStEjoCqsJlxWD5rLgbVWsQtUpjYjyarOg9DVVrELRqTOfEgiIrameurCJoNRrLtFBkxUHuGBUErdL5wkiRFcE7YgJBq+VYpoUgK/hUdxC04ga2U8BnhfRL4uBXUDOImNWgVK7aE2SF02kpBDGrcVgkhSArHkPFesSsrsUiKfpZccC7Ys8jZlU7uwMZ+llxKSpyiFmlcYVbPyvcjlihCFk1pfGbmXZW7ONHn1URsmrDEiXaWVG+GPVCELJK4wqjdlaEnKozhKxWYIkS3azoDjv/qyJkxU2wpY9uVnxUe7GAQ8gqcjywOppZ0R/zpqogZHUAS3ToZsV81IpAxKqR/sKpZlbEJYWDiNUwLBDCZ8XH2CPC5kGoFYWI1VlYoEMvK/YMRaVIRKzoO89pZUXvaNSJRsQqYXSRPFpZURa4l7aI1e1YIIN/s0tkxSJUiUPEips8ShedrLgfVWIRsaKeCPp5/G0f8axY544tSELEaicWqNDICjEpISviLjEaWSEoJWRF3NVWPStEpUSsSG98VEE5K4SlcrBSzgpxKREr4slr+azg5gYNRUIqeyvVrJCRyt5KMSukpESsaO+to5YVa6WkMrfa3liPSFb8Aq0VJfPnSoHPZ6OxwmT+vpLnADdBUyICVtSfwpJsj7yLcDQCVtRnTHJ01t3iVAgRqxyfrOCNQIURscrrtiCVj+yIK6RJiFjdgIXM2Vsd+yaLiNUkLGTNhvAL9AKIWLXkEhdH5qCJCohYlbqxlCWbdO6dLWRF/iNTIr38HFoyCFlNwFJmbMH9TFURsiq9iMVs6MNoenXErK7BYiZs43ucyiJm1XwYy+lz/Ab9O5wLWqU0UwxPeXXs9V5RBK1GZvORtVn+S0coglalLO5ntTOyX5IsolYtqX933D+H4A0FRK0EJ6FT5sgile9RUQhbiU0YqMjxJYmXeqUQtxKa3FGJ46sw3QsZ4laltoSJiBXpuTlk8IAmElal9hS0tsyiywgfGStyrb4Vql92E5CyotV65/pTcVhy5KzotMobZ+CQyoyYBPgfDCWtSu0KYyk5+rsWEKQem/Ce7ysja1Ua9jQ2q3L0yaujuqFLwUbvbcOGGqStKl+2NGYvOriyXe6aTTRLcUgr5FcbBavSCMW7nO7uGI8jENBU/cp3JORUS8WqVJone55x4oUV80ahMg1sBoe7sKEWNatS6ZJ1oh08T761an4b1cvOJyYr1K0qr8OOxD4z5V2d131zMMrTEpcVOlaV891JN6wO+9p1Yv/za5ffNHf6mOghD9rEZYWelcvQ6TctW9n5xJrO+1auWLb0lnkzxrViT5rEZgWBVT7EZoWxVrFZYaoVG778LDbUYaZVfFYYapWQFYZaJWSFoVYJWWGmVVJWmGmVlBVGWrHLTrXzIAYx0IpNVxKVFUZaJWaFiVbJWWGiVXJWGGglkBUGWglkhYFWAllhnpVIVphnJZIVxlkJZYVxViwrlmJDOIZZPYs2xWaFaVZiWWGalVhWGGYlmBWGWQlmhWFWEVlx2VLA5lI1yYplxVZsAGzSWjZk0iQrdqvruqww2ioyK4y2iswKo60izytMtorKCrOtorJCzAqPPsWwYtO28+cVBltditZYPZ31sCFHzGo9NjB4qx4UzReR6ZOYFXdLP97q8zR6W0ojZcXNCdNgfYAlxpkomysyVoO5fjsN1p+wxGD/BXkiY8WNFzvZYJ2PRca9KJwrMlbcoNmXGizuA+vjuMkis0LG6m2sM34aYpU0B2EmSFhdjFUfO8yq2yudKxJW3GewY2X9Fcs+wTsW5ULrpcl4g3GnD6DVjE8cq29hxafvG255IxjSg0b7XORY8S9B6zn6zphp0Ykm12A7VtZL3kotG0zRYqf2Psc8q5AnyxStEClrqmdlHXLXghAM402d1rC7xA3YFavfVha+460H6SvCx1YsM0Pv0fWAY+W+/MKeLMvaOS/hl+A8abxiCxfpDs5TVbFysiLsneVwePnsQob81y/v2I8m1nOeZ+UavexuCeXIrh0vFIod3TF3h/vAkXKsfl9ZsUOfTQNxpRwr1+gcb6PpOFEBqynO+sPuVsN53ZNyrexHnS3/dLcbzbEvuU6wsp1ktz/0dplL2XVx8Kzct5Z9zNtpKu4nlQes3Hg3+9nynynfyv2SZb/h7jeSQ1Ng4lC18p4t63fuvwbyKiw8fCvbndFiipkfxxfAAdRY2f919tuvusWM4j37C1AAtVa2863EvCws/xDN9wlY2fYnbrkp3oMRlM978ItovE+dlX2RV9Z+zXssOv8+G+0OUm9l279ChXMK/wZ7c+r79pfR6iC8lW2fW/1qbJ/9wCv0t7choPz6Q1Ns6xG0tx7b/j+A8OJ/NwQdYQAAAABJRU5ErkJggg==' +r8 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAALi4uMDAwPT09Pz8//1VV/1ZW/1dX/1hY/1lZ/1pa/1tb/1xc/11d/15e/2Bg/2Fh/2Ji/2Nj/2Rk/2Vl/2Zm/2dn/2ho/2lp/2pq/2tr/2xs/21t/25u/3Bw/3Fx/3Jy/3Nz/3R0/3V1/3Z2/3h4/3p6/3t7/3x8/319/35+/39/k5OTlJSUlpaWmZmZm5ubnJycnp6en5+foKCgoqKipKSkpqamq6urrKysr6+vsrKys7OztLS0tbW1tra2urq6u7u7vb29v7+//4CA/4KC/4SE/4WF/4aG/4iI/4qK/4uL/4yM/42N/46O/4+P/5CQ/5GR/5KS/5SU/5WV/5aW/5eX/5iY/5qa/5yc/52d/56e/5+f/6Cg/6Gh/6Ki/6Oj/6Sk/6Wl/6am/6en/6io/6mp/6qq/6ys/62t/66u/6+v/7Cw/7Gx/7Ky/7Oz/7S0/7W1/7a2/7e3/7i4/7m5/7q6/7u7/7y8/729/76+wcHBw8PDxMTEyMjIycnJysrKzMzMzc3Nzs7Oz8/P09PT1NTU1dXV1tbW2dnZ2tra29vb3d3d3t7e39/f/8DA/8HB/8LC/8PD/8TE/8bG/8fH/8jI/8rK/8zM/83N/87O/8/P/9DQ/9HR/9LS/9PT/9TU/9bW/9fX/9jY/9nZ/9ra/9vb/9zc/93d/97e/9/f4ODg4eHh4uLi4+Pj5OTk5ubm5+fn6Ojo6enp7Ozs7e3t7u7u7+/v/+Dg/+Hh/+Li/+Tk/+bm/+fn/+jo/+np/+rq/+vr/+zs/+3t/+7u/+/v8PDw8vLy8/Pz9PT09fX19vb29/f3//Dw//Hx//Ly//Pz//T0//X1//b2//f3+Pj4+fn5+vr6+/v7//j4//n5//r6//v7/vz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXn6cBAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABYNSURBVHhe1Z35YxTnfYfVYxdJyAghQMiYw0KSFTvpmTg90tZtJTCYOBibIB8EsCorHAoGQznSNG2aJo3jxLLAXEYGc1t13bqpU4SMxaUmbW0QshobHav5T6ZzfPadd+Z9Z+Z935ndnXl+2d33fWc1j2Z39j2/b5kexO//3X9qieSzV/4Ep8jF3+r3foZ3SCyf/Q1OlcHP6t9wZMKZ+jOcrxuu1W//Hw5KA/+Ik6Zhrf5Q/1+UTwvfxZk7sFY/RdkUkfsCzj2Px+ov9WmUTBcv4/yB2+oLf4tSqeMjGNi4rf4VZVLINBQsXFYJ/ckV5IuwMKCtfoHstPIleFBWX9TfR2Z6gYpj9SX9J8hKM5AhVtpfICPVfAobWGk60lPOu7aObfWp/imS086XLR/L6l3te0jkcPPsyb5k8dbAJM6Nxf7ZMq2+7Pv5u71j1fxMAqlsfuYtn6rdj/NW0/q/I8nNpXWVeJck0rBvHOfpBlY/5l+q8Y1ZHJ9UFp/Hqbp4z7YyniCB5uJiHJtgZnRO4WxpLKv3uJfqdBWOTDZPcLR+aFpp2rfxkiIlUnwtw+qHmp7DK4cP7sFByedZnDLFb+llhhpeOORacEgaOImTdnjPtHoELxy6cYCbuhVffaw5eff6BaM4awfDSv8fPCeMzMQBFM09w1be5NvfqEZSUnjBOjEa0wpPHdhLtfQsskzGvlmO5GRQy9Sf/ohjlatHccLmCWSB/iXISAa9OC3COxyrkyhM2IEMh1v3IysRLMdZEabLtK/gKWEbCufZgnSaWwuRmQSqmYpumfYPeEZYjcLgQfbnzOB0kiqJH+CkCGXaO3hGWICyNhUfItnDBuQnAeaLVaYx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' +r9 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAALi4uMDAwPz8//1VV/1ZW/1dX/1hY/1lZ/1pa/1tb/1xc/11d/15e/2Bg/2Fh/2Ji/2Rk/2Vl/2Zm/2ho/2lp/2pq/2tr/2xs/21t/25u/29v/3Bw/3Fx/3Jy/3Nz/3R0/3V1/3Z2/3h4/3p6/3x8/319/35+/39/kpKSlJSUlZWVl5eXmJiYmZmZnJycnZ2dnp6eoKCgoqKipKSkpqamqKioqampqqqqrKysra2trq6usrKytLS0tbW1tra2uLi4ubm5urq6u7u7vr6+v7+//4CA/4KC/4OD/4SE/4WF/4aG/4iI/4qK/4yM/42N/46O/4+P/5CQ/5GR/5KS/5SU/5WV/5aW/5eX/5iY/5mZ/5qa/5yc/56e/6Cg/6Ki/6Oj/6Sk/6am/6en/6io/6mp/6qq/6ur/6ys/66u/7Cw/7Gx/7Ky/7Oz/7S0/7a2/7i4/7m5/7q6/7u7/7y8/729/76+/7+/wcHBwsLCw8PDxMTExsbGyMjIysrKy8vLzc3Nzs7Oz8/P0NDQ0dHR0tLS09PT1NTU1dXV1tbW19fX2dnZ2tra29vb3d3d3t7e39/f/8DA/8LC/8TE/8bG/8jI/8nJ/8rK/8vL/8zM/83N/87O/9DQ/9HR/9LS/9TU/9XV/9bW/9jY/9ra/9vb/9zc/93d/97e/9/f4eHh4uLi4+Pj5OTk5+fn6Ojo6urq7Ozs7e3t7u7u/+Dg/+Li/+Tk/+bm/+fn/+jo/+np/+rq/+vr/+zs/+3t/+7u/+/v8fHx8vLy8/Pz9fX19vb2//Dw//Hx//Ly//Pz//T0//X1//b2//f3+Pj4+fn5+vr6+/v7//j4//n5//r6//v7/vz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI8jCgAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABVhSURBVHhe3Z39YxTHfYfV9g4hhGSwZMybsSwJk7Zum7R22/QlTdNaMkaigDHYCCTABgvzHgQ0tZu3NmlaN22RMAgkMCK8JWnqJiBj8WK5bRAKqE4R0mn/m+2+fG52dmdmd2Z272V5frm92dnTPrrb3Xn9ToUZxnPvfDhjlCO5H/8FTpFLiNW/4RPKlplv40wZRFb/jCPLnJl3cb5++Faf4qA08COcMw1r9UXzp8ifFr6PM/dgrb6JvGnij3HueQJWL5r/i4zp4kOcP/Bb/cYfIVfqyMHAxW/1d8iTRr4IBxuf1b8iQzp5ERYWtNUPsTutfA0elNXvpuXBG8KX4EKsfs98B7vSzG/CJm9lPIcdqWYGNrAyzPIsm6vyP66Oa/VL8z+RnHa+4fg4Vj82fh+JHMZ/8MGZ8uLcpQc4Nw7E6gXh72/i8LqFmTJkVsPr/TmcY4D/ylvNmN9Akp+Rrlp8SjmyYPcvcJ5+nnOtvm+YSPCR21uF48uVx0/hVH185loZxrtIoLmxAseWMxvv42xpHKufcL+q6/U4sLxZztH61LYyjN/CW4qUSPG1LKvvGebP8M7j3gIcVP6sZG/ff2lWWGp4Q7EBh6SBgzhnj2m+VT8O8JFdumr16pefxLvyofo6ztrDsjK/i21Cjn3y1u88d8/deXew6zEklglr3BOj+LxlxTykma9q+fvT2OUweWQZdpQFs27jvAj/ZFlh02MlsoO5h5DuMfVWJXaWA2/irAg5jtUnyAyWjyDdx+Wl2F0G1OOcPDhWJ5HZpVVQPr5TRr/CT3BOhArjBWwR3kBeB5FUWWn145QIFcaXsUWgL6vFE0jkcLtsSvTMhVVhMK0wjchr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' +y0 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABUVFRYWFhgYGBkZGR0dHR4eHiIiIiUlJSYmJigoKCsrKywsLC4uLjAwMDExMTIyMjMzMzQ0NDk5OTw8PD09PT8/P0BAQEpKSktLS0xMTE5OTk9PT1BQUFJSUlNTU1ZWVllZWVtbW11dXWBgYGFhYWJiYmRkZGhoaGpqam1tbW5ubnBwcHFxcXJycnNzc3V1dXZ2dnl5eXp6en19fX5+fv+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2JP+2Jv+3KP+4Kv+4LP+5Lv+6MP+6Mv+7NP+8Nv+8OP+9Ov++PP++Pv+/QP/AQv/ARP/BRv/CSP/CSv/DTP/ETv/EUP/FUv/GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/LZP/MZv/MaP/Nav/ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/TfP/UfoCAgIKCgoODg4SEhIWFhYeHh4iIiIuLi4yMjI+Pj5CQkJKSkpOTk5WVlZaWlpiYmJqampycnKCgoKKioqSkpKampqioqKqqqqysrK6urq+vr7CwsLa2trm5ubq6ur+/v//UgP/Vgv/WhP/Whv/XiP/Yiv/YjP/Zjv/akP/akv/blP/clv/cmP/dmv/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/mtP/mtv/nuP/ouv/ovP/pvsDAwMLCwsTExMbGxsjIyMrKyszMzM7Ozs/Pz9DQ0NHR0dLS0tTU1NbW1tjY2NnZ2dvb293d3f/qwP/qwv/rxP/rx//sxv/syP/syv/tzP/uzP/uzv/u0P/v0v/w0v/w1P/x1v/y2P/y2v/z3P/03uHh4eLi4uTk5Ofn5+jo6Orq6uvr6+zs7O7u7v/04P/14v/25P/25v/36P/46v/47P/57vDw8PLy8vPz8/T09Pb29vf39//68P/68v/79P/89vj4+Pr6+v/8+P/9+vz8/P39/f/+/P7+/v///wAAAHrYiUMAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAATyUlEQVR4Xu2df5wUZ33Ht9ra2lh/tNa21ljbmBil0Vp1j+M4OCCQu3CQAwnhVwg/EjgCgUDANqaNqVVr1bRqld+EI/y4C+EgEEitabVaf8AVKFACAY0xNhwcKDX3I9yS3Vnnx2efeWaeZ2ae55nZmZ3Xa99/hNnneXZ33rnd2Wee5/t8n0zRm7e/+8F//s+XXtMqjqs//dY//dW73oHT5OBl9d4/e/i/CniRCqXwnYfei7N1w7e65i9/iKdWON/70Ftwyg54Vm/99C/xpBRw+eHfw2lTsFav/2SKnAwuf/QNOHWC2+qmP/wRGqeIH9yEsy/hsvr65yr8EsHntU/9OgQsnFa/+x00Sx3P/j4UTGir6679GdqkkJ9cBwsDymrIO1N2mXByeQg8dGyrv/3jV1GfUn5paxGrz1/7CmpTy2XyISxZ/ePb/g91KebF0iUDVo8M+R5qUs1/4AJvWX1A+wLKU85nTB1YXXkPStNOweplmFY//rWfopTDYM+5CqMnh1Pj8GOzT2hYfVH7DMrc9O64t2VotuKonbSkox+n6OahklXhTVdQ5OT0kuF4mQpkxLIzOE0nrxg3JrrVD7QvocRB/xI8v1KpWT6IU3XwWdNqiPZbV1FA09WIJ1cw44/hZGlefath9RPtETym2VWBXyeW2n04XZpPGFban3N6FemQ4mu9cEMx813tT/CIYn9KpHStIzhliuuLGY1zrei9Gc9JAU3sJf6zutWN7AdwAZ7hpKFpQlMDjiuIpThpmxd0qzfj2KYL7SnGreg8Z9Z1737gFpRVCifNE6P5g4x2Ew5t5qI5YfqePKoM8k/NQHllsAjnZXND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' +y1 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABUVFRYWFhgYGBkZGR0dHR4eHiUlJSYmJigoKCsrKywsLC4uLjAwMDExMTIyMjMzMzQ0NDk5OTw8PD09PT8/P0pKSktLS0xMTE5OTlBQUFFRUVNTU1RUVFZWVlhYWFtbW1xcXF1dXV5eXmBgYGFhYWJiYmRkZGhoaGlpaWpqam1tbW5ubm9vb3BwcHFxcXNzc3V1dXp6enx8fH19fX9/f/+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wE/+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2JP+2Jv+3Kf+4Kv+4LP+5Lv+6MP+6Mv+7NP+8Nv+8OP+9Ov++PP++Pv+/QP/AQv/ARP/BRv/CSP/DS//DTf/ETv/EUP/FU//GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/LZP/MZv/MaP/Nav/ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/TfP/Uf4CAgIGBgYKCgoSEhIeHh4iIiImJiYuLi4yMjJGRkZKSkpSUlJWVlZiYmJqampycnKCgoKKioqWlpaampqioqKmpqaqqqqysrLCwsLKysrm5ubq6ur29vb6+vr+/v//UgP/Vgv/WhP/Whv/XiP/Yiv/YjP/Zjv/akP/akv/blP/clv/dmf/dmv/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/mtP/mtv/nuP/ouv/ovP/pvsHBwcLCwsTExMbGxsnJycrKysvLy8zMzM7Ozs/Pz9DQ0NHR0dLS0tTU1NXV1dnZ2dra2tvb29zc3N3d3d7e3v/qwP/qwv/rxP/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03uHh4eLi4uTk5OXl5ebm5ujo6Onp6erq6uzs7O3t7e7u7u/v7//04P/14v/25P/25v/36P/46v/47P/57vLy8vT09Pb29v/68P/68v/79P/89vj4+Pr6+vv7+//8+P/9+vz8/P39/f/+/P7+/v///wAAAAvkMikAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAOwklEQVR4Xu3deZwT5R3H8VRbe1hrLw+0WouKWrS2FrMHLHLIscqxIqJsC4qC3LgqWM9aa7WltbbaCgIKVASRywXU3traVi2Iq4Cg1Wq1FhfZ9YAFFskmneObZ45nknlm5vdkZvKazz87mUyenfcLkp0kc6RyhfvS4d1++qc39mYj1/63n/rFjV89DKvpUCHVCced+cf9GCSqPXvLCVhbe86qz5z8Zzwy4r123eewypacVIde8188KAbtuf2LWG1TvOrAU9/CA2LSnlsOwqqz7KrTD38SC8eoN4/D2uezqX7dbQ+WjFc//zgAelbVF+7CUrHrn18GQcus6nz001gmhr3fCQo1k+q0I9/EErFs74lwKBmqmzq9jftj2v6TIDGpbj8q1v9Sah8dAwtT/fjzMX5O5fsg/5IB1c2nxfbVz9zreIHXVV2z3TA/5t2tcaDac2w8//jyna55NNWrHyuymZRpaX4nWu1ox6o59L62TaiqZmZPxTx77cunDe+ejlwVgyc8sAOraO/OvKrjYOet9ObpvTFMBKu+/EWsprUO9Y2Jono6eybmWMrMqcIAUe2yVqyqpcc11anZTzq9SdwyDI+NcH0ewcpaOlRVvZ49GTfNNdXgkdFuIVbX3B2qKvsNh88oYoJyZO3ukkv9LfuVDtw02hIXVDq9FKtsqmsulXV4rcjE4DmVr+YdrLTRY4rqlD/ghtEcPAL1HIL6YUakGsn9V9urqA75CDdY260v6X22YH52GeZEq+VYO6NOqezpmDSagcX1DFREVcOxdkY3pbLfxiSrvQ8W1zKhIqpKb8TqsX6Vys7EJGsFFtYyo6KqmozVY/0n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' +y10 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABkZGR4eHi4uLjAwMDExMTk5OTw8PD09PT8/P0pKSktLS0xMTE1NTU5OTlFRUVJSUlVVVVZWVldXV1hYWFtbW11dXV5eXl9fX2BgYGFhYWNjY2RkZGVlZWhoaGtra2xsbG1tbW5ubm9vb3FxcXJycnV1dXZ2dnh4eHp6enx8fH5+fn9/f/+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2JP+2Jv+3KP+4Kv+4LP+5Lv+6MP+6Mv+7NP+8Nv+8OP+9Ov++PP++Pv+/QP/AQv/ARP/BRv/CSP/CSv/DTP/ETv/EUP/FUv/GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/LZP/MZv/MaP/Nav/ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/Tff/UfoCAgIKCgoODg4SEhIaGhoiIiIqKiouLi4yMjI6Ojo+Pj5GRkZKSkpOTk5SUlJaWlpeXl5qampubm5ycnKCgoKGhoaKioqOjo6SkpKWlpaampqmpqaqqqqurq6ysrK+vr7CwsLKysrS0tLW1tbi4uLq6ury8vL29vb6+vv/UgP/Vgv/WhP/Whv/XiP/Yiv/YjP/Zjv/akP/akv/blP/clv/cmP/dmv/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/mtP/mtv/nuP/ouv/ovP/pvsHBwcPDw8TExMbGxsfHx8jIyMrKys3Nzc7Ozs/Pz9LS0tPT09TU1NbW1tjY2Nra2tvb29zc3N3d3d7e3v/qwP/qwv/rxP/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03uDg4OHh4ePj4+Tk5OXl5efn5+jo6Ovr6+zs7O/v7//04P/14v/25P/25v/36P/46v/47P/57vLy8vT09Pb29vf39//68P/68v/79P/89vj4+Pn5+fr6+vv7+//8+P/9+vz8/P39/f/+/P7+/v///wAAAM9q+HsAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAYc0lEQVR4XtWdeWAc1XnAt3dpKGkbSppSjkDTxAmj2xK2ZRnjU7Z8gPGJMTbCJ24hJJSkaQu5ILQpadPEt3yCjeVDtrGTNqVtCm5DsC2f8tHmaKkl2VYJtkWJRFazmePbN2/m+97MezOzs7O/fzz73ux6ftrZmTfvfe97mZyYX7v5L77x+lsDeur4yX9+66nbbrgGDpNAZPWhG/76f+Ez0spbX7vpfXC0Xmira7/8E3hrunn3q0/+ChyyC8rqg9+BN5UC3/3Ar8Jhc2Cra74F+5cK//KlX4RDZ3it/vDJ92Dn0mHgCx+Go8/jsbr232HP0uJH3/gFELBxW938DuxWarz3iV8HBQve6obPwj6lyFf+ACxMOKvbn4MdSpNvDgIPA8fq01+F6lLl258AE87q81+EytLl67eBC7P64p9AVSnz9HVgA1af+a0UNmLVuRUu8LbVh/W0N2XleOe7lg5YvVtqrSQRrz5h+VhWP7gZCimudHemi+7LPr+WR602oWn1rP4mlHk5uWZGvZY+hkxb2S4we+eVvNXAk1Dkpn9HE3xKGhm7tReO081z19tW/6G/DSUujt0N708r9fvhSF387KBldZv+BBTw9C8vgzenmOarcLQ8z/6OafVj6qreNw3emG4mXIbj5Xj3H00r/ffhJUeJSNFaH78xl3lV/ya8chiYBW9KP01ZOGaHg4/nMsYTF7xy2AZvKQXWwDFzfM+w+iBsO3TVwDtohowYNWrEEHhRdCpOwlE7fMyw+gJsO8yBN2AaZq99+aK9U8+BdXNGQHFRabKPh+Pvb8no34NtRlc57O+h4v7DsAfj6LxKqCwiJ+BgGG89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' +y11 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABkZGR4eHi4uLjAwMDExMTk5OTw8PD09PT8/P0tLS0xMTE1NTU5OTk9PT1BQUFJSUlRUVFZWVldXV1hYWFpaWl1dXV5eXl9fX2BgYGFhYWNjY2RkZGVlZWZmZmhoaGlpaWtra2xsbG1tbW5ubm9vb3FxcXJycnNzc3R0dHV1dXZ2dnl5eXp6ent7e35+fn9/f/+qAP+qAv+rBP+sB/+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2JP+2Jv+3KP+4Kv+4LP+5Lv+6MP+6Mv+7NP+8OP+9Ov++PP++Pv+/QP/AQv/ARP/BRv/CSP/CSv/DTP/ETv/EUP/FUv/GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/LZP/MZv/MaP/Na//ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/TfP/UfoCAgIODg4SEhIeHh4iIiIuLi4yMjJCQkJGRkZOTk5SUlJWVlZmZmZycnJ6enqCgoKGhoaKioqSkpKampqmpqaqqqqurq6ysrK+vr7CwsLKysrOzs7S0tLa2tri4uLq6ury8vL+/v//UgP/Ugv/WhP/Whv/XiP/Yiv/YjP/Zjv/akP/akv/blP/clv/cmP/dmv/dnf/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/ltP/mtP/mtv/nuP/ouv/ovP/pvsDAwMHBwcLCwsTExMXFxcbGxsfHx8rKyszMzM7OztHR0dLS0tTU1NfX19jY2NnZ2dvb29zc3N3d3d/f3//qwP/rw//rxP/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03uDg4OHh4ePj4+Tk5OXl5ebm5ufn5+jo6Ovr6+zs7O7u7v/04P/14v/25P/25v/36P/46v/47P/57vDw8PHx8fLy8vPz8/T09PX19fb29v/68P/68v/79P/89vn5+fr6+v/8+P/9+vz8/P39/f/+/P7+/v///wAAAD9msOwAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAASQElEQVR4XtWdCZgUxRWAJ3c8IsYzhnjFMwfRnnUXkJtFVEAUxGNFFBYUVI7EK0ZDjFcukmhYCTdEblwSRIkxQQ1JTFROLyRqojHcq0YFVlnd7Ukfb3q6u6q733vdPdP1fx92dXfVTP3uTE91ddWrXCGYzx313V/+9e02PXN88Nqf7vjGEftBNSUEWR110O2vw2tklQ9Wnro/1NaP3OqAW/8LRbPNx7869DNQZQ8yqyMnZfBTF8Qrx38Wqu1CtNrvHoWcTJ4+5JNQdQe/1clffw8yK8S9J0Dti/isDngMMqrFO1/6BAjYeK2OVeMiIeEHnwcFC7fVESd9BHkU5LGvgIWJy+qkGyCDmvylA3gYlKxuuglOq8rfTwMTl9Xt34KT6rL6RHBxrO44XLFfKRkrDwIbsLrl4PfhjNLcBhd42+oE/Sk4rjZtX7R0wOrD78Nh1XnzZsvHsnr12JAv1d4dW7PFtqaQ2v7YahOaVnfpq+GYny0zhvXRskfnweNWtEIVfbStKlq1HQOHvLQ9fGkeXiaD1E7fDfX08uRhttVT+qtwxMPmC6B8Vum8QPpJPNSyOlFvD/tu2uZ2hMIZ5tIdUFs3TxxiWr2u/xn2XbSNgYLZptcWqK+bP5pW+pdhz4UiUnKtO9sXcqv122DPxQQolH16N0GVS7x3YyGn62IP2doMX/v8DIc6uzjEsDoS0iX2Bv1G9TzXTwb0G6HWJe4wrL4J6RINkF+gz3bI4dANzlSQHi1QF4fXjs/pkyDtsC+4qoJWBqy0xVCXEnflxK/VIsgtw6+VBavzoC4lDs6JP8GDILcUn1YWrLQXoTIOp+WEi0VrDWSW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' +y12 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAAAICAgYGBg4KAAkJCQ0NDRIMABcPABERERUVFRgYGBoaGh0dHR4eHiUZAC4eACEhISUlJSkpKS0tLTAwMDY2Njk5OTo6Ojw8PD4+PlI3AHZOAEFBQURERElJSUpKSkxMTE5OTlBQUFJSUlRUVFZWVlhYWFpaWlxcXF5eXmBgYGNjY2RkZGdnZ2hoaGtra2xsbG5ubnFxcXJycnV1dXh4eHp6enx8fH5+fo5eAJNiAJxoALx9AL2BC5yQecCAAMSCAMaEANaOANmQAOGWAOSYAOucAPGgAPqmAPyoAP+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2JP+2Jv+3KP+4Kv+4LP+5Lv+6MP+6Mv+7NP+8Nv+8OP+9Ov++PP++Pv+/QP/AQv/ARP/BRv/CSf/DTP/ETv/EUf/GVP/GVv/HWP/IWv/IXv/KYP/KYv/LZP/MZv/MaP/Nav/ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/TfP/UfoCAgIKCgoSEhIaGhoiIiIuLi4yMjI6OjpCQkJOTk5SUlJaWlpmZmZycnKCgoKKioqWlpaampqioqKqqqqysrLCwsLKysrS0tLi4uLq6ur27ury8vL6+vv/UgP/Vgv/Whf/XiP/Yiv/YjP/Zjv/akf/blP/clv/cmP/dmv/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/mtP/mtv/nuP/ouv/ovP/pvsDAwMLCwsXFxcjIyMrKyszMzM7OztDQ0NPT09TU1NbW1tnZ2dra2tzc3N7e3v/qwP/qwv/rxP/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03uHh4eLi4uTk5Obm5ujo6Orq6uzs7O7u7v/04P/14v/25P/25v/36P/46v/47P/57vLy8vT09Pb29v/68P/68v/79P/89vj4+Pr6+v/8+P/9+vz8/P/+/P7+/gAAAHdvKjQAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAWDklEQVR4Xt2deYAVxZ3HCxZ2PbIbDMGV3RDBA1BchEjQva9k152BgUFAUA4PRETkkkPwQCLHGrMSF3Q1GuO6yDWAUUBAcBSTJRIP5D5UJHiCyKAwMwww/dLd79vVR3VX/6pfd7/X+fwB9epVv+7PvNe/rq6ug+WCOa/9Qz9/8/PTWsnR8Mlvnrjy/NY4TB+CrC5t98hmfEapcnrjVefjaL34W7V98CNsWuK80fnbOGQXflaXPNqAjTLAZ7PPxWE7EK1aP5IhJ4PPuv4pDp3jtfpeh09ROENs6oKjt/BYtX0SBbNFw5VnQSCP26rzuyiWOZ45DwomTquO7b5GmQzyzmWwMHBYdb20BC+4dD7tDg8d2+onl2VaStM+vwomDqtHL8q4lP5tdYULt3qswzG8l2HeaQcbWM258GO8k2meQYDPW3XRnkV+xrnS1IFVw/eQm3Ua/sv0Ma0OdJZcqE4eOVRafFHTiEPzYZNZJzSsHteeQp6XI89PubG8rOToNWLampM4RC9mHDSstL9Cjofdk3viY0qQfjO/wGG6+ax93uod7VfIcVEzEduXKj0X+v4SjWsxy3XVOuG1i/X9sXEJM/wDHKyTzy42rD7WfobXTpZhw9KmcicO10lnw0q79AReOsiGlL/Wbzrl2JtaF7xysAoblT6V+3DIDh7KMc0nVhyqxDYZYLgYMq7SrS4RG1/uwBZkrht6w+BeSKfNQhy0zUbd6gKkbVajPI1Ri7fWGls1vvfilN7IS5Oeh82DdnD6cqb9BGmbEShPoPd9ruB6fOkQvJEi87Fzm8eZ9n9IcnajNIExwt+pcWHq9ZH+QuWpO+sktP/d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' +y2 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABUVFRYWFhgYGBkZGR0dHR4eHiUlJSYmJigoKCsrKywsLC4uLjAwMDExMTIyMjMzMzQ0NDk5OTw8PD09PT8/P0pKSktLS0xMTE5OTk9PT1BQUFNTU1RUVFZWVldXV1lZWVpaWltbW11dXV5eXmBgYGFhYWJiYmRkZGZmZmhoaGpqamtra21tbW5ubnBwcHJycnNzc3V1dXZ2dnh4eHp6en19fX5+fv+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+zHv+0Hv+0IP+1Iv+2JP+2Jv+3KP+4Kv+4LP+5Lv+6MP+6Mv+7NP+8Nv+8OP+9Ov++PP++Pv+/QP/AQv/ARP/BRv/CSP/CSv/DTP/ET//EUP/FUv/GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/LZP/MZv/MaP/Nav/ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/TfP/UfoCAgIODg4SEhIeHh4iIiIuLi4yMjJCQkJGRkZKSkpSUlJWVlZmZmZycnJ6enqCgoKKioqWlpaampqmpqaqqqqysrK+vr7CwsLKysrOzs7i4uLq6ury8vL6+vr+/v//UgP/Vgv/VhP/WhP/Whv/XiP/Yiv/YjP/Zjv/akP/akv/blP/clv/cmP/dmv/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/ltP/mtP/mtv/nuP/ou//ovP/pvsDAwMHBwcPDw8TExMfHx83Nzc7OztHR0dLS0tTU1NbW1tjY2NnZ2dvb29zc3N/f3//qwP/qwv/rxP/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03uDg4OHh4ePj4+Tk5OXl5ebm5ufn5+jo6Ovr6+3t7e7u7v/04P/14v/25P/25v/36P/46v/47P/57vDw8PHx8fLy8vT09Pb29v/68P/68v/79P/89vn5+fr6+v/8+P/9+vz8/P39/f/+/P7+/v///wAAAB2rsOgAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAUOUlEQVR4Xt2de2AUx33Hr2mbPtL0ncQ1bmiTOI7dBjduXd8dQpKFRAUIyYBlEMQ4CIwBY4wskGnjJE2cunEa9+EmDRQLxMM2CGSCa2TLrds4zsOxEGAeAjdJQ9MIS7ZqOwglUnzay+3eV7OPmdmbmZ292/Xnn9ubmV32g253Z+fxm0SWz++8+0/v/8/v/diIHBOvfeOf//ryd+E0GfCsLn/fR56OoI+Lc5+7FGfrhW31q1O//CZ2jTY/vPfXccouWFa/8cffwU4xYOLB38ZpO6Ctfv6938YOMWHigbfj1Aleq6vf/UUUjhFvXIOzn8Rj9eXLX0fJePHML0Agj9vqt/4WpWLHD38XChZOq/dPeQZlYshPp8HCxGE17ZKvo0Q8uQceOWyrT/7e88iOK5+EicPqc1OeQ2Z8uRYuxOr+33waWTFm4g9hA6tPT/sscmLNj3CDz1t92Pj9CWTEm29ZOrD6ydT/Q3Lc+RvLx7L67s/9PRIZTAy/fD5aDF3EqTGYsOqEptXfGdM4v79Md9vSymT0qFu1cwCn6OW5SauJdzyLJDfDHXNwlAiSWv4U+09xZd7qW8ZUJLiY6IziX8lJ00s4VRfftaymGb/0VSQ4GVqOfSNM+SOsP9cVptU54yp8dTIwG3tGmxaG1tdMK+Pqz+Org5hIsbWuyCaeMy57A99shiN8m/CwGafs4LPZhMG6V6zGLjEgdRTnbHMuZ3XV/fhicwh7uJlR11AfwR9m3SjO2iZn9c7vYZswXoMdbMpv33cqY+aN9HYsRVpU2GqdtJM/SxhXY9PmAIoT5u2+gCyL/g3lyIgENeM4L8KDCeMybNrchOJg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' +y3 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABkZGR4eHi4uLjAwMDExMTk5OTw8PD09PT8/P0BAQEJCQkREREZGRklJSUtLS0xMTE9PT1FRUVJSUlZWVldXV1hYWFpaWl1dXV5eXmBgYGFhYWNjY2RkZGVlZWZmZmhoaGtra2xsbG5ubm9vb3FxcXJycnV1dXd3d3h4eHp6enx8fH5+fv+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2JP+2Jv+3KP+4Kv+4LP+5Lv+6MP+6Mv+7NP+8Nv+8OP+9Ov++PP++Pv+/QP/AQv/ARP/BRv/CSP/CSv/DTP/ETv/EUP/FUv/GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/LZP/MZv/MaP/Nav/ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/TfP/UfoCAgIKCgoSEhIaGhoiIiIuLi4yMjI+Pj5CQkJKSkpSUlJWVlZeXl5mZmZqampubm5ycnJ6enqCgoKGhoaKioqSkpKWlpaampqmpqaqqqqurq6ysrK2tra+vr7KysrS0tLa2tri4uLq6ury8vL29vb6+vv/UgP/Vgv/WhP/Whv/XiP/Yiv/YjP/Zjv/akP/akv/blP/clv/cmP/dmv/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/mtP/mtv/nuP/ouv/ovP/pvsDAwMHBwcPDw8TExMXFxcbGxsfHx8jIyMrKyszMzM7Ozs/Pz9LS0tPT09TU1NbW1tjY2Nra2tvb29zc3N3d3d7e3v/qwP/qwv/rxP/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03uDg4OHh4ePj4+Tk5OXl5ebm5ujo6Ovr6+3t7e7u7u/v7//04P/14v/25P/25v/36P/46v/47P/57vHx8fLy8vT09Pb29vf39//68P/68v/79P/89vj4+Pr6+vv7+//8+P/9+vz8/P39/f/+/P7+/v///wAAAJQ+NvAAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAU6ElEQVR4Xt2deWAc1X3Ht3dJL9IcjSkFktCkJKwky5J8yadsfFs+hLGNbXziM4SQENI2bUoh0JomLbGx5QtjG98HQiW9krZxSRowNr4tt2mcUIwPqRB04Ep0Nds5vvtmZt+bmXft7ow//+zse29G89Huzrx5x++lssH8yie/+tJ//MyIHb3v/PDpP7ztphtwmgyCrG665a/ewUHiypt/8bEP4mzzYVv9xupr2DXe/OzPH/klnLIPltVHvoedksA//uYv47Q90FY3/DPKJ4WXnvx5nDoh3+r3/6wXhZPD+1/6NM4+R57Vr/8YJZPF9//+5yDg4Le6830USxrv3farULDxWn3s6yiTRL58OywsPFa3fwsFkskTD8LDxLV66NvITiqrH4KJx+pr30Rmcnn0M3AhVo/+KbKSzAO/AxtYPfwJZCSa3g/hAu9YfcJ4DxnJ5s0f2DqwunYYyUnnpT+yfWyrHz2ARAa97ZffiheXO3BqLG6z64SW1eNB37/eo2unD0zHj9oZ60/hFPN543DOqvdJJPnp2n4XjhJHJu7twXn6+dKtjtUPDGY1/cVa7B9XRh7Hmfp490e21SeNx5HgpXMR9o0x5atYH9dDN1tWFwzG03z7OOwZb6Z343w9vPmvlpXxWbz1kBApttbv3pxNHTa+j3cuPROxU/yZSV8TvvWVbAqbPtZhlySwE+fs8v4F0+oOvHE5VY49/AyqqxuEzRhRfQln7dLHtHoa2y6M71/l/ENXrawrB+f1RVJcmG2fs5ev3ZEyqCbakyjuUrG2DXkmrSvZH2WpKL+MEyP8+1OM39U8FCeMzquenKhDRjxYhdMi9F5I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' +y4 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABkZGR4eHi4uLjAwMDExMTk5OTw8PD09PT8/P0BAQEREREZGRktLS0xMTE1NTU9PT1FRUVNTU1RUVFZWVldXV1hYWFlZWVpaWl1dXV5eXl9fX2BgYGFhYWJiYmRkZGZmZmpqamtra2xsbG5ubnBwcHFxcXJycnV1dXh4eHp6en9/f/+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2JP+2Jv+3KP+3Kv+4Kv+4LP+5Lv+6MP+6Mv+7NP+8Nv+8OP+9Ov+9Pf++PP++Pv++QP/AQv/ARP/BRv/CSP/CSv/DTP/ETv/EUP/FUv/GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/LZP/MZv/MaP/Nav/ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/TfP/Tfv/UfoCAgIKCgoSEhIaGhoeHh4iIiIuLi4yMjI6OjpCQkJOTk5SUlJWVlZaWlpiYmJqampycnJ2dnZ6enp+fn6CgoKKioqSkpKampqioqKmpqaqqqqurq62tra+vr7GxsbKysrS0tLW1tbe3t7i4uLq6ury8vL29vb6+vv/UgP/Vgv/WhP/Whv/XiP/Xiv/Yiv/YjP/Zjv/akf/akv/blP/clv/cmP/dmv/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/ltP/mtP/mtv/nuP/ouv/ovP/pvsDAwMHBwcPDw8TExMbGxsnJyczMzM7OztDQ0NLS0tTU1NXV1dbW1tfX19jY2Nra2tvb29zc3N7e3v/qwP/qwv/rxP/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03uHh4ePj4+Tk5Obm5ujo6Orq6u3t7e/v7//04P/14v/25P/25v/36P/46v/47P/57vDw8PLy8vPz8/T09Pb29vf39//68P/68v/79P/89vj4+Pr6+vv7+//8+P/9+vz8/P/+/P7+/v///wAAAGcqjO8AAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAASDklEQVR4Xu2deZzWxBnH397Vth5tvVqLtNjisRcILCBUuxwrVAW5VHRFUXAFuopASyse9a5t1VZbri6KyKnAUhFQa6vV1mJVEN1yqWjLcnoDCstu3r5Jfu/kmMn7PpNM8ib72e8/bzJHNt99d5PJZOaZVNqbL7W97v7V7zdrseOjN5666fvHH4LTFOBldfwxd/wXx4grH/7+u0fgbN2Irb568weoGm/233PYF3DKDkRWRz0Zw786L/75rS/itG3wVofch/JJ4bm7PotTZ7itfjDhUxRODs13noSzz+Ky+spzKJks3jnsMxAwcVod9yGKJY3miV+GgoHd6rgJCbpKuLn7RFjo2KxOvBkFksnTE+CRwbKadBuyk8rfJsHEZnXLFGQml6dOgQuzuvUkZCWZO4+FDawmtzuInERzMi7wplU77R2kJ5v9qw0dWH16L5KTzr+vN3wMqzePRaKIPdsb4sX23Tluq5ONNqFudbu2BWlu1tde2KMofpQPrnnZw2z/c1mr5muQ5KSpbiCOEkd6z92L83Tyu7am1WrtPaQ4qO+D+nGl23KcqYPmNw2rE7VTkWCnaWYpKseYSz/G2dq5p41utUV7G/s2GoejYrzpswvna+Pg33Ur7RvYtZEQKbHWxDbp1PPab7Fn41JUij+VB3DKFm9dl05p2ifYs1iKKklgLM7ZxpaM1ZHYtthZjhouuvcBpyMhDhSvxVlbXJux+gW2LS5DBRclDcjXLkZKLOjL3Y//enJKewbbjF1lKO/iMuRrG4uREg9ewWkxPr07pXE9ZbUo7aJkM/K1EUiJCRfitCy2pL6JLYszUNrFJcjWNpcgJSaU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' +y5 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABkZGR4eHi4uLjAwMDExMTk5OTw8PD09PT8/P0BAQEREREZGRkpKSktLS0xMTE9PT1FRUVJSUlRUVFZWVldXV1hYWFpaWlxcXF1dXV5eXl9fX2BgYGFhYWJiYmRkZGVlZWZmZmlpaWtra2xsbG1tbW5ubm9vb3FxcXJycnNzc3V1dXZ2dnd3d3h4eHp6ent7e35+fn9/f/+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2JP+2Jv+3KP+4K/+4LP+5Lv+6MP+6Mv+7NP+8Nv+8OP+9Ov++PP++Pv+/QP/AQv/ARP/BRv/CSP/CSv/DTP/ETv/EUP/FUv/GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/LZP/MZv/MaP/Nav/ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/TfP/UfoCAgIODg4SEhIeHh4iIiIuLi4yMjI6Ojo+Pj5CQkJOTk5SUlJmZmZqampycnJ6enqCgoKKioqOjo6SkpKWlpaampqenp6qqqq2tra6urrKysrS0tLa2tri4uLq6ury8vL6+vv/UgP/Vgv/WhP/Whv/XiP/Yiv/YjP/Zjv/akP/akv/blP/clv/cmP/dmv/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/mtP/mtv/nuP/ouv/ovP/pvsDAwMHBwcPDw8TExMbGxsjIyMnJycrKyszMzM3Nzc/Pz9DQ0NLS0tTU1NfX19jY2Nra2tzc3N7e3t/f3//qwP/qwv/rxP/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03uHh4eLi4uTk5OXl5ebm5ufn5+jo6Onp6evr6+zs7O/v7//04P/14v/25P/25v/36P/46v/47P/57vDw8PLy8vPz8/T09PX19fb29v/68P/68v/79P/89vj4+Pr6+vv7+//8+P/9+vz8/P39/f/+/P7+/v///wAAAIAkMWMAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAUiElEQVR4Xu2deYAW5X3H3941bdWkidbGkFpjUptWbWfZw11YUETlEEGR+wjIIcppo6a1qWnSNDFqeiD3ERCX+xCSpo29kpAUkFsEj6aNgZVlm7TCrpaV3Xk7x/f9zfE8z8wzz8y8M5Py+eed+T3PzDyfffed45nnKJXF/NJVf/zV7/xXj5473n3jH754w9WXoJgcRFZXX/q517GPvPK/f/f7l6O0fvhWv/onP8Sm+abnm1f9AorsgWf1oa9cwFYF4N+v/0UU2wVrdclfFMjJ5PXf/FkUnfBb/c51P0bmAvGNT6L0FXxWv/K3yFgs/ue3fwYCNl6rq/4T2QrHl38ZChZuq6s++i7yFJB/+gQsTFxWn7gphxdceb7/CDwMHKvH/gDJReW1x2Disvr8xwv9TZl87ya4kNUXLi/YVYrHt66EDawe/1gBL1MsX8AJ3ra6Tv9XxAvORywdWL37GUSLzo//zPKxrF678j1EOXSePpUvWs90o2gc/sq6JzStvqS/iJifUyun3K7lj5vvnbNNZPaBilXPlYh46dk7oQa7ySG3LDmDcnrZfY1ttVvfjYiH1lHYPq80rOFeYT9qWX1c/yDW3fS0NGLjHDOqFaV1s7uXafUD/e+x7qJnPjbMN/1eQXndXGZa6b/OfpEFkeJrPd2rXPq2/ijWXCzDRvmnXxuK7PDuZ8sl46YQaw6He2ObAjCe/U8zviv9/Vh2OD/Iyt88OIxcnFBaUGqHpwyrj2HZYYWdfSlWxXzKzpgtTR0oDfGjG0r6l7FMdA+wsxfESluD0jg8XWIvwduQuyhWg5hf1tWlDzI3tuOQuyhW2n4Uh3isxJws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' +y6 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABkZGR4eHi4uLjAwMDExMTk5OTw8PD09PT8/P0BAQEREREZGRkpKSktLS0xMTE1NTU5OTk9PT1FRUVJSUlNTU1RUVFVVVVZWVldXV1hYWFlZWVpaWlxcXF1dXV9fX2BgYGFhYWJiYmRkZGVlZWZmZmlpaWtra2xsbG5ubm9vb3FxcXJycnV1dXZ2dnh4eHp6ent7e3x8fH5+fn9/f/+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2JP+2Jv+3KP+4Kv+4LP+5Lv+6MP+6Mv+7NP+8Nv+8OP+9Ov++PP++Pv+/QP/AQv/ARP/BRv/CSP/CSv/DTP/ETv/EUP/FUv/GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/LZP/MZv/MaP/Nav/ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/TfP/UfoODg4SEhIaGhoeHh4iIiIqKiouLi4yMjI2NjY6OjpCQkJGRkZKSkpWVlZmZmZqampycnJ6enqCgoKKioqOjo6Wlpaampqqqqqurq7CwsLGxsbKysrW1tba2trq6ury8vP/UgP/Vgv/WhP/Whv/XiP/Yiv/YjP/Zjv/akP/akv/blP/clv/cmP/dmv/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/mtP/mtv/nuP/ouv/ovP/pvsDAwMPDw8TExMbGxsnJyc3Nzc/Pz9HR0dLS0tPT09TU1NbW1tfX19jY2NnZ2dra2tvb293d3d7e3v/pwP/qwP/qwv/rxP/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03uDg4OHh4eLi4ubm5ufn5+np6evr6+3t7e/v7//04P/14v/25P/25v/36P/46v/47P/57vDw8PHx8fLy8vPz8/T09Pb29v/68P/68v/79P/89vj4+Pn5+fr6+vv7+//8+P/9+vz8/P39/f/+/P7+/v///wAAAKxo9DAAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAV8UlEQVR4Xt2deWAU133Ht3fdNnZrpy2mbpripnFSu2mOkYQEAmQQt5A5TEAgwGAhwOauY9duHbdNmqRp67TmPmQjJAtzI8dpk7ZJmjStzI0wUDtOYw4BbhxLyHF2YTXbOb775nhv3rw3M7s7488/zL55u5oPu/v2Hb/3m1TOm1/67Uf//t9+eEONHdd/8PUvf+qWm3CZDLysPnjzk98dwIvElBvfeORWXK0bttWvffJVPDXm/PtHfgGX7IBldftfv4MnJYA3P/OLuGwbtNVNTyTISefNP/5ZXDrBbfVH7/8+KieIb92Dq8/jsvrVL8a8iWBz/TM/AwETp9UH/gPVEsdLvwwFA7vVB+78P9RJIK9+FBY6NquP3v4T1EgkbzwKDw3L6vHB13E+ofzocZjYrP7mfe/ibGJ54+NwIVZfuPUtnEswr90BG1h99q7/wZlE8zU08KbVXerTKE84jxk6sHr3TpQmnRt/ZfgYVq/d8SZKGaQvX4gXF69kcGkMvmP0CXWrv1W/iDI3V1ubJ5crsWPo1Id29eMS3RjtoG41cAd7vHuquRIvE0OqV53HZTr50YdMq/9Uv4ISB71NeH5cKV/L/CQ+YVh9RB3E6qd3jsaTY0zdKVysnbeG6Favq5/DYzvteGK8qXwZl2tHG2ylcupv/RgPbSRDiq313SG51DfVD+KRjX14UvypPIlLtvGXuZTKaCsuj8BzEsCkNC7a4nHN6ra38YAw0IhnOBk5fmLtSBzHiDW4aotva1Z34djiIOrbGLtm70Xj3OX2BcNRFhPKzhoXZmPgYyn1kzi2mIX6hIaDWZzSyXRNR3k8WI7rshiUUv8Bh4QzqJ2ntgsnCNnWOL1fw6/hsgiPpQZ9D4eEVagNlvSh3E7PApyNA224KMLTqdt+ikOC8/O1GaVuVuJ8DFiCSyJ8O0U1FllHl9ZLSlUXoUbpqcMVEd5KDcYRoRt1DVaikEFmNuqUnHL3qGQgNQRHBHu7PpH+ibO4Ngm1Ss4FXBEh9SQOCHtRVaP8BMoMeo52HnX8r7yIaiXnDC6IkPoYDgh7UFXD/jXsmlemlVTO6cRjjUxc3qxXcEEEurWwWXWjSBvqT0WRojT1mkWZtlqUlBwpq/tRoklNQZHOdP3LFiMnSSvy65a2SynKA/FykrQilZ9HQZ6VsXKSsxpGurT3oSSuyFjNQIF6HAWxRcZqAQrUVhTEFhmrB1GgbjYejrx/zvy502I57ylj1YQCdZNSMXMzZj2y3Ttn4nx8CGS1bcVlHJmcXlqBKjEhkBVNt/MHrNREZKVm1qNSLIjKKl4NY3RWcdKK0Epdi3qlJ0qrzGRULDlhrA63tbQfx7HBqbg08IGt+p6baBROabMN8hcbRaUnqNXZe1GoKOMvoUxVT6Ko1AS0skk5tKahqMQEs+q1S2laZJX5WZSUmGBW21GSZxfK1WMoKDGBrLLjUJJnGk6o6Xi0goGs6NlMMqUWj5+sQFbPocBiD86o96OgtMhYkbHwFhRYkDm1eKwgyFiReYv31Hv1aRSoXSiwSPD3agQKVHU8SvJMR7majkeYnYyVQkLVWlCQ5wWUJ/H3yrr4Pmf82UTSt3Drlggpq7koUdVzdq0JPShVVWv9p6RIWZVZ0ZLnxqDMIXUCRaVGykpZhSKN/lazuZvaYVsqjku0p5xV1TmUGRzr2LHLEbd2slAtYNmouobmlWvWbdi0dXvLlg1rmibpq7feyFkpM+zxS27SUS8Lj5g0q2nNs3uPXaTjaa8d2bbQ/ftiIWmlbEMhi9WoEwVjF2zpYkUWOTjz8DBUdyFrVUZadwq6HxWM0Y0bD13Fa/pxDbMnLmStvLWikKpuWLffalHF6GJ0qKWtlLItrO9Weg1OB6d2eRdnZwSHjmq8AkHeShv5UqEn6smwvdop61mh6IJcasCr5AlipVQ+5PQ61RyqSS+f2UIFHknS5mw2AllpzNrZbX4QMyd3hIpPrZrfIdo08LjgCCsIaqVROXX23Nn1Q/EoGHU7vbbiyNJr74KGsApN+QNH8CeiwK5VOqua9daUbyTYtEplNW1XsFach6VVEquhixmbOSKgL98zLIHV8I1X8MqRcwxd+aJbVawomJMGejjFtlrE3nwYFRgMFddqVmG+TzbMgWsxrepsgccFw4hmKZ7VmA7eODoy0qO0v1UsqxHbePH9UbJO+2tFsloYRQ9WjEvaN6soViPJkkkxWFAcq3nOaMJCc7gYVtVkKbxYTC681RzZ2ZXwtBTaang7XqSYnCiw1Sxz922RyVQU0qqyFa9QbOoLaDW64J0+L5YVzmpa8ZuJPG0Fs2oqVg+JQXeBrMp4aycFJ1sYq2EH8dwSQe/WjMBqLPV/VWQKYTWzeB10D6hcEOGtHvad6es/sn1R/cTampoxE2Y/3HIw7NIBTfRWz+JpHlzdsZjKvjVueWe0c56RW/H7E6cWe+xCG7bQERkfkqiteFKZF7hrQjP2R5aENuLWgifVWoNKnkw4hKphidaKI3WRSj7DYmE0w+ZIrThS7YKJZaqp7ChBiLJv4S3VMwdVBFgUvgMZZY/JW+qEVOqtaaGXFy5HZ8WRouIh+NSexhODcjIyq+iktC9XSK0DUVltRWUaeSltGB1uvqM1IitrY4ybIFKKMjFUB3l9NFbTPNutK/oSRQCmhekYLonEarT3FEXgRGF0vjxx5kRhxUqvCHajijzlx/ASAZgShZX3ikeYHJHjg8cC1URgtR71GLBzRIKyKn4MFJ0GUJBsWXgrstOHZheq0ExdtVtfzM9cap/vETqrfQapUZIgl8LPs9dRKQgtJqCOi8pme4RjpnM+yt0sRg1Zjoe2GsX5vexEHRf0It1+55ZWk+HrkZNLmn1hrcqPohKLuajkoLoDZ+30LcVZQnAnPa45pNUG1GFxnrU/oIYa0JnsclQO46Sqy0Ja1fN6AK50ngZeUqq6DTU0wjnpObBCWVXw+tb9jN+qYdSfs8jn9QzrpGaGhrPaghpM9qOSHc4UgDrwgF4jtJOR4iCM1VRuCA8jM8lsnGJzZXgUTkamlxBWlZ7fEQN6o4NtUxqT56JwUtXmUFbbcd4DOm92I84UmLowVtytWKp6AdVsvIhThUXf3BvYyrltjoYeg9TiTIHRN/cGttqBs17Qv1YLcabA6IlDglrNwklP6C5rkZaK9R2jAa0qfD5/qurePKQoh3GmwOib5wJa+Y/o6KSC0S8psrimdyiDWQ3znzSms/04ByD9r5w4eqz7bOShJof1PxXMahNOcaDTrJL/iVNbF00ja1kjZ6/dF6WaEacfyOpegYkSD6v+XQ8yFudq5h2Map3R2JMayGonzvBgWp1b4TmTO25bJN2ls8aLBbGaKBKYzrA62sDdZ161NOxaiMZW46WCWO3HCS60lUCinGbf7dx+mOvpAaxIimIutJUIY0L2FS+bn4YAVmJTxcGsFGUZZybOn53mi8hbzUexD0GtlLFh+iBYf5a2KuePFQmBrZSKfXgJea5hjlvaynv9zUlwqxBa+RtPSFuJhgiHsAqu9SBeQNaK5NTzI4xVUK1M/jde1kp400coK6VC6DfRDclUJmlVI7xcG85KqQ6y8XsJnixrxVmBcxHSSmnA60hwlcQeylmVi/8PhrUS6kI7sabq5aweQJEAoa2GyY6ds2PxTFkricwNflbldfMWLmycwOnFk3SFghzA8zSkrKi7ZXHgWo3dfAxxJ31dazzjTCT3btnGBFJWMh91jtWnDzgGvpmOOpxwMRkVxDDHiyYyVtUyERCeVtXPo4ZFdhM7Ta5UP3c5nqQjY2XLSOePl9VMZjPazUyBxQl6oLhmD4GVsZIagHtYNXjEcV1hJXSS+CFRd+A5BhJW4/BYDLaVl5SH1jqcFMDxZktYcW7/x4BpxbvZXg9j+mmUcAfNmaxWwkouzRDLqpy7a4IVHyS8zWIenmAibjVSLpEDy2otznnAiPx5Dqf86Hb+motbSUYVMaz8fhnO0h0N0T/qipcXt5Ic8TCsVuCUJ/SM4SSc8eFlVM8jbFUpGYRIW5X5rnnZenKAuvcnG/cfE7aah0ei0Fb34Yw3A/RmEqEmilqDFraSTRNAWy3DGQ50HnSf8AeDjDUEAaJWZbIB5rSVwG4deolcJFSavjGGqJV1W01BaCuBFJUvoKqFbwujDWboeBVRK5FPggPaSmCXxCFUtViKMxz0pD4uRK2kI3vp7N8C2+DoJP3+P1g9jP2fglZWGn1R6C9+oPfKv4mhgls1BK34MXAs6F9UgbnsDlS18P1enWGlbxW08unBMaAD9Hkhj2AFqlr4toHMTaCCVvLz3svM17dB3c+dht5P7LNT3DlYJAhayc8Pt5mvb8N/hipL70PwWdg8V4V6TsSsanAogeN+8ya+MwT6/5+TCs4wUyM7A/VciFnNwaEEWfp/0fe3h243fd5f9x2r8ohZ8YLxvaC/I1U+cQenUc8G/7t4xuuGuWJWQRKm2OfngE+kGqM547abWfqXHohZBdmXTP/2KGUv4xwTVnPG/Y2jb+2UR8hqDI6kuMyYj63lfAZZzdlo3lzJae/7oglZyY4YTRbhT9iZ7hkjcpEaJGnwIvYynJv/ClltxpEczDsReWkxpYbyPvkbUImFkFXA7Er1+BsO6plRKIetG+TYIDdHY3Cc1f/LI2RF7tklRzv+hpPKbVSAY3oFe3HuBM4zuMTaXkcQsgq4fTxND1INprQ7egy921ifPg3O9E2aHpTaEbEaigNpPD/6I1fuxxjy/O4l7K6cBifzKqslsiFiNRYH0mR4N+4ZPWPWrOke76YBZ7OM9y+ViYgVuWucNGFusjTCe0ZgP2eN3EDESmbJz0WIO6/vxkvQnPbcOJ1HxCrw1nH+TyUf79COK7Wo4o2IFXf7og/dAW/3Osqz3c0I3OhSxIq1b1mYdr/vAJNK734wa07JjYhVFw6C0RZAq9L7TwrdkErESjDS1gt5LY7UbqFWVcQqbOi8rFZoKRGr4CHLeeS0wkuJWEWQ/q7TeYdRLnXeayeiUiJWUWyI7VuMv+dH+TrvEAthKRGr/8a/4TjgmxNRZyJn8CEuJWIVrmEnXPXpZ2uUr+ZMakpIiVhxJ4ZkeGUZtwM3ai1vLUhGSsQqwh2xfS0eCXL0u8RyY5akpIpspdG5aDzVzpdPXsr5PunISYlYRXnzN4O+FzfPz/e7yyYs2n7UN1RkE2qLUgorg3TvpXPne3pFQuX6F+JihSn6J1CeS8wZOC4CVhG17EE5LvRD50TAKqpkG50HfGHkrNoV5DaXAlb75MIdPRFIZTkVVQnZYLfCFbDaE8HmZJ0AVn3MpGL+iFhFdFcaeavzQW8ELmL1EA5CIm11KHCmSBEr6tMeDEmrPrLzTR4Rq6HCUeVc5Ky6/Gf9vBGx4q24SFA/1hcyS9z/MK4vGEJWAqGH0XJkHC4vIEJWw0Pt+JcmvTLAFKIDISuRcLHoOO45BhNGzEowWD4K0mvDvlEaYlZKZKN8Pw4wt5fJImglmNQiLMcF1jtEELQqi6Zx53M2cIJwN4JWyiR+oF4EXH5Ibm6Ch6iVshqPCsS1Db7LohIIW5WFyJfuS2ZHgAEvB2GrMPnSfcjuDf8L5UTcqlD9Js/QmBBIWMnvFRHg1BKvKNMwyFhFrpXZ7RHjHBYpq2i1ejZw48bCIGcVodaxhQEjMUD5sBGeYV2yVpw718jQvdEj+YMYo5pbT+rj82uHty5gfi1lrZSGIMl37GQPrwjX6E3tsPdzrm5lTAVIWynDw4TK9O9r4gXPCVBzAC9FyG6lpnflrRSlMWB20CvtjaGbceaN9V9xR3YGsVJG7JTu6/bsXzcjguGgx9aOdOAd6w5GrBbPK3T10MZGiXgLHp77VVxaAa203m6jwFpJX9eWBRH2hzgZNtKOzTaBrTQmLGs7zVwvyfac2L9jXXPDeFSMCO4Yz7EhI4yVTtX05c8ffPnYyeNHD3d1Hty3c8PSufX3Rjf8s1Pu2ArTf+H0Jcecsn3zTFirImJfxDjZrLemzggNWzBsgqysMMVeslOrfLn1FbBtdUiOlbVludf+89RMtGy3ZUmOFYkE73f+5lq7Ja0Vh+RYkf5nKwrykAVeK+NCYqzuxdWoqntZlbxZ51CQIKu5uBoq841SRVKgk3W/xFiRd2QzCixISBJ5FxNjRbZ1rEaBBcmpREKDEmNFfoPpDTWkQ0r2DyfGiuSvdjeBtkYweVb1uBpbVlswBSeSaGVlT2hGSR4rdCd5VlbSvVPOMfUoa/4/gVZWkpcOu1a1bXySQKtR1pjRpmWXSqKVPYn64UbTq2qZI09UEq0m2Ye+F9Y3zW9ucd0uJolW/hlVE2nFT1aqkUgrpdZnEjKZVn5aCbVSarlJKZJqpVRs4sShJ9ZKUe476PTKtJItHwm2UpRx28nMTH/nilplLx4k20qjZs7aLds3rZllrMcRKzKlllArB2R7DkmG/l6wIrctJomC3gNW5A4dV1GQRKtKdyIQsqO+EwXJs6pcefmKMwrAus/iRpQkzUpz0i7ouH0+ZpwV/2FFpiTJynTSeNGKkbRJHUGRBm01GAeEuFjNtFIZ9S41V4HHt9hybxj30zehrR7DASEuViPt2UPShzau2+aIIjhhW42mrW7DAYHOcF8iuLf+SNvD+6kb76d+FwcEZh7AkkDf4cfCsahA5YRJvQ8HhP7CBBoEoNw7kSFuFWpC3aXmndRgKr0f614zpaHSK/zcIUXn3fqv1O99H4cE98R2Cakm/XM7WVf2Aeoe9c+k1GdwSKDWLEvJXDq1xxkyrjKhb8X0VEp9HIeEgaDbdgtCVYtz8+j5Ve6gRzqH3pCU+n4cWtALYSVl2Py2/A/yxT1z6ahDOsnDoyl1yA0cE9KxerMM6uc3LW1qYO4uaaSau9dzKfVX/hkPLMLkbCw2jByRn9es1HvwwIbVyY89jBylt+hWH76ORxbZENvHiwvVqqvq/96qW6n/aD6ykxQthpT6FznD6m7zkYPs+gR8t6pY9wK6/inN6hva5/BfUeDgRCSbXgvJTKqvrvPlnGaV0w7onyyd9LNR72mLlKm7mFPw1x81rF5VWY27wUDngxHHPUdEeZ1n9q3Pa1Kalf5mDaabwTy9XbufjxcdezjZt974A1h9U3vw52ZZ8rlTl9KtclqXY7Cu9h7gK4aUYfU57eHNPzaLk81rt1tWue9pBbdTncTk8fYThhOscm9rRZ8wzySYG4MMGQ3TSv9qqZ81zyWWgT80XTRg9ad6cbK1bnzYVNGBVe4p/cQnEvzdeucOmOjkrXLGG/U7iW0Jf/AIPAyIVe5P9JH+73/LrJQ0vvrrsDCxrHK5t/TzT3p3nmLL2/f8HBSA3SqnjUq0ccm/GDWTw8DTv4nrJzisco/8RK82KFHdp5fu/nlcvYXTKpf7J6PmbzxDTafFk3f/7kM348rtuK1yua8Z1W/5+Ndj38z/9Kt3PXYTrtoJbZXLfUnvQGkMfuqlH5pHsWPg9Wf+7Nbv3I0LdpHL/T82BHVTzMs3wQAAAABJRU5ErkJggg==' +y7 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABkZGR4eHi4uLjAwMDExMTk5OTw8PD09PT8/P0BAQEREREZGRkpKSktLS0xMTE1NTU5OTk9PT1FRUVJSUlNTU1RUVFVVVVZWVldXV1hYWFlZWVpaWltbW1xcXF1dXV9fX2BgYGFhYWJiYmRkZGVlZWZmZmlpaWtra2xsbG5ubm9vb3FxcXJycnV1dXh4eHp6enx8fH5+fn9/f/+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2Jf+2Jv+3KP+4Kv+4LP+5Lv+6MP+6Mv+7NP+8Nv+8OP+9Ov++Pf++Pv+/QP/AQv/ARP/BR//CSP/CSv/DTP/ETv/EUP/FUv/GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/LZP/MZv/MaP/Nav/ObP/Obv/PcP/Qcv/Rdf/Rdv/SeP/Sev/TfP/UfoODg4SEhIaGhoeHh4iIiIqKiouLi4yMjI2NjY6OjpCQkJGRkZKSkpSUlJqampycnJ6enqCgoKKioqOjo6Wlpaampqqqqqurq7CwsLGxsbOzs7S0tLa2trq6ury8vP/UgP/Vgv/WhP/Whv/XiP/Yiv/YjP/Zjv/akP/akv/blP/clv/cmP/dmv/enf/env/foP/go//gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/mtP/mtv/nuP/ouv/ovP/pvsDAwMPDw8TExMfHx8nJyc3Nzc/Pz9HR0dLS0tPT09TU1NbW1tfX19jY2NnZ2dra2tvb29zc3N/f3//pwP/qwP/qwv/rxP/rxv/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03+Hh4eLi4uPj4+Xl5ebm5ufn5+jo6Onp6evr6+3t7e/v7//04P/14v/25P/25v/36P/46v/47P/57vDw8PLy8vPz8/T09Pb29v/68P/68v/79P/89vj4+Pn5+fr6+vv7+//8+P/9+vz8/P39/f/+/P7+/v///wAAACsZAT0AAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAQLUlEQVR4Xt2de4BUVR3Hp3dWvoAKVs0MKtFE090FBEFeCriISBAqkgjyCAmENDVTy8qyBwXiIg9BFHkoIqilFZamLQQIqKBZZro8NRUWH7uwe6f7+M6ZO3Pu3DmP332cPv/sufeec+d8dma+c+fOuedmsqX5xJFn3PbYqwet1HHotT/+8nufPwzdDKCU1QlHXP34IewkpbQ8dWMr9LaYYKvPnPQnNE05L53+MXS5gCCrdte8iUYG8O6PPo5u++CtDuv0OhoYwrs3fBhdZxRbfa3NE6hsEP9qg97nKLL69DUpjLzytNz6IQh4FFod/wiqGcdfPgkFF7/V8R1eQh0DefNkWDj4rE5uZ1hMFPJeO3jY5K2ur/gvthvKwQqY+Kx+crjRz5TD+4fDhVn9tNU/sM1g3joWNrC6qeOj2GI0zyDgPauO1nVYbzi/cnVg9X6HlB+fC9PB9XGtXj7uSawMoGnvzh3pYk8juhbAm+4xoWP1c+s0rCvmwNJJQ7pUpo7qmvF3v4EuFnNrzqrl2OBPqvopZ2E3KaTr+K3oZiGHvuJZ/dX6PtYU0DS9GjtIK+P2oasFzHCtTrLavoUVfrbWoG2K6bManfXT0t6xesXqhGU/dV3RMt3ci+76ucWxsj73FBZ9GCIVqPV2+2xmrXUClnxsMUWqsvIBdNnHCdmMFZAVjeehiQH03INO55lhW7X+MxbyXOXW71pTnh5uzUQZ1YJeM96xrTpya7dXudWHYDGM77g1k2UV+pLn1IzVFsU8k73aplhdhL7kOT1jXYsio6G7V9sUq8pt6AzjV5m2M1Bk3IPKxlhNRWcYT2f4sBiPysZYDUVn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' +y8 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABkZGR4eHi4uLjAwMDExMTk5OTw8PD09PT8/P0BAQEREREZGRkpKSktLS0xMTE1NTU5OTk9PT1FRUVJSUlRUVFZWVldXV1hYWFlZWVpaWlxcXF1dXV5eXl9fX2BgYGFhYWJiYmRkZGVlZWlpaWtra2xsbG1tbW5ubm9vb3FxcXJycnNzc3V1dXZ2dnd3d3h4eHp6en5+fn9/f/+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2JP+2Jv+3KP+4Kv+4LP+5Lv+6MP+7M/+7NP+8Nv+8OP+9Ov++PP++Pv+/QP/AQv/ARP/BRv/CSP/CSv/DTP/ETv/EUP/FUv/GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/LZP/MZv/MaP/Nav/ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/TfP/UfoGBgYKCgoSEhIiIiIuLi4yMjI6Ojo+Pj5CQkJOTk5WVlZqampycnJ2dnaCgoKKioqOjo6SkpKWlpaampqenp6urq62tra+vr7KysrS0tLa2trm5ubq6ur29vf/UgP/Vgv/WhP/Whv/XiP/Yiv/YjP/Zjv/akP/akv/blP/clv/cmP/dmv/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/mtP/mtv/nuP/ouv/ovP/pvsDAwMHBwcPDw8TExMbGxsjIyMnJycrKyszMzM3Nzc/Pz9DQ0NLS0tTU1NfX19jY2Nra2tzc3N3d3d7e3t/f3//qwP/qwv/rxP/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03uHh4eLi4uPj4+Tk5OXl5ebm5ufn5+jo6Onp6evr6+zs7O7u7v/04P/14v/25P/25v/36P/46v/47P/57vDw8PLy8vPz8/T09PX19fb29v/68P/68v/79P/89vj4+Pr6+vv7+//8+P/9+vz8/P39/f/+/P7+/v///wAAABfKiGAAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAWaklEQVR4XtWdeWAdx13HH2dJoXFJg+OG0DSmTgrhaGB1WbJs+YyP+IitxLcdK/J9xDYQAoGUltJCkxZ8yld83zdQIFxt0oJvy7YslxoKTX1ICikgWwQpedrHHt83O7szuzszu++93c8/fm9m9mk/fm935/xNJufPh/p85gt//a/v6Ymj9z+/8ZXfeegenCYHP6uH7/3Vv/w/fEhSuf7Ze3G2XvhWP/XQ13pxaLL53u/+GE7ZBc/qgcf/DQelgA/+5Mdx2hSs1T0/dx0HpIQP/vCHceoEr9Uv3v8XKJwi3n0MZ5/HY/WTn/pvlEwXf/ZDELBxWz30JZRKHf/xE1CwoK0e6v93KJNC3usPCxPK6hce+CeUSCW9T8DDwLH67X7/gvy08mswoaw+95FvIjO19H4aLsTq8/e9gbwU8/59sIHVy49+Hjmp5l3c4G2rx/RPIj3l/KOlA6v3+r+L5LTzkuVjWX3nwa8ikUO249bNZNHWhVPj8L5VJzStvqjfjzQv2SMr6qu15PFkw5ZbOEUvb+Steh98C0luOjYMw6ckkLLZp/lNwI/bVm/p/ZHgonf7QHxAUpnK/b7etKw+rfflfVW3puLYBFOzh/d19TWtvqv3wVuaq3U4Mtms5mj9lWml/8yreEuREimuVu8juczX9YfZvrG2tEhpWhNOmeLFXEbn3Ct6Z+GQFFB+CSft8E3D6mNfxhuHPTjCw/Axo2vwMkGM68ZZOxhWj34frwl3B+EAisGrTt8x867tm46UxLDZOmmaARm9L146bEdxh9pd1H9I6zykJoSRWZwY4UsZ/WG8JPSOQXHCzDZkgUO1yEgGR3BahDcz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' +y9 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABkZGR4eHi4uLjAwMDExMTk5OTw8PD09PT8/P0pKSktLS0xMTE1NTU5OTlBQUFNTU1RUVFZWVlhYWFlZWVtbW11dXV5eXmBgYGFhYWJiYmRkZGZmZmpqamtra2xsbG1tbW5ubnBwcHFxcXJycnV1dXh4eHp6en5+fv+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2JP+2Jv+3KP+3Kv+4Kv+4LP+5Lv+6MP+6Mv+7NP+8Nv+8OP+9Ov++PP++Pv+/QP/AQv/ARP/BRv/CSP/CSv/CTP/DTv/ETv/EUP/FUv/GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/KZP/MZv/MaP/Nav/NbP/ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/TfP/UfoCAgIKCgoSEhIaGhoeHh4iIiImJiYqKioyMjI6Ojo+Pj5CQkJOTk5WVlZaWlpiYmJqampycnJ2dnZ+fn6CgoKKioqOjo6SkpKampqioqKmpqaurq62trbGxsbKysrS0tLW1tba2tri4uLq6ury8vL29vb6+vv/UgP/Vgv/WhP/Whv/XiP/Yiv/YjP/Zjv/ZkP/akP/akv/blP/clv/cmP/dmv/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/ltP/mtP/mtv/nuP/nuv/ouv/ovP/pvsHBwcPDw8TExMbGxsnJycrKyszMzM7OztDQ0NLS0tTU1NXV1dbW1tfX19nZ2dra2tvb29zc3N7e3v/qwP/qwv/rxP/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03uHh4ePj4+Tk5Ofn5+jo6Orq6uvr6+zs7O3t7e/v7//04P/14v/25P/25v/36P/46v/47P/57vDw8PLy8vPz8/T09PX19fb29vf39//68P/68v/79P/89vj4+Pr6+vv7+//8+P/9+vz8/P/+/P7+/v///wAAAJqY7cUAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAV7ElEQVR4Xt2deWAVx33HX++6ce06dd3Ubp24dWM/ISEkLiFQOQRGnKKY+zCUSxxNGidtnaZuYsd2mto52iIQUC6Jw8hABQXiuKldp3XtIsRtjtRxmhQkJOqkNgg7T0j7usf3zR4zszszu+9Yf/5A+2Znn/aD9pjzN4k0n1/63S+++L33tIKj78ev/+1f/PZdt+A0GfCsPvY733gXX1Ko/OiZOz+Cs/XCtrr1uZ/i0MLmJ1/681/AKbtgWf3mv+OgGND3ra/+Ik7bAW11y6s4IC5888s/i1MneK1+7yt9yBwfPvjMJ3D2GTxWt/4AOePFq3/3MxCwcFs9Gr8/lMX/3fXLUDBxWt31LPLEkL7P3AMLA4fVfS8hRzz50gPw0LGtPvcv2B1XnnoQJg6rJ17EzvjyhfvgQqye/Ap2xZnfvw02sHrsk9gRa26+gwe8ZfUJLR7lviB+8K+mDqw++E8kx52v/anpY1r912NIZNB3teNyYdFxHafG4jfMMqFh9TTv+utrXVM7KFl4DJu14U2copfvfydj1fcNJLnpbhyFbylEJu/rxXm6+dSdltXrGrP01zIYxxcq1Wdwpi7eec20uk97DglOri3EsQVMcQPrz/XgRw2r72s38dlB1xgcWdjM7sH5Onj7JcNK+xw+OoiJFFvrjrvTie9qb+GTTWosDip8FuKUHfzNo+kENl2swiFxYB/O2eb9N3SrP8EHm+NFOMJFceWokcOYe/LKoE6ctc3tutV3sE3oq8YBNsWzt59MGfu627ZMKzCzReZJO/n8vQntA2wTWpGdMHSd6//jYl05dhQE/a/ivAgvP824r2Yhe4blN7CD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' + + + +Update = lambda elem, value: window[elem].Update(value) + +class BadInputError(Exception): + pass + + +class Player(): + + def __init__(self, name): + self.id = None + self.name = name + self.type = 'Human' + self.hand = Hand() + self.legalCards = [] + self.wildCards = [] + self.valueChangeCards = [] + self.zeroCards = [] + self.canSkip = False + self.canReverse = False + self.canDrawTwo = False + self.canDrawFour = False + self.canValueChange = False + self.drew = False + self.scrollMax = 0 + self.points = 0 + self.forceDraw = 0 + + def addCard(self, card): + self.drew = True + if self.forceDraw > 0: + self.forceDraw -= 1 + self.drew = False + self.hand.addCard(card) + + def beginTurn(self): + self.drew = False + + def didDraw(self): + return self.drew + + def getLegalCards(self, color, value, zeroChange=False): + self.canSkip = False + self.canReverse = False + self.canDrawTwo = False + self.canDrawFour = False + self.canValueChange = False + self.canZeroChange = False + self.legalCards = [] + self.wildCards = [] + self.valueChangeCards = [] + self.zeroCards = [] + plusFours = [] + for card in self.hand: + if card.isWild(): + if card.getValue() == '+4': + plusFours.append(card) + else: + self.wildCards.append(card) + elif zeroChange and card.isZero(): + self.canZero = True + self.zeroCards.append(card) + elif card.getColor() == color or card.getValue() == value: + if card.getColor() != color: + self.canValueChange = True + self.valueChangeCards.append(card) + if card.getValue() == "+2": + self.canDrawTwo = True + elif card.getValue() == 'R': + self.canReverse = True + elif card.getValue() == 'X': + self.canSkip = True + self.legalCards.append(card) + if len(self.legalCards) == 0 and len(plusFours) > 0: + self.canDrawFour = True + self.wildCards += plusFours + + def getValidCards(self): + return self.legalCards + + def getAllValidCards(self): + return self.legalCards + self.wildCards + self.zeroCards + + def hasLegalCard(self): + return len(self.legalCards) > 0 + + def addPoints(self, amount): + if (self.points + amount) <= 999999999999999999999: + self.points += amount + + def removeCard(self, index): + return self.hand.removeCard(index) + + def assignID(self, identity): + self.id = identity + + def getName(self): + return self.name + + def getID(self): + return self.id + + def getPoints(self): + return self.points + + def getType(self): + return self.type + + def getCardNum(self): + return len(self.hand) + + def getHand(self, scrollNum=0, hide=False): + return self.hand.show(scrollNum, hide) + + def getForceDraws(self): + return self.forceDraw + + def addForceDraw(self, num): + self.forceDraw += num + + def decreaseForceDraw(self): + self.forceDraw -= 1 + + def removeForceDraw(self): + self.forceDraw = 0 + + def checkCard(self, index): + return self.hand.getCard(int(index)) + + def discardHand(self): + self.hand.discard() + + def __str__(self): + return self.name + + def __repr__(self): + return '({},{})'.format(self.name, self.points) + + +class Hand(): + ''''deck' (Deck) : Card's Color (rgby) + 'numberOfCards' (int) : Card's Value (0-9, R, X, W, +2, +4)''' + + def __init__(self, deck=None, numberOfCards=0): + self.hand = [] + if deck != None: + self.draw(deck, numberOfCards) + + def __iter__(self): + return iter(self.hand) + + def __len__(self): + return len(self.hand) + + def __getitem__(self, item): + try: + return self.hand[item] + except: + return '' + + def addCard(self, card): + self.hand.append(card) + + def removeCard(self, index): + index = int(index) + if (0 <= index < len(self)): + return self.hand.pop(index) + + def discard(self): + self.hand = [] + + def show(self, scrollNum=0, hide=False): + return '' + + def getCard(self, index): + return self.hand[index] + + def indexCard(self, card): + return self.hand.index(card) + + +class GameSettings(): + playerIdentities = ('play1', 'play2', 'play3', 'play4') + computerNames = ('Watson', 'SkyNet', 'Hal', 'Metal Gear') + + def __init__(self): + self.playerStaging = [] # Where Player Objs Are Stored Before Game Starts + self.players = {} # ID : Player Obj + self.numPlayers = 0 + self.useColor = True + self.displayEffects = True + self.hideComputerHands = True + self.zeroChange = False + self.computerSimulation = False + self.mainMenuError = '' + self.computerSpeed = 'normal' + + def canAddPlayer(self): + return (self.numPlayers < 4) + + def canRemovePlayer(self): + return (self.numPlayers > 0) + + def canBegin(self): + return (self.numPlayers > 1) + + def addPlayer(self, player): + self.playerStaging.append(player) + self.numPlayers += 1 + + def removePlayer(self, number): + number -= 1 + del self.playerStaging[number] + self.numPlayers -= 1 + + def clearStaging(self): + self.numPlayers = 0 + self.playerStaging = [] + + def finalizePlayers(self): + self.players.clear() + identity = 0 + for player in self.playerStaging: + playerID = GameSettings.playerIdentities[identity] + player.assignID(playerID) + self.players[playerID] = player + identity += 1 + + def getPlayerNum(self): + return self.numPlayers + + def getComputerName(self): + complete = False + index = self.numPlayers + while not complete: + name = self.computerNames[index] + complete = True + for player in self.playerStaging: + if player.getName() == name: + index += 1 + if index >= len(self.computerNames): + index = 0 + complete = False + + return self.computerNames[index] + + def getRandomIdentity(self): + '''For Getting a Random Player for First Turn.''' + return random.choice(self.players.keys()) + + + def changeComputerSpeed(self): + return + + + +class Deck(): + ''''shuffle' (bool) : shuffle deck.''' + + colors = ('red', 'yellow', 'green', 'blue') + values = ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'X', 'R', '+2') + + def __init__(self, populate): + '''Initializes proper deck of 108 Uno Cards.''' + self.deck = [] + if populate: + self.populate(True) + + def __getitem__(self, index): + return self.deck[index] + + def populate(self, shuffle=True): + for color in self.colors: + for value in self.values: + self.deck.append(Card(color, value)) + if value != '0': + self.deck.append(Card(color, value)) + for i in range(4): + self.deck.append(Card('wild', '+4')) + self.deck.append(Card('wild', 'W')) + if shuffle: + self.shuffle() + + def __iter__(self): + return iter(self.deck) + + def __len__(self): + return len(self.deck) + + def draw(self): + return self.deck.pop() + + def place(self, card): + return self.deck.append(card) + + def insert(self, card): + self.deck.insert(0, card) + + def shuffle(self): + random.shuffle(self.deck) + + +class ComputerPlayer(Player): + + def __init__(self, name): + super().__init__(name) + self.type = 'Computer' + self.begun = False + self.colorsInHand = {'red': 0, 'blue': 0, 'green': 0, 'yellow': 0, 'wild': 0} + self.colorsOutHand = {} + self.currentColor = "" + + def addCard(self, card): + Player.addCard(self, card) + color = card.getColor() + self.colorsInHand[color] += 1 + + def indexCard(self, cardColor, cardValue): + for card in self.hand: + if card.getValue() == cardValue: + if cardValue in ('+4', 'W'): + return self.hand.indexCard(card) + else: + if card.getColor() == cardColor: + return self.hand.indexCard(card) + raise ValueError("Card Cannot Be Found") + + def think(self, match): + card = None + self.currentColor = match.currentColor + currentValue = match.currentValue + zeroChangeRule = match.zeroChange + twoPlayers = False + previousTurnID = match.getNextTurn(True) + nextTurnID = match.getNextTurn(False) + previousPlayer = match.getPlayer(previousTurnID) + # nextPlayer = match.getPlayer(nextTurnID) + if previousTurnID == nextTurnID: + twoPlayers = True + if self.canSkip == False and self.canReverse == True: + self.canSkip = True + self.canReverse = False + + self.getLegalCards(self.currentColor, currentValue, zeroChangeRule) + + ### DRAW CASE ### + + if len(self.legalCards) == 0 and len(self.wildCards) == 0: + return "d" + + else: + + ### NO LEGAL CARD, USE WILD CARD ### + + if len(self.legalCards) == 0: + + if zeroChangeRule and self.canZeroChange: + bestZeroColor = self.getBestColor(self.zeroCards) + card = self.getCardByColor(self.zeroCards, bestZeroColor) + + else: + + if self.canDrawFour: + card = self.getCardByValue(self.wildCards, "+4") + # print(card) + + else: + card = random.choice(self.wildCards) + + else: + + ### HAS LEGAL CARD ### + + if twoPlayers and self.canSkip: # Always play a skip card in a two player game + # print("Shed Skip Strategy") + card = self.getCardByValue(self.legalCards, "R", "X") + + if self.canReverse and previousPlayer.didDraw(): + # print("Reverse Strategy") + reverseCards = self.getAllCardsByValue(self.legalCards, "R") + for reverseCard in reverseCards: + if reverseCard.getColor() == self.currentColor: + card = reverseCard + + if self.canValueChange: + # Computer Can Value Change, However, Should it? + # Computer Checks to See if Value Change Color is Better Than Current + currentColorNum = self.colorsInHand[self.currentColor] + bestValueChangeColor = self.getBestColor(self.valueChangeCards) + if self.colorsInHand[bestValueChangeColor] > currentColorNum or len(self.valueChangeCards) == len( + self.legalCards): + card = self.getCardByColor(self.valueChangeCards, bestValueChangeColor) + + if card == None: + # print("Random Strategy") + card = random.choice(list(set(self.legalCards) - set(self.valueChangeCards))) + + color = card.getColor() + self.colorsInHand[color] -= 1 + return str(self.indexCard(card.getColor(), card.getValue())) + + def getWildColor(self): + maxKey = max(self.colorsInHand, key=self.colorsInHand.get) + if maxKey == 'wild': + return random.choice(('r', 'g', 'b', 'y')) + else: + return maxKey + + def getCardByValue(self, cardList, *values): + for card in cardList: + if card.getValue() in values: + return card + + def getAllCardsByValue(self, cardList, *values): + cards = [] + for card in cardList: + if card.getValue() in values: + cards.append(card) + return cards + + def getCardByColor(self, cardList, *colors): + for card in cardList: + if card.getColor() in colors: + return card + + def getBestColor(self, cardList): + bestColor = None + bestColorNum = 0 + for card in cardList: + color = card.getColor() + if self.colorsInHand[color] > bestColorNum: + bestColor = color + bestColorNum = self.colorsInHand[color] + return bestColor + + +class Card(): + ''' + 'suit' (string) : Card's Color (rgby) + 'rank' (string) : Card's Value (0-9, R, X, W, +2, +4) + ''' + # 11 = reverse, 12 = +2 + # 0-9, X, R, W, +2, +4 + # '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'X', 'R', '+2', '+4', 'W' + green_dict = {'0':g0, '1':g1, '2':g2, '3':g3, '4':g4, '5':g5, '6':g6, '7':g7, '8':g8, '9':g9, 'X':g10, 'R':g11, '+2':g12, '+4':plusfourgreen, 'W':wildgreen} + red_dict = {'0':r0, '1':r1, '2':r2, '3':r3, '4':r4, '5':r5, '6':r6, '7':r7, '8':r8, '9':r9, 'X':r10, 'R':r11, '+2':r12, '+4':plusfourred, 'W':wildred} + blue_dict = {'0':b0, '1':b1, '2':b2, '3':b3, '4':b4, '5':b5, '6':b6, '7':b7, '8':b8, '9':b9, 'X':b10, 'R':b11, '+2':b12, '+4':plusfourblue, 'W':wildblue} + yellow_dict = {'0':y0, '1':y1, '2':y2, '3':y3, '4':y4, '5':y5, '6':y6, '7':y7, '8':y8, '9':y9, 'X':y10, 'R':y11, '+2':y12, '+4':plusfouryellow, 'W':wildyellow} + green_cards = [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9, g10, g11, g12 ] + red_cards = [r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12 ] + blue_cards = [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12 ] + yellow_cards = [y0, y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, y11, y12 ] + wild_card = wild + + + colors = { + 'red': '\033[91m', + 'green': '\033[92m', + 'yellow': '\033[93m', + 'blue': '\033[94m', + 'purple': '\033[95m', + 'cyan': '\033[96m', + 'white': '\033[97m', + 'wild': '', + 'dwild': '', + 'dred': '\033[31m', + 'dgreen': '\033[32m', + 'dyellow': '\033[33m', + 'dblue': '\033[34m', + 'dpurple': '\033[35m', + 'dcyan': '\033[36m', + 'dwhite': '\033[37m', + } + + idMap = { + 'red': 'R', 'blue': 'B', 'green': 'G', 'yellow': 'Y', 'wild': 'W', + '0': '0', '1': '1', '2': '2', '3': '3', '4': '4', '5': '5', '6': '6', '7': '7', '8': '8', '9': '9', + '+2': '+', 'R': 'R', 'W': 'W', '+4': '$', 'X': 'X' + } + + + def __init__(self, color, value): + '''Initializes Uno Card w/ Color and Value.''' + self.wild = False # Is wild card? + self.zero = False + self.cardID = '{}{}'.format(self.idMap[color], self.idMap[value]) + self.setColor(color) + self.setValue(value) + self.setPoints(value) + + ############################################# + + ### -\/- Retrieve Card Information -\/- ### + + def __repr__(self): + return "{},{}".format(self.color, self.value) + + def getBigNum(self, reverse, reverseSeed=0): + '''Returns list of strings to draw card's value on the pile.''' + return '' + + def getColor(self): + '''Returns card's color.''' + return self.color + + def getColorCode(self): + '''Returns card's color code.''' + return self.colorCode + + def getValue(self): + '''Returns card's value.''' + return self.value + + def getPoints(self): + '''Returns card's point value.''' + return self.points + + def getRow(self, rowNum, hide=False): + return + + ############################################# + + ### -\/- Set Card Information -\/- ### + + def setColor(self, color): + '''Sets Card's color and escape code.''' + if color == 'blue': + self.color = 'blue' + self.colorCode = self.colors['blue'] + self.colorCodeDark = self.colors['dblue'] + elif color == 'red': + self.color = 'red' + self.colorCode = self.colors['red'] + self.colorCodeDark = self.colors['dred'] + elif color == 'yellow': + self.color = 'yellow' + self.colorCode = self.colors['yellow'] + self.colorCodeDark = self.colors['dyellow'] + elif color == 'green': + self.color = 'green' + self.colorCode = self.colors['green'] + self.colorCodeDark = self.colors['dgreen'] + elif color == 'wild': # No color modification + self.wild = True + self.color = 'wild' + self.colorCodeDark = self.colors['dwild'] + self.colorCode = self.colors['wild'] + + def setValue(self, value): + if value in ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'X', 'R', '+2', '+4', 'W'): + self.value = value + self.displaySpace = ' ' + if len(value) == 2: + self.displaySpace = '' + if value == '0': + self.zero = True + + def setPoints(self, value): + if value in ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'): + self.points = int(value) + elif value in ("W", "+4"): + self.points = 50 + else: + self.points = 20 + + ############################################# + + ### -\/- Wild Card Methods -\/- ### + + def changeColor(self, color): + '''Changes Card's Color, Intended for Wild Cards.''' + self.setColor(color) + + def isWild(self): + '''Returns if card is a wild card.''' + return self.wild + + def isZero(self): + return self.zero + + +class Match(): + elementsInit = { + ### Names (final) ### + 'P1Name': ' ', 'P2Name': ' ', 'P3Name': ' ', 'P4Name': ' ', + ### Card Values ### + 'P1Cards': ' ', 'P2Cards': ' ', 'P3Cards': ' ', 'P4Cards': ' ', + ### Turn Colors / Hand### + 'P1Turn': '', 'P2Turn': '', 'P3Turn': '', 'P4Turn': '', + 'HName': '\t\t', 'HVisual': '', 'Hand': '', + ### Deck ### + 'DNum': '', 'Deck': ['', '', '', '', '', '', '', '', ''], + 'PostDNum': '', + ### Pile ### + 'uHeader': '\t\t\t\t', 'uMiddle': ' ', 'uLower': ' ', + 'oHeader': '\t\t\t', + 'oMiddle': ['\t\t\t', '\t\t\t', '\t\t\t', '\t\t\t', '\t\t\t', '\t\t\t', '\t\t\t', '\t\t\t'], + ### Messages ### + 'Console': '', 'Error': '' + } + + speeds = {'slow': 2, 'normal': 1, 'fast': 0} + + window = None + + def __init__(self, gs): + ### Decks ### + self.deck = Deck(True) + self.pile = Deck(False) + + ### Player Information ### + self.players = gs.players + self.turnList = [] + self.handTitles = {'play1': '', 'play2': '', 'play3': '', 'play4': ''} + + ### Carry Information ### + self.displayEffects = gs.displayEffects + self.hideComputerHands = gs.hideComputerHands + self.zeroChange = gs.zeroChange + self.computerSpeed = self.speeds[gs.computerSpeed] + self.simulation = gs.computerSimulation + + ### Data ### + self.handPosition = 0 # For hand displays + self.drawAmount = 0 # Used for force draws + self.passes = 0 # Keep track of consecutive passes for emergency color change + self.passMax = 0 # Max passes before color change + self.turn = '' # Current turn + self.event = '' # Wild, Reverse, Skip, etc + self.wildColorChange = '' # Specifies color to change wild card to + self.currentColor = '' # Current color + self.currentValue = '' # Current value + self.winnerID = '' # ID of Player who Won + self.reverse = False # Is turn order reversed + self.turnComplete = False # Is turn complete + self.matchComplete = False # Is the Game over? + self.matchAbort = False # Did the match conclude without a winner? + self.forcedWild = False # Force change wild + + self.max_cards_displayed = 0 + self.previous_card = None + ### Initialize Names / Cards / Deck (Assuming New Game) ### + self.elements = dict(self.elementsInit) + + keyStringName = 'P{}Name' + keyStringCards = 'P{}Cards' + + for i in self.players: + self.elements[keyStringName.format(i[-1])] = self.players[i].getName() + ( + ' ' * (11 - len(self.players[i].getName()))) + self.elements[keyStringCards.format(i[-1])] = ' ' + ( + ' ' * (3 - len(str(self.players[i].getCardNum())))) + str( + self.players[i].getCardNum()) + ' Cards' + + self.elements['DNum'] = len(self.deck) + + if len(str(len(self.deck))) < 2: + self.elements['PostDNum'] = '\t' + + j = 8 + for i in range(int(math.ceil(len(self.deck) / 12))): + self.elements['Deck'][j] = '=' + j -= 1 + + for key in GameSettings.playerIdentities: + try: + self.buildHandString(key) + self.turnList += [key] + except KeyError: + pass + + self.passMax = len(self.turnList) + # ----------------------------------------- Create the GUI window ----------------------------------------- + sg.SetOptions(background_color='black', element_background_color='black', text_color='white', border_width=0) + Card = lambda image_data, key: sg.B('', image_data=image_data, image_subsample=4, image_size=(60, 80), button_color=('white', 'black'), key=key) + CardBig = lambda image_data: sg.B(button_text='', image_data=image_data, image_subsample=1, image_size=(200, 300), + button_color=('white', 'black'), pad=(0, 0)) + CardBig2 = lambda image_data: sg.Image(data=image_data, size=(100, 300), pad=(0, 0), background_color='black') + + Elem = lambda key: Match.window[key] + T = lambda text, key=None, font='Helvetica 16', **kwargs: sg.T(text, key=key, font=font, **kwargs ) + + MyButton = lambda text, size=(6, 1), font='Helvetica 14', **kwargs: sg.B(text, size=size, font=font, button_color=('white', 'green3'), **kwargs) + OvalButton = lambda text, image_data, **kwargs: sg.B(text, image_data=image_data, font='Helvetica 14', button_color=('white', 'black'), **kwargs) + + col_players = [ + [OvalButton('Quit', greenbutton, key='_QUIT_', visible=False)], + [T('Player', '_P1_', text_color=yellow_color)], + [T('Cards', '_C1_', text_color=yellow_color)], + [T(' ' * 15)], + [T('Player', '_P2_', text_color=red_color)], + [T('Cards', '_C2_', text_color=red_color)], + [T(' ' * 15,'_S3_', visible=False,)], + [T('Player', '_P3_', visible=False)], + [T('Cards', '_C3_', visible=False)], + [T(' ' * 15, '_S4_', visible=False,)], + [T('Player', '_P4_', visible=False)], + [T('Cards', '_C4_', visible=False)],] + + col_cards_left = [ + [OvalButton('Draw', redbutton, key='_DRAW_')], + [T(' '), Card(back, '_DRAW_')], + [T('0 Cards Left', font='Helvetica 14', key='_CARDS_LEFT_')], + [OvalButton('Pass', bluebutton, key='_PASS_')],] + + NUM_COLS = 10 # how many cards shown across bottom in 1 row + NUM_ROWS = 4 + cards = [] + for j in range(NUM_ROWS): + cards.append([sg.T(' ' * 5,font=('Any 5'))] + [Card(None, j*NUM_COLS+i) for i in range(NUM_COLS)]) + + layout = [ + [sg.Column(col_cards_left), + sg.Graph((400, 360), (0, 300), (400, 0), key='_GRAPH_', ), + sg.Column(col_players)], + [T(' ')], + [T(' ')], + [sg.T('', justification='center', size=(55, 2), font='Helvetica 18', key='_MESSAGES_')], + [sg.T('', justification='center', size=(55, 2), font='Helvetica 18', key='_MESSAGES2_')], + ] + layout += cards + + Match.window = sg.Window('Uno',layout, + background_color='black', + use_default_focus=False, + disable_close=True) + + def clearShell(self): + os.system('cls' if os.name == 'nt' else 'clear') + + def begin(self): + self.elements['Console'] = 'Beginning Game, Click Draw to Deal.' + self.drawScreen() + self.enterBreak() + self.eventDealCards() + self.turn = random.choice(self.turnList) + self.elements['Console'] = 'First turn will be {}. Click Draw'.format(self.players[self.turn].getName()) + self.drawScreen(True) + self.enterBreak() + self.placeCard() + self.elements['P{}Turn'.format(self.turn[-1])] = '\033[93m' + if self.event == 'wild': + self.eventWildCard() + elif self.event == 'reverse': + self.eventReverse() + + def end(self, gs): + if not self.matchAbort: + points = 0 + self.elements['P{}Turn'.format(self.turn[-1])] = '' + self.elements['Console'] = '{} Wins! Click Draw to Begin Point Tally'.format( + self.players[self.winnerID].getName()) + self.drawScreen() + self.enterBreak() + + for identity in self.turnList: + if identity != self.winnerID: + self.turn = identity + self.elements['HName'] = self.handTitles[self.turn] + self.elements['P{}Turn'.format(self.turn[-1])] = '\033[93m' + while self.players[identity].getCardNum() > 0: + card = self.players[identity].removeCard(0) + points += card.getPoints() + self.elements['Console'] = '{} Won {} Points!'.format(self.players[self.winnerID].getName(), + points) + + keyStringCards = 'P{}Cards' + self.elements[keyStringCards.format(identity[-1])] = ' ' + ( + ' ' * (3 - len(str(self.players[identity].getCardNum())))) + str( + self.players[identity].getCardNum()) + ' Cards' + self.players[identity].maxScroll = math.ceil((self.players[identity].getCardNum() / 10) - 1) + if self.handPosition > self.players[identity].maxScroll: + self.handPosition -= 1 + self.buildHandVisual(identity) + + if self.displayEffects and not self.simulation: + self.drawScreen() + time.sleep(.1) + self.elements['P{}Turn'.format(self.turn[-1])] = '' + + self.players[self.winnerID].addPoints(points) + self.elements['Console'] = '{} Won {} Points! Click Draw'.format(self.players[self.winnerID].getName(), + points) + self.drawScreen() + self.enterBreak() + + gs.clearStaging() + for identity in self.turnList: + self.players[identity].discardHand() + gs.addPlayer(self.players[identity]) + return gs + + def adjustCardAmount(self, playerID): + keyStringCards = 'P{}Cards' + self.elements[keyStringCards.format(playerID[-1])] = ' ' + ( + ' ' * (3 - len(str(self.players[playerID].getCardNum())))) + str( + self.players[playerID].getCardNum()) + ' Cards' + self.players[playerID].maxScroll = math.ceil((self.players[playerID].getCardNum() / 10) - 1) + if self.handPosition > self.players[playerID].maxScroll: + self.handPosition -= 1 + self.buildHandVisual(playerID) + + def buildHandString(self, playerID): + playerName = self.players[playerID].getName() + if len(playerName) < 9: + self.handTitles[playerID] = "{}'s Hand\t".format(self.players[playerID].getName()) + else: + self.handTitles[playerID] = "{}'s Hand".format(self.players[playerID].getName()) + + def buildHandVisual(self, playerID): + string = '[' + for i in range(self.players[playerID].maxScroll + 1): + if i == self.handPosition: + string += '|' + else: + string += '-' + string += ']' + self.elements['HVisual'] = string + + def checkInput(self, playerInput): + if playerInput == '': + return {'valid': False, 'entry': playerInput} + if playerInput.isnumeric(): + if int(playerInput) + (10 * self.handPosition) < self.players[self.turn].getCardNum(): + return {'valid': True, 'entry': str(int(playerInput) + (10 * self.handPosition)), 'type': 'card'} + else: + self.elements['Error'] = '{} is not a card.'.format(playerInput) + return {'valid': False, 'entry': playerInput} + else: + playerInput = playerInput.lower()[0] + if playerInput in ['<', '>', 'u', 'd', 'p', 'q', 's']: + return {'valid': True, 'entry': playerInput} + else: + self.elements['Error'] = '{} is not a valid selection.'.format(playerInput) + return {'valid': False, 'entry': playerInput} + + def checkColorInput(self, playerInput): + if playerInput == '': + return {'valid': False, 'entry': playerInput} + playerInput = str(playerInput).lower()[0] + if playerInput[0] == 'b': + return {'valid': True, 'entry': 'blue'} + elif playerInput[0] == 'r': + return {'valid': True, 'entry': 'red'} + elif playerInput[0] == 'g': + return {'valid': True, 'entry': 'green'} + elif playerInput[0] == 'y': + return {'valid': True, 'entry': 'yellow'} + return {'valid': False, 'entry': playerInput} + + def eventDealCards(self): + if self.displayEffects and not self.simulation: + self.elements['Console'] = 'Dealing Cards...' + for i in ('play1', 'play2', 'play3', 'play4'): + if i in self.players: + for j in range(7): + self.dealCard(i) + + def eventReverse(self): + if self.displayEffects and not self.simulation: + hide = False + if self.players[self.turn].getType() == "Computer": + hide = self.hideComputerHands + self.elements['Console'] = "Reverse Card Played! Reversing Turn Order.".format( + self.players[self.turn].getName()) + self.drawScreen(hide) + time.sleep(1) + for i in range(10): + cardBigNums = self.pile[0].getBigNum(self.reverse, i) + self.elements['oMiddle'] = cardBigNums + self.drawScreen(hide) + if self.displayEffects and not self.simulation: + time.sleep(.1) + cardBigNums = self.pile[0].getBigNum(self.reverse, 9) + self.elements['oMiddle'] = cardBigNums + self.reverse = not self.reverse + self.event = '' + + def eventSkip(self): + if self.displayEffects and not self.simulation: + hide = False + if self.players[self.turn].getType() == "Computer": + hide = self.hideComputerHands + self.elements['Console'] = "Skip Card Placed! Skipping {}'s Turn.".format(self.players[self.turn].getName()) + self.drawScreen(hide) + time.sleep(1) + for i in range(2): + self.elements['P{}Turn'.format(self.turn[-1])] = '\033[91m' + self.drawScreen(hide) + time.sleep(.3) + self.elements['P{}Turn'.format(self.turn[-1])] = '' + self.drawScreen(hide) + time.sleep(.3) + self.turnComplete = True + self.event = '' + + def eventWildCard(self): + hide = False + if not self.forcedWild: + if self.players[self.turn].getType() == 'Human': + self.elements['Console'] = 'Wild Card! Specifiy a Color' + self.elements['Error'] = 'Specifiy A Color' + self.drawScreen() + while True: + layout=[[sg.T('Wild Card! Specify a Color')], + [sg.Combo(('Blue', 'Red', 'Green', 'Yellow'))], + [sg.OK()]] + window = sg.Window('Wild Card', layout) + + event, values = window.read() + try: + playerInput = values[0].lower()[0] + except: + playerInput = ' ' + # playerInput = str(input("Color Change: ")) + checked = self.checkColorInput(playerInput) + if checked['valid']: + window.close() + break + else: + hide = self.hideComputerHands + checked = self.checkColorInput(self.players[self.turn].getWildColor()) + self.wildColorChange = checked['entry'] + else: + self.wildColorChange = self.checkColorInput(random.choice(('r', 'b', 'g', 'y')))['entry'] + self.forcedWild = False + self.currentColor = self.wildColorChange + self.elements['Error'] = "" + if self.displayEffects and not self.simulation: + self.elements['Console'] = 'Wild Card! Changing Color.' + seed = 1 + for i in range(10): + if seed > 4: + seed = 1 + self.drawScreen(hide, wildSeed=seed) + time.sleep(.1) + seed += 1 + self.pile[0].changeColor(self.wildColorChange) + self.wildColorChange = '' + cardBigNums = self.pile[0].getBigNum(self.reverse) + self.elements['oHeader'] = '{}\u2666\u2666\u2666=========\u2666\u2666\u2666\033[0m\t'.format( + self.pile[0].getColorCode()) + self.elements['oMiddle'] = cardBigNums + self.event = '' + + def eventDraw(self): + self.players[self.turn].addForceDraw(self.drawAmount) + self.drawAmount = 0 + self.event = '' + + def dealCard(self, playerID): + + card = self.deck.draw() + self.players[playerID].addCard(card) + + ### Adjust Hand Visual ### + self.players[playerID].maxScroll = math.ceil((self.players[playerID].getCardNum() / 10) - 1) + self.handPosition = self.players[playerID].maxScroll + self.buildHandVisual(playerID) + + ### Adjust Player Tile ### + keyStringCards = 'P{}Cards' + self.elements[keyStringCards.format(playerID[-1])] = ' ' + ( + ' ' * (3 - len(str(self.players[playerID].getCardNum())))) + str( + self.players[playerID].getCardNum()) + ' Cards' + + ### Adjust Deck ### + self.elements['DNum'] = len(self.deck) + if len(str(len(self.deck))) < 2: + self.elements['PostDNum'] = '\t' + j = 8 + self.elements['Deck'] = [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '] + for i in range(math.ceil(len(self.deck) / 12)): + self.elements['Deck'][j] = '=' + j -= 1 + + def placeCard(self, card=None): + if card == None: + ### Used At Beginning For First Card ### + card = self.deck.draw() + self.elements['DNum'] = len(self.deck) + + cardColor = card.getColorCode() + cardBigNums = card.getBigNum(self.reverse) + + self.currentColor = card.getColor() + self.currentValue = card.getValue() + + self.pile.insert(card) + self.elements['oHeader'] = '{}\u2666\u2666\u2666=========\u2666\u2666\u2666\033[0m\t'.format(cardColor) + self.elements['oMiddle'] = cardBigNums + + if len(self.pile) > 1: + previousCard = self.pile[1] + previousCardColor = previousCard.getColorCode() + self.elements['uHeader'] = '{} \u2666\u2666\u2666=========\u2666\u2666\u2666\033[0m\t\t'.format( + previousCardColor) + self.elements['uMiddle'] = '{}| |\033[0m'.format(previousCardColor) + self.elements['uLower'] = '{}\u2666\u2666\u2666\033[0m'.format(previousCardColor) + + if self.currentColor == 'wild': + self.event = 'wild' + + if self.currentValue == 'X': + self.event = 'skip' + elif self.currentValue == 'R': + if len(self.players) > 2: + self.event = 'reverse' + else: + self.event = 'skip' + elif self.currentValue == '+4': + self.drawAmount = 4 + elif self.currentValue == '+2': + self.drawAmount = 2 + self.passes = 0 + + def extractCard(self, playerID, index): + card = self.players[playerID].removeCard(index) + if self.players[playerID].getCardNum() == 0: + self.matchComplete = True + self.winnerID = self.turn + self.adjustCardAmount(playerID) + return card + + def enterBreak(self): + if not self.simulation: + while True: + if Match.window is None: + break + event, values = Match.window.read() + if event == '_DRAW_': + break + if event == '_QUIT_': + if sg.PopupYesNo('Do you really want to quit?') == 'Yes': + self.matchAbort = True + self.matchComplete = True + + def nextTurn(self): + self.turnComplete = False + self.handPosition = 0 + turnType = self.players[self.turn].getType() + self.players[self.turn].beginTurn() + ### Prepare Hand Visuals ### + + self.elements['HName'] = self.handTitles[self.turn] + self.buildHandVisual(self.turn) + + if self.event == 'skip': + self.eventSkip() + elif self.drawAmount > 0: + self.eventDraw() + #-------------- Main GUI event loop --------------- + while not self.turnComplete: + if turnType == 'Human': + self.players[self.turn].getLegalCards(self.currentColor, self.currentValue, self.zeroChange) + if len(self.deck) > 0: + self.elements['Console'] = 'Select a card or Draw' + else: + self.players[self.turn].removeForceDraw() + self.elements['Console'] = 'Select a card, Draw, or Pass' + if self.players[self.turn].getForceDraws() > 0: + self.elements['Error'] = 'Draw Card Played! Draw {} cards.'.format( + self.players[self.turn].getForceDraws()) + self.drawScreen() + ## GUI INPUT + event, values = Match.window.read() + + playerInput = str(event) + if event == '_DRAW_': + playerInput = 'd' + elif event == '_PASS_': + playerInput = 's' + elif event == '_QUIT_': + if sg.PopupYesNo('Do you really want to quit?') == 'Yes': + self.matchAbort = True + self.matchComplete = True + break + + if playerInput == '<': + self.handPosition -= 1 + if self.handPosition == -1: + self.handPosition = self.players[self.turn].maxScroll + self.buildHandVisual(self.turn) + elif playerInput == '>': + self.handPosition += 1 + if self.handPosition > self.players[self.turn].maxScroll: + self.handPosition = 0 + self.buildHandVisual(self.turn) + elif playerInput == 'd': + if len(self.deck) > 0: + self.elements['Error'] = '' + self.dealCard(self.turn) + else: + self.elements['Error'] = "Cannot Draw. Deck is Empty" + elif playerInput == 'p': + pauseOutput = self.pauseScreen() + if pauseOutput == 'quit': + self.matchComplete = True + self.turnComplete = True + self.winnerID = 'play1' + self.matchAbort = True + elif playerInput == 's': + if len(self.deck) > 0: + self.elements['Error'] = "Cannot pass until Deck is empty." + elif len(self.players[self.turn].getAllValidCards()) > 0: + self.elements['Error'] = "Cannot pass while having playable cards." + else: + self.turnComplete = True + self.passes += 1 + if self.passes == self.passMax: + self.forcedWild = True + self.event = 'wild' + self.passes = 0 + elif playerInput.isnumeric(): + if self.players[self.turn].getForceDraws() == 0: + cardCheck = self.players[self.turn].checkCard(playerInput) + if cardCheck in self.players[self.turn].getAllValidCards(): + card = self.extractCard(self.turn, playerInput) + self.placeCard(card) + self.elements['Error'] = "" + self.turnComplete = True + else: + self.elements['Error'] = "Card Doesn't Match The Color {} or Value {}!".format( + self.currentColor, self.currentValue) + else: + pass + + elif turnType == 'Computer': + event, values = Match.window.read(timeout=0) + if event == '_QUIT_': + if sg.PopupYesNo('Do you really want to quit?') == 'Yes': + self.matchAbort = True + self.matchComplete = True + break + + self.elements['Console'] = '{}\'s Turn'.format(self.players[self.turn].getName()) + self.drawScreen(self.hideComputerHands) + if not self.simulation: + time.sleep(self.computerSpeed) + # str(input()) + while (True): + if self.displayEffects and not self.simulation: + time.sleep(.2) + if self.players[self.turn].getForceDraws() > 0 and len(self.deck) > 0: + cardIndex = 'd' + else: + cardIndex = self.players[self.turn].think(self) + if cardIndex.isnumeric(): + card = self.extractCard(self.turn, int(cardIndex)) + if card.getColor() != self.currentColor: + self.resetDrawBool() + self.placeCard(card) + self.turnComplete = True + break + else: + if cardIndex == 'd': + if len(self.deck) > 0: + self.dealCard(self.turn) + self.drawScreen(self.hideComputerHands) + else: + self.turnComplete = True + self.players[self.turn].removeForceDraw() + self.passes += 1 + if self.passes == self.passMax: + self.forcedWild = True + self.event = 'wild' + self.passes = 0 + break + + ### DECODE INPUT ### + if self.event == 'reverse': + self.eventReverse() + elif self.event == 'wild': + self.eventWildCard() + + # Clear Current Turn + self.elements['P{}Turn'.format(self.turn[-1])] = '' + # Prepare Next Turn + self.turn = self.getNextTurn() + self.elements['P{}Turn'.format(self.turn[-1])] = '\033[93m' + + # --------------------------------------- drawScreen --------------------------------------- + def drawScreen(self, hide=False, wildSeed=0): + if Match.window is None: + return + def get_card_graphic(color, value): + dict = Card.red_dict + if color == 'red': + dict = Card.red_dict + if color == 'blue': + dict = Card.blue_dict + if color == 'green': + dict = Card.green_dict + if color == 'yellow': + dict = Card.yellow_dict + card_graphic = dict[value] if value != '' else Card.wild_card + return card_graphic + + Update = lambda key, value, **kwargs: Match.window[key].Update(value, **kwargs) + elem = lambda key: self.elements[key] + if self.simulation: + return + + currentTurn = self.turn + if currentTurn == '': + currentTurn = self.turnList[-1] + hide = True + + Update('_MESSAGES_', elem('Console')) + Update('_MESSAGES2_', elem('Error')) + Update('_P1_', elem('P1Name')) + Update('_C1_', elem('P1Cards')) + Update('_P2_', elem('P2Name')) + Update('_C2_', elem('P2Cards')) + if elem('P3Name') != ' ': + Update('_P3_', elem('P3Name'), visible=True) + Update('_C3_', elem('P3Cards'), visible=True) + Update('_S3_', None, visible=True) + if elem('P4Name') != ' ': + Update('_P4_', elem('P4Name'), visible=True) + Update('_C4_', elem('P4Cards'), visible=True) + Update('_S4_',None, visible=True) + Update('_CARDS_LEFT_', '{} Cards Left'.format(elem('DNum'))) + # hand = self.players[currentTurn].hand + hand = self.players[currentTurn].hand.hand + i=0 + for i, card in enumerate(hand): + if card.value == 'W': + card_graphic = wild + elif card.value == '+4': + card_graphic = plusfour + else: + card_graphic = get_card_graphic(card.color, card.value) + if hide: + card_graphic = back + + Update(i, '', image_data=card_graphic, image_subsample=4, image_size=(60, 80), visible=True) + else: + for x in range(i+1, self.max_cards_displayed+1): + Update(x, '', image_data=blank, image_subsample=4, image_size=(60, 80), visible=True) + self.max_cards_displayed = max(i, self.max_cards_displayed) + + card_graphic = get_card_graphic(self.currentColor, self.currentValue) + + if self.previous_card is not None: + Match.window['_GRAPH_'].draw_image(data=self.previous_card, location=(0,0)) + Match.window['_GRAPH_'].draw_image(data=card_graphic, location=(100,40)) + + self.previous_card = card_graphic + + Match.window.Refresh() + + return '' + + def pauseScreen(self): + return + + def isComplete(self): + return self.matchComplete + + def next(self): + self.turn = self.getNextTurn() + + def getNextTurn(self, forceReverse=False): + if forceReverse: + reverse = not self.reverse + else: + reverse = self.reverse + currentIndex = self.turnList.index(self.turn) + if not reverse: + if (currentIndex + 1) == len(self.turnList): + return self.turnList[0] + else: + return self.turnList[currentIndex + 1] + else: + if currentIndex == 0: + return self.turnList[len(self.turnList) - 1] + else: + return self.turnList[currentIndex - 1] + + def getPlayer(self, playerID): + return self.players[playerID] + + def resetDrawBool(self): + for identity in self.players: + self.players[identity].drew = False + +def clearShell(): + os.system('cls' if os.name == 'nt' else 'clear') + +def mainMenu(): + gs = GameSettings() + + PLAYER_TYPE_HUMAN = 'HUMAN' + PLAYER_TYPE_COMPUTER = 'COMPUTER' + computer_names = ('Watson', 'SkyNet', 'Hal', 'Metal Gear') + layout = [ + [sg.B('1 - No Player', size=(20,5), key=0, pad=(1,1)), + sg.B('2 - No Player', size=(20, 5), key=1, pad=(1,1), disabled=True)], + [sg.B('3 - No Player', size=(20, 5), key=2, pad=(1,1), disabled=True), + sg.B('4 - No Player', size=(20, 5), key=3, pad=(1,1), disabled=True)], + [sg.T('Enter player 1 (none) name', key='_TXT_'), sg.I(key='_IN_', do_not_clear=True, size=(22,1)), sg.B('Set name')], + [sg.B('Begin'), sg.B('Settings')],] + + Elem = lambda key: window[key] + + button_states = [0] * 4 + player_names = [''] * 4 + player_types = [None] * 4 + + window = sg.Window('Uno Setup', border_depth=0, layout=layout) + + current_player = 0 + while True: # Event Loop + event, values = window.read() + # print(event, values) + if event == sg.WIN_CLOSED or event == 'Exit': + break + if event == 'Begin': + window.Hide() + gs.finalizePlayers() + # ---------------------- START THE MATCH ---------------------- + gs = playMatch(gs) + for i, id in enumerate(gs.players): + player = gs.players[id] + window[i].Update('{} - {}\n{} points'.format(i+1, player.name, player.points)) + window.UnHide() + window.Refresh() + elif event == 'Settings': + layout2 = [[sg.Checkbox('Hide computer hands', key='_HIDE_', default=True)], + [sg.T('Computer speed')], + [sg.Radio('Fast', 1, key='_FAST_')], + [sg.Radio('Normal', 1, key='_NORMAL_', default=True)], + [sg.Radio('Slow', 1, key='_SLOW_')], + [sg.OK(), sg.Cancel()] + ] + win2 = sg.Window('Settings').Layout(layout2) + ev, vals = win2.read() + win2.Close() + if ev == 'OK': + if vals['_NORMAL_']: + gs.computerspeed = 'normal' + if vals['_FAST_']: + gs.computerspeed = 'slow' + if vals['_SLOW_']: + gs.computerspeed = 'slow' + gs.hideComputerHands = vals['_HIDE_'] + elif event == 'Set name': + if values['_IN_'] in player_names: + sg.Popup('Duplicate - Cannot set to same as other players name') + else: + Elem(current_player).Update(str(current_player+1) + ' - '+values['_IN_']) + player_names[current_player] = values['_IN_'] + Elem(current_player + (current_player < 3)).Update(disabled=False) + if player_types[current_player] == PLAYER_TYPE_HUMAN: + addPlayer(gs, values['_IN_']) + else: + addComputer(gs, values['_IN_']) + elif 0 <= event <= 3: + current_player = event + state = button_states[event] = button_states[event]+1 if button_states[event] < 2 else 0 + Elem('_TXT_').Update('Enter Player %s (%s) Name'%(str(current_player+1), ('human', 'computer', 'none')[state-1])) + if state == 1: + Elem('_IN_').SetFocus() + Elem('_IN_').Update('Player name', select=True) + Elem(event).Update(str(event+1) +' - Player') + player_types[event] = PLAYER_TYPE_HUMAN + elif state == 2: + Elem('_IN_').SetFocus() + Elem('_IN_').Update(computer_names[event], select=True) + Elem(event).Update(str(event+1) + ' - ' + computer_names[event]) + player_types[event] = PLAYER_TYPE_COMPUTER + elif state == 0: + Elem(event).Update(str(event+1) +' - No Player') + Elem('_IN_').SetFocus() + Elem('_IN_').Update('', select=True) + for i in range(event): + pass + player_types[event] = None + player_names[event] = '' + for i in range(event+1,4): + Elem(i).Update(text='%s - No player'%i, disabled=True) + player_names[i] = '' + try: + gs.removePlayer(i) + except: + pass + window.close() + return player_names + + +def playMatch(gs): + m = Match(gs) + m.begin() + Match.window['_QUIT_'].Update(visible=True) + while (not m.isComplete()): + m.nextTurn() + gs = m.end(gs) + Match.window.close() + Match.window = None + return gs + + +def addPlayer(gs, name): + p = Player(name) + gs.addPlayer(p) + gs.mainMenuError = "" + + return gs + + +def addComputer(gs, name): + c = ComputerPlayer(name) + gs.addPlayer(c) + + return gs + + + +if __name__ == "__main__": + mainMenu() + diff --git a/DemoPrograms/Demo_User_Setting_Save_Window_Inputs.py b/DemoPrograms/Demo_User_Setting_Save_Window_Inputs.py deleted file mode 100644 index 6c808fe82..000000000 --- a/DemoPrograms/Demo_User_Setting_Save_Window_Inputs.py +++ /dev/null @@ -1,61 +0,0 @@ -import PySimpleGUI as sg - -""" - Demo - User Setting API to save and load a window's contents - - The PySimpleGUI "User Settings API" is a simple interface to JSON and Config Files. - If you're thinking of storying information in a JSON file, consider using the PySimpleGUI - User Settings API calls. They make JSON files act like dictionaries. There's no need - to load nor save as that's done for you. - - There are 2 interfaces to the User Settings API. - 1. Function calls - sg.user_settings - 2. UserSettings Object - Uses a simple class interface - - Note that using the Object/class interface does not require you to write a class. If you're using - PySimpleGUI, you are already using many different objects. The Elements & Window are objects. - - In this demo, a UserSetting object is used to save the values from Input elements into a JSON file. - You can also re-loda the values from the JSON into your window. - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - -# Create a UserSettings object. The JSON file will be saved in the same folder as this .py file -window_contents = sg.UserSettings(path='.', filename='mysettings.json') - -def main(): - layout = [ [sg.Text('My Window')], - [sg.Input(key='-IN1-')], - [sg.Input(key='-IN2-')], - [sg.Input(key='-IN3-')], - [sg.Input(key='-IN4-')], - [sg.Input(key='-IN5-')], - [sg.Button('Save'), sg.Button('Load'), sg.Button('Exit')] ] - - window = sg.Window('Save / Load Inputs Using User Settings API', layout) - - while True: # Event Loop - event, values = window.read() - print(event, values) - if event == sg.WIN_CLOSED or event == 'Exit': - break - - # To SAVE the values, loop through all elements in the values dictionary and save their values - if event == 'Save': - for key in values: - window_contents[key] = values[key] - # To LOAD values from a settings file into a window, loop through values dictionary and update each element - if event == 'Load': - for key in values: - saved_value = window_contents[key] - window[key].update(saved_value) - - window.close() - -if __name__ == '__main__': - main() diff --git a/DemoPrograms/Demo_User_Settings.py b/DemoPrograms/Demo_User_Settings.py index 57e3e1443..9dd42c9d4 100644 --- a/DemoPrograms/Demo_User_Settings.py +++ b/DemoPrograms/Demo_User_Settings.py @@ -11,11 +11,7 @@ Two windows are shown. One is a super-simple "save previously entered filename" The other is a larger "settings window" where multiple settings are saved/loaded - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ SETTINGS_PATH = '.' @@ -40,13 +36,13 @@ def make_window(): :return: (sg.Window) The window that was created """ - sg.theme(sg.user_settings_get_entry('-theme-', 'DarkBlue2')) # set the theme + sg.theme(sg.user_settings_get_entry('theme', 'DarkBlue2')) # set the theme layout = [[sg.Text('Settings Window')], - [sg.Input(sg.user_settings_get_entry('-input-', ''), k='-IN-')], + [sg.Input(sg.user_settings_get_entry('input', ''), k='-IN-')], [sg.Listbox(sg.theme_list(), default_values=[sg.user_settings_get_entry('theme')], size=(15, 10), k='-LISTBOX-')], - [sg.CB('Option 1', sg.user_settings_get_entry('-option1-', True), k='-CB1-')], - [sg.CB('Option 2', sg.user_settings_get_entry('-option2-', False), k='-CB2-')], + [sg.CB('Option 1', sg.user_settings_get_entry('option1', True), k='-CB1-')], + [sg.CB('Option 2', sg.user_settings_get_entry('option2', False), k='-CB2-')], [sg.T('Settings file = ' + sg.user_settings_filename())], [sg.Button('Save'), sg.Button('Exit without saving', k='Exit')]] @@ -68,10 +64,10 @@ def settings_window(): break if event == 'Save': # Save some of the values as user settings - sg.user_settings_set_entry('-input-', values['-IN-']) - sg.user_settings_set_entry('-theme-', values['-LISTBOX-'][0]) - sg.user_settings_set_entry('-option1-', values['-CB1-']) - sg.user_settings_set_entry('-option2-', values['-CB2-']) + sg.user_settings_set_entry('input', values['-IN-']) + sg.user_settings_set_entry('theme', values['-LISTBOX-'][0]) + sg.user_settings_set_entry('option1', values['-CB1-']) + sg.user_settings_set_entry('option2', values['-CB2-']) # if the theme was changed, restart the window if values['-LISTBOX-'][0] != current_theme: @@ -90,17 +86,17 @@ def save_previous_filename_demo(): # Notice that the Input element has a default value given (first parameter) that is read from the user settings layout = [[sg.Text('Enter a filename:')], - [sg.Input(sg.user_settings_get_entry('-filename-', ''), key='-IN-'), sg.FileBrowse()], + [sg.Input(sg.user_settings_get_entry('filename', ''), key='-IN-'), sg.FileBrowse()], [sg.B('Save'), sg.B('Exit Without Saving', key='Exit')]] window = sg.Window('Filename Example', layout) while True: event, values = window.read() - if event in (sg.WINDOW_CLOSED, 'Exit'): + if event in(sg.WINDOW_CLOSED, 'Exit'): break elif event == 'Save': - sg.user_settings_set_entry('-filename-', values['-IN-']) + sg.user_settings_set_entry('filename', values['-IN-']) window.close() diff --git a/DemoPrograms/Demo_User_Settings_As_Simple_Database.py b/DemoPrograms/Demo_User_Settings_As_Simple_Database.py deleted file mode 100644 index b4c89fd1e..000000000 --- a/DemoPrograms/Demo_User_Settings_As_Simple_Database.py +++ /dev/null @@ -1,70 +0,0 @@ -import PySimpleGUI as sg - -""" - Demo - User Settings as a Database - - The PySimpleGUI User Settings APIs are implemnted to look like a dictionary to the - user and utilize JSON files to store the data. As a result, one "key" is used to - store and retrieve each "setting". This capability cab be used to implement a - simple database. - - In this demo the User Settings file is used to store a user ID and data associated - with that ID. Each User ID has a dictionary stored in the User Settings file. This - dictionary is built from the values dictionary of the window. There is a map varaible - called data_map that translates between the two dictionaries. - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - -def get_id_data(user_setting, id): - return user_setting[id] - -def main(): - # Maps between keys used in the User Settings an the Window itself - data_map = {'-name-': '-NAME-', '-password-': '-PASSWORD-', '-dept-': '-DEPT-', '-security-': '-SECURITY-'} - user_data = sg.UserSettings('my_user_data.json') - INPUT_SIZE=30 - layout = [ [sg.Text('User ID Management')], - [sg.Push(), sg.Text('User ID:'), sg.Input(key='-ID-', size=INPUT_SIZE)], - [sg.Push(), sg.Text('Name:'), sg.Input(key='-NAME-', size=INPUT_SIZE,)], - [sg.Push(), sg.Text('Password:'), sg.Input(key='-PASSWORD-', size=INPUT_SIZE, password_char='*')], - [sg.Push(), sg.Text('Department:'), sg.Input(key='-DEPT-', size=INPUT_SIZE,)], - [ sg.Text('Security Level:'), sg.Combo(('Low', 'Medium', 'High'), size=(INPUT_SIZE-2,3), readonly=True, default_value='Low', key='-SECURITY-')], - - [sg.Button('Add/Update'), sg.Button('Load'), sg.Button('Display'), sg.Button('Exit')] ] - - window = sg.Window('User Settings as Database', layout) - - while True: # Event Loop - event, values = window.read() - print(event, values) - if event == sg.WIN_CLOSED or event == 'Exit': - break - elif event == 'Add/Update': - # Make a dictionary of data for the ID being added/updated based on the window's values - user = values['-ID-'] - data = {} - for setting_key, values_key in data_map.items(): - data[setting_key] = values[values_key] - user_data[user] = data - sg.popup(f'Added or updated user: {values["-ID-"]}') - elif event == 'Load': - user = values['-ID-'] - data = user_data[user] - for setting_key, values_key in data_map.items(): - value = data[setting_key] if data is not None else '' - window[values_key].update(value) - elif event == 'Display': - user = values['-ID-'] - data = user_data[user] - output = f'Detailed User Information for ID: {user}\n' - for setting_key, values_key in data_map.items(): - value = data[setting_key] if data is not None else '' - output += f'{setting_key} = {value}\n' - sg.popup_scrolled(output, title='Detailed User Data') -if __name__ == '__main__': - main() diff --git a/DemoPrograms/Demo_User_Settings_Auto_Load_and_Save.py b/DemoPrograms/Demo_User_Settings_Auto_Load_and_Save.py deleted file mode 100644 index 60f240a95..000000000 --- a/DemoPrograms/Demo_User_Settings_Auto_Load_and_Save.py +++ /dev/null @@ -1,59 +0,0 @@ -import PySimpleGUI as sg - -""" - Demo - User Setting API to automatically save and load Input Elements - - This Demo Program shows an easy way to add saving and loading of Input elements. - - The variable keys_to_save is used to determine which elements will be saved to the user settings file. - - The function make_key returns a dictionary that's used as keyword parameters that are passed to the Input elements. Using this technique allows the Input elements in the layout to benefit from the docstrings provided by PySimpleGUI. Another approach could be to use a function that returns an Input element, but that limits the flexibility for configuring Input elements. - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - -keys_to_save = ('-IN1-', '-IN2-', '-IN3-', '-IN4-') - -def make_key(key): - """ - Returns a dictionary that is used to pass parameters to an Input element. - Another approach could be to return an Input element. The downside to that approach is - the lack of parameters and associated docstrings when creating the layout. - - :param key: - :return: Dict - """ - return {'default_text':sg.user_settings_get_entry(key, ''), 'key':key} - - -def main(): - layout = [ [sg.Text('Automatically Load and Save Of Inputs', font='_ 15')], - [sg.Text('Input 1'), sg.Input(**make_key('-IN1-'))], - [sg.Text('Input 2'), sg.Input(**make_key('-IN2-'), background_color='green')], - [sg.Text('Input 3'), sg.Input(**make_key('-IN3-'), text_color='blue')], - [sg.Text('Input 4'), sg.Input(**make_key('-IN4-'), size=5)], - [sg.Button('Exit (and save)', key='-EXIT SAVE-'), sg.Button('Exit without save')] ] - - window = sg.Window('Save / Load Inputs Using User Settings API', layout) - - while True: # Event Loop - event, values = window.read() - print(event, values) - if event == sg.WIN_CLOSED or event == 'Exit without save': - sg.popup_quick_message('Exiting without save', text_color='white', background_color='red', font='_ 20') - - break - elif event == '-EXIT SAVE-': - sg.popup_quick_message('Saving settings & Exiting', text_color='white', background_color='red', font='_ 20') - for key in keys_to_save: - sg.user_settings_set_entry(key, values[key]) - break - - window.close() - -if __name__ == '__main__': - main() diff --git a/DemoPrograms/Demo_User_Settings_Browse_File_Folder.py b/DemoPrograms/Demo_User_Settings_Browse_File_Folder.py index 7205a329e..9b6bc10e7 100644 --- a/DemoPrograms/Demo_User_Settings_Browse_File_Folder.py +++ b/DemoPrograms/Demo_User_Settings_Browse_File_Folder.py @@ -21,46 +21,38 @@ If your window is not a 1-shot, add an event loop instead of a read with close paramter - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ # ------------------- The Old Way ------------------- -import PySimpleGUI as sg layout = [[sg.Text('My Window')], [sg.InputText(size=(50, 1), key='-FILENAME-'), sg.FileBrowse()], [sg.Button('Go'), sg.Button('Exit')]] -event1, values1 = sg.Window('Normal Filename', layout).read(close=True) +event1, values1 = sg.Window('Window Title', layout).read(close=True) # ------------------- The New Way with history ------------------- -import PySimpleGUI as sg layout = [[sg.Text('My Window')], [sg.Combo(sg.user_settings_get_entry('-filenames-', []), default_value=sg.user_settings_get_entry('-last filename-', ''), size=(50, 1), key='-FILENAME-'), sg.FileBrowse()], [sg.Button('Go'), sg.Button('Exit')]] -event, values = sg.Window('Filename with History', layout).read(close=True) +event, values = sg.Window('Window Title', layout).read(close=True) if event == 'Go': sg.user_settings_set_entry('-filenames-', list(set(sg.user_settings_get_entry('-filenames-', []) + [values['-FILENAME-'], ]))) sg.user_settings_set_entry('-last filename-', values['-FILENAME-']) - # ------------------- The New Way with history and clear ------------------- -import PySimpleGUI as sg layout = [[sg.Text('My Window')], [sg.Combo(sg.user_settings_get_entry('-filenames-', []), default_value=sg.user_settings_get_entry('-last filename-', ''), size=(50, 1), key='-FILENAME-'), sg.FileBrowse()], [sg.Button('Go'), sg.B('Clear'), sg.Button('Exit')]] -window = sg.Window('Filename History Clearable', layout) +window = sg.Window('Window Title', layout) while True: event, values = window.read() diff --git a/DemoPrograms/Demo_User_Settings_Class.py b/DemoPrograms/Demo_User_Settings_Class.py deleted file mode 100644 index 3af545fd6..000000000 --- a/DemoPrograms/Demo_User_Settings_Class.py +++ /dev/null @@ -1,127 +0,0 @@ -import PySimpleGUI as sg - -""" - Demo - User Settings Using Class - - There are 2 interfaces for the User Settings APIs in PySimpleGUI. - 1. Function calls - 2. The UserSettings class - - This demo focuses on using the class interface. The advantage of using the class is that - lookups resemble the syntax used for Python dictionaries - - This demo is very basic. The user_settings functions are used directly without a lookup table - or some other mechanism to map between PySimpleGUI keys and user settings keys. - - Note that there are 2 coding conventions being used. The PySimpleGUI Demo Programs all use - keys on the elements that are strings with the format '-KEY-'. They are upper case. The - coding convention being used in Demo Programs that use User Settings use keys that have - the same format, but are lower case. A User Settings key is '-key-'. The reason for this - convention is so that you will immediately know what the string you are looking at is. - By following this convention, someone reading the code that encounters '-filename-' will - immediately recognize that this is a User Setting. - - Two windows are shown. One is a super-simple "save previously entered filename" - The other is a larger "settings window" where multiple settings are saved/loaded - - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - -SETTINGS_PATH = '.' - -# create the settings object that will be used globally, but not need to change so not declared as global -settings = sg.UserSettings(path=SETTINGS_PATH) - -def make_window(): - """ - Creates a new window. The default values for some elements are pulled directly from the - "User Settings" without the use of temp variables. - - Some get_entry calls don't have a default value, such as theme, because there was an initial call - that would have set the default value if the setting wasn't present. Could still put the default - value if you wanted but it would be 2 places to change if you wanted a different default value. - - Use of a lookup table to map between element keys and user settings could be aded. This demo - is intentionally done without one to show how to use the settings APIs in the most basic, - straightforward way. - - If your application allows changing the theme, then a make_window function is good to have - so that you can close and re-create a window easily. - - :return: (sg.Window) The window that was created - """ - - sg.theme(settings.get('-theme-', 'DarkBlue2')) # set the theme - - layout = [[sg.Text('Settings Window')], - [sg.Input(settings.get('-input-', ''), k='-IN-')], - [sg.Listbox(sg.theme_list(), default_values=[settings['-theme-'],], size=(15, 10), k='-LISTBOX-')], - [sg.CB('Option 1', settings.get('-option1-', True), k='-CB1-')], - [sg.CB('Option 2', settings.get('-option2-', False), k='-CB2-')], - [sg.T('Settings file = ' + settings.get_filename())], - [sg.Button('Save'), sg.Button('Settings Dictionary'), sg.Button('Exit without saving', k='Exit')]] - - window = sg.Window('A Settings Window', layout) - - -def settings_window(): - """ - Create and interact with a "settings window". You can a similar pair of functions to your - code to add a "settings" feature. - """ - - window = make_window() - current_theme = sg.theme() - - while True: - event, values = window.read() - if event in (sg.WINDOW_CLOSED, 'Exit'): - break - if event == 'Save': - # Save some of the values as user settings - settings['-input-'] = values['-IN-'] - settings['-theme-'] = values['-LISTBOX-'][0] - settings['-option1-'] = values['-CB1-'] - settings['-option2-'] = values['-CB2-'] - elif event == 'Settings Dictionary': - sg.popup(settings) - # if a listbox item is selected and if the theme was changed, then restart the window - if values['-LISTBOX-'] and values['-LISTBOX-'][0] != current_theme: - current_theme = values['-LISTBOX-'][0] - window.close() - window = make_window() - - -def save_previous_filename_demo(): - """ - Saving the previously selected filename.... - A demo of one of the likely most popular use of user settings - * Use previous input as default for Input - * When a new filename is chosen, write the filename to user settings - """ - - # Notice that the Input element has a default value given (first parameter) that is read from the user settings - layout = [[sg.Text('Enter a filename:')], - [sg.Input(settings.get('-filename-', ''), key='-IN-'), sg.FileBrowse()], - [sg.B('Save'), sg.B('Exit Without Saving', key='Exit')]] - - window = sg.Window('Filename Example', layout) - - while True: - event, values = window.read() - if event in (sg.WINDOW_CLOSED, 'Exit'): - break - elif event == 'Save': - settings['-filename-'] = values['-IN-'] - - window.close() - - -if __name__ == '__main__': - # Run a couple of demo windows - save_previous_filename_demo() - settings_window() diff --git a/DemoPrograms/Demo_User_Settings_Class_Remember_Input_and_Combo.py b/DemoPrograms/Demo_User_Settings_Class_Remember_Input_and_Combo.py index 1ee67d98e..48c1d65d7 100644 --- a/DemoPrograms/Demo_User_Settings_Class_Remember_Input_and_Combo.py +++ b/DemoPrograms/Demo_User_Settings_Class_Remember_Input_and_Combo.py @@ -6,11 +6,7 @@ This demo is the same as the Demo_User_Settings_Remember_Input_and_Combo.py The difference between the 2 files is that this one users the UserSettings class syntax while the other uses the function calls. - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ def main(): diff --git a/DemoPrograms/Demo_User_Settings_Config_INI_Format.ini b/DemoPrograms/Demo_User_Settings_Config_INI_Format.ini new file mode 100644 index 000000000..e101355f4 --- /dev/null +++ b/DemoPrograms/Demo_User_Settings_Config_INI_Format.ini @@ -0,0 +1,14 @@ +[My Section] +filename = test1234 +filename2 = number 2 +filename3 = number 3 + +[Section 2] +var = New Value +var1 = Default + +[Empty] + +[last section] +bool = True + diff --git a/DemoPrograms/Demo_User_Settings_Config_INI_Format.py b/DemoPrograms/Demo_User_Settings_Config_INI_Format.py index 69e50b0ea..5e093182a 100644 --- a/DemoPrograms/Demo_User_Settings_Config_INI_Format.py +++ b/DemoPrograms/Demo_User_Settings_Config_INI_Format.py @@ -21,11 +21,7 @@ NOTE - There is a setting (default is ON) that converts True", "False, "None" into Python values of True, False, None - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ @@ -83,13 +79,4 @@ def save_previous_filename_demo(): SETTINGS_PATH = '.' # create the settings object and use ini format settings = sg.UserSettings(path=SETTINGS_PATH, use_config_file=True, convert_bools_and_none=True) - # sg.popup(settings) - # settings['My Section1'].delete_entry(key='test') - # settings.delete_entry(section='My Section1', key='test') - # settings['My Section1'].delete_section() - # del settings['My Section1'] - # settings.delete_section(section='My Section1') - settings['Section 2'].set('var1', 'Default') - settings['Section 2']['var'] = 'New Value' - settings['NEW SECTION']['a'] = 'brand new section' save_previous_filename_demo() diff --git a/DemoPrograms/Demo_User_Settings_Element_setting_Parameter.py b/DemoPrograms/Demo_User_Settings_Element_setting_Parameter.py deleted file mode 100644 index a9a17538c..000000000 --- a/DemoPrograms/Demo_User_Settings_Element_setting_Parameter.py +++ /dev/null @@ -1,48 +0,0 @@ -import PySimpleGUI as sg - -""" - Demo - User Settings - - Using the PySimpleGUI 5 setting parameter. - - New in the PSG5 release is a capability to automatically save and restore values in elements. Each element that has the capability has a parameter called "setting" - - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - - -def make_window(): - layout = [[sg.Text('Window with values saved between runs')], - [sg.Input(key='-IN-', setting='My initial value')], - [sg.Checkbox('Checkbox', key='-CB-', setting=True)], - [sg.Button('Re-create Window'), sg.Button('Exit')]] - - window = sg.Window('Setting Example', layout, enable_close_attempted_event=True, print_event_values=True, auto_save_location=True) - - return window - - -def main(): - - window = make_window() - - while True: - event, values = window.read() - if event == sg.WIN_CLOSED or event == 'Exit' or event == sg.WIN_CLOSE_ATTEMPTED_EVENT: - window.settings_save(values) - break - - if event == 'Re-create Window': # You can also close and re-open a window using the values previously entered - window.settings_save(values) - window.close() - window = make_window() - - window.close() - - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/DemoPrograms/Demo_User_Settings_Remember_Input_and_Combo.py b/DemoPrograms/Demo_User_Settings_Remember_Input_and_Combo.py index 6d00cb9b2..48c8d828c 100644 --- a/DemoPrograms/Demo_User_Settings_Remember_Input_and_Combo.py +++ b/DemoPrograms/Demo_User_Settings_Remember_Input_and_Combo.py @@ -7,11 +7,7 @@ Then, when the OK button is clicked, it's one line of code to save the newly added name into the saved list. - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ def main(): diff --git a/DemoPrograms/Demo_Watermark_Window.py b/DemoPrograms/Demo_Watermark_Window.py deleted file mode 100644 index f1a2a3ca1..000000000 --- a/DemoPrograms/Demo_Watermark_Window.py +++ /dev/null @@ -1,113 +0,0 @@ -import PySimpleGUI as sg - -""" - Demo - Watermarking all windows - - Watermarking windows can be done in 4.60.0.160 and greater. It's a very simple mechanism for now. - - The option is normally set in the Global Settings control panel. However, you can "Force" the watermark - on all windows by setting the Window paramter watermark=True on any window you create and from then on - all windows will have the watermark. - - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - -""" -M"""""""`YM -M mmmm. M -M MMMMM M .d8888b. -M MMMMM M 88' `88 -M MMMMM M 88. .88 -M MMMMM M `88888P' -MMMMMMMMMMM - -M""MMM""MMM""M dP dP -M MMM MMM M 88 88 -M MMP MMP M .d8888b. d8888P .d8888b. 88d888b. 88d8b.d8b. .d8888b. 88d888b. 88 .dP -M MM' MM' .M 88' `88 88 88ooood8 88' `88 88'`88'`88 88' `88 88' `88 88888" -M `' . '' .MM 88. .88 88 88. ... 88 88 88 88 88. .88 88 88 `8b. -M .d .dMMM `88888P8 dP `88888P' dP dP dP dP `88888P8 dP dP `YP -MMMMMMMMMMMMMM -""" - -layout = [ [sg.Text('No Watermark')], - [sg.Button('Exit')] ] - -window = sg.Window('No Watermark', layout) - -while True: - event, values = window.read() - if event == sg.WIN_CLOSED or event == 'Exit': - break - -window.close() - - -""" -MP""""""`MM dP -M mmmmm..M 88 -M. `YM dP dP .d8888b. d8888P .d8888b. 88d8b.d8b. -MMMMMMM. M 88 88 Y8ooooo. 88 88ooood8 88'`88'`88 -M. .MMM' M 88. .88 88 88 88. ... 88 88 88 -Mb. .dM `8888P88 `88888P' dP `88888P' dP dP dP -MMMMMMMMMMM .88 - d8888P -M""MMM""MMM""M dP dP -M MMM MMM M 88 88 -M MMP MMP M .d8888b. d8888P .d8888b. 88d888b. 88d8b.d8b. .d8888b. 88d888b. 88 .dP -M MM' MM' .M 88' `88 88 88ooood8 88' `88 88'`88'`88 88' `88 88' `88 88888" -M `' . '' .MM 88. .88 88 88. ... 88 88 88 88 88. .88 88 88 `8b. -M .d .dMMM `88888P8 dP `88888P' dP dP dP dP `88888P8 dP dP `YP -MMMMMMMMMMMMMM -""" - -sg.set_options(watermark_text='') # noramlly not requird unless previously set by user - -layout = [ [sg.Text('System Provided Watermark')], - [sg.Button('Exit')] ] - -window = sg.Window('System Watermark', layout, watermark=True) - -while True: - event, values = window.read() - if event == sg.WIN_CLOSED or event == 'Exit': - break - -window.close() - - -""" -M""MMMMM""M -M MMMMM M -M MMMMM M .d8888b. .d8888b. 88d888b. -M MMMMM M Y8ooooo. 88ooood8 88' `88 -M `MMM' M 88 88. ... 88 -Mb dM `88888P' `88888P' dP -MMMMMMMMMMM - -M""MMM""MMM""M dP dP -M MMM MMM M 88 88 -M MMP MMP M .d8888b. d8888P .d8888b. 88d888b. 88d8b.d8b. .d8888b. 88d888b. 88 .dP -M MM' MM' .M 88' `88 88 88ooood8 88' `88 88'`88'`88 88' `88 88' `88 88888" -M `' . '' .MM 88. .88 88 88. ... 88 88 88 88 88. .88 88 88 `8b. -M .d .dMMM `88888P8 dP `88888P' dP dP dP dP `88888P8 dP dP `YP -MMMMMMMMMMMMMM -""" - -sg.set_options(watermark_text='User Supplied Version 1.0') - -layout = [ [sg.Text('User Supplied Watermark')], - [sg.Button('Exit')] ] - -window = sg.Window('User Supplied Watermark', layout, watermark=True) - -while True: - event, values = window.read() - if event == sg.WIN_CLOSED or event == 'Exit': - break - -window.close() diff --git a/DemoPrograms/Demo_Window_Background_Image.py b/DemoPrograms/Demo_Window_Background_Image.py index 36f36049e..2a0a6778e 100644 --- a/DemoPrograms/Demo_Window_Background_Image.py +++ b/DemoPrograms/Demo_Window_Background_Image.py @@ -6,11 +6,7 @@ Requires the latest PySimpleGUI from GitHub. Your copy of PySimpleGUI should be local to your application so that the global variable _move_all_windows can be changed. - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ diff --git a/DemoPrograms/Demo_Window_Config_Events.py b/DemoPrograms/Demo_Window_Config_Events.py deleted file mode 100644 index af82e991a..000000000 --- a/DemoPrograms/Demo_Window_Config_Events.py +++ /dev/null @@ -1,38 +0,0 @@ -import PySimpleGUI as sg - -""" - Demo Window Config Events - - The Window object has a parameter enable_window_config_events that when set to True will - cause sg.WINDOW_CONFIG_EVENT events to be generated when the window is moved or resized. - - Note that if you move the window using the Titlebar supplied by the operating system, then you - will only get an event at the end of the window being moved. If you want to receive numerous - events during the movement, then you can achieve this using a grab_anywhere setting either - at the window level or on a single element as shown in this demo. - - Copyright 2022-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - -layout = [ [sg.Text('Demonstration of the enable_window_config_events')], - [sg.Text('Grab me HERE for continuous location changed events', grab=True, text_color=sg.theme_background_color(), background_color=sg.theme_text_color())], - [sg.Text(key='-OUT-', font='_18')], - [sg.VPush()], - [sg.Button('Go'), sg.Button('Exit'), sg.Sizegrip()] ] - -window = sg.Window('Window Title', layout, resizable=True, enable_window_config_events=True, finalize=True) - -window.set_min_size(window.current_size_accurate()) - -while True: - event, values = window.read() - if event == sg.WIN_CLOSED or event == 'Exit': - break - if event == sg.WINDOW_CONFIG_EVENT: - window['-OUT-'].update(f'Size: {window.current_size_accurate()}\nLocation:{window.current_location()}') - -window.close() diff --git a/DemoPrograms/Demo_Window_Disappear.py b/DemoPrograms/Demo_Window_Disappear.py index 4add56736..cdf48aeca 100644 --- a/DemoPrograms/Demo_Window_Disappear.py +++ b/DemoPrograms/Demo_Window_Disappear.py @@ -1,14 +1,6 @@ #!/usr/bin/env python import PySimpleGUI as sg -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - # Example .disappear() .reappear() methods in window diff --git a/DemoPrograms/Demo_Window_Location_Finder.py b/DemoPrograms/Demo_Window_Location_Finder.py index 57634b61c..6a5a46a95 100644 --- a/DemoPrograms/Demo_Window_Location_Finder.py +++ b/DemoPrograms/Demo_Window_Location_Finder.py @@ -11,33 +11,28 @@ The value in the center is the screen dimensions for the primary window. - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ sg.theme('dark green 7') layout = [ [sg.T(sg.SYMBOL_UP_ARROWHEAD), sg.Text(size=(None,1), key='-OUT-'), - sg.Text(size=(None,1), key='-OUT2-', expand_x=True, expand_y=True, justification='c'), sg.T(sg.SYMBOL_UP_ARROWHEAD)], - [sg.T('Screen size: '),sg.T(sg.Window.get_screen_size()), sg.T(sg.SYMBOL_SQUARE)], + sg.Text(size=(None,1), key='-OUT2-', justification='c'), sg.T(sg.SYMBOL_UP_ARROWHEAD)], + [sg.T('Screen size: '),sg.T(sg.Window.get_screen_size())], [sg.T(sg.SYMBOL_DOWN_ARROWHEAD), sg.Text(size=(None,1), key='-OUT4-'), - sg.Text(size=(None,1), key='-OUT3-', expand_x=True, expand_y=True, justification='r'), sg.T(sg.SYMBOL_DOWN_ARROWHEAD, justification='r')], + sg.Text(size=(None,1), key='-OUT3-', justification='r'), sg.T(sg.SYMBOL_DOWN_ARROWHEAD, justification='r')], ] -window = sg.Window('Title not seen', layout, grab_anywhere=True, no_titlebar=True, margins=(0,0), element_padding=(0,0), right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_EXIT, keep_on_top=True, font='_ 25', finalize=True, transparent_color=sg.theme_background_color()) +window = sg.Window('Title not seen', layout, grab_anywhere=True, no_titlebar=True, margins=(0,0), element_padding=(0,0), right_click_menu=sg.MENU_RIGHT_CLICK_EXIT, keep_on_top=True, font='_ 25', finalize=True) +window['-OUT3-'].expand(True, True, True) +window['-OUT2-'].expand(True, True, True) while True: event, values = window.read(timeout=100) if event == sg.WIN_CLOSED or event == 'Exit': break - if event == 'Edit Me': - sg.execute_editor(__file__) - loc = window.current_location() window['-OUT-'].update(loc) window['-OUT2-'].update((loc[0]+window.size[0], loc[1])) diff --git a/DemoPrograms/Demo_Window_Open_Multiple_Times.py b/DemoPrograms/Demo_Window_Open_Multiple_Times.py index c2ad1dfca..ffcc6a49e 100644 --- a/DemoPrograms/Demo_Window_Open_Multiple_Times.py +++ b/DemoPrograms/Demo_Window_Open_Multiple_Times.py @@ -13,11 +13,7 @@ way to encapsulate windows if your applcation is gettinga little larger than the typical small data entry window. - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ diff --git a/DemoPrograms/Demo_Window_Pin_On_Top.py b/DemoPrograms/Demo_Window_Pin_On_Top.py index 0520e5ecd..13508e0b9 100644 --- a/DemoPrograms/Demo_Window_Pin_On_Top.py +++ b/DemoPrograms/Demo_Window_Pin_On_Top.py @@ -12,11 +12,7 @@ A temporary implementation is included in case you don't have that version - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ def main(): diff --git a/DemoPrograms/Demo_Window_Relative_Location.py b/DemoPrograms/Demo_Window_Relative_Location.py index ff11a8f89..6af84ae3d 100644 --- a/DemoPrograms/Demo_Window_Relative_Location.py +++ b/DemoPrograms/Demo_Window_Relative_Location.py @@ -17,11 +17,7 @@ Both positive and negative values are valid. relative_location=(0, -150) will create the window UP 150 pixels from where it would normally be created - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ diff --git a/DemoPrograms/Demo_YouTube_Intro.py b/DemoPrograms/Demo_YouTube_Intro.py index 850a91bde..2961dee47 100644 --- a/DemoPrograms/Demo_YouTube_Intro.py +++ b/DemoPrograms/Demo_YouTube_Intro.py @@ -1,13 +1,5 @@ import PySimpleGUI as sg -""" - Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. -""" - layout = [[sg.Text('What is your name?')], [sg.InputText()], [sg.Button('Ok')]] diff --git a/DemoPrograms/Demo_Youtube-dl_Frontend.py b/DemoPrograms/Demo_Youtube-dl_Frontend.py index 0473b1872..a4aa11539 100644 --- a/DemoPrograms/Demo_Youtube-dl_Frontend.py +++ b/DemoPrograms/Demo_Youtube-dl_Frontend.py @@ -8,14 +8,7 @@ Paste the youtube link into the GUI. The GUI link is queried when you click Get List. Get List will populate the pulldown list with the language options available for the video. Choose the language to download and click Download - -Copyright 2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - -Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - -You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. """ - youtube_executable = 'path/to/youtube-dl' diff --git a/DemoPrograms/Demo_one_line_progress_meter.py b/DemoPrograms/Demo_one_line_progress_meter.py index 8489fefc2..c35b73e18 100644 --- a/DemoPrograms/Demo_one_line_progress_meter.py +++ b/DemoPrograms/Demo_one_line_progress_meter.py @@ -20,11 +20,7 @@ * Add - A call to the meter update funciton inside your loop - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI.org """ diff --git a/DemoPrograms/Demo_System_Tray_Icon_Using_psgtray.py b/DemoPrograms/Demo_psgtray_Tray_Icon_Tkinter.py similarity index 87% rename from DemoPrograms/Demo_System_Tray_Icon_Using_psgtray.py rename to DemoPrograms/Demo_psgtray_Tray_Icon_Tkinter.py index 6c536efdc..44eefde80 100644 --- a/DemoPrograms/Demo_System_Tray_Icon_Using_psgtray.py +++ b/DemoPrograms/Demo_psgtray_Tray_Icon_Tkinter.py @@ -17,11 +17,7 @@ One trick employed here is to change the window's event to be the event from the System Tray. - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright PySimpleGUI 2021 """ def main(): diff --git a/DemoPrograms/Demo_psutil_Kill_Processes.py b/DemoPrograms/Demo_psutil_Kill_Processes.py index 3edeeb594..18c7990fe 100644 --- a/DemoPrograms/Demo_psutil_Kill_Processes.py +++ b/DemoPrograms/Demo_psutil_Kill_Processes.py @@ -13,11 +13,7 @@ Utility to show running processes, CPU usage and provides way to kill processes. Based on psutil package that is easily installed using pip - Copyright 2021-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2021 PySimpleGUI """ def kill_proc_tree(pid, sig=signal.SIGTERM, include_parent=True, diff --git a/DemoPrograms/Demo_psutil_Kill_Python_Processes.py b/DemoPrograms/Demo_psutil_Kill_Python_Processes.py index ee07aefe7..90147766d 100644 --- a/DemoPrograms/Demo_psutil_Kill_Python_Processes.py +++ b/DemoPrograms/Demo_psutil_Kill_Python_Processes.py @@ -19,11 +19,7 @@ to launch the program. This is particularly good for programs that have no titlebar or are running in the background or system tray. - Copyright 2020-2023 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - - Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - - You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant to the PySimpleGUI License Agreement. + Copyright 2020 PySimpleGUI.org """ @@ -79,23 +75,23 @@ def get_all_procs(): return disp_data -def show_list_by_name(python_only=False): +def show_list_by_name(): disp_data = get_all_procs() disp_data = sorted(disp_data, key=operator.itemgetter(3), reverse=False) display_list = [] for process in disp_data: - if not python_only or (python_only and 'python' in process[2].lower()): + if 'python' in process[2].lower(): display_list.append('{:5d} {:5.2f} {} {}\n'.format(process[0], process[1], process[2], process[3])) return display_list -def show_list_by_cpu(python_only=False): +def show_list_by_cpu(): disp_data = get_all_procs() disp_data = sorted(disp_data, key=operator.itemgetter(1), reverse=True) display_list = [] for process in disp_data: - if not python_only or (python_only and 'python' in process[2].lower()): + if 'python' in process[2].lower(): display_list.append('{:5d} {:5.2f} {} {}\n'.format(process[0], process[1], process[2], process[3])) return display_list @@ -103,32 +99,27 @@ def show_list_by_cpu(python_only=False): def make_window(): layout = [[sg.Text('Python Process Killer - Choose one or more processes', size=(45, 1), font=('Helvetica', 15), text_color='yellow')], - [sg.Listbox(values=[' '], size=(130, 30), select_mode=sg.SELECT_MODE_EXTENDED, font=('Courier', 10), key='-PROCESSES-', expand_x=True, expand_y=True)], + [sg.Listbox(values=[' '], size=(100, 20), select_mode=sg.SELECT_MODE_EXTENDED, font=('Courier', 10), key='-processes-')], [sg.Text('Click refresh once or twice.. once for list, second to get CPU usage')], - [sg.Text('Filter by typing name', font='ANY 14'), sg.Input(size=(15, 1), font='any 14', key='-FILTER-', enable_events=True), - sg.Checkbox('Show only Python processes', default=True, enable_events=True, key='-PYTHON ONLY-')], + [sg.Text('Filter by typing name', font='ANY 14'), sg.Input(size=(15, 1), font='any 14', key='-filter-')], [sg.Button('Sort by Name', ), sg.Button('Sort by % CPU', button_color=('white', 'DarkOrange2')), - sg.Button('Show Open Files', button_color=('white', 'dark green')), sg.Button('Kill Selected', button_color=('white', 'red'), bind_return_key=True), sg.Button('Kill All', button_color='red on white'), sg.Button('Kill All & Exit', button_color='red on white'), - sg.Exit(button_color=('white', 'sea green')), sg.Sizegrip()]] + sg.Exit(button_color=('white', 'sea green'))]] window = sg.Window('Python Process Killer', layout, keep_on_top=True, auto_size_buttons=False, default_button_element_size=(12, 1), return_keyboard_events=True, - resizable=True, - right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_EXIT, finalize=True) - window.bind('', 'Kill Selected') - window.set_min_size(window.size) + return window -def kill_all(python_only=True): - processes_to_kill = show_list_by_name(python_only=python_only) +def kill_all(): + processes_to_kill = show_list_by_name() for proc in processes_to_kill: pid = int(proc[0:5]) try: @@ -139,18 +130,15 @@ def kill_all(python_only=True): def main(silent=False): if silent: - kill_all(python_only=True) + kill_all() sg.popup_auto_close('Killed everything....', 'This window autocloses') sys.exit() # ---------------- Create Form ---------------- sg.theme('Dark Grey 9') - sg.set_options(icon=icon) - window = make_window() - current_display_list = display_list = show_list_by_name(window['-PYTHON ONLY-'].get()) - window['-PROCESSES-'].update(display_list) + display_list = show_list_by_name() + window['-processes-'].update(display_list) name_sorted = True - # ---------------- main loop ---------------- while True: # --------- Read and update window -------- @@ -164,13 +152,13 @@ def main(silent=False): # --------- Do Button Operations -------- if event == 'Sort by Name': - window['-PROCESSES-'].update(show_list_by_name(values['-PYTHON ONLY-'])) + window['-processes-'].update(show_list_by_name()) name_sorted = True elif event.startswith('Kill'): if event.startswith('Kill All'): - processes_to_kill = show_list_by_name(values['-PYTHON ONLY-']) + processes_to_kill = show_list_by_name() else: - processes_to_kill = values['-PROCESSES-'] + processes_to_kill = values['-processes-'] for proc in processes_to_kill: pid = int(proc[0:5]) try: @@ -179,43 +167,24 @@ def main(silent=False): except Exception as e: if event.endswith('Selected'): # only show the error if trying to kill only 1 process sg.popup_no_wait('Error killing process', e, auto_close_duration=2, auto_close=True, keep_on_top=True) - current_display_list = show_list_by_name(values['-PYTHON ONLY-']) if name_sorted else show_list_by_cpu(values['-PYTHON ONLY-']) - window['-PROCESSES-'].update(current_display_list) + window['-processes-'].update(show_list_by_name() if name_sorted else show_list_by_cpu()) if event.endswith('Exit'): break elif event == 'Sort by % CPU': - window['-PROCESSES-'].update(show_list_by_cpu(values['-PYTHON ONLY-'])) + window['-processes-'].update(show_list_by_cpu()) name_sorted = False - elif event == 'Show Open Files': - for proc in values['-PROCESSES-']: - pid = int(proc[0:5]) - parent = psutil.Process(pid) - file_list = parent.open_files() - out = '' - for f in file_list: - out += f'{f}\n' - sg.popup_scrolled(out, non_blocking=True, keep_on_top=True,size=(100,30)) - elif event == '-PYTHON ONLY-': # if checkbox changed - current_display_list = show_list_by_name(values['-PYTHON ONLY-']) if name_sorted else show_list_by_cpu(values['-PYTHON ONLY-']) - window['-PROCESSES-'].update(current_display_list) - elif event == '-FILTER-': # was a typed character - # display_list = window['-PROCESSES-'].get_list_values() - display_list = current_display_list + else: # was a typed character if display_list is not None: new_output = [] for line in display_list: - if values['-FILTER-'] in line.lower(): + if values['-filter-'] in line.lower(): new_output.append(line) - window['-PROCESSES-'].update(new_output) - elif event == 'Edit Me': - sg.execute_editor(__file__) + window['-processes-'].update(new_output) window.close() if __name__ == "__main__": - icon = b'iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAFLklEQVR4nO2ZW2xURRjHfzNnz9meXnYplHKtIhKEAgoEabUgKARBQTQ8+mLi5dXERIJPhMREownhyQfii8+aKKCCRIPRQiGEi3IRuSXc5dbSbbvdc5vxYUvAsmfP6bKtmuwvOS87s9/3/We++WbOHKhQoUKFChVKR4Q1fP3T3k1Jy5rluu5IxhOKZVk4rnvitWVtGwu1J4r8d0WyqqpVyFCtI4plJXFcdxIwVCHacZwcrutiGgkMwwCthynMEIQgCAK8wEdrDWgnrGuxGcl3MAz2nDzM2WuXQBpljTMSFTBtQhNLm+dFdo0WIg32nztJ+5H9YJoxnOv8yhNlSEnPY9G8VpbPXoCKijOOPdNIgGlFC9EaWVuNdj2065VBjMj7joF8SE/30BohJaPfWEl1SzP4QdlMx6F8QrwAu2Um1S3NpFa1IOvrQEUlRPkoj5BAYTSkSa9dBFpjNjVSt3wBBP83IVqTerkVs6kR/1Y32vWoXTYf89HxI5ZiDy/ED0g2T6H2hfmo3iy3t+6g/+hZEmPSpNY8C4aEEdh+4pUEpfIjKwbp1hphJxm17jlkrU33tnaco2fQjkvVrClUL5xJtuME/Yf+BLOAq0AV32T9IPY6ixaiNUZDmsRjExCJQd0Dhf30DJLNU3AvXKfn+wNgmbhnr9C75wjptYtJvdJG7tRFtOP+sxwrTWJcPcJOhorRvo9RX5dvjyjlkUK06zNq3VIaGtqwVAFjIi8os2Mvwa07YJkQKHp+OIg9fzrJJ5qoXfIUPd/tB2vAnR+QmNhA44bXSTSkQlPPRVF7zkVnfEgW38OiZ0QIgkwfvt+L1AWEGAbOmUtk9528lz6GJLjZRebbDsa8vZq6lS1kD58muHEnv2akIL22DbNxFH5nBt3vFjyH+1qheo1YG2ukEGEluPPlz9w+dhASBUZFgA5UPpfvd2gmyHYcp6a1GXv+dFKrWun6Yhe4PvbCGdS0ziLI9HFry1e456+CUeAc53v0zFmAeGlqZL2IV7UChfZ8tF/g8fyB89WgURMCnfPo3taO6slSu/hJrOlNiJok6VcXI+wkPT8ewjl1Ea11cdsxiCfk7iEw9An5nylxTl2k95ffkHU2qdXPkFrThvX4JJzzV+nZfRASRnHbMYlXfktGAJqeXQew507LP3Omol2PzPZ2VGcmXxzKQPnOWmEYEv9aJ5mdBxBCICyT/sOnyR74o/DeUiLDLwTANOj79XdyZy6j+vrp/qY9vxmW451lgGFOrQGEQGdzZLbvw5rcgHfhr/zaKCMjIwTATJA7do7c8fNlFwExhfhBAJ5X5PIoJnePInFTyvPyvmMQKcT1fdYtXMLzM+bCSF8NKc3oVBrX90lEFIZIIUorpjVOQo5vKlt8Q0Epha+iZyVeaqkAYhj7NwkXIrBtuxpZ6AwUhdZ4IVetpmWVVHaTVhLHdeyw9mIzsrk/29fk+N6Qneb6c2Nvdna/jxgUsdZ67Oj0p1V21c2h2lS+D3AprH1YVu9b6z+eXD+u/mIhIV3Xux75/JMNl8vtc1j2kXGNdSKQ8sEU0ppxjXXDMnglG/1gy2ezlTJbpSFNNei9WgjRiNYbC80IQmzSWt+4/2cpJSpQnonu+PC9d06UEk9JQtZv3jpLCHYnq+yJd0+4g+MtttgH67trw8nlrkgpV3z07psnhxpTSaklpFhRU5ua6DoOhFwvJ0LuibXWA58IHrBKTV1qUl9v5kVgZIRIoS/5nrvT90I/V5SElAIpdGhlqlChQoUK/zn+BhjXF7IsC7cbAAAAAElFTkSuQmCC' - if len(sys.argv) == 2 and sys.argv[1] == 'silent': main(silent=True) else: - main(silent=False) \ No newline at end of file + main(silent=False) diff --git a/DemoPrograms/Demo_pyfiglet.pyw b/DemoPrograms/Demo_pyfiglet.pyw new file mode 100644 index 000000000..6560bf3cd --- /dev/null +++ b/DemoPrograms/Demo_pyfiglet.pyw @@ -0,0 +1,164 @@ +import PySimpleGUI as sg +import sys +import pyfiglet + +""" + Demo pyfiglet integration + + '##:::::'##:'##::::'##::::'###::::'########::::'####::'######:: + ##:'##: ##: ##:::: ##:::'## ##:::... ##..:::::. ##::'##... ##: + ##: ##: ##: ##:::: ##::'##:. ##::::: ##:::::::: ##:: ##:::..:: + ##: ##: ##: #########:'##:::. ##:::: ##:::::::: ##::. ######:: + ##: ##: ##: ##.... ##: #########:::: ##:::::::: ##:::..... ##: + ##: ##: ##: ##:::: ##: ##.... ##:::: ##:::::::: ##::'##::: ##: + . ###. ###:: ##:::: ##: ##:::: ##:::: ##:::::::'####:. ######:: + :...::...:::..:::::..::..:::::..:::::..::::::::....:::......::: + :::'###:::::::'########:'####::'######:::'##:::::::'########:'########::'#######:: + ::'## ##:::::: ##.....::. ##::'##... ##:: ##::::::: ##.....::... ##..::'##.... ##: + :'##:. ##::::: ##:::::::: ##:: ##:::..::: ##::::::: ##:::::::::: ##::::..:::: ##:: + '##:::. ##:::: ######:::: ##:: ##::'####: ##::::::: ######:::::: ##:::::::: ###::: + #########:::: ##...::::: ##:: ##::: ##:: ##::::::: ##...::::::: ##::::::: ##.:::: + ##.... ##:::: ##:::::::: ##:: ##::: ##:: ##::::::: ##:::::::::: ##:::::::..:::::: + ##:::: ##:::: ##:::::::'####:. ######::: ########: ########:::: ##:::::::'##::::: + ..:::::..:::::..::::::::....:::......::::........::........:::::..::::::::..:::::: + + + Adapted from code originally from this fantastic repository: + https://github.com/nycynik/ascii-font-processor + Thank you nycynik for a fantastic headstart + + If you are running PySimpleGUI before verion 4.35.0.11, then you'll get an error + message saying there is a problem with: bound method Multiline.__del__ + It's because a newer parm is used in this code. It'll all still work just fine with this error. + + This demo has an interesting little trick. If the window is resized, then it + will use the new size of the Multiline element to compute the numiber of characters + wide the Multiline has to work with. This number is passed to the figlet renderer. + + + ____________________________________ + ______ + / / , , + ---/------/__-------__-----------__- + / / ) / (_ ` / (_ ` + _/______/___/_/___(__)_____/___(__)_ + + + ___________________________________________________________ + _____ __ __ _ _____ ______ + / ' / / ) / / ' / + ----__-------/__--------/----/--------/------/__------/---- + / ) / / / --, / / / + _(___(_____/________ _/_ __(____/___/____/_/____ ___/______ + + + + Copyright 2021 PySimpleGUI +""" + + +DEFAULT_FONT = 'nancyj-fancy' + +def change_theme(location): + layout = [[sg.Text(f'Current theme {sg.theme()}')], + [sg.Listbox(values=sg.theme_list(), size=(20, 20), key='-LIST-', enable_events=True)], + [sg.OK(), sg.Cancel()]] + + window = sg.Window('Look and Feel Browser', layout, location=location, keep_on_top=True) + while True: # Event Loop + event, values = window.read() + if event in (sg.WIN_CLOSED, 'Exit', 'OK', 'Cancel'): + break + window.close() + + if event == 'OK' and values['-LIST-']: + sg.theme(values['-LIST-'][0]) + sg.user_settings_set_entry('-theme-', values['-LIST-'][0]) + return values['-LIST-'][0] + return None + + + +def draw_text(font, text, width=80): + """Simple wrapper for the main draw function""" + + return pyfiglet.Figlet(font=font, width=width).renderText(text) + +def make_window(): + selected_font = DEFAULT_FONT + LINE_LENGTH = 100 + MULTILINE_FONT = ('Courier', 12) + fonts = pyfiglet.FigletFont.getFonts() + sg.theme_background_color(sg.theme_input_background_color()) + sg.theme_text_element_background_color(sg.theme_input_background_color()) + column_left = [[sg.Table(headings=['Font Name'], values=fonts, key='-FONT-LIST-', + col_widths=[40], num_rows=30, enable_events=True), sg.VerticalSeparator(pad=((5, 5), 0))]] + try: + mline_input = sg.Multiline('PySimpleGUI', size=(40,3), key='-TEXT-TO-SHOW-', no_scrollbar=True, enable_events=True, focus=True) + except Exception as e: + mline_input = sg.Multiline('PySimpleGUI', size=(40,3), key='-TEXT-TO-SHOW-', enable_events=True, focus=True) + + column_right = [[sg.Text("Font Name:", size=(10,1)), sg.Input(selected_font, size=(12,1), key='-FONT-NAME-')], + [sg.Text("Text:", size=(10,1)), mline_input, sg.T('Font size for display below'), sg.Combo(list(range(4,20)), 12, enable_events=True, k='-FONT-SIZE-')], + [sg.Multiline(size=(LINE_LENGTH, 20), key='-OUTPUT-', border_width=0, font=MULTILINE_FONT, expand_x=True, expand_y=True, pad=(40,40), )], + [sg.B('Copy to Clipboard'), sg.B('Change Theme')],] + + layout = [[sg.Column(column_left, expand_y=False, expand_x=False), sg.Column(column_right, expand_x=False, expand_y=False,k='-COL R-')], + [sg.Button('Exit', right_click_menu=sg.MENU_RIGHT_CLICK_DISABLED), sg.T('PySimpleGUI ver ' + sg.version.split(' ')[0] + ' tkinter ver ' + sg.tclversion_detailed + ' Python ver ' + sys.version, font='Default 8', pad=(0,0))],] + layout[-1].append(sg.Sizegrip()) + + window = sg.Window('psg-figlet', layout, resizable=True, finalize=True, right_click_menu=['_', ['Edit Me', 'Copy', 'Exit']], icon=icon) + + window['-COL R-'].expand(True, True, True) + # window['-OUTPUT-'].expand(True, True, False) + # window['-FONT-LIST-'].expand(False, False, False) + window['-OUTPUT-'].update(draw_text(selected_font, 'PySimpleGUI').strip()) + return window + +def main(): + window = make_window() + selected_font = DEFAULT_FONT + LINE_LENGTH = 100 + MULTILINE_FONT = ('Courier', 12) + fonts = pyfiglet.FigletFont.getFonts() + + while True: # Event Loop + event, values = window.read() + # print(event,values) + if event == sg.WIN_CLOSED or event == 'Exit': + break + if event == '-FONT-SIZE-': + MULTILINE_FONT = (MULTILINE_FONT[0], values['-FONT-SIZE-']) + window['-OUTPUT-'].update(font=MULTILINE_FONT) + window.refresh() + elif event == '-FONT-LIST-': + # first one is the selected, no multi-select allowed. + selected_font = fonts[values['-FONT-LIST-'][0]] + window['-FONT-NAME-'].update(selected_font) + elif event == 'Edit Me': + sg.execute_editor(__file__) + if event in ('Show', '-TEXT-TO-SHOW-', '-FONT-SIZE-', '-FONT-LIST-'): + text = values['-TEXT-TO-SHOW-'] + if text.strip() == '': + text = selected_font.strip() + # fancy way of detecting the size of the multiline so the window can be resized + # line_length = window["-OUTPUT-"].get_size()[0] // sg.Text.char_width_in_pixels(MULTILINE_FONT) + line_length = window["-OUTPUT-"].get_size()[0] // sg.tkinter.font.Font(font=MULTILINE_FONT).measure('A') + window['-OUTPUT-'].update(draw_text(selected_font, text, line_length).rstrip()) + if event.startswith('Copy'): + sg.clipboard_set(window['-OUTPUT-'].get()) + elif event == 'Change Theme': + if change_theme(window.current_location()): + window.close() + window = make_window() + window.close() + +if __name__ == "__main__": + # sg.theme('Dark red') + sg.theme(sg.user_settings_get_entry('-theme-', sg.theme())) + # sg.theme('Dark Gray 13') + # sg.theme_input_background_color('#36393F') + # sg.theme_background_color('#36393F') + # sg.theme_input_text_color('white') + icon = b'iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAMAAAC5zwKfAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAH+UExURf/YAL2gAJB5AMysAP7XAG5dAAAAAAcFAEM4AHxpAPHMALKWACUfABQQAJiAAH9rAEA2AMurAO7JAFJFAMqrACQeACMdALWZAAsJAPbQAKGIAMipAKKJAJqCALebAGtaAAoIAD0zAG9eABgUAEs/AFVIAJV+AHhlAFFEABwXACchAMeoAOC9AKaMAGFSAOzHAAQDAPvUALGVAFlLANCwAN68ADAoAOfDAIl0ACojALOXALqdAGlYALibADcuAJZ/AJ6FAHZjANOyAFNGAA8MADEpAEQ5AAkHAHpnANi2AKyRAAYFAPzVAIBsAEo+AFBDAI95ABANANa1ACAbAPTOAPLMAOTBAE1BACwlABsWACskAEI3AFpMAHFfAIhzAMGjAGVVAAEAAEE3AGNTAKuQAPjSAH1pAB4ZAPPNAK2SAMCiAMWmAN27AIt1APXPACghACEbAL+hAA4LAFRHAHdkAJuDAMmqACYgAEk9AFxNAIFtAI54AI13AAwKAKqQAE9CANKxAKeNAObCAK6TAGxbANy6AHtoAMSmAD81AF1OANW0APnSAOPAAGZWAKmPAO3IAOXBAFhKADoxAOK/AO/KAGBRAIx2ABYSABEOAAUEAJJ7AGRUAHBeAHJgAJyEALmcAFdJAIZxANGxAKOKAAMCADsxACIcALaaAL6gAOG+AFD17/gAAAAJcEhZcwAADsMAAA7DAcdvqGQAAALDSURBVFhH7df5W0xhFAfwS3VHUkpMqQYZ00Ixxq5FIYxMaLFEUhTJMhGFyDItpkRMdtm3/9Lcc78z7oy7vvc+jx/M55fe855zvs/TU93ucAkJ/8acuUk4WSI5hed527zU+ajNSlsQzhOkZ+DGnIWIE2Rm4ZLdomxkibJxzWzxEiSBHfescnIRFLUUHTZ5SJHIR4tJAUKkHOixWIaMGMvRZJC0AhkxCtFlsBIRsZzoMlglJriKiktKxSNBl8FqMWCNcC4rX+sUS34dNVm4xYD1KDnPBqo3ojRsE63zm1EKtmzdxvPbURhWIQZWooSq6h04GZYhBtagNK9WDNyJ0rxdlLcblQXqKHAPKgvspcB9qMzzUh5fhdK8/ZRXfwCleT4KbEBlgYMUeAiVBQ5ToHW/hY2U14TKpOaWliOpFBj3h8zg6LHjcf843aWtJ062nSpoL0vGjBGnkSKro6nzzNkuTOrTjVVl585jVJcibCmrxaQ+PdhSdgGT+vRiS1FJMyb1uYg1RZcwqNNlrMlIv+K08f4+DEY04quSq9iWqLvWf73CK36ffz10bvBtOMkT36IHqgdvpty67RgSila05IXfk+/cxVkbvTOoj/uFkeF7qDTQ/7tMFPLuCyNh/Q9woeYhjao/+ztpRhDw4krRCD0JR1HJG6MscKXhVl5voTA0jkrBI0qKsvuCaMSZ8FTaacKt/qSepKEY9sdTT9CNeDo1bUOXz8OdglGMxXnWXZOT9XyC40Ij+Y6ZAdwKXmBRyUvMyXv1GocozYdUHwZ1msGaijcY1eUtllS9w7AO77GioRjjmnxY0CT9FK3CwKvHbD12VPg/YFiX4DjWFH0MYVSvTzKPZYkhjBkQUvnZTH/GkDGTPunnwD8G2zHA4EvDV6RE5Lo86DHq8gS+Rd6xOr4HfuDapODPntnysV+oEhIS/jsc9xvWwm7SqLETuAAAAABJRU5ErkJggg==' + main() \ No newline at end of file diff --git a/DemoPrograms/LICENSE.txt b/DemoPrograms/LICENSE.txt deleted file mode 100644 index d688c9b82..000000000 --- a/DemoPrograms/LICENSE.txt +++ /dev/null @@ -1,588 +0,0 @@ -PySimpleGUI License Agreement - -Version 1.0, Last updated: January 17, 2024 - -This PySimpleGUI License Agreement (the "Agreement") governs the use, -reproduction, distribution, modification and all other exploitation of -PySimpleGUI. The Agreement is made by and between PySimpleSoft, Inc. -("Licensor") and the person or legal entity using PySimpleGUI hereunder -("Licensee" and, together with Licensor, the "Parties"). - -If you are using PySimpleGUI on behalf of a legal entity such as an employer, -then "Licensee" means that legal entity, and you represent and warrant that you -have the authority and capacity to enter into this Agreement on behalf of -Licensee. - -"PySimpleGUI" consists of the following materials: -* the PySimpleGUI software library, version 5.0 or later (the "Library"); -* the PySimpleGUI Library documentation (the "Documentation"); -* sample programs demonstrating use of the Library (the "Demo Programs"); and -* utility programs relating to PySimpleGUI (the "Utilities"). - -PySimpleGUI may require you to obtain and use third-party software which is -distributed under separate license terms. Any such software is not considered -"PySimpleGUI" hereunder and is subject solely to such separate license terms. - -PySimpleGUI is made available to Licensee pursuant to this Agreement for the -purpose of (1) pursuant to Section 1.2, enabling Authorized Developers to use -the Library in connection with developing Licensee Applications, and to use the -Documentation, the Demo Programs and the Utilities in connection therewith; and -(2) pursuant to Section 1.3, enabling End Users of the Licensee Applications to -execute the Library as a dependency of the Licensee Applications; each as -defined and more fully set forth herein and subject to the limitations set -forth herein. - -Licensor agrees to license PySimpleGUI to Licensee only in accordance with the -terms of this Agreement. By using PySimpleGUI, Licensee agrees to be bound by -the terms of this Agreement. If you do not agree to the terms of this -Agreement, you may not copy, use, distribute, modify or otherwise attempt to -exploit PySimpleGUI. - -Licensee acknowledges that Licensor may from time to time update or modify this -Agreement, by publishing a new version of this Agreement on Licensor's website. -Licensee may continue to use the version of PySimpleGUI that it previously -obtained under the prior version of this Agreement, but any version of -PySimpleGUI received or used thereafter shall be subject to the updated version -of this Agreement. - -Accordingly, in consideration of the mutual covenants set forth herein, the -receipt and sufficiency of which is hereby acknowledged, the Parties agree as -follows. - -1. Authorized Developers; License Grants; Limitations. - -1.1. Definitions. As used herein: - -* "Authorized Developer" means any individual person who has registered on - Licensor's site at https://PySimpleGUI.com (the "Site") to develop one or - more of Licensee's own applications which make use of the Library as a - dependency in accordance with Section 1.5 (collectively, "Licensee - Applications") and is either (1) a Hobbyist Developer; or (2) a Commercial - Developer who has purchased an active PySimpleGUI paid license hereunder, in - effect at the time of development, which is fully paid up pursuant to Section - 3. - -* "Hobbyist Developer" means any individual who uses PySimpleGUI for - development purposes solely for either or both of the following: (1) personal - (e.g., not on behalf of an employer or other third party), Non-Commercial - purposes; or (2) Non-Commercial educational or learning purposes (1 and 2 - together, the "Permitted No-cost Purposes"). - -* "Commercial Developer" means any individual who uses PySimpleGUI for - development purposes who is not a Hobbyist Developer. - -As used in this Section 1, "Non-Commercial" means use which is both (1) not on -behalf or for the benefit of any company or other organization; and (2) not -involving the receipt of any commercial advantage or monetary compensation. If -you have questions about whether your contemplated use is "Non-Commercial," -please contact us at license@pysimplegui.com. - -For the avoidance of doubt: - -* Only Authorized Developers (e.g., Hobbyist Developers and Commercial - Developers who satisfy the requirements for Authorized Developers) may use - PySimpleGUI for development purposes. - -* A Hobbyist Developer may not use PySimpleGUI for any development purpose - other than the Permitted No-cost Purposes. - -* Only Commercial Developers may use PySimpleGUI to develop Licensee - Applications for any commercial purpose; for the benefit of, on behalf of or - on computer hardware belonging to an employing company or other organization; - or for commercial educational purposes, such as the development of a paid - training course. - -If you have questions about whether your contemplated Licensee Application -would be a Permitted No-cost Purpose subject to a Hobbyist Developer license, -please contact us at license@pysimplegui.com. - -1.2. Development License Grants. Subject to the terms and conditions of this -Agreement: - -1.2.1. Library. Licensor grants Licensee a limited, personal, revocable, -non-exclusive, non-sublicensable, non-transferable license during the Term (1) -for its Authorized Developers to internally install, use, reproduce and modify -the Library to develop Licensee Applications; and (2) to redistribute the -Library to recipients of its Licensee Applications ("End Users"); provided, -that such redistribution may not include publishing the source code of the -Library (in modified or unmodified form) in a publicly accessible website or -repository or in other publicly accessible form. - -1.2.2. Documentation. Licensor grants Licensee a limited, personal, revocable, -non-exclusive, non-sublicensable, non-transferable license during the Term for -its Authorized Developers to internally access, use, and reproduce a reasonable -number of copies of the Documentation for the sole purpose of facilitating the -use of the Library by Licensee Applications in accordance with this Agreement. -For the avoidance of doubt, Licensee may not modify or redistribute the -Documentation. - -1.2.3. Demo Programs. Licensor grants Licensee a limited, personal, revocable, -non-exclusive, non-sublicensable, non-transferable license during the Term to -install, use, execute, reproduce and modify the Demo Programs, and to -incorporate modified portions of the Demo Programs into the Licensee -Applications; provided, that (1) the Demo Programs may not be used for any -purposes other than in connection with the use of the Library; and (2) the Demo -Programs may not be (individually or as a whole) redistributed in unmodified -form or as a program with substantially similar functionality to the Demo -Programs. - -1.2.4. Utilities. Licensor grants Licensee a limited, personal, revocable, -non-exclusive, non-sublicensable, non-transferable license during the Term to -install, use, execute, reproduce and modify the Utilities, but not to -distribute or publish the Utilities or any modified version. - -1.2.5. Developer Key Required. The licenses granted in this Section 1.2 may -only be exercised by Authorized Developers within the period of time during -which each such Authorized Developer has a then-active Developer Key pursuant -to Section 3. Licensor may in its discretion permit recipients of PySimpleGUI -to make limited use of it for a limited trial period without a Developer Key. - -1.2.6. Limitations for Hobbyist Developers. For Hobbyist Developers, the -licenses granted in this Section 1.2 may only be exercised for the Permitted -No-cost Purposes. - -1.2.7. Limitations on Modification of the Library. Licensee's right to modify -the Library pursuant to this Section 1.2 is further limited as follows: (a) -Licensee may not modify or extend the Library or take any other action which -has the effect of enabling bypass of the Library's protection mechanisms -requiring the use of valid Developer Keys or Distribution Keys. (b) Licensee -explicitly acknowledges and agrees that Licensor's digital signature of the -Library is only applicable to the unmodified Library as made available by -Licensor, and that any modifications to the Library will result in Licensor's -digital signature no longer applying to the modified version. - -1.2.8. Limitations on Distribution of the Library. Licensee's right to -distribute the Library (in modified or unmodified form) pursuant to this -Section 1.2 is subject to Licensee (a) including the applicable proprietary -notices set forth in Section 2.2; and (b) including the PySimpleGUI Flow-Down -License Terms set forth in Exhibit A in the license terms that Licensee uses to -distribute the Licensee Application. - -1.2.9. Distribution Keys. Commercial Developers may obtain from Licensor a -PySimpleGUI distribution key ("Distribution Key") through the Authorized -Developer's Site account and utilizing the Distribution Key through the -protection mechanism made available in the Library to permit distribution to -End Users. The Commercial Developer may use its Distribution Key to enable End -Users to install and execute the Licensee Applications, including the Library -incorporated therein, without requiring each recipient to obtain a Developer -Key or be limited to a trial period as described in Section 1.2.5. Licensee -shall be responsible for all activities occurring under Distribution Keys -obtained by its Authorized Developers and for the compliance with this -Agreement of all Licensee Applications using such Distribution Keys. - -1.3. Run-time End User License Grant. Subject to the terms and conditions of -this Agreement, Licensor grants Licensee a limited, personal, revocable, -non-exclusive, non-sublicensable, non-transferable license during the Term to -install and execute the Library solely for it and its employee End Users to -internally use the corresponding Licensee Applications with which the Library -is distributed. For the avoidance of doubt, the license set forth in this -Section 1.3 does not permit modification, external redistribution, integration -of the Library with other software, or any other use of the Library (for -development purposes or otherwise) except solely as distributed with the -unmodified Licensee Applications; any such activities are permitted only by -Authorized Developers and only to the extent permitted by Section 1.2. If the -Licensee Application does not include a valid Distribution Key from a -Commercial Developer, then the period of use of the Library within the Licensee -Application will be limited to a trial period for any End User who does not -register as an Authorized Developer hereunder. - -1.4. License Restrictions. The licenses granted to Licensee hereunder are -expressly made subject to the following limitations: except as expressly -permitted herein, Licensee may not (and shall not permit any third party to): -(a) copy all or any portion of PySimpleGUI; (b) modify or translate -PySimpleGUI; (c) reverse engineer, decompile or disassemble the Software, in -whole or in part, except solely to the extent permitted under applicable law; -(d) create derivative works based on PySimpleGUI; (e) publicly display or -publish PySimpleGUI; (f) rent, lease, sublicense, sell, distribute, assign, -transfer, or otherwise permit access to PySimpleGUI to any third party; (g) -bypass or work around any requirements for license keys, limitations on access, -or obfuscation or security mechanisms incorporated into PySimpleGUI; (h) use -PySimpleGUI for illegal or otherwise harmful purposes, including without -limitation harassment, defamation, creation or delivery of unsolicited emails -or spam, infringement of third party intellectual property rights or other -third party rights, or distribution of viruses, worms, malware or other harmful -or destructive software; (i) incorporate PySimpleGUI or any portion thereof -into any software that purports to subject it to open source software or -similar license terms, including any prior version of PySimpleGUI (modified or -unmodified) which was previously distributed under such licenses; or (j) -exercise any other right to PySimpleGUI not expressly granted in this -Agreement. - -1.5. Licensee Application Prohibitions. Notwithstanding anything else in -this Agreement, Licensee shall ensure that Licensee Applications (a) do not -have the purpose, intent or functionality of enabling End Users to make further -use of PySimpleGUI for their own development purposes or to carry out any -activities otherwise restricted or prohibited hereunder; (b) do not have a -substantially similar purpose to PySimpleGUI; (c) do not enable End Users to -interact, integrate or otherwise develop user interfaces via direct or indirect -access to PySimpleGUI's functionality; and (d) are not intended or designed for -use in high-risk use cases that could reasonably result in death, severe bodily -injury, or other physical property or environmental damage. - -1.6. No Use with Earlier Versions of PySimpleGUI. For the avoidance of -doubt, no portions of PySimpleGUI distributed under this Agreement may be used -in connection with, or in any way incorporated with or into, any versions of -the PySimpleGUI library prior to version 5.0 that have been distributed under -the GNU Lesser General Public License. - -1.7. Additional Grant to Python Software Foundation. With regards to -portions of PySimpleGUI that Licensor uploads to PyPI, Python Software -Foundation ("PSF") may copy and redistribute such portions unmodified on PyPI -in the form provided by Licensor, with no further action required by PSF. - -1.8. Prohibition on Training Artificial Intelligence. As used herein, -"Artificial Intelligence" means a system or model that is intended to generate -or identify patterns in code or data, produce insights or correlations, or make -predictions, recommendations, or decisions; in each case, where the system or -model operates using machine learning, neural networks, large language models, -or other approaches designed to approximate cognitive abilities. Licensee shall -not (and shall not directly or indirectly permit or assist anyone else to) use -PySimpleGUI, or any part thereof, to train an Artificial Intelligence that is -offered to third parties on a commercial basis or as part of a larger -commercial offering. The preceding sentence does not prohibit use of -PySimpleGUI in conjunction with an Artificial Intelligence in other ways, such -as developing a front-end user interface. - -2. Intellectual Property Ownership; Notices. - -2.1. Licensor Ownership. PySimpleGUI is not sold to Licensee, and all rights -not expressly granted herein are reserved to Licensor. As between the parties, -Licensor and its licensors own all right, title and interest in and to -PySimpleGUI and any part thereof, including, without limitation, all -copyrights, patents, trademarks, trade secrets or other intellectual property -or proprietary rights. - -2.2. Proprietary Notices. Licensee shall not modify or remove any copyright -or patent notices or other proprietary notices or markings from any portion of -PySimpleGUI (whether modified or unmodified) without Licensor's explicit -written permission. Licensor shall ensure that any Licensee Applications that -use the Library include a notice in the following form within the Licensee -Application as well as any corresponding Licensee documentation or materials: - -For unmodified versions of PySimpleGUI: - - This product includes PySimpleGUI (https://PySimpleGUI.com). PySimpleGUI - is Copyright (c) PySimpleSoft, Inc. and/or its licensors. Use of - PySimpleGUI is subject to the license terms available at - https://PySimpleGUI.com/eula - - PYSIMPLEGUI IS PROVIDED "AS IS," WITHOUT ANY WARRANTIES, WHETHER EXPRESS OR - IMPLIED. PYSIMPLESOFT DISCLAIMS ALL IMPLIED WARRANTIES, INCLUDING WITHOUT - LIMITATION THE IMPLIED WARRANTIES OF NONINFRINGEMENT, TITLE, - MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - -For modified versions of PySimpleGUI: - - This product includes a modified version of PySimpleGUI - (https://PySimpleGUI.com). PySimpleGUI is Copyright (c) PySimpleSoft, Inc. - and/or its licensors. Use of PySimpleGUI is subject to the license terms - available at https://PySimpleGUI.com/eula - - PYSIMPLEGUI IS PROVIDED "AS IS," WITHOUT ANY WARRANTIES, WHETHER EXPRESS OR - IMPLIED. PYSIMPLESOFT DISCLAIMS ALL IMPLIED WARRANTIES, INCLUDING WITHOUT - LIMITATION THE IMPLIED WARRANTIES OF NONINFRINGEMENT, TITLE, - MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - -If the Licensee Application or the corresponding Licensee documentation or -materials include Licensee's copyright notices or other third parties' notices, -then Licensee shall include the above notice together with such notices. - -2.3. Licensor Marks. As between the parties hereto, all of Licensor's -trademarks and service marks applicable to Licensor or PySimpleGUI -(collectively, the "Licensor Marks") are the sole property of Licensor and/or -its licensors. Subject to the terms and conditions of this Agreement, Licensor -grants Licensee a limited, personal, revocable, non-exclusive, -non-sublicensable, non-transferable license to use the Licensor Mark -"PySimpleGUI" in connection with Licensee's permitted distribution of the -Library hereunder. The license set forth in this Section 2.3 is explicitly -conditioned on (a) Licensee's agreement not to challenge Licensor's ownership -of the Licensor Marks at any time during the Term or thereafter; (b) Licensee -ensuring that any modified version of the Library is clearly and prominently -noted as such; (c) Licensee complying with all trademark usage guidelines and -requirements that Licensor may publish from time to time; and (d) Licensee -immediately correcting incorrect usage of the Licensor Marks upon request from -Licensor. Licensee shall immediately cease usage of the Licensor Marks upon -written notice thereof from Licensor. All goodwill arising from use of the -Licensor Marks shall inure to the benefit of Licensor. - -3. Developer Keys; Fees and Payments. - -3.1. Developer Keys. In order to develop Licensee Applications pursuant to -Section 1.2 (and subject to any limited trial period usage as may be permitted -by Licensor from time to time), each Authorized Developer shall obtain a -PySimpleGUI developer license key ("Developer Key") by registering on the Site -as set forth therein. Each Developer Key is personal to the specific Authorized -Developer, and Licensee shall not permit Authorized Developers to disclose, -share or reuse Developer Keys. For the avoidance of doubt, any disclosure, -sharing or reuse of a Developer Key by Licensee's Authorized Developers, -whether or not authorized by Licensee, shall be a material breach permitting -termination of this Agreement pursuant to Section 8.3. Developer Keys are -Licensor's Confidential Information pursuant to Section 5. Developer Keys are -limited to a specified time period (which shall be annual from the start date -of the Developer Key, unless otherwise explicitly stated by Licensor). Upon the -expiration of a Developer Key, the corresponding Authorized Developer may no -longer use the Developer Key and must obtain a new Developer Key from the Site -in order to continue using PySimpleGUI for development purposes pursuant to -Section 1.2. - -3.2. Fees for Commercial Developer Keys; Taxes. Before obtaining each -Developer Key for a Commercial Developer, Licensee shall pay to Licensor the -corresponding fees as stated on the Site and using the payment mechanism made -available on the Site. All payments shall be made in United States dollars. All -amounts payable by Licensee hereunder are exclusive of taxes and similar -assessments, and Licensee is responsible for all sales, use, and excise taxes, -and any other similar taxes of any kind imposed by any federal, state, or local -governmental or regulatory authority on any amounts payable by Licensee -hereunder, excluding any taxes imposed on Licensor's income. - -3.3. Accuracy of Registration Details. Licensee represents and warrants that -(a) all information provided by it and its Authorized Developers when -registering for Developer Keys shall be truthful, accurate, complete and not -misleading, and (b) it and its Authorized Developers shall not misrepresent -their use of PySimpleGUI as qualifying for a Hobbyist Developer Key if their -use does not satisfy the Permitted No-cost Purposes. - -4. Support and Updates. - -4.1. Support. Licensor has no obligation hereunder to provide support to -Licensee or its Authorized Developers. Authorized Developers may submit -Feedback (as defined in Section 5.4) consisting of issues and bug reports to -the PySimpleGUI software repository as described on the Site or in the -Documentation. Licensor may in its sole discretion address such issues or bug -reports in current or future versions of PySimpleGUI, but has no obligation to -do so. - -4.2. Updates. Licensor has no obligation hereunder to make available updated -versions of PySimpleGUI. In the event that Licensor elects to make available an -updated version of PySimpleGUI, then Authorized Developers with a then-active -Developer Key may download and use the updated version, and the updated version -shall be included in the definition of "PySimpleGUI" thereafter for purposes of -this Agreement. - -5. Confidentiality; Feedback. - -5.1. Confidential Information. Licensee acknowledges that portions of -PySimpleGUI and certain other materials are confidential as provided herein. -"Confidential Information" means any and all information, whether provided in -writing, orally, visually, electronically or by other means, related to -Licensor's or its licensors' services and/or business that, whether it -constitutes a Trade Secret or not, is treated as confidential or secret by -Licensor (that is, it is the subject of efforts by Licensor that are reasonable -under the circumstances to maintain its secrecy), including, but not limited -to, (i) Trade Secrets as defined below; (ii) any and all other information -which is disclosed by Licensor to Licensee orally, electronically, visually, or -in a document or other tangible form which is either identified as or should be -reasonably understood to be confidential and/or proprietary; and, (iii) any -notes, extracts, analysis, or materials prepared by Licensee which are copies -of or derivative works of Licensor's or its licensors' proprietary or -confidential information from which the substance of Confidential Information -can be inferred or otherwise understood. Confidential Information shall not -include information which Licensee can clearly establish by written evidence: -(a) already is lawfully known to or independently developed by Licensee without -access to the Confidential Information or Trade Secrets, (b) is disclosed by -Licensor in non-confidential published materials, (c) is generally known to the -public, or (d) is rightfully obtained from any third party without any -obligation of confidentiality. - -5.2. Trade Secrets. As used herein, "Trade Secrets" means all non-public -information whether tangible or intangible related to Licensor's and its -licensors' services or business that (i) derives economic value, actual or -potential, from not being generally known to or readily ascertainable by other -persons who can obtain economic value from its disclosure or use; and (ii) is -the subject of efforts that are reasonable under the circumstances to maintain -its secrecy, which may include, without limitation, (a) marking any information -reduced to tangible form clearly and conspicuously with a legend identifying -its confidential or trade secret nature; (b) identifying any oral communication -as confidential or secret immediately before, during, or after such oral -communication; or (c) otherwise treating such information as confidential. - -5.3. Licensee Obligations. Licensee agrees not to disclose Confidential -Information or Trade Secrets to any third party and will protect and treat all -Confidential Information and Trade Secrets with the highest degree of care. -Except as otherwise expressly provided in this Agreement, Licensee will not use -or make any copies of Confidential Information or Trade Secrets, in whole or in -part, without the prior written authorization of Licensor. Licensee may -disclose Confidential Information or Trade Secrets if required by statute, -regulation, or order of a court of competent jurisdiction, provided that -Licensee provides Licensor with prior notice, discloses only the minimum -Confidential Information or Trade Secrets required to be disclosed, and -cooperates with Licensor in taking appropriate protective measures. These -obligations shall continue for three (3) years following termination or -expiration of this Agreement with respect to Confidential Information that does -not rise to the level of a Trade Secret and shall continue for Trade Secrets so -long as they remain Trade Secrets. - -5.4. Feedback. As used herein, "Feedback" means any comments, questions, -suggestions, issues, bug reports, or related feedback provided by Licensee to -Licensor relating to PySimpleGUI, including, without limitation, suggesting or -recommending changes to any part of PySimpleGUI, or new features or -functionality relating thereto. All Feedback is, and will be treated as, -non-confidential and non-proprietary, regardless of any markings Licensee may -apply to it. Licensee hereby assigns to Licensor all right, title, and interest -in, and Licensor is free to use without any attribution or compensation to -Licensee, any ideas, know-how, concepts, techniques, or other intellectual -property and proprietary rights contained in the Feedback, whether or not -patentable, for any purpose whatsoever, including but not limited to, -developing, manufacturing, having manufactured, licensing, marketing, and -selling, directly or indirectly, products and services using such Feedback. To -the extent the foregoing assignment of rights, title and interest in and to -Feedback is prohibited by applicable law, Licensee hereby grants Licensor a -non-exclusive, perpetual, irrevocable, royalty-free, fully paid-up, worldwide -license (including the right to sublicense through multiple tiers) to (a) fully -use, practice and exploit those non-assignable rights, title and interest, -including, but not limited to, the right to use, reproduce, adapt, publicly -perform, publicly display, modify, prepare derivative works, publish, transmit -and distribute Feedback, or any portion thereof, in any form, medium or -distribution method now known or hereafter existing, known or developed, for -any purpose, and to develop, manufacture, have manufactured, license, market, -and sell, directly or indirectly, products and services using Feedback; and (b) -authorize any such use by others of Feedback, or any portion thereof, in the -same manner. - -6. NO LICENSOR WARRANTIES; LIABILITY. - -6.1. DISCLAIMER OF WARRANTIES. PYSIMPLEGUI IS PROVIDED TO LICENSEE "AS IS". -LICENSOR DOES NOT MAKE ANY, AND HEREBY SPECIFICALLY DISCLAIMS ANY, -REPRESENTATIONS, ENDORSEMENTS, GUARANTEES, OR WARRANTIES, EXPRESS OR IMPLIED, -RELATED TO PYSIMPLEGUI INCLUDING, BUT NOT LIMITED TO, ANY IMPLIED WARRANTY OF -MERCHANTABILITY, TITLE, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT OF -INTELLECTUAL PROPERTY RIGHTS. Licensee acknowledges that Licensor does not -guarantee compatibility between PySimpleGUI and any future versions thereof, -and that Licensor makes no commitments as to future development, availability, -release or licensing of any current or future versions of PySimpleGUI. Licensee -will have sole responsibility for the adequate protection and backup of -Licensee's software, data and equipment used with PySimpleGUI. The entire risk -as to the quality and performance of PySimpleGUI and any obligation with -respect to service and support is borne by Licensee. Licensee understands that -Software hosted by Licensor for evaluation purposes may not be secure or -stable. Licensee waives any claim against Licensor which may arise as a result -of Licensee's breach of the foregoing. This Agreement does not grant Licensee -any right to any maintenance, services, including without limitation, any -support, enhancement, modification, bug fix or update to the Software, and -Licensor is under no obligation to provide or inform Licensee of any such -maintenance or services. - -6.2. DISCLAIMER OF LIABILITY. LICENSEE EXPLICITLY AGREES THAT, TO THE -MAXIMUM EXTENT PERMITTED BY LAW, LICENSOR SHALL NOT BE LIABLE UNDER ANY LEGAL -THEORY FOR ANY DAMAGES SUFFERED IN CONNECTION WITH THE USE OF THE SOFTWARE, -INCLUDING BUT NOT LIMITED TO ANY LOST PROFITS, LOST SAVINGS OR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE OR CONSEQUENTIAL DAMAGES, -WHETHER RESULTING FROM IMPAIRED OR LOST DATA, SOFTWARE OR COMPUTER FAILURE, THE -LICENSEE APPLICATIONS, OR ANY OTHER CAUSE, BY LICENSEE OR ANY OTHER THIRD -PARTY, EVEN IF IT HAS BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. -LICENSEE HEREBY EXPRESSLY RELEASES LICENSOR FROM ANY AND ALL LIABILITY OR -RESPONSIBILITY TO ANY DAMAGE CAUSED, DIRECTLY OR INDIRECTLY, TO LICENSEE OR ANY -THIRD PARTY AS A RESULT OF THE USE OF THE SOFTWARE OR THE INSTALLATION THEREOF -INTO LICENSEE'S COMPUTER ENVIRONMENT. IN THE EVENT THAT THE DISCLAIMERS OF -LIABILITY SET FORTH HEREIN ARE HELD TO BE UNENFORCEABLE, THE PARTIES AGREE THAT -UNDER NO CIRCUMSTANCES SHALL LICENSOR'S AGGREGATE LIABILITY HEREUNDER OR IN -CONNECTION WITH THIS AGREEMENT EXCEED THE AMOUNTS PAID BY LICENSEE TO LICENSOR -IN THE 12 MONTHS PRECEDING THE DATE THAT A CLAIM FIRST ACCRUES. LICENSEE SHALL -BRING ANY CLAIM AGAINST LICENSOR WITHIN 12 MONTHS OF THE DATE THAT THE CLAIM -FIRST ACCRUES, AND HEREBY WAIVES ANY CLAIMS THAT IT DOES NOT BRING WITHIN SUCH -TIME PERIOD. - -6.3. Essential Terms. THIS SECTION 6 IS AN ESSENTIAL BASIS OF LICENSOR'S -DECISION TO OFFER PYSIMPLEGUI, AND SHALL APPLY REGARDLESS OF THE LEGAL THEORY -UPON WHICH DAMAGES MAY BE CLAIMED; REGARDLESS OF WHETHER A PARTY KNEW OR SHOULD -HAVE KNOWN OF THE POSSIBILITY OF SUCH DAMAGES; AND REGARDLESS OF WHETHER THE -FOREGOING LIMITATIONS OF LIABILITY CAUSE ANY REMEDY TO FAIL IN ITS ESSENTIAL -PURPOSE. - -7. Indemnification. Licensee agrees to defend, indemnify and hold Licensor -and its directors, officers, employees and representatives harmless for any -claims, expenses, losses, costs, fees (including attorneys' fees) or damages of -any sort resulting from (a) Licensee's breach of this Agreement; (b) Licensee's -use of PySimpleGUI or exercise of the license rights granted hereunder; or (c) -the Licensee Applications, or Licensee's or any third party's use thereof. - -8. Term and Termination. - -8.1. Term. This Agreement shall commence on the date on which Licensee -downloads PySimpleGUI or otherwise obtains a copy of PySimpleGUI, and shall -continue thereafter until terminated as set forth herein. - -8.2. Termination by Licensee. Licensee may terminate this Agreement with -written notice to Licensor, effective upon Licensee destroying all copies of -PySimpleGUI in its possession and refraining from receiving or downloading -further copies. - -8.3. Termination for Licensee's Breach. This limited License will -immediately terminate without notice if Licensee fails to comply with any -obligation of this Agreement. Additionally, if Licensor reasonably suspects -that Licensee has breached the Agreement, then Licensor may deliver written -notice of the suspected breach to Licensee, and the Agreement shall -automatically terminate 10 days following the date of such notice unless -Licensee cures the breach to Licensor's satisfaction within such period. - -8.4. Effect of Termination; Survival. Upon termination of this Agreement for -any reason, the licenses granted to Licensee with respect to PySimpleGUI shall -immediately terminate and Licensee hereby undertakes to: (i) immediately cease -to use, distribute or otherwise exploit any part of PySimpleGUI or any modified -version thereof; and (ii) promptly destroy and delete any copy of PySimpleGUI -installed or copied by Licensee. Sections 2.1, 2.3, 3, 5-7, 8.4, 9 and 10 will -survive termination of this Agreement indefinitely in accordance with their -terms. - -9. Assignment; Governing Law. The License is personal to Licensee and -Licensee agrees not to transfer, sublicense, lease, rent, or assign their -rights under this Agreement, and any such attempt shall be null and void. -Licensor may assign, transfer, or sublicense this Agreement or any rights or -obligations thereunder at any time in its sole discretion. This Agreement shall -be governed by and construed in accordance with the laws of the State of North -Carolina and the United States of America without regard to the conflicts of -laws provisions thereof. The parties expressly exclude the United Nations -Convention on Contracts for the International Sale of Goods from this -Agreement. All actions arising out of or in connection with this Agreement -shall be brought in the state or federal courts residing in Durham, North -Carolina, United States of America, and both parties hereby irrevocably consent -to the exclusive jurisdiction of such courts and waive any objections as to -venue or inconvenience of forum. - -10. Miscellaneous. No changes or modifications to this Agreement by -Licensee or waivers of any provision of this Agreement by Licensor shall be -effective unless evidenced in a writing referencing this Agreement and signed -for and on behalf of Licensor. The failure of Licensor to enforce its rights -under this Agreement at any time for any period shall not be construed as a -waiver of such rights. There are no third party beneficiaries hereunder. This -Agreement constitutes the entire agreement between the parties regarding the -subject matter hereof and supersede all negotiations, conversations, or -discussions between or among the parties relating to the subject matter of this -Agreement. Neither Party relied on any promises or representations, written or -oral, of the other party in forming this Agreement, except for those expressly -contained herein. In the event that any provision of this Agreement shall be -determined to be unenforceable, that provision will be limited or eliminated to -the minimum extent necessary so that this Agreement shall otherwise remain in -full force and effect and enforceable. Licensee may not distribute, download or -otherwise export or re-export PySimpleGUI or any underlying technology except -in full compliance with this Agreement, United States laws and regulations and -any other applicable laws and regulations. Licensee represents and warrants -that it and its Authorized Developers are not located in, under control of, or -a national or resident of any country where exercise of the licenses granted -hereunder would not comply with all such laws or regulations. It is agreed that -because of the proprietary nature of PySimpleGUI, Licensor's remedies at law -for a breach by the Licensee of its obligations under this Agreement may be -inadequate and that Licensor will, in the event of such breach, be entitled to, -in addition to any other remedy available to it, equitable relief, including -injunctive relief, without the posting of any bond and in addition to all other -remedies provided under this Agreement or available at law. - -Exhibit A - -PySimpleGUI Flow-Down License Terms - -This product (the "Product") includes PySimpleGUI (https://PySimpleGUI.com) or -a version of PySimpleGUI modified by the person or legal entity that provided -you with this product ("Provider"). - -PySimpleGUI is Copyright (c) PySimpleSoft, Inc. and/or its licensors. - -Use of PySimpleGUI is subject to the license terms available at -https://PySimpleGUI.com/eula, including all limitations of liability and other -terms set forth therein. By using the Product, you acknowledge and agree that -PySimpleSoft has no obligation or liability to you regarding the operation, -support or maintenance of PySimpleGUI or of the Product. PYSIMPLEGUI IS -PROVIDED "AS IS," WITHOUT ANY WARRANTIES, WHETHER EXPRESS OR IMPLIED. -PYSIMPLESOFT DISCLAIMS ALL IMPLIED WARRANTIES, INCLUDING WITHOUT LIMITATION THE -IMPLIED WARRANTIES OF NONINFRINGEMENT, TITLE, MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE. diff --git a/DemoPrograms/PyDroid3/Demo_Game_Frontend_Battleship.py b/DemoPrograms/PyDroid3/Demo_Game_Frontend_Battleship.py new file mode 100644 index 000000000..e1b11f56a --- /dev/null +++ b/DemoPrograms/PyDroid3/Demo_Game_Frontend_Battleship.py @@ -0,0 +1,32 @@ +import tkinter +import PySimpleGUI as sg +from random import randint + +def Battleship(): + sg.change_look_and_feel('Dark Blue 3') + MAX_ROWS = MAX_COL = 8 + + # Start building layout with the top 2 rows that contain Text elements + layout = [[sg.Text('BATTLESHIP', font='Default 12')], + [sg.Text(size=(15,1), key='-MESSAGE-', font='any 8')]] + # Add the board, a grid a buttons + layout += [[sg.Button(str('O'), size=(1, 1), pad=(0,0), border_width=0, font='any 8',key=(row,col)) for col in range(MAX_COL)] for row in range(MAX_ROWS)] + # Add the exit button as the last row + layout += [[sg.Button('Exit', button_color=('white', 'red'))]] + + window = sg.Window('Battleship', layout, location=(0,0)) + + while True: # The Event Loop + event, values = window.read() + print(event, values) + if event in (None, 'Exit'): + break + if randint(1,10) < 5: # simulate a hit or a miss + window[event].update('H', button_color=('white','red')) + window['-MESSAGE-'].update('Hit') + else: + window[event].update('M', button_color=('white','black')) + window['-MESSAGE-'].update('Miss') + window.close() + +Battleship() diff --git a/DemoPrograms/PyDroid3/Demo_OpenCV_4_Line_Program.py b/DemoPrograms/PyDroid3/Demo_OpenCV_4_Line_Program.py new file mode 100644 index 000000000..9efba4c65 --- /dev/null +++ b/DemoPrograms/PyDroid3/Demo_OpenCV_4_Line_Program.py @@ -0,0 +1,6 @@ +import tkinter +import cv2, PySimpleGUI as sg +USE_CAMERA = 0 # change to 1 for front facing camera +window, cap = sg.Window('Demo Application - OpenCV Integration', [[sg.Image(filename='', key='image')], ], location=(0, 0), grab_anywhere=True), cv2.VideoCapture(USE_CAMERA) +while window(timeout=20)[0] is not None: + window['image'](data=cv2.imencode('.png', cap.read()[1])[1].tobytes()) diff --git a/DemoPrograms/PyDroid3/Demo_OpenCV_Webcam_ASCII.py b/DemoPrograms/PyDroid3/Demo_OpenCV_Webcam_ASCII.py new file mode 100644 index 000000000..0905756eb --- /dev/null +++ b/DemoPrograms/PyDroid3/Demo_OpenCV_Webcam_ASCII.py @@ -0,0 +1,99 @@ +import tkinter +import cv2 +from PIL import Image +import numpy as np +import PySimpleGUI as sg + +font_size = 3 +CAMERA_FRONT = 1 +CAMERA_REAR = 0 + +USE_CAMERA = CAMERA_REAR + +""" +Interesting program that shows your webcam's image as ASCII text. Runs in realtime, producing a stream of +images so that it is actually animated ASCII text. Wild stuff that came about from a post on Reddit of all +places. The software bits that turn the image into ASCII text were shamelessly taken from this gist: +https://gist.github.com/cdiener/10491632 +Brilliant work to have pulled off so much with so little Numpy +What's remarkable about this program is that the animation is created by updating individual Text Elements going +down the window, one line at a time, every time through the loop. That's 48 lines of text every time. Rough +timing shows an animation of more than 10 fps when running any of the PySimpleGUI ports. +Also added onto this are a spinner and a slider. They do essentially the same thing, enable a pair of parameters +to be modified on the fly. + +You need PySimpleGUI installed as well as OpenCV. Both are easily installed via pip: +pip install PySimpleGUI +pip install opencv-python + +On Linux / Mac use pip3 instead of pip +""" + +# The magic bits that make the ASCII stuff work shamelessly taken from https://gist.github.com/cdiener/10491632 +chars = np.asarray(list(' .,:;irsXA253hMHGS#9B&@')) +SC, GCF, WCF = .1, 1, 7/4 + +sg.change_look_and_feel('Dark Black 1') # make it look cool + +# ---------------- A Quick Little Window - to get camera to use ---------------- +win_get_cam = sg.Window('Which Camera?',[[sg.T('Which camera?')],[sg.Combo(['Front', 'Rear'], default_value='Rear', font='any 20')],[sg.T(size=(1,2))], [sg.Ok()]], location=(0,0)) +event, values = win_get_cam.read() +win_get_cam.close() +if event != 'Ok': exit() +USE_CAMERA = [CAMERA_FRONT, CAMERA_REAR][values[0]=='Rear'] + +# ------------ Turn on camera and read a frame to find the number of lines of text needed --------- +cap = cv2.VideoCapture(USE_CAMERA) # Setup camera using your camera choice + +ret, frame = cap.read() + +img = Image.fromarray(frame) # create PIL image from frame +GCF = 1.0 # Variable user will be able to change +WCF = 1.75 # Variable user will be able to change +# ----------- magic that coverts the image to ascii ----------- +S = (round(img.size[0] * SC * WCF), round(img.size[1] * SC)) +img = np.sum(np.asarray(img.resize(S)), axis=2) +img -= img.min() +img = (1.0 - img / img.max()) ** GCF * (chars.size - 1) + +# Find number of lines of text that will be drawn so can create the right size of window +NUM_LINES = len(chars[img.astype(int)]) +LINE_LENGTH = len("".join(chars[img.astype(int)][0])) +print(f'line len = {LINE_LENGTH}') +# ------------- define the window layout ------------- +# number of lines of text elements. Depends on cameras image size and the variable SC (scaller) + +layout = [[sg.Text(i, size=(LINE_LENGTH, 1), font=('Courier', font_size), pad=(0, 0), key='-OUT-'+str(i))] for i in range(NUM_LINES)] + +layout += [[sg.Button('Exit', size=(5, 1)), + sg.Text('GCF', size=(4, 1)), + sg.Spin([round(i, 2) for i in np.arange(0.1, 20.0, 0.1)], initial_value=1, key='-SPIN-GCF-', size=(5, 1), font='any 20')], + [sg.Text('WCF', size=(4, 1)), + sg.Slider((1, 4), resolution=.05, default_value=1.75, orientation='h', key='-SLIDER-WCF-', size=(15, 30))]] + +# ------------- create the window ------------- +window = sg.Window('Demo Application - OpenCV Integration', layout, location=(0,0)) + +# ---===--- Event LOOP Read and display frames, operate the GUI --- # +while True: + + event, values = window.read(timeout=0) + if event in ('Exit', None): + break + # Read image from capture device (camera) + ret, frame = cap.read() + + img = Image.fromarray(frame) # create PIL image from frame + GCF = float(values['-SPIN-GCF-']) + WCF = values['-SLIDER-WCF-'] + # More magic that coverts the image to ascii + S = (round(img.size[0] * SC * WCF), round(img.size[1] * SC)) + img = np.sum(np.asarray(img.resize(S)), axis=2) + img -= img.min() + img = (1.0 - img / img.max()) ** GCF * (chars.size - 1) + + # "Draw" the image in the window, one line of text at a time! + for i, r in enumerate(chars[img.astype(int)]): + window['-OUT-'+str(i)].update("".join(r)) + +window.close() diff --git a/DemoPrograms/PyDroid3/Demo_OpenCV_Webcam_Minimal.py b/DemoPrograms/PyDroid3/Demo_OpenCV_Webcam_Minimal.py new file mode 100644 index 000000000..9396135b2 --- /dev/null +++ b/DemoPrograms/PyDroid3/Demo_OpenCV_Webcam_Minimal.py @@ -0,0 +1,44 @@ +import tkinter +import PySimpleGUI as sg +import cv2 + +""" + Demo of using OpenCV to show your webcam in a GUI window. + This demo will run on tkinter, Qt, and Web(Remi). The web version flickers at the moment though + To exit, right click and choose exit. If on Qt, you'll have to kill the program as there are no right click menus + in PySimpleGUIQt (yet). +""" + +CAMERA_FRONT = 1 +CAMERA_REAR = 0 + +sg.change_look_and_feel('Dark Black 1') + +# ---------------- A Quick Little Window - to get camera to use ---------------- +win_get_cam = sg.Window('Which Camera?',[[sg.T('Which camera?')],[sg.Combo(['Front', 'Rear'], default_value='Rear', font='any 20')],[sg.T(size=(1,2))], [sg.Ok()]], location=(0,0)) +event, values = win_get_cam.read() +win_get_cam.close() +if event != 'Ok': exit() +USE_CAMERA = [CAMERA_FRONT, CAMERA_REAR][values[0]=='Rear'] + + +# define the window layout +layout = [[sg.Image(filename='', key='-IMAGE-', tooltip='Right click for exit menu')], + [sg.Exit()],] + +# create the window and show it without the plot +window = sg.Window('Demo Application - OpenCV Integration', layout, location=(0,0), + no_titlebar=True, grab_anywhere=True, + right_click_menu=['&Right', ['E&xit']], ) # if trying Qt, you will need to remove this right click menu + +# ---===--- Event LOOP Read and display frames, operate the GUI --- # +cap = cv2.VideoCapture(USE_CAMERA) # Setup the OpenCV capture device (webcam) +while True: + event, values = window.read(timeout=20) + if event in ('Exit', None): + break + ret, frame = cap.read() # Read image from capture device (camera) + imgbytes=cv2.imencode('.png', frame)[1].tobytes() # Convert the image to PNG Bytes + window['-IMAGE-'].update(data=imgbytes) # Change the Image Element to show the new image + +window.close() diff --git a/DemoPrograms/README.md b/DemoPrograms/README.md deleted file mode 100644 index abfb00885..000000000 --- a/DemoPrograms/README.md +++ /dev/null @@ -1,121 +0,0 @@ -

-

- -

psgdemos

-

A PySimpleGUI Application

-

- -PySimpleGUI Demo Programs - -Demonstrate PySimpleGUI features. Are you trying to figure out a -specific feature of PySimpleGUI? There's a demo for that! The Demo -Browser let's you search through hundreds of demo programs to find -ones that demonstrates the features you need. - - - - - -

- - - -## Features - -* Hundreds of programs to demonstrate any feature. -* Run demos with a single click. -* Browse demo names and search demo source code. -* Integrates with your favorite editor. -* Advanced features for advanced users. - -## Installation - -### Using PIP with PyPI - -The latest official release of PySimpleGUI products can be found on PyPI. To pip install the demo applications from PyPI, use this command - -#### If you use the command `python` on your computer to invoke Python (Windows): - -`pip install --upgrade psgdemos` - -#### If you use the command `python3` on your computer to invoke Python (Linux, Mac): - -`pip3 install --upgrade psgdemos` - -### Using PIP with GitHub - -You can also pip install the Demo Programs that are in the PySimpleGUI GitHub account. The GitHub version has bug fixes and new programs/features that have not yet been released to PyPI. These same Demo Programs can be found in the `psgdemos` repo. To directly pip install from that repo: - -#### If you use the command `python` on your computer to invoke Python (Windows): - -```bash -python -m pip install --upgrade https://github.com/PySimpleGUI/psgdemos/zipball/main -``` - -#### If you use the command `python3` on your computer to invoke Python (Linux, Mac): - -```bash -python3 -m pip install --upgrade https://github.com/PySimpleGUI/psgdemos/zipball/main -``` - -## Usage - -Once installed, launch psgdemos by typing the following in your command line: - -`psgdemos` - -## Create a Windows 1-Click Shortcut - -psgdemos is your first stop when implementing any new feature for your -application. To keep psgdemos at your fingertips, on Windows, you can -create a shortcut that keeps psgdemos as close as a single click. Use -the [`psgshortcut` application](https://pypi.org/project/psgshortcut/) -app to make such shortcuts. You can then add the shortcut to your -desktop or taskbar and launch psgdemos with a single click! - -To do this, follow these steps: - -1. `pip install psgshortcut` -1. Open a command window (We promise, it's the last time you'll need the command line for psgdemos) -2. Type `where psgdemos` -3. Copy the resulting line into psgshortcut first input -4. Run psgdemos by typing `psgdemos` in your command window -5. Right click and choose "File Location" -6. Copy the file location results, but change the extension from .py to .ico and paste into the Icon file input of the shortcut maker -7. Click "Create Shortcut" - -These steps create a shortcut in the same folder as the target file. You can now move this shortcut file to any place you want (like to your desktop). Double-click the shortcut and your program will launch. - -## License & Copyright - -Copyright 2023-2024 PySimpleSoft, Inc. and/or its licensors. - -This is a free-to-use "Utility" and is licensed under the -PySimpleGUI License Agreement, a copy of which is included in the -license.txt file and also available at https://pysimplegui.com/eula. - -Please see Section 1.2 of the license regarding the use of this Utility, -and see https://pysimplegui.com/faq for any questions. - - -## Contributing - -We are happy to receive issues describing bug reports and feature -requests! If your bug report relates to a security vulnerability, -please do not file a public issue, and please instead reach out to us -at issues@PySimpleGUI.com. - -We do not accept (and do not wish to receive) contributions of -user-created or third-party code, including patches, pull requests, or -code snippets incorporated into submitted issues. Please do not send -us any such code! Bug reports and feature requests should not include -any source code. - -If you nonetheless submit any user-created or third-party code to us, -(1) you assign to us all rights and title in or relating to the code; -and (2) to the extent any such assignment is not fully effective, you -hereby grant to us a royalty-free, perpetual, irrevocable, worldwide, -unlimited, sublicensable, transferrable license under all intellectual -property rights embodied therein or relating thereto, to exploit the -code in any manner we choose, including to incorporate the code into -PySimpleGUI and to redistribute it under any terms at our discretion. diff --git a/DemoPrograms/db.sqlite3 b/DemoPrograms/db.sqlite3 new file mode 100644 index 000000000..d6e38fae2 Binary files /dev/null and b/DemoPrograms/db.sqlite3 differ diff --git a/DemoPrograms/default_icon.ico b/DemoPrograms/default_icon.ico new file mode 100644 index 000000000..1a41525ec Binary files /dev/null and b/DemoPrograms/default_icon.ico differ diff --git a/DemoPrograms/exampleGIF.gif b/DemoPrograms/exampleGIF.gif new file mode 100644 index 000000000..212b4a249 Binary files /dev/null and b/DemoPrograms/exampleGIF.gif differ diff --git a/DemoPrograms/logo200.png b/DemoPrograms/logo200.png new file mode 100644 index 000000000..a7177b7b6 Binary files /dev/null and b/DemoPrograms/logo200.png differ diff --git a/DemoPrograms/ping.py b/DemoPrograms/ping.py new file mode 100644 index 000000000..7422b9ce6 --- /dev/null +++ b/DemoPrograms/ping.py @@ -0,0 +1,606 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +""" + A pure python ping implementation using raw sockets. + + (This is Python 3 port of https://github.com/jedie/python-ping) + (Tested and working with python 2.7, should work with 2.6+) + + Note that ICMP messages can only be sent from processes running as root + (in Windows, you must run this script as 'Administrator'). + + Derived from ping.c distributed in Linux's netkit. That code is + copyright (c) 1989 by The Regents of the University of California. + That code is in turn derived from code written by Mike Muuss of the + US Army Ballistic Research Laboratory in December, 1983 and + placed in the public domain. They have my thanks. + + Bugs are naturally mine. I'd be glad to hear about them. There are + certainly word - size dependencies here. + + Copyright (c) Matthew Dixon Cowles, . + Distributable under the terms of the GNU General Public License + version 2. Provided with no warranties of any sort. + + Original Version from Matthew Dixon Cowles: + -> ftp://ftp.visi.com/users/mdc/ping.py + + Rewrite by Jens Diemer: + -> http://www.python-forum.de/post-69122.html#69122 + + Rewrite by George Notaras: + -> http://www.g-loaded.eu/2009/10/30/python-ping/ + + Enhancements by Martin Falatic: + -> http://www.falatic.com/index.php/39/pinging-with-python + + Enhancements and fixes by Georgi Kolev: + -> http://github.com/jedie/python-ping/ + + Bug fix by Andrejs Rozitis: + -> http://github.com/rozitis/python-ping/ + + Revision history + ~~~~~~~~~~~~~~~~ + May 1, 2014 + ----------- + Little modifications by Mohammad Emami + - Added Python 3 support. For now this project will just support + python 3.x + - Tested with python 3.3 + - version was upped to 0.6 + + March 19, 2013 + -------------- + * Fixing bug to prevent divide by 0 during run-time. + + January 26, 2012 + ---------------- + * Fixing BUG #4 - competability with python 2.x [tested with 2.7] + - Packet data building is different for 2.x and 3.x. + 'cose of the string/bytes difference. + * Fixing BUG #10 - the multiple resolv issue. + - When pinging domain names insted of hosts (for exmaple google.com) + you can get different IP every time you try to resolv it, we should + resolv the host only once and stick to that IP. + * Fixing BUGs #3 #10 - Doing hostname resolv only once. + * Fixing BUG #14 - Removing all 'global' stuff. + - You should not use globul! Its bad for you...and its not thread safe! + * Fix - forcing the use of different times on linux/windows for + more accurate mesurments. (time.time - linux/ time.clock - windows) + * Adding quiet_ping function - This way we'll be able to use this script + as external lib. + * Changing default timeout to 3s. (1second is not enought) + * Switching data syze to packet size. It's easyer for the user to ignore the + fact that the packet headr is 8b and the datasize 64 will make packet with + size 72. + + October 12, 2011 + -------------- + Merged updates from the main project + -> https://github.com/jedie/python-ping + + September 12, 2011 + -------------- + Bugfixes + cleanup by Jens Diemer + Tested with Ubuntu + Windows 7 + + September 6, 2011 + -------------- + Cleanup by Martin Falatic. Restored lost comments and docs. Improved + functionality: constant time between pings, internal times consistently + use milliseconds. Clarified annotations (e.g., in the checksum routine). + Using unsigned data in IP & ICMP header pack/unpack unless otherwise + necessary. Signal handling. Ping-style output formatting and stats. + + August 3, 2011 + -------------- + Ported to py3k by Zach Ware. Mostly done by 2to3; also minor changes to + deal with bytes vs. string changes (no more ord() in checksum() because + >source_string< is actually bytes, added .encode() to data in + send_one_ping()). That's about it. + + March 11, 2010 + -------------- + changes by Samuel Stauffer: + - replaced time.clock with default_timer which is set to + time.clock on windows and time.time on other systems. + + November 8, 2009 + ---------------- + Improved compatibility with GNU/Linux systems. + + Fixes by: + * George Notaras -- http://www.g-loaded.eu + Reported by: + * Chris Hallman -- http://cdhallman.blogspot.com + + Changes in this release: + - Re-use time.time() instead of time.clock(). The 2007 implementation + worked only under Microsoft Windows. Failed on GNU/Linux. + time.clock() behaves differently under the two OSes[1]. + + [1] http://docs.python.org/library/time.html#time.clock + + May 30, 2007 + ------------ + little rewrite by Jens Diemer: + - change socket asterisk import to a normal import + - replace time.time() with time.clock() + - delete "return None" (or change to "return" only) + - in checksum() rename "str" to "source_string" + + December 4, 2000 + ---------------- + Changed the struct.pack() calls to pack the checksum and ID as + unsigned. My thanks to Jerome Poincheval for the fix. + + November 22, 1997 + ----------------- + Initial hack. Doesn't do much, but rather than try to guess + what features I (or others) will want in the future, I've only + put in what I need now. + + December 16, 1997 + ----------------- + For some reason, the checksum bytes are in the wrong order when + this is run under Solaris 2.X for SPARC but it works right under + Linux x86. Since I don't know just what's wrong, I'll swap the + bytes always and then do an htons(). + + =========================================================================== + IP header info from RFC791 + -> http://tools.ietf.org/html/rfc791) + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |Version| IHL |Type of Service| Total Length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Identification |Flags| Fragment Offset | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Time to Live | Protocol | Header Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Source Address | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Destination Address | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Options | Padding | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + =========================================================================== + ICMP Echo / Echo Reply Message header info from RFC792 + -> http://tools.ietf.org/html/rfc792 + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Identifier | Sequence Number | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Data ... + +-+-+-+-+- + + =========================================================================== + ICMP parameter info: + -> http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xml + + =========================================================================== + An example of ping's typical output: + + PING heise.de (193.99.144.80): 56 data bytes + 64 bytes from 193.99.144.80: icmp_seq=0 ttl=240 time=127 ms + 64 bytes from 193.99.144.80: icmp_seq=1 ttl=240 time=127 ms + 64 bytes from 193.99.144.80: icmp_seq=2 ttl=240 time=126 ms + 64 bytes from 193.99.144.80: icmp_seq=3 ttl=240 time=126 ms + 64 bytes from 193.99.144.80: icmp_seq=4 ttl=240 time=127 ms + + ----heise.de PING Statistics---- + 5 packets transmitted, 5 packets received, 0.0% packet loss + round-trip (ms) min/avg/max/med = 126/127/127/127 + + =========================================================================== +""" + +#=============================================================================# +import argparse +import os +import sys +import socket +import struct +import select +import time +import signal + +__description__ = 'A pure python ICMP ping implementation using raw sockets.' + +if sys.platform == "win32": + # On Windows, the best timer is time.clock() + default_timer = time.clock +else: + # On most other platforms the best timer is time.time() + default_timer = time.time + +NUM_PACKETS = 3 +PACKET_SIZE = 64 +WAIT_TIMEOUT = 3.0 + +#=============================================================================# +# ICMP parameters + +ICMP_ECHOREPLY = 0 # Echo reply (per RFC792) +ICMP_ECHO = 8 # Echo request (per RFC792) +ICMP_MAX_RECV = 2048 # Max size of incoming buffer + +MAX_SLEEP = 1000 + + +class MyStats: + thisIP = "0.0.0.0" + pktsSent = 0 + pktsRcvd = 0 + minTime = 999999999 + maxTime = 0 + totTime = 0 + avrgTime = 0 + fracLoss = 1.0 + + +myStats = MyStats # NOT Used globally anymore. + +#=============================================================================# + + +def checksum(source_string): + """ + A port of the functionality of in_cksum() from ping.c + Ideally this would act on the string as a series of 16-bit ints (host + packed), but this works. + Network data is big-endian, hosts are typically little-endian + """ + countTo = (int(len(source_string)/2))*2 + suma = 0 + count = 0 + + # Handle bytes in pairs (decoding as short ints) + loByte = 0 + hiByte = 0 + while count < countTo: + if (sys.byteorder == "little"): + loByte = source_string[count] + hiByte = source_string[count + 1] + else: + loByte = source_string[count + 1] + hiByte = source_string[count] + try: # For Python3 + suma = suma + (hiByte * 256 + loByte) + except: # For Python2 + suma = suma + (ord(hiByte) * 256 + ord(loByte)) + count += 2 + + # Handle last byte if applicable (odd-number of bytes) + # Endianness should be irrelevant in this case + if countTo < len(source_string): # Check for odd length + loByte = source_string[len(source_string)-1] + try: # For Python3 + suma += loByte + except: # For Python2 + suma += ord(loByte) + + # Truncate suma to 32 bits (a variance from ping.c, which + suma &= 0xffffffff + # uses signed ints, but overflow is unlikely in ping) + + suma = (suma >> 16) + (suma & 0xffff) # Add high 16 bits to low 16 bits + suma += (suma >> 16) # Add carry from above (if any) + answer = ~suma & 0xffff # Invert and truncate to 16 bits + answer = socket.htons(answer) + + return answer + +#=============================================================================# + + +def do_one(myStats, destIP, hostname, timeout, mySeqNumber, packet_size, quiet=False): + """ + Returns either the delay (in ms) or None on timeout. + """ + delay = None + + try: # One could use UDP here, but it's obscure + mySocket = socket.socket( + socket.AF_INET, socket.SOCK_RAW, socket.getprotobyname("icmp")) + except socket.error as e: + print("failed. (socket error: '%s')" % e.args[1]) + raise # raise the original error + + my_ID = os.getpid() & 0xFFFF + + sentTime = send_one_ping(mySocket, destIP, my_ID, mySeqNumber, packet_size) + if sentTime == None: + mySocket.close() + return delay + + myStats.pktsSent += 1 + + recvTime, dataSize, iphSrcIP, icmpSeqNumber, iphTTL = receive_one_ping( + mySocket, my_ID, timeout) + + mySocket.close() + + if recvTime: + delay = (recvTime-sentTime)*1000 + if not quiet: + print("%d bytes from %s: icmp_seq=%d ttl=%d time=%d ms" % ( + dataSize, socket.inet_ntoa(struct.pack("!I", iphSrcIP)), icmpSeqNumber, iphTTL, delay) + ) + myStats.pktsRcvd += 1 + myStats.totTime += delay + if myStats.minTime > delay: + myStats.minTime = delay + if myStats.maxTime < delay: + myStats.maxTime = delay + else: + delay = None + print("Request timed out.") + + return delay + +#=============================================================================# + + +def send_one_ping(mySocket, destIP, myID, mySeqNumber, packet_size): + """ + Send one ping to the given >destIP<. + """ + #destIP = socket.gethostbyname(destIP) + + # Header is type (8), code (8), checksum (16), id (16), sequence (16) + # (packet_size - 8) - Remove header size from packet size + myChecksum = 0 + + # Make a dummy heder with a 0 checksum. + header = struct.pack( + "!BBHHH", ICMP_ECHO, 0, myChecksum, myID, mySeqNumber + ) + + padBytes = [] + startVal = 0x42 + # 'cose of the string/byte changes in python 2/3 we have + # to build the data differnely for different version + # or it will make packets with unexpected size. + if sys.version[:1] == '2': + bytes = struct.calcsize("d") + data = ((packet_size - 8) - bytes) * "Q" + data = struct.pack("d", default_timer()) + data + else: + for i in range(startVal, startVal + (packet_size-8)): + padBytes += [(i & 0xff)] # Keep chars in the 0-255 range + #data = bytes(padBytes) + data = bytearray(padBytes) + + # Calculate the checksum on the data and the dummy header. + myChecksum = checksum(header + data) # Checksum is in network order + + # Now that we have the right checksum, we put that in. It's just easier + # to make up a new header than to stuff it into the dummy. + header = struct.pack( + "!BBHHH", ICMP_ECHO, 0, myChecksum, myID, mySeqNumber + ) + + packet = header + data + + sendTime = default_timer() + + try: + # Port number is irrelevant for ICMP + mySocket.sendto(packet, (destIP, 1)) + except socket.error as e: + print("General failure (%s)" % (e.args[1])) + return + + return sendTime + +#=============================================================================# + + +def receive_one_ping(mySocket, myID, timeout): + """ + Receive the ping from the socket. Timeout = in ms + """ + timeLeft = timeout/1000 + + while True: # Loop while waiting for packet or timeout + startedSelect = default_timer() + whatReady = select.select([mySocket], [], [], timeLeft) + howLongInSelect = (default_timer() - startedSelect) + if whatReady[0] == []: # Timeout + return None, 0, 0, 0, 0 + + timeReceived = default_timer() + + recPacket, addr = mySocket.recvfrom(ICMP_MAX_RECV) + + ipHeader = recPacket[:20] + iphVersion, iphTypeOfSvc, iphLength, \ + iphID, iphFlags, iphTTL, iphProtocol, \ + iphChecksum, iphSrcIP, iphDestIP = struct.unpack( + "!BBHHHBBHII", ipHeader + ) + + icmpHeader = recPacket[20:28] + icmpType, icmpCode, icmpChecksum, \ + icmpPacketID, icmpSeqNumber = struct.unpack( + "!BBHHH", icmpHeader + ) + + if icmpPacketID == myID: # Our packet + dataSize = len(recPacket) - 28 + #print (len(recPacket.encode())) + return timeReceived, (dataSize+8), iphSrcIP, icmpSeqNumber, iphTTL + + timeLeft = timeLeft - howLongInSelect + if timeLeft <= 0: + return None, 0, 0, 0, 0 + +#=============================================================================# + + +def dump_stats(myStats): + """ + Show stats when pings are done + """ + print("\n----%s PYTHON PING Statistics----" % (myStats.thisIP)) + + if myStats.pktsSent > 0: + myStats.fracLoss = (myStats.pktsSent - + myStats.pktsRcvd)/myStats.pktsSent + + print("%d packets transmitted, %d packets received, %0.1f%% packet loss" % ( + myStats.pktsSent, myStats.pktsRcvd, 100.0 * myStats.fracLoss + )) + + if myStats.pktsRcvd > 0: + print("round-trip (ms) min/avg/max = %d/%0.1f/%d" % ( + myStats.minTime, myStats.totTime/myStats.pktsRcvd, myStats.maxTime + )) + + print("") + return + +#=============================================================================# + + +def signal_handler(signum, frame): + """ + Handle exit via signals + """ + dump_stats() + print("\n(Terminated with signal %d)\n" % (signum)) + sys.exit(0) + +#=============================================================================# + + +def verbose_ping(hostname, timeout=WAIT_TIMEOUT, count=NUM_PACKETS, + packet_size=PACKET_SIZE, path_finder=False): + """ + Send >count< ping to >destIP< with the given >timeout< and display + the result. + """ + signal.signal(signal.SIGINT, signal_handler) # Handle Ctrl-C + if hasattr(signal, "SIGBREAK"): + # Handle Ctrl-Break e.g. under Windows + signal.signal(signal.SIGBREAK, signal_handler) + + myStats = MyStats() # Reset the stats + + mySeqNumber = 0 # Starting value + + try: + destIP = socket.gethostbyname(hostname) + print("\nPYTHON PING %s (%s): %d data bytes" % + (hostname, destIP, packet_size)) + except socket.gaierror as e: + print("\nPYTHON PING: Unknown host: %s (%s)" % (hostname, e.args[1])) + print() + return + + myStats.thisIP = destIP + + for i in range(count): + delay = do_one(myStats, destIP, hostname, + timeout, mySeqNumber, packet_size) + + if delay == None: + delay = 0 + + mySeqNumber += 1 + + # Pause for the remainder of the MAX_SLEEP period (if applicable) + if (MAX_SLEEP > delay): + time.sleep((MAX_SLEEP - delay)/1000) + + dump_stats(myStats) + +#=============================================================================# + + +def quiet_ping(hostname, timeout=WAIT_TIMEOUT, count=NUM_PACKETS, + packet_size=PACKET_SIZE, path_finder=False): + """ + Same as verbose_ping, but the results are returned as tuple + """ + myStats = MyStats() # Reset the stats + mySeqNumber = 0 # Starting value + + try: + destIP = socket.gethostbyname(hostname) + except socket.gaierror as e: + return False + + myStats.thisIP = destIP + + # This will send packet that we dont care about 0.5 seconds before it starts + # acrutally pinging. This is needed in big MAN/LAN networks where you sometimes + # loose the first packet. (while the switches find the way... :/ ) + if path_finder: + fakeStats = MyStats() + do_one(fakeStats, destIP, hostname, timeout, + mySeqNumber, packet_size, quiet=True) + time.sleep(0.5) + + for i in range(count): + delay = do_one(myStats, destIP, hostname, timeout, + mySeqNumber, packet_size, quiet=True) + + if delay == None: + delay = 0 + + mySeqNumber += 1 + + # Pause for the remainder of the MAX_SLEEP period (if applicable) + if (MAX_SLEEP > delay): + time.sleep((MAX_SLEEP - delay)/1000) + + if myStats.pktsSent > 0: + myStats.fracLoss = (myStats.pktsSent - + myStats.pktsRcvd)/myStats.pktsSent + if myStats.pktsRcvd > 0: + myStats.avrgTime = myStats.totTime / myStats.pktsRcvd + + # return tuple(max_rtt, min_rtt, avrg_rtt, percent_lost) + return myStats.maxTime, myStats.minTime, myStats.avrgTime, myStats.fracLoss + +#=============================================================================# + + +def main(): + + parser = argparse.ArgumentParser(description=__description__) + parser.add_argument('-q', '--quiet', action='store_true', + help='quiet output') + parser.add_argument('-c', '--count', type=int, default=NUM_PACKETS, + help=('number of packets to be sent ' + '(default: %(default)s)')) + parser.add_argument('-W', '--timeout', type=float, default=WAIT_TIMEOUT, + help=('time to wait for a response in seoncds ' + '(default: %(default)s)')) + parser.add_argument('-s', '--packet-size', type=int, default=PACKET_SIZE, + help=('number of data bytes to be sent ' + '(default: %(default)s)')) + parser. add_argument('destination') + # args = parser.parse_args() + + ping = verbose_ping + # if args.quiet: + # ping = quiet_ping + ping('Google.com', timeout=1000) + # ping(args.destination, timeout=args.timeout*1000, count=args.count, + # packet_size=args.packet_size) + + +if __name__ == '__main__': + main() diff --git a/DemoPrograms/psgdemos.ico b/DemoPrograms/psgdemos.ico deleted file mode 100644 index 8eda664ef..000000000 Binary files a/DemoPrograms/psgdemos.ico and /dev/null differ diff --git a/DemoPrograms/psgdemos.py b/DemoPrograms/psgdemos.py deleted file mode 100644 index 329a6ec12..000000000 --- a/DemoPrograms/psgdemos.py +++ /dev/null @@ -1,1066 +0,0 @@ -''' -Copyright 2022-2024 PySimpleSoft, Inc. and/or its licensors. All rights reserved. - -Redistribution, modification, or any other use of PySimpleGUI or any portion thereof is subject -to the terms of the PySimpleGUI License Agreement available at https://eula.pysimplegui.com. - -You may not redistribute, modify or otherwise use PySimpleGUI or its contents except pursuant -to the PySimpleGUI License Agreement. -''' - -import os -import sys -import mmap, re -import warnings -import PySimpleGUI as sg - -version = '5.0.0' -__version__ = version.split()[0] - - -packages_with_weird_names = {'cv2':'opencv-python', - 'PIL':'pillow', - 'vlc':'python-vlc', - } - - -""" - PySimpleGUI Demo Program Browser - - Originaly written for PySimpleGUI Demo Programs, but expanded to - be a general purpose tool. Enable Advanced Mode in settings for more fun - - Use to filter and search your source code tree. - Then run or edit your files - - Filter the list of : - * Search using filename - * Searching within the programs' source code (like grep) - - The basic file operations are - * Edit a file in your editor - * Run a file - * Filter file list - * Search in files - * Run a regular expression search on all files - * Display the matching line in a file - - Additional operations - * Edit this file in editor - - Keeps a "history" of the previously chosen folders to easy switching between projects - - Versions: - 5.0.0 11-Feb-2024 The NEW Demo Browser for use with PySimpleGUI 5! - - Copyright 2021, 2022, 2023, 2024 PySimpleSoft Inc. -""" - -''' -MM""""""""`M oo dP -MM mmmmmmmM 88 -M' MMMM dP 88 .d8888b. -MM MMMMMMMM 88 88 88ooood8 -MM MMMMMMMM 88 88 88. ... -MM MMMMMMMM dP dP `88888P' -MMMMMMMMMMMM - -MM""""""""`M -MM mmmmmmmM -M' MMMM dP dP 88d888b. .d8888b. .d8888b. -MM MMMMMMMM 88 88 88' `88 88' `"" Y8ooooo. -MM MMMMMMMM 88. .88 88 88 88. ... 88 -MM MMMMMMMM `88888P' dP dP `88888P' `88888P' -MMMMMMMMMMMM -''' - -def get_file_list_dict(): - """ - Returns dictionary of files - Key is short filename - Value is the full filename and path - - :return: Dictionary of demo files - :rtype: Dict[str:str] - """ - python_only = not sg.user_settings_get_entry('-show all files-', False) - demo_path = get_demo_path() - demo_files_dict = {} - for dirname, dirnames, filenames in os.walk(demo_path): - for filename in filenames: - if python_only is not True or filename.endswith('.py') or filename.endswith('.pyw'): - fname_full = os.path.join(dirname, filename) - if filename not in demo_files_dict.keys(): - demo_files_dict[filename] = fname_full - else: - # Allow up to 100 dupicated names. After that, give up - for i in range(1, 100): - new_filename = f'{filename}_{i}' - if new_filename not in demo_files_dict: - demo_files_dict[new_filename] = fname_full - break - - return demo_files_dict - - -def get_file_list(): - """ - Returns list of filenames of files to display - No path is shown, only the short filename - - :return: List of filenames - :rtype: List[str] - """ - return sorted(list(get_file_list_dict().keys())) - - -def get_demo_path(): - """ - Get the top-level folder path - :return: Path to list of files using the user settings for this file. Returns folder of this file if not found - :rtype: str - """ - demo_path = sg.user_settings_get_entry('-demos folder-', os.path.dirname(__file__)) - - return demo_path - - -def get_global_editor(): - """ - Get the path to the editor based on user settings or on PySimpleGUI's global settings - - :return: Path to the editor - :rtype: str - """ - try: # in case running with old version of PySimpleGUI that doesn't have a global PSG settings path - global_editor = sg.pysimplegui_user_settings.get('-editor program-') - except: - global_editor = '' - return global_editor - - -def get_editor(): - """ - Get the path to the editor based on user settings or on PySimpleGUI's global settings - - :return: Path to the editor - :rtype: str - """ - try: # in case running with old version of PySimpleGUI that doesn't have a global PSG settings path - global_editor = sg.pysimplegui_user_settings.get('-editor program-') - except: - global_editor = '' - user_editor = sg.user_settings_get_entry('-editor program-', '') - if user_editor == '': - user_editor = global_editor - - return user_editor - -def using_local_editor(): - user_editor = sg.user_settings_get_entry('-editor program-', None) - return get_editor() == user_editor - - -def get_explorer(): - """ - Get the path to the file explorer program - - :return: Path to the file explorer EXE - :rtype: str - """ - try: # in case running with old version of PySimpleGUI that doesn't have a global PSG settings path - global_explorer = sg.pysimplegui_user_settings.get('-explorer program-', '') - except: - global_explorer = '' - explorer = sg.user_settings_get_entry('-explorer program-', '') - if explorer == '': - explorer = global_explorer - return explorer - - -def advanced_mode(): - """ - Returns True is advanced GUI should be shown - - :return: True if user indicated wants the advanced GUI to be shown (set in the settings window) - :rtype: bool - """ - return sg.user_settings_get_entry('-advanced mode-', True) - - - -def get_theme(): - """ - Get the theme to use for the program - Value is in this program's user settings. If none set, then use PySimpleGUI's global default theme - :return: The theme - :rtype: str - """ - # First get the current global theme for PySimpleGUI to use if none has been set for this program - try: - global_theme = sg.theme_global() - except: - global_theme = sg.theme() - # Get theme from user settings for this program. Use global theme if no entry found - user_theme = sg.user_settings_get_entry('-theme-', '') - if user_theme == '': - user_theme = global_theme - return user_theme - -# We handle our code properly. But in case the user types in a flag, the flags are now in the middle of a regex. Ignore this warning. - -warnings.filterwarnings("ignore", category=DeprecationWarning) - -# New function -def get_line_number(file_path, string, dupe_lines): - lmn = 0 - with open(file_path, encoding="utf-8") as f: - for num, line in enumerate(f, 1): - if string.strip() == line.strip() and num not in dupe_lines: - lmn = num - return lmn - -def kill_ascii(s): - return "".join([x if ord(x) < 128 else '?' for x in s]) - -''' -MM'""""'YMM dP dP -M' .mmm. `M 88 88 -M MMMMMooM 88d888b. .d8888b. .d8888b. 88 .dP -M MMMMMMMM 88' `88 88ooood8 88' `"" 88888" -M. `MMM' .M 88 88 88. ... 88. ... 88 `8b. -MM. .dM dP dP `88888P' `88888P' dP `YP -MMMMMMMMMMM - -M""M dP -M M 88 -M M 88d8b.d8b. 88d888b. .d8888b. 88d888b. d8888P .d8888b. -M M 88'`88'`88 88' `88 88' `88 88' `88 88 Y8ooooo. -M M 88 88 88 88. .88 88. .88 88 88 88 -M M dP dP dP 88Y888P' `88888P' dP dP `88888P' -MMMM 88 - dP -''' - - -def offer_install(module): - if sg.popup_yes_no(f'The program failed to import a package. You need to install {module}.', 'Would you like PySimpleGUI to install this package for you?', - title=f'Package {module} not found') != 'Yes': - return False - if module in packages_with_weird_names.keys(): - module = packages_with_weird_names[module] - try: - sg.execute_pip_install_package(module) - sg.cprint(f'Module {module} successfully installed.', colors='white on green') - sg.popup('Restarting your application to reload the modules...', auto_close_duration=2, auto_close=True) - sg.execute_command_subprocess(sys.executable, __file__, pipe_output=False, wait=False) - exit() - return True - except Exception as e: - sg.popup('Error performing the pip install. You may need a newer version of PySimpleGUI.', e) - # pip_install_latest(package) - # sg.popup('Restarting your application...', auto_close_duration=2, auto_close=True) - # sg.execute_command_subprocess(sys.executable, __file__, pipe_output=False, wait=False) - return False - -def check_module(module): - try: - __import__(module) - # print(f'{module} passed') - return True - except ImportError: - sg.cprint(f'Module {module} not found.', colors='white on red') - if offer_install(module): - return True - return False - - -def check_modules_on_import_line(line:str): - modules = line.split(' ', 1)[1].split(',') - # print(f'modules = {modules}') - for module in modules: - if ' as ' in module: - module = module.split('as')[0].strip() - if '.' in module: - module = module.split('.')[0].strip() - # print(f'checking "{module}"') - if not check_module(module): - return False - - return True - - - - -def check_imports_in_file(filename): - # Check if the file exists - if not os.path.exists(filename): - print("File does not exist") - return False - all_passed = True - # Open the file - file = open(filename, 'r', encoding='utf-8') - lines = file.readlines() - # Read the file line by line - for line in lines: - # print(line) - # Check if the line is an import statement - sline = line.strip() # strip the line in case it's indented - if sline.startswith('import'): - # Check if the module exists - if not check_modules_on_import_line(sline): - all_passed = False - elif sline.startswith('from'): - module = re.search(r'from (\w+)', sline).group(1) - if not check_module(module): - all_passed = False - # Close the file - file.close() - return all_passed - -''' -MM""""""""`M oo dP -MM mmmmmmmM 88 -M' MMMM dP 88 .d8888b. -MM MMMMMMMM 88 88 88ooood8 -MM MMMMMMMM 88 88 88. ... -MM MMMMMMMM dP dP `88888P' -MMMMMMMMMMMM - -MP""""""`MM dP -M mmmmm..M 88 -M. `YM .d8888b. .d8888b. 88d888b. .d8888b. 88d888b. -MMMMMMM. M 88ooood8 88' `88 88' `88 88' `"" 88' `88 -M. .MMM' M 88. ... 88. .88 88 88. ... 88 88 -Mb. .dM `88888P' `88888P8 dP `88888P' dP dP -MMMMMMMMMMM -''' - -def find_in_file(string, demo_files_dict, regex=False, verbose=False, window=None, ignore_case=True, show_first_match=True): - """ - Search through the demo files for a string. - The case of the string and the file contents are ignored - - :param string: String to search for - :param verbose: if True print the FIRST match - :type verbose: bool - :param find_all_matches: if True, then return all matches in the dictionary - :type find_all_matches: bool - :return: List of files containing the string - :rtype: List[str] - """ - - - # So you face a predicament here. You wish to read files, both small and large; however the bigger the file/bigger the list, the longer to read the file. - # This probably isn't what you want, right? - # Well, we can't use a direct command line to run grep and parse. But it is an option. The user may not have it. - # We could check if grep exists and if not use our method; but it isn't the best way. - # So using background knowldge, we know that grep is *very* fast. - # - # Why? - # Grep reads a *ton* of files into memory then searches through the memory to find the string or regex/pattern corresponding to the file. - # (This is useful if you ever accidently delete a file, grep may be able to get you the contents of it again!) - # How can we load a file into memory on python as fast as grep whilst keeping it universal? - # memory mapping (mmap). - # We can't load a lot of files into memory as we may face issues with watchdog on other operating systems. So we load one file at a time and search though there. - # This will allow the fastest searching and loading of a file without sacrificing read times. - # 2.8 seconds on the highend for both small and large files in memory. - # We also don't have to iterate over lines this way. - file_list = [] - num_files = 0 - matched_dict = {} - for file in demo_files_dict: - try: - full_filename = demo_files_dict[file] - if not demo_files_dict == get_file_list_dict(): - full_filename = full_filename[0] - matches = None - - with open(full_filename, 'rb', 0) as f, mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) as s: - if regex: - window['-FIND NUMBER-'].update(f'{num_files} files') - window.refresh() - matches = re.finditer(bytes("^.*(" + string + ").*$", 'utf-8'), s, re.MULTILINE) - if matches: - for match in matches: - if match is not None: - if file not in file_list: - file_list.append(file) - num_files += 1 - if verbose: - sg.cprint(f"{file}:", c = 'white on green') - sg.cprint(f"{match.group(0).decode('utf-8')}\n") - else: - window['-FIND NUMBER-'].update(f'{num_files} files') - window.refresh() - matches = None - if ignore_case: - if show_first_match: - matches = re.search(br'(?i)^' + bytes(".*("+re.escape(string.lower()) + ").*$", 'utf-8'), s, re.MULTILINE) - else: - matches = re.finditer(br'(?i)^' + bytes(".*("+re.escape(string.lower()) + ").*$", 'utf-8'), s, re.MULTILINE) - else: - if show_first_match: - matches = re.search(br'^' + bytes(".*("+re.escape(string) + ").*$", 'utf-8'), s, re.MULTILINE) - else: - matches = re.finditer(br'^' + bytes(".*("+re.escape(string) + ").*$", 'utf-8'), s, re.MULTILINE) - if matches: - if show_first_match: - #file_list.append(file) - #num_files += 1 - match_array = [] - - matched_str = matches.group(0).decode('utf-8') - if not all(x in matched_str for x in ("b'", '=')) and len(matched_str) < 500: - # safe to assume this is not a base64 string as it does not contain the proper ending - match_array.append(matches.group(0).decode('utf-8')) - matched_dict[full_filename] = match_array - file_list.append(file) - num_files += 1 - else: - # We need to do this because strings are "falsy" in Python, but empty matches still return True... - append_file = False - match_array = [] - for match_ in matches: - matched_str = match_.group(0).decode('utf-8') - if matched_str: - if not all(x in matched_str for x in ("b'", '=')) and len(matched_str) < 500: - # if len(match_str) < 500 and "=" not in match_str and "b'" not in match_str: - match_array.append(matched_str) - append_file = True - if append_file: - file_list.append(file) - num_files += 1 - matched_dict[full_filename] = match_array - - # del matches - except ValueError: - del matches - except Exception as e: - exc_type, exc_obj, exc_tb = sys.exc_info() - fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] - print(exc_type, fname, exc_tb.tb_lineno) - print(f'{file}', e, file=sys.stderr) - - # Format of the matches dictionary - # Filename, [num1, num2, num3] - file_lines_dict = {} - list_of_matches = [] - if not regex: - for key in matched_dict: - head, tail = os.path.split(key) - # Tails. Don't wanna put Washington in places he doesn't want to be. - file_array_old = [key] - - file_array_new = [] - - file_match_list = [] - - if verbose: - sg.cprint(f"{tail}:", c='white on green') - try: - dupe_lines = [] - for _match in matched_dict[key]: - line_num_match = get_line_number(key, _match, dupe_lines) - dupe_lines.append(line_num_match) - file_array_new.append(line_num_match) - file_match_list.append(_match) # I *really* overthinked this. - if verbose: - sg.cprint(f"Line: {line_num_match} ", c='white on purple', end='') - sg.cprint(f"{_match.strip()}\n") - # Make a list of the matches found in this file to add to the dictionry - list_of_matches.append(_match.strip()) - file_array_old.append(file_array_new) - file_array_old.append(file_match_list) - - if tail in file_lines_dict: - for i in range(1, 100): - new_tail = f'{tail}_{i}' - if new_tail not in file_lines_dict: - file_lines_dict[new_tail] = file_array_old - break - else: - file_lines_dict[tail] = file_array_old - except Exception as e: - pass - find_in_file.file_list_dict = file_lines_dict - - file_list = list(set(file_list)) - return file_list - - -def window_choose_line_to_edit(filename, full_filename, line_num_list, match_list): - # sg.popup('matches previously found for this file:', filename, line_num_list) - i = 0 - if len(line_num_list) == 1: - return full_filename, line_num_list[0] - layout = [[sg.T(f'Choose line from {filename}', font='_ 14')]] - for line in sorted(set(line_num_list)): - match_text = match_list[i] - layout += [[sg.Text(f'Line {line} : {match_text}', key=('-T-', line), enable_events=True, size=(min(len(match_text), 90), None))]] - i += 1 - layout += [[sg.B('Cancel')]] - - window = sg.Window('Open Editor', layout) - - line_chosen = line_num_list[0] - while True: - event, values = window.read() - if event in ('Cancel', sg.WIN_CLOSED): - line_chosen = None - break - # At this point we know a line was chosen - line_chosen = event[1] - break - - window.close() - return full_filename, line_chosen - -''' -MP""""""`MM dP dP oo -M mmmmm..M 88 88 -M. `YM .d8888b. d8888P d8888P dP 88d888b. .d8888b. .d8888b. -MMMMMMM. M 88ooood8 88 88 88 88' `88 88' `88 Y8ooooo. -M. .MMM' M 88. ... 88 88 88 88 88 88. .88 88 -Mb. .dM `88888P' dP dP dP dP dP `8888P88 `88888P' -MMMMMMMMMMM .88 - d8888P -M""MMM""MMM""M oo dP -M MMM MMM M 88 -M MMP MMP M dP 88d888b. .d888b88 .d8888b. dP dP dP -M MM' MM' .M 88 88' `88 88' `88 88' `88 88 88 88 -M `' . '' .MM 88 88 88 88. .88 88. .88 88.88b.88' -M .d .dMMM dP dP dP `88888P8 `88888P' 8888P Y8P -MMMMMMMMMMMMMM - -''' - - -def settings_window(): - """ - Show the settings window. - This is where the folder paths and program paths are set. - Returns True if settings were changed - - :return: True if settings were changed - :rtype: (bool) - """ - - try: - global_editor = sg.pysimplegui_user_settings.get('-editor program-') - except: - global_editor = '' - try: - global_explorer = sg.pysimplegui_user_settings.get('-explorer program-') - except: - global_explorer = '' - try: # in case running with old version of PySimpleGUI that doesn't have a global PSG settings path - global_theme = sg.theme_global() - except: - global_theme = '' - - layout = [[sg.T('Program Settings', font='DEFAULT 25')], - [sg.T('Path to Tree', font='_ 16')], - [sg.Combo(sorted(sg.user_settings_get_entry('-folder names-', [])), default_value=sg.user_settings_get_entry('-demos folder-', get_demo_path()), size=(50, 1), key='-FOLDERNAME-'), - sg.FolderBrowse('Folder Browse', target='-FOLDERNAME-'), sg.B('Clear History')], - [sg.T('Editor Program', font='_ 16')], - [sg.T('Leave blank to use global default'), sg.T(global_editor)], - [ sg.In(sg.user_settings_get_entry('-editor program-', ''),k='-EDITOR PROGRAM-'), sg.FileBrowse()], - [sg.T('File Explorer Program', font='_ 16')], - [sg.T('Leave blank to use global default'), sg.T(global_explorer)], - [ sg.In(sg.user_settings_get_entry('-explorer program-'), k='-EXPLORER PROGRAM-'), sg.FileBrowse()], - [sg.T('Theme', font='_ 16')], - [sg.T('Leave blank to use global default'), sg.T(global_theme)], - [sg.Combo(['']+sg.theme_list(),sg.user_settings_get_entry('-theme-', ''), readonly=True, k='-THEME-')], - [sg.T('Double-click a File Will:'), sg.R('Run', 2, sg.user_settings_get_entry('-dclick runs-', False), k='-DCLICK RUNS-'), sg.R('Edit', 2, sg.user_settings_get_entry('-dclick edits-', False), k='-DCLICK EDITS-'), sg.R('Nothing', 2, sg.user_settings_get_entry('-dclick none-', False), k='-DCLICK NONE-')], - [sg.CB('Check That Imported Modules Are Installed', sg.user_settings_get_entry('-check imports-', False), k='-CHECK IMPORTS-')], - [sg.CB('Use Advanced Interface', default=advanced_mode() ,k='-ADVANCED MODE-')], - [sg.B('Ok', bind_return_key=True), sg.B('Cancel')], - ] - - window = sg.Window('Settings', layout) - - settings_changed = False - - while True: - event, values = window.read() - if event in ('Cancel', sg.WIN_CLOSED): - break - if event == 'Ok': - sg.user_settings_set_entry('-demos folder-', values['-FOLDERNAME-']) - sg.user_settings_set_entry('-editor program-', values['-EDITOR PROGRAM-']) - sg.user_settings_set_entry('-theme-', values['-THEME-']) - sg.user_settings_set_entry('-folder names-', list(set(sg.user_settings_get_entry('-folder names-', []) + [values['-FOLDERNAME-'], ]))) - sg.user_settings_set_entry('-explorer program-', values['-EXPLORER PROGRAM-']) - sg.user_settings_set_entry('-advanced mode-', values['-ADVANCED MODE-']) - sg.user_settings_set_entry('-dclick runs-', values['-DCLICK RUNS-']) - sg.user_settings_set_entry('-dclick edits-', values['-DCLICK EDITS-']) - sg.user_settings_set_entry('-dclick nothing-', values['-DCLICK NONE-']) - sg.user_settings_set_entry('-check imports-', values['-CHECK IMPORTS-']) - settings_changed = True - break - elif event == 'Clear History': - sg.user_settings_set_entry('-folder names-', []) - sg.user_settings_set_entry('-last filename-', '') - window['-FOLDERNAME-'].update(values=[], value='') - - window.close() - return settings_changed - - - -''' -M"""""`'"""`YM oo -M mm. mm. M -M MMM MMM M .d8888b. dP 88d888b. -M MMM MMM M 88' `88 88 88' `88 -M MMM MMM M 88. .88 88 88 88 -M MMM MMM M `88888P8 dP dP dP -MMMMMMMMMMMMMM - -M""MMM""MMM""M oo dP -M MMM MMM M 88 -M MMP MMP M dP 88d888b. .d888b88 .d8888b. dP dP dP -M MM' MM' .M 88 88' `88 88' `88 88' `88 88 88 88 -M `' . '' .MM 88 88 88 88. .88 88. .88 88.88b.88' -M .d .dMMM dP dP dP `88888P8 `88888P' 8888P Y8P -MMMMMMMMMMMMMM -''' - -ML_KEY = '-ML-' # Multline's key - -# --------------------------------- Create the window --------------------------------- -def make_window(): - """ - Creates the main window - :return: The main window object - :rtype: (sg.Window) - """ - theme = get_theme() - if not theme: - theme = sg.OFFICIAL_PYSIMPLEGUI_THEME - sg.theme(theme) - # First the window layout...2 columns - - find_tooltip = "Find in file\nEnter a string in box to search for string inside of the files.\nFile list will update with list of files string found inside." - filter_tooltip = "Filter files\nEnter a string in box to narrow down the list of files.\nFile list will update with list of files with string in filename." - find_re_tooltip = "Find in file using Regular Expression\nEnter a string in box to search for string inside of the files.\nSearch is performed after clicking the FindRE button." - - - left_col = sg.Column([ - [sg.Listbox(values=get_file_list(), select_mode=sg.SELECT_MODE_EXTENDED, size=(50,20), bind_return_key=True, key='-DEMO LIST-', expand_x=True, expand_y=True)], - [sg.Text('Filter (F1):', tooltip=filter_tooltip), sg.Input(size=(25, 1), focus=True, enable_events=True, key='-FILTER-', tooltip=filter_tooltip), - sg.T(size=(15,1), k='-FILTER NUMBER-')], - [sg.Button('Run'), sg.B('Edit'), sg.B('Clear'), sg.B('Open Folder'), sg.B('Copy Path')], - [sg.Text('Find (F2):', tooltip=find_tooltip), sg.Input(size=(25, 1), enable_events=True, key='-FIND-', tooltip=find_tooltip), - sg.T(size=(15,1), k='-FIND NUMBER-')], - ], element_justification='l', expand_x=True, expand_y=True) - - lef_col_find_re = sg.pin(sg.Col([ - [sg.Text('Find (F3):', tooltip=find_re_tooltip), sg.Input(size=(25, 1),key='-FIND RE-', tooltip=find_re_tooltip),sg.B('Find RE')]], k='-RE COL-')) - - right_col = [ - [sg.Multiline(size=(70, 21), write_only=True, expand_x=True, expand_y=True, key=ML_KEY, reroute_stdout=True, echo_stdout_stderr=True, reroute_cprint=True)], - [sg.B('Settings'), sg.Button('Exit')], - [sg.T('Demo Browser Ver ' + version)], - [sg.T('PySimpleGUI ver ' + sg.version.split(' ')[0] + ' tkinter ver ' + sg.tclversion_detailed, font='Default 8', pad=(0,0))], - [sg.T('Python ver ' + sys.version, font='Default 8', pad=(0,0))], - [sg.T('Interpreter ' + sg.execute_py_get_interpreter(), font='Default 8', pad=(0,0))], - ] - - options_at_bottom = sg.pin(sg.Column([[sg.CB('Verbose', enable_events=True, k='-VERBOSE-', tooltip='Enable to see the matches in the right hand column'), - sg.CB('Show only first match in file', default=True, enable_events=True, k='-FIRST MATCH ONLY-', tooltip='Disable to see ALL matches found in files'), - sg.CB('Find ignore case', default=True, enable_events=True, k='-IGNORE CASE-'), - sg.CB('Wait for Runs to Complete', default=False, enable_events=True, k='-WAIT-'), - sg.CB('Show ALL file types', default=sg.user_settings_get_entry('-show all files-', False), enable_events=True, k='-SHOW ALL FILES-'), - ]], - pad=(0,0), k='-OPTIONS BOTTOM-', expand_x=True, expand_y=False), expand_x=True, expand_y=False) - - choose_folder_at_top = sg.pin(sg.Column([[sg.T('Click settings to set top of your tree or choose a previously chosen folder'), - sg.Combo(sorted(sg.user_settings_get_entry('-folder names-', [])), default_value=sg.user_settings_get_entry('-demos folder-', ''), size=(50, 30), key='-FOLDERNAME-', enable_events=True, readonly=True)]], pad=(0,0), k='-FOLDER CHOOSE-')) - # ----- Full layout ----- - - layout = [[sg.Text('PySimpleGUI Demo Program & Project Browser', font='Any 20')], - [choose_folder_at_top], - # [sg.Column([[left_col],[ lef_col_find_re]], element_justification='l', expand_x=True, expand_y=True), sg.Column(right_col, element_justification='c', expand_x=True, expand_y=True)], - [sg.Pane([sg.Column([[left_col],[ lef_col_find_re]], element_justification='l', expand_x=True, expand_y=True), sg.Column(right_col, element_justification='c', expand_x=True, expand_y=True) ], orientation='h', relief=sg.RELIEF_SUNKEN, expand_x=True, expand_y=True, k='-PANE-')], - [options_at_bottom, sg.Sizegrip()]] - - # --------------------------------- Create Window --------------------------------- - # TODO Uncomment when deploy PSG5 - # window = sg.Window('PSG Demo & Project Browser', layout, finalize=True, resizable=True, use_default_focus=False, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT, auto_save_location=True) - # TODO Remove when deploy PSG5 - window = sg.Window('PSG Demo & Project Browser', layout, finalize=True, resizable=True, use_default_focus=False, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT) - window.set_min_size(window.size) - - - # window.bind("", 'Exit') # matches the underscore shown on the Exit button (For now disabled this feature until buttons with underscore released to PyPI) - - window.bind('', '-FOCUS FILTER-') - window.bind('', '-FOCUS FIND-') - window.bind('', '-FOCUS RE FIND-') - if not advanced_mode(): - window['-FOLDER CHOOSE-'].update(visible=False) - window['-RE COL-'].update(visible=False) - window['-OPTIONS BOTTOM-'].update(visible=False) - - window.bring_to_front() - return window - - -''' -M""M dP dP dP -M M 88 88 88 -M M 88d888b. .d8888b. d8888P .d8888b. 88 88 .d8888b. 88d888b. -M M 88' `88 Y8ooooo. 88 88' `88 88 88 88ooood8 88' `88 -M M 88 88 88 88 88. .88 88 88 88. ... 88 -M M dP dP `88888P' dP `88888P8 dP dP `88888P' dP -MMMM -''' - - -def pip_install_thread(window, sp): - window.write_event_value('-THREAD-', (sp, 'Install thread started')) - for line in sp.stdout: - oline = line.decode().rstrip() - window.write_event_value('-THREAD-', (sp, oline)) - - - -def pip_install_latest(): - - pip_command = '-m pip install --upgrade --no-cache-dir PySimpleGUI>=5' - - python_command = sys.executable # always use the currently running interpreter to perform the pip! - if 'pythonw' in python_command: - python_command = python_command.replace('pythonw', 'python') - - layout = [[sg.Text('Installing PySimpleGUI', font='_ 14')], - [sg.Multiline(s=(90, 15), k='-MLINE-', reroute_cprint=True, reroute_stdout=True, echo_stdout_stderr=True, write_only=True, expand_x=True, expand_y=True)], - [sg.Push(), sg.Button('Downloading...', k='-EXIT-'), sg.Sizegrip()]] - - window = sg.Window('Pip Install PySimpleGUI Utilities', layout, finalize=True, keep_on_top=True, modal=True, disable_close=True, resizable=True) - - window.disable_debugger() - - sg.cprint('Installing with the Python interpreter =', python_command, c='white on purple') - - sp = sg.execute_command_subprocess(python_command, pip_command, pipe_output=True, wait=False) - - window.start_thread(lambda: pip_install_thread(window, sp), end_key='-THREAD DONE-') - - while True: - event, values = window.read() - if event == sg.WIN_CLOSED or (event == '-EXIT-' and window['-EXIT-'].ButtonText == 'Done'): - break - elif event == '-THREAD DONE-': - sg.cprint('\n') - show_package_version('PySimpleGUI') - sg.cprint('Done Installing PySimpleGUI. Click Done and the program will restart.', c='white on red', font='default 12 italic') - window['-EXIT-'].update(text='Done', button_color='white on red') - elif event == '-THREAD-': - sg.cprint(values['-THREAD-'][1]) - - window.close() - -def suggest_upgrade_gui(): - layout = [[sg.Image(sg.EMOJI_BASE64_HAPPY_GASP), sg.Text(f'PySimpleGUI 5+ Required', font='_ 15 bold')], - [sg.Text(f'PySimpleGUI 5+ required for this program to function correctly.')], - [sg.Text(f'You are running PySimpleGUI {sg.version}')], - [sg.Text('Would you like to upgrade to the latest version of PySimpleGUI now?')], - [sg.Push(), sg.Button('Upgrade', size=8, k='-UPGRADE-'), sg.Button('Cancel', size=8)]] - - window = sg.Window(title=f'Newer version of PySimpleGUI required', layout=layout, font='_ 12') - - while True: - event, values = window.read() - - if event in (sg.WIN_CLOSED, 'Cancel'): - window.close() - break - elif event == '-UPGRADE-': - window.close() - pip_install_latest() - sg.execute_command_subprocess(sys.executable, __file__, pipe_output=True, wait=False) - break - - -def make_str_pre_38(package): - return f""" -import warnings -warnings.filterwarnings("ignore", category=DeprecationWarning) -import pkg_resources -try: - ver=pkg_resources.get_distribution("{package}").version.rstrip() -except: - ver=' ' -print(ver, end='') -""" - -def make_str(package): - return f""" -import importlib.metadata - -try: - ver = importlib.metadata.version("{package}") -except importlib.metadata.PackageNotFoundError: - ver = ' ' -print(ver, end='') -""" - - -def show_package_version(package): - """ - Function that shows all versions of a package - """ - interpreter = sg.execute_py_get_interpreter() - sg.cprint(f'{package} upgraded to ', end='', c='red') - # print(f'{interpreter}') - if sys.version_info.major == 3 and sys.version_info.minor in (6, 7): # if running Python version 3.6 or 3.7 - pstr = make_str_pre_38(package) - else: - pstr = make_str(package) - temp_file = os.path.join(os.path.dirname(__file__), 'temp_py.py') - with open(temp_file, 'w') as file: - file.write(pstr) - sg.execute_py_file(temp_file, interpreter_command=interpreter, pipe_output=True, wait=True) - os.remove(temp_file) - - - -def upgrade_check(): - if not sg.version.startswith('5'): - suggest_upgrade_gui() - exit() - - - -''' -M"""""`'"""`YM oo -M mm. mm. M -M MMM MMM M .d8888b. dP 88d888b. -M MMM MMM M 88' `88 88 88' `88 -M MMM MMM M 88. .88 88 88 88 -M MMM MMM M `88888P8 dP dP dP -MMMMMMMMMMMMMM -''' -# --------------------------------- Main Program Layout --------------------------------- - -def main(): - """ - The main program that contains the event loop. - It will call the make_window function to create the window. - """ - - sg.user_settings_filename(filename='psgdemos.json') - upgrade_check() - - sg.user_settings_filename('psgdemos.json') - sg.set_options(icon=sg.EMOJI_BASE64_HAPPY_IDEA) - find_in_file.file_list_dict = None - - old_typed_value = None - - file_list_dict = get_file_list_dict() - file_list = get_file_list() - window = make_window() - window['-FILTER NUMBER-'].update(f'{len(file_list)} files') - window.force_focus() - window['-FILTER-'].set_focus() - counter = 0 - while True: - event, values = window.read() - # print(event, values) - - counter += 1 - if event in (sg.WINDOW_CLOSED, 'Exit'): - break - if event == '-DEMO LIST-': # if double clicked (used the bind return key parm) - if sg.user_settings_get_entry('-dclick runs-'): - event = 'Run' - elif sg.user_settings_get_entry('-dclick edits-'): - event = 'Edit' - if event == 'Edit': - editor_program = get_editor() - for file in values['-DEMO LIST-']: - if find_in_file.file_list_dict is not None: - full_filename, line = window_choose_line_to_edit(file, find_in_file.file_list_dict[file][0], find_in_file.file_list_dict[file][1], find_in_file.file_list_dict[file][2]) - else: - full_filename, line = get_file_list_dict()[file], 1 - if line is not None: - sg.cprint(f'Editing using {editor_program}', c='white on red', end='') - sg.cprint('') - sg.cprint(f'{full_filename}', c='white on purple') - if not get_editor(): - sg.popup_error_with_traceback('No editor has been configured', 'You need to configure an editor in order to use this feature', 'You can configure the editor in the Demo Brower Settings or the PySimpleGUI Global Settings') - else: - if using_local_editor(): - sg.execute_command_subprocess(editor_program, f'"{full_filename}"') - else: - try: - sg.execute_editor(full_filename, line_number=int(line)) - except: - sg.execute_command_subprocess(editor_program, f'"{full_filename}"') - else: - sg.cprint('Editing canceled') - elif event == 'Run': - sg.cprint('Running....', c='white on green', end='') - sg.cprint('') - - for file in values['-DEMO LIST-']: - file_to_run = str(file_list_dict[file]) - # sg.cprint('Checking Imports....', c='white on green') - if sg.user_settings_get_entry('-check imports-', False) and not check_imports_in_file(file_to_run): - sg.cprint(f'The demo program {os.path.basename(file_to_run)} depends on modules that are not installed.') - else: - sg.cprint(file_to_run,text_color='white', background_color='purple') - try: - sp = sg.execute_py_file(file_to_run, pipe_output=values['-WAIT-']) - except Exception as e: - sg.cprint(f'Error trying to run python file. Error info:', e, c='white on red') - try: - if values['-WAIT-']: - sg.cprint(f'Waiting on results..', text_color='white', background_color='red', end='') - while True: - results = sg.execute_get_results(sp) - sg.cprint(f'STDOUT:', text_color='white', background_color='green') - sg.cprint(results[0]) - sg.cprint(f'STDERR:', text_color='white', background_color='green') - sg.cprint(results[1]) - if not sg.execute_subprocess_still_running(sp): - break - except AttributeError: - sg.cprint('Your version of PySimpleGUI needs to be upgraded to fully use the "WAIT" feature.', c='white on red') - elif event.startswith('Edit Me'): - editor_program = get_editor() - sg.cprint(f'opening using {editor_program}:') - sg.cprint(f'{__file__}', text_color='white', background_color='red', end='') - sg.execute_command_subprocess(f'{editor_program}', f'"{__file__}"') - elif event == '-FILTER-': - new_list = [i for i in file_list if values['-FILTER-'].lower() in i.lower()] - window['-DEMO LIST-'].update(new_list) - window['-FILTER NUMBER-'].update(f'{len(new_list)} files') - window['-FIND NUMBER-'].update('') - window['-FIND-'].update('') - window['-FIND RE-'].update('') - elif event == '-FOCUS FIND-': - window['-FIND-'].set_focus() - elif event == '-FOCUS FILTER-': - window['-FILTER-'].set_focus() - elif event == '-FOCUS RE FIND-': - window['-FIND RE-'].set_focus() - elif event == '-FIND-' or event == '-FIRST MATCH ONLY-' or event == '-VERBOSE-' or event == '-FIND RE-': - is_ignore_case = values['-IGNORE CASE-'] - old_ignore_case = False - current_typed_value = str(values['-FIND-']) - if len(values['-FIND-']) == 1: - window[ML_KEY].update('') - window['-VERBOSE-'].update(False) - values['-VERBOSE-'] = False - if values['-VERBOSE-']: - window[ML_KEY].update('') - if values['-FIND-']: - if find_in_file.file_list_dict is None or old_typed_value is None or old_ignore_case is not is_ignore_case: - # New search. - old_typed_value = current_typed_value - file_list = find_in_file(values['-FIND-'], get_file_list_dict(), verbose=values['-VERBOSE-'], window=window, ignore_case=is_ignore_case, show_first_match=values['-FIRST MATCH ONLY-']) - elif current_typed_value.startswith(old_typed_value) and old_ignore_case is is_ignore_case: - old_typed_value = current_typed_value - file_list = find_in_file(values['-FIND-'], find_in_file.file_list_dict, verbose=values['-VERBOSE-'], window=window, ignore_case=is_ignore_case, show_first_match=values['-FIRST MATCH ONLY-']) - else: - old_typed_value = current_typed_value - file_list = find_in_file(values['-FIND-'], get_file_list_dict(), verbose=values['-VERBOSE-'], window=window, ignore_case=is_ignore_case, show_first_match=values['-FIRST MATCH ONLY-']) - window['-DEMO LIST-'].update(sorted(file_list)) - window['-FIND NUMBER-'].update(f'{len(file_list)} files') - window['-FILTER NUMBER-'].update('') - window['-FIND RE-'].update('') - window['-FILTER-'].update('') - elif values['-FIND RE-']: - window['-ML-'].update('') - file_list = find_in_file(values['-FIND RE-'], get_file_list_dict(), regex=True, verbose=values['-VERBOSE-'],window=window) - window['-DEMO LIST-'].update(sorted(file_list)) - window['-FIND NUMBER-'].update(f'{len(file_list)} files') - window['-FILTER NUMBER-'].update('') - window['-FIND-'].update('') - window['-FILTER-'].update('') - elif event == 'Find RE': - window['-ML-'].update('') - file_list = find_in_file(values['-FIND RE-'], get_file_list_dict(), regex=True, verbose=values['-VERBOSE-'],window=window) - window['-DEMO LIST-'].update(sorted(file_list)) - window['-FIND NUMBER-'].update(f'{len(file_list)} files') - window['-FILTER NUMBER-'].update('') - window['-FIND-'].update('') - window['-FILTER-'].update('') - sg.cprint('Regular expression find completed') - elif event == 'Settings': - if settings_window() is True: - window.close() - window = make_window() - file_list_dict = get_file_list_dict() - file_list = get_file_list() - window['-FILTER NUMBER-'].update(f'{len(file_list)} files') - elif event == 'Clear': - file_list = get_file_list() - window['-FILTER-'].update('') - window['-FILTER NUMBER-'].update(f'{len(file_list)} files') - window['-FIND-'].update('') - window['-DEMO LIST-'].update(file_list) - window['-FIND NUMBER-'].update('') - window['-FIND RE-'].update('') - window['-ML-'].update('') - elif event == '-FOLDERNAME-': - sg.user_settings_set_entry('-demos folder-', values['-FOLDERNAME-']) - file_list_dict = get_file_list_dict() - file_list = get_file_list() - window['-DEMO LIST-'].update(values=file_list) - window['-FILTER NUMBER-'].update(f'{len(file_list)} files') - window['-ML-'].update('') - window['-FIND NUMBER-'].update('') - window['-FIND-'].update('') - window['-FIND RE-'].update('') - window['-FILTER-'].update('') - elif event == 'Open Folder': - explorer_program = get_explorer() - if explorer_program: - sg.cprint(f'Opening Folder using {explorer_program}...', c='white on green', end='') - sg.cprint('') - for file in values['-DEMO LIST-']: - file_selected = str(file_list_dict[file]) - file_path = os.path.dirname(file_selected) - if sg.running_windows(): - file_path = file_path.replace('/', '\\') - sg.cprint(file_path, text_color='white', background_color='purple') - sg.execute_command_subprocess(explorer_program, file_path) - elif event == 'Copy Path': - for file in values['-DEMO LIST-']: - sg.cprint('Copying the last highlighted filename in your list') - if find_in_file.file_list_dict is not None: - full_filename, line = window_choose_line_to_edit(file, find_in_file.file_list_dict[file][0], find_in_file.file_list_dict[file][1], find_in_file.file_list_dict[file][2]) - else: - full_filename, line = get_file_list_dict()[file], 1 - if line is not None: - sg.cprint(f'Added to Clipboard Full Path {full_filename}', c='white on purple') - sg.clipboard_set(full_filename) - elif event == 'Version': - sg.popup_scrolled(sg.get_versions(), f'This Program: {__file__}' ,keep_on_top=True, non_blocking=True) - elif event == '-SHOW ALL FILES-': - sg.user_settings_set_entry('-show all files-', values[event]) - file_list_dict = get_file_list_dict() - file_list = get_file_list() - window['-DEMO LIST-'].update(values=file_list) - window['-FILTER NUMBER-'].update(f'{len(file_list)} files') - window['-ML-'].update('') - window['-FIND NUMBER-'].update('') - window['-FIND-'].update('') - window['-FIND RE-'].update('') - window['-FILTER-'].update('') - window.close() - - - - - - -if __name__ == '__main__': - - main() diff --git a/DemoPrograms/readme.md b/DemoPrograms/readme.md new file mode 100644 index 000000000..54dd32a04 --- /dev/null +++ b/DemoPrograms/readme.md @@ -0,0 +1,119 @@ +# PySimpleGUI Demo Programs + +## One Stop Shopping For Templates and Techniques + +This folder of over 170 programs is your jump-start, spring board, boost, shove in the back, cheat sheet to get you to a solution as quickly as possible. You can think of them as Recipes from a large PySimpleGUI Cookbook. + +Programs in this folder have a range of uses and reasons for existing + +* Demonstrate a particular PySimpleGUI Element / Feature (Tables, Trees, Buttons) +* Design patterns are "official" ways to get something done (Multiple windows) +* Integrate PySimpleGUI with another package / technology (OpenCV, Matplotlib) +* Assemble PySimpleGUI elements in a useful way (Bar graphs, games) +* Additional user code that enable new functionality (ANSI color strings) +* How to deal with common GUI problems (work requiring lots of time) + + +## Demo Program Browser + +The best way to work with these demos is to use the Demo Program Browser. You'll find installation instructions in the Cookbook. This browser will enable you to search by filename and also enable you to search inside the demos, a particularly powerful capability. + +## Coding Conventions + +Special attention is given to the programs in this folder to ensure they conform to the latest "preferred" technique or naming convention. In the past, when technique changed, so did all of these demo programs. For example, the use of the `FindElement` method was replaced by using `[ ]`. All of these Demo Programs were updated to use the new convention. + +For example, this line of code: + +```python +window.FindElement('status').Update(event) +``` + +was replaced with: + +```python +window['status'].Update(event) +``` + +There was a recent sweep through all of the Demo Programs where all code was changed to use the PEP8 naming conventions / bindings. All calls to `Window.Read()` were changed to `window.read()` + +PySimpleGUI is on a swift development path. In a short amount of time a lot can change. To help ensure that users are using the latest, preferred, methods of using the PySimpleGUI package, these Demo Programs are the vehicle in which to communicate the latest design patterns. + +Take a look at the Cookbook for more information about coding conventions used. + +## Ports + +Not all of the programs presented here are limited to the tkinter port of PySimpleGUI. Some programs show multiple import statements with some that are commented out. This is done to show you that the code is capable of running more than 1 platform. This example is from the Demo_Matplotlibe_Two_Windows.py file + +```python +from matplotlib import use +# import PySimpleGUI as sg +import PySimpleGUIQt as sg; use('qt5agg') +``` + +This indicates that the code can be run on either the tkinter or the Qt port. To switch ports, uncomment the one you want to run on and comment out the others. + +There are Demo Programs folders under each of the ports folders in the GitHub. + + +## Running Demos Online + +Recently two online Python services have been used to demonstrate using PySimpleGUI- Trinket & repl.it. You will find not only some of the Demo Programs from this folder on these sites, but other demo programs as well. They make good "scratch pads" for posting PySimpleGUI code. They are superior to GithubGists because not only can you share your code, but people can run the code without having to install or do anything locally. + + +### Trinket + +If a demo does not require another package be installed and it's not specific to a particular platform then there's a possibility that it can be run online using Trinket. You'll find a number of these Demo Programs have been added to the PySimpleGUI Trinket pages. + +The benefits of using Trinket include + +* No need to install PySimpleGUI or even Python on your local machine +* Additional explanation can be included with the code, including images + +You'll find the demos that have been added to Trinket here: + +http://Trinket.PySimpleGUI.org + + + +### Repl.it + +Prior to discovering Trinket PySimpleGUI demo programs were being hosted online on repl.it. Repl.it has several advantages over Trinket including: + +* Able to run both PySimpleGUI and PySimpleGUIWeb programs +* Can use other packages with PySimpleGUI +* Can pip install specific PySimpleGUI versions to use + +You'll find a list of repl.it demos here: + +https://repl.it/@PySimpleGUI + +These programs may not be the most up to date and in fact are likely to contain old coding constructs and examples. As a result, use them more of a demonstration of "what's possible" rather than "exactly how to do it". + +## Other Sample Code in this GitHub Account + +The PySimpleGUI GitHub account has a number of repos that contain larger applications that use PySimpleGUI. A few linger in the PySimpleGUI project folder like the HowDoI, chess, exemaker, and some user created programs. They'll get moved out at some point. Until then, browse around the repo. Explore a little. Some are older, some newer, but none are as important as the Demo Programs folder which is kept up to date. + +## Support + +These programs are not "officially" part of the PySimpleGUI code. They are not installed when you do a pip install for example.' + +They are demonstrations, examples, and as a result may not be fully built-out, completed programs. In order to keep the code simple, they may not have all of the error checking that your program should have. + +If you encounter a problem where a demo no longer functions, you are of course encouraged to open an Issue on the GitHub. + +If you encounter more subtle problems, you should take into account that these programs are demonstrations, not end-user products. For example, if an image viewer application doesn't display all types of image files like JPGs, then that's more than likely a limitation that the underlying GUI Framework has rather than a bug. In this example, it's your responsibility to figure out how to convert your images into a format that's understood by the framework rather than an improvement needed in the demo program that will show you how to do that. + + +# Author + +The PySimpleGUI Organization and PySimpleGUI users + +If the code has been provide by a PySimpleGUI user, then the comments at the top of the program will indicate the author. + + + +# License + +Copyright 2019 PySimpleGUI.org + +GNU Lesser General Public License (LGPL 3) + diff --git a/DemoPrograms/red_plus.ico b/DemoPrograms/red_plus.ico new file mode 100644 index 000000000..60b916c47 Binary files /dev/null and b/DemoPrograms/red_plus.ico differ diff --git a/DemoPrograms/screenshot.jpg b/DemoPrograms/screenshot.jpg deleted file mode 100644 index a168611ec..000000000 Binary files a/DemoPrograms/screenshot.jpg and /dev/null differ diff --git a/Demo_Toolbar/Demo_Floating_Toolbar.py b/Demo_Toolbar/Demo_Floating_Toolbar.py new file mode 100644 index 000000000..de69a7cc6 --- /dev/null +++ b/Demo_Toolbar/Demo_Floating_Toolbar.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python +import sys +if sys.version_info[0] >= 3: + import PySimpleGUI as sg +else: + import PySimpleGUI27 as sg + +import os + +BUTTON_PATH = '.' +button_names = ('close', 'cookbook', 'cpu', 'github', 'pysimplegui', 'run', 'storage', 'timer', 'checkmark', 'camera', 'house', 'download') + + +def ShowMeTheButtons(): + button_files = [os.path.join(BUTTON_PATH, b+'.png') for b in button_names] + + sg.SetOptions(auto_size_buttons=True, margins=(0,0), button_color=sg.COLOR_SYSTEM_DEFAULT) + + toolbar_buttons = [[sg.RButton('{}'.format(button_names[i]), image_size=(32,32), image_filename=f, pad=(0,0), tooltip=button_names[i]) for i, f in enumerate(button_files)],] + + layout = [[sg.Frame('', toolbar_buttons,)]] + + form = sg.FlexForm('Toolbar', + no_titlebar=True, + grab_anywhere=True, + background_color='grey76', + keep_on_top=True, + ).Layout(layout) + + # ---===--- Loop taking in user input --- # + while True: + button, value = form.Read() + print(button) + if button == 'close' or button is None: + break # exit button clicked + +if __name__ == '__main__': + ShowMeTheButtons() \ No newline at end of file diff --git a/Demo_Toolbar/Demo_Floating_Toolbar_Includes_Buttons.py b/Demo_Toolbar/Demo_Floating_Toolbar_Includes_Buttons.py new file mode 100644 index 000000000..05019d693 --- /dev/null +++ b/Demo_Toolbar/Demo_Floating_Toolbar_Includes_Buttons.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python +import sys +if sys.version_info[0] >= 3: + import PySimpleGUI as sg +else: + import PySimpleGUI27 as sg + +import io +from PIL import Image +import base64 +import subprocess + +button_names = ('close', 'cookbook', 'cpu', 'github', 'pysimplegui', 'run', 'storage', 'timer') + + +house64='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' + + +timer64='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' + +close64 = 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAEQ0lEQVR42r2XW2wbRRSG/1177TgkdkyoS4shaaWogVIKRAXUVn4BgRBEIRBSkSK1lAakPhTxABJSK6BEtAoXCUHEWwWi4oEXUAVvRUASSBuJliAh5QJp6hrspoGQi69r73LO7Npu6kvsBGek0ezOrvf79szsmbG0D2iwAN8DaMQaFA0YHQFaLwCX6TQuHQAuNtjR2PawD05LZeFzKeC7b/txPoLxU8Aj1BVkAf1wqw/uejeU9RsASaqYQGp+Dv8EAvjgdD9OAg9S14gQOPKED1XNWyv7+lT0VArxiVH0fCUEOqjr3JoKcImN/pYW2EOnQyUJTESBJkdpgGkV8Cj/owDDdx59A8Mf92FT+GpR+KSlBrt6ehE6+hL0pLp6AYbvfusE5FontFgUZ989UVAiDU+X0OsvQ0/EVy4g4MeOQ3a6Mn38wKHet3MkrofzZJMsFlzpeRVaeLF8ASPsb8Javy7nDXRVxdA7x7FpIZQXnrlP0yDJMoKvHVpZBKq23Qv3M8/nzQt6PIah93qhRxaLwvPNhbLmgGP7Drg694mHlVqKwcsWEBItD8DVvleM6WrhRQXUwBSsnpthvclDY++BZLdnflS9YxecrZ2QFGVZePDIYcq5yWuGK47k39NIzlCdDkHxNuYXiJzrz/xIrr4BFpdbfAFyTS1CSi1uf7IDrqeeheyoLihxubsD2sI8UuEFaItUKfen5mahRcLZl7nft7xAvjIQs+GFP2cLCmjRCL5p3oDN6nzR56xIYDl4ORJlCwyqDnT7Z5aFL5G4w4vN8dnVCwymatA9daVkeCkSJQv8qDtxcDKYF86AwKEuSDYbvB+doq/DlnMPJ6uvmzfmSJQk0E9D+OLVcEG4f38bwgNnxLmz9Wl4+z6HZLXm3JuYHMfE7i0ri8Ck3Y3Hx4L0lvYl8Et7H0Xk7NJ7Xe1d8H74GX2/2YyZmv8XY3euo4SUXJkAFyvtEbdc+CsDn2r3Ifrrz3nHvW7Pftzy/kmxdhSCly2Qlmj66Xf88dB2qP6LRme+jauuo67rIDyvHMN4i1esmvlK6QIUTrEISbKxDnDlPkk2BK6VIDhXXaddP6Vk0H6A9wSUn0WKFn2lCgiYbDEmFVXJYjWOuU1LcHudgAASSLS0FnD4dV4TksYxNEOqsMDwgAAxELToSFZFfGaiVWzGNV6MWM4Uyc5OE8wQCr2AqwmxIuoJowX3k5CjZSd6vvxhqcBj921Fc2g8C2Mwzf5sax7zNZZjSdkcCg6/EEgacAYzlLZvRk1kW7rm39iELwZHsgLPATN311rqb7trG+65dT2FXTEg4o1NoDinZKOYQ8ICFo4ADwMJpEwBDrnKIU+YMqZQ0pAbC4QwODwCf0Rd/BQ4IATagM46oI+CeiNPPVS40EDF6M/pJ78Ap+n0PL8Cp7sGs9asgQSFDLxBmKJ6STKBVSbcZsa10gKcJHi/Hv0PWqbBbaFH/AEAAAAASUVORK5CYII=' + + +def ExecuteCommandSubprocess(command, *args, wait=False): + # try: + if sys.platform == 'linux': + arg_string = '' + for arg in args: + arg_string += ' ' + str(arg) + sp = subprocess.Popen(['python3' + arg_string, ], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + else: + expanded_args = [] + for a in args: + expanded_args += a + sp = subprocess.Popen([command, expanded_args], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + if wait: + out, err = sp.communicate() + if out: + print(out.decode("utf-8")) + if err: + print(err.decode("utf-8")) + # except: pass + + +def get_image_bytes(image64): + image_file = io.BytesIO(base64.b64decode(image64)) + img = Image.open(image_file) + bio = io.BytesIO() + img.save(bio, format='PNG') + imgbytes = bio.getvalue() + return imgbytes + +def ShowMeTheButtons(): + + sg.SetOptions(auto_size_buttons=True, margins=(0,0), button_color=sg.COLOR_SYSTEM_DEFAULT) + + toolbar_buttons = [[sg.RButton('', image_data=get_image_bytes(close64),button_color=('white', 'black'), pad=(0,0), key='_close_'), + sg.RButton('', image_data=get_image_bytes(timer64), button_color=('white', 'black'), pad=(0, 0), key='_timer_'), + sg.RButton('', image_data=get_image_bytes(house64), button_color=('white', 'black'), pad=(0, 0), key='_house_'), + ]] + + # layout = toolbar_buttons + layout = [[sg.Frame('Launcher', toolbar_buttons,title_color='white', background_color='black')]] + + window = sg.Window('Toolbar', no_titlebar=True, grab_anywhere=True, background_color='black').Layout(layout) + + # ---===--- Loop taking in user input --- # + while True: + button, value = window.Read() + print(button) + if button == '_close_' or button is None: + break # exit button clicked + elif button == '_timer_': + pass # add your call to launch a timer program + elif button == '_cpu_': + pass # add your call to launch a CPU measuring utility +if __name__ == '__main__': + ShowMeTheButtons() + diff --git a/Demo_Toolbar/Mike_Toolbar.py b/Demo_Toolbar/Mike_Toolbar.py new file mode 100644 index 000000000..67af45171 --- /dev/null +++ b/Demo_Toolbar/Mike_Toolbar.py @@ -0,0 +1,27 @@ +import PySimpleGUI as sg +import os + +BUTTON_PATH = 'C:/Python/PycharmProjects/GooeyGUI/ButtonGraphics/Good ones/For toolbar' +button_names = ('close', 'cookbook', 'cpu', 'github', 'pysimplegui', 'run', 'storage', 'timer') + + +def ShowMeTheButtons(): + button_files = [os.path.join(BUTTON_PATH, b+'.png') for b in button_names] + + sg.SetOptions(auto_size_buttons=True, margins=(0,0), button_color=sg.COLOR_SYSTEM_DEFAULT) + + toolbar_buttons = [[sg.RButton('{}'.format(button_names[i]), image_size=(32,32), image_filename=f, pad=(0,0), tooltip=button_names[i]) for i, f in enumerate(button_files)],] + + layout = [[sg.Frame('', toolbar_buttons)]] + + form = sg.FlexForm('Toolbar', no_titlebar=True).Layout(layout) + + # ---===--- Loop taking in user input --- # + while True: + button, value = form.Read() + print(button) + if button == 'close' or button is None: + break # exit button clicked + +if __name__ == '__main__': + ShowMeTheButtons() \ No newline at end of file diff --git a/Demo_Toolbar/camera.png b/Demo_Toolbar/camera.png new file mode 100644 index 000000000..9f7cbc09f Binary files /dev/null and b/Demo_Toolbar/camera.png differ diff --git a/Demo_Toolbar/checkmark.png b/Demo_Toolbar/checkmark.png new file mode 100644 index 000000000..e5f4d178b Binary files /dev/null and b/Demo_Toolbar/checkmark.png differ diff --git a/Demo_Toolbar/close.png b/Demo_Toolbar/close.png new file mode 100644 index 000000000..391665608 Binary files /dev/null and b/Demo_Toolbar/close.png differ diff --git a/Demo_Toolbar/cookbook.png b/Demo_Toolbar/cookbook.png new file mode 100644 index 000000000..726234afc Binary files /dev/null and b/Demo_Toolbar/cookbook.png differ diff --git a/Demo_Toolbar/cpu.png b/Demo_Toolbar/cpu.png new file mode 100644 index 000000000..6337c8a3f Binary files /dev/null and b/Demo_Toolbar/cpu.png differ diff --git a/Demo_Toolbar/download.png b/Demo_Toolbar/download.png new file mode 100644 index 000000000..53de7e071 Binary files /dev/null and b/Demo_Toolbar/download.png differ diff --git a/Demo_Toolbar/github.png b/Demo_Toolbar/github.png new file mode 100644 index 000000000..3245ab502 Binary files /dev/null and b/Demo_Toolbar/github.png differ diff --git a/Demo_Toolbar/house.png b/Demo_Toolbar/house.png new file mode 100644 index 000000000..e4fbd085c Binary files /dev/null and b/Demo_Toolbar/house.png differ diff --git a/Demo_Toolbar/pysimplegui.png b/Demo_Toolbar/pysimplegui.png new file mode 100644 index 000000000..4fe82d1b3 Binary files /dev/null and b/Demo_Toolbar/pysimplegui.png differ diff --git a/Demo_Toolbar/run.png b/Demo_Toolbar/run.png new file mode 100644 index 000000000..93d2892ee Binary files /dev/null and b/Demo_Toolbar/run.png differ diff --git a/Demo_Toolbar/storage.png b/Demo_Toolbar/storage.png new file mode 100644 index 000000000..fe9f038ac Binary files /dev/null and b/Demo_Toolbar/storage.png differ diff --git a/Demo_Toolbar/timer.png b/Demo_Toolbar/timer.png new file mode 100644 index 000000000..f2df8f43e Binary files /dev/null and b/Demo_Toolbar/timer.png differ diff --git a/images/GIFs/bar_striped.gif b/GIFs/bar_striped.gif similarity index 100% rename from images/GIFs/bar_striped.gif rename to GIFs/bar_striped.gif diff --git a/images/GIFs/blue_blocks.gif b/GIFs/blue_blocks.gif similarity index 100% rename from images/GIFs/blue_blocks.gif rename to GIFs/blue_blocks.gif diff --git a/images/GIFs/blue_circle.gif b/GIFs/blue_circle.gif similarity index 100% rename from images/GIFs/blue_circle.gif rename to GIFs/blue_circle.gif diff --git a/images/GIFs/blue_dots.gif b/GIFs/blue_dots.gif similarity index 100% rename from images/GIFs/blue_dots.gif rename to GIFs/blue_dots.gif diff --git a/images/GIFs/dots_pulse.gif b/GIFs/dots_pulse.gif similarity index 100% rename from images/GIFs/dots_pulse.gif rename to GIFs/dots_pulse.gif diff --git a/images/GIFs/dots_wave.gif b/GIFs/dots_wave.gif similarity index 100% rename from images/GIFs/dots_wave.gif rename to GIFs/dots_wave.gif diff --git a/images/GIFs/gray_circle.gif b/GIFs/gray_circle.gif similarity index 100% rename from images/GIFs/gray_circle.gif rename to GIFs/gray_circle.gif diff --git a/images/GIFs/gray_dots.gif b/GIFs/gray_dots.gif similarity index 100% rename from images/GIFs/gray_dots.gif rename to GIFs/gray_dots.gif diff --git a/images/GIFs/gray_spokes.gif b/GIFs/gray_spokes.gif similarity index 100% rename from images/GIFs/gray_spokes.gif rename to GIFs/gray_spokes.gif diff --git a/images/GIFs/light_blue_circle.gif b/GIFs/light_blue_circle.gif similarity index 100% rename from images/GIFs/light_blue_circle.gif rename to GIFs/light_blue_circle.gif diff --git a/images/GIFs/line_boxes.gif b/GIFs/line_boxes.gif similarity index 100% rename from images/GIFs/line_boxes.gif rename to GIFs/line_boxes.gif diff --git a/images/GIFs/line_bubbles.gif b/GIFs/line_bubbles.gif similarity index 100% rename from images/GIFs/line_bubbles.gif rename to GIFs/line_bubbles.gif diff --git a/images/GIFs/output.py b/GIFs/output.py similarity index 100% rename from images/GIFs/output.py rename to GIFs/output.py diff --git a/images/GIFs/red_circle.gif b/GIFs/red_circle.gif similarity index 100% rename from images/GIFs/red_circle.gif rename to GIFs/red_circle.gif diff --git a/images/GIFs/red_dots_ring.gif b/GIFs/red_dots_ring.gif similarity index 100% rename from images/GIFs/red_dots_ring.gif rename to GIFs/red_dots_ring.gif diff --git a/images/GIFs/ring_black_dots.gif b/GIFs/ring_black_dots.gif similarity index 100% rename from images/GIFs/ring_black_dots.gif rename to GIFs/ring_black_dots.gif diff --git a/images/GIFs/ring_blue.gif b/GIFs/ring_blue.gif similarity index 100% rename from images/GIFs/ring_blue.gif rename to GIFs/ring_blue.gif diff --git a/images/GIFs/ring_gray_segments.gif b/GIFs/ring_gray_segments.gif similarity index 100% rename from images/GIFs/ring_gray_segments.gif rename to GIFs/ring_gray_segments.gif diff --git a/images/GIFs/ring_lines.gif b/GIFs/ring_lines.gif similarity index 100% rename from images/GIFs/ring_lines.gif rename to GIFs/ring_lines.gif diff --git a/images/GIFs/squish.gif b/GIFs/squish.gif similarity index 100% rename from images/GIFs/squish.gif rename to GIFs/squish.gif diff --git a/HowDoI/PySimpleGUI-HowDoI.py b/HowDoI/PySimpleGUI-HowDoI.py new file mode 100644 index 000000000..7df8a04e5 --- /dev/null +++ b/HowDoI/PySimpleGUI-HowDoI.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python +import sys +if sys.version_info[0] >= 3: + import PySimpleGUI as sg +else: + import PySimpleGUI27 as sg +import subprocess + + +# Test this command in a dos window if you are having trouble. +HOW_DO_I_COMMAND = 'python -m howdoi.howdoi' + +# if you want an icon on your taskbar for this gui, then change this line of code to point to the ICO file +DEFAULT_ICON = './QuestionMark.ico' + +def HowDoI(): + ''' + Make and show a window (PySimpleGUI form) that takes user input and sends to the HowDoI web oracle + Excellent example of 2 GUI concepts + 1. Output Element that will show text in a scrolled window + 2. Non-Window-Closing Buttons - These buttons will cause the form to return with the form's values, but doesn't close the form + :return: never returns + ''' + # ------- Make a new Window ------- # + sg.ChangeLookAndFeel('GreenTan') # give our form a spiffy set of colors + + layout = [ + [sg.Text('Ask and your answer will appear here....', size=(40, 1))], + [sg.Output(size=(127, 30), font=('Helvetica 10'))], + [ sg.Spin(values=(1, 2, 3, 4), initial_value=1, size=(2, 1), key='Num Answers', font='Helvetica 15'), + sg.Text('Num Answers',font='Helvetica 15'), sg.Checkbox('Display Full Text', key='full text', font='Helvetica 15'), + sg.T('Command History', font='Helvetica 15'), sg.T('', size=(40,3), text_color=sg.BLUES[0], key='history')], + [sg.Multiline(size=(85, 5), enter_submits=True, key='query', do_not_clear=False), + sg.ReadButton('SEND', button_color=(sg.YELLOWS[0], sg.BLUES[0]), bind_return_key=True), + sg.Button('EXIT', button_color=(sg.YELLOWS[0], sg.GREENS[0]))] + ] + + window = sg.Window('How Do I ??', + default_element_size=(30, 2), + font=('Helvetica',' 13'), + default_button_element_size=(8,2), + icon=DEFAULT_ICON, + return_keyboard_events=True).Layout(layout) + + # ---===--- Loop taking in user input and using it to query HowDoI --- # + command_history = [] + history_offset = 0 + while True: + (button, value) = window.Read() + if button == 'SEND': + query = value['query'].rstrip() + print(query) + QueryHowDoI(query, value['Num Answers'], value['full text']) # send the string to HowDoI + command_history.append(query) + history_offset = len(command_history)-1 + window.FindElement('query').Update('') # manually clear input because keyboard events blocks clear + window.FindElement('history').Update('\n'.join(command_history[-3:])) + elif button in (None, 'EXIT'): # if exit button or closed using X + break + elif 'Up' in button and len(command_history): # scroll back in history + command = command_history[history_offset] + history_offset -= 1 * (history_offset > 0) # decrement is not zero + window.FindElement('query').Update(command) + elif 'Down' in button and len(command_history): # scroll forward in history + history_offset += 1 * (history_offset < len(command_history)-1) # increment up to end of list + command = command_history[history_offset] + window.FindElement('query').Update(command) + elif 'Escape' in button: # clear currently line + window.FindElement('query').Update('') + + +def QueryHowDoI(Query, num_answers, full_text): + ''' + Kicks off a subprocess to send the 'Query' to HowDoI + Prints the result, which in this program will route to a gooeyGUI window + :param Query: text english question to ask the HowDoI web engine + :return: nothing + ''' + howdoi_command = HOW_DO_I_COMMAND + full_text_option = ' -a' if full_text else '' + t = subprocess.Popen(howdoi_command + ' \"'+ Query + '\" -n ' + str(num_answers)+full_text_option, stdout=subprocess.PIPE) + (output, err) = t.communicate() + print('{:^88}'.format(Query.rstrip())) + print('_'*60) + print(output.decode("utf-8") ) + exit_code = t.wait() + +if __name__ == '__main__': + HowDoI() + diff --git a/HowDoI/QuestionMark.ico b/HowDoI/QuestionMark.ico new file mode 100644 index 000000000..dee9a36e9 Binary files /dev/null and b/HowDoI/QuestionMark.ico differ diff --git a/HowDoI/readme.md b/HowDoI/readme.md new file mode 100644 index 000000000..a90ac8743 --- /dev/null +++ b/HowDoI/readme.md @@ -0,0 +1,46 @@ +# PySimpleGUI-HowDoI + +## Introduction +This package contains a GUI front-end to the AMAZING tool, HowDoI. You can ask this tool any programming question and it will tap into the enormous database of programming questions and answers, StackOverflow. + +This program takes you question and returns CODE as a response. + +The way it works is that it searches StackOverflow, gets the results and then finds the highest voted answer. From that answer it takes the code it finds and that is what is returned to you. It works shockingly well. + +To learn more about HowDoI, visit their GitHub site: +https://github.com/gleitz/howdoi + + + +![snag-0081](https://user-images.githubusercontent.com/13696193/46911287-3a151580-cf25-11e8-8328-f36fda446c4b.jpg) + + +Check out this example. This was not rehearsed. While typing this readme, an example was needed and a random question, that I've never asked before, was posed. Once again this program delivered a great answer. + +You can copy and paste the solution right into your code if you wish. + +## Installing + +When you install PySimpleGUI-HowDoI, it will install the other components that it requires. To install, on windows, type this into a command prompt: + + pip install pysimplegui-howdoi + + +## Running the GUI Program + +Afer your Pip install completes you can run the program. Do run it, type this into your command prompt: + + python -m pysimplegui-howdoi.pysimplegui-howdoi + +Once running you simply type in your question and press enter or click the "SEND" button. If you want to ask a question again, you can use the arrow keys or your mouse wheel to access the history of questions you've previously asked. + +Ask ANY question you want for ANY programming language. I recommend starting the question with the programming language. + + +## PySimpleGUI Project + +This program was built as a sample application of the PySimpleGUI GUI Framework. It quickly became a tool I was unable to live without. I've been trying for some time to bring it to life for others to try. + +## Windows Only? + +This has only been tested using Windows. I have not gotten it to work under Linux. The linkage between the program and the howdoI package was messed up on Linux. If you're able to get a Linux version running, please let me know at info@PySimpleGUI.org diff --git a/LICENSE.txt b/LICENSE.txt deleted file mode 100644 index 6a6cce6db..000000000 --- a/LICENSE.txt +++ /dev/null @@ -1,591 +0,0 @@ -PySimpleGUI License Agreement - -Version 1.1, Last updated: March 26, 2024 - -This PySimpleGUI License Agreement (the "Agreement") governs the use, -reproduction, distribution, modification and all other exploitation of -PySimpleGUI. The Agreement is made by and between PySimpleSoft, Inc. -("Licensor") and the person or legal entity using PySimpleGUI hereunder -("Licensee" and, together with Licensor, the "Parties"). - -If you are using PySimpleGUI on behalf of a legal entity such as an employer, -then "Licensee" means that legal entity, and you represent and warrant that you -have the authority and capacity to enter into this Agreement on behalf of -Licensee. - -"PySimpleGUI" consists of the following materials: -* the PySimpleGUI software library, version 5.0 or later (the "Library"); -* the PySimpleGUI Library documentation (the "Documentation"); -* sample programs demonstrating use of the Library (the "Demo Programs"); and -* utility programs relating to PySimpleGUI (the "Utilities"). - -PySimpleGUI may require you to obtain and use third-party software which is -distributed under separate license terms. Any such software is not considered -"PySimpleGUI" hereunder and is subject solely to such separate license terms. - -PySimpleGUI is made available to Licensee pursuant to this Agreement for the -purpose of (1) pursuant to Section 1.2, enabling Authorized Developers to use -the Library in connection with developing Licensee Applications, and to use the -Documentation, the Demo Programs and the Utilities in connection therewith; and -(2) pursuant to Section 1.3, enabling End Users of the Licensee Applications to -execute the Library as a dependency of the Licensee Applications; each as -defined and more fully set forth herein and subject to the limitations set -forth herein. - -Licensor agrees to license PySimpleGUI to Licensee only in accordance with the -terms of this Agreement. By using PySimpleGUI, Licensee agrees to be bound by -the terms of this Agreement. If you do not agree to the terms of this -Agreement, you may not copy, use, distribute, modify or otherwise attempt to -exploit PySimpleGUI. - -Licensee acknowledges that Licensor may from time to time update or modify this -Agreement, by publishing a new version of this Agreement on Licensor's website. -Licensee may continue to use the version of PySimpleGUI that it previously -obtained under the prior version of this Agreement, but any version of -PySimpleGUI received or used thereafter shall be subject to the updated version -of this Agreement. - -Accordingly, in consideration of the mutual covenants set forth herein, the -receipt and sufficiency of which is hereby acknowledged, the Parties agree as -follows. - -1. Authorized Developers; License Grants; Limitations. - -1.1. Definitions. As used herein: - -* "Authorized Developer" means any individual person who has registered on - Licensor's site at https://PySimpleGUI.com (the "Site") to develop one or - more of Licensee's own applications which make use of the Library as a - dependency in accordance with Section 1.5 (collectively, "Licensee - Applications") and is either (1) a Hobbyist Developer; or (2) a Commercial - Developer who has purchased an active PySimpleGUI paid license hereunder - which is fully paid up pursuant to Section 3. - -* "Hobbyist Developer" means any individual who uses PySimpleGUI for - development purposes solely for either or both of the following: (1) personal - (e.g., not on behalf of an employer or other third party), Non-Commercial - purposes; or (2) Non-Commercial educational or learning purposes (1 and 2 - together, the "Permitted No-cost Purposes"). - -* "Commercial Developer" means any individual who uses PySimpleGUI for - development purposes who is not a Hobbyist Developer. - -As used in this Section 1, "Non-Commercial" means use which is both (1) not on -behalf or for the benefit of any company or other organization; and (2) not -involving the receipt of any commercial advantage or monetary compensation. If -you have questions about whether your contemplated use is "Non-Commercial," -please contact us at license@pysimplegui.com. - -For the avoidance of doubt: - -* Only Authorized Developers (e.g., Hobbyist Developers and Commercial - Developers who satisfy the requirements for Authorized Developers) may use - PySimpleGUI for development purposes. - -* A Hobbyist Developer may not use PySimpleGUI for any development purpose - other than the Permitted No-cost Purposes. - -* Only Commercial Developers may use PySimpleGUI to develop Licensee - Applications for any commercial purpose; for the benefit of, on behalf of or - on computer hardware belonging to an employing company or other organization; - or for commercial educational purposes, such as the development of a paid - training course. - -If you have questions about whether your contemplated Licensee Application -would be a Permitted No-cost Purpose subject to a Hobbyist Developer license, -please contact us at license@pysimplegui.com. - -1.2. Development License Grants. Subject to the terms and conditions of this -Agreement: - -1.2.1. Library. Licensor grants Licensee a limited, personal, revocable, -non-exclusive, non-sublicensable, non-transferable license during the Term (1) -for its Authorized Developers to internally install, use, reproduce and modify -the Library to develop Licensee Applications; and (2) to redistribute the -Library to recipients of its Licensee Applications ("End Users"); provided, -that such redistribution may not include publishing the source code of the -Library (in modified or unmodified form) in a publicly accessible website or -repository or in other publicly accessible form. - -1.2.2. Documentation. Licensor grants Licensee a limited, personal, revocable, -non-exclusive, non-sublicensable, non-transferable license during the Term for -its Authorized Developers to internally access, use, and reproduce a reasonable -number of copies of the Documentation for the sole purpose of facilitating the -use of the Library by Licensee Applications in accordance with this Agreement. -For the avoidance of doubt, Licensee may not modify or redistribute the -Documentation. - -1.2.3. Demo Programs. Licensor grants Licensee a limited, personal, revocable, -non-exclusive, non-sublicensable, non-transferable license during the Term to -install, use, execute, reproduce and modify the Demo Programs, and to -incorporate modified portions of the Demo Programs into the Licensee -Applications; provided, that (1) the Demo Programs may not be used for any -purposes other than in connection with the use of the Library; and (2) the Demo -Programs may not be (individually or as a whole) redistributed in unmodified -form or as a program with substantially similar functionality to the Demo -Programs. - -1.2.4. Utilities. Licensor grants Licensee a limited, personal, revocable, -non-exclusive, non-sublicensable, non-transferable license during the Term to -install, use, execute, reproduce and modify the Utilities, but not to -distribute or publish the Utilities or any modified version. - -1.2.5. Developer Key Required. The licenses granted in this Section 1.2 may -only be exercised by Authorized Developers. For Hobbyist Developers, these -licenses may only be exercised within the period of time during which each such -Hobbyist Developer has a then-active Developer Key pursuant to Section 3. -Licensor may in its discretion permit recipients of PySimpleGUI to make limited -use of it for a limited trial period without a Developer Key. - -1.2.6. Limitations for Hobbyist Developers. For Hobbyist Developers, the -licenses granted in this Section 1.2 may only be exercised for the Permitted -No-cost Purposes. - -1.2.7. Limitations on Modification of the Library. Licensee's right to modify -the Library pursuant to this Section 1.2 is further limited as follows: (a) -Licensee may not modify or extend the Library or take any other action which -has the effect of enabling bypass of the Library's protection mechanisms -requiring the use of valid Developer Keys or Distribution Keys. (b) Licensee -explicitly acknowledges and agrees that Licensor's digital signature of the -Library is only applicable to the unmodified Library as made available by -Licensor, and that any modifications to the Library will result in Licensor's -digital signature no longer applying to the modified version. - -1.2.8. Limitations on Distribution of the Library. Licensee's right to -distribute the Library (in modified or unmodified form) pursuant to this -Section 1.2 is subject to Licensee (a) including the applicable proprietary -notices set forth in Section 2.2; and (b) including the PySimpleGUI Flow-Down -License Terms set forth in Exhibit A in the license terms that Licensee uses to -distribute the Licensee Application. - -1.2.9. Distribution Keys. Commercial Developers may obtain from Licensor a -PySimpleGUI distribution key ("Distribution Key") through the Authorized -Developer's Site account and utilizing the Distribution Key through the -protection mechanism made available in the Library to permit distribution to -End Users. The Commercial Developer may use its Distribution Key to enable End -Users to install and execute the Licensee Applications, including the Library -incorporated therein, without requiring each recipient to obtain a Developer -Key or be limited to a trial period as described in Section 1.2.5. Licensee -shall be responsible for all activities occurring under Distribution Keys -obtained by its Authorized Developers and for the compliance with this -Agreement of all Licensee Applications using such Distribution Keys. - -1.3. Run-time End User License Grant. Subject to the terms and conditions of -this Agreement, Licensor grants Licensee a limited, personal, revocable, -non-exclusive, non-sublicensable, non-transferable license during the Term to -install and execute the Library solely for it and its employee End Users to -internally use the corresponding Licensee Applications with which the Library -is distributed. For the avoidance of doubt, the license set forth in this -Section 1.3 does not permit modification, external redistribution, integration -of the Library with other software, or any other use of the Library (for -development purposes or otherwise) except solely as distributed with the -unmodified Licensee Applications; any such activities are permitted only by -Authorized Developers and only to the extent permitted by Section 1.2. If the -Licensee Application does not include a valid Distribution Key from a -Commercial Developer, then the period of use of the Library within the Licensee -Application will be limited to a trial period for any End User who does not -register as an Authorized Developer hereunder. - -1.4. License Restrictions. The licenses granted to Licensee hereunder are -expressly made subject to the following limitations: except as expressly -permitted herein, Licensee may not (and shall not permit any third party to): -(a) copy all or any portion of PySimpleGUI; (b) modify or translate -PySimpleGUI; (c) reverse engineer, decompile or disassemble the Software, in -whole or in part, except solely to the extent permitted under applicable law; -(d) create derivative works based on PySimpleGUI; (e) publicly display or -publish PySimpleGUI; (f) rent, lease, sublicense, sell, distribute, assign, -transfer, or otherwise permit access to PySimpleGUI to any third party; (g) -bypass or work around any requirements for license keys, limitations on access, -or obfuscation or security mechanisms incorporated into PySimpleGUI; (h) use -PySimpleGUI for illegal or otherwise harmful purposes, including without -limitation harassment, defamation, creation or delivery of unsolicited emails -or spam, infringement of third party intellectual property rights or other -third party rights, or distribution of viruses, worms, malware or other harmful -or destructive software; (i) incorporate PySimpleGUI or any portion thereof -into any software that purports to subject it to open source software or -similar license terms, including any prior version of PySimpleGUI (modified or -unmodified) which was previously distributed under such licenses; or (j) -exercise any other right to PySimpleGUI not expressly granted in this -Agreement. - -1.5. Licensee Application Prohibitions. Notwithstanding anything else in -this Agreement, Licensee shall ensure that Licensee Applications (a) do not -have the purpose, intent or functionality of enabling End Users to make further -use of PySimpleGUI for their own development purposes or to carry out any -activities otherwise restricted or prohibited hereunder; (b) do not have a -substantially similar purpose to PySimpleGUI; (c) do not enable End Users to -interact, integrate or otherwise develop user interfaces via direct or indirect -access to PySimpleGUI's functionality; and (d) are not intended or designed for -use in high-risk use cases that could reasonably result in death, severe bodily -injury, or other physical property or environmental damage. - -1.6. No Use with Earlier Versions of PySimpleGUI. For the avoidance of -doubt, no portions of PySimpleGUI distributed under this Agreement may be used -in connection with, or in any way incorporated with or into, any versions of -the PySimpleGUI library prior to version 5.0 that have been distributed under -the GNU Lesser General Public License. - -1.7. Additional Grant to Python Software Foundation. With regards to -portions of PySimpleGUI that Licensor uploads to PyPI, Python Software -Foundation ("PSF") may copy and redistribute such portions unmodified on PyPI -in the form provided by Licensor, with no further action required by PSF. - -1.8. Prohibition on Training Artificial Intelligence. As used herein, -"Artificial Intelligence" means a system or model that is intended to generate -or identify patterns in code or data, produce insights or correlations, or make -predictions, recommendations, or decisions; in each case, where the system or -model operates using machine learning, neural networks, large language models, -or other approaches designed to approximate cognitive abilities. Licensee shall -not (and shall not directly or indirectly permit or assist anyone else to) use -PySimpleGUI, or any part thereof, to train an Artificial Intelligence that is -offered to third parties on a commercial basis or as part of a larger -commercial offering. The preceding sentence does not prohibit use of -PySimpleGUI in conjunction with an Artificial Intelligence in other ways, such -as developing a front-end user interface. - -2. Intellectual Property Ownership; Notices. - -2.1. Licensor Ownership. PySimpleGUI is not sold to Licensee, and all rights -not expressly granted herein are reserved to Licensor. As between the parties, -Licensor and its licensors own all right, title and interest in and to -PySimpleGUI and any part thereof, including, without limitation, all -copyrights, patents, trademarks, trade secrets or other intellectual property -or proprietary rights. - -2.2. Proprietary Notices. Licensee shall not modify or remove any copyright -or patent notices or other proprietary notices or markings from any portion of -PySimpleGUI (whether modified or unmodified) without Licensor's explicit -written permission. Licensor shall ensure that any Licensee Applications that -use the Library include a notice in the following form within the Licensee -Application as well as any corresponding Licensee documentation or materials: - -For unmodified versions of PySimpleGUI: - - This product includes PySimpleGUI (https://PySimpleGUI.com). PySimpleGUI - is Copyright (c) PySimpleSoft, Inc. and/or its licensors. Use of - PySimpleGUI is subject to the license terms available at - https://PySimpleGUI.com/eula - - PYSIMPLEGUI IS PROVIDED "AS IS," WITHOUT ANY WARRANTIES, WHETHER EXPRESS OR - IMPLIED. PYSIMPLESOFT DISCLAIMS ALL IMPLIED WARRANTIES, INCLUDING WITHOUT - LIMITATION THE IMPLIED WARRANTIES OF NONINFRINGEMENT, TITLE, - MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - -For modified versions of PySimpleGUI: - - This product includes a modified version of PySimpleGUI - (https://PySimpleGUI.com). PySimpleGUI is Copyright (c) PySimpleSoft, Inc. - and/or its licensors. Use of PySimpleGUI is subject to the license terms - available at https://PySimpleGUI.com/eula - - PYSIMPLEGUI IS PROVIDED "AS IS," WITHOUT ANY WARRANTIES, WHETHER EXPRESS OR - IMPLIED. PYSIMPLESOFT DISCLAIMS ALL IMPLIED WARRANTIES, INCLUDING WITHOUT - LIMITATION THE IMPLIED WARRANTIES OF NONINFRINGEMENT, TITLE, - MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - -If the Licensee Application or the corresponding Licensee documentation or -materials include Licensee's copyright notices or other third parties' notices, -then Licensee shall include the above notice together with such notices. - -2.3. Licensor Marks. As between the parties hereto, all of Licensor's -trademarks and service marks applicable to Licensor or PySimpleGUI -(collectively, the "Licensor Marks") are the sole property of Licensor and/or -its licensors. Subject to the terms and conditions of this Agreement, Licensor -grants Licensee a limited, personal, revocable, non-exclusive, -non-sublicensable, non-transferable license to use the Licensor Mark -"PySimpleGUI" in connection with Licensee's permitted distribution of the -Library hereunder. The license set forth in this Section 2.3 is explicitly -conditioned on (a) Licensee's agreement not to challenge Licensor's ownership -of the Licensor Marks at any time during the Term or thereafter; (b) Licensee -ensuring that any modified version of the Library is clearly and prominently -noted as such; (c) Licensee complying with all trademark usage guidelines and -requirements that Licensor may publish from time to time; and (d) Licensee -immediately correcting incorrect usage of the Licensor Marks upon request from -Licensor. Licensee shall immediately cease usage of the Licensor Marks upon -written notice thereof from Licensor. All goodwill arising from use of the -Licensor Marks shall inure to the benefit of Licensor. - -3. Developer Keys; Fees and Payments. - -3.1. Developer Keys. In order to develop Licensee Applications pursuant to -Section 1.2 (and subject to any limited trial period usage as may be permitted -by Licensor from time to time), each Authorized Developer shall obtain a -PySimpleGUI developer license key ("Developer Key") by registering on the -Site as set forth therein. Each Developer Key is personal to the specific -Authorized Developer, and Licensee shall not permit Authorized Developers to -disclose, share or reuse Developer Keys. For the avoidance of doubt, any -disclosure, sharing or reuse of a Developer Key by Licensee's Authorized -Developers, whether or not authorized by Licensee, shall be a material breach -permitting termination of this Agreement pursuant to Section 8.3. Developer -Keys are Licensor's Confidential Information pursuant to Section 5. Developer -Keys are limited to a specified time period (which shall be annual from the -start date of the Developer Key, unless otherwise explicitly stated by -Licensor). Upon the expiration of a Developer Key for a Hobbyist Developer, -they may no longer use the Developer Key and must obtain a new Developer Key -from the Site in order to continue using PySimpleGUI for development purposes -pursuant to Section 1.2. Upon the expiration of a Developer Key for a -Commercial Developer, they may continue to use their Developer Key for versions -of PySimpleGUI released during that period, but may not obtain subsequent -updated versions under Section 4.2 unless they purchase a new Developer Key. - -3.2. Fees for Commercial Developer Keys; Taxes. Before obtaining each -Developer Key for a Commercial Developer, Licensee shall pay to Licensor the -corresponding fees as stated on the Site and using the payment mechanism made -available on the Site. All payments shall be made in United States dollars. All -amounts payable by Licensee hereunder are exclusive of taxes and similar -assessments, and Licensee is responsible for all sales, use, and excise taxes, -and any other similar taxes of any kind imposed by any federal, state, or local -governmental or regulatory authority on any amounts payable by Licensee -hereunder, excluding any taxes imposed on Licensor's income. - -3.3. Accuracy of Registration Details. Licensee represents and warrants that -(a) all information provided by it and its Authorized Developers when -registering for Developer Keys shall be truthful, accurate, complete and not -misleading, and (b) it and its Authorized Developers shall not misrepresent -their use of PySimpleGUI as qualifying for a Hobbyist Developer Key if their -use does not satisfy the Permitted No-cost Purposes. - -4. Support and Updates. - -4.1. Support. Licensor has no obligation hereunder to provide support to -Licensee or its Authorized Developers. Authorized Developers may submit -Feedback (as defined in Section 5.4) consisting of issues and bug reports to -the PySimpleGUI software repository as described on the Site or in the -Documentation. Licensor may in its sole discretion address such issues or bug -reports in current or future versions of PySimpleGUI, but has no obligation to -do so. - -4.2. Updates. Licensor has no obligation hereunder to make available updated -versions of PySimpleGUI. In the event that Licensor elects to make available an -updated version of PySimpleGUI, then Authorized Developers with a then-active -Developer Key may download and use the updated version, and the updated version -shall be included in the definition of "PySimpleGUI" thereafter for purposes of -this Agreement. - -5. Confidentiality; Feedback. - -5.1. Confidential Information. Licensee acknowledges that portions of -PySimpleGUI and certain other materials are confidential as provided herein. -"Confidential Information" means any and all information, whether provided in -writing, orally, visually, electronically or by other means, related to -Licensor's or its licensors' services and/or business that, whether it -constitutes a Trade Secret or not, is treated as confidential or secret by -Licensor (that is, it is the subject of efforts by Licensor that are reasonable -under the circumstances to maintain its secrecy), including, but not limited -to, (i) Trade Secrets as defined below; (ii) any and all other information -which is disclosed by Licensor to Licensee orally, electronically, visually, or -in a document or other tangible form which is either identified as or should be -reasonably understood to be confidential and/or proprietary; and, (iii) any -notes, extracts, analysis, or materials prepared by Licensee which are copies -of or derivative works of Licensor's or its licensors' proprietary or -confidential information from which the substance of Confidential Information -can be inferred or otherwise understood. Confidential Information shall not -include information which Licensee can clearly establish by written evidence: -(a) already is lawfully known to or independently developed by Licensee without -access to the Confidential Information or Trade Secrets, (b) is disclosed by -Licensor in non-confidential published materials, (c) is generally known to the -public, or (d) is rightfully obtained from any third party without any -obligation of confidentiality. - -5.2. Trade Secrets. As used herein, "Trade Secrets" means all non-public -information whether tangible or intangible related to Licensor's and its -licensors' services or business that (i) derives economic value, actual or -potential, from not being generally known to or readily ascertainable by other -persons who can obtain economic value from its disclosure or use; and (ii) is -the subject of efforts that are reasonable under the circumstances to maintain -its secrecy, which may include, without limitation, (a) marking any information -reduced to tangible form clearly and conspicuously with a legend identifying -its confidential or trade secret nature; (b) identifying any oral communication -as confidential or secret immediately before, during, or after such oral -communication; or (c) otherwise treating such information as confidential. - -5.3. Licensee Obligations. Licensee agrees not to disclose Confidential -Information or Trade Secrets to any third party and will protect and treat all -Confidential Information and Trade Secrets with the highest degree of care. -Except as otherwise expressly provided in this Agreement, Licensee will not use -or make any copies of Confidential Information or Trade Secrets, in whole or in -part, without the prior written authorization of Licensor. Licensee may -disclose Confidential Information or Trade Secrets if required by statute, -regulation, or order of a court of competent jurisdiction, provided that -Licensee provides Licensor with prior notice, discloses only the minimum -Confidential Information or Trade Secrets required to be disclosed, and -cooperates with Licensor in taking appropriate protective measures. These -obligations shall continue for three (3) years following termination or -expiration of this Agreement with respect to Confidential Information that does -not rise to the level of a Trade Secret and shall continue for Trade Secrets so -long as they remain Trade Secrets. - -5.4. Feedback. As used herein, "Feedback" means any comments, questions, -suggestions, issues, bug reports, or related feedback provided by Licensee to -Licensor relating to PySimpleGUI, including, without limitation, suggesting or -recommending changes to any part of PySimpleGUI, or new features or -functionality relating thereto. All Feedback is, and will be treated as, -non-confidential and non-proprietary, regardless of any markings Licensee may -apply to it. Licensee hereby assigns to Licensor all right, title, and interest -in, and Licensor is free to use without any attribution or compensation to -Licensee, any ideas, know-how, concepts, techniques, or other intellectual -property and proprietary rights contained in the Feedback, whether or not -patentable, for any purpose whatsoever, including but not limited to, -developing, manufacturing, having manufactured, licensing, marketing, and -selling, directly or indirectly, products and services using such Feedback. To -the extent the foregoing assignment of rights, title and interest in and to -Feedback is prohibited by applicable law, Licensee hereby grants Licensor a -non-exclusive, perpetual, irrevocable, royalty-free, fully paid-up, worldwide -license (including the right to sublicense through multiple tiers) to (a) fully -use, practice and exploit those non-assignable rights, title and interest, -including, but not limited to, the right to use, reproduce, adapt, publicly -perform, publicly display, modify, prepare derivative works, publish, transmit -and distribute Feedback, or any portion thereof, in any form, medium or -distribution method now known or hereafter existing, known or developed, for -any purpose, and to develop, manufacture, have manufactured, license, market, -and sell, directly or indirectly, products and services using Feedback; and (b) -authorize any such use by others of Feedback, or any portion thereof, in the -same manner. - -6. NO LICENSOR WARRANTIES; LIABILITY. - -6.1. DISCLAIMER OF WARRANTIES. PYSIMPLEGUI IS PROVIDED TO LICENSEE "AS IS". -LICENSOR DOES NOT MAKE ANY, AND HEREBY SPECIFICALLY DISCLAIMS ANY, -REPRESENTATIONS, ENDORSEMENTS, GUARANTEES, OR WARRANTIES, EXPRESS OR IMPLIED, -RELATED TO PYSIMPLEGUI INCLUDING, BUT NOT LIMITED TO, ANY IMPLIED WARRANTY OF -MERCHANTABILITY, TITLE, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT OF -INTELLECTUAL PROPERTY RIGHTS. Licensee acknowledges that Licensor does not -guarantee compatibility between PySimpleGUI and any future versions thereof, -and that Licensor makes no commitments as to future development, availability, -release or licensing of any current or future versions of PySimpleGUI. Licensee -will have sole responsibility for the adequate protection and backup of -Licensee's software, data and equipment used with PySimpleGUI. The entire risk -as to the quality and performance of PySimpleGUI and any obligation with -respect to service and support is borne by Licensee. Licensee understands that -Software hosted by Licensor for evaluation purposes may not be secure or -stable. Licensee waives any claim against Licensor which may arise as a result -of Licensee's breach of the foregoing. This Agreement does not grant Licensee -any right to any maintenance, services, including without limitation, any -support, enhancement, modification, bug fix or update to the Software, and -Licensor is under no obligation to provide or inform Licensee of any such -maintenance or services. - -6.2. DISCLAIMER OF LIABILITY. LICENSEE EXPLICITLY AGREES THAT, TO THE -MAXIMUM EXTENT PERMITTED BY LAW, LICENSOR SHALL NOT BE LIABLE UNDER ANY LEGAL -THEORY FOR ANY DAMAGES SUFFERED IN CONNECTION WITH THE USE OF THE SOFTWARE, -INCLUDING BUT NOT LIMITED TO ANY LOST PROFITS, LOST SAVINGS OR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE OR CONSEQUENTIAL DAMAGES, -WHETHER RESULTING FROM IMPAIRED OR LOST DATA, SOFTWARE OR COMPUTER FAILURE, THE -LICENSEE APPLICATIONS, OR ANY OTHER CAUSE, BY LICENSEE OR ANY OTHER THIRD -PARTY, EVEN IF IT HAS BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. -LICENSEE HEREBY EXPRESSLY RELEASES LICENSOR FROM ANY AND ALL LIABILITY OR -RESPONSIBILITY TO ANY DAMAGE CAUSED, DIRECTLY OR INDIRECTLY, TO LICENSEE OR ANY -THIRD PARTY AS A RESULT OF THE USE OF THE SOFTWARE OR THE INSTALLATION THEREOF -INTO LICENSEE'S COMPUTER ENVIRONMENT. IN THE EVENT THAT THE DISCLAIMERS OF -LIABILITY SET FORTH HEREIN ARE HELD TO BE UNENFORCEABLE, THE PARTIES AGREE THAT -UNDER NO CIRCUMSTANCES SHALL LICENSOR'S AGGREGATE LIABILITY HEREUNDER OR IN -CONNECTION WITH THIS AGREEMENT EXCEED THE AMOUNTS PAID BY LICENSEE TO LICENSOR -IN THE 12 MONTHS PRECEDING THE DATE THAT A CLAIM FIRST ACCRUES. LICENSEE SHALL -BRING ANY CLAIM AGAINST LICENSOR WITHIN 12 MONTHS OF THE DATE THAT THE CLAIM -FIRST ACCRUES, AND HEREBY WAIVES ANY CLAIMS THAT IT DOES NOT BRING WITHIN SUCH -TIME PERIOD. - -6.3. Essential Terms. THIS SECTION 6 IS AN ESSENTIAL BASIS OF LICENSOR'S -DECISION TO OFFER PYSIMPLEGUI, AND SHALL APPLY REGARDLESS OF THE LEGAL THEORY -UPON WHICH DAMAGES MAY BE CLAIMED; REGARDLESS OF WHETHER A PARTY KNEW OR SHOULD -HAVE KNOWN OF THE POSSIBILITY OF SUCH DAMAGES; AND REGARDLESS OF WHETHER THE -FOREGOING LIMITATIONS OF LIABILITY CAUSE ANY REMEDY TO FAIL IN ITS ESSENTIAL -PURPOSE. - -7. Indemnification. Licensee agrees to defend, indemnify and hold Licensor -and its directors, officers, employees and representatives harmless for any -claims, expenses, losses, costs, fees (including attorneys' fees) or damages of -any sort resulting from (a) Licensee's breach of this Agreement; (b) Licensee's -use of PySimpleGUI or exercise of the license rights granted hereunder; or (c) -the Licensee Applications, or Licensee's or any third party's use thereof. - -8. Term and Termination. - -8.1. Term. This Agreement shall commence on the date on which Licensee -downloads PySimpleGUI or otherwise obtains a copy of PySimpleGUI, and shall -continue thereafter until terminated as set forth herein. - -8.2. Termination by Licensee. Licensee may terminate this Agreement with -written notice to Licensor, effective upon Licensee destroying all copies of -PySimpleGUI in its possession and refraining from receiving or downloading -further copies. - -8.3. Termination for Licensee's Breach. This limited License will -immediately terminate without notice if Licensee fails to comply with any -obligation of this Agreement. Additionally, if Licensor reasonably suspects -that Licensee has breached the Agreement, then Licensor may deliver written -notice of the suspected breach to Licensee, and the Agreement shall -automatically terminate 10 days following the date of such notice unless -Licensee cures the breach to Licensor's satisfaction within such period. - -8.4. Effect of Termination; Survival. Upon termination of this Agreement for -any reason, the licenses granted to Licensee with respect to PySimpleGUI shall -immediately terminate and Licensee hereby undertakes to: (i) immediately cease -to use, distribute or otherwise exploit any part of PySimpleGUI or any modified -version thereof; and (ii) promptly destroy and delete any copy of PySimpleGUI -installed or copied by Licensee. Sections 2.1, 2.3, 3, 5-7, 8.4, 9 and 10 will -survive termination of this Agreement indefinitely in accordance with their -terms. - -9. Assignment; Governing Law. The License is personal to Licensee and -Licensee agrees not to transfer, sublicense, lease, rent, or assign their -rights under this Agreement, and any such attempt shall be null and void. -Licensor may assign, transfer, or sublicense this Agreement or any rights or -obligations thereunder at any time in its sole discretion. This Agreement shall -be governed by and construed in accordance with the laws of the State of North -Carolina and the United States of America without regard to the conflicts of -laws provisions thereof. The parties expressly exclude the United Nations -Convention on Contracts for the International Sale of Goods from this -Agreement. All actions arising out of or in connection with this Agreement -shall be brought in the state or federal courts residing in Durham, North -Carolina, United States of America, and both parties hereby irrevocably consent -to the exclusive jurisdiction of such courts and waive any objections as to -venue or inconvenience of forum. - -10. Miscellaneous. No changes or modifications to this Agreement by -Licensee or waivers of any provision of this Agreement by Licensor shall be -effective unless evidenced in a writing referencing this Agreement and signed -for and on behalf of Licensor. The failure of Licensor to enforce its rights -under this Agreement at any time for any period shall not be construed as a -waiver of such rights. There are no third party beneficiaries hereunder. This -Agreement constitutes the entire agreement between the parties regarding the -subject matter hereof and supersede all negotiations, conversations, or -discussions between or among the parties relating to the subject matter of this -Agreement. Neither Party relied on any promises or representations, written or -oral, of the other party in forming this Agreement, except for those expressly -contained herein. In the event that any provision of this Agreement shall be -determined to be unenforceable, that provision will be limited or eliminated to -the minimum extent necessary so that this Agreement shall otherwise remain in -full force and effect and enforceable. Licensee may not distribute, download or -otherwise export or re-export PySimpleGUI or any underlying technology except -in full compliance with this Agreement, United States laws and regulations and -any other applicable laws and regulations. Licensee represents and warrants -that it and its Authorized Developers are not located in, under control of, or -a national or resident of any country where exercise of the licenses granted -hereunder would not comply with all such laws or regulations. It is agreed that -because of the proprietary nature of PySimpleGUI, Licensor's remedies at law -for a breach by the Licensee of its obligations under this Agreement may be -inadequate and that Licensor will, in the event of such breach, be entitled to, -in addition to any other remedy available to it, equitable relief, including -injunctive relief, without the posting of any bond and in addition to all other -remedies provided under this Agreement or available at law. - -Exhibit A - -PySimpleGUI Flow-Down License Terms - -This product (the "Product") includes PySimpleGUI (https://PySimpleGUI.com) or -a version of PySimpleGUI modified by the person or legal entity that provided -you with this product ("Provider"). - -PySimpleGUI is Copyright (c) PySimpleSoft, Inc. and/or its licensors. - -Use of PySimpleGUI is subject to the license terms available at -https://PySimpleGUI.com/eula, including all limitations of liability and other -terms set forth therein. By using the Product, you acknowledge and agree that -PySimpleSoft has no obligation or liability to you regarding the operation, -support or maintenance of PySimpleGUI or of the Product. PYSIMPLEGUI IS -PROVIDED "AS IS," WITHOUT ANY WARRANTIES, WHETHER EXPRESS OR IMPLIED. -PYSIMPLESOFT DISCLAIMS ALL IMPLIED WARRANTIES, INCLUDING WITHOUT LIMITATION THE -IMPLIED WARRANTIES OF NONINFRINGEMENT, TITLE, MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE. diff --git a/ProgrammingClassExamples/MacOS versions/10a PSG Plot (Matplotlib numpy pyplot(y=sinx)) .py b/ProgrammingClassExamples/MacOS versions/10a PSG Plot (Matplotlib numpy pyplot(y=sinx)) .py new file mode 100644 index 000000000..0343059c7 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/10a PSG Plot (Matplotlib numpy pyplot(y=sinx)) .py @@ -0,0 +1,65 @@ +#matplotlib, numpy, pyplot +#Tony Crewe +#Oct 2018 MacOS + +import PySimpleGUI as sg +import matplotlib +# added this to work with MacOs +matplotlib.use('TkAgg') +import matplotlib.pyplot as plt +from matplotlib.backends.backend_tkagg import FigureCanvasAgg +import matplotlib.backends.tkagg as tkagg +import numpy as np +import tkinter as tk + +""" +Demonstrates one way of embedding Matplotlib figures into a PySimpleGUI window. +Adapted: From https://gitlab.com/lotspaih/PySimpleGUI/tree/master + +Basic steps are: + * Create a Canvas Element + * Layout form + * Display form (NON BLOCKING) + * Draw plots onto convas + * Display form (BLOCKING) +""" + +#No exactly sure how all this works, but taken from example given as a template. +def draw_figure(canvas, figure, loc = (0,0)): + + figure_canvas_agg = FigureCanvasAgg(figure) + figure_canvas_agg.draw() + figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds + figure_w, figure_h = int(figure_w), int(figure_h) + photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h) + canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo) + tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2) + return photo + + +#------------ Matplotlib code ---------------------- +#see https://matplotlib.org/ +fig = plt.figure() +ax = fig.add_subplot(111) +#x-values +x = np.linspace(-np.pi*2, np.pi*2, 100) +#y-values +y = np.sin(x) +plt.plot(x,y) + +ax.set_title('sin(x)') +figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds + +#------------End Matplotlib code -------------------- + +layout = [[sg.Text('Plot Test - PySimpleGUI and Matplotlib', font = ('Calibri', 18, 'bold'))], + [sg.Canvas(size = (figure_w, figure_h), key = '_canvas_')], + [sg.OK(pad=((figure_w / 2, 0), 3), size=(6, 2))]] + +window = sg.Window('Matplot in PySimpleGUI', force_toplevel = True).Layout(layout).Finalize() + +fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig) + +button, value = window.Read() + + diff --git a/ProgrammingClassExamples/MacOS versions/10b PSG Plot (axes moved).py b/ProgrammingClassExamples/MacOS versions/10b PSG Plot (axes moved).py new file mode 100644 index 000000000..f20bce435 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/10b PSG Plot (axes moved).py @@ -0,0 +1,57 @@ +#matplotlib, numpy, pyplot +#Tony Crewe +#Oct 2018 MacOS + +import PySimpleGUI as sg +import matplotlib +# added this to work with MacOs +matplotlib.use('TkAgg') +import matplotlib.pyplot as plt +from matplotlib.backends.backend_tkagg import FigureCanvasAgg +import matplotlib.backends.tkagg as tkagg +import numpy as np +import tkinter as tk + +def draw_figure(canvas, figure, loc = (0,0)): + + figure_canvas_agg = FigureCanvasAgg(figure) + figure_canvas_agg.draw() + figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds + figure_w, figure_h = int(figure_w), int(figure_h) + photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h) + canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo) + tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2) + return photo + + +#------------ Matplotlib code -------------------- +fig=plt.figure() +ax = fig.add_subplot(111) +x = np.linspace(-np.pi*2, np.pi*2, 100) +y= np.sin(x) +plt.plot(x,y) + +ax.set_title('sin(x)') + +#centre bottom and left axes to zero + +ax.spines['left'].set_position('zero') +ax.spines['right'].set_color('none') +ax.spines['bottom'].set_position('zero') +ax.spines['top'].set_color('none') + +figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds + +#------------End Matplotlib code -------------------- + +layout = [[sg.Text('Plot Test - PySimpleGUI and Matplotlib (axes centred)', font = ('Calibri', 18, 'bold'))], + [sg.Canvas(size = (figure_w, figure_h), key = '_canvas_')], + [sg.OK(pad=((figure_w / 2, 0), 3), size=(6, 2))]] + +window = sg.Window('Matplot in PySimpleGUI', force_toplevel = True).Layout(layout).Finalize() + +fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig) + +button, value = window.Read() + + diff --git a/ProgrammingClassExamples/MacOS versions/10c PSG Plot (axes pi format).py b/ProgrammingClassExamples/MacOS versions/10c PSG Plot (axes pi format).py new file mode 100644 index 000000000..721ffbad2 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/10c PSG Plot (axes pi format).py @@ -0,0 +1,73 @@ +#matplotlib, numpy, pyplot +#Tony Crewe +#Oct 2018 MacOS + +import PySimpleGUI as sg +import matplotlib +# added this to work with MacOs +matplotlib.use('TkAgg') +import matplotlib.pyplot as plt +import matplotlib.ticker as ticker +from matplotlib.backends.backend_tkagg import FigureCanvasAgg +import matplotlib.backends.tkagg as tkagg +import numpy as np +import tkinter as tk + + + +""" +Demonstrates one way of embedding Matplotlib figures into a PySimpleGUI window. + +Basic steps are: + * Create a Canvas Element + * Layout form + * Display form (NON BLOCKING) + * Draw plots onto convas + * Display form (BLOCKING) +""" + +def draw_figure(canvas, figure, loc = (0,0)): + + figure_canvas_agg = FigureCanvasAgg(figure) + figure_canvas_agg.draw() + figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds + figure_w, figure_h = int(figure_w), int(figure_h) + photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h) + canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo) + tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2) + return photo + + +#------------ Matplotlib code -------------------- +fig=plt.figure() +ax = fig.add_subplot(111) +x = np.linspace(-np.pi*2, np.pi*2, 100) +y= np.sin(x) +plt.plot(x/np.pi,y) + +ax.set_title('sin(x)') +#centre bottom and left axes to zero + +ax.spines['left'].set_position('zero') +ax.spines['right'].set_color('none') +ax.spines['bottom'].set_position('zero') +ax.spines['top'].set_color('none') + +#Format axes - nicer eh! +ax.xaxis.set_major_formatter(ticker.FormatStrFormatter('%g $\pi$')) + +figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds + +#------------End Matplotlib code -------------------- + +layout = [[sg.Text('Plot Test - PySimpleGUI and Matplotlib (axes pi format)', font = ('Calibri', 18, 'bold'))], + [sg.Canvas(size = (figure_w, figure_h), key = '_canvas_')], + [sg.OK(pad=((figure_w / 2, 0), 3), size=(6, 2))]] + +window = sg.Window('Matplot in PySimpleGUI', force_toplevel = True).Layout(layout).Finalize() + +fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig) + +button, value = window.Read() + + diff --git a/ProgrammingClassExamples/MacOS versions/10d PSG (Plots Tabs and sin cos options).py b/ProgrammingClassExamples/MacOS versions/10d PSG (Plots Tabs and sin cos options).py new file mode 100644 index 000000000..203c3281e --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/10d PSG (Plots Tabs and sin cos options).py @@ -0,0 +1,100 @@ +#matplotlib, numpy, pyplot +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg +import matplotlib +# added this to work with MacOs +matplotlib.use('TkAgg') +import matplotlib.pyplot as plt +import matplotlib.ticker as ticker +from matplotlib.backends.backend_tkagg import FigureCanvasAgg +import matplotlib.backends.tkagg as tkagg +import numpy as np +import tkinter as tk + +sg.SetOptions (background_color = 'LightBlue', + element_background_color = 'LightBlue', + text_element_background_color = 'LightBlue', + font = ('Arial', 14, 'bold'), + text_color = 'DarkBlue', + input_text_color ='DarkBlue', + button_color = ('DarkBlue', 'White')) + +def draw_figure(canvas, figure, loc = (0,0)): + + figure_canvas_agg = FigureCanvasAgg(figure) + figure_canvas_agg.draw() + figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds + figure_w, figure_h = int(figure_w), int(figure_h) + photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h) + canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo) + tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2) + return photo + + +#------------ Matplotlib code -------------------- + +def set_plot(amp, function): + global figure_w, figure_h, fig + fig=plt.figure() + ax = fig.add_subplot(111) + x = np.linspace(-np.pi*2, np.pi*2, 100) + if function == 'sine': + y= amp*np.sin(x) + ax.set_title('sin(x)') + else: + y=amp*np.cos(x) + ax.set_title('cos(x)') + plt.plot(x/np.pi,y) + + + #centre bottom and left axes to zero + + ax.spines['left'].set_position('zero') + ax.spines['right'].set_color('none') + ax.spines['bottom'].set_position('zero') + ax.spines['top'].set_color('none') + + #Format axes - nicer eh! + ax.xaxis.set_major_formatter(ticker.FormatStrFormatter('%g $\pi$')) + + figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds +amp = 1 +function = 'sine' +set_plot(amp, function) + +#------------End Matplotlib code -------------------- + +#use Tabs - one for options, one for canvas to be displayed +#set spinner for amplitude and combo for function type + +tab1_layout = [[sg.Text('Select Amplitude and trig function type', font = ('Calibri', 18, 'bold'))], + [sg.Spin([sz for sz in range (1,5)], initial_value =1, size = (2,1), key = '_spin_'), + sg.Text('Amplitude', size = (10, 1), font = ('Calibri', 12, 'bold'))], + [sg.InputCombo(['sine', 'cosine'], size = (8, 4), key = '_function_'), + sg.Text('Function', size = (10, 1),font = ('Calibri', 12, 'bold'))], + [sg.ReadButton('Redraw Plot')], + [sg.Text('', size = (2, 25))]] + +tab2_layout = [[sg.Text('Plot Test - PySimpleGUI and Matplotlib and options', font = ('Calibri', 18, 'bold'))], + [sg.Canvas(size = (figure_w, figure_h), key = '_canvas_')], + [sg.OK(pad=((figure_w / 2, 0), 3), size=(6, 2))]] + +layout = [[sg.TabGroup([[sg.Tab('Select options', tab1_layout), sg.Tab('Display Plot', tab2_layout)]])]] +window = sg.Window('Matplot, PySimpleGUI and options', force_toplevel = True).Layout(layout).Finalize() + +fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig) + +while True: + button, value = window.Read() + if button == 'Redraw Plot': + amp = int(value['_spin_']) + function = value['_function_'] + set_plot(amp,function) + fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig) + + if button is None: + break + + diff --git a/ProgrammingClassExamples/MacOS versions/10e PSG (Same Window).py b/ProgrammingClassExamples/MacOS versions/10e PSG (Same Window).py new file mode 100644 index 000000000..041bfe541 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/10e PSG (Same Window).py @@ -0,0 +1,98 @@ +#matplotlib, numpy, pyplot +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg +import matplotlib +# added this to work with MacOs +matplotlib.use('TkAgg') +import matplotlib.pyplot as plt +import matplotlib.ticker as ticker +from matplotlib.backends.backend_tkagg import FigureCanvasAgg +import matplotlib.backends.tkagg as tkagg +import numpy as np +import tkinter as tk + +sg.SetOptions (background_color = 'LightBlue', + element_background_color = 'LightBlue', + text_element_background_color = 'LightBlue', + font = ('Arial', 14, 'bold'), + text_color = 'DarkBlue', + input_text_color ='DarkBlue', + button_color = ('DarkBlue', 'White')) + +def draw_figure(canvas, figure, loc = (0,0)): + + figure_canvas_agg = FigureCanvasAgg(figure) + figure_canvas_agg.draw() + figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds + figure_w, figure_h = int(figure_w), int(figure_h) + photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h) + canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo) + tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2) + return photo + + +#------------ Matplotlib code -------------------- + +def set_plot(amp, function): + global figure_w, figure_h, fig + fig=plt.figure() + ax = fig.add_subplot(111) + x = np.linspace(-np.pi*2, np.pi*2, 100) + if function == 'sine': + y= amp*np.sin(x) + ax.set_title('sin(x)') + else: + y=amp*np.cos(x) + ax.set_title('cos(x)') + plt.plot(x/np.pi,y) + + + #centre bottom and left axes to zero + + ax.spines['left'].set_position('zero') + ax.spines['right'].set_color('none') + ax.spines['bottom'].set_position('zero') + ax.spines['top'].set_color('none') + + #Format axes - nicer eh! + ax.xaxis.set_major_formatter(ticker.FormatStrFormatter('%g $\pi$')) + + figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds +amp = 1 +function = 'sine' +set_plot(amp, function) + +#------------End Matplotlib code -------------------- + +#using one window based on two columns instead of Tabs +column1 = [[sg.Text('Select Amplitude and trig function type', font = ('Calibri', 18, 'bold'))], + [sg.Spin([sz for sz in range (1,5)], initial_value =1, size = (2,1), key = '_spin_'), + sg.Text('Amplitude', size = (10, 1), font = ('Calibri', 12, 'bold'))], + [sg.InputCombo(['sine', 'cosine'], size = (8, 4), key = '_function_'), + sg.Text('Function', size = (10, 1),font = ('Calibri', 12, 'bold'))], + [sg.ReadButton('Redraw Plot')], + [sg.Text('', size = (1, 27))]] + +column2 = [[sg.Text('Plot Test - PySimpleGUI and Matplotlib and options', font = ('Calibri', 18, 'bold'))], + [sg.Canvas(size = (figure_w, figure_h), key = '_canvas_')], + [sg.OK(pad=((figure_w / 2, 0), 3), size=(6, 2))]] + +layout = [[sg.Column(column1), sg.Column(column2)]] +window = sg.Window('Matplot, PySimpleGUI and options', force_toplevel = True).Layout(layout).Finalize() + +fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig) + +while True: + button, value = window.Read() + if button == 'Redraw Plot': + amp = int(value['_spin_']) + function = value['_function_'] + set_plot(amp,function) + fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig) + + if button is None: + break + + diff --git a/ProgrammingClassExamples/MacOS versions/10f PSG (linear and quadratics).py b/ProgrammingClassExamples/MacOS versions/10f PSG (linear and quadratics).py new file mode 100644 index 000000000..580fa88ff --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/10f PSG (linear and quadratics).py @@ -0,0 +1,121 @@ +#matplotlib, numpy, pyplot +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg +import matplotlib +# added this to work with MacOs +matplotlib.use('TkAgg') +import matplotlib.pyplot as plt +import matplotlib.ticker as ticker +from matplotlib.backends.backend_tkagg import FigureCanvasAgg +import matplotlib.backends.tkagg as tkagg +import numpy as np +import tkinter as tk + +sg.SetOptions (background_color = 'Grey', + element_background_color = 'Grey', + text_element_background_color = 'Grey', + font = ('Arial', 14, 'bold'), + text_color = 'Black', + input_text_color ='Black', + button_color = ('Black', 'White')) + +#sg.ChangeLookAndFeel('Black') + +def draw_figure(canvas, figure, loc = (0,0)): + + figure_canvas_agg = FigureCanvasAgg(figure) + figure_canvas_agg.draw() + figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds + figure_w, figure_h = int(figure_w), int(figure_h) + photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h) + canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo) + tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2) + return photo + + +#------------ Matplotlib code -------------------- + +def set_plot(a,b,c, function): + global figure_w, figure_h, fig + fig=plt.figure() + ax = fig.add_subplot(111) + x = np.linspace(-10, 10, 100) + if function == 'y = ax + b': + y= a*x + b + if a == 1: + a = '' + if a == -1: + a = '-' + title = str('y = ') + str(a) + 'x + ' + str(b) + ax.set_title(title) + else: + y = a*x**2 + b*x + c + #avoiding getting -1x or -1x**2 instead of -x for title + if a == 1: + a = '' + if a == -1: + a = '-' + if b == 1: + b = '' + if b == -1: + b = '-' + title = str('y = ') + str(a) + 'x**2 + ' + str(b) + 'x + ' + str(c) + ax.set_title(title) + plt.plot(x,y) + + + #centre bottom and left axes to zero + + ax.spines['left'].set_position('zero') + ax.spines['right'].set_color('none') + ax.spines['bottom'].set_position('zero') + ax.spines['top'].set_color('none') + + + figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds +amp = 1 +function = 'y = ax + b' +set_plot(1,1,1, function) + +#------------End Matplotlib code -------------------- + +#column 1 for function type and constant values ... + +column1 = [ + [sg.Text('Select constants & function type', )], + [sg.InputCombo(['y = ax + b', 'y = ax^2 + bx + c'], size = (16, 4), key = '_function_'), + sg.Text('Function', size = (10, 1))], [sg.Text('', size = (1, 2))], + [sg.Spin([sz for sz in range (-6,6)], initial_value =1, size = (3,2), key = '_a_'), + sg.Text('a', size = (3, 1)), + sg.Spin([sz for sz in range (-6,6)], initial_value =1, size = (3,2), key = '_b_'), + sg.Text('b', size = (3, 1)), + sg.Spin([sz for sz in range (-6,6)], initial_value =1, size = (3,2), key = '_c_'), + sg.Text('c', size = (3, 1))], [sg.Text('', size = (1, 1))], + [sg.ReadButton('Redraw Plot', size = (14,1))], + [sg.Text('', size = (1, 14))]] + +column2 = [[sg.Text('Plot Test - PySimpleGUI and Matplotlib and options')], + [sg.Canvas(size = (figure_w, figure_h), key = '_canvas_')], + [sg.OK(pad=((figure_w / 2, 0), 1), size=(4, 1))]] + +layout = [[sg.Column(column1), sg.Column(column2)]] +window = sg.Window('Matplot, PySimpleGUI and options', force_toplevel = True).Layout(layout).Finalize() + +fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig) + +while True: + button, value = window.Read() + if button == 'Redraw Plot': + a = int(value['_a_']) + b = int(value['_b_']) + c = int(value['_c_']) + function = value['_function_'] + set_plot(a,b,c,function) + fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig) + + if button is None: + break + + diff --git a/ProgrammingClassExamples/MacOS versions/1a PSG (Entry and PopUp).py b/ProgrammingClassExamples/MacOS versions/1a PSG (Entry and PopUp).py new file mode 100644 index 000000000..86ecab1c3 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/1a PSG (Entry and PopUp).py @@ -0,0 +1,36 @@ +#PySimple examples (v 3.8) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg + +#layout, Text, Input,button on line below +layout = [ + [sg.Text('Celcius'), sg.InputText()], + [sg.Submit()], + ] + +#setup window with Title +window = sg.Window('Temperature Converter').Layout(layout) + +#get value (part of a list) +button, value = window.Read() +if button is None: + #windows was closed without button being pressed + exit(0) + +#convert and create string +fahrenheit = round(9/5*float(value[0]) +32, 1) +result = 'Temperature in Fahrenheit is: ' + str(fahrenheit) +#display in Popup +sg.Popup('Result', result) + + + + + + + + + + diff --git a/ProgrammingClassExamples/MacOS versions/1b PSG (Format).py b/ProgrammingClassExamples/MacOS versions/1b PSG (Format).py new file mode 100644 index 000000000..346705478 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/1b PSG (Format).py @@ -0,0 +1,41 @@ +#PySimple examples (v 3.8) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg + +#Set formatting options for all elements rather than individually. +#MacOs - colour background issue buttons - make text LightBlue + +sg.SetOptions (background_color = 'LightBlue', + element_background_color = 'LightBlue', + text_element_background_color = 'LightBlue', + font = ('Arial', 10, 'bold'), + text_color = 'Blue', + input_text_color ='Blue', + button_color = ('Blue', 'White') + ) +#adjust widths +layout = [ + [sg.Text('Celcius', size =(12,1)), sg.InputText(size = (8,1))], + [sg.Submit()] + ] + +window = sg.Window('Converter').Layout(layout) +button, value = window.Read() +if button is None: + #windows was closed without button being pressed + exit(0) +fahrenheit = round(9/5*float(value[0]) +32, 1) +result = 'Temperature in Fahrenheit is: ' + str(fahrenheit) +sg.Popup('Result',result) + + + + + + + + + + diff --git a/ProgrammingClassExamples/MacOS versions/1c PSG (persistent form and bind key).py b/ProgrammingClassExamples/MacOS versions/1c PSG (persistent form and bind key).py new file mode 100644 index 000000000..e686da7fc --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/1c PSG (persistent form and bind key).py @@ -0,0 +1,35 @@ +#PySimple examples (v 3.8) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg + +sg.SetOptions (background_color = 'LightBlue', + element_background_color = 'LightBlue', + text_element_background_color = 'LightBlue', + font = ('Arial', 12, 'bold'), + text_color = 'Blue', + input_text_color ='Blue', + button_color = ('Blue', 'White') + ) +#update (via list) values and and display answers +#value[0] is celcius input, value[1] is input to place result. +#Use ReadButton with while true: - keeps window open. + +layout = [ [sg.Text('Enter a Temperature in Celcius')], + [sg.Text('Celcius', size =(8,1)), sg.InputText(size = (15,1))], + [sg.Text('Result', size =(8,1)), sg.InputText(size = (15,1))], + [sg.ReadButton('Submit', bind_return_key = True)]] +#Return = button press +window = sg.Window('Converter').Layout(layout) + +while True: + #get result + button, value = window.Read() + #break out of loop is button not pressed. + if button is not None: + fahrenheit = round(9/5*float(value[0]) +32, 1) + #put result in 2nd input box + window.FindElement(1).Update(fahrenheit) + else: + break diff --git a/ProgrammingClassExamples/MacOS versions/1d PSG (named input keys and catch errors).py b/ProgrammingClassExamples/MacOS versions/1d PSG (named input keys and catch errors).py new file mode 100644 index 000000000..88c567ba6 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/1d PSG (named input keys and catch errors).py @@ -0,0 +1,36 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg + +sg.SetOptions (background_color = 'LightBlue', + element_background_color = 'LightBlue', + text_element_background_color = 'LightBlue', + font = ('Arial', 12, 'bold'), + text_color = 'Blue', + input_text_color ='Blue', + button_color = ('Blue', 'White') + ) +#name inputs (key) uses dictionary- easy to see updating of results +#value[input] first input value te c... +layout = [ [sg.Text('Enter a Temperature in Celcius')], + [sg.Text('Celcius', size =(8,1)), sg.InputText(size = (15,1),key = '_input_')], + [sg.Text('Result', size =(8,1)), sg.InputText(size = (15,1),key = '_result_')], + [sg.ReadButton('Submit', bind_return_key = True)]] + +window = sg.FlexForm('Temp Converter').Layout(layout) + +while True: + button, value = window.Read() + if button is not None: + #catch program errors for text or blank entry: + try: + fahrenheit = round(9/5*float(value['_input_']) +32, 1) + #put result in text box + window.FindElement('_result_').Update(fahrenheit) + except ValueError: + sg.Popup('Error','Please try again') + + else: + break diff --git a/ProgrammingClassExamples/MacOS versions/1e PSG (validation and Look and Feel).py b/ProgrammingClassExamples/MacOS versions/1e PSG (validation and Look and Feel).py new file mode 100644 index 000000000..c31194ae1 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/1e PSG (validation and Look and Feel).py @@ -0,0 +1,36 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOS + +import PySimpleGUI as sg + +#Can use a variety of themes - plus individual options +#Not on MacOS +#sg.ChangeLookAndFeel('SandyBeach') +#use set Options see previous +sg.SetOptions (font = ('Calbri', 12, 'bold')) + + +layout = [ [sg.Text('Enter a Temperature in Celcius')], + [sg.Text('Celcius', size =(8,1)), sg.InputText(size = (6,1),key = '_input_')], + [sg.Text('Result', size =(8,1)), sg.InputText(size = (6,1),key = '_result_')], + [sg.ReadButton('Submit', bind_return_key = True)]] + +window = sg.Window('Temp Converter').Layout(layout) + +while True: + button, value = window.Read() + if button is not None: + #catch program errors for text, floats or blank entry: + #Also validation for range [0, 50] + try: + if float(value['_input_']) > 50 or float(value['_input_']) <0: + sg.Popup('Error','Out of range') + else: + fahrenheit = round(9/5*int(value['_input_']) +32, 1) + window.FindElement('_result_').Update(fahrenheit) + except ValueError: + sg.Popup('Error','Please try again') + + else: + break diff --git a/ProgrammingClassExamples/MacOS versions/1e PSG (validation).py b/ProgrammingClassExamples/MacOS versions/1e PSG (validation).py new file mode 100644 index 000000000..3db950a1b --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/1e PSG (validation).py @@ -0,0 +1,34 @@ +#PySimple examples (v 3.8) +#Tony Crewe +#Sep 2018 + +import PySimpleGUI as sg + +#Can use a variety of themes - plus individual options +sg.ChangeLookAndFeel('SandyBeach') +sg.SetOptions (font = ('Arial', 10, 'bold')) + + +layout = [ [sg.Text('Enter a Temperature in Celcius')], + [sg.Text('Celcius', size =(8,1)), sg.InputText(size = (15,1),key = '_input_')], + [sg.Text('Result', size =(8,1)), sg.InputText(size = (15,1),key = '_result_')], + [sg.ReadButton('Submit', bind_return_key = True)]] + +window = sg.Window('Temp Converter').Layout(layout) + +while True: + button, value = window.Read() + if button is not None: + #catch program errors for text, floats or blank entry: + #Also validation for range [0, 50] + try: + if float(value['_input_']) > 50 or float(value['_input_']) <0: + sg.Popup('Error','Out of range') + else: + fahrenheit = round(9/5*int(value['_input_']) +32, 1) + window.FindElement('_result_').Update(fahrenheit) + except ValueError: + sg.Popup('Error','Please try again') + + else: + break diff --git a/ProgrammingClassExamples/MacOS versions/2a. PSG (checkbox and radiobuttons) - Copy.py b/ProgrammingClassExamples/MacOS versions/2a. PSG (checkbox and radiobuttons) - Copy.py new file mode 100644 index 000000000..189959b42 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/2a. PSG (checkbox and radiobuttons) - Copy.py @@ -0,0 +1,49 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg + +#Set colour scheme and font +#sg.ChangeLookAndFeel('GreenTan') + +sg.SetOptions (background_color = 'LightPink', + element_background_color = 'LightPink', + text_element_background_color = 'LightPink', + font = ('Arial', 14, 'bold'), + text_color = 'Green', + input_text_color ='Green', + button_color = ('Green', 'White')) + +#One checkbox and three radio buttons (grouped as 'Radio1') +#value[0] - checkbox, Value[1-3] radiobutton selection +layout = [[sg.Text('Membership Calculator', font = ('Calibri', 16, 'bold'))], + [sg.Checkbox(' Student? 10% off', size = (25,1)), + sg.ReadButton('Display Cost', size = (14,1))], + [sg.Radio('1 month $50', 'Radio1', default = True), + sg.Radio('3 months $100', 'Radio1'), + sg.Radio('1 year $300', 'Radio1')], + [sg.Text('', size = (30,1), justification = 'center', font =('Calibri', 16, 'bold'), key = 'result')]] + +window = sg.Window('Gym Membership').Layout(layout) + +while True: + button, value = window.Read() + if button is not None: + if value[1]: + cost = 50 + elif value[2]: + cost = 100 + else: + cost = 300 + if value[0]: + #apply discount + cost = cost*0.9 + + #format as currency $ symbol and 2 d.p. - make a string + result = str(' Cost: ' + '${:.2f}'.format(cost)) + #put the result in Textbox + window.FindElement('result').Update(result) + + else: + break diff --git a/ProgrammingClassExamples/MacOS versions/2b. PSG (Add logo).py b/ProgrammingClassExamples/MacOS versions/2b. PSG (Add logo).py new file mode 100644 index 000000000..aa4d1038a --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/2b. PSG (Add logo).py @@ -0,0 +1,42 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOS + +import PySimpleGUI as sg +import os + +sg.SetOptions (font =('Calibri',12,'bold')) + +#get pathname to current file +dirname, filename = os.path.split(os.path.abspath(__file__)) +#add file name for image +pathname = os.path.join(dirname ,'Gym_Logo.png') + +layout = [[sg.Image(pathname),sg.Text(' Membership Calculator', font = ('Calibri', 16, 'bold'))], + [sg.Checkbox(' Student? 10% off', size = (25,1)), + sg.ReadButton('Display Cost', size = (14,1),button_color = ('Red', 'White'))], + [sg.Radio('1 month $50', 'Radio1', default = True), + sg.Radio('3 months $100', 'Radio1'), + sg.Radio('1 year $300', 'Radio1')], + [sg.Text('', size = (30,1), justification = 'center', font =('Calibri', 16, 'bold'), key = 'result')]] + +window = sg.Window('Gym Membership').Layout(layout) + +while True: + button, value = window.Read() + if button is not None: + if value[1]: + cost = 50 + elif value[2]: + cost = 100 + else: + cost = 300 + if value[0]: + cost = cost*0.9 + + #format as currency $ symbol and 2 d.p. - make a string + result = str(' Cost: ' + '${:.2f}'.format(cost)) + window.FindElement('result').Update(result) + + else: + break diff --git a/ProgrammingClassExamples/MacOS versions/3 PSG (multiline display).py b/ProgrammingClassExamples/MacOS versions/3 PSG (multiline display).py new file mode 100644 index 000000000..d1348a914 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/3 PSG (multiline display).py @@ -0,0 +1,46 @@ + +#PySimple examples (v 3.8) +#Tony Crewe +#Oct 2018 MacOS + +import PySimpleGUI as sg + +#sg.ChangeLookAndFeel('GreenTan') + +sg.SetOptions (background_color = 'Grey', + element_background_color = 'Grey', + text_element_background_color = 'Grey', + font = ('Courier New', 12, 'bold'), + text_color = 'White', + input_text_color ='White', + button_color = ('Grey', 'White')) + + +layout = [ + [sg.Text('Enter and Add Data to Display', font = ('Calibri', 16,'bold'))], + [sg.Text('Race:', size = (5,1)), sg.InputText(size = (8,1)), + sg.Text('Club:', size = (5,1)), sg.InputText(size = (8,1))], + [sg.Text('Name:', size = (5,1)), sg.InputText(size = (8,1)), + sg.Text('Time:', size = (5,1)), sg.InputText(size = (8,1)),sg.Text(' '), + sg.ReadButton('Add Data', font = ('Calibri', 12, 'bold'))], + [sg.Text('_'*40)], + [sg.Text(' Race Club Name Time')], + [sg.Multiline(size =(44,6),key = '_multiline_')] + ] + +window = sg.Window('Enter & Display Data').Layout(layout) + +string = '' +S=[] +while True: + + button, value = window.Read() + if button is not None: + #use string formatting - best way? plus Courier New font - non-proportional font + S = S + ['{:^9s}{:<11s}{:<10s}{:>8s}'.format(value[0],value[1],value[2],value[3])] + for s in S: + string = string + s + '\n' + window.FindElement('_multiline_').Update(string) + string ='' + else: + break diff --git a/ProgrammingClassExamples/MacOS versions/4a PSG (Sliders and combo).py b/ProgrammingClassExamples/MacOS versions/4a PSG (Sliders and combo).py new file mode 100644 index 000000000..77258ca82 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/4a PSG (Sliders and combo).py @@ -0,0 +1,55 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg + +sg.SetOptions (background_color = 'LightPink', + element_background_color = 'LightPink', + text_element_background_color = 'LightPink', + font = ('Calibri', 14, 'bold'), + text_color = 'Black', + input_text_color ='Black', + button_color = ('Black', 'White')) +#use of Column to help with layout - vertical sliders take up space + +column1 = [ + [sg.Text('Pick operation', size = (15,1), font = ('Calibri', 16, 'bold'))], + [sg.InputCombo(['Add','Subtract','Multiply','Divide'], size = (10,8))], + [sg.Text('', size =(1,4))]] +column2 = [ + [sg.ReadButton('Submit', font = ('Calibri', 16, 'bold'), size = (8, 1))], + [sg.Text('Result:', font = ('Calibri', 16, 'bold'))],[sg.InputText(size = (12,1), key = '_result_')] + ] + + +layout = [ + [sg.Text('Slider and Combo box demo', font = ('Calibri', 16,'bold'))], + [sg.Slider(range = (-9, 9),orientation = 'v', size = (5,20), default_value = 0), + sg.Slider(range = (-9, 9),orientation = 'v', size = (5, 20), default_value = 0), + sg.Text(' '), sg.Column(column1), sg.Column(column2)]] + +#added grab_anywhere to when moving slider, who window doesn't move. + +window = sg.Window('Enter & Display Data',grab_anywhere = False).Layout(layout) + +#Get selection from combo: value[2] +#Slider values: value[0] and value[1] +while True: + button, value = window.Read() + if button is not None: + if value[2] == 'Add': + result = value[0] + value[1] + elif value[2] == 'Multiply': + result = value[0] * value[1] + elif value[2] == 'Subtract': + result = value[0] - value[1] + elif value[2] == 'Divide': #check for zero + if value[1] ==0: + sg.Popup('Second value can\'t be zero') + result = 'NA' + else: + result = value[0] / value[1] + window.FindElement('_result_').Update(result) + else: + break diff --git a/ProgrammingClassExamples/MacOS versions/4b PSG (Spinner and combo) .py b/ProgrammingClassExamples/MacOS versions/4b PSG (Spinner and combo) .py new file mode 100644 index 000000000..8d696c312 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/4b PSG (Spinner and combo) .py @@ -0,0 +1,43 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg + +sg.SetOptions(background_color = 'LightGreen', + element_background_color = 'LightGreen', + text_element_background_color = 'LightGreen', + font= ('Calibri', 12, 'bold')) + +layout = [ + [sg.Text('Spinner and Combo box demo', font = ('Calibri', 14, 'bold'))], + [sg.Spin([sz for sz in range (-9,10)], size = (2,1),initial_value = 0), + sg.Spin([sz for sz in range (-9,10)], size = (2,1), initial_value = 0), + sg.Text('Pick operation ->', size = (15,1)), + sg.InputCombo(['Add','Subtract','Multiply','Divide'], size = (8,6))], + [sg.Text('Result: ')],[sg.InputText(size = (5,1), key = '_result_'), + sg.ReadButton('Calculate', button_color = ('Black', 'White'))]] + +window = sg.Window('Enter & Display Data', grab_anywhere= False).Layout(layout) + +while True: + button, value = window.Read() + + if button is not None: + #convert returned values to integers + val = [int(value[0]), int(value[1])] + if value[2] == 'Add': + result = val[0] + val[1] + elif value[2] == 'Multiply': + result = val[0] * val[1] + elif value[2] == 'Subtract': + result = val[0] - val[1] + elif value[2] == 'Divide': + if val[1] ==0: + sg.Popup('Second value can\'t be zero') + result = 'NA' + else: + result = round( val[0] / val[1], 3) + window.FindElement('_result_').Update(result) + else: + break diff --git a/ProgrammingClassExamples/MacOS versions/5a PSG (listboxes add remove).py b/ProgrammingClassExamples/MacOS versions/5a PSG (listboxes add remove).py new file mode 100644 index 000000000..293b69299 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/5a PSG (listboxes add remove).py @@ -0,0 +1,51 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg + +#sg.ChangeLookAndFeel('BlueMono') +sg.SetOptions (background_color = 'LightBlue', + element_background_color = 'LightBlue', + text_element_background_color = 'LightBlue', + font = ('Calibri', 14, 'bold'), + text_color = 'Black', + input_text_color ='Black', + button_color = ('Black', 'White')) + +#use column feature with height listbox takes up +column1 = [ + [sg.Text('Add or Delete Items\nfrom a Listbox')], + [sg.InputText( size = (15,1), key = 'add'), sg.ReadButton('Add', size = (5,1))], + [sg.ReadButton('Delete selected entry', size = (18,1))]] + +#initial listbox entries +List = ['Austalia', 'Canada', 'Greece'] + +#add initial List to listbox +layout = [ + [sg.Listbox(values=[l for l in List], size = (20,8), key ='_listbox_'), + sg.Column(column1)]] + +window = sg.Window('Listbox').Layout(layout) + +while True: + button, value = window.Read() + if button is not None: + #value[listbox] returns a list + #using value[listbox][0] gives the string + if button == 'Delete selected entry': + #ensure something is selected + if value['_listbox_'] == []: + sg.Popup('Error','You must select a Country') + else: + #find and remove this + List.remove(value['_listbox_'][0]) + if button == 'Add': + #add string in add box to list + List.append(value['add']) + List.sort() + #update listbox + window.FindElement('_listbox_').Update(List) + else: + break diff --git a/ProgrammingClassExamples/MacOS versions/6a PSG (search linear and binary).py b/ProgrammingClassExamples/MacOS versions/6a PSG (search linear and binary).py new file mode 100644 index 000000000..45bf802ad --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/6a PSG (search linear and binary).py @@ -0,0 +1,90 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg + + +sg.SetOptions(background_color = 'Grey', + element_background_color = 'Grey', + text_element_background_color = 'Grey', + font= ('Calibri', 14, 'bold')) + +layout =[[sg.Text('Search Demo', font =('Calibri', 18, 'bold')), sg.ReadButton('Show Names')], +[sg.Text('',size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color ='White',key = '_display1_'), + sg.Text('',size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color ='White',key = '_display2_')], + [sg.Text('_'*35,font = ('Calibri', 16))], + [sg.InputText(size = (10,1), key = '_linear_'), sg.InputText(size = (11,1), key = '_binary_')], + [sg.ReadButton('Linear Search', size = (11,1)), sg.ReadButton('Binary Search', size = (11,1))], + ] +window = sg.Window('Search Demo').Layout(layout) + +#names for Demo, could be loaded from a file +names = ['Roberta', 'Kylie', 'Jenny', 'Helen', + 'Andrea', 'Meredith','Deborah','Pauline', + 'Belinda', 'Wendy'] + +sorted_names = ['Andrea','Belinda','Deborah','Helen', + 'Jenny','Kylie','Meredith','Pauline', + 'Roberta','Wendy'] + +#function to display list +def display_list(list, display): + names = '' + for l in list: #add list elements with new line + names = names + l + '\n' + window.FindElement(display).Update(names) + +#Linear Search - no need for Ordered list +def linear_search(): + l = names[:] + found = False + for l in l: + if l == value['_linear_']: #Check each value + found = True + window.FindElement('_display1_').Update('Linear search\n' + l + ' found.') + break + if not found: + window.FindElement('_display1_').Update(value['_linear_'] + ' was \nNot found') + +#Binary Search - only works for ordered lists +def binary_search(): + l = sorted_names[:] + lo = 0 + hi = len(l)-1 + #Start with found is False + found = False + while lo <= hi: + #Start in middle + mid = (lo + hi) //2 + #get the value from the search box + if l[mid] == value['_binary_']: + window.FindElement('_display2_').Update('Binary search\n' + l[mid] + ' found.') + #If found display name and stop + found = True + break + elif l[mid] < value['_binary_']: + #Search in top half + lo = mid + 1 + else: + #Search in lower half + hi = mid - 1 + #If we get to end - display not found + if not found: + window.FindElement('_display2_').Update(value['_binary_'] + ' was \nNot found') + +while True: + button, value = window.Read() + + if button is not None: + #show names - unordered and sorted + if button == 'Show Names': + display_list(names,'_display1_') + display_list(sorted_names, '_display2_') + if button == 'Linear Search': + linear_search() + if button == 'Binary Search': + binary_search() + else: + break + diff --git a/ProgrammingClassExamples/MacOS versions/6b PSG (search - disabled buttons).py b/ProgrammingClassExamples/MacOS versions/6b PSG (search - disabled buttons).py new file mode 100644 index 000000000..8c9171664 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/6b PSG (search - disabled buttons).py @@ -0,0 +1,98 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg + +sg.SetOptions(background_color = 'LightBlue', + element_background_color = 'LightBlue', + text_element_background_color = 'LightBlue', + font= ('Calibri', 14, 'bold')) + +layout =[[sg.Text('Search Demo', font =('Calibri', 18, 'bold')), sg.ReadButton('Show Names')], +[sg.Text('',size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color ='White',key = '_display1_'), + sg.Text('',size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color ='White',key = '_display2_')], + [sg.Text('_'*35,font = ('Calibri', 16))], + [sg.InputText(size = (10,1), key = '_linear_'), sg.InputText(size = (11,1), key = '_binary_')], + [sg.ReadButton('Linear Search', key = '_ls_',size = (11,1)), sg.ReadButton('Binary Search', key ='_bs_',size = (11,1))], + ] +window = sg.Window('Search Demo').Layout(layout) + +#finalize allows the disabling of the two buttons before .Read statement +window.Finalize() +window.FindElement('_ls_').Update(disabled = True) +window.FindElement('_bs_').Update(disabled = True) + +#names for Demo, could be loaded from a file +names = ['Roberta', 'Kylie', 'Jenny', 'Helen', + 'Andrea', 'Meredith','Deborah','Pauline', + 'Belinda', 'Wendy'] + +sorted_names = ['Andrea','Belinda','Deborah','Helen', + 'Jenny','Kylie','Meredith','Pauline', + 'Roberta','Wendy'] + +#function to display list +def display_list(list, display): + names = '' + #add list elements with new line + for l in list: + names = names + l + '\n' + window.FindElement(display).Update(names) + #enable buttons now data loaded + window.FindElement('_ls_').Update(disabled = False) + window.FindElement('_bs_').Update(disabled = False) + +#Linear Search - no need for Ordered list +def linear_search(): + l = names[:] + found = False + for l in l: + #Check each value + if l == value['_linear_']: + found = True + window.FindElement('_display1_').Update('Linear search\n' + l + ' found.') + break + if not found: + window.FindElement('_display1_').Update(value['_linear_'] + ' was \nNot found') + +#Binary Search - only works for ordered lists +def binary_search(): + l = sorted_names[:] + lo = 0 + hi = len(l)-1 + #Start with found is Flase + found = False + while lo <= hi: + #Start in middle + mid = (lo + hi) //2 + #get the value from the search box + if l[mid] == value['_binary_']: + window.FindElement('_display2_').Update('Binary search\n' + l[mid] + ' found.') + #If found display and stop + found = True + break + elif l[mid] < value['_binary_']: + #Search in top half + lo = mid + 1 + else: + #Search in lower half + hi = mid - 1 + #If we get to end - display not found + if not found: + window.FindElement('_display2_').Update(value['_binary_'] + ' was \nNot found') + +while True: + button, value = window.Read() + if button is not None: + #show names - unordered and sorted + if button == 'Show Names': + display_list(names,'_display1_') + display_list(sorted_names, '_display2_') + if button == '_ls_': + linear_search() + if button == '_bs_': + binary_search() + else: + break + diff --git a/ProgrammingClassExamples/MacOS versions/6c PSG (search text preloaded).py b/ProgrammingClassExamples/MacOS versions/6c PSG (search text preloaded).py new file mode 100644 index 000000000..65b3c3b4f --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/6c PSG (search text preloaded).py @@ -0,0 +1,79 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg + +sg.SetOptions(background_color = 'Grey', + element_background_color = 'Grey', + text_element_background_color = 'Grey', + font= ('Calibri', 14, 'bold')) + +#names for Demo, could be loaded from a file + +names = ['Roberta', 'Kylie', 'Jenny', 'Helen', + 'Andrea', 'Meredith','Deborah','Pauline', + 'Belinda', 'Wendy'] +name = '' +for l in names: + name = name + l + '\n' + +sorted_names = ['Andrea','Belinda','Deborah','Helen', + 'Jenny','Kylie','Meredith','Pauline', + 'Roberta','Wendy'] + +sortname = '' +for l in sorted_names: + sortname = sortname + l +'\n' + +layout =[[sg.Text('Search Demo', font =('Calibri', 18, 'bold'))], +[sg.Text(name,size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color ='White',key = '_display1_'), + sg.Text(sortname,size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color ='White',key = '_display2_')], + [sg.Text('_'*35,font = ('Calibri', 16))], + [sg.InputText(size = (10,1), key = '_linear_'), sg.InputText(size = (11,1), key = '_binary_')], + [sg.ReadButton('Linear Search', size = (11,1)), sg.ReadButton('Binary Search', size = (11,1))], + ] +window = sg.Window('Search Demo').Layout(layout) + +#Linear Search - no need for Ordered list +def linear_search(): + l = names[:] + found = False + for l in l: + if l == value['_linear_']: + found = True + sg.Popup('Linear search\n' + l + ' found.') + break + if not found: + sg.Popup('Linear search\n' +(value['_linear_'] + ' was not found')) + +#Binary Search - only works for ordered lists +def binary_search(): + l = sorted_names[:] + lo = 0 + hi = len(l)-1 + found = False + while lo <= hi: + mid = (lo + hi) //2 + if l[mid] == value['_binary_']: + sg.Popup('Binary search\n' + l[mid] + ' found.') + found = True + break + elif l[mid] < value['_binary_']: + lo = mid + 1 + else: + hi = mid - 1 + if not found: + sg.Popup('Binary search\n' +(value['_binary_'] + ' was not found')) + +while True: + button, value = window.Read() + + if button is not None: + if button == 'Linear Search': + linear_search() + if button == 'Binary Search': + binary_search() + else: + break + diff --git a/ProgrammingClassExamples/MacOS versions/6d PSG (sort and search with textbox.py b/ProgrammingClassExamples/MacOS versions/6d PSG (sort and search with textbox.py new file mode 100644 index 000000000..ea354d902 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/6d PSG (sort and search with textbox.py @@ -0,0 +1,139 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOS + +import PySimpleGUI as sg + +sg.SetOptions(background_color = 'LightBlue', + element_background_color = 'LightBlue', + text_element_background_color = 'LightBlue', + font= ('Calibri', 14, 'bold')) + +#setup column (called column1) of buttons to use in layout + +column1 = [[sg.ReadButton('Original list', size = (11,1))], + [sg.ReadButton('Default sort', size = (11,1))], + [sg.ReadButton('Sort: selection',size = (11,1))], + [sg.ReadButton('Sort: quick', size = (11,1))]] + +layout =[[sg.Text('Search and Sort Demo', font =('Calibri', 20, 'bold'))], +[sg.Text('',size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color = 'White',key = '_display_'), sg.Column(column1)], + [sg.Text('_'*35,font = ('Calibri', 16))], + [sg.InputText(size = (10,1), key = '_linear_'), sg.Text(' '), sg.InputText(size = (11,1), key = '_binary_')], + [sg.ReadButton('Linear Search', size = (11,1)), sg.Text(' '), sg.ReadButton('Binary Search', size = (11,1))], + ] + +window = sg.Window('Search and Sort Demo').Layout(layout) + +#names for Demo, could be loaded from a file +names= ['Roberta', 'Kylie', 'Jenny', 'Helen', + 'Andrea', 'Meredith','Deborah','Pauline', + 'Belinda', 'Wendy'] + +#function to display list +def display_list(list): + #store list in Multiline text globally + global list_displayed + list_displayed = list + display = '' + #add list elements with new line + for l in list: + display = display + l + '\n' + window.FindElement('_display_').Update(display) + +#use inbuilt python sort +def default(names): + l = names[:] + l.sort() + display_list(l) + +#Selection sort - See Janson Ch 7 +def sel_sort(names): + l = names[:] + for i in range(len(l)): + smallest = i + for j in range(i+1, len(l)): + #find smallest value + if l[j] < l[smallest]: + #swap it to front + smallest = j + #repeat from next position + l[smallest], l[i] = l[i], l[smallest] + display_list(l) + +#Quick sort - See Janson Ch 7 +def qsort_holder(names): + l = names[:] + #pass List, first and last + quick_sort(l, 0, len(l) -1) + display_list(l) +#Quicksort is a partition sort +def quick_sort(l, first, last): + if first >= last: + return l + pivot = l[first] + low = first + high = last + while low < high: + while l[high] > pivot: + high = high -1 + while l[low] < pivot: + low = low + 1 + if low <= high: + l[high], l[low] = l[low], l[high] + low = low + 1 + high = high -1 + #continue splitting - sort small list + quick_sort(l, first, low -1) + quick_sort(l, low, last) + +#Linear Search - no need for Ordered list +def linear_search(): + l = names[:] + found = False + for l in l: + if l == value['_linear_']: + found = True + window.FindElement('_display_').Update('Linear search\n' + l + ' found.') + break + if not found: + window.FindElement('_display_').Update(value['_linear_'] + ' was \nNot found') + +#Binary Search - only works for ordered lists +def binary_search(): + l= list_displayed[:] + lo = 0 + hi = len(l)-1 + found = False + while lo <= hi: + mid = (lo + hi) //2 + if l[mid] == value['_binary_']: + window.FindElement('_display_').Update('Binary search\n' + l[mid] + ' found.') + found = True + break + elif l[mid] < value['_binary_']: + lo = mid + 1 + else: + hi = mid - 1 + if not found: + window.FindElement('_display_').Update(value['_binary_'] + ' was \nNot found') + + +while True: + button, value = window.Read() + if button is not None: + if button == 'Original list': + display_list(names) + if button == 'Default sort': + default(names) + if button == 'Sort: selection': + sel_sort(names) + if button == 'Sort: quick': + qsort_holder(names) + if button == 'Linear Search': + linear_search() + if button == 'Binary Search': + binary_search() + else: + break + diff --git a/ProgrammingClassExamples/MacOS versions/6e PSG (sort and search with listbox).py b/ProgrammingClassExamples/MacOS versions/6e PSG (sort and search with listbox).py new file mode 100644 index 000000000..b39be3bb4 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/6e PSG (sort and search with listbox).py @@ -0,0 +1,137 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg + +sg.SetOptions(background_color = 'DarkGrey', + element_background_color = 'DarkGrey', + text_element_background_color = 'DarkGrey', + font= ('Calibri', 14, 'bold')) + +#setup column (called column1) of buttons to use in layout + +column1 = [[sg.ReadButton('Original list', size = (10,1))], + [sg.ReadButton('Default sort', size = (10,1))], + [sg.ReadButton('Sort: selection',size = (10,1))], + [sg.ReadButton('Sort: quick', size = (10,1))]] + +layout =[[sg.Text('Search and Sort Demo', font =('Calibri', 20, 'bold'))], +[sg.Listbox(values =[''], size = (14, 11),font = ('Calibri', 12), background_color ='White',key = '_display_'), sg.Column(column1)], + [sg.Text('_'*38,font = ('Calibri', 16))], + [sg.InputText(size = (10,1), key = '_linear_'), sg.Text(' '), sg.InputText(size = (11,1), key = '_binary_')], + [sg.ReadButton('Linear Search', size = (11,1)), sg.Text(' '), sg.ReadButton('Binary Search', size = (11,1))], + ] + +window = sg.Window('Search and Sort Demo').Layout(layout) + +names= ['Roberta', 'Kylie', 'Jenny', 'Helen', + 'Andrea', 'Meredith','Deborah','Pauline', + 'Belinda', 'Wendy'] + +#function to display list +def display_list(list): + global list_displayed + #store list in Multiline text globally + list_displayed = list + #add list elements with new line + values = [l for l in list] + window.FindElement('_display_').Update(values) + +#use inbuilt python sort +def default(names): + l = names[:] + l.sort() + display_list(l) + +#Selection sort +def sel_sort(names): + l = names[:] + for i in range(len(l)): + smallest = i + for j in range(i+1, len(l)): + if l[j] < l[smallest]: + smallest = j + l[smallest], l[i] = l[i], l[smallest] + display_list(l) + +#Quick sort +def qsort_holder(names): + l = names[:] + quick_sort(l, 0, len(l) - 1) + display_list(l) + +def quick_sort(l, first, last): + if first >= last: + return l + pivot = l[first] + low = first + high = last + while low < high: + while l[high] > pivot: + high = high -1 + while l[low] < pivot: + low = low + 1 + if low <= high: + l[high], l[low] = l[low], l[high] + low = low + 1 + high = high -1 + quick_sort(l, first, low -1) + quick_sort(l, low, last) + +#Linear Search - no need for Ordered list +def linear_search(): + l = names[:] + found = False + for l in l: + if l == value['_linear_']: + found = True + #Create list for display + result = ['Linear search', l + ' found'] + window.FindElement('_display_').Update(result) + break + if not found: + #Create list for display + result = [value['_linear_'], 'was not found'] + window.FindElement('_display_').Update(result) + +#Binary Search +def binary_search(): + l = list_displayed[:] + lo = 0 + hi = len(l)-1 + found = False + while lo <= hi: + mid = (lo + hi) //2 + if l[mid] == value['_binary_']: + #Create list for display + result = ['Binary search', l[mid] + ' found.'] + window.FindElement('_display_').Update(result) + found = True + break + elif l[mid] < value['_binary_']: + lo = mid + 1 + else: + hi = mid - 1 + if not found: + #Create list for display + result = [value['_binary_'], 'was not found'] + window.FindElement('_display_').Update(result) + +while True: + button, value = window.Read() + if button is not None: + if button == 'Original list': + display_list(names) + if button == 'Default sort': + default(names) + if button == 'Sort: selection': + sel_sort(names) + if button == 'Sort: quick': + qsort_holder(names) + if button == 'Linear Search': + linear_search() + if button == 'Binary Search': + binary_search() + else: + break diff --git a/ProgrammingClassExamples/MacOS versions/6f PSG (data from text file).py b/ProgrammingClassExamples/MacOS versions/6f PSG (data from text file).py new file mode 100644 index 000000000..76118d8be --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/6f PSG (data from text file).py @@ -0,0 +1,148 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg +import os + +sg.SetOptions(background_color = 'LightBlue', + element_background_color = 'LightBlue', + text_element_background_color = 'LightBlue', + font= ('Calibri', 14, 'bold')) + +#get pathname to current file + +dirname, filename = os.path.split(os.path.abspath(__file__)) +pathname = os.path.join(dirname, 'Names.txt') #original data +spathname = os.path.join(dirname, 'Names(sorted).txt') #sorted data + +#Get data from file +names = [line.strip() for line in open(pathname)] + +column1 = [[sg.ReadButton('Original list', size = (11,1))], + [sg.ReadButton('Default sort', size = (11,1))], + [sg.ReadButton('Sort: selection',size = (11,1))], + [sg.ReadButton('Sort: quick', size = (11,1))], + [sg.Text('_________________',font = ('Calibri', 16))], + [sg.ReadButton('Save data\ndisplayed', size = (11,2))]] + +layout =[[sg.Text('Search and Sort Demo', font =('Calibri', 20, 'bold'))], +[sg.Listbox(values =[''], size = (14, 11),font = ('Calibri', 12), background_color ='White',key = '_display_'), sg.Column(column1)], + [sg.Text('_'*38,font = ('Calibri', 16))], + [sg.InputText(size = (11,1), key = '_linear_'), sg.Text(' '), sg.InputText(size = (11,1), key = '_binary_')], + [sg.ReadButton('Linear Search', size = (12,1)), sg.Text(' '), sg.ReadButton('Binary Search', size = (11,1))], + ] + +window = sg.Window('Search and Sort Demo').Layout(layout) + +#function to display list +def display_list(list): + global list_displayed + #store list in Multiline text globally + list_displayed = list + #add list elements with new line + values = [l for l in list] + window.FindElement('_display_').Update(values) + +#use inbuilt python sort +def default(names): + l = names[:] + l.sort() + display_list(l) + +#Selection sort +def sel_sort(names): + l = names[:] + for i in range(len(l)): + smallest = i + for j in range(i+1, len(l)): + if l[j] < l[smallest]: + smallest = j + l[smallest], l[i] = l[i], l[smallest] + display_list(l) + +#Quick sort +def qsort_holder(names): + l = names[:] + quick_sort(l, 0, len(l) - 1) + display_list(l) + +def quick_sort(l, first, last): + if first >= last: + return l + pivot = l[first] + low = first + high = last + while low < high: + while l[high] > pivot: + high = high -1 + while l[low] < pivot: + low = low + 1 + if low <= high: + l[high], l[low] = l[low], l[high] + low = low + 1 + high = high -1 + quick_sort(l, first, low -1) + quick_sort(l, low, last) + +#Linear Search - no need for Ordered list +def linear_search(): + l = names[:] + found = False + for l in l: + if l == value['_linear_']: + found = True + #Create list for display + result = ['Linear search', l + ' found'] + window.FindElement('_display_').Update(result) + break + if not found: + #Create list for display + result = [value['_linear_'], 'was not found'] + window.FindElement('_display_').Update(result) + +#Binary Search +def binary_search(): + l = list_displayed[:] + lo = 0 + hi = len(l)-1 + found = False + while lo <= hi: + mid = (lo + hi) //2 + if l[mid] == value['_binary_']: + #Create list for display + found = True + result = ['Binary search', l[mid] + ' found.'] + window.FindElement('_display_').Update(result) + break + elif l[mid] < value['_binary_']: + lo = mid + 1 + else: + hi = mid - 1 + if not found: + #Create list for display + result = [value['_binary_'], 'was not found'] + window.FindElement('_display_').Update(result) + +while True: + button, value = window.Read() + if button is not None: + if button == 'Original list': + display_list(names) + if button == 'Default sort': + default(names) + if button == 'Sort: selection': + sel_sort(names) + if button == 'Sort: quick': + qsort_holder(names) + if button == 'Linear Search': + linear_search() + if button == 'Binary Search': + binary_search() + if button == 'Save data\ndisplayed': + f = open(spathname, 'w') + for name in list_displayed: + print (name, file = f) + f.close() + else: + break diff --git a/ProgrammingClassExamples/MacOS versions/7a PSG (Data entry calc using file save retrieve).py b/ProgrammingClassExamples/MacOS versions/7a PSG (Data entry calc using file save retrieve).py new file mode 100644 index 000000000..e7ba23862 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/7a PSG (Data entry calc using file save retrieve).py @@ -0,0 +1,67 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg +import os + +#sg.ChangeLookAndFeel('GreenTan') + +sg.SetOptions(background_color = 'LightBlue', + element_background_color = 'LightBlue', + text_element_background_color = 'LightBlue', + font= ('Calibri', 14, 'bold')) + +layout = [ + [sg.Text('Enter a Name and four Marks')], + [sg.Text('Name:', size =(8,1)), sg.InputText(size = (10,1), key = '_name_')], + [sg.Text('Mark1:', size =(8,1)), sg.InputText(size = (5,1), key = '_m1_')], + [sg.Text('Mark2:', size =(8,1)), sg.InputText(size = (5,1), key = '_m2_')], + [sg.Text('Mark3:', size =(8,1)), sg.InputText(size = (5,1), key = '_m3_')], + [sg.Text('Mark4:', size =(8,1)), sg.InputText(size = (5,1), key = '_m4_')], + [sg.ReadButton('Save', size = (6,1),key = '_save_'), sg.Text('Press to Save to file')], + [sg.ReadButton('Display',size = (6,1), key = '_display_'), sg.Text('To retrieve and Display')], + [sg.Multiline(size = (24,4), key = '_multiline_', pad = (2,15))]] + +window = sg.Window('Simple Average Finder').Layout(layout) + + +while True: + button, value = window.Read() #value is a dictionary holding name and marks (4) + if button is not None: + #initialise variables + total = 0.0 + index = '' + name = value['_name_'] + #get pathname to current file + dirname, filename = os.path.split(os.path.abspath(__file__)) + #add desired file name for saving to path + pathname = os.path.join(dirname , 'results.txt' ) + + #needs validation and try/catch error checking, will crash if blank or text entry for marks + + if button == '_save_': + #create dictionary index _m1_ ... _m4_ + for i in range (1,5): + index = '_m' + str(i) + '_' + total += float(value[index]) + average = total/4 + #open file and save + f = open(pathname, 'w') + print (name, file = f) + print (total, file = f) + print (average, file = f) + f.close() + + #some error checking for missing file needed here + + if button == '_display_': + #This loads the file line by line into a list called data. + #the strip() removes whitespaces from beginning and end of each line. + data = [line.strip() for line in open(pathname)] + #create single string to display in multiline object. + string = 'Name: ' + data[0] +'\nTotal: ' + str(data[1]) + '\nAverage: ' + str(data[2]) + window.FindElement('_multiline_').Update(string) + else: + break + diff --git a/ProgrammingClassExamples/MacOS versions/7b PSG (add validation and error trap).py b/ProgrammingClassExamples/MacOS versions/7b PSG (add validation and error trap).py new file mode 100644 index 000000000..412bbb64b --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/7b PSG (add validation and error trap).py @@ -0,0 +1,72 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg +import os #to work with windows OS + +#sg.ChangeLookAndFeel('GreenTan') + +sg.SetOptions(background_color = 'LightBlue', + element_background_color = 'LightBlue', + text_element_background_color = 'LightBlue', + font= ('Calibri', 14, 'bold')) + +layout = [ + [sg.Text('Enter a Name and four Marks')], + [sg.Text('Name:', size =(8,1)), sg.InputText(size = (10,1), key = '_name_')], + [sg.Text('Mark1:', size =(8,1)), sg.InputText(size = (5,1), key = '_m1_')], + [sg.Text('Mark2:', size =(8,1)), sg.InputText(size = (5,1), key = '_m2_')], + [sg.Text('Mark3:', size =(8,1)), sg.InputText(size = (5,1), key = '_m3_')], + [sg.Text('Mark4:', size =(8,1)), sg.InputText(size = (5,1), key = '_m4_')], + [sg.ReadButton('Save', size = (6,1),key = '_save_'), sg.Text('Press to Save to file')], + [sg.ReadButton('Display',size = (6,1), key = '_display_'), sg.Text('To retrieve and Display')], + [sg.Multiline(size = (24,4), key = '_multiline_', pad = (2,15))]] + +window = sg.Window('Simple Average Finder').Layout(layout) + + +while True: + button, value = window.Read() #value is a dictionary holding name and marks (4) + if button is not None: + #initialise variables + total = 0.0 + index = '' + name = value['_name_'] + #get pathname to current file + dirname, filename = os.path.split(os.path.abspath(__file__)) + #add desired file name for saving to path + pathname = os.path.join(dirname , 'results.txt' ) + #generic catch error - blanks or wrong data types + try: + if button == '_save_': + for i in range (1,5): + index = '_m' + str(i) + '_' + + #Check for values between 0 and 100 + if float(value[index]) < 0 or float(value[index]) >100: + sg.Popup('Out of Range', 'Enter Marks between 0 and 100') + else: + total += float(value[index]) + average = total/4 + f = open(pathname, 'w') + print (name, file = f) + print (total, file = f) + print (average, file = f) + f.close() + except ValueError: + sg.Popup('Error','Check entries and try again') + + if button == '_display_': + #This loads the file line by line into a list called data. + #the strip() removes whitespaces from beginning and end of each line. + try: + data = [line.strip() for line in open(pathname)] + #create single string to display in multiline object. + string = 'Name: ' + data[0] +'\nTotal: ' + str(data[1]) + '\nAverage: ' + str(data[2]) + window.FindElement('_multiline_').Update(string) + except: + sg.PopupError('Error', 'Problem finding or reading file') + else: + break + diff --git a/ProgrammingClassExamples/MacOS versions/7c PSG (add get pathname to save and retrieve files).py b/ProgrammingClassExamples/MacOS versions/7c PSG (add get pathname to save and retrieve files).py new file mode 100644 index 000000000..b3d208a34 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/7c PSG (add get pathname to save and retrieve files).py @@ -0,0 +1,80 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg +import os #to work with windows OS + +#sg.ChangeLookAndFeel('GreenTan') + +sg.SetOptions(background_color = 'LightBlue', + element_background_color = 'LightBlue', + text_element_background_color = 'LightBlue', + font= ('Calibri', 14, 'bold')) + +layout = [ + [sg.Text('Enter a Name and four Marks')], + [sg.Text('Name:', size =(8,1)), sg.InputText(size = (10,1), key = '_name_')], + [sg.Text('Mark1:', size =(8,1)), sg.InputText(size = (5,1), key = '_m1_')], + [sg.Text('Mark2:', size =(8,1)), sg.InputText(size = (5,1), key = '_m2_')], + [sg.Text('Mark3:', size =(8,1)), sg.InputText(size = (5,1), key = '_m3_')], + [sg.Text('Mark4:', size =(8,1)), sg.InputText(size = (5,1), key = '_m4_')], + [sg.ReadButton('Save', size = (6,1),key = '_save_'), sg.Text('Press to Save to file')], + [sg.ReadButton('Display',size = (6,1), key = '_display_'), sg.Text('To retrieve and Display')], + [sg.Multiline(size = (24,4), key = '_multiline_', pad = (2,15))]] + +window = sg.Window('Simple Average Finder').Layout(layout) + + +while True: + button, value = window.Read() #value is a dictionary holding name and marks (4) + if button is not None: + #initialise variables + total = 0.0 + index = '' + name = value['_name_'] + #get pathname to current file + dirname, filename = os.path.split(os.path.abspath(__file__)) + #add desired file name for saving to path + pathname = os.path.join(dirname , 'results.txt') + #generic catch error - blanks or wrong data types + try: + if button == '_save_': + for i in range (1,5): + index = '_m' + str(i) + '_' + + #Check for values between 0 and 100 + if float(value[index]) < 0 or float(value[index]) >100: + sg.Popup('Out of Range', 'Enter Marks between 0 and 100') + else: + total += float(value[index]) + average = total/4 + #check location and file name for file, no_window so go straight to folder selection + + foldername = sg.PopupGetFolder('', no_window=True) + filename = sg.PopupGetFile('Please enter a file name for your results') + pathname = os.path.join(foldername ,filename + '.txt') + + f = open(pathname, 'w') + print (name, file = f) + print (total, file = f) + print (average, file = f) + f.close() + except ValueError: + sg.Popup('Error','Check entries and try again') + + if button == '_display_': + #get pathname: folder and file + pathname = sg.PopupGetFile('file to open', no_window=True, file_types=(("text files","*.txt"),)) + #This loads the file line by line into a list called data. + #the strip() removes whitespaces from beginning and end of each line. + try: + data = [line.strip() for line in open(pathname)] + #create single string to display in multiline object. + string = 'Name: ' + data[0] +'\nTotal: ' + str(data[1]) + '\nAverage: ' + str(data[2]) + window.FindElement('_multiline_').Update(string) + except: + sg.PopupError('Error', 'Problem finding or reading file') + else: + break + diff --git a/ProgrammingClassExamples/MacOS versions/8a PSG (Data to plot from csv file).py b/ProgrammingClassExamples/MacOS versions/8a PSG (Data to plot from csv file).py new file mode 100644 index 000000000..c8b6b85c4 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/8a PSG (Data to plot from csv file).py @@ -0,0 +1,40 @@ +#matplotlib, pyplt and csv +#Tony Crewe +#Sep 2017 - updated Oct 2018 MacOs + +import matplotlib.pyplot as plt +import csv +from matplotlib.ticker import MaxNLocator + + +x=[] +y=[] + +with open('weight 2018.csv', 'r', encoding = 'utf-8-sig') as csvfile: + plots = csv.reader(csvfile) + for data in plots: + #get heading for x and y axes + var1 = (data[0]) + var2 = (data[1]) + break + for data in plots: + #get values - add to x list and y list + x.append(data[0]) + y.append(float(data[1])) + + +ax = plt.subplot(1,1,1) +ax.set_ylim([82, 96]) +ax.xaxis.set_major_locator(MaxNLocator(10)) +ax.spines['right'].set_color('none') +ax.spines['top'].set_color('none') + +plt.plot(x,y, label = 'data loaded\nfrom csv file') +plt.axhline(y = 85.5, color = 'orange', linestyle = '--', label = 'target') +plt.xlabel(var1) +plt.ylabel(var2) +plt.title('weight loss from\n first quarter 2018') + + +plt.legend() +plt.show() diff --git a/ProgrammingClassExamples/MacOS versions/8b PSG (Tables and calc from csv file).py b/ProgrammingClassExamples/MacOS versions/8b PSG (Tables and calc from csv file).py new file mode 100644 index 000000000..174303cda --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/8b PSG (Tables and calc from csv file).py @@ -0,0 +1,69 @@ +#PySimple examples (v 3.9.3) +#Tony Crewe +#Oct 2018 MacOs + +#Based of Example program from MikeTheWatchGuy +#https://gitlab.com/lotspaih/PySimpleGUI + +import sys +import PySimpleGUI as sg +import csv +#sg.ChangeLookAndFeel('BrownBlue') +sg.SetOptions(background_color = 'LightBlue', + element_background_color = 'LightBlue') + +def calc_ladder(): + + filename = sg.PopupGetFile('Get required file', no_window = True,file_types=(("CSV Files","*.csv"),)) + #populate table with file contents + #Assume we know csv has heading in row 1 + #Assume we know 7 columns of data - relevenat to AFL w/o Pts or % shown + #data is a list of lists containing data about each team + #data[0] is one teams data data[0[[0] = team, data[0][1] P, data[0] [2] W, + #data[0][3] L, data [0][4] D, data [0][5] F, data [0][6] A + #no error checking or validation used. + + #initialise variable + data = [] + header_list = [] + #read csv + with open(filename, "r") as infile: + reader = csv.reader(infile) + for i in range (1): + #get headings + header = next(reader) + #read everything else into a list of rows + data = list(reader) + #add headings + header = header + ['%', 'Pts'] + for i in range (len(data)): + #calculate % and format to 2 decimal places + percent = str('{:.2f}'.format(int(data[i][5])/int(data[i][6])*100)) + data[i] = data[i] + [percent] #add to data + pts = int(data[i][2])*4 + int(data[i][4])*2 + data[i] = data[i] + [pts] #add to data + + + #use Table (explore settings) and add to column layout + # + #------ With MacOs -- manually adjust col_widths, auto to False ------------ + # + col_layout = [[sg.Table(values=data, headings=header,col_widths = (16, 4,4,4,4,6,6,7,4), auto_size_columns=False, + max_col_width = 30,justification='right', size=(None, len(data)))]] + + layout = [[sg.Column(col_layout, size=(520,360), scrollable=True)],] + + window = sg.Window('AFL Ladder',location = (500, 310), grab_anywhere = False).Layout(layout) + b, v = window.Read() + +slayout = [[sg.Text('Load AFL file to display results with points and percentage', font = ('Arial', 14, 'bold')), + sg.ReadButton('Load File', font = ('Arial', 14, 'bold'), size = (15,1))]] +swindow = sg.Window('Load File', location = (500,250)).Layout(slayout) + +while True: + button, value = swindow.Read() + if button is not None: + if button == 'Load File': + calc_ladder() + else: + break diff --git a/ProgrammingClassExamples/MacOS versions/8c PSG (Tables - add sort).py b/ProgrammingClassExamples/MacOS versions/8c PSG (Tables - add sort).py new file mode 100644 index 000000000..4071b9717 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/8c PSG (Tables - add sort).py @@ -0,0 +1,77 @@ +#PySimple examples (v 3.9.3) +#Tony Crewe +#Oct 2018 MacOs + +#Based of Example program from MikeTheWatchGuy +#https://gitlab.com/lotspaih/PySimpleGUI + +import sys +import PySimpleGUI as sg +import csv +import operator + +#sg.ChangeLookAndFeel('Dark') +sg.SetOptions(background_color = 'LightGrey', + element_background_color = 'LightGrey') + +def table_example(): + + filename = sg.PopupGetFile('Get required file', no_window = True,file_types=(("CSV Files","*.csv"),)) + #populate table with file contents + #Assume we know csv has heading in row 1 + #Assume we know 7 columns of data - relevenat to AFL w/o Pts or % shown + #data is a list of lists containing data about each team + #data[0] is one teams data data[0[[0] = team, data[0][1] P, data[0] [2] W, + #data[0][3] L, data [0][4] D, data [0][5] F, data [0][6] A + #no error checking or validation used. + + #initialise variables + data = [] + header_list = [] + with open(filename, "r") as infile: + reader = csv.reader(infile) + for i in range (1): + header = next(reader) + data = list(reader) + header = header + ['%', 'Pts'] + for i in range (len(data)): + #calculate % + percent = int(data[i][5])/int(data[i][6])*100 + data[i] = data[i] + [percent] + pts = int(data[i][2])*4 + int(data[i][4])*2 + data[i] = data[i] + [pts] + #sort data + #first by % + + data.sort(key = operator.itemgetter(7), reverse = True) + #then by pts + + data.sort(key = operator.itemgetter(8), reverse = True) + + #and format string to 2 decimal places + for i in range(len(data)): + data[i][7] = str('{:.2f}'.format(data[i][7])) + + #use Table (explore settings) and add to column layout + # + #------ With MacOs -- manually adjust col_widths, auto to False ------------ + # + col_layout = [[sg.Table(values=data, headings=header, col_widths = (16, 3,3,3,3,6,6,7,4), auto_size_columns=False, + max_col_width = 30,justification='right', size=(None, len(data)))]] + + layout = [[sg.Column(col_layout, size=(480,360), scrollable=True)],] + + window = sg.Window('Ladder', location = (350, 310), grab_anywhere = False).Layout(layout) + b, v = window.Read() + +slayout = [[sg.Text(' Load AFL (csv) file to display sorted results.', font = ('Calibri', 16, 'bold')), + sg.ReadButton('Load File', font = ('Calibri', 16, 'bold'), button_color = ('Red', 'White'), size = (10,1))]] +swindow = sg.Window('Load File', location = (350,250)).Layout(slayout) + +while True: + button, value = swindow.Read() + if button is not None: + if button == 'Load File': + table_example() + else: + break diff --git a/ProgrammingClassExamples/MacOS versions/8d PSG (Tables - add logo).py b/ProgrammingClassExamples/MacOS versions/8d PSG (Tables - add logo).py new file mode 100644 index 000000000..c2fe109b5 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/8d PSG (Tables - add logo).py @@ -0,0 +1,71 @@ +#PySimple examples (v 3.9.3) +#Tony Crewe +#Oct 2018 MacOs + +#Based of Example program from MikeTheWatchGuy +#https://gitlab.com/lotspaih/PySimpleGUI + +import sys +import PySimpleGUI as sg +import csv +import operator +import os + +sg.SetOptions(background_color = 'Black', + element_background_color = 'Black', + font = ('Calibri', 16, 'bold'), + text_color = 'White') + +#get pathname to current file and add file name for image +dirname, filename = os.path.split(os.path.abspath(__file__)) + +pathname = os.path.join(dirname , 'AFL.png' ) + +def table_example(): + + filename = sg.PopupGetFile('Get required file', no_window = True,file_types=(("CSV Files","*.csv"),)) + + + data = [] + header_list = [] + + with open(filename, "r") as infile: + reader = csv.reader(infile) + for i in range (1): + header = next(reader) + data = list(reader) + header = header + ['%', 'Pts'] + for i in range (len(data)): + + percent = int(data[i][5])/int(data[i][6])*100 + data[i] = data[i] + [percent] + + pts = int(data[i][2])*4 + int(data[i][4])*2 + data[i] = data[i] + [pts] + + data.sort(key = operator.itemgetter(7), reverse = True) + data.sort(key = operator.itemgetter(8), reverse = True) + + for i in range(len(data)): + data[i][7] = str('{:.2f}'.format(data[i][7])) + + col_layout = [[sg.Table(values=data, headings=header, col_widths = (16, 3,3,3,3,6,6,6,4), auto_size_columns=False, + max_col_width = 30,justification='right', size=(None, len(data)))]] + + layout = [[sg.Column(col_layout, size=(480,360), scrollable=True)],] + + window = sg.Window('Table', no_titlebar = False, location = (350, 318), grab_anywhere = False).Layout(layout) + b, v = window.Read() + +slayout = [[sg.Image(pathname),sg.Text(' Load AFL (csv) file to display results. '), + sg.ReadButton('Load File', size = (10,1))]] +swindow = sg.Window('Load File', location = (350,250)).Layout(slayout) + +while True: + button, value = swindow.Read() + if button is not None: + if button == 'Load File': + table_example() + else: + break + diff --git a/ProgrammingClassExamples/MacOS versions/9a PSG Windows(location hide).py b/ProgrammingClassExamples/MacOS versions/9a PSG Windows(location hide).py new file mode 100644 index 000000000..312af3b4a --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/9a PSG Windows(location hide).py @@ -0,0 +1,52 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Sep 2018 MacOs + +import PySimpleGUI as sg + +#sg.ChangeLookAndFeel('SandyBeach') +sg.SetOptions (background_color = 'LightBlue', + element_background_color = 'LightBlue', + text_element_background_color = 'LightBlue', + font = ('Arial', 14, 'bold'), + text_color = 'Blue', + input_text_color ='Blue', + button_color = ('Blue', 'White') + ) + +layout0 = [[sg.ReadButton('Show/Hide window1'),sg.ReadButton('Show/Hide window2')]] + +layout1 =[[ sg.Text('window1')], [sg.Multiline( size = (35, 10))]] +layout2 =[[ sg.Text('window2')], [sg.Multiline( size = (35, 10))]] +window0 = sg.Window('Home Window', location = (200, 140)).Layout(layout0) + +window1 = sg.Window('Window1', location = (200, 200)).Layout(layout1).Finalize() +window1.Hide() +w1 = False + +window2 = sg.Window('Window2', location = (600, 200)).Layout(layout2).Finalize() +window2.Hide() +w2 = False + +while True: + button, v = window0.Read() + if button is not None: + if button =='Show/Hide window1': + if w1 == True: + window1.Hide() + w1 = False + else: + window1.UnHide() + w1=True + if button =='Show/Hide window2': + if w2 == True: + window2.Hide() + w2 = False + else: + window2.UnHide() + w2=True + else: + break + + + diff --git a/ProgrammingClassExamples/MacOS versions/9b PSG Tabs example.py b/ProgrammingClassExamples/MacOS versions/9b PSG Tabs example.py new file mode 100644 index 000000000..7c4ec0f5a --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/9b PSG Tabs example.py @@ -0,0 +1,22 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg + +tab1_layout = [[sg.Text('This is inside tab 1')]] + +tab2_layout = [[sg.Text('This is inside tab 2')]] + +layout = [[sg.TabGroup([[sg.Tab('Tab 1', tab1_layout), + sg.Tab('Tab 2', tab2_layout)]])], + [sg.ReadButton('Read')]] + +window = sg.Window('Main Window').Layout(layout) + +while True: + b, v = window.Read() + if b is not None: + print(b,v) + else: + break diff --git a/ProgrammingClassExamples/MacOS versions/9c PSG Tabs example plus.py b/ProgrammingClassExamples/MacOS versions/9c PSG Tabs example plus.py new file mode 100644 index 000000000..b69965e38 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/9c PSG Tabs example plus.py @@ -0,0 +1,89 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg +import os + +#sg.ChangeLookAndFeel('BlueMono') +sg.SetOptions (background_color = 'LightBlue', + element_background_color = 'LightBlue', + text_element_background_color = 'LightBlue', + font = ('Arial', 12, 'bold'), + text_color = 'Blue', + input_text_color ='Blue', + button_color = ('Blue', 'White')) + +#get pathname to current file + +dirname, filename = os.path.split(os.path.abspath(__file__)) +pathname = os.path.join(dirname , 'Names.txt' ) + +#Get data from file +names = [line.strip() for line in open(pathname)] +sorted_names = names[:] +sorted_names.sort() + +tab1_layout =[[sg.Text('Linear Search Demo', font =('Calibri', 14, 'bold'))], + [sg.Listbox(values =[n for n in names], size = (15, 12),font = ('Calibri', 12), background_color ='White',key = '_display1_')], + [sg.Text('_'*25,font = ('Calibri', 12))], + [sg.Text('Enter name to search for:',font = ('Calibri', 14, 'bold'))], + [sg.InputText(size = (15,1), key = '_linear_')], + [sg.ReadButton('Linear Search', font = ('Calibri', 14, 'bold'), size = (11,1))]] + +tab2_layout = [[sg.Text('Binary Search Demo', font =('Calibri', 14, 'bold'))], + [sg.Listbox(values =[n for n in sorted_names], size = (15, 12),font = ('Calibri', 12), background_color ='White',key = '_display2_')], + [sg.Text('_'*25,font = ('Calibri', 12))], + [sg.Text('Enter name to search for:',font = ('Calibri', 14, 'bold'))], + [sg.InputText(size = (15,1), key = '_binary_')], + [sg.ReadButton('Binary Search',font = ('Calibri', 14, 'bold'), size = (11,1))]] + +layout = [ + [sg.TabGroup([[sg.Tab('Linear Search', tab1_layout),sg.Tab('Binary Search', tab2_layout)]])]] + +window = sg.Window('Main Window').Layout(layout) + +#Linear Search - no need for Ordered list +def linear_search(): + l = names[:] + found = False + for l in l: + if l == value['_linear_']: #Check each value + found = True + result = ['Linear search', l + ' found'] + window.FindElement('_display1_').Update(result) + break + if not found: + result = [value['_linear_'], 'was not found'] + window.FindElement('_display1_').Update(result) + +#Binary Search - only works for ordered lists +def binary_search(): + l = sorted_names + lo = 0 + hi = len(l)-1 + found = False + while lo <= hi: + mid = (lo + hi) //2 + if l[mid] == value['_binary_']: + found = True + result = ['Binary search', l[mid] + ' found.'] + window.FindElement('_display2_').Update(result) + break + elif l[mid] < value['_binary_']: + lo = mid + 1 + else: + hi = mid - 1 + if not found: + result = [value['_binary_'], 'was not found'] + window.FindElement('_display2_').Update(result) + +while True: + button, value = window.Read() + if button is not None: + if button == 'Linear Search': + linear_search() + if button == 'Binary Search': + binary_search() + else: + break diff --git a/ProgrammingClassExamples/MacOS versions/AFL.png b/ProgrammingClassExamples/MacOS versions/AFL.png new file mode 100644 index 000000000..ee3a35597 Binary files /dev/null and b/ProgrammingClassExamples/MacOS versions/AFL.png differ diff --git a/ProgrammingClassExamples/MacOS versions/AFL2018 (sorted alpha teams).csv b/ProgrammingClassExamples/MacOS versions/AFL2018 (sorted alpha teams).csv new file mode 100644 index 000000000..798296f6e --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/AFL2018 (sorted alpha teams).csv @@ -0,0 +1,19 @@ +Team,P,W,L,D,F,A +Adelaide Crows,22,12,10,0,1941,1865 +Brisbane Lions,22,5,17,0,1825,2049 +Carlton,22,2,20,0,1353,2282 +Collingwood,22,15,7,0,2046,1699 +Essendon,22,12,10,0,1932,1838 +Fremantle,22,8,14,0,1556,2041 +Geelong Cats,22,13,9,0,2045,1554 +Gold Coast Suns,22,4,18,0,1308,2182 +GWS Giants,22,13,8,1,1898,1661 +Hawthorn,22,15,7,0,1972,1642 +Melbourne,22,14,8,0,2299,1749 +North Melbourne,22,12,10,0,1950,1790 +Port Adelaide,22,12,10,0,1780,1654 +Richmond,22,18,4,0,2143,1574 +St Kilda,22,4,17,1,1606,2125 +Sydney Swans,22,14,8,0,1822,1664 +West Coast Eagles,22,16,6,0,2012,1657 +Western Bulldogs,22,8,14,0,1575,2037 diff --git a/ProgrammingClassExamples/MacOS versions/AFL2018 (sorted pts and %).csv b/ProgrammingClassExamples/MacOS versions/AFL2018 (sorted pts and %).csv new file mode 100644 index 000000000..71cb8c18a --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/AFL2018 (sorted pts and %).csv @@ -0,0 +1,19 @@ +Team,P,W,L,D,F,A +Richmond,22,18,4,0,2143,1574 +West Coast Eagles,22,16,6,0,2012,1657 +Collingwood,22,15,7,0,2046,1699 +Hawthorn,22,15,7,0,1972,1642 +Melbourne,22,14,8,0,2299,1749 +Sydney Swans,22,14,8,0,1822,1664 +GWS Giants,22,13,8,1,1898,1661 +Geelong Cats,22,13,9,0,2045,1554 +North Melbourne,22,12,10,0,1950,1790 +Port Adelaide,22,12,10,0,1780,1654 +Essendon,22,12,10,0,1932,1838 +Adelaide Crows,22,12,10,0,1941,1865 +Western Bulldogs,22,8,14,0,1575,2037 +Fremantle,22,8,14,0,1556,2041 +Brisbane Lions,22,5,17,0,1825,2049 +St Kilda,22,4,17,1,1606,2125 +Gold Coast Suns,22,4,18,0,1308,2182 +Carlton,22,2,20,0,1353,2282 diff --git a/ProgrammingClassExamples/MacOS versions/Gym_Logo.png b/ProgrammingClassExamples/MacOS versions/Gym_Logo.png new file mode 100644 index 000000000..45bb5f7bc Binary files /dev/null and b/ProgrammingClassExamples/MacOS versions/Gym_Logo.png differ diff --git a/ProgrammingClassExamples/MacOS versions/Names(sorted).txt b/ProgrammingClassExamples/MacOS versions/Names(sorted).txt new file mode 100644 index 000000000..eb2415c84 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/Names(sorted).txt @@ -0,0 +1,10 @@ +Andrea +Belinda +Deborah +Helen +Jenny +Kylie +Meredith +Pauline +Roberta +Wendy diff --git a/ProgrammingClassExamples/MacOS versions/Names.txt b/ProgrammingClassExamples/MacOS versions/Names.txt new file mode 100644 index 000000000..d1b9fd24d --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/Names.txt @@ -0,0 +1,10 @@ +Roberta +Kylie +Jenny +Helen +Andrea +Meredith +Deborah +Pauline +Belinda +Wendy \ No newline at end of file diff --git a/ProgrammingClassExamples/MacOS versions/Test.txt b/ProgrammingClassExamples/MacOS versions/Test.txt new file mode 100644 index 000000000..6f15df0a6 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/Test.txt @@ -0,0 +1,3 @@ +T +202.0 +50.5 diff --git a/ProgrammingClassExamples/MacOS versions/TonyCrewe2.txt b/ProgrammingClassExamples/MacOS versions/TonyCrewe2.txt new file mode 100644 index 000000000..5ee47eaf9 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/TonyCrewe2.txt @@ -0,0 +1,3 @@ +Tony +158.0 +39.5 diff --git a/ProgrammingClassExamples/MacOS versions/default_icon.ico b/ProgrammingClassExamples/MacOS versions/default_icon.ico new file mode 100644 index 000000000..1a41525ec Binary files /dev/null and b/ProgrammingClassExamples/MacOS versions/default_icon.ico differ diff --git a/ProgrammingClassExamples/MacOS versions/results.txt b/ProgrammingClassExamples/MacOS versions/results.txt new file mode 100644 index 000000000..0d13392a0 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/results.txt @@ -0,0 +1,3 @@ +Tony +224.0 +56.0 diff --git a/ProgrammingClassExamples/MacOS versions/weight 2018.csv b/ProgrammingClassExamples/MacOS versions/weight 2018.csv new file mode 100644 index 000000000..66e7c2d97 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/weight 2018.csv @@ -0,0 +1,98 @@ +Date,Weight (kg) +29-Dec,94.5 +30-Dec,94 +31-Dec,94 +1-Jan,93.5 +2-Jan,94.2 +3-Jan,94 +4-Jan,94 +5-Jan,93.4 +6-Jan,92.6 +7-Jan,93.1 +8-Jan,92.7 +9-Jan,92.5 +10-Jan,92.3 +11-Jan,92.1 +12-Jan,92.5 +13-Jan,92.6 +14-Jan,92.5 +15-Jan,92.1 +16-Jan,91.6 +17-Jan,91.3 +18-Jan,91.8 +19-Jan,91.7 +20-Jan,91.9 +21-Jan,91.8 +22-Jan,91.1 +23-Jan,90.7 +24-Jan,90.5 +25-Jan,90.5 +26-Jan,90.3 +27-Jan,90.1 +28-Jan,89.9 +29-Jan,90.2 +30-Jan,90.1 +31-Jan,89.9 +1-Feb,89.5 +2-Feb,89.1 +3-Feb,89.3 +4-Feb,89.4 +5-Feb,89.2 +6-Feb,88.2 +7-Feb,88.2 +8-Feb,88.3 +9-Feb,88.2 +10-Feb,89.1 +11-Feb,88.9 +12-Feb,88.6 +13-Feb,88.7 +14-Feb,88.5 +15-Feb,88.1 +16-Feb,87.8 +17-Feb,87.9 +18-Feb,88.1 +19-Feb,87.9 +20-Feb,87.6 +21-Feb,87.5 +22-Feb,87.3 +23-Feb,87 +24-Feb,87.5 +25-Feb,87.7 +26-Feb,87.4 +27-Feb,87.2 +28-Feb,86.9 +1-Mar,86.9 +2-Mar,86.9 +3-Mar,86.5 +4-Mar,86.8 +5-Mar,87 +6-Mar,86.9 +7-Mar,86.2 +8-Mar,86.4 +9-Mar,86.1 +10-Mar,86.7 +11-Mar,85.6 +12-Mar,85.8 +13-Mar,85.3 +14-Mar,85.1 +15-Mar,85.4 +16-Mar,84.5 +17-Mar,85.1 +18-Mar,84.8 +19-Mar,84.8 +20-Mar,84.8 +21-Mar,84.9 +22-Mar,85.5 +23-Mar,85.1 +24-Mar,85.5 +25-Mar,85.6 +26-Mar,85.9 +27-Mar,85.9 +28-Mar,85.5 +29-Mar,85.9 +30-Mar,85.5 +1-Apr,85.2 +2-Apr,84.8 +3-Apr,85.3 +4-Apr,85.4 +5-Apr,85.3 diff --git a/ProgrammingClassExamples/Win10 versions/10a PSG Plot (Matplotlib numpy pyplot(y=sinx)) .py b/ProgrammingClassExamples/Win10 versions/10a PSG Plot (Matplotlib numpy pyplot(y=sinx)) .py new file mode 100644 index 000000000..9847f3be3 --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/10a PSG Plot (Matplotlib numpy pyplot(y=sinx)) .py @@ -0,0 +1,62 @@ +#matplotlib, numpy, pyplot +#Tony Crewe +#Oct 2018 + +import PySimpleGUI as sg +import matplotlib.pyplot as plt +from matplotlib.backends.backend_tkagg import FigureCanvasAgg +import matplotlib.backends.tkagg as tkagg +import numpy as np +import tkinter as tk + +""" +Demonstrates one way of embedding Matplotlib figures into a PySimpleGUI window. +Adapted: From https://gitlab.com/lotspaih/PySimpleGUI/tree/master + +Basic steps are: + * Create a Canvas Element + * Layout form + * Display form (NON BLOCKING) + * Draw plots onto convas + * Display form (BLOCKING) +""" + +#No exactly sure how all this works, but taken from example given as a template. +def draw_figure(canvas, figure, loc = (0,0)): + + figure_canvas_agg = FigureCanvasAgg(figure) + figure_canvas_agg.draw() + figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds + figure_w, figure_h = int(figure_w), int(figure_h) + photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h) + canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo) + tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2) + return photo + + +#------------ Matplotlib code ---------------------- +#see https://matplotlib.org/ +fig = plt.figure() +ax = fig.add_subplot(111) +#x-values +x = np.linspace(-np.pi*2, np.pi*2, 100) +#y-values +y = np.sin(x) +plt.plot(x,y) + +ax.set_title('sin(x)') +figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds + +#------------End Matplotlib code -------------------- + +layout = [[sg.Text('Plot Test - PySimpleGUI and Matplotlib', font = ('Calibri', 18, 'bold'))], + [sg.Canvas(size = (figure_w, figure_h), key = '_canvas_')], + [sg.OK(pad=((figure_w / 2, 0), 3), size=(6, 2))]] + +window = sg.Window('Matplot in PySimpleGUI', force_toplevel = True).Layout(layout).Finalize() + +fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig) + +button, value = window.Read() + + diff --git a/ProgrammingClassExamples/Win10 versions/10b PSG Plot (axes moved).py b/ProgrammingClassExamples/Win10 versions/10b PSG Plot (axes moved).py new file mode 100644 index 000000000..4a7aade10 --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/10b PSG Plot (axes moved).py @@ -0,0 +1,54 @@ +#matplotlib, numpy, pyplot +#Tony Crewe +#Oct 2018 + +import PySimpleGUI as sg +import matplotlib.pyplot as plt +from matplotlib.backends.backend_tkagg import FigureCanvasAgg +import matplotlib.backends.tkagg as tkagg +import numpy as np +import tkinter as tk + +def draw_figure(canvas, figure, loc = (0,0)): + + figure_canvas_agg = FigureCanvasAgg(figure) + figure_canvas_agg.draw() + figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds + figure_w, figure_h = int(figure_w), int(figure_h) + photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h) + canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo) + tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2) + return photo + + +#------------ Matplotlib code -------------------- +fig=plt.figure() +ax = fig.add_subplot(111) +x = np.linspace(-np.pi*2, np.pi*2, 100) +y= np.sin(x) +plt.plot(x,y) + +ax.set_title('sin(x)') + +#centre bottom and left axes to zero + +ax.spines['left'].set_position('zero') +ax.spines['right'].set_color('none') +ax.spines['bottom'].set_position('zero') +ax.spines['top'].set_color('none') + +figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds + +#------------End Matplotlib code -------------------- + +layout = [[sg.Text('Plot Test - PySimpleGUI and Matplotlib (axes centred)', font = ('Calibri', 18, 'bold'))], + [sg.Canvas(size = (figure_w, figure_h), key = '_canvas_')], + [sg.OK(pad=((figure_w / 2, 0), 3), size=(6, 2))]] + +window = sg.Window('Matplot in PySimpleGUI', force_toplevel = True).Layout(layout).Finalize() + +fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig) + +button, value = window.Read() + + diff --git a/ProgrammingClassExamples/Win10 versions/10c PSG Plot (axes pi format).py b/ProgrammingClassExamples/Win10 versions/10c PSG Plot (axes pi format).py new file mode 100644 index 000000000..d4f9ca2ef --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/10c PSG Plot (axes pi format).py @@ -0,0 +1,68 @@ +#matplotlib, numpy, pyplot +#Tony Crewe +#Oct 2018 + +import PySimpleGUI as sg +import matplotlib.pyplot as plt +import matplotlib.ticker as ticker +from matplotlib.backends.backend_tkagg import FigureCanvasAgg +import matplotlib.backends.tkagg as tkagg +import numpy as np +import tkinter as tk + +""" +Demonstrates one way of embedding Matplotlib figures into a PySimpleGUI window. + +Basic steps are: + * Create a Canvas Element + * Layout form + * Display form (NON BLOCKING) + * Draw plots onto convas + * Display form (BLOCKING) +""" + +def draw_figure(canvas, figure, loc = (0,0)): + + figure_canvas_agg = FigureCanvasAgg(figure) + figure_canvas_agg.draw() + figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds + figure_w, figure_h = int(figure_w), int(figure_h) + photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h) + canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo) + tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2) + return photo + + +#------------ Matplotlib code -------------------- +fig=plt.figure() +ax = fig.add_subplot(111) +x = np.linspace(-np.pi*2, np.pi*2, 100) +y= np.sin(x) +plt.plot(x/np.pi,y) + +ax.set_title('sin(x)') +#centre bottom and left axes to zero + +ax.spines['left'].set_position('zero') +ax.spines['right'].set_color('none') +ax.spines['bottom'].set_position('zero') +ax.spines['top'].set_color('none') + +#Format axes - nicer eh! +ax.xaxis.set_major_formatter(ticker.FormatStrFormatter('%g $\pi$')) + +figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds + +#------------End Matplotlib code -------------------- + +layout = [[sg.Text('Plot Test - PySimpleGUI and Matplotlib (axes pi format)', font = ('Calibri', 18, 'bold'))], + [sg.Canvas(size = (figure_w, figure_h), key = '_canvas_')], + [sg.OK(pad=((figure_w / 2, 0), 3), size=(6, 2))]] + +window = sg.Window('Matplot in PySimpleGUI', force_toplevel = True).Layout(layout).Finalize() + +fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig) + +button, value = window.Read() + + diff --git a/ProgrammingClassExamples/Win10 versions/10d PSG (Plots Tabs and sin cos options).py b/ProgrammingClassExamples/Win10 versions/10d PSG (Plots Tabs and sin cos options).py new file mode 100644 index 000000000..b0bbc2f95 --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/10d PSG (Plots Tabs and sin cos options).py @@ -0,0 +1,90 @@ +#matplotlib, numpy, pyplot +#Tony Crewe +#Oct 2018 + +import PySimpleGUI as sg +import matplotlib.pyplot as plt +import matplotlib.ticker as ticker +from matplotlib.backends.backend_tkagg import FigureCanvasAgg +import matplotlib.backends.tkagg as tkagg +import numpy as np +import tkinter as tk + + +def draw_figure(canvas, figure, loc = (0,0)): + + figure_canvas_agg = FigureCanvasAgg(figure) + figure_canvas_agg.draw() + figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds + figure_w, figure_h = int(figure_w), int(figure_h) + photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h) + canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo) + tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2) + return photo + + +#------------ Matplotlib code -------------------- + +def set_plot(amp, function): + global figure_w, figure_h, fig + fig=plt.figure() + ax = fig.add_subplot(111) + x = np.linspace(-np.pi*2, np.pi*2, 100) + if function == 'sine': + y= amp*np.sin(x) + ax.set_title('sin(x)') + else: + y=amp*np.cos(x) + ax.set_title('cos(x)') + plt.plot(x/np.pi,y) + + + #centre bottom and left axes to zero + + ax.spines['left'].set_position('zero') + ax.spines['right'].set_color('none') + ax.spines['bottom'].set_position('zero') + ax.spines['top'].set_color('none') + + #Format axes - nicer eh! + ax.xaxis.set_major_formatter(ticker.FormatStrFormatter('%g $\pi$')) + + figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds +amp = 1 +function = 'sine' +set_plot(amp, function) + +#------------End Matplotlib code -------------------- + +#use Tabs - one for options, one for canvas to be displayed +#set spinner for amplitude and combo for function type + +tab1_layout = [[sg.Text('Select Amplitude and trig function type', font = ('Calibri', 18, 'bold'))], + [sg.Spin([sz for sz in range (1,5)], initial_value =1, size = (2,1), key = '_spin_'), + sg.Text('Amplitude', size = (10, 1), font = ('Calibri', 12, 'bold'))], + [sg.InputCombo(['sine', 'cosine'], size = (8, 4), key = '_function_'), + sg.Text('Function', size = (10, 1),font = ('Calibri', 12, 'bold'))], + [sg.ReadButton('Redraw Plot')], + [sg.Text('', size = (2, 25))]] + +tab2_layout = [[sg.Text('Plot Test - PySimpleGUI and Matplotlib and options', font = ('Calibri', 18, 'bold'))], + [sg.Canvas(size = (figure_w, figure_h), key = '_canvas_')], + [sg.OK(pad=((figure_w / 2, 0), 3), size=(6, 2))]] + +layout = [[sg.TabGroup([[sg.Tab('Select options', tab1_layout), sg.Tab('Display Plot', tab2_layout)]])]] +window = sg.Window('Matplot, PySimpleGUI and options', force_toplevel = True).Layout(layout).Finalize() + +fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig) + +while True: + button, value = window.Read() + if button == 'Redraw Plot': + amp = int(value['_spin_']) + function = value['_function_'] + set_plot(amp,function) + fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig) + + if button is None: + break + + diff --git a/ProgrammingClassExamples/Win10 versions/10e PSG (Same Window).py b/ProgrammingClassExamples/Win10 versions/10e PSG (Same Window).py new file mode 100644 index 000000000..f6d1a25ef --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/10e PSG (Same Window).py @@ -0,0 +1,88 @@ +#matplotlib, numpy, pyplot +#Tony Crewe +#Oct 2018 + +import PySimpleGUI as sg +import matplotlib.pyplot as plt +import matplotlib.ticker as ticker +from matplotlib.backends.backend_tkagg import FigureCanvasAgg +import matplotlib.backends.tkagg as tkagg +import numpy as np +import tkinter as tk + + +def draw_figure(canvas, figure, loc = (0,0)): + + figure_canvas_agg = FigureCanvasAgg(figure) + figure_canvas_agg.draw() + figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds + figure_w, figure_h = int(figure_w), int(figure_h) + photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h) + canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo) + tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2) + return photo + + +#------------ Matplotlib code -------------------- + +def set_plot(amp, function): + global figure_w, figure_h, fig + fig=plt.figure() + ax = fig.add_subplot(111) + x = np.linspace(-np.pi*2, np.pi*2, 100) + if function == 'sine': + y= amp*np.sin(x) + ax.set_title('sin(x)') + else: + y=amp*np.cos(x) + ax.set_title('cos(x)') + plt.plot(x/np.pi,y) + + + #centre bottom and left axes to zero + + ax.spines['left'].set_position('zero') + ax.spines['right'].set_color('none') + ax.spines['bottom'].set_position('zero') + ax.spines['top'].set_color('none') + + #Format axes - nicer eh! + ax.xaxis.set_major_formatter(ticker.FormatStrFormatter('%g $\pi$')) + + figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds +amp = 1 +function = 'sine' +set_plot(amp, function) + +#------------End Matplotlib code -------------------- + +#using one window based on two columns instead of Tabs +column1 = [[sg.Text('Select Amplitude and trig function type', font = ('Calibri', 18, 'bold'))], + [sg.Spin([sz for sz in range (1,5)], initial_value =1, size = (2,1), key = '_spin_'), + sg.Text('Amplitude', size = (10, 1), font = ('Calibri', 12, 'bold'))], + [sg.InputCombo(['sine', 'cosine'], size = (8, 4), key = '_function_'), + sg.Text('Function', size = (10, 1),font = ('Calibri', 12, 'bold'))], + [sg.ReadButton('Redraw Plot')], + [sg.Text('', size = (1, 27))]] + +column2 = [[sg.Text('Plot Test - PySimpleGUI and Matplotlib and options', font = ('Calibri', 18, 'bold'))], + [sg.Canvas(size = (figure_w, figure_h), key = '_canvas_')], + [sg.OK(pad=((figure_w / 2, 0), 3), size=(6, 2))]] + +layout = [[sg.Column(column1), sg.Column(column2)]] +window = sg.Window('Matplot, PySimpleGUI and options', force_toplevel = True).Layout(layout).Finalize() + +fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig) + +while True: + button, value = window.Read() + if button == 'Redraw Plot': + amp = int(value['_spin_']) + function = value['_function_'] + set_plot(amp,function) + fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig) + + if button is None: + break + + diff --git a/ProgrammingClassExamples/Win10 versions/10f PSG (linear and quadratics).py b/ProgrammingClassExamples/Win10 versions/10f PSG (linear and quadratics).py new file mode 100644 index 000000000..b208bd76c --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/10f PSG (linear and quadratics).py @@ -0,0 +1,111 @@ +#matplotlib, numpy, pyplot +#Tony Crewe +#Oct 2018 + +import PySimpleGUI as sg +import matplotlib.pyplot as plt +import matplotlib.ticker as ticker +from matplotlib.backends.backend_tkagg import FigureCanvasAgg +import matplotlib.backends.tkagg as tkagg +import numpy as np +import tkinter as tk + +sg.ChangeLookAndFeel('Black') +sg.SetOptions(font = ('Calibri', 14, 'bold')) + +def draw_figure(canvas, figure, loc = (0,0)): + + figure_canvas_agg = FigureCanvasAgg(figure) + figure_canvas_agg.draw() + figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds + figure_w, figure_h = int(figure_w), int(figure_h) + photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h) + canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo) + tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2) + return photo + + +#------------ Matplotlib code -------------------- + +def set_plot(a,b,c, function): + global figure_w, figure_h, fig + fig=plt.figure() + ax = fig.add_subplot(111) + x = np.linspace(-10, 10, 100) + if function == 'y = ax + b': + y= a*x + b + if a == 1: + a = '' + if a == -1: + a = '-' + title = str('y = ') + str(a) + 'x + ' + str(b) + ax.set_title(title) + else: + y = a*x**2 + b*x + c + #avoiding getting -1x or -1x**2 instead of -x for title + if a == 1: + a = '' + if a == -1: + a = '-' + if b == 1: + b = '' + if b == -1: + b = '-' + title = str('y = ') + str(a) + 'x**2 + ' + str(b) + 'x + ' + str(c) + ax.set_title(title) + plt.plot(x,y) + + + #centre bottom and left axes to zero + + ax.spines['left'].set_position('zero') + ax.spines['right'].set_color('none') + ax.spines['bottom'].set_position('zero') + ax.spines['top'].set_color('none') + + + figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds +amp = 1 +function = 'y = ax + b' +set_plot(1,1,1, function) + +#------------End Matplotlib code -------------------- + +#column 1 for function type and constant values ... + +column1 = [ + [sg.Text('Select constants & function type', )], + [sg.InputCombo(['y = ax + b', 'y = ax^2 + bx + c'], size = (16, 4), key = '_function_'), + sg.Text('Function', size = (10, 1))], [sg.Text('', size = (1, 2))], + [sg.Spin([sz for sz in range (-6,6)], initial_value =1, size = (3,2), key = '_a_'), + sg.Text('a', size = (3, 1)), + sg.Spin([sz for sz in range (-6,6)], initial_value =1, size = (3,2), key = '_b_'), + sg.Text('b', size = (3, 1)), + sg.Spin([sz for sz in range (-6,6)], initial_value =1, size = (3,2), key = '_c_'), + sg.Text('c', size = (3, 1))], [sg.Text('', size = (1, 1))], + [sg.ReadButton('Redraw Plot', button_color = ('White', 'Red'))], + [sg.Text('', size = (1, 14))]] + +column2 = [[sg.Text('Plot Test - PySimpleGUI and Matplotlib and options')], + [sg.Canvas(size = (figure_w, figure_h), key = '_canvas_')], + [sg.OK(pad=((figure_w / 2, 0), 1), size=(4, 1), button_color = ('White', 'Red'))]] + +layout = [[sg.Column(column1), sg.Column(column2)]] +window = sg.Window('Matplot, PySimpleGUI and options', force_toplevel = True).Layout(layout).Finalize() + +fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig) + +while True: + button, value = window.Read() + if button == 'Redraw Plot': + a = int(value['_a_']) + b = int(value['_b_']) + c = int(value['_c_']) + function = value['_function_'] + set_plot(a,b,c,function) + fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig) + + if button is None: + break + + diff --git a/ProgrammingClassExamples/Win10 versions/1a PSG (Entry and PopUp).py b/ProgrammingClassExamples/Win10 versions/1a PSG (Entry and PopUp).py new file mode 100644 index 000000000..1b7b9ded7 --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/1a PSG (Entry and PopUp).py @@ -0,0 +1,36 @@ +#PySimple examples (v 3.8) +#Tony Crewe +#Sep 2018 + +import PySimpleGUI as sg + +#layout, Text, Input,button on line below +layout = [ + [sg.Text('Celcius'), sg.InputText()], + [sg.Submit()], + ] + +#setup window with Title +window = sg.Window('Temperature Converter').Layout(layout) + +#get value (part of a list) +button, value = window.Read() +if button is None: + #windows was closed without button being pressed + exit(0) + +#convert and create string +fahrenheit = round(9/5*float(value[0]) +32, 1) +result = 'Temperature in Fahrenheit is: ' + str(fahrenheit) +#display in Popup +sg.Popup('Result', result) + + + + + + + + + + diff --git a/ProgrammingClassExamples/Win10 versions/1b PSG (Format).py b/ProgrammingClassExamples/Win10 versions/1b PSG (Format).py new file mode 100644 index 000000000..2b65953fe --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/1b PSG (Format).py @@ -0,0 +1,39 @@ +#PySimple examples (v 3.8) +#Tony Crewe +#Sep 2018 + +import PySimpleGUI as sg + +#Set formatting options for all elements rather than individually. +sg.SetOptions (background_color = 'LightBlue', + element_background_color = 'LightBlue', + text_element_background_color = 'LightBlue', + font = ('Arial', 10, 'bold'), + text_color = 'Blue', + input_text_color ='Blue', + button_color = ('White', 'Blue') + ) +#adjust widths +layout = [ + [sg.Text('Celcius', size =(12,1)), sg.InputText(size = (8,1))], + [sg.Submit()] + ] + +window = sg.Window('Converter').Layout(layout) +button, value = window.Read() +if button is None: + #windows was closed without button being pressed + exit(0) +fahrenheit = round(9/5*float(value[0]) +32, 1) +result = 'Temperature in Fahrenheit is: ' + str(fahrenheit) +sg.Popup('Result',result) + + + + + + + + + + diff --git a/ProgrammingClassExamples/Win10 versions/1c PSG (persistent form and bind key).py b/ProgrammingClassExamples/Win10 versions/1c PSG (persistent form and bind key).py new file mode 100644 index 000000000..ee46d08f5 --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/1c PSG (persistent form and bind key).py @@ -0,0 +1,35 @@ +#PySimple examples (v 3.8) +#Tony Crewe +#Sep 2018 + +import PySimpleGUI as sg + +sg.SetOptions (background_color = 'LightBlue', + element_background_color = 'LightBlue', + text_element_background_color = 'LightBlue', + font = ('Arial', 10, 'bold'), + text_color = 'Blue', + input_text_color ='Blue', + button_color = ('White', 'Blue') + ) +#update (via list) values and and display answers +#value[0] is celcius input, value[1] is input to place result. +#Use ReadButton with while true: - keeps window open. + +layout = [ [sg.Text('Enter a Temperature in Celcius')], + [sg.Text('Celcius', size =(8,1)), sg.InputText(size = (15,1))], + [sg.Text('Result', size =(8,1)), sg.InputText(size = (15,1))], + [sg.ReadButton('Submit', bind_return_key = True)]] +#Return = button press +window = sg.Window('Converter').Layout(layout) + +while True: + #get result + button, value = window.Read() + #break out of loop is button not pressed. + if button is not None: + fahrenheit = round(9/5*float(value[0]) +32, 1) + #put result in 2nd input box + window.FindElement(1).Update(fahrenheit) + else: + break diff --git a/ProgrammingClassExamples/Win10 versions/1d PSG (named input keys and catch errors).py b/ProgrammingClassExamples/Win10 versions/1d PSG (named input keys and catch errors).py new file mode 100644 index 000000000..2aa09f44d --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/1d PSG (named input keys and catch errors).py @@ -0,0 +1,36 @@ +#PySimple examples (v 3.8) +#Tony Crewe +#Sep 2018 + +import PySimpleGUI as sg + +sg.SetOptions (background_color = 'LightBlue', + element_background_color = 'LightBlue', + text_element_background_color = 'LightBlue', + font = ('Arial', 10, 'bold'), + text_color = 'Blue', + input_text_color ='Blue', + button_color = ('White', 'Blue') + ) +#name inputs (key) uses dictionary- easy to see updating of results +#value[input] first input value te c... +layout = [ [sg.Text('Enter a Temperature in Celcius')], + [sg.Text('Celcius', size =(8,1)), sg.InputText(size = (15,1),key = '_input_')], + [sg.Text('Result', size =(8,1)), sg.InputText(size = (15,1),key = '_result_')], + [sg.ReadButton('Submit', bind_return_key = True)]] + +window = sg.FlexForm('Temp Converter').Layout(layout) + +while True: + button, value = window.Read() + if button is not None: + #catch program errors for text or blank entry: + try: + fahrenheit = round(9/5*float(value['_input_']) +32, 1) + #put result in text box + window.FindElement('_result_').Update(fahrenheit) + except ValueError: + sg.Popup('Error','Please try again') + + else: + break diff --git a/ProgrammingClassExamples/Win10 versions/1e PSG (validation and Look and Feel).py b/ProgrammingClassExamples/Win10 versions/1e PSG (validation and Look and Feel).py new file mode 100644 index 000000000..3db950a1b --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/1e PSG (validation and Look and Feel).py @@ -0,0 +1,34 @@ +#PySimple examples (v 3.8) +#Tony Crewe +#Sep 2018 + +import PySimpleGUI as sg + +#Can use a variety of themes - plus individual options +sg.ChangeLookAndFeel('SandyBeach') +sg.SetOptions (font = ('Arial', 10, 'bold')) + + +layout = [ [sg.Text('Enter a Temperature in Celcius')], + [sg.Text('Celcius', size =(8,1)), sg.InputText(size = (15,1),key = '_input_')], + [sg.Text('Result', size =(8,1)), sg.InputText(size = (15,1),key = '_result_')], + [sg.ReadButton('Submit', bind_return_key = True)]] + +window = sg.Window('Temp Converter').Layout(layout) + +while True: + button, value = window.Read() + if button is not None: + #catch program errors for text, floats or blank entry: + #Also validation for range [0, 50] + try: + if float(value['_input_']) > 50 or float(value['_input_']) <0: + sg.Popup('Error','Out of range') + else: + fahrenheit = round(9/5*int(value['_input_']) +32, 1) + window.FindElement('_result_').Update(fahrenheit) + except ValueError: + sg.Popup('Error','Please try again') + + else: + break diff --git a/ProgrammingClassExamples/Win10 versions/2a. PSG (checkbox and radiobuttons) - Copy.py b/ProgrammingClassExamples/Win10 versions/2a. PSG (checkbox and radiobuttons) - Copy.py new file mode 100644 index 000000000..c5f9cacb4 --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/2a. PSG (checkbox and radiobuttons) - Copy.py @@ -0,0 +1,44 @@ +#PySimple examples (v 3.8) +#Tony Crewe +#Sep 2018 + +import PySimpleGUI as sg + +#Set colour scheme and font +sg.ChangeLookAndFeel('GreenTan') +sg.SetOptions (font =('Calibri',12,'bold')) + + + +#One checkbox and three radio buttons (grouped as 'Radio1') +#value[0] - checkbox, Value[1-3] radiobutton selection +layout = [[sg.Text('Membership Calculator', font = ('Calibri', 16, 'bold'))], + [sg.Checkbox(' Student? 10% off', size = (25,1)), + sg.ReadButton('Display Cost', size = (14,1))], + [sg.Radio('1 month $50', 'Radio1', default = True), + sg.Radio('3 months $100', 'Radio1'), + sg.Radio('1 year $300', 'Radio1')], + [sg.Text('', size = (30,1), justification = 'center', font =('Calibri', 16, 'bold'), key = 'result')]] + +window = sg.Window('Gym Membership').Layout(layout) + +while True: + button, value = window.Read() + if button is not None: + if value[1]: + cost = 50 + elif value[2]: + cost = 100 + else: + cost = 300 + if value[0]: + #apply discount + cost = cost*0.9 + + #format as currency $ symbol and 2 d.p. - make a string + result = str(' Cost: ' + '${:.2f}'.format(cost)) + #put the result in Textbox + window.FindElement('result').Update(result) + + else: + break diff --git a/ProgrammingClassExamples/Win10 versions/2b. PSG (Add logo).py b/ProgrammingClassExamples/Win10 versions/2b. PSG (Add logo).py new file mode 100644 index 000000000..cf35f47d2 --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/2b. PSG (Add logo).py @@ -0,0 +1,42 @@ +#PySimple examples (v 3.8) +#Tony Crewe +#Sep 2018 + +import PySimpleGUI as sg +import os + +sg.SetOptions (font =('Calibri',12,'bold')) + +#get pathname to current file +dirname, filename = os.path.split(os.path.abspath(__file__)) +#add file name for image +pathname = os.path.join(dirname ,'Gym_Logo.png') + +layout = [[sg.Image(pathname),sg.Text(' Membership Calculator', font = ('Calibri', 16, 'bold'))], + [sg.Checkbox(' Student? 10% off', size = (25,1)), + sg.ReadButton('Display Cost', size = (14,1))], + [sg.Radio('1 month $50', 'Radio1', default = True), + sg.Radio('3 months $100', 'Radio1'), + sg.Radio('1 year $300', 'Radio1')], + [sg.Text('', size = (30,1), justification = 'center', font =('Calibri', 16, 'bold'), key = 'result')]] + +window = sg.Window('Gym Membership').Layout(layout) + +while True: + button, value = window.Read() + if button is not None: + if value[1]: + cost = 50 + elif value[2]: + cost = 100 + else: + cost = 300 + if value[0]: + cost = cost*0.9 + + #format as currency $ symbol and 2 d.p. - make a string + result = str(' Cost: ' + '${:.2f}'.format(cost)) + window.FindElement('result').Update(result) + + else: + break diff --git a/ProgrammingClassExamples/Win10 versions/2b_makewinexe_file.py b/ProgrammingClassExamples/Win10 versions/2b_makewinexe_file.py new file mode 100644 index 000000000..351f082d1 --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/2b_makewinexe_file.py @@ -0,0 +1,36 @@ +import PySimpleGUI as sg +#pip install PyInstaller +#windows command prompt pyinstaller -wF 2b_makewinexe_file.py +#must CD to directory where py file is + +sg.ChangeLookAndFeel('GreenTan') #Set colour scheme +sg.SetOptions (font =('Calibri',12,'bold') ) #and font + +form = sg.FlexForm('Gym Membership') + + +layout = [[sg.Text('Membership Calculator', font = ('Calibri', 16, 'bold'))], + [sg.Checkbox('CGS student?', size = (22,1)), #value[0] + sg.ReadButton('Display Cost', size = (14,1))], + [sg.Radio('One Month', 'Radio1', default = True), #value[1] + sg.Radio('Three Month', 'Radio1'), #value[2] + sg.Radio('One Year', 'Radio1')], #value[3] + [sg.Text('', size = (30,1), justification = 'center', font =('Calibri', 16, 'bold'), key = 'result')]] + +form.Layout(layout) +while True: + button, value = form.Read() + if button is not None: + if value[1]: + cost = 50 + elif value[2]: + cost = 100 + else: + cost = 300 + if value[0]: + cost = cost*0.9 + result = str(' Cost: ' + '${:.2f}'.format(cost)) #format as currency - make a string + form.FindElement('result').Update(result) #put the result in Textbox + + else: + break diff --git a/ProgrammingClassExamples/Win10 versions/3 PSG (multiline display).py b/ProgrammingClassExamples/Win10 versions/3 PSG (multiline display).py new file mode 100644 index 000000000..1f6e50433 --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/3 PSG (multiline display).py @@ -0,0 +1,41 @@ + +#PySimple examples (v 3.8) +#Tony Crewe +#Sep 2018 + +import PySimpleGUI as sg + +sg.ChangeLookAndFeel('GreenTan') + +sg.SetOptions(font = ('Courier New', 12)) + + + +layout = [ + [sg.Text('Enter and Add Data to Display', font = ('Calibri', 14,'bold'))], + [sg.Text('Race:', size = (5,1)), sg.InputText(size = (8,1)), + sg.Text('Club:', size = (5,1)), sg.InputText(size = (8,1))], + [sg.Text('Name:', size = (5,1)), sg.InputText(size = (8,1)), + sg.Text('Time:', size = (5,1)), sg.InputText(size = (8,1)),sg.Text(' '), + sg.ReadButton('Add Data', font = ('Calibri', 12, 'bold'))], + [sg.Text('_'*40)], + [sg.Text(' Race Club Name Time')], + [sg.Multiline(size =(40,6),key = '_multiline_')] + ] + +window = sg.Window('Enter & Display Data').Layout(layout) + +string = '' +S=[] +while True: + + button, value = window.Read() + if button is not None: + #use string formatting - best way? plus Courier New font - non-proportional font + S = S + ['{:^9s}{:<11s}{:<10s}{:>8s}'.format(value[0],value[1],value[2],value[3])] + for s in S: + string = string + s + '\n' + window.FindElement('_multiline_').Update(string) + string ='' + else: + break diff --git a/ProgrammingClassExamples/Win10 versions/4a PSG (Sliders and combo).py b/ProgrammingClassExamples/Win10 versions/4a PSG (Sliders and combo).py new file mode 100644 index 000000000..ed19269f7 --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/4a PSG (Sliders and combo).py @@ -0,0 +1,48 @@ +#PySimple examples (v 3.8) +#Tony Crewe +#Sep 2018 + +import PySimpleGUI as sg + +#use of Column to help with layout - vertical sliders take up space + +column1 = [ + [sg.Text('Pick operation', size = (15,1), font = ('Calibri', 12, 'bold'))], + [sg.InputCombo(['Add','Subtract','Multiply','Divide'], size = (10,6))], + [sg.Text('', size =(1,4))]] +column2 = [ + [sg.ReadButton('Submit', font = ('Calibri', 12, 'bold'), button_color = ('White', 'Red'))], + [sg.Text('Result:', font = ('Calibri', 12, 'bold'))],[sg.InputText(size = (12,1), key = '_result_')] + ] + + +layout = [ + [sg.Text('Slider and Combo box demo', font = ('Calibri', 14,'bold'))], + [sg.Slider(range = (-9, 9),orientation = 'v', size = (5,20), default_value = 0), + sg.Slider(range = (-9, 9),orientation = 'v', size = (5, 20), default_value = 0), + sg.Text(' '), sg.Column(column1), sg.Column(column2)]] + +#added grab_anywhere to when moving slider, who window doesn't move. + +window = sg.Window('Enter & Display Data',grab_anywhere = False).Layout(layout) + +#Get selection from combo: value[2] +#Slider values: value[0] and value[1] +while True: + button, value = window.Read() + if button is not None: + if value[2] == 'Add': + result = value[0] + value[1] + elif value[2] == 'Multiply': + result = value[0] * value[1] + elif value[2] == 'Subtract': + result = value[0] - value[1] + elif value[2] == 'Divide': #check for zero + if value[1] ==0: + sg.Popup('Second value can\'t be zero') + result = 'NA' + else: + result = value[0] / value[1] + window.FindElement('_result_').Update(result) + else: + break diff --git a/ProgrammingClassExamples/Win10 versions/4b PSG (Spinner and combo) .py b/ProgrammingClassExamples/Win10 versions/4b PSG (Spinner and combo) .py new file mode 100644 index 000000000..47d8a1a61 --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/4b PSG (Spinner and combo) .py @@ -0,0 +1,39 @@ +#PySimple examples (v 3.8) +#Tony Crewe +#Sep 2018 + +import PySimpleGUI as sg +sg.SetOptions(font= ('Calibri', 12, 'bold')) + +layout = [ + [sg.Text('Spinner and Combo box demo', font = ('Calibri', 14, 'bold'))], + [sg.Spin([sz for sz in range (-9,10)], size = (2,1),initial_value = 0), + sg.Spin([sz for sz in range (-9,10)], size = (2,1), initial_value = 0), + sg.Text('Pick operation ->', size = (15,1)), + sg.InputCombo(['Add','Subtract','Multiply','Divide'], size = (8,6))], + [sg.Text('Result: ')],[sg.InputText(size = (5,1), key = '_result_'), + sg.ReadButton('Calculate', button_color = ('White', 'Red'))]] + +window = sg.Window('Enter & Display Data', grab_anywhere= False).Layout(layout) + +while True: + button, value = window.Read() + + if button is not None: + #convert returned values to integers + val = [int(value[0]), int(value[1])] + if value[2] == 'Add': + result = val[0] + val[1] + elif value[2] == 'Multiply': + result = val[0] * val[1] + elif value[2] == 'Subtract': + result = val[0] - val[1] + elif value[2] == 'Divide': + if val[1] ==0: + sg.Popup('Second value can\'t be zero') + result = 'NA' + else: + result = round( val[0] / val[1], 3) + window.FindElement('_result_').Update(result) + else: + break diff --git a/ProgrammingClassExamples/Win10 versions/5a PSG (listboxes add remove).py b/ProgrammingClassExamples/Win10 versions/5a PSG (listboxes add remove).py new file mode 100644 index 000000000..24833c78f --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/5a PSG (listboxes add remove).py @@ -0,0 +1,44 @@ +#PySimple examples (v 3.8) +#Tony Crewe +#Sep 2018 + +import PySimpleGUI as sg + +sg.ChangeLookAndFeel('BlueMono') + +#use column feature with height listbox takes up +column1 = [ + [sg.Text('Add or Delete Items\nfrom a Listbox', font = ('Arial', 12, 'bold'))], + [sg.InputText( size = (15,1), key = 'add'), sg.ReadButton('Add')], + [sg.ReadButton('Delete selected entry')]] + +#initial listbox entries +List = ['Austalia', 'Canada', 'Greece'] + +#add initial List to listbox +layout = [ + [sg.Listbox(values=[l for l in List], size = (30,8), key ='_listbox_'), + sg.Column(column1)]] + +window = sg.Window('Listbox').Layout(layout) + +while True: + button, value = window.Read() + if button is not None: + #value[listbox] returns a list + #using value[listbox][0] gives the string + if button == 'Delete selected entry': + #ensure something is selected + if value['_listbox_'] == []: + sg.Popup('Error','You must select a Country') + else: + #find and remove this + List.remove(value['_listbox_'][0]) + if button == 'Add': + #add string in add box to list + List.append(value['add']) + List.sort() + #update listbox + window.FindElement('_listbox_').Update(List) + else: + break diff --git a/ProgrammingClassExamples/Win10 versions/6a PSG (search linear and binary).py b/ProgrammingClassExamples/Win10 versions/6a PSG (search linear and binary).py new file mode 100644 index 000000000..18bb76a28 --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/6a PSG (search linear and binary).py @@ -0,0 +1,86 @@ +#PySimple examples (v 3.8) +#Tony Crewe +#Sep 2018 + +import PySimpleGUI as sg + +sg.SetOptions (font =('Calibri',12,'bold')) + +layout =[[sg.Text('Search Demo', font =('Calibri', 18, 'bold')), sg.ReadButton('Show Names')], +[sg.Text('',size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color ='White',key = '_display1_'), + sg.Text('',size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color ='White',key = '_display2_')], + [sg.Text('_'*32,font = ('Calibri', 12))], + [sg.InputText(size = (14,1), key = '_linear_'), sg.InputText(size = (14,1), key = '_binary_')], + [sg.ReadButton('Linear Search', size = (13,1)), sg.ReadButton('Binary Search', size = (14,1))], + ] +window = sg.Window('Search Demo').Layout(layout) + +#names for Demo, could be loaded from a file +names = ['Roberta', 'Kylie', 'Jenny', 'Helen', + 'Andrea', 'Meredith','Deborah','Pauline', + 'Belinda', 'Wendy'] + +sorted_names = ['Andrea','Belinda','Deborah','Helen', + 'Jenny','Kylie','Meredith','Pauline', + 'Roberta','Wendy'] + +#function to display list +def display_list(list, display): + names = '' + for l in list: #add list elements with new line + names = names + l + '\n' + window.FindElement(display).Update(names) + +#Linear Search - no need for Ordered list +def linear_search(): + l = names[:] + found = False + for l in l: + if l == value['_linear_']: #Check each value + found = True + window.FindElement('_display1_').Update('Linear search\n' + l + ' found.') + break + if not found: + window.FindElement('_display1_').Update(value['_linear_'] + ' was \nNot found') + +#Binary Search - only works for ordered lists +def binary_search(): + l = sorted_names[:] + lo = 0 + hi = len(l)-1 + #Start with found is False + found = False + while lo <= hi: + #Start in middle + mid = (lo + hi) //2 + #get the value from the search box + if l[mid] == value['_binary_']: + window.FindElement('_display2_').Update('Binary search\n' + l[mid] + ' found.') + #If found display name and stop + found = True + break + elif l[mid] < value['_binary_']: + #Search in top half + lo = mid + 1 + else: + #Search in lower half + hi = mid - 1 + #If we get to end - display not found + if not found: + window.FindElement('_display2_').Update(value['_binary_'] + ' was \nNot found') + +while True: + button, value = window.Read() + + if button is not None: + #show names - unordered and sorted + if button == 'Show Names': + display_list(names,'_display1_') + display_list(sorted_names, '_display2_') + if button == 'Linear Search': + linear_search() + if button == 'Binary Search': + binary_search() + else: + break + diff --git a/ProgrammingClassExamples/Win10 versions/6b PSG (search - disabled buttons).py b/ProgrammingClassExamples/Win10 versions/6b PSG (search - disabled buttons).py new file mode 100644 index 000000000..f617e471b --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/6b PSG (search - disabled buttons).py @@ -0,0 +1,95 @@ +#PySimple examples (v 3.8) +#Tony Crewe +#Sep 2018 + +import PySimpleGUI as sg + +sg.SetOptions (font =('Calibri',12,'bold')) + +layout =[[sg.Text('Search Demo', font =('Calibri', 18, 'bold')), sg.ReadButton('Show Names')], +[sg.Text('',size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color ='White',key = '_display1_'), + sg.Text('',size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color ='White',key = '_display2_')], + [sg.Text('_'*32,font = ('Calibri', 12))], + [sg.InputText(size = (14,1), key = '_linear_'), sg.InputText(size = (14,1), key = '_binary_')], + [sg.ReadButton('Linear Search', size = (13,1),key = '_ls_'), sg.ReadButton('Binary Search', size = (14,1),key='_bs_')], + ] +window = sg.Window('Search Demo').Layout(layout) + +#finalize allows the disabling of the two buttons before .Read statement +window.Finalize() +window.FindElement('_ls_').Update(disabled = True) +window.FindElement('_bs_').Update(disabled = True) + +#names for Demo, could be loaded from a file +names = ['Roberta', 'Kylie', 'Jenny', 'Helen', + 'Andrea', 'Meredith','Deborah','Pauline', + 'Belinda', 'Wendy'] + +sorted_names = ['Andrea','Belinda','Deborah','Helen', + 'Jenny','Kylie','Meredith','Pauline', + 'Roberta','Wendy'] + +#function to display list +def display_list(list, display): + names = '' + #add list elements with new line + for l in list: + names = names + l + '\n' + window.FindElement(display).Update(names) + #enable buttons now data loaded + window.FindElement('_ls_').Update(disabled = False) + window.FindElement('_bs_').Update(disabled = False) + +#Linear Search - no need for Ordered list +def linear_search(): + l = names[:] + found = False + for l in l: + #Check each value + if l == value['_linear_']: + found = True + window.FindElement('_display1_').Update('Linear search\n' + l + ' found.') + break + if not found: + window.FindElement('_display1_').Update(value['_linear_'] + ' was \nNot found') + +#Binary Search - only works for ordered lists +def binary_search(): + l = sorted_names[:] + lo = 0 + hi = len(l)-1 + #Start with found is Flase + found = False + while lo <= hi: + #Start in middle + mid = (lo + hi) //2 + #get the value from the search box + if l[mid] == value['_binary_']: + window.FindElement('_display2_').Update('Binary search\n' + l[mid] + ' found.') + #If found display and stop + found = True + break + elif l[mid] < value['_binary_']: + #Search in top half + lo = mid + 1 + else: + #Search in lower half + hi = mid - 1 + #If we get to end - display not found + if not found: + window.FindElement('_display2_').Update(value['_binary_'] + ' was \nNot found') + +while True: + button, value = window.Read() + if button is not None: + #show names - unordered and sorted + if button == 'Show Names': + display_list(names,'_display1_') + display_list(sorted_names, '_display2_') + if button == '_ls_': + linear_search() + if button == '_bs_': + binary_search() + else: + break + diff --git a/ProgrammingClassExamples/Win10 versions/6c PSG (search text preloaded).py b/ProgrammingClassExamples/Win10 versions/6c PSG (search text preloaded).py new file mode 100644 index 000000000..89009642c --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/6c PSG (search text preloaded).py @@ -0,0 +1,76 @@ +#PySimple examples (v 3.8) +#Tony Crewe +#Sep 2018 + +import PySimpleGUI as sg + +sg.SetOptions (font =('Calibri',12,'bold')) + +#names for Demo, could be loaded from a file + +names = ['Roberta', 'Kylie', 'Jenny', 'Helen', + 'Andrea', 'Meredith','Deborah','Pauline', + 'Belinda', 'Wendy'] +name = '' +for l in names: + name = name + l + '\n' + +sorted_names = ['Andrea','Belinda','Deborah','Helen', + 'Jenny','Kylie','Meredith','Pauline', + 'Roberta','Wendy'] + +sortname = '' +for l in sorted_names: + sortname = sortname + l +'\n' + +layout =[[sg.Text('Search Demo', font =('Calibri', 18, 'bold'))], +[sg.Text(name, size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color = 'White',key = '_display1_'), + sg.Text(sortname, size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color = 'White',key = '_display2_')], + [sg.Text('_'*32,font = ('Calibri', 12))], + [sg.InputText(size = (14,1), key = '_linear_'), sg.InputText(size = (14,1), key = '_binary_')], + [sg.ReadButton('Linear Search', size = (13,1)), sg.ReadButton('Binary Search', size = (14,1))], + ] +window = sg.Window('Search Demo').Layout(layout) + +#Linear Search - no need for Ordered list +def linear_search(): + l = names[:] + found = False + for l in l: + if l == value['_linear_']: + found = True + sg.Popup('Linear search\n' + l + ' found.') + break + if not found: + sg.Popup('Linear search\n' +(value['_linear_'] + ' was not found')) + +#Binary Search - only works for ordered lists +def binary_search(): + l = sorted_names[:] + lo = 0 + hi = len(l)-1 + found = False + while lo <= hi: + mid = (lo + hi) //2 + if l[mid] == value['_binary_']: + sg.Popup('Binary search\n' + l[mid] + ' found.') + found = True + break + elif l[mid] < value['_binary_']: + lo = mid + 1 + else: + hi = mid - 1 + if not found: + sg.Popup('Binary search\n' +(value['_binary_'] + ' was not found')) + +while True: + button, value = window.Read() + + if button is not None: + if button == 'Linear Search': + linear_search() + if button == 'Binary Search': + binary_search() + else: + break + diff --git a/ProgrammingClassExamples/Win10 versions/6d PSG (sort and search with textbox.py b/ProgrammingClassExamples/Win10 versions/6d PSG (sort and search with textbox.py new file mode 100644 index 000000000..90a7f9af5 --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/6d PSG (sort and search with textbox.py @@ -0,0 +1,137 @@ +#PySimple examples (v 3.8) +#Tony Crewe +#Sep 2018 + +import PySimpleGUI as sg + +sg.SetOptions (font =('Calibri',12,'bold')) + + +#setup column (called column1) of buttons to use in layout + +column1 = [[sg.ReadButton('Original list', size = (13,1))], + [sg.ReadButton('Default sort', size = (13,1))], + [sg.ReadButton('Sort: selection',size = (13,1))], + [sg.ReadButton('Sort: quick', size = (13,1))]] + +layout =[[sg.Text('Search and Sort Demo', font =('Calibri', 20, 'bold'))], +[sg.Text('',size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color = 'White',key = '_display_'), sg.Column(column1)], + [sg.Text('_'*32,font = ('Calibri', 12))], + [sg.InputText(size = (13,1), key = '_linear_'), sg.Text(' '), sg.InputText(size = (13,1), key = '_binary_')], + [sg.ReadButton('Linear Search', size = (13,1)), sg.Text(' '), sg.ReadButton('Binary Search', size = (13,1))], + ] + +window = sg.Window('Search and Sort Demo').Layout(layout) + +#names for Demo, could be loaded from a file +names= ['Roberta', 'Kylie', 'Jenny', 'Helen', + 'Andrea', 'Meredith','Deborah','Pauline', + 'Belinda', 'Wendy'] + +#function to display list +def display_list(list): + #store list in Multiline text globally + global list_displayed + list_displayed = list + display = '' + #add list elements with new line + for l in list: + display = display + l + '\n' + window.FindElement('_display_').Update(display) + +#use inbuilt python sort +def default(names): + l = names[:] + l.sort() + display_list(l) + +#Selection sort - See Janson Ch 7 +def sel_sort(names): + l = names[:] + for i in range(len(l)): + smallest = i + for j in range(i+1, len(l)): + #find smallest value + if l[j] < l[smallest]: + #swap it to front + smallest = j + #repeat from next position + l[smallest], l[i] = l[i], l[smallest] + display_list(l) + +#Quick sort - See Janson Ch 7 +def qsort_holder(names): + l = names[:] + #pass List, first and last + quick_sort(l, 0, len(l) -1) + display_list(l) +#Quicksort is a partition sort +def quick_sort(l, first, last): + if first >= last: + return l + pivot = l[first] + low = first + high = last + while low < high: + while l[high] > pivot: + high = high -1 + while l[low] < pivot: + low = low + 1 + if low <= high: + l[high], l[low] = l[low], l[high] + low = low + 1 + high = high -1 + #continue splitting - sort small list + quick_sort(l, first, low -1) + quick_sort(l, low, last) + +#Linear Search - no need for Ordered list +def linear_search(): + l = names[:] + found = False + for l in l: + if l == value['_linear_']: + found = True + window.FindElement('_display_').Update('Linear search\n' + l + ' found.') + break + if not found: + window.FindElement('_display_').Update(value['_linear_'] + ' was \nNot found') + +#Binary Search - only works for ordered lists +def binary_search(): + l= list_displayed[:] + lo = 0 + hi = len(l)-1 + found = False + while lo <= hi: + mid = (lo + hi) //2 + if l[mid] == value['_binary_']: + window.FindElement('_display_').Update('Binary search\n' + l[mid] + ' found.') + found = True + break + elif l[mid] < value['_binary_']: + lo = mid + 1 + else: + hi = mid - 1 + if not found: + window.FindElement('_display_').Update(value['_binary_'] + ' was \nNot found') + + +while True: + button, value = window.Read() + if button is not None: + if button == 'Original list': + display_list(names) + if button == 'Default sort': + default(names) + if button == 'Sort: selection': + sel_sort(names) + if button == 'Sort: quick': + qsort_holder(names) + if button == 'Linear Search': + linear_search() + if button == 'Binary Search': + binary_search() + else: + break + diff --git a/ProgrammingClassExamples/Win10 versions/6e PSG (sort and search with listbox).py b/ProgrammingClassExamples/Win10 versions/6e PSG (sort and search with listbox).py new file mode 100644 index 000000000..09434f89d --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/6e PSG (sort and search with listbox).py @@ -0,0 +1,132 @@ +#PySimple examples (v 3.8) +#Tony Crewe +#Sep 2018 + +import PySimpleGUI as sg + +sg.SetOptions (font =('Calibri',12,'bold')) + +column1 = [[sg.ReadButton('Original list', size = (13,1))], + [sg.ReadButton('Default sort', size = (13,1))], + [sg.ReadButton('Sort: selection',size = (13,1))], + [sg.ReadButton('Sort: quick', size = (13,1))]] + +layout =[[sg.Text('Search and Sort Demo', font =('Calibri', 20, 'bold'))], +[sg.Listbox(values =[''], size = (14, 11),font = ('Calibri', 12), background_color ='White',key = '_display_'), sg.Column(column1)], + [sg.Text('_'*32,font = ('Calibri', 12))], + [sg.InputText(size = (13,1), key = '_linear_'), sg.Text(' '), sg.InputText(size = (13,1), key = '_binary_')], + [sg.ReadButton('Linear Search', size = (13,1)), sg.Text(' '), sg.ReadButton('Binary Search', size = (13,1))], + ] + +window = sg.Window('Search and Sort Demo').Layout(layout) + +names= ['Roberta', 'Kylie', 'Jenny', 'Helen', + 'Andrea', 'Meredith','Deborah','Pauline', + 'Belinda', 'Wendy'] + +#function to display list +def display_list(list): + global list_displayed + #store list in Multiline text globally + list_displayed = list + #add list elements with new line + values = [l for l in list] + window.FindElement('_display_').Update(values) + +#use inbuilt python sort +def default(names): + l = names[:] + l.sort() + display_list(l) + +#Selection sort +def sel_sort(names): + l = names[:] + for i in range(len(l)): + smallest = i + for j in range(i+1, len(l)): + if l[j] < l[smallest]: + smallest = j + l[smallest], l[i] = l[i], l[smallest] + display_list(l) + +#Quick sort +def qsort_holder(names): + l = names[:] + quick_sort(l, 0, len(l) - 1) + display_list(l) + +def quick_sort(l, first, last): + if first >= last: + return l + pivot = l[first] + low = first + high = last + while low < high: + while l[high] > pivot: + high = high -1 + while l[low] < pivot: + low = low + 1 + if low <= high: + l[high], l[low] = l[low], l[high] + low = low + 1 + high = high -1 + quick_sort(l, first, low -1) + quick_sort(l, low, last) + +#Linear Search - no need for Ordered list +def linear_search(): + l = names[:] + found = False + for l in l: + if l == value['_linear_']: + found = True + #Create list for display + result = ['Linear search', l + ' found'] + window.FindElement('_display_').Update(result) + break + if not found: + #Create list for display + result = [value['_linear_'], 'was not found'] + window.FindElement('_display_').Update(result) + +#Binary Search +def binary_search(): + l = list_displayed[:] + lo = 0 + hi = len(l)-1 + found = False + while lo <= hi: + mid = (lo + hi) //2 + if l[mid] == value['_binary_']: + #Create list for display + result = ['Binary search', l[mid] + ' found.'] + window.FindElement('_display_').Update(result) + found = True + break + elif l[mid] < value['_binary_']: + lo = mid + 1 + else: + hi = mid - 1 + if not found: + #Create list for display + result = [value['_binary_'], 'was not found'] + window.FindElement('_display_').Update(result) + +while True: + button, value = window.Read() + if button is not None: + if button == 'Original list': + display_list(names) + if button == 'Default sort': + default(names) + if button == 'Sort: selection': + sel_sort(names) + if button == 'Sort: quick': + qsort_holder(names) + if button == 'Linear Search': + linear_search() + if button == 'Binary Search': + binary_search() + else: + break diff --git a/ProgrammingClassExamples/Win10 versions/6f PSG (data from text file).py b/ProgrammingClassExamples/Win10 versions/6f PSG (data from text file).py new file mode 100644 index 000000000..126dcfa07 --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/6f PSG (data from text file).py @@ -0,0 +1,145 @@ +#PySimple examples (v 3.8) +#Tony Crewe +#Sep 2018 + +import PySimpleGUI as sg +import os + +sg.SetOptions (font =('Calibri',12,'bold')) + +#get pathname to current file + +dirname, filename = os.path.split(os.path.abspath(__file__)) +pathname = os.path.join(dirname, 'Names.txt') #original data +spathname = os.path.join(dirname, 'Names(sorted).txt') #sorted data + +#Get data from file +names = [line.strip() for line in open(pathname)] + +column1 = [[sg.ReadButton('Original list', size = (13,1))], + [sg.ReadButton('Default sort', size = (13,1))], + [sg.ReadButton('Sort: selection',size = (13,1))], + [sg.ReadButton('Sort: quick', size = (13,1))], + [sg.Text('______________',font = ('Calibri', 12))], + [sg.ReadButton('Save data\ndisplayed', size = (13,2))]] + +layout =[[sg.Text('Search and Sort Demo', font =('Calibri', 20, 'bold'))], +[sg.Listbox(values =[''], size = (14, 11),font = ('Calibri', 12), background_color ='White',key = '_display_'), sg.Column(column1)], + [sg.Text('_'*32,font = ('Calibri', 12))], + [sg.InputText(size = (13,1), key = '_linear_'), sg.Text(' '), sg.InputText(size = (13,1), key = '_binary_')], + [sg.ReadButton('Linear Search', size = (13,1)), sg.Text(' '), sg.ReadButton('Binary Search', size = (13,1))], + ] + +window = sg.Window('Search and Sort Demo').Layout(layout) + +#function to display list +def display_list(list): + global list_displayed + #store list in Multiline text globally + list_displayed = list + #add list elements with new line + values = [l for l in list] + window.FindElement('_display_').Update(values) + +#use inbuilt python sort +def default(names): + l = names[:] + l.sort() + display_list(l) + +#Selection sort +def sel_sort(names): + l = names[:] + for i in range(len(l)): + smallest = i + for j in range(i+1, len(l)): + if l[j] < l[smallest]: + smallest = j + l[smallest], l[i] = l[i], l[smallest] + display_list(l) + +#Quick sort +def qsort_holder(names): + l = names[:] + quick_sort(l, 0, len(l) - 1) + display_list(l) + +def quick_sort(l, first, last): + if first >= last: + return l + pivot = l[first] + low = first + high = last + while low < high: + while l[high] > pivot: + high = high -1 + while l[low] < pivot: + low = low + 1 + if low <= high: + l[high], l[low] = l[low], l[high] + low = low + 1 + high = high -1 + quick_sort(l, first, low -1) + quick_sort(l, low, last) + +#Linear Search - no need for Ordered list +def linear_search(): + l = names[:] + found = False + for l in l: + if l == value['_linear_']: + found = True + #Create list for display + result = ['Linear search', l + ' found'] + window.FindElement('_display_').Update(result) + break + if not found: + #Create list for display + result = [value['_linear_'], 'was not found'] + window.FindElement('_display_').Update(result) + +#Binary Search +def binary_search(): + l = list_displayed[:] + lo = 0 + hi = len(l)-1 + found = False + while lo <= hi: + mid = (lo + hi) //2 + if l[mid] == value['_binary_']: + #Create list for display + found = True + result = ['Binary search', l[mid] + ' found.'] + window.FindElement('_display_').Update(result) + break + elif l[mid] < value['_binary_']: + lo = mid + 1 + else: + hi = mid - 1 + if not found: + #Create list for display + result = [value['_binary_'], 'was not found'] + window.FindElement('_display_').Update(result) + +while True: + button, value = window.Read() + if button is not None: + if button == 'Original list': + display_list(names) + if button == 'Default sort': + default(names) + if button == 'Sort: selection': + sel_sort(names) + if button == 'Sort: quick': + qsort_holder(names) + if button == 'Linear Search': + linear_search() + if button == 'Binary Search': + binary_search() + if button == 'Save data\ndisplayed': + f = open(spathname, 'w') + for name in list_displayed: + print (name, file = f) + f.close() + else: + break diff --git a/ProgrammingClassExamples/Win10 versions/7a PSG (Data entry calc using file save retrieve).py b/ProgrammingClassExamples/Win10 versions/7a PSG (Data entry calc using file save retrieve).py new file mode 100644 index 000000000..002599f17 --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/7a PSG (Data entry calc using file save retrieve).py @@ -0,0 +1,63 @@ +#PySimple examples (v 3.8) +#Tony Crewe +#Sep 2018 + +import PySimpleGUI as sg +import os #to work with windows OS + +sg.ChangeLookAndFeel('GreenTan') +sg.SetOptions(font = ('Calibri', 12, 'bold')) + +layout = [ + [sg.Text('Enter a Name and four Marks')], + [sg.Text('Name:', size =(10,1)), sg.InputText(size = (12,1), key = '_name_')], + [sg.Text('Mark1:', size =(10,1)), sg.InputText(size = (6,1), key = '_m1_')], + [sg.Text('Mark2:', size =(10,1)), sg.InputText(size = (6,1), key = '_m2_')], + [sg.Text('Mark3:', size =(10,1)), sg.InputText(size = (6,1), key = '_m3_')], + [sg.Text('Mark4:', size =(10,1)), sg.InputText(size = (6,1), key = '_m4_')], + [sg.ReadButton('Save', size = (8,1),key = '_save_'), sg.Text('Press to Save to file')], + [sg.ReadButton('Display',size = (8,1), key = '_display_'), sg.Text('To retrieve and Display')], + [sg.Multiline(size = (28,4), key = '_multiline_')]] + +window = sg.Window('Simple Average Finder').Layout(layout) + + +while True: + button, value = window.Read() #value is a dictionary holding name and marks (4) + if button is not None: + #initialise variables + total = 0.0 + index = '' + name = value['_name_'] + #get pathname to current file + dirname, filename = os.path.split(os.path.abspath(__file__)) + #add desired file name for saving to path + pathname = os.path.join(dirname , 'results.txt' ) + + #needs validation and try/catch error checking, will crash if blank or text entry for marks + + if button == '_save_': + #create dictionary index _m1_ ... _m4_ + for i in range (1,5): + index = '_m' + str(i) + '_' + total += float(value[index]) + average = total/4 + #open file and save + f = open(pathname, 'w') + print (name, file = f) + print (total, file = f) + print (average, file = f) + f.close() + + #some error checking for missing file needed here + + if button == '_display_': + #This loads the file line by line into a list called data. + #the strip() removes whitespaces from beginning and end of each line. + data = [line.strip() for line in open(pathname)] + #create single string to display in multiline object. + string = 'Name: ' + data[0] +'\nTotal: ' + str(data[1]) + '\nAverage: ' + str(data[2]) + window.FindElement('_multiline_').Update(string) + else: + break + diff --git a/ProgrammingClassExamples/Win10 versions/7b PSG (add validation and error trap).py b/ProgrammingClassExamples/Win10 versions/7b PSG (add validation and error trap).py new file mode 100644 index 000000000..53bfb180d --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/7b PSG (add validation and error trap).py @@ -0,0 +1,68 @@ +#PySimple examples (v 3.8) +#Tony Crewe +#Sep 2018 + +import PySimpleGUI as sg +import os #to work with windows OS + +sg.ChangeLookAndFeel('Dark') +sg.SetOptions(font = ('Calibri', 12, 'bold')) + +layout = [ + [sg.Text('Enter a Name and four Marks')], + [sg.Text('Name:', size =(10,1)), sg.InputText(size = (12,1), key = '_name_')], + [sg.Text('Mark1:', size =(10,1)), sg.InputText(size = (6,1), key = '_m1_')], + [sg.Text('Mark2:', size =(10,1)), sg.InputText(size = (6,1), key = '_m2_')], + [sg.Text('Mark3:', size =(10,1)), sg.InputText(size = (6,1), key = '_m3_')], + [sg.Text('Mark4:', size =(10,1)), sg.InputText(size = (6,1), key = '_m4_')], + [sg.ReadButton('Save', size = (8,1),key = '_save_'), sg.Text('Press to Save to file')], + [sg.ReadButton('Display',size = (8,1), key = '_display_'), sg.Text('To retrieve and Display')], + [sg.Multiline(size = (28,4), key = '_multiline_')]] + +window = sg.Window('Simple Average Finder').Layout(layout) + + +while True: + button, value = window.Read() #value is a dictionary holding name and marks (4) + if button is not None: + #initialise variables + total = 0.0 + index = '' + name = value['_name_'] + #get pathname to current file + dirname, filename = os.path.split(os.path.abspath(__file__)) + #add desired file name for saving to path + pathname = os.path.join(dirname , 'results.txt' ) + #generic catch error - blanks or wrong data types + try: + if button == '_save_': + for i in range (1,5): + index = '_m' + str(i) + '_' + + #Check for values between 0 and 100 + if float(value[index]) < 0 or float(value[index]) >100: + sg.Popup('Out of Range', 'Enter Marks between 0 and 100') + else: + total += float(value[index]) + average = total/4 + f = open(pathname, 'w') + print (name, file = f) + print (total, file = f) + print (average, file = f) + f.close() + except ValueError: + sg.Popup('Error','Check entries and try again') + + if button == '_display_': + #This loads the file line by line into a list called data. + #the strip() removes whitespaces from beginning and end of each line. + try: + data = [line.strip() for line in open(pathname)] + #create single string to display in multiline object. + string = 'Name: ' + data[0] +'\nTotal: ' + str(data[1]) + '\nAverage: ' + str(data[2]) + window.FindElement('_multiline_').Update(string) + except: + sg.PopupError('Error', 'Problem finding or reading file') + else: + break + diff --git a/ProgrammingClassExamples/Win10 versions/7c PSG (add get pathname to save and retrieve files).py b/ProgrammingClassExamples/Win10 versions/7c PSG (add get pathname to save and retrieve files).py new file mode 100644 index 000000000..a4af2ca27 --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/7c PSG (add get pathname to save and retrieve files).py @@ -0,0 +1,76 @@ +#PySimple examples (v 3.8) +#Tony Crewe +#Sep 2018 + +import PySimpleGUI as sg +import os #to work with windows OS + +sg.ChangeLookAndFeel('BlueMono') +sg.SetOptions(font = ('Calibri', 12, 'bold')) + +layout = [ + [sg.Text('Enter a Name and four Marks')], + [sg.Text('Name:', size =(10,1)), sg.InputText(size = (12,1), key = '_name_')], + [sg.Text('Mark1:', size =(10,1)), sg.InputText(size = (6,1), key = '_m1_')], + [sg.Text('Mark2:', size =(10,1)), sg.InputText(size = (6,1), key = '_m2_')], + [sg.Text('Mark3:', size =(10,1)), sg.InputText(size = (6,1), key = '_m3_')], + [sg.Text('Mark4:', size =(10,1)), sg.InputText(size = (6,1), key = '_m4_')], + [sg.ReadButton('Save', size = (8,1),key = '_save_'), sg.Text('Press to Save to file')], + [sg.ReadButton('Display',size = (8,1), key = '_display_'), sg.Text('To retrieve and Display')], + [sg.Multiline(size = (28,4), key = '_multiline_')]] + +window = sg.Window('Simple Average Finder').Layout(layout) + + +while True: + button, value = window.Read() #value is a dictionary holding name and marks (4) + if button is not None: + #initialise variables + total = 0.0 + index = '' + name = value['_name_'] + #get pathname to current file + dirname, filename = os.path.split(os.path.abspath(__file__)) + #add desired file name for saving to path + pathname = dirname + '\\results.txt' + #generic catch error - blanks or wrong data types + try: + if button == '_save_': + for i in range (1,5): + index = '_m' + str(i) + '_' + + #Check for values between 0 and 100 + if float(value[index]) < 0 or float(value[index]) >100: + sg.Popup('Out of Range', 'Enter Marks between 0 and 100') + else: + total += float(value[index]) + average = total/4 + #check location and file name for file, no_window so go straight to folder selection + + foldername = sg.PopupGetFolder('', no_window=True) + filename = sg.PopupGetFile('Please enter a file name for your results') + pathname = os.path.join(foldername ,filename + '.txt') + + f = open(pathname, 'w') + print (name, file = f) + print (total, file = f) + print (average, file = f) + f.close() + except ValueError: + sg.Popup('Error','Check entries and try again') + + if button == '_display_': + #get pathname: folder and file + pathname = sg.PopupGetFile('file to open', no_window=True, file_types=(("text files","*.txt"),)) + #This loads the file line by line into a list called data. + #the strip() removes whitespaces from beginning and end of each line. + try: + data = [line.strip() for line in open(pathname)] + #create single string to display in multiline object. + string = 'Name: ' + data[0] +'\nTotal: ' + str(data[1]) + '\nAverage: ' + str(data[2]) + window.FindElement('_multiline_').Update(string) + except: + sg.PopupError('Error', 'Problem finding or reading file') + else: + break + diff --git a/ProgrammingClassExamples/Win10 versions/8a PSG (Data to plot from csv file).py b/ProgrammingClassExamples/Win10 versions/8a PSG (Data to plot from csv file).py new file mode 100644 index 000000000..d419d623f --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/8a PSG (Data to plot from csv file).py @@ -0,0 +1,40 @@ +#Matplotlib, pyplt and csv +#Tony Crewe +#Sep 2017 - updated Sep 2018 + +import matplotlib.pyplot as plt +import csv +from matplotlib.ticker import MaxNLocator + + +x=[] +y=[] + +with open('weight 2018.csv', 'r', encoding = 'utf-8-sig') as csvfile: + plots = csv.reader(csvfile) + for data in plots: + #get heading for x and y axes + var1 = (data[0]) + var2 = (data[1]) + break + for data in plots: + #get values - add to x list and y list + x.append(data[0]) + y.append(float(data[1])) + + +ax = plt.subplot(1,1,1) +ax.set_ylim([82, 96]) +ax.xaxis.set_major_locator(MaxNLocator(10)) +ax.spines['right'].set_color('none') +ax.spines['top'].set_color('none') + +plt.plot(x,y, label = 'data loaded\nfrom csv file') +plt.axhline(y = 85.5, color = 'orange', linestyle = '--', label = 'target') +plt.xlabel(var1) +plt.ylabel(var2) +plt.title('weight loss from\n first quarter 2018') + + +plt.legend() +plt.show() diff --git a/ProgrammingClassExamples/Win10 versions/8b PSG (Tables and calc from csv file).py b/ProgrammingClassExamples/Win10 versions/8b PSG (Tables and calc from csv file).py new file mode 100644 index 000000000..880caee9e --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/8b PSG (Tables and calc from csv file).py @@ -0,0 +1,67 @@ +# PySimple examples (v 3.9.3) +# Tony Crewe +# Sep 2018 - updated Oct 2018 + +# Based of Example program from MikeTheWatchGuy +# https://gitlab.com/lotspaih/PySimpleGUI + +import sys +import PySimpleGUI as sg +import csv + +sg.ChangeLookAndFeel('BrownBlue') + + +def calc_ladder(): + filename = sg.PopupGetFile('Get required file', no_window=True, file_types=(("CSV Files", "*.csv"),)) + # populate table with file contents + # Assume we know csv has heading in row 1 + # Assume we know 7 columns of data - relevenat to AFL w/o Pts or % shown + # data is a list of lists containing data about each team + # data[0] is one teams data data[0[[0] = team, data[0][1] P, data[0] [2] W, + # data[0][3] L, data [0][4] D, data [0][5] F, data [0][6] A + # no error checking or validation used. + + # initialise variable + data = [] + header_list = [] + # read csv + with open(filename, "r") as infile: + reader = csv.reader(infile) + for i in range(1): + # get headings + header = next(reader) + # read everything else into a list of rows + data = list(reader) + # add headings + header = header + ['%', 'Pts'] + for i in range(len(data)): + # calculate % and format to 2 decimal places + percent = str('{:.2f}'.format(int(data[i][5]) / int(data[i][6]) * 100)) + data[i] = data[i] + [percent] # add to data + pts = int(data[i][2]) * 4 + int(data[i][4]) * 2 + data[i] = data[i] + [pts] # add to data + + # use Table (explore settings) and add to column layout + col_layout = [[sg.Table(values=data, headings=header, auto_size_columns=True, + max_col_width=12, justification='right', background_color='White', + text_color='Black', alternating_row_color='LightBlue', size=(None, len(data)))]] + + layout = [[sg.Column(col_layout, size=(500, 400), scrollable=True)], ] + + window = sg.Window('Table', location=(700, 325), grab_anywhere=False).Layout(layout) + b, v = window.Read() + + +slayout = [ + [sg.Text('Load AFL file to display results with points and percentage'), sg.ReadButton('Load File', size=(20, 1))]] +swindow = sg.Window('Load File', location=(700, 250)).Layout(slayout) + +while True: + button, value = swindow.Read() + if button is not None: + if button == 'Load File': + calc_ladder() + else: + break + diff --git a/ProgrammingClassExamples/Win10 versions/8c PSG (Tables - add sort).py b/ProgrammingClassExamples/Win10 versions/8c PSG (Tables - add sort).py new file mode 100644 index 000000000..1880145df --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/8c PSG (Tables - add sort).py @@ -0,0 +1,70 @@ +#PySimple examples (v 3.9.3) +#Tony Crewe +#Sep 2018 - updated Oct 2018 + +#Based of Example program from MikeTheWatchGuy +#https://gitlab.com/lotspaih/PySimpleGUI + +import sys +import PySimpleGUI as sg +import csv +import operator + +sg.ChangeLookAndFeel('Dark') + +def table_example(): + + filename = sg.PopupGetFile('Get required file', no_window = True,file_types=(("CSV Files","*.csv"),)) + #populate table with file contents + #Assume we know csv has heading in row 1 + #Assume we know 7 columns of data - relevenat to AFL w/o Pts or % shown + #data is a list of lists containing data about each team + #data[0] is one teams data data[0[[0] = team, data[0][1] P, data[0] [2] W, + #data[0][3] L, data [0][4] D, data [0][5] F, data [0][6] A + #no error checking or validation used. + + #initialise variables + data = [] + header_list = [] + with open(filename, "r") as infile: + reader = csv.reader(infile) + for i in range (1): + header = next(reader) + data = list(reader) + header = header + ['%', 'Pts'] + for i in range (len(data)): + #calculate % + percent = int(data[i][5])/int(data[i][6])*100 + data[i] = data[i] + [percent] + pts = int(data[i][2])*4 + int(data[i][4])*2 + data[i] = data[i] + [pts] + #sort data + #first by % + data.sort(key = operator.itemgetter(7), reverse = True) + #then by pts + data.sort(key = operator.itemgetter(8), reverse = True) + #and format string to 2 decimal places + for i in range(len(data)): + data[i][7] = str('{:.2f}'.format(data[i][7])) + #use Table (explore settings) and add to column layout + col_layout = [[sg.Table(values=data, headings=header, auto_size_columns=True, + max_col_width = 12,justification='right', text_color = 'White', + alternating_row_color = 'Grey', size=(None, len(data)))]] + #experimented with size and location to get windows to fit :-) + #remove titlebar of main display window + + layout = [[sg.Column(col_layout, size=(415,400), scrollable=True)],] + window = sg.Window('Table', location = (662, 320), no_titlebar=True, grab_anywhere=False).Layout(layout) + b, v = window.Read() + +slayout = [[sg.Text(' Load AFL (csv) file to display results.', font = ('Calibri', 14, 'bold') ), + sg.ReadButton('Load File', size = (14,1))]] +swindow = sg.Window('Load File', location = (654,250)).Layout(slayout) + +while True: + button, value = swindow.Read() + if button is not None: + if button == 'Load File': + table_example() + else: + break diff --git a/ProgrammingClassExamples/Win10 versions/8d PSG (Tables - add logo).py b/ProgrammingClassExamples/Win10 versions/8d PSG (Tables - add logo).py new file mode 100644 index 000000000..1e3819d57 --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/8d PSG (Tables - add logo).py @@ -0,0 +1,66 @@ +#PySimple examples (v 3.9.3) +#Tony Crewe +#Sep 2018 - updated Oct 2018 + +#Based of Example program from MikeTheWatchGuy +#https://gitlab.com/lotspaih/PySimpleGUI + +import sys +import PySimpleGUI as sg +import csv +import operator +import os + +sg.ChangeLookAndFeel('Dark') + +#get pathname to current file and add file name for image +dirname, filename = os.path.split(os.path.abspath(__file__)) + +pathname = os.path.join(dirname , 'AFL.png' ) + +def table_example(): + + filename = sg.PopupGetFile('Get required file', no_window = True,file_types=(("CSV Files","*.csv"),)) + + + data = [] + header_list = [] + + with open(filename, "r") as infile: + reader = csv.reader(infile) + for i in range (1): + header = next(reader) + data = list(reader) + header = header + ['%', 'Pts'] + for i in range (len(data)): + + percent = int(data[i][5])/int(data[i][6])*100 + data[i] = data[i] + [percent] + pts = int(data[i][2])*4 + int(data[i][4])*2 + data[i] = data[i] + [pts] + + data.sort(key = operator.itemgetter(7), reverse = True) + data.sort(key = operator.itemgetter(8), reverse = True) + + for i in range(len(data)): + data[i][7] = str('{:.2f}'.format(data[i][7])) + + col_layout = [[sg.Table(values=data, headings=header, auto_size_columns=True, + max_col_width = 12,justification='right', text_color = 'White', + alternating_row_color = 'Grey', size=(None, len(data)))]] + + layout = [[sg.Column(col_layout, size=(443,400), scrollable=True)],] + window = sg.Window('Table', location = (662, 328), no_titlebar=True, grab_anywhere=False).Layout(layout) + b, v = window.Read() + +slayout = [[sg.Image(pathname),sg.Text('Load AFL data to display results.', font = ('Calibri', 14, 'bold') ), + sg.ReadButton('Load File', size = (14,1))]] +swindow = sg.Window('Load File', location = (654,250)).Layout(slayout) + +while True: + button, value = swindow.Read() + if button is not None: + if button == 'Load File': + table_example() + else: + break diff --git a/ProgrammingClassExamples/Win10 versions/9a PSG Windows(location hide).py b/ProgrammingClassExamples/Win10 versions/9a PSG Windows(location hide).py new file mode 100644 index 000000000..823e091cd --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/9a PSG Windows(location hide).py @@ -0,0 +1,47 @@ +#PySimple examples (v 3.8) +#Tony Crewe +#Sep 2018 + +import PySimpleGUI as sg + +sg.ChangeLookAndFeel('SandyBeach') +sg.SetOptions (font = ('Calibri', 12, 'bold')) + + + +layout0 = [[sg.ReadButton('Show/Hide window1'),sg.ReadButton('Show/Hide window2')]] + +layout1 =[[ sg.Text('window1')], [sg.Multiline( size = (35, 10))]] +layout2 =[[ sg.Text('window2')], [sg.Multiline( size = (35, 10))]] +window0 = sg.Window('Home Window', location = (400, 150)).Layout(layout0) + +window1 = sg.Window('Window1', location = (400, 250)).Layout(layout1).Finalize() +window1.Hide() +w1 = False + +window2 = sg.Window('Window2', location = (800, 250)).Layout(layout2).Finalize() +window2.Hide() +w2 = False + +while True: + button, v = window0.Read() + if button is not None: + if button =='Show/Hide window1': + if w1 == True: + window1.Hide() + w1 = False + else: + window1.UnHide() + w1=True + if button =='Show/Hide window2': + if w2 == True: + window2.Hide() + w2 = False + else: + window2.UnHide() + w2=True + else: + break + + + diff --git a/ProgrammingClassExamples/Win10 versions/9b PSG Tabs example.py b/ProgrammingClassExamples/Win10 versions/9b PSG Tabs example.py new file mode 100644 index 000000000..1ddcf009a --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/9b PSG Tabs example.py @@ -0,0 +1,22 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 + +import PySimpleGUI as sg + +tab1_layout = [[sg.Text('This is inside tab 1')]] + +tab2_layout = [[sg.Text('This is inside tab 2')]] + +layout = [[sg.TabGroup([[sg.Tab('Tab 1', tab1_layout), + sg.Tab('Tab 2', tab2_layout)]])], + [sg.ReadButton('Read')]] + +window = sg.Window('Main Window').Layout(layout) + +while True: + b, v = window.Read() + if b is not None: + print(b,v) + else: + break diff --git a/ProgrammingClassExamples/Win10 versions/9c PSG Tabs example plus.py b/ProgrammingClassExamples/Win10 versions/9c PSG Tabs example plus.py new file mode 100644 index 000000000..68829e85a --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/9c PSG Tabs example plus.py @@ -0,0 +1,78 @@ +import PySimpleGUI as sg +import os + +sg.ChangeLookAndFeel('BlueMono') + +#get pathname to current file + +dirname, filename = os.path.split(os.path.abspath(__file__)) +pathname = os.path.join(dirname , 'Names.txt') + +#Get data from file +names = [line.strip() for line in open(pathname)] +sorted_names = names[:] +sorted_names.sort() + +tab1_layout =[[sg.Text('Linear Search Demo', font =('Calibri', 14, 'bold'))], + [sg.Listbox(values =[n for n in names], size = (15, 12),font = ('Calibri', 12), background_color ='White',key = '_display1_')], + [sg.Text('_'*15,font = ('Calibri', 12))], + [sg.Text('Enter name to search for:')], + [sg.InputText(size = (18,1), key = '_linear_')], + [sg.ReadButton('Linear Search', size = (15,1))]] + +tab2_layout = [[sg.Text('Binary Search Demo', font =('Calibri', 14, 'bold'))], + [sg.Listbox(values =[n for n in sorted_names], size = (15, 12),font = ('Calibri', 12), background_color ='White',key = '_display2_')], + [sg.Text('_'*18,font = ('Calibri', 12))], + [sg.Text('Enter name to search for:')], + [sg.InputText(size = (18,1), key = '_binary_')], + [sg.ReadButton('Binary Search', size = (15,1))]] + +layout = [ + [sg.TabGroup([[sg.Tab('Linear Search', tab1_layout),sg.Tab('Binary Search', tab2_layout)]])]] + +window = sg.Window('Main Window').Layout(layout) + +#Linear Search - no need for Ordered list +def linear_search(): + l = names[:] + found = False + for l in l: + if l == value['_linear_']: #Check each value + found = True + result = ['Linear search', l + ' found'] + window.FindElement('_display1_').Update(result) + break + if not found: + result = [value['_linear_'], 'was not found'] + window.FindElement('_display1_').Update(result) + +#Binary Search - only works for ordered lists +def binary_search(): + l = sorted_names + lo = 0 + hi = len(l)-1 + found = False + while lo <= hi: + mid = (lo + hi) //2 + if l[mid] == value['_binary_']: + found = True + result = ['Binary search', l[mid] + ' found.'] + window.FindElement('_display2_').Update(result) + break + elif l[mid] < value['_binary_']: + lo = mid + 1 + else: + hi = mid - 1 + if not found: + result = [value['_binary_'], 'was not found'] + window.FindElement('_display2_').Update(result) + +while True: + button, value = window.Read() + if button is not None: + if button == 'Linear Search': + linear_search() + if button == 'Binary Search': + binary_search() + else: + break diff --git a/ProgrammingClassExamples/Win10 versions/AFL.png b/ProgrammingClassExamples/Win10 versions/AFL.png new file mode 100644 index 000000000..ee3a35597 Binary files /dev/null and b/ProgrammingClassExamples/Win10 versions/AFL.png differ diff --git a/ProgrammingClassExamples/Win10 versions/AFL2018 (sorted alpha teams).csv b/ProgrammingClassExamples/Win10 versions/AFL2018 (sorted alpha teams).csv new file mode 100644 index 000000000..798296f6e --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/AFL2018 (sorted alpha teams).csv @@ -0,0 +1,19 @@ +Team,P,W,L,D,F,A +Adelaide Crows,22,12,10,0,1941,1865 +Brisbane Lions,22,5,17,0,1825,2049 +Carlton,22,2,20,0,1353,2282 +Collingwood,22,15,7,0,2046,1699 +Essendon,22,12,10,0,1932,1838 +Fremantle,22,8,14,0,1556,2041 +Geelong Cats,22,13,9,0,2045,1554 +Gold Coast Suns,22,4,18,0,1308,2182 +GWS Giants,22,13,8,1,1898,1661 +Hawthorn,22,15,7,0,1972,1642 +Melbourne,22,14,8,0,2299,1749 +North Melbourne,22,12,10,0,1950,1790 +Port Adelaide,22,12,10,0,1780,1654 +Richmond,22,18,4,0,2143,1574 +St Kilda,22,4,17,1,1606,2125 +Sydney Swans,22,14,8,0,1822,1664 +West Coast Eagles,22,16,6,0,2012,1657 +Western Bulldogs,22,8,14,0,1575,2037 diff --git a/ProgrammingClassExamples/Win10 versions/AFL2018 (sorted pts and %).csv b/ProgrammingClassExamples/Win10 versions/AFL2018 (sorted pts and %).csv new file mode 100644 index 000000000..71cb8c18a --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/AFL2018 (sorted pts and %).csv @@ -0,0 +1,19 @@ +Team,P,W,L,D,F,A +Richmond,22,18,4,0,2143,1574 +West Coast Eagles,22,16,6,0,2012,1657 +Collingwood,22,15,7,0,2046,1699 +Hawthorn,22,15,7,0,1972,1642 +Melbourne,22,14,8,0,2299,1749 +Sydney Swans,22,14,8,0,1822,1664 +GWS Giants,22,13,8,1,1898,1661 +Geelong Cats,22,13,9,0,2045,1554 +North Melbourne,22,12,10,0,1950,1790 +Port Adelaide,22,12,10,0,1780,1654 +Essendon,22,12,10,0,1932,1838 +Adelaide Crows,22,12,10,0,1941,1865 +Western Bulldogs,22,8,14,0,1575,2037 +Fremantle,22,8,14,0,1556,2041 +Brisbane Lions,22,5,17,0,1825,2049 +St Kilda,22,4,17,1,1606,2125 +Gold Coast Suns,22,4,18,0,1308,2182 +Carlton,22,2,20,0,1353,2282 diff --git a/ProgrammingClassExamples/Win10 versions/Gym_Logo.png b/ProgrammingClassExamples/Win10 versions/Gym_Logo.png new file mode 100644 index 000000000..45bb5f7bc Binary files /dev/null and b/ProgrammingClassExamples/Win10 versions/Gym_Logo.png differ diff --git a/ProgrammingClassExamples/Win10 versions/Names.txt b/ProgrammingClassExamples/Win10 versions/Names.txt new file mode 100644 index 000000000..d1b9fd24d --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/Names.txt @@ -0,0 +1,10 @@ +Roberta +Kylie +Jenny +Helen +Andrea +Meredith +Deborah +Pauline +Belinda +Wendy \ No newline at end of file diff --git a/ProgrammingClassExamples/Win10 versions/default_icon.ico b/ProgrammingClassExamples/Win10 versions/default_icon.ico new file mode 100644 index 000000000..1a41525ec Binary files /dev/null and b/ProgrammingClassExamples/Win10 versions/default_icon.ico differ diff --git a/ProgrammingClassExamples/Win10 versions/weight 2018.csv b/ProgrammingClassExamples/Win10 versions/weight 2018.csv new file mode 100644 index 000000000..66e7c2d97 --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/weight 2018.csv @@ -0,0 +1,98 @@ +Date,Weight (kg) +29-Dec,94.5 +30-Dec,94 +31-Dec,94 +1-Jan,93.5 +2-Jan,94.2 +3-Jan,94 +4-Jan,94 +5-Jan,93.4 +6-Jan,92.6 +7-Jan,93.1 +8-Jan,92.7 +9-Jan,92.5 +10-Jan,92.3 +11-Jan,92.1 +12-Jan,92.5 +13-Jan,92.6 +14-Jan,92.5 +15-Jan,92.1 +16-Jan,91.6 +17-Jan,91.3 +18-Jan,91.8 +19-Jan,91.7 +20-Jan,91.9 +21-Jan,91.8 +22-Jan,91.1 +23-Jan,90.7 +24-Jan,90.5 +25-Jan,90.5 +26-Jan,90.3 +27-Jan,90.1 +28-Jan,89.9 +29-Jan,90.2 +30-Jan,90.1 +31-Jan,89.9 +1-Feb,89.5 +2-Feb,89.1 +3-Feb,89.3 +4-Feb,89.4 +5-Feb,89.2 +6-Feb,88.2 +7-Feb,88.2 +8-Feb,88.3 +9-Feb,88.2 +10-Feb,89.1 +11-Feb,88.9 +12-Feb,88.6 +13-Feb,88.7 +14-Feb,88.5 +15-Feb,88.1 +16-Feb,87.8 +17-Feb,87.9 +18-Feb,88.1 +19-Feb,87.9 +20-Feb,87.6 +21-Feb,87.5 +22-Feb,87.3 +23-Feb,87 +24-Feb,87.5 +25-Feb,87.7 +26-Feb,87.4 +27-Feb,87.2 +28-Feb,86.9 +1-Mar,86.9 +2-Mar,86.9 +3-Mar,86.5 +4-Mar,86.8 +5-Mar,87 +6-Mar,86.9 +7-Mar,86.2 +8-Mar,86.4 +9-Mar,86.1 +10-Mar,86.7 +11-Mar,85.6 +12-Mar,85.8 +13-Mar,85.3 +14-Mar,85.1 +15-Mar,85.4 +16-Mar,84.5 +17-Mar,85.1 +18-Mar,84.8 +19-Mar,84.8 +20-Mar,84.8 +21-Mar,84.9 +22-Mar,85.5 +23-Mar,85.1 +24-Mar,85.5 +25-Mar,85.6 +26-Mar,85.9 +27-Mar,85.9 +28-Mar,85.5 +29-Mar,85.9 +30-Mar,85.5 +1-Apr,85.2 +2-Apr,84.8 +3-Apr,85.3 +4-Apr,85.4 +5-Apr,85.3 diff --git a/PySimpleGUI.png b/PySimpleGUI.png new file mode 100644 index 000000000..5e72ffcf3 Binary files /dev/null and b/PySimpleGUI.png differ diff --git a/PySimpleGUI.py b/PySimpleGUI.py new file mode 100644 index 000000000..1cab07414 --- /dev/null +++ b/PySimpleGUI.py @@ -0,0 +1,23118 @@ +#!/usr/bin/python3 +version = __version__ = "4.55.1.3 Unreleased" + +_change_log = """ + Changelog since 4.55.1 released to PyPI on 7-Nov-2021 + + 4.55.1.1 + Addition of stdin parm to execute_command_subprocess. This is to fix problem when pyinstaller is used to make an EXE from a psg program that calls this function + 4.55.1.2 + Changed getargspec call in the SDK Reference window to getfullargspec. In 3.11 getargspec is no longer supported and thus crashes + Added try to SDK Reference event loop to catch any additional problems that may pop up in 3.11 + 4.55.1.3 + Added Window.move_to_center - moves a window to the center of the screen. Good for when your window changes size or you want to recenter it + Disable debugger when installing from github + Better error reporting when a problem with the layout detected + """ + +__version__ = version.split()[0] # For PEP 396 and PEP 345 + +# The shortened version of version +try: + ver = version.split(' ')[0] +except: + ver = '' + +# __version__ = version + +port = 'PySimpleGUI' + +# 8""""8 8""""8 8""""8 8 8 8 +# 8 8 e e 8 e eeeeeee eeeee e eeee 8 " 8 8 8 +# 8eeee8 8 8 8eeeee 8 8 8 8 8 8 8 8 8e 8e 8 8e +# 88 8eeee8 88 8e 8e 8 8 8eee8 8e 8eee 88 ee 88 8 88 +# 88 88 e 88 88 88 8 8 88 88 88 88 8 88 8 88 +# 88 88 8eee88 88 88 8 8 88 88eee 88ee 88eee8 88ee8 88 + + +""" + Copyright 2018, 2019, 2020, 2021 PySimpleGUI(tm) + + Before getting into the details, let's talk about the high level goals of the PySimpleGUI project. + + From the inception these have been the project principals upon which it is all built + 1. Fun - it's a serious goal of the project. If we're not having FUN while making stuff, then something's not right + 2. Successful - you need to be successful or it's all for naught + 3. You are the important party - It's your success that determines the success of PySimpleGUI + + If these 3 things are kept at the forefront, then the rest tends to fall into place. + + PySimpleGUI is a "system", not just a program. There are 4 components of the "PySimpleGUI system" + 1. This software - PySimpleGUI.com + 2. The documentation - PySimpleGUI.org + 3. Demo Programs - Demos.PySimpleGUI.org + 4. Support - Issues.PySimpleGUI.org + + + This software is available for your use under a LGPL3+ license + + This notice, these first 150 lines of code shall remain unchanged + + + + 888 .d8888b. 8888888b. 888 .d8888b. + 888 d88P Y88b 888 Y88b 888 d88P Y88b + 888 888 888 888 888 888 .d88P + 888 888 888 d88P 888 8888" 888 + 888 888 88888 8888888P" 888 "Y8b. 8888888 + 888 888 888 888 888 888 888 888 + 888 Y88b d88P 888 888 Y88b d88P + 88888888 "Y8888P88 888 88888888 "Y8888P" + + + In addition to the normal publishing requirements of LGPL3+, these also apply: + 1. These and all comments are to remain in the source code + 2. The "Official" version of PySimpleGUI and the associated documentation lives on two (and **only** two) places: + 1. GitHub - (http://www.PySimpleGUI.com) currently pointing at: + https://github.com/PySimpleGUI/PySimpleGUI + 2. PyPI - pip install PySimpleGUI is the customary way of obtaining the latest release + + THE official documentation location is: + Read the Docs (via http://www.PySimpleGUI.org). Currently is pointed at: + https://pysimplegui.readthedocs.io/en/latest/ + If you've obtained this software in any other way, then those listed here, then SUPPORT WILL NOT BE PROVIDED. + 3. If you use PySimpleGUI in your project/product, a notice of its use needs to be displayed in your readme file + ----------------------------------------------------------------------------------------------------------------- + + The PySimpleGUI project goals are simple: + 1. Have fun + 2. You, the user, are successful + + The first bit of good news for you is that literally 100s of pages of documentation await you. + 300 Demo Programs have been written as a "jump start" mechanism to get your running as quickly as possible. + + Some general bits of advice: + Upgrade your software! python -m pip install --upgrade --no-cache-dir PySimpleGUI + If you're thinking of filing an Issue or posting a problem, Upgrade your software first + There are constantly something new and interesting coming out of this project so stay current if you can + + The FASTEST WAY to learn PySimpleGUI is to begin to play with it, and to read the documentation. + http://www.PySimpleGUI.org + http://Calls.PySimpleGUI.org + http://Cookbook.PySimpleGUI.org + + The User Manual and the Cookbook are both designed to paint some nice looking GUIs on your screen within 5 minutes of you deciding to PySimpleGUI out. + + A note from your sponsor.... + “Don’t aim at success. The more you aim at it and make it a target, the more you are going to miss it. + For success, like happiness, cannot be pursued; it must ensue, and it only does so as the unintended side effect of one’s personal dedication to a cause greater.” + — Viktor Frankl + + I first saw this quote in a truncated format: + "Happiness, cannot be pursued; it must ensue, and it only does so as the unintended side effect of one’s personal dedication to a cause greater." + + Everyone is different, but my experience with the PySimpleGUI project matches this theory. It's taken a lifetime of trying and "failing" and trying + to find happiness before I finally figured this truth-for-me out. If I do a long list of things, and live life in a kind & loving way, then the + result is happiness. It's a biproduct, not a directly produced thing. This should be taught in school. Or maybe it can't. + I hope you find happiness, but more importantly, or maybe first, I hope you find that bigger-than-you thing. For me it's always been programming. It seems to be + the giving back part, not just the calling, that makes the happiness fusion-reactor operate. + + "Thank you" has fueled this project. I'm incredibly grateful to have users that are in turn grateful. It's a feedback loop of gratitude. What a fantastic thing! +""" + +# all of the tkinter involved imports +import tkinter as tk +from tkinter import filedialog +from tkinter.colorchooser import askcolor +from tkinter import ttk +import tkinter.scrolledtext as tkst +import tkinter.font +from uuid import uuid4 + +# end of tkinter specific imports +# get the tkinter detailed version +tclversion_detailed = tkinter.Tcl().eval('info patchlevel') +framework_version = tclversion_detailed + +import time +import pickle +import calendar +import datetime +import textwrap + +import inspect +import traceback +import difflib +import copy +import pprint +try: # Because Raspberry Pi is still on 3.4....it's not critical if this module isn't imported on the Pi + from typing import List, Any, Union, Tuple, Dict, SupportsAbs, Optional # because this code has to run on 2.7 can't use real type hints. Must do typing only in comments +except: + print('*** Skipping import of Typing module. "pip3 install typing" to remove this warning ***') +import random +import warnings +from math import floor +from math import fabs +from functools import wraps + +try: # Because Raspberry Pi is still on 3.4.... + # from subprocess import run, PIPE, Popen + import subprocess +except Exception as e: + print('** Import error {} **'.format(e)) + +import threading +import itertools +import os +import json +import configparser +import queue + +try: + import webbrowser + + webbrowser_available = True +except: + webbrowser_available = False +# used for github upgrades +import urllib.request +import urllib.error +import urllib.parse +import pydoc +from urllib import request +import os +import sys +import re +import site +import tempfile +import ctypes +import platform + +warnings.simplefilter('always', UserWarning) + +g_time_start = 0 +g_time_end = 0 +g_time_delta = 0 + + +# These timer routines are to help you quickly time portions of code. Place the timer_start call at the point +# you want to start timing and the timer_stop at the end point. The delta between the start and stop calls +# is returned from calling timer_stop + +def timer_start(): + """ + Time your code easily.... starts the timer. + Uses the time.time value, a technique known to not be terribly accurage, but tis' gclose enough for our purposes + """ + global g_time_start + + g_time_start = time.time() + + +def timer_stop(): + """ + Time your code easily.... stop the timer and print the number of milliseconds since the timer start + + :return: delta in milliseconds from timer_start was called + :rtype: int + """ + global g_time_delta, g_time_end + + g_time_end = time.time() + g_time_delta = g_time_end - g_time_start + return int(g_time_delta * 1000) + + +def _timeit(func): + """ + Put @_timeit as a decorator to a function to get the time spent in that function printed out + + :param func: Decorated function + :type func: + :return: Execution time for the decorated function + :rtype: + """ + + @wraps(func) + def wrapper(*args, **kwargs): + start = time.time() + result = func(*args, **kwargs) + end = time.time() + print('{} executed in {:.4f} seconds'.format(func.__name__, end - start)) + return result + + return wrapper + + +_timeit_counter = 0 +MAX_TIMEIT_COUNT = 1000 +_timeit_total = 0 + + +def _timeit_summary(func): + """ + Same as the timeit decorator except that the value is shown as an averave + Put @_timeit_summary as a decorator to a function to get the time spent in that function printed out + + :param func: Decorated function + :type func: + :return: Execution time for the decorated function + :rtype: + """ + + @wraps(func) + def wrapper(*args, **kwargs): + global _timeit_counter, _timeit_total + + start = time.time() + result = func(*args, **kwargs) + end = time.time() + _timeit_counter += 1 + _timeit_total += end - start + if _timeit_counter > MAX_TIMEIT_COUNT: + print('{} executed in {:.4f} seconds'.format(func.__name__, _timeit_total / MAX_TIMEIT_COUNT)) + _timeit_counter = 0 + _timeit_total = 0 + return result + + return wrapper + + +def running_linux(): + """ + Determines the OS is Linux by using sys.platform + + Returns True if Linux + + :return: True if sys.platform indicates running Linux + :rtype: (bool) + """ + return sys.platform.startswith('linux') + + +def running_mac(): + """ + Determines the OS is Mac by using sys.platform + + Returns True if Mac + + :return: True if sys.platform indicates running Mac + :rtype: (bool) + """ + return sys.platform.startswith('darwin') + + +def running_windows(): + """ + Determines the OS is Windows by using sys.platform + + Returns True if Windows + + :return: True if sys.platform indicates running Windows + :rtype: (bool) + """ + return sys.platform.startswith('win') + + +def running_trinket(): + """ + A special case for Trinket. Checks both the OS and the number of environment variables + Currently, Trinket only has ONE environment variable. This fact is used to figure out if Trinket is being used. + + Returns True if "Trinket" (in theory) + + :return: True if sys.platform indicates Linux and the number of environment variables is 1 + :rtype: (bool) + """ + if len(os.environ) == 1 and sys.platform.startswith('linux'): + return True + return False + + +def running_replit(): + """ + A special case for REPLIT. Checks both the OS and for the existance of the number of environment variable REPL_OWNER + Currently, Trinket only has ONE environment variable. This fact is used to figure out if Trinket is being used. + + Returns True if running on "replit" + + :return: True if sys.platform indicates Linux and setting REPL_OWNER is found in the environment variables + :rtype: (bool) + """ + if 'REPL_OWNER' in os.environ and sys.platform.startswith('linux'): + return True + return False + + + + +# Handy python statements to increment and decrement with wrapping that I don't want to forget +# count = (count + (MAX - 1)) % MAX # Decrement - roll over to MAX from 0 +# count = (count + 1) % MAX # Increment to MAX then roll over to 0 + +""" + Welcome to the "core" PySimpleGUI code.... + + It's a mess.... really... it's a mess internally... it's the external-facing interfaces that + are not a mess. The Elements and the methods for them are well-designed. + PEP8 - this code is far far from PEP8 compliant. + It was written PRIOR to learning that PEP8 existed. + + I'll be honest.... started learning Python in Nov 2017, started writing PySimpleGUI in Feb 2018. + Released PySimpleGUI in July 2018. I knew so little about Python that my parameters were all named + using CamelCase. DOH! Someone on Reddit set me straight on that. So overnight I renamed all of the + parameters to lower case. Unfortunately, the internal naming conventions have been set. Mixing them + with PEP8 at this moment would be even MORE confusing. + + Code I write now, outside PySimpleGUI, IS PEP8 compliant. + + The variable and function naming in particular are not compliant. There is + liberal use of CamelVariableAndFunctionNames, but for anything externally facing, there are aliases + available for all functions. If you've got a serious enough problem with 100% PEP8 compliance + that you'll pass on this package, then that's your right and I invite you to do so. However, if + perhaps you're a practical thinker where it's the results that matter, then you'll have no + trouble with this code base. There is consisency however. + + I truly hope you get a lot of enjoyment out of using PySimpleGUI. It came from good intentions. +""" + +# ----====----====----==== Constants the user CAN safely change ====----====----====----# + +# Base64 encoded GIF file +DEFAULT_BASE64_ICON = b'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' + +DEFAULT_BASE64_ICON_16_BY_16 = b'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAKCSURBVDhPVZNbSFRRFIb35YwXItBIGtDsiqENEUTRjJlZkJggPSUYBD0UhULElE6hBY6ID/ZSpD1IDxaCEPhUaFLRQyWRNxIJe8syMxCjMCbB07fOsaMt+GftvWf//7/2Whyt1sTei/fCpDqQBTrGOi9Myrk7URwhnQUfQLeOvErJuUQgADlK6gObvAOl5sHx0doHljwARFRiCpxG5J1sjPxALiYNgn9kiQ3gafdYUYzseCd+FICX7sShw7LR++q6cl3XHaXQHFdOJLxFsJtvKHnbUr1nqp01hhStpXAzo7TZZXOjJ+9orT9pY74aY3ZobZZYW8D/GpjM19Ob088fmJxW2tkC4AJt17Oeg2MLrHX6jXWes16w1sbBkrFWBTB2nTLpv5VJg7wGNhRDwCS0tR1cbECkidwMQohAdoScqiz8/FCZUKlPCgSWlQ71elOI1fcco9hCXp1kS7dX3u+qVOm2L4nW8qE4Neetvl8v83NOb++9703BcUI/cU3imuWV7JedKtv5LdFaMRzHLW+N+zJoVDZzRLj6SFNfPlMYwy5bDiRcCojmz15tKx+6hKPv7LvjrG/Q2RoOwjSyzNDlahyzA2dAJeNtFcMHA2cfLn24STNr6P4I728jJ7hvf/lEGuaXLnkRAp0PyFK+hlyLSJGyGWnKyeBi2oJU0IPIjNd15uuL2f2PJgueQBKhVRETCgNeYU+xaeEpnWaw8cQPRM7g/McT8eF0De9u7P+49TqXF7no98BDEEkdvvXem8LAtfJniFRB/A5XeiAiG2+/icgHVQUW5d5KyAhl3M2y+U+ysv1FDukyKGQW3Y+vHJWvU7mz8RJSPZgDd3H2RqiUUn8BSQuaBvGjGpsAAAAASUVORK5CYII=' + +DEFAULT_BASE64_LOADING_GIF = b'R0lGODlhQABAAKUAAAQCBJyenERCRNTS1CQiJGRmZLS2tPTy9DQyNHR2dAwODKyqrFRSVNze3GxubMzKzPz6/Dw6PAwKDKSmpExKTNza3CwqLLy+vHx+fBQWFLSytAQGBKSipERGRNTW1CQmJGxqbLy6vPT29DQ2NHx6fBQSFKyurFRWVOTi5HRydPz+/Dw+PP7+/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQJCQAsACwAAAAAQABAAAAG/kCWcEgsGo/IpHLJbDqf0CjxwEmkJgepdrvIAL6A0mJLdi7AaMC4zD4eSmlwKduuCwNxdMDOfEw4D0oOeWAOfEkmBGgEJkgphF8ph0cYhCRHeJB7SCgJAgIJKFpnkGtTCoQKdEYGEmgSBlEqipAEEEakcROcqGkSok8PkGCBRhNwcrtICYQJUJnDm0YHASkpAatHK4Qrz8Nf0mTbed3B3wDFZY95kk8QtIS2bQ29r8BPE8PKbRquYBuxpJCwdKhBghUrQpFZAA8AgX2T7DwIACiixYsYM2rc+OSAhwrZOEa5QGHDlw0dLoiEAqEAoQK3VjJxCQmEzCUhzgXciOKE/gIFJ+4NEXBOAEcPyL6UqEBExLkvIjYyiMOAyICnAAZs9IdGgVWsWjWaTON1yAGsUTVOTUOhyLhh5TQi7cqUyIVzKjmiYCBBQtAjNAnZvKmk5cuYhJVc6DAWZd7ETTx6CAm5suXLRQY4sPDTQoqwmIlAADE2DYi0oUUQhbQC8WUQ5wZf9oDVA58KdaPAflqgTgMEXxA0iPIB64c6I9AgiFL624Y2FeLkbtJ82HM2tNPYfmLBOHLlUQJ/6z0POADhUa4+3V7HA/vw58gfEaFBA+qMIt6Su9/UPAL+F4mwWxwwJZGLGitp9kFfHzgAGhIHmhKaESIkB8AIrk1YBAQmDJiQoYYghijiiFAEAQAh+QQJCQApACwAAAAAQABAAIUEAgSEgoREQkTU0tRkYmQ0MjSkpqTs6ux0cnQUEhSMjozc3ty0trT09vRUUlRsamw8OjwMCgxMSkx8fnwcGhyUlpTk5uS8vrz8/vwEBgSMioxERkTc2txkZmQ0NjS0srT08vR0dnQUFhSUkpTk4uS8urz8+vxsbmw8Pjz+/v4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG/sCUcEgsGo/IpHLJbDqf0Kh0Sl0aPACAx1DtOh/ZMODhLSMNYjHXzBZi01lPm42BizHz5CAk2YQGSSYZdll4eUUYCHAhJkhvcAWHRiGECGeEa0gNAR4QEw1TA4RZgEcdcB1KBwViBQdSiqOWZ6wABZlIE3ATUhujAAJsj2FyUQK/wWbDcVInvydsumm8UaKjpWWrra+whNBtDRMeHp9UJs5pJ4aSXgMnGxsI2Oz09fb3+Pn6+/xEJh8KRjBo1M/JiARiEowoyIQAIQIMk1T4tXAfBw6aEI5KAArfgjcFFhj58CsLg3zDIhXRUBKABnwc4GAkoqDly3vWxMxLQbLk/kl8tbKoJAJCIyGO+RbUCnlkxC8F/DjsLOLQDsSISRREEBMBKlYlDRgoUMCg49ezaNOqVQJCqtm1Qy5IGAQgw4YLcFOYOGWnA8G0fAmRSVui5c+zx0omM2NBgwYLUhq0zPKWSIMFHCojsUAhiwjIUHKWnPpBAF27H5YEEBOg2mQA80A4ICQBRBJpWVpDAfHabAMUv1BoFkJChGcSUoCXREGEUslZRxoHAB3lQku8Qg7Q/ZWB26HAdgYLmTi5Aru9hPwSqdryKrsLG07fNTJ7soN7IAZwsH2EfUn3ETk1WUVYWbDdKBlQh1Usv0D3VQPLpOHBcAyBIAFt/K31AQrbBqGQWhtBAAAh+QQJCQAyACwAAAAAQABAAIUEAgSEgoTEwsREQkTk4uQsLiykoqRkYmQUEhTU0tRUUlT08vS0srSMjox8enwMCgzMysw8OjwcGhxcWlz8+vy8urxMSkzs6uysqqxsamzc2tyUlpQEBgSMiozExsTk5uQ0NjSkpqRkZmQUFhRUVlT09vS0trSUkpR8fnwMDgzMzsw8PjwcHhxcXlz8/vy8vrxMTkzc3tz+/v4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG/kCZcEgsGo/IpHLJbDqf0Kh0Sq1ar8nEgMOxqLBgZCIFKAMeibB6aDGbB2u1i+Muc1xxJSWmoSwpdHUcfnlGJSgIZSkoJUptdXCFRRQrdQArhEcqD24PX0wUmVMOlmUOSiqPXkwLLQ8PLQtTFCOlAAiiVyRuJFMatmVpYIB1jVEJwADCWCWBdsZQtLa4artmvaO2p2oXrhyxVCWVdSvQahR4ViUOZAApDuaSVhQaGvHy+Pn6+/z9/v8AAzrxICJCBBEeBII6YOnAPYVDWthqAfGIgGQC/H3o0OEDEonAKPL7IKHMCI9GQCQD0S+AmwBHVAJjyQ/FyyMgJ/YjUAvA/ggCFjFqDNAxSc46IitOOlqmRS6lQwSIABHhwAuoWLNq3cq1ogcHLVqgyFiFAoMGJ0w8teJBphsQCaWcaFcGwYkwITiV4hAiCsNSB7B4cLYXwpMNye5WcVEgWZkC6ZaUSAQMwUMnFRybqdCEgWYTVUhpBrBtSQfNHZC48BDCgIfIRKxpxrakAWojLjaUNCNhA2wZsh3TVuLZMWgiJRTYgiFKtObSShbQLZUinohkIohkHs25yYnERVRo/iSDQmPHBdYi+Wsp6ZDrjrNH1Uz2SYPpKRocOZ+sQJEQhLnBgQFTlHBWAyZcxoJmEhjRliVw4cMfMP4ZQYEADpDQggMvJ/yWB3zYYQWBZnFBxV4p8mFVAgzLqacQBSf0ZNIJLla0mgGu1ThFEAAh+QQJCQAqACwAAAAAQABAAIUEAgSUkpRERkTMyswkIiTs6uy0trRkZmQ0MjTU1tQcGhykpqRUVlT09vTEwsQsKix8enwMCgycnpzU0tS8vrw8Ojzc3txcXlz8/vwEBgSUlpRMSkzMzswkJiT08vS8urxsamw0NjTc2twcHhysqqz8+vzExsQsLix8fnxkYmT+/v4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG/kCVcEgsGo/IpHLJbDqf0Kh0Sq1ar8tEAstdWk4AwMnSLRfBYbF5nUint+tu2w2Ax5OFghMdPt2TBg9hDwZMImgnIn9HH3QAhUxaTw0LCw1WHY4dax6CAA8eVAWOYXplEm4SoqQApl2oaapUmXSbZgW0HaFUBo6QZpQLu1UGub+LWHnIy8zNzs/Q0dLTzSYQFxcoDtRMAwiOCCZJDRwDl88kGawZC0YlEOoAGRDnywPx6wNEHnxpJ8N/SvRjdaLEkAOsDiyjwMrRByEe8NHJADAOhIZ0IAgZgFHcIgYY3TAQYqIjMpAhw4xUEXFdxTUXUwLQKAQhKYXIGsl8CHGg/piXa0p4wvgAA5EG8MLMq4esZEiPRRoMMMGU2QKJbthxQ2LiG51wW5NgcACBwQUIFIyGXcu2bdgGGjZ06LBBQ1UoJg5UqHAAKhcTBByN8OukRApHKe5OcYA1TQbCTC6wuoClQeCGIxQjcYBxm5UAKQM8kdyQshUBKQU8CYERwZURKUc88crKNZIJZRlAmIAEdkjZTkhPPtLAppsDd1GHVO2Ec0PPREoodyTAIBHQIUWPHm5EA0btQxoowKgAaJISwtNcsF7ENyvgRCg0Vgq5iYMDISqkoIDEQkoyRZjgXhojQHcHRyHpYwRcAhBAgAB2LeNfSACyNaBgbqngXUPgGLElHSvVZahCA4fRcYFma3GQGwQciAhNEAAh+QQJCQAwACwAAAAAQABAAIUEAgSEgoTEwsRERkTk4uQkIiSkpqRsamwUEhTU0tT08vSUkpRUUlQ0MjS0trQMCgzMyszs6ux8enwcGhzc2tz8+vyMioxMTkysrqw8OjwEBgSEhoTExsRMSkzk5uQkJiSsqqxsbmwUFhTU1tT09vSUlpRUVlQ0NjS8vrwMDgzMzszs7ux8fnwcHhzc3tz8/vz+/v4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG/kCYcEgsGo/IpHLJbDqf0Kh0Sq1ar9hs1sNiebRgowsBACBczJcKA1K9wkxWucxSVgKTOUC0qcCTcnN1SBEnenoZX39iZAApaEcVhod6J35SFSgoJE4EXYpHFpSUAVIqBWUFKlkVIqOHIpdOJHlzE5xXEK+UHFAClChYBruHBlAowMLEesZPtHoiuFa6y2W9UBAtZS2rWK3VsVIkmtJYosuDi1Ekk68n5epPhe4R8VR3rnN8svZTLxAg2vDrR7CgwYMItZAo0eHDhw4l4CVMwgHVoRbXjrygMOLNQQEaXmnISARErQnNCFbQtqsFPBCUUtpbUG0BkRe19EzwaG9A/rUBREa8GkHQIrEWRCgMJcjyKJFvsHjG87kMaMmYBWkus1nEwEmZ9p7tmqBA44gRA/uhCDlq5MQlHJrOaSHgLZOFAwoUGBDRrt+/gAMLhkMiwYiyV0iogCARCwUTbDWYoHBPQmQJjak4eEDpgQMpKxpQarAiCwXOox4QhXLg1YEsDIgxgKKALSUNiKvUXpb5CLVXJKeoqNatCQdiwY2QyH0kAfEnu9syJ0Jiw4dUGxorqNb7SOtRr4+saDeH9BETsqOEHl36yIVXF46MQN15NRQSlstowIzk+K7kMGzW2WdUKAABB90FQEwp8l1g2wX2xfOda0oolkB3YWyw4GBCIfgHHIdCvDdKByAKsd4h5pUIAwkBsNRCdioWoUB7MRoUBAAh+QQJCQAuACwAAAAAQABAAIUEAgSEhoTMzsxMSkykpqQcHhz08vRkYmQUEhSUlpS0trTc3twsLixsbmwMCgzU1tSsrqz8+vycnpyMjoxUUlQkJiRsamwcGhy8vrw0NjR0dnQEBgTU0tSsqqz09vRkZmQUFhScmpy8urzk5uQ0MjR0cnQMDgzc2ty0srT8/vykoqSUkpRUVlQsKiz+/v4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG/kCXcEgsGo8RRWlAaSgix6h0Sp2KKoCstiKqer/fkHasTYDP6KFoQ25303BqBNsmV6DxvBFSr0P0gEMNfW0WgYEDhGQDRwsTFhYTC4dTiYpajEQeB2xjBx6URxaXWoZDHiR9JKChRHykAH9DB4oHcQIlJQJRc6R3Qwukk2gcnRscUSKkb0ITpBNpo6VSCZ11ZkS0l7Zo0lmmUQp0YxUKRtq1aQLGyFNJDUxOeEXOl9DqDbqhJ6QnrYDo6nD7l8cDgz4MWBHMYyBglgMGFh46MeHDhwn+JGrcyLGjx48gO3rg8CBiSDQnWBhjkfFkFQUO2jgwF8UACgUmPz6IWcfB/oMjGBBkQYABJAVFFIwYMDEGQc6NBqz1USjk1RhZHAWQ2kUERRsUHrVe4jpk6RgTTzV6IEVVCAamAEwU/XiUUNIjNlGk5bizj0+XVGDKpAl4yoO6WSj8LOzFgwAObRlLnky5suXLEg2o0FCCwF40KU48SEGwg1AtCDrk6XAhywUCrTr0UZ1GNhnYhwycbuMUdGsyF0gHkqBIApoHfRYDKqGoAcrkhzQoKoEmAog2IIRHSSEiQAAR84wQJ2Qcje0xuKOcaDGmhfIiZuughUPg9+spI66TATEiyvnbeaTwwAPhidLHB1IQsBsACKS3kX7YTWGABLlI8BlBEShSIGUQIO6HmRDekIHgh/lh19+HLjzA3hbvfZiEdwpoh+KMjAUBACH5BAkJACYALAAAAABAAEAAhQQCBISGhMzKzERCRDQyNKSmpOzq7GRiZBQSFHRydJyanNTW1LS2tPz6/Dw6PAwODLSytPTy9GxubBweHHx6fKSipNze3AQGBIyKjMzOzExOTDQ2NKyqrOzu7GRmZBQWFHR2dJyenNza3Ly+vPz+/Dw+PP7+/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAb+QJNwSCwaj8ikcslsmjoYx+fjwHSc2KyS8QF4vwiGdjxmXL5or5jMXnYQ6TTi2q4bA/F4wM60UDZTGxQWRw55aRt8SSQUhyAkRQ+HaA+KRw0akwAaDUSSmgCVRg0hA1MDCp1ZIKAACUQbrYlFBrGIBlgirV4LQ3ige0QNtnEbqkwSuwASQ2+aD3RDCpoKTgTKBEQMmmtEhpMlTp+tokMMcGkP3UToh+VL46DvQh0BGwgIGwHRkc/W2HW+HQrXJNkuZm2mTarWZIGyXm2GHTKGhRWoV3ZqFcOFBZMmTooaKCiBr0SqMQ0sxgFxzJIiESAI4CMAQoTLmzhz6tzJs6f+z59Ah0SoACJBgQhByXDoAoZD0iwcDjlFIuDAAQFPOzCNM+dIhjMALmRIGkJTiCMe0BxIavAQwiIH1CZNoAljka9exJI1iySDVaxJneV5gPQpk6h5Chh2UqAdAASKFzvpEKJoCH6SM2vezLmz58+gQ7fhsOHCBQeR20SAwKDwzbZf3o4ZgQ7BiJsFDqXOEiFeV0sCEZGBEGcqHxKaIGkhngaCJRJg41xQnkWwF8IuiQknM+LTg9tMBAQIADhJ7sRtOrDGfIRE3C8HWhqB7UV2Twx6lhQofWHDbp8TxDGBaEIgl4d8nwWYxoAEmvALGsEQ6J5aCIYmHnkNZqghgUEBAAAh+QQJCQAnACwAAAAAQABAAIUEAgSEgoRERkTEwsTk4uRkYmQ0MjQUFhRUVlTU1tT08vSkpqQMCgxMTkzMysxsbmz8+vzs6uwcHhxcXlzc3tysrqwEBgSEhoRMSkzExsRkZmQ8OjwcGhxcWlzc2tz09vSsqqwMDgxUUlTMzsx0dnT8/vzs7uz+/v4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG/sCTcEgsGo/IpHLJbA5NjozJSa02RxiAFiAYWb/g08Ky3VoW4TRzxCiXLV613Jh1lwVzJ4RCgCQjdnZTeUkZImQAFiIZRxmBbgOERyUkjyQlRQOPZZFIFCAVHmGVmyRFgJtag0UUAncUVpqpAJ1Drpt4RhQHdgewVHWpGEUOiHZwR7d2uU0fbbMWfkRjx2hGHqkJTtizWqLEylwOSAup1kzc3d9GERlSShWpIE4fxpvRaumB2k7BuHPh7lSRlapWml29flEhZYkQARF31lGBwNANCWmEPIAAwS9MhgaILDQwKEnSHgoYS6pcqRJCSpZzMhTgBeBAAZIwrXzo8AjB/oecXxQYSGVgFdAmCLohODoEhAELFjacE+KoGy2mD+w8IJLU6lKgIB6d42C15tENjwwMKatFQc4SqTCdYAvALcwS9t7IpdntwNGhgdQK4en1aNhA5wjOwrkyq5utXJUyFbLgqQUDU4UIJWp3MhMFXe0gMOqZyYAJZAFwmMC4dBMIP13Lnk27tu3buHPnSYABKoaOYRwUKMBIZYJnWhgAtzIiZBxJ/rQw+6KhTIGSEPImkvulgPWSeI+9pNJcC7KS0bmoGTFhwnNJx8sod10BAYIKTRLcErD86IUyAeiGhAn2WECagCeMYMd7CJ5A4BsHIhgAgA0eUd99FWao4YYcAy4RBAA7OEloRWRqYW9jdzhOTjdUeHV4MTVCcmpRRWxDKzdGSWtiWnV5UUlCY0t5QTlKYmUzU25OM3ArSDd0K3JOMEtOTw==' + +# Old debugger logo +# PSG_DEBUGGER_LOGO = b'R0lGODlhMgAtAPcAAAAAADD/2akK/4yz0pSxyZWyy5u3zZ24zpW30pG52J250J+60aC60KS90aDC3a3E163F2K3F2bPI2bvO3rzP3qvJ4LHN4rnR5P/zuf/zuv/0vP/0vsDS38XZ6cnb6f/xw//zwv/yxf/1w//zyP/1yf/2zP/3z//30wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAP8ALAAAAAAyAC0AAAj/AP8JHEiwoMGDCBMqXMiwoUOFAiJGXBigYoAPDxlK3CigwUGLIAOEyIiQI8cCBUOqJFnQpEkGA1XKZPlPgkuXBATK3JmRws2bB3TuXNmQw8+jQoeCbHj0qIGkSgNobNoUqlKIVJs++BfV4oiEWalaHVpyosCwJidw7Sr1YMQFBDn+y4qSbUW3AiDElXiWqoK1bPEKGLixr1jAXQ9GuGn4sN22Bl02roo4Kla+c8OOJbsQM9rNPJlORlr5asbPpTk/RP2YJGu7rjWnDm2RIQLZrSt3zgp6ZmqwmkHAng3ccWDEMe8Kpnw8JEHlkXnPdh6SxHPILaU/dp60LFUP07dfRq5aYntohAO0m+c+nvT6pVMPZ3jv8AJu8xktyNbw+ATJDtKFBx9NlA20gWU0DVQBYwZhsJMICRrkwEYJJGRCSBtEqGGCAQEAOw==' + +PSG_DEBUGGER_LOGO = b'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' + +BLANK_BASE64 = b'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAANSURBVBhXY2BgYGAAAAAFAAGKM+MAAAAAAElFTkSuQmCC' +BLANK_BASE64 = b'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=' + + +DEFAULT_WINDOW_ICON = DEFAULT_BASE64_ICON + +DEFAULT_ELEMENT_SIZE = (45, 1) # In CHARACTERS +DEFAULT_BUTTON_ELEMENT_SIZE = (10, 1) # In CHARACTERS +DEFAULT_MARGINS = (10, 5) # Margins for each LEFT/RIGHT margin is first term +DEFAULT_ELEMENT_PADDING = (5, 3) # Padding between elements (row, col) in pixels +DEFAULT_AUTOSIZE_TEXT = True +DEFAULT_AUTOSIZE_BUTTONS = True +DEFAULT_FONT = ("Helvetica", 10) +DEFAULT_TEXT_JUSTIFICATION = 'left' +DEFAULT_BORDER_WIDTH = 1 +DEFAULT_AUTOCLOSE_TIME = 3 # time in seconds to show an autoclose form +DEFAULT_DEBUG_WINDOW_SIZE = (80, 20) +DEFAULT_WINDOW_LOCATION = (None, None) +MAX_SCROLLED_TEXT_BOX_HEIGHT = 50 +DEFAULT_TOOLTIP_TIME = 400 +DEFAULT_TOOLTIP_OFFSET = (0, -20) +DEFAULT_KEEP_ON_TOP = None +DEFAULT_SCALING = None +TOOLTIP_BACKGROUND_COLOR = "#ffffe0" +TOOLTIP_FONT = None +#################### COLOR STUFF #################### +BLUES = ("#082567", "#0A37A3", "#00345B") +PURPLES = ("#480656", "#4F2398", "#380474") +GREENS = ("#01826B", "#40A860", "#96D2AB", "#00A949", "#003532") +YELLOWS = ("#F3FB62", "#F0F595") +TANS = ("#FFF9D5", "#F4EFCF", "#DDD8BA") +NICE_BUTTON_COLORS = ((GREENS[3], TANS[0]), + ('#000000', '#FFFFFF'), + ('#FFFFFF', '#000000'), + (YELLOWS[0], PURPLES[1]), + (YELLOWS[0], GREENS[3]), + (YELLOWS[0], BLUES[2])) + +COLOR_SYSTEM_DEFAULT = '1234567890' # A Magic Number kind of signal to PySimpleGUI that the color should not be set at all +DEFAULT_BUTTON_COLOR = ('white', BLUES[0]) # Foreground, Background (None, None) == System Default +OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR = ('white', BLUES[0]) + +# The "default PySimpleGUI theme" +OFFICIAL_PYSIMPLEGUI_THEME = CURRENT_LOOK_AND_FEEL = 'Dark Blue 3' + +DEFAULT_ERROR_BUTTON_COLOR = ("#FFFFFF", "#FF0000") +DEFAULT_BACKGROUND_COLOR = None +DEFAULT_ELEMENT_BACKGROUND_COLOR = None +DEFAULT_ELEMENT_TEXT_COLOR = COLOR_SYSTEM_DEFAULT +DEFAULT_TEXT_ELEMENT_BACKGROUND_COLOR = None +DEFAULT_TEXT_COLOR = COLOR_SYSTEM_DEFAULT +DEFAULT_INPUT_ELEMENTS_COLOR = COLOR_SYSTEM_DEFAULT +DEFAULT_INPUT_TEXT_COLOR = COLOR_SYSTEM_DEFAULT +DEFAULT_SCROLLBAR_COLOR = None +# DEFAULT_BUTTON_COLOR = (YELLOWS[0], PURPLES[0]) # (Text, Background) or (Color "on", Color) as a way to remember +# DEFAULT_BUTTON_COLOR = (GREENS[3], TANS[0]) # Foreground, Background (None, None) == System Default +# DEFAULT_BUTTON_COLOR = (YELLOWS[0], GREENS[4]) # Foreground, Background (None, None) == System Default +# DEFAULT_BUTTON_COLOR = ('white', 'black') # Foreground, Background (None, None) == System Default +# DEFAULT_BUTTON_COLOR = (YELLOWS[0], PURPLES[2]) # Foreground, Background (None, None) == System Default +# DEFAULT_PROGRESS_BAR_COLOR = (GREENS[2], GREENS[0]) # a nice green progress bar +# DEFAULT_PROGRESS_BAR_COLOR = (BLUES[1], BLUES[1]) # a nice green progress bar +# DEFAULT_PROGRESS_BAR_COLOR = (BLUES[0], BLUES[0]) # a nice green progress bar +# DEFAULT_PROGRESS_BAR_COLOR = (PURPLES[1],PURPLES[0]) # a nice purple progress bar + + +# A transparent button is simply one that matches the background +# TRANSPARENT_BUTTON = 'This constant has been depricated. You must set your button background = background it is on for it to be transparent appearing' + + +# -------------------------------------------------------------------------------- +# Progress Bar Relief Choices +RELIEF_RAISED = 'raised' +RELIEF_SUNKEN = 'sunken' +RELIEF_FLAT = 'flat' +RELIEF_RIDGE = 'ridge' +RELIEF_GROOVE = 'groove' +RELIEF_SOLID = 'solid' + +# These are the spepific themes that tkinter offers +THEME_DEFAULT = 'default' # this is a TTK theme, not a PSG theme!!! +THEME_WINNATIVE = 'winnative' +THEME_CLAM = 'clam' +THEME_ALT = 'alt' +THEME_CLASSIC = 'classic' +THEME_VISTA = 'vista' +THEME_XPNATIVE = 'xpnative' +THEME_LIST = ('default', 'winnative', 'clam', 'alt', 'classic', 'vista', 'xpnative') + +# The theme to use by default for all windows +DEFAULT_TTK_THEME = THEME_DEFAULT +TTK_THEME_LIST = ('default', 'winnative', 'clam', 'alt', 'classic', 'vista', 'xpnative') + + +USE_TTK_BUTTONS = None + +DEFAULT_PROGRESS_BAR_COLOR = ("#01826B", '#D0D0D0') # a nice green progress bar +DEFAULT_PROGRESS_BAR_COMPUTE = ('#000000', '#000000') # Means that the progress bar colors should be computed from other colors +DEFAULT_PROGRESS_BAR_COLOR_OFFICIAL = ("#01826B", '#D0D0D0') # a nice green progress bar +DEFAULT_PROGRESS_BAR_SIZE = (20, 20) # Size of Progress Bar (characters for length, pixels for width) +DEFAULT_PROGRESS_BAR_BORDER_WIDTH = 1 +DEFAULT_PROGRESS_BAR_RELIEF = RELIEF_GROOVE +PROGRESS_BAR_STYLES = ('default', 'winnative', 'clam', 'alt', 'classic', 'vista', 'xpnative') +DEFAULT_PROGRESS_BAR_STYLE = DEFAULT_TTK_THEME +DEFAULT_METER_ORIENTATION = 'Horizontal' +DEFAULT_SLIDER_ORIENTATION = 'vertical' +DEFAULT_SLIDER_BORDER_WIDTH = 1 +DEFAULT_SLIDER_RELIEF = tk.FLAT +DEFAULT_FRAME_RELIEF = tk.GROOVE + +DEFAULT_LISTBOX_SELECT_MODE = tk.SINGLE +SELECT_MODE_MULTIPLE = tk.MULTIPLE +LISTBOX_SELECT_MODE_MULTIPLE = 'multiple' +SELECT_MODE_BROWSE = tk.BROWSE +LISTBOX_SELECT_MODE_BROWSE = 'browse' +SELECT_MODE_EXTENDED = tk.EXTENDED +LISTBOX_SELECT_MODE_EXTENDED = 'extended' +SELECT_MODE_SINGLE = tk.SINGLE +LISTBOX_SELECT_MODE_SINGLE = 'single' + +TABLE_SELECT_MODE_NONE = tk.NONE +TABLE_SELECT_MODE_BROWSE = tk.BROWSE +TABLE_SELECT_MODE_EXTENDED = tk.EXTENDED +DEFAULT_TABLE_SELECT_MODE = TABLE_SELECT_MODE_EXTENDED + + +TAB_LOCATION_TOP = 'top' +TAB_LOCATION_TOP_LEFT = 'topleft' +TAB_LOCATION_TOP_RIGHT = 'topright' +TAB_LOCATION_LEFT = 'left' +TAB_LOCATION_LEFT_TOP = 'lefttop' +TAB_LOCATION_LEFT_BOTTOM = 'leftbottom' +TAB_LOCATION_RIGHT = 'right' +TAB_LOCATION_RIGHT_TOP = 'righttop' +TAB_LOCATION_RIGHT_BOTTOM = 'rightbottom' +TAB_LOCATION_BOTTOM = 'bottom' +TAB_LOCATION_BOTTOM_LEFT = 'bottomleft' +TAB_LOCATION_BOTTOM_RIGHT = 'bottomright' + + +TITLE_LOCATION_TOP = tk.N +TITLE_LOCATION_BOTTOM = tk.S +TITLE_LOCATION_LEFT = tk.W +TITLE_LOCATION_RIGHT = tk.E +TITLE_LOCATION_TOP_LEFT = tk.NW +TITLE_LOCATION_TOP_RIGHT = tk.NE +TITLE_LOCATION_BOTTOM_LEFT = tk.SW +TITLE_LOCATION_BOTTOM_RIGHT = tk.SE + +TEXT_LOCATION_TOP = tk.N +TEXT_LOCATION_BOTTOM = tk.S +TEXT_LOCATION_LEFT = tk.W +TEXT_LOCATION_RIGHT = tk.E +TEXT_LOCATION_TOP_LEFT = tk.NW +TEXT_LOCATION_TOP_RIGHT = tk.NE +TEXT_LOCATION_BOTTOM_LEFT = tk.SW +TEXT_LOCATION_BOTTOM_RIGHT = tk.SE +TEXT_LOCATION_CENTER = tk.CENTER + +GRAB_ANYWHERE_IGNORE_THESE_WIDGETS = (ttk.Sizegrip, tk.Scale, ttk.Scrollbar, tk.scrolledtext.ScrolledText, tk.Scrollbar, tk.Entry, tk.Text, tk.PanedWindow, tk.Listbox) + +# ----====----====----==== Constants the user should NOT f-with ====----====----====----# +ThisRow = 555666777 # magic number + +# DEFAULT_WINDOW_ICON = '' +MESSAGE_BOX_LINE_WIDTH = 60 + +# "Special" Key Values.. reserved +# Key representing a Read timeout +EVENT_TIMEOUT = TIMEOUT_EVENT = TIMEOUT_KEY = '__TIMEOUT__' +WIN_CLOSED = WINDOW_CLOSED = None +WINDOW_CLOSE_ATTEMPTED_EVENT = WIN_X_EVENT = WIN_CLOSE_ATTEMPTED_EVENT = '-WINDOW CLOSE ATTEMPTED-' + +TITLEBAR_MINIMIZE_KEY = '__TITLEBAR MINIMIZE__' +TITLEBAR_MAXIMIZE_KEY = '__TITLEBAR MAXIMIZE__' +TITLEBAR_CLOSE_KEY = '__TITLEBAR CLOSE__' +TITLEBAR_IMAGE_KEY = '__TITLEBAR IMAGE__' +TITLEBAR_DO_NOT_USE_AN_ICON = '__TITLEBAR_NO_ICON__' + +# Key indicating should not create any return values for element +WRITE_ONLY_KEY = '__WRITE ONLY__' + +MENU_DISABLED_CHARACTER = '!' +MENU_SHORTCUT_CHARACTER = '&' +MENU_KEY_SEPARATOR = '::' +MENU_SEPARATOR_LINE = '---' +MENU_RIGHT_CLICK_EDITME_EXIT = ['', ['Edit Me', 'Exit']] +MENU_RIGHT_CLICK_EDITME_VER_EXIT = ['', ['Edit Me', 'Version', 'Exit']] +MENU_RIGHT_CLICK_EDITME_VER_LOC_EXIT = ['', ['Edit Me', 'Version', 'File Location', 'Exit']] +MENU_RIGHT_CLICK_EDITME_VER_SETTINGS_EXIT = ['', ['Edit Me', 'Settings', 'Version', 'Exit']] +MENU_RIGHT_CLICK_EXIT = ['', ['Exit']] +MENU_RIGHT_CLICK_DISABLED = ['', []] +_MENU_RIGHT_CLICK_TABGROUP_DEFAULT = ['TABGROUP DEFAULT', []] +ENABLE_TK_WINDOWS = False + +USE_CUSTOM_TITLEBAR = False +CUSTOM_TITLEBAR_BACKGROUND_COLOR = None +CUSTOM_TITLEBAR_TEXT_COLOR = None +CUSTOM_TITLEBAR_ICON = None +CUSTOM_TITLEBAR_FONT = None +TITLEBAR_METADATA_MARKER = 'This window has a titlebar' + +CUSTOM_MENUBAR_METADATA_MARKER = 'This is a custom menubar' + +SUPPRESS_ERROR_POPUPS = False +SUPPRESS_RAISE_KEY_ERRORS = True +SUPPRESS_KEY_GUESSING = False + +ENABLE_TREEVIEW_869_PATCH = True + +# These are now set based on the global settings file +ENABLE_MAC_NOTITLEBAR_PATCH = False +ENABLE_MAC_MODAL_DISABLE_PATCH = False +ENABLE_MAC_DISABLE_GRAB_ANYWHERE_WITH_TITLEBAR = True + +OLD_TABLE_TREE_SELECTED_ROW_COLORS = ('#FFFFFF', '#4A6984') +ALTERNATE_TABLE_AND_TREE_SELECTED_ROW_COLORS = ('SystemHighlightText', 'SystemHighlight') + +# Some handy unicode symbols +SYMBOL_SQUARE = '█' +SYMBOL_CIRCLE = '⚫' +SYMBOL_CIRCLE_OUTLINE = '◯' +SYMBOL_UP = '▲' +SYMBOL_RIGHT = '►' +SYMBOL_LEFT = '◄' +SYMBOL_DOWN = '▼' +SYMBOL_X = '❎' +SYMBOL_CHECK = '✅' +SYMBOL_BALLOT_X = '☒' +SYMBOL_BALLOT_CHECK = '☑' +SYMBOL_LEFT_DOUBLE = '«' +SYMBOL_RIGHT_DOUBLE = '»' +SYMBOL_LEFT_ARROWHEAD = '⮜' +SYMBOL_RIGHT_ARROWHEAD = '⮞' +SYMBOL_UP_ARROWHEAD = '⮝' +SYMBOL_DOWN_ARROWHEAD = '⮟' + +if sum([int(i) for i in tclversion_detailed.split('.')]) > 19: + SYMBOL_TITLEBAR_MINIMIZE = '_' + SYMBOL_TITLEBAR_MAXIMIZE = '◻' + SYMBOL_TITLEBAR_CLOSE = 'X' +else: + SYMBOL_TITLEBAR_MINIMIZE = '_' + SYMBOL_TITLEBAR_MAXIMIZE = 'O' + SYMBOL_TITLEBAR_CLOSE = 'X' + +#################### PATHS for user_settings APIs #################### +# These paths are passed to os.path.expanduser to get the default path for user_settings +# They can be changed using set_options + +DEFAULT_USER_SETTINGS_WIN_PATH = r'~\AppData\Local\PySimpleGUI\settings' +DEFAULT_USER_SETTINGS_LINUX_PATH = r'~/.config/PySimpleGUI/settings' +DEFAULT_USER_SETTINGS_MAC_PATH = r'~/Library/Application Support/PySimpleGUI/settings' +DEFAULT_USER_SETTINGS_TRINKET_PATH = r'.' +DEFAULT_USER_SETTINGS_REPLIT_PATH = r'.' +DEFAULT_USER_SETTINGS_UNKNOWN_OS_PATH = r'~/Library/Application Support/PySimpleGUI/settings' +DEFAULT_USER_SETTINGS_PATH = None # value set by user to override all paths above +DEFAULT_USER_SETTINGS_PYSIMPLEGUI_PATH = None # location of the global PySimpleGUI settings +DEFAULT_USER_SETTINGS_PYSIMPLEGUI_FILENAME = '_PySimpleGUI_settings_global_.json' # location of the global PySimpleGUI settings + + +# ====================================================================== # +# One-liner functions that are handy as f_ck # +# ====================================================================== # +def rgb(red, green, blue): + """ + Given integer values of Red, Green, Blue, return a color string "#RRGGBB" + :param red: Red portion from 0 to 255 + :type red: (int) + :param green: Green portion from 0 to 255 + :type green: (int) + :param blue: Blue portion from 0 to 255 + :type blue: (int) + :return: A single RGB String in the format "#RRGGBB" where each pair is a hex number. + :rtype: (str) + """ + red = min(int(red), 255) if red > 0 else 0 + blue = min(int(blue), 255) if blue > 0 else 0 + green = min(int(green), 255) if green > 0 else 0 + return '#%02x%02x%02x' % (red, green, blue) + + +# ====================================================================== # +# Enums for types # +# ====================================================================== # +# ------------------------- Button types ------------------------- # +# uncomment this line and indent to go back to using Enums +BUTTON_TYPE_BROWSE_FOLDER = 1 +BUTTON_TYPE_BROWSE_FILE = 2 +BUTTON_TYPE_BROWSE_FILES = 21 +BUTTON_TYPE_SAVEAS_FILE = 3 +BUTTON_TYPE_CLOSES_WIN = 5 +BUTTON_TYPE_CLOSES_WIN_ONLY = 6 +BUTTON_TYPE_READ_FORM = 7 +BUTTON_TYPE_REALTIME = 9 +BUTTON_TYPE_CALENDAR_CHOOSER = 30 +BUTTON_TYPE_COLOR_CHOOSER = 40 +BUTTON_TYPE_SHOW_DEBUGGER = 50 + +BROWSE_FILES_DELIMITER = ';' # the delimiter to be used between each file in the returned string + +FILE_TYPES_ALL_FILES = (("ALL Files", "*.* *"),) + +BUTTON_DISABLED_MEANS_IGNORE = 'ignore' + +# ------------------------- Element types ------------------------- # + +ELEM_TYPE_TEXT = 'text' +ELEM_TYPE_INPUT_TEXT = 'input' +ELEM_TYPE_INPUT_COMBO = 'combo' +ELEM_TYPE_INPUT_OPTION_MENU = 'option menu' +ELEM_TYPE_INPUT_RADIO = 'radio' +ELEM_TYPE_INPUT_MULTILINE = 'multiline' +ELEM_TYPE_INPUT_CHECKBOX = 'checkbox' +ELEM_TYPE_INPUT_SPIN = 'spind' +ELEM_TYPE_BUTTON = 'button' +ELEM_TYPE_IMAGE = 'image' +ELEM_TYPE_CANVAS = 'canvas' +ELEM_TYPE_FRAME = 'frame' +ELEM_TYPE_GRAPH = 'graph' +ELEM_TYPE_TAB = 'tab' +ELEM_TYPE_TAB_GROUP = 'tabgroup' +ELEM_TYPE_INPUT_SLIDER = 'slider' +ELEM_TYPE_INPUT_LISTBOX = 'listbox' +ELEM_TYPE_OUTPUT = 'output' +ELEM_TYPE_COLUMN = 'column' +ELEM_TYPE_MENUBAR = 'menubar' +ELEM_TYPE_PROGRESS_BAR = 'progressbar' +ELEM_TYPE_BLANK = 'blank' +ELEM_TYPE_TABLE = 'table' +ELEM_TYPE_TREE = 'tree' +ELEM_TYPE_ERROR = 'error' +ELEM_TYPE_SEPARATOR = 'separator' +ELEM_TYPE_STATUSBAR = 'statusbar' +ELEM_TYPE_PANE = 'pane' +ELEM_TYPE_BUTTONMENU = 'buttonmenu' +ELEM_TYPE_TITLEBAR = 'titlebar' +ELEM_TYPE_SIZEGRIP = 'sizegrip' + +# STRETCH == ERROR ELEMENT as a filler + +# ------------------------- Popup Buttons Types ------------------------- # +POPUP_BUTTONS_YES_NO = 1 +POPUP_BUTTONS_CANCELLED = 2 +POPUP_BUTTONS_ERROR = 3 +POPUP_BUTTONS_OK_CANCEL = 4 +POPUP_BUTTONS_OK = 0 +POPUP_BUTTONS_NO_BUTTONS = 5 + + +# ------------------------------------------------------------------------- # +# ToolTip used by the Elements # +# ------------------------------------------------------------------------- # + +class ToolTip: + """ + Create a tooltip for a given widget + (inspired by https://stackoverflow.com/a/36221216) + This is an INTERNALLY USED only class. Users should not refer to this class at all. + """ + + def __init__(self, widget, text, timeout=DEFAULT_TOOLTIP_TIME): + """ + :param widget: The tkinter widget + :type widget: widget type varies + :param text: text for the tooltip. It can inslude \n + :type text: (str) + :param timeout: Time in milliseconds that mouse must remain still before tip is shown + :type timeout: (int) + """ + self.widget = widget + self.text = text + self.timeout = timeout + # self.wraplength = wraplength if wraplength else widget.winfo_screenwidth() // 2 + self.tipwindow = None + self.id = None + self.x = self.y = 0 + self.widget.bind("", self.enter) + self.widget.bind("", self.leave) + self.widget.bind("", self.leave) + + def enter(self, event=None): + """ + Called by tkinter when mouse enters a widget + :param event: from tkinter. Has x,y coordinates of mouse + :type event: + + """ + self.x = event.x + self.y = event.y + self.schedule() + + def leave(self, event=None): + """ + Called by tktiner when mouse exits a widget + :param event: from tkinter. Event info that's not used by function. + :type event: + + """ + self.unschedule() + self.hidetip() + + def schedule(self): + """ + Schedule a timer to time how long mouse is hovering + """ + self.unschedule() + self.id = self.widget.after(self.timeout, self.showtip) + + def unschedule(self): + """ + Cancel timer used to time mouse hover + """ + if self.id: + self.widget.after_cancel(self.id) + self.id = None + + def showtip(self): + """ + Creates a topoltip window with the tooltip text inside of it + """ + if self.tipwindow: + return + x = self.widget.winfo_rootx() + self.x + DEFAULT_TOOLTIP_OFFSET[0] + y = self.widget.winfo_rooty() + self.y + DEFAULT_TOOLTIP_OFFSET[1] + self.tipwindow = tk.Toplevel(self.widget) + # if not sys.platform.startswith('darwin'): + try: + self.tipwindow.wm_overrideredirect(True) + # if running_mac() and ENABLE_MAC_NOTITLEBAR_PATCH: + if _mac_should_apply_notitlebar_patch(): + self.tipwindow.wm_overrideredirect(False) + except Exception as e: + print('* Error performing wm_overrideredirect in showtip *', e) + self.tipwindow.wm_geometry("+%d+%d" % (x, y)) + self.tipwindow.wm_attributes("-topmost", 1) + + label = ttk.Label(self.tipwindow, text=self.text, justify=tk.LEFT, + background=TOOLTIP_BACKGROUND_COLOR, relief=tk.SOLID, borderwidth=1) + if TOOLTIP_FONT is not None: + label.config(font=TOOLTIP_FONT) + label.pack() + + def hidetip(self): + """ + Destroy the tooltip window + """ + if self.tipwindow: + self.tipwindow.destroy() + self.tipwindow = None + + +# ---------------------------------------------------------------------- # +# Cascading structure.... Objects get larger # +# Button # +# Element # +# Row # +# Form # +# ---------------------------------------------------------------------- # +# ------------------------------------------------------------------------- # +# Element CLASS # +# ------------------------------------------------------------------------- # +class Element(): + """ The base class for all Elements. Holds the basic description of an Element like size and colors """ + + def __init__(self, type, size=(None, None), auto_size_text=None, font=None, background_color=None, text_color=None, key=None, pad=None, tooltip=None, + visible=True, metadata=None): + """ + Element base class. Only used internally. User will not create an Element object by itself + + :param type: The type of element. These constants all start with "ELEM_TYPE_" + :type type: (int) (could be enum) + :param size: w=characters-wide, h=rows-high. If an int instead of a tuple is supplied, then height is auto-set to 1 + :type size: (int, int) | (None, None) | int + :param auto_size_text: True if the Widget should be shrunk to exactly fit the number of chars to show + :type auto_size_text: bool + :param font: specifies the font family, size. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param background_color: color of background. Can be in #RRGGBB format or a color name "black" + :type background_color: (str) + :param text_color: element's text color. Can be in #RRGGBB format or a color name "black" + :type text_color: (str) + :param key: Identifies an Element. Should be UNIQUE to this window. + :type key: str | int | tuple | object + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom). If an int is given, then auto-converted to tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param visible: set visibility state of the element (Default = True) + :type visible: (bool) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + if size is not None and size != (None, None): + if isinstance(size, int): + size = (size, 1) + if isinstance(size, tuple) and len(size) == 1: + size = (size[0], 1) + + if pad is not None and pad != (None, None): + if isinstance(pad, int): + pad = (pad, pad) + + + self.Size = size + self.Type = type + self.AutoSizeText = auto_size_text + + self.Pad = pad + self.Font = font + + self.TKStringVar = None + self.TKIntVar = None + self.TKText = None + self.TKEntry = None + self.TKImage = None + self.ttk_style_name = '' # set in the packer function + + self._metadata = None # type: Any + + self.ParentForm = None # type: Window + self.ParentContainer = None # will be a Form, Column, or Frame element # UNBIND + self.TextInputDefault = None + self.Position = (0, 0) # Default position Row 0, Col 0 + self.BackgroundColor = background_color if background_color is not None else DEFAULT_ELEMENT_BACKGROUND_COLOR + self.TextColor = text_color if text_color is not None else DEFAULT_ELEMENT_TEXT_COLOR + self.Key = key # dictionary key for return values + self.Tooltip = tooltip + self.TooltipObject = None + self._visible = visible + self.TKRightClickMenu = None + self.Widget = None # Set when creating window. Has the main tkinter widget for element + self.Tearoff = False # needed because of right click menu code + self.ParentRowFrame = None # type tk.Frame + self.metadata = metadata + self.user_bind_dict = {} # Used when user defines a tkinter binding using bind method - convert bind string to key modifier + self.user_bind_event = None # Used when user defines a tkinter binding using bind method - event data from tkinter + self.pad_used = (0, 0) # the amount of pad used when was inserted into the layout + self._popup_menu_location = (None, None) + + if not hasattr(self, 'DisabledTextColor'): + self.DisabledTextColor = None + if not hasattr(self, 'ItemFont'): + self.ItemFont = None + if not hasattr(self, 'RightClickMenu'): + self.RightClickMenu = None + + @property + def visible(self): + """ + Returns visibility state for the element. This is a READONLY property + :return: Visibility state for element + :rtype: (bool) + """ + return self._visible + + @property + def metadata(self): + """ + Metadata is an Element property that you can use at any time to hold any value + :return: the current metadata value + :rtype: (Any) + """ + return self._metadata + + @metadata.setter + def metadata(self, value): + """ + Metadata is an Element property that you can use at any time to hold any value + :param value: Anything you want it to be + :type value: (Any) + """ + self._metadata = value + + def _RightClickMenuCallback(self, event): + """ + Callback function that's called when a right click happens. Shows right click menu as result + + :param event: information provided by tkinter about the event including x,y location of click + :type event: + + """ + if self.Type == ELEM_TYPE_TAB_GROUP: + try: + index = self.Widget.index('@{},{}'.format(event.x,event.y)) + tab = self.Widget.tab(index, 'text') + key = self.find_key_from_tab_name(tab) + tab_element = self.ParentForm.key_dict[key] + if tab_element.RightClickMenu is None: # if this tab didn't explicitly have a menu, then don't show anything + return + tab_element.TKRightClickMenu.tk_popup(event.x_root, event.y_root, 0) + self.TKRightClickMenu.grab_release() + except: + pass + return + self.TKRightClickMenu.tk_popup(event.x_root, event.y_root, 0) + self.TKRightClickMenu.grab_release() + if self.Type == ELEM_TYPE_GRAPH: + self._update_position_for_returned_values(event) + + def _tearoff_menu_callback(self, parent, menu): + """ + Callback function that's called when a right click menu is torn off. + The reason for this function is to relocate the torn-off menu. It will default to 0,0 otherwise + This callback moves the right click menu window to the location of the current window + + :param parent: information provided by tkinter - the parent of the Meny + :type parent: + :param menu: information provided by tkinter - the menu window + :type menu: + + """ + if self._popup_menu_location == (None, None): + winx, winy = self.ParentForm.current_location() + else: + winx, winy = self._popup_menu_location + # self.ParentForm.TKroot.update() + self.ParentForm.TKroot.tk.call('wm', 'geometry', menu, "+{}+{}".format(winx, winy)) + + def _MenuItemChosenCallback(self, item_chosen): # TEXT Menu item callback + """ + Callback function called when user chooses a menu item from menubar, Button Menu or right click menu + + :param item_chosen: String holding the value chosen. + :type item_chosen: str + + """ + # print('IN MENU ITEM CALLBACK', item_chosen) + self.MenuItemChosen = item_chosen + self.ParentForm.LastButtonClicked = self.MenuItemChosen + self.ParentForm.FormRemainedOpen = True + _exit_mainloop(self.ParentForm) + # Window._window_that_exited = self.ParentForm + # self.ParentForm.TKroot.quit() # kick the users out of the mainloop + + def _FindReturnKeyBoundButton(self, form): + """ + Searches for which Button has the flag Button.BindReturnKey set. It is called recursively when a + "Container Element" is encountered. Func has to walk entire window including these "sub-forms" + + :param form: the Window object to search + :type form: + :return: Button Object if a button is found, else None + :rtype: Button | None + """ + for row in form.Rows: + for element in row: + if element.Type == ELEM_TYPE_BUTTON: + if element.BindReturnKey: + return element + if element.Type == ELEM_TYPE_COLUMN: + rc = self._FindReturnKeyBoundButton(element) + if rc is not None: + return rc + if element.Type == ELEM_TYPE_FRAME: + rc = self._FindReturnKeyBoundButton(element) + if rc is not None: + return rc + if element.Type == ELEM_TYPE_TAB_GROUP: + rc = self._FindReturnKeyBoundButton(element) + if rc is not None: + return rc + if element.Type == ELEM_TYPE_TAB: + rc = self._FindReturnKeyBoundButton(element) + if rc is not None: + return rc + if element.Type == ELEM_TYPE_PANE: + rc = self._FindReturnKeyBoundButton(element) + if rc is not None: + return rc + return None + + def _TextClickedHandler(self, event): + """ + Callback that's called when a text element is clicked on with events enabled on the Text Element. + Result is that control is returned back to user (quits mainloop). + + :param event: + :type event: + + """ + # If this is a minimize button for a custom titlebar, then minimize the window + if self.Key == TITLEBAR_MINIMIZE_KEY: + if running_linux(): + self.ParentForm.TKroot.wm_attributes("-type", "normal") + # self.ParentForm.TKroot.state('icon') + # return + # self.ParentForm.maximize() + self.ParentForm.TKroot.wm_overrideredirect(False) + # self.ParentForm.minimize() + # self.ParentForm.TKroot.wm_overrideredirect(False) + self.ParentForm.TKroot.iconify() + # self._skip_first_restore_callback = True + self.ParentForm.TKroot.bind('', self._titlebar_restore) + else: + self.ParentForm.TKroot.wm_overrideredirect(False) + self.ParentForm.Minimize() + self.ParentForm.TKroot.bind('', self._titlebar_restore) + elif self.Key == TITLEBAR_MAXIMIZE_KEY: + if self.ParentForm.maximized: + self.ParentForm.normal() + else: + self.ParentForm.maximize() + elif self.Key == TITLEBAR_CLOSE_KEY: + self.ParentForm._OnClosingCallback() + else: + self._generic_callback_handler(self.DisplayText) + return + + def _titlebar_restore(self, event): + if running_linux(): + # if self._skip_first_restore_callback: + # self._skip_first_restore_callback = False + # return + self.ParentForm.TKroot.unbind('') + self.ParentForm.TKroot.deiconify() + + # self.ParentForm.TKroot.wm_overrideredirect(True) + self.ParentForm.TKroot.wm_attributes("-type", 'dock') + + else: + self.ParentForm.TKroot.unbind('') + self.ParentForm.TKroot.wm_overrideredirect(True) + self.ParentForm.normal() + + def _ReturnKeyHandler(self, event): + """ + Internal callback for the ENTER / RETURN key. Results in calling the ButtonCallBack for element that has the return key bound to it, just as if button was clicked. + + :param event: + :type event: + + """ + MyForm = self.ParentForm + button_element = self._FindReturnKeyBoundButton(MyForm) + if button_element is not None: + button_element.ButtonCallBack() + + def _generic_callback_handler(self, alternative_to_key=None, force_key_to_be=None): + """ + Peforms the actions that were in many of the callback functions previously. Combined so that it's + easier to modify and is in 1 place now + + :param event: From tkinter and is not used + :type event: Any + :param alternate_to_key: If key is None, then use this value instead + :type alternate_to_key: Any + """ + if force_key_to_be is not None: + self.ParentForm.LastButtonClicked = force_key_to_be + elif self.Key is not None: + self.ParentForm.LastButtonClicked = self.Key + else: + self.ParentForm.LastButtonClicked = alternative_to_key + self.ParentForm.FormRemainedOpen = True + + _exit_mainloop(self.ParentForm) + # if self.ParentForm.CurrentlyRunningMainloop: + # Window._window_that_exited = self.ParentForm + # self.ParentForm.TKroot.quit() # kick the users out of the mainloop + + def _ListboxSelectHandler(self, event): + """ + Internal callback function for when a listbox item is selected + + :param event: Information from tkinter about the callback + :type event: + + """ + self._generic_callback_handler('') + + def _ComboboxSelectHandler(self, event): + """ + Internal callback function for when an entry is selected in a Combobox. + :param event: Event data from tkinter (not used) + :type event: + + """ + self._generic_callback_handler('') + + def _RadioHandler(self): + """ + Internal callback for when a radio button is selected and enable events was set for radio + """ + self._generic_callback_handler('') + + def _CheckboxHandler(self): + """ + Internal callback for when a checkbnox is selected and enable events was set for checkbox + """ + self._generic_callback_handler('') + + def _TabGroupSelectHandler(self, event): + """ + Internal callback for when a Tab is selected and enable events was set for TabGroup + + :param event: Event data passed in by tkinter (not used) + :type event: + """ + self._generic_callback_handler('') + + def _KeyboardHandler(self, event): + """ + Internal callback for when a key is pressed andd return keyboard events was set for window + + :param event: Event data passed in by tkinter (not used) + :type event: + """ + self._generic_callback_handler('') + + def _ClickHandler(self, event): + """ + Internal callback for when a mouse was clicked... I think. + + :param event: Event data passed in by tkinter (not used) + :type event: + """ + self._generic_callback_handler('') + + def _user_bind_callback(self, bind_string, event): + """ + Used when user binds a tkinter event directly to an element + + :param bind_string: The event that was bound so can lookup the key modifier + :type bind_string: (str) + :param event: Event data passed in by tkinter (not used) + :type event: (Any) + """ + key_suffix = self.user_bind_dict.get(bind_string, '') + self.user_bind_event = event + if self.Type == ELEM_TYPE_GRAPH: + self._update_position_for_returned_values(event) + if self.Key is not None: + if isinstance(self.Key, str): + key = self.Key + str(key_suffix) + else: + key = (self.Key, key_suffix) # old way (pre 2021) was to make a brand new tuple + # key = self.Key + (key_suffix,) # in 2021 tried this. It will break existing applications though - if key is a tuple, add one more item + else: + key = bind_string + + self._generic_callback_handler(force_key_to_be=key) + + def bind(self, bind_string, key_modifier): + """ + Used to add tkinter events to an Element. + The tkinter specific data is in the Element's member variable user_bind_event + :param bind_string: The string tkinter expected in its bind function + :type bind_string: (str) + :param key_modifier: Additional data to be added to the element's key when event is returned + :type key_modifier: (str) + """ + if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow + return + + self.Widget.bind(bind_string, lambda evt: self._user_bind_callback(bind_string, evt)) + self.user_bind_dict[bind_string] = key_modifier + + def unbind(self, bind_string): + """ + Removes a previously bound tkinter event from an Element. + :param bind_string: The string tkinter expected in its bind function + :type bind_string: (str) + """ + if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow + return + self.Widget.unbind(bind_string) + self.user_bind_dict.pop(bind_string, None) + + def set_tooltip(self, tooltip_text): + """ + Called by application to change the tooltip text for an Element. Normally invoked using the Element Object such as: window.Element('key').SetToolTip('New tip'). + + :param tooltip_text: the text to show in tooltip. + :type tooltip_text: (str) + """ + + if self.TooltipObject: + try: + self.TooltipObject.leave() + except: + pass + + self.TooltipObject = ToolTip(self.Widget, text=tooltip_text, timeout=DEFAULT_TOOLTIP_TIME) + + def set_focus(self, force=False): + """ + Sets the current focus to be on this element + + :param force: if True will call focus_force otherwise calls focus_set + :type force: bool + """ + + try: + if force: + self.Widget.focus_force() + else: + self.Widget.focus_set() + except: + print('Was unable to set focus. The Widget passed in was perhaps not present in this element? Check your elements .Widget property') + + def block_focus(self, block=True): + """ + Enable or disable the element from getting focus by using the keyboard. + If the block parameter is True, then this element will not be given focus by using + the keyboard to go from one element to another. + You CAN click on the element and utilize it. + + :param block: if True the element will not get focus via the keyboard + :type block: bool + """ + if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow + return + try: + self.ParentForm.TKroot.focus_force() + if block: + self.Widget.configure(takefocus=0) + else: + self.Widget.configure(takefocus=1) + except: + print('Was unable to block the focus. Check your elements .Widget property') + + def set_size(self, size=(None, None)): + """ + Changes the size of an element to a specific size. + It's possible to specify None for one of sizes so that only 1 of the element's dimensions are changed. + + :param size: The size in characters, rows typically. In some cases they are pixels + :type size: (int, int) + """ + try: + if size[0] != None: + self.Widget.config(width=size[0]) + except: + print('Warning, error setting width on element with key=', self.Key) + try: + if size[1] != None: + self.Widget.config(height=size[1]) + except: + try: + self.Widget.config(length=size[1]) + except: + print('Warning, error setting height on element with key=', self.Key) + + if self.Type == ELEM_TYPE_GRAPH: + self.CanvasSize = size + + + def get_size(self): + """ + Return the size of an element in Pixels. Care must be taken as some elements use characters to specify their size but will return pixels when calling this get_size method. + :return: width and height of the element + :rtype: (int, int) + """ + try: + w = self.Widget.winfo_width() + h = self.Widget.winfo_height() + except: + print('Warning, error getting size of element', self.Key) + w = h = None + return w, h + + def hide_row(self): + """ + Hide the entire row an Element is located on. + Use this if you must have all space removed when you are hiding an element, including the row container + """ + try: + self.ParentRowFrame.pack_forget() + except: + print('Warning, error hiding element row for key =', self.Key) + + def unhide_row(self): + """ + Unhides (makes visible again) the row container that the Element is located on. + Note that it will re-appear at the bottom of the window / container, most likely. + """ + try: + self.ParentRowFrame.pack() + except: + print('Warning, error hiding element row for key =', self.Key) + + def expand(self, expand_x=False, expand_y=False, expand_row=True): + """ + Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions + + :param expand_x: If True Element will expand in the Horizontal directions + :type expand_x: (bool) + :param expand_y: If True Element will expand in the Vertical directions + :type expand_y: (bool) + :param expand_row: If True the row containing the element will also expand. Without this your element is "trapped" within the row + :type expand_row: (bool) + """ + if expand_x and expand_y: + fill = tk.BOTH + elif expand_x: + fill = tk.X + elif expand_y: + fill = tk.Y + else: + return + + if not self._widget_was_created(): + return + self.Widget.pack(expand=True, fill=fill) + self.ParentRowFrame.pack(expand=expand_row, fill=fill) + if self.element_frame is not None: + self.element_frame.pack(expand=True, fill=fill) + + def set_cursor(self, cursor=None, cursor_color=None): + """ + Sets the cursor for the current Element. + "Cursor" is used in 2 different ways in this call. + For the parameter "cursor" it's actually the mouse pointer. + If you do not want any mouse pointer, then use the string "none" + For the parameter "cursor_color" it's the color of the beam used when typing into an input element + + :param cursor: The tkinter cursor name + :type cursor: (str) + :param cursor_color: color to set the "cursor" to + :type cursor_color: (str) + """ + if not self._widget_was_created(): + return + if cursor is not None: + try: + self.Widget.config(cursor=cursor) + except Exception as e: + print('Warning bad cursor specified ', cursor) + print(e) + if cursor_color is not None: + try: + self.Widget.config(insertbackground=cursor_color) + except Exception as e: + print('Warning bad cursor color', cursor_color) + print(e) + + def set_vscroll_position(self, percent_from_top): + """ + Attempts to set the vertical scroll postition for an element's Widget + :param percent_from_top: From 0 to 1.0, the percentage from the top to move scrollbar to + :type percent_from_top: (float) + """ + try: + self.Widget.yview_moveto(percent_from_top) + except Exception as e: + print('Warning setting the vertical scroll (yview_moveto failed)') + print(e) + + def _widget_was_created(self): + """ + Determines if a Widget was created for this element. + + :return: True if a Widget has been created previously (Widget is not None) + :rtype: (bool) + """ + if self.Widget is not None: + return True + else: + warnings.warn('You cannot Update element with key = {} until the window.read() is called or finalized=True when creating window'.format(self.Key), + UserWarning) + if not SUPPRESS_ERROR_POPUPS: + _error_popup_with_traceback('Unable to complete operation on element with key {}'.format(self.Key), + 'You cannot perform operations (such as calling update) on an Element until:', + ' window.read() is called or finalize=True when Window created.', + 'Adding a "finalize=True" parameter to your Window creation will likely fix this.', + _create_error_message(), + ) + return False + + + def _grab_anywhere_on_using_control_key(self): + """ + Turns on Grab Anywhere functionality AFTER a window has been created. Don't try on a window that's not yet + been Finalized or Read. + """ + self.Widget.bind("", self.ParentForm._StartMove) + self.Widget.bind("", self.ParentForm._StopMove) + self.Widget.bind("", self.ParentForm._OnMotion) + + + def _grab_anywhere_on(self): + """ + Turns on Grab Anywhere functionality AFTER a window has been created. Don't try on a window that's not yet + been Finalized or Read. + """ + self.Widget.bind("", self.ParentForm._StartMove) + self.Widget.bind("", self.ParentForm._StopMove) + self.Widget.bind("", self.ParentForm._OnMotion) + + def _grab_anywhere_off(self): + """ + Turns off Grab Anywhere functionality AFTER a window has been created. Don't try on a window that's not yet + been Finalized or Read. + """ + self.Widget.unbind("") + self.Widget.unbind("") + self.Widget.unbind("") + + def grab_anywhere_exclude(self): + """ + Excludes this element from being used by the grab_anywhere feature + Handy for elements like a Graph element when dragging is enabled. You want the Graph element to get the drag events instead of the window dragging. + """ + self.ParentForm._grab_anywhere_ignore_these_list.append(self.Widget) + + def grab_anywhere_include(self): + """ + Includes this element in the grab_anywhere feature + This will allow you to make a Multline element drag a window for example + """ + self.ParentForm._grab_anywhere_include_these_list.append(self.Widget) + + + + def set_right_click_menu(self, menu=None): + if menu == MENU_RIGHT_CLICK_DISABLED: + return + if menu is None: + menu = self.ParentForm.RightClickMenu + if menu is None: + return + if menu: + top_menu = tk.Menu(self.ParentForm.TKroot, tearoff=self.ParentForm.right_click_menu_tearoff, tearoffcommand=self._tearoff_menu_callback) + + if self.ParentForm.right_click_menu_background_color not in (COLOR_SYSTEM_DEFAULT, None): + top_menu.config(bg=self.ParentForm.right_click_menu_background_color) + if self.ParentForm.right_click_menu_text_color not in (COLOR_SYSTEM_DEFAULT, None): + top_menu.config(fg=self.ParentForm.right_click_menu_text_color) + if self.ParentForm.right_click_menu_disabled_text_color not in (COLOR_SYSTEM_DEFAULT, None): + top_menu.config(disabledforeground=self.ParentForm.right_click_menu_disabled_text_color) + if self.ParentForm.right_click_menu_font is not None: + top_menu.config(font=self.ParentForm.right_click_menu_font) + + if self.ParentForm.right_click_menu_selected_colors[0] not in (COLOR_SYSTEM_DEFAULT, None): + top_menu.config(activeforeground=self.ParentForm.right_click_menu_selected_colors[0]) + if self.ParentForm.right_click_menu_selected_colors[1] not in (COLOR_SYSTEM_DEFAULT, None): + top_menu.config(activebackground=self.ParentForm.right_click_menu_selected_colors[1]) + AddMenuItem(top_menu, menu[1], self, right_click_menu=True) + self.TKRightClickMenu = top_menu + if self.ParentForm.RightClickMenu: # if the top level has a right click menu, then setup a callback for the Window itself + if self.ParentForm.TKRightClickMenu is None: + self.ParentForm.TKRightClickMenu = top_menu + if (running_mac()): + self.ParentForm.TKroot.bind('', self.ParentForm._RightClickMenuCallback) + else: + self.ParentForm.TKroot.bind('', self.ParentForm._RightClickMenuCallback) + if (running_mac()): + self.Widget.bind('', self._RightClickMenuCallback) + else: + self.Widget.bind('', self._RightClickMenuCallback) + + + + + + + + + + + + def update(self, *args, **kwargs): + """ + A dummy update call. This will only be called if an element hasn't implemented an update method + It is provided here for docstring purposes. If you got here by browing code via PyCharm, know + that this is not the function that will be called. Your actual element's update method will be called + """ + print('* Base Element Class update was called. Your element does not seem to have an update method') + + + def __call__(self, *args, **kwargs): + """ + Makes it possible to "call" an already existing element. When you do make the "call", it actually calls + the Update method for the element. + Example: If this text element was in yoiur layout: + sg.Text('foo', key='T') + Then you can call the Update method for that element by writing: + window.find_element('T')('new text value') + """ + return self.update(*args, **kwargs) + + + + + + + SetTooltip = set_tooltip + SetFocus = set_focus + + +# ---------------------------------------------------------------------- # +# Input Class # +# ---------------------------------------------------------------------- # +class Input(Element): + """ + Display a single text input field. Based on the tkinter Widget `Entry` + """ + + def __init__(self, default_text='', size=(None, None), s=(None, None), disabled=False, password_char='', + justification=None, background_color=None, text_color=None, font=None, tooltip=None, border_width=None, + change_submits=False, enable_events=False, do_not_clear=True, key=None, k=None, focus=False, pad=None, p=None, + use_readonly_for_disable=True, readonly=False, disabled_readonly_background_color=None, disabled_readonly_text_color=None, expand_x=False, expand_y=False, + right_click_menu=None, visible=True, metadata=None): + """ + :param default_text: Text initially shown in the input box as a default value(Default value = ''). Will automatically be converted to string + :type default_text: (Any) + :param size: w=characters-wide, h=rows-high. If an int is supplied rather than a tuple, then a tuple is created width=int supplied and heigh=1 + :type size: (int, int) | (int, None) | int + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param disabled: set disable state for element (Default = False) + :type disabled: (bool) + :param password_char: Password character if this is a password field (Default value = '') + :type password_char: (char) + :param justification: justification for data display. Valid choices - left, right, center + :type justification: (str) + :param background_color: color of background in one of the color formats + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param font: specifies the font family, size. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param border_width: width of border around element in pixels + :type border_width: (int) + :param change_submits: * DEPRICATED DO NOT USE. Use `enable_events` instead + :type change_submits: (bool) + :param enable_events: If True then changes to this element are immediately reported as an event. Use this instead of change_submits (Default = False) + :type enable_events: (bool) + :param do_not_clear: If False then the field will be set to blank after ANY event (button, any event) (Default = True) + :type do_not_clear: (bool) + :param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param focus: Determines if initial focus should go to this element. + :type focus: (bool) + :param pad: Amount of padding to put around element. Normally (horizontal pixels, vertical pixels) but can be split apart further into ((horizontal left, horizontal right), (vertical above, vertical below)). If int is given, then converted to tuple (int, int) with the value provided duplicated + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param use_readonly_for_disable: If True (the default) tkinter state set to 'readonly'. Otherwise state set to 'disabled' + :type use_readonly_for_disable: (bool) + :param readonly: If True tkinter state set to 'readonly'. Use this in place of use_readonly_for_disable as another way of achieving readonly. Note cannot set BOTH readonly and disabled as tkinter only supplies a single flag + :type readonly: (bool) + :param disabled_readonly_background_color: If state is set to readonly or disabled, the color to use for the background + :type disabled_readonly_background_color: (str) + :param disabled_readonly_text_color: If state is set to readonly or disabled, the color to use for the text + :type disabled_readonly_text_color: (str) + :param expand_x: If True the element will automatically expand in the X direction to fill available space + :type expand_x: (bool) + :param expand_y: If True the element will automatically expand in the Y direction to fill available space + :type expand_y: (bool) + :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. + :type right_click_menu: List[List[ List[str] | str ]] + :param visible: set visibility state of the element (Default = True) + :type visible: (bool) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + + + self.DefaultText = default_text if default_text is not None else '' + self.PasswordCharacter = password_char + bg = background_color if background_color is not None else DEFAULT_INPUT_ELEMENTS_COLOR + fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR + self.Focus = focus + self.do_not_clear = do_not_clear + self.Justification = justification + self.Disabled = disabled + self.ChangeSubmits = change_submits or enable_events + self.RightClickMenu = right_click_menu + self.UseReadonlyForDisable = use_readonly_for_disable + self.disabled_readonly_background_color = disabled_readonly_background_color + self.disabled_readonly_text_color = disabled_readonly_text_color + self.ReadOnly = readonly + self.BorderWidth = border_width if border_width is not None else DEFAULT_BORDER_WIDTH + self.TKEntry = self.Widget = None # type: tk.Entry + key = key if key is not None else k + sz = size if size != (None, None) else s + pad = pad if pad is not None else p + self.expand_x = expand_x + self.expand_y = expand_y + + super().__init__(ELEM_TYPE_INPUT_TEXT, size=sz, background_color=bg, text_color=fg, key=key, pad=pad, + font=font, tooltip=tooltip, visible=visible, metadata=metadata) + + def update(self, value=None, disabled=None, select=None, visible=None, text_color=None, background_color=None, move_cursor_to='end', password_char=None): + """ + Changes some of the settings for the Input Element. Must call `Window.Read` or `Window.Finalize` prior + + :param value: new text to display as default text in Input field + :type value: (str) + :param disabled: disable or enable state of the element (sets Entry Widget to readonly or normal) + :type disabled: (bool) + :param select: if True, then the text will be selected + :type select: (bool) + :param visible: change visibility of element + :type visible: (bool) + :param text_color: change color of text being typed + :type text_color: (str) + :param background_color: change color of the background + :type background_color: (str) + :param move_cursor_to: Moves the cursor to a particular offset. Defaults to 'end' + :type move_cursor_to: int | str + :param password_char: Password character if this is a password field + :type password_char: str + """ + if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow + return + if disabled is True: + self.TKEntry['state'] = 'readonly' if self.UseReadonlyForDisable else 'disabled' + elif disabled is False: + self.TKEntry['state'] = 'readonly' if self.ReadOnly else 'normal' + if background_color not in (None, COLOR_SYSTEM_DEFAULT): + self.TKEntry.configure(background=background_color) + if text_color not in (None, COLOR_SYSTEM_DEFAULT): + self.TKEntry.configure(fg=text_color) + if value is not None: + try: + self.TKStringVar.set(value) + except: + pass + self.DefaultText = value + if move_cursor_to == 'end': + self.TKEntry.icursor(tk.END) + elif move_cursor_to is not None: + self.TKEntry.icursor(move_cursor_to) + if select: + self.TKEntry.select_range(0, 'end') + if visible is False: + self.TKEntry.pack_forget() + elif visible is True: + self.TKEntry.pack(padx=self.pad_used[0], pady=self.pad_used[1]) + # self.TKEntry.pack(padx=self.pad_used[0], pady=self.pad_used[1], in_=self.ParentRowFrame) + if visible is not None: + self._visible = visible + if password_char is not None: + self.TKEntry.configure(show=password_char) + self.PasswordCharacter = password_char + + def get(self): + """ + Read and return the current value of the input element. Must call `Window.Read` or `Window.Finalize` prior + + :return: current value of Input field or '' if error encountered + :rtype: (str) + """ + try: + text = self.TKStringVar.get() + except: + text = '' + return text + + Get = get + Update = update + + +# ------------------------- INPUT TEXT Element lazy functions ------------------------- # +In = Input +InputText = Input +I = Input + + +# ---------------------------------------------------------------------- # +# Combo # +# ---------------------------------------------------------------------- # +class Combo(Element): + """ + ComboBox Element - A combination of a single-line input and a drop-down menu. User can type in their own value or choose from list. + """ + + def __init__(self, values, default_value=None, size=(None, None), s=(None, None), auto_size_text=None, background_color=None, + text_color=None, bind_return_key=False, change_submits=False, enable_events=False, disabled=False, key=None, k=None, pad=None, p=None, expand_x=False, expand_y=False, + tooltip=None, readonly=False, font=None, visible=True, metadata=None): + """ + :param values: values to choose. While displayed as text, the items returned are what the caller supplied, not text + :type values: List[Any] or Tuple[Any] + :param default_value: Choice to be displayed as initial value. Must match one of values variable contents + :type default_value: (Any) + :param size: width, height. Width = characters-wide, height = NOTE it's the number of entries to show in the list. If an Int is passed rather than a tuple, then height is auto-set to 1 and width is value of the int + :type size: (int, int) | (None, None) | int + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param auto_size_text: True if element should be the same size as the contents + :type auto_size_text: (bool) + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param bind_return_key: If True, then the return key will cause a the Combo to generate an event + :type bind_return_key: (bool) + :param change_submits: DEPRICATED DO NOT USE. Use `enable_events` instead + :type change_submits: (bool) + :param enable_events: Turns on the element specific events. Combo event is when a choice is made + :type enable_events: (bool) + :param disabled: set disable state for element + :type disabled: (bool) + :param key: Used with window.find_element and with return values to uniquely identify this element + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param expand_x: If True the element will automatically expand in the X direction to fill available space + :type expand_x: (bool) + :param expand_y: If True the element will automatically expand in the Y direction to fill available space + :type expand_y: (bool) :param tooltip: text that will appear when mouse hovers over this element + :type tooltip: (str) + :param readonly: make element readonly (user can't change). True means user cannot change + :type readonly: (bool) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param visible: set visibility state of the element + :type visible: (bool) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + self.Values = values + self.DefaultValue = default_value + self.ChangeSubmits = change_submits or enable_events + self.Widget = self.TKCombo = None # type: ttk.Combobox + self.Disabled = disabled + self.Readonly = readonly + self.BindReturnKey = bind_return_key + bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR + fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR + key = key if key is not None else k + sz = size if size != (None, None) else s + pad = pad if pad is not None else p + self.expand_x = expand_x + self.expand_y = expand_y + + super().__init__(ELEM_TYPE_INPUT_COMBO, size=sz, auto_size_text=auto_size_text, background_color=bg, + text_color=fg, key=key, pad=pad, tooltip=tooltip, font=font or DEFAULT_FONT, visible=visible, metadata=metadata) + + def update(self, value=None, values=None, set_to_index=None, disabled=None, readonly=None, font=None, visible=None, size=(None, None)): + """ + Changes some of the settings for the Combo Element. Must call `Window.Read` or `Window.Finalize` prior. + Note that the state can be in 3 states only.... enabled, disabled, readonly even + though more combinations are available. The easy way to remember is that if you + change the readonly parameter then you are enabling the element. + :param value: change which value is current selected based on new list of previous list of choices + :type value: (Any) + :param values: change list of choices + :type values: List[Any] + :param set_to_index: change selection to a particular choice starting with index = 0 + :type set_to_index: (int) + :param disabled: disable or enable state of the element + :type disabled: (bool) + :param readonly: if True make element readonly (user cannot change any choices). Enables the element if either choice are made. + :type readonly: (bool) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param visible: control visibility of element + :type visible: (bool) + :param size: width, height. Width = characters-wide, height = NOTE it's the number of entries to show in the list + :type size: (int, int) + """ + if size != (None, None): + if isinstance(size, int): + size = (size, 1) + if isinstance(size, tuple) and len(size) == 1: + size = (size[0], 1) + + if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow + return + if values is not None: + try: + self.TKCombo['values'] = values + # self.TKCombo.current(0) # don't set any value if a new set of values was made + except: + pass + self.Values = values + if value is None: + self.TKCombo.set('') + if size == (None, None): + max_line_len = max([len(str(l)) for l in self.Values]) if len(self.Values) else 0 + if self.AutoSizeText is False: + width = self.Size[0] + else: + width = max_line_len + 1 + # self.TKCombo.configure(width=width) + else: + self.TKCombo.configure(height=size[1]) + self.TKCombo.configure(width=size[0]) + if value is not None: + if value not in self.Values: + self.TKCombo.set(value) + else: + for index, v in enumerate(self.Values): + if v == value: + try: + self.TKCombo.current(index) + except: + pass + self.DefaultValue = value + break + if set_to_index is not None: + try: + self.TKCombo.current(set_to_index) + self.DefaultValue = self.Values[set_to_index] + except: + pass + if readonly: + self.Readonly = True + self.TKCombo['state'] = 'readonly' + elif readonly is False: + self.Readonly = False + self.TKCombo['state'] = 'enable' + if disabled is True: + self.TKCombo['state'] = 'disable' + elif disabled is False and self.Readonly is True: + self.TKCombo['state'] = 'readonly' + elif disabled is False and self.Readonly is False: + self.TKCombo['state'] = 'enable' + self.Disabled = disabled if disabled is not None else self.Disabled + if font is not None: + self.TKCombo.configure(font=font) + if visible is False: + self.TKCombo.pack_forget() + elif visible is True: + self.TKCombo.pack(padx=self.pad_used[0], pady=self.pad_used[1]) + if visible is not None: + self._visible = visible + + def get(self): + """ + Returns the current (right now) value of the Combo. DO NOT USE THIS AS THE NORMAL WAY OF READING A COMBO! + You should be using values from your call to window.read instead. Know what you're doing if you use it. + + :return: Returns the value of what is currently chosen + :rtype: Any | None + """ + try: + if self.TKCombo.current() == -1: # if the current value was not in the original list + value = self.TKCombo.get() # then get the value typed in by user + else: + value = self.Values[self.TKCombo.current()] # get value from original list given index + except: + value = None # only would happen if user closes window + return value + + Get = get + Update = update + + +# ------------------------- INPUT COMBO Element lazy functions ------------------------- # +InputCombo = Combo +DropDown = InputCombo +Drop = InputCombo +DD = Combo + + +# ---------------------------------------------------------------------- # +# Option Menu # +# ---------------------------------------------------------------------- # +class OptionMenu(Element): + """ + Option Menu is an Element available ONLY on the tkinter port of PySimpleGUI. It's is a widget that is unique + to tkinter. However, it looks much like a ComboBox. Instead of an arrow to click to pull down the list of + choices, another little graphic is shown on the widget to indicate where you click. After clicking to activate, + it looks like a Combo Box that you scroll to select a choice. + """ + + def __init__(self, values, default_value=None, size=(None, None), s=(None, None), disabled=False, auto_size_text=None, expand_x=False, expand_y=False, + background_color=None, text_color=None, key=None, k=None, pad=None, p=None, tooltip=None, visible=True, metadata=None): + """ + :param values: Values to be displayed + :type values: List[Any] or Tuple[Any] + :param default_value: the value to choose by default + :type default_value: (Any) + :param size: (width, height) size in characters (wide), height is ignored and present to be consistent with other elements + :type size: (int, int) (width, UNUSED) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param disabled: control enabled / disabled + :type disabled: (bool) + :param auto_size_text: True if size of Element should match the contents of the items + :type auto_size_text: (bool) + :param expand_x: If True the element will automatically expand in the X direction to fill available space + :type expand_x: (bool) + :param expand_y: If True the element will automatically expand in the Y direction to fill available space + :type expand_y: (bool) + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param key: Used with window.find_element and with return values to uniquely identify this element + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param tooltip: text that will appear when mouse hovers over this element + :type tooltip: (str) + :param visible: set visibility state of the element + :type visible: (bool) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + + self.Values = values + self.DefaultValue = default_value + self.Widget = self.TKOptionMenu = None # type: tk.OptionMenu + self.Disabled = disabled + bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR + fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR + key = key if key is not None else k + sz = size if size != (None, None) else s + pad = pad if pad is not None else p + self.expand_x = expand_x + self.expand_y = expand_y + + super().__init__(ELEM_TYPE_INPUT_OPTION_MENU, size=sz, auto_size_text=auto_size_text, background_color=bg, + text_color=fg, key=key, pad=pad, tooltip=tooltip, visible=visible, metadata=metadata) + + def update(self, value=None, values=None, disabled=None, visible=None, size=(None, None)): + """ + Changes some of the settings for the OptionMenu Element. Must call `Window.Read` or `Window.Finalize` prior + :param value: the value to choose by default + :type value: (Any) + :param values: Values to be displayed + :type values: List[Any] + :param disabled: disable or enable state of the element + :type disabled: (bool) + :param visible: control visibility of element + :type visible: (bool) + :param size: (width, height) size in characters (wide), height is ignored and present to be consistent with other elements + :type size: (int, int) (width, UNUSED) + """ + if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow + return + + if values is not None: + self.Values = values + self.TKOptionMenu['menu'].delete(0, 'end') + + # Insert list of new options (tk._setit hooks them up to var) + # self.TKStringVar.set(self.Values[0]) + for new_value in self.Values: + self.TKOptionMenu['menu'].add_command(label=new_value, command=tk._setit(self.TKStringVar, new_value)) + if value is None: + self.TKStringVar.set('') + + if size == (None, None): + max_line_len = max([len(str(l)) for l in self.Values]) if len(self.Values) else 0 + if self.AutoSizeText is False: + width = self.Size[0] + else: + width = max_line_len + 1 + self.TKOptionMenu.configure(width=width) + else: + self.TKOptionMenu.configure(width=size[0]) + + if value is not None: + self.DefaultValue = value + self.TKStringVar.set(value) + + if disabled == True: + self.TKOptionMenu['state'] = 'disabled' + elif disabled == False: + self.TKOptionMenu['state'] = 'normal' + if visible is False: + self.TKOptionMenu.pack_forget() + elif visible is True: + self.TKOptionMenu.pack(padx=self.pad_used[0], pady=self.pad_used[1]) + if visible is not None: + self._visible = visible + + Update = update + + +# ------------------------- OPTION MENU Element lazy functions ------------------------- # +InputOptionMenu = OptionMenu + + +# ---------------------------------------------------------------------- # +# Listbox # +# ---------------------------------------------------------------------- # +class Listbox(Element): + """ + A List Box. Provide a list of values for the user to choose one or more of. Returns a list of selected rows + when a window.read() is executed. + """ + + def __init__(self, values, default_values=None, select_mode=None, change_submits=False, enable_events=False, + bind_return_key=False, size=(None, None), s=(None, None), disabled=False, auto_size_text=None, font=None, no_scrollbar=False, horizontal_scroll=False, + background_color=None, text_color=None, highlight_background_color=None, highlight_text_color=None, + key=None, k=None, pad=None, p=None, tooltip=None, expand_x=False, expand_y=False,right_click_menu=None, visible=True, metadata=None): + """ + :param values: list of values to display. Can be any type including mixed types as long as they have __str__ method + :type values: List[Any] or Tuple[Any] + :param default_values: which values should be initially selected + :type default_values: List[Any] + :param select_mode: Select modes are used to determine if only 1 item can be selected or multiple and how they can be selected. Valid choices begin with "LISTBOX_SELECT_MODE_" and include: LISTBOX_SELECT_MODE_SINGLE LISTBOX_SELECT_MODE_MULTIPLE LISTBOX_SELECT_MODE_BROWSE LISTBOX_SELECT_MODE_EXTENDED + :type select_mode: [enum] + :param change_submits: DO NOT USE. Only listed for backwards compat - Use enable_events instead + :type change_submits: (bool) + :param enable_events: Turns on the element specific events. Listbox generates events when an item is clicked + :type enable_events: (bool) + :param bind_return_key: If True, then the return key will cause a the Listbox to generate an event + :type bind_return_key: (bool) + :param size: w=characters-wide, h=rows-high. If an int instead of a tuple is supplied, then height is auto-set to 1 + :type size: (int, int) | (int, None) | int + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param disabled: set disable state for element + :type disabled: (bool) + :param auto_size_text: True if element should be the same size as the contents + :type auto_size_text: (bool) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param no_scrollbar: Controls if a scrollbar should be shown. If True, no scrollbar will be shown + :type no_scrollbar: (bool) + :param horizontal_scroll: Controls if a horizontal scrollbar should be shown. If True a horizontal scrollbar will be shown in addition to vertical + :type horizontal_scroll: (bool) + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param highlight_background_color: color of the background when an item is selected. Defaults to normal text color (a reverse look) + :type highlight_background_color: (str) + :param highlight_text_color: color of the text when an item is selected. Defaults to the normal background color (a rerverse look) + :type highlight_text_color: (str) + :param key: Used with window.find_element and with return values to uniquely identify this element + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param expand_x: If True the element will automatically expand in the X direction to fill available space + :type expand_x: (bool) + :param expand_y: If True the element will automatically expand in the Y direction to fill available space + :type expand_y: (bool) + :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. + :type right_click_menu: List[List[ List[str] | str ]] + :param visible: set visibility state of the element + :type visible: (bool) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + + self.Values = values + self.DefaultValues = default_values + self.TKListbox = None + self.ChangeSubmits = change_submits or enable_events + self.BindReturnKey = bind_return_key + self.Disabled = disabled + if select_mode == LISTBOX_SELECT_MODE_BROWSE: + self.SelectMode = SELECT_MODE_BROWSE + elif select_mode == LISTBOX_SELECT_MODE_EXTENDED: + self.SelectMode = SELECT_MODE_EXTENDED + elif select_mode == LISTBOX_SELECT_MODE_MULTIPLE: + self.SelectMode = SELECT_MODE_MULTIPLE + elif select_mode == LISTBOX_SELECT_MODE_SINGLE: + self.SelectMode = SELECT_MODE_SINGLE + else: + self.SelectMode = DEFAULT_LISTBOX_SELECT_MODE + bg = background_color if background_color is not None else theme_input_background_color() + fg = text_color if text_color is not None else theme_input_text_color() + self.HighlightBackgroundColor = highlight_background_color if highlight_background_color is not None else fg + self.HighlightTextColor = highlight_text_color if highlight_text_color is not None else bg + self.RightClickMenu = right_click_menu + self.vsb = None # type: tk.Scrollbar or None + self.hsb = None # type: tk.Scrollbar | None + self.TKListbox = self.Widget = None # type: tk.Listbox + self.element_frame = None # type: tk.Frame + self.NoScrollbar = no_scrollbar + self.HorizontalScroll = horizontal_scroll + key = key if key is not None else k + sz = size if size != (None, None) else s + pad = pad if pad is not None else p + self.expand_x = expand_x + self.expand_y = expand_y + + super().__init__(ELEM_TYPE_INPUT_LISTBOX, size=sz, auto_size_text=auto_size_text, font=font, + background_color=bg, text_color=fg, key=key, pad=pad, tooltip=tooltip, visible=visible, metadata=metadata) + + def update(self, values=None, disabled=None, set_to_index=None, scroll_to_index=None, select_mode=None, visible=None): + """ + Changes some of the settings for the Listbox Element. Must call `Window.Read` or `Window.Finalize` prior + :param values: new list of choices to be shown to user + :type values: List[Any] + :param disabled: disable or enable state of the element + :type disabled: (bool) + :param set_to_index: highlights the item(s) indicated. If parm is an int one entry will be set. If is a list, then each entry in list is highlighted + :type set_to_index: int | list | tuple + :param scroll_to_index: scroll the listbox so that this index is the first shown + :type scroll_to_index: (int) + :param select_mode: changes the select mode according to tkinter's listbox widget + :type select_mode: (str) + :param visible: control visibility of element + :type visible: (bool) + """ + + if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow + return + + if disabled is True: + self.TKListbox.configure(state='disabled') + elif disabled is False: + self.TKListbox.configure(state='normal') + if values is not None: + self.TKListbox.delete(0, 'end') + for item in list(values): + self.TKListbox.insert(tk.END, item) + # self.TKListbox.selection_set(0, 0) + self.Values = list(values) + if set_to_index is not None: + self.TKListbox.selection_clear(0, len(self.Values)) # clear all listbox selections + if type(set_to_index) in (tuple, list): + for i in set_to_index: + try: + self.TKListbox.selection_set(i, i) + except: + warnings.warn('* Listbox Update selection_set failed with index {}*'.format(set_to_index)) + else: + try: + self.TKListbox.selection_set(set_to_index, set_to_index) + except: + warnings.warn('* Listbox Update selection_set failed with index {}*'.format(set_to_index)) + if visible is False: + self.element_frame.pack_forget() + if not self.NoScrollbar: + self.vsb.pack_forget() + elif visible is True: + self.element_frame.pack(padx=self.pad_used[0], pady=self.pad_used[1]) + if not self.NoScrollbar: + self.vsb.pack() + if scroll_to_index is not None and len(self.Values): + self.TKListbox.yview_moveto(scroll_to_index / len(self.Values)) + if select_mode is not None: + try: + self.TKListbox.config(selectmode=select_mode) + except: + print('Listbox.update error trying to change mode to: ', select_mode) + if visible is not None: + self._visible = visible + + def set_value(self, values): + """ + Set listbox highlighted choices + + :param values: new values to choose based on previously set values + :type values: List[Any] | Tuple[Any] + + """ + for index, item in enumerate(self.Values): + try: + if item in values: + self.TKListbox.selection_set(index) + else: + self.TKListbox.selection_clear(index) + except: + pass + self.DefaultValues = values + + def get_list_values(self): + # type: (Listbox) -> List[Any] + """ + Returns list of Values provided by the user in the user's format + + :return: List of values. Can be any / mixed types -> [] + :rtype: List[Any] + """ + return self.Values + + def get_indexes(self): + """ + Returns the items currently selected as a list of indexes + + :return: A list of offsets into values that is currently selected + :rtype: List[int] + """ + return self.TKListbox.curselection() + + def get(self): + """ + Returns the list of items currently selected in this listbox. It should be identical + to the value you would receive when performing a window.read() call. + + :return: The list of currently selected items. The actual items are returned, not the indexes + :rtype: List[Any] + """ + try: + items = self.TKListbox.curselection() + value = [self.Values[int(item)] for item in items] + except: + value = [] + return value + + GetIndexes = get_indexes + GetListValues = get_list_values + SetValue = set_value + Update = update + + +LBox = Listbox +LB = Listbox + + +# ---------------------------------------------------------------------- # +# Radio # +# ---------------------------------------------------------------------- # +class Radio(Element): + """ + Radio Button Element - Used in a group of other Radio Elements to provide user with ability to select only + 1 choice in a list of choices. + """ + + def __init__(self, text, group_id, default=False, disabled=False, size=(None, None), s=(None, None), auto_size_text=None, + background_color=None, text_color=None, circle_color=None, font=None, key=None, k=None, pad=None, p=None, tooltip=None, + change_submits=False, enable_events=False, right_click_menu=None, expand_x=False, expand_y=False, visible=True, metadata=None): + """ + :param text: Text to display next to button + :type text: (str) + :param group_id: Groups together multiple Radio Buttons. Any type works + :type group_id: (Any) + :param default: Set to True for the one element of the group you want initially selected + :type default: (bool) + :param disabled: set disable state + :type disabled: (bool) + :param size: (w, h) w=characters-wide, h=rows-high. If an int instead of a tuple is supplied, then height is auto-set to 1 + :type size: (int, int) | (None, None) | int + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param auto_size_text: if True will size the element to match the length of the text + :type auto_size_text: (bool) + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param circle_color: color of background of the circle that has the dot selection indicator in it + :type circle_color: (str) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param key: Used with window.find_element and with return values to uniquely identify this element + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param change_submits: DO NOT USE. Only listed for backwards compat - Use enable_events instead + :type change_submits: (bool) + :param enable_events: Turns on the element specific events. Radio Button events happen when an item is selected + :type enable_events: (bool) + :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. + :type right_click_menu: List[List[ List[str] | str ]] + :param expand_x: If True the element will automatically expand in the X direction to fill available space + :type expand_x: (bool) + :param expand_y: If True the element will automatically expand in the Y direction to fill available space + :type expand_y: (bool) + :param visible: set visibility state of the element + :type visible: (bool) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + + + self.InitialState = default + self.Text = text + self.Widget = self.TKRadio = None # type: tk.Radiobutton + self.GroupID = group_id + self.Value = None + self.Disabled = disabled + self.TextColor = text_color if text_color else theme_text_color() + self.RightClickMenu = right_click_menu + + if circle_color is None: + # ---- compute color of circle background --- + try: # something in here will fail if a color is not specified in Hex + text_hsl = _hex_to_hsl(self.TextColor) + background_hsl = _hex_to_hsl(background_color if background_color else theme_background_color()) + l_delta = abs(text_hsl[2] - background_hsl[2]) / 10 + if text_hsl[2] > background_hsl[2]: # if the text is "lighter" than the background then make background darker + bg_rbg = _hsl_to_rgb(background_hsl[0], background_hsl[1], background_hsl[2] - l_delta) + else: + bg_rbg = _hsl_to_rgb(background_hsl[0], background_hsl[1], background_hsl[2] + l_delta) + self.CircleBackgroundColor = rgb(*bg_rbg) + except: + self.CircleBackgroundColor = background_color if background_color else theme_background_color() + else: + self.CircleBackgroundColor = circle_color + self.ChangeSubmits = change_submits or enable_events + self.EncodedRadioValue = None + key = key if key is not None else k + sz = size if size != (None, None) else s + pad = pad if pad is not None else p + self.expand_x = expand_x + self.expand_y = expand_y + + super().__init__(ELEM_TYPE_INPUT_RADIO, size=sz, auto_size_text=auto_size_text, font=font, + background_color=background_color, text_color=self.TextColor, key=key, pad=pad, + tooltip=tooltip, visible=visible, metadata=metadata) + + def update(self, value=None, text=None, background_color=None, text_color=None, circle_color=None, disabled=None, visible=None): + """ + Changes some of the settings for the Radio Button Element. Must call `Window.read` or `Window.finalize` prior + :param value: if True change to selected and set others in group to unselected + :type value: (bool) + :param text: Text to display next to radio button + :type text: (str) + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text. Note this also changes the color of the selection dot + :type text_color: (str) + :param circle_color: color of background of the circle that has the dot selection indicator in it + :type circle_color: (str) + :param disabled: disable or enable state of the element + :type disabled: (bool) + :param visible: control visibility of element + :type visible: (bool) + """ + + if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow + return + + if value is not None: + try: + if value is True: + self.TKIntVar.set(self.EncodedRadioValue) + elif value is False: + if self.TKIntVar.get() == self.EncodedRadioValue: + self.TKIntVar.set(0) + except: + print('Error updating Radio') + self.InitialState = value + if text is not None: + self.Text = str(text) + self.TKRadio.configure(text=self.Text) + if background_color not in (None, COLOR_SYSTEM_DEFAULT): + self.TKRadio.configure(background=background_color) + self.BackgroundColor = background_color + if text_color not in (None, COLOR_SYSTEM_DEFAULT): + self.TKRadio.configure(fg=text_color) + self.TextColor = text_color + + if circle_color not in (None, COLOR_SYSTEM_DEFAULT): + self.CircleBackgroundColor = circle_color + self.TKRadio.configure(selectcolor=self.CircleBackgroundColor) # The background of the radio button + elif text_color or background_color: + if self.TextColor not in (None, COLOR_SYSTEM_DEFAULT) and self.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT) and self.TextColor.startswith( + '#') and self.BackgroundColor.startswith('#'): + # ---- compute color of circle background --- + text_hsl = _hex_to_hsl(self.TextColor) + background_hsl = _hex_to_hsl(self.BackgroundColor if self.BackgroundColor else theme_background_color()) + l_delta = abs(text_hsl[2] - background_hsl[2]) / 10 + if text_hsl[2] > background_hsl[2]: # if the text is "lighter" than the background then make background darker + bg_rbg = _hsl_to_rgb(background_hsl[0], background_hsl[1], background_hsl[2] - l_delta) + else: + bg_rbg = _hsl_to_rgb(background_hsl[0], background_hsl[1], background_hsl[2] + l_delta) + self.CircleBackgroundColor = rgb(*bg_rbg) + self.TKRadio.configure(selectcolor=self.CircleBackgroundColor) # The background of the checkbox + + if disabled is True: + self.TKRadio['state'] = 'disabled' + elif disabled is False: + self.TKRadio['state'] = 'normal' + if visible is False: + self.TKRadio.pack_forget() + elif visible is True: + self.TKRadio.pack(padx=self.pad_used[0], pady=self.pad_used[1]) + if visible is not None: + self._visible = visible + + def reset_group(self): + """ + Sets all Radio Buttons in the group to not selected + """ + self.TKIntVar.set(0) + + def get(self): + # type: (Radio) -> bool + """ + A snapshot of the value of Radio Button -> (bool) + + :return: True if this radio button is selected + :rtype: (bool) + """ + return self.TKIntVar.get() == self.EncodedRadioValue + + Get = get + ResetGroup = reset_group + Update = update + + +R = Radio +Rad = Radio + + +# ---------------------------------------------------------------------- # +# Checkbox # +# ---------------------------------------------------------------------- # +class Checkbox(Element): + """ + Checkbox Element - Displays a checkbox and text next to it + """ + + def __init__(self, text, default=False, size=(None, None), s=(None, None), auto_size_text=None, font=None, background_color=None, + text_color=None, checkbox_color=None, change_submits=False, enable_events=False, disabled=False, key=None, k=None, pad=None, p=None, tooltip=None, + right_click_menu=None, expand_x=False, expand_y=False, visible=True, metadata=None): + """ + :param text: Text to display next to checkbox + :type text: (str) + :param default: Set to True if you want this checkbox initially checked + :type default: (bool) + :param size: (w, h) w=characters-wide, h=rows-high. If an int instead of a tuple is supplied, then height is auto-set to 1 + :type size: (int, int) | (None, None) | int + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param auto_size_text: if True will size the element to match the length of the text + :type auto_size_text: (bool) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param checkbox_color: color of background of the box that has the check mark in it. The checkmark is the same color as the text + :type checkbox_color: (str) + :param change_submits: DO NOT USE. Only listed for backwards compat - Use enable_events instead + :type change_submits: (bool) + :param enable_events: Turns on the element specific events. Checkbox events happen when an item changes + :type enable_events: (bool) + :param disabled: set disable state + :type disabled: (bool) + :param key: Used with window.find_element and with return values to uniquely identify this element + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. + :type right_click_menu: List[List[ List[str] | str ]] + :param expand_x: If True the element will automatically expand in the X direction to fill available space + :type expand_x: (bool) + :param expand_y: If True the element will automatically expand in the Y direction to fill available space + :type expand_y: (bool) + :param visible: set visibility state of the element + :type visible: (bool) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + + + self.Text = text + self.InitialState = default + self.Value = None + self.TKCheckbutton = self.Widget = None # type: tk.Checkbutton + self.Disabled = disabled + self.TextColor = text_color if text_color else theme_text_color() + self.RightClickMenu = right_click_menu + + # ---- compute color of circle background --- + if checkbox_color is None: + try: # something in here will fail if a color is not specified in Hex + text_hsl = _hex_to_hsl(self.TextColor) + background_hsl = _hex_to_hsl(background_color if background_color else theme_background_color()) + l_delta = abs(text_hsl[2] - background_hsl[2]) / 10 + if text_hsl[2] > background_hsl[2]: # if the text is "lighter" than the background then make background darker + bg_rbg = _hsl_to_rgb(background_hsl[0], background_hsl[1], background_hsl[2] - l_delta) + else: + bg_rbg = _hsl_to_rgb(background_hsl[0], background_hsl[1], background_hsl[2] + l_delta) + self.CheckboxBackgroundColor = rgb(*bg_rbg) + except: + self.CheckboxBackgroundColor = background_color if background_color else theme_background_color() + else: + self.CheckboxBackgroundColor = checkbox_color + self.ChangeSubmits = change_submits or enable_events + key = key if key is not None else k + sz = size if size != (None, None) else s + pad = pad if pad is not None else p + self.expand_x = expand_x + self.expand_y = expand_y + + super().__init__(ELEM_TYPE_INPUT_CHECKBOX, size=sz, auto_size_text=auto_size_text, font=font, + background_color=background_color, text_color=self.TextColor, key=key, pad=pad, + tooltip=tooltip, visible=visible, metadata=metadata) + + def get(self): + # type: (Checkbox) -> bool + """ + Return the current state of this checkbox + + :return: Current state of checkbox + :rtype: (bool) + """ + return self.TKIntVar.get() != 0 + + def update(self, value=None, text=None, background_color=None, text_color=None, checkbox_color=None, disabled=None, visible=None): + """ + Changes some of the settings for the Checkbox Element. Must call `Window.Read` or `Window.Finalize` prior. + Note that changing visibility may cause element to change locations when made visible after invisible + :param value: if True checks the checkbox, False clears it + :type value: (bool) + :param text: Text to display next to checkbox + :type text: (str) + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text. Note this also changes the color of the checkmark + :type text_color: (str) + :param disabled: disable or enable element + :type disabled: (bool) + :param visible: control visibility of element + :type visible: (bool) + """ + + if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow + return + + if value is not None: + value = bool(value) + try: + self.TKIntVar.set(value) + self.InitialState = value + except: + print('Checkbox update failed') + if disabled == True: + self.TKCheckbutton.configure(state='disabled') + elif disabled == False: + self.TKCheckbutton.configure(state='normal') + if text is not None: + self.Text = str(text) + self.TKCheckbutton.configure(text=self.Text) + if background_color not in (None, COLOR_SYSTEM_DEFAULT): + self.TKCheckbutton.configure(background=background_color) + self.BackgroundColor = background_color + if text_color not in (None, COLOR_SYSTEM_DEFAULT): + self.TKCheckbutton.configure(fg=text_color) + self.TextColor = text_color + # Color the checkbox itself + if checkbox_color not in (None, COLOR_SYSTEM_DEFAULT): + self.CheckboxBackgroundColor = checkbox_color + self.TKCheckbutton.configure(selectcolor=self.CheckboxBackgroundColor) # The background of the checkbox + elif text_color or background_color: + if self.CheckboxBackgroundColor is not None and self.TextColor is not None and self.BackgroundColor is not None and self.TextColor.startswith( + '#') and self.BackgroundColor.startswith('#'): + # ---- compute color of checkbox background --- + text_hsl = _hex_to_hsl(self.TextColor) + background_hsl = _hex_to_hsl(self.BackgroundColor if self.BackgroundColor else theme_background_color()) + l_delta = abs(text_hsl[2] - background_hsl[2]) / 10 + if text_hsl[2] > background_hsl[2]: # if the text is "lighter" than the background then make background darker + bg_rbg = _hsl_to_rgb(background_hsl[0], background_hsl[1], background_hsl[2] - l_delta) + else: + bg_rbg = _hsl_to_rgb(background_hsl[0], background_hsl[1], background_hsl[2] + l_delta) + self.CheckboxBackgroundColor = rgb(*bg_rbg) + self.TKCheckbutton.configure(selectcolor=self.CheckboxBackgroundColor) # The background of the checkbox + + if visible is False: + self.TKCheckbutton.pack_forget() + elif visible is True: + self.TKCheckbutton.pack(padx=self.pad_used[0], pady=self.pad_used[1]) + if visible is not None: + self._visible = visible + + Get = get + Update = update + + +# ------------------------- CHECKBOX Element lazy functions ------------------------- # +CB = Checkbox +CBox = Checkbox +Check = Checkbox + + +# ---------------------------------------------------------------------- # +# Spin # +# ---------------------------------------------------------------------- # + +class Spin(Element): + """ + A spinner with up/down buttons and a single line of text. Choose 1 values from list + """ + + def __init__(self, values, initial_value=None, disabled=False, change_submits=False, enable_events=False, readonly=False, + size=(None, None), s=(None, None), auto_size_text=None, font=None, background_color=None, text_color=None, key=None, k=None, pad=None, p=None, + tooltip=None, right_click_menu=None, expand_x=False, expand_y=False, visible=True, metadata=None): + """ + :param values: List of valid values + :type values: Tuple[Any] or List[Any] + :param initial_value: Initial item to show in window. Choose from list of values supplied + :type initial_value: (Any) + :param disabled: set disable state + :type disabled: (bool) + :param change_submits: DO NOT USE. Only listed for backwards compat - Use enable_events instead + :type change_submits: (bool) + :param enable_events: Turns on the element specific events. Spin events happen when an item changes + :type enable_events: (bool) + :param readonly: Turns on the element specific events. Spin events happen when an item changes + :type readonly: (bool) + :param size: (w, h) w=characters-wide, h=rows-high. If an int instead of a tuple is supplied, then height is auto-set to 1 + :type size: (int, int) | (None, None) | int + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param auto_size_text: if True will size the element to match the length of the text + :type auto_size_text: (bool) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param key: Used with window.find_element and with return values to uniquely identify this element + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. + :type right_click_menu: List[List[ List[str] | str ]] + :param expand_x: If True the element will automatically expand in the X direction to fill available space + :type expand_x: (bool) + :param expand_y: If True the element will automatically expand in the Y direction to fill available space + :type expand_y: (bool) + :param visible: set visibility state of the element + :type visible: (bool) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + + + self.Values = values + self.DefaultValue = initial_value + self.ChangeSubmits = change_submits or enable_events + self.TKSpinBox = self.Widget = None # type: tk.Spinbox + self.Disabled = disabled + self.Readonly = readonly + self.RightClickMenu = right_click_menu + + bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR + fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR + key = key if key is not None else k + sz = size if size != (None, None) else s + pad = pad if pad is not None else p + self.expand_x = expand_x + self.expand_y = expand_y + + + super().__init__(ELEM_TYPE_INPUT_SPIN, size=sz, auto_size_text=auto_size_text, font=font, background_color=bg, text_color=fg, + key=key, pad=pad, tooltip=tooltip, visible=visible, metadata=metadata) + return + + def update(self, value=None, values=None, disabled=None, readonly=None, visible=None): + """ + Changes some of the settings for the Spin Element. Must call `Window.Read` or `Window.Finalize` prior + Note that the state can be in 3 states only.... enabled, disabled, readonly even + though more combinations are available. The easy way to remember is that if you + change the readonly parameter then you are enabling the element. + :param value: set the current value from list of choices + :type value: (Any) + :param values: set available choices + :type values: List[Any] + :param disabled: disable. Note disabled and readonly cannot be mixed. It must be one OR the other + :type disabled: (bool) + :param readonly: make element readonly. Note disabled and readonly cannot be mixed. It must be one OR the other + :type readonly: (bool) + :param visible: control visibility of element + :type visible: (bool) + """ + + if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow + return + + if values != None: + old_value = self.TKStringVar.get() + self.Values = values + self.TKSpinBox.configure(values=values) + self.TKStringVar.set(old_value) + if value is not None: + try: + self.TKStringVar.set(value) + self.DefaultValue = value + except: + pass + + if readonly is True: + self.Readonly = True + self.TKSpinBox['state'] = 'readonly' + elif readonly is False: + self.Readonly = False + self.TKSpinBox['state'] = 'normal' + if disabled is True: + self.TKSpinBox['state'] = 'disable' + elif disabled is False: + if self.Readonly: + self.TKSpinBox['state'] = 'readonly' + else: + self.TKSpinBox['state'] = 'normal' + + if visible is False: + self.TKSpinBox.pack_forget() + elif visible is True: + self.TKSpinBox.pack(padx=self.pad_used[0], pady=self.pad_used[1]) + if visible is not None: + self._visible = visible + + def _SpinChangedHandler(self, event): + """ + Callback function. Used internally only. Called by tkinter when Spinbox Widget changes. Results in Window.Read() call returning + + :param event: passed in from tkinter + :type event: + """ + # first, get the results table built + if self.Key is not None: + self.ParentForm.LastButtonClicked = self.Key + else: + self.ParentForm.LastButtonClicked = '' + self.ParentForm.FormRemainedOpen = True + _exit_mainloop(self.ParentForm) + # if self.ParentForm.CurrentlyRunningMainloop: + # Window._window_that_exited = self.ParentForm + # self.ParentForm.TKroot.quit() # kick the users out of the mainloop + + def get(self): + """ + Return the current chosen value showing in spinbox. + This value will be the same as what was provided as list of choices. If list items are ints, then the + item returned will be an int (not a string) + + :return: The currently visible entry + :rtype: (Any) + """ + value = self.TKStringVar.get() + for v in self.Values: + if str(v) == value: + value = v + break + return value + + Get = get + Update = update + + +Sp = Spin # type: Spin + + +# ---------------------------------------------------------------------- # +# Multiline # +# ---------------------------------------------------------------------- # +class Multiline(Element): + """ + Multiline Element - Display and/or read multiple lines of text. This is both an input and output element. + Other PySimpleGUI ports have a separate MultilineInput and MultilineOutput elements. May want to split this + one up in the future too. + """ + + def __init__(self, default_text='', enter_submits=False, disabled=False, autoscroll=False, border_width=None, + size=(None, None), s=(None, None), auto_size_text=None, background_color=None, text_color=None, change_submits=False, + enable_events=False, do_not_clear=True, key=None, k=None, write_only=False, auto_refresh=False, reroute_stdout=False, reroute_stderr=False, reroute_cprint=False, echo_stdout_stderr=False, focus=False, font=None, pad=None, p=None, tooltip=None, justification=None, no_scrollbar=False, expand_x=False, expand_y=False, rstrip=True, right_click_menu=None, visible=True, metadata=None): + """ + :param default_text: Initial text to show + :type default_text: (Any) + :param enter_submits: if True, the Window.Read call will return is enter key is pressed in this element + :type enter_submits: (bool) + :param disabled: set disable state + :type disabled: (bool) + :param autoscroll: If True the contents of the element will automatically scroll as more data added to the end + :type autoscroll: (bool) + :param border_width: width of border around element in pixels + :type border_width: (int) + :param size: (w, h) w=characters-wide, h=rows-high. If an int instead of a tuple is supplied, then height is auto-set to 1 + :type size: (int, int) | (None, None) | int + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param auto_size_text: if True will size the element to match the length of the text + :type auto_size_text: (bool) + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param change_submits: DO NOT USE. Only listed for backwards compat - Use enable_events instead + :type change_submits: (bool) + :param enable_events: Turns on the element specific events. Spin events happen when an item changes + :type enable_events: (bool) + :param do_not_clear: if False the element will be cleared any time the Window.Read call returns + :type do_not_clear: (bool) + :param key: Used with window.find_element and with return values to uniquely identify this element to uniquely identify this element + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param write_only: If True then no entry will be added to the values dictionary when the window is read + :type write_only: bool + :param auto_refresh: If True then anytime the element is updated, the window will be refreshed so that the change is immediately displayed + :type auto_refresh: (bool) + :param reroute_stdout: If True then all output to stdout will be output to this element + :type reroute_stdout: (bool) + :param reroute_stderr: If True then all output to stderr will be output to this element + :type reroute_stderr: (bool) + :param reroute_cprint: If True your cprint calls will output to this element. It's the same as you calling cprint_set_output_destination + :type reroute_cprint: (bool) + :param echo_stdout_stderr: If True then output to stdout and stderr will be output to this element AND also to the normal console location + :type echo_stdout_stderr: (bool) + :param focus: if True initial focus will go to this element + :type focus: (bool) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param justification: text justification. left, right, center. Can use single characters l, r, c. + :type justification: (str) + :param no_scrollbar: If False then a scrollbar will be shown (the default) + :type no_scrollbar: (bool) + :param expand_x: If True the element will automatically expand in the X direction to fill available space + :type expand_x: (bool) + :param expand_y: If True the element will automatically expand in the Y direction to fill available space + :type expand_y: (bool) + :param rstrip: If True the value returned in will have whitespace stripped from the right side + :type rstrip: (bool) + :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. + :type right_click_menu: List[List[ List[str] | str ]] + :param visible: set visibility state of the element + :type visible: (bool) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + + self.DefaultText = str(default_text) + self.EnterSubmits = enter_submits + bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR + self.Focus = focus + self.do_not_clear = do_not_clear + fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR + self.Autoscroll = autoscroll + self.Disabled = disabled + self.ChangeSubmits = change_submits or enable_events + self.RightClickMenu = right_click_menu + self.BorderWidth = border_width if border_width is not None else DEFAULT_BORDER_WIDTH + self.TagCounter = 0 + self.TKText = self.Widget = None # type: tkst.ScrolledText + self.tags = set() + self.WriteOnly = write_only + self.AutoRefresh = auto_refresh + key = key if key is not None else k + self.previous_stdout = None + self.previous_stderr = None + self.reroute_cprint = reroute_cprint + self.echo_stdout_stderr = echo_stdout_stderr + self.Justification = 'left' if justification is None else justification + self.justification_tag = self.just_center_tag = self.just_left_tag = self.just_right_tag = None + pad = pad if pad is not None else p + self.expand_x = expand_x + self.expand_y = expand_y + self.rstrip = rstrip + if reroute_stdout: + self.reroute_stdout_to_here() + if reroute_stderr: + self.reroute_stderr_to_here() + self.no_scrollbar = no_scrollbar + sz = size if size != (None, None) else s + + super().__init__(ELEM_TYPE_INPUT_MULTILINE, size=sz, auto_size_text=auto_size_text, background_color=bg, + text_color=fg, key=key, pad=pad, tooltip=tooltip, font=font or DEFAULT_FONT, visible=visible, metadata=metadata) + return + + def update(self, value=None, disabled=None, append=False, font=None, text_color=None, background_color=None, text_color_for_value=None, + background_color_for_value=None, visible=None, autoscroll=None, justification=None, font_for_value=None): + """ + Changes some of the settings for the Multiline Element. Must call `Window.Read` or `Window.Finalize` prior + :param value: new text to display + :type value: (Any) + :param disabled: disable or enable state of the element + :type disabled: (bool) + :param append: if True then new value will be added onto the end of the current value. if False then contents will be replaced. + :type append: (bool) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike for the entire element + :type font: (str or (str, int[, str]) or None) + :param text_color: color of the text + :type text_color: (str) + :param background_color: color of background + :type background_color: (str) + :param text_color_for_value: color of the new text being added (the value paramter) + :type text_color_for_value: (str) + :param background_color_for_value: color of the new background of the text being added (the value paramter) + :type background_color_for_value: (str) + :param visible: set visibility state of the element + :type visible: (bool) + :param autoscroll: if True then contents of element are scrolled down when new text is added to the end + :type autoscroll: (bool) + :param justification: text justification. left, right, center. Can use single characters l, r, c. Sets only for this value, not entire element + :type justification: (str) + :param font_for_value: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike for the value being updated + :type font_for_value: str | (str, int) + """ + + if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow + return + + if autoscroll is not None: + self.Autoscroll = autoscroll + + if justification is not None: + if justification.startswith('l'): + just_tag = 'left' + if justification.startswith('r'): + just_tag = 'right' + if justification.startswith('c'): + just_tag = 'center' + else: + just_tag = self.justification_tag + + starting_point = self.Widget.index(tk.INSERT) + tag = None + if value is not None: + value = str(value) + if background_color_for_value is not None or text_color_for_value is not None or font_for_value is not None: + try: + tag = 'Multiline(' + str(text_color_for_value) + ',' + str(background_color_for_value) + ',' + str(font_for_value) + ')' + if tag not in self.tags: + self.tags.add(tag) + if background_color_for_value is not None: + self.TKText.tag_configure(tag, background=background_color_for_value) + if text_color_for_value is not None: + self.TKText.tag_configure(tag, foreground=text_color_for_value) + if font_for_value is not None: + self.TKText.tag_configure(tag, font=font_for_value) + except Exception as e: + print('* Multiline.update - bad color likely specified:', e) + if self.Disabled: + self.TKText.configure(state='normal') + try: + if not append: + self.TKText.delete('1.0', tk.END) + if tag is not None or just_tag is not None: + self.TKText.insert(tk.END, value, (just_tag, tag)) + else: + self.TKText.insert(tk.END, value) + + # self.TKText.tag_add(just_tag, starting_point, starting_point) + + except Exception as e: + print("* Error setting multiline *", e) + if self.Disabled: + self.TKText.configure(state='disabled') + self.DefaultText = value + + if self.Autoscroll: + self.TKText.see(tk.END) + if disabled is True: + self.TKText.configure(state='disabled') + self.Disabled = True + elif disabled is False: + self.TKText.configure(state='normal') + self.Disabled = False + if background_color not in (None, COLOR_SYSTEM_DEFAULT): + self.TKText.configure(background=background_color) + if text_color not in (None, COLOR_SYSTEM_DEFAULT): + self.TKText.configure(fg=text_color) + if font is not None: + self.TKText.configure(font=font) + if visible is False: + self.TKText.pack_forget() + elif visible is True: + self.TKText.pack(padx=self.pad_used[0], pady=self.pad_used[1]) + + if self.AutoRefresh and self.ParentForm: + try: # in case the window was destroyed + self.ParentForm.refresh() + except: + pass + if visible is not None: + self._visible = visible + + def get(self): + """ + Return current contents of the Multiline Element + + :return: current contents of the Multiline Element (used as an input type of Multiline + :rtype: (str) + """ + value = str(self.TKText.get(1.0, tk.END)) + if self.rstrip: + return value.rstrip() + return value + + + def print(self, *args, end=None, sep=None, text_color=None, background_color=None, justification=None, font=None, colors=None, t=None, b=None, c=None, + autoscroll=True): + """ + Print like Python normally prints except route the output to a multiline element and also add colors if desired + + colors -(str, str) or str. A combined text/background color definition in a single parameter + + There are also "aliases" for text_color, background_color and colors (t, b, c) + t - An alias for color of the text (makes for shorter calls) + b - An alias for the background_color parameter + c - (str, str) - "shorthand" way of specifying color. (foreground, backgrouned) + c - str - can also be a string of the format "foreground on background" ("white on red") + + With the aliases it's possible to write the same print but in more compact ways: + cprint('This will print white text on red background', c=('white', 'red')) + cprint('This will print white text on red background', c='white on red') + cprint('This will print white text on red background', text_color='white', background_color='red') + cprint('This will print white text on red background', t='white', b='red') + + :param args: The arguments to print + :type args: (Any) + :param end: The end char to use just like print uses + :type end: (str) + :param sep: The separation character like print uses + :type sep: (str) + :param text_color: The color of the text + :type text_color: (str) + :param background_color: The background color of the line + :type background_color: (str) + :param justification: text justification. left, right, center. Can use single characters l, r, c. Sets only for this value, not entire element + :type justification: (str) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike for the args being printed + :type font: (str or (str, int[, str]) or None) + :param colors: Either a tuple or a string that has both the text and background colors. Or just the text color + :type colors: (str) or (str, str) + :param t: Color of the text + :type t: (str) + :param b: The background color of the line + :type b: (str) + :param c: Either a tuple or a string that has both the text and background colors or just tex color (same as the color parm) + :type c: (str) or (str, str) + :param autoscroll: If True the contents of the element will automatically scroll as more data added to the end + :type autoscroll: (bool) + """ + + kw_text_color = text_color or t + kw_background_color = background_color or b + dual_color = colors or c + try: + if isinstance(dual_color, tuple): + kw_text_color = dual_color[0] + kw_background_color = dual_color[1] + elif isinstance(dual_color, str): + if ' on ' in dual_color: # if has "on" in the string, then have both text and background + kw_text_color = dual_color.split(' on ')[0] + kw_background_color = dual_color.split(' on ')[1] + else: # if no "on" then assume the color string is just the text color + kw_text_color = dual_color + except Exception as e: + print('* multiline print warning * you messed up with color formatting', e) + + _print_to_element(self, *args, end=end, sep=sep, text_color=kw_text_color, background_color=kw_background_color, justification=justification, + autoscroll=autoscroll, font=font) + + def reroute_stdout_to_here(self): + """ + Sends stdout (prints) to this element + """ + self.previous_stdout = sys.stdout + sys.stdout = self + + def reroute_stderr_to_here(self): + """ + Sends stderr to this element + """ + self.previous_stderr = sys.stderr + sys.stderr = self + + def restore_stdout(self): + """ + Restore a previously re-reouted stdout back to the original destination + """ + if self.previous_stdout: + sys.stdout = self.previous_stdout + self.previous_stdout = None # indicate no longer routed here + + def restore_stderr(self): + """ + Restore a previously re-reouted stderr back to the original destination + """ + if self.previous_stderr: + sys.stderr = self.previous_stderr + self.previous_stderr = None # indicate no longer routed here + + def write(self, txt): + """ + Called by Python (not tkinter?) when stdout or stderr wants to write + + :param txt: text of output + :type txt: (str) + """ + try: + self.update(txt, append=True) + if self.echo_stdout_stderr: + self.previous_stdout.write(txt) + except: + pass + + def flush(self): + """ + Flush parameter was passed into a print statement. + For now doing nothing. Not sure what action should be taken to ensure a flush happens regardless. + """ + try: + self.previous_stdout.flush() + except: + pass + + def __del__(self): + """ + If this Widget is deleted, be sure and restore the old stdout, stderr + """ + # These trys are here because found that if the init fails, then + # the variables holding the old stdout won't exist and will get an error + try: + self.restore_stdout() + except Exception as e: + pass + try: + self.restore_stderr() + except: + pass + + Get = get + Update = update + + +ML = Multiline +MLine = Multiline + + +# ---------------------------------------------------------------------- # +# Text # +# ---------------------------------------------------------------------- # +class Text(Element): + """ + Text - Display some text in the window. Usually this means a single line of text. However, the text can also be multiple lines. If multi-lined there are no scroll bars. + """ + + def __init__(self, text='', size=(None, None), s=(None, None), auto_size_text=None, click_submits=False, enable_events=False, relief=None, font=None, + text_color=None, background_color=None, border_width=None, justification=None, pad=None, p=None, key=None, k=None, right_click_menu=None, expand_x=False, expand_y=False, grab=None, + tooltip=None, visible=True, metadata=None): + """ + :param text: The text to display. Can include /n to achieve multiple lines. Will convert (optional) parameter into a string + :type text: Any + :param size: (w, h) w=characters-wide, h=rows-high. If an int instead of a tuple is supplied, then height is auto-set to 1 + :type size: (int, int) | (int, None) | (None, None) | (int, ) | int + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (int, None) | (None, None) | (int, ) | int + :param auto_size_text: if True size of the Text Element will be sized to fit the string provided in 'text' parm + :type auto_size_text: (bool) + :param click_submits: DO NOT USE. Only listed for backwards compat - Use enable_events instead + :type click_submits: (bool) + :param enable_events: Turns on the element specific events. Text events happen when the text is clicked + :type enable_events: (bool) + :param relief: relief style around the text. Values are same as progress meter relief values. Should be a constant that is defined at starting with "RELIEF_" - `RELIEF_RAISED, RELIEF_SUNKEN, RELIEF_FLAT, RELIEF_RIDGE, RELIEF_GROOVE, RELIEF_SOLID` + :type relief: (str/enum) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param text_color: color of the text + :type text_color: (str) + :param background_color: color of background + :type background_color: (str) + :param border_width: number of pixels for the border (if using a relief) + :type border_width: (int) + :param justification: how string should be aligned within space provided by size. Valid choices = `left`, `right`, `center` + :type justification: (str) + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param key: Used with window.find_element and with return values to uniquely identify this element to uniquely identify this element + :type key: str or int or tuple or object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. + :type right_click_menu: List[List[ List[str] | str ]] + :param expand_x: If True the element will automatically expand in the X direction to fill available space + :type expand_x: (bool) + :param expand_y: If True the element will automatically expand in the Y direction to fill available space + :type expand_y: (bool) + :param grab: If True can grab this element and move the window around. Default is False + :type grab: (bool) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param visible: set visibility state of the element + :type visible: (bool) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + + self.DisplayText = str(text) + self.TextColor = text_color if text_color else DEFAULT_TEXT_COLOR + self.Justification = justification + self.Relief = relief + self.ClickSubmits = click_submits or enable_events + if background_color is None: + bg = DEFAULT_TEXT_ELEMENT_BACKGROUND_COLOR + else: + bg = background_color + self.RightClickMenu = right_click_menu + self.TKRightClickMenu = None + self.BorderWidth = border_width + self.Grab = grab + key = key if key is not None else k + sz = size if size != (None, None) else s + pad = pad if pad is not None else p + self.expand_x = expand_x + self.expand_y = expand_y + + super().__init__(ELEM_TYPE_TEXT, auto_size_text=auto_size_text, size=sz, background_color=bg, font=font if font else DEFAULT_FONT, + text_color=self.TextColor, pad=pad, key=key, tooltip=tooltip, visible=visible, metadata=metadata) + + def update(self, value=None, background_color=None, text_color=None, font=None, visible=None): + """ + Changes some of the settings for the Text Element. Must call `Window.Read` or `Window.Finalize` prior + :param value: new text to show + :type value: (str) + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param visible: set visibility state of the element + :type visible: (bool) + """ + + if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow + return + if value is not None: + self.DisplayText = str(value) + self.TKStringVar.set(str(value)) + if background_color not in (None, COLOR_SYSTEM_DEFAULT): + self.TKText.configure(background=background_color) + if text_color not in (None, COLOR_SYSTEM_DEFAULT): + self.TKText.configure(fg=text_color) + if font is not None: + self.TKText.configure(font=font) + if visible is False: + self.TKText.pack_forget() + elif visible is True: + self.TKText.pack(padx=self.pad_used[0], pady=self.pad_used[1]) + if visible is not None: + self._visible = visible + + def get(self): + """ + Gets the current value of the displayed text + + :return: The current value + :rtype: (str) + """ + try: + text = self.TKStringVar.get() + except: + text = '' + return text + + + @classmethod + def char_width_in_pixels(cls, font, character='W'): + """ + Get the with of the character "W" in pixels for the font being passed in or + the character of your choosing if "W" is not a good representative character. + Cannot be used until a window has been created. + If an error occurs, 0 will be returned + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike, to be measured + :type font: (str or (str, int[, str]) or None) + :param character: specifies a SINGLE CHARACTER character to measure + :type character: (str) + :return: Width in pixels of "A" + :rtype: (int) + """ + size = 0 + try: + size = tkinter.font.Font(font=font).measure(character) # single character width + except Exception as e: + print('Error retrieving font information', e) + return size + + @classmethod + def char_height_in_pixels(cls, font): + """ + Get the height of a string if using the supplied font in pixels. + Cannot be used until a window has been created. + If an error occurs, 0 will be returned + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike, to be measured + :type font: (str or (str, int[, str]) or None) + :return: Height in pixels of "A" + :rtype: (int) + """ + size = 0 + try: + size = tkinter.font.Font(font=font).metrics('linespace') + except Exception as e: + print('Error retrieving font information', e) + return size + + @classmethod + def string_width_in_pixels(cls, font, string): + """ + Get the with of the supplied string in pixels for the font being passed in. + Cannot be used until a window has been created. + If an error occurs, 0 will be returned + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike, to be measured + :type font: (str or (str, int[, str]) or None) + :param string: the string to measure + :type string: str + :return: Width in pixels of string + :rtype: (int) + """ + size = 0 + try: + size = tkinter.font.Font(font=font).measure(string) # string's width + except Exception as e: + print('Error retrieving font information', e) + return size + + Get = get + Update = update + + +# ------------------------- Text Element lazy functions ------------------------- # + +Txt = Text # type: Text +T = Text # type: Text + + +# ---------------------------------------------------------------------- # +# StatusBar # +# ---------------------------------------------------------------------- # +class StatusBar(Element): + """ + A StatusBar Element creates the sunken text-filled strip at the bottom. Many Windows programs have this line + """ + + def __init__(self, text, size=(None, None), s=(None, None), auto_size_text=None, click_submits=None, enable_events=False, + relief=RELIEF_SUNKEN, font=None, text_color=None, background_color=None, justification=None, pad=None, p=None, + key=None, k=None, right_click_menu=None, expand_x=False, expand_y=False, tooltip=None, visible=True, metadata=None): + """ + :param text: Text that is to be displayed in the widget + :type text: (str) + :param size: (w, h) w=characters-wide, h=rows-high. If an int instead of a tuple is supplied, then height is auto-set to 1 + :type size: (int, int) | (int, None) | int + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param auto_size_text: True if size should fit the text length + :type auto_size_text: (bool) + :param click_submits: DO NOT USE. Only listed for backwards compat - Use enable_events instead + :type click_submits: (bool) + :param enable_events: Turns on the element specific events. StatusBar events occur when the bar is clicked + :type enable_events: (bool) + :param relief: relief style. Values are same as progress meter relief values. Can be a constant or a string: `RELIEF_RAISED RELIEF_SUNKEN RELIEF_FLAT RELIEF_RIDGE RELIEF_GROOVE RELIEF_SOLID` + :type relief: (enum) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param text_color: color of the text + :type text_color: (str) + :param background_color: color of background + :type background_color: (str) + :param justification: how string should be aligned within space provided by size. Valid choices = `left`, `right`, `center` + :type justification: (str) + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param key: Used with window.find_element and with return values to uniquely identify this element to uniquely identify this element + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. + :type right_click_menu: List[List[ List[str] | str ]] + :param expand_x: If True the element will automatically expand in the X direction to fill available space + :type expand_x: (bool) + :param expand_y: If True the element will automatically expand in the Y direction to fill available space + :type expand_y: (bool) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param visible: set visibility state of the element + :type visible: (bool) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + + + self.DisplayText = text + self.TextColor = text_color if text_color else DEFAULT_TEXT_COLOR + self.Justification = justification + self.Relief = relief + self.ClickSubmits = click_submits or enable_events + if background_color is None: + bg = DEFAULT_TEXT_ELEMENT_BACKGROUND_COLOR + else: + bg = background_color + self.TKText = self.Widget = None # type: tk.Label + key = key if key is not None else k + self.RightClickMenu = right_click_menu + sz = size if size != (None, None) else s + pad = pad if pad is not None else p + self.expand_x = expand_x + self.expand_y = expand_y + + super().__init__(ELEM_TYPE_STATUSBAR, size=sz, auto_size_text=auto_size_text, background_color=bg, + font=font or DEFAULT_FONT, text_color=self.TextColor, pad=pad, key=key, tooltip=tooltip, + visible=visible, metadata=metadata) + return + + def update(self, value=None, background_color=None, text_color=None, font=None, visible=None): + """ + Changes some of the settings for the Status Bar Element. Must call `Window.Read` or `Window.Finalize` prior + :param value: new text to show + :type value: (str) + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param visible: set visibility state of the element + :type visible: (bool) + """ + + if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow + return + + if value is not None: + self.DisplayText = value + stringvar = self.TKStringVar + stringvar.set(value) + if background_color not in (None, COLOR_SYSTEM_DEFAULT): + self.TKText.configure(background=background_color) + if text_color not in (None, COLOR_SYSTEM_DEFAULT): + self.TKText.configure(fg=text_color) + if font is not None: + self.TKText.configure(font=font) + if visible is False: + self.TKText.pack_forget() + elif visible is True: + self.TKText.pack(padx=self.pad_used[0], pady=self.pad_used[1]) + if visible is not None: + self._visible = visible + + Update = update + + +SBar = StatusBar + + +# ---------------------------------------------------------------------- # +# TKProgressBar # +# Emulate the TK ProgressBar using canvas and rectangles +# ---------------------------------------------------------------------- # + +class TKProgressBar(): + uniqueness_counter = 0 + + def __init__(self, root, max, length=400, width=DEFAULT_PROGRESS_BAR_SIZE[1], ttk_theme=DEFAULT_TTK_THEME, style_name='', + relief=DEFAULT_PROGRESS_BAR_RELIEF, border_width=DEFAULT_PROGRESS_BAR_BORDER_WIDTH, + orientation='horizontal', BarColor=(None, None), key=None): + """ + :param root: The root window bar is to be shown in + :type root: tk.Tk | tk.TopLevel + :param max: Maximum value the bar will be measuring + :type max: (int) + :param length: length in pixels of the bar + :type length: (int) + :param width: width in pixels of the bar + :type width: (int) + :param style_name: Progress bar style to use. Set in the packer function + :type style_name: (str) + :param ttk_theme: Progress bar style defined as one of these 'default', 'winnative', 'clam', 'alt', 'classic', 'vista', 'xpnative' + :type ttk_theme: (str) + :param relief: relief style. Values are same as progress meter relief values. Can be a constant or a string: `RELIEF_RAISED RELIEF_SUNKEN RELIEF_FLAT RELIEF_RIDGE RELIEF_GROOVE RELIEF_SOLID` (Default value = DEFAULT_PROGRESS_BAR_RELIEF) + :type relief: (str) + :param border_width: The amount of pixels that go around the outside of the bar + :type border_width: (int) + :param orientation: 'horizontal' or 'vertical' ('h' or 'v' work) (Default value = 'vertical') + :type orientation: (str) + :param BarColor: The 2 colors that make up a progress bar. One is the background, the other is the bar + :type BarColor: (str, str) + :param key: Used with window.find_element and with return values to uniquely identify this element to uniquely identify this element + :type key: str | int | tuple | object + """ + + self.Length = length + self.Width = width + self.Max = max + self.Orientation = orientation + self.Count = None + self.PriorCount = 0 + self.style_name = style_name + + TKProgressBar.uniqueness_counter += 1 + + if orientation.lower().startswith('h'): + s = ttk.Style() + s.theme_use(ttk_theme) + + # self.style_name = str(key) + str(TKProgressBar.uniqueness_counter) + "my.Horizontal.TProgressbar" + if BarColor != COLOR_SYSTEM_DEFAULT and BarColor[0] != COLOR_SYSTEM_DEFAULT: + s.configure(self.style_name, background=BarColor[0], troughcolor=BarColor[1], + troughrelief=relief, borderwidth=border_width, thickness=width) + else: + s.configure(self.style_name, troughrelief=relief, borderwidth=border_width, thickness=width) + + self.TKProgressBarForReal = ttk.Progressbar(root, maximum=self.Max, style=self.style_name, length=length, orient=tk.HORIZONTAL, mode='determinate') + else: + s = ttk.Style() + s.theme_use(ttk_theme) + # self.style_name = str(key) + str(TKProgressBar.uniqueness_counter) + "my.Vertical.TProgressbar" + if BarColor != COLOR_SYSTEM_DEFAULT and BarColor[0] != COLOR_SYSTEM_DEFAULT: + + s.configure(self.style_name, background=BarColor[0], + troughcolor=BarColor[1], troughrelief=relief, borderwidth=border_width, thickness=width) + else: + s.configure(self.style_name, troughrelief=relief, borderwidth=border_width, thickness=width) + + self.TKProgressBarForReal = ttk.Progressbar(root, maximum=self.Max, style=self.style_name, length=length, orient=tk.VERTICAL, mode='determinate') + + def Update(self, count=None, max=None): + """ + Update the current value of the bar and/or update the maximum value the bar can reach + :param count: current value + :type count: (int) + :param max: the maximum value + :type max: (int) + """ + if max is not None: + self.Max = max + try: + self.TKProgressBarForReal.config(maximum=max) + except: + return False + if count is not None: + try: + self.TKProgressBarForReal['value'] = count + except: + return False + return True + + +# ---------------------------------------------------------------------- # +# TKOutput # +# New Type of TK Widget that's a Text Widget in disguise # +# Note that it's inherited from the TKFrame class so that the # +# Scroll bar will span the length of the frame # +# ---------------------------------------------------------------------- # +class TKOutput(tk.Frame): + """ + tkinter style class. Inherits Frame class from tkinter. Adds a tk.Text and a scrollbar together. + Note - This is NOT a user controlled class. Users should NOT be directly using it unless making an extention + to PySimpleGUI by directly manipulating tkinter. + """ + + def __init__(self, parent, width, height, bd, background_color=None, text_color=None, echo_stdout_stderr=False, font=None, pad=None): + """ + :param parent: The "Root" that the Widget will be in + :type parent: tk.Tk | tk.Toplevel + :param width: Width in characters + :type width: (int) + :param height: height in rows + :type height: (int) + :param bd: Border Depth. How many pixels of border to show + :type bd: (int) + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param echo_stdout_stderr: If True then output to stdout will be output to this element AND also to the normal console location + :type echo_stdout_stderr: (bool) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + """ + self.frame = tk.Frame(parent) + tk.Frame.__init__(self, self.frame) + self.output = tk.Text(self.frame, width=width, height=height, bd=bd, font=font) + if background_color and background_color != COLOR_SYSTEM_DEFAULT: + self.output.configure(background=background_color) + self.frame.configure(background=background_color) + if text_color and text_color != COLOR_SYSTEM_DEFAULT: + self.output.configure(fg=text_color) + self.output.configure(insertbackground=text_color) + self.vsb = tk.Scrollbar(self.frame, orient="vertical", command=self.output.yview) + self.output.configure(yscrollcommand=self.vsb.set) + self.output.pack(side="left", fill="both", expand=True) + self.vsb.pack(side="left", fill="y", expand=False) + self.frame.pack(side="left", padx=pad[0], pady=pad[1], expand=True, fill='y') + self.previous_stdout = sys.stdout + self.previous_stderr = sys.stderr + self.parent = parent + self.echo_stdout_stderr = echo_stdout_stderr + + sys.stdout = self + sys.stderr = self + self.pack() + + def write(self, txt): + """ + Called by Python (not tkinter?) when stdout or stderr wants to write + Refreshes the window after the write so that the change is immediately displayed + + :param txt: text of output + :type txt: (str) + """ + try: + self.output.insert(tk.END, str(txt)) + self.output.see(tk.END) + self.parent.update() + except: + pass + + try: + if self.echo_stdout_stderr: + self.previous_stdout.write(txt) + except: + pass + + def Close(self): + """ + Called when wanting to restore the old stdout/stderr + """ + sys.stdout = self.previous_stdout + sys.stderr = self.previous_stderr + + def flush(self): + """ + Flush parameter was passed into a print statement. + For now doing nothing. Not sure what action should be taken to ensure a flush happens regardless. + """ + try: + if self.echo_stdout_stderr: + self.previous_stdout.flush() + except: + pass + + def __del__(self): + """ + If this Widget is deleted, be sure and restore the old stdout, stderr + """ + sys.stdout = self.previous_stdout + sys.stderr = self.previous_stderr + + +# ---------------------------------------------------------------------- # +# Output # +# Routes stdout, stderr to a scrolled window # +# ---------------------------------------------------------------------- # +class Output(Element): + """ + Output Element - a multi-lined text area where stdout and stderr are re-routed to. + + The Multiline Element is the superior and recommended method for showing the output of stdout. + The Multiline Element has been added to significantly while the Output element has not. + + Of course, Output Element continues to operate and be backwards compatible, but you're missing out on + features such as routing the cprint output to the element. + """ + + def __init__(self, size=(None, None), s=(None, None), background_color=None, text_color=None, pad=None, p=None, echo_stdout_stderr=False, font=None, tooltip=None, + key=None, k=None, right_click_menu=None, expand_x=False, expand_y=False, visible=True, metadata=None): + """ + :param size: (w, h) w=characters-wide, h=rows-high. If an int instead of a tuple is supplied, then height is auto-set to 1 + :type size: (int, int) | (None, None) | int + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param echo_stdout_stderr: If True then output to stdout will be output to this element AND also to the normal console location + :type echo_stdout_stderr: (bool) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param key: Used with window.find_element and with return values to uniquely identify this element to uniquely identify this element + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. + :type right_click_menu: List[List[ List[str] | str ]] + :param expand_x: If True the element will automatically expand in the X direction to fill available space + :type expand_x: (bool) + :param expand_y: If True the element will automatically expand in the Y direction to fill available space + :type expand_y: (bool) + :param visible: set visibility state of the element + :type visible: (bool) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + + self._TKOut = self.Widget = None # type: TKOutput + bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR + fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR + self.RightClickMenu = right_click_menu + key = key if key is not None else k + self.echo_stdout_stderr = echo_stdout_stderr + sz = size if size != (None, None) else s + pad = pad if pad is not None else p + self.expand_x = expand_x + self.expand_y = expand_y + + super().__init__(ELEM_TYPE_OUTPUT, size=sz, background_color=bg, text_color=fg, pad=pad, font=font, + tooltip=tooltip, key=key, visible=visible, metadata=metadata) + + @property + def tk_out(self): + """ + Returns the TKOutput object used to create the element + + :return: The TKOutput object + :rtype: (TKOutput) + """ + if self._TKOut is None: + print('*** Did you forget to call Finalize()? Your code should look something like: ***') + print('*** form = sg.Window("My Form").Layout(layout).Finalize() ***') + return self._TKOut + + def update(self, value=None, visible=None): + """ + Changes some of the settings for the Output Element. Must call `Window.Read` or `Window.Finalize` prior + + :param value: string that will replace current contents of the output area + :type value: (str) + :param visible: control visibility of element + :type visible: (bool) + """ + if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow + return + + if value is not None: + self._TKOut.output.delete('1.0', tk.END) + self._TKOut.output.insert(tk.END, value) + if visible is False: + self._TKOut.frame.pack_forget() + elif visible is True: + self._TKOut.frame.pack(padx=self.pad_used[0], pady=self.pad_used[1]) + if visible is not None: + self._visible = visible + + def get(self): + """ + Returns the current contents of the output. Similar to Get method other Elements + :return: the current value of the output + :rtype: (str) + """ + return self._TKOut.output.get(1.0, tk.END) + + def expand(self, expand_x=False, expand_y=False, expand_row=True): + """ + Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions + + :param expand_x: If True Element will expand in the Horizontal directions + :type expand_x: (bool) + :param expand_y: If True Element will expand in the Vertical directions + :type expand_y: (bool) + """ + + if expand_x and expand_y: + fill = tk.BOTH + elif expand_x: + fill = tk.X + elif expand_y: + fill = tk.Y + else: + return + + self._TKOut.output.pack(expand=True, fill=fill) + self._TKOut.frame.pack(expand=True, fill=fill) + self.ParentRowFrame.pack(expand=expand_row, fill=fill) + + def __del__(self): + """ + Delete this element. Normally Elements do not have their delete method specified, but for this one + it's important that the underlying TKOut object get deleted so that the stdout will get restored properly + """ + self._TKOut.__del__() + + TKOut = tk_out + Update = update + Get = get + + +# ---------------------------------------------------------------------- # +# Button Class # +# ---------------------------------------------------------------------- # +class Button(Element): + """ + Button Element - Defines all possible buttons. The shortcuts such as Submit, FileBrowse, ... each create a Button + """ + + def __init__(self, button_text='', button_type=BUTTON_TYPE_READ_FORM, target=(None, None), tooltip=None, + file_types=FILE_TYPES_ALL_FILES, initial_folder=None, default_extension='', disabled=False, change_submits=False, + enable_events=False, image_filename=None, image_data=None, image_size=(None, None), + image_subsample=None, border_width=None, size=(None, None), s=(None, None), auto_size_button=None, button_color=None, + disabled_button_color=None, + highlight_colors=None, mouseover_colors=(None, None), use_ttk_buttons=None, font=None, bind_return_key=False, focus=False, pad=None, p=None, key=None, + k=None, right_click_menu=None, expand_x=False, expand_y=False, visible=True, metadata=None): + """ + :param button_text: Text to be displayed on the button + :type button_text: (str) + :param button_type: You should NOT be setting this directly. ONLY the shortcut functions set this + :type button_type: (int) + :param target: key or (row,col) target for the button. Note that -1 for column means 1 element to the left of this one. The constant ThisRow is used to indicate the current row. The Button itself is a valid target for some types of button + :type target: str | (int, int) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param file_types: the filetypes that will be used to match files. To indicate all files: (("ALL Files", "*.* *"),). Note - NOT SUPPORTED ON MAC + :type file_types: Tuple[(str, str), ...] + :param initial_folder: starting path for folders and files + :type initial_folder: (str) + :param default_extension: If no extension entered by user, add this to filename (only used in saveas dialogs) + :type default_extension: (str) + :param disabled: If True button will be created disabled. If BUTTON_DISABLED_MEANS_IGNORE then the button will be ignored rather than disabled using tkinter + :type disabled: (bool | str) + :param change_submits: DO NOT USE. Only listed for backwards compat - Use enable_events instead + :type change_submits: (bool) + :param enable_events: Turns on the element specific events. If this button is a target, should it generate an event when filled in + :type enable_events: (bool) + :param image_filename: image filename if there is a button image. GIFs and PNGs only. + :type image_filename: (str) + :param image_data: Raw or Base64 representation of the image to put on button. Choose either filename or data + :type image_data: bytes | str + :param image_size: Size of the image in pixels (width, height) + :type image_size: (int, int) + :param image_subsample: amount to reduce the size of the image. Divides the size by this number. 2=1/2, 3=1/3, 4=1/4, etc + :type image_subsample: (int) + :param border_width: width of border around button in pixels + :type border_width: (int) + :param size: (w, h) w=characters-wide, h=rows-high. If an int instead of a tuple is supplied, then height is auto-set to 1 + :type size: (int, int) | (None, None) | int + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param auto_size_button: if True the button size is sized to fit the text + :type auto_size_button: (bool) + :param button_color: Color of button. default is from theme or the window. Easy to remember which is which if you say "ON" between colors. "red" on "green". Normally a tuple, but can be a simplified-button-color-string "foreground on background". Can be a single color if want to set only the background. + :type button_color: (str, str) | str | (int, int) | None + :param disabled_button_color: colors to use when button is disabled (text, background). Use None for a color if don't want to change. Only ttk buttons support both text and background colors. tk buttons only support changing text color + :type disabled_button_color: (str, str) | str + :param highlight_colors: colors to use when button has focus (has focus, does not have focus). None will use colors based on theme. Only used by Linux and only for non-TTK button + :type highlight_colors: (str, str) + :param mouseover_colors: Important difference between Linux & Windows! Linux - Colors when mouse moved over button. Windows - colors when button is pressed. The default is to switch the text and background colors (an inverse effect) + :type mouseover_colors: (str, str) | str + :param use_ttk_buttons: True = use ttk buttons. False = do not use ttk buttons. None (Default) = use ttk buttons only if on a Mac and not with button images + :type use_ttk_buttons: (bool) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param bind_return_key: If True the return key will cause this button to be pressed + :type bind_return_key: (bool) + :param focus: if True, initial focus will be put on this button + :type focus: (bool) + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param key: Used with window.find_element and with return values to uniquely identify this element to uniquely identify this element + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. + :type right_click_menu: List[List[ List[str] | str ]] + :param expand_x: If True the element will automatically expand in the X direction to fill available space + :type expand_x: (bool) + :param expand_y: If True the element will automatically expand in the Y direction to fill available space + :type expand_y: (bool) + :param visible: set visibility state of the element + :type visible: (bool) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + + + self.AutoSizeButton = auto_size_button + self.BType = button_type + self.FileTypes = file_types + self.Widget = self.TKButton = None # type: tk.Button + self.Target = target + self.ButtonText = str(button_text) + self.RightClickMenu = right_click_menu + # Button colors can be a tuple (text, background) or a string with format "text on background" + # bc = button_color + # if button_color is None: + # bc = DEFAULT_BUTTON_COLOR + # else: + # try: + # if isinstance(button_color,str): + # bc = button_color.split(' on ') + # except Exception as e: + # print('* cprint warning * you messed up with color formatting', e) + # if bc[1] is None: + # bc = (bc[0], theme_button_color()[1]) + # self.ButtonColor = bc + self.ButtonColor = button_color_to_tuple(button_color) + + # experimental code to compute disabled button text color + # if disabled_button_color is None: + # try: + # disabled_button_color = (get_complimentary_hex(theme_button_color()[0]), theme_button_color()[1]) + # # disabled_button_color = disabled_button_color + # except: + # print('* Problem computing disabled button color *') + self.DisabledButtonColor = button_color_to_tuple(disabled_button_color) if disabled_button_color is not None else (None, None) + self.ImageFilename = image_filename + self.ImageData = image_data + self.ImageSize = image_size + self.ImageSubsample = image_subsample + self.UserData = None + self.BorderWidth = border_width if border_width is not None else DEFAULT_BORDER_WIDTH + self.BindReturnKey = bind_return_key + self.Focus = focus + self.TKCal = None + self.calendar_default_date_M_D_Y = (None, None, None) + self.calendar_close_when_chosen = False + self.calendar_locale = None + self.calendar_format = None + self.calendar_location = (None, None) + self.calendar_no_titlebar = True + self.calendar_begin_at_sunday_plus = 0 + self.calendar_month_names = None + self.calendar_day_abbreviations = None + self.calendar_title = '' + self.calendar_selection = '' + self.InitialFolder = initial_folder + self.DefaultExtension = default_extension + self.Disabled = disabled + self.ChangeSubmits = change_submits or enable_events + self.UseTtkButtons = use_ttk_buttons + self.ttk_style_name = '' # set in the packer function + self._files_delimiter = BROWSE_FILES_DELIMITER # used by the file browse button. used when multiple files are selected by user + if use_ttk_buttons is None and running_mac(): + self.UseTtkButtons = True + # if image_filename or image_data: + # self.UseTtkButtons = False # if an image is to be displayed, then force the button to not be a TTK Button + if key is None and k is None: + _key = self.ButtonText + else: + _key = key if key is not None else k + if highlight_colors is not None: + self.HighlightColors = highlight_colors + else: + self.HighlightColors = self._compute_highlight_colors() + + if mouseover_colors != (None, None): + self.MouseOverColors = button_color_to_tuple(mouseover_colors) + elif button_color != None: + self.MouseOverColors = (self.ButtonColor[1], self.ButtonColor[0]) + else: + self.MouseOverColors = (theme_button_color()[1], theme_button_color()[0]) + pad = pad if pad is not None else p + self.expand_x = expand_x + self.expand_y = expand_y + + sz = size if size != (None, None) else s + super().__init__(ELEM_TYPE_BUTTON, size=sz, font=font, pad=pad, key=_key, tooltip=tooltip, visible=visible, metadata=metadata) + return + + def _compute_highlight_colors(self): + """ + Determines the color to use to indicate the button has focus. This setting is only used by Linux. + :return: Pair of colors. (Highlight, Highlight Background) + :rtype: (str, str) + """ + highlight_color = highlight_background = COLOR_SYSTEM_DEFAULT + if self.ButtonColor != COLOR_SYSTEM_DEFAULT and theme_background_color() != COLOR_SYSTEM_DEFAULT: + highlight_background = theme_background_color() + if self.ButtonColor != COLOR_SYSTEM_DEFAULT and self.ButtonColor[0] != COLOR_SYSTEM_DEFAULT: + if self.ButtonColor[0] != theme_background_color(): + highlight_color = self.ButtonColor[0] + else: + highlight_color = 'red' + return (highlight_color, highlight_background) + + # Realtime button release callback + + def ButtonReleaseCallBack(self, parm): + """ + Not a user callable function. Called by tkinter when a "realtime" button is released + + :param parm: the event info from tkinter + :type parm: + + """ + self.LastButtonClickedWasRealtime = False + self.ParentForm.LastButtonClicked = None + + # Realtime button callback + def ButtonPressCallBack(self, parm): + """ + Not a user callable method. Callback called by tkinter when a "realtime" button is pressed + + :param parm: Event info passed in by tkinter + :type parm: + + """ + self.ParentForm.LastButtonClickedWasRealtime = True + if self.Key is not None: + self.ParentForm.LastButtonClicked = self.Key + else: + self.ParentForm.LastButtonClicked = self.ButtonText + # if self.ParentForm.CurrentlyRunningMainloop: + # Window._window_that_exited = self.ParentForm + # self.ParentForm.TKroot.quit() # kick out of loop if read was called + _exit_mainloop(self.ParentForm) + + def _find_target(self): + target = self.Target + target_element = None + if target[0] == ThisRow: + target = [self.Position[0], target[1]] + if target[1] < 0: + target[1] = self.Position[1] + target[1] + strvar = None + should_submit_window = False + if target == (None, None): + strvar = self.TKStringVar + else: + if not isinstance(target, str): + if target[0] < 0: + target = [self.Position[0] + target[0], target[1]] + target_element = self.ParentContainer._GetElementAtLocation(target) + else: + target_element = self.ParentForm.find_element(target) + try: + strvar = target_element.TKStringVar + except: + pass + try: + if target_element.ChangeSubmits: + should_submit_window = True + except: + pass + return target_element, strvar, should_submit_window + + # ------- Button Callback ------- # + def ButtonCallBack(self): + """ + Not user callable! Called by tkinter when a button is clicked. This is where all the fun begins! + """ + # global _my_windows + + # print('Button callback') + + # Button Callback - Parent = {self.ParentForm} Position = {self.Position}') + # Buttons modify targets or return from the form + # If modifying target, get the element object at the target and modify its StrVar + # target = self.Target + # target_element = None + # if target[0] == ThisRow: + # target = [self.Position[0], target[1]] + # if target[1] < 0: + # target[1] = self.Position[1] + target[1] + # strvar = None + # should_submit_window = False + # if target == (None, None): + # strvar = self.TKStringVar + # else: + # if not isinstance(target, str): + # if target[0] < 0: + # target = [self.Position[0] + target[0], target[1]] + # target_element = self.ParentContainer._GetElementAtLocation(target) + # else: + # target_element = self.ParentForm.find_element(target) + # try: + # strvar = target_element.TKStringVar + # except: + # pass + # try: + # if target_element.ChangeSubmits: + # should_submit_window = True + # except: + # pass + + if self.Disabled == BUTTON_DISABLED_MEANS_IGNORE: + return + target_element, strvar, should_submit_window = self._find_target() + + filetypes = FILE_TYPES_ALL_FILES if self.FileTypes is None else self.FileTypes + + if self.BType == BUTTON_TYPE_BROWSE_FOLDER: + if running_mac(): # macs don't like seeing the parent window (go firgure) + folder_name = tk.filedialog.askdirectory(initialdir=self.InitialFolder) # show the 'get folder' dialog box + else: + folder_name = tk.filedialog.askdirectory(initialdir=self.InitialFolder, parent=self.ParentForm.TKroot) # show the 'get folder' dialog box + if folder_name: + try: + strvar.set(folder_name) + self.TKStringVar.set(folder_name) + except: + pass + elif self.BType == BUTTON_TYPE_BROWSE_FILE: + if running_mac(): + file_name = tk.filedialog.askopenfilename(initialdir=self.InitialFolder) # show the 'get file' dialog box + else: + file_name = tk.filedialog.askopenfilename(filetypes=filetypes, + initialdir=self.InitialFolder, parent=self.ParentForm.TKroot) # show the 'get file' dialog box + if file_name: + strvar.set(file_name) + self.TKStringVar.set(file_name) + elif self.BType == BUTTON_TYPE_COLOR_CHOOSER: + color = tk.colorchooser.askcolor(parent=self.ParentForm.TKroot) # show the 'get file' dialog box + color = color[1] # save only the #RRGGBB portion + strvar.set(color) + self.TKStringVar.set(color) + elif self.BType == BUTTON_TYPE_BROWSE_FILES: + if running_mac(): + file_name = tk.filedialog.askopenfilenames(initialdir=self.InitialFolder) + else: + file_name = tk.filedialog.askopenfilenames(filetypes=filetypes, initialdir=self.InitialFolder, parent=self.ParentForm.TKroot) + if file_name: + file_name = self._files_delimiter.join(file_name) # normally a ';' + strvar.set(file_name) + self.TKStringVar.set(file_name) + elif self.BType == BUTTON_TYPE_SAVEAS_FILE: + # show the 'get file' dialog box + if running_mac(): + file_name = tk.filedialog.asksaveasfilename(defaultextension=self.DefaultExtension, initialdir=self.InitialFolder) + else: + file_name = tk.filedialog.asksaveasfilename(filetypes=filetypes, defaultextension=self.DefaultExtension, initialdir=self.InitialFolder, + parent=self.ParentForm.TKroot) + if file_name: + strvar.set(file_name) + self.TKStringVar.set(file_name) + elif self.BType == BUTTON_TYPE_CLOSES_WIN: # this is a return type button so GET RESULTS and destroy window + # first, get the results table built + # modify the Results table in the parent FlexForm object + if self.Key is not None: + self.ParentForm.LastButtonClicked = self.Key + else: + self.ParentForm.LastButtonClicked = self.ButtonText + self.ParentForm.FormRemainedOpen = False + self.ParentForm._Close() + _exit_mainloop(self.ParentForm) + + if self.ParentForm.NonBlocking: + self.ParentForm.TKroot.destroy() + Window._DecrementOpenCount() + elif self.BType == BUTTON_TYPE_READ_FORM: # LEAVE THE WINDOW OPEN!! DO NOT CLOSE + # This is a PLAIN BUTTON + # first, get the results table built + # modify the Results table in the parent FlexForm object + if self.Key is not None: + self.ParentForm.LastButtonClicked = self.Key + else: + self.ParentForm.LastButtonClicked = self.ButtonText + self.ParentForm.FormRemainedOpen = True + _exit_mainloop(self.ParentForm) + elif self.BType == BUTTON_TYPE_CLOSES_WIN_ONLY: # special kind of button that does not exit main loop + self.ParentForm._Close(without_event=True) + self.ParentForm.TKroot.destroy() # close the window with tkinter + Window._DecrementOpenCount() + elif self.BType == BUTTON_TYPE_CALENDAR_CHOOSER: # this is a return type button so GET RESULTS and destroy window + # ------------ new chooser code ------------- + self.ParentForm.LastButtonClicked = self.Key # key should have been generated already if not set by user + self.ParentForm.FormRemainedOpen = True + should_submit_window = False + _exit_mainloop(self.ParentForm) + # elif self.BType == BUTTON_TYPE_SHOW_DEBUGGER: + # **** DEPRICATED ***** + # if self.ParentForm.DebuggerEnabled: + # show_debugger_popout_window() + + if should_submit_window: + self.ParentForm.LastButtonClicked = target_element.Key + self.ParentForm.FormRemainedOpen = True + _exit_mainloop(self.ParentForm) + + return + + def update(self, text=None, button_color=(None, None), disabled=None, image_data=None, image_filename=None, + visible=None, image_subsample=None, disabled_button_color=(None, None), image_size=None): + """ + Changes some of the settings for the Button Element. Must call `Window.Read` or `Window.Finalize` prior + :param text: sets button text + :type text: (str) + :param button_color: Color of button. default is from theme or the window. Easy to remember which is which if you say "ON" between colors. "red" on "green". Normally a tuple, but can be a simplified-button-color-string "foreground on background". Can be a single color if want to set only the background. + :type button_color: (str, str) | str | (int, int) | None + :param disabled: True/False to enable/disable at the GUI level. Use BUTTON_DISABLED_MEANS_IGNORE to ignore clicks (won't change colors) + :type disabled: (bool | str) + :param image_data: Raw or Base64 representation of the image to put on button. Choose either filename or data + :type image_data: bytes | str + :param image_filename: image filename if there is a button image. GIFs and PNGs only. + :type image_filename: (str) + :param disabled_button_color: colors to use when button is disabled (text, background). Use None for a color if don't want to change. Only ttk buttons support both text and background colors. tk buttons only support changing text color + :type disabled_button_color: (str, str) + :param visible: control visibility of element + :type visible: (bool) + :param image_subsample: amount to reduce the size of the image. Divides the size by this number. 2=1/2, 3=1/3, 4=1/4, etc + :type image_subsample: (int) + :param image_size: Size of the image in pixels (width, height) + :type image_size: (int, int) + """ + + if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow + return + + if self.UseTtkButtons: + style_name = self.ttk_style_name # created when made initial window (in the pack) + # style_name = str(self.Key) + 'custombutton.TButton' + button_style = ttk.Style() + if text is not None: + self.TKButton.configure(text=text) + self.ButtonText = text + if button_color != (None, None) and button_color != COLOR_SYSTEM_DEFAULT: + bc = button_color_to_tuple(button_color, self.ButtonColor) + # if isinstance(button_color, str): + # try: + # button_color = button_color.split(' on ') + # except Exception as e: + # print('** Error in formatting your button color **', button_color, e) + if self.UseTtkButtons: + if bc[0] not in (None, COLOR_SYSTEM_DEFAULT): + button_style.configure(style_name, foreground=bc[0]) + if bc[1] not in (None, COLOR_SYSTEM_DEFAULT): + button_style.configure(style_name, background=bc[1]) + else: + if bc[0] not in (None, COLOR_SYSTEM_DEFAULT): + self.TKButton.config(foreground=bc[0], activeforeground=bc[0]) + if bc[1] not in (None, COLOR_SYSTEM_DEFAULT): + self.TKButton.config(background=bc[1], activebackground=bc[1]) + self.ButtonColor = bc + if disabled is True: + self.TKButton['state'] = 'disabled' + self.Disabled = True + elif disabled is False: + self.TKButton['state'] = 'normal' + self.Disabled = False + elif disabled == BUTTON_DISABLED_MEANS_IGNORE: + self.TKButton['state'] = 'normal' + self.Disabled = BUTTON_DISABLED_MEANS_IGNORE + if image_data is not None: + image = tk.PhotoImage(data=image_data) + if image_subsample: + image = image.subsample(image_subsample) + if image_size is not None: + width, height = image_size + else: + width, height = image.width(), image.height() + if self.UseTtkButtons: + button_style.configure(style_name, image=image, width=width, height=height) + else: + self.TKButton.config(image=image, width=width, height=height) + self.TKButton.image = image + if image_filename is not None: + image = tk.PhotoImage(file=image_filename) + if image_subsample: + image = image.subsample(image_subsample) + if image_size is not None: + width, height = image_size + else: + width, height = image.width(), image.height() + if self.UseTtkButtons: + button_style.configure(style_name, image=image, width=width, height=height) + else: + self.TKButton.config(highlightthickness=0, image=image, width=width, height=height) + self.TKButton.image = image + if visible is False: + self.TKButton.pack_forget() + elif visible is True: + self.TKButton.pack(padx=self.pad_used[0], pady=self.pad_used[1]) + if disabled_button_color != (None, None) and disabled_button_color != COLOR_SYSTEM_DEFAULT: + if not self.UseTtkButtons: + self.TKButton['disabledforeground'] = disabled_button_color[0] + else: + if disabled_button_color[0] is not None: + button_style.map(style_name, foreground=[('disabled', disabled_button_color[0])]) + if disabled_button_color[1] is not None: + button_style.map(style_name, background=[('disabled', disabled_button_color[1])]) + self.DisabledButtonColor = (disabled_button_color[0] if disabled_button_color[0] is not None else self.DisabledButtonColor[0], + disabled_button_color[1] if disabled_button_color[1] is not None else self.DisabledButtonColor[1]) + + if visible is not None: + self._visible = visible + + def get_text(self): + """ + Returns the current text shown on a button + + :return: The text currently displayed on the button + :rtype: (str) + """ + return self.ButtonText + + def click(self): + """ + Generates a click of the button as if the user clicked the button + Calls the tkinter invoke method for the button + """ + try: + self.TKButton.invoke() + except: + print('Exception clicking button') + + Click = click + GetText = get_text + Update = update + + +# ------------------------- Button lazy functions ------------------------- # +B = Button +Btn = Button + + +# ---------------------------------------------------------------------- # +# ButtonMenu Class # +# ---------------------------------------------------------------------- # +class ButtonMenu(Element): + """ + The Button Menu Element. Creates a button that when clicked will show a menu similar to right click menu + """ + + def __init__(self, button_text, menu_def, tooltip=None, disabled=False, + image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, border_width=None, + size=(None, None), s=(None, None), auto_size_button=None, button_color=None, text_color=None, background_color=None, disabled_text_color=None, + font=None, item_font=None, pad=None, p=None, expand_x=False, expand_y=False, key=None, k=None, tearoff=False, visible=True, metadata=None): + """ + :param button_text: Text to be displayed on the button + :type button_text: (str) + :param menu_def: A list of lists of Menu items to show when this element is clicked. See docs for format as they are the same for all menu types + :type menu_def: List[List[str]] + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param disabled: If True button will be created disabled + :type disabled: (bool) + :param image_filename: image filename if there is a button image. GIFs and PNGs only. + :type image_filename: (str) + :param image_data: Raw or Base64 representation of the image to put on button. Choose either filename or data + :type image_data: bytes | str + :param image_size: Size of the image in pixels (width, height) + :type image_size: (int, int) + :param image_subsample: amount to reduce the size of the image. Divides the size by this number. 2=1/2, 3=1/3, 4=1/4, etc + :type image_subsample: (int) + :param border_width: width of border around button in pixels + :type border_width: (int) + :param size: (w, h) w=characters-wide, h=rows-high. If an int instead of a tuple is supplied, then height is auto-set to 1 + :type size: (int, int) | (None, None) | int + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param auto_size_button: if True the button size is sized to fit the text + :type auto_size_button: (bool) + :param button_color: of button. Easy to remember which is which if you say "ON" between colors. "red" on "green" + :type button_color: (str, str) or str + :param background_color: color of the background + :type background_color: (str) + :param text_color: element's text color. Can be in #RRGGBB format or a color name "black" + :type text_color: (str) + :param disabled_text_color: color to use for text when item is disabled. Can be in #RRGGBB format or a color name "black" + :type disabled_text_color: (str) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param item_font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike, for the menu items + :type item_font: (str or (str, int[, str]) or None) + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param expand_x: If True the element will automatically expand in the X direction to fill available space + :type expand_x: (bool) + :param expand_y: If True the element will automatically expand in the Y direction to fill available space + :type expand_y: (bool) + :param key: Used with window.find_element and with return values to uniquely identify this element to uniquely identify this element + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param tearoff: Determines if menus should allow them to be torn off + :type tearoff: (bool) + :param visible: set visibility state of the element + :type visible: (bool) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + + self.MenuDefinition = copy.deepcopy(menu_def) + + self.AutoSizeButton = auto_size_button + self.ButtonText = button_text + self.ButtonColor = button_color_to_tuple(button_color) + # self.TextColor = self.ButtonColor[0] + # self.BackgroundColor = self.ButtonColor[1] + self.BackgroundColor = background_color if background_color is not None else theme_input_background_color() + self.TextColor = text_color if text_color is not None else theme_input_text_color() + self.DisabledTextColor = disabled_text_color if disabled_text_color is not None else COLOR_SYSTEM_DEFAULT + self.ItemFont = item_font + self.BorderWidth = border_width if border_width is not None else DEFAULT_BORDER_WIDTH + self.ImageFilename = image_filename + self.ImageData = image_data + self.ImageSize = image_size + self.ImageSubsample = image_subsample + self.Disabled = disabled + self.IsButtonMenu = True + self.MenuItemChosen = None + self.Widget = self.TKButtonMenu = None # type: tk.Menubutton + self.TKMenu = None # type: tk.Menu + self.part_of_custom_menubar = False + self.custom_menubar_key = None + # self.temp_size = size if size != (NONE, NONE) else + key = key if key is not None else k + sz = size if size != (None, None) else s + pad = pad if pad is not None else p + self.expand_x = expand_x + self.expand_y = expand_y + + super().__init__(ELEM_TYPE_BUTTONMENU, size=sz, font=font, pad=pad, key=key, tooltip=tooltip, + text_color=self.TextColor, background_color=self.BackgroundColor, visible=visible, metadata=metadata) + self.Tearoff = tearoff + + def _MenuItemChosenCallback(self, item_chosen): # ButtonMenu Menu Item Chosen Callback + """ + Not a user callable function. Called by tkinter when an item is chosen from the menu. + + :param item_chosen: The menu item chosen. + :type item_chosen: (str) + """ + # print('IN MENU ITEM CALLBACK', item_chosen) + self.MenuItemChosen = item_chosen + self.ParentForm.LastButtonClicked = self.Key + self.ParentForm.FormRemainedOpen = True + # if self.ParentForm.CurrentlyRunningMainloop: + # self.ParentForm.TKroot.quit() # kick the users out of the mainloop + _exit_mainloop(self.ParentForm) + + def update(self, menu_definition=None, visible=None): + """ + Changes some of the settings for the ButtonMenu Element. Must call `Window.Read` or `Window.Finalize` prior + + :param menu_definition: (New menu definition (in menu definition format) + :type menu_definition: List[List] + :param visible: control visibility of element + :type visible: (bool) + """ + + if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow + return + + if menu_definition is not None: + self.MenuDefinition = copy.deepcopy(menu_definition) + top_menu = self.TKMenu = tk.Menu(self.TKButtonMenu, tearoff=self.Tearoff, font=self.ItemFont, tearoffcommand=self._tearoff_menu_callback) + + if self.BackgroundColor not in (COLOR_SYSTEM_DEFAULT, None): + top_menu.config(bg=self.BackgroundColor) + if self.TextColor not in (COLOR_SYSTEM_DEFAULT, None): + top_menu.config(fg=self.TextColor) + if self.DisabledTextColor not in (COLOR_SYSTEM_DEFAULT, None): + top_menu.config(disabledforeground=self.DisabledTextColor) + if self.ItemFont is not None: + top_menu.config(font=self.ItemFont) + AddMenuItem(self.TKMenu, self.MenuDefinition[1], self) + self.TKButtonMenu.configure(menu=self.TKMenu) + if visible is False: + self.TKButtonMenu.pack_forget() + elif visible is True: + self.TKButtonMenu.pack(padx=self.pad_used[0], pady=self.pad_used[1]) + if visible is not None: + self._visible = visible + + def Click(self): + """ + Generates a click of the button as if the user clicked the button + Calls the tkinter invoke method for the button + """ + try: + self.TKMenu.invoke(1) + except: + print('Exception clicking button') + + Update = update + + +BMenu = ButtonMenu +BM = ButtonMenu + + +# ---------------------------------------------------------------------- # +# ProgreessBar # +# ---------------------------------------------------------------------- # +class ProgressBar(Element): + """ + Progress Bar Element - Displays a colored bar that is shaded as progress of some operation is made + """ + + def __init__(self, max_value, orientation=None, size=(None, None), s=(None, None), size_px=(None, None), auto_size_text=None, bar_color=None, style=None, border_width=None, + relief=None, key=None, k=None, pad=None, p=None, right_click_menu=None, expand_x=False, expand_y=False, visible=True, metadata=None): + """ + :param max_value: max value of progressbar + :type max_value: (int) + :param orientation: 'horizontal' or 'vertical' + :type orientation: (str) + :param size: Size of the bar. If horizontal (chars long, pixels wide), vert (chars high, pixels wide). Vert height measured using horizontal chars units. + :type size: (int, int) | (int, None) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) + :param size_px: Size in pixels (length, width). Will be used in place of size parm if specified + :type size_px: (int, int) | (None, None) + :param auto_size_text: Not sure why this is here + :type auto_size_text: (bool) + :param bar_color: The 2 colors that make up a progress bar. Easy to remember which is which if you say "ON" between colors. "red" on "green". + :type bar_color: (str, str) or str + :param style: Progress bar style defined as one of these 'default', 'winnative', 'clam', 'alt', 'classic', 'vista', 'xpnative' + :type style: (str) + :param border_width: The amount of pixels that go around the outside of the bar + :type border_width: (int) + :param relief: relief style. Values are same as progress meter relief values. Can be a constant or a string: `RELIEF_RAISED RELIEF_SUNKEN RELIEF_FLAT RELIEF_RIDGE RELIEF_GROOVE RELIEF_SOLID` (Default value = DEFAULT_PROGRESS_BAR_RELIEF) + :type relief: (str) + :param key: Used with window.find_element and with return values to uniquely identify this element to uniquely identify this element + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. + :type right_click_menu: List[List[ List[str] | str ]] + :param expand_x: If True the element will automatically expand in the X direction to fill available space + :type expand_x: (bool) + :param expand_y: If True the element will automatically expand in the Y direction to fill available space + :type expand_y: (bool) + :param visible: set visibility state of the element + :type visible: (bool) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + + + self.MaxValue = max_value + self.TKProgressBar = None # type: TKProgressBar + self.Cancelled = False + self.NotRunning = True + self.Orientation = orientation if orientation else DEFAULT_METER_ORIENTATION + self.RightClickMenu = right_click_menu + self.ttk_style_name = None # set in the pack function so can use in the update + # Progress Bar colors can be a tuple (text, background) or a string with format "bar on background" - examples "red on white" or ("red", "white") + if bar_color is None: + bar_color = DEFAULT_PROGRESS_BAR_COLOR + else: + bar_color = _simplified_dual_color_to_tuple(bar_color, default=DEFAULT_PROGRESS_BAR_COLOR) + + self.BarColor = bar_color # should be a tuple at this point + self.BarStyle = style if style else DEFAULT_TTK_THEME + self.BorderWidth = border_width if border_width else DEFAULT_PROGRESS_BAR_BORDER_WIDTH + self.Relief = relief if relief else DEFAULT_PROGRESS_BAR_RELIEF + self.BarExpired = False + key = key if key is not None else k + sz = size if size != (None, None) else s + pad = pad if pad is not None else p + self.expand_x = expand_x + self.expand_y = expand_y + self.size_px = size_px + + super().__init__(ELEM_TYPE_PROGRESS_BAR, size=sz, auto_size_text=auto_size_text, key=key, pad=pad, + visible=visible, metadata=metadata) + + # returns False if update failed + def update_bar(self, current_count, max=None): + """ + DEPRECATED BUT STILL USABLE - has been combined with the normal ProgressBar.update method. + Change what the bar shows by changing the current count and optionally the max count + + :param current_count: sets the current value + :type current_count: (int) + :param max: changes the max value + :type max: (int) + """ + + if self.ParentForm.TKrootDestroyed: + return False + self.TKProgressBar.Update(current_count, max=max) + try: + self.ParentForm.TKroot.update() + except: + Window._DecrementOpenCount() + # _my_windows.Decrement() + return False + return True + + def update(self, current_count=None, max=None, bar_color=None, visible=None): + """ + Changes some of the settings for the ProgressBar Element. Must call `Window.Read` or `Window.Finalize` prior + Now has the ability to modify the count so that the update_bar method is not longer needed separately + + :param current_count: sets the current value + :type current_count: (int) + :param max: changes the max value + :type max: (int) + :param bar_color: The 2 colors that make up a progress bar. Easy to remember which is which if you say "ON" between colors. "red" on "green". + :type bar_color: (str, str) or str + :param visible: control visibility of element + :type visible: (bool) + :return: Returns True if update was OK. False means something wrong with window or it was closed + :rtype: (bool) + """ + if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow + return False + + if self.ParentForm.TKrootDestroyed: + return False + + if visible is False: + self.TKProgressBar.TKProgressBarForReal.pack_forget() + elif visible is True: + self.TKProgressBar.TKProgressBarForReal.pack(padx=self.pad_used[0], pady=self.pad_used[1]) + if visible is not None: + self._visible = visible + if bar_color is not None: + bar_color = _simplified_dual_color_to_tuple(bar_color, default=DEFAULT_PROGRESS_BAR_COLOR) + self.BarColor = bar_color + style = ttk.Style() + style.configure(self.ttk_style_name, background=bar_color[0], troughcolor=bar_color[1]) + if current_count is not None: + self.TKProgressBar.Update(current_count, max=max) + + try: + self.ParentForm.TKroot.update() + except: + # Window._DecrementOpenCount() + # _my_windows.Decrement() + return False + return True + + Update = update + UpdateBar = update_bar + + +PBar = ProgressBar +Prog = ProgressBar +Progress = ProgressBar + + +# ---------------------------------------------------------------------- # +# Image # +# ---------------------------------------------------------------------- # +class Image(Element): + """ + Image Element - show an image in the window. Should be a GIF or a PNG only + """ + + def __init__(self, source=None, filename=None, data=None, background_color=None, size=(None, None), s=(None, None), pad=None, p=None, key=None, k=None, tooltip=None, subsample=None, right_click_menu=None, expand_x=False, expand_y=False, visible=True, enable_events=False, metadata=None): + """ + :param source: A filename or a base64 bytes. Will automatically detect the type and fill in filename or data for you. + :type source: str | bytes | None + :param filename: image filename if there is a button image. GIFs and PNGs only. + :type filename: str | None + :param data: Raw or Base64 representation of the image to put on button. Choose either filename or data + :type data: bytes | str | None + :param background_color: color of background + :type background_color: + :param size: (width, height) size of image in pixels + :type size: (int, int) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param key: Used with window.find_element and with return values to uniquely identify this element to uniquely identify this element + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param subsample: amount to reduce the size of the image. Divides the size by this number. 2=1/2, 3=1/3, 4=1/4, etc + :type subsample: (int) + :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. + :type right_click_menu: List[List[ List[str] | str ]] + :param expand_x: If True the element will automatically expand in the X direction to fill available space + :type expand_x: (bool) + :param expand_y: If True the element will automatically expand in the Y direction to fill available space + :type expand_y: (bool) + :param visible: set visibility state of the element + :type visible: (bool) + :param enable_events: Turns on the element specific events. For an Image element, the event is "image clicked" + :type enable_events: (bool) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + + if source is not None: + if isinstance(source, bytes): + data = source + elif isinstance(source, str): + filename = source + else: + warnings.warn('Image element - source is not a valid type: {}'.format(type(source)), UserWarning) + + self.Filename = filename + self.Data = data + self.Widget = self.tktext_label = None # type: tk.Label + self.BackgroundColor = background_color + if data is None and filename is None: + self.Filename = '' + self.EnableEvents = enable_events + self.RightClickMenu = right_click_menu + self.AnimatedFrames = None + self.CurrentFrameNumber = 0 + self.TotalAnimatedFrames = 0 + self.LastFrameTime = 0 + self.ImageSubsample = subsample + + self.Source = filename if filename is not None else data + key = key if key is not None else k + sz = size if size != (None, None) else s + pad = pad if pad is not None else p + self.expand_x = expand_x + self.expand_y = expand_y + + super().__init__(ELEM_TYPE_IMAGE, size=sz, background_color=background_color, pad=pad, key=key, + tooltip=tooltip, visible=visible, metadata=metadata) + return + + def update(self, source=None, filename=None, data=None, size=(None, None), subsample=None, visible=None): + """ + Changes some of the settings for the Image Element. Must call `Window.Read` or `Window.Finalize` prior. + To clear an image that's been displayed, call with NONE of the options set. A blank update call will + delete the previously shown image. + :param source: A filename or a base64 bytes. Will automatically detect the type and fill in filename or data for you. + :type source: str | bytes | None + :param filename: filename to the new image to display. + :type filename: (str) + :param data: Base64 encoded string OR a tk.PhotoImage object + :type data: str | tkPhotoImage + :param size: (width, height) size of image in pixels + :type size: Tuple[int,int] + :param subsample: amount to reduce the size of the image. Divides the size by this number. 2=1/2, 3=1/3, 4=1/4, etc + :type subsample: (int) + :param visible: control visibility of element + :type visible: (bool) + """ + + if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow + return + + if source is not None: + if isinstance(source, bytes): + data = source + elif isinstance(source, str): + filename = source + else: + warnings.warn('Image element - source is not a valid type: {}'.format(type(source)), UserWarning) + + image = None + if filename is not None: + image = tk.PhotoImage(file=filename) + if subsample is not None: + image = image.subsample(subsample) + elif data is not None: + # if type(data) is bytes: + try: + image = tk.PhotoImage(data=data) + if subsample is not None: + image = image.subsample(subsample) + except Exception as e: + image = data + # return # an error likely means the window has closed so exit + + if image is not None: + if type(image) is not bytes: + width, height = size[0] if size[0] is not None else image.width(), size[1] if size[1] is not None else image.height() + else: + width, height = size + try: # sometimes crashes if user closed with X + self.tktext_label.configure(image=image, width=width, height=height) + except Exception as e: + _error_popup_with_traceback('Exception updating Image element', e) + self.tktext_label.image = image + if visible is False: + self.tktext_label.pack_forget() + elif visible is True: + self.tktext_label.pack(padx=self.pad_used[0], pady=self.pad_used[1]) + # if everything is set to None, then delete the image + if filename is None and image is None and visible is None and size == (None, None): + # Using a try because the image may have been previously deleted and don't want an error if that's happened + try: + self.tktext_label.configure(width=1, height=1, bd=0) + self.tktext_label.image = None + except: + pass + + if visible is not None: + self._visible = visible + + def update_animation(self, source, time_between_frames=0): + """ + Show an Animated GIF. Call the function as often as you like. The function will determine when to show the next frame and will automatically advance to the next frame at the right time. + NOTE - does NOT perform a sleep call to delay + :param source: Filename or Base64 encoded string containing Animated GIF + :type source: str | bytes | None + :param time_between_frames: Number of milliseconds to wait between showing frames + :type time_between_frames: (int) + """ + + if self.Source != source: + self.AnimatedFrames = None + self.Source = source + + if self.AnimatedFrames is None: + self.TotalAnimatedFrames = 0 + self.AnimatedFrames = [] + # Load up to 1000 frames of animation. stops when a bad frame is returns by tkinter + for i in range(1000): + if type(source) is not bytes: + try: + self.AnimatedFrames.append(tk.PhotoImage(file=source, format='gif -index %i' % (i))) + except Exception as e: + break + else: + try: + self.AnimatedFrames.append(tk.PhotoImage(data=source, format='gif -index %i' % (i))) + except Exception as e: + break + self.TotalAnimatedFrames = len(self.AnimatedFrames) + self.LastFrameTime = time.time() + self.CurrentFrameNumber = -1 # start at -1 because it is incremented before every frame is shown + # show the frame + + now = time.time() + + if time_between_frames: + if (now - self.LastFrameTime) * 1000 > time_between_frames: + self.LastFrameTime = now + self.CurrentFrameNumber = (self.CurrentFrameNumber + 1) % self.TotalAnimatedFrames + else: # don't reshow the frame again if not time for new frame + return + else: + self.CurrentFrameNumber = (self.CurrentFrameNumber + 1) % self.TotalAnimatedFrames + image = self.AnimatedFrames[self.CurrentFrameNumber] + try: # needed in case the window was closed with an "X" + self.tktext_label.configure(image=image, width=image.width(), heigh=image.height()) + except Exception as e: + print('Exception in update_animation', e) + + + def update_animation_no_buffering(self, source, time_between_frames=0): + """ + Show an Animated GIF. Call the function as often as you like. The function will determine when to show the next frame and will automatically advance to the next frame at the right time. + NOTE - does NOT perform a sleep call to delay + + :param source: Filename or Base64 encoded string containing Animated GIF + :type source: str | bytes + :param time_between_frames: Number of milliseconds to wait between showing frames + :type time_between_frames: (int) + """ + + if self.Source != source: + self.AnimatedFrames = None + self.Source = source + self.frame_num = 0 + + now = time.time() + + if time_between_frames: + if (now - self.LastFrameTime) * 1000 > time_between_frames: + self.LastFrameTime = now + else: # don't reshow the frame again if not time for new frame + return + + # read a frame + while True: + if type(source) is not bytes: + try: + self.image = tk.PhotoImage(file=source, format='gif -index %i' % (self.frame_num)) + self.frame_num += 1 + except: + self.frame_num = 0 + else: + try: + self.image = tk.PhotoImage(data=source, format='gif -index %i' % (self.frame_num)) + self.frame_num += 1 + except: + self.frame_num = 0 + if self.frame_num: + break + + try: # needed in case the window was closed with an "X" + self.tktext_label.configure(image=self.image, width=self.image.width(), heigh=self.image.height()) + + except: + pass + + Update = update + UpdateAnimation = update_animation + + +Im = Image + + +# ---------------------------------------------------------------------- # +# Canvas # +# ---------------------------------------------------------------------- # +class Canvas(Element): + + def __init__(self, canvas=None, background_color=None, size=(None, None), s=(None, None), pad=None, p=None, key=None, k=None, tooltip=None, + right_click_menu=None, expand_x=False, expand_y=False, visible=True, border_width=0, metadata=None): + """ + :param canvas: Your own tk.Canvas if you already created it. Leave blank to create a Canvas + :type canvas: (tk.Canvas) + :param background_color: color of background + :type background_color: (str) + :param size: (width in char, height in rows) size in pixels to make canvas + :type size: (int,int) | (None, None) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param key: Used with window.find_element and with return values to uniquely identify this element + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. + :type right_click_menu: List[List[ List[str] | str ]] + :param expand_x: If True the element will automatically expand in the X direction to fill available space + :type expand_x: (bool) + :param expand_y: If True the element will automatically expand in the Y direction to fill available space + :type expand_y: (bool) + :param visible: set visibility state of the element + :type visible: (bool) + :param border_width: width of border around element in pixels. Not normally used with Canvas element + :type border_width: (int) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + + + self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR + self._TKCanvas = canvas + self.RightClickMenu = right_click_menu + self.BorderWidth = border_width + key = key if key is not None else k + sz = size if size != (None, None) else s + pad = pad if pad is not None else p + self.expand_x = expand_x + self.expand_y = expand_y + + super().__init__(ELEM_TYPE_CANVAS, background_color=background_color, size=sz, pad=pad, key=key, + tooltip=tooltip, visible=visible, metadata=metadata) + return + + @property + def tk_canvas(self): + """ + Returns the underlying tkiner Canvas widget + + :return: The tkinter canvas widget + :rtype: (tk.Canvas) + """ + if self._TKCanvas is None: + print('*** Did you forget to call Finalize()? Your code should look something like: ***') + print('*** window = sg.Window("My Form", layout, finalize=True) ***') + return self._TKCanvas + + TKCanvas = tk_canvas + + +# ---------------------------------------------------------------------- # +# Graph # +# ---------------------------------------------------------------------- # +class Graph(Element): + """ + Creates an area for you to draw on. The MAGICAL property this Element has is that you interact + with the element using your own coordinate system. This is an important point!! YOU define where the location + is for (0,0). Want (0,0) to be in the middle of the graph like a math 4-quadrant graph? No problem! Set your + lower left corner to be (-100,-100) and your upper right to be (100,100) and you've got yourself a graph with + (0,0) at the center. + One of THE coolest of the Elements. + You can also use float values. To do so, be sure and set the float_values parameter. + Mouse click and drag events are possible and return the (x,y) coordinates of the mouse + Drawing primitives return an "id" that is referenced when you want to operation on that item (e.g. to erase it) + """ + + def __init__(self, canvas_size, graph_bottom_left, graph_top_right, background_color=None, pad=None, p=None, + change_submits=False, drag_submits=False, enable_events=False, key=None, k=None, tooltip=None, + right_click_menu=None, expand_x=False, expand_y=False, visible=True, float_values=False, border_width=0, metadata=None): + """ + :param canvas_size: size of the canvas area in pixels + :type canvas_size: (int, int) + :param graph_bottom_left: (x,y) The bottoms left corner of your coordinate system + :type graph_bottom_left: (int, int) + :param graph_top_right: (x,y) The top right corner of your coordinate system + :type graph_top_right: (int, int) + :param background_color: background color of the drawing area + :type background_color: (str) + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param change_submits: * DEPRICATED DO NOT USE. Use `enable_events` instead + :type change_submits: (bool) + :param drag_submits: if True and Events are enabled for the Graph, will report Events any time the mouse moves while button down + :type drag_submits: (bool) + :param enable_events: If True then clicks on the Graph are immediately reported as an event. Use this instead of change_submits + :type enable_events: (bool) + :param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. + :type right_click_menu: List[List[ List[str] | str ]] + :param expand_x: If True the element will automatically expand in the X direction to fill available space + :type expand_x: (bool) + :param expand_y: If True the element will automatically expand in the Y direction to fill available space + :type expand_y: (bool) + :param visible: set visibility state of the element (Default = True) + :type visible: (bool) + :param float_values: If True x,y coordinates are returned as floats, not ints + :type float_values: (bool) + :param border_width: width of border around element in pixels. Not normally used for Graph Elements + :type border_width: (int) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + + self.CanvasSize = canvas_size + self.BottomLeft = graph_bottom_left + self.TopRight = graph_top_right + # self._TKCanvas = None # type: tk.Canvas + self._TKCanvas2 = self.Widget = None # type: tk.Canvas + self.ChangeSubmits = change_submits or enable_events + self.DragSubmits = drag_submits + self.ClickPosition = (None, None) + self.MouseButtonDown = False + self.Images = {} + self.RightClickMenu = right_click_menu + self.FloatValues = float_values + self.BorderWidth = border_width + key = key if key is not None else k + pad = pad if pad is not None else p + self.expand_x = expand_x + self.expand_y = expand_y + + super().__init__(ELEM_TYPE_GRAPH, background_color=background_color, size=canvas_size, pad=pad, key=key, + tooltip=tooltip, visible=visible, metadata=metadata) + return + + def _convert_xy_to_canvas_xy(self, x_in, y_in): + """ + Not user callable. Used to convert user's coordinates into the ones used by tkinter + :param x_in: The x coordinate to convert + :type x_in: int | float + :param y_in: The y coordinate to convert + :type y_in: int | float + :return: (int, int) The converted canvas coordinates + :rtype: (int, int) + """ + if None in (x_in, y_in): + return None, None + try: + scale_x = (self.CanvasSize[0] - 0) / (self.TopRight[0] - self.BottomLeft[0]) + scale_y = (0 - self.CanvasSize[1]) / (self.TopRight[1] - self.BottomLeft[1]) + except: + scale_x = scale_y = 0 + + new_x = 0 + scale_x * (x_in - self.BottomLeft[0]) + new_y = self.CanvasSize[1] + scale_y * (y_in - self.BottomLeft[1]) + return new_x, new_y + + def _convert_canvas_xy_to_xy(self, x_in, y_in): + """ + Not user callable. Used to convert tkinter Canvas coords into user's coordinates + + :param x_in: The x coordinate in canvas coordinates + :type x_in: (int) + :param y_in: (int) The y coordinate in canvas coordinates + :type y_in: + :return: The converted USER coordinates + :rtype: (int, int) | Tuple[float, float] + """ + if None in (x_in, y_in): + return None, None + scale_x = (self.CanvasSize[0] - 0) / (self.TopRight[0] - self.BottomLeft[0]) + scale_y = (0 - self.CanvasSize[1]) / (self.TopRight[1] - self.BottomLeft[1]) + + new_x = x_in / scale_x + self.BottomLeft[0] + new_y = (y_in - self.CanvasSize[1]) / scale_y + self.BottomLeft[1] + if self.FloatValues: + return new_x, new_y + else: + return floor(new_x), floor(new_y) + + def draw_line(self, point_from, point_to, color='black', width=1): + """ + Draws a line from one point to another point using USER'S coordinates. Can set the color and width of line + :param point_from: Starting point for line + :type point_from: (int, int) | Tuple[float, float] + :param point_to: Ending point for line + :type point_to: (int, int) | Tuple[float, float] + :param color: Color of the line + :type color: (str) + :param width: width of line in pixels + :type width: (int) + :return: id returned from tktiner or None if user closed the window. id is used when you + :rtype: int | None + """ + if point_from == (None, None): + return + converted_point_from = self._convert_xy_to_canvas_xy(point_from[0], point_from[1]) + converted_point_to = self._convert_xy_to_canvas_xy(point_to[0], point_to[1]) + if self._TKCanvas2 is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + try: # in case window was closed with an X + id = self._TKCanvas2.create_line(converted_point_from, converted_point_to, width=width, fill=color) + except: + id = None + return id + + def draw_lines(self, points, color='black', width=1): + """ + Draw a series of lines given list of points + + :param points: list of points that define the polygon + :type points: List[(int, int) | Tuple[float, float]] + :param color: Color of the line + :type color: (str) + :param width: width of line in pixels + :type width: (int) + :return: id returned from tktiner or None if user closed the window. id is used when you + :rtype: int | None + """ + converted_points = [self._convert_xy_to_canvas_xy(point[0], point[1]) for point in points] + + try: # in case window was closed with an X + id = self._TKCanvas2.create_line(*converted_points, width=width, fill=color) + except: + if self._TKCanvas2 is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + id = None + return id + + def draw_point(self, point, size=2, color='black'): + """ + Draws a "dot" at the point you specify using the USER'S coordinate system + :param point: Center location using USER'S coordinate system + :type point: (int, int) | Tuple[float, float] + :param size: Radius? (Or is it the diameter?) in user's coordinate values. + :type size: int | float + :param color: color of the point to draw + :type color: (str) + :return: id returned from tkinter that you'll need if you want to manipulate the point + :rtype: int | None + """ + if point == (None, None): + return + converted_point = self._convert_xy_to_canvas_xy(point[0], point[1]) + size_converted = self._convert_xy_to_canvas_xy(point[0] + size, point[1]) + size = size_converted[0] - converted_point[0] + if self._TKCanvas2 is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + try: # needed in case window was closed with an X + point1 = converted_point[0] - size // 2, converted_point[1] - size // 2 + point2 = converted_point[0] + size // 2, converted_point[1] + size // 2 + id = self._TKCanvas2.create_oval(point1[0], point1[1], + point2[0], point2[1], + width=0, + fill=color, + outline=color) + except: + id = None + return id + + def draw_circle(self, center_location, radius, fill_color=None, line_color='black', line_width=1): + """ + Draws a circle, cenetered at the location provided. Can set the fill and outline colors + :param center_location: Center location using USER'S coordinate system + :type center_location: (int, int) | Tuple[float, float] + :param radius: Radius in user's coordinate values. + :type radius: int | float + :param fill_color: color of the point to draw + :type fill_color: (str) + :param line_color: color of the outer line that goes around the circle (sorry, can't set thickness) + :type line_color: (str) + :param line_width: width of the line around the circle, the outline, in pixels + :type line_width: (int) + :return: id returned from tkinter that you'll need if you want to manipulate the circle + :rtype: int | None + """ + if center_location == (None, None): + return + converted_point = self._convert_xy_to_canvas_xy(center_location[0], center_location[1]) + radius_converted = self._convert_xy_to_canvas_xy(center_location[0] + radius, center_location[1]) + radius = radius_converted[0] - converted_point[0] + # radius = radius_converted[1]-5 + if self._TKCanvas2 is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + # print('Oval parms', int(converted_point[0]) - int(radius), int(converted_point[1]) - int(radius), + # int(converted_point[0]) + int(radius), int(converted_point[1]) + int(radius)) + try: # needed in case the window was closed with an X + id = self._TKCanvas2.create_oval(int(converted_point[0]) - int(radius), int(converted_point[1]) - int(radius), + int(converted_point[0]) + int(radius), int(converted_point[1]) + int(radius), fill=fill_color, + outline=line_color, width=line_width) + except: + id = None + return id + + def draw_oval(self, top_left, bottom_right, fill_color=None, line_color=None, line_width=1): + """ + Draws an oval based on coordinates in user coordinate system. Provide the location of a "bounding rectangle" + :param top_left: the top left point of bounding rectangle + :type top_left: (int, int) | Tuple[float, float] + :param bottom_right: the bottom right point of bounding rectangle + :type bottom_right: (int, int) | Tuple[float, float] + :param fill_color: color of the interrior + :type fill_color: (str) + :param line_color: color of outline of oval + :type line_color: (str) + :param line_width: width of the line around the oval, the outline, in pixels + :type line_width: (int) + :return: id returned from tkinter that you'll need if you want to manipulate the oval + :rtype: int | None + """ + converted_top_left = self._convert_xy_to_canvas_xy(top_left[0], top_left[1]) + converted_bottom_right = self._convert_xy_to_canvas_xy(bottom_right[0], bottom_right[1]) + if self._TKCanvas2 is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + try: # in case windows close with X + id = self._TKCanvas2.create_oval(converted_top_left[0], converted_top_left[1], converted_bottom_right[0], + converted_bottom_right[1], fill=fill_color, outline=line_color, width=line_width) + except: + id = None + + return id + + def draw_arc(self, top_left, bottom_right, extent, start_angle, style=None, arc_color='black', line_width=1, fill_color=None): + """ + Draws different types of arcs. Uses a "bounding box" to define location + :param top_left: the top left point of bounding rectangle + :type top_left: (int, int) | Tuple[float, float] + :param bottom_right: the bottom right point of bounding rectangle + :type bottom_right: (int, int) | Tuple[float, float] + :param extent: Andle to end drawing. Used in conjunction with start_angle + :type extent: (float) + :param start_angle: Angle to begin drawing. Used in conjunction with extent + :type start_angle: (float) + :param style: Valid choices are One of these Style strings- 'pieslice', 'chord', 'arc', 'first', 'last', 'butt', 'projecting', 'round', 'bevel', 'miter' + :type style: (str) + :param arc_color: color to draw arc with + :type arc_color: (str) + :param fill_color: color to fill the area + :type fill_color: (str) + :return: id returned from tkinter that you'll need if you want to manipulate the arc + :rtype: int | None + """ + converted_top_left = self._convert_xy_to_canvas_xy(top_left[0], top_left[1]) + converted_bottom_right = self._convert_xy_to_canvas_xy(bottom_right[0], bottom_right[1]) + tkstyle = tk.PIESLICE if style is None else style + if self._TKCanvas2 is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + try: # in case closed with X + id = self._TKCanvas2.create_arc(converted_top_left[0], converted_top_left[1], converted_bottom_right[0], + converted_bottom_right[1], extent=extent, start=start_angle, style=tkstyle, + outline=arc_color, width=line_width, fill=fill_color) + except Exception as e: + print('Error encountered drawing arc.', e) + id = None + return id + + def draw_rectangle(self, top_left, bottom_right, fill_color=None, line_color=None, line_width=None): + """ + Draw a rectangle given 2 points. Can control the line and fill colors + + :param top_left: the top left point of rectangle + :type top_left: (int, int) | Tuple[float, float] + :param bottom_right: the bottom right point of rectangle + :type bottom_right: (int, int) | Tuple[float, float] + :param fill_color: color of the interior + :type fill_color: (str) + :param line_color: color of outline + :type line_color: (str) + :param line_width: width of the line in pixels + :type line_width: (int) + :return: int | None id returned from tkinter that you'll need if you want to manipulate the rectangle + :rtype: int | None + """ + + converted_top_left = self._convert_xy_to_canvas_xy(top_left[0], top_left[1]) + converted_bottom_right = self._convert_xy_to_canvas_xy(bottom_right[0], bottom_right[1]) + if self._TKCanvas2 is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + if line_width is None: + line_width = 1 + try: # in case closed with X + id = self._TKCanvas2.create_rectangle(converted_top_left[0], converted_top_left[1], + converted_bottom_right[0], + converted_bottom_right[1], fill=fill_color, outline=line_color, width=line_width) + except: + id = None + return id + + def draw_polygon(self, points, fill_color=None, line_color=None, line_width=None): + """ + Draw a polygon given list of points + + :param points: list of points that define the polygon + :type points: List[(int, int) | Tuple[float, float]] + :param fill_color: color of the interior + :type fill_color: (str) + :param line_color: color of outline + :type line_color: (str) + :param line_width: width of the line in pixels + :type line_width: (int) + :return: id returned from tkinter that you'll need if you want to manipulate the rectangle + :rtype: int | None + """ + + converted_points = [self._convert_xy_to_canvas_xy(point[0], point[1]) for point in points] + if self._TKCanvas2 is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + try: # in case closed with X + id = self._TKCanvas2.create_polygon(converted_points, fill=fill_color, outline=line_color, width=line_width) + except: + id = None + return id + + def draw_text(self, text, location, color='black', font=None, angle=0, text_location=TEXT_LOCATION_CENTER): + """ + Draw some text on your graph. This is how you label graph number lines for example + + :param text: text to display + :type text: (Any) + :param location: location to place first letter + :type location: (int, int) | Tuple[float, float] + :param color: text color + :type color: (str) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param angle: Angle 0 to 360 to draw the text. Zero represents horizontal text + :type angle: (float) + :param text_location: "anchor" location for the text. Values start with TEXT_LOCATION_ + :type text_location: (enum) + :return: id returned from tkinter that you'll need if you want to manipulate the text + :rtype: int | None + """ + text = str(text) + if location == (None, None): + return + converted_point = self._convert_xy_to_canvas_xy(location[0], location[1]) + if self._TKCanvas2 is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + try: # in case closed with X + id = self._TKCanvas2.create_text(converted_point[0], converted_point[1], text=text, font=font, fill=color, angle=angle, anchor=text_location) + except: + id = None + return id + + def draw_image(self, filename=None, data=None, location=(None, None)): + """ + Places an image onto your canvas. It's a really important method for this element as it enables so much + + :param filename: if image is in a file, path and filename for the image. (GIF and PNG only!) + :type filename: (str) + :param data: if image is in Base64 format or raw? format then use instead of filename + :type data: str | bytes + :param location: the (x,y) location to place image's top left corner + :type location: (int, int) | Tuple[float, float] + :return: id returned from tkinter that you'll need if you want to manipulate the image + :rtype: int | None + """ + if location == (None, None): + return + if filename is not None: + image = tk.PhotoImage(file=filename) + elif data is not None: + # if type(data) is bytes: + try: + image = tk.PhotoImage(data=data) + except: + return None # an error likely means the window has closed so exit + converted_point = self._convert_xy_to_canvas_xy(location[0], location[1]) + if self._TKCanvas2 is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + try: # in case closed with X + id = self._TKCanvas2.create_image(converted_point, image=image, anchor=tk.NW) + self.Images[id] = image + except: + id = None + return id + + def erase(self): + """ + Erase the Graph - Removes all figures previously "drawn" using the Graph methods (e.g. DrawText) + """ + if self._TKCanvas2 is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + self.Images = {} + try: # in case window was closed with X + self._TKCanvas2.delete('all') + except: + pass + + def delete_figure(self, id): + """ + Remove from the Graph the figure represented by id. The id is given to you anytime you call a drawing primitive + + :param id: the id returned to you when calling one of the drawing methods + :type id: (int) + """ + try: + self._TKCanvas2.delete(id) + except: + print('DeleteFigure - bad ID {}'.format(id)) + try: + del self.Images[id] # in case was an image. If wasn't an image, then will get exception + except: + pass + + def update(self, background_color=None, visible=None): + """ + Changes some of the settings for the Graph Element. Must call `Window.Read` or `Window.Finalize` prior + + :param background_color: color of background + :type background_color: ??? + :param visible: control visibility of element + :type visible: (bool) + """ + if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow + return + + if background_color is not None and background_color != COLOR_SYSTEM_DEFAULT: + self._TKCanvas2.configure(background=background_color) + if visible is False: + self._TKCanvas2.pack_forget() + elif visible is True: + self._TKCanvas2.pack(padx=self.pad_used[0], pady=self.pad_used[1]) + if visible is not None: + self._visible = visible + + def move(self, x_direction, y_direction): + """ + Moves the entire drawing area (the canvas) by some delta from the current position. Units are indicated in your coordinate system indicated number of ticks in your coordinate system + + :param x_direction: how far to move in the "X" direction in your coordinates + :type x_direction: int | float + :param y_direction: how far to move in the "Y" direction in your coordinates + :type y_direction: int | float + """ + zero_converted = self._convert_xy_to_canvas_xy(0, 0) + shift_converted = self._convert_xy_to_canvas_xy(x_direction, y_direction) + shift_amount = (shift_converted[0] - zero_converted[0], shift_converted[1] - zero_converted[1]) + if self._TKCanvas2 is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + self._TKCanvas2.move('all', shift_amount[0], shift_amount[1]) + + def move_figure(self, figure, x_direction, y_direction): + """ + Moves a previously drawn figure using a "delta" from current position + + :param figure: Previously obtained figure-id. These are returned from all Draw methods + :type figure: (id) + :param x_direction: delta to apply to position in the X direction + :type x_direction: int | float + :param y_direction: delta to apply to position in the Y direction + :type y_direction: int | float + """ + zero_converted = self._convert_xy_to_canvas_xy(0, 0) + shift_converted = self._convert_xy_to_canvas_xy(x_direction, y_direction) + shift_amount = (shift_converted[0] - zero_converted[0], shift_converted[1] - zero_converted[1]) + if figure is None: + print('* move_figure warning - your figure is None *') + return None + self._TKCanvas2.move(figure, shift_amount[0], shift_amount[1]) + + def relocate_figure(self, figure, x, y): + """ + Move a previously made figure to an arbitrary (x,y) location. This differs from the Move methods because it + uses absolute coordinates versus relative for Move + + :param figure: Previously obtained figure-id. These are returned from all Draw methods + :type figure: (id) + :param x: location on X axis (in user coords) to move the upper left corner of the figure + :type x: int | float + :param y: location on Y axis (in user coords) to move the upper left corner of the figure + :type y: int | float + """ + + zero_converted = self._convert_xy_to_canvas_xy(0, 0) + shift_converted = self._convert_xy_to_canvas_xy(x, y) + shift_amount = (shift_converted[0] - zero_converted[0], shift_converted[1] - zero_converted[1]) + if figure is None: + print('*** WARNING - Your figure is None. It most likely means your did not Finalize your Window ***') + print('Call Window.Finalize() prior to all graph operations') + return None + xy = self._TKCanvas2.coords(figure) + self._TKCanvas2.move(figure, shift_converted[0] - xy[0], shift_converted[1] - xy[1]) + + def send_figure_to_back(self, figure): + """ + Changes Z-order of figures on the Graph. Sends the indicated figure to the back of all other drawn figures + + :param figure: value returned by tkinter when creating the figure / drawing + :type figure: (int) + """ + self.TKCanvas.tag_lower(figure) # move figure to the "bottom" of all other figure + + def bring_figure_to_front(self, figure): + """ + Changes Z-order of figures on the Graph. Brings the indicated figure to the front of all other drawn figures + + :param figure: value returned by tkinter when creating the figure / drawing + :type figure: (int) + """ + self.TKCanvas.tag_raise(figure) # move figure to the "top" of all other figures + + def get_figures_at_location(self, location): + """ + Returns a list of figures located at a particular x,y location within the Graph + + :param location: point to check + :type location: (int, int) | Tuple[float, float] + :return: a list of previously drawn "Figures" (returned from the drawing primitives) + :rtype: List[int] + """ + x, y = self._convert_xy_to_canvas_xy(location[0], location[1]) + ids = self.TKCanvas.find_overlapping(x, y, x, y) + return ids + + def get_bounding_box(self, figure): + """ + Given a figure, returns the upper left and lower right bounding box coordinates + + :param figure: a previously drawing figure + :type figure: object + :return: upper left x, upper left y, lower right x, lower right y + :rtype: Tuple[int, int, int, int] | Tuple[float, float, float, float] + """ + box = self.TKCanvas.bbox(figure) + top_left = self._convert_canvas_xy_to_xy(box[0], box[1]) + bottom_right = self._convert_canvas_xy_to_xy(box[2], box[3]) + return top_left, bottom_right + + def change_coordinates(self, graph_bottom_left, graph_top_right): + """ + Changes the corrdinate system to a new one. The same 2 points in space are used to define the coorinate + system - the bottom left and the top right values of your graph. + + :param graph_bottom_left: The bottoms left corner of your coordinate system + :type graph_bottom_left: (int, int) (x,y) + :param graph_top_right: The top right corner of your coordinate system + :type graph_top_right: (int, int) (x,y) + """ + self.BottomLeft = graph_bottom_left + self.TopRight = graph_top_right + + @property + def tk_canvas(self): + """ + Returns the underlying tkiner Canvas widget + + :return: The tkinter canvas widget + :rtype: (tk.Canvas) + """ + if self._TKCanvas2 is None: + print('*** Did you forget to call Finalize()? Your code should look something like: ***') + print('*** form = sg.Window("My Form").Layout(layout).Finalize() ***') + return self._TKCanvas2 + + # button release callback + def button_release_call_back(self, event): + """ + Not a user callable method. Used to get Graph click events. Called by tkinter when button is released + + :param event: (event) event info from tkinter. Note not used in this method + :type event: + """ + if not self.DragSubmits: # only report mouse up for drag operations + return + self.ClickPosition = self._convert_canvas_xy_to_xy(event.x, event.y) + self.LastButtonClickedWasRealtime = not self.DragSubmits + if self.Key is not None: + self.ParentForm.LastButtonClicked = self.Key + else: + self.ParentForm.LastButtonClicked = '__GRAPH__' # need to put something rather than None + # if self.ParentForm.CurrentlyRunningMainloop: + # self.ParentForm.TKroot.quit() + _exit_mainloop(self.ParentForm) + if self.DragSubmits: + if isinstance(self.ParentForm.LastButtonClicked, str): + self.ParentForm.LastButtonClicked = self.ParentForm.LastButtonClicked + '+UP' + else: + self.ParentForm.LastButtonClicked = (self.ParentForm.LastButtonClicked, '+UP') + # self.ParentForm.LastButtonClicked += '+UP' # this is the old method that required string key + self.MouseButtonDown = False + + # button callback + def button_press_call_back(self, event): + """ + Not a user callable method. Used to get Graph click events. Called by tkinter when button is released + + :param event: (event) event info from tkinter. Contains the x and y coordinates of a click + :type event: + """ + + self.ClickPosition = self._convert_canvas_xy_to_xy(event.x, event.y) + self.ParentForm.LastButtonClickedWasRealtime = self.DragSubmits + if self.Key is not None: + self.ParentForm.LastButtonClicked = self.Key + else: + self.ParentForm.LastButtonClicked = '__GRAPH__' # need to put something rather than None + # if self.ParentForm.CurrentlyRunningMainloop: + # self.ParentForm.TKroot.quit() # kick out of loop if read was called + _exit_mainloop(self.ParentForm) + self.MouseButtonDown = True + + def _update_position_for_returned_values(self, event): + """ + Updates the variable that's used when the values dictionary is returned from a window read. + + Not called by the user. It's called from another method/function that tkinter calledback + + :param event: (event) event info from tkinter. Contains the x and y coordinates of a click + :type event: + """ + """ + Updates the variable that's used when the values dictionary is returned from a window read. + + Not called by the user. It's called from another method/function that tkinter calledback + + :param event: (event) event info from tkinter. Contains the x and y coordinates of a click + :type event: + """ + + self.ClickPosition = self._convert_canvas_xy_to_xy(event.x, event.y) + + # button callback + def motion_call_back(self, event): + """ + Not a user callable method. Used to get Graph mouse motion events. Called by tkinter when mouse moved + + :param event: (event) event info from tkinter. Contains the x and y coordinates of a mouse + :type event: + """ + + if not self.MouseButtonDown: + return + self.ClickPosition = self._convert_canvas_xy_to_xy(event.x, event.y) + self.ParentForm.LastButtonClickedWasRealtime = self.DragSubmits + if self.Key is not None: + self.ParentForm.LastButtonClicked = self.Key + else: + self.ParentForm.LastButtonClicked = '__GRAPH__' # need to put something rather than None + # if self.ParentForm.CurrentlyRunningMainloop: + # self.ParentForm.TKroot.quit() # kick out of loop if read was called + _exit_mainloop(self.ParentForm) + + BringFigureToFront = bring_figure_to_front + ButtonPressCallBack = button_press_call_back + ButtonReleaseCallBack = button_release_call_back + DeleteFigure = delete_figure + DrawArc = draw_arc + DrawCircle = draw_circle + DrawImage = draw_image + DrawLine = draw_line + DrawOval = draw_oval + DrawPoint = draw_point + DrawPolygon = draw_polygon + DrawLines = draw_lines + DrawRectangle = draw_rectangle + DrawText = draw_text + GetFiguresAtLocation = get_figures_at_location + GetBoundingBox = get_bounding_box + Erase = erase + MotionCallBack = motion_call_back + Move = move + MoveFigure = move_figure + RelocateFigure = relocate_figure + SendFigureToBack = send_figure_to_back + TKCanvas = tk_canvas + Update = update + + +G = Graph + + +# ---------------------------------------------------------------------- # +# Frame # +# ---------------------------------------------------------------------- # +class Frame(Element): + """ + A Frame Element that contains other Elements. Encloses with a line around elements and a text label. + """ + + def __init__(self, title, layout, title_color=None, background_color=None, title_location=None, + relief=DEFAULT_FRAME_RELIEF, size=(None, None), s=(None, None), font=None, pad=None, p=None, border_width=None, key=None, k=None, + tooltip=None, right_click_menu=None, expand_x=False, expand_y=False, grab=None, visible=True, element_justification='left', vertical_alignment=None, metadata=None): + """ + :param title: text that is displayed as the Frame's "label" or title + :type title: (str) + :param layout: The layout to put inside the Frame + :type layout: List[List[Elements]] + :param title_color: color of the title text + :type title_color: (str) + :param background_color: background color of the Frame + :type background_color: (str) + :param title_location: location to place the text title. Choices include: TITLE_LOCATION_TOP TITLE_LOCATION_BOTTOM TITLE_LOCATION_LEFT TITLE_LOCATION_RIGHT TITLE_LOCATION_TOP_LEFT TITLE_LOCATION_TOP_RIGHT TITLE_LOCATION_BOTTOM_LEFT TITLE_LOCATION_BOTTOM_RIGHT + :type title_location: (enum) + :param relief: relief style. Values are same as other elements with reliefs. Choices include RELIEF_RAISED RELIEF_SUNKEN RELIEF_FLAT RELIEF_RIDGE RELIEF_GROOVE RELIEF_SOLID + :type relief: (enum) + :param size: (width, height) Sets an initial hard-coded size for the Frame. This used to be a problem, but was fixed in 4.53.0 and works better than Columns when using the size paramter + :type size: (int, int) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param font: specifies the font family, size, etc. for the TITLE. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param border_width: width of border around element in pixels + :type border_width: (int) + :param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. + :type right_click_menu: List[List[ List[str] | str ]] + :param expand_x: If True the element will automatically expand in the X direction to fill available space + :type expand_x: (bool) + :param expand_y: If True the element will automatically expand in the Y direction to fill available space + :type expand_y: (bool) + :param grab: If True can grab this element and move the window around. Default is False + :type grab: (bool) + :param visible: set visibility state of the element + :type visible: (bool) + :param element_justification: All elements inside the Frame will have this justification 'left', 'right', 'center' are valid values + :type element_justification: (str) + :param vertical_alignment: Place the Frame at the 'top', 'center', 'bottom' of the row (can also use t,c,r). Defaults to no setting (tkinter decides) + :type vertical_alignment: (str) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + + + self.UseDictionary = False + self.ReturnValues = None + self.ReturnValuesList = [] + self.ReturnValuesDictionary = {} + self.DictionaryKeyCounter = 0 + self.ParentWindow = None + self.Rows = [] + # self.ParentForm = None + self.TKFrame = None + self.Title = title + self.Relief = relief + self.TitleLocation = title_location + self.BorderWidth = border_width + self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR + self.RightClickMenu = right_click_menu + self.ContainerElemementNumber = Window._GetAContainerNumber() + self.ElementJustification = element_justification + self.VerticalAlignment = vertical_alignment + self.Widget = None # type: tk.LabelFrame + self.Grab = grab + self.Layout(layout) + key = key if key is not None else k + sz = size if size != (None, None) else s + pad = pad if pad is not None else p + self.expand_x = expand_x + self.expand_y = expand_y + + super().__init__(ELEM_TYPE_FRAME, background_color=background_color, text_color=title_color, size=sz, + font=font, pad=pad, key=key, tooltip=tooltip, visible=visible, metadata=metadata) + return + + + def add_row(self, *args): + """ + Not recommended user call. Used to add rows of Elements to the Frame Element. + + :param *args: The list of elements for this row + :type *args: List[Element] + """ + NumRows = len(self.Rows) # number of existing rows is our row number + CurrentRowNumber = NumRows # this row's number + CurrentRow = [] # start with a blank row and build up + # ------------------------- Add the elements to a row ------------------------- # + for i, element in enumerate(args): # Loop through list of elements and add them to the row + if type(element) == list: + PopupError('Error creating Frame layout', + 'Layout has a LIST instead of an ELEMENT', + 'This means you have a badly placed ]', + 'The offensive list is:', + element, + 'This list will be stripped from your layout', + keep_on_top=True + ) + continue + elif callable(element) and not isinstance(element, Element): + PopupError('Error creating Frame layout', + 'Layout has a FUNCTION instead of an ELEMENT', + 'This likely means you are missing () from your layout', + 'The offensive list is:', + element, + 'This item will be stripped from your layout', + keep_on_top=True) + continue + if element.ParentContainer is not None: + warnings.warn( + '*** YOU ARE ATTEMPTING TO RESUSE AN ELEMENT IN YOUR LAYOUT! Once placed in a layout, an element cannot be used in another layout. ***', + UserWarning) + _error_popup_with_traceback('Error creating Frame layout', + 'The layout specified has already been used', + 'You MUST start witha "clean", unused layout every time you create a window', + 'The offensive Element = ', + element, + 'and has a key = ', element.Key, + 'This item will be stripped from your layout', + 'Hint - try printing your layout and matching the IDs "print(layout)"', + ) + continue + element.Position = (CurrentRowNumber, i) + element.ParentContainer = self + CurrentRow.append(element) + if element.Key is not None: + self.UseDictionary = True + # ------------------------- Append the row to list of Rows ------------------------- # + self.Rows.append(CurrentRow) + + def layout(self, rows): + """ + Can use like the Window.Layout method, but it's better to use the layout parameter when creating + + :param rows: The rows of Elements + :type rows: List[List[Element]] + :return: Used for chaining + :rtype: (Frame) + """ + + for row in rows: + try: + iter(row) + except TypeError: + PopupError('Error creating Frame layout', + 'Your row is not an iterable (e.g. a list)', + 'Instead of a list, the type found was {}'.format(type(row)), + 'The offensive row = ', + row, + 'This item will be stripped from your layout', keep_on_top=True, image=_random_error_emoji()) + continue + self.AddRow(*row) + return self + + def _GetElementAtLocation(self, location): + """ + Not user callable. Used to find the Element at a row, col position within the layout + + :param location: (row, column) position of the element to find in layout + :type location: (int, int) + :return: (Element) The element found at the location + :rtype: (Element) + """ + + (row_num, col_num) = location + row = self.Rows[row_num] + element = row[col_num] + return element + + def update(self, value=None, visible=None): + """ + Changes some of the settings for the Frame Element. Must call `Window.Read` or `Window.Finalize` prior + + :param value: New text value to show on frame + :type value: (Any) + :param visible: control visibility of element + :type visible: (bool) + """ + if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow + return + + if visible is False: + self.TKFrame.pack_forget() + elif visible is True: + self.TKFrame.pack(padx=self.pad_used[0], pady=self.pad_used[1]) + if value is not None: + self.TKFrame.config(text=str(value)) + if visible is not None: + self._visible = visible + + AddRow = add_row + Layout = layout + Update = update + + +Fr = Frame + + +# ---------------------------------------------------------------------- # +# Vertical Separator # +# ---------------------------------------------------------------------- # +class VerticalSeparator(Element): + """ + Vertical Separator Element draws a vertical line at the given location. It will span 1 "row". Usually paired with + Column Element if extra height is needed + """ + + def __init__(self, color=None, pad=None, p=None, key=None, k=None): + """ + :param color: Color of the line. Defaults to theme's text color. Can be name or #RRGGBB format + :type color: (str) + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + """ + key = key if key is not None else k + pad = pad if pad is not None else p + self.expand_x = None + self.expand_y = None + self.Orientation = 'vertical' # for now only vertical works + self.color = color if color is not None else theme_text_color() + super().__init__(ELEM_TYPE_SEPARATOR, pad=pad, key=key) + + +VSeperator = VerticalSeparator +VSeparator = VerticalSeparator +VSep = VerticalSeparator + + +# ---------------------------------------------------------------------- # +# Horizontal Separator # +# ---------------------------------------------------------------------- # +class HorizontalSeparator(Element): + """ + Horizontal Separator Element draws a Horizontal line at the given location. + """ + + def __init__(self, color=None, pad=None, p=None, key=None, k=None): + """ + :param color: Color of the line. Defaults to theme's text color. Can be name or #RRGGBB format + :type color: (str) + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + """ + + self.Orientation = 'horizontal' # for now only vertical works + self.color = color if color is not None else theme_text_color() + self.expand_x = True + self.expand_y = None + key = key if key is not None else k + pad = pad if pad is not None else p + + super().__init__(ELEM_TYPE_SEPARATOR, pad=pad, key=key) + + +HSeparator = HorizontalSeparator +HSep = HorizontalSeparator + + +# ---------------------------------------------------------------------- # +# Sizegrip # +# ---------------------------------------------------------------------- # +class Sizegrip(Element): + """ + Sizegrip element will be added to the bottom right corner of your window. + It should be placed on the last row of your window along with any other elements on that row. + The color will match the theme's background color. + """ + + def __init__(self, background_color=None, key=None): + """ + + :param background_color: color to use for the background of the grip + :type background_color: str + """ + bg = background_color if background_color is not None else theme_background_color() + + super().__init__(ELEM_TYPE_SIZEGRIP, background_color=bg,key=key) + + +SGrip = Sizegrip + + +# ---------------------------------------------------------------------- # +# Tab # +# ---------------------------------------------------------------------- # +class Tab(Element): + """ + Tab Element is another "Container" element that holds a layout and displays a tab with text. Used with TabGroup only + Tabs are never placed directly into a layout. They are always "Contained" in a TabGroup layout + """ + + def __init__(self, title, layout, title_color=None, background_color=None, font=None, pad=None, p=None, disabled=False, + border_width=None, key=None, k=None, tooltip=None, right_click_menu=None, expand_x=False, expand_y=False, visible=True, element_justification='left', image_source=None, image_subsample=None, metadata=None): + """ + :param title: text to show on the tab + :type title: (str) + :param layout: The element layout that will be shown in the tab + :type layout: List[List[Element]] + :param title_color: color of the tab text (note not currently working on tkinter) + :type title_color: (str) + :param background_color: color of background of the entire layout + :type background_color: (str) + :param font: NOT USED in the tkinter port + :type font: (str or (str, int[, str]) or None) + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param disabled: If True button will be created disabled + :type disabled: (bool) + :param border_width: NOT USED in tkinter port + :type border_width: (int) + :param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. + :type right_click_menu: List[List[ List[str] | str ]] + :param expand_x: If True the element will automatically expand in the X direction to fill available space + :type expand_x: (bool) + :param expand_y: If True the element will automatically expand in the Y direction to fill available space + :type expand_y: (bool) + :param visible: set visibility state of the element + :type visible: (bool) + :param element_justification: All elements inside the Tab will have this justification 'left', 'right', 'center' are valid values + :type element_justification: (str) + :param image_source: A filename or a base64 bytes of an image to place on the Tab + :type image_source: str | bytes | None + :param image_subsample: amount to reduce the size of the image. Divides the size by this number. 2=1/2, 3=1/3, 4=1/4, etc + :type image_subsample: (int) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + + filename = data = None + if image_source is not None: + if isinstance(image_source, bytes): + data = image_source + elif isinstance(image_source, str): + filename = image_source + else: + warnings.warn('Image element - source is not a valid type: {}'.format(type(image_source)), UserWarning) + + self.Filename = filename + self.Data = data + self.ImageSubsample = image_subsample + self.UseDictionary = False + self.ReturnValues = None + self.ReturnValuesList = [] + self.ReturnValuesDictionary = {} + self.DictionaryKeyCounter = 0 + self.ParentWindow = None + self.Rows = [] + self.TKFrame = None + self.Widget = None # type: tk.Frame + self.Title = title + self.BorderWidth = border_width + self.Disabled = disabled + self.ParentNotebook = None + self.TabID = None + self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR + self.RightClickMenu = right_click_menu + self.ContainerElemementNumber = Window._GetAContainerNumber() + self.ElementJustification = element_justification + key = key if key is not None else k + pad = pad if pad is not None else p + self.expand_x = expand_x + self.expand_y = expand_y + + self.Layout(layout) + + super().__init__(ELEM_TYPE_TAB, background_color=background_color, text_color=title_color, font=font, pad=pad, key=key, tooltip=tooltip, + visible=visible, metadata=metadata) + return + + def add_row(self, *args): + """ + Not recommended use call. Used to add rows of Elements to the Frame Element. + + :param *args: The list of elements for this row + :type *args: List[Element] + """ + NumRows = len(self.Rows) # number of existing rows is our row number + CurrentRowNumber = NumRows # this row's number + CurrentRow = [] # start with a blank row and build up + # ------------------------- Add the elements to a row ------------------------- # + for i, element in enumerate(args): # Loop through list of elements and add them to the row + if type(element) == list: + PopupError('Error creating Tab layout', + 'Layout has a LIST instead of an ELEMENT', + 'This means you have a badly placed ]', + 'The offensive list is:', + element, + 'This list will be stripped from your layout', keep_on_top=True, image=_random_error_emoji() + ) + continue + elif callable(element) and not isinstance(element, Element): + PopupError('Error creating Tab layout', + 'Layout has a FUNCTION instead of an ELEMENT', + 'This likely means you are missing () from your layout', + 'The offensive list is:', + element, + 'This item will be stripped from your layout', keep_on_top=True, image=_random_error_emoji()) + continue + if element.ParentContainer is not None: + warnings.warn( + '*** YOU ARE ATTEMPTING TO RESUSE AN ELEMENT IN YOUR LAYOUT! Once placed in a layout, an element cannot be used in another layout. ***', + UserWarning) + PopupError('Error creating Tab layout', + 'The layout specified has already been used', + 'You MUST start witha "clean", unused layout every time you create a window', + 'The offensive Element = ', + element, + 'and has a key = ', element.Key, + 'This item will be stripped from your layout', + 'Hint - try printing your layout and matching the IDs "print(layout)"', keep_on_top=True, image=_random_error_emoji()) + continue + element.Position = (CurrentRowNumber, i) + element.ParentContainer = self + CurrentRow.append(element) + if element.Key is not None: + self.UseDictionary = True + # ------------------------- Append the row to list of Rows ------------------------- # + self.Rows.append(CurrentRow) + + def layout(self, rows): + """ + Not user callable. Use layout parameter instead. Creates the layout using the supplied rows of Elements + + :param rows: List[List[Element]] The list of rows + :type rows: List[List[Element]] + :return: (Tab) used for chaining + :rtype: + """ + + for row in rows: + try: + iter(row) + except TypeError: + PopupError('Error creating Tab layout', + 'Your row is not an iterable (e.g. a list)', + 'Instead of a list, the type found was {}'.format(type(row)), + 'The offensive row = ', + row, + 'This item will be stripped from your layout', keep_on_top=True, image=_random_error_emoji()) + continue + self.AddRow(*row) + return self + + def update(self, title=None, disabled=None, visible=None): + """ + Changes some of the settings for the Tab Element. Must call `Window.Read` or `Window.Finalize` prior + + :param title: tab title + :type title: (str) + :param disabled: disable or enable state of the element + :type disabled: (bool) + :param visible: control visibility of element + :type visible: (bool) + """ + if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow + return + + state = 'normal' + if disabled is not None: + self.Disabled = disabled + if disabled: + state = 'disabled' + if visible is False: + state = 'hidden' + if visible is not None: + self._visible = visible + + self.ParentNotebook.tab(self.TabID, state=state) + + if title is not None: + self.Title = str(title) + self.ParentNotebook.tab(self.TabID, text=self.Title) + # self.ParentNotebook.tab(self.ContainerElemementNumber-1, text=self.Title) + + # if visible is False: + # self.ParentNotebook.pack_forget() + # elif visible is True: + # self.ParentNotebook.pack() + return self + + def _GetElementAtLocation(self, location): + """ + Not user callable. Used to find the Element at a row, col position within the layout + + :param location: (row, column) position of the element to find in layout + :type location: (int, int) + :return: The element found at the location + :rtype: (Element) + """ + + (row_num, col_num) = location + row = self.Rows[row_num] + element = row[col_num] + return element + + def select(self): + """ + Create a tkinter event that mimics user clicking on a tab. Must have called window.Finalize / Read first! + + """ + # Use a try in case the window has been destoyed + try: + self.ParentNotebook.select(self.TabID) + except Exception as e: + print('Exception Selecting Tab {}'.format(e)) + + AddRow = add_row + Layout = layout + Select = select + Update = update + + +# ---------------------------------------------------------------------- # +# TabGroup # +# ---------------------------------------------------------------------- # +class TabGroup(Element): + """ + TabGroup Element groups together your tabs into the group of tabs you see displayed in your window + """ + + def __init__(self, layout, tab_location=None, title_color=None, tab_background_color=None, selected_title_color=None, selected_background_color=None, + background_color=None, focus_color=None, font=None, change_submits=False, enable_events=False, pad=None, p=None, border_width=None, tab_border_width=None, theme=None, key=None, k=None, + size=(None, None), s=(None, None), tooltip=None, right_click_menu=None, expand_x=False, expand_y=False, visible=True, metadata=None): + """ + :param layout: Layout of Tabs. Different than normal layouts. ALL Tabs should be on first row + :type layout: List[List[Tab]] + :param tab_location: location that tabs will be displayed. Choices are left, right, top, bottom, lefttop, leftbottom, righttop, rightbottom, bottomleft, bottomright, topleft, topright + :type tab_location: (str) + :param title_color: color of text on tabs + :type title_color: (str) + :param tab_background_color: color of all tabs that are not selected + :type tab_background_color: (str) + :param selected_title_color: color of tab text when it is selected + :type selected_title_color: (str) + :param selected_background_color: color of tab when it is selected + :type selected_background_color: (str) + :param background_color: color of background area that tabs are located on + :type background_color: (str) + :param focus_color: color of focus indicator on the tabs + :type focus_color: (str) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param change_submits: * DEPRICATED DO NOT USE. Use `enable_events` instead + :type change_submits: (bool) + :param enable_events: If True then switching tabs will generate an Event + :type enable_events: (bool) + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param border_width: width of border around element in pixels + :type border_width: (int) + :param tab_border_width: width of border around the tabs + :type tab_border_width: (int) + :param theme: DEPRICATED - You can only specify themes using set options or when window is created. It's not possible to do it on an element basis + :type theme: (enum) + :param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param size: (width, height) w=pixels-wide, h=pixels-high. Either item in tuple can be None to indicate use the computed value and set only 1 direction + :type size: (int|None, int|None) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int|None, int|None) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. + :type right_click_menu: List[List[ List[str] | str ]] + :param expand_x: If True the element will automatically expand in the X direction to fill available space + :type expand_x: (bool) + :param expand_y: If True the element will automatically expand in the Y direction to fill available space + :type expand_y: (bool) + :param visible: set visibility state of the element + :type visible: (bool) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + + + self.UseDictionary = False + self.ReturnValues = None + self.ReturnValuesList = [] + self.ReturnValuesDictionary = {} + self.DictionaryKeyCounter = 0 + self.ParentWindow = None + self.SelectedTitleColor = selected_title_color if selected_title_color is not None else LOOK_AND_FEEL_TABLE[CURRENT_LOOK_AND_FEEL]['TEXT'] + self.SelectedBackgroundColor = selected_background_color if selected_background_color is not None else LOOK_AND_FEEL_TABLE[CURRENT_LOOK_AND_FEEL][ + 'BACKGROUND'] + title_color = title_color if title_color is not None else LOOK_AND_FEEL_TABLE[CURRENT_LOOK_AND_FEEL]['TEXT_INPUT'] + self.TabBackgroundColor = tab_background_color if tab_background_color is not None else LOOK_AND_FEEL_TABLE[CURRENT_LOOK_AND_FEEL]['INPUT'] + self.Rows = [] + self.TKNotebook = None # type: ttk.Notebook + self.Widget = None # type: ttk.Notebook + self.TabCount = 0 + self.BorderWidth = border_width + self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR + self.ChangeSubmits = change_submits or enable_events + self.TabLocation = tab_location + self.ElementJustification = 'left' + self.RightClickMenu = right_click_menu + self.TabBorderWidth = tab_border_width + self.FocusColor = focus_color + + key = key if key is not None else k + sz = size if size != (None, None) else s + pad = pad if pad is not None else p + self.expand_x = expand_x + self.expand_y = expand_y + + self.Layout(layout) + + super().__init__(ELEM_TYPE_TAB_GROUP, size=sz, background_color=background_color, text_color=title_color, font=font, + pad=pad, key=key, tooltip=tooltip, visible=visible, metadata=metadata) + return + + def add_row(self, *args): + """ + Not recommended user call. Used to add rows of Elements to the Frame Element. + + :param *args: The list of elements for this row + :type *args: List[Element] + """ + + NumRows = len(self.Rows) # number of existing rows is our row number + CurrentRowNumber = NumRows # this row's number + CurrentRow = [] # start with a blank row and build up + # ------------------------- Add the elements to a row ------------------------- # + for i, element in enumerate(args): # Loop through list of elements and add them to the row + if type(element) == list: + PopupError('Error creating Tab layout', + 'Layout has a LIST instead of an ELEMENT', + 'This means you have a badly placed ]', + 'The offensive list is:', + element, + 'This list will be stripped from your layout', keep_on_top=True, image=_random_error_emoji() + ) + continue + elif callable(element) and not isinstance(element, Element): + PopupError('Error creating Tab layout', + 'Layout has a FUNCTION instead of an ELEMENT', + 'This likely means you are missing () from your layout', + 'The offensive list is:', + element, + 'This item will be stripped from your layout', keep_on_top=True, image=_random_error_emoji()) + continue + if element.ParentContainer is not None: + warnings.warn( + '*** YOU ARE ATTEMPTING TO RESUSE AN ELEMENT IN YOUR LAYOUT! Once placed in a layout, an element cannot be used in another layout. ***', + UserWarning) + PopupError('Error creating Tab layout', + 'The layout specified has already been used', + 'You MUST start witha "clean", unused layout every time you create a window', + 'The offensive Element = ', + element, + 'and has a key = ', element.Key, + 'This item will be stripped from your layout', + 'Hint - try printing your layout and matching the IDs "print(layout)"', keep_on_top=True, image=_random_error_emoji()) + continue + element.Position = (CurrentRowNumber, i) + element.ParentContainer = self + CurrentRow.append(element) + if element.Key is not None: + self.UseDictionary = True + # ------------------------- Append the row to list of Rows ------------------------- # + self.Rows.append(CurrentRow) + + def layout(self, rows): + """ + Can use like the Window.Layout method, but it's better to use the layout parameter when creating + + :param rows: The rows of Elements + :type rows: List[List[Element]] + :return: Used for chaining + :rtype: (Frame) + """ + for row in rows: + try: + iter(row) + except TypeError: + PopupError('Error creating Tab layout', + 'Your row is not an iterable (e.g. a list)', + 'Instead of a list, the type found was {}'.format(type(row)), + 'The offensive row = ', + row, + 'This item will be stripped from your layout', keep_on_top=True, image=_random_error_emoji()) + continue + self.AddRow(*row) + return self + + def _GetElementAtLocation(self, location): + """ + Not user callable. Used to find the Element at a row, col position within the layout + + :param location: (row, column) position of the element to find in layout + :type location: (int, int) + :return: The element found at the location + :rtype: (Element) + """ + + (row_num, col_num) = location + row = self.Rows[row_num] + element = row[col_num] + return element + + def find_key_from_tab_name(self, tab_name): + """ + Searches through the layout to find the key that matches the text on the tab. Implies names should be unique + + :param tab_name: name of a tab + :type tab_name: str + :return: Returns the key or None if no key found + :rtype: key | None + """ + for row in self.Rows: + for element in row: + if element.Title == tab_name: + return element.Key + return None + + def get(self): + """ + Returns the current value for the Tab Group, which will be the currently selected tab's KEY or the text on + the tab if no key is defined. Returns None if an error occurs. + Note that this is exactly the same data that would be returned from a call to Window.Read. Are you sure you + are using this method correctly? + + :return: The key of the currently selected tab or the tab's text if it has no key + :rtype: Any | None + """ + + try: + value = self.TKNotebook.tab(self.TKNotebook.index('current'))['text'] + tab_key = self.FindKeyFromTabName(value) + if tab_key is not None: + value = tab_key + except: + value = None + return value + + def add_tab(self, tab_element): + """ + Add a new tab to an existing TabGroup + This call was written so that tabs can be added at runtime as your user performs operations. + Your Window should already be created and finalized. + + :param tab_element: A Tab Element that has a layout in it + :type tab_element: Tab + """ + + self.add_row(tab_element) + tab_element.TKFrame = tab_element.Widget = tk.Frame(self.TKNotebook) + form = self.ParentForm + form._BuildKeyDictForWindow(form, tab_element, form.AllKeysDict) + form.AllKeysDict[tab_element.Key] = tab_element + # Pack the tab's layout into the tab. NOTE - This does NOT pack the Tab itself... for that see below... + PackFormIntoFrame(tab_element, tab_element.TKFrame, self.ParentForm) + + # - This is below - Perform the same operation that is performed when a Tab is packed into the window. + # If there's an image in the tab, then do the imagey-stuff + # ------------------- start of imagey-stuff ------------------- + try: + if tab_element.Filename is not None: + photo = tk.PhotoImage(file=tab_element.Filename) + elif tab_element.Data is not None: + photo = tk.PhotoImage(data=tab_element.Data) + else: + photo = None + + if tab_element.ImageSubsample and photo is not None: + photo = photo.subsample(tab_element.ImageSubsample) + # print('*ERROR laying out form.... Image Element has no image specified*') + except Exception as e: + photo = None + _error_popup_with_traceback('Your Window has an Tab Element with an IMAGE problem', + 'The traceback will show you the Window with the problem layout', + 'Look in this Window\'s layout for an Image tab_element that has a key of {}'.format(tab_element.Key), + 'The error occuring is:', e) + + tab_element.photo = photo + # add the label + if photo is not None: + width, height = photo.width(), photo.height() + tab_element.tktext_label = tk.Label(tab_element.ParentRowFrame, image=photo, width=width, height=height, bd=0) + else: + tab_element.tktext_label = tk.Label(tab_element.ParentRowFrame, bd=0) + # ------------------- end of imagey-stuff ------------------- + + state = 'normal' + if tab_element.Disabled: + state = 'disabled' + if tab_element.visible is False: + state = 'hidden' + if photo is not None: + self.TKNotebook.add(tab_element.TKFrame, text=tab_element.Title, compound=tk.LEFT, state=state, image=photo) + else: + self.TKNotebook.add(tab_element.TKFrame, text=tab_element.Title, state=state) + tab_element.ParentNotebook = self.TKNotebook + tab_element.TabID = self.TabCount + tab_element.ParentForm = self.ParentForm + self.TabCount += 1 + if tab_element.BackgroundColor != COLOR_SYSTEM_DEFAULT and tab_element.BackgroundColor is not None: + tab_element.TKFrame.configure(background=tab_element.BackgroundColor, highlightbackground=tab_element.BackgroundColor, + highlightcolor=tab_element.BackgroundColor) + if tab_element.BorderWidth is not None: + tab_element.TKFrame.configure(borderwidth=tab_element.BorderWidth) + if tab_element.Tooltip is not None: + tab_element.TooltipObject = ToolTip(tab_element.TKFrame, text=tab_element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) + _add_right_click_menu(tab_element, form) + + AddRow = add_row + FindKeyFromTabName = find_key_from_tab_name + Get = get + Layout = layout + + +# ---------------------------------------------------------------------- # +# Slider # +# ---------------------------------------------------------------------- # +class Slider(Element): + """ + A slider, horizontal or vertical + """ + + def __init__(self, range=(None, None), default_value=None, resolution=None, tick_interval=None, orientation=None, + disable_number_display=False, border_width=None, relief=None, change_submits=False, + enable_events=False, disabled=False, size=(None, None), s=(None, None), font=None, background_color=None, + text_color=None, trough_color=None, key=None, k=None, pad=None, p=None, expand_x=False, expand_y=False, tooltip=None, visible=True, metadata=None): + """ + :param range: slider's range (min value, max value) + :type range: (int, int) | Tuple[float, float] + :param default_value: starting value for the slider + :type default_value: int | float + :param resolution: the smallest amount the slider can be moved + :type resolution: int | float + :param tick_interval: how often a visible tick should be shown next to slider + :type tick_interval: int | float + :param orientation: 'horizontal' or 'vertical' ('h' or 'v' also work) + :type orientation: (str) + :param disable_number_display: if True no number will be displayed by the Slider Element + :type disable_number_display: (bool) + :param border_width: width of border around element in pixels + :type border_width: (int) + :param relief: relief style. Use constants - RELIEF_RAISED RELIEF_SUNKEN RELIEF_FLAT RELIEF_RIDGE RELIEF_GROOVE RELIEF_SOLID + :type relief: str | None + :param change_submits: * DEPRICATED DO NOT USE. Use `enable_events` instead + :type change_submits: (bool) + :param enable_events: If True then moving the slider will generate an Event + :type enable_events: (bool) + :param disabled: set disable state for element + :type disabled: (bool) + :param size: (l=length chars/rows, w=width pixels) + :type size: (int, int) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param background_color: color of slider's background + :type background_color: (str) + :param text_color: color of the slider's text + :type text_color: (str) + :param trough_color: color of the slider's trough + :type trough_color: (str) + :param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param expand_x: If True the element will automatically expand in the X direction to fill available space + :type expand_x: (bool) + :param expand_y: If True the element will automatically expand in the Y direction to fill available space + :type expand_y: (bool) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param visible: set visibility state of the element + :type visible: (bool) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + + self.TKScale = self.Widget = None # type: tk.Scale + self.Range = (1, 10) if range == (None, None) else range + self.DefaultValue = self.Range[0] if default_value is None else default_value + self.Orientation = orientation if orientation else DEFAULT_SLIDER_ORIENTATION + self.BorderWidth = border_width if border_width else DEFAULT_SLIDER_BORDER_WIDTH + self.Relief = relief if relief else DEFAULT_SLIDER_RELIEF + self.Resolution = 1 if resolution is None else resolution + self.ChangeSubmits = change_submits or enable_events + self.Disabled = disabled + self.TickInterval = tick_interval + self.DisableNumericDisplay = disable_number_display + self.TroughColor = trough_color or DEFAULT_SCROLLBAR_COLOR + sz = size if size != (None, None) else s + temp_size = sz + if temp_size == (None, None): + temp_size = (20, 20) if self.Orientation.startswith('h') else (8, 20) + key = key if key is not None else k + pad = pad if pad is not None else p + self.expand_x = expand_x + self.expand_y = expand_y + + super().__init__(ELEM_TYPE_INPUT_SLIDER, size=temp_size, font=font, background_color=background_color, + text_color=text_color, key=key, pad=pad, tooltip=tooltip, visible=visible, metadata=metadata) + return + + def update(self, value=None, range=(None, None), disabled=None, visible=None): + """ + Changes some of the settings for the Slider Element. Must call `Window.Read` or `Window.Finalize` prior + + :param value: sets current slider value + :type value: int | float + :param range: Sets a new range for slider + :type range: (int, int) | Tuple[float, float + :param disabled: disable or enable state of the element + :type disabled: (bool) + :param visible: control visibility of element + :type visible: (bool) + """ + if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow + return + + if value is not None: + try: + self.TKIntVar.set(value) + except: + pass + self.DefaultValue = value + if disabled == True: + self.TKScale['state'] = 'disabled' + elif disabled == False: + self.TKScale['state'] = 'normal' + if visible is False: + self.TKScale.pack_forget() + elif visible is True: + self.TKScale.pack(padx=self.pad_used[0], pady=self.pad_used[1]) + if range != (None, None): + self.TKScale.config(from_=range[0], to_=range[1]) + if visible is not None: + self._visible = visible + + def _SliderChangedHandler(self, event): + """ + Not user callable. Callback function for when slider is moved. + + :param event: (event) the event data provided by tkinter. Unknown format. Not used. + :type event: + """ + + if self.Key is not None: + self.ParentForm.LastButtonClicked = self.Key + else: + self.ParentForm.LastButtonClicked = '' + self.ParentForm.FormRemainedOpen = True + # if self.ParentForm.CurrentlyRunningMainloop: + # self.ParentForm.TKroot.quit() # kick the users out of the mainloop + _exit_mainloop(self.ParentForm) + + Update = update + + +Sl = Slider + + +# ---------------------------------------------------------------------- # +# TkFixedFrame (Used by Column) # +# ---------------------------------------------------------------------- # +class TkFixedFrame(tk.Frame): + """ + A tkinter frame that is used with Column Elements that do not have a scrollbar + """ + + def __init__(self, master, **kwargs): + """ + :param master: The parent widget + :type master: (tk.Widget) + :param **kwargs: The keyword args + :type **kwargs: + """ + tk.Frame.__init__(self, master, **kwargs) + + self.canvas = tk.Canvas(self) + + self.canvas.pack(side="left", fill="both", expand=True) + + # reset the view + self.canvas.xview_moveto(0) + self.canvas.yview_moveto(0) + + # create a frame inside the canvas which will be scrolled with it + self.TKFrame = tk.Frame(self.canvas, **kwargs) + self.frame_id = self.canvas.create_window(0, 0, window=self.TKFrame, anchor="nw") + self.canvas.config(borderwidth=0, highlightthickness=0) + self.TKFrame.config(borderwidth=0, highlightthickness=0) + self.config(borderwidth=0, highlightthickness=0) + + +# ---------------------------------------------------------------------- # +# TkScrollableFrame (Used by Column) # +# ---------------------------------------------------------------------- # +class TkScrollableFrame(tk.Frame): + """ + A frame with one or two scrollbars. Used to make Columns with scrollbars + """ + + def __init__(self, master, vertical_only, **kwargs): + """ + :param master: The parent widget + :type master: (tk.Widget) + :param vertical_only: if True the only a vertical scrollbar will be shown + :type vertical_only: (bool) + """ + tk.Frame.__init__(self, master, **kwargs) + # create a canvas object and a vertical scrollbar for scrolling it + + # Okay, we're gonna make a list. Containing the y-min, x-min, y-max, and x-max of the frame + + self.vscrollbar = tk.Scrollbar(self, orient=tk.VERTICAL) + self.vscrollbar.pack(side='right', fill="y", expand="false") + + if not vertical_only: + self.hscrollbar = tk.Scrollbar(self, orient=tk.HORIZONTAL) + self.hscrollbar.pack(side='bottom', fill="x", expand="false") + self.canvas = tk.Canvas(self, yscrollcommand=self.vscrollbar.set, xscrollcommand=self.hscrollbar.set) + else: + self.canvas = tk.Canvas(self, yscrollcommand=self.vscrollbar.set) + + self.canvas.pack(side="left", fill="both", expand=True) + + self.vscrollbar.config(command=self.canvas.yview) + if not vertical_only: + self.hscrollbar.config(command=self.canvas.xview) + + # reset the view + self.canvas.xview_moveto(0) + self.canvas.yview_moveto(0) + + # create a frame inside the canvas which will be scrolled with it + self.TKFrame = tk.Frame(self.canvas, **kwargs) + self.frame_id = self.canvas.create_window(0, 0, window=self.TKFrame, anchor="nw") + self.canvas.config(borderwidth=0, highlightthickness=0) + self.TKFrame.config(borderwidth=0, highlightthickness=0) + self.config(borderwidth=0, highlightthickness=0) + + # Canvas can be: master, canvas, TKFrame + + # Chr0nic + + self.unhookMouseWheel(None) + self.TKFrame.bind("", self.hookMouseWheel) + self.TKFrame.bind("", self.unhookMouseWheel) + + # self.canvas.bind_all('<4>', self.yscroll, add='+') + # self.canvas.bind_all('<5>', self.yscroll, add='+') + # self.canvas.bind_all("", self.yscroll, add='+') + # self.canvas.bind_all("", self.xscroll, add='+') + + self.bind('', self.set_scrollregion) + + # Chr0nic + def hookMouseWheel(self, e): + # print("enter") + VarHolder.canvas_holder = self.canvas + self.TKFrame.bind_all('<4>', self.yscroll, add='+') + self.TKFrame.bind_all('<5>', self.yscroll, add='+') + self.TKFrame.bind_all("", self.yscroll, add='+') + self.TKFrame.bind_all("", self.xscroll, add='+') + + # Chr0nic + def unhookMouseWheel(self, e): + # print("leave") + VarHolder.canvas_holder = None + self.TKFrame.unbind_all('<4>') + self.TKFrame.unbind_all('<5>') + self.TKFrame.unbind_all("") + self.TKFrame.unbind_all("") + + def resize_frame(self, e): + self.canvas.itemconfig(self.frame_id, height=e.height, width=e.width) + + def yscroll(self, event): + if self.canvas.yview() == (0.0, 1.0): + return + if event.num == 5 or event.delta < 0: + self.canvas.yview_scroll(1, "unit") + elif event.num == 4 or event.delta > 0: + self.canvas.yview_scroll(-1, "unit") + + def xscroll(self, event): + if event.num == 5 or event.delta < 0: + self.canvas.xview_scroll(1, "unit") + elif event.num == 4 or event.delta > 0: + self.canvas.xview_scroll(-1, "unit") + + def bind_mouse_scroll(self, parent, mode): + # ~~ Windows only + parent.bind("", mode) + # ~~ Unix only + parent.bind("", mode) + parent.bind("", mode) + + def set_scrollregion(self, event=None): + """ Set the scroll region on the canvas """ + self.canvas.configure(scrollregion=self.canvas.bbox('all')) + + +# ---------------------------------------------------------------------- # +# Column # +# ---------------------------------------------------------------------- # +class Column(Element): + """ + A container element that is used to create a layout within your window's layout + """ + + def __init__(self, layout, background_color=None, size=(None, None), s=(None, None), pad=None, p=None, scrollable=False, + vertical_scroll_only=False, right_click_menu=None, key=None, k=None, visible=True, justification=None, element_justification=None, + vertical_alignment=None, grab=None, expand_x=None, expand_y=None, metadata=None): + """ + :param layout: Layout that will be shown in the Column container + :type layout: List[List[Element]] + :param background_color: color of background of entire Column + :type background_color: (str) + :param size: (width, height) size in pixels (doesn't work quite right, sometimes only 1 dimension is set by tkinter. Use a Sizer Element to help set sizes + :type size: (int | None, int | None) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int | None, int | None) + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param scrollable: if True then scrollbars will be added to the column + :type scrollable: (bool) + :param vertical_scroll_only: if Truen then no horizontal scrollbar will be shown + :type vertical_scroll_only: (bool) + :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. + :type right_click_menu: List[List[ List[str] | str ]] + :param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param visible: set visibility state of the element + :type visible: (bool) + :param justification: set justification for the Column itself. Note entire row containing the Column will be affected + :type justification: (str) + :param element_justification: All elements inside the Column will have this justification 'left', 'right', 'center' are valid values + :type element_justification: (str) + :param vertical_alignment: Place the column at the 'top', 'center', 'bottom' of the row (can also use t,c,r). Defaults to no setting (tkinter decides) + :type vertical_alignment: (str) + :param grab: If True can grab this element and move the window around. Default is False + :type grab: (bool) + :param expand_x: If True the column will automatically expand in the X direction to fill available space + :type expand_x: (bool) + :param expand_y: If True the column will automatically expand in the Y direction to fill available space + :type expand_y: (bool) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + + self.UseDictionary = False + self.ReturnValues = None + self.ReturnValuesList = [] + self.ReturnValuesDictionary = {} + self.DictionaryKeyCounter = 0 + self.ParentWindow = None + self.ParentPanedWindow = None + self.Rows = [] + self.TKFrame = None + self.TKColFrame = None # type: tk.Frame + self.Scrollable = scrollable + self.VerticalScrollOnly = vertical_scroll_only + + self.RightClickMenu = right_click_menu + bg = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR + self.ContainerElemementNumber = Window._GetAContainerNumber() + self.ElementJustification = element_justification + self.Justification = justification + self.VerticalAlignment = vertical_alignment + key = key if key is not None else k + self.Grab = grab + self.ExpandX = expand_x + self.ExpandY = expand_y + self.Layout(layout) + sz = size if size != (None, None) else s + pad = pad if pad is not None else p + + super().__init__(ELEM_TYPE_COLUMN, background_color=bg, size=sz, pad=pad, key=key, visible=visible, metadata=metadata) + return + + def add_row(self, *args): + """ + Not recommended user call. Used to add rows of Elements to the Column Element. + + :param *args: The list of elements for this row + :type *args: List[Element] + """ + + NumRows = len(self.Rows) # number of existing rows is our row number + CurrentRowNumber = NumRows # this row's number + CurrentRow = [] # start with a blank row and build up + # ------------------------- Add the elements to a row ------------------------- # + for i, element in enumerate(args): # Loop through list of elements and add them to the row + if type(element) == list: + PopupError('Error creating Column layout', + 'Layout has a LIST instead of an ELEMENT', + 'This means you have a badly placed ]', + 'The offensive list is:', + element, + 'This list will be stripped from your layout', keep_on_top=True, image=_random_error_emoji() + ) + continue + elif callable(element) and not isinstance(element, Element): + PopupError('Error creating Column layout', + 'Layout has a FUNCTION instead of an ELEMENT', + 'This likely means you are missing () from your layout', + 'The offensive list is:', + element, + 'This item will be stripped from your layout', keep_on_top=True, image=_random_error_emoji()) + continue + if element.ParentContainer is not None: + warnings.warn( + '*** YOU ARE ATTEMPTING TO RESUSE AN ELEMENT IN YOUR LAYOUT! Once placed in a layout, an element cannot be used in another layout. ***', + UserWarning) + PopupError('Error creating Column layout', + 'The layout specified has already been used', + 'You MUST start witha "clean", unused layout every time you create a window', + 'The offensive Element = ', + element, + 'and has a key = ', element.Key, + 'This item will be stripped from your layout', + 'Hint - try printing your layout and matching the IDs "print(layout)"', keep_on_top=True, image=_random_error_emoji()) + continue + element.Position = (CurrentRowNumber, i) + element.ParentContainer = self + CurrentRow.append(element) + if element.Key is not None: + self.UseDictionary = True + # ------------------------- Append the row to list of Rows ------------------------- # + self.Rows.append(CurrentRow) + + def layout(self, rows): + """ + Can use like the Window.Layout method, but it's better to use the layout parameter when creating + + :param rows: The rows of Elements + :type rows: List[List[Element]] + :return: Used for chaining + :rtype: (Column) + """ + + for row in rows: + try: + iter(row) + except TypeError: + PopupError('Error creating Column layout', + 'Your row is not an iterable (e.g. a list)', + 'Instead of a list, the type found was {}'.format(type(row)), + 'The offensive row = ', + row, + 'This item will be stripped from your layout', keep_on_top=True, image=_random_error_emoji()) + continue + self.AddRow(*row) + return self + + def _GetElementAtLocation(self, location): + """ + Not user callable. Used to find the Element at a row, col position within the layout + + :param location: (row, column) position of the element to find in layout + :type location: (int, int) + :return: The element found at the location + :rtype: (Element) + """ + + (row_num, col_num) = location + row = self.Rows[row_num] + element = row[col_num] + return element + + def update(self, visible=None): + """ + Changes some of the settings for the Column Element. Must call `Window.Read` or `Window.Finalize` prior + + :param visible: control visibility of element + :type visible: (bool) + """ + if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow + return + + if self.ExpandX and self.ExpandY: + expand = tk.BOTH + elif self.ExpandX: + expand = tk.X + elif self.ExpandY: + expand = tk.Y + else: + expand = None + + if visible is False: + if self.TKColFrame: + self.TKColFrame.pack_forget() + if self.ParentPanedWindow: + self.ParentPanedWindow.remove(self.TKColFrame) + elif visible is True: + if self.TKColFrame: + self.TKColFrame.pack(padx=self.pad_used[0], pady=self.pad_used[1], fill=expand) + if self.ParentPanedWindow: + self.ParentPanedWindow.add(self.TKColFrame) + if visible is not None: + self._visible = visible + + def contents_changed(self): + """ + When a scrollable column has part of its layout changed by making elements visible or invisible or the + layout is extended for the Column, then this method needs to be called so that the new scroll area + is computed to match the new contents. + """ + self.TKColFrame.canvas.config(scrollregion=self.TKColFrame.canvas.bbox('all')) + + AddRow = add_row + Layout = layout + Update = update + + +Col = Column + + +# ---------------------------------------------------------------------- # +# Pane # +# ---------------------------------------------------------------------- # +class Pane(Element): + """ + A sliding Pane that is unique to tkinter. Uses Columns to create individual panes + """ + + def __init__(self, pane_list, background_color=None, size=(None, None), s=(None, None), pad=None, p=None, orientation='vertical', + show_handle=True, relief=RELIEF_RAISED, handle_size=None, border_width=None, key=None, k=None, expand_x=None, expand_y=None, visible=True, metadata=None): + """ + :param pane_list: Must be a list of Column Elements. Each Column supplied becomes one pane that's shown + :type pane_list: List[Column] | Tuple[Column] + :param background_color: color of background + :type background_color: (str) + :param size: (width, height) w=characters-wide, h=rows-high How much room to reserve for the Pane + :type size: (int, int) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param orientation: 'horizontal' or 'vertical' or ('h' or 'v'). Direction the Pane should slide + :type orientation: (str) + :param show_handle: if True, the handle is drawn that makes it easier to grab and slide + :type show_handle: (bool) + :param relief: relief style. Values are same as other elements that use relief values. RELIEF_RAISED RELIEF_SUNKEN RELIEF_FLAT RELIEF_RIDGE RELIEF_GROOVE RELIEF_SOLID + :type relief: (enum) + :param handle_size: Size of the handle in pixels + :type handle_size: (int) + :param border_width: width of border around element in pixels + :type border_width: (int) + :param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param expand_x: If True the column will automatically expand in the X direction to fill available space + :type expand_x: (bool) + :param expand_y: If True the column will automatically expand in the Y direction to fill available space + :type expand_y: (bool) + :param visible: set visibility state of the element + :type visible: (bool) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + + + self.UseDictionary = False + self.ReturnValues = None + self.ReturnValuesList = [] + self.ReturnValuesDictionary = {} + self.DictionaryKeyCounter = 0 + self.ParentWindow = None + self.Rows = [] + self.TKFrame = None + self.PanedWindow = None + self.Orientation = orientation + self.PaneList = pane_list + self.ShowHandle = show_handle + self.Relief = relief + self.HandleSize = handle_size or 8 + self.BorderDepth = border_width + bg = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR + + self.Rows = [pane_list] + key = key if key is not None else k + sz = size if size != (None, None) else s + pad = pad if pad is not None else p + self.expand_x = expand_x + self.expand_y = expand_y + + super().__init__(ELEM_TYPE_PANE, background_color=bg, size=sz, pad=pad, key=key, visible=visible, metadata=metadata) + return + + def update(self, visible=None): + """ + Changes some of the settings for the Pane Element. Must call `Window.Read` or `Window.Finalize` prior + + :param visible: control visibility of element + :type visible: (bool) + """ + if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow + return + + if visible is False: + self.PanedWindow.pack_forget() + elif visible is True: + self.PanedWindow.pack(padx=self.pad_used[0], pady=self.pad_used[1]) + if visible is not None: + self._visible = visible + + Update = update + + +# ---------------------------------------------------------------------- # +# Calendar # +# ---------------------------------------------------------------------- # +class TKCalendar(ttk.Frame): + """ + This code was shamelessly lifted from moshekaplan's repository - moshekaplan/tkinter_components + NONE of this code is user callable. Stay away! + """ + # XXX ToDo: cget and configure + + datetime = calendar.datetime.datetime + timedelta = calendar.datetime.timedelta + + def __init__(self, master=None, target_element=None, close_when_chosen=True, default_date=(None, None, None), **kw): + """WIDGET-SPECIFIC OPTIONS: locale, firstweekday, year, month, selectbackground, selectforeground """ + self._TargetElement = target_element + default_mon, default_day, default_year = default_date + # remove custom options from kw before initializating ttk.Frame + fwday = kw.pop('firstweekday', calendar.MONDAY) + year = kw.pop('year', default_year or self.datetime.now().year) + month = kw.pop('month', default_mon or self.datetime.now().month) + locale = kw.pop('locale', None) + sel_bg = kw.pop('selectbackground', '#ecffc4') + sel_fg = kw.pop('selectforeground', '#05640e') + self.format = kw.pop('format') + if self.format is None: + self.format = '%Y-%m-%d %H:%M:%S' + + self._date = self.datetime(year, month, default_day or 1) + self._selection = None # no date selected + self._master = master + self.close_when_chosen = close_when_chosen + ttk.Frame.__init__(self, master, **kw) + + # instantiate proper calendar class + if locale is None: + self._cal = calendar.TextCalendar(fwday) + else: + self._cal = calendar.LocaleTextCalendar(fwday, locale) + + self.__setup_styles() # creates custom styles + self.__place_widgets() # pack/grid used widgets + self.__config_calendar() # adjust calendar columns and setup tags + # configure a canvas, and proper bindings, for selecting dates + self.__setup_selection(sel_bg, sel_fg) + + # store items ids, used for insertion later + self._items = [self._calendar.insert('', 'end', values='') + for _ in range(6)] + # insert dates in the currently empty calendar + self._build_calendar() + + def __setitem__(self, item, value): + if item in ('year', 'month'): + raise AttributeError("attribute '%s' is not writeable" % item) + elif item == 'selectbackground': + self._canvas['background'] = value + elif item == 'selectforeground': + self._canvas.itemconfigure(self._canvas.text, item=value) + else: + ttk.Frame.__setitem__(self, item, value) + + def __getitem__(self, item): + if item in ('year', 'month'): + return getattr(self._date, item) + elif item == 'selectbackground': + return self._canvas['background'] + elif item == 'selectforeground': + return self._canvas.itemcget(self._canvas.text, 'fill') + else: + r = ttk.tclobjs_to_py({item: ttk.Frame.__getitem__(self, item)}) + return r[item] + + def __setup_styles(self): + # custom ttk styles + style = ttk.Style(self.master) + arrow_layout = lambda dir: ( + [('Button.focus', {'children': [('Button.%sarrow' % dir, None)]})] + ) + style.layout('L.TButton', arrow_layout('left')) + style.layout('R.TButton', arrow_layout('right')) + + def __place_widgets(self): + # header frame and its widgets + hframe = ttk.Frame(self) + lbtn = ttk.Button(hframe, style='L.TButton', command=self._prev_month) + rbtn = ttk.Button(hframe, style='R.TButton', command=self._next_month) + self._header = ttk.Label(hframe, width=15, anchor='center') + # the calendar + self._calendar = ttk.Treeview(self, show='', selectmode='none', height=7) + + # pack the widgets + hframe.pack(in_=self, side='top', pady=4, anchor='center') + lbtn.grid(in_=hframe) + self._header.grid(in_=hframe, column=1, row=0, padx=12) + rbtn.grid(in_=hframe, column=2, row=0) + self._calendar.pack(in_=self, expand=1, fill='both', side='bottom') + + def __config_calendar(self): + cols = self._cal.formatweekheader(3).split() + self._calendar['columns'] = cols + self._calendar.tag_configure('header', background='grey90') + self._calendar.insert('', 'end', values=cols, tag='header') + # adjust its columns width + font = tkinter.font.Font() + maxwidth = max(font.measure(col) for col in cols) + for col in cols: + self._calendar.column(col, width=maxwidth, minwidth=maxwidth, + anchor='e') + + def __setup_selection(self, sel_bg, sel_fg): + self._font = tkinter.font.Font() + self._canvas = canvas = tk.Canvas(self._calendar, + background=sel_bg, borderwidth=0, highlightthickness=0) + canvas.text = canvas.create_text(0, 0, fill=sel_fg, anchor='w') + + canvas.bind('', lambda evt: canvas.place_forget()) + self._calendar.bind('', lambda evt: canvas.place_forget()) + self._calendar.bind('', self._pressed) + + def __minsize(self, evt): + width, height = self._calendar.master.geometry().split('x') + height = height[:height.index('+')] + self._calendar.master.minsize(width, height) + + def _build_calendar(self): + year, month = self._date.year, self._date.month + + # update header text (Month, YEAR) + header = self._cal.formatmonthname(year, month, 0) + self._header['text'] = header.title() + + # update calendar shown dates + cal = self._cal.monthdayscalendar(year, month) + for indx, item in enumerate(self._items): + week = cal[indx] if indx < len(cal) else [] + fmt_week = [('%02d' % day) if day else '' for day in week] + self._calendar.item(item, values=fmt_week) + + def _show_selection(self, text, bbox): + """ Configure canvas for a new selection. """ + x, y, width, height = bbox + + textw = self._font.measure(text) + + canvas = self._canvas + canvas.configure(width=width, height=height) + canvas.coords(canvas.text, width - textw, height / 2 - 1) + canvas.itemconfigure(canvas.text, text=text) + canvas.place(in_=self._calendar, x=x, y=y) + + # Callbacks + + def _pressed(self, evt): + """ Clicked somewhere in the calendar. """ + x, y, widget = evt.x, evt.y, evt.widget + item = widget.identify_row(y) + column = widget.identify_column(x) + + if not column or not item in self._items: + # clicked in the weekdays row or just outside the columns + return + + item_values = widget.item(item)['values'] + if not len(item_values): # row is empty for this month + return + + text = item_values[int(column[1]) - 1] + if not text: # date is empty + return + + bbox = widget.bbox(item, column) + if not bbox: # calendar not visible yet + return + + # update and then show selection + text = '%02d' % text + self._selection = (text, item, column) + self._show_selection(text, bbox) + year, month = self._date.year, self._date.month + now = self.datetime.now() + try: + self._TargetElement.Update( + self.datetime(year, month, int(self._selection[0]), now.hour, now.minute, now.second).strftime( + self.format)) + if self._TargetElement.ChangeSubmits: + self._TargetElement.ParentForm.LastButtonClicked = self._TargetElement.Key + self._TargetElement.ParentForm.FormRemainedOpen = True + self._TargetElement.ParentForm.TKroot.quit() # kick the users out of the mainloop + except: + pass + if self.close_when_chosen: + self._master.destroy() + + def _prev_month(self): + """Updated calendar to show the previous month.""" + self._canvas.place_forget() + + self._date = self._date - self.timedelta(days=1) + self._date = self.datetime(self._date.year, self._date.month, 1) + self._build_calendar() # reconstuct calendar + + def _next_month(self): + """Update calendar to show the next month.""" + self._canvas.place_forget() + + year, month = self._date.year, self._date.month + self._date = self._date + self.timedelta( + days=calendar.monthrange(year, month)[1] + 1) + self._date = self.datetime(self._date.year, self._date.month, 1) + self._build_calendar() # reconstruct calendar + + # Properties + + @property + def selection(self): + if not self._selection: + return None + + year, month = self._date.year, self._date.month + return self.datetime(year, month, int(self._selection[0])) + + +# ---------------------------------------------------------------------- # +# Menu # +# ---------------------------------------------------------------------- # +class Menu(Element): + """ + Menu Element is the Element that provides a Menu Bar that goes across the top of the window, just below titlebar. + Here is an example layout. The "&" are shortcut keys ALT+key. + Is a List of - "Item String" + List + Where Item String is what will be displayed on the Menubar itself. + The List that follows the item represents the items that are shown then Menu item is clicked + Notice how an "entry" in a mennu can be a list which means it branches out and shows another menu, etc. (resursive) + menu_def = [['&File', ['!&Open', '&Save::savekey', '---', '&Properties', 'E&xit']], + ['!&Edit', ['!&Paste', ['Special', 'Normal', ], 'Undo'], ], + ['&Debugger', ['Popout', 'Launch Debugger']], + ['&Toolbar', ['Command &1', 'Command &2', 'Command &3', 'Command &4']], + ['&Help', '&About...'], ] + Finally, "keys" can be added to entries so make them unique. The "Save" entry has a key associated with it. You + can see it has a "::" which signifies the beginning of a key. The user will not see the key portion when the + menu is shown. The key portion is returned as part of the event. + """ + + def __init__(self, menu_definition, background_color=None, text_color=None, disabled_text_color=None, size=(None, None), s=(None, None), tearoff=False, + font=None, pad=None, p=None, key=None, k=None, visible=True, metadata=None): + """ + :param menu_definition: The Menu definition specified using lists (docs explain the format) + :type menu_definition: List[List[Tuple[str, List[str]]] + :param background_color: color of the background + :type background_color: (str) + :param text_color: element's text color. Can be in #RRGGBB format or a color name "black" + :type text_color: (str) + :param disabled_text_color: color to use for text when item is disabled. Can be in #RRGGBB format or a color name "black" + :type disabled_text_color: (str) + :param size: Not used in the tkinter port + :type size: (int, int) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) + :param tearoff: if True, then can tear the menu off from the window ans use as a floating window. Very cool effect + :type tearoff: (bool) + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param visible: set visibility state of the element + :type visible: (bool) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + + self.BackgroundColor = background_color if background_color is not None else theme_input_background_color() + self.TextColor = text_color if text_color is not None else theme_input_text_color() + + self.DisabledTextColor = disabled_text_color if disabled_text_color is not None else COLOR_SYSTEM_DEFAULT + self.MenuDefinition = copy.deepcopy(menu_definition) + self.Widget = self.TKMenu = None # type: tk.Menu + self.MenuItemChosen = None + key = key if key is not None else k + sz = size if size != (None, None) else s + pad = pad if pad is not None else p + + super().__init__(ELEM_TYPE_MENUBAR, background_color=self.BackgroundColor, text_color=self.TextColor, size=sz, pad=pad, key=key, visible=visible, + font=font, metadata=metadata) + # super().__init__(ELEM_TYPE_MENUBAR, background_color=COLOR_SYSTEM_DEFAULT, text_color=COLOR_SYSTEM_DEFAULT, size=sz, pad=pad, key=key, visible=visible, font=None, metadata=metadata) + + self.Tearoff = tearoff + + return + + def _MenuItemChosenCallback(self, item_chosen): # Menu Menu Item Chosen Callback + """ + Not user callable. Called when some end-point on the menu (an item) has been clicked. Send the information back to the application as an event. Before event can be sent + + :param item_chosen: the text that was clicked on / chosen from the menu + :type item_chosen: (str) + """ + # print('IN MENU ITEM CALLBACK', item_chosen) + self.MenuItemChosen = item_chosen + self.ParentForm.LastButtonClicked = item_chosen + self.ParentForm.FormRemainedOpen = True + # if self.ParentForm.CurrentlyRunningMainloop: + # self.ParentForm.TKroot.quit() # kick the users out of the mainloop + _exit_mainloop(self.ParentForm) + + def update(self, menu_definition=None, visible=None): + """ + Update a menubar - can change the menu definition and visibility. The entire menu has to be specified + + :param menu_definition: ??? + :type menu_definition: List[List[Tuple[str, List[str]]] + :param visible: control visibility of element + :type visible: (bool) + """ + if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow + return + + if menu_definition is not None: + self.MenuDefinition = copy.deepcopy(menu_definition) + + self.TKMenu = tk.Menu(self.ParentForm.TKroot, tearoff=self.Tearoff, tearoffcommand=self._tearoff_menu_callback) # create the menubar + menubar = self.TKMenu + for menu_entry in self.MenuDefinition: + baritem = tk.Menu(menubar, tearoff=self.Tearoff, tearoffcommand=self._tearoff_menu_callback) + + if self.BackgroundColor not in (COLOR_SYSTEM_DEFAULT, None): + baritem.config(bg=self.BackgroundColor) + if self.TextColor not in (COLOR_SYSTEM_DEFAULT, None): + baritem.config(fg=self.TextColor) + if self.DisabledTextColor not in (COLOR_SYSTEM_DEFAULT, None): + baritem.config(disabledforeground=self.DisabledTextColor) + if self.Font is not None: + baritem.config(font=self.Font) + + if self.Font is not None: + baritem.config(font=self.Font) + pos = menu_entry[0].find(MENU_SHORTCUT_CHARACTER) + # print(pos) + if pos != -1: + if pos == 0 or menu_entry[0][pos - len(MENU_SHORTCUT_CHARACTER)] != "\\": + menu_entry[0] = menu_entry[0][:pos] + menu_entry[0][pos + len(MENU_SHORTCUT_CHARACTER):] + if menu_entry[0][0] == MENU_DISABLED_CHARACTER: + menubar.add_cascade(label=menu_entry[0][len(MENU_DISABLED_CHARACTER):], menu=baritem, underline=pos) + menubar.entryconfig(menu_entry[0][len(MENU_DISABLED_CHARACTER):], state='disabled') + else: + menubar.add_cascade(label=menu_entry[0], menu=baritem, underline=pos) + + if len(menu_entry) > 1: + AddMenuItem(baritem, menu_entry[1], self) + + if visible is False: + self.ParentForm.TKroot.configure(menu=[]) # this will cause the menubar to disappear + elif self.TKMenu is not None: + self.ParentForm.TKroot.configure(menu=self.TKMenu) + if visible is not None: + self._visible = visible + + Update = update + + +MenuBar = Menu # another name for Menu to make it clear it's the Menu Bar +Menubar = Menu # another name for Menu to make it clear it's the Menu Bar + + +# ---------------------------------------------------------------------- # +# Table # +# ---------------------------------------------------------------------- # +class Table(Element): + + def __init__(self, values, headings=None, visible_column_map=None, col_widths=None, def_col_width=10, + auto_size_columns=True, max_col_width=20, select_mode=None, display_row_numbers=False, num_rows=None, + row_height=None, font=None, justification='right', text_color=None, background_color=None, + alternating_row_color=None, selected_row_colors=(None, None), header_text_color=None, header_background_color=None, header_font=None, + row_colors=None, vertical_scroll_only=True, hide_vertical_scroll=False, + size=(None, None), s=(None, None), change_submits=False, enable_events=False, enable_click_events=False, bind_return_key=False, pad=None, p=None, + key=None, k=None, tooltip=None, right_click_menu=None, expand_x=False, expand_y=False, visible=True, metadata=None): + """ + :param values: ??? + :type values: List[List[str | int | float]] + :param headings: The headings to show on the top line + :type headings: List[str] + :param visible_column_map: One entry for each column. False indicates the column is not shown + :type visible_column_map: List[bool] + :param col_widths: Number of characters that each column will occupy + :type col_widths: List[int] + :param def_col_width: Default column width in characters + :type def_col_width: (int) + :param auto_size_columns: if True columns will be sized automatically + :type auto_size_columns: (bool) + :param max_col_width: Maximum width for all columns in characters + :type max_col_width: (int) + :param select_mode: Select Mode. Valid values start with "TABLE_SELECT_MODE_". Valid values are: TABLE_SELECT_MODE_NONE TABLE_SELECT_MODE_BROWSE TABLE_SELECT_MODE_EXTENDED + :type select_mode: (enum) + :param display_row_numbers: if True, the first column of the table will be the row # + :type display_row_numbers: (bool) + :param num_rows: The number of rows of the table to display at a time + :type num_rows: (int) + :param row_height: height of a single row in pixels + :type row_height: (int) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param justification: 'left', 'right', 'center' are valid choices + :type justification: (str) + :param text_color: color of the text + :type text_color: (str) + :param background_color: color of background + :type background_color: (str) + :param alternating_row_color: if set then every other row will have this color in the background. + :type alternating_row_color: (str) + :param selected_row_colors: Sets the text color and background color for a selected row. Same format as button colors - tuple ('red', 'yellow') or string 'red on yellow'. Defaults to theme's button color + :type selected_row_colors: str or (str, str) + :param header_text_color: sets the text color for the header + :type header_text_color: (str) + :param header_background_color: sets the background color for the header + :type header_background_color: (str) + :param header_font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type header_font: (str or (str, int[, str]) or None) + :param row_colors: list of tuples of (row, background color) OR (row, foreground color, background color). Sets the colors of listed rows to the color(s) provided (note the optional foreground color) + :type row_colors: List[Tuple[int, str] | Tuple[Int, str, str]] + :param vertical_scroll_only: if True only the vertical scrollbar will be visible + :type vertical_scroll_only: (bool) + :param hide_vertical_scroll: if True vertical scrollbar will be hidden + :type hide_vertical_scroll: (bool) + :param size: DO NOT USE! Use num_rows instead + :type size: (int, int) + :param change_submits: DO NOT USE. Only listed for backwards compat - Use enable_events instead + :type change_submits: (bool) + :param enable_events: Turns on the element specific events. Table events happen when row is clicked + :type enable_events: (bool) + :param enable_click_events: Turns on the element click events that will give you (row, col) click data when the table is clicked + :type enable_click_events: (bool) + :param bind_return_key: if True, pressing return key will cause event coming from Table, ALSO a left button double click will generate an event if this parameter is True + :type bind_return_key: (bool) + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param key: Used with window.find_element and with return values to uniquely identify this element to uniquely identify this element + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. + :type right_click_menu: List[List[ List[str] | str ]] + :param expand_x: If True the element will automatically expand in the X direction to fill available space + :type expand_x: (bool) + :param expand_y: If True the element will automatically expand in the Y direction to fill available space + :type expand_y: (bool) + :param visible: set visibility state of the element + :type visible: (bool) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + + + self.Values = values + self.ColumnHeadings = headings + self.ColumnsToDisplay = visible_column_map + self.ColumnWidths = col_widths + self.MaxColumnWidth = max_col_width + self.DefaultColumnWidth = def_col_width + self.AutoSizeColumns = auto_size_columns + self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR + self.TextColor = text_color + self.HeaderTextColor = header_text_color if header_text_color is not None else LOOK_AND_FEEL_TABLE[CURRENT_LOOK_AND_FEEL]['TEXT_INPUT'] + self.HeaderBackgroundColor = header_background_color if header_background_color is not None else LOOK_AND_FEEL_TABLE[CURRENT_LOOK_AND_FEEL]['INPUT'] + self.HeaderFont = header_font + self.Justification = justification + self.InitialState = None + self.SelectMode = select_mode + self.DisplayRowNumbers = display_row_numbers + self.NumRows = num_rows if num_rows is not None else size[1] + self.RowHeight = row_height + self.Widget = self.TKTreeview = None # type: ttk.Treeview + self.AlternatingRowColor = alternating_row_color + self.VerticalScrollOnly = vertical_scroll_only + self.HideVerticalScroll = hide_vertical_scroll + self.SelectedRows = [] + self.ChangeSubmits = change_submits or enable_events + self.BindReturnKey = bind_return_key + self.StartingRowNumber = 0 # When displaying row numbers, where to start + self.RowHeaderText = 'Row' + self.enable_click_events = enable_click_events + self.last_clicked_position = (None, None) + if selected_row_colors == (None, None): + # selected_row_colors = DEFAULT_TABLE_AND_TREE_SELECTED_ROW_COLORS + selected_row_colors = theme_button_color() + else: + try: + if isinstance(selected_row_colors, str): + selected_row_colors = selected_row_colors.split(' on ') + except Exception as e: + print('* Table Element Warning * you messed up with color formatting of Selected Row Color', e) + self.SelectedRowColors = selected_row_colors + + self.RightClickMenu = right_click_menu + self.RowColors = row_colors + self.tree_ids = [] # ids returned when inserting items into table - will use to delete colors + key = key if key is not None else k + sz = size if size != (None, None) else s + pad = pad if pad is not None else p + self.expand_x = expand_x + self.expand_y = expand_y + + super().__init__(ELEM_TYPE_TABLE, text_color=text_color, background_color=background_color, font=font, + size=sz, pad=pad, key=key, tooltip=tooltip, visible=visible, metadata=metadata) + return + + def update(self, values=None, num_rows=None, visible=None, select_rows=None, alternating_row_color=None, row_colors=None): + """ + Changes some of the settings for the Table Element. Must call `Window.Read` or `Window.Finalize` prior + + :param values: A new 2-dimensional table to show + :type values: List[List[str | int | float]] + :param num_rows: How many rows to display at a time + :type num_rows: (int) + :param visible: if True then will be visible + :type visible: (bool) + :param select_rows: List of rows to select as if user did + :type select_rows: List[int] + :param alternating_row_color: the color to make every other row + :type alternating_row_color: (str) + :param row_colors: list of tuples of (row, background color) OR (row, foreground color, background color). Changes the colors of listed rows to the color(s) provided (note the optional foreground color) + :type row_colors: List[Tuple[int, str] | Tuple[Int, str, str]] + """ + if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow + return + + if values is not None: + for id in self.tree_ids: + self.TKTreeview.item(id, tags=()) + if self.BackgroundColor is not None and self.BackgroundColor != COLOR_SYSTEM_DEFAULT: + self.TKTreeview.tag_configure(id, background=self.BackgroundColor) + else: + self.TKTreeview.tag_configure(id, background='#FFFFFF', foreground='#000000') + if self.TextColor is not None and self.TextColor != COLOR_SYSTEM_DEFAULT: + self.TKTreeview.tag_configure(id, foreground=self.TextColor) + else: + self.TKTreeview.tag_configure(id, foreground='#000000') + + children = self.TKTreeview.get_children() + for i in children: + self.TKTreeview.detach(i) + self.TKTreeview.delete(i) + children = self.TKTreeview.get_children() + + self.tree_ids = [] + for i, value in enumerate(values): + if self.DisplayRowNumbers: + value = [i + self.StartingRowNumber] + value + id = self.TKTreeview.insert('', 'end', text=value, iid=i + 1, values=value, tag=i) + if self.BackgroundColor is not None and self.BackgroundColor != COLOR_SYSTEM_DEFAULT: + self.TKTreeview.tag_configure(id, background=self.BackgroundColor) + else: + self.TKTreeview.tag_configure(id, background='#FFFFFF') + self.tree_ids.append(id) + self.Values = values + self.SelectedRows = [] + if visible is False: + self.TKTreeview.pack_forget() + elif visible is True: + self.TKTreeview.pack(padx=self.pad_used[0], pady=self.pad_used[1]) + if num_rows is not None: + self.TKTreeview.config(height=num_rows) + if select_rows is not None: + rows_to_select = [i + 1 for i in select_rows] + self.TKTreeview.selection_set(rows_to_select) + + if alternating_row_color is not None: # alternating colors + self.AlternatingRowColor = alternating_row_color + + if self.AlternatingRowColor is not None: + for row in range(0, len(self.Values), 2): + self.TKTreeview.tag_configure(row, background=self.AlternatingRowColor) + if row_colors is not None: # individual row colors + self.RowColors = row_colors + for row_def in self.RowColors: + if len(row_def) == 2: # only background is specified + self.TKTreeview.tag_configure(row_def[0], background=row_def[1]) + else: + self.TKTreeview.tag_configure(row_def[0], background=row_def[2], foreground=row_def[1]) + if visible is not None: + self._visible = visible + + def _treeview_selected(self, event): + """ + Not user callable. Callback function that is called when something is selected from Table. + Stores the selected rows in Element as they are being selected. If events enabled, then returns from Read + + :param event: event information from tkinter + :type event: (unknown) + """ + # print('**-- in treeview selected --**') + selections = self.TKTreeview.selection() + self.SelectedRows = [int(x) - 1 for x in selections] + if self.ChangeSubmits: + if self.Key is not None: + self.ParentForm.LastButtonClicked = self.Key + else: + self.ParentForm.LastButtonClicked = '' + self.ParentForm.FormRemainedOpen = True + # if self.ParentForm.CurrentlyRunningMainloop: + # self.ParentForm.TKroot.quit() + _exit_mainloop(self.ParentForm) + + def _treeview_double_click(self, event): + """ + Not user callable. Callback function that is called when something is selected from Table. + Stores the selected rows in Element as they are being selected. If events enabled, then returns from Read + + :param event: event information from tkinter + :type event: (unknown) + """ + selections = self.TKTreeview.selection() + self.SelectedRows = [int(x) - 1 for x in selections] + if self.BindReturnKey: # Signifies BOTH a return key AND a double click + if self.Key is not None: + self.ParentForm.LastButtonClicked = self.Key + else: + self.ParentForm.LastButtonClicked = '' + self.ParentForm.FormRemainedOpen = True + # if self.ParentForm.CurrentlyRunningMainloop: + # self.ParentForm.TKroot.quit() + _exit_mainloop(self.ParentForm) + + + def _table_clicked(self, event): + """ + Not user callable. Callback function that is called a click happens on a table. + Stores the selected rows in Element as they are being selected. If events enabled, then returns from Read + + :param event: event information from tkinter + :type event: (unknown) + """ + if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow + return + try: + region = self.Widget.identify('region', event.x, event.y) + if region == 'heading': + row = -1 + elif region == 'cell': + row = int(self.Widget.identify_row(event.y))-1 + elif region == 'separator': + row = None + else: + row = None + col_identified = self.Widget.identify_column(event.x) + if col_identified: # Sometimes tkinter returns a value of '' which would cause an error if cast to an int + column = int(self.Widget.identify_column(event.x)[1:])-1-int(self.DisplayRowNumbers is True) + else: + column = None + except Exception as e: + warnings.warn('Error getting table click data for table with key= {}\nError: {}'.format(self.Key, e), UserWarning) + if not SUPPRESS_ERROR_POPUPS: + _error_popup_with_traceback('Unable to complete operation getting the clicked event for table with key {}'.format(self.Key), _create_error_message(), e, 'Event data:', obj_to_string_single_obj(event)) + row = column = None + + self.last_clicked_position = (row, column) + + # update the rows being selected if appropriate + self.ParentForm.TKroot.update() + # self.TKTreeview.() + selections = self.TKTreeview.selection() + # print(selections) + self.SelectedRows = [int(x) - 1 for x in selections] + # print('The new selected rows = ', self.SelectedRows) + if self.enable_click_events is True: + if self.Key is not None: + self.ParentForm.LastButtonClicked = (self.Key, '+CICKED+', (row, column)) + else: + self.ParentForm.LastButtonClicked = '' + self.ParentForm.FormRemainedOpen = True + _exit_mainloop(self.ParentForm) + + + def get(self): + """ + Dummy function for tkinter port. In the Qt port you can read back the values in the table in case they were + edited. Don't know yet how to enable editing of a Tree in tkinter so just returning the values provided by + user when Table was created or Updated. + + :return: the current table values (for now what was originally provided up updated) + :rtype: List[List[Any]] + """ + return self.Values + + + def get_last_clicked_position(self): + """ + Dummy function for tkinter port. In the Qt port you can read back the values in the table in case they were + edited. Don't know yet how to enable editing of a Tree in tkinter so just returning the values provided by + user when Table was created or Updated. + + :return: the current table values (for now what was originally provided up updated) + :rtype: (int | None, int | None) + """ + return self.last_clicked_position + + + + + Update = update + Get = get + + +# ---------------------------------------------------------------------- # +# Tree # +# ---------------------------------------------------------------------- # +class Tree(Element): + """ + Tree Element - Presents data in a tree-like manner, much like a file/folder browser. Uses the TreeData class + to hold the user's data and pass to the element for display. + """ + + def __init__(self, data=None, headings=None, visible_column_map=None, col_widths=None, col0_width=10, + def_col_width=10, auto_size_columns=True, max_col_width=20, select_mode=None, show_expanded=False, + change_submits=False, enable_events=False, font=None, justification='right', text_color=None, + background_color=None, selected_row_colors=(None, None), header_text_color=None, header_background_color=None, header_font=None, num_rows=None, + row_height=None, pad=None, p=None, key=None, k=None, tooltip=None, + right_click_menu=None, expand_x=False, expand_y=False, visible=True, metadata=None): + """ + :param data: The data represented using a PySimpleGUI provided TreeData class + :type data: (TreeData) + :param headings: List of individual headings for each column + :type headings: List[str] + :param visible_column_map: Determines if a column should be visible. If left empty, all columns will be shown + :type visible_column_map: List[bool] + :param col_widths: List of column widths so that individual column widths can be controlled + :type col_widths: List[int] + :param col0_width: Size of Column 0 which is where the row numbers will be optionally shown + :type col0_width: (int) + :param def_col_width: default column width + :type def_col_width: (int) + :param auto_size_columns: if True, the size of a column is determined using the contents of the column + :type auto_size_columns: (bool) + :param max_col_width: the maximum size a column can be + :type max_col_width: (int) + :param select_mode: Use same values as found on Table Element. Valid values include: TABLE_SELECT_MODE_NONE TABLE_SELECT_MODE_BROWSE TABLE_SELECT_MODE_EXTENDED + :type select_mode: (enum) + :param show_expanded: if True then the tree will be initially shown with all nodes completely expanded + :type show_expanded: (bool) + :param change_submits: DO NOT USE. Only listed for backwards compat - Use enable_events instead + :type change_submits: (bool) + :param enable_events: Turns on the element specific events. Tree events happen when row is clicked + :type enable_events: (bool) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param justification: 'left', 'right', 'center' are valid choices + :type justification: (str) + :param text_color: color of the text + :type text_color: (str) + :param background_color: color of background + :type background_color: (str) + :param selected_row_colors: Sets the text color and background color for a selected row. Same format as button colors - tuple ('red', 'yellow') or string 'red on yellow'. Defaults to theme's button color + :type selected_row_colors: str or (str, str) + :param header_text_color: sets the text color for the header + :type header_text_color: (str) + :param header_background_color: sets the background color for the header + :type header_background_color: (str) + :param header_font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type header_font: (str or (str, int[, str]) or None) + :param num_rows: The number of rows of the table to display at a time + :type num_rows: (int) + :param row_height: height of a single row in pixels + :type row_height: (int) + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param key: Used with window.find_element and with return values to uniquely identify this element to uniquely identify this element + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. + :type right_click_menu: List[List[str] | str]] + :param expand_x: If True the element will automatically expand in the X direction to fill available space + :type expand_x: (bool) + :param expand_y: If True the element will automatically expand in the Y direction to fill available space + :type expand_y: (bool) + :param visible: set visibility state of the element + :type visible: (bool) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + + self.image_dict = {} + + self.TreeData = data + self.ColumnHeadings = headings + self.ColumnsToDisplay = visible_column_map + self.ColumnWidths = col_widths + self.MaxColumnWidth = max_col_width + self.DefaultColumnWidth = def_col_width + self.AutoSizeColumns = auto_size_columns + self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR + self.TextColor = text_color + self.HeaderTextColor = header_text_color if header_text_color is not None else LOOK_AND_FEEL_TABLE[CURRENT_LOOK_AND_FEEL]['TEXT_INPUT'] + self.HeaderBackgroundColor = header_background_color if header_background_color is not None else LOOK_AND_FEEL_TABLE[CURRENT_LOOK_AND_FEEL]['INPUT'] + + if selected_row_colors == (None, None): + # selected_row_colors = DEFAULT_TABLE_AND_TREE_SELECTED_ROW_COLORS + selected_row_colors = theme_button_color() + else: + try: + if isinstance(selected_row_colors, str): + selected_row_colors = selected_row_colors.split(' on ') + except Exception as e: + print('* Table Element Warning * you messed up with color formatting of Selected Row Color', e) + self.SelectedRowColors = selected_row_colors + + self.HeaderFont = header_font + self.Justification = justification + self.InitialState = None + self.SelectMode = select_mode + self.ShowExpanded = show_expanded + self.NumRows = num_rows + self.Col0Width = col0_width + self.TKTreeview = None # type: ttk.Treeview + self.element_frame = None # type: tk.Frame + self.SelectedRows = [] + self.ChangeSubmits = change_submits or enable_events + self.RightClickMenu = right_click_menu + self.RowHeight = row_height + self.IconList = {} + self.IdToKey = {'': ''} + self.KeyToID = {'': ''} + key = key if key is not None else k + pad = pad if pad is not None else p + self.expand_x = expand_x + self.expand_y = expand_y + + super().__init__(ELEM_TYPE_TREE, text_color=text_color, background_color=background_color, font=font, pad=pad, key=key, tooltip=tooltip, + visible=visible, metadata=metadata) + return + + def _treeview_selected(self, event): + """ + Not a user function. Callback function that happens when an item is selected from the tree. In this + method, it saves away the reported selections so they can be properly returned. + + :param event: An event parameter passed in by tkinter. Not used + :type event: (Any) + """ + + selections = self.TKTreeview.selection() + # self.SelectedRows = [x for x in selections] + self.SelectedRows = [self.IdToKey[x] for x in selections] + if self.ChangeSubmits: + MyForm = self.ParentForm + if self.Key is not None: + self.ParentForm.LastButtonClicked = self.Key + else: + self.ParentForm.LastButtonClicked = '' + self.ParentForm.FormRemainedOpen = True + # if self.ParentForm.CurrentlyRunningMainloop: + # self.ParentForm.TKroot.quit() + _exit_mainloop(self.ParentForm) + + def add_treeview_data(self, node): + """ + Not a user function. Recursive method that inserts tree data into the tkinter treeview widget. + + :param node: The node to insert. Will insert all nodes from starting point downward, recursively + :type node: (TreeData) + """ + if node.key != '': + if node.icon: + try: + if node.icon not in self.image_dict: + if type(node.icon) is bytes: + photo = tk.PhotoImage(data=node.icon) + else: + photo = tk.PhotoImage(file=node.icon) + self.image_dict[node.icon] = photo + else: + photo = self.image_dict.get(node.icon) + + node.photo = photo + id = self.TKTreeview.insert(self.KeyToID[node.parent], 'end', iid=None, text=node.text, + values=node.values, open=self.ShowExpanded, image=node.photo) + self.IdToKey[id] = node.key + self.KeyToID[node.key] = id + except: + self.photo = None + else: + id = self.TKTreeview.insert(self.KeyToID[node.parent], 'end', iid=None, text=node.text, + values=node.values, open=self.ShowExpanded) + self.IdToKey[id] = node.key + self.KeyToID[node.key] = id + + for node in node.children: + self.add_treeview_data(node) + + def update(self, values=None, key=None, value=None, text=None, icon=None, visible=None): + """ + Changes some of the settings for the Tree Element. Must call `Window.Read` or `Window.Finalize` prior + + :param values: Representation of the tree + :type values: (TreeData) + :param key: identifies a particular item in tree to update + :type key: str | int | tuple | object + :param value: sets the node identified by key to a particular value + :type value: (Any) + :param text: sets the node identified by ket to this string + :type text: (str) + :param icon: can be either a base64 icon or a filename for the icon + :type icon: bytes | str + :param visible: control visibility of element + :type visible: (bool) + """ + if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow + return + + if values is not None: + children = self.TKTreeview.get_children() + for i in children: + self.TKTreeview.detach(i) + self.TKTreeview.delete(i) + children = self.TKTreeview.get_children() + self.TreeData = values + self.IdToKey = {'': ''} + self.KeyToID = {'': ''} + self.add_treeview_data(self.TreeData.root_node) + self.SelectedRows = [] + if key is not None: + for id in self.IdToKey.keys(): + if key == self.IdToKey[id]: + break + else: + id = None + print('** Key not found **') + else: + id = None + if id: + # item = self.TKTreeview.item(id) + if value is not None: + self.TKTreeview.item(id, values=value) + if text is not None: + self.TKTreeview.item(id, text=text) + if icon is not None: + try: + if type(icon) is bytes: + photo = tk.PhotoImage(data=icon) + else: + photo = tk.PhotoImage(file=icon) + self.TKTreeview.item(id, image=photo) + self.IconList[key] = photo # save so that it's not deleted (save reference) + except: + pass + # item = self.TKTreeview.item(id) + if visible is False: + self.TKTreeview.pack_forget() + elif visible is True: + self.TKTreeview.pack(padx=self.pad_used[0], pady=self.pad_used[1]) + if visible is not None: + self._visible = visible + + return self + + Update = update + + +class TreeData(object): + """ + Class that user fills in to represent their tree data. It's a very simple tree representation with a root "Node" + with possibly one or more children "Nodes". Each Node contains a key, text to display, list of values to display + and an icon. The entire tree is built using a single method, Insert. Nothing else is required to make the tree. + """ + + class Node(object): + """ + Contains information about the individual node in the tree + """ + + def __init__(self, parent, key, text, values, icon=None): + """ + Represents a node within the TreeData class + + :param parent: The parent Node + :type parent: (TreeData.Node) + :param key: Used to uniquely identify this node + :type key: str | int | tuple | object + :param text: The text that is displayed at this node's location + :type text: (str) + :param values: The list of values that are displayed at this node + :type values: List[Any] + :param icon: just a icon + :type icon: str | bytes + """ + + self.parent = parent # type: TreeData.Node + self.children = [] # type: List[TreeData.Node] + self.key = key # type: str + self.text = text # type: str + self.values = values # type: List[Any] + self.icon = icon # type: str | bytes + + def _Add(self, node): + self.children.append(node) + + def __init__(self): + """ + Instantiate the object, initializes the Tree Data, creates a root node for you + """ + self.tree_dict = {} # type: Dict[str, TreeData.Node] + self.root_node = self.Node("", "", 'root', [], None) # The root node + self.tree_dict[""] = self.root_node # Start the tree out with the root node + + def _AddNode(self, key, node): + """ + Adds a node to tree dictionary (not user callable) + + :param key: Uniquely identifies this Node + :type key: (str) + :param node: Node being added + :type node: (TreeData.Node) + """ + self.tree_dict[key] = node + + def insert(self, parent, key, text, values, icon=None): + """ + Inserts a node into the tree. This is how user builds their tree, by Inserting Nodes + This is the ONLY user callable method in the TreeData class + + :param parent: the parent Node + :type parent: (Node) + :param key: Used to uniquely identify this node + :type key: str | int | tuple | object + :param text: The text that is displayed at this node's location + :type text: (str) + :param values: The list of values that are displayed at this node + :type values: List[Any] + :param icon: icon + :type icon: str | bytes + """ + + node = self.Node(parent, key, text, values, icon) + self.tree_dict[key] = node + parent_node = self.tree_dict[parent] + parent_node._Add(node) + + def __repr__(self): + """ + Converts the TreeData into a printable version, nicely formatted + + :return: (str) A formatted, text version of the TreeData + :rtype: + """ + return self._NodeStr(self.root_node, 1) + + def _NodeStr(self, node, level): + """ + Does the magic of converting the TreeData into a nicely formatted string version + + :param node: The node to begin printing the tree + :type node: (TreeData.Node) + :param level: The indentation level for string formatting + :type level: (int) + """ + return '\n'.join( + [str(node.key) + ' : ' + str(node.text)] + + [' ' * 4 * level + self._NodeStr(child, level + 1) for child in node.children]) + + Insert = insert + + +# ---------------------------------------------------------------------- # +# Error Element # +# ---------------------------------------------------------------------- # +class ErrorElement(Element): + """ + A "dummy Element" that is returned when there are error conditions, like trying to find an element that's invalid + """ + + def __init__(self, key=None, metadata=None): + """ + :param key: Used with window.find_element and with return values to uniquely identify this element + :type key: + """ + self.Key = key + + super().__init__(ELEM_TYPE_ERROR, key=key, metadata=metadata) + + def update(self, silent_on_error=True, *args, **kwargs): + """ + Update method for the Error Element, an element that should not be directly used by developer + + :param silent_on_error: if False, then a Popup window will be shown + :type silent_on_error: (bool) + :param *args: meant to "soak up" any normal parameters passed in + :type *args: (Any) + :param **kwargs: meant to "soak up" any keyword parameters that were passed in + :type **kwargs: (Any) + :return: returns 'self' so call can be chained + :rtype: (ErrorElement) + """ + print('** Your update is being ignored because you supplied a bad key earlier **') + return self + + def get(self): + """ + One of the method names found in other Elements. Used here to return an error string in case it's called + + :return: A warning text string. + :rtype: (str) + """ + return 'This is NOT a valid Element!\nSTOP trying to do things with it or I will have to crash at some point!' + + Get = get + Update = update + + +# ---------------------------------------------------------------------- # +# Stretch Element # +# ---------------------------------------------------------------------- # +# This is for source code compatibility with tkinter version. No tkinter equivalent but you can fake it using a Text element that expands in the X direction +def Stretch(background_color=None): + """ + Acts like a Stretch element found in the Qt port. + Used in a Horizontal fashion. Placing one on each side of an element will enter the element. + Place one to the left and the element to the right will be right justified. See VStretch for vertical type + :param background_color: color of background may be needed because of how this is implemented + :type background_color: (str) + :return: (Text) + """ + return Text(font='_ 1', background_color=background_color, pad=(0,0), expand_x=True) + +Push = Stretch +P = Stretch + +def VStretch(background_color=None): + """ + Acts like a Stretch element found in the Qt port. + Used in a Vertical fashion. + :param background_color: color of background may be needed because of how this is implemented + :type background_color: (str) + :return: (Text) + """ + return Text(font='_ 1', background_color=background_color, pad=(0,0), expand_y=True) + + +VPush = VStretch +VP = VStretch + + +# ------------------------------------------------------------------------- # +# Window CLASS # +# ------------------------------------------------------------------------- # +class Window: + """ + Represents a single Window + """ + NumOpenWindows = 0 + _user_defined_icon = None + hidden_master_root = None # type: tk.Tk + _animated_popup_dict = {} # type: Dict + _active_windows = {} # type: Dict[Window, tk.Tk()] + _move_all_windows = False # if one window moved, they will move + _window_that_exited = None # type: Window + _root_running_mainloop = None # type: tk.Tk() # (may be the hidden root or a window's root) + _timeout_key = None + _TKAfterID = None # timer that is used to run reads with timeouts + _window_running_mainloop = None # The window that is running the mainloop + _container_element_counter = 0 # used to get a number of Container Elements (Frame, Column, Tab) + _read_call_from_debugger = False + _timeout_0_counter = 0 # when timeout=0 then go through each window one at a time + _counter_for_ttk_widgets = 0 + _floating_debug_window_build_needed = False + _main_debug_window_build_needed = False + + def __init__(self, title, layout=None, default_element_size=None, + default_button_element_size=(None, None), + auto_size_text=None, auto_size_buttons=None, location=(None, None), relative_location=(None, None), size=(None, None), + element_padding=None, margins=(None, None), button_color=None, font=None, + progress_bar_color=(None, None), background_color=None, border_depth=None, auto_close=False, + auto_close_duration=DEFAULT_AUTOCLOSE_TIME, icon=None, force_toplevel=False, + alpha_channel=1, return_keyboard_events=False, use_default_focus=True, text_justification=None, + no_titlebar=False, grab_anywhere=False, grab_anywhere_using_control=True, keep_on_top=None, resizable=False, disable_close=False, + disable_minimize=False, right_click_menu=None, transparent_color=None, debugger_enabled=True, + right_click_menu_background_color=None, right_click_menu_text_color=None, right_click_menu_disabled_text_color=None, + right_click_menu_selected_colors=(None, None), + right_click_menu_font=None, right_click_menu_tearoff=False, + finalize=False, element_justification='left', ttk_theme=None, use_ttk_buttons=None, modal=False, enable_close_attempted_event=False, + titlebar_background_color=None, titlebar_text_color=None, titlebar_font=None, titlebar_icon=None, + use_custom_titlebar=None, scaling=None, metadata=None): + """ + :param title: The title that will be displayed in the Titlebar and on the Taskbar + :type title: (str) + :param layout: The layout for the window. Can also be specified in the Layout method + :type layout: List[List[Element]] | Tuple[Tuple[Element]] + :param default_element_size: size in characters (wide) and rows (high) for all elements in this window + :type default_element_size: (int, int) - (width, height) + :param default_button_element_size: (width, height) size in characters (wide) and rows (high) for all Button elements in this window + :type default_button_element_size: (int, int) + :param auto_size_text: True if Elements in Window should be sized to exactly fir the length of text + :type auto_size_text: (bool) + :param auto_size_buttons: True if Buttons in this Window should be sized to exactly fit the text on this. + :type auto_size_buttons: (bool) + :param relative_location: (x,y) location relative to the default location of the window, in pixels. Normally the window centers. This location is relative to the location the window would be created. Note they can be negative. + :type relative_location: (int, int) + :param location: (x,y) location, in pixels, to locate the upper left corner of the window on the screen. Default is to center on screen. + :type location: (int, int) + :param size: (width, height) size in pixels for this window. Normally the window is autosized to fit contents, not set to an absolute size by the user. Try not to set this value. You risk, the contents being cut off, etc. Let the layout determine the window size instead + :type size: (int, int) + :param element_padding: Default amount of padding to put around elements in window (left/right, top/bottom) or ((left, right), (top, bottom)), or an int. If an int, then it's converted into a tuple (int, int) + :type element_padding: (int, int) or ((int, int),(int,int)) or int + :param margins: (left/right, top/bottom) Amount of pixels to leave inside the window's frame around the edges before your elements are shown. + :type margins: (int, int) + :param button_color: Default button colors for all buttons in the window + :type button_color: (str, str) or str + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param progress_bar_color: (bar color, background color) Sets the default colors for all progress bars in the window + :type progress_bar_color: (str, str) + :param background_color: color of background + :type background_color: (str) + :param border_depth: Default border depth (width) for all elements in the window + :type border_depth: (int) + :param auto_close: If True, the window will automatically close itself + :type auto_close: (bool) + :param auto_close_duration: Number of seconds to wait before closing the window + :type auto_close_duration: (int) + :param icon: Can be either a filename or Base64 value. For Windows if filename, it MUST be ICO format. For Linux, must NOT be ICO. Most portable is to use a Base64 of a PNG file. This works universally across all OS's + :type icon: (str | bytes) + :param force_toplevel: If True will cause this window to skip the normal use of a hidden master window + :type force_toplevel: (bool) + :param alpha_channel: Sets the opacity of the window. 0 = invisible 1 = completely visible. Values bewteen 0 & 1 will produce semi-transparent windows in SOME environments (The Raspberry Pi always has this value at 1 and cannot change. + :type alpha_channel: (float) + :param return_keyboard_events: if True key presses on the keyboard will be returned as Events from Read calls + :type return_keyboard_events: (bool) + :param use_default_focus: If True will use the default focus algorithm to set the focus to the "Correct" element + :type use_default_focus: (bool) + :param text_justification: Default text justification for all Text Elements in window + :type text_justification: 'left' | 'right' | 'center' + :param no_titlebar: If true, no titlebar nor frame will be shown on window. This means you cannot minimize the window and it will not show up on the taskbar + :type no_titlebar: (bool) + :param grab_anywhere: If True can use mouse to click and drag to move the window. Almost every location of the window will work except input fields on some systems + :type grab_anywhere: (bool) + :param grab_anywhere_using_control: If True can use CONTROL key + left mouse mouse to click and drag to move the window. DEFAULT is TRUE. Unlike normal grab anywhere, it works on all elements. + :type grab_anywhere_using_control: (bool) + :param keep_on_top: If True, window will be created on top of all other windows on screen. It can be bumped down if another window created with this parm + :type keep_on_top: (bool) + :param resizable: If True, allows the user to resize the window. Note the not all Elements will change size or location when resizing. + :type resizable: (bool) + :param disable_close: If True, the X button in the top right corner of the window will no work. Use with caution and always give a way out toyour users + :type disable_close: (bool) + :param disable_minimize: if True the user won't be able to minimize window. Good for taking over entire screen and staying that way. + :type disable_minimize: (bool) + :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. + :type right_click_menu: List[List[ List[str] | str ]] + :param transparent_color: Any portion of the window that has this color will be completely transparent. You can even click through these spots to the window under this window. + :type transparent_color: (str) + :param debugger_enabled: If True then the internal debugger will be enabled + :type debugger_enabled: (bool) + :param right_click_menu_background_color: Background color for right click menus + :type right_click_menu_background_color: (str) + :param right_click_menu_text_color: Text color for right click menus + :type right_click_menu_text_color: (str) + :param right_click_menu_disabled_text_color: Text color for disabled right click menu items + :type right_click_menu_disabled_text_color: (str) + :param right_click_menu_selected_colors: Text AND background colors for a selected item. Can be a Tuple OR a color string. simplified-button-color-string "foreground on background". Can be a single color if want to set only the background. Normally a tuple, but can be a simplified-dual-color-string "foreground on background". Can be a single color if want to set only the background. + :type right_click_menu_selected_colors: (str, str) | str | Tuple + :param right_click_menu_font: Font for right click menus + :type right_click_menu_font: (str or (str, int[, str]) or None) + :param right_click_menu_tearoff: If True then all right click menus can be torn off + :type right_click_menu_tearoff: bool + :param finalize: If True then the Finalize method will be called. Use this rather than chaining .Finalize for cleaner code + :type finalize: (bool) + :param element_justification: All elements in the Window itself will have this justification 'left', 'right', 'center' are valid values + :type element_justification: (str) + :param ttk_theme: Set the tkinter ttk "theme" of the window. Default = DEFAULT_TTK_THEME. Sets all ttk widgets to this theme as their default + :type ttk_theme: (str) + :param use_ttk_buttons: Affects all buttons in window. True = use ttk buttons. False = do not use ttk buttons. None = use ttk buttons only if on a Mac + :type use_ttk_buttons: (bool) + :param modal: If True then this window will be the only window a user can interact with until it is closed + :type modal: (bool) + :param enable_close_attempted_event: If True then the window will not close when "X" clicked. Instead an event WINDOW_CLOSE_ATTEMPTED_EVENT if returned from window.read + :type enable_close_attempted_event: (bool) + :param titlebar_background_color: If custom titlebar indicated by use_custom_titlebar, then use this as background color + :type titlebar_background_color: (str | None) + :param titlebar_text_color: If custom titlebar indicated by use_custom_titlebar, then use this as text color + :type titlebar_text_color: (str | None) + :param titlebar_font: If custom titlebar indicated by use_custom_titlebar, then use this as title font + :type titlebar_font: (str or (str, int[, str]) or None) + :param titlebar_icon: If custom titlebar indicated by use_custom_titlebar, then use this as the icon (file or base64 bytes) + :type titlebar_icon: (bytes | str) + :param use_custom_titlebar: If True, then a custom titlebar will be used instead of the normal titlebar + :type use_custom_titlebar: bool + :param scaling: Apply scaling to the elements in the window. Can be set on a global basis using set_options + :type scaling: float + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + + self._metadata = None # type: Any + self.AutoSizeText = auto_size_text if auto_size_text is not None else DEFAULT_AUTOSIZE_TEXT + self.AutoSizeButtons = auto_size_buttons if auto_size_buttons is not None else DEFAULT_AUTOSIZE_BUTTONS + self.Title = str(title) + self.Rows = [] # a list of ELEMENTS for this row + self.DefaultElementSize = default_element_size if default_element_size is not None else DEFAULT_ELEMENT_SIZE + self.DefaultButtonElementSize = default_button_element_size if default_button_element_size != ( + None, None) else DEFAULT_BUTTON_ELEMENT_SIZE + self.Location = location + self.RelativeLoction = relative_location + self.ButtonColor = button_color_to_tuple(button_color) + self.BackgroundColor = background_color if background_color else DEFAULT_BACKGROUND_COLOR + self.ParentWindow = None + self.Font = font if font else DEFAULT_FONT + self.RadioDict = {} + self.BorderDepth = border_depth + if icon: + self.WindowIcon = icon + elif Window._user_defined_icon is not None: + self.WindowIcon = Window._user_defined_icon + else: + self.WindowIcon = DEFAULT_WINDOW_ICON + self.AutoClose = auto_close + self.NonBlocking = False + self.TKroot = None # type: tk.Tk + self.TKrootDestroyed = False + self.CurrentlyRunningMainloop = False + self.FormRemainedOpen = False + self.TKAfterID = None + self.ProgressBarColor = progress_bar_color + self.AutoCloseDuration = auto_close_duration + self.RootNeedsDestroying = False + self.Shown = False + self.ReturnValues = None + self.ReturnValuesList = [] + self.ReturnValuesDictionary = {} + self.DictionaryKeyCounter = 0 + self.LastButtonClicked = None + self.LastButtonClickedWasRealtime = False + self.UseDictionary = False + self.UseDefaultFocus = use_default_focus + self.ReturnKeyboardEvents = return_keyboard_events + self.LastKeyboardEvent = None + self.TextJustification = text_justification + self.NoTitleBar = no_titlebar + self.Grab = grab_anywhere + self.GrabAnywhere = grab_anywhere + self.GrabAnywhereUsingControlKey = grab_anywhere_using_control + if keep_on_top is None and DEFAULT_KEEP_ON_TOP is not None: + keep_on_top = DEFAULT_KEEP_ON_TOP + elif keep_on_top is None: + keep_on_top = False + self.KeepOnTop = keep_on_top + self.ForceTopLevel = force_toplevel + self.Resizable = resizable + self._AlphaChannel = alpha_channel + self.Timeout = None + self.TimeoutKey = TIMEOUT_KEY + self.TimerCancelled = False + self.DisableClose = disable_close + self.DisableMinimize = disable_minimize + self._Hidden = False + self._Size = size + self.XFound = False + if element_padding is not None: + if isinstance(element_padding, int): + element_padding = (element_padding, element_padding) + + if element_padding is None: + self.ElementPadding = DEFAULT_ELEMENT_PADDING + else: + self.ElementPadding = element_padding + self.RightClickMenu = right_click_menu + self.Margins = margins if margins != (None, None) else DEFAULT_MARGINS + self.ContainerElemementNumber = Window._GetAContainerNumber() + self.AllKeysDict = {} + self.TransparentColor = transparent_color + self.UniqueKeyCounter = 0 + self.DebuggerEnabled = debugger_enabled + self.WasClosed = False + self.ElementJustification = element_justification + self.FocusSet = False + self.metadata = metadata + self.TtkTheme = ttk_theme or DEFAULT_TTK_THEME + self.UseTtkButtons = use_ttk_buttons if use_ttk_buttons is not None else USE_TTK_BUTTONS + self.user_bind_dict = {} # Used when user defines a tkinter binding using bind method - convert bind string to key modifier + self.user_bind_event = None # Used when user defines a tkinter binding using bind method - event data from tkinter + self.modal = modal + self.thread_queue = None # type: queue.Queue + self.thread_lock = None # type: threading.Lock + self.thread_timer = None # type: tk.Misc + self.thread_strvar = None # type: tk.StringVar + self.read_closed_window_count = 0 + self.config_last_size = (None, None) + self.config_last_location = (None, None) + self.starting_window_position = (None, None) + self.not_completed_initial_movement = True + self.config_count = 0 + self.saw_00 = False + self.maximized = False + self.right_click_menu_background_color = right_click_menu_background_color if right_click_menu_background_color is not None else theme_input_background_color() + self.right_click_menu_text_color = right_click_menu_text_color if right_click_menu_text_color is not None else theme_input_text_color() + self.right_click_menu_disabled_text_color = right_click_menu_disabled_text_color if right_click_menu_disabled_text_color is not None else COLOR_SYSTEM_DEFAULT + self.right_click_menu_font = right_click_menu_font if right_click_menu_font is not None else self.Font + self.right_click_menu_tearoff = right_click_menu_tearoff + self.auto_close_timer_needs_starting = False + self.finalize_in_progress = False + self.close_destroys_window = not enable_close_attempted_event if enable_close_attempted_event is not None else None + self.override_custom_titlebar = False + self.use_custom_titlebar = use_custom_titlebar or USE_CUSTOM_TITLEBAR + self.titlebar_background_color = titlebar_background_color + self.titlebar_text_color = titlebar_text_color + self.titlebar_font = titlebar_font + self.titlebar_icon = titlebar_icon + self.right_click_menu_selected_colors = _simplified_dual_color_to_tuple(right_click_menu_selected_colors, + (self.right_click_menu_background_color, self.right_click_menu_text_color)) + self.TKRightClickMenu = None + self._grab_anywhere_ignore_these_list = [] + self._grab_anywhere_include_these_list = [] + self._has_custom_titlebar = use_custom_titlebar + self._mousex = self._mousey = 0 + self._startx = self._starty = 0 + self.scaling = scaling if scaling is not None else DEFAULT_SCALING + if self.use_custom_titlebar: + self.Margins = (0, 0) + self.NoTitleBar = True + + if no_titlebar is True: + self.override_custom_titlebar = True + + if layout is not None and type(layout) not in (list, tuple): + warnings.warn('Your layout is not a list or tuple... this is not good!') + + if layout is not None: + self.Layout(layout) + if finalize: + self.Finalize() + + if CURRENT_LOOK_AND_FEEL == 'Default': + print("Window will be a boring gray. Try removing the theme call entirely\n", + "You will get the default theme or the one set in global settings\n" + "If you seriously want this gray window and no more nagging, add theme('DefaultNoMoreNagging') or theme('Gray Gray Gray') for completely gray/System Defaults") + + + @classmethod + def _GetAContainerNumber(cls): + """ + Not user callable! + :return: A simple counter that makes each container element unique + :rtype: + """ + cls._container_element_counter += 1 + return cls._container_element_counter + + @classmethod + def _IncrementOpenCount(self): + """ + Not user callable! Increments the number of open windows + Note - there is a bug where this count easily gets out of sync. Issue has been opened already. No ill effects + """ + self.NumOpenWindows += 1 + # print('+++++ INCREMENTING Num Open Windows = {} ---'.format(Window.NumOpenWindows)) + + @classmethod + def _DecrementOpenCount(self): + """ + Not user callable! Decrements the number of open windows + """ + self.NumOpenWindows -= 1 * (self.NumOpenWindows != 0) # decrement if not 0 + # print('----- DECREMENTING Num Open Windows = {} ---'.format(Window.NumOpenWindows)) + + @classmethod + def get_screen_size(self): + """ + This is a "Class Method" meaning you call it by writing: width, height = Window.get_screen_size() + Returns the size of the "screen" as determined by tkinter. This can vary depending on your operating system and the number of monitors installed on your system. For Windows, the primary monitor's size is returns. On some multi-monitored Linux systems, the monitors are combined and the total size is reported as if one screen. + + :return: Size of the screen in pixels as determined by tkinter + :rtype: (int, int) + """ + root = tk.Tk() + screen_width = root.winfo_screenwidth() # get window info to move to middle of screen + screen_height = root.winfo_screenheight() + root.destroy() + return screen_width, screen_height + + @property + def metadata(self): + """ + Metadata is available for all windows. You can set to any value. + :return: the current metadata value + :rtype: (Any) + """ + return self._metadata + + @metadata.setter + def metadata(self, value): + """ + Metadata is available for all windows. You can set to any value. + :param value: Anything you want it to be + :type value: (Any) + """ + self._metadata = value + + # ------------------------- Add ONE Row to Form ------------------------- # + def add_row(self, *args): + """ + Adds a single row of elements to a window's self.Rows variables. + Generally speaking this is NOT how users should be building Window layouts. + Users, create a single layout (a list of lists) and pass as a parameter to Window object, or call Window.Layout(layout) + + :param *args: List[Elements] + :type *args: + """ + NumRows = len(self.Rows) # number of existing rows is our row number + CurrentRowNumber = NumRows # this row's number + CurrentRow = [] # start with a blank row and build up + # ------------------------- Add the elements to a row ------------------------- # + for i, element in enumerate(args): # Loop through list of elements and add them to the row + + if isinstance(element, tuple) or isinstance(element, list): + self.add_row(*element) + continue + _error_popup_with_traceback('Error creating Window layout', + 'Layout has a LIST instead of an ELEMENT', + 'This means you have a badly placed ]', + 'The offensive list is:', + element, + 'This list will be stripped from your layout' + ) + continue + elif callable(element) and not isinstance(element, Element): + _error_popup_with_traceback('Error creating Window layout', + 'Layout has a FUNCTION instead of an ELEMENT', + 'This likely means you are missing () from your layout', + 'The offensive list is:', + element, + 'This item will be stripped from your layout') + continue + if element.ParentContainer is not None: + warnings.warn( + '*** YOU ARE ATTEMPTING TO RESUSE AN ELEMENT IN YOUR LAYOUT! Once placed in a layout, an element cannot be used in another layout. ***', + UserWarning) + _error_popup_with_traceback('Error creating Window layout', + 'The layout specified has already been used', + 'You MUST start witha "clean", unused layout every time you create a window', + 'The offensive Element = ', + element, + 'and has a key = ', element.Key, + 'This item will be stripped from your layout', + 'Hint - try printing your layout and matching the IDs "print(layout)"') + continue + element.Position = (CurrentRowNumber, i) + element.ParentContainer = self + CurrentRow.append(element) + # if this element is a titlebar, then automatically set the window margins to (0,0) and turn off normal titlebar + if element.metadata == TITLEBAR_METADATA_MARKER: + self.Margins = (0, 0) + self.NoTitleBar = True + # ------------------------- Append the row to list of Rows ------------------------- # + self.Rows.append(CurrentRow) + + # ------------------------- Add Multiple Rows to Form ------------------------- # + def add_rows(self, rows): + """ + Loops through a list of lists of elements and adds each row, list, to the layout. + This is NOT the best way to go about creating a window. Sending the entire layout at one time and passing + it as a parameter to the Window call is better. + + :param rows: A list of a list of elements + :type rows: List[List[Elements]] + """ + for row in rows: + try: + iter(row) + except TypeError: + _error_popup_with_traceback('Error Creating Window Layout', 'Error creating Window layout', + 'Your row is not an iterable (e.g. a list)', + 'Instead of a list, the type found was {}'.format(type(row)), + 'The offensive row = ', + row, + 'This item will be stripped from your layout') + continue + self.add_row(*row) + + def layout(self, rows): + """ + Second of two preferred ways of telling a Window what its layout is. The other way is to pass the layout as + a parameter to Window object. The parameter method is the currently preferred method. This call to Layout + has been removed from examples contained in documents and in the Demo Programs. Trying to remove this call + from history and replace with sending as a parameter to Window. + + :param rows: Your entire layout + :type rows: List[List[Elements]] + :return: self so that you can chain method calls + :rtype: (Window) + """ + if self.use_custom_titlebar and not self.override_custom_titlebar: + if self.titlebar_icon is not None: + icon = self.titlebar_icon + elif CUSTOM_TITLEBAR_ICON is not None: + icon = CUSTOM_TITLEBAR_ICON + elif self.titlebar_icon is not None: + icon = self.titlebar_icon + elif self.WindowIcon == DEFAULT_WINDOW_ICON: + icon = DEFAULT_BASE64_ICON_16_BY_16 + else: + icon = None + + new_rows = [[Titlebar(title=self.Title, icon=icon, text_color=self.titlebar_text_color, background_color=self.titlebar_background_color, + font=self.titlebar_font)]] + rows + else: + new_rows = rows + self.add_rows(new_rows) + self._BuildKeyDict() + + if self._has_custom_titlebar_element(): + self.Margins = (0, 0) + self.NoTitleBar = True + self._has_custom_titlebar = True + return self + + def extend_layout(self, container, rows): + """ + Adds new rows to an existing container element inside of this window + If the container is a scrollable Column, you need to also call the contents_changed() method + + :param container: The container Element the layout will be placed inside of + :type container: Frame | Column | Tab + :param rows: The layout to be added + :type rows: (List[List[Element]]) + :return: (Window) self so could be chained + :rtype: (Window) + """ + column = Column(rows, pad=(0, 0)) + if self == container: + frame = self.TKroot + elif isinstance(container.Widget, TkScrollableFrame): + frame = container.Widget.TKFrame + else: + frame = container.Widget + PackFormIntoFrame(column, frame, self) + # sg.PackFormIntoFrame(col, window.TKroot, window) + self.AddRow(column) + self.AllKeysDict = self._BuildKeyDictForWindow(self, column, self.AllKeysDict) + return self + + def LayoutAndRead(self, rows, non_blocking=False): + """ + Deprecated!! Now your layout your window's rows (layout) and then separately call Read. + + :param rows: The layout of the window + :type rows: List[List[Element]] + :param non_blocking: if True the Read call will not block + :type non_blocking: (bool) + """ + _error_popup_with_traceback('LayoutAndRead Depricated', 'Wow! You have been using PySimpleGUI for a very long time.', + 'The Window.LayoutAndRead call is no longer supported') + + raise DeprecationWarning( + 'LayoutAndRead is no longer supported... change your call window.Layout(layout).Read()\nor window(title, layout).Read()') + # self.AddRows(rows) + # self._Show(non_blocking=non_blocking) + # return self.ReturnValues + + def LayoutAndShow(self, rows): + """ + Deprecated - do not use any longer. Layout your window and then call Read. Or can add a Finalize call before the Read + """ + raise DeprecationWarning('LayoutAndShow is no longer supported... ') + + def _Show(self, non_blocking=False): + """ + NOT TO BE CALLED BY USERS. INTERNAL ONLY! + It's this method that first shows the window to the user, collects results + + :param non_blocking: if True, this is a non-blocking call + :type non_blocking: (bool) + :return: Tuple[Any, Dict] The event, values turple that is returned from Read calls + :rtype: + """ + self.Shown = True + # Compute num rows & num cols (it'll come in handy debugging) + self.NumRows = len(self.Rows) + self.NumCols = max(len(row) for row in self.Rows) + self.NonBlocking = non_blocking + + # Search through entire form to see if any elements set the focus + # if not, then will set the focus to the first input element + found_focus = False + for row in self.Rows: + for element in row: + try: + if element.Focus: + found_focus = True + except: + pass + try: + if element.Key is not None: + self.UseDictionary = True + except: + pass + + if not found_focus and self.UseDefaultFocus: + self.UseDefaultFocus = True + else: + self.UseDefaultFocus = False + # -=-=-=-=-=-=-=-=- RUN the GUI -=-=-=-=-=-=-=-=- ## + StartupTK(self) + # If a button or keyboard event happened but no results have been built, build the results + if self.LastKeyboardEvent is not None or self.LastButtonClicked is not None: + return _BuildResults(self, False, self) + return self.ReturnValues + + # ------------------------- SetIcon - set the window's fav icon ------------------------- # + def set_icon(self, icon=None, pngbase64=None): + """ + Changes the icon that is shown on the title bar and on the task bar. + NOTE - The file type is IMPORTANT and depends on the OS! + Can pass in: + * filename which must be a .ICO icon file for windows, PNG file for Linux + * bytes object + * BASE64 encoded file held in a variable + + :param icon: Filename or bytes object + :type icon: (str) + :param pngbase64: Base64 encoded image + :type pngbase64: (bytes) + """ + if type(icon) is bytes or pngbase64 is not None: + wicon = tkinter.PhotoImage(data=icon if icon is not None else pngbase64) + try: + self.TKroot.tk.call('wm', 'iconphoto', self.TKroot._w, wicon) + except: + wicon = tkinter.PhotoImage(data=DEFAULT_BASE64_ICON) + try: + self.TKroot.tk.call('wm', 'iconphoto', self.TKroot._w, wicon) + except: + pass + self.WindowIcon = wicon + return + + wicon = icon + try: + self.TKroot.iconbitmap(icon) + except: + try: + wicon = tkinter.PhotoImage(file=icon) + self.TKroot.tk.call('wm', 'iconphoto', self.TKroot._w, wicon) + except: + try: + wicon = tkinter.PhotoImage(data=DEFAULT_BASE64_ICON) + try: + self.TKroot.tk.call('wm', 'iconphoto', self.TKroot._w, wicon) + except: + pass + except: + pass + self.WindowIcon = wicon + + def _GetElementAtLocation(self, location): + """ + Given a (row, col) location in a layout, return the element located at that position + + :param location: (int, int) Return the element located at (row, col) in layout + :type location: + :return: (Element) The Element located at that position in this window + :rtype: + """ + + (row_num, col_num) = location + row = self.Rows[row_num] + element = row[col_num] + return element + + def _GetDefaultElementSize(self): + """ + Returns the default elementSize + + :return: (width, height) of the default element size + :rtype: (int, int) + """ + + return self.DefaultElementSize + + def _AutoCloseAlarmCallback(self): + """ + Function that's called by tkinter when autoclode timer expires. Closes the window + + """ + try: + window = self + if window: + if window.NonBlocking: + self.Close() + else: + window._Close() + self.TKroot.quit() + self.RootNeedsDestroying = True + except: + pass + + def _TimeoutAlarmCallback(self): + """ + Read Timeout Alarm callback. Will kick a mainloop call out of the tkinter event loop and cause it to return + """ + # first, get the results table built + # modify the Results table in the parent FlexForm object + # print('TIMEOUT CALLBACK') + if self.TimerCancelled: + # print('** timer was cancelled **') + return + self.LastButtonClicked = self.TimeoutKey + self.FormRemainedOpen = True + self.TKroot.quit() # kick the users out of the mainloop + + def _calendar_chooser_button_clicked(self, elem): + """ + + :param elem: + :type elem: + :return: + :rtype: + """ + target_element, strvar, should_submit_window = elem._find_target() + + if elem.calendar_default_date_M_D_Y == (None, None, None): + now = datetime.datetime.now() + cur_month, cur_day, cur_year = now.month, now.day, now.year + else: + cur_month, cur_day, cur_year = elem.calendar_default_date_M_D_Y + + date_chosen = popup_get_date(start_mon=cur_month, start_day=cur_day, start_year=cur_year, close_when_chosen=elem.calendar_close_when_chosen, + no_titlebar=elem.calendar_no_titlebar, begin_at_sunday_plus=elem.calendar_begin_at_sunday_plus, + locale=elem.calendar_locale, location=elem.calendar_location, month_names=elem.calendar_month_names, + day_abbreviations=elem.calendar_day_abbreviations, title=elem.calendar_title) + if date_chosen is not None: + month, day, year = 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(elem.calendar_format) + except Exception as e: + print('Bad format string in calendar chooser button', e) + date_string = 'Bad format string' + + if target_element is not None and target_element != elem: + target_element.update(date_string) + elif target_element == elem: + elem.calendar_selection = date_string + + strvar.set(date_string) + elem.TKStringVar.set(date_string) + if should_submit_window: + self.LastButtonClicked = target_element.Key + results = _BuildResults(self, False, self) + else: + should_submit_window = False + return should_submit_window + + # @_timeit_summary + def read(self, timeout=None, timeout_key=TIMEOUT_KEY, close=False): + """ + THE biggest deal method in the Window class! This is how you get all of your data from your Window. + Pass in a timeout (in milliseconds) to wait for a maximum of timeout milliseconds. Will return timeout_key + if no other GUI events happen first. + + :param timeout: Milliseconds to wait until the Read will return IF no other GUI events happen first + :type timeout: (int) + :param timeout_key: The value that will be returned from the call if the timer expired + :type timeout_key: (Any) + :param close: if True the window will be closed prior to returning + :type close: (bool) + :return: (event, values) + :rtype: Tuple[(Any), Dict[Any, Any], List[Any], None] + """ + + if Window._floating_debug_window_build_needed is True: + Window._floating_debug_window_build_needed = False + _Debugger.debugger._build_floating_window() + + if Window._main_debug_window_build_needed is True: + Window._main_debug_window_build_needed = False + _Debugger.debugger._build_main_debugger_window() + + + # ensure called only 1 time through a single read cycle + if not Window._read_call_from_debugger: + _refresh_debugger() + + Window._root_running_mainloop = self.TKroot + + while True: + results = self._read(timeout=timeout, timeout_key=timeout_key) + # Post processing for Calendar Chooser Button + try: + if results[0] == timeout_key: # if a timeout, then not a calendar button + break + elem = self.find_element(results[0], silent_on_error=True) # get the element that caused the event + if elem.Type == ELEM_TYPE_BUTTON: + if elem.BType == BUTTON_TYPE_CALENDAR_CHOOSER: + if self._calendar_chooser_button_clicked(elem): # returns True if should break out + # results[0] = self.LastButtonClicked + results = self.ReturnValues + break + else: + continue + break + except: + break # wasn't a calendar button for sure + + if close: + self.close() + + return results + + # @_timeit + def _read(self, timeout=None, timeout_key=TIMEOUT_KEY): + """ + THE biggest deal method in the Window class! This is how you get all of your data from your Window. + Pass in a timeout (in milliseconds) to wait for a maximum of timeout milliseconds. Will return timeout_key + if no other GUI events happen first. + + :param timeout: Milliseconds to wait until the Read will return IF no other GUI events happen first + :type timeout: (int) + :param timeout_key: The value that will be returned from the call if the timer expired + :type timeout_key: (Any) + :return: (event, values) (event or timeout_key or None, Dictionary of values or List of values from all elements in the Window) + :rtype: Tuple[(Any), Dict[Any, Any], List[Any], None] + """ + + # if there are events in the thread event queue, then return those events before doing anything else. + if self._queued_thread_event_available(): + self.ReturnValues = results = _BuildResults(self, False, self) + return results + + if self.finalize_in_progress and self.auto_close_timer_needs_starting: + self._start_autoclose_timer() + self.auto_close_timer_needs_starting = False + + timeout = int(timeout) if timeout is not None else None + if timeout == 0: # timeout of zero runs the old readnonblocking + event, values = self._ReadNonBlocking() + if event is None: + event = timeout_key + if values is None: + event = None + return event, values # make event None if values was None and return + # Read with a timeout + self.Timeout = timeout + self.TimeoutKey = timeout_key + self.NonBlocking = False + if self.TKrootDestroyed: + self.read_closed_window_count += 1 + if self.read_closed_window_count > 100: + popup_error('You have tried 100 times to read a closed window.', 'You need to add a check for event == WIN_CLOSED', + title='Trying to read a closed window') + return None, None + if not self.Shown: + self._Show() + else: + # if already have a button waiting, the return previously built results + if self.LastButtonClicked is not None and not self.LastButtonClickedWasRealtime: + results = _BuildResults(self, False, self) + self.LastButtonClicked = None + return results + InitializeResults(self) + + if self._queued_thread_event_available(): + self.ReturnValues = results = _BuildResults(self, False, self) + return results + + # if the last button clicked was realtime, emulate a read non-blocking + # the idea is to quickly return realtime buttons without any blocks until released + if self.LastButtonClickedWasRealtime: + # clear the realtime flag if the element is not a button element (for example a graph element that is dragging) + if self.AllKeysDict.get(self.LastButtonClicked, None): + if self.AllKeysDict.get(self.LastButtonClicked).Type != ELEM_TYPE_BUTTON: + self.LastButtonClickedWasRealtime = False # stops from generating events until something changes + else: # it is possible for the key to not be in the dicitonary because it has a modifier. If so, then clear the realtime button flag + self.LastButtonClickedWasRealtime = False # stops from generating events until something changes + + try: + rc = self.TKroot.update() + except: + self.TKrootDestroyed = True + Window._DecrementOpenCount() + # _my_windows.Decrement() + # print('ROOT Destroyed') + results = _BuildResults(self, False, self) + if results[0] != None and results[0] != timeout_key: + return results + else: + pass + + # else: + # print("** REALTIME PROBLEM FOUND **", results) + + if self.RootNeedsDestroying: + # print('*** DESTROYING really late***') + try: + self.TKroot.destroy() + except: + pass + # _my_windows.Decrement() + self.LastButtonClicked = None + return None, None + + # normal read blocking code.... + if timeout != None: + self.TimerCancelled = False + self.TKAfterID = self.TKroot.after(timeout, self._TimeoutAlarmCallback) + self.CurrentlyRunningMainloop = True + # self.TKroot.protocol("WM_DESTROY_WINDOW", self._OnClosingCallback) + # self.TKroot.protocol("WM_DELETE_WINDOW", self._OnClosingCallback) + Window._window_running_mainloop = self + Window._root_running_mainloop.mainloop() + + # print('Out main') + self.CurrentlyRunningMainloop = False + # if self.LastButtonClicked != TIMEOUT_KEY: + try: + self.TKroot.after_cancel(self.TKAfterID) + del self.TKAfterID + except: + pass + # print('** tkafter cancel failed **') + self.TimerCancelled = True + if self.RootNeedsDestroying: + # print('*** DESTROYING LATE ***') + try: + self.TKroot.destroy() + except: + pass + Window._DecrementOpenCount() + # _my_windows.Decrement() + self.LastButtonClicked = None + return None, None + # if form was closed with X + if self.LastButtonClicked is None and self.LastKeyboardEvent is None and self.ReturnValues[0] is None: + Window._DecrementOpenCount() + # _my_windows.Decrement() + # Determine return values + if self.LastKeyboardEvent is not None or self.LastButtonClicked is not None: + results = _BuildResults(self, False, self) + if not self.LastButtonClickedWasRealtime: + self.LastButtonClicked = None + return results + else: + if self._queued_thread_event_available(): + self.ReturnValues = results = _BuildResults(self, False, self) + return results + if not self.XFound and self.Timeout != 0 and self.Timeout is not None and self.ReturnValues[ + 0] is None: # Special Qt case because returning for no reason so fake timeout + self.ReturnValues = self.TimeoutKey, self.ReturnValues[1] # fake a timeout + elif not self.XFound and self.ReturnValues[0] is None: # Return a timeout event... can happen when autoclose used on another window + # print("*** Faking timeout ***") + self.ReturnValues = self.TimeoutKey, self.ReturnValues[1] # fake a timeout + return self.ReturnValues + + def _ReadNonBlocking(self): + """ + Should be NEVER called directly by the user. The user can call Window.Read(timeout=0) to get same effect + + :return: (event, values). (event or timeout_key or None, Dictionary of values or List of values from all elements in the Window) + :rtype: Tuple[(Any), Dict[Any, Any] | List[Any] | None] + """ + if self.TKrootDestroyed: + try: + self.TKroot.quit() + self.TKroot.destroy() + except: + pass + # print('DESTROY FAILED') + return None, None + if not self.Shown: + self._Show(non_blocking=True) + try: + rc = self.TKroot.update() + except: + self.TKrootDestroyed = True + Window._DecrementOpenCount() + # _my_windows.Decrement() + # print("read failed") + # return None, None + if self.RootNeedsDestroying: + # print('*** DESTROYING LATE ***', self.ReturnValues) + self.TKroot.destroy() + Window._DecrementOpenCount() + # _my_windows.Decrement() + self.Values = None + self.LastButtonClicked = None + return None, None + return _BuildResults(self, False, self) + + def _start_autoclose_timer(self): + duration = DEFAULT_AUTOCLOSE_TIME if self.AutoCloseDuration is None else self.AutoCloseDuration + self.TKAfterID = self.TKroot.after(int(duration * 1000), self._AutoCloseAlarmCallback) + + def finalize(self): + """ + Use this method to cause your layout to built into a real tkinter window. In reality this method is like + Read(timeout=0). It doesn't block and uses your layout to create tkinter widgets to represent the elements. + Lots of action! + + :return: Returns 'self' so that method "Chaining" can happen (read up about it as it's very cool!) + :rtype: (Window) + """ + + if self.TKrootDestroyed: + return self + self.finalize_in_progress = True + + self.Read(timeout=1) + + if self.AutoClose: + self.auto_close_timer_needs_starting = True + # add the window to the list of active windows + Window._active_windows[self] = Window.hidden_master_root + return self + # OLD CODE FOLLOWS + if not self.Shown: + self._Show(non_blocking=True) + try: + rc = self.TKroot.update() + except: + self.TKrootDestroyed = True + Window._DecrementOpenCount() + print('** Finalize failed **') + # _my_windows.Decrement() + # return None, None + return self + + def refresh(self): + """ + Refreshes the window by calling tkroot.update(). Can sometimes get away with a refresh instead of a Read. + Use this call when you want something to appear in your Window immediately (as soon as this function is called). + Without this call your changes to a Window will not be visible to the user until the next Read call + + :return: `self` so that method calls can be easily "chained" + :rtype: (Window) + """ + + if self.TKrootDestroyed: + return self + try: + rc = self.TKroot.update() + except: + pass + return self + + def fill(self, values_dict): + """ + Fill in elements that are input fields with data based on a 'values dictionary' + + :param values_dict: pairs + :type values_dict: (Dict[Any, Any]) - {Element_key : value} + :return: returns self so can be chained with other methods + :rtype: (Window) + """ + + FillFormWithValues(self, values_dict) + return self + + def _find_closest_key(self, search_key): + if not isinstance(search_key, str): + search_key = str(search_key) + matches = difflib.get_close_matches(search_key, [str(k) for k in self.AllKeysDict.keys()]) + if not len(matches): + return None + for k in self.AllKeysDict.keys(): + if matches[0] == str(k): + return k + return matches[0] if len(matches) else None + + def FindElement(self, key, silent_on_error=False): + """ + ** Warning ** This call will eventually be depricated. ** + + It is suggested that you modify your code to use the recommended window[key] lookup or the PEP8 compliant window.find_element(key) + + For now, you'll only see a message printed and the call will continue to funcation as before. + + :param key: Used with window.find_element and with return values to uniquely identify this element + :type key: str | int | tuple | object + :param silent_on_error: If True do not display popup nor print warning of key errors + :type silent_on_error: (bool) + :return: Return value can be: the Element that matches the supplied key if found; an Error Element if silent_on_error is False; None if silent_on_error True; + :rtype: Element | Error Element | None + """ + + warnings.warn('Use of FindElement is not recommended.\nEither switch to the recommended window[key] format\nor the PEP8 compliant find_element', + UserWarning) + print('** Warning - FindElement should not be used to look up elements. window[key] or window.find_element are recommended. **') + + return self.find_element(key, silent_on_error=silent_on_error) + + def find_element(self, key, silent_on_error=False): + """ + Find element object associated with the provided key. + THIS METHOD IS NO LONGER NEEDED to be called by the user + + You can perform the same operation by writing this statement: + element = window[key] + + You can drop the entire "find_element" function name and use [ ] instead. + + However, if you wish to perform a lookup without error checking, and don't have error popups turned + off globally, you'll need to make this call so that you can disable error checks on this call. + + find_element is yypically used in combination with a call to element's Update method (or any other element method!): + window[key].update(new_value) + + Versus the "old way" + window.FindElement(key).Update(new_value) + + This call can be abbreviated to any of these: + find_element = FindElement == Element == Find + With find_element being the PEP8 compliant call that should be used. + + Rememeber that this call will return None if no match is found which may cause your code to crash if not + checked for. + + :param key: Used with window.find_element and with return values to uniquely identify this element + :type key: str | int | tuple | object + :param silent_on_error: If True do not display popup nor print warning of key errors + :type silent_on_error: (bool) + :return: Return value can be: the Element that matches the supplied key if found; an Error Element if silent_on_error is False; None if silent_on_error True; + :rtype: Element | Error Element | None + """ + try: + element = self.AllKeysDict[key] + key_error = False + except KeyError: + closest_key = self._find_closest_key(key) + if not silent_on_error: + print('** Error looking up your element using the key: ', key, 'The closest matching key: ', closest_key) + _error_popup_with_traceback('Key Error', 'Problem finding your key ' + str(key), 'Closest match = ' + str(closest_key)) + if not SUPPRESS_RAISE_KEY_ERRORS: + raise KeyError(key) + element = ErrorElement(key=key) + key_error = True + else: + element = ErrorElement(key=key) + return element + if key_error: + if closest_key is not None and not SUPPRESS_KEY_GUESSING: + element = self.AllKeysDict[closest_key] + return element + if not SUPPRESS_RAISE_KEY_ERRORS: + raise KeyError(key) + return element + + Element = find_element # Shortcut function + Find = find_element # Shortcut function, most likely not used by many people. + Elem = find_element # NEW for 2019! More laziness... Another shortcut + + def find_element_with_focus(self): + """ + Returns the Element that currently has focus as reported by tkinter. If no element is found None is returned! + :return: An Element if one has been found with focus or None if no element found + :rtype: Element | None + """ + element = _FindElementWithFocusInSubForm(self) + return element + + def _BuildKeyDict(self): + """ + Used internally only! Not user callable + Builds a dictionary containing all elements with keys for this window. + """ + dict = {} + self.AllKeysDict = self._BuildKeyDictForWindow(self, self, dict) + + def _BuildKeyDictForWindow(self, top_window, window, key_dict): + """ + Loop through all Rows and all Container Elements for this window and create the keys for all of them. + Note that the calls are recursive as all pathes must be walked + + :param top_window: The highest level of the window + :type top_window: (Window) + :param window: The "sub-window" (container element) to be searched + :type window: Column | Frame | TabGroup | Pane | Tab + :param key_dict: The dictionary as it currently stands.... used as part of recursive call + :type key_dict: + :return: (dict) Dictionary filled with all keys in the window + :rtype: + """ + for row_num, row in enumerate(window.Rows): + for col_num, element in enumerate(row): + if element.Type == ELEM_TYPE_COLUMN: + key_dict = self._BuildKeyDictForWindow(top_window, element, key_dict) + if element.Type == ELEM_TYPE_FRAME: + key_dict = self._BuildKeyDictForWindow(top_window, element, key_dict) + if element.Type == ELEM_TYPE_TAB_GROUP: + key_dict = self._BuildKeyDictForWindow(top_window, element, key_dict) + if element.Type == ELEM_TYPE_PANE: + key_dict = self._BuildKeyDictForWindow(top_window, element, key_dict) + if element.Type == ELEM_TYPE_TAB: + key_dict = self._BuildKeyDictForWindow(top_window, element, key_dict) + if element.Key is None: # if no key has been assigned.... create one for input elements + if element.Type == ELEM_TYPE_BUTTON: + element.Key = element.ButtonText + elif element.Type == ELEM_TYPE_TAB: + element.Key = element.Title + if element.Type in (ELEM_TYPE_MENUBAR, ELEM_TYPE_BUTTONMENU, + ELEM_TYPE_INPUT_SLIDER, ELEM_TYPE_GRAPH, ELEM_TYPE_IMAGE, + ELEM_TYPE_INPUT_CHECKBOX, ELEM_TYPE_INPUT_LISTBOX, ELEM_TYPE_INPUT_COMBO, + ELEM_TYPE_INPUT_MULTILINE, ELEM_TYPE_INPUT_OPTION_MENU, ELEM_TYPE_INPUT_SPIN, + ELEM_TYPE_INPUT_RADIO, ELEM_TYPE_INPUT_TEXT, ELEM_TYPE_PROGRESS_BAR, + ELEM_TYPE_TABLE, ELEM_TYPE_TREE, + ELEM_TYPE_TAB_GROUP, ELEM_TYPE_SEPARATOR): + element.Key = top_window.DictionaryKeyCounter + top_window.DictionaryKeyCounter += 1 + if element.Key is not None: + if element.Key in key_dict.keys(): + if element.Type == ELEM_TYPE_BUTTON and WARN_DUPLICATE_BUTTON_KEY_ERRORS: # for Buttons see if should complain + warnings.warn('*** Duplicate key found in your layout {} ***'.format(element.Key), UserWarning) + warnings.warn('*** Replaced new key with {} ***'.format(str(element.Key) + str(self.UniqueKeyCounter))) + if not SUPPRESS_ERROR_POPUPS: + _error_popup_with_traceback('Duplicate key found in your layout', 'Dupliate key: {}'.format(element.Key), + 'Is being replaced with: {}'.format(str(element.Key) + str(self.UniqueKeyCounter)), + 'The line of code above shows you which layout, but does not tell you exactly where the element was defined', + 'The element type is {}'.format(element.Type)) + element.Key = str(element.Key) + str(self.UniqueKeyCounter) + self.UniqueKeyCounter += 1 + key_dict[element.Key] = element + return key_dict + + def element_list(self): + """ + Returns a list of all elements in the window + + :return: List of all elements in the window and container elements in the window + :rtype: List[Element] + """ + return self._build_element_list() + + def _build_element_list(self): + """ + Used internally only! Not user callable + Builds a dictionary containing all elements with keys for this window. + """ + elem_list = [] + elem_list = self._build_element_list_for_form(self, self, elem_list) + return elem_list + + def _build_element_list_for_form(self, top_window, window, elem_list): + """ + Loop through all Rows and all Container Elements for this window and create a list + Note that the calls are recursive as all pathes must be walked + + :param top_window: The highest level of the window + :type top_window: (Window) + :param window: The "sub-window" (container element) to be searched + :type window: Column | Frame | TabGroup | Pane | Tab + :param elem_list: The element list as it currently stands.... used as part of recursive call + :type elem_list: ??? + :return: List of all elements in this sub-window + :rtype: List[Element] + """ + for row_num, row in enumerate(window.Rows): + for col_num, element in enumerate(row): + elem_list.append(element) + if element.Type in (ELEM_TYPE_COLUMN, ELEM_TYPE_FRAME, ELEM_TYPE_TAB_GROUP, ELEM_TYPE_PANE, ELEM_TYPE_TAB): + elem_list = self._build_element_list_for_form(top_window, element, elem_list) + return elem_list + + def save_to_disk(self, filename): + """ + Saves the values contained in each of the input areas of the form. Basically saves what would be returned from a call to Read. It takes these results and saves them to disk using pickle. + Note that every element in your layout that is to be saved must have a key assigned to it. + + :param filename: Filename to save the values to in pickled form + :type filename: str + """ + try: + event, values = _BuildResults(self, False, self) + remove_these = [] + for key in values: + if self.Element(key).Type == ELEM_TYPE_BUTTON: + remove_these.append(key) + for key in remove_these: + del values[key] + with open(filename, 'wb') as sf: + pickle.dump(values, sf) + except: + print('*** Error saving Window contents to disk ***') + + def load_from_disk(self, filename): + """ + Restore values from a previous call to SaveToDisk which saves the returned values dictionary in Pickle format + + :param filename: Pickle Filename to load + :type filename: (str) + """ + try: + with open(filename, 'rb') as df: + self.Fill(pickle.load(df)) + except: + print('*** Error loading form to disk ***') + + def get_screen_dimensions(self): + """ + Get the screen dimensions. NOTE - you must have a window already open for this to work (blame tkinter not me) + + :return: Tuple containing width and height of screen in pixels + :rtype: Tuple[None, None] | Tuple[width, height] + """ + + if self.TKrootDestroyed or self.TKroot is None: + return Window.get_screen_size() + screen_width = self.TKroot.winfo_screenwidth() # get window info to move to middle of screen + screen_height = self.TKroot.winfo_screenheight() + return screen_width, screen_height + + def move(self, x, y): + """ + Move the upper left corner of this window to the x,y coordinates provided + :param x: x coordinate in pixels + :type x: (int) + :param y: y coordinate in pixels + :type y: (int) + """ + try: + self.TKroot.geometry("+%s+%s" % (x, y)) + self.config_last_location = (int(x), (int(y))) + + except: + pass + + + def move_to_center(self): + """ + Recenter your window after it's been moved or the size changed. + + This is a conveinence method. There are no tkinter calls involved, only pure PySimpleGUI API calls. + """ + if not self._is_window_created('tried Window.move_to_center'): + return + screen_width, screen_height = self.get_screen_dimensions() + win_width, win_height = self.size + x, y = (screen_width - win_width)//2, (screen_height - win_height)//2 + self.move(x, y) + + + + def minimize(self): + """ + Minimize this window to the task bar + """ + if not self._is_window_created('tried Window.minimize'): + return + self.TKroot.iconify() + self.maximized = False + + def maximize(self): + """ + Maximize the window. This is done differently on a windows system versus a linux or mac one. For non-Windows + the root attribute '-fullscreen' is set to True. For Windows the "root" state is changed to "zoomed" + The reason for the difference is the title bar is removed in some cases when using fullscreen option + """ + + if not self._is_window_created('tried Window.maximize'): + return + if not running_linux(): + self.TKroot.state('zoomed') + else: + self.TKroot.attributes('-fullscreen', True) + # this method removes the titlebar too + # self.TKroot.attributes('-fullscreen', True) + self.maximized = True + + def normal(self): + """ + Restore a window to a non-maximized state. Does different things depending on platform. See Maximize for more. + """ + if not self._is_window_created('tried Window.normal'): + return + if self.TKroot.state() == 'iconic': + self.TKroot.deiconify() + else: + if not running_linux(): + self.TKroot.state('normal') + else: + self.TKroot.attributes('-fullscreen', False) + self.maximized = False + + + def _StartMoveUsingControlKey(self, event): + """ + Used by "Grab Anywhere" style windows. This function is bound to mouse-down. It marks the beginning of a drag. + :param event: event information passed in by tkinter. Contains x,y position of mouse + :type event: (event) + """ + + self._StartMove(event) + + + def _StartMoveGrabAnywhere(self, event): + + + """ + Used by "Grab Anywhere" style windows. This function is bound to mouse-down. It marks the beginning of a drag. + :param event: event information passed in by tkinter. Contains x,y position of mouse + :type event: (event) + """ + if (isinstance(event.widget, GRAB_ANYWHERE_IGNORE_THESE_WIDGETS) or event.widget in self._grab_anywhere_ignore_these_list) and event.widget not in self._grab_anywhere_include_these_list: + # print('Found widget to ignore in grab anywhere...') + return + + self._StartMove(event) + + + def _StartMove(self, event): + try: + geometry = self.TKroot.geometry() + location = geometry[geometry.find('+')+1:].split('+') + self._startx = int(location[0]) + self._starty = int(location[1]) + self._mousex = event.x + event.widget.winfo_rootx() + self._mousey = event.y + event.widget.winfo_rooty() + # print(self._startx, self._starty) + # print(self._mousex, self._mousey) + # print(self.TKroot.geometry()) + except: + pass + # print('Start move {},{} widget {}'.format(event.x,event.y, event.widget)) + + if Window._move_all_windows: + for window in Window._active_windows: + window._offsetx = event.x + event.widget.winfo_rootx() - window.TKroot.winfo_rootx() + window._offsety = event.y + event.widget.winfo_rooty() - window.TKroot.winfo_rooty() + + + + def _StopMove(self, event): + """ + Used by "Grab Anywhere" style windows. This function is bound to mouse-up. It marks the ending of a drag. + Sets the position of the window to this final x,y coordinates + :param event: event information passed in by tkinter. Contains x,y position of mouse + :type event: (event) + """ + return + + + def _OnMotionUsingControlKey(self, event): + self._OnMotion(event) + + + def _OnMotionGrabAnywhere(self, event): + + """ + Used by "Grab Anywhere" style windows. This function is bound to mouse motion. It actually moves the window + :param event: event information passed in by tkinter. Contains x,y position of mouse + :type event: (event) + """ + if (isinstance(event.widget, GRAB_ANYWHERE_IGNORE_THESE_WIDGETS) or event.widget in self._grab_anywhere_ignore_these_list) and event.widget not in self._grab_anywhere_include_these_list: + # print('Found widget to ignore in grab anywhere...') + return + + self._OnMotion(event) + + + def _OnMotion(self, event): + try: + + _mousex = event.x + event.widget.winfo_rootx() + _mousey = event.y + event.widget.winfo_rooty() + deltax = _mousex - self._mousex + deltay = _mousey - self._mousey + x = self._startx + deltax + y = self._starty + deltay + self.TKroot.geometry("+%s+%s" % (x, y)) # this is what really moves the window + if Window._move_all_windows: + for window in Window._active_windows: + deltax = window._offsetx + deltay = window._offsety + x = window.TKroot.winfo_pointerx() - deltax + y = window.TKroot.winfo_pointery() - deltay + window.TKroot.geometry("+%s+%s" % (x, y)) # this is what really moves the window + except Exception as e: + print('on motion error', e) + + def _focus_callback(self, event): + print('Focus event = {} window = {}'.format(event, self.Title)) + + def _config_callback(self, event): + print('Config event = {} window = {}'.format(event, self.Title)) + # + # try: + # deltax = event.x - self.TKroot.x + # deltay = event.y - self.TKroot.y + # x = self.TKroot.winfo_x() + deltax + # y = self.TKroot.winfo_y() + deltay + # self.TKroot.geometry("+%s+%s" % (x, y)) # this is what really moves the window + # # print('{},{}'.format(x,y)) + # + # if Window._move_all_windows: + # for window in Window._active_windows: + # x = window.TKroot.winfo_x() + deltax + # y = window.TKroot.winfo_y() + deltay + # window.TKroot.geometry("+%s+%s" % (x, y)) # this is what really moves the window + # except Exception as e: + # print('on motion error {}'.format(e), 'title = {}'.format(window.Title)) + + """ + def _config_callback(self, event): + new_x = event.x + new_y = event.y + + + if self.not_completed_initial_movement: + if self.starting_window_position != (new_x, new_y): + return + self.not_completed_initial_movement = False + return + + if not self.saw_00: + if new_x == 0 and new_y == 0: + self.saw_00 = True + + # self.config_count += 1 + # if self.config_count < 40: + # return + + print('Move LOGIC') + + if self.config_last_size != (event.width, event.height): + self.config_last_size = (event.width, event.height) + + if self.config_last_location[0] != new_x or self.config_last_location[1] != new_y: + if self.config_last_location == (None, None): + self.config_last_location = (new_x, new_y) + return + + deltax = self.config_last_location[0] - event.x + deltay = self.config_last_location[1] - event.y + if deltax == 0 and deltay == 0: + print('not moving so returning') + return + if Window._move_all_windows: + print('checking all windows') + for window in Window._active_windows: + if window == self: + continue + x = window.TKroot.winfo_x() + deltax + y = window.TKroot.winfo_y() + deltay + # window.TKroot.geometry("+%s+%s" % (x, y)) # this is what really moves the window + # window.config_last_location = (x,y) + """ + + def _KeyboardCallback(self, event): + """ + Window keyboard callback. Called by tkinter. Will kick user out of the tkinter event loop. Should only be + called if user has requested window level keyboard events + + :param event: object provided by tkinter that contains the key information + :type event: (event) + """ + self.LastButtonClicked = None + self.FormRemainedOpen = True + if event.char != '': + self.LastKeyboardEvent = event.char + else: + self.LastKeyboardEvent = str(event.keysym) + ':' + str(event.keycode) + # if not self.NonBlocking: + # _BuildResults(self, False, self) + _exit_mainloop(self) + + def _MouseWheelCallback(self, event): + """ + Called by tkinter when a mouse wheel event has happened. Only called if keyboard events for the window + have been enabled + + :param event: object sent in by tkinter that has the wheel direction + :type event: (event) + """ + self.LastButtonClicked = None + self.FormRemainedOpen = True + self.LastKeyboardEvent = 'MouseWheel:Down' if event.delta < 0 or event.num == 5 else 'MouseWheel:Up' + # if not self.NonBlocking: + # _BuildResults(self, False, self) + _exit_mainloop(self) + + def _Close(self, without_event=False): + """ + The internal close call that does the real work of building. This method basically sets up for closing + but doesn't destroy the window like the User's version of Close does + + :parm without_event: if True, then do not cause an event to be generated, "silently" close the window + :type without_event: (bool) + """ + try: + self.TKroot.update() + except: + pass + + if not self.NonBlocking or not without_event: + _BuildResults(self, False, self) + if self.TKrootDestroyed: + return + self.TKrootDestroyed = True + self.RootNeedsDestroying = True + return + + def close(self): + """ + Closes window. Users can safely call even if window has been destroyed. Should always call when done with + a window so that resources are properly freed up within your thread. + """ + try: + del Window._active_windows[self] # will only be in the list if window was explicitly finalized + except: + pass + + try: + self.TKroot.update() # On Linux must call update if the user closed with X or else won't actually close the window + except: + pass + if self.TKrootDestroyed: + return + try: + self.TKroot.destroy() + self.TKroot.update() + Window._DecrementOpenCount() + except: + pass + # if down to 1 window, try and destroy the hidden window, if there is one + # if Window.NumOpenWindows == 1: + # try: + # Window.hidden_master_root.destroy() + # Window.NumOpenWindows = 0 # if no hidden window, then this won't execute + # except: + # pass + self.TKrootDestroyed = True + + # Free up anything that was held in the layout and the root variables + self.Rows = None + self.TKroot = None + + # IT FINALLY WORKED! 29-Oct-2018 was the first time this damned thing got called + def _OnClosingCallback(self): + """ + Internally used method ONLY. Not sure callable. tkinter calls this when the window is closed by clicking X + """ + # global _my_windows + # print('Got closing callback', self.DisableClose) + if self.DisableClose: + return + if self.CurrentlyRunningMainloop: # quit if this is the current mainloop, otherwise don't quit! + _exit_mainloop(self) + if self.close_destroys_window: + self.TKroot.destroy() # destroy this window + self.TKrootDestroyed = True + self.XFound = True + else: + self.LastButtonClicked = WINDOW_CLOSE_ATTEMPTED_EVENT + elif Window._root_running_mainloop == Window.hidden_master_root: + _exit_mainloop(self) + else: + if self.close_destroys_window: + self.TKroot.destroy() # destroy this window + self.XFound = True + else: + self.LastButtonClicked = WINDOW_CLOSE_ATTEMPTED_EVENT + if self.close_destroys_window: + self.RootNeedsDestroying = True + + def disable(self): + """ + Disables window from taking any input from the user + """ + if not self._is_window_created('tried Window.disable'): + return + self.TKroot.attributes('-disabled', 1) + # self.TKroot.grab_set_global() + + def enable(self): + """ + Re-enables window to take user input after having it be Disabled previously + """ + if not self._is_window_created('tried Window.enable'): + return + self.TKroot.attributes('-disabled', 0) + # self.TKroot.grab_release() + + def hide(self): + """ + Hides the window from the screen and the task bar + """ + if not self._is_window_created('tried Window.hide'): + return + self._Hidden = True + self.TKroot.withdraw() + + def un_hide(self): + """ + Used to bring back a window that was previously hidden using the Hide method + """ + if not self._is_window_created('tried Window.un_hide'): + return + if self._Hidden: + self.TKroot.deiconify() + self._Hidden = False + + def disappear(self): + """ + Causes a window to "disappear" from the screen, but remain on the taskbar. It does this by turning the alpha + channel to 0. NOTE that on some platforms alpha is not supported. The window will remain showing on these + platforms. The Raspberry Pi for example does not have an alpha setting + """ + if not self._is_window_created('tried Window.disappear'): + return + self.TKroot.attributes('-alpha', 0) + + def reappear(self): + """ + Causes a window previously made to "Disappear" (using that method). Does this by restoring the alpha channel + """ + if not self._is_window_created('tried Window.reappear'): + return + self.TKroot.attributes('-alpha', 255) + + def set_alpha(self, alpha): + """ + Sets the Alpha Channel for a window. Values are between 0 and 1 where 0 is completely transparent + + :param alpha: 0 to 1. 0 is completely transparent. 1 is completely visible and solid (can't see through) + :type alpha: (float) + """ + if not self._is_window_created('tried Window.set_alpha'): + return + self._AlphaChannel = alpha + self.TKroot.attributes('-alpha', alpha) + + @property + def alpha_channel(self): + """ + A property that changes the current alpha channel value (internal value) + :return: the current alpha channel setting according to self, not read directly from tkinter + :rtype: (float) + """ + return self._AlphaChannel + + @alpha_channel.setter + def alpha_channel(self, alpha): + """ + The setter method for this "property". + Planning on depricating so that a Set call is always used by users. This is more in line with the SDK + :param alpha: 0 to 1. 0 is completely transparent. 1 is completely visible and solid (can't see through) + :type alpha: (float) + """ + if not self._is_window_created('tried Window.alpha_channel'): + return + self._AlphaChannel = alpha + self.TKroot.attributes('-alpha', alpha) + + def bring_to_front(self): + """ + Brings this window to the top of all other windows (perhaps may not be brought before a window made to "stay + on top") + """ + if not self._is_window_created('tried Window.bring_to_front'): + return + if running_windows(): + try: + self.TKroot.wm_attributes("-topmost", 0) + self.TKroot.wm_attributes("-topmost", 1) + if not self.KeepOnTop: + self.TKroot.wm_attributes("-topmost", 0) + except Exception as e: + warnings.warn('Problem in Window.bring_to_front' + str(e), UserWarning) + else: + try: + self.TKroot.lift() + except: + pass + + def send_to_back(self): + """ + Pushes this window to the bottom of the stack of windows. It is the opposite of BringToFront + """ + if not self._is_window_created('tried Window.send_to_back'): + return + try: + self.TKroot.lower() + except: + pass + + + def keep_on_top_set(self): + """ + Sets keep_on_top after a window has been created. Effect is the same + as if the window was created with this set. The Window is also brought + to the front + """ + if not self._is_window_created('tried Window.keep_on_top_set'): + return + self.KeepOnTop = True + self.bring_to_front() + try: + self.TKroot.wm_attributes("-topmost", 1) + except Exception as e: + warnings.warn('Problem in Window.keep_on_top_set trying to set wm_attributes topmost' + str(e), UserWarning) + + + def keep_on_top_clear(self): + """ + Clears keep_on_top after a window has been created. Effect is the same + as if the window was created with this set. + """ + if not self._is_window_created('tried Window.keep_on_top_clear'): + return + self.KeepOnTop = False + try: + self.TKroot.wm_attributes("-topmost", 0) + except Exception as e: + warnings.warn('Problem in Window.keep_on_top_clear trying to clear wm_attributes topmost' + str(e), UserWarning) + + + + def current_location(self, more_accurate=False): + """ + Get the current location of the window's top left corner. + Sometimes, depending on the environment, the value returned does not include the titlebar,etc + A new option, more_accurate, can be used to get the theoretical upper leftmost corner of the window. + The titlebar and menubar are crated by the OS. It gets really confusing when running in a webpage (repl, trinket) + Thus, the values can appear top be "off" due to the sometimes unpredictable way the location is calculated. + + :param more_accurate: If True, will use the window's geometry to get the topmost location with titlebar, menubar taken into account + :type more_accurate: (bool) + :return: The x and y location in tuple form (x,y) + :rtype: Tuple[(int | None), (int | None)] + """ + + if not self._is_window_created('tried Window.current_location'): + return (None, None) + try: + if more_accurate: + geometry = self.TKroot.geometry() + location = geometry[geometry.find('+') + 1:].split('+') + x, y = int(location[0]), int(location[1]) + else: + x, y = int(self.TKroot.winfo_x()), int(self.TKroot.winfo_y()) + except Exception as e: + warnings.warn('Error in Window.current_location. Trouble getting x,y location\n' + str(e), UserWarning) + x, y = (None, None) + return (x,y) + + def current_size_accurate(self): + """ + Get the current location of the window based on tkinter's geometry setting + + :return: The x and y size in tuple form (x,y) + :rtype: Tuple[(int | None), (int | None)] + """ + + if not self._is_window_created('tried Window.current_location'): + return (None, None) + try: + geometry = self.TKroot.geometry() + geometry_tuple = geometry.split('+') + window_size = geometry_tuple[0].split('x') + x, y = int(window_size[0]), int(window_size[1]) + except Exception as e: + warnings.warn('Error in Window.current_size_accurate. Trouble getting x,y size\n{} {}'.format(geometry, geometry_tuple) + str(e), UserWarning) + x, y = (None, None) + return (x,y) + + @property + def size(self): + """ + Return the current size of the window in pixels + + :return: (width, height) of the window + :rtype: Tuple[(int), (int)] or Tuple[None, None] + """ + if not self._is_window_created('Tried to use Window.size property'): + return (None, None) + win_width = self.TKroot.winfo_width() + win_height = self.TKroot.winfo_height() + return win_width, win_height + + @size.setter + def size(self, size): + """ + Changes the size of the window, if possible + + :param size: (width, height) of the desired window size + :type size: (int, int) + """ + try: + self.TKroot.geometry("%sx%s" % (size[0], size[1])) + self.TKroot.update_idletasks() + except: + pass + + def set_min_size(self, size): + """ + Changes the minimum size of the window. Note Window must be read or finalized first. + + :param size: (width, height) tuple (int, int) of the desired window size in pixels + :type size: (int, int) + """ + if not self._is_window_created('tried Window.set_min_size'): + return + self.TKroot.minsize(size[0], size[1]) + self.TKroot.update_idletasks() + + def visibility_changed(self): + """ + When making an element in a column or someplace that has a scrollbar, then you'll want to call this function + prior to the column's contents_changed() method. + """ + self.refresh() + + def set_transparent_color(self, color): + """ + Set the color that will be transparent in your window. Areas with this color will be SEE THROUGH. + + :param color: Color string that defines the transparent color + :type color: (str) + """ + if not self._is_window_created('tried Window.set_transparent_color'): + return + try: + self.TKroot.attributes('-transparentcolor', color) + self.TransparentColor = color + except: + print('Transparent color not supported on this platform (windows only)') + + def mouse_location(self): + """ + Return the (x,y) location of the mouse relative to the entire screen. It's the same location that + you would use to create a window, popup, etc. + + :return: The location of the mouse pointer + :rtype: (int, int) + """ + if not self._is_window_created('tried Window.mouse_location'): + return (0,0) + + return (self.TKroot.winfo_pointerx(), self.TKroot.winfo_pointery()) + + def grab_any_where_on(self): + """ + Turns on Grab Anywhere functionality AFTER a window has been created. Don't try on a window that's not yet + been Finalized or Read. + """ + if not self._is_window_created('tried Window.grab_any_where_on'): + return + self.TKroot.bind("", self._StartMoveGrabAnywhere) + self.TKroot.bind("", self._StopMove) + self.TKroot.bind("", self._OnMotionGrabAnywhere) + + def grab_any_where_off(self): + """ + Turns off Grab Anywhere functionality AFTER a window has been created. Don't try on a window that's not yet + been Finalized or Read. + """ + if not self._is_window_created('tried Window.grab_any_where_off'): + return + self.TKroot.unbind("") + self.TKroot.unbind("") + self.TKroot.unbind("") + + def _user_bind_callback(self, bind_string, event): + """ + Used when user binds a tkinter event directly to an element + + :param bind_string: The event that was bound so can lookup the key modifier + :type bind_string: (str) + :param event: Event data passed in by tkinter (not used) + :type event: + """ + # print('bind callback', bind_string, event) + key = self.user_bind_dict.get(bind_string, '') + self.user_bind_event = event + if key is not None: + self.LastButtonClicked = key + else: + self.LastButtonClicked = bind_string + self.FormRemainedOpen = True + # if self.CurrentlyRunningMainloop: + # self.TKroot.quit() + _exit_mainloop(self) + + def bind(self, bind_string, key): + """ + Used to add tkinter events to a Window. + The tkinter specific data is in the Window's member variable user_bind_event + :param bind_string: The string tkinter expected in its bind function + :type bind_string: (str) + :param key: The event that will be generated when the tkinter event occurs + :type key: str | int | tuple | object + """ + if not self._is_window_created('tried Window.bind'): + return + self.TKroot.bind(bind_string, lambda evt: self._user_bind_callback(bind_string, evt)) + self.user_bind_dict[bind_string] = key + + def _callback_main_debugger_window_create_keystroke(self, event): + """ + Called when user presses the key that creates the main debugger window + + :param event: (event) not used. Passed in event info + :type event: + """ + Window._main_debug_window_build_needed = True + # _Debugger.debugger._build_main_debugger_window() + + def _callback_popout_window_create_keystroke(self, event): + """ + Called when user presses the key that creates the floating debugger window + + :param event: (event) not used. Passed in event info + :type event: + """ + Window._floating_debug_window_build_needed = True + # _Debugger.debugger._build_floating_window() + + def enable_debugger(self): + """ + Enables the internal debugger. By default, the debugger IS enabled + """ + if not self._is_window_created('tried Window.enable_debugger'): + return + self.TKroot.bind('', self._callback_main_debugger_window_create_keystroke) + self.TKroot.bind('', self._callback_popout_window_create_keystroke) + self.DebuggerEnabled = True + + def disable_debugger(self): + """ + Disable the internal debugger. By default the debugger is ENABLED + """ + if not self._is_window_created('tried Window.disable_debugger'): + return + self.TKroot.unbind("") + self.TKroot.unbind("") + self.DebuggerEnabled = False + + def set_title(self, title): + """ + Change the title of the window + + :param title: The string to set the title to + :type title: (str) + """ + if not self._is_window_created('tried Window.set_title'): + return + self.TKroot.wm_title(str(title)) + + def make_modal(self): + """ + Makes a window into a "Modal Window" + This means user will not be able to interact with other windows until this one is closed + + NOTE - Sorry Mac users - you can't have modal windows.... lobby your tkinter Mac devs + """ + if not self._is_window_created('tried Window.make_modal'): + return + + if running_mac() and ENABLE_MAC_MODAL_DISABLE_PATCH: + return + + try: + self.TKroot.transient() + self.TKroot.grab_set() + self.TKroot.focus_force() + except Exception as e: + print('Exception trying to make modal', e) + + def force_focus(self): + """ + Forces this window to take focus + """ + if not self._is_window_created('tried Window.force_focus'): + return + self.TKroot.focus_force() + + def was_closed(self): + """ + Returns True if the window was closed + + :return: True if the window is closed + :rtype: bool + """ + return self.TKrootDestroyed + + def set_cursor(self, cursor): + """ + Sets the cursor for the window. + If you do not want any mouse pointer, then use the string "none" + + :param cursor: The tkinter cursor name + :type cursor: (str) + """ + + if not self._is_window_created('tried Window.set_cursor'): + return + try: + self.TKroot.config(cursor=cursor) + except Exception as e: + print('Warning bad cursor specified ', cursor) + print(e) + + def ding(self, display_number=0): + """ + Make a "bell" sound. A capability provided by tkinter. Your window needs to be finalized prior to calling. + Ring a display's bell is the tkinter description of the call. + :param display_number: Passed to tkinter's bell method as parameter "displayof". + :type display_number: int + """ + if not self._is_window_created('tried Window.ding'): + return + try: + self.TKroot.bell(display_number) + except Exception as e: + if not SUPPRESS_ERROR_POPUPS: + _error_popup_with_traceback('Window.ding() - tkinter reported error from bell() call', e) + + def _window_tkvar_changed_callback(self, *args): + """ + Internal callback function for when the thread + + :param event: Information from tkinter about the callback + :type event: + + """ + # print('Thread callback info', threading.current_thread()) + # print(event) + # trace_details = traceback.format_stack() + # print(''.join(trace_details)) + # self.thread_lock.acquire() + # if self.thread_timer: + # self.TKroot.after_cancel(id=self.thread_timer) + # self.thread_timer = None + # self.thread_lock.release() + + if self._queued_thread_event_available(): + self.FormRemainedOpen = True + _exit_mainloop(self) + + def _create_thread_queue(self): + """ + Creates the queue used by threads to communicate with this window + """ + + if self.thread_queue is None: + self.thread_queue = queue.Queue() + + if self.thread_lock is None: + self.thread_lock = threading.Lock() + + if self.thread_strvar is None: + self.thread_strvar = tk.StringVar() + self.thread_strvar.trace('w', self._window_tkvar_changed_callback) + + def write_event_value(self, key, value): + """ + Adds a key & value tuple to the queue that is used by threads to communicate with the window + + :param key: The key that will be returned as the event when reading the window + :type key: Any + :param value: The value that will be in the values dictionary + :type value: Any + """ + + if self.thread_queue is None: + print('*** Warning Window.write_event_value - no thread queue found ***') + return + # self.thread_lock.acquire() # first lock the critical section + self.thread_queue.put(item=(key, value)) + self.TKroot.tk.willdispatch() # brilliant bit of code provided by Giuliano who I owe a million thank yous! + self.thread_strvar.set('new item') + + # self.thread_queue.put(item=(key, value)) + # self.thread_strvar.set('new item') + # March 28 2021 - finally found a solution! It needs a little more work and a lock + # if no timer is running, then one should be started + # if self.thread_timer is None: + # print('Starting a timer') + # self.thread_timer = self.TKroot.after(1, self._window_tkvar_changed_callback) + # self.thread_lock.release() + + def _queued_thread_event_read(self): + if self.thread_queue is None: + return None + + try: # see if something has been posted to Queue + message = self.thread_queue.get_nowait() + except queue.Empty: # get_nowait() will get exception when Queue is empty + return None + + return message + + def _queued_thread_event_available(self): + + if self.thread_queue is None: + return False + # self.thread_lock.acquire() + qsize = self.thread_queue.qsize() + if qsize == 0: + self.thread_timer = None + # self.thread_lock.release() + return qsize != 0 + + + + def _RightClickMenuCallback(self, event): + """ + When a right click menu is specified for an entire window, then this callback catches right clicks + that happen to the window itself, when there are no elements that are in that area. + + The only portion that is not currently covered correctly is the row frame itself. There will still + be parts of the window, at the moment, that don't respond to a right click. It's getting there, bit + by bit. + + Callback function that's called when a right click happens. Shows right click menu as result. + + :param event: information provided by tkinter about the event including x,y location of click + :type event: + """ + # if there are widgets under the mouse, then see if it's the root only. If not, then let the widget (element) show their menu instead + x, y = self.TKroot.winfo_pointerxy() + widget = self.TKroot.winfo_containing(x, y) + if widget != self.TKroot: + return + self.TKRightClickMenu.tk_popup(event.x_root, event.y_root, 0) + self.TKRightClickMenu.grab_release() + + + + def perform_long_operation(self, func, end_key): + """ + Call your function that will take a long time to execute. When it's complete, send an event + specified by the end_key. + + :param func: A lambda or a function name with no parms + :type func: Any + :param end_key: The key that will be generated when the function returns + :type end_key: (Any) + :return: The id of the thread + :rtype: threading.Thread + """ + + thread = threading.Thread(target=_long_func_thread, args=(self, end_key, func), daemon=True) + thread.start() + return thread + + @property + def key_dict(self): + """ + Returns a dictionary with all keys and their corresponding elements + { key : Element } + :return: Dictionary of keys and elements + :rtype: Dict[Any, Element] + """ + return self.AllKeysDict + + # def __enter__(self): + # """ + # WAS used with context managers which are no longer needed nor advised. It is here for legacy support and + # am afraid of removing right now + # :return: (window) + # :rtype: + # """ + # return self + + def __getitem__(self, key): + """ + Returns Element that matches the passed in key. + This is "called" by writing code as thus: + window['element key'].Update + + :param key: The key to find + :type key: str | int | tuple | object + :rtype: Element | Input | Combo | OptionMenu | Listbox | Radio | Checkbox | Spin | Multiline | Text | StatusBar | Output | Button | ButtonMenu | ProgressBar | Image | Canvas | Graph | Frame | VerticalSeparator | HorizontalSeparator | Tab | TabGroup | Slider | Column | Pane | Menu | Table | Tree | ErrorElement | None + """ + + return self.find_element(key) + + def __call__(self, *args, **kwargs): + """ + Call window.read but without having to type it out. + window() == window.read() + window(timeout=50) == window.read(timeout=50) + + :return: The famous event, values that Read returns. + :rtype: Tuple[Any, Dict[Any, Any]] + """ + return self.read(*args, **kwargs) + + def _is_window_created(self, additional_message=''): + msg = str(additional_message) + if self.TKroot is None: + warnings.warn( + 'You cannot perform operations on a Window until it is read or finalized. Adding a "finalize=True" parameter to your Window creation will fix this. ' + msg, + UserWarning) + if not SUPPRESS_ERROR_POPUPS: + _error_popup_with_traceback('You cannot perform operations on a Window until it is read or finalized.', + 'Adding a "finalize=True" parameter to your Window creation will likely fix this', msg) + return False + return True + + def _has_custom_titlebar_element(self): + for elem in self.AllKeysDict.values(): + if elem.Key in (TITLEBAR_MAXIMIZE_KEY, TITLEBAR_CLOSE_KEY, TITLEBAR_IMAGE_KEY): + return True + if elem.metadata == TITLEBAR_METADATA_MARKER: + return True + return False + + AddRow = add_row + AddRows = add_rows + AlphaChannel = alpha_channel + BringToFront = bring_to_front + Close = close + CurrentLocation = current_location + Disable = disable + DisableDebugger = disable_debugger + Disappear = disappear + Enable = enable + EnableDebugger = enable_debugger + Fill = fill + Finalize = finalize + # FindElement = find_element + FindElementWithFocus = find_element_with_focus + GetScreenDimensions = get_screen_dimensions + GrabAnyWhereOff = grab_any_where_off + GrabAnyWhereOn = grab_any_where_on + Hide = hide + Layout = layout + LoadFromDisk = load_from_disk + Maximize = maximize + Minimize = minimize + Move = move + Normal = normal + Read = read + Reappear = reappear + Refresh = refresh + SaveToDisk = save_to_disk + SendToBack = send_to_back + SetAlpha = set_alpha + SetIcon = set_icon + SetTransparentColor = set_transparent_color + Size = size + UnHide = un_hide + VisibilityChanged = visibility_changed + CloseNonBlocking = close + CloseNonBlockingForm = close + + # + # def __exit__(self, *a): + # """ + # WAS used with context managers which are no longer needed nor advised. It is here for legacy support and + # am afraid of removing right now + # :param *a: (?) Not sure what's passed in. + # :type *a: + # :return: Always returns False which was needed for context manager to work + # :rtype: + # """ + # self.__del__() + # return False + # + # def __del__(self): + # # print('DELETING WINDOW') + # for row in self.Rows: + # for element in row: + # element.__del__() + + +# -------------------------------- PEP8-ify the Window Class USER Interfaces -------------------------------- # + + +FlexForm = Window + + +def _long_func_thread(window, end_key, original_func): + """ + Used to run long operations on the user's behalf. Called by the window object + + :param window: The window that will get the event + :type window: (Window) + :param end_key: The event that will be sent when function returns + :type end_key: (Any) + :param original_func: The user's function that is called. Can be a function with no arguments or a lambda experession + :type original_func: (Any) + """ + + return_value = original_func() + window.write_event_value(end_key, return_value) + + +def _exit_mainloop(exiting_window): + if exiting_window == Window._window_running_mainloop or Window._root_running_mainloop == Window.hidden_master_root: + Window._window_that_exited = exiting_window + if Window._root_running_mainloop is not None: + Window._root_running_mainloop.quit() + # print('** Exited window mainloop **') + + +def _timeout_alarm_callback_hidden(): + """ + Read Timeout Alarm callback. Will kick a mainloop call out of the tkinter event loop and cause it to return + """ + + del Window._TKAfterID + + # first, get the results table built + # modify the Results table in the parent FlexForm object + # print('TIMEOUT CALLBACK') + Window._root_running_mainloop.quit() # kick the users out of the mainloop + + # Get window that caused return + Window._window_that_exited = None + + +def read_all_windows(timeout=None, timeout_key=TIMEOUT_KEY): + """ + Reads all windows that are "active" when the call is made. "Active" means that it's been finalized or read. + If a window has not been finalized then it will not be considered an "active window" + + If any of the active windows returns a value then the window and its event and values + are returned. + + If no windows are open, then the value (None, WIN_CLOSED, None) will be returned + Since WIN_CLOSED is None, it means (None, None, None) is what's returned when no windows remain opened + + :param timeout: Time in milliseconds to delay before a returning a timeout event + :type timeout: (int) + :param timeout_key: Key to return when a timeout happens. Defaults to the standard TIMEOUT_KEY + :type timeout_key: (Any) + :return: A tuple with the (Window, event, values dictionary/list) + :rtype: (Window, Any, Dict | List) + """ + + if len(Window._active_windows) == 0: + return None, WIN_CLOSED, None + + # first see if any queued events are waiting for any of the windows + for window in Window._active_windows.keys(): + if window._queued_thread_event_available(): + _BuildResults(window, False, window) + event, values = window.ReturnValues + return window, event, values + + Window._root_running_mainloop = Window.hidden_master_root + Window._timeout_key = timeout_key + + if timeout == 0: + window = list(Window._active_windows.keys())[Window._timeout_0_counter] + event, values = window._ReadNonBlocking() + if event is None: + event = timeout_key + if values is None: + event = None + Window._timeout_0_counter = (Window._timeout_0_counter + 1) % len(Window._active_windows) + return window, event, values + + Window._timeout_0_counter = 0 # reset value if not reading with timeout 0 so ready next time needed + + # setup timeout timer + if timeout != None: + try: + Window.hidden_master_root.after_cancel(Window._TKAfterID) + del Window._TKAfterID + except: + pass + + Window._TKAfterID = Window.hidden_master_root.after(timeout, _timeout_alarm_callback_hidden) + + # ------------ Call Mainloop ------------ + Window._root_running_mainloop.mainloop() + + try: + Window.hidden_master_root.after_cancel(Window._TKAfterID) + del Window._TKAfterID + except: + pass + # print('** tkafter cancel failed **') + + # Get window that caused return + + window = Window._window_that_exited + + if window is None: + return None, timeout_key, None + + if window.XFound: + event, values = None, None + window.close() + try: + del Window._active_windows[window] + except: + pass + # print('Error deleting window, but OK') + else: + _BuildResults(window, False, window) + event, values = window.ReturnValues + + return window, event, values + + +###### ## ## ###### ######## ######## ## ## +## ## ## ## ## ## ## ## ### ### +## #### ## ## ## #### #### +###### ## ###### ## ###### ## ### ## +## ## ## ## ## ## ## +## ## ## ## ## ## ## ## ## +###### ## ###### ## ######## ## ## + +######## ######## ### ## ## +## ## ## ## ## ## ## +## ## ## ## ## #### +## ######## ## ## ## +## ## ## ######### ## +## ## ## ## ## ## +## ## ## ## ## ## + +# ------------------------------------------------------------------------- # +# SystemTray - class for implementing a psyeudo tray # +# ------------------------------------------------------------------------- # + +# -------------------------------- System Tray Begins Here -------------------------------- # +# Feb 2020 - Just starting on this so code commented out for now. Basing on PySimpleGUIQt's implementation / call format + + +# ------------------------------------------------------------------- +# fade in/out info and default window alpha +SYSTEM_TRAY_WIN_MARGINS = 160, 60 # from right edge of screen, from bottom of screen +SYSTEM_TRAY_MESSAGE_MAX_LINE_LENGTH = 50 +# colors +SYSTEM_TRAY_MESSAGE_WIN_COLOR = "#282828" +SYSTEM_TRAY_MESSAGE_TEXT_COLOR = "#ffffff" + +SYSTEM_TRAY_MESSAGE_DISPLAY_DURATION_IN_MILLISECONDS = 3000 # how long to display the window +SYSTEM_TRAY_MESSAGE_FADE_IN_DURATION = 1000 # how long to fade in / fade out the window + +EVENT_SYSTEM_TRAY_ICON_DOUBLE_CLICKED = '__DOUBLE_CLICKED__' +EVENT_SYSTEM_TRAY_ICON_ACTIVATED = '__ACTIVATED__' +EVENT_SYSTEM_TRAY_MESSAGE_CLICKED = '__MESSAGE_CLICKED__' + +# Base64 Images to use as icons in the window +_tray_icon_error = b'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAA3NCSVQICAjb4U/gAAAACXBIWXMAAADlAAAA5QGP5Zs8AAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAIpQTFRF////20lt30Bg30pg4FJc409g4FBe4E9f4U9f4U9g4U9f4E9g31Bf4E9f4E9f4E9f4E9f4E9f4FFh4Vdm4lhn42Bv5GNx5W575nJ/6HqH6HyI6YCM6YGM6YGN6oaR8Kev9MPI9cbM9snO9s3R+Nfb+dzg+d/i++vt/O7v/fb3/vj5//z8//7+////KofnuQAAABF0Uk5TAAcIGBktSYSXmMHI2uPy8/XVqDFbAAAA8UlEQVQ4y4VT15LCMBBTQkgPYem9d9D//x4P2I7vILN68kj2WtsAhyDO8rKuyzyLA3wjSnvi0Eujf3KY9OUP+kno651CvlB0Gr1byQ9UXff+py5SmRhhIS0oPj4SaUUCAJHxP9+tLb/ezU0uEYDUsCc+l5/T8smTIVMgsPXZkvepiMj0Tm5txQLENu7gSF7HIuMreRxYNkbmHI0u5Hk4PJOXkSMz5I3nyY08HMjbpOFylF5WswdJPmYeVaL28968yNfGZ2r9gvqFalJNUy2UWmq1Wa7di/3Kxl3tF1671YHRR04dWn3s9cXRV09f3vb1fwPD7z9j1WgeRgAAAABJRU5ErkJggg==' +_tray_icon_success = b'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAA3NCSVQICAjb4U/gAAAACXBIWXMAAAEKAAABCgEWpLzLAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAHJQTFRF////ZsxmbbZJYL9gZrtVar9VZsJcbMRYaMZVasFYaL9XbMFbasRZaMFZacRXa8NYasFaasJaasFZasJaasNZasNYasJYasJZasJZasJZasJZasJZasJYasJZasJZasJZasJZasJaasJZasJZasJZasJZ2IAizQAAACV0Uk5TAAUHCA8YGRobHSwtPEJJUVtghJeYrbDByNjZ2tvj6vLz9fb3/CyrN0oAAADnSURBVDjLjZPbWoUgFIQnbNPBIgNKiwwo5v1fsQvMvUXI5oqPf4DFOgCrhLKjC8GNVgnsJY3nKm9kgTsduVHU3SU/TdxpOp15P7OiuV/PVzk5L3d0ExuachyaTWkAkLFtiBKAqZHPh/yuAYSv8R7XE0l6AVXnwBNJUsE2+GMOzWL8k3OEW7a/q5wOIS9e7t5qnGExvF5Bvlc4w/LEM4Abt+d0S5BpAHD7seMcf7+ZHfclp10TlYZc2y2nOqc6OwruxUWx0rDjNJtyp6HkUW4bJn0VWdf/a7nDpj1u++PBOR694+Ftj/8PKNdnDLn/V8YAAAAASUVORK5CYII=' +_tray_icon_halt = b'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAANswNuMPDO8HBO8FCe0HCu4IBu4IB+oLDeoLDu8JC+wKCu4JDO4LDOwKEe4OEO4OEeUQDewQDe0QDucVEuYcG+ccHOsQFuwWHe4fH/EGAvMEBfMFBvAHBPMGBfEGBvYCAfYDAvcDA/cDBPcDBfUDBvYEAPYEAfYEAvYEA/QGAPQGAfQGAvYEBPUEBvYFB/QGBPQGBfQHB/EFCvIHCPMHCfIHC/IFDfMHDPQGCPQGCfQGCvEIBPIIBfAIB/UIB/QICPYICfoBAPoBAfoBAvsBA/kCAPkCAfkCAvkCA/oBBPkCBPkCBfkCBvgCB/gEAPkEAfgEAvkEA/gGAfkGAvkEBPgEBfkEBv0AAP0AAfwAAvwAA/wCAPwCAfwCAvwCA/wABP0ABfwCBfwEAPwFA/ASD/ESFPAUEvAUE/EXFvAdH+kbIOobIeofIfEfIOcmKOohIukgJOggJesiKuwiKewoLe0tLO0oMOQ3OO43Oew4OfAhIPAhIfAiIPEiI+dDRe9ES+lQTOdSWupSUOhTUehSV+hUVu1QUO1RUe1SV+tTWe5SWOxXWOpYV+pZWelYXexaW+xaXO9aX+lZYeNhYOxjZ+lna+psbOttbehsbupscepucuxtcuxucep3fet7e+p/ffB6gOmKiu2Iie2Sk+2Qle2QluySlOyTleuYmvKFivCOjgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIxGNZsAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACVElEQVQ4T22S93PTMBhADQdl791SSsuRARTKKHsn+STZBptAi6zIacous+w9yyxl7z1T1h8ptHLhrrzLD5+/987R2XZElZ/39tZsbGg42NdvF4pqcGMs4XEcozAB/oQeu6wGr5fkAZcKOUIIRgQXR723wgaXt/NSgcwlO1r3oARkATfhbmNMMCnlMZdz5J8RN9fVhglS5JA/pJUOJiYXoShCkz/flheDvpzlBCBmya5KcDG1sMSB+r/VQtG+YoFXlwN0Us4yeBXujPmWCOqNlVwX5zHntLH5iQ420YiqX9pqTZFSCrBGBc+InBUDAsbwLRlMC40fGJT8YLRwfnhY3v6/AUtDc9m5z0tRJBOAvHUaFchdY6+zDzEghHv1tUnrNCaIOw84Q2WQmkeO/Xopj1xFBREFr8ZZjuRhA++PEB+t05ggwBucpbH8i/n5C1ZU0EEEmRZnSMxoIYcarKigA0Cb1zpHAyZnGj21xqICAA9dcvo4UgEdZ41FBZSTzEOn30f6QeE3Vhl0gLN+2RGDzZPMHLHKoAO3MFy+ix4sDxFlvMXfrdNgFezy7qrXPaaJg0u27j5nneKrCjJ4pf4e3m4DVMcjNNNKxWnpo6jtnfnkunExB4GbuGKk5FNanpB1nJCjCsThJPAAJ8lVdSF5sSrklM2ZqmYdiC40G7Dfnhp57ZsQz6c3hylEO6ZoZQJxqiVgbhoQK3T6AIgU4rbjxthAPF6NAwAOAcS+ixlp/WBFJRDi0fj2RtcjWRwif8Qdu/w3EKLcu3/YslnrZzwo24UQQvwFCrp/iM1NnHwAAAAASUVORK5CYII=' +_tray_icon_notallowed = b'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAAPcICPcLC/cMDPcQEPcSEvcXF/cYGPcaGvcbG/ccHPgxMfgyMvg0NPg5Ofg6Ovg7O/hBQfhCQvlFRflGRvljY/pkZPplZfpnZ/p2dgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMgEwNYAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABE0lEQVQ4T4WT65bDIAiExWbbtN0m3Uua+P4P6g4jGtN4NvNL4DuCCC5WWobe++uwmEmtwNxJUTebcwWCt5jJBwsYcKf3NE4hTOOJxj1FEnBTz4NH6qH2jUcCGr/QLLpkQgHe/6VWJXVqFgBB4yI/KVCkBCoFgPrPHw0CWbwCL8RibBFwzQDQH62/QeAtHQBeADUIDbkF/UnmnkB1ixtERrN3xCgyuF5kMntHTCJXh2vyv+wIdMhvgTeCQJ0C2hBMgSKfZlM1wSLXZ5oqgs8sjSpaCQ2VVlfKhLU6fdZGSvyWz9JMb+NE4jt/Nwfm0yJZSkBpYDg7TcJGrjm0Z7jK0B6P/fHiHK8e9Pp/eSmuf1+vf4x/ralnCN9IrncAAAAASUVORK5CYII=' +_tray_icon_stop = b'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAANsAANsBAdsCAtwEBNwFBdwHB9wICNwLC90MDN0NDd0PD90REd0SEt4TE94UFN4WFt4XF94ZGeAjI+AlJeEnJ+EpKeEqKuErK+EsLOEuLuIvL+IyMuIzM+M1NeM2NuM3N+M6OuM8POQ9PeQ+PuQ/P+RAQOVISOVJSeVKSuZLS+ZOTuZQUOZRUedSUudVVehbW+lhYeljY+poaOtvb+twcOtxcetzc+t0dOx3d+x4eOx6eu19fe1+fu2AgO2Cgu6EhO6Ghu6Hh+6IiO6Jie+Kiu+Li++MjO+Nje+Oju+QkPCUlPCVlfKgoPKkpPKlpfKmpvOrq/SurvSxsfSysvW4uPW6uvW7u/W8vPa9vfa+vvbAwPbCwvfExPfFxffGxvfHx/fIyPfJyffKyvjLy/jNzfjQ0PjR0fnS0vnU1PnY2Pvg4Pvi4vvj4/vl5fvm5vzo6Pzr6/3u7v3v7/3x8f3z8/309P719f729v739/74+P75+f76+v77+//8/P/9/f/+/v///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPHCyoUAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABnUlEQVQ4T33S50PTQBgG8D6lzLbsIUv2kD0FFWTvPWTvISDIUBGV1ecvj+8luZTR9P1wSe755XK5O4+hK4gn5bc7DcMBz/InQoMXeVjY4FXuCAtEyLUwQcTcFgq45JYQ4JqbwhMtV8IjeUJDjQ+5paqCyG9srEsGgoUlpeXpIjxA1nfyi2+Jqmo7Q9JeV+ODerpvBQTM8/ySzQ3t+xxoL7h7nJve5jd85M7wJq9McHaT8o6TwBTfIIfHQGzoAZ/YiSTSq8D5dSDQVqFADrJ5KFMLPaKLHQiQMQoscClezdgCB4CXD/jM90izR8g85UaKA3YAn4AejhV189acA5LX+DVOg00gnvfoVX/BRQsgbplNGqzLusgIffx1tDchiyRgdRbVHNdgRRZHQD9H1asm+PMzYyYMtoBU/sYgRxxgrmGtBRL/cnf5RL4zzCEHZF2QE14LoOWf6B9vMcJBG/iBxKo8dVtYnyStv6yuUq7FLfmqTzbLEOFest1GNGEemCjCPnKuwjm0LsLMbRBJWLkGr4WdO+Cl0HkYPBc6N4z//HcQqVwcOuIAAAAASUVORK5CYII=' +_tray_icon_exclamation = b'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAAN0zM900NN01Nd02Nt03N944ON45Od46Ot47O98/P99BQd9CQt9DQ+FPT+JSUuJTU+JUVOJVVeJWVuNbW+ReXuVjY+Zra+dxceh4eOl7e+l8fOl+ful/f+qBgeqCguqDg+qFheuJieuLi+yPj+yQkO2Wlu+cnO+hofGqqvGtrfre3vrf3/ri4vvn5/75+f76+v/+/v///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMQ8SQkAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABJElEQVQ4T4WS63KCMBBGsyBai62X0otY0aq90ZZa3v/dtpvsJwTijOfXt7tnILOJYY9tNonjNCtQOlqhuKKG0RrNVjgkmIHBHgMId+h7zHSiwg2a9FNVVYScupETmjkd67o+CWpYwft+R6CpCgeUlq5AOyf45+8JsRUKFI6eQLkI3n5CIREBUekLxGaLpATCymRISiAszARJCYSxiZGUQKDLQoqgnPnFhUPOTWeRoZD3FvVZlmVHkE2OEM9iV71GVoZDBGUpAg9QWN5/jx+Ilsi9hz0q4VHOWD+hEF70yc1QEr1a4Q0F0S3eJDfLuv8T4QEFXduZE1rj+et7g6hzCDxF08N+X4DAu+6lUSTnc5wE5tx73ckSTV8QVoux3N88Rykw/wP3i+vwPKk17AAAAABJRU5ErkJggg==' +_tray_icon_none = None + +SYSTEM_TRAY_MESSAGE_ICON_INFORMATION = _tray_icon_success +SYSTEM_TRAY_MESSAGE_ICON_WARNING = _tray_icon_exclamation +SYSTEM_TRAY_MESSAGE_ICON_CRITICAL = _tray_icon_stop +SYSTEM_TRAY_MESSAGE_ICON_NOICON = _tray_icon_none + + +# ------------------------------------------------------------------------- # +# Tray CLASS # +# ------------------------------------------------------------------------- # +class SystemTray: + """ + A "Simulated System Tray" that duplicates the API calls available to PySimpleGUIWx and PySimpleGUIQt users. + + All of the functionality works. The icon is displayed ABOVE the system tray rather than inside of it. + """ + + def __init__(self, menu=None, filename=None, data=None, data_base64=None, tooltip=None, metadata=None): + """ + SystemTray - create an icon in the system tray + :param menu: Menu definition. Example - ['UNUSED', ['My', 'Simple', '---', 'Menu', 'Exit']] + :type menu: List[List[List[str] or str]] + :param filename: filename for icon + :type filename: (str) + :param data: in-ram image for icon (same as data_base64 parm) + :type data: (bytes) + :param data_base64: base-64 data for icon + :type data_base64: (bytes) + :param tooltip: tooltip string + :type tooltip: (str) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + self._metadata = None + self.Menu = menu + self.TrayIcon = None + self.Shown = False + self.MenuItemChosen = TIMEOUT_KEY + self.metadata = metadata + self.last_message_event = None + + screen_size = Window.get_screen_size() + + if filename: + image_elem = Image(filename=filename, background_color='red', enable_events=True, tooltip=tooltip, key='-IMAGE-') + elif data_base64: + image_elem = Image(data=data_base64, background_color='red', enable_events=True, tooltip=tooltip, key='-IMAGE-') + elif data: + image_elem = Image(data=data, background_color='red', enable_events=True, tooltip=tooltip, key='-IMAGE-') + else: + image_elem = Image(background_color='red', enable_events=True, tooltip=tooltip, key='-IMAGE-') + layout = [ + [image_elem], + ] + self.window = Window('Window Title', layout, element_padding=(0, 0), margins=(0, 0), grab_anywhere=True, no_titlebar=True, transparent_color='red', + keep_on_top=True, right_click_menu=menu, location=(screen_size[0] - 100, screen_size[1] - 100), finalize=True) + + self.window['-IMAGE-'].bind('', '+DOUBLE_CLICK') + + @property + def metadata(self): + """ + Metadata is an SystemTray property that you can use at any time to hold any value + :return: the current metadata value + :rtype: (Any) + """ + return self._metadata + + @metadata.setter + def metadata(self, value): + """ + Metadata is an SystemTray property that you can use at any time to hold any value + :param value: Anything you want it to be + :type value: (Any) + """ + self._metadata = value + + def read(self, timeout=None): + """ + Reads the context menu + :param timeout: Optional. Any value other than None indicates a non-blocking read + :type timeout: + :return: + :rtype: + """ + if self.last_message_event != TIMEOUT_KEY and self.last_message_event is not None: + event = self.last_message_event + self.last_message_event = None + return event + event, values = self.window.read(timeout=timeout) + if event.endswith('DOUBLE_CLICK'): + return EVENT_SYSTEM_TRAY_ICON_DOUBLE_CLICKED + elif event == '-IMAGE-': + return EVENT_SYSTEM_TRAY_ICON_ACTIVATED + + return event + + def hide(self): + """ + Hides the icon + """ + self.window.hide() + + def un_hide(self): + """ + Restores a previously hidden icon + """ + self.window.un_hide() + + def show_message(self, title, message, filename=None, data=None, data_base64=None, messageicon=None, + time=(SYSTEM_TRAY_MESSAGE_FADE_IN_DURATION, SYSTEM_TRAY_MESSAGE_DISPLAY_DURATION_IN_MILLISECONDS)): + """ + Shows a balloon above icon in system tray + :param title: Title shown in balloon + :type title: str + :param message: Message to be displayed + :type message: str + :param filename: Optional icon filename + :type filename: str + :param data: Optional in-ram icon + :type data: b'' + :param data_base64: Optional base64 icon + :type data_base64: b'' + :param time: Amount of time to display message in milliseconds. If tuple, first item is fade in/out duration + :type time: int | (int, int) + :return: The event that happened during the display such as user clicked on message + :rtype: Any + """ + + if isinstance(time, tuple): + fade_duraction, display_duration = time + else: + fade_duration = SYSTEM_TRAY_MESSAGE_FADE_IN_DURATION + display_duration = time + + user_icon = data_base64 or filename or data or messageicon + + event = self.notify(title, message, icon=user_icon, fade_in_duration=fade_duraction, display_duration_in_ms=display_duration) + self.last_message_event = event + return event + + def close(self): + """ + Close the system tray window + """ + self.window.close() + + def update(self, menu=None, tooltip=None, filename=None, data=None, data_base64=None, ): + """ + Updates the menu, tooltip or icon + :param menu: menu defintion + :type menu: ??? + :param tooltip: string representing tooltip + :type tooltip: ??? + :param filename: icon filename + :type filename: ??? + :param data: icon raw image + :type data: ??? + :param data_base64: icon base 64 image + :type data_base64: ??? + """ + # Menu + if menu is not None: + top_menu = tk.Menu(self.window.TKroot, tearoff=False) + AddMenuItem(top_menu, menu[1], self.window['-IMAGE-']) + self.window['-IMAGE-'].TKRightClickMenu = top_menu + + if filename: + self.window['-IMAGE-'].update(filename=filename) + elif data_base64: + self.window['-IMAGE-'].update(data=data_base64) + elif data: + self.window['-IMAGE-'].update(data=data) + + if tooltip: + self.window['-IMAGE-'].set_tooltip(tooltip) + + @classmethod + def notify(cls, title, message, icon=_tray_icon_success, display_duration_in_ms=SYSTEM_TRAY_MESSAGE_DISPLAY_DURATION_IN_MILLISECONDS, + fade_in_duration=SYSTEM_TRAY_MESSAGE_FADE_IN_DURATION, alpha=0.9, location=None): + """ + Displays a "notification window", usually in the bottom right corner of your display. Has an icon, a title, and a message + The window will slowly fade in and out if desired. Clicking on the window will cause it to move through the end the current "phase". For example, if the window was fading in and it was clicked, then it would immediately stop fading in and instead be fully visible. It's a way for the user to quickly dismiss the window. + :param title: Text to be shown at the top of the window in a larger font + :type title: (str) + :param message: Text message that makes up the majority of the window + :type message: (str) + :param icon: A base64 encoded PNG/GIF image or PNG/GIF filename that will be displayed in the window + :type icon: bytes | str + :param display_duration_in_ms: Number of milliseconds to show the window + :type display_duration_in_ms: (int) + :param fade_in_duration: Number of milliseconds to fade window in and out + :type fade_in_duration: (int) + :param alpha: Alpha channel. 0 - invisible 1 - fully visible + :type alpha: (float) + :param location: Location on the screen to display the window + :type location: (int, int) + :return: (int) reason for returning + :rtype: (int) + """ + + messages = message.split('\n') + full_msg = '' + for m in messages: + m_wrap = textwrap.fill(m, SYSTEM_TRAY_MESSAGE_MAX_LINE_LENGTH) + full_msg += m_wrap + '\n' + message = full_msg[:-1] + + win_msg_lines = message.count("\n") + 1 + max_line = max(message.split('\n')) + + screen_res_x, screen_res_y = Window.get_screen_size() + win_margin = SYSTEM_TRAY_WIN_MARGINS # distance from screen edges + win_width, win_height = 364, 66 + (14.8 * win_msg_lines) + + layout = [[Graph(canvas_size=(win_width, win_height), graph_bottom_left=(0, win_height), graph_top_right=(win_width, 0), key="-GRAPH-", + background_color=SYSTEM_TRAY_MESSAGE_WIN_COLOR, enable_events=True)]] + + win_location = location if location is not None else (screen_res_x - win_width - win_margin[0], screen_res_y - win_height - win_margin[1]) + window = Window(title, layout, background_color=SYSTEM_TRAY_MESSAGE_WIN_COLOR, no_titlebar=True, + location=win_location, keep_on_top=True, alpha_channel=0, margins=(0, 0), element_padding=(0, 0), grab_anywhere=True, finalize=True) + + window["-GRAPH-"].draw_rectangle((win_width, win_height), (-win_width, -win_height), fill_color=SYSTEM_TRAY_MESSAGE_WIN_COLOR, + line_color=SYSTEM_TRAY_MESSAGE_WIN_COLOR) + if type(icon) is bytes: + window["-GRAPH-"].draw_image(data=icon, location=(20, 20)) + elif icon is not None: + window["-GRAPH-"].draw_image(filename=icon, location=(20, 20)) + window["-GRAPH-"].draw_text(title, location=(64, 20), color=SYSTEM_TRAY_MESSAGE_TEXT_COLOR, font=("Helvetica", 12, "bold"), + text_location=TEXT_LOCATION_TOP_LEFT) + window["-GRAPH-"].draw_text(message, location=(64, 44), color=SYSTEM_TRAY_MESSAGE_TEXT_COLOR, font=("Helvetica", 9), + text_location=TEXT_LOCATION_TOP_LEFT) + window["-GRAPH-"].set_cursor('hand2') + + if fade_in_duration: + for i in range(1, int(alpha * 100)): # fade in + window.set_alpha(i / 100) + event, values = window.read(timeout=fade_in_duration // 100) + if event != TIMEOUT_KEY: + window.set_alpha(1) + break + if event != TIMEOUT_KEY: + window.close() + return EVENT_SYSTEM_TRAY_MESSAGE_CLICKED if event == '-GRAPH-' else event + event, values = window(timeout=display_duration_in_ms) + if event == TIMEOUT_KEY: + for i in range(int(alpha * 100), 1, -1): # fade out + window.set_alpha(i / 100) + event, values = window.read(timeout=fade_in_duration // 100) + if event != TIMEOUT_KEY: + break + else: + window.set_alpha(alpha) + event, values = window(timeout=display_duration_in_ms) + window.close() + + return EVENT_SYSTEM_TRAY_MESSAGE_CLICKED if event == '-GRAPH-' else event + + Close = close + Hide = hide + Read = read + ShowMessage = show_message + UnHide = un_hide + Update = update + + +# ################################################################################ +# ################################################################################ +# END OF ELEMENT DEFINITIONS +# ################################################################################ +# ################################################################################ + + +# =========================================================================== # +# Button Lazy Functions so the caller doesn't have to define a bunch of stuff # +# =========================================================================== # + +# ------------------------- A fake Element... the Pad Element ------------------------- # +def Sizer(h_pixels=0, v_pixels=0): + """ + "Pushes" out the size of whatever it is placed inside of. This includes Columns, Frames, Tabs and Windows + + :param h_pixels: number of horizontal pixels + :type h_pixels: (int) + :param v_pixels: number of vertical pixels + :type v_pixels: (int) + :return: (Column) A column element that has a pad setting set according to parameters + :rtype: (Column) + """ + + return Column([[]], pad=((h_pixels, 0), (v_pixels, 0))) + + +def pin(elem, vertical_alignment=None, shrink=True, expand_x=None, expand_y=None): + """ + Pin's an element provided into a layout so that when it's made invisible and visible again, it will + be in the correct place. Otherwise it will be placed at the end of its containing window/column. + + :param elem: the element to put into the layout + :type elem: Element + :param vertical_alignment: Aligns elements vertically. 'top', 'center', 'bottom'. Can be shortened to 't', 'c', 'b' + :type vertical_alignment: str | None + :param shrink: If True, then the space will shrink down to a single pixel when hidden. False leaves the area large and blank + :type shrink: bool + :param expand_x: If True/False the value will be passed to the Column Elements used to make this feature + :type expand_x: (bool) + :param expand_y: If True/False the value will be passed to the Column Elements used to make this feature + :type expand_y: (bool) + :return: A column element containing the provided element + :rtype: Column + """ + if shrink: + # return Column([[elem, Canvas(size=(0, 0),background_color=elem.BackgroundColor, pad=(0, 0))]], pad=(0, 0), vertical_alignment=vertical_alignment, expand_x=expand_x, expand_y=expand_y) + return Column([[elem, Column([[]],pad=(0,0))]], pad=(0, 0), vertical_alignment=vertical_alignment, expand_x=expand_x, expand_y=expand_y) + else: + return Column([[elem]], pad=(0, 0), vertical_alignment=vertical_alignment, expand_x=expand_x, expand_y=expand_y) + + +def vtop(elem_or_row, expand_x=None, expand_y=None): + """ + Align an element or a row of elements to the top of the row that contains it + + :param elem_or_row: the element or row of elements + :type elem_or_row: Element | List[Element] | Tuple[Element] + :param expand_x: If True/False the value will be passed to the Column Elements used to make this feature + :type expand_x: (bool) + :param expand_y: If True/False the value will be passed to the Column Elements used to make this feature + :type expand_y: (bool) + :return: A column element containing the provided element aligned to the top or list of elements (a row) + :rtype: Column | List[Column] + """ + + if isinstance(elem_or_row, list) or isinstance(elem_or_row, tuple): + return [Column([[e]], pad=(0, 0), vertical_alignment='top', expand_x=expand_x, expand_y=expand_y) for e in elem_or_row] + + return Column([[elem_or_row]], pad=(0, 0), vertical_alignment='top', expand_x=expand_x, expand_y=expand_y) + + +def vcenter(elem_or_row, expand_x=None, expand_y=None): + """ + Align an element or a row of elements to the center of the row that contains it + + :param elem_or_row: the element or row of elements + :type elem_or_row: Element | List[Element] | Tuple[Element] + :param expand_x: If True/False the value will be passed to the Column Elements used to make this feature + :type expand_x: (bool) + :param expand_y: If True/False the value will be passed to the Column Elements used to make this feature + :type expand_y: (bool) + :return: A column element containing the provided element aligned to the center or list of elements (a row) + :rtype: Column | List[Column] + """ + + if isinstance(elem_or_row, list) or isinstance(elem_or_row, tuple): + return [Column([[e]], pad=(0, 0), vertical_alignment='center') for e in elem_or_row] + + return Column([[elem_or_row]], pad=(0, 0), vertical_alignment='center') + + +def vbottom(elem_or_row, expand_x=None, expand_y=None): + """ + Align an element or a row of elements to the bottom of the row that contains it + + :param elem_or_row: the element or row of elements + :type elem_or_row: Element | List[Element] | Tuple[Element] + :param expand_x: If True/False the value will be passed to the Column Elements used to make this feature + :type expand_x: (bool) + :param expand_y: If True/False the value will be passed to the Column Elements used to make this feature + :type expand_y: (bool) + :return: A column element containing the provided element aligned to the bottom or list of elements (a row) + :rtype: Column | List[Column] + """ + + if isinstance(elem_or_row, list) or isinstance(elem_or_row, tuple): + return [Column([[e]], pad=(0, 0), vertical_alignment='bottom') for e in elem_or_row] + + return Column([[elem_or_row]], pad=(0, 0), vertical_alignment='bottom') + + +def Titlebar(title='', icon=None, text_color=None, background_color=None, font=None, key=None, k=None): + """ + A custom titlebar that replaces the OS provided titlebar, thus giving you control + the is not possible using the OS provided titlebar such as the color. + + NOTE LINUX USERS - at the moment the minimize function is not yet working. Windows users + should have no problem and it should function as a normal window would. + + This titlebar is created from a row of elements that is then encapulated into a + single Column element which is what the Titlebar returns to you. + + A custom titlebar removes the margins from your window. Ify ou want the remainder + of your Window to have margins, place the layout after the Titlebar into a Column and + set the pad of that Column to the dimensions you would like your margins to have. + + The Titlebar is a COLUMN element. You can thus call the update method for the column and + perform operations such as making the column visible/invisible + + :param icon: Can be either a filename or Base64 byte string of a PNG. For Windows if filename, it MUST be ICO format. For Linux, must NOT be ICO + :type icon: str or bytes or None + :param title: The "title" to show in the titlebar + :type title: str + :param text_color: Text color for titlebar + :type text_color: str | None + :param background_color: Background color for titlebar + :type background_color: str | None + :param font: Font to be used for the text and the symbols + :type font: (str or (str, int[, str]) or None) + :param key: Identifies an Element. Should be UNIQUE to this window. + :type key: str | int | tuple | object | None + :param k: Exactly the same as key. Choose one of them to use + :type k: str | int | tuple | object | None + :return: A single Column element that has eveything in 1 element + :rtype: Column + """ + bc = background_color or CUSTOM_TITLEBAR_BACKGROUND_COLOR or theme_button_color()[1] + tc = text_color or CUSTOM_TITLEBAR_TEXT_COLOR or theme_button_color()[0] + font = font or CUSTOM_TITLEBAR_FONT or ('Helvetica', 12) + key = k or key + + if isinstance(icon, bytes): + icon_and_text_portion = [Image(data=icon, background_color=bc, key=TITLEBAR_IMAGE_KEY)] + elif icon == TITLEBAR_DO_NOT_USE_AN_ICON: + icon_and_text_portion = [] + elif icon is not None: + icon_and_text_portion = [Image(filename=icon, background_color=bc, key=TITLEBAR_IMAGE_KEY)] + elif CUSTOM_TITLEBAR_ICON is not None: + if isinstance(CUSTOM_TITLEBAR_ICON, bytes): + icon_and_text_portion = [Image(data=CUSTOM_TITLEBAR_ICON, background_color=bc, key=TITLEBAR_IMAGE_KEY)] + else: + icon_and_text_portion = [Image(filename=CUSTOM_TITLEBAR_ICON, background_color=bc, key=TITLEBAR_IMAGE_KEY)] + else: + icon_and_text_portion = [Image(data=DEFAULT_BASE64_ICON_16_BY_16, background_color=bc, key=TITLEBAR_IMAGE_KEY)] + + icon_and_text_portion += [T(title, text_color=tc, background_color=bc, font=font, grab=True)] + + return Column([[Column([icon_and_text_portion], pad=(0, 0), background_color=bc), + Column([[T(SYMBOL_TITLEBAR_MINIMIZE, text_color=tc, background_color=bc, enable_events=True, font=font, key=TITLEBAR_MINIMIZE_KEY), + Text(SYMBOL_TITLEBAR_MAXIMIZE, text_color=tc, background_color=bc, enable_events=True, font=font, key=TITLEBAR_MAXIMIZE_KEY), + Text(SYMBOL_TITLEBAR_CLOSE, text_color=tc, background_color=bc, font=font, enable_events=True, key=TITLEBAR_CLOSE_KEY), ]], + element_justification='r', expand_x=True, grab=True, pad=(0, 0), background_color=bc)]], expand_x=True, grab=True, + background_color=bc, pad=(0, 0), metadata=TITLEBAR_METADATA_MARKER, key=key) + + +# Not ready for prime time +def MenubarCustom(menu_definition, disabled_text_color=None, bar_font=None, font=None, tearoff=False, pad=None, p=None, background_color=None, text_color=None, + bar_background_color=None, bar_text_color=None, key=None, k=None): + """ + A custom Menubar that replaces the OS provided Menubar + + Why? + Two reasons - 1. they look great (see custom titlebar) 2. if you have a custom titlebar, then you have to use a custom menubar if you want a menubar + + :param menu_definition: The Menu definition specified using lists (docs explain the format) + :type menu_definition: List[List[Tuple[str, List[str]]] + :param disabled_text_color: color to use for text when item is disabled. Can be in #RRGGBB format or a color name "black" + :type disabled_text_color: (str) + :param bar_font: specifies the font family, size to be used for the chars in the bar itself + :type bar_font: (str or (str, int[, str]) or None) + :param font: specifies the font family, size to be used for the menu items + :type font: (str or (str, int[, str]) or None) + :param tearoff: if True, then can tear the menu off from the window ans use as a floating window. Very cool effect + :type tearoff: (bool) + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param background_color: color to use for background of the menus that are displayed after making a section. Can be in #RRGGBB format or a color name "black". Defaults to the color of the bar text + :type background_color: (str) + :param text_color: color to use for the text of the many items in the displayed menus. Can be in #RRGGBB format or a color name "black". Defaults to the bar background + :type text_color: (str) + :param bar_background_color: color to use for the menubar. Can be in #RRGGBB format or a color name "black". Defaults to theme's button text color + :type bar_background_color: (str) + :param bar_text_color: color to use for the menu items text when item is disabled. Can be in #RRGGBB format or a color name "black". Defaults to theme's button background color + :type bar_text_color: (str) + :param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :returns: A Column element that has a series of ButtonMenu elements + :rtype: Column + """ + + bar_bg = bar_background_color if bar_background_color is not None else theme_button_color()[0] + bar_text = bar_text_color if bar_text_color is not None else theme_button_color()[1] + menu_bg = background_color if background_color is not None else bar_text + menu_text = text_color if text_color is not None else bar_bg + pad = pad if pad is not None else p + + row = [] + for menu in menu_definition: + text = menu[0] + if MENU_SHORTCUT_CHARACTER in text: + text = text.replace(MENU_SHORTCUT_CHARACTER, '') + if text.startswith(MENU_DISABLED_CHARACTER): + disabled = True + text = text[len(MENU_DISABLED_CHARACTER):] + else: + disabled = False + + button_menu = ButtonMenu(text, menu, border_width=0, button_color=(bar_text, bar_bg), key=text, pad=(0, 0), disabled=disabled, font=bar_font, + item_font=font, disabled_text_color=disabled_text_color, text_color=menu_text, background_color=menu_bg, tearoff=tearoff) + button_menu.part_of_custom_menubar = True + button_menu.custom_menubar_key = key if key is not None else k + row += [button_menu] + return Column([row], pad=pad, background_color=bar_bg, expand_x=True, key=key if key is not None else k) + + +# ------------------------- FOLDER BROWSE Element lazy function ------------------------- # +def FolderBrowse(button_text='Browse', target=(ThisRow, -1), initial_folder=None, tooltip=None, size=(None, None), s=(None, None), + auto_size_button=None, button_color=None, disabled=False, change_submits=False, enable_events=False, + font=None, pad=None, p=None, key=None, k=None, visible=True, metadata=None): + """ + :param button_text: text in the button (Default value = 'Browse') + :type button_text: (str) + :param target: target for the button (Default value = (ThisRow, -1)) + :type target: str | (int, int) + :param initial_folder: starting path for folders and files + :type initial_folder: (str) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param size: (w,h) w=characters-wide, h=rows-high + :type size: (int, int) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param auto_size_button: True if button size is determined by button text + :type auto_size_button: (bool) + :param button_color: button color (foreground, background) + :type button_color: + :param disabled: set disable state for element (Default = False) + :type disabled: (bool) + :param change_submits: If True, pressing Enter key submits window (Default = False) + :type enable_events: (bool) + :param enable_events: Turns on the element specific events.(Default = False) + :type enable_events: (bool) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param key: Used with window.find_element and with return values to uniquely identify this element + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param visible: set initial visibility state of the Button + :type visible: (bool) + :param metadata: Anything you want to store along with this button + :type metadata: (Any) + :return: The Button created + :rtype: (Button) + """ + + return Button(button_text=button_text, button_type=BUTTON_TYPE_BROWSE_FOLDER, target=target, + initial_folder=initial_folder, tooltip=tooltip, size=size, s=s, auto_size_button=auto_size_button, + disabled=disabled, button_color=button_color, change_submits=change_submits, + enable_events=enable_events, font=font, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata) + + +# ------------------------- FILE BROWSE Element lazy function ------------------------- # +def FileBrowse(button_text='Browse', target=(ThisRow, -1), file_types=FILE_TYPES_ALL_FILES, initial_folder=None, + tooltip=None, size=(None, None), s=(None, None), auto_size_button=None, button_color=None, change_submits=False, + enable_events=False, font=None, disabled=False, + pad=None, p=None, key=None, k=None, visible=True, metadata=None): + """ + + :param button_text: text in the button (Default value = 'Browse') + :type button_text: (str) + :param target: key or (row,col) target for the button (Default value = (ThisRow, -1)) + :type target: str | (int, int) + :param file_types: filter file types (Default value = (("ALL Files", "*.* *"))) + :type file_types: Tuple[(str, str), ...] + :param initial_folder: starting path for folders and files + :type initial_folder: + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param size: (w,h) w=characters-wide, h=rows-high + :type size: (int, int) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param auto_size_button: True if button size is determined by button text + :type auto_size_button: (bool) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param change_submits: If True, pressing Enter key submits window (Default = False) + :type change_submits: (bool) + :param enable_events: Turns on the element specific events.(Default = False) + :type enable_events: (bool) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param disabled: set disable state for element (Default = False) + :type disabled: (bool) + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param key: key for uniquely identify this element (for window.find_element) + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param visible: set initial visibility state of the Button + :type visible: (bool) + :param metadata: Anything you want to store along with this button + :type metadata: (Any) + :return: returns a button + :rtype: (Button) + """ + return Button(button_text=button_text, button_type=BUTTON_TYPE_BROWSE_FILE, target=target, file_types=file_types, + initial_folder=initial_folder, tooltip=tooltip, size=size, s=s, auto_size_button=auto_size_button, + change_submits=change_submits, enable_events=enable_events, disabled=disabled, + button_color=button_color, font=font, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata) + + +# ------------------------- FILES BROWSE Element (Multiple file selection) lazy function ------------------------- # +def FilesBrowse(button_text='Browse', target=(ThisRow, -1), file_types=FILE_TYPES_ALL_FILES, disabled=False, + initial_folder=None, tooltip=None, size=(None, None), s=(None, None), auto_size_button=None, button_color=None, + change_submits=False, enable_events=False, + font=None, pad=None, p=None, key=None, k=None, visible=True, files_delimiter=BROWSE_FILES_DELIMITER, metadata=None): + """ + Allows browsing of multiple files. File list is returned as a single list with the delimiter defined using the files_delimiter parameter. + + :param button_text: text in the button (Default value = 'Browse') + :type button_text: (str) + :param target: key or (row,col) target for the button (Default value = (ThisRow, -1)) + :type target: str | (int, int) + :param file_types: (Default value = (("ALL Files", "*.* *"))) + :type file_types: Tuple[(str, str), ...] + :param disabled: set disable state for element (Default = False) + :type disabled: (bool) + :param initial_folder: starting path for folders and files + :type initial_folder: (str) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param size: (w,h) w=characters-wide, h=rows-high + :type size: (int, int) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param auto_size_button: True if button size is determined by button text + :type auto_size_button: (bool) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param change_submits: If True, pressing Enter key submits window (Default = False) + :type change_submits: (bool) + :param enable_events: Turns on the element specific events.(Default = False) + :type enable_events: (bool) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param key: key for uniquely identify this element (for window.find_element) + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param visible: set initial visibility state of the Button + :type visible: (bool) + :param files_delimiter: String to place between files when multiple files are selected. Normally a ; + :type files_delimiter: str + :param metadata: Anything you want to store along with this button + :type metadata: (Any) + :return: returns a button + :rtype: (Button) + """ + button = Button(button_text=button_text, button_type=BUTTON_TYPE_BROWSE_FILES, target=target, file_types=file_types, + initial_folder=initial_folder, change_submits=change_submits, enable_events=enable_events, + tooltip=tooltip, size=size, s=s, auto_size_button=auto_size_button, + disabled=disabled, button_color=button_color, font=font, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata) + button._files_delimiter = files_delimiter + return button + + +# ------------------------- FILE BROWSE Element lazy function ------------------------- # +def FileSaveAs(button_text='Save As...', target=(ThisRow, -1), file_types=FILE_TYPES_ALL_FILES, initial_folder=None, + default_extension='', disabled=False, tooltip=None, size=(None, None), s=(None, None), auto_size_button=None, button_color=None, + change_submits=False, enable_events=False, font=None, + pad=None, p=None, key=None, k=None, visible=True, metadata=None): + """ + + :param button_text: text in the button (Default value = 'Save As...') + :type button_text: (str) + :param target: key or (row,col) target for the button (Default value = (ThisRow, -1)) + :type target: str | (int, int) + :param file_types: (Default value = (("ALL Files", "*.* *"))) + :type file_types: Tuple[(str, str), ...] + :param default_extension: If no extension entered by user, add this to filename (only used in saveas dialogs) + :type default_extension: (str) + :param initial_folder: starting path for folders and files + :type initial_folder: (str) + :param disabled: set disable state for element (Default = False) + :type disabled: (bool) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param size: (w,h) w=characters-wide, h=rows-high + :type size: (int, int) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param auto_size_button: True if button size is determined by button text + :type auto_size_button: (bool) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param change_submits: If True, pressing Enter key submits window (Default = False) + :type change_submits: (bool) + :param enable_events: Turns on the element specific events.(Default = False) + :type enable_events: (bool) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param key: key for uniquely identify this element (for window.find_element) + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param visible: set initial visibility state of the Button + :type visible: (bool) + :param metadata: Anything you want to store along with this button + :type metadata: (Any) + :return: returns a button + :rtype: (Button) + """ + return Button(button_text=button_text, button_type=BUTTON_TYPE_SAVEAS_FILE, target=target, file_types=file_types, + initial_folder=initial_folder, default_extension=default_extension, tooltip=tooltip, size=size, s=s, disabled=disabled, + auto_size_button=auto_size_button, button_color=button_color, change_submits=change_submits, + enable_events=enable_events, font=font, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata) + + +# ------------------------- SAVE AS Element lazy function ------------------------- # +def SaveAs(button_text='Save As...', target=(ThisRow, -1), file_types=FILE_TYPES_ALL_FILES, initial_folder=None, default_extension='', + disabled=False, tooltip=None, size=(None, None), s=(None, None), auto_size_button=None, button_color=None, + change_submits=False, enable_events=False, font=None, + pad=None, p=None, key=None, k=None, visible=True, metadata=None): + """ + + :param button_text: text in the button (Default value = 'Save As...') + :type button_text: (str) + :param target: key or (row,col) target for the button (Default value = (ThisRow, -1)) + :type target: str | (int, int) + :param file_types: (Default value = (("ALL Files", "*.* *"))) + :type file_types: Tuple[(str, str), ...] + :param default_extension: If no extension entered by user, add this to filename (only used in saveas dialogs) + :type default_extension: (str) + :param initial_folder: starting path for folders and files + :type initial_folder: (str) + :param disabled: set disable state for element (Default = False) + :type disabled: (bool) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param size: (w,h) w=characters-wide, h=rows-high + :type size: (int, int) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param auto_size_button: True if button size is determined by button text + :type auto_size_button: (bool) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param change_submits: If True, pressing Enter key submits window (Default = False) + :type change_submits: (bool) + :param enable_events: Turns on the element specific events.(Default = False) + :type enable_events: (bool) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int :param key: key for uniquely identify this element (for window.find_element) + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param visible: set initial visibility state of the Button + :type visible: (bool) + :param metadata: Anything you want to store along with this button + :type metadata: (Any) + :return: returns a button + :rtype: (Button) + """ + return Button(button_text=button_text, button_type=BUTTON_TYPE_SAVEAS_FILE, target=target, file_types=file_types, + initial_folder=initial_folder, default_extension=default_extension, tooltip=tooltip, size=size, s=s, disabled=disabled, + auto_size_button=auto_size_button, button_color=button_color, change_submits=change_submits, + enable_events=enable_events, font=font, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata) + + +# ------------------------- SAVE BUTTON Element lazy function ------------------------- # +def Save(button_text='Save', size=(None, None), s=(None, None), auto_size_button=None, button_color=None, bind_return_key=True, + disabled=False, tooltip=None, font=None, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None): + """ + + :param button_text: text in the button (Default value = 'Save') + :type button_text: (str) + :param size: (w,h) w=characters-wide, h=rows-high + :type size: (int, int) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param auto_size_button: True if button size is determined by button text + :type auto_size_button: (bool) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param bind_return_key: (Default = True) If True, then the return key will cause a the Listbox to generate an event + :type bind_return_key: (bool) + :param disabled: set disable state for element (Default = False) + :type disabled: (bool) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param focus: if focus should be set to this + :type focus: idk_yetReally + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param key: key for uniquely identify this element (for window.find_element) + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param visible: set initial visibility state of the Button + :type visible: (bool) + :param metadata: Anything you want to store along with this button + :type metadata: (Any) + :return: returns a button + :rtype: (Button) + """ + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, s=s, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata) + + +# ------------------------- SUBMIT BUTTON Element lazy function ------------------------- # +def Submit(button_text='Submit', size=(None, None), s=(None, None), auto_size_button=None, button_color=None, disabled=False, + bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None): + """ + + :param button_text: text in the button (Default value = 'Submit') + :type button_text: (str) + :param size: (w,h) w=characters-wide, h=rows-high + :type size: (int, int) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param auto_size_button: True if button size is determined by button text + :type auto_size_button: (bool) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param disabled: set disable state for element (Default = False) + :type disabled: (bool) + :param bind_return_key: (Default = True) If True, then the return key will cause a the Listbox to generate an event + :type bind_return_key: (bool) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param focus: if focus should be set to this + :type focus: idk_yetReally + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param key: key for uniquely identify this element (for window.find_element) + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param visible: set initial visibility state of the Button + :type visible: (bool) + :param metadata: Anything you want to store along with this button + :type metadata: (Any) + :return: returns a button + :rtype: (Button) + """ + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, s=s, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata) + + +# ------------------------- OPEN BUTTON Element lazy function ------------------------- # +# ------------------------- OPEN BUTTON Element lazy function ------------------------- # +def Open(button_text='Open', size=(None, None), s=(None, None), auto_size_button=None, button_color=None, disabled=False, + bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None): + """ + + :param button_text: text in the button (Default value = 'Open') + :type button_text: (str) + :param size: (w,h) w=characters-wide, h=rows-high + :type size: (int, int) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param auto_size_button: True if button size is determined by button text + :type auto_size_button: (bool) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param disabled: set disable state for element (Default = False) + :type disabled: (bool) + :param bind_return_key: (Default = True) If True, then the return key will cause a the Listbox to generate an event + :type bind_return_key: (bool) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param focus: if focus should be set to this + :type focus: idk_yetReally + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param key: key for uniquely identify this element (for window.find_element) + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param visible: set initial visibility state of the Button + :type visible: (bool) + :param metadata: Anything you want to store along with this button + :type metadata: (Any) + :return: returns a button + :rtype: (Button) + """ + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, s=s, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata) + + +# ------------------------- OK BUTTON Element lazy function ------------------------- # +def OK(button_text='OK', size=(None, None), s=(None, None), auto_size_button=None, button_color=None, disabled=False, + bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None): + """ + + :param button_text: text in the button (Default value = 'OK') + :type button_text: (str) + :param size: (w,h) w=characters-wide, h=rows-high + :type size: (int, int) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param auto_size_button: True if button size is determined by button text + :type auto_size_button: (bool) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param disabled: set disable state for element (Default = False) + :type disabled: (bool) + :param bind_return_key: (Default = True) If True, then the return key will cause a the Listbox to generate an event + :type bind_return_key: (bool) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param focus: if focus should be set to this + :type focus: idk_yetReally + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param key: key for uniquely identify this element (for window.find_element) + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param visible: set initial visibility state of the Button + :type visible: (bool) + :param metadata: Anything you want to store along with this button + :type metadata: (Any) + :return: returns a button + :rtype: (Button) + """ + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, s=s, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata) + + +# ------------------------- YES BUTTON Element lazy function ------------------------- # +def Ok(button_text='Ok', size=(None, None), s=(None, None), auto_size_button=None, button_color=None, disabled=False, + bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None): + """ + + :param button_text: text in the button (Default value = 'Ok') + :type button_text: (str) + :param size: (w,h) w=characters-wide, h=rows-high + :type size: (int, int) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param auto_size_button: True if button size is determined by button text + :type auto_size_button: (bool) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param disabled: set disable state for element (Default = False) + :type disabled: (bool) + :param bind_return_key: (Default = True) If True, then the return key will cause a the Listbox to generate an event + :type bind_return_key: (bool) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param focus: if focus should be set to this + :type focus: idk_yetReally + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param key: key for uniquely identify this element (for window.find_element) + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param visible: set initial visibility state of the Button + :type visible: (bool) + :param metadata: Anything you want to store along with this button + :type metadata: (Any) + :return: returns a button + :rtype: (Button) + """ + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, s=s, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata) + + +# ------------------------- CANCEL BUTTON Element lazy function ------------------------- # +def Cancel(button_text='Cancel', size=(None, None), s=(None, None), auto_size_button=None, button_color=None, disabled=False, + tooltip=None, font=None, bind_return_key=False, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None): + """ + + :param button_text: text in the button (Default value = 'Cancel') + :type button_text: (str) + :param size: (w,h) w=characters-wide, h=rows-high + :type size: (int, int) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param auto_size_button: True if button size is determined by button text + :type auto_size_button: (bool) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param disabled: set disable state for element (Default = False) + :type disabled: (bool) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param bind_return_key: (Default = False) If True, then the return key will cause a the Listbox to generate an event + :type bind_return_key: (bool) + :param focus: if focus should be set to this + :type focus: + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param key: key for uniquely identify this element (for window.find_element) + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param visible: set initial visibility state of the Button + :type visible: (bool) + :param metadata: Anything you want to store along with this button + :type metadata: (Any) + :return: returns a button + :rtype: (Button) + """ + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, s=s, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata) + + +# ------------------------- QUIT BUTTON Element lazy function ------------------------- # +def Quit(button_text='Quit', size=(None, None), s=(None, None), auto_size_button=None, button_color=None, disabled=False, tooltip=None, + font=None, bind_return_key=False, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None): + """ + + :param button_text: text in the button (Default value = 'Quit') + :type button_text: (str) + :param size: (w,h) w=characters-wide, h=rows-high + :type size: (int, int) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param auto_size_button: True if button size is determined by button text + :type auto_size_button: (bool) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param disabled: set disable state for element (Default = False) + :type disabled: (bool) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param bind_return_key: (Default = False) If True, then the return key will cause a the Listbox to generate an event + :type bind_return_key: (bool) + :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) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param key: key for uniquely identify this element (for window.find_element) + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param visible: set initial visibility state of the Button + :type visible: (bool) + :param metadata: Anything you want to store along with this button + :type metadata: (Any) + :return: returns a button + :rtype: (Button) + """ + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, s=s, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata) + + +# ------------------------- Exit BUTTON Element lazy function ------------------------- # +def Exit(button_text='Exit', size=(None, None), s=(None, None), auto_size_button=None, button_color=None, disabled=False, tooltip=None, + font=None, bind_return_key=False, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None): + """ + + :param button_text: text in the button (Default value = 'Exit') + :type button_text: (str) + :param size: (w,h) w=characters-wide, h=rows-high + :type size: (int, int) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param auto_size_button: True if button size is determined by button text + :type auto_size_button: (bool) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param disabled: set disable state for element (Default = False) + :type disabled: (bool) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param bind_return_key: (Default = False) If True, then the return key will cause a the Listbox to generate an event + :type bind_return_key: (bool) + :param focus: if focus should be set to this + :type focus: + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param key: key for uniquely identify this element (for window.find_element) + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param visible: set initial visibility state of the Button + :type visible: (bool) + :param metadata: Anything you want to store along with this button + :type metadata: (Any) + :return: returns a button + :rtype: (Button) + """ + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, s=s, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata) + + +# ------------------------- YES BUTTON Element lazy function ------------------------- # +def Yes(button_text='Yes', size=(None, None), s=(None, None), auto_size_button=None, button_color=None, disabled=False, tooltip=None, + font=None, bind_return_key=True, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None): + """ + + :param button_text: text in the button (Default value = 'Yes') + :type button_text: (str) + :param size: (w,h) w=characters-wide, h=rows-high + :type size: (int, int) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param auto_size_button: True if button size is determined by button text + :type auto_size_button: (bool) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param disabled: set disable state for element (Default = False) + :type disabled: (bool) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param bind_return_key: (Default = True) If True, then the return key will cause a the Listbox to generate an event + :type bind_return_key: (bool) + :param focus: if focus should be set to this + :type focus: + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param key: key for uniquely identify this element (for window.find_element) + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param visible: set initial visibility state of the Button + :type visible: (bool) + :param metadata: Anything you want to store along with this button + :type metadata: (Any) + :return: returns a button + :rtype: (Button) + """ + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, s=s, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata) + + +# ------------------------- NO BUTTON Element lazy function ------------------------- # +def No(button_text='No', size=(None, None), s=(None, None), auto_size_button=None, button_color=None, disabled=False, tooltip=None, + font=None, bind_return_key=False, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None): + """ + + :param button_text: text in the button (Default value = 'No') + :type button_text: (str) + :param size: (w,h) w=characters-wide, h=rows-high + :type size: (int, int) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param auto_size_button: True if button size is determined by button text + :type auto_size_button: (bool) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param disabled: set disable state for element (Default = False) + :type disabled: (bool) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param bind_return_key: (Default = False) If True, then the return key will cause a the Listbox to generate an event + :type bind_return_key: (bool) + :param focus: if focus should be set to this + :type focus: + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param key: key for uniquely identify this element (for window.find_element) + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param visible: set initial visibility state of the Button + :type visible: (bool) + :param metadata: Anything you want to store along with this button + :type metadata: (Any) + :return: returns a button + :rtype: (Button) + """ + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, s=s, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata) + + +# ------------------------- NO BUTTON Element lazy function ------------------------- # +def Help(button_text='Help', size=(None, None), s=(None, None), auto_size_button=None, button_color=None, disabled=False, font=None, + tooltip=None, bind_return_key=False, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None): + """ + + :param button_text: text in the button (Default value = 'Help') + :type button_text: (str) + :param size: (w,h) w=characters-wide, h=rows-high + :type size: (int, int) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param auto_size_button: True if button size is determined by button text + :type auto_size_button: (bool) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param disabled: set disable state for element (Default = False) + :type disabled: (bool) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param bind_return_key: (Default = False) If True, then the return key will cause a the Listbox to generate an event + :type bind_return_key: (bool) + :param focus: if focus should be set to this + :type focus: + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param key: key for uniquely identify this element (for window.find_element) + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param visible: set initial visibility state of the Button + :type visible: (bool) + :param metadata: Anything you want to store along with this button + :type metadata: (Any) + :return: returns a button + :rtype: (Button) + """ + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, s=s, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata) + + +# ------------------------- NO BUTTON Element lazy function ------------------------- # +def Debug(button_text='', size=(None, None), s=(None, None), auto_size_button=None, button_color=None, disabled=False, font=None, + tooltip=None, bind_return_key=False, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None): + """ + This Button has been changed in how it works!! + Your button has been replaced with a normal button that has the PySimpleGUI Debugger buggon logo on it. + In your event loop, you will need to check for the event of this button and then call: + show_debugger_popout_window() + :param button_text: text in the button (Default value = '') + :type button_text: (str) + :param size: (w,h) w=characters-wide, h=rows-high + :type size: (int, int) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param auto_size_button: True if button size is determined by button text + :type auto_size_button: (bool) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param disabled: set disable state for element (Default = False) + :type disabled: (bool) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param bind_return_key: (Default = False) If True, then the return key will cause a the Listbox to generate an event + :type bind_return_key: (bool) + :param focus: if focus should be set to this + :type focus: + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param key: key for uniquely identify this element (for window.find_element) + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param visible: set initial visibility state of the Button + :type visible: (bool) + :param metadata: Anything you want to store along with this button + :type metadata: (Any) + :return: returns a button + :rtype: (Button) + """ + + + user_key = key if key is not None else k if k is not None else button_text + + return Button(button_text='', button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, s=s, + auto_size_button=auto_size_button, button_color=theme_button_color(), font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=user_key, k=k, visible=visible, image_data=PSG_DEBUGGER_LOGO, + image_subsample=2, border_width=0, metadata=metadata) + + +# ------------------------- GENERIC BUTTON Element lazy function ------------------------- # +def SimpleButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, + border_width=None, tooltip=None, size=(None, None), s=(None, None), auto_size_button=None, button_color=None, + font=None, bind_return_key=False, disabled=False, focus=False, pad=None, p=None, key=None, k=None, metadata=None): + """ + DEPIRCATED + + This Button should not be used. + + :param button_text: text in the button + :type button_text: (str) + :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 + :type image_data: in-RAM image to be displayed on button + :param image_size: image size (O.K.) + :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 + :type tooltip: (str) + :param size: (w,h) w=characters-wide, h=rows-high + :type size: (int, int) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param auto_size_button: True if button size is determined by button text + :type auto_size_button: (bool) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param bind_return_key: (Default = False) If True, then the return key will cause a the Listbox to generate an event + :type bind_return_key: (bool) + :param disabled: set disable state for element (Default = False) + :type disabled: (bool) + :param focus: if focus should be set to this + :type focus: idk_yetReally + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param key: key for uniquely identify this element (for window.find_element) + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param metadata: Anything you want to store along with this button + :type metadata: (Any) + :return: returns a button + :rtype: (Button) + """ + return Button(button_text=button_text, button_type=BUTTON_TYPE_CLOSES_WIN, image_filename=image_filename, + image_data=image_data, image_size=image_size, image_subsample=image_subsample, + border_width=border_width, tooltip=tooltip, disabled=disabled, size=size, s=s, + auto_size_button=auto_size_button, button_color=button_color, font=font, + bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, metadata=metadata) + + +# ------------------------- CLOSE BUTTON Element lazy function ------------------------- # +def CloseButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, + border_width=None, tooltip=None, size=(None, None), s=(None, None), auto_size_button=None, button_color=None, font=None, + bind_return_key=False, disabled=False, focus=False, pad=None, p=None, key=None, k=None, metadata=None): + """ + DEPRICATED + + This button should not be used. Instead explicitly close your windows by calling window.close() or by using + the close parameter in window.read + + :param button_text: text in the button + :type button_text: (str) + :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 + :type image_data: in-RAM image to be displayed on button + :param image_size: image size (O.K.) + :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 + :type tooltip: (str) + :param size: (w,h) w=characters-wide, h=rows-high + :type size: (int, int) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param auto_size_button: True if button size is determined by button text + :type auto_size_button: (bool) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param bind_return_key: (Default = False) If True, then the return key will cause a the Listbox to generate an event + :type bind_return_key: (bool) + :param disabled: set disable state for element (Default = False) + :type disabled: (bool) + :param focus: if focus should be set to this + :type focus: idk_yetReally + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param key: key for uniquely identify this element (for window.find_element) + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param metadata: Anything you want to store along with this button + :type metadata: (Any) + :return: returns a button + :rtype: (Button) + """ + return Button(button_text=button_text, button_type=BUTTON_TYPE_CLOSES_WIN, image_filename=image_filename, + image_data=image_data, image_size=image_size, image_subsample=image_subsample, + border_width=border_width, tooltip=tooltip, disabled=disabled, size=size, s=s, + auto_size_button=auto_size_button, button_color=button_color, font=font, + bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, metadata=metadata) + + +CButton = CloseButton + + +# ------------------------- GENERIC BUTTON Element lazy function ------------------------- # +def ReadButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, + border_width=None, tooltip=None, size=(None, None), s=(None, None), auto_size_button=None, button_color=None, font=None, + bind_return_key=False, disabled=False, focus=False, pad=None, p=None, key=None, k=None, metadata=None): + """ + :param button_text: text in the button + :type button_text: (str) + :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 + :type image_data: in-RAM image to be displayed on button + :param image_size: image size (O.K.) + :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 + :type tooltip: (str) + :param size: (w,h) w=characters-wide, h=rows-high + :type size: (int, int) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param auto_size_button: True if button size is determined by button text + :type auto_size_button: (bool) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param bind_return_key: (Default = False) If True, then the return key will cause a the Listbox to generate an event + :type bind_return_key: (bool) + :param disabled: set disable state for element (Default = False) + :type disabled: (bool) + :param focus: if focus should be set to this + :type focus: idk_yetReally + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param key: key for uniquely identify this element (for window.find_element) + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param border_width: width of border around element + :type border_width: (int) + :param metadata: Anything you want to store along with this button + :type metadata: (Any) + :return: Button created + :rtype: (Button) + """ + + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, image_filename=image_filename, + image_data=image_data, image_size=image_size, image_subsample=image_subsample, + border_width=border_width, tooltip=tooltip, size=size, s=s, disabled=disabled, + auto_size_button=auto_size_button, button_color=button_color, font=font, + bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, metadata=metadata) + + +ReadFormButton = ReadButton +RButton = ReadFormButton + + +# ------------------------- Realtime BUTTON Element lazy function ------------------------- # +def RealtimeButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, + border_width=None, tooltip=None, size=(None, None), s=(None, None), auto_size_button=None, button_color=None, + font=None, disabled=False, bind_return_key=False, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None): + """ + + :param button_text: text in the button + :type button_text: (str) + :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 + :type image_data: in-RAM image to be displayed on button + :param image_size: image size (O.K.) + :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 border_width: width of border around element + :type border_width: (int) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param size: (w,h) w=characters-wide, h=rows-high + :type size: (int, int) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param auto_size_button: True if button size is determined by button text + :type auto_size_button: (bool) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param disabled: set disable state for element (Default = False) + :type disabled: (bool) + :param bind_return_key: (Default = False) If True, then the return key will cause a the Listbox to generate an event + :type bind_return_key: (bool) + :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) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param key: key for uniquely identify this element (for window.find_element) + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param visible: set initial visibility state of the Button + :type visible: (bool) + :param metadata: Anything you want to store along with this button + :type metadata: (Any) + :return: Button created + :rtype: (Button) + """ + return Button(button_text=button_text, button_type=BUTTON_TYPE_REALTIME, image_filename=image_filename, + image_data=image_data, image_size=image_size, image_subsample=image_subsample, + border_width=border_width, tooltip=tooltip, disabled=disabled, size=size, s=s, + auto_size_button=auto_size_button, button_color=button_color, font=font, + bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata) + + +# ------------------------- Dummy BUTTON Element lazy function ------------------------- # +def DummyButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, + border_width=None, tooltip=None, size=(None, None), s=(None, None), auto_size_button=None, button_color=None, font=None, + disabled=False, bind_return_key=False, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None): + """ + This is a special type of Button. + + It will close the window but NOT send an event that the window has been closed. + + It's used in conjunction with non-blocking windows to silently close them. They are used to + implement the non-blocking popup windows. They're also found in some Demo Programs, so look there for proper use. + + :param button_text: text in the button + :type button_text: (str) + :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 + :type image_data: in-RAM image to be displayed on button + :param image_size: image size (O.K.) + :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 border_width: width of border around element + :type border_width: (int) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param size: (w,h) w=characters-wide, h=rows-high + :type size: (int, int) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param auto_size_button: True if button size is determined by button text + :type auto_size_button: (bool) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param disabled: set disable state for element (Default = False) + :type disabled: (bool) + :param bind_return_key: (Default = False) If True, then the return key will cause a the Listbox to generate an event + :type bind_return_key: (bool) + :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) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param key: key for uniquely identify this element (for window.find_element) + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param visible: set initial visibility state of the Button + :type visible: (bool) + :param metadata: Anything you want to store along with this button + :type metadata: (Any) + :return: returns a button + :rtype: (Button) + """ + return Button(button_text=button_text, button_type=BUTTON_TYPE_CLOSES_WIN_ONLY, image_filename=image_filename, + image_data=image_data, image_size=image_size, image_subsample=image_subsample, + border_width=border_width, tooltip=tooltip, size=size, s=s, auto_size_button=auto_size_button, + button_color=button_color, font=font, disabled=disabled, bind_return_key=bind_return_key, focus=focus, + pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata) + + +# ------------------------- Calendar Chooser Button lazy function ------------------------- # +def CalendarButton(button_text, target=(ThisRow, -1), close_when_date_chosen=True, default_date_m_d_y=(None, None, None), + image_filename=None, image_data=None, image_size=(None, None), + image_subsample=None, tooltip=None, border_width=None, size=(None, None), s=(None, None), auto_size_button=None, + button_color=None, disabled=False, font=None, bind_return_key=False, focus=False, pad=None, p=None, enable_events=None, + key=None, k=None, visible=True, locale=None, format='%Y-%m-%d %H:%M:%S', begin_at_sunday_plus=0, month_names=None, day_abbreviations=None, + title='Choose Date', + no_titlebar=True, location=(None, None), metadata=None): + """ + Button that will show a calendar chooser window. Fills in the target element with result + + :param button_text: text in the button + :type button_text: (str) + :param target: Key or "coordinate" (see docs) of target element + :type target: (int, int) | Any + :param close_when_date_chosen: (Default = True) + :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 + :type image_filename: image filename if there is a button image + :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: image size (O.K.) + :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 + :type tooltip: (str) + :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 + :type size: (int, int) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param auto_size_button: True if button size is determined by button text + :type auto_size_button: (bool) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param disabled: set disable state for element (Default = False) + :type disabled: (bool) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param bind_return_key: (Default = False) If True, then the return key will cause a the Listbox to generate an event + :type bind_return_key: bool + :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) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param key: key for uniquely identify this element (for window.find_element) + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param locale: defines the locale used to get day names + :type locale: str + :param format: formats result using this strftime format + :type format: str + :param month_names: optional list of month names to use (should be 12 items) + :type month_names: List[str] + :param day_abbreviations: optional list of abbreviations to display as the day of week + :type day_abbreviations: List[str] + :param title: Title shown on the date chooser window + :type title: (str) + :param no_titlebar: if True no titlebar will be shown on the date chooser window + :type no_titlebar: bool + :param location: Location on the screen (x,y) to show the calendar popup window + :type location: (int, int) + :param visible: set initial visibility state of the Button + :type visible: (bool) + :param metadata: Anything you want to store along with this button + :type metadata: (Any) + :return: returns a button + :rtype: (Button) + """ + button = Button(button_text=button_text, button_type=BUTTON_TYPE_CALENDAR_CHOOSER, target=target, + image_filename=image_filename, image_data=image_data, image_size=image_size, + image_subsample=image_subsample, border_width=border_width, tooltip=tooltip, size=size, s=s, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, enable_events=enable_events, + bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata) + button.calendar_close_when_chosen = close_when_date_chosen + button.calendar_default_date_M_D_Y = default_date_m_d_y + button.calendar_locale = locale + button.calendar_format = format + button.calendar_no_titlebar = no_titlebar + button.calendar_location = location + button.calendar_begin_at_sunday_plus = begin_at_sunday_plus + button.calendar_month_names = month_names + button.calendar_day_abbreviations = day_abbreviations + button.calendar_title = title + + return button + + +# ------------------------- Calendar Chooser Button lazy function ------------------------- # +def ColorChooserButton(button_text, target=(ThisRow, -1), image_filename=None, image_data=None, image_size=(None, None), + image_subsample=None, tooltip=None, border_width=None, size=(None, None), s=(None, None), auto_size_button=None, + button_color=None, disabled=False, font=None, bind_return_key=False, focus=False, pad=None, p=None, + key=None, k=None, visible=True, metadata=None): + """ + + :param button_text: text in the button + :type button_text: (str) + :param target: key or (row,col) target for the button. Note that -1 for column means 1 element to the left of this one. The constant ThisRow is used to indicate the current row. The Button itself is a valid target for some types of button + :type target: str | (int, int) + :type image_filename: (str) + :param image_filename: image filename if there is a button image. GIFs and PNGs only. + :type image_filename: (str) + :param image_data: Raw or Base64 representation of the image to put on button. Choose either filename or data + :type image_data: bytes | str + :param image_size: Size of the image in pixels (width, height) + :type image_size: (int, int) + :param image_subsample: amount to reduce the size of the image. Divides the size by this number. 2=1/2, 3=1/3, 4=1/4, etc + :type image_subsample: (int) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param border_width: width of border around element + :type border_width: (int) + :param size: (w,h) w=characters-wide, h=rows-high + :type size: (int, int) + :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used + :type s: (int, int) | (None, None) | int + :param auto_size_button: True if button size is determined by button text + :type auto_size_button: (bool) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param disabled: set disable state for element (Default = False) + :type disabled: (bool) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param bind_return_key: If True, then the return key will cause a the Listbox to generate an event + :type bind_return_key: (bool) + :param focus: Determines if initial focus should go to this element. + :type focus: (bool) + :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used + :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int + :param key: key for uniquely identify this element (for window.find_element) + :type key: str | int | tuple | object + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: str | int | tuple | object + :param visible: set initial visibility state of the Button + :type visible: (bool) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + :return: returns a button + :rtype: (Button) + """ + return Button(button_text=button_text, button_type=BUTTON_TYPE_COLOR_CHOOSER, target=target, + image_filename=image_filename, image_data=image_data, image_size=image_size, + image_subsample=image_subsample, border_width=border_width, tooltip=tooltip, size=size, s=s, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata) + + +##################################### ----- BUTTON Functions ------ ################################################## + +def button_color_to_tuple(color_tuple_or_string, default=(None, None)): + """ + Convert a color tuple or color string into 2 components and returns them as a tuple + (Text Color, Button Background Color) + If None is passed in as the first parameter, then the theme's button color is + returned + + :param color_tuple_or_string: Button color - tuple or a simplied color string with word "on" between color + :type color_tuple_or_string: str | (str, str) + :param default: The 2 colors to use if there is a problem. Otherwise defaults to the theme's button color + :type default: (str, str) + :return: (str | (str, str) + :rtype: str | (str, str) + """ + if default == (None, None): + color_tuple = _simplified_dual_color_to_tuple(color_tuple_or_string, default=theme_button_color()) + elif color_tuple_or_string == COLOR_SYSTEM_DEFAULT: + color_tuple = (COLOR_SYSTEM_DEFAULT, COLOR_SYSTEM_DEFAULT) + else: + color_tuple = _simplified_dual_color_to_tuple(color_tuple_or_string, default=default) + + return color_tuple + + +def _simplified_dual_color_to_tuple(color_tuple_or_string, default=(None, None)): + """ + Convert a color tuple or color string into 2 components and returns them as a tuple + (Text Color, Button Background Color) + If None is passed in as the first parameter, theme_ + + :param color_tuple_or_string: Button color - tuple or a simplied color string with word "on" between color + :type color_tuple_or_string: str | (str, str} | (None, None) + :param default: The 2 colors to use if there is a problem. Otherwise defaults to the theme's button color + :type default: (str, str) + :return: (str | (str, str) + :rtype: str | (str, str) + """ + if color_tuple_or_string is None or color_tuple_or_string == (None, None): + color_tuple_or_string = default + if color_tuple_or_string == COLOR_SYSTEM_DEFAULT: + return (COLOR_SYSTEM_DEFAULT, COLOR_SYSTEM_DEFAULT) + text_color = background_color = COLOR_SYSTEM_DEFAULT + try: + if isinstance(color_tuple_or_string, (tuple, list)): + if len(color_tuple_or_string) >= 2: + text_color = color_tuple_or_string[0] or default[0] + background_color = color_tuple_or_string[1] or default[1] + elif len(color_tuple_or_string) == 1: + background_color = color_tuple_or_string[0] or default[1] + elif isinstance(color_tuple_or_string, str): + color_tuple_or_string = color_tuple_or_string.lower() + split_colors = color_tuple_or_string.split(' on ') + if len(split_colors) >= 2: + text_color = split_colors[0].strip() or default[0] + background_color = split_colors[1].strip() or default[1] + elif len(split_colors) == 1: + split_colors = color_tuple_or_string.split('on') + if len(split_colors) == 1: + text_color, background_color = default[0], split_colors[0].strip() + else: + split_colors = split_colors[0].strip(), split_colors[1].strip() + text_color = split_colors[0] or default[0] + background_color = split_colors[1] or default[1] + # text_color, background_color = color_tuple_or_string, default[1] + else: + text_color, background_color = default + else: + if not SUPPRESS_ERROR_POPUPS: + _error_popup_with_traceback('** Badly formatted dual-color... not a tuple nor string **', color_tuple_or_string) + else: + print('** Badly formatted dual-color... not a tuple nor string **', color_tuple_or_string) + text_color, background_color = default + except Exception as e: + if not SUPPRESS_ERROR_POPUPS: + _error_popup_with_traceback('** Badly formatted button color **', color_tuple_or_string, e) + else: + print('** Badly formatted button color... not a tuple nor string **', color_tuple_or_string, e) + text_color, background_color = default + if isinstance(text_color, int): + text_color = "#%06X" % text_color + if isinstance(background_color, int): + background_color = "#%06X" % background_color + # print('converted button color', color_tuple_or_string, 'to', (text_color, background_color)) + + return (text_color, background_color) + + +##################################### ----- RESULTS ------ ################################################## + +def AddToReturnDictionary(form, element, value): + form.ReturnValuesDictionary[element.Key] = value + # if element.Key is None: + # form.ReturnValuesDictionary[form.DictionaryKeyCounter] = value + # element.Key = form.DictionaryKeyCounter + # form.DictionaryKeyCounter += 1 + # else: + # form.ReturnValuesDictionary[element.Key] = value + + +def AddToReturnList(form, value): + form.ReturnValuesList.append(value) + + +# ----------------------------------------------------------------------------# +# ------- FUNCTION InitializeResults. Sets up form results matrix --------# +def InitializeResults(form): + _BuildResults(form, True, form) + return + + +# ===== Radio Button RadVar encoding and decoding =====# +# ===== The value is simply the row * 1000 + col =====# +def DecodeRadioRowCol(RadValue): + container = RadValue // 100000 + row = RadValue // 1000 + col = RadValue % 1000 + return container, row, col + + +def EncodeRadioRowCol(container, row, col): + RadValue = container * 100000 + row * 1000 + col + return RadValue + + +# ------- FUNCTION BuildResults. Form exiting so build the results to pass back ------- # +# format of return values is +# (Button Pressed, input_values) +def _BuildResults(form, initialize_only, top_level_form): + # Results for elements are: + # TEXT - Nothing + # INPUT - Read value from TK + # Button - Button Text and position as a Tuple + + # Get the initialized results so we don't have to rebuild + # form.DictionaryKeyCounter = 0 + form.ReturnValuesDictionary = {} + form.ReturnValuesList = [] + _BuildResultsForSubform(form, initialize_only, top_level_form) + if not top_level_form.LastButtonClickedWasRealtime: + top_level_form.LastButtonClicked = None + return form.ReturnValues + + +def _BuildResultsForSubform(form, initialize_only, top_level_form): + event = top_level_form.LastButtonClicked + for row_num, row in enumerate(form.Rows): + for col_num, element in enumerate(row): + if element.Key is not None and WRITE_ONLY_KEY in str(element.Key): + continue + value = None + if element.Type == ELEM_TYPE_COLUMN: + element.DictionaryKeyCounter = top_level_form.DictionaryKeyCounter + element.ReturnValuesList = [] + element.ReturnValuesDictionary = {} + _BuildResultsForSubform(element, initialize_only, top_level_form) + for item in element.ReturnValuesList: + AddToReturnList(top_level_form, item) + if element.UseDictionary: + top_level_form.UseDictionary = True + if element.ReturnValues[0] is not None: # if a button was clicked + event = element.ReturnValues[0] + + if element.Type == ELEM_TYPE_FRAME: + element.DictionaryKeyCounter = top_level_form.DictionaryKeyCounter + element.ReturnValuesList = [] + element.ReturnValuesDictionary = {} + _BuildResultsForSubform(element, initialize_only, top_level_form) + for item in element.ReturnValuesList: + AddToReturnList(top_level_form, item) + if element.UseDictionary: + top_level_form.UseDictionary = True + if element.ReturnValues[0] is not None: # if a button was clicked + event = element.ReturnValues[0] + + if element.Type == ELEM_TYPE_PANE: + element.DictionaryKeyCounter = top_level_form.DictionaryKeyCounter + element.ReturnValuesList = [] + element.ReturnValuesDictionary = {} + _BuildResultsForSubform(element, initialize_only, top_level_form) + for item in element.ReturnValuesList: + AddToReturnList(top_level_form, item) + if element.UseDictionary: + top_level_form.UseDictionary = True + if element.ReturnValues[0] is not None: # if a button was clicked + event = element.ReturnValues[0] + + if element.Type == ELEM_TYPE_TAB_GROUP: + element.DictionaryKeyCounter = top_level_form.DictionaryKeyCounter + element.ReturnValuesList = [] + element.ReturnValuesDictionary = {} + _BuildResultsForSubform(element, initialize_only, top_level_form) + for item in element.ReturnValuesList: + AddToReturnList(top_level_form, item) + if element.UseDictionary: + top_level_form.UseDictionary = True + if element.ReturnValues[0] is not None: # if a button was clicked + event = element.ReturnValues[0] + + if element.Type == ELEM_TYPE_TAB: + element.DictionaryKeyCounter = top_level_form.DictionaryKeyCounter + element.ReturnValuesList = [] + element.ReturnValuesDictionary = {} + _BuildResultsForSubform(element, initialize_only, top_level_form) + for item in element.ReturnValuesList: + AddToReturnList(top_level_form, item) + if element.UseDictionary: + top_level_form.UseDictionary = True + if element.ReturnValues[0] is not None: # if a button was clicked + event = element.ReturnValues[0] + + if not initialize_only: + if element.Type == ELEM_TYPE_INPUT_TEXT: + try: + value = element.TKStringVar.get() + except: + value = '' + if not top_level_form.NonBlocking and not element.do_not_clear and not top_level_form.ReturnKeyboardEvents: + element.TKStringVar.set('') + elif element.Type == ELEM_TYPE_INPUT_CHECKBOX: + value = element.TKIntVar.get() + value = (value != 0) + elif element.Type == ELEM_TYPE_INPUT_RADIO: + RadVar = element.TKIntVar.get() + this_rowcol = EncodeRadioRowCol(form.ContainerElemementNumber, row_num, col_num) + # this_rowcol = element.EncodedRadioValue # could use the saved one + value = RadVar == this_rowcol + elif element.Type == ELEM_TYPE_BUTTON: + if top_level_form.LastButtonClicked == element.Key: + event = top_level_form.LastButtonClicked + if element.BType != BUTTON_TYPE_REALTIME: # Do not clear realtime buttons + top_level_form.LastButtonClicked = None + if element.BType == BUTTON_TYPE_CALENDAR_CHOOSER: + # value = None + value = element.calendar_selection + else: + try: + value = element.TKStringVar.get() + except: + value = None + elif element.Type == ELEM_TYPE_INPUT_COMBO: + element = element # type: Combo + # value = element.TKStringVar.get() + try: + if element.TKCombo.current() == -1: # if the current value was not in the original list + value = element.TKCombo.get() + else: + value = element.Values[element.TKCombo.current()] # get value from original list given index + except: + value = '*Exception occurred*' + elif element.Type == ELEM_TYPE_INPUT_OPTION_MENU: + value = element.TKStringVar.get() + elif element.Type == ELEM_TYPE_INPUT_LISTBOX: + try: + items = element.TKListbox.curselection() + value = [element.Values[int(item)] for item in items] + except Exception as e: + value = '' + elif element.Type == ELEM_TYPE_INPUT_SPIN: + try: + value = element.TKStringVar.get() + for v in element.Values: + if str(v) == value: + value = v + break + except: + value = 0 + elif element.Type == ELEM_TYPE_INPUT_SLIDER: + try: + value = float(element.TKScale.get()) + except: + value = 0 + elif element.Type == ELEM_TYPE_INPUT_MULTILINE: + if element.WriteOnly: # if marked as "write only" when created, then don't include with the values being returned + continue + try: + value = element.TKText.get(1.0, tk.END) + if element.rstrip: + value = value.rstrip() + if not top_level_form.NonBlocking and not element.do_not_clear and not top_level_form.ReturnKeyboardEvents: + element.TKText.delete('1.0', tk.END) + except: + value = None + elif element.Type == ELEM_TYPE_TAB_GROUP: + try: + value = element.TKNotebook.tab(element.TKNotebook.index('current'))['text'] + tab_key = element.FindKeyFromTabName(value) + if tab_key is not None: + value = tab_key + except: + value = None + elif element.Type == ELEM_TYPE_TABLE: + value = element.SelectedRows + elif element.Type == ELEM_TYPE_TREE: + value = element.SelectedRows + elif element.Type == ELEM_TYPE_GRAPH: + value = element.ClickPosition + elif element.Type == ELEM_TYPE_MENUBAR: + if element.MenuItemChosen is not None: + event = top_level_form.LastButtonClicked = element.MenuItemChosen + value = element.MenuItemChosen + element.MenuItemChosen = None + elif element.Type == ELEM_TYPE_BUTTONMENU: + element = element # type: ButtonMenu + value = element.MenuItemChosen + if element.part_of_custom_menubar: + if element.MenuItemChosen is not None: + value = event = element.MenuItemChosen + top_level_form.LastButtonClicked = element.MenuItemChosen + if element.custom_menubar_key is not None: + top_level_form.ReturnValuesDictionary[element.custom_menubar_key] = value + element.MenuItemChosen = None + else: + if element.custom_menubar_key not in top_level_form.ReturnValuesDictionary: + top_level_form.ReturnValuesDictionary[element.custom_menubar_key] = None + value = None + + # if element.MenuItemChosen is not None: + # button_pressed_text = top_level_form.LastButtonClicked = element.MenuItemChosen + # value = element.MenuItemChosen + # element.MenuItemChosen = None + else: + value = None + + # if an input type element, update the results + if element.Type not in ( + ELEM_TYPE_BUTTON, ELEM_TYPE_TEXT, ELEM_TYPE_IMAGE, ELEM_TYPE_OUTPUT, ELEM_TYPE_PROGRESS_BAR, ELEM_TYPE_COLUMN, ELEM_TYPE_FRAME, ELEM_TYPE_SEPARATOR, + ELEM_TYPE_TAB): + if not (element.Type == ELEM_TYPE_BUTTONMENU and element.part_of_custom_menubar): + AddToReturnList(form, value) + AddToReturnDictionary(top_level_form, element, value) + elif (element.Type == ELEM_TYPE_BUTTON and + element.BType == BUTTON_TYPE_COLOR_CHOOSER and + element.Target == (None, None)) or \ + (element.Type == ELEM_TYPE_BUTTON + and element.Key is not None and + (element.BType in (BUTTON_TYPE_SAVEAS_FILE, BUTTON_TYPE_BROWSE_FILE, BUTTON_TYPE_BROWSE_FILES, + BUTTON_TYPE_BROWSE_FOLDER, BUTTON_TYPE_CALENDAR_CHOOSER))): + AddToReturnList(form, value) + AddToReturnDictionary(top_level_form, element, value) + + # if this is a column, then will fail so need to wrap with try + try: + if form.ReturnKeyboardEvents and form.LastKeyboardEvent is not None: + event = form.LastKeyboardEvent + form.LastKeyboardEvent = None + except: + pass + + try: + form.ReturnValuesDictionary.pop(None, None) # clean up dictionary include None was included + except: + pass + + # if no event was found + if not initialize_only and event is None and form == top_level_form: + queued_event_value = form._queued_thread_event_read() + if queued_event_value is not None: + event, value = queued_event_value + AddToReturnList(form, value) + form.ReturnValuesDictionary[event] = value + + if not form.UseDictionary: + form.ReturnValues = event, form.ReturnValuesList + else: + form.ReturnValues = event, form.ReturnValuesDictionary + + return form.ReturnValues + + +def fill_form_with_values(window, values_dict): + """ + Fills a window with values provided in a values dictionary { element_key : new_value } + + :param window: The window object to fill + :type window: (Window) + :param values_dict: A dictionary with element keys as key and value is values parm for Update call + :type values_dict: (Dict[Any, Any]) + :return: None + :rtype: None + """ + + for element_key in values_dict: + try: + window.AllKeysDict[element_key].Update(values_dict[element_key]) + except Exception as e: + print('Problem filling form. Perhaps bad key? This is a suspected bad key: {}'.format(element_key)) + + +def _FindElementWithFocusInSubForm(form): + """ + Searches through a "sub-form" (can be a window or container) for the current element with focus + + :param form: a Window, Column, Frame, or TabGroup (container elements) + :type form: container elements + :return: Element + :rtype: Element | None + """ + for row_num, row in enumerate(form.Rows): + for col_num, element in enumerate(row): + if element.Type == ELEM_TYPE_COLUMN: + matching_elem = _FindElementWithFocusInSubForm(element) + if matching_elem is not None: + return matching_elem + elif element.Type == ELEM_TYPE_FRAME: + matching_elem = _FindElementWithFocusInSubForm(element) + if matching_elem is not None: + return matching_elem + elif element.Type == ELEM_TYPE_TAB_GROUP: + matching_elem = _FindElementWithFocusInSubForm(element) + if matching_elem is not None: + return matching_elem + elif element.Type == ELEM_TYPE_TAB: + matching_elem = _FindElementWithFocusInSubForm(element) + if matching_elem is not None: + return matching_elem + elif element.Type == ELEM_TYPE_PANE: + matching_elem = _FindElementWithFocusInSubForm(element) + if matching_elem is not None: + return matching_elem + elif element.Type == ELEM_TYPE_INPUT_TEXT: + if element.TKEntry is not None: + if element.TKEntry is element.TKEntry.focus_get(): + return element + elif element.Type == ELEM_TYPE_INPUT_MULTILINE: + if element.TKText is not None: + if element.TKText is element.TKText.focus_get(): + return element + elif element.Type == ELEM_TYPE_BUTTON: + if element.TKButton is not None: + if element.TKButton is element.TKButton.focus_get(): + return element + else: # The "Catch All" - if type isn't one of the above, try generic element.Widget + try: + if element.Widget is not None: + if element.Widget is element.Widget.focus_get(): + return element + except: + return None + + return None + + +def AddMenuItem(top_menu, sub_menu_info, element, is_sub_menu=False, skip=False, right_click_menu=False): + """ + Only to be used internally. Not user callable + :param top_menu: ??? + :type top_menu: ??? + :param sub_menu_info: ??? + :type sub_menu_info: + :param element: ??? + :type element: idk_yetReally + :param is_sub_menu: (Default = False) + :type is_sub_menu: (bool) + :param skip: (Default = False) + :type skip: (bool) + + """ + return_val = None + if type(sub_menu_info) is str: + if not is_sub_menu and not skip: + pos = sub_menu_info.find(MENU_SHORTCUT_CHARACTER) + if pos != -1: + if pos < len(MENU_SHORTCUT_CHARACTER) or sub_menu_info[pos - len(MENU_SHORTCUT_CHARACTER)] != "\\": + sub_menu_info = sub_menu_info[:pos] + sub_menu_info[pos + len(MENU_SHORTCUT_CHARACTER):] + if sub_menu_info == '---': + top_menu.add('separator') + else: + try: + item_without_key = sub_menu_info[:sub_menu_info.index(MENU_KEY_SEPARATOR)] + except: + item_without_key = sub_menu_info + + if item_without_key[0] == MENU_DISABLED_CHARACTER: + top_menu.add_command(label=item_without_key[len(MENU_DISABLED_CHARACTER):], underline=pos - 1, + command=lambda: element._MenuItemChosenCallback(sub_menu_info)) + top_menu.entryconfig(item_without_key[len(MENU_DISABLED_CHARACTER):], state='disabled') + else: + top_menu.add_command(label=item_without_key, underline=pos, + command=lambda: element._MenuItemChosenCallback(sub_menu_info)) + else: + i = 0 + while i < (len(sub_menu_info)): + item = sub_menu_info[i] + if i != len(sub_menu_info) - 1: + if type(sub_menu_info[i + 1]) == list: + new_menu = tk.Menu(top_menu, tearoff=element.Tearoff) + # if a right click menu, then get styling from the top-level window + if right_click_menu: + window = element.ParentForm + if window.right_click_menu_background_color not in (COLOR_SYSTEM_DEFAULT, None): + new_menu.config(bg=window.right_click_menu_background_color) + if window.right_click_menu_text_color not in (COLOR_SYSTEM_DEFAULT, None): + new_menu.config(fg=window.right_click_menu_text_color) + if window.right_click_menu_disabled_text_color not in (COLOR_SYSTEM_DEFAULT, None): + new_menu.config(disabledforeground=window.right_click_menu_disabled_text_color) + if window.right_click_menu_font is not None: + new_menu.config(font=window.right_click_menu_font) + else: + if element.Font is not None: + new_menu.config(font=element.Font) + if element.BackgroundColor not in (COLOR_SYSTEM_DEFAULT, None): + new_menu.config(bg=element.BackgroundColor) + if element.TextColor not in (COLOR_SYSTEM_DEFAULT, None): + new_menu.config(fg=element.TextColor) + if element.DisabledTextColor not in (COLOR_SYSTEM_DEFAULT, None): + new_menu.config(disabledforeground=element.DisabledTextColor) + if element.ItemFont is not None: + new_menu.config(font=element.ItemFont) + return_val = new_menu + pos = sub_menu_info[i].find(MENU_SHORTCUT_CHARACTER) + if pos != -1: + if pos < len(MENU_SHORTCUT_CHARACTER) or sub_menu_info[i][pos - len(MENU_SHORTCUT_CHARACTER)] != "\\": + sub_menu_info[i] = sub_menu_info[i][:pos] + sub_menu_info[i][pos + len(MENU_SHORTCUT_CHARACTER):] + if sub_menu_info[i][0] == MENU_DISABLED_CHARACTER: + top_menu.add_cascade(label=sub_menu_info[i][len(MENU_DISABLED_CHARACTER):], menu=new_menu, + underline=pos, state='disabled') + else: + top_menu.add_cascade(label=sub_menu_info[i], menu=new_menu, underline=pos) + AddMenuItem(new_menu, sub_menu_info[i + 1], element, is_sub_menu=True, right_click_menu=right_click_menu) + i += 1 # skip the next one + else: + AddMenuItem(top_menu, item, element, right_click_menu=right_click_menu) + else: + AddMenuItem(top_menu, item, element, right_click_menu=right_click_menu) + i += 1 + return return_val + + +# 888 888 d8b 888 +# 888 888 Y8P 888 +# 888 888 888 +# 888888 888 888 888 88888b. 888888 .d88b. 888d888 +# 888 888 .88P 888 888 "88b 888 d8P Y8b 888P" +# 888 888888K 888 888 888 888 88888888 888 +# Y88b. 888 "88b 888 888 888 Y88b. Y8b. 888 +# "Y888 888 888 888 888 888 "Y888 "Y8888 888 + +# My crappy tkinter code starts here. (search for "crappy" to get here quickly... that's the purpose if you hadn't caught on + +""" + ) + ( + , + ___)\ + (_____) + (_______) + +""" + + +# Chr0nic || This is probably *very* bad practice. But it works. Simple, but it works... +class VarHolder(object): + canvas_holder = None + + def __init__(self): + self.canvas_holder = None + + +# Also, to get to the point in the code where each element's widget is created, look for element + "p lacement" (without the space) + + +# ======================== TK CODE STARTS HERE ========================================= # +def _fixed_map(style, style_name, option, highlight_colors=(None, None)): + # Fix for setting text colour for Tkinter 8.6.9 + # From: https://core.tcl.tk/tk/info/509cafafae + + # default_map = [elm for elm in style.map("Treeview", query_opt=option) if '!' not in elm[0]] + # custom_map = [elm for elm in style.map(style_name, query_opt=option) if '!' not in elm[0]] + default_map = [elm for elm in style.map("Treeview", query_opt=option) if '!' not in elm[0] and 'selected' not in elm[0]] + custom_map = [elm for elm in style.map(style_name, query_opt=option) if '!' not in elm[0] and 'selected' not in elm[0]] + if option == 'background': + custom_map.append(('selected', highlight_colors[1] if highlight_colors[1] is not None else ALTERNATE_TABLE_AND_TREE_SELECTED_ROW_COLORS[1])) + elif option == 'foreground': + custom_map.append(('selected', highlight_colors[0] if highlight_colors[0] is not None else ALTERNATE_TABLE_AND_TREE_SELECTED_ROW_COLORS[0])) + + new_map = custom_map + default_map + return new_map + # + # new_map = [elm for elm in style.map(style_name, query_opt=option) if elm[:2] != ('!disabled', '!selected')] + # + # if option == 'background': + # new_map.append(('selected', highlight_colors[1] if highlight_colors[1] is not None else ALTERNATE_TABLE_AND_TREE_SELECTED_ROW_COLORS[1])) + # elif option == 'foreground': + # new_map.append(('selected', highlight_colors[0] if highlight_colors[0] is not None else ALTERNATE_TABLE_AND_TREE_SELECTED_ROW_COLORS[0])) + # return new_map + # + +def _add_right_click_menu(element, toplevel_form): + if element.RightClickMenu == MENU_RIGHT_CLICK_DISABLED: + return + if element.RightClickMenu or toplevel_form.RightClickMenu: + menu = element.RightClickMenu or toplevel_form.RightClickMenu + top_menu = tk.Menu(toplevel_form.TKroot, tearoff=toplevel_form.right_click_menu_tearoff, tearoffcommand=element._tearoff_menu_callback) + + if toplevel_form.right_click_menu_background_color not in (COLOR_SYSTEM_DEFAULT, None): + top_menu.config(bg=toplevel_form.right_click_menu_background_color) + if toplevel_form.right_click_menu_text_color not in (COLOR_SYSTEM_DEFAULT, None): + top_menu.config(fg=toplevel_form.right_click_menu_text_color) + if toplevel_form.right_click_menu_disabled_text_color not in (COLOR_SYSTEM_DEFAULT, None): + top_menu.config(disabledforeground=toplevel_form.right_click_menu_disabled_text_color) + if toplevel_form.right_click_menu_font is not None: + top_menu.config(font=toplevel_form.right_click_menu_font) + + if toplevel_form.right_click_menu_selected_colors[0] not in (COLOR_SYSTEM_DEFAULT, None): + top_menu.config(activeforeground=toplevel_form.right_click_menu_selected_colors[0]) + if toplevel_form.right_click_menu_selected_colors[1] not in (COLOR_SYSTEM_DEFAULT, None): + top_menu.config(activebackground=toplevel_form.right_click_menu_selected_colors[1]) + AddMenuItem(top_menu, menu[1], element, right_click_menu=True) + element.TKRightClickMenu = top_menu + if (running_mac()): + element.Widget.bind('', element._RightClickMenuCallback) + else: + element.Widget.bind('', element._RightClickMenuCallback) + + +class Stylist: + + @staticmethod + def get_elements(layout): + """Return a list of elements contained in the style""" + elements = [] + element = layout[0][0] + elements.append(element) + sublayout = layout[0][1] + + if 'children' in sublayout: + child_elements = Stylist.get_elements(sublayout['children']) + elements.extend(child_elements) + return elements + + @staticmethod + def get_options(ttkstyle, theme=None): + style = ttk.Style() + if theme is not None: + style.theme_use(theme) + layout = style.layout(ttkstyle) + elements = Stylist.get_elements(layout) + options = [] + for e in elements: + _opts = style.element_options(e) + if _opts: + options.extend(list(_opts)) + return list(set(options)) + + @staticmethod + def create_style(base_style: str, theme=None, **kwargs): + style = ttk.Style() + if theme is not None: + style.theme_use(theme) + style_id = uuid4() + ttkstyle = '{}.{}'.format(style_id, base_style) + style.configure(ttkstyle, **kwargs) + return ttkstyle + + +# if __name__ == '__main__': +# root = tk.Tk() +# +# # find out what options are available for the theme and widget style +# options = Stylist.get_options('TFrame', 'default') +# print('The options for this style and theme are', options) +# +# # create a new style +# frame_style = Stylist.create_style('TFrame', 'alt', relief=tk.RAISED, borderwidth=1) +# +# # apply the new style +# ttk.Frame(style=frame_style, width=100, height=100).pack(padx=10, pady=10) +# +# root.mainloop() + +# @_timeit +def PackFormIntoFrame(form, containing_frame, toplevel_form): + """ + + :param form: a window class + :type form: (Window) + :param containing_frame: ??? + :type containing_frame: ??? + :param toplevel_form: ??? + :type toplevel_form: (Window) + + """ + + # Old bindings + def yscroll_old(event): + try: + if event.num == 5 or event.delta < 0: + VarHolder.canvas_holder.yview_scroll(1, "unit") + elif event.num == 4 or event.delta > 0: + VarHolder.canvas_holder.yview_scroll(-1, "unit") + except: + pass + + def xscroll_old(event): + try: + if event.num == 5 or event.delta < 0: + VarHolder.canvas_holder.xview_scroll(1, "unit") + elif event.num == 4 or event.delta > 0: + VarHolder.canvas_holder.xview_scroll(-1, "unit") + except: + pass + + # Chr0nic + def testMouseHook2(em): + combo = em.TKCombo + combo.unbind_class("TCombobox", "") + combo.unbind_class("TCombobox", "") + combo.unbind_class("TCombobox", "") + containing_frame.unbind_all('<4>') + containing_frame.unbind_all('<5>') + containing_frame.unbind_all("") + containing_frame.unbind_all("") + + # Chr0nic + def testMouseUnhook2(em): + containing_frame.bind_all('<4>', yscroll_old, add="+") + containing_frame.bind_all('<5>', yscroll_old, add="+") + containing_frame.bind_all("", yscroll_old, add="+") + containing_frame.bind_all("", xscroll_old, add="+") + + # Chr0nic + def testMouseHook(em): + containing_frame.unbind_all('<4>') + containing_frame.unbind_all('<5>') + containing_frame.unbind_all("") + containing_frame.unbind_all("") + + # Chr0nic + def testMouseUnhook(em): + containing_frame.bind_all('<4>', yscroll_old, add="+") + containing_frame.bind_all('<5>', yscroll_old, add="+") + containing_frame.bind_all("", yscroll_old, add="+") + containing_frame.bind_all("", xscroll_old, add="+") + + def _char_width_in_pixels(font): + return tkinter.font.Font(font=font).measure('A') # single character width + + def _char_height_in_pixels(font): + return tkinter.font.Font(font=font).metrics('linespace') + + def _string_width_in_pixels(font, string): + return tkinter.font.Font(font=font).measure(string) # single character width + + def _valid_theme(style, theme_name): + if theme_name in style.theme_names(): + return True + _error_popup_with_traceback('Your Window has an invalid ttk theme specified', + 'The traceback will show you the Window with the problem layout', + '** Invalid ttk theme specified {} **'.format(theme_name), + '\nValid choices include: {}'.format(style.theme_names())) + + # print('** Invalid ttk theme specified {} **'.format(theme_name), + # '\nValid choices include: {}'.format(style.theme_names())) + return False + + + def _make_ttk_style_name(base_style, element): + Window._counter_for_ttk_widgets += 1 + style_name = str(Window._counter_for_ttk_widgets) + '___' + str(element.Key) + base_style + element.ttk_style_name = style_name + return style_name + + def _add_grab(element): + + try: + if form.Grab is True or element.Grab is True: + # if something already about to the button, then don't do the grab stuff + if '' not in element.Widget.bind(): + element.Widget.bind("", toplevel_form._StartMoveGrabAnywhere) + element.Widget.bind("", toplevel_form._StopMove) + element.Widget.bind("", toplevel_form._OnMotionGrabAnywhere) + element.ParentRowFrame.bind("", toplevel_form._StartMoveGrabAnywhere) + element.ParentRowFrame.bind("", toplevel_form._StopMove) + element.ParentRowFrame.bind("", toplevel_form._OnMotionGrabAnywhere) + if element.Type == ELEM_TYPE_COLUMN: + element.TKColFrame.canvas.bind("", toplevel_form._StartMoveGrabAnywhere) + element.TKColFrame.canvas.bind("", toplevel_form._StopMove) + element.TKColFrame.canvas.bind("", toplevel_form._OnMotionGrabAnywhere) + except Exception as e: + pass + # print(e) + + def _add_right_click_menu_and_grab(element): + if element.RightClickMenu == MENU_RIGHT_CLICK_DISABLED: + return + if element.Type == ELEM_TYPE_TAB_GROUP: # unless everything disabled, then need to always set a right click menu for tabgroups + if toplevel_form.RightClickMenu == MENU_RIGHT_CLICK_DISABLED: + return + menu = _MENU_RIGHT_CLICK_TABGROUP_DEFAULT + else: + menu = element.RightClickMenu or form.RightClickMenu or toplevel_form.RightClickMenu + + if menu: + top_menu = tk.Menu(toplevel_form.TKroot, tearoff=toplevel_form.right_click_menu_tearoff, tearoffcommand=element._tearoff_menu_callback) + + if toplevel_form.right_click_menu_background_color not in (COLOR_SYSTEM_DEFAULT, None): + top_menu.config(bg=toplevel_form.right_click_menu_background_color) + if toplevel_form.right_click_menu_text_color not in (COLOR_SYSTEM_DEFAULT, None): + top_menu.config(fg=toplevel_form.right_click_menu_text_color) + if toplevel_form.right_click_menu_disabled_text_color not in (COLOR_SYSTEM_DEFAULT, None): + top_menu.config(disabledforeground=toplevel_form.right_click_menu_disabled_text_color) + if toplevel_form.right_click_menu_font is not None: + top_menu.config(font=toplevel_form.right_click_menu_font) + + if toplevel_form.right_click_menu_selected_colors[0] not in (COLOR_SYSTEM_DEFAULT, None): + top_menu.config(activeforeground=toplevel_form.right_click_menu_selected_colors[0]) + if toplevel_form.right_click_menu_selected_colors[1] not in (COLOR_SYSTEM_DEFAULT, None): + top_menu.config(activebackground=toplevel_form.right_click_menu_selected_colors[1]) + AddMenuItem(top_menu, menu[1], element, right_click_menu=True) + element.TKRightClickMenu = top_menu + if toplevel_form.RightClickMenu: # if the top level has a right click menu, then setup a callback for the Window itself + if toplevel_form.TKRightClickMenu is None: + toplevel_form.TKRightClickMenu = top_menu + if (running_mac()): + toplevel_form.TKroot.bind('', toplevel_form._RightClickMenuCallback) + else: + toplevel_form.TKroot.bind('', toplevel_form._RightClickMenuCallback) + if (running_mac()): + element.Widget.bind('', element._RightClickMenuCallback) + else: + element.Widget.bind('', element._RightClickMenuCallback) + try: + if element.Type == ELEM_TYPE_COLUMN: + element.TKColFrame.canvas.bind('', element._RightClickMenuCallback) + except: + pass + _add_grab(element) + + + def _add_expansion(element, row_should_expand, row_fill_direction): + expand = True + if element.expand_x and element.expand_y: + fill = tk.BOTH + row_fill_direction = tk.BOTH + row_should_expand = True + elif element.expand_x: + fill = tk.X + row_fill_direction = tk.X if row_fill_direction == tk.NONE else tk.BOTH if row_fill_direction == tk.Y else tk.X + elif element.expand_y: + fill = tk.Y + row_fill_direction = tk.Y if row_fill_direction == tk.NONE else tk.BOTH if row_fill_direction == tk.X else tk.Y + row_should_expand = True + else: + fill = tk.NONE + expand = False + return expand, fill, row_should_expand, row_fill_direction + + tclversion_detailed = tkinter.Tcl().eval('info patchlevel') + + + # --------------------------------------------------------------------------- # + # **************** Use FlexForm to build the tkinter window ********** ----- # + # Building is done row by row. # + # WARNING - You can't use print in this function. If the user has rerouted # + # stdout then there will be an error saying the window isn't finalized # + # --------------------------------------------------------------------------- # + ######################### LOOP THROUGH ROWS ######################### + # *********** ------- Loop through ROWS ------- ***********# + for row_num, flex_row in enumerate(form.Rows): + ######################### LOOP THROUGH ELEMENTS ON ROW ######################### + # *********** ------- Loop through ELEMENTS ------- ***********# + # *********** Make TK Row ***********# + tk_row_frame = tk.Frame(containing_frame) + row_should_expand = False + row_fill_direction = tk.NONE + + if form.ElementJustification is not None: + row_justify = form.ElementJustification + # elif toplevel_form.ElementJustification is not None: + # row_justify = toplevel_form.ElementJustification + else: + row_justify = 'l' + + for col_num, element in enumerate(flex_row): + element.ParentRowFrame = tk_row_frame + element.element_frame = None # for elements that have a scrollbar too + element.ParentForm = toplevel_form # save the button's parent form object + if toplevel_form.Font and (element.Font == DEFAULT_FONT or element.Font is None): + font = toplevel_form.Font + elif element.Font is not None: + font = element.Font + else: + font = DEFAULT_FONT + # ------- Determine Auto-Size setting on a cascading basis ------- # + if element.AutoSizeText is not None: # if element overide + auto_size_text = element.AutoSizeText + elif toplevel_form.AutoSizeText is not None: # if form override + auto_size_text = toplevel_form.AutoSizeText + else: + auto_size_text = DEFAULT_AUTOSIZE_TEXT + element_type = element.Type + # Set foreground color + text_color = element.TextColor + elementpad = element.Pad if element.Pad is not None else toplevel_form.ElementPadding + element.pad_used = elementpad # store the value used back into the element + # Determine Element size + element_size = element.Size + if (element_size == (None, None) and element_type not in ( + ELEM_TYPE_BUTTON, ELEM_TYPE_BUTTONMENU)): # user did not specify a size + element_size = toplevel_form.DefaultElementSize + elif (element_size == (None, None) and element_type in (ELEM_TYPE_BUTTON, ELEM_TYPE_BUTTONMENU)): + element_size = toplevel_form.DefaultButtonElementSize + else: + auto_size_text = False # if user has specified a size then it shouldn't autosize + + border_depth = toplevel_form.BorderDepth if toplevel_form.BorderDepth is not None else DEFAULT_BORDER_WIDTH + try: + if element.BorderWidth is not None: + border_depth = element.BorderWidth + except: + pass + + # ------------------------- COLUMN placement element ------------------------- # + if element_type == ELEM_TYPE_COLUMN: + element = element # type: Column + # ----------------------- SCROLLABLE Column ---------------------- + if element.Scrollable: + element.Widget = element.TKColFrame = TkScrollableFrame(tk_row_frame, element.VerticalScrollOnly) # do not use yet! not working + PackFormIntoFrame(element, element.TKColFrame.TKFrame, toplevel_form) + element.TKColFrame.TKFrame.update() + if element.Size == (None, None): # if no size specified, use column width x column height/2 + element.TKColFrame.canvas.config(width=element.TKColFrame.TKFrame.winfo_reqwidth(), + height=element.TKColFrame.TKFrame.winfo_reqheight() // 2) + else: + element.TKColFrame.canvas.config(width=element.TKColFrame.TKFrame.winfo_reqwidth(), + height=element.TKColFrame.TKFrame.winfo_reqheight() // 2) + if None not in (element.Size[0], element.Size[1]): + element.TKColFrame.canvas.config(width=element.Size[0], height=element.Size[1]) + elif element.Size[1] is not None: + element.TKColFrame.canvas.config(height=element.Size[1]) + elif element.Size[0] is not None: + element.TKColFrame.canvas.config(width=element.Size[0]) + + if not element.BackgroundColor in (None, COLOR_SYSTEM_DEFAULT): + element.TKColFrame.canvas.config(background=element.BackgroundColor) + element.TKColFrame.TKFrame.config(background=element.BackgroundColor, borderwidth=0, highlightthickness=0) + element.TKColFrame.config(background=element.BackgroundColor, borderwidth=0, + highlightthickness=0) + # ----------------------- PLAIN Column ---------------------- + else: + + if element.Size != (None, None): + element.Widget = element.TKColFrame = TkFixedFrame(tk_row_frame) + PackFormIntoFrame(element, element.TKColFrame.TKFrame, toplevel_form) + element.TKColFrame.TKFrame.update() + if None not in (element.Size[0], element.Size[1]): + element.TKColFrame.canvas.config(width=element.Size[0], height=element.Size[1]) + elif element.Size[1] is not None: + element.TKColFrame.canvas.config(height=element.Size[1]) + elif element.Size[0] is not None: + element.TKColFrame.canvas.config(width=element.Size[0]) + if not element.BackgroundColor in (None, COLOR_SYSTEM_DEFAULT): + element.TKColFrame.canvas.config(background=element.BackgroundColor) + element.TKColFrame.TKFrame.config(background=element.BackgroundColor, borderwidth=0, highlightthickness=0) + else: + element.Widget = element.TKColFrame = tk.Frame(tk_row_frame) + PackFormIntoFrame(element, element.TKColFrame, toplevel_form) + if not element.BackgroundColor in (None, COLOR_SYSTEM_DEFAULT): + element.TKColFrame.config(background=element.BackgroundColor, borderwidth=0, highlightthickness=0) + + if element.Justification is None: + pass + elif element.Justification.lower().startswith('l'): + row_justify = 'l' + elif element.Justification.lower().startswith('c'): + row_justify = 'c' + elif element.Justification.lower().startswith('r'): + row_justify = 'r' + + # anchor=tk.NW + # side = tk.LEFT + # row_justify = element.Justification + + element.Widget = element.TKColFrame + + expand = True + if element.ExpandX and element.ExpandY: + fill = tk.BOTH + row_fill_direction = tk.BOTH + row_should_expand = True + elif element.ExpandX: + fill = tk.X + row_fill_direction = tk.X + elif element.ExpandY: + fill = tk.Y + row_fill_direction = tk.Y + row_should_expand = True + else: + fill = tk.NONE + expand = False + + if element.VerticalAlignment is not None: + anchor = tk.CENTER # Default to center if a bad choice is made + + if element.VerticalAlignment.lower().startswith('t'): + anchor = tk.N + if element.VerticalAlignment.lower().startswith('c'): + anchor = tk.CENTER + if element.VerticalAlignment.lower().startswith('b'): + anchor = tk.S + element.TKColFrame.pack(side=tk.LEFT, anchor=anchor, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill) + else: + element.TKColFrame.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill) + + # element.TKColFrame.pack(side=side, padx=elementpad[0], pady=elementpad[1], expand=True, fill='both') + if element.visible is False: + element.TKColFrame.pack_forget() + # element.TKColFrame = element.TKColFrame + # if element.BackgroundColor != COLOR_SYSTEM_DEFAULT and element.BackgroundColor is not None: + # element.TKColFrame.configure(background=element.BackgroundColor, + # highlightbackground=element.BackgroundColor, + # highlightcolor=element.BackgroundColor) + + _add_right_click_menu_and_grab(element) + # if element.Grab: + # element._grab_anywhere_on() + # row_should_expand = True + # ------------------------- Pane placement element ------------------------- # + if element_type == ELEM_TYPE_PANE: + bd = element.BorderDepth if element.BorderDepth is not None else border_depth + element.PanedWindow = element.Widget = tk.PanedWindow(tk_row_frame, + orient=tk.VERTICAL if element.Orientation.startswith( + 'v') else tk.HORIZONTAL, + borderwidth=bd, + bd=bd, + ) + if element.Relief is not None: + element.PanedWindow.configure(relief=element.Relief) + element.PanedWindow.configure(handlesize=element.HandleSize) + if element.ShowHandle: + element.PanedWindow.config(showhandle=True) + if element.Size != (None, None): + element.PanedWindow.config(width=element.Size[0], height=element.Size[1]) + if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + element.PanedWindow.configure(background=element.BackgroundColor) + for pane in element.PaneList: + pane.Widget = pane.TKColFrame = tk.Frame(element.PanedWindow) + pane.ParentPanedWindow = element.PanedWindow + PackFormIntoFrame(pane, pane.TKColFrame, toplevel_form) + if pane.visible: + element.PanedWindow.add(pane.TKColFrame) + if pane.BackgroundColor != COLOR_SYSTEM_DEFAULT and pane.BackgroundColor is not None: + pane.TKColFrame.configure(background=pane.BackgroundColor, + highlightbackground=pane.BackgroundColor, + highlightcolor=pane.BackgroundColor) + expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction) + element.PanedWindow.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill) + # element.PanedWindow.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=True, fill='both') + if element.visible is False: + element.PanedWindow.pack_forget() + # ------------------------- TEXT placement element ------------------------- # + elif element_type == ELEM_TYPE_TEXT: + # auto_size_text = element.AutoSizeText + element = element # type: Text + display_text = element.DisplayText # text to display + if auto_size_text is False: + width, height = element_size + else: + width, height = None, None + # lines = display_text.split('\n') + # max_line_len = max([len(l) for l in lines]) + # num_lines = len(lines) + # if max_line_len > element_size[0]: # if text exceeds element size, the will have to wrap + # width = element_size[0] + # else: + # width = max_line_len + # height = num_lines + # ---===--- LABEL widget create and place --- # + element = element # type: Text + bd = element.BorderWidth if element.BorderWidth is not None else border_depth + stringvar = tk.StringVar() + element.TKStringVar = stringvar + stringvar.set(str(display_text)) + if auto_size_text: + width = 0 + if element.Justification is not None: + justification = element.Justification + elif toplevel_form.TextJustification is not None: + justification = toplevel_form.TextJustification + else: + justification = DEFAULT_TEXT_JUSTIFICATION + justify = tk.LEFT if justification.startswith('l') else tk.CENTER if justification.startswith('c') else tk.RIGHT + anchor = tk.NW if justification.startswith('l') else tk.N if justification.startswith('c') else tk.NE + tktext_label = element.Widget = tk.Label(tk_row_frame, textvariable=stringvar, width=width, + height=height, justify=justify, bd=bd, font=font) + # Set wrap-length for text (in PIXELS) == PAIN IN THE ASS + wraplen = tktext_label.winfo_reqwidth() # width of widget in Pixels + if auto_size_text or (not auto_size_text and height == 1): # if just 1 line high, ensure no wrap happens + wraplen = 0 + tktext_label.configure(anchor=anchor, wraplen=wraplen) # set wrap to width of widget + if element.Relief is not None: + tktext_label.configure(relief=element.Relief) + if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + tktext_label.configure(background=element.BackgroundColor) + if element.TextColor != COLOR_SYSTEM_DEFAULT and element.TextColor is not None: + tktext_label.configure(fg=element.TextColor) + expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction) + tktext_label.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill) + if element.visible is False: + tktext_label.pack_forget() + element.TKText = tktext_label + if element.ClickSubmits: + tktext_label.bind('', element._TextClickedHandler) + if element.Tooltip is not None: + element.TooltipObject = ToolTip(element.TKText, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) + _add_right_click_menu_and_grab(element) + if element.Grab: + element._grab_anywhere_on() + # ------------------------- BUTTON placement element non-ttk version ------------------------- # + elif (element_type == ELEM_TYPE_BUTTON and element.UseTtkButtons is False) or \ + (element_type == ELEM_TYPE_BUTTON and element.UseTtkButtons is not True and toplevel_form.UseTtkButtons is not True): + element = element # type: Button + element.UseTtkButtons = False # indicate that ttk button was not used + stringvar = tk.StringVar() + element.TKStringVar = stringvar + element.Location = (row_num, col_num) + btext = element.ButtonText + btype = element.BType + if element.AutoSizeButton is not None: + auto_size = element.AutoSizeButton + else: + auto_size = toplevel_form.AutoSizeButtons + if auto_size is False or element.Size[0] is not None: + width, height = element_size + else: + width = 0 + height = toplevel_form.DefaultButtonElementSize[1] + if element.ButtonColor != (None, None) and element.ButtonColor != DEFAULT_BUTTON_COLOR: + bc = element.ButtonColor + elif toplevel_form.ButtonColor != (None, None) and toplevel_form.ButtonColor != DEFAULT_BUTTON_COLOR: + bc = toplevel_form.ButtonColor + else: + bc = DEFAULT_BUTTON_COLOR + + bd = element.BorderWidth + + try: + if btype != BUTTON_TYPE_REALTIME: + tkbutton = element.Widget = tk.Button(tk_row_frame, text=btext, width=width, height=height, + command=element.ButtonCallBack, justify=tk.CENTER, bd=bd, font=font) + else: + tkbutton = element.Widget = tk.Button(tk_row_frame, text=btext, width=width, height=height, + justify=tk.CENTER, bd=bd, font=font) + tkbutton.bind('', element.ButtonReleaseCallBack) + tkbutton.bind('', element.ButtonPressCallBack) + if bc != (None, None) and COLOR_SYSTEM_DEFAULT not in bc: + tkbutton.config(foreground=bc[0], background=bc[1]) + else: + if bc[0] != COLOR_SYSTEM_DEFAULT: + tkbutton.config(foreground=bc[0]) + if bc[1] != COLOR_SYSTEM_DEFAULT: + tkbutton.config(background=bc[1]) + except Exception as e: + _error_popup_with_traceback('Button has a problem....', + 'The traceback information will not show the line in your layout with the problem, but it does tell you which window.', + 'Error {}'.format(e), + # 'Button Text: {}'.format(btext), + # 'Button key: {}'.format(element.Key), + # 'Color string: {}'.format(bc), + "Parent Window's Title: {}".format(toplevel_form.Title)) + + if bd == 0 and not running_mac(): + tkbutton.config(relief=tk.FLAT) + + element.TKButton = tkbutton # not used yet but save the TK button in case + wraplen = tkbutton.winfo_reqwidth() # width of widget in Pixels + if elementpad[0] == 0 or elementpad[1] == 0: + tkbutton.config(highlightthickness=0) + + ## -------------- TK Button With Image -------------- ## + if element.ImageFilename: # if button has an image on it + tkbutton.config(highlightthickness=0) + try: + photo = tk.PhotoImage(file=element.ImageFilename) + if element.ImageSubsample: + photo = photo.subsample(element.ImageSubsample) + if element.ImageSize != (None, None): + width, height = element.ImageSize + else: + width, height = photo.width(), photo.height() + except Exception as e: + _error_popup_with_traceback('Button Element error {}'.format(e), 'Image filename: {}'.format(element.ImageFilename), + 'Button element key: {}'.format(element.Key), + "Parent Window's Title: {}".format(toplevel_form.Title)) + tkbutton.config(image=photo, compound=tk.CENTER, width=width, height=height) + tkbutton.image = photo + if element.ImageData: # if button has an image on it + tkbutton.config(highlightthickness=0) + try: + photo = tk.PhotoImage(data=element.ImageData) + if element.ImageSubsample: + photo = photo.subsample(element.ImageSubsample) + if element.ImageSize != (None, None): + width, height = element.ImageSize + else: + width, height = photo.width(), photo.height() + tkbutton.config(image=photo, compound=tk.CENTER, width=width, height=height) + tkbutton.image = photo + except Exception as e: + _error_popup_with_traceback('Button Element error {}'.format(e), + 'Problem using BASE64 Image data Image Susample', + 'Buton element key: {}'.format(element.Key), + "Parent Window's Title: {}".format(toplevel_form.Title)) + + if width != 0: + tkbutton.configure(wraplength=wraplen + 10) # set wrap to width of widget + expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction) + + tkbutton.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill) + if element.visible is False: + tkbutton.pack_forget() + if element.BindReturnKey: + element.TKButton.bind('', element._ReturnKeyHandler) + if element.Focus is True or (toplevel_form.UseDefaultFocus and not toplevel_form.FocusSet): + toplevel_form.FocusSet = True + element.TKButton.bind('', element._ReturnKeyHandler) + element.TKButton.focus_set() + toplevel_form.TKroot.focus_force() + if element.Disabled is True: + element.TKButton['state'] = 'disabled' + if element.DisabledButtonColor != (None, None) and element.DisabledButtonColor != (COLOR_SYSTEM_DEFAULT, COLOR_SYSTEM_DEFAULT): + if element.DisabledButtonColor[0] not in (None, COLOR_SYSTEM_DEFAULT): + element.TKButton['disabledforeground'] = element.DisabledButtonColor[0] + if element.MouseOverColors[1] not in (COLOR_SYSTEM_DEFAULT, None): + tkbutton.config(activebackground=element.MouseOverColors[1]) + if element.MouseOverColors[0] not in (COLOR_SYSTEM_DEFAULT, None): + tkbutton.config(activeforeground=element.MouseOverColors[0]) + + if element.Tooltip is not None: + element.TooltipObject = ToolTip(element.TKButton, text=element.Tooltip, + timeout=DEFAULT_TOOLTIP_TIME) + try: + if element.HighlightColors[1] != COLOR_SYSTEM_DEFAULT: + tkbutton.config(highlightbackground=element.HighlightColors[1]) + if element.HighlightColors[0] != COLOR_SYSTEM_DEFAULT: + tkbutton.config(highlightcolor=element.HighlightColors[0]) + except Exception as e: + _error_popup_with_traceback('Button Element error {}'.format(e), + 'Button element key: {}'.format(element.Key), + 'Button text: {}'.format(btext), + 'Has a bad highlight color {}'.format(element.HighlightColors), + "Parent Window's Title: {}".format(toplevel_form.Title)) + # print('Button with text: ', btext, 'has a bad highlight color', element.HighlightColors) + _add_right_click_menu_and_grab(element) + + # ------------------------- BUTTON placement element ttk version ------------------------- # + elif element_type == ELEM_TYPE_BUTTON: + element = element # type: Button + element.UseTtkButtons = True # indicate that ttk button was used + stringvar = tk.StringVar() + element.TKStringVar = stringvar + element.Location = (row_num, col_num) + btext = element.ButtonText + btype = element.BType + if element.AutoSizeButton is not None: + auto_size = element.AutoSizeButton + else: + auto_size = toplevel_form.AutoSizeButtons + if auto_size is False or element.Size[0] is not None: + width, height = element_size + else: + width = 0 + height = toplevel_form.DefaultButtonElementSize[1] + if element.ButtonColor != (None, None) and element.ButtonColor != COLOR_SYSTEM_DEFAULT: + bc = element.ButtonColor + elif toplevel_form.ButtonColor != (None, None) and toplevel_form.ButtonColor != COLOR_SYSTEM_DEFAULT: + bc = toplevel_form.ButtonColor + else: + bc = DEFAULT_BUTTON_COLOR + bd = element.BorderWidth + if btype != BUTTON_TYPE_REALTIME: + tkbutton = element.Widget = ttk.Button(tk_row_frame, text=btext, width=width, command=element.ButtonCallBack) + else: + tkbutton = element.Widget = ttk.Button(tk_row_frame, text=btext, width=width) + tkbutton.bind('', element.ButtonReleaseCallBack) + tkbutton.bind('', element.ButtonPressCallBack) + # Window._counter_for_ttk_widgets += 1 + # style_name = str(Window._counter_for_ttk_widgets) + (element.Key) + 'custombutton.TButton' + style_name = _make_ttk_style_name('.custombutton.TButton', element) + button_style = ttk.Style() + if _valid_theme(button_style, toplevel_form.TtkTheme): + button_style.theme_use(toplevel_form.TtkTheme) + button_style.configure(style_name, font=font) + + if bc != (None, None) and COLOR_SYSTEM_DEFAULT not in bc: + button_style.configure(style_name, foreground=bc[0], background=bc[1]) + elif bc[0] != COLOR_SYSTEM_DEFAULT: + button_style.configure(style_name, foreground=bc[0]) + elif bc[1] != COLOR_SYSTEM_DEFAULT: + button_style.configure(style_name, background=bc[1]) + + if bd == 0 and not running_mac(): + button_style.configure(style_name, relief=tk.FLAT) + button_style.configure(style_name, borderwidth=0) + else: + button_style.configure(style_name, borderwidth=bd) + button_style.configure(style_name, justify=tk.CENTER) + + if element.MouseOverColors[1] not in (COLOR_SYSTEM_DEFAULT, None): + button_style.map(style_name, background=[('active', element.MouseOverColors[1])]) + if element.MouseOverColors[0] not in (COLOR_SYSTEM_DEFAULT, None): + button_style.map(style_name, foreground=[('active', element.MouseOverColors[0])]) + + if element.DisabledButtonColor[0] not in (COLOR_SYSTEM_DEFAULT, None): + button_style.map(style_name, foreground=[('disabled', element.DisabledButtonColor[0])]) + if element.DisabledButtonColor[1] not in (COLOR_SYSTEM_DEFAULT, None): + button_style.map(style_name, background=[('disabled', element.DisabledButtonColor[1])]) + + if height > 1: + button_style.configure(style_name, padding=height * _char_width_in_pixels(font)) # should this be height instead? + wraplen = tkbutton.winfo_reqwidth() # width of widget in Pixels + if width != 0: + button_style.configure(style_name, wraplength=wraplen) # set wrap to width of widget + + ## -------------- TTK Button With Image -------------- ## + if element.ImageFilename: # if button has an image on it + button_style.configure(style_name, borderwidth=0) + # tkbutton.configure(highlightthickness=0) + photo = tk.PhotoImage(file=element.ImageFilename) + if element.ImageSubsample: + photo = photo.subsample(element.ImageSubsample) + if element.ImageSize != (None, None): + width, height = element.ImageSize + else: + width, height = photo.width(), photo.height() + button_style.configure(style_name, image=photo, compound=tk.CENTER, width=width, height=height) + tkbutton.image = photo + if element.ImageData: # if button has an image on it + # tkbutton.configure(highlightthickness=0) + button_style.configure(style_name, borderwidth=0) + + photo = tk.PhotoImage(data=element.ImageData) + if element.ImageSubsample: + photo = photo.subsample(element.ImageSubsample) + if element.ImageSize != (None, None): + width, height = element.ImageSize + else: + width, height = photo.width(), photo.height() + button_style.configure(style_name, image=photo, compound=tk.CENTER, width=width, height=height) + # tkbutton.configure(image=photo, compound=tk.CENTER, width=width, height=height) + tkbutton.image = photo + + element.TKButton = tkbutton # not used yet but save the TK button in case + expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction) + tkbutton.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill) + if element.visible is False: + tkbutton.pack_forget() + if element.BindReturnKey: + element.TKButton.bind('', element._ReturnKeyHandler) + if element.Focus is True or (toplevel_form.UseDefaultFocus and not toplevel_form.FocusSet): + toplevel_form.FocusSet = True + element.TKButton.bind('', element._ReturnKeyHandler) + element.TKButton.focus_set() + toplevel_form.TKroot.focus_force() + if element.Disabled is True: + element.TKButton['state'] = 'disabled' + + tkbutton.configure(style=style_name) # IMPORTANT! Apply the style to the button! + _add_right_click_menu_and_grab(element) + + if element.Tooltip is not None: + element.TooltipObject = ToolTip(element.TKButton, text=element.Tooltip, + timeout=DEFAULT_TOOLTIP_TIME) + # ------------------------- BUTTONMENU placement element ------------------------- # + elif element_type == ELEM_TYPE_BUTTONMENU: + element = element # type: ButtonMenu + element.Location = (row_num, col_num) + btext = element.ButtonText + if element.AutoSizeButton is not None: + auto_size = element.AutoSizeButton + else: + auto_size = toplevel_form.AutoSizeButtons + if auto_size is False or element.Size[0] is not None: + width, height = element_size + else: + width = 0 + height = toplevel_form.DefaultButtonElementSize[1] + if element.ButtonColor != (None, None) and element.ButtonColor != DEFAULT_BUTTON_COLOR: + bc = element.ButtonColor + elif toplevel_form.ButtonColor != (None, None) and toplevel_form.ButtonColor != DEFAULT_BUTTON_COLOR: + bc = toplevel_form.ButtonColor + else: + bc = DEFAULT_BUTTON_COLOR + bd = element.BorderWidth + if element.ItemFont is None: + element.ItemFont = font + tkbutton = element.Widget = tk.Menubutton(tk_row_frame, text=btext, width=width, height=height, justify=tk.LEFT, bd=bd, font=font) + element.TKButtonMenu = tkbutton + if bc != (None, None) and bc != COLOR_SYSTEM_DEFAULT and bc[1] != COLOR_SYSTEM_DEFAULT: + tkbutton.config(foreground=bc[0], background=bc[1]) + elif bc[0] != COLOR_SYSTEM_DEFAULT: + tkbutton.config(foreground=bc[0]) + if bd == 0 and not running_mac(): + tkbutton.config(relief=RELIEF_FLAT) + elif bd != 0: + tkbutton.config(relief=RELIEF_RAISED) + + element.TKButton = tkbutton # not used yet but save the TK button in case + wraplen = tkbutton.winfo_reqwidth() # width of widget in Pixels + if element.ImageFilename: # if button has an image on it + photo = tk.PhotoImage(file=element.ImageFilename) + if element.ImageSize != (None, None): + width, height = element.ImageSize + if element.ImageSubsample: + photo = photo.subsample(element.ImageSubsample) + else: + width, height = photo.width(), photo.height() + tkbutton.config(image=photo, compound=tk.CENTER, width=width, height=height) + tkbutton.image = photo + if element.ImageData: # if button has an image on it + photo = tk.PhotoImage(data=element.ImageData) + if element.ImageSize != (None, None): + width, height = element.ImageSize + if element.ImageSubsample: + photo = photo.subsample(element.ImageSubsample) + else: + width, height = photo.width(), photo.height() + tkbutton.config(image=photo, compound=tk.CENTER, width=width, height=height) + tkbutton.image = photo + if width != 0: + tkbutton.configure(wraplength=wraplen + 10) # set wrap to width of widget + expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction) + tkbutton.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill) + + menu_def = element.MenuDefinition + + element.TKMenu = top_menu = tk.Menu(tkbutton, tearoff=element.Tearoff, font=element.ItemFont, tearoffcommand=element._tearoff_menu_callback) + + if element.BackgroundColor not in (COLOR_SYSTEM_DEFAULT, None): + top_menu.config(bg=element.BackgroundColor) + if element.TextColor not in (COLOR_SYSTEM_DEFAULT, None): + top_menu.config(fg=element.TextColor) + if element.DisabledTextColor not in (COLOR_SYSTEM_DEFAULT, None): + top_menu.config(disabledforeground=element.DisabledTextColor) + if element.ItemFont is not None: + top_menu.config(font=element.ItemFont) + + AddMenuItem(top_menu, menu_def[1], element) + if elementpad[0] == 0 or elementpad[1] == 0: + tkbutton.config(highlightthickness=0) + tkbutton.configure(menu=top_menu) + element.TKMenu = top_menu + if element.visible is False: + tkbutton.pack_forget() + if element.Disabled == True: + element.TKButton['state'] = 'disabled' + if element.Tooltip is not None: + element.TooltipObject = ToolTip(element.TKButton, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) + + # ------------------------- INPUT placement element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_TEXT: + element = element # type: InputText + default_text = element.DefaultText + element.TKStringVar = tk.StringVar() + element.TKStringVar.set(default_text) + show = element.PasswordCharacter if element.PasswordCharacter else "" + bd = border_depth + if element.Justification is not None: + justification = element.Justification + else: + justification = DEFAULT_TEXT_JUSTIFICATION + justify = tk.LEFT if justification.startswith('l') else tk.CENTER if justification.startswith('c') else tk.RIGHT + # anchor = tk.NW if justification == 'left' else tk.N if justification == 'center' else tk.NE + element.TKEntry = element.Widget = tk.Entry(tk_row_frame, width=element_size[0], + textvariable=element.TKStringVar, bd=bd, + font=font, show=show, justify=justify) + if element.ChangeSubmits: + element.TKEntry.bind('', element._KeyboardHandler) + element.TKEntry.bind('', element._ReturnKeyHandler) + if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + element.TKEntry.configure(background=element.BackgroundColor) + if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT: + element.TKEntry.configure(fg=text_color) + + if element.disabled_readonly_background_color is not None: + element.TKEntry.config(readonlybackground=element.disabled_readonly_background_color) + if element.disabled_readonly_text_color is not None: + element.TKEntry.config(fg=element.disabled_readonly_text_color) + + element.Widget.config(highlightthickness=0) + # element.pack_keywords = {'side':tk.LEFT, 'padx':elementpad[0], 'pady':elementpad[1], 'expand':False, 'fill':tk.NONE } + # element.TKEntry.pack(**element.pack_keywords) + expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction) + element.TKEntry.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill) + if element.visible is False: + element.TKEntry.pack_forget() + if element.Focus is True or (toplevel_form.UseDefaultFocus and not toplevel_form.FocusSet): + toplevel_form.FocusSet = True + element.TKEntry.focus_set() + if element.Disabled: + element.TKEntry['state'] = 'readonly' if element.UseReadonlyForDisable else 'disabled' + if element.ReadOnly: + element.TKEntry['state'] = 'readonly' + + if element.Tooltip is not None: + element.TooltipObject = ToolTip(element.TKEntry, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) + _add_right_click_menu_and_grab(element) + if theme_input_text_color() not in (COLOR_SYSTEM_DEFAULT, None): + element.Widget.config(insertbackground=theme_input_text_color()) + + # row_should_expand = True + + # ------------------------- COMBO placement element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_COMBO: + element = element # type: InputCombo + max_line_len = max([len(str(l)) for l in element.Values]) if len(element.Values) else 0 + if auto_size_text is False: + width = element_size[0] + else: + width = max_line_len + 1 + element.TKStringVar = tk.StringVar() + style_name = _make_ttk_style_name('.TCombobox', element) + # style_name = 'TCombobox' + s = ttk.Style() + if _valid_theme(s, toplevel_form.TtkTheme): + s.theme_use(toplevel_form.TtkTheme) + # s.theme_use('default') + + if element.TextColor is not None and element.TextColor != COLOR_SYSTEM_DEFAULT: + # Creates 1 style per Text Color/ Background Color combination + # style_name = str(element.Key) + '.TCombobox' + + combostyle = ttk.Style() + if _valid_theme(combostyle, toplevel_form.TtkTheme): + combostyle.theme_use(toplevel_form.TtkTheme) + + # Creates a unique name for each field element(Sure there is a better way to do this) + # unique_field = str(element.Key) + '.TCombobox.field' + unique_field = _make_ttk_style_name('.TCombobox.field', element) + + + # Clones over the TCombobox.field element from the "alt" theme. + # This is what will allow us to change the background color without altering the whole programs theme + + # try: # if this element is in a window that's shown TWICE, will get an error here, so skip error + # combostyle.element_create(unique_field, "from", "alt") + # except: + # pass + + # Create widget layout using cloned "alt" field + # combostyle.layout(style_name, [ + # (unique_field, {'children': [('Combobox.downarrow', {'side': 'right', 'sticky': 'ns'}), + # ('Combobox.padding', + # {'children': [('Combobox.focus', + # {'children': [('Combobox.textarea', + # {'sticky': 'nswe'})], + # 'expand': '1', + # 'sticky': 'nswe'})], + # 'expand': '1', + # 'sticky': 'nswe'})], + # 'sticky': 'nswe'})]) + + # Copy default TCombobox settings + # Getting an error on this line of code + # combostyle.configure(style_name, *combostyle.configure("TCombobox")) + + # Set individual widget options + combostyle.configure(style_name, foreground=element.TextColor) + combostyle.configure(style_name, selectbackground=element.BackgroundColor) + combostyle.map(style_name, fieldbackground=[('readonly', element.BackgroundColor)]) + combostyle.configure(style_name, fieldbackground=element.BackgroundColor) + combostyle.configure(style_name, selectforeground=element.TextColor) + combostyle.configure(style_name, insertcolor=element.TextColor) + + try: + combostyle.configure(style_name, arrowcolor=theme_button_color()[0]) + combostyle.configure(style_name, background=theme_button_color()[1]) + except Exception as e: + _error_popup_with_traceback('Combo Element error {}'.format(e), + 'Combo element key: {}'.format(element.Key), + 'The theme button color is used to make the arrows. theme_button_color= {}'.format(theme_button_color()), + "Parent Window's Title: {}".format(toplevel_form.Title)) + # print('* Problem setting combobox button color *', e) + + # Strange code that is needed to set the font for the drop-down list + element._newfont = tkinter.font.Font(font=font) + tk_row_frame.option_add("*TCombobox*Listbox*Font", element._newfont) + + element.TKCombo = element.Widget = ttk.Combobox(tk_row_frame, width=width, + textvariable=element.TKStringVar, font=font, + style=style_name) + + # Chr0nic + element.TKCombo.bind("", lambda event, em=element: testMouseHook2(em)) + element.TKCombo.bind("", lambda event, em=element: testMouseUnhook2(em)) + + if toplevel_form.UseDefaultFocus and not toplevel_form.FocusSet: + toplevel_form.FocusSet = True + element.TKCombo.focus_set() + + if element.Size[1] != 1 and element.Size[1] is not None: + element.TKCombo.configure(height=element.Size[1]) + element.TKCombo['values'] = element.Values + expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction) + element.TKCombo.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill) + if element.visible is False: + element.TKCombo.pack_forget() + if element.DefaultValue is not None: + element.TKCombo.set(element.DefaultValue) + # for i, v in enumerate(element.Values): + # if v == element.DefaultValue: + # element.TKCombo.current(i) + # break + # elif element.Values: + # element.TKCombo.current(0) + if element.ChangeSubmits: + element.TKCombo.bind('<>', element._ComboboxSelectHandler) + if element.BindReturnKey: + element.TKCombo.bind('', element._ComboboxSelectHandler) + if element.Readonly: + element.TKCombo['state'] = 'readonly' + if element.Disabled is True: # note overrides readonly if disabled + element.TKCombo['state'] = 'disabled' + if element.Tooltip is not None: + element.TooltipObject = ToolTip(element.TKCombo, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) + _add_right_click_menu_and_grab(element) + + # ------------------------- OPTIONMENU placement Element (Like ComboBox but different) element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_OPTION_MENU: + max_line_len = max([len(str(l)) for l in element.Values]) + if auto_size_text is False: + width = element_size[0] + else: + width = max_line_len + element.TKStringVar = tk.StringVar() + if element.DefaultValue: + element.TKStringVar.set(element.DefaultValue) + element.TKOptionMenu = element.Widget = tk.OptionMenu(tk_row_frame, element.TKStringVar, *element.Values) + element.TKOptionMenu.config(highlightthickness=0, font=font, width=width) + element.TKOptionMenu['menu'].config(font=font) + element.TKOptionMenu.config(borderwidth=border_depth) + if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + element.TKOptionMenu.configure(background=element.BackgroundColor) + element.TKOptionMenu['menu'].config(background=element.BackgroundColor) + if element.TextColor != COLOR_SYSTEM_DEFAULT and element.TextColor is not None: + element.TKOptionMenu.configure(fg=element.TextColor) + element.TKOptionMenu['menu'].config(fg=element.TextColor) + expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction) + element.TKOptionMenu.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill) + if element.visible is False: + element.TKOptionMenu.pack_forget() + if element.Disabled == True: + element.TKOptionMenu['state'] = 'disabled' + if element.Tooltip is not None: + element.TooltipObject = ToolTip(element.TKOptionMenu, text=element.Tooltip, + timeout=DEFAULT_TOOLTIP_TIME) + # ------------------------- LISTBOX placement element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_LISTBOX: + element = element # type: Listbox + max_line_len = max([len(str(l)) for l in element.Values]) if len(element.Values) else 0 + if auto_size_text is False: + width = element_size[0] + else: + width = max_line_len + element_frame = tk.Frame(tk_row_frame) + element.TKStringVar = tk.StringVar() + element.TKListbox = element.Widget = tk.Listbox(element_frame, height=element_size[1], width=width, + selectmode=element.SelectMode, font=font, exportselection=False) + element.Widget.config(highlightthickness=0) + for index, item in enumerate(element.Values): + element.TKListbox.insert(tk.END, item) + if element.DefaultValues is not None and item in element.DefaultValues: + element.TKListbox.selection_set(index) + if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + element.TKListbox.configure(background=element.BackgroundColor) + if element.HighlightBackgroundColor is not None and element.HighlightBackgroundColor != COLOR_SYSTEM_DEFAULT: + element.TKListbox.config(selectbackground=element.HighlightBackgroundColor) + if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT: + element.TKListbox.configure(fg=text_color) + if element.HighlightTextColor is not None and element.HighlightTextColor != COLOR_SYSTEM_DEFAULT: + element.TKListbox.config(selectforeground=element.HighlightTextColor) + if element.ChangeSubmits: + element.TKListbox.bind('<>', element._ListboxSelectHandler) + if not element.NoScrollbar: + # Vertical scrollbar + element.vsb = tk.Scrollbar(element_frame, orient="vertical", command=element.TKListbox.yview) + element.TKListbox.configure(yscrollcommand=element.vsb.set) + element.vsb.pack(side=tk.RIGHT, fill='y') + + # Horizontal scrollbar + if element.HorizontalScroll: + hscrollbar = tk.Scrollbar(element_frame, orient=tk.HORIZONTAL) + hscrollbar.pack(side=tk.BOTTOM, fill='x') + hscrollbar.config(command=element.Widget.xview) + element.Widget.configure(xscrollcommand=hscrollbar.set) + element.hsb = hscrollbar + + # Chr0nic + element.TKListbox.bind("", lambda event, em=element: testMouseHook(em)) + element.TKListbox.bind("", lambda event, em=element: testMouseUnhook(em)) + + + + + + expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction) + element_frame.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], fill=fill, expand=expand) + element.TKListbox.pack(side=tk.LEFT, fill=fill, expand=expand) + if element.visible is False: + element_frame.pack_forget() + element.vsb.pack_forget() + if element.BindReturnKey: + element.TKListbox.bind('', element._ListboxSelectHandler) + element.TKListbox.bind('', element._ListboxSelectHandler) + if element.Disabled is True: + element.TKListbox['state'] = 'disabled' + if element.Tooltip is not None: + element.TooltipObject = ToolTip(element.TKListbox, text=element.Tooltip, + timeout=DEFAULT_TOOLTIP_TIME) + element.element_frame = element_frame + _add_right_click_menu_and_grab(element) + # ------------------------- MULTILINE placement element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_MULTILINE: + element = element # type: Multiline + width, height = element_size + bd = element.BorderWidth + if element.no_scrollbar: + element.TKText = element.Widget = tk.Text(tk_row_frame, width=width, height=height, wrap='word', bd=bd, font=font, relief=RELIEF_SUNKEN) + else: + element.TKText = element.Widget = tk.scrolledtext.ScrolledText(tk_row_frame, width=width, height=height, wrap='word', bd=bd, font=font, + relief=RELIEF_SUNKEN) + if element.DefaultText: + element.TKText.insert(1.0, element.DefaultText) # set the default text + element.TKText.config(highlightthickness=0) + if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + element.TKText.configure(background=element.BackgroundColor) + + element.TKText.tag_configure("center", justify='center') + element.TKText.tag_configure("left", justify='left') + element.TKText.tag_configure("right", justify='right') + + if element.Justification.startswith('l'): + element.TKText.tag_add("left", 1.0, "end") + element.justification_tag = 'left' + elif element.Justification.startswith('r'): + element.TKText.tag_add("right", 1.0, "end") + element.justification_tag = 'right' + elif element.Justification.startswith('c'): + element.TKText.tag_add("center", 1.0, "end") + element.justification_tag = 'center' + # if DEFAULT_SCROLLBAR_COLOR not in (None, COLOR_SYSTEM_DEFAULT): # only works on Linux so not including it + # element.TKText.vbar.config(troughcolor=DEFAULT_SCROLLBAR_COLOR) + expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction) + + element.TKText.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], fill=fill, expand=expand) + + + if element.visible is False: + element.TKText.pack_forget() + else: + # Chr0nic + element.TKText.bind("", lambda event, em=element: testMouseHook(em)) + element.TKText.bind("", lambda event, em=element: testMouseUnhook(em)) + if element.ChangeSubmits: + element.TKText.bind('', element._KeyboardHandler) + if element.EnterSubmits: + element.TKText.bind('', element._ReturnKeyHandler) + if element.Focus is True or (toplevel_form.UseDefaultFocus and not toplevel_form.FocusSet): + toplevel_form.FocusSet = True + element.TKText.focus_set() + if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT: + element.TKText.configure(fg=text_color) + if element.Disabled is True: + element.TKText['state'] = 'disabled' + if element.Tooltip is not None: + element.TooltipObject = ToolTip(element.TKText, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) + + if element.reroute_cprint: + cprint_set_output_destination(toplevel_form, element.Key) + + _add_right_click_menu_and_grab(element) + if theme_input_text_color() not in (COLOR_SYSTEM_DEFAULT, None): + element.Widget.config(insertbackground=theme_input_text_color()) + + # row_should_expand = True + # ------------------------- CHECKBOX pleacement element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_CHECKBOX: + element = element # type: Checkbox + width = 0 if auto_size_text else element_size[0] + default_value = element.InitialState + element.TKIntVar = tk.IntVar() + element.TKIntVar.set(default_value if default_value is not None else 0) + if element.ChangeSubmits: + element.TKCheckbutton = element.Widget = tk.Checkbutton(tk_row_frame, anchor=tk.NW, + text=element.Text, width=width, + variable=element.TKIntVar, bd=border_depth, + font=font, + command=element._CheckboxHandler) + else: + element.TKCheckbutton = element.Widget = tk.Checkbutton(tk_row_frame, anchor=tk.NW, + text=element.Text, width=width, + variable=element.TKIntVar, bd=border_depth, + font=font) + if element.Disabled: + element.TKCheckbutton.configure(state='disable') + if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + element.TKCheckbutton.configure(background=element.BackgroundColor) + element.TKCheckbutton.configure(selectcolor=element.CheckboxBackgroundColor) # The background of the checkbox + element.TKCheckbutton.configure(activebackground=element.BackgroundColor) + if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT: + element.TKCheckbutton.configure(fg=text_color) + + element.Widget.configure(highlightthickness=1) + if element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + element.TKCheckbutton.config(highlightbackground=element.BackgroundColor) + if element.TextColor != COLOR_SYSTEM_DEFAULT: + element.TKCheckbutton.config(highlightcolor=element.TextColor) + expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction) + element.TKCheckbutton.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill) + if element.visible is False: + element.TKCheckbutton.pack_forget() + if element.Tooltip is not None: + element.TooltipObject = ToolTip(element.TKCheckbutton, text=element.Tooltip, + timeout=DEFAULT_TOOLTIP_TIME) + _add_right_click_menu_and_grab(element) + + # ------------------------- PROGRESS placement element ------------------------- # + elif element_type == ELEM_TYPE_PROGRESS_BAR: + element = element # type: ProgressBar + if element.size_px != (None, None): + progress_length, progress_width = element.size_px + else: + width = element_size[0] + fnt = tkinter.font.Font() + char_width = fnt.measure('A') # single character width + progress_length = width * char_width + progress_width = element_size[1] + direction = element.Orientation + if element.BarColor != (None, None): # if element has a bar color, use it + bar_color = element.BarColor + else: + bar_color = DEFAULT_PROGRESS_BAR_COLOR + if element.Orientation.lower().startswith('h'): + base_style_name = ".Horizontal.TProgressbar" + else: + base_style_name = ".Vertical.TProgressbar" + style_name = _make_ttk_style_name(base_style_name, element) + element.TKProgressBar = TKProgressBar(tk_row_frame, element.MaxValue, progress_length, progress_width, + orientation=direction, BarColor=bar_color, + border_width=element.BorderWidth, relief=element.Relief, + ttk_theme=toplevel_form.TtkTheme, key=element.Key, style_name=style_name) + expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction) + element.TKProgressBar.TKProgressBarForReal.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill) + if element.visible is False: + element.TKProgressBar.TKProgressBarForReal.pack_forget() + element.Widget = element.TKProgressBar.TKProgressBarForReal + _add_right_click_menu_and_grab(element) + + # ------------------------- RADIO placement element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_RADIO: + element = element # type: Radio + width = 0 if auto_size_text else element_size[0] + default_value = element.InitialState + ID = element.GroupID + # see if ID has already been placed + value = EncodeRadioRowCol(form.ContainerElemementNumber, row_num, + col_num) # value to set intvar to if this radio is selected + element.EncodedRadioValue = value + if ID in toplevel_form.RadioDict: + RadVar = toplevel_form.RadioDict[ID] + else: + RadVar = tk.IntVar() + toplevel_form.RadioDict[ID] = RadVar + element.TKIntVar = RadVar # store the RadVar in Radio object + if default_value: # if this radio is the one selected, set RadVar to match + element.TKIntVar.set(value) + if element.ChangeSubmits: + element.TKRadio = element.Widget = tk.Radiobutton(tk_row_frame, anchor=tk.NW, text=element.Text, + width=width, + variable=element.TKIntVar, value=value, + bd=border_depth, font=font, + command=element._RadioHandler) + else: + element.TKRadio = element.Widget = tk.Radiobutton(tk_row_frame, anchor=tk.NW, text=element.Text, + width=width, + variable=element.TKIntVar, value=value, + bd=border_depth, font=font) + if not element.BackgroundColor in (None, COLOR_SYSTEM_DEFAULT): + element.TKRadio.configure(background=element.BackgroundColor) + element.TKRadio.configure(selectcolor=element.CircleBackgroundColor) + element.TKRadio.configure(activebackground=element.BackgroundColor) + if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT: + element.TKRadio.configure(fg=text_color) + + element.Widget.configure(highlightthickness=1) + if element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + element.TKRadio.config(highlightbackground=element.BackgroundColor) + if element.TextColor != COLOR_SYSTEM_DEFAULT: + element.TKRadio.config(highlightcolor=element.TextColor) + + if element.Disabled: + element.TKRadio['state'] = 'disabled' + expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction) + element.TKRadio.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill) + if element.visible is False: + element.TKRadio.pack_forget() + if element.Tooltip is not None: + element.TooltipObject = ToolTip(element.TKRadio, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) + _add_right_click_menu_and_grab(element) + + # ------------------------- SPIN placement element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_SPIN: + element = element # type: Spin + width, height = element_size + width = 0 if auto_size_text else element_size[0] + element.TKStringVar = tk.StringVar() + element.TKSpinBox = element.Widget = tk.Spinbox(tk_row_frame, values=element.Values, + textvariable=element.TKStringVar, + width=width, bd=border_depth) + if element.DefaultValue is not None: + element.TKStringVar.set(element.DefaultValue) + element.TKSpinBox.configure(font=font) # set wrap to width of widget + if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + element.TKSpinBox.configure(background=element.BackgroundColor) + element.TKSpinBox.configure(buttonbackground=element.BackgroundColor) + element.Widget.config(highlightthickness=0) + expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction) + element.TKSpinBox.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill) + if element.visible is False: + element.TKSpinBox.pack_forget() + if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT: + element.TKSpinBox.configure(fg=text_color) + if element.ChangeSubmits: + element.TKSpinBox.bind('', element._SpinChangedHandler) + element.TKSpinBox.bind('', element._SpinChangedHandler) + element.TKSpinBox.bind('', element._SpinChangedHandler) + if element.Readonly: + element.TKSpinBox['state'] = 'readonly' + if element.Disabled is True: # note overrides readonly if disabled + element.TKSpinBox['state'] = 'disabled' + if element.Tooltip is not None: + element.TooltipObject = ToolTip(element.TKSpinBox, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) + if theme_input_text_color() not in (COLOR_SYSTEM_DEFAULT, None): + element.Widget.config(insertbackground=theme_input_text_color()) + _add_right_click_menu_and_grab(element) + + # ------------------------- OUTPUT placement element ------------------------- # + elif element_type == ELEM_TYPE_OUTPUT: + element = element # type: Output + width, height = element_size + element._TKOut = element.Widget = TKOutput(tk_row_frame, width=width, height=height, bd=border_depth, + background_color=element.BackgroundColor, + text_color=text_color, font=font, + pad=elementpad, echo_stdout_stderr=element.echo_stdout_stderr) + element._TKOut.output.configure(takefocus=0) # make it so that Output does not get focus + expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction) + element._TKOut.pack(side=tk.LEFT, expand=expand, fill=fill) + if element.visible is False: + element._TKOut.frame.pack_forget() + if element.Tooltip is not None: + element.TooltipObject = ToolTip(element._TKOut, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) + _add_right_click_menu_and_grab(element) + # row_should_expand = True + # ------------------------- IMAGE placement element ------------------------- # + elif element_type == ELEM_TYPE_IMAGE: + element = element # type: Image + try: + if element.Filename is not None: + photo = tk.PhotoImage(file=element.Filename) + elif element.Data is not None: + photo = tk.PhotoImage(data=element.Data) + else: + photo = None + + if element.ImageSubsample and photo is not None: + photo = photo.subsample(element.ImageSubsample) + # print('*ERROR laying out form.... Image Element has no image specified*') + except Exception as e: + photo = None + _error_popup_with_traceback('Your Window has an Image Element with a problem', + 'The traceback will show you the Window with the problem layout', + 'Look in this Window\'s layout for an Image element that has a key of {}'.format(element.Key), + 'The error occuring is:', e) + + if photo is not None: + if element_size == (None, None) or element_size is None or element_size == toplevel_form.DefaultElementSize: + width, height = photo.width(), photo.height() + else: + width, height = element_size + element.tktext_label = tk.Label(tk_row_frame, image=photo, width=width, height=height, bd=0) + else: + element.tktext_label = tk.Label(tk_row_frame, bd=0) + + if not element.BackgroundColor in (None, COLOR_SYSTEM_DEFAULT): + element.tktext_label.config(background=element.BackgroundColor) + + element.tktext_label.image = photo + # tktext_label.configure(anchor=tk.NW, image=photo) + expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction) + element.tktext_label.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill) + + if element.visible is False: + element.tktext_label.pack_forget() + if element.Tooltip is not None: + element.TooltipObject = ToolTip(element.tktext_label, text=element.Tooltip, + timeout=DEFAULT_TOOLTIP_TIME) + if element.EnableEvents and element.tktext_label is not None: + element.tktext_label.bind('', element._ClickHandler) + element.Widget = element.tktext_label + + _add_right_click_menu_and_grab(element) + + # ------------------------- Canvas placement element ------------------------- # + elif element_type == ELEM_TYPE_CANVAS: + element = element # type: Canvas + width, height = element_size + if element._TKCanvas is None: + element._TKCanvas = tk.Canvas(tk_row_frame, width=width, height=height, bd=border_depth) + else: + element._TKCanvas.master = tk_row_frame + if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + element._TKCanvas.configure(background=element.BackgroundColor, highlightthickness=0) + expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction) + element._TKCanvas.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill) + if element.visible is False: + element._TKCanvas.pack_forget() + if element.Tooltip is not None: + element.TooltipObject = ToolTip(element._TKCanvas, text=element.Tooltip, + timeout=DEFAULT_TOOLTIP_TIME) + element.Widget = element._TKCanvas + _add_right_click_menu_and_grab(element) + + # ------------------------- Graph placement element ------------------------- # + elif element_type == ELEM_TYPE_GRAPH: + element = element # type: Graph + width, height = element_size + # I don't know why TWO canvases were being defined, on inside the other. Was it so entire canvas can move? + # if element._TKCanvas is None: + # element._TKCanvas = tk.Canvas(tk_row_frame, width=width, height=height, bd=border_depth) + # else: + # element._TKCanvas.master = tk_row_frame + element._TKCanvas2 = element.Widget = tk.Canvas(tk_row_frame, width=width, height=height, + bd=border_depth) + expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction) + element._TKCanvas2.pack(side=tk.LEFT, expand=expand, fill=fill) + element._TKCanvas2.addtag_all('mytag') + if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + element._TKCanvas2.configure(background=element.BackgroundColor, highlightthickness=0) + # element._TKCanvas.configure(background=element.BackgroundColor, highlightthickness=0) + element._TKCanvas2.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill) + if element.visible is False: + # element._TKCanvas.pack_forget() + element._TKCanvas2.pack_forget() + if element.Tooltip is not None: + element.TooltipObject = ToolTip(element._TKCanvas2, text=element.Tooltip, + timeout=DEFAULT_TOOLTIP_TIME) + if element.ChangeSubmits: + element._TKCanvas2.bind('', element.ButtonReleaseCallBack) + element._TKCanvas2.bind('', element.ButtonPressCallBack) + if element.DragSubmits: + element._TKCanvas2.bind('', element.MotionCallBack) + _add_right_click_menu_and_grab(element) + # ------------------------- MENU placement element ------------------------- # + elif element_type == ELEM_TYPE_MENUBAR: + element = element # type: MenuBar + menu_def = element.MenuDefinition + element.TKMenu = element.Widget = tk.Menu(toplevel_form.TKroot, tearoff=element.Tearoff, + tearoffcommand=element._tearoff_menu_callback) # create the menubar + menubar = element.TKMenu + if font is not None: # if a font is used, make sure it's saved in the element + element.Font = font + for menu_entry in menu_def: + baritem = tk.Menu(menubar, tearoff=element.Tearoff, tearoffcommand=element._tearoff_menu_callback) + if element.BackgroundColor not in (COLOR_SYSTEM_DEFAULT, None): + baritem.config(bg=element.BackgroundColor) + if element.TextColor not in (COLOR_SYSTEM_DEFAULT, None): + baritem.config(fg=element.TextColor) + if element.DisabledTextColor not in (COLOR_SYSTEM_DEFAULT, None): + baritem.config(disabledforeground=element.DisabledTextColor) + if font is not None: + baritem.config(font=font) + pos = menu_entry[0].find(MENU_SHORTCUT_CHARACTER) + # print(pos) + if pos != -1: + if pos == 0 or menu_entry[0][pos - len(MENU_SHORTCUT_CHARACTER)] != "\\": + menu_entry[0] = menu_entry[0][:pos] + menu_entry[0][pos + 1:] + if menu_entry[0][0] == MENU_DISABLED_CHARACTER: + menubar.add_cascade(label=menu_entry[0][len(MENU_DISABLED_CHARACTER):], menu=baritem, + underline=pos - 1) + menubar.entryconfig(menu_entry[0][len(MENU_DISABLED_CHARACTER):], state='disabled') + else: + menubar.add_cascade(label=menu_entry[0], menu=baritem, underline=pos) + + if len(menu_entry) > 1: + AddMenuItem(baritem, menu_entry[1], element) + toplevel_form.TKroot.configure(menu=element.TKMenu) + # ------------------------- Frame placement element ------------------------- # + elif element_type == ELEM_TYPE_FRAME: + element = element # type: Frame + labeled_frame = element.Widget = tk.LabelFrame(tk_row_frame, text=element.Title, relief=element.Relief) + element.TKFrame = labeled_frame + PackFormIntoFrame(element, labeled_frame, toplevel_form) + expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction) + if element.VerticalAlignment is not None: + anchor = tk.CENTER # Default to center if a bad choice is made + if element.VerticalAlignment.lower().startswith('t'): + anchor = tk.N + if element.VerticalAlignment.lower().startswith('c'): + anchor = tk.CENTER + if element.VerticalAlignment.lower().startswith('b'): + anchor = tk.S + labeled_frame.pack(side=tk.LEFT, anchor=anchor, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill) + else: + labeled_frame.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill) + + if element.Size != (None, None): + labeled_frame.config(width=element.Size[0], height=element.Size[1]) + labeled_frame.pack_propagate(0) + if not element.visible: + labeled_frame.pack_forget() + if element.BackgroundColor != COLOR_SYSTEM_DEFAULT and element.BackgroundColor is not None: + labeled_frame.configure(background=element.BackgroundColor, + highlightbackground=element.BackgroundColor, + highlightcolor=element.BackgroundColor) + if element.TextColor != COLOR_SYSTEM_DEFAULT and element.TextColor is not None: + labeled_frame.configure(foreground=element.TextColor) + if font is not None: + labeled_frame.configure(font=font) + if element.TitleLocation is not None: + labeled_frame.configure(labelanchor=element.TitleLocation) + if element.BorderWidth is not None: + labeled_frame.configure(borderwidth=element.BorderWidth) + if element.Tooltip is not None: + element.TooltipObject = ToolTip(labeled_frame, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) + _add_right_click_menu_and_grab(element) + # row_should_expand=True + # ------------------------- Tab placement element ------------------------- # + elif element_type == ELEM_TYPE_TAB: + element = element # type: Tab + element.TKFrame = element.Widget = tk.Frame(form.TKNotebook) + PackFormIntoFrame(element, element.TKFrame, toplevel_form) + state = 'normal' + if element.Disabled: + state = 'disabled' + if element.visible is False: + state = 'hidden' + # this code will add an image to the tab. Use it when adding the image on a tab enhancement + try: + if element.Filename is not None: + photo = tk.PhotoImage(file=element.Filename) + elif element.Data is not None: + photo = tk.PhotoImage(data=element.Data) + else: + photo = None + + if element.ImageSubsample and photo is not None: + photo = photo.subsample(element.ImageSubsample) + # print('*ERROR laying out form.... Image Element has no image specified*') + except Exception as e: + photo = None + _error_popup_with_traceback('Your Window has an Tab Element with an IMAGE problem', + 'The traceback will show you the Window with the problem layout', + 'Look in this Window\'s layout for an Image element that has a key of {}'.format(element.Key), + 'The error occuring is:', e) + + element.photo = photo + if photo is not None: + if element_size == (None, None) or element_size is None or element_size == toplevel_form.DefaultElementSize: + width, height = photo.width(), photo.height() + else: + width, height = element_size + element.tktext_label = tk.Label(tk_row_frame, image=photo, width=width, height=height, bd=0) + else: + element.tktext_label = tk.Label(tk_row_frame, bd=0) + if photo is not None: + form.TKNotebook.add(element.TKFrame, text=element.Title, compound=tk.LEFT, state=state,image=photo) + + # element.photo_image = tk.PhotoImage(data=DEFAULT_BASE64_ICON) + # form.TKNotebook.add(element.TKFrame, text=element.Title, compound=tk.LEFT, state=state,image = element.photo_image) + form.TKNotebook.add(element.TKFrame, text=element.Title, state=state) + expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction) + form.TKNotebook.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], fill=fill, expand=expand) + + element.ParentNotebook = form.TKNotebook + element.TabID = form.TabCount + form.TabCount += 1 + if element.BackgroundColor != COLOR_SYSTEM_DEFAULT and element.BackgroundColor is not None: + element.TKFrame.configure(background=element.BackgroundColor, + highlightbackground=element.BackgroundColor, + highlightcolor=element.BackgroundColor) + + # if element.BorderWidth is not None: + # element.TKFrame.configure(borderwidth=element.BorderWidth) + if element.Tooltip is not None: + element.TooltipObject = ToolTip(element.TKFrame, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) + _add_right_click_menu_and_grab(element) + # row_should_expand = True + # ------------------------- TabGroup placement element ------------------------- # + elif element_type == ELEM_TYPE_TAB_GROUP: + element = element # type: TabGroup + # custom_style = str(element.Key) + 'customtab.TNotebook' + custom_style = _make_ttk_style_name('.customtab.TNotebook', element) + style = ttk.Style() + style.theme_use(toplevel_form.TtkTheme) + if element.TabLocation is not None: + position_dict = {'left': 'w', 'right': 'e', 'top': 'n', 'bottom': 's', 'lefttop': 'wn', + 'leftbottom': 'ws', 'righttop': 'en', 'rightbottom': 'es', 'bottomleft': 'sw', + 'bottomright': 'se', 'topleft': 'nw', 'topright': 'ne'} + try: + tab_position = position_dict[element.TabLocation] + except: + tab_position = position_dict['top'] + style.configure(custom_style, tabposition=tab_position) + + if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + style.configure(custom_style, background=element.BackgroundColor) + + # FINALLY the proper styling to get tab colors! + if element.SelectedTitleColor is not None and element.SelectedTitleColor != COLOR_SYSTEM_DEFAULT: + style.map(custom_style + '.Tab', foreground=[("selected", element.SelectedTitleColor)]) + if element.SelectedBackgroundColor is not None and element.SelectedBackgroundColor != COLOR_SYSTEM_DEFAULT: + style.map(custom_style + '.Tab', background=[("selected", element.SelectedBackgroundColor)]) + if element.TabBackgroundColor is not None and element.TabBackgroundColor != COLOR_SYSTEM_DEFAULT: + style.configure(custom_style + '.Tab', background=element.TabBackgroundColor) + if element.TextColor is not None and element.TextColor != COLOR_SYSTEM_DEFAULT: + style.configure(custom_style + '.Tab', foreground=element.TextColor) + if element.BorderWidth is not None: + style.configure(custom_style, borderwidth=element.BorderWidth) + if element.TabBorderWidth is not None: + style.configure(custom_style + '.Tab', borderwidth=element.TabBorderWidth) # if ever want to get rid of border around the TABS themselves + if element.FocusColor is not None: + style.configure(custom_style + '.Tab', focuscolor=element.FocusColor) + + style.configure(custom_style + '.Tab', font=font) + element.Style = style + element.StyleName = custom_style + element.TKNotebook = element.Widget = ttk.Notebook(tk_row_frame, style=custom_style) + + PackFormIntoFrame(element, toplevel_form.TKroot, toplevel_form) + + expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction) + element.TKNotebook.pack(anchor=tk.SW, side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], fill=fill, expand=expand) + + if element.ChangeSubmits: + element.TKNotebook.bind('<>', element._TabGroupSelectHandler) + if element.Tooltip is not None: + element.TooltipObject = ToolTip(element.TKNotebook, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) + if element.Size != (None, None): + element.TKNotebook.configure(width=element.Size[0], height=element.Size[1]) + _add_right_click_menu_and_grab(element) + + # row_should_expand = True + # ------------------- SLIDER placement element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_SLIDER: + element = element # type: Slider + slider_length = element_size[0] * _char_width_in_pixels(font) + slider_width = element_size[1] + element.TKIntVar = tk.IntVar() + element.TKIntVar.set(element.DefaultValue) + if element.Orientation.startswith('v'): + range_from = element.Range[1] + range_to = element.Range[0] + slider_length += DEFAULT_MARGINS[1] * (element_size[0] * 2) # add in the padding + else: + range_from = element.Range[0] + range_to = element.Range[1] + if element.ChangeSubmits: + tkscale = element.Widget = tk.Scale(tk_row_frame, orient=element.Orientation, + variable=element.TKIntVar, + from_=range_from, to_=range_to, resolution=element.Resolution, + length=slider_length, width=slider_width, + bd=element.BorderWidth, + relief=element.Relief, font=font, + tickinterval=element.TickInterval, + command=element._SliderChangedHandler) + else: + tkscale = element.Widget = tk.Scale(tk_row_frame, orient=element.Orientation, + variable=element.TKIntVar, + from_=range_from, to_=range_to, resolution=element.Resolution, + length=slider_length, width=slider_width, + bd=element.BorderWidth, + relief=element.Relief, font=font, + tickinterval=element.TickInterval) + tkscale.config(highlightthickness=0) + if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + tkscale.configure(background=element.BackgroundColor) + if element.TroughColor != COLOR_SYSTEM_DEFAULT: + tkscale.config(troughcolor=element.TroughColor) + if element.DisableNumericDisplay: + tkscale.config(showvalue=0) + if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT: + tkscale.configure(fg=text_color) + expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction) + tkscale.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill) + if element.visible is False: + tkscale.pack_forget() + element.TKScale = tkscale + if element.Disabled == True: + element.TKScale['state'] = 'disabled' + if element.Tooltip is not None: + element.TooltipObject = ToolTip(element.TKScale, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) + _add_right_click_menu_and_grab(element) + + # ------------------------- TABLE placement element ------------------------- # + elif element_type == ELEM_TYPE_TABLE: + element = element # type: Table + element.element_frame = frame = tk.Frame(tk_row_frame) + element.table_frame = frame + height = element.NumRows + if element.Justification.startswith('l'): + anchor = tk.W + elif element.Justification.startswith('r'): + anchor = tk.E + else: + anchor = tk.CENTER + column_widths = {} + # create column width list + for row in element.Values: + for i, col in enumerate(row): + col_width = min(len(str(col)), element.MaxColumnWidth) + try: + if col_width > column_widths[i]: + column_widths[i] = col_width + except: + column_widths[i] = col_width + + if element.ColumnsToDisplay is None: + displaycolumns = element.ColumnHeadings if element.ColumnHeadings is not None else element.Values[0] + else: + displaycolumns = [] + for i, should_display in enumerate(element.ColumnsToDisplay): + if should_display: + if element.ColumnHeadings is not None: + displaycolumns.append(element.ColumnHeadings[i]) + else: + displaycolumns.append(str(i)) + + column_headings = element.ColumnHeadings if element.ColumnHeadings is not None else displaycolumns + if element.DisplayRowNumbers: # if display row number, tack on the numbers to front of columns + displaycolumns = [element.RowHeaderText, ] + displaycolumns + if column_headings is not None: + column_headings = [element.RowHeaderText, ] + element.ColumnHeadings + else: + column_headings = [element.RowHeaderText, ] + displaycolumns + element.TKTreeview = element.Widget = ttk.Treeview(frame, columns=column_headings, + displaycolumns=displaycolumns, show='headings', + height=height, + selectmode=element.SelectMode, ) + treeview = element.TKTreeview + if element.DisplayRowNumbers: + treeview.heading(element.RowHeaderText, text=element.RowHeaderText) # make a dummy heading + treeview.column(element.RowHeaderText, width=_string_width_in_pixels(font, element.RowHeaderText) + 10, minwidth=10, anchor=anchor, + stretch=0) + + headings = element.ColumnHeadings if element.ColumnHeadings is not None else element.Values[0] + for i, heading in enumerate(headings): + treeview.heading(heading, text=heading) + if element.AutoSizeColumns: + width = max(column_widths[i], len(heading)) * _char_width_in_pixels(font) + else: + try: + width = element.ColumnWidths[i] * _char_width_in_pixels(font) + except: + width = element.DefaultColumnWidth * _char_width_in_pixels(font) + treeview.column(heading, width=width, minwidth=10, anchor=anchor, stretch=element.expand_x) + # Insert values into the tree + for i, value in enumerate(element.Values): + if element.DisplayRowNumbers: + value = [i + element.StartingRowNumber] + value + id = treeview.insert('', 'end', text=value, iid=i + 1, values=value, tag=i) + element.tree_ids.append(id) + if element.AlternatingRowColor is not None: # alternating colors + for row in range(0, len(element.Values), 2): + treeview.tag_configure(row, background=element.AlternatingRowColor) + if element.RowColors is not None: # individual row colors + for row_def in element.RowColors: + if len(row_def) == 2: # only background is specified + treeview.tag_configure(row_def[0], background=row_def[1]) + else: + treeview.tag_configure(row_def[0], background=row_def[2], foreground=row_def[1]) + # ------ Do Styling of Colors ----- + # style_name = str(element.Key) + 'customtable.Treeview' + style_name = _make_ttk_style_name( '.customtable.Treeview', element) + + table_style = ttk.Style() + + table_style.theme_use(toplevel_form.TtkTheme) + if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + table_style.configure(style_name, background=element.BackgroundColor, fieldbackground=element.BackgroundColor, ) + if element.SelectedRowColors[1] is not None: + table_style.map(style_name, background=_fixed_map(table_style, style_name, 'background', element.SelectedRowColors)) + if element.TextColor is not None and element.TextColor != COLOR_SYSTEM_DEFAULT: + table_style.configure(style_name, foreground=element.TextColor) + if element.SelectedRowColors[0] is not None: + table_style.map(style_name, foreground=_fixed_map(table_style, style_name, 'foreground', element.SelectedRowColors)) + if element.RowHeight is not None: + table_style.configure(style_name, rowheight=element.RowHeight) + else: + table_style.configure(style_name, rowheight=_char_height_in_pixels(font)) + if element.HeaderTextColor is not None and element.HeaderTextColor != COLOR_SYSTEM_DEFAULT: + table_style.configure(style_name + '.Heading', foreground=element.HeaderTextColor) + if element.HeaderBackgroundColor is not None and element.HeaderBackgroundColor != COLOR_SYSTEM_DEFAULT: + table_style.configure(style_name + '.Heading', background=element.HeaderBackgroundColor) + if element.HeaderFont is not None: + table_style.configure(style_name + '.Heading', font=element.HeaderFont) + else: + table_style.configure(style_name + '.Heading', font=font) + table_style.configure(style_name, font=font) + treeview.configure(style=style_name) + # scrollable_frame.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=True, fill='both') + if element.enable_click_events is True: + treeview.bind('', element._table_clicked) + treeview.bind("<>", element._treeview_selected) + if element.BindReturnKey: + treeview.bind('', element._treeview_double_click) + treeview.bind('', element._treeview_double_click) + + if not element.HideVerticalScroll: + scrollbar = tk.Scrollbar(frame) + scrollbar.pack(side=tk.RIGHT, fill='y') + scrollbar.config(command=treeview.yview) + treeview.configure(yscrollcommand=scrollbar.set) + + if not element.VerticalScrollOnly: + hscrollbar = tk.Scrollbar(frame, orient=tk.HORIZONTAL) + hscrollbar.pack(side=tk.BOTTOM, fill='x') + hscrollbar.config(command=treeview.xview) + treeview.configure(xscrollcommand=hscrollbar.set) + + expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction) + element.TKTreeview.pack(side=tk.LEFT, padx=0, pady=0, expand=expand, fill=fill) + if element.visible is False: + element.TKTreeview.pack_forget() + frame.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill) + if element.Tooltip is not None: + element.TooltipObject = ToolTip(element.TKTreeview, text=element.Tooltip, + timeout=DEFAULT_TOOLTIP_TIME) + _add_right_click_menu_and_grab(element) + + if tclversion_detailed == '8.6.9' and ENABLE_TREEVIEW_869_PATCH: + # print('*** tk version 8.6.9 detected.... patching ttk treeview code ***') + table_style.map(style_name, + foreground=_fixed_map(table_style, style_name, 'foreground', element.SelectedRowColors), + background=_fixed_map(table_style, style_name, 'background', element.SelectedRowColors)) + # ------------------------- Tree placement element ------------------------- # + elif element_type == ELEM_TYPE_TREE: + element = element # type: Tree + element.element_frame = element_frame = tk.Frame(tk_row_frame) + + height = element.NumRows + if element.Justification.startswith('l'): # justification + anchor = tk.W + elif element.Justification.startswith('r'): + anchor = tk.E + else: + anchor = tk.CENTER + + if element.ColumnsToDisplay is None: # Which cols to display + displaycolumns = element.ColumnHeadings + else: + displaycolumns = [] + for i, should_display in enumerate(element.ColumnsToDisplay): + if should_display: + displaycolumns.append(element.ColumnHeadings[i]) + column_headings = element.ColumnHeadings + # ------------- GET THE TREEVIEW WIDGET ------------- + element.TKTreeview = element.Widget = ttk.Treeview(element_frame, columns=column_headings, + displaycolumns=displaycolumns, show='tree headings', + height=height, + selectmode=element.SelectMode) + treeview = element.TKTreeview + for i, heading in enumerate(element.ColumnHeadings): # Configure cols + headings + treeview.heading(heading, text=heading) + if element.AutoSizeColumns: + width = min(element.MaxColumnWidth, len(heading) + 1) + else: + try: + width = element.ColumnWidths[i] + except: + width = element.DefaultColumnWidth + treeview.column(heading, width=width * _char_width_in_pixels(font) + 10, anchor=anchor) + + def add_treeview_data(node): + """ + + :param node: + :type node: + + """ + if node.key != '': + if node.icon: + if node.icon not in element.image_dict: + if type(node.icon) is bytes: + photo = tk.PhotoImage(data=node.icon) + else: + photo = tk.PhotoImage(file=node.icon) + element.image_dict[node.icon] = photo + else: + photo = element.image_dict.get(node.icon) + + node.photo = photo + try: + id = treeview.insert(element.KeyToID[node.parent], 'end', iid=None, text=node.text, values=node.values, + open=element.ShowExpanded, image=node.photo) + element.IdToKey[id] = node.key + element.KeyToID[node.key] = id + except Exception as e: + print('Error inserting image into tree', e) + else: + id = treeview.insert(element.KeyToID[node.parent], 'end', iid=None, text=node.text, values=node.values, + open=element.ShowExpanded) + element.IdToKey[id] = node.key + element.KeyToID[node.key] = id + + for node in node.children: + add_treeview_data(node) + + add_treeview_data(element.TreeData.root_node) + treeview.column('#0', width=element.Col0Width * _char_width_in_pixels(font), anchor=anchor) + # ----- configure colors ----- + # style_name = str(element.Key) + '.Treeview' + style_name = _make_ttk_style_name('.Treeview', element) + tree_style = ttk.Style() + tree_style.theme_use(toplevel_form.TtkTheme) + if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + tree_style.configure(style_name, background=element.BackgroundColor, fieldbackground=element.BackgroundColor) + if element.SelectedRowColors[1] is not None: + tree_style.map(style_name, background=_fixed_map(tree_style, style_name, 'background', element.SelectedRowColors)) + if element.TextColor is not None and element.TextColor != COLOR_SYSTEM_DEFAULT: + tree_style.configure(style_name, foreground=element.TextColor) + if element.SelectedRowColors[0] is not None: + tree_style.map(style_name, foreground=_fixed_map(tree_style, style_name, 'foreground', element.SelectedRowColors)) + if element.HeaderTextColor is not None and element.HeaderTextColor != COLOR_SYSTEM_DEFAULT: + tree_style.configure(style_name + '.Heading', foreground=element.HeaderTextColor) + if element.HeaderBackgroundColor is not None and element.HeaderBackgroundColor != COLOR_SYSTEM_DEFAULT: + tree_style.configure(style_name + '.Heading', background=element.HeaderBackgroundColor) + if element.HeaderFont is not None: + tree_style.configure(style_name + '.Heading', font=element.HeaderFont) + else: + tree_style.configure(style_name + '.Heading', font=font) + tree_style.configure(style_name, font=font) + if element.RowHeight: + tree_style.configure(style_name, rowheight=element.RowHeight) + treeview.configure(style=style_name) # IMPORTANT! Be sure and set the style name for this widget + element.scrollbar = scrollbar = tk.Scrollbar(element_frame) + scrollbar.pack(side=tk.RIGHT, fill='y') + scrollbar.config(command=treeview.yview) + treeview.configure(yscrollcommand=scrollbar.set) + expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction) + element.TKTreeview.pack(side=tk.LEFT, padx=0, pady=0, expand=expand, fill=fill) + if element.visible is False: + element.TKTreeview.pack_forget() + element_frame.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill) + treeview.bind("<>", element._treeview_selected) + if element.Tooltip is not None: # tooltip + element.TooltipObject = ToolTip(element.TKTreeview, text=element.Tooltip, + timeout=DEFAULT_TOOLTIP_TIME) + _add_right_click_menu_and_grab(element) + + if tclversion_detailed == '8.6.9' and ENABLE_TREEVIEW_869_PATCH: + # print('*** tk version 8.6.9 detected.... patching ttk treeview code ***') + tree_style.map(style_name, + foreground=_fixed_map(tree_style, style_name, 'foreground', element.SelectedRowColors), + background=_fixed_map(tree_style, style_name, 'background', element.SelectedRowColors)) + + # ------------------------- Separator placement element ------------------------- # + elif element_type == ELEM_TYPE_SEPARATOR: + element = element # type: VerticalSeparator + # style_name = str(element.Key) + "Line.TSeparator" + style_name = _make_ttk_style_name(".Line.TSeparator", element) + style = ttk.Style() + style.theme_use(toplevel_form.TtkTheme) + if element.color is not None: + style.configure(style_name, background=element.color) + separator = element.Widget = ttk.Separator(tk_row_frame, orient=element.Orientation, ) + + expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction) + + if element.Orientation.startswith('h'): + separator.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], fill=tk.X, expand=True) + else: + separator.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], fill=tk.Y, expand=False) + element.Widget.configure(style=style_name) # IMPORTANT! Apply the style + # ------------------------- SizeGrip placement element ------------------------- # + elif element_type == ELEM_TYPE_SIZEGRIP: + element = element # type: Sizegrip + style_name = "Sizegrip.TSizegrip" + style = ttk.Style() + style.theme_use(toplevel_form.TtkTheme) + size_grip = element.Widget = ttk.Sizegrip(tk_row_frame) + toplevel_form.sizegrip_widget = size_grip + # if no size is specified, then use the background color for the window + if element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + style.configure(style_name, background=element.BackgroundColor) + else: + style.configure(style_name, background=toplevel_form.TKroot['bg']) + size_grip.configure(style=style_name) + + size_grip.pack(side=tk.BOTTOM, anchor='se', padx=0, pady=0, fill=tk.X, expand=True) + # tricky part of sizegrip... it shouldn't cause the row to expand, but should expand and should add X axis if + # not already filling in that direction. Otherwise, leaves things alone! + # row_should_expand = True + row_fill_direction = tk.BOTH if row_fill_direction in (tk.Y, tk.BOTH) else tk.X + # ------------------------- StatusBar placement element ------------------------- # + elif element_type == ELEM_TYPE_STATUSBAR: + # auto_size_text = element.AutoSizeText + display_text = element.DisplayText # text to display + if auto_size_text is False: + width, height = element_size + else: + lines = display_text.split('\n') + max_line_len = max([len(l) for l in lines]) + num_lines = len(lines) + if max_line_len > element_size[0]: # if text exceeds element size, the will have to wrap + width = element_size[0] + else: + width = max_line_len + height = num_lines + # ---===--- LABEL widget create and place --- # + stringvar = tk.StringVar() + element.TKStringVar = stringvar + stringvar.set(display_text) + if auto_size_text: + width = 0 + if element.Justification is not None: + justification = element.Justification + elif toplevel_form.TextJustification is not None: + justification = toplevel_form.TextJustification + else: + justification = DEFAULT_TEXT_JUSTIFICATION + justify = tk.LEFT if justification.startswith('l') else tk.CENTER if justification.startswith('c') else tk.RIGHT + anchor = tk.NW if justification.startswith('l') else tk.N if justification.startswith('c') else tk.NE + # tktext_label = tk.Label(tk_row_frame, textvariable=stringvar, width=width, height=height, + # justify=justify, bd=border_depth, font=font) + tktext_label = element.Widget = tk.Label(tk_row_frame, textvariable=stringvar, width=width, + height=height, + justify=justify, bd=border_depth, font=font) + # Set wrap-length for text (in PIXELS) == PAIN IN THE ASS + wraplen = tktext_label.winfo_reqwidth() + 40 # width of widget in Pixels + if not auto_size_text and height == 1: + wraplen = 0 + # print("wraplen, width, height", wraplen, width, height) + tktext_label.configure(anchor=anchor, wraplen=wraplen) # set wrap to width of widget + if element.Relief is not None: + tktext_label.configure(relief=element.Relief) + if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + tktext_label.configure(background=element.BackgroundColor) + if element.TextColor != COLOR_SYSTEM_DEFAULT and element.TextColor is not None: + tktext_label.configure(fg=element.TextColor) + tktext_label.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], fill=tk.X, expand=True) + row_fill_direction = tk.X + if element.visible is False: + tktext_label.pack_forget() + element.TKText = tktext_label + if element.ClickSubmits: + tktext_label.bind('', element._TextClickedHandler) + if element.Tooltip is not None: + element.TooltipObject = ToolTip(element.TKText, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) + _add_right_click_menu_and_grab(element) + + # ............................DONE WITH ROW pack the row of widgets ..........................# + # done with row, pack the row of widgets + # tk_row_frame.grid(row=row_num+2, sticky=tk.NW, padx=DEFAULT_MARGINS[0]) + + anchor = 'nw' + + if row_justify.lower().startswith('c'): + anchor = 'n' + side = tk.LEFT + elif row_justify.lower().startswith('r'): + anchor = 'ne' + side = tk.RIGHT + elif row_justify.lower().startswith('l'): + anchor = 'nw' + side = tk.LEFT + # elif toplevel_form.ElementJustification.lower().startswith('c'): + # anchor = 'n' + # side = tk.TOP + # elif toplevel_form.ElementJustification.lower().startswith('r'): + # anchor = 'ne' + # side = tk.TOP + # else: + # anchor = 'nw' + # side = tk.TOP + + # row_should_expand = False + + # if form.RightClickMenu: + # menu = form.RightClickMenu + # top_menu = tk.Menu(toplevel_form.TKroot, tearoff=False) + # AddMenuItem(top_menu, menu[1], form) + # tk_row_frame.bind('', form._RightClickMenuCallback) + + tk_row_frame.pack(side=tk.TOP, anchor=anchor, padx=0, pady=0, expand=row_should_expand, fill=row_fill_direction) + if form.BackgroundColor is not None and form.BackgroundColor != COLOR_SYSTEM_DEFAULT: + tk_row_frame.configure(background=form.BackgroundColor) + + return + + +def _no_titlebar_setup(window): + """ + Does the operations required to turn off the titlebar for the window. + The Raspberry Pi required the settings to be make after the window's creation. + Calling twice seems to have had better overall results so that's what's currently done. + The MAC has been the problem with this feature. It's been a chronic problem on the Mac. + :param window: window to turn off the titlebar if indicated in the settings + :type window: Window + """ + try: + if window.NoTitleBar: + if running_linux(): + # window.TKroot.wm_attributes("-type", 'splash') + window.TKroot.wm_attributes("-type", 'dock') + else: + window.TKroot.wm_overrideredirect(True) + # Special case for Mac. Need to clear flag again if not tkinter version 8.6.10+ + # Previously restricted patch to only certain tkinter versions. Now use the patch setting exclusively regardless of tk ver + # if running_mac() and ENABLE_MAC_NOTITLEBAR_PATCH and (sum([int(i) for i in tclversion_detailed.split('.')]) < 24): + # if running_mac() and ENABLE_MAC_NOTITLEBAR_PATCH: + if _mac_should_apply_notitlebar_patch(): + print('* Applying Mac no_titlebar patch *') + window.TKroot.wm_overrideredirect(False) + except Exception as e: + warnings.warn('** Problem setting no titlebar {} **'.format(e), UserWarning) + + +def _convert_window_to_tk(window): + """ + + :type window: (Window) + + """ + master = window.TKroot + master.title(window.Title) + InitializeResults(window) + + PackFormIntoFrame(window, master, window) + + window.TKroot.configure(padx=window.Margins[0], pady=window.Margins[1]) + + # ....................................... DONE creating and laying out window ..........................# + if window._Size != (None, None): + master.geometry("%sx%s" % (window._Size[0], window._Size[1])) + screen_width = master.winfo_screenwidth() # get window info to move to middle of screen + screen_height = master.winfo_screenheight() + if window.Location != (None, None): + x, y = window.Location + elif DEFAULT_WINDOW_LOCATION != (None, None): + x, y = DEFAULT_WINDOW_LOCATION + else: + master.update_idletasks() # don't forget to do updates or values are bad + win_width = master.winfo_width() + win_height = master.winfo_height() + x = screen_width / 2 - win_width / 2 + y = screen_height / 2 - win_height / 2 + if y + win_height > screen_height: + y = screen_height - win_height + if x + win_width > screen_width: + x = screen_width - win_width + + if window.RelativeLoction != (None, None): + x += window.RelativeLoction[0] + y += window.RelativeLoction[1] + + move_string = '+%i+%i' % (int(x), int(y)) + master.geometry(move_string) + window.config_last_location = (int(x), (int(y))) + window.TKroot.x = int(x) + window.TKroot.y = int(y) + window.starting_window_position = (int(x), (int(y))) + master.update_idletasks() # don't forget + master.geometry(move_string) + master.update_idletasks() # don't forget + + _no_titlebar_setup(window) + + return + + +# ----====----====----====----====----==== STARTUP TK ====----====----====----====----====----# +def StartupTK(window): + """ + NOT user callable + Creates the window (for real) lays out all the elements, etc. It's a HUGE set of things it does. It's the basic + "porting layer" that will change depending on the GUI framework PySimpleGUI is running on top of. + + :param window: you window object + :type window: (Window) + + """ + window = window # type: Window + # global _my_windows + # ow = _my_windows.NumOpenWindows + ow = Window.NumOpenWindows + # print('Starting TK open Windows = {}'.format(ow)) + if ENABLE_TK_WINDOWS: + root = tk.Tk() + elif not ow and not window.ForceTopLevel: + # if first window being created, make a throwaway, hidden master root. This stops one user + # window from becoming the child of another user window. All windows are children of this + # hidden window + Window._IncrementOpenCount() + Window.hidden_master_root = tk.Tk() + Window.hidden_master_root.attributes('-alpha', 0) # HIDE this window really really really + # if not running_mac(): + try: + Window.hidden_master_root.wm_overrideredirect(True) + except Exception as e: + print('* Error performing wm_overrideredirect while hiding the hidden master root*', e) + Window.hidden_master_root.withdraw() + # root = tk.Toplevel(Window.hidden_master_root) # This code caused problems when running with timeout=0 and closed with X + root = tk.Toplevel(class_=window.Title) + else: + # root = tk.Toplevel(Window.hidden_master_root) # This code caused problems when running with timeout=0 and closed with X + root = tk.Toplevel(class_=window.Title) + if window.DebuggerEnabled: + root.bind('', window._callback_main_debugger_window_create_keystroke) + root.bind('', window._callback_popout_window_create_keystroke) + + # root.bind('', Debugger._build_main_debugger_window) + # root.bind('', Debugger._build_floating_window) + try: + if not running_mac() or \ + (running_mac() and not window.NoTitleBar) or \ + (running_mac() and window.NoTitleBar and not _mac_should_apply_notitlebar_patch()): + root.attributes('-alpha', 0) # hide window while building it. makes for smoother 'paint' + except Exception as e: + print('*** Exception setting alpha channel to zero while creating window ***', e) + + + if window.BackgroundColor is not None and window.BackgroundColor != COLOR_SYSTEM_DEFAULT: + root.configure(background=window.BackgroundColor) + Window._IncrementOpenCount() + + window.TKroot = root + + window._create_thread_queue() + + # for the Raspberry Pi. Need to set the attributes here, prior to the building of the window + # so going ahead and doing it for all platforms, in addition to doing it after the window is packed + _no_titlebar_setup(window) + + if not window.Resizable: + root.resizable(False, False) + + if window.DisableMinimize: + root.attributes("-toolwindow", 1) + + if window.KeepOnTop: + root.wm_attributes("-topmost", 1) + + if window.TransparentColor is not None: + window.SetTransparentColor(window.TransparentColor) + + if window.scaling is not None: + root.tk.call('tk', 'scaling', window.scaling) + + + # root.protocol("WM_DELETE_WINDOW", MyFlexForm.DestroyedCallback()) + # root.bind('', MyFlexForm.DestroyedCallback()) + _convert_window_to_tk(window) + + # Make moveable window + if (window.GrabAnywhere is not False and not ( + window.NonBlocking and window.GrabAnywhere is not True)): + if not (ENABLE_MAC_DISABLE_GRAB_ANYWHERE_WITH_TITLEBAR and running_mac() and not window.NoTitleBar): + root.bind("", window._StartMoveGrabAnywhere) + root.bind("", window._StopMove) + root.bind("", window._OnMotionGrabAnywhere) + if (window.GrabAnywhereUsingControlKey is not False and not ( + window.NonBlocking and window.GrabAnywhereUsingControlKey is not True)): + root.bind("", window._StartMoveUsingControlKey) + root.bind("", window._StopMove) + root.bind("", window._OnMotionUsingControlKey) + window.set_icon(window.WindowIcon) + + try: + root.attributes('-alpha', 1 if window.AlphaChannel is None else window.AlphaChannel) # Make window visible again + except: + pass + + if window.ReturnKeyboardEvents and not window.NonBlocking: + root.bind("", window._KeyboardCallback) + root.bind("", window._MouseWheelCallback) + root.bind("", window._MouseWheelCallback) + root.bind("", window._MouseWheelCallback) + elif window.ReturnKeyboardEvents: + root.bind("", window._KeyboardCallback) + root.bind("", window._MouseWheelCallback) + root.bind("", window._MouseWheelCallback) + root.bind("", window._MouseWheelCallback) + + if window.NoTitleBar: + window.TKroot.focus_force() + + if window.AutoClose: + # if the window is being finalized, then don't start the autoclose timer + if not window.finalize_in_progress: + window._start_autoclose_timer() + # duration = DEFAULT_AUTOCLOSE_TIME if window.AutoCloseDuration is None else window.AutoCloseDuration + # window.TKAfterID = root.after(int(duration * 1000), window._AutoCloseAlarmCallback) + + if window.Timeout != None: + window.TKAfterID = root.after(int(window.Timeout), window._TimeoutAlarmCallback) + if window.NonBlocking: + window.TKroot.protocol("WM_DESTROY_WINDOW", window._OnClosingCallback) + window.TKroot.protocol("WM_DELETE_WINDOW", window._OnClosingCallback) + + else: # it's a blocking form + # print('..... CALLING MainLoop') + window.CurrentlyRunningMainloop = True + window.TKroot.protocol("WM_DESTROY_WINDOW", window._OnClosingCallback) + window.TKroot.protocol("WM_DELETE_WINDOW", window._OnClosingCallback) + + if window.modal: + window.make_modal() + + # window.TKroot.bind("", window._config_callback) + + # ----------------------------------- tkinter mainloop call ----------------------------------- + Window._window_running_mainloop = window + Window._root_running_mainloop = window.TKroot + window.TKroot.mainloop() + window.CurrentlyRunningMainloop = False + window.TimerCancelled = True + # print('..... BACK from MainLoop') + if not window.FormRemainedOpen: + Window._DecrementOpenCount() + # _my_windows.Decrement() + if window.RootNeedsDestroying: + try: + window.TKroot.destroy() + except: + pass + window.RootNeedsDestroying = False + return + + +def _set_icon_for_tkinter_window(root, icon=None, pngbase64=None): + """ + At the moment, this function is only used by the get_filename or folder with the no_window option set. + Changes the icon that is shown on the title bar and on the task bar. + NOTE - The file type is IMPORTANT and depends on the OS! + Can pass in: + * filename which must be a .ICO icon file for windows, PNG file for Linux + * bytes object + * BASE64 encoded file held in a variable + + :param root: The window being modified + :type root: (tk.Tk or tk.TopLevel) + :param icon: Filename or bytes object + :type icon: (str | bytes) + :param pngbase64: Base64 encoded image + :type pngbase64: (bytes) + """ + + if type(icon) is bytes or pngbase64 is not None: + wicon = tkinter.PhotoImage(data=icon if icon is not None else pngbase64) + try: + root.tk.call('wm', 'iconphoto', root._w, wicon) + except: + wicon = tkinter.PhotoImage(data=DEFAULT_BASE64_ICON) + try: + root.tk.call('wm', 'iconphoto', root._w, wicon) + except Exception as e: + print('Set icon exception', e) + pass + return + + wicon = icon + try: + root.iconbitmap(icon) + except Exception as e: + try: + wicon = tkinter.PhotoImage(file=icon) + root.tk.call('wm', 'iconphoto', root._w, wicon) + except Exception as e: + try: + wicon = tkinter.PhotoImage(data=DEFAULT_BASE64_ICON) + try: + root.tk.call('wm', 'iconphoto', root._w, wicon) + except Exception as e: + print('Set icon exception', e) + pass + except: + print('Set icon exception', e) + pass + + +# ==============================_GetNumLinesNeeded ==# +# Helper function for determining how to wrap text # +# ===================================================# +def _GetNumLinesNeeded(text, max_line_width): + if max_line_width == 0: + return 1 + lines = text.split('\n') + num_lines = len(lines) # number of original lines of text + max_line_len = max([len(l) for l in lines]) # longest line + lines_used = [] + for L in lines: + lines_used.append(len(L) // max_line_width + (len(L) % max_line_width > 0)) # fancy math to round up + total_lines_needed = sum(lines_used) + return total_lines_needed + + +# ============================== PROGRESS METER ========================================== # + +def convert_args_to_single_string(*args): + """ + + :param *args: + :type *args: + + """ + max_line_total, width_used, total_lines, = 0, 0, 0 + single_line_message = '' + # loop through args and built a SINGLE string from them + for message in args: + # fancy code to check if string and convert if not is not need. Just always convert to string :-) + # if not isinstance(message, str): message = str(message) + message = str(message) + longest_line_len = max([len(l) for l in message.split('\n')]) + width_used = max(longest_line_len, width_used) + max_line_total = max(max_line_total, width_used) + lines_needed = _GetNumLinesNeeded(message, width_used) + total_lines += lines_needed + single_line_message += message + '\n' + return single_line_message, width_used, total_lines + + +METER_REASON_CANCELLED = 'cancelled' +METER_REASON_CLOSED = 'closed' +METER_REASON_REACHED_MAX = 'finished' +METER_OK = True +METER_STOPPED = False + + +class QuickMeter(object): + active_meters = {} + exit_reasons = {} + + def __init__(self, title, current_value, max_value, key, *args, orientation='v', bar_color=(None, None), button_color=(None, None), + size=DEFAULT_PROGRESS_BAR_SIZE, border_width=None, grab_anywhere=False, no_titlebar=False, keep_on_top=None, no_button=False): + """ + + :param title: text to display in element + :type title: (str) + :param current_value: current value + :type current_value: (int) + :param max_value: max value of QuickMeter + :type max_value: (int) + :param key: Used with window.find_element and with return values to uniquely identify this element + :type key: str | int | tuple | object + :param *args: stuff to output + :type *args: (Any) + :param orientation: 'horizontal' or 'vertical' ('h' or 'v' work) (Default value = 'vertical' / 'v') + :type orientation: (str) + :param bar_color: color of a bar line + :type bar_color: (str, str) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param size: (w,h) w=characters-wide, h=rows-high (Default value = DEFAULT_PROGRESS_BAR_SIZE) + :type size: (int, int) + :param border_width: width of border around element + :type border_width: (int) + :param grab_anywhere: If True: can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param no_titlebar: If True: window will be created without a titlebar + :type no_titlebar: (bool) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param no_button: If True: window will be created without a cancel button + :type no_button: (bool) + """ + self.start_time = datetime.datetime.utcnow() + self.key = key + self.orientation = orientation + self.bar_color = bar_color + self.size = size + self.grab_anywhere = grab_anywhere + self.button_color = button_color + self.border_width = border_width + self.no_titlebar = no_titlebar + self.title = title + self.current_value = current_value + self.max_value = max_value + self.close_reason = None + self.keep_on_top = keep_on_top + self.no_button = no_button + self.window = self.BuildWindow(*args) + + def BuildWindow(self, *args): + layout = [] + if self.orientation.lower().startswith('h'): + col = [] + col += [[T(''.join(map(lambda x: str(x) + '\n', args)), + key='_OPTMSG_')]] ### convert all *args into one string that can be updated + col += [[T('', size=(30, 10), key='_STATS_')], + [ProgressBar(max_value=self.max_value, orientation='h', key='_PROG_', size=self.size, + bar_color=self.bar_color)]] + if not self.no_button: + col += [[Cancel(button_color=self.button_color), Stretch()]] + layout = [Column(col)] + else: + col = [[ProgressBar(max_value=self.max_value, orientation='v', key='_PROG_', size=self.size, + bar_color=self.bar_color)]] + col2 = [] + col2 += [[T(''.join(map(lambda x: str(x) + '\n', args)), + key='_OPTMSG_')]] ### convert all *args into one string that can be updated + col2 += [[T('', size=(30, 10), key='_STATS_')]] + if not self.no_button: + col2 += [[Cancel(button_color=self.button_color), Stretch()]] + + layout = [Column(col), Column(col2)] + self.window = Window(self.title, grab_anywhere=self.grab_anywhere, border_depth=self.border_width, no_titlebar=self.no_titlebar, disable_close=True, keep_on_top=self.keep_on_top) + self.window.Layout([layout]).Finalize() + + return self.window + + def UpdateMeter(self, current_value, max_value, *args): ### support for *args when updating + + self.current_value = current_value + self.max_value = max_value + self.window.Element('_PROG_').UpdateBar(self.current_value, self.max_value) + self.window.Element('_STATS_').Update('\n'.join(self.ComputeProgressStats())) + self.window.Element('_OPTMSG_').Update( + value=''.join(map(lambda x: str(x) + '\n', args))) ### update the string with the args + event, values = self.window.read(timeout=0) + if event in ('Cancel', None) or current_value >= max_value: + exit_reason = METER_REASON_CANCELLED if event in ('Cancel', None) else METER_REASON_REACHED_MAX if current_value >= max_value else METER_STOPPED + self.window.close() + del (QuickMeter.active_meters[self.key]) + QuickMeter.exit_reasons[self.key] = exit_reason + return QuickMeter.exit_reasons[self.key] + return METER_OK + + def ComputeProgressStats(self): + utc = datetime.datetime.utcnow() + time_delta = utc - self.start_time + total_seconds = time_delta.total_seconds() + if not total_seconds: + total_seconds = 1 + try: + time_per_item = total_seconds / self.current_value + except: + time_per_item = 1 + seconds_remaining = (self.max_value - self.current_value) * time_per_item + time_remaining = str(datetime.timedelta(seconds=seconds_remaining)) + time_remaining_short = (time_remaining).split(".")[0] + time_delta_short = str(time_delta).split(".")[0] + total_time = time_delta + datetime.timedelta(seconds=seconds_remaining) + total_time_short = str(total_time).split(".")[0] + self.stat_messages = [ + '{} of {}'.format(self.current_value, self.max_value), + '{} %'.format(100 * self.current_value // self.max_value), + '', + ' {:6.2f} Iterations per Second'.format(self.current_value / total_seconds), + ' {:6.2f} Seconds per Iteration'.format(total_seconds / (self.current_value if self.current_value else 1)), + '', + '{} Elapsed Time'.format(time_delta_short), + '{} Time Remaining'.format(time_remaining_short), + '{} Estimated Total Time'.format(total_time_short)] + return self.stat_messages + + +def one_line_progress_meter(title, current_value, max_value, *args, key='OK for 1 meter', orientation='v', bar_color=(None, None), button_color=None, size=DEFAULT_PROGRESS_BAR_SIZE, border_width=None, grab_anywhere=False, no_titlebar=False, keep_on_top=None, no_button=False): + """ + :param title: text to display in eleemnt + :type title: (str) + :param current_value: current value + :type current_value: (int) + :param max_value: max value of QuickMeter + :type max_value: (int) + :param *args: stuff to output + :type *args: (Any) + :param key: Used to differentiate between mutliple meters. Used to cancel meter early. Now optional as there is a default value for single meters + :type key: str | int | tuple | object + :param orientation: 'horizontal' or 'vertical' ('h' or 'v' work) (Default value = 'vertical' / 'v') + :type orientation: (str) + :param bar_color: color of a bar line + :type bar_color: Tuple(str, str) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param size: (w,h) w=characters-wide, h=rows-high (Default value = DEFAULT_PROGRESS_BAR_SIZE) + :type size: (int, int) + :param border_width: width of border around element + :type border_width: (int) + :param grab_anywhere: If True: can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param no_titlebar: If True: no titlebar will be shown on the window + :type no_titlebar: (bool) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param no_button: If True: window will be created without a cancel button + :type no_button: (bool) + :return: True if updated successfully. False if user closed the meter with the X or Cancel button + :rtype: (bool) + """ + if key not in QuickMeter.active_meters: + meter = QuickMeter(title, current_value, max_value, key, *args, orientation=orientation, bar_color=bar_color, button_color=button_color, size=size, border_width=border_width, grab_anywhere=grab_anywhere, no_titlebar=no_titlebar, keep_on_top=keep_on_top, no_button=no_button) + QuickMeter.active_meters[key] = meter + QuickMeter.exit_reasons[key] = None + + else: + meter = QuickMeter.active_meters[key] + + rc = meter.UpdateMeter(current_value, max_value, *args) ### pass the *args to to UpdateMeter function + OneLineProgressMeter.exit_reasons = getattr(OneLineProgressMeter, 'exit_reasons', QuickMeter.exit_reasons) + exit_reason = OneLineProgressMeter.exit_reasons.get(key) + return METER_OK if exit_reason in (None, METER_REASON_REACHED_MAX) else METER_STOPPED + + +def one_line_progress_meter_cancel(key='OK for 1 meter'): + """ + Cancels and closes a previously created One Line Progress Meter window + + :param key: Key used when meter was created + :type key: (Any) + :return: None + :rtype: None + """ + try: + meter = QuickMeter.active_meters[key] + meter.window.Close() + del (QuickMeter.active_meters[key]) + QuickMeter.exit_reasons[key] = METER_REASON_CANCELLED + except: # meter is already deleted + return + + +def get_complimentary_hex(color): + """ + :param color: color string, like "#RRGGBB" + :type color: (str) + :return: color string, like "#RRGGBB" + :rtype: (str) + """ + + # strip the # from the beginning + color = color[1:] + # convert the string into hex + color = int(color, 16) + # invert the three bytes + # as good as substracting each of RGB component by 255(FF) + comp_color = 0xFFFFFF ^ color + # convert the color back to hex by prefixing a # + comp_color = "#%06X" % comp_color + return comp_color + + +# ======================== EasyPrint =====# +# ===================================================# +class _DebugWin(): + debug_window = None + + def __init__(self, size=(None, None), location=(None, None), relative_location=(None, None), font=None, no_titlebar=False, no_button=False, + grab_anywhere=False, keep_on_top=None, do_not_reroute_stdout=True, echo_stdout=False, resizable=True): + """ + + :param size: (w,h) w=characters-wide, h=rows-high + :type size: (int, int) + :param location: Location of upper left corner of the window + :type location: (int, int) + :param relative_location: (x,y) location relative to the default location of the window, in pixels. Normally the window centers. This location is relative to the location the window would be created. Note they can be negative. + :type relative_location: (int, int) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + :param no_button: show button + :type no_button: (bool) + :param grab_anywhere: If True: can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param location: Location of upper left corner of the window + :type location: (int, int) + :param do_not_reroute_stdout: bool value + :type do_not_reroute_stdout: (bool) + :param echo_stdout: If True stdout is sent to both the console and the debug window + :type echo_stdout: (bool) + :param resizable: if True, makes the window resizble + :type resizable: (bool) + """ + + # Show a form that's a running counter + self.size = size + self.location = location + self.relative_location = relative_location + self.font = font + self.no_titlebar = no_titlebar + self.no_button = no_button + self.grab_anywhere = grab_anywhere + self.keep_on_top = keep_on_top + self.do_not_reroute_stdout = do_not_reroute_stdout + self.echo_stdout = echo_stdout + self.resizable = resizable + + win_size = size if size != (None, None) else DEFAULT_DEBUG_WINDOW_SIZE + self.output_element = Multiline(size=win_size, autoscroll=True, auto_refresh=True, reroute_stdout=False if do_not_reroute_stdout else True, echo_stdout_stderr=self.echo_stdout, reroute_stderr=False if do_not_reroute_stdout else True, expand_x=True, expand_y=True, key='-MULTILINE-') + if no_button: + self.layout = [[self.output_element]] + else: + self.layout = [[self.output_element], + [DummyButton('Quit'), Stretch()]] + + self.layout[-1] += [Sizegrip()] + + self.window = Window('Debug Window', self.layout, no_titlebar=no_titlebar, auto_size_text=True, location=location, relative_location=relative_location, + font=font or ('Courier New', 10), grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, finalize=False, resizable=resizable) + return + + def Print(self, *args, end=None, sep=None, text_color=None, background_color=None, erase_all=False, font=None): + sepchar = sep if sep is not None else ' ' + endchar = end if end is not None else '\n' + + if self.window is None: # if window was destroyed already re-open it + self.__init__(size=self.size, location=self.location, relative_location=self.relative_location, font=self.font, no_titlebar=self.no_titlebar, + no_button=self.no_button, grab_anywhere=self.grab_anywhere, keep_on_top=self.keep_on_top, + do_not_reroute_stdout=self.do_not_reroute_stdout, resizable=self.resizable, echo_stdout=self.echo_stdout) + + event, values = self.window.read(timeout=0) + if event == 'Quit' or event is None: + self.Close() + self.__init__(size=self.size, location=self.location, relative_location=self.relative_location, font=self.font, no_titlebar=self.no_titlebar, + no_button=self.no_button, grab_anywhere=self.grab_anywhere, keep_on_top=self.keep_on_top, + do_not_reroute_stdout=self.do_not_reroute_stdout, resizable=self.resizable, echo_stdout=self.echo_stdout) + event, values = self.window.read(timeout=0) + if erase_all: + self.window['-MULTILINE-'].update('') + if self.do_not_reroute_stdout: + end_str = str(end) if end is not None else '\n' + sep_str = str(sep) if sep is not None else ' ' + + outstring = '' + num_args = len(args) + for i, arg in enumerate(args): + outstring += str(arg) + if i != num_args - 1: + outstring += sep_str + outstring += end_str + + self.output_element.Update(outstring, append=True, text_color_for_value=text_color, background_color_for_value=background_color, + font_for_value=font) + else: + print(*args, sep=sepchar, end=endchar) + + def Close(self): + if self.window.XFound: # increment the number of open windows to get around a bug with debug windows + Window._IncrementOpenCount() + self.window.close() + self.window = None + + +def easy_print(*args, size=(None, None), end=None, sep=None, location=(None, None), relative_location=(None, None), font=None, no_titlebar=False, + no_button=False, grab_anywhere=False, keep_on_top=None, do_not_reroute_stdout=True, echo_stdout=False, text_color=None, background_color=None, colors=None, c=None, + erase_all=False, resizable=True): + """ + Works like a "print" statement but with windowing options. Routes output to the "Debug Window" + + In addition to the normal text and background colors, you can use a "colors" tuple/string + The "colors" or "c" parameter defines both the text and background in a single parm. + It can be a tuple or a single single. Both text and background colors need to be specified + colors -(str, str) or str. A combined text/background color definition in a single parameter + c - (str, str) - Colors tuple has format (foreground, backgrouned) + c - str - can also be a string of the format "foreground on background" ("white on red") + + :param *args: stuff to output + :type *args: (Any) + :param size: (w,h) w=characters-wide, h=rows-high + :type size: (int, int) + :param end: end character + :type end: (str) + :param sep: separator character + :type sep: (str) + :param location: Location of upper left corner of the window + :type location: (int, int) + :param relative_location: (x,y) location relative to the default location of the window, in pixels. Normally the window centers. This location is relative to the location the window would be created. Note they can be negative. + :type relative_location: (int, int) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + :param no_button: don't show button + :type no_button: (bool) + :param grab_anywhere: If True: can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param location: Location of upper left corner of the window + :type location: (int, int) + :param do_not_reroute_stdout: do not reroute stdout and stderr. If False, both stdout and stderr will reroute to here + :type do_not_reroute_stdout: (bool) + :param echo_stdout: If True stdout is sent to both the console and the debug window + :type echo_stdout: (bool) + :param colors: Either a tuple or a string that has both the text and background colors + :type colors: (str) or (str, str) + :param c: Either a tuple or a string that has both the text and background colors + :type c: (str) or (str, str) + :param resizable: if True, the user can resize the debug window. Default is True + :type resizable: (bool) + :param erase_all: If True when erase the output before printing + :type erase_all: (bool) + :return: + :rtype: + """ + if _DebugWin.debug_window is None: + _DebugWin.debug_window = _DebugWin(size=size, location=location, relative_location=relative_location, font=font, no_titlebar=no_titlebar, + no_button=no_button, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, + do_not_reroute_stdout=do_not_reroute_stdout, echo_stdout=echo_stdout, resizable=resizable) + txt_color, bg_color = _parse_colors_parm(c or colors) + _DebugWin.debug_window.Print(*args, end=end, sep=sep, text_color=text_color or txt_color, background_color=background_color or bg_color, + erase_all=erase_all, font=font) + + +def easy_print_close(): + """ + Close a previously opened EasyPrint window + + :return: + :rtype: + """ + if _DebugWin.debug_window is not None: + _DebugWin.debug_window.Close() + _DebugWin.debug_window = None + + +# d8b 888 +# Y8P 888 +# 888 +# .d8888b 88888b. 888d888 888 88888b. 888888 +# d88P" 888 "88b 888P" 888 888 "88b 888 +# 888 888 888 888 888 888 888 888 +# Y88b. 888 d88P 888 888 888 888 Y88b. +# "Y8888P 88888P" 888 888 888 888 "Y888 +# 888 +# 888 +# 888 + + +CPRINT_DESTINATION_WINDOW = None +CPRINT_DESTINATION_MULTILINE_ELMENT_KEY = None + + +def cprint_set_output_destination(window, multiline_key): + """ + Sets up the color print (cprint) output destination + :param window: The window that the cprint call will route the output to + :type window: (Window) + :param multiline_key: Key for the Multiline Element where output will be sent + :type multiline_key: (Any) + :return: None + :rtype: None + """ + + global CPRINT_DESTINATION_WINDOW, CPRINT_DESTINATION_MULTILINE_ELMENT_KEY + + CPRINT_DESTINATION_WINDOW = window + CPRINT_DESTINATION_MULTILINE_ELMENT_KEY = multiline_key + + +def cprint(*args, end=None, sep=' ', text_color=None, font=None, t=None, background_color=None, b=None, colors=None, c=None, window=None, key=None, + justification=None, autoscroll=True): + """ + Color print to a multiline element in a window of your choice. + Must have EITHER called cprint_set_output_destination prior to making this call so that the + window and element key can be saved and used here to route the output, OR used the window + and key parameters to the cprint function to specicy these items. + + args is a variable number of things you want to print. + + end - The end char to use just like print uses + sep - The separation character like print uses + text_color - The color of the text + key - overrides the previously defined Multiline key + window - overrides the previously defined window to output to + background_color - The color of the background + colors -(str, str) or str. A combined text/background color definition in a single parameter + + There are also "aliases" for text_color, background_color and colors (t, b, c) + t - An alias for color of the text (makes for shorter calls) + b - An alias for the background_color parameter + c - (str, str) - "shorthand" way of specifying color. (foreground, backgrouned) + c - str - can also be a string of the format "foreground on background" ("white on red") + + With the aliases it's possible to write the same print but in more compact ways: + cprint('This will print white text on red background', c=('white', 'red')) + cprint('This will print white text on red background', c='white on red') + cprint('This will print white text on red background', text_color='white', background_color='red') + cprint('This will print white text on red background', t='white', b='red') + + :param *args: stuff to output + :type *args: (Any) + :param text_color: Color of the text + :type text_color: (str) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike for the value being updated + :type font: (str or (str, int[, str]) or None) + :param background_color: The background color of the line + :type background_color: (str) + :param colors: Either a tuple or a string that has both the text and background colors "text on background" or just the text color + :type colors: (str) or (str, str) + :param t: Color of the text + :type t: (str) + :param b: The background color of the line + :type b: (str) + :param c: Either a tuple or a string. Same as the color parm + :type c: (str) or (str, str) + :param end: end character + :type end: (str) + :param sep: separator character + :type sep: (str) + :param key: key of multiline to output to (if you want to override the one previously set) + :type key: (Any) + :param window: Window containing the multiline to output to (if you want to override the one previously set) + :type window: (Window) + :param justification: text justification. left, right, center. Can use single characters l, r, c. Sets only for this value, not entire element + :type justification: (str) + :param autoscroll: If True the contents of the element will automatically scroll as more data added to the end + :type autoscroll: (bool) + """ + + destination_key = CPRINT_DESTINATION_MULTILINE_ELMENT_KEY if key is None else key + destination_window = window or CPRINT_DESTINATION_WINDOW + + if (destination_window is None and window is None) or (destination_key is None and key is None): + print('** Warning ** Attempting to perform a cprint without a valid window & key', + 'Will instead print on Console', + 'You can specify window and key in this cprint call, or set ahead of time using cprint_set_output_destination') + print(*args) + return + + kw_text_color = text_color or t + kw_background_color = background_color or b + dual_color = colors or c + try: + if isinstance(dual_color, tuple): + kw_text_color = dual_color[0] + kw_background_color = dual_color[1] + elif isinstance(dual_color, str): + if ' on ' in dual_color: # if has "on" in the string, then have both text and background + kw_text_color = dual_color.split(' on ')[0] + kw_background_color = dual_color.split(' on ')[1] + else: # if no "on" then assume the color string is just the text color + kw_text_color = dual_color + except Exception as e: + print('* cprint warning * you messed up with color formatting', e) + + mline = destination_window.find_element(destination_key, silent_on_error=True) # type: Multiline + try: + # mline = destination_window[destination_key] # type: Multiline + if end is None: + mline.print(*args, text_color=kw_text_color, background_color=kw_background_color, end='', sep=sep, justification=justification, font=font, + autoscroll=autoscroll) + mline.print('', justification=justification, autoscroll=autoscroll) + else: + mline.print(*args, text_color=kw_text_color, background_color=kw_background_color, end=end, sep=sep, justification=justification, font=font, + autoscroll=autoscroll) + except Exception as e: + print('** cprint error trying to print to the multiline. Printing to console instead **', e) + print(*args, end=end, sep=sep) + + +# ------------------------------------------------------------------------------------------------ # +# A print-like call that can be used to output to a multiline element as if it's an Output element # +# ------------------------------------------------------------------------------------------------ # + +def _print_to_element(multiline_element, *args, end=None, sep=None, text_color=None, background_color=None, autoscroll=None, justification=None, font=None): + """ + Print like Python normally prints except route the output to a multiline element and also add colors if desired + + :param multiline_element: The multiline element to be output to + :type multiline_element: (Multiline) + :param args: The arguments to print + :type args: List[Any] + :param end: The end char to use just like print uses + :type end: (str) + :param sep: The separation character like print uses + :type sep: (str) + :param text_color: color of the text + :type text_color: (str) + :param background_color: The background color of the line + :type background_color: (str) + :param autoscroll: If True (the default), the element will scroll to bottom after updating + :type autoscroll: (bool) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike for the value being updated + :type font: str | (str, int) + """ + end_str = str(end) if end is not None else '\n' + sep_str = str(sep) if sep is not None else ' ' + + outstring = '' + num_args = len(args) + for i, arg in enumerate(args): + outstring += str(arg) + if i != num_args - 1: + outstring += sep_str + outstring += end_str + + multiline_element.update(outstring, append=True, text_color_for_value=text_color, background_color_for_value=background_color, autoscroll=autoscroll, + justification=justification, font_for_value=font) + + try: # if the element is set to autorefresh, then refresh the parent window + if multiline_element.AutoRefresh: + multiline_element.ParentForm.refresh() + except: + pass + + +def _parse_colors_parm(colors): + """ + Parse a colors parameter into its separate colors. + Some functions accept a dual colors string/tuple. + This function parses the parameter into the component colors + + :param colors: Either a tuple or a string that has both the text and background colors + :type colors: (str) or (str, str) + :return: tuple with the individual text and background colors + :rtype: (str, str) + """ + if colors is None: + return None, None + dual_color = colors + kw_text_color = kw_background_color = None + try: + if isinstance(dual_color, tuple): + kw_text_color = dual_color[0] + kw_background_color = dual_color[1] + elif isinstance(dual_color, str): + if ' on ' in dual_color: # if has "on" in the string, then have both text and background + kw_text_color = dual_color.split(' on ')[0] + kw_background_color = dual_color.split(' on ')[1] + else: # if no "on" then assume the color string is just the text color + kw_text_color = dual_color + except Exception as e: + print('* warning * you messed up with color formatting', e) + + return kw_text_color, kw_background_color + + +# ============================== set_global_icon ====# +# Sets the icon to be used by default # +# ===================================================# +def set_global_icon(icon): + """ + Sets the icon which will be used any time a window is created if an icon is not provided when the + window is created. + + :param icon: Either a Base64 byte string or a filename + :type icon: bytes | str + """ + + Window._user_defined_icon = icon + + +# ============================== set_options ========# +# Sets the icon to be used by default # +# ===================================================# +def set_options(icon=None, button_color=None, element_size=(None, None), button_element_size=(None, None), + margins=(None, None), + element_padding=(None, None), auto_size_text=None, auto_size_buttons=None, font=None, border_width=None, + slider_border_width=None, slider_relief=None, slider_orientation=None, + autoclose_time=None, message_box_line_width=None, + progress_meter_border_depth=None, progress_meter_style=None, + progress_meter_relief=None, progress_meter_color=None, progress_meter_size=None, + text_justification=None, background_color=None, element_background_color=None, + text_element_background_color=None, input_elements_background_color=None, input_text_color=None, + scrollbar_color=None, text_color=None, element_text_color=None, debug_win_size=(None, None), + window_location=(None, None), error_button_color=(None, None), tooltip_time=None, tooltip_font=None, use_ttk_buttons=None, ttk_theme=None, + suppress_error_popups=None, suppress_raise_key_errors=None, suppress_key_guessing=None,warn_button_key_duplicates=False, enable_treeview_869_patch=None, + enable_mac_notitlebar_patch=None, use_custom_titlebar=None, titlebar_background_color=None, titlebar_text_color=None, titlebar_font=None, + titlebar_icon=None, user_settings_path=None, pysimplegui_settings_path=None, pysimplegui_settings_filename=None, keep_on_top=None, dpi_awareness=None, scaling=None): + """ + :param icon: Can be either a filename or Base64 value. For Windows if filename, it MUST be ICO format. For Linux, must NOT be ICO. Most portable is to use a Base64 of a PNG file. This works universally across all OS's + :type icon: bytes | str + :param button_color: Color of the button (text, background) + :type button_color: (str, str) or str + :param element_size: element size (width, height) in characters + :type element_size: (int, int) + :param button_element_size: Size of button + :type button_element_size: (int, int) + :param margins: (left/right, top/bottom) tkinter margins around outsize. Amount of pixels to leave inside the window's frame around the edges before your elements are shown. + :type margins: (int, int) + :param element_padding: Default amount of padding to put around elements in window (left/right, top/bottom) or ((left, right), (top, bottom)) + :type element_padding: (int, int) or ((int, int),(int,int)) + :param auto_size_text: True if the Widget should be shrunk to exactly fit the number of chars to show + :type auto_size_text: bool + :param auto_size_buttons: True if Buttons in this Window should be sized to exactly fit the text on this. + :type auto_size_buttons: (bool) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param border_width: width of border around element + :type border_width: (int) + :param slider_border_width: Width of the border around sliders + :type slider_border_width: (int) + :param slider_relief: Type of relief to use for sliders + :type slider_relief: (str) + :param slider_orientation: ??? + :type slider_orientation: ??? + :param autoclose_time: ??? + :type autoclose_time: ??? + :param message_box_line_width: ??? + :type message_box_line_width: ??? + :param progress_meter_border_depth: ??? + :type progress_meter_border_depth: ??? + :param progress_meter_style: You can no longer set a progress bar style. All ttk styles must be the same for the window + :type progress_meter_style: ??? + :param progress_meter_relief: + :type progress_meter_relief: ??? + :param progress_meter_color: ??? + :type progress_meter_color: ??? + :param progress_meter_size: ??? + :type progress_meter_size: ??? + :param text_justification: Default text justification for all Text Elements in window + :type text_justification: 'left' | 'right' | 'center' + :param background_color: color of background + :type background_color: (str) + :param element_background_color: element background color + :type element_background_color: (str) + :param text_element_background_color: text element background color + :type text_element_background_color: (str) + :param input_elements_background_color: Default color to use for the background of input elements + :type input_elements_background_color: (str) + :param input_text_color: Default color to use for the text for Input elements + :type input_text_color: (str) + :param scrollbar_color: Default color to use for the slider trough + :type scrollbar_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param element_text_color: Default color to use for Text elements + :type element_text_color: (str) + :param debug_win_size: window size + :type debug_win_size: (int, int) + :param window_location: Default location to place windows. Not setting will center windows on the display + :type window_location: (int, int) | None + :param error_button_color: (Default = (None)) + :type error_button_color: ??? + :param tooltip_time: time in milliseconds to wait before showing a tooltip. Default is 400ms + :type tooltip_time: (int) + :param tooltip_font: font to use for all tooltips + :type tooltip_font: str or Tuple[str, int] or Tuple[str, int, str] + :param use_ttk_buttons: if True will cause all buttons to be ttk buttons + :type use_ttk_buttons: (bool) + :param ttk_theme: Theme to use with ttk widgets. Choices (on Windows) include - 'default', 'winnative', 'clam', 'alt', 'classic', 'vista', 'xpnative' + :type ttk_theme: (str) + :param suppress_error_popups: If True then error popups will not be shown if generated internally to PySimpleGUI + :type suppress_error_popups: (bool) + :param suppress_raise_key_errors: If True then key errors won't be raised (you'll still get popup error) + :type suppress_raise_key_errors: (bool) + :param suppress_key_guessing: If True then key errors won't try and find closest matches for you + :type suppress_key_guessing: (bool) + :param warn_button_key_duplicates: If True then duplicate Button Keys generate warnings (not recommended as they're expected) + :type warn_button_key_duplicates: (bool) + :param enable_treeview_869_patch: If True, then will use the treeview color patch for tk 8.6.9 + :type enable_treeview_869_patch: (bool) + :param enable_mac_notitlebar_patch: If True then Windows with no titlebar use an alternative technique when tkinter version < 8.6.10 + :type enable_mac_notitlebar_patch: (bool) + :param use_custom_titlebar: If True then a custom titlebar is used instead of the normal system titlebar + :type use_custom_titlebar: (bool) + :param titlebar_background_color: If custom titlebar indicated by use_custom_titlebar, then use this as background color + :type titlebar_background_color: str | None + :param titlebar_text_color: If custom titlebar indicated by use_custom_titlebar, then use this as text color + :type titlebar_text_color: str | None + :param titlebar_font: If custom titlebar indicated by use_custom_titlebar, then use this as title font + :type titlebar_font: (str or (str, int[, str]) or None) | None + :param titlebar_icon: If custom titlebar indicated by use_custom_titlebar, then use this as the icon (file or base64 bytes) + :type titlebar_icon: bytes | str + :param user_settings_path: default path for user_settings API calls. Expanded with os.path.expanduser so can contain ~ to represent user + :type user_settings_path: (str) + :param pysimplegui_settings_path: default path for the global PySimpleGUI user_settings + :type pysimplegui_settings_path: (str) + :param pysimplegui_settings_filename: default filename for the global PySimpleGUI user_settings + :type pysimplegui_settings_filename: (str) + :param keep_on_top: If True then all windows will automatically be set to keep_on_top=True + :type keep_on_top: (bool) + :param dpi_awareness: If True then will turn on DPI awareness (Windows only at the moment) + :type dpi_awareness: (bool) + :param scaling: Sets the default scaling for all windows including popups, etc. + :type scaling: (float) + :return: None + :rtype: None + """ + + global DEFAULT_ELEMENT_SIZE + global DEFAULT_BUTTON_ELEMENT_SIZE + global DEFAULT_MARGINS # Margins for each LEFT/RIGHT margin is first term + global DEFAULT_ELEMENT_PADDING # Padding between elements (row, col) in pixels + global DEFAULT_AUTOSIZE_TEXT + global DEFAULT_AUTOSIZE_BUTTONS + global DEFAULT_FONT + global DEFAULT_BORDER_WIDTH + global DEFAULT_AUTOCLOSE_TIME + global DEFAULT_BUTTON_COLOR + global MESSAGE_BOX_LINE_WIDTH + global DEFAULT_PROGRESS_BAR_BORDER_WIDTH + global DEFAULT_PROGRESS_BAR_STYLE + global DEFAULT_PROGRESS_BAR_RELIEF + global DEFAULT_PROGRESS_BAR_COLOR + global DEFAULT_PROGRESS_BAR_SIZE + global DEFAULT_TEXT_JUSTIFICATION + global DEFAULT_DEBUG_WINDOW_SIZE + global DEFAULT_SLIDER_BORDER_WIDTH + global DEFAULT_SLIDER_RELIEF + global DEFAULT_SLIDER_ORIENTATION + global DEFAULT_BACKGROUND_COLOR + global DEFAULT_INPUT_ELEMENTS_COLOR + global DEFAULT_ELEMENT_BACKGROUND_COLOR + global DEFAULT_TEXT_ELEMENT_BACKGROUND_COLOR + global DEFAULT_SCROLLBAR_COLOR + global DEFAULT_TEXT_COLOR + global DEFAULT_WINDOW_LOCATION + global DEFAULT_ELEMENT_TEXT_COLOR + global DEFAULT_INPUT_TEXT_COLOR + global DEFAULT_TOOLTIP_TIME + global DEFAULT_ERROR_BUTTON_COLOR + global DEFAULT_TTK_THEME + global USE_TTK_BUTTONS + global TOOLTIP_FONT + global SUPPRESS_ERROR_POPUPS + global SUPPRESS_RAISE_KEY_ERRORS + global SUPPRESS_KEY_GUESSING + global WARN_DUPLICATE_BUTTON_KEY_ERRORS + global ENABLE_TREEVIEW_869_PATCH + global ENABLE_MAC_NOTITLEBAR_PATCH + global USE_CUSTOM_TITLEBAR + global CUSTOM_TITLEBAR_BACKGROUND_COLOR + global CUSTOM_TITLEBAR_TEXT_COLOR + global CUSTOM_TITLEBAR_ICON + global CUSTOM_TITLEBAR_FONT + global DEFAULT_USER_SETTINGS_PATH + global DEFAULT_USER_SETTINGS_PYSIMPLEGUI_PATH + global DEFAULT_USER_SETTINGS_PYSIMPLEGUI_FILENAME + global DEFAULT_KEEP_ON_TOP + global DEFAULT_SCALING + global _pysimplegui_user_settings + # global _my_windows + + if icon: + Window._user_defined_icon = icon + # _my_windows._user_defined_icon = icon + + if button_color != None: + if button_color == COLOR_SYSTEM_DEFAULT: + DEFAULT_BUTTON_COLOR = (COLOR_SYSTEM_DEFAULT, COLOR_SYSTEM_DEFAULT) + else: + DEFAULT_BUTTON_COLOR = button_color + + if element_size != (None, None): + DEFAULT_ELEMENT_SIZE = element_size + + if button_element_size != (None, None): + DEFAULT_BUTTON_ELEMENT_SIZE = button_element_size + + if margins != (None, None): + DEFAULT_MARGINS = margins + + if element_padding != (None, None): + DEFAULT_ELEMENT_PADDING = element_padding + + if auto_size_text != None: + DEFAULT_AUTOSIZE_TEXT = auto_size_text + + if auto_size_buttons != None: + DEFAULT_AUTOSIZE_BUTTONS = auto_size_buttons + + if font != None: + DEFAULT_FONT = font + + if border_width != None: + DEFAULT_BORDER_WIDTH = border_width + + if autoclose_time != None: + DEFAULT_AUTOCLOSE_TIME = autoclose_time + + if message_box_line_width != None: + MESSAGE_BOX_LINE_WIDTH = message_box_line_width + + if progress_meter_border_depth != None: + DEFAULT_PROGRESS_BAR_BORDER_WIDTH = progress_meter_border_depth + + if progress_meter_style != None: + warnings.warn('You can no longer set a progress bar style. All ttk styles must be the same for the window', UserWarning) + # DEFAULT_PROGRESS_BAR_STYLE = progress_meter_style + + if progress_meter_relief != None: + DEFAULT_PROGRESS_BAR_RELIEF = progress_meter_relief + + if progress_meter_color != None: + DEFAULT_PROGRESS_BAR_COLOR = progress_meter_color + + if progress_meter_size != None: + DEFAULT_PROGRESS_BAR_SIZE = progress_meter_size + + if slider_border_width != None: + DEFAULT_SLIDER_BORDER_WIDTH = slider_border_width + + if slider_orientation != None: + DEFAULT_SLIDER_ORIENTATION = slider_orientation + + if slider_relief != None: + DEFAULT_SLIDER_RELIEF = slider_relief + + if text_justification != None: + DEFAULT_TEXT_JUSTIFICATION = text_justification + + if background_color != None: + DEFAULT_BACKGROUND_COLOR = background_color + + if text_element_background_color != None: + DEFAULT_TEXT_ELEMENT_BACKGROUND_COLOR = text_element_background_color + + if input_elements_background_color != None: + DEFAULT_INPUT_ELEMENTS_COLOR = input_elements_background_color + + if element_background_color != None: + DEFAULT_ELEMENT_BACKGROUND_COLOR = element_background_color + + if window_location != (None, None): + DEFAULT_WINDOW_LOCATION = window_location + + if debug_win_size != (None, None): + DEFAULT_DEBUG_WINDOW_SIZE = debug_win_size + + if text_color != None: + DEFAULT_TEXT_COLOR = text_color + + if scrollbar_color != None: + DEFAULT_SCROLLBAR_COLOR = scrollbar_color + + if element_text_color != None: + DEFAULT_ELEMENT_TEXT_COLOR = element_text_color + + if input_text_color is not None: + DEFAULT_INPUT_TEXT_COLOR = input_text_color + + if tooltip_time is not None: + DEFAULT_TOOLTIP_TIME = tooltip_time + + if error_button_color != (None, None): + DEFAULT_ERROR_BUTTON_COLOR = error_button_color + + if ttk_theme is not None: + DEFAULT_TTK_THEME = ttk_theme + + if use_ttk_buttons is not None: + USE_TTK_BUTTONS = use_ttk_buttons + + if tooltip_font is not None: + TOOLTIP_FONT = tooltip_font + + if suppress_error_popups is not None: + SUPPRESS_ERROR_POPUPS = suppress_error_popups + + if suppress_raise_key_errors is not None: + SUPPRESS_RAISE_KEY_ERRORS = suppress_raise_key_errors + + if suppress_key_guessing is not None: + SUPPRESS_KEY_GUESSING = suppress_key_guessing + + if warn_button_key_duplicates is not None: + WARN_DUPLICATE_BUTTON_KEY_ERRORS = warn_button_key_duplicates + + if enable_treeview_869_patch is not None: + ENABLE_TREEVIEW_869_PATCH = enable_treeview_869_patch + + if enable_mac_notitlebar_patch is not None: + ENABLE_MAC_NOTITLEBAR_PATCH = enable_mac_notitlebar_patch + + if use_custom_titlebar is not None: + USE_CUSTOM_TITLEBAR = use_custom_titlebar + + if titlebar_background_color is not None: + CUSTOM_TITLEBAR_BACKGROUND_COLOR = titlebar_background_color + + if titlebar_text_color is not None: + CUSTOM_TITLEBAR_TEXT_COLOR = titlebar_text_color + + if titlebar_font is not None: + CUSTOM_TITLEBAR_FONT = titlebar_font + + if titlebar_icon is not None: + CUSTOM_TITLEBAR_ICON = titlebar_icon + + if user_settings_path is not None: + DEFAULT_USER_SETTINGS_PATH = user_settings_path + + if pysimplegui_settings_path is not None: + DEFAULT_USER_SETTINGS_PYSIMPLEGUI_PATH = pysimplegui_settings_path + + if pysimplegui_settings_filename is not None: + DEFAULT_USER_SETTINGS_PYSIMPLEGUI_FILENAME = pysimplegui_settings_filename + + if pysimplegui_settings_filename is not None or pysimplegui_settings_filename is not None: + _pysimplegui_user_settings = UserSettings(filename=DEFAULT_USER_SETTINGS_PYSIMPLEGUI_FILENAME, + path=DEFAULT_USER_SETTINGS_PYSIMPLEGUI_PATH) + + if keep_on_top is not None: + DEFAULT_KEEP_ON_TOP = keep_on_top + + if dpi_awareness is not None: + if running_windows(): + if platform.release() == "7": + ctypes.windll.user32.SetProcessDPIAware() + elif platform.release() == "8" or platform.release() == "10": + ctypes.windll.shcore.SetProcessDpiAwareness(1) + + if scaling is not None: + DEFAULT_SCALING = scaling + + return True + + +# ----------------------------------------------------------------- # + +# .########.##.....##.########.##.....##.########..######. +# ....##....##.....##.##.......###...###.##.......##....## +# ....##....##.....##.##.......####.####.##.......##...... +# ....##....#########.######...##.###.##.######....######. +# ....##....##.....##.##.......##.....##.##.............## +# ....##....##.....##.##.......##.....##.##.......##....## +# ....##....##.....##.########.##.....##.########..######. + +# ----------------------------------------------------------------- # + +# The official Theme code + +#################### ChangeLookAndFeel ####################### +# Predefined settings that will change the colors and styles # +# of the elements. # +############################################################## +LOOK_AND_FEEL_TABLE = { + "SystemDefault": {"BACKGROUND": COLOR_SYSTEM_DEFAULT, "TEXT": COLOR_SYSTEM_DEFAULT, "INPUT": COLOR_SYSTEM_DEFAULT, "TEXT_INPUT": COLOR_SYSTEM_DEFAULT, + "SCROLL": COLOR_SYSTEM_DEFAULT, "BUTTON": OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR, "PROGRESS": COLOR_SYSTEM_DEFAULT, "BORDER": 1, + "SLIDER_DEPTH": 1, "PROGRESS_DEPTH": 0, }, + "SystemDefaultForReal": {"BACKGROUND": COLOR_SYSTEM_DEFAULT, "TEXT": COLOR_SYSTEM_DEFAULT, "INPUT": COLOR_SYSTEM_DEFAULT, + "TEXT_INPUT": COLOR_SYSTEM_DEFAULT, "SCROLL": COLOR_SYSTEM_DEFAULT, "BUTTON": COLOR_SYSTEM_DEFAULT, + "PROGRESS": COLOR_SYSTEM_DEFAULT, "BORDER": 1, "SLIDER_DEPTH": 1, "PROGRESS_DEPTH": 0, }, + "SystemDefault1": {"BACKGROUND": COLOR_SYSTEM_DEFAULT, "TEXT": COLOR_SYSTEM_DEFAULT, "INPUT": COLOR_SYSTEM_DEFAULT, "TEXT_INPUT": COLOR_SYSTEM_DEFAULT, + "SCROLL": COLOR_SYSTEM_DEFAULT, "BUTTON": COLOR_SYSTEM_DEFAULT, "PROGRESS": COLOR_SYSTEM_DEFAULT, "BORDER": 1, "SLIDER_DEPTH": 1, + "PROGRESS_DEPTH": 0, }, + "Material1": {"BACKGROUND": "#E3F2FD", "TEXT": "#000000", "INPUT": "#86A8FF", "TEXT_INPUT": "#000000", "SCROLL": "#86A8FF", + "BUTTON": ("#FFFFFF", "#5079D3"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 0, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "ACCENT1": "#FF0266", "ACCENT2": "#FF5C93", "ACCENT3": "#C5003C", }, + "Material2": {"BACKGROUND": "#FAFAFA", "TEXT": "#000000", "INPUT": "#004EA1", "TEXT_INPUT": "#FFFFFF", "SCROLL": "#5EA7FF", + "BUTTON": ("#FFFFFF", "#0079D3"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 0, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "ACCENT1": "#FF0266", "ACCENT2": "#FF5C93", "ACCENT3": "#C5003C", }, + "Reddit": {"BACKGROUND": "#ffffff", "TEXT": "#1a1a1b", "INPUT": "#dae0e6", "TEXT_INPUT": "#222222", "SCROLL": "#a5a4a4", "BUTTON": ("#FFFFFF", "#0079d3"), + "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, "ACCENT1": "#ff5414", "ACCENT2": "#33a8ff", + "ACCENT3": "#dbf0ff", }, + "Topanga": {"BACKGROUND": "#282923", "TEXT": "#E7DB74", "INPUT": "#393a32", "TEXT_INPUT": "#E7C855", "SCROLL": "#E7C855", "BUTTON": ("#E7C855", "#284B5A"), + "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, "ACCENT1": "#c15226", "ACCENT2": "#7a4d5f", + "ACCENT3": "#889743", }, + "GreenTan": {"BACKGROUND": "#9FB8AD", "TEXT": '#000000', "INPUT": "#F7F3EC", "TEXT_INPUT": "#000000", "SCROLL": "#F7F3EC", "BUTTON": ("#FFFFFF", "#475841"), + "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "Dark": {"BACKGROUND": "#404040", "TEXT": "#FFFFFF", "INPUT": "#4D4D4D", "TEXT_INPUT": "#FFFFFF", "SCROLL": "#707070", "BUTTON": ("#FFFFFF", "#004F00"), + "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "LightGreen": {"BACKGROUND": "#B7CECE", "TEXT": "#000000", "INPUT": "#FDFFF7", "TEXT_INPUT": "#000000", "SCROLL": "#FDFFF7", + "BUTTON": ("#FFFFFF", "#658268"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "ACCENT1": "#76506d", + "ACCENT2": "#5148f1", "ACCENT3": "#0a1c84", "PROGRESS_DEPTH": 0, }, + "Dark2": {"BACKGROUND": "#404040", "TEXT": "#FFFFFF", "INPUT": "#FFFFFF", "TEXT_INPUT": "#000000", "SCROLL": "#707070", "BUTTON": ("#FFFFFF", "#004F00"), + "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "Black": {"BACKGROUND": "#000000", "TEXT": "#FFFFFF", "INPUT": "#4D4D4D", "TEXT_INPUT": "#FFFFFF", "SCROLL": "#707070", "BUTTON": ("#000000", "#FFFFFF"), + "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "Tan": {"BACKGROUND": "#fdf6e3", "TEXT": "#268bd1", "INPUT": "#eee8d5", "TEXT_INPUT": "#6c71c3", "SCROLL": "#eee8d5", "BUTTON": ("#FFFFFF", "#063542"), + "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "TanBlue": {"BACKGROUND": "#e5dece", "TEXT": "#063289", "INPUT": "#f9f8f4", "TEXT_INPUT": "#242834", "SCROLL": "#eee8d5", "BUTTON": ("#FFFFFF", "#063289"), + "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "DarkTanBlue": {"BACKGROUND": "#242834", "TEXT": "#dfe6f8", "INPUT": "#97755c", "TEXT_INPUT": "#FFFFFF", "SCROLL": "#a9afbb", + "BUTTON": ("#FFFFFF", "#063289"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "DarkAmber": {"BACKGROUND": "#2c2825", "TEXT": "#fdcb52", "INPUT": "#705e52", "TEXT_INPUT": "#fdcb52", "SCROLL": "#705e52", + "BUTTON": ("#000000", "#fdcb52"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "DarkBlue": {"BACKGROUND": "#1a2835", "TEXT": "#d1ecff", "INPUT": "#335267", "TEXT_INPUT": "#acc2d0", "SCROLL": "#1b6497", "BUTTON": ("#000000", "#fafaf8"), + "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "Reds": {"BACKGROUND": "#280001", "TEXT": "#FFFFFF", "INPUT": "#d8d584", "TEXT_INPUT": "#000000", "SCROLL": "#763e00", "BUTTON": ("#000000", "#daad28"), + "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "Green": {"BACKGROUND": "#82a459", "TEXT": "#000000", "INPUT": "#d8d584", "TEXT_INPUT": "#000000", "SCROLL": "#e3ecf3", "BUTTON": ("#FFFFFF", "#517239"), + "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "BluePurple": {"BACKGROUND": "#A5CADD", "TEXT": "#6E266E", "INPUT": "#E0F5FF", "TEXT_INPUT": "#000000", "SCROLL": "#E0F5FF", + "BUTTON": ("#FFFFFF", "#303952"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "Purple": {"BACKGROUND": "#B0AAC2", "TEXT": "#000000", "INPUT": "#F2EFE8", "SCROLL": "#F2EFE8", "TEXT_INPUT": "#000000", "BUTTON": ("#000000", "#C2D4D8"), + "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "BlueMono": {"BACKGROUND": "#AAB6D3", "TEXT": "#000000", "INPUT": "#F1F4FC", "SCROLL": "#F1F4FC", "TEXT_INPUT": "#000000", "BUTTON": ("#FFFFFF", "#7186C7"), + "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "GreenMono": {"BACKGROUND": "#A8C1B4", "TEXT": "#000000", "INPUT": "#DDE0DE", "SCROLL": "#E3E3E3", "TEXT_INPUT": "#000000", + "BUTTON": ("#FFFFFF", "#6D9F85"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "BrownBlue": {"BACKGROUND": "#64778d", "TEXT": "#FFFFFF", "INPUT": "#f0f3f7", "SCROLL": "#A6B2BE", "TEXT_INPUT": "#000000", + "BUTTON": ("#FFFFFF", "#283b5b"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "BrightColors": {"BACKGROUND": "#b4ffb4", "TEXT": "#000000", "INPUT": "#ffff64", "SCROLL": "#ffb482", "TEXT_INPUT": "#000000", + "BUTTON": ("#000000", "#ffa0dc"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "NeutralBlue": {"BACKGROUND": "#92aa9d", "TEXT": "#000000", "INPUT": "#fcfff6", "SCROLL": "#fcfff6", "TEXT_INPUT": "#000000", + "BUTTON": ("#000000", "#d0dbbd"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "Kayak": {"BACKGROUND": "#a7ad7f", "TEXT": "#000000", "INPUT": "#e6d3a8", "SCROLL": "#e6d3a8", "TEXT_INPUT": "#000000", "BUTTON": ("#FFFFFF", "#5d907d"), + "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "SandyBeach": {"BACKGROUND": "#efeccb", "TEXT": "#012f2f", "INPUT": "#e6d3a8", "SCROLL": "#e6d3a8", "TEXT_INPUT": "#012f2f", + "BUTTON": ("#FFFFFF", "#046380"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "TealMono": {"BACKGROUND": "#a8cfdd", "TEXT": "#000000", "INPUT": "#dfedf2", "SCROLL": "#dfedf2", "TEXT_INPUT": "#000000", "BUTTON": ("#FFFFFF", "#183440"), + "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "Default": {"BACKGROUND": COLOR_SYSTEM_DEFAULT, "TEXT": COLOR_SYSTEM_DEFAULT, "INPUT": COLOR_SYSTEM_DEFAULT, "TEXT_INPUT": COLOR_SYSTEM_DEFAULT, + "SCROLL": COLOR_SYSTEM_DEFAULT, "BUTTON": OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR, "PROGRESS": COLOR_SYSTEM_DEFAULT, "BORDER": 1, "SLIDER_DEPTH": 1, + "PROGRESS_DEPTH": 0, }, + "Default1": {"BACKGROUND": COLOR_SYSTEM_DEFAULT, "TEXT": COLOR_SYSTEM_DEFAULT, "INPUT": COLOR_SYSTEM_DEFAULT, "TEXT_INPUT": COLOR_SYSTEM_DEFAULT, + "SCROLL": COLOR_SYSTEM_DEFAULT, "BUTTON": COLOR_SYSTEM_DEFAULT, "PROGRESS": COLOR_SYSTEM_DEFAULT, "BORDER": 1, "SLIDER_DEPTH": 1, + "PROGRESS_DEPTH": 0, }, + "DefaultNoMoreNagging": {"BACKGROUND": COLOR_SYSTEM_DEFAULT, "TEXT": COLOR_SYSTEM_DEFAULT, "INPUT": COLOR_SYSTEM_DEFAULT, + "TEXT_INPUT": COLOR_SYSTEM_DEFAULT, "SCROLL": COLOR_SYSTEM_DEFAULT, "BUTTON": OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR, + "PROGRESS": COLOR_SYSTEM_DEFAULT, "BORDER": 1, "SLIDER_DEPTH": 1, "PROGRESS_DEPTH": 0, }, + "GrayGrayGray": {"BACKGROUND": COLOR_SYSTEM_DEFAULT, "TEXT": COLOR_SYSTEM_DEFAULT, "INPUT": COLOR_SYSTEM_DEFAULT, "TEXT_INPUT": COLOR_SYSTEM_DEFAULT, + "SCROLL": COLOR_SYSTEM_DEFAULT, "BUTTON": COLOR_SYSTEM_DEFAULT, "PROGRESS": COLOR_SYSTEM_DEFAULT, "BORDER": 1, "SLIDER_DEPTH": 1, + "PROGRESS_DEPTH": 0, }, + "LightBlue": {"BACKGROUND": "#E3F2FD", "TEXT": "#000000", "INPUT": "#86A8FF", "TEXT_INPUT": "#000000", "SCROLL": "#86A8FF", + "BUTTON": ("#FFFFFF", "#5079D3"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 0, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "ACCENT1": "#FF0266", "ACCENT2": "#FF5C93", "ACCENT3": "#C5003C", }, + "LightGrey": {"BACKGROUND": "#FAFAFA", "TEXT": "#000000", "INPUT": "#004EA1", "TEXT_INPUT": "#FFFFFF", "SCROLL": "#5EA7FF", + "BUTTON": ("#FFFFFF", "#0079D3"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 0, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "ACCENT1": "#FF0266", "ACCENT2": "#FF5C93", "ACCENT3": "#C5003C", }, + "LightGrey1": {"BACKGROUND": "#ffffff", "TEXT": "#1a1a1b", "INPUT": "#dae0e6", "TEXT_INPUT": "#222222", "SCROLL": "#a5a4a4", + "BUTTON": ("#FFFFFF", "#0079d3"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "ACCENT1": "#ff5414", "ACCENT2": "#33a8ff", "ACCENT3": "#dbf0ff", }, + "DarkBrown": {"BACKGROUND": "#282923", "TEXT": "#E7DB74", "INPUT": "#393a32", "TEXT_INPUT": "#E7C855", "SCROLL": "#E7C855", + "BUTTON": ("#E7C855", "#284B5A"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "ACCENT1": "#c15226", "ACCENT2": "#7a4d5f", "ACCENT3": "#889743", }, + "LightGreen1": {"BACKGROUND": "#9FB8AD", "TEXT": "#000000", "INPUT": "#F7F3EC", "TEXT_INPUT": "#000000", "SCROLL": "#F7F3EC", + "BUTTON": ("#FFFFFF", "#475841"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "DarkGrey": {"BACKGROUND": "#404040", "TEXT": "#FFFFFF", "INPUT": "#4D4D4D", "TEXT_INPUT": "#FFFFFF", "SCROLL": "#707070", "BUTTON": ("#FFFFFF", "#004F00"), + "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "LightGreen2": {"BACKGROUND": "#B7CECE", "TEXT": "#000000", "INPUT": "#FDFFF7", "TEXT_INPUT": "#000000", "SCROLL": "#FDFFF7", + "BUTTON": ("#FFFFFF", "#658268"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "ACCENT1": "#76506d", + "ACCENT2": "#5148f1", "ACCENT3": "#0a1c84", "PROGRESS_DEPTH": 0, }, + "DarkGrey1": {"BACKGROUND": "#404040", "TEXT": "#FFFFFF", "INPUT": "#FFFFFF", "TEXT_INPUT": "#000000", "SCROLL": "#707070", + "BUTTON": ("#FFFFFF", "#004F00"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "DarkBlack": {"BACKGROUND": "#000000", "TEXT": "#FFFFFF", "INPUT": "#4D4D4D", "TEXT_INPUT": "#FFFFFF", "SCROLL": "#707070", + "BUTTON": ("#000000", "#FFFFFF"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "LightBrown": {"BACKGROUND": "#fdf6e3", "TEXT": "#268bd1", "INPUT": "#eee8d5", "TEXT_INPUT": "#6c71c3", "SCROLL": "#eee8d5", + "BUTTON": ("#FFFFFF", "#063542"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "LightBrown1": {"BACKGROUND": "#e5dece", "TEXT": "#063289", "INPUT": "#f9f8f4", "TEXT_INPUT": "#242834", "SCROLL": "#eee8d5", + "BUTTON": ("#FFFFFF", "#063289"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "DarkBlue1": {"BACKGROUND": "#242834", "TEXT": "#dfe6f8", "INPUT": "#97755c", "TEXT_INPUT": "#FFFFFF", "SCROLL": "#a9afbb", + "BUTTON": ("#FFFFFF", "#063289"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "DarkBrown1": {"BACKGROUND": "#2c2825", "TEXT": "#fdcb52", "INPUT": "#705e52", "TEXT_INPUT": "#fdcb52", "SCROLL": "#705e52", + "BUTTON": ("#000000", "#fdcb52"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "DarkBlue2": {"BACKGROUND": "#1a2835", "TEXT": "#d1ecff", "INPUT": "#335267", "TEXT_INPUT": "#acc2d0", "SCROLL": "#1b6497", + "BUTTON": ("#000000", "#fafaf8"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "DarkBrown2": {"BACKGROUND": "#280001", "TEXT": "#FFFFFF", "INPUT": "#d8d584", "TEXT_INPUT": "#000000", "SCROLL": "#763e00", + "BUTTON": ("#000000", "#daad28"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "DarkGreen": {"BACKGROUND": "#82a459", "TEXT": "#000000", "INPUT": "#d8d584", "TEXT_INPUT": "#000000", "SCROLL": "#e3ecf3", + "BUTTON": ("#FFFFFF", "#517239"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "LightBlue1": {"BACKGROUND": "#A5CADD", "TEXT": "#6E266E", "INPUT": "#E0F5FF", "TEXT_INPUT": "#000000", "SCROLL": "#E0F5FF", + "BUTTON": ("#FFFFFF", "#303952"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "LightPurple": {"BACKGROUND": "#B0AAC2", "TEXT": "#000000", "INPUT": "#F2EFE8", "SCROLL": "#F2EFE8", "TEXT_INPUT": "#000000", + "BUTTON": ("#000000", "#C2D4D8"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "LightBlue2": {"BACKGROUND": "#AAB6D3", "TEXT": "#000000", "INPUT": "#F1F4FC", "SCROLL": "#F1F4FC", "TEXT_INPUT": "#000000", + "BUTTON": ("#FFFFFF", "#7186C7"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "LightGreen3": {"BACKGROUND": "#A8C1B4", "TEXT": "#000000", "INPUT": "#DDE0DE", "SCROLL": "#E3E3E3", "TEXT_INPUT": "#000000", + "BUTTON": ("#FFFFFF", "#6D9F85"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "DarkBlue3": {"BACKGROUND": "#64778d", "TEXT": "#FFFFFF", "INPUT": "#f0f3f7", "SCROLL": "#A6B2BE", "TEXT_INPUT": "#000000", + "BUTTON": ("#FFFFFF", "#283b5b"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "LightGreen4": {"BACKGROUND": "#b4ffb4", "TEXT": "#000000", "INPUT": "#ffff64", "SCROLL": "#ffb482", "TEXT_INPUT": "#000000", + "BUTTON": ("#000000", "#ffa0dc"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "LightGreen5": {"BACKGROUND": "#92aa9d", "TEXT": "#000000", "INPUT": "#fcfff6", "SCROLL": "#fcfff6", "TEXT_INPUT": "#000000", + "BUTTON": ("#000000", "#d0dbbd"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "LightBrown2": {"BACKGROUND": "#a7ad7f", "TEXT": "#000000", "INPUT": "#e6d3a8", "SCROLL": "#e6d3a8", "TEXT_INPUT": "#000000", + "BUTTON": ("#FFFFFF", "#5d907d"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "LightBrown3": {"BACKGROUND": "#efeccb", "TEXT": "#012f2f", "INPUT": "#e6d3a8", "SCROLL": "#e6d3a8", "TEXT_INPUT": "#012f2f", + "BUTTON": ("#FFFFFF", "#046380"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "LightBlue3": {"BACKGROUND": "#a8cfdd", "TEXT": "#000000", "INPUT": "#dfedf2", "SCROLL": "#dfedf2", "TEXT_INPUT": "#000000", + "BUTTON": ("#FFFFFF", "#183440"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "LightBrown4": {"BACKGROUND": "#d7c79e", "TEXT": "#a35638", "INPUT": "#9dab86", "TEXT_INPUT": "#000000", "SCROLL": "#a35638", + "BUTTON": ("#FFFFFF", "#a35638"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#a35638", "#9dab86", "#e08f62", "#d7c79e"], }, + "DarkTeal": {"BACKGROUND": "#003f5c", "TEXT": "#fb5b5a", "INPUT": "#bc4873", "TEXT_INPUT": "#FFFFFF", "SCROLL": "#bc4873", "BUTTON": ("#FFFFFF", "#fb5b5a"), + "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#003f5c", "#472b62", "#bc4873", "#fb5b5a"], }, + "DarkPurple": {"BACKGROUND": "#472b62", "TEXT": "#fb5b5a", "INPUT": "#bc4873", "TEXT_INPUT": "#FFFFFF", "SCROLL": "#bc4873", + "BUTTON": ("#FFFFFF", "#472b62"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#003f5c", "#472b62", "#bc4873", "#fb5b5a"], }, + "LightGreen6": {"BACKGROUND": "#eafbea", "TEXT": "#1f6650", "INPUT": "#6f9a8d", "TEXT_INPUT": "#FFFFFF", "SCROLL": "#1f6650", + "BUTTON": ("#FFFFFF", "#1f6650"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#1f6650", "#6f9a8d", "#ea5e5e", "#eafbea"], }, + "DarkGrey2": {"BACKGROUND": "#2b2b28", "TEXT": "#f8f8f8", "INPUT": "#f1d6ab", "TEXT_INPUT": "#000000", "SCROLL": "#f1d6ab", + "BUTTON": ("#2b2b28", "#e3b04b"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#2b2b28", "#e3b04b", "#f1d6ab", "#f8f8f8"], }, + "LightBrown6": {"BACKGROUND": "#f9b282", "TEXT": "#8f4426", "INPUT": "#de6b35", "TEXT_INPUT": "#FFFFFF", "SCROLL": "#8f4426", + "BUTTON": ("#FFFFFF", "#8f4426"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#8f4426", "#de6b35", "#64ccda", "#f9b282"], }, + "DarkTeal1": {"BACKGROUND": "#396362", "TEXT": "#ffe7d1", "INPUT": "#f6c89f", "TEXT_INPUT": "#000000", "SCROLL": "#f6c89f", + "BUTTON": ("#ffe7d1", "#4b8e8d"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#396362", "#4b8e8d", "#f6c89f", "#ffe7d1"], }, + "LightBrown7": {"BACKGROUND": "#f6c89f", "TEXT": "#396362", "INPUT": "#4b8e8d", "TEXT_INPUT": "#FFFFFF", "SCROLL": "#396362", + "BUTTON": ("#FFFFFF", "#396362"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#396362", "#4b8e8d", "#f6c89f", "#ffe7d1"], }, + "DarkPurple1": {"BACKGROUND": "#0c093c", "TEXT": "#fad6d6", "INPUT": "#eea5f6", "TEXT_INPUT": "#000000", "SCROLL": "#eea5f6", + "BUTTON": ("#FFFFFF", "#df42d1"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#0c093c", "#df42d1", "#eea5f6", "#fad6d6"], }, + "DarkGrey3": {"BACKGROUND": "#211717", "TEXT": "#dfddc7", "INPUT": "#f58b54", "TEXT_INPUT": "#000000", "SCROLL": "#f58b54", + "BUTTON": ("#dfddc7", "#a34a28"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#211717", "#a34a28", "#f58b54", "#dfddc7"], }, + "LightBrown8": {"BACKGROUND": "#dfddc7", "TEXT": "#211717", "INPUT": "#a34a28", "TEXT_INPUT": "#dfddc7", "SCROLL": "#211717", + "BUTTON": ("#dfddc7", "#a34a28"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#211717", "#a34a28", "#f58b54", "#dfddc7"], }, + "DarkBlue4": {"BACKGROUND": "#494ca2", "TEXT": "#e3e7f1", "INPUT": "#c6cbef", "TEXT_INPUT": "#000000", "SCROLL": "#c6cbef", + "BUTTON": ("#FFFFFF", "#8186d5"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#494ca2", "#8186d5", "#c6cbef", "#e3e7f1"], }, + "LightBlue4": {"BACKGROUND": "#5c94bd", "TEXT": "#470938", "INPUT": "#1a3e59", "TEXT_INPUT": "#FFFFFF", "SCROLL": "#470938", + "BUTTON": ("#FFFFFF", "#470938"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#470938", "#1a3e59", "#5c94bd", "#f2d6eb"], }, + "DarkTeal2": {"BACKGROUND": "#394a6d", "TEXT": "#c0ffb3", "INPUT": "#52de97", "TEXT_INPUT": "#000000", "SCROLL": "#52de97", + "BUTTON": ("#c0ffb3", "#394a6d"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#394a6d", "#3c9d9b", "#52de97", "#c0ffb3"], }, + "DarkTeal3": {"BACKGROUND": "#3c9d9b", "TEXT": "#c0ffb3", "INPUT": "#52de97", "TEXT_INPUT": "#000000", "SCROLL": "#52de97", + "BUTTON": ("#c0ffb3", "#394a6d"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#394a6d", "#3c9d9b", "#52de97", "#c0ffb3"], }, + "DarkPurple5": {"BACKGROUND": "#730068", "TEXT": "#f6f078", "INPUT": "#01d28e", "TEXT_INPUT": "#000000", "SCROLL": "#01d28e", + "BUTTON": ("#f6f078", "#730068"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#730068", "#434982", "#01d28e", "#f6f078"], }, + "DarkPurple2": {"BACKGROUND": "#202060", "TEXT": "#b030b0", "INPUT": "#602080", "TEXT_INPUT": "#FFFFFF", "SCROLL": "#602080", + "BUTTON": ("#FFFFFF", "#202040"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#202040", "#202060", "#602080", "#b030b0"], }, + "DarkBlue5": {"BACKGROUND": "#000272", "TEXT": "#ff6363", "INPUT": "#a32f80", "TEXT_INPUT": "#FFFFFF", "SCROLL": "#a32f80", + "BUTTON": ("#FFFFFF", "#341677"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#000272", "#341677", "#a32f80", "#ff6363"], }, + "LightGrey2": {"BACKGROUND": "#f6f6f6", "TEXT": "#420000", "INPUT": "#d4d7dd", "TEXT_INPUT": "#420000", "SCROLL": "#420000", + "BUTTON": ("#420000", "#d4d7dd"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#420000", "#d4d7dd", "#eae9e9", "#f6f6f6"], }, + "LightGrey3": {"BACKGROUND": "#eae9e9", "TEXT": "#420000", "INPUT": "#d4d7dd", "TEXT_INPUT": "#420000", "SCROLL": "#420000", + "BUTTON": ("#420000", "#d4d7dd"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#420000", "#d4d7dd", "#eae9e9", "#f6f6f6"], }, + "DarkBlue6": {"BACKGROUND": "#01024e", "TEXT": "#ff6464", "INPUT": "#8b4367", "TEXT_INPUT": "#FFFFFF", "SCROLL": "#8b4367", + "BUTTON": ("#FFFFFF", "#543864"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#01024e", "#543864", "#8b4367", "#ff6464"], }, + "DarkBlue7": {"BACKGROUND": "#241663", "TEXT": "#eae7af", "INPUT": "#a72693", "TEXT_INPUT": "#eae7af", "SCROLL": "#a72693", + "BUTTON": ("#eae7af", "#160f30"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#160f30", "#241663", "#a72693", "#eae7af"], }, + "LightBrown9": {"BACKGROUND": "#f6d365", "TEXT": "#3a1f5d", "INPUT": "#c83660", "TEXT_INPUT": "#f6d365", "SCROLL": "#3a1f5d", + "BUTTON": ("#f6d365", "#c83660"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#3a1f5d", "#c83660", "#e15249", "#f6d365"], }, + "DarkPurple3": {"BACKGROUND": "#6e2142", "TEXT": "#ffd692", "INPUT": "#e16363", "TEXT_INPUT": "#ffd692", "SCROLL": "#e16363", + "BUTTON": ("#ffd692", "#943855"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#6e2142", "#943855", "#e16363", "#ffd692"], }, + "LightBrown10": {"BACKGROUND": "#ffd692", "TEXT": "#6e2142", "INPUT": "#943855", "TEXT_INPUT": "#FFFFFF", "SCROLL": "#6e2142", + "BUTTON": ("#FFFFFF", "#6e2142"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#6e2142", "#943855", "#e16363", "#ffd692"], }, + "DarkPurple4": {"BACKGROUND": "#200f21", "TEXT": "#f638dc", "INPUT": "#5a3d5c", "TEXT_INPUT": "#FFFFFF", "SCROLL": "#5a3d5c", + "BUTTON": ("#FFFFFF", "#382039"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#200f21", "#382039", "#5a3d5c", "#f638dc"], }, + "LightBlue5": {"BACKGROUND": "#b2fcff", "TEXT": "#3e64ff", "INPUT": "#5edfff", "TEXT_INPUT": "#000000", "SCROLL": "#3e64ff", + "BUTTON": ("#FFFFFF", "#3e64ff"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#3e64ff", "#5edfff", "#b2fcff", "#ecfcff"], }, + "DarkTeal4": {"BACKGROUND": "#464159", "TEXT": "#c7f0db", "INPUT": "#8bbabb", "TEXT_INPUT": "#000000", "SCROLL": "#8bbabb", + "BUTTON": ("#FFFFFF", "#6c7b95"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#464159", "#6c7b95", "#8bbabb", "#c7f0db"], }, + "LightTeal": {"BACKGROUND": "#c7f0db", "TEXT": "#464159", "INPUT": "#6c7b95", "TEXT_INPUT": "#FFFFFF", "SCROLL": "#464159", + "BUTTON": ("#FFFFFF", "#464159"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#464159", "#6c7b95", "#8bbabb", "#c7f0db"], }, + "DarkTeal5": {"BACKGROUND": "#8bbabb", "TEXT": "#464159", "INPUT": "#6c7b95", "TEXT_INPUT": "#FFFFFF", "SCROLL": "#464159", + "BUTTON": ("#c7f0db", "#6c7b95"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#464159", "#6c7b95", "#8bbabb", "#c7f0db"], }, + "LightGrey4": {"BACKGROUND": "#faf5ef", "TEXT": "#672f2f", "INPUT": "#99b19c", "TEXT_INPUT": "#672f2f", "SCROLL": "#672f2f", + "BUTTON": ("#672f2f", "#99b19c"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#672f2f", "#99b19c", "#d7d1c9", "#faf5ef"], }, + "LightGreen7": {"BACKGROUND": "#99b19c", "TEXT": "#faf5ef", "INPUT": "#d7d1c9", "TEXT_INPUT": "#000000", "SCROLL": "#d7d1c9", + "BUTTON": ("#FFFFFF", "#99b19c"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#672f2f", "#99b19c", "#d7d1c9", "#faf5ef"], }, + "LightGrey5": {"BACKGROUND": "#d7d1c9", "TEXT": "#672f2f", "INPUT": "#99b19c", "TEXT_INPUT": "#672f2f", "SCROLL": "#672f2f", + "BUTTON": ("#FFFFFF", "#672f2f"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#672f2f", "#99b19c", "#d7d1c9", "#faf5ef"], }, + "DarkBrown3": {"BACKGROUND": "#a0855b", "TEXT": "#f9f6f2", "INPUT": "#f1d6ab", "TEXT_INPUT": "#000000", "SCROLL": "#f1d6ab", + "BUTTON": ("#FFFFFF", "#38470b"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#38470b", "#a0855b", "#f1d6ab", "#f9f6f2"], }, + "LightBrown11": {"BACKGROUND": "#f1d6ab", "TEXT": "#38470b", "INPUT": "#a0855b", "TEXT_INPUT": "#FFFFFF", "SCROLL": "#38470b", + "BUTTON": ("#f9f6f2", "#a0855b"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#38470b", "#a0855b", "#f1d6ab", "#f9f6f2"], }, + "DarkRed": {"BACKGROUND": "#83142c", "TEXT": "#f9d276", "INPUT": "#ad1d45", "TEXT_INPUT": "#FFFFFF", "SCROLL": "#ad1d45", "BUTTON": ("#f9d276", "#ad1d45"), + "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#44000d", "#83142c", "#ad1d45", "#f9d276"], }, + "DarkTeal6": {"BACKGROUND": "#204969", "TEXT": "#fff7f7", "INPUT": "#dadada", "TEXT_INPUT": "#000000", "SCROLL": "#dadada", + "BUTTON": ("#000000", "#fff7f7"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#204969", "#08ffc8", "#dadada", "#fff7f7"], }, + "DarkBrown4": {"BACKGROUND": "#252525", "TEXT": "#ff0000", "INPUT": "#af0404", "TEXT_INPUT": "#FFFFFF", "SCROLL": "#af0404", + "BUTTON": ("#FFFFFF", "#252525"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#252525", "#414141", "#af0404", "#ff0000"], }, + "LightYellow": {"BACKGROUND": "#f4ff61", "TEXT": "#27aa80", "INPUT": "#32ff6a", "TEXT_INPUT": "#000000", "SCROLL": "#27aa80", + "BUTTON": ("#f4ff61", "#27aa80"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#27aa80", "#32ff6a", "#a8ff3e", "#f4ff61"], }, + "DarkGreen1": {"BACKGROUND": "#2b580c", "TEXT": "#fdef96", "INPUT": "#f7b71d", "TEXT_INPUT": "#000000", "SCROLL": "#f7b71d", + "BUTTON": ("#fdef96", "#2b580c"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#2b580c", "#afa939", "#f7b71d", "#fdef96"], }, + "LightGreen8": {"BACKGROUND": "#c8dad3", "TEXT": "#63707e", "INPUT": "#93b5b3", "TEXT_INPUT": "#000000", "SCROLL": "#63707e", + "BUTTON": ("#FFFFFF", "#63707e"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#63707e", "#93b5b3", "#c8dad3", "#f2f6f5"], }, + "DarkTeal7": {"BACKGROUND": "#248ea9", "TEXT": "#fafdcb", "INPUT": "#aee7e8", "TEXT_INPUT": "#000000", "SCROLL": "#aee7e8", + "BUTTON": ("#000000", "#fafdcb"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#248ea9", "#28c3d4", "#aee7e8", "#fafdcb"], }, + "DarkBlue8": {"BACKGROUND": "#454d66", "TEXT": "#d9d872", "INPUT": "#58b368", "TEXT_INPUT": "#000000", "SCROLL": "#58b368", + "BUTTON": ("#000000", "#009975"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#009975", "#454d66", "#58b368", "#d9d872"], }, + "DarkBlue9": {"BACKGROUND": "#263859", "TEXT": "#ff6768", "INPUT": "#6b778d", "TEXT_INPUT": "#FFFFFF", "SCROLL": "#6b778d", + "BUTTON": ("#ff6768", "#263859"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#17223b", "#263859", "#6b778d", "#ff6768"], }, + "DarkBlue10": {"BACKGROUND": "#0028ff", "TEXT": "#f1f4df", "INPUT": "#10eaf0", "TEXT_INPUT": "#000000", "SCROLL": "#10eaf0", + "BUTTON": ("#f1f4df", "#24009c"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#24009c", "#0028ff", "#10eaf0", "#f1f4df"], }, + "DarkBlue11": {"BACKGROUND": "#6384b3", "TEXT": "#e6f0b6", "INPUT": "#b8e9c0", "TEXT_INPUT": "#000000", "SCROLL": "#b8e9c0", + "BUTTON": ("#e6f0b6", "#684949"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#684949", "#6384b3", "#b8e9c0", "#e6f0b6"], }, + "DarkTeal8": {"BACKGROUND": "#71a0a5", "TEXT": "#212121", "INPUT": "#665c84", "TEXT_INPUT": "#FFFFFF", "SCROLL": "#212121", + "BUTTON": ("#fab95b", "#665c84"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#212121", "#665c84", "#71a0a5", "#fab95b"], }, + "DarkRed1": {"BACKGROUND": "#c10000", "TEXT": "#eeeeee", "INPUT": "#dedede", "TEXT_INPUT": "#000000", "SCROLL": "#dedede", "BUTTON": ("#c10000", "#eeeeee"), + "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#c10000", "#ff4949", "#dedede", "#eeeeee"], }, + "LightBrown5": {"BACKGROUND": "#fff591", "TEXT": "#e41749", "INPUT": "#f5587b", "TEXT_INPUT": "#000000", "SCROLL": "#e41749", + "BUTTON": ("#fff591", "#e41749"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#e41749", "#f5587b", "#ff8a5c", "#fff591"], }, + "LightGreen9": {"BACKGROUND": "#f1edb3", "TEXT": "#3b503d", "INPUT": "#4a746e", "TEXT_INPUT": "#f1edb3", "SCROLL": "#3b503d", + "BUTTON": ("#f1edb3", "#3b503d"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#3b503d", "#4a746e", "#c8cf94", "#f1edb3"], "DESCRIPTION": ["Green", "Turquoise", "Yellow"], }, + "DarkGreen2": {"BACKGROUND": "#3b503d", "TEXT": "#f1edb3", "INPUT": "#c8cf94", "TEXT_INPUT": "#000000", "SCROLL": "#c8cf94", + "BUTTON": ("#f1edb3", "#3b503d"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#3b503d", "#4a746e", "#c8cf94", "#f1edb3"], "DESCRIPTION": ["Green", "Turquoise", "Yellow"], }, + "LightGray1": {"BACKGROUND": "#f2f2f2", "TEXT": "#222831", "INPUT": "#393e46", "TEXT_INPUT": "#FFFFFF", "SCROLL": "#222831", + "BUTTON": ("#f2f2f2", "#222831"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#222831", "#393e46", "#f96d00", "#f2f2f2"], "DESCRIPTION": ["#000000", "Grey", "Orange", "Grey", "Autumn"], }, + "DarkGrey4": {"BACKGROUND": "#52524e", "TEXT": "#e9e9e5", "INPUT": "#d4d6c8", "TEXT_INPUT": "#000000", "SCROLL": "#d4d6c8", + "BUTTON": ("#FFFFFF", "#9a9b94"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#52524e", "#9a9b94", "#d4d6c8", "#e9e9e5"], "DESCRIPTION": ["Grey", "Pastel", "Winter"], }, + "DarkBlue12": {"BACKGROUND": "#324e7b", "TEXT": "#f8f8f8", "INPUT": "#86a6df", "TEXT_INPUT": "#000000", "SCROLL": "#86a6df", + "BUTTON": ("#FFFFFF", "#5068a9"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#324e7b", "#5068a9", "#86a6df", "#f8f8f8"], "DESCRIPTION": ["Blue", "Grey", "Cold", "Winter"], }, + "DarkPurple6": {"BACKGROUND": "#070739", "TEXT": "#e1e099", "INPUT": "#c327ab", "TEXT_INPUT": "#e1e099", "SCROLL": "#c327ab", + "BUTTON": ("#e1e099", "#521477"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#070739", "#521477", "#c327ab", "#e1e099"], "DESCRIPTION": ["#000000", "Purple", "Yellow", "Dark"], }, + "DarkPurple7": {"BACKGROUND": "#191930", "TEXT": "#B1B7C5", "INPUT": "#232B5C", "TEXT_INPUT": "#D0E3E7", "SCROLL": "#B1B7C5", + "BUTTON": ("#272D38", "#B1B7C5"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "DarkBlue13": {"BACKGROUND": "#203562", "TEXT": "#e3e8f8", "INPUT": "#c0c5cd", "TEXT_INPUT": "#000000", "SCROLL": "#c0c5cd", + "BUTTON": ("#FFFFFF", "#3e588f"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#203562", "#3e588f", "#c0c5cd", "#e3e8f8"], "DESCRIPTION": ["Blue", "Grey", "Wedding", "Cold"], }, + "DarkBrown5": {"BACKGROUND": "#3c1b1f", "TEXT": "#f6e1b5", "INPUT": "#e2bf81", "TEXT_INPUT": "#000000", "SCROLL": "#e2bf81", + "BUTTON": ("#3c1b1f", "#f6e1b5"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#3c1b1f", "#b21e4b", "#e2bf81", "#f6e1b5"], "DESCRIPTION": ["Brown", "Red", "Yellow", "Warm"], }, + "DarkGreen3": {"BACKGROUND": "#062121", "TEXT": "#eeeeee", "INPUT": "#e4dcad", "TEXT_INPUT": "#000000", "SCROLL": "#e4dcad", + "BUTTON": ("#eeeeee", "#181810"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#062121", "#181810", "#e4dcad", "#eeeeee"], "DESCRIPTION": ["#000000", "#000000", "Brown", "Grey"], }, + "DarkBlack1": {"BACKGROUND": "#181810", "TEXT": "#eeeeee", "INPUT": "#e4dcad", "TEXT_INPUT": "#000000", "SCROLL": "#e4dcad", + "BUTTON": ("#FFFFFF", "#062121"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#062121", "#181810", "#e4dcad", "#eeeeee"], "DESCRIPTION": ["#000000", "#000000", "Brown", "Grey"], }, + "DarkGrey5": {"BACKGROUND": "#343434", "TEXT": "#f3f3f3", "INPUT": "#e9dcbe", "TEXT_INPUT": "#000000", "SCROLL": "#e9dcbe", + "BUTTON": ("#FFFFFF", "#8e8b82"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#343434", "#8e8b82", "#e9dcbe", "#f3f3f3"], "DESCRIPTION": ["Grey", "Brown"], }, + "LightBrown12": {"BACKGROUND": "#8e8b82", "TEXT": "#f3f3f3", "INPUT": "#e9dcbe", "TEXT_INPUT": "#000000", "SCROLL": "#e9dcbe", + "BUTTON": ("#f3f3f3", "#8e8b82"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#343434", "#8e8b82", "#e9dcbe", "#f3f3f3"], "DESCRIPTION": ["Grey", "Brown"], }, + "DarkTeal9": {"BACKGROUND": "#13445a", "TEXT": "#fef4e8", "INPUT": "#446878", "TEXT_INPUT": "#FFFFFF", "SCROLL": "#446878", + "BUTTON": ("#fef4e8", "#446878"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#13445a", "#970747", "#446878", "#fef4e8"], "DESCRIPTION": ["Red", "Grey", "Blue", "Wedding", "Retro"], }, + "DarkBlue14": {"BACKGROUND": "#21273d", "TEXT": "#f1f6f8", "INPUT": "#b9d4f1", "TEXT_INPUT": "#000000", "SCROLL": "#b9d4f1", + "BUTTON": ("#FFFFFF", "#6a759b"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#21273d", "#6a759b", "#b9d4f1", "#f1f6f8"], "DESCRIPTION": ["Blue", "#000000", "Grey", "Cold", "Winter"], }, + "LightBlue6": {"BACKGROUND": "#f1f6f8", "TEXT": "#21273d", "INPUT": "#6a759b", "TEXT_INPUT": "#FFFFFF", "SCROLL": "#21273d", + "BUTTON": ("#f1f6f8", "#6a759b"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#21273d", "#6a759b", "#b9d4f1", "#f1f6f8"], "DESCRIPTION": ["Blue", "#000000", "Grey", "Cold", "Winter"], }, + "DarkGreen4": {"BACKGROUND": "#044343", "TEXT": "#e4e4e4", "INPUT": "#045757", "TEXT_INPUT": "#e4e4e4", "SCROLL": "#045757", + "BUTTON": ("#e4e4e4", "#045757"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#222222", "#044343", "#045757", "#e4e4e4"], "DESCRIPTION": ["#000000", "Turquoise", "Grey", "Dark"], }, + "DarkGreen5": {"BACKGROUND": "#1b4b36", "TEXT": "#e0e7f1", "INPUT": "#aebd77", "TEXT_INPUT": "#000000", "SCROLL": "#aebd77", + "BUTTON": ("#FFFFFF", "#538f6a"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#1b4b36", "#538f6a", "#aebd77", "#e0e7f1"], "DESCRIPTION": ["Green", "Grey"], }, + "DarkTeal10": {"BACKGROUND": "#0d3446", "TEXT": "#d8dfe2", "INPUT": "#71adb5", "TEXT_INPUT": "#000000", "SCROLL": "#71adb5", + "BUTTON": ("#FFFFFF", "#176d81"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#0d3446", "#176d81", "#71adb5", "#d8dfe2"], "DESCRIPTION": ["Grey", "Turquoise", "Winter", "Cold"], }, + "DarkGrey6": {"BACKGROUND": "#3e3e3e", "TEXT": "#ededed", "INPUT": "#68868c", "TEXT_INPUT": "#ededed", "SCROLL": "#68868c", + "BUTTON": ("#FFFFFF", "#405559"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#3e3e3e", "#405559", "#68868c", "#ededed"], "DESCRIPTION": ["Grey", "Turquoise", "Winter"], }, + "DarkTeal11": {"BACKGROUND": "#405559", "TEXT": "#ededed", "INPUT": "#68868c", "TEXT_INPUT": "#ededed", "SCROLL": "#68868c", + "BUTTON": ("#ededed", "#68868c"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#3e3e3e", "#405559", "#68868c", "#ededed"], "DESCRIPTION": ["Grey", "Turquoise", "Winter"], }, + "LightBlue7": {"BACKGROUND": "#9ed0e0", "TEXT": "#19483f", "INPUT": "#5c868e", "TEXT_INPUT": "#FFFFFF", "SCROLL": "#19483f", + "BUTTON": ("#FFFFFF", "#19483f"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#19483f", "#5c868e", "#ff6a38", "#9ed0e0"], "DESCRIPTION": ["Orange", "Blue", "Turquoise"], }, + "LightGreen10": {"BACKGROUND": "#d8ebb5", "TEXT": "#205d67", "INPUT": "#639a67", "TEXT_INPUT": "#FFFFFF", "SCROLL": "#205d67", + "BUTTON": ("#d8ebb5", "#205d67"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#205d67", "#639a67", "#d9bf77", "#d8ebb5"], "DESCRIPTION": ["Blue", "Green", "Brown", "Vintage"], }, + "DarkBlue15": {"BACKGROUND": "#151680", "TEXT": "#f1fea4", "INPUT": "#375fc0", "TEXT_INPUT": "#f1fea4", "SCROLL": "#375fc0", + "BUTTON": ("#f1fea4", "#1c44ac"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#151680", "#1c44ac", "#375fc0", "#f1fea4"], "DESCRIPTION": ["Blue", "Yellow", "Cold"], }, + "DarkBlue16": {"BACKGROUND": "#1c44ac", "TEXT": "#f1fea4", "INPUT": "#375fc0", "TEXT_INPUT": "#f1fea4", "SCROLL": "#375fc0", + "BUTTON": ("#f1fea4", "#151680"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#151680", "#1c44ac", "#375fc0", "#f1fea4"], "DESCRIPTION": ["Blue", "Yellow", "Cold"], }, + "DarkTeal12": {"BACKGROUND": "#004a7c", "TEXT": "#fafafa", "INPUT": "#e8f1f5", "TEXT_INPUT": "#000000", "SCROLL": "#e8f1f5", + "BUTTON": ("#fafafa", "#005691"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#004a7c", "#005691", "#e8f1f5", "#fafafa"], "DESCRIPTION": ["Grey", "Blue", "Cold", "Winter"], }, + "LightBrown13": {"BACKGROUND": "#ebf5ee", "TEXT": "#921224", "INPUT": "#bdc6b8", "TEXT_INPUT": "#921224", "SCROLL": "#921224", + "BUTTON": ("#FFFFFF", "#921224"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#921224", "#bdc6b8", "#bce0da", "#ebf5ee"], "DESCRIPTION": ["Red", "Blue", "Grey", "Vintage", "Wedding"], }, + "DarkBlue17": {"BACKGROUND": "#21294c", "TEXT": "#f9f2d7", "INPUT": "#f2dea8", "TEXT_INPUT": "#000000", "SCROLL": "#f2dea8", + "BUTTON": ("#f9f2d7", "#141829"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#141829", "#21294c", "#f2dea8", "#f9f2d7"], "DESCRIPTION": ["#000000", "Blue", "Yellow"], }, + "DarkBrown6": {"BACKGROUND": "#785e4d", "TEXT": "#f2eee3", "INPUT": "#baaf92", "TEXT_INPUT": "#000000", "SCROLL": "#baaf92", + "BUTTON": ("#FFFFFF", "#785e4d"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#785e4d", "#ff8426", "#baaf92", "#f2eee3"], "DESCRIPTION": ["Grey", "Brown", "Orange", "Autumn"], }, + "DarkGreen6": {"BACKGROUND": "#5c715e", "TEXT": "#f2f9f1", "INPUT": "#ddeedf", "TEXT_INPUT": "#000000", "SCROLL": "#ddeedf", + "BUTTON": ("#f2f9f1", "#5c715e"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#5c715e", "#b6cdbd", "#ddeedf", "#f2f9f1"], "DESCRIPTION": ["Grey", "Green", "Vintage"], }, + "DarkGreen7": {"BACKGROUND": "#0C231E", "TEXT": "#efbe1c", "INPUT": "#153C33", "TEXT_INPUT": "#efbe1c", "SCROLL": "#153C33", + "BUTTON": ("#efbe1c", "#153C33"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "DarkGrey7": {"BACKGROUND": "#4b586e", "TEXT": "#dddddd", "INPUT": "#574e6d", "TEXT_INPUT": "#dddddd", "SCROLL": "#574e6d", + "BUTTON": ("#dddddd", "#43405d"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#43405d", "#4b586e", "#574e6d", "#dddddd"], "DESCRIPTION": ["Grey", "Winter", "Cold"], }, + "DarkRed2": {"BACKGROUND": "#ab1212", "TEXT": "#f6e4b5", "INPUT": "#cd3131", "TEXT_INPUT": "#f6e4b5", "SCROLL": "#cd3131", "BUTTON": ("#f6e4b5", "#ab1212"), + "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#ab1212", "#1fad9f", "#cd3131", "#f6e4b5"], "DESCRIPTION": ["Turquoise", "Red", "Yellow"], }, + "LightGrey6": {"BACKGROUND": "#e3e3e3", "TEXT": "#233142", "INPUT": "#455d7a", "TEXT_INPUT": "#e3e3e3", "SCROLL": "#233142", + "BUTTON": ("#e3e3e3", "#455d7a"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, + "COLOR_LIST": ["#233142", "#455d7a", "#f95959", "#e3e3e3"], "DESCRIPTION": ["#000000", "Blue", "Red", "Grey"], }, + "HotDogStand": {"BACKGROUND": "red", "TEXT": "yellow", "INPUT": "yellow", "TEXT_INPUT": "#000000", "SCROLL": "yellow", "BUTTON": ("red", "yellow"), + "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "DarkGrey8": {"BACKGROUND": "#19232D", "TEXT": "#ffffff", "INPUT": "#32414B", "TEXT_INPUT": "#ffffff", "SCROLL": "#505F69", + "BUTTON": ("#ffffff", "#32414B"), "PROGRESS": ("#505F69", "#32414B"), "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "DarkGrey9": {"BACKGROUND": "#36393F", "TEXT": "#DCDDDE", "INPUT": "#40444B", "TEXT_INPUT": "#ffffff", "SCROLL": "#202225", + "BUTTON": ("#202225", "#B9BBBE"), "PROGRESS": ("#202225", "#40444B"), "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "DarkGrey10": {"BACKGROUND": "#1c1e23", "TEXT": "#cccdcf", "INPUT": "#272a31", "TEXT_INPUT": "#8b9fde", "SCROLL": "#313641", + "BUTTON": ("#f5f5f6", "#2e3d5a"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "DarkGrey11": {"BACKGROUND": "#1c1e23", "TEXT": "#cccdcf", "INPUT": "#313641", "TEXT_INPUT": "#cccdcf", "SCROLL": "#313641", + "BUTTON": ("#f5f5f6", "#313641"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "DarkGrey12": {"BACKGROUND": "#1c1e23", "TEXT": "#8b9fde", "INPUT": "#313641", "TEXT_INPUT": "#8b9fde", "SCROLL": "#313641", + "BUTTON": ("#cccdcf", "#2e3d5a"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "DarkGrey13": {"BACKGROUND": "#1c1e23", "TEXT": "#cccdcf", "INPUT": "#272a31", "TEXT_INPUT": "#cccdcf", "SCROLL": "#313641", + "BUTTON": ("#8b9fde", "#313641"), "PROGRESS": ("#cccdcf", "#272a31"), "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "DarkGrey14": {"BACKGROUND": "#24292e", "TEXT": "#fafbfc", "INPUT": "#1d2125", "TEXT_INPUT": "#fafbfc", "SCROLL": "#1d2125", + "BUTTON": ("#fafbfc", "#155398"), "PROGRESS": ("#155398", "#1d2125"), "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, }, + "DarkBrown7": {"BACKGROUND": "#2c2417", "TEXT": "#baa379", "INPUT": "#baa379", "TEXT_INPUT": "#000000", "SCROLL": "#392e1c", + "BUTTON": ("#000000", "#baa379"), "PROGRESS": ("#baa379", "#453923"), "BORDER": 1, "SLIDER_DEPTH": 1, "PROGRESS_DEPTH": 0, }, + "Python": {"BACKGROUND": "#3d7aab", "TEXT": "#ffde56", "INPUT": "#295273", "TEXT_INPUT": "#ffde56", "SCROLL": "#295273", "BUTTON": ("#ffde56", "#295273"), + "PROGRESS": ("#ffde56", "#295273"), "BORDER": 1, "SLIDER_DEPTH": 1, "PROGRESS_DEPTH": 0, }, +} + + +def list_of_look_and_feel_values(): + """ + Get a list of the valid values to pass into your call to change_look_and_feel + + :return: list of valid string values + :rtype: List[str] + """ + + return sorted(list(LOOK_AND_FEEL_TABLE.keys())) + + +def theme(new_theme=None): + """ + Sets / Gets the current Theme. If none is specified then returns the current theme. + This call replaces the ChangeLookAndFeel / change_look_and_feel call which only sets the theme. + + :param new_theme: the new theme name to use + :type new_theme: (str) + :return: the currently selected theme + :rtype: (str) + """ + global TRANSPARENT_BUTTON + + if new_theme is not None: + change_look_and_feel(new_theme) + TRANSPARENT_BUTTON = (theme_background_color(), theme_background_color()) + return CURRENT_LOOK_AND_FEEL + + +def theme_background_color(color=None): + """ + Sets/Returns the background color currently in use + Used for Windows and containers (Column, Frame, Tab) and tables + + :param color: new background color to use (optional) + :type color: (str) + :return: color string of the background color currently in use + :rtype: (str) + """ + if color is not None: + set_options(background_color=color) + return DEFAULT_BACKGROUND_COLOR + + +# This "constant" is misleading but rather than remove and break programs, will try this method instead +TRANSPARENT_BUTTON = (theme_background_color(), theme_background_color()) # replaces an older version that had hardcoded numbers + + +def theme_element_background_color(color=None): + """ + Sets/Returns the background color currently in use for all elements except containers + + :return: (str) - color string of the element background color currently in use + :rtype: (str) + """ + if color is not None: + set_options(element_background_color=color) + return DEFAULT_ELEMENT_BACKGROUND_COLOR + + +def theme_text_color(color=None): + """ + Sets/Returns the text color currently in use + + :return: (str) - color string of the text color currently in use + :rtype: (str) + """ + if color is not None: + set_options(text_color=color) + return DEFAULT_TEXT_COLOR + + +def theme_text_element_background_color(color=None): + """ + Sets/Returns the background color for text elements + + :return: (str) - color string of the text background color currently in use + :rtype: (str) + """ + if color is not None: + set_options(text_element_background_color=color) + return DEFAULT_TEXT_ELEMENT_BACKGROUND_COLOR + + +def theme_input_background_color(color=None): + """ + Sets/Returns the input element background color currently in use + + :return: (str) - color string of the input element background color currently in use + :rtype: (str) + """ + if color is not None: + set_options(input_elements_background_color=color) + return DEFAULT_INPUT_ELEMENTS_COLOR + + +def theme_input_text_color(color=None): + """ + Sets/Returns the input element entry color (not the text but the thing that's displaying the text) + + :return: (str) - color string of the input element color currently in use + :rtype: (str) + """ + if color is not None: + set_options(input_text_color=color) + return DEFAULT_INPUT_TEXT_COLOR + + +def theme_button_color(color=None): + """ + Sets/Returns the button color currently in use + + :return: (str, str) - TUPLE with color strings of the button color currently in use (button text color, button background color) + :rtype: (str, str) + """ + if color is not None: + if color == COLOR_SYSTEM_DEFAULT: + color_tuple = (COLOR_SYSTEM_DEFAULT, COLOR_SYSTEM_DEFAULT) + else: + color_tuple = button_color_to_tuple(color, (None, None)) + if color_tuple == (None, None): + if not SUPPRESS_ERROR_POPUPS: + popup_error('theme_button_color - bad color string passed in', color) + else: + print('** Badly formatted button color... not a tuple nor string **', color) + set_options(button_color=color) # go ahead and try with their string + else: + set_options(button_color=color_tuple) + return DEFAULT_BUTTON_COLOR + + +def theme_progress_bar_color(color=None): + """ + Sets/Returns the progress bar colors by the current color theme + + :return: (str, str) - TUPLE with color strings of the ProgressBar color currently in use(button text color, button background color) + :rtype: (str, str) + """ + if color is not None: + set_options(progress_meter_color=color) + return DEFAULT_PROGRESS_BAR_COLOR + + +def theme_slider_color(color=None): + """ + Sets/Returns the slider color (used for sliders) + + :return: color string of the slider color currently in use + :rtype: (str) + """ + if color is not None: + set_options(scrollbar_color=color) + return DEFAULT_SCROLLBAR_COLOR + + +def theme_border_width(border_width=None): + """ + Sets/Returns the border width currently in use + Used by non ttk elements at the moment + + :return: border width currently in use + :rtype: (int) + """ + if border_width is not None: + set_options(border_width=border_width) + return DEFAULT_BORDER_WIDTH + + +def theme_slider_border_width(border_width=None): + """ + Sets/Returns the slider border width currently in use + + :return: border width currently in use for sliders + :rtype: (int) + """ + if border_width is not None: + set_options(slider_border_width=border_width) + return DEFAULT_SLIDER_BORDER_WIDTH + + +def theme_progress_bar_border_width(border_width=None): + """ + Sets/Returns the progress meter border width currently in use + + :return: border width currently in use for progress meters + :rtype: (int) + """ + if border_width is not None: + set_options(progress_meter_border_depth=border_width) + return DEFAULT_PROGRESS_BAR_BORDER_WIDTH + + +def theme_element_text_color(color=None): + """ + Sets/Returns the text color used by elements that have text as part of their display (Tables, Trees and Sliders) + + :return: color string currently in use + :rtype: (str) + """ + if color is not None: + set_options(element_text_color=color) + return DEFAULT_ELEMENT_TEXT_COLOR + + +def theme_list(): + """ + Returns a sorted list of the currently available color themes + + :return: A sorted list of the currently available color themes + :rtype: List[str] + """ + return list_of_look_and_feel_values() + + +def theme_add_new(new_theme_name, new_theme_dict): + """ + Add a new theme to the dictionary of themes + + :param new_theme_name: text to display in element + :type new_theme_name: (str) + :param new_theme_dict: text to display in element + :type new_theme_dict: (dict) + """ + global LOOK_AND_FEEL_TABLE + try: + LOOK_AND_FEEL_TABLE[new_theme_name] = new_theme_dict + except Exception as e: + print('Exception during adding new theme {}'.format(e)) + + +def theme_global(new_theme=None): + """ + Sets / Gets the global PySimpleGUI Theme. If none is specified then returns the global theme from user settings + + :param new_theme: the new theme name to use + :type new_theme: (str) + :return: the currently selected theme + :rtype: (str) + """ + if new_theme is not None: + pysimplegui_user_settings.set('-theme-', new_theme) + theme(new_theme) + return new_theme + else: + return pysimplegui_user_settings.get('-theme-', CURRENT_LOOK_AND_FEEL) + + +def theme_previewer(columns=12, scrollable=False, scroll_area_size=(None, None), search_string=None, location=(None, None)): + """ + Displays a "Quick Reference Window" showing all of the different Look and Feel settings that are available. + They are sorted alphabetically. The legacy color names are mixed in, but otherwise they are sorted into Dark and Light halves + + :param columns: The number of themes to display per row + :type columns: int + :param scrollable: If True then scrollbars will be added + :type scrollable: bool + :param scroll_area_size: Size of the scrollable area (The Column Element used to make scrollable) + :type scroll_area_size: (int, int) + :param search_string: If specified then only themes containing this string will be shown + :type search_string: str + :param location: Location on the screen to place the window. Defaults to the center like all windows + :type location: (int, int) + """ + + current_theme = theme() + + # Show a "splash" type message so the user doesn't give up waiting + popup_quick_message('Hang on for a moment, this will take a bit to create....', keep_on_top=True, background_color='red', text_color='#FFFFFF', + auto_close=True, non_blocking=True) + + web = False + + win_bg = 'black' + + def sample_layout(): + return [[Text('Text element'), InputText('Input data here', size=(10, 1))], + [Button('Ok'), Button('Disabled', disabled=True), Slider((1, 10), orientation='h', size=(5, 15))]] + + names = list_of_look_and_feel_values() + names.sort() + if search_string not in (None, ''): + names = [name for name in names if search_string.lower().replace(" ", "") in name.lower().replace(" ", "")] + + if search_string not in (None, ''): + layout = [[Text('Themes containing "{}"'.format(search_string), font='Default 18', background_color=win_bg)]] + else: + layout = [[Text('List of all themes', font='Default 18', background_color=win_bg)]] + + col_layout = [] + row = [] + for count, theme_name in enumerate(names): + theme(theme_name) + if not count % columns: + col_layout += [row] + row = [] + row += [Frame(theme_name, sample_layout() if not web else [[T(theme_name)]] + sample_layout(), pad=(2, 2))] + if row: + col_layout += [row] + + layout += [[Column(col_layout, scrollable=scrollable, size=scroll_area_size, pad=(0, 0), background_color=win_bg, key='-COL-')]] + window = Window('Preview of Themes', layout, background_color=win_bg, resizable=True, location=location, keep_on_top=True, finalize=True, modal=True) + window['-COL-'].expand(True, True, True) # needed so that col will expand with the window + window.read(close=True) + theme(current_theme) + + +preview_all_look_and_feel_themes = theme_previewer + + +def _theme_preview_window_swatches(): + # Begin the layout with a header + layout = [[Text('Themes as color swatches', text_color='white', background_color='black', font='Default 25')], + [Text('Tooltip and right click a color to get the value', text_color='white', background_color='black', font='Default 15')], + [Text('Left click a color to copy to clipboard', text_color='white', background_color='black', font='Default 15')]] + layout = [[Column(layout, element_justification='c', background_color='black')]] + # Create the pain part, the rows of Text with color swatches + for i, theme_name in enumerate(theme_list()): + theme(theme_name) + colors = [theme_background_color(), theme_text_color(), theme_input_background_color(), + theme_input_text_color()] + if theme_button_color() != COLOR_SYSTEM_DEFAULT: + colors.append(theme_button_color()[0]) + colors.append(theme_button_color()[1]) + colors = list(set(colors)) # de-duplicate items + row = [T(theme(), background_color='black', text_color='white', size=(20, 1), justification='r')] + for color in colors: + if color != COLOR_SYSTEM_DEFAULT: + row.append(T(SYMBOL_SQUARE, text_color=color, background_color='black', pad=(0, 0), font='DEFAUlT 20', right_click_menu=['Nothing', [color]], + tooltip=color, enable_events=True, key=(i, color))) + layout += [row] + # place layout inside of a Column so that it's scrollable + layout = [[Column(layout, size=(500, 900), scrollable=True, vertical_scroll_only=True, background_color='black')]] + # finish the layout by adding an exit button + layout += [[B('Exit')]] + + # create and return Window that uses the layout + return Window('Theme Color Swatches', layout, background_color='black', finalize=True, keep_on_top=True) + + +def theme_previewer_swatches(): + """ + Display themes in a window as color swatches. + Click on a color swatch to see the hex value printed on the console. + If you hover over a color or right click it you'll also see the hext value. + """ + current_theme = theme() + popup_quick_message('This is going to take a minute...', text_color='white', background_color='red', font='Default 20', keep_on_top=True) + window = _theme_preview_window_swatches() + theme(OFFICIAL_PYSIMPLEGUI_THEME) + # col_height = window.get_screen_size()[1]-200 + # if window.size[1] > 100: + # window.size = (window.size[0], col_height) + # window.move(window.get_screen_size()[0] // 2 - window.size[0] // 2, 0) + + while True: # Event Loop + event, values = window.read() + if event == WIN_CLOSED or event == 'Exit': + break + if isinstance(event, tuple): # someone clicked a swatch + chosen_color = event[1] + else: + if event[0] == '#': # someone right clicked + chosen_color = event + else: + chosen_color = '' + print('Copied to clipboard color = ', chosen_color) + clipboard_set(chosen_color) + # window.TKroot.clipboard_clear() + # window.TKroot.clipboard_append(chosen_color) + window.close() + theme(current_theme) + + +def change_look_and_feel(index, force=False): + """ + Change the "color scheme" of all future PySimpleGUI Windows. + The scheme are string names that specify a group of colors. Background colors, text colors, button colors. + There are 13 different color settings that are changed at one time using a single call to ChangeLookAndFeel + The look and feel table itself has these indexes into the dictionary LOOK_AND_FEEL_TABLE. + The original list was (prior to a major rework and renaming)... these names still work... + In Nov 2019 a new Theme Formula was devised to make choosing a theme easier: + The "Formula" is: + ["Dark" or "Light"] Color Number + Colors can be Blue Brown Grey Green Purple Red Teal Yellow Black + The number will vary for each pair. There are more DarkGrey entries than there are LightYellow for example. + Default = The default settings (only button color is different than system default) + Default1 = The full system default including the button (everything's gray... how sad... don't be all gray... please....) + :param index: the name of the index into the Look and Feel table (does not have to be exact, can be "fuzzy") + :type index: (str) + :param force: no longer used + :type force: (bool) + :return: None + :rtype: None + """ + global CURRENT_LOOK_AND_FEEL + + # if running_mac() and not force: + # print('*** Changing look and feel is not supported on Mac platform ***') + # return + + requested_theme_name = index + theme_names_list = list_of_look_and_feel_values() + # normalize available l&f values by setting all to lower case + lf_values_lowercase = [item.lower() for item in theme_names_list] + # option 1 + opt1 = requested_theme_name.replace(' ', '').lower() + # option 3 is option 1 with gray replaced with grey + opt3 = opt1.replace('gray', 'grey') + # option 2 (reverse lookup) + optx = requested_theme_name.lower().split(' ') + optx.reverse() + opt2 = ''.join(optx) + + # search for valid l&f name + if requested_theme_name in theme_names_list: + ix = theme_names_list.index(requested_theme_name) + elif opt1 in lf_values_lowercase: + ix = lf_values_lowercase.index(opt1) + elif opt2 in lf_values_lowercase: + ix = lf_values_lowercase.index(opt2) + elif opt3 in lf_values_lowercase: + ix = lf_values_lowercase.index(opt3) + else: + ix = random.randint(0, len(lf_values_lowercase) - 1) + print('** Warning - {} Theme is not a valid theme. Change your theme call. **'.format(index)) + print('valid values are', list_of_look_and_feel_values()) + print('Instead, please enjoy a random Theme named {}'.format(list_of_look_and_feel_values()[ix])) + + selection = theme_names_list[ix] + CURRENT_LOOK_AND_FEEL = selection + try: + colors = LOOK_AND_FEEL_TABLE[selection] + + # Color the progress bar using button background and input colors...unless they're the same + if colors['PROGRESS'] != COLOR_SYSTEM_DEFAULT: + if colors['PROGRESS'] == DEFAULT_PROGRESS_BAR_COMPUTE: + if colors['BUTTON'][1] != colors['INPUT'] and colors['BUTTON'][1] != colors['BACKGROUND']: + colors['PROGRESS'] = colors['BUTTON'][1], colors['INPUT'] + else: # if the same, then use text input on top of input color + colors['PROGRESS'] = (colors['TEXT_INPUT'], colors['INPUT']) + else: + colors['PROGRESS'] = DEFAULT_PROGRESS_BAR_COLOR_OFFICIAL + # call to change all the colors + SetOptions(background_color=colors['BACKGROUND'], + text_element_background_color=colors['BACKGROUND'], + element_background_color=colors['BACKGROUND'], + text_color=colors['TEXT'], + input_elements_background_color=colors['INPUT'], + # button_color=colors['BUTTON'] if not running_mac() else None, + button_color=colors['BUTTON'], + progress_meter_color=colors['PROGRESS'], + border_width=colors['BORDER'], + slider_border_width=colors['SLIDER_DEPTH'], + progress_meter_border_depth=colors['PROGRESS_DEPTH'], + scrollbar_color=(colors['SCROLL']), + element_text_color=colors['TEXT'], + input_text_color=colors['TEXT_INPUT']) + except: # most likely an index out of range + print('** Warning - Theme value not valid. Change your theme call. **') + print('valid values are', list_of_look_and_feel_values()) + + +# ------------------------ Color processing functions ------------------------ + +def _hex_to_hsl(hex): + r, g, b = _hex_to_rgb(hex) + return _rgb_to_hsl(r, g, b) + + +def _hex_to_rgb(hex): + hex = hex.lstrip('#') + hlen = len(hex) + return tuple(int(hex[i:i + hlen // 3], 16) for i in range(0, hlen, hlen // 3)) + + +def _rgb_to_hsl(r, g, b): + r = float(r) + g = float(g) + b = float(b) + high = max(r, g, b) + low = min(r, g, b) + h, s, v = ((high + low) / 2,) * 3 + if high == low: + h = s = 0.0 + else: + d = high - low + l = (high + low) / 2 + s = d / (2 - high - low) if l > 0.5 else d / (high + low) + h = { + r: (g - b) / d + (6 if g < b else 0), + g: (b - r) / d + 2, + b: (r - g) / d + 4, + }[high] + h /= 6 + return h, s, v + + +def _hsl_to_rgb(h, s, l): + def hue_to_rgb(p, q, t): + t += 1 if t < 0 else 0 + t -= 1 if t > 1 else 0 + if t < 1 / 6: return p + (q - p) * 6 * t + if t < 1 / 2: return q + if t < 2 / 3: p + (q - p) * (2 / 3 - t) * 6 + return p + + if s == 0: + r, g, b = l, l, l + else: + q = l * (1 + s) if l < 0.5 else l + s - l * s + p = 2 * l - q + r = hue_to_rgb(p, q, h + 1 / 3) + g = hue_to_rgb(p, q, h) + b = hue_to_rgb(p, q, h - 1 / 3) + + return r, g, b + + +def _hsv_to_hsl(h, s, v): + l = 0.5 * v * (2 - s) + s = v * s / (1 - fabs(2 * l - 1)) + return h, s, l + + +def _hsl_to_hsv(h, s, l): + v = (2 * l + s * (1 - fabs(2 * l - 1))) / 2 + s = 2 * (v - l) / v + return h, s, v + + +# Converts an object's contents into a nice printable string. Great for dumping debug data +def obj_to_string_single_obj(obj): + """ + Dumps an Object's values as a formatted string. Very nicely done. Great way to display an object's member variables in human form + Returns only the top-most object's variables instead of drilling down to dispolay more + :param obj: The object to display + :type obj: (Any) + :return: Formatted output of the object's values + :rtype: (str) + """ + if obj is None: + return 'None' + return str(obj.__class__) + '\n' + '\n'.join( + (repr(item) + ' = ' + repr(obj.__dict__[item]) for item in sorted(obj.__dict__))) + + +def obj_to_string(obj, extra=' '): + """ + Dumps an Object's values as a formatted string. Very nicely done. Great way to display an object's member variables in human form + :param obj: The object to display + :type obj: (Any) + :param extra: extra stuff (Default value = ' ') + :type extra: (str) + :return: Formatted output of the object's values + :rtype: (str) + """ + if obj is None: + return 'None' + return str(obj.__class__) + '\n' + '\n'.join( + (extra + (str(item) + ' = ' + + (ObjToString(obj.__dict__[item], extra + ' ') if hasattr(obj.__dict__[item], '__dict__') else str( + obj.__dict__[item]))) + for item in sorted(obj.__dict__))) + + +# ...######..##.......####.########..########...#######.....###....########..########. +# ..##....##.##........##..##.....##.##.....##.##.....##...##.##...##.....##.##.....## +# ..##.......##........##..##.....##.##.....##.##.....##..##...##..##.....##.##.....## +# ..##.......##........##..########..########..##.....##.##.....##.########..##.....## +# ..##.......##........##..##........##.....##.##.....##.#########.##...##...##.....## +# ..##....##.##........##..##........##.....##.##.....##.##.....##.##....##..##.....## +# ...######..########.####.##........########...#######..##.....##.##.....##.########. +# ................................................................................ +# ..########.##.....##.##....##..######..########.####..#######..##....##..######. +# ..##.......##.....##.###...##.##....##....##.....##..##.....##.###...##.##....## +# ..##.......##.....##.####..##.##..........##.....##..##.....##.####..##.##...... +# ..######...##.....##.##.##.##.##..........##.....##..##.....##.##.##.##..######. +# ..##.......##.....##.##..####.##..........##.....##..##.....##.##..####.......## +# ..##.......##.....##.##...###.##....##....##.....##..##.....##.##...###.##....## +# ..##........#######..##....##..######.....##....####..#######..##....##..######. + +def clipboard_set(new_value): + """ + Sets the clipboard to a specific value. + IMPORTANT NOTE - Your PySimpleGUI application needs to remain running until you've pasted + your clipboard. This is a tkinter limitation. A workaround was found for Windows, but you still + need to stay running for Linux systems. + + :param new_value: value to set the clipboard to. Will be converted to a string + :type new_value: (str | bytes) + """ + # Create and use a temp window + root = tk.Tk() + root.withdraw() + root.clipboard_clear() + root.clipboard_append(str(new_value)) + root.update() + root.destroy() + + +def clipboard_get(): + """ + Gets the clipboard current value. + + :return: The current value of the clipboard + :rtype: (str) + """ + # Create and use a temp window + root = tk.Tk() + root.withdraw() + try: + value = root.clipboard_get() + except: + value = '' + root.update() + root.destroy() + return value + + +# MM"""""""`YM +# MM mmmmm M +# M' .M .d8888b. 88d888b. dP dP 88d888b. .d8888b. +# MM MMMMMMMM 88' `88 88' `88 88 88 88' `88 Y8ooooo. +# MM MMMMMMMM 88. .88 88. .88 88. .88 88. .88 88 +# MM MMMMMMMM `88888P' 88Y888P' `88888P' 88Y888P' `88888P' +# MMMMMMMMMMMM 88 88 +# dP dP +# ------------------------------------------------------------------------------------------------------------------ # +# ===================================== Upper PySimpleGUI ======================================================== # +# ------------------------------------------------------------------------------------------------------------------ # +# ----------------------------------- The mighty Popup! ------------------------------------------------------------ # + +def popup(*args, title=None, button_color=None, background_color=None, text_color=None, button_type=POPUP_BUTTONS_OK, auto_close=False, + auto_close_duration=None, custom_text=(None, None), non_blocking=False, icon=None, line_width=None, font=None, no_titlebar=False, grab_anywhere=False, + keep_on_top=None, location=(None, None), relative_location=(None, None), any_key_closes=False, image=None, modal=True): + """ + Popup - Display a popup Window with as many parms as you wish to include. This is the GUI equivalent of the + "print" statement. It's also great for "pausing" your program's flow until the user can read some error messages. + + If this popup doesn't have the features you want, then you can easily make your own. Popups can be accomplished in 1 line of code: + choice, _ = sg.Window('Continue?', [[sg.T('Do you want to continue?')], [sg.Yes(s=10), sg.No(s=10)]], disable_close=True).read(close=True) + + + :param *args: Variable number of your arguments. Load up the call with stuff to see! + :type *args: (Any) + :param title: Optional title for the window. If none provided, the first arg will be used instead. + :type title: (str) + :param button_color: Color of the buttons shown (text color, button color) + :type button_color: (str, str) | None + :param background_color: Window's background color + :type background_color: (str) + :param text_color: text color + :type text_color: (str) + :param button_type: NOT USER SET! Determines which pre-defined buttons will be shown (Default value = POPUP_BUTTONS_OK). There are many Popup functions and they call Popup, changing this parameter to get the desired effect. + :type button_type: (int) + :param auto_close: If True the window will automatically close + :type auto_close: (bool) + :param auto_close_duration: time in seconds to keep window open before closing it automatically + :type auto_close_duration: (int) + :param custom_text: A string or pair of strings that contain the text to display on the buttons + :type custom_text: (str, str) | str + :param non_blocking: If True then will immediately return from the function without waiting for the user's input. + :type non_blocking: (bool) + :param icon: icon to display on the window. Same format as a Window call + :type icon: str | bytes + :param line_width: Width of lines in characters. Defaults to MESSAGE_BOX_LINE_WIDTH + :type line_width: (int) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: str | Tuple[font_name, size, modifiers] + :param no_titlebar: If True will not show the frame around the window and the titlebar across the top + :type no_titlebar: (bool) + :param grab_anywhere: If True can grab anywhere to move the window. If no_titlebar is True, grab_anywhere should likely be enabled too + :type grab_anywhere: (bool) + :param location: Location on screen to display the top left corner of window. Defaults to window centered on screen + :type location: (int, int) + :param relative_location: (x,y) location relative to the default location of the window, in pixels. Normally the window centers. This location is relative to the location the window would be created. Note they can be negative. + :type relative_location: (int, int) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param any_key_closes: If True then will turn on return_keyboard_events for the window which will cause window to close as soon as any key is pressed. Normally the return key only will close the window. Default is false. + :type any_key_closes: (bool) + :param image: Image to include at the top of the popup window + :type image: (str) or (bytes) + :param modal: If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True + :type modal: bool + :return: Returns text of the button that was pressed. None will be returned if user closed window with X + :rtype: str | None + """ + + if not args: + args_to_print = [''] + else: + args_to_print = args + if line_width != None: + local_line_width = line_width + else: + local_line_width = MESSAGE_BOX_LINE_WIDTH + _title = title if title is not None else args_to_print[0] + + layout = [[]] + max_line_total, total_lines = 0, 0 + if image is not None: + if isinstance(image, str): + layout += [[Image(filename=image)]] + else: + layout += [[Image(data=image)]] + + for message in args_to_print: + # fancy code to check if string and convert if not is not need. Just always convert to string :-) + # if not isinstance(message, str): message = str(message) + message = str(message) + if message.count('\n'): # if there are line breaks, then wrap each segment separately + # message_wrapped = message # used to just do this, but now breaking into smaller pieces + message_wrapped = '' + msg_list = message.split('\n') # break into segments that will each be wrapped + message_wrapped = '\n'.join([textwrap.fill(msg, local_line_width) for msg in msg_list]) + else: + message_wrapped = textwrap.fill(message, local_line_width) + message_wrapped_lines = message_wrapped.count('\n') + 1 + longest_line_len = max([len(l) for l in message.split('\n')]) + width_used = min(longest_line_len, local_line_width) + max_line_total = max(max_line_total, width_used) + # height = _GetNumLinesNeeded(message, width_used) + height = message_wrapped_lines + layout += [[ + Text(message_wrapped, auto_size_text=True, text_color=text_color, background_color=background_color)]] + total_lines += height + + if non_blocking: + PopupButton = DummyButton # important to use or else button will close other windows too! + else: + PopupButton = Button + # show either an OK or Yes/No depending on paramater + if custom_text != (None, None): + if type(custom_text) is not tuple: + layout += [[PopupButton(custom_text, size=(len(custom_text), 1), button_color=button_color, focus=True, + bind_return_key=True)]] + elif custom_text[1] is None: + layout += [[ + PopupButton(custom_text[0], size=(len(custom_text[0]), 1), button_color=button_color, focus=True, + bind_return_key=True)]] + else: + layout += [[PopupButton(custom_text[0], button_color=button_color, focus=True, bind_return_key=True, + size=(len(custom_text[0]), 1)), + PopupButton(custom_text[1], button_color=button_color, size=(len(custom_text[1]), 1))]] + elif button_type is POPUP_BUTTONS_YES_NO: + layout += [[PopupButton('Yes', button_color=button_color, focus=True, bind_return_key=True, pad=((20, 5), 3), + size=(5, 1)), PopupButton('No', button_color=button_color, size=(5, 1))]] + elif button_type is POPUP_BUTTONS_CANCELLED: + layout += [[ + PopupButton('Cancelled', button_color=button_color, focus=True, bind_return_key=True, pad=((20, 0), 3))]] + elif button_type is POPUP_BUTTONS_ERROR: + layout += [[PopupButton('Error', size=(6, 1), button_color=button_color, focus=True, bind_return_key=True, + pad=((20, 0), 3))]] + elif button_type is POPUP_BUTTONS_OK_CANCEL: + layout += [[PopupButton('OK', size=(6, 1), button_color=button_color, focus=True, bind_return_key=True), + PopupButton('Cancel', size=(6, 1), button_color=button_color)]] + elif button_type is POPUP_BUTTONS_NO_BUTTONS: + pass + else: + layout += [[PopupButton('OK', size=(5, 1), button_color=button_color, focus=True, bind_return_key=True, + pad=((20, 0), 3))]] + + window = Window(_title, layout, auto_size_text=True, background_color=background_color, button_color=button_color, + auto_close=auto_close, auto_close_duration=auto_close_duration, icon=icon, font=font, + no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location, relative_location=relative_location, return_keyboard_events=any_key_closes, + modal=modal) + + + if non_blocking: + button, values = window.read(timeout=0) + else: + button, values = window.read() + window.close() + del window + + return button + + +# ============================== MsgBox============# +# Lazy function. Same as calling Popup with parms # +# This function WILL Disappear perhaps today # +# ==================================================# +# MsgBox is the legacy call and should not be used any longer +def MsgBox(*args): + """ + Do not call this anymore it will raise exception. Use Popups instead + :param *args: + :type *args: + + """ + raise DeprecationWarning('MsgBox is no longer supported... change your call to Popup') + + +# ======================== Scrolled Text Box =====# +# ===================================================# +def popup_scrolled(*args, title=None, button_color=None, background_color=None, text_color=None, yes_no=False, auto_close=False, auto_close_duration=None, + size=(None, None), location=(None, None), relative_location=(None, None), non_blocking=False, no_titlebar=False, grab_anywhere=False, keep_on_top=None, font=None, + image=None, icon=None, modal=True, no_sizegrip=False): + """ + Show a scrolled Popup window containing the user's text that was supplied. Use with as many items to print as you + want, just like a print statement. + + :param *args: Variable number of items to display + :type *args: (Any) + :param title: Title to display in the window. + :type title: (str) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param yes_no: If True, displays Yes and No buttons instead of Ok + :type yes_no: (bool) + :param auto_close: if True window will close itself + :type auto_close: (bool) + :param auto_close_duration: Older versions only accept int. Time in seconds until window will close + :type auto_close_duration: int | float + :param size: (w,h) w=characters-wide, h=rows-high + :type size: (int, int) + :param location: Location on the screen to place the upper left corner of the window + :type location: (int, int) + :param relative_location: (x,y) location relative to the default location of the window, in pixels. Normally the window centers. This location is relative to the location the window would be created. Note they can be negative. + :type relative_location: (int, int) + :param non_blocking: if True the call will immediately return rather than waiting on user input + :type non_blocking: (bool) + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + :param grab_anywhere: If True, than can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param image: Image to include at the top of the popup window + :type image: (str) or (bytes) + :param icon: filename or base64 string to be used for the window's icon + :type icon: bytes | str + :param modal: If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True + :type modal: bool + :param no_sizegrip: If True no Sizegrip will be shown when there is no titlebar. It's only shown if there is no titlebar + :type no_sizegrip: (bool) + :return: Returns text of the button that was pressed. None will be returned if user closed window with X + :rtype: str | None | TIMEOUT_KEY + """ + if not args: return + width, height = size + width = width if width else MESSAGE_BOX_LINE_WIDTH + + layout = [[]] + + if image is not None: + if isinstance(image, str): + layout += [[Image(filename=image)]] + else: + layout += [[Image(data=image)]] + max_line_total, max_line_width, total_lines, height_computed = 0, 0, 0, 0 + complete_output = '' + for message in args: + # fancy code to check if string and convert if not is not need. Just always convert to string :-) + # if not isinstance(message, str): message = str(message) + message = str(message) + longest_line_len = max([len(l) for l in message.split('\n')]) + width_used = min(longest_line_len, width) + max_line_total = max(max_line_total, width_used) + max_line_width = width + lines_needed = _GetNumLinesNeeded(message, width_used) + height_computed += lines_needed + 1 + complete_output += message + '\n' + total_lines += lines_needed + height_computed = MAX_SCROLLED_TEXT_BOX_HEIGHT if height_computed > MAX_SCROLLED_TEXT_BOX_HEIGHT else height_computed + if height: + height_computed = height + layout += [[Multiline(complete_output, size=(max_line_width, height_computed), background_color=background_color, text_color=text_color, expand_x=True, + expand_y=True, k='-MLINE-')]] + pad = max_line_total - 15 if max_line_total > 15 else 1 + # show either an OK or Yes/No depending on paramater + button = DummyButton if non_blocking else Button + if yes_no: + layout += [[Text('', size=(pad, 1), auto_size_text=False, background_color=background_color), button('Yes'), button('No')]] + else: + layout += [[Text('', size=(pad, 1), auto_size_text=False, background_color=background_color), + button('OK', size=(5, 1), button_color=button_color)]] + if no_titlebar and no_sizegrip is not True: + layout += [[Sizegrip()]] + + window = Window(title or args[0], layout, auto_size_text=True, button_color=button_color, auto_close=auto_close, + auto_close_duration=auto_close_duration, location=location, relative_location=relative_location, resizable=True, font=font, background_color=background_color, + no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, modal=modal, icon=icon) + if non_blocking: + button, values = window.read(timeout=0) + else: + button, values = window.read() + window.close() + del window + return button + + +# ============================== sprint ======# +# Is identical to the Scrolled Text Box # +# Provides a crude 'print' mechanism but in a # +# GUI environment # +# This is in addition to the Print function # +# which routes output to a "Debug Window" # +# ============================================# + + +# --------------------------- popup_no_buttons --------------------------- +def popup_no_buttons(*args, title=None, background_color=None, text_color=None, auto_close=False, + auto_close_duration=None, non_blocking=False, icon=None, line_width=None, font=None, + no_titlebar=False, grab_anywhere=False, keep_on_top=None, location=(None, None), relative_location=(None, None), image=None, modal=True): + """Show a Popup but without any buttons + + :param *args: Variable number of items to display + :type *args: (Any) + :param title: Title to display in the window. + :type title: (str) + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param auto_close: if True window will close itself + :type auto_close: (bool) + :param auto_close_duration: Older versions only accept int. Time in seconds until window will close + :type auto_close_duration: int | float + :param non_blocking: If True then will immediately return from the function without waiting for the user's input. (Default = False) + :type non_blocking: (bool) + :param icon: filename or base64 string to be used for the window's icon + :type icon: bytes | str + :param line_width: Width of lines in characters + :type line_width: (int) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + :param grab_anywhere: If True, than can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param location: Location of upper left corner of the window + :type location: (int, int) + :param relative_location: (x,y) location relative to the default location of the window, in pixels. Normally the window centers. This location is relative to the location the window would be created. Note they can be negative. + :type relative_location: (int, int) + :param image: Image to include at the top of the popup window + :type image: (str) or (bytes) + :param modal: If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True + :type modal: bool + :return: Returns text of the button that was pressed. None will be returned if user closed window with X + :rtype: str | None | TIMEOUT_KEY """ + Popup(*args, title=title, background_color=background_color, text_color=text_color, + button_type=POPUP_BUTTONS_NO_BUTTONS, + auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon, + line_width=line_width, + font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location, relative_location=relative_location, image=image, modal=modal) + + +# --------------------------- popup_non_blocking --------------------------- +def popup_non_blocking(*args, title=None, button_type=POPUP_BUTTONS_OK, button_color=None, background_color=None, + text_color=None, auto_close=False, auto_close_duration=None, non_blocking=True, icon=None, + line_width=None, font=None, no_titlebar=False, grab_anywhere=False, keep_on_top=None, + location=(None, None), relative_location=(None, None), image=None, modal=False): + """ + Show Popup window and immediately return (does not block) + + :param *args: Variable number of items to display + :type *args: (Any) + :param title: Title to display in the window. + :type title: (str) + :param button_type: Determines which pre-defined buttons will be shown (Default value = POPUP_BUTTONS_OK). + :type button_type: (int) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param auto_close: if True window will close itself + :type auto_close: (bool) + :param auto_close_duration: Older versions only accept int. Time in seconds until window will close + :type auto_close_duration: int | float + :param non_blocking: if True the call will immediately return rather than waiting on user input + :type non_blocking: (bool) + :param icon: filename or base64 string to be used for the window's icon + :type icon: bytes | str + :param line_width: Width of lines in characters + :type line_width: (int) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + :param grab_anywhere: If True: can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param location: Location of upper left corner of the window + :type location: (int, int) + :param relative_location: (x,y) location relative to the default location of the window, in pixels. Normally the window centers. This location is relative to the location the window would be created. Note they can be negative. + :type relative_location: (int, int) + :param image: Image to include at the top of the popup window + :type image: (str) or (bytes) + :param modal: If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = False + :type modal: bool + :return: Reason for popup closing + :rtype: str | None + """ + + return popup(*args, title=title, button_color=button_color, background_color=background_color, text_color=text_color, + button_type=button_type, + auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon, + line_width=line_width, + font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location, relative_location=relative_location, image=image, modal=modal) + + +# --------------------------- popup_quick - a NonBlocking, Self-closing Popup --------------------------- +def popup_quick(*args, title=None, button_type=POPUP_BUTTONS_OK, button_color=None, background_color=None, + text_color=None, auto_close=True, auto_close_duration=2, non_blocking=True, icon=None, line_width=None, + font=None, no_titlebar=False, grab_anywhere=False, keep_on_top=None, location=(None, None), relative_location=(None, None), image=None, modal=False): + """ + Show Popup box that doesn't block and closes itself + + :param *args: Variable number of items to display + :type *args: (Any) + :param title: Title to display in the window. + :type title: (str) + :param button_type: Determines which pre-defined buttons will be shown (Default value = POPUP_BUTTONS_OK). + :type button_type: (int) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param auto_close: if True window will close itself + :type auto_close: (bool) + :param auto_close_duration: Older versions only accept int. Time in seconds until window will close + :type auto_close_duration: int | float + :param non_blocking: if True the call will immediately return rather than waiting on user input + :type non_blocking: (bool) + :param icon: filename or base64 string to be used for the window's icon + :type icon: bytes | str + :param line_width: Width of lines in characters + :type line_width: (int) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + :param grab_anywhere: If True: can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param location: Location of upper left corner of the window + :type location: (int, int) + :param relative_location: (x,y) location relative to the default location of the window, in pixels. Normally the window centers. This location is relative to the location the window would be created. Note they can be negative. + :type relative_location: (int, int) + :param image: Image to include at the top of the popup window + :type image: (str) or (bytes) + :param modal: If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = False + :type modal: bool + :return: Returns text of the button that was pressed. None will be returned if user closed window with X + :rtype: str | None | TIMEOUT_KEY + """ + + return popup(*args, title=title, button_color=button_color, background_color=background_color, text_color=text_color, + button_type=button_type, + auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon, + line_width=line_width, + font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location, relative_location=relative_location, image=image, modal=modal) + + +# --------------------------- popup_quick_message - a NonBlocking, Self-closing Popup with no titlebar and no buttons --------------------------- +def popup_quick_message(*args, title=None, button_type=POPUP_BUTTONS_NO_BUTTONS, button_color=None, background_color=None, + text_color=None, auto_close=True, auto_close_duration=2, non_blocking=True, icon=None, line_width=None, + font=None, no_titlebar=True, grab_anywhere=False, keep_on_top=None, location=(None, None), relative_location=(None, None), image=None, modal=False): + """ + Show Popup window with no titlebar, doesn't block, and auto closes itself. + + :param *args: Variable number of items to display + :type *args: (Any) + :param title: Title to display in the window. + :type title: (str) + :param button_type: Determines which pre-defined buttons will be shown (Default value = POPUP_BUTTONS_OK). + :type button_type: (int) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param auto_close: if True window will close itself + :type auto_close: (bool) + :param auto_close_duration: Older versions only accept int. Time in seconds until window will close + :type auto_close_duration: int | float + :param non_blocking: if True the call will immediately return rather than waiting on user input + :type non_blocking: (bool) + :param icon: filename or base64 string to be used for the window's icon + :type icon: bytes | str + :param line_width: Width of lines in characters + :type line_width: (int) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + :param grab_anywhere: If True: can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param location: Location of upper left corner of the window + :type location: (int, int) + :param relative_location: (x,y) location relative to the default location of the window, in pixels. Normally the window centers. This location is relative to the location the window would be created. Note they can be negative. + :type relative_location: (int, int) + :param image: Image to include at the top of the popup window + :type image: (str) or (bytes) + :param modal: If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = False + :type modal: bool + :return: Returns text of the button that was pressed. None will be returned if user closed window with X + :rtype: str | None | TIMEOUT_KEY + """ + return popup(*args, title=title, button_color=button_color, background_color=background_color, text_color=text_color, + button_type=button_type, + auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon, + line_width=line_width, + font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location, relative_location=relative_location, image=image, modal=modal) + + +# --------------------------- PopupNoTitlebar --------------------------- +def popup_no_titlebar(*args, title=None, button_type=POPUP_BUTTONS_OK, button_color=None, background_color=None, + text_color=None, auto_close=False, auto_close_duration=None, non_blocking=False, icon=None, + line_width=None, font=None, grab_anywhere=True, keep_on_top=None, location=(None, None), relative_location=(None, None), image=None, modal=True): + """ + Display a Popup without a titlebar. Enables grab anywhere so you can move it + + :param *args: Variable number of items to display + :type *args: (Any) + :param title: Title to display in the window. + :type title: (str) + :param button_type: Determines which pre-defined buttons will be shown (Default value = POPUP_BUTTONS_OK). + :type button_type: (int) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param auto_close: if True window will close itself + :type auto_close: (bool) + :param auto_close_duration: Older versions only accept int. Time in seconds until window will close + :type auto_close_duration: int | float + :param non_blocking: if True the call will immediately return rather than waiting on user input + :type non_blocking: (bool) + :param icon: filename or base64 string to be used for the window's icon + :type icon: bytes | str + :param line_width: Width of lines in characters + :type line_width: (int) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param grab_anywhere: If True: can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param location: Location of upper left corner of the window + :type location: (int, int) + :param relative_location: (x,y) location relative to the default location of the window, in pixels. Normally the window centers. This location is relative to the location the window would be created. Note they can be negative. + :type relative_location: (int, int) + :param image: Image to include at the top of the popup window + :type image: (str) or (bytes) + :param modal: If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True + :type modal: bool + :return: Returns text of the button that was pressed. None will be returned if user closed window with X + :rtype: str | None | TIMEOUT_KEY + """ + return popup(*args, title=title, button_color=button_color, background_color=background_color, text_color=text_color, + button_type=button_type, + auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon, + line_width=line_width, + font=font, no_titlebar=True, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location, relative_location=relative_location, image=image, modal=modal) + + +# --------------------------- PopupAutoClose --------------------------- +def popup_auto_close(*args, title=None, button_type=POPUP_BUTTONS_OK, button_color=None, background_color=None, text_color=None, + auto_close=True, auto_close_duration=None, non_blocking=False, icon=None, + line_width=None, font=None, no_titlebar=False, grab_anywhere=False, keep_on_top=None, + location=(None, None), relative_location=(None, None), image=None, modal=True): + """Popup that closes itself after some time period + + :param *args: Variable number of items to display + :type *args: (Any) + :param title: Title to display in the window. + :type title: (str) + :param button_type: Determines which pre-defined buttons will be shown (Default value = POPUP_BUTTONS_OK). + :type button_type: (int) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param auto_close: if True window will close itself + :type auto_close: (bool) + :param auto_close_duration: Older versions only accept int. Time in seconds until window will close + :type auto_close_duration: int | float + :param non_blocking: if True the call will immediately return rather than waiting on user input + :type non_blocking: (bool) + :param icon: filename or base64 string to be used for the window's icon + :type icon: bytes | str + :param line_width: Width of lines in characters + :type line_width: (int) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + :param grab_anywhere: If True: can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param location: Location of upper left corner of the window + :type location: (int, int) + :param relative_location: (x,y) location relative to the default location of the window, in pixels. Normally the window centers. This location is relative to the location the window would be created. Note they can be negative. + :type relative_location: (int, int) + :param image: Image to include at the top of the popup window + :type image: (str) or (bytes) + :param modal: If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True + :type modal: bool + :return: Returns text of the button that was pressed. None will be returned if user closed window with X + :rtype: str | None | TIMEOUT_KEY + """ + + return popup(*args, title=title, button_color=button_color, background_color=background_color, text_color=text_color, + button_type=button_type, + auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon, + line_width=line_width, + font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location, relative_location=relative_location, image=image, modal=modal) + + +# --------------------------- popup_error --------------------------- +def popup_error(*args, title=None, button_color=(None, None), background_color=None, text_color=None, auto_close=False, + auto_close_duration=None, non_blocking=False, icon=None, line_width=None, font=None, + no_titlebar=False, grab_anywhere=False, keep_on_top=None, location=(None, None), relative_location=(None, None), image=None, modal=True): + """ + Popup with colored button and 'Error' as button text + + :param *args: Variable number of items to display + :type *args: (Any) + :param title: Title to display in the window. + :type title: (str) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param auto_close: if True window will close itself + :type auto_close: (bool) + :param auto_close_duration: Older versions only accept int. Time in seconds until window will close + :type auto_close_duration: int | float + :param non_blocking: if True the call will immediately return rather than waiting on user input + :type non_blocking: (bool) + :param icon: filename or base64 string to be used for the window's icon + :type icon: bytes | str + :param line_width: Width of lines in characters + :type line_width: (int) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + :param grab_anywhere: If True: can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param location: Location of upper left corner of the window + :type location: (int, int) + :param relative_location: (x,y) location relative to the default location of the window, in pixels. Normally the window centers. This location is relative to the location the window would be created. Note they can be negative. + :type relative_location: (int, int) + :param image: Image to include at the top of the popup window + :type image: (str) or (bytes) + :param modal: If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True + :type modal: bool + :return: Returns text of the button that was pressed. None will be returned if user closed window with X + :rtype: str | None | TIMEOUT_KEY + """ + tbutton_color = DEFAULT_ERROR_BUTTON_COLOR if button_color == (None, None) else button_color + return popup(*args, title=title, button_type=POPUP_BUTTONS_ERROR, background_color=background_color, text_color=text_color, + non_blocking=non_blocking, icon=icon, line_width=line_width, button_color=tbutton_color, + auto_close=auto_close, + auto_close_duration=auto_close_duration, font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, + keep_on_top=keep_on_top, location=location, relative_location=relative_location, image=image, modal=modal) + + +# --------------------------- popup_cancel --------------------------- +def popup_cancel(*args, title=None, button_color=None, background_color=None, text_color=None, auto_close=False, + auto_close_duration=None, non_blocking=False, icon=None, line_width=None, font=None, + no_titlebar=False, grab_anywhere=False, keep_on_top=None, location=(None, None), relative_location=(None, None), image=None, modal=True): + """ + Display Popup with "cancelled" button text + + :param *args: Variable number of items to display + :type *args: (Any) + :param title: Title to display in the window. + :type title: (str) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param auto_close: if True window will close itself + :type auto_close: (bool) + :param auto_close_duration: Older versions only accept int. Time in seconds until window will close + :type auto_close_duration: int | float + :param non_blocking: if True the call will immediately return rather than waiting on user input + :type non_blocking: (bool) + :param icon: filename or base64 string to be used for the window's icon + :type icon: bytes | str + :param line_width: Width of lines in characters + :type line_width: (int) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + :param grab_anywhere: If True: can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param location: Location of upper left corner of the window + :type location: (int, int) + :param relative_location: (x,y) location relative to the default location of the window, in pixels. Normally the window centers. This location is relative to the location the window would be created. Note they can be negative. + :type relative_location: (int, int) + :param image: Image to include at the top of the popup window + :type image: (str) or (bytes) + :param modal: If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True + :type modal: bool + :return: Returns text of the button that was pressed. None will be returned if user closed window with X + :rtype: str | None | TIMEOUT_KEY + """ + return popup(*args, title=title, button_type=POPUP_BUTTONS_CANCELLED, background_color=background_color, + text_color=text_color, + non_blocking=non_blocking, icon=icon, line_width=line_width, button_color=button_color, auto_close=auto_close, + auto_close_duration=auto_close_duration, font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, + keep_on_top=keep_on_top, location=location, relative_location=relative_location, image=image, modal=modal) + + +# --------------------------- popup_ok --------------------------- +def popup_ok(*args, title=None, button_color=None, background_color=None, text_color=None, auto_close=False, + auto_close_duration=None, non_blocking=False, icon=None, line_width=None, font=None, + no_titlebar=False, grab_anywhere=False, keep_on_top=None, location=(None, None), relative_location=(None, None), image=None, modal=True): + """ + Display Popup with OK button only + + :param *args: Variable number of items to display + :type *args: (Any) + :param title: Title to display in the window. + :type title: (str) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param auto_close: if True window will close itself + :type auto_close: (bool) + :param auto_close_duration: Older versions only accept int. Time in seconds until window will close + :type auto_close_duration: int | float + :param non_blocking: if True the call will immediately return rather than waiting on user input + :type non_blocking: (bool) + :param icon: filename or base64 string to be used for the window's icon + :type icon: bytes | str + :param line_width: Width of lines in characters + :type line_width: (int) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + :param grab_anywhere: If True: can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param location: Location of upper left corner of the window + :type location: (int, int) + :param relative_location: (x,y) location relative to the default location of the window, in pixels. Normally the window centers. This location is relative to the location the window would be created. Note they can be negative. + :type relative_location: (int, int) + :param image: Image to include at the top of the popup window + :type image: (str) or (bytes) + :param modal: If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True + :type modal: bool + :return: Returns text of the button that was pressed. None will be returned if user closed window with X + :rtype: str | None | TIMEOUT_KEY + """ + return popup(*args, title=title, button_type=POPUP_BUTTONS_OK, background_color=background_color, text_color=text_color, + non_blocking=non_blocking, icon=icon, line_width=line_width, button_color=button_color, auto_close=auto_close, + auto_close_duration=auto_close_duration, font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, + keep_on_top=keep_on_top, location=location, relative_location=relative_location, image=image, modal=modal) + + +# --------------------------- popup_ok_cancel --------------------------- +def popup_ok_cancel(*args, title=None, button_color=None, background_color=None, text_color=None, auto_close=False, + auto_close_duration=None, non_blocking=False, icon=DEFAULT_WINDOW_ICON, line_width=None, font=None, + no_titlebar=False, grab_anywhere=False, keep_on_top=None, location=(None, None), relative_location=(None, None), image=None, modal=True): + """ + Display popup with OK and Cancel buttons + + :param *args: Variable number of items to display + :type *args: (Any) + :param title: Title to display in the window. + :type title: (str) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param auto_close: if True window will close itself + :type auto_close: (bool) + :param auto_close_duration: Older versions only accept int. Time in seconds until window will close + :type auto_close_duration: int | float + :param non_blocking: if True the call will immediately return rather than waiting on user input + :type non_blocking: (bool) + :param icon: filename or base64 string to be used for the window's icon + :type icon: bytes | str + :param line_width: Width of lines in characters + :type line_width: (int) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + :param grab_anywhere: If True: can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param location: Location of upper left corner of the window + :type location: (int, int) + :param relative_location: (x,y) location relative to the default location of the window, in pixels. Normally the window centers. This location is relative to the location the window would be created. Note they can be negative. + :type relative_location: (int, int) + :param image: Image to include at the top of the popup window + :type image: (str) or (bytes) + :param modal: If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True + :type modal: bool + :return: clicked button + :rtype: "OK" | "Cancel" | None + """ + return popup(*args, title=title, button_type=POPUP_BUTTONS_OK_CANCEL, background_color=background_color, + text_color=text_color, + non_blocking=non_blocking, icon=icon, line_width=line_width, button_color=button_color, + auto_close=auto_close, auto_close_duration=auto_close_duration, font=font, no_titlebar=no_titlebar, + grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location, relative_location=relative_location, image=image, modal=modal) + + +# --------------------------- popup_yes_no --------------------------- +def popup_yes_no(*args, title=None, button_color=None, background_color=None, text_color=None, auto_close=False, + auto_close_duration=None, non_blocking=False, icon=None, line_width=None, font=None, + no_titlebar=False, grab_anywhere=False, keep_on_top=None, location=(None, None), relative_location=(None, None), image=None, modal=True): + """ + Display Popup with Yes and No buttons + + :param *args: Variable number of items to display + :type *args: (Any) + :param title: Title to display in the window. + :type title: (str) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param auto_close: if True window will close itself + :type auto_close: (bool) + :param auto_close_duration: Older versions only accept int. Time in seconds until window will close + :type auto_close_duration: int | float + :param non_blocking: if True the call will immediately return rather than waiting on user input + :type non_blocking: (bool) + :param icon: filename or base64 string to be used for the window's icon + :type icon: bytes | str + :param line_width: Width of lines in characters + :type line_width: (int) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + :param grab_anywhere: If True: can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param location: Location of upper left corner of the window + :type location: (int, int) + :param relative_location: (x,y) location relative to the default location of the window, in pixels. Normally the window centers. This location is relative to the location the window would be created. Note they can be negative. + :type relative_location: (int, int) + :param image: Image to include at the top of the popup window + :type image: (str) or (bytes) + :param modal: If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True + :type modal: bool + :return: clicked button + :rtype: "Yes" | "No" | None + """ + return popup(*args, title=title, button_type=POPUP_BUTTONS_YES_NO, background_color=background_color, + text_color=text_color, + non_blocking=non_blocking, icon=icon, line_width=line_width, button_color=button_color, + auto_close=auto_close, auto_close_duration=auto_close_duration, font=font, no_titlebar=no_titlebar, + grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location, relative_location=relative_location, image=image, modal=modal) + + +############################################################################## +# The popup_get_____ functions - Will return user input # +############################################################################## + +# --------------------------- popup_get_folder --------------------------- + + +def popup_get_folder(message, title=None, default_path='', no_window=False, size=(None, None), button_color=None, + background_color=None, text_color=None, icon=None, font=None, no_titlebar=False, + grab_anywhere=False, keep_on_top=None, location=(None, None), relative_location=(None, None), initial_folder=None, image=None, modal=True, history=False, + history_setting_filename=None): + """ + Display popup with text entry field and browse button so that a folder can be chosen. + + :param message: message displayed to user + :type message: (str) + :param title: Window title + :type title: (str) + :param default_path: path to display to user as starting point (filled into the input field) + :type default_path: (str) + :param no_window: if True, no PySimpleGUI window will be shown. Instead just the tkinter dialog is shown + :type no_window: (bool) + :param size: (width, height) of the InputText Element + :type size: (int, int) + :param button_color: button color (foreground, background) + :type button_color: (str, str) or str + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param icon: filename or base64 string to be used for the window's icon + :type icon: bytes | str + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + :param grab_anywhere: If True: can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param location: Location of upper left corner of the window + :type location: (int, int) + :param relative_location: (x,y) location relative to the default location of the window, in pixels. Normally the window centers. This location is relative to the location the window would be created. Note they can be negative. + :type relative_location: (int, int) + :param initial_folder: location in filesystem to begin browsing + :type initial_folder: (str) + :param image: Image to include at the top of the popup window + :type image: (str) or (bytes) + :param modal: If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True + :type modal: bool + :param history: If True then enable a "history" feature that will display previous entries used. Uses settings filename provided or default if none provided + :type history: bool + :param history_setting_filename: Filename to use for the User Settings. Will store list of previous entries in this settings file + :type history_setting_filename: (str) + :return: string representing the path chosen, None if cancelled or window closed with X + :rtype: str | None + """ + + # First setup the history settings file if history feature is enabled + if history and history_setting_filename is not None: + try: + history_settings = UserSettings(history_setting_filename) + except Exception as e: + _error_popup_with_traceback('popup_get_folder - Something is wrong with your supplied history settings filename', + 'Exception: {}'.format(e)) + return None + elif history: + history_settings_filename = os.path.basename(inspect.stack()[1].filename) + history_settings_filename = os.path.splitext(history_settings_filename)[0] + '.json' + history_settings = UserSettings(history_settings_filename) + else: + history_settings = None + + # global _my_windows + if no_window: + if not Window.hidden_master_root: + # if first window being created, make a throwaway, hidden master root. This stops one user + # window from becoming the child of another user window. All windows are children of this + # hidden window + Window._IncrementOpenCount() + Window.hidden_master_root = tk.Tk() + Window.hidden_master_root.attributes('-alpha', 0) # HIDE this window really really really + + # if not running_mac(): + try: + Window.hidden_master_root.wm_overrideredirect(True) + except Exception as e: + print('* Error performing wm_overrideredirect while hiding hidden master root in get folder *', e) + + Window.hidden_master_root.withdraw() + root = tk.Toplevel() + + try: + root.attributes('-alpha', 0) # hide window while building it. makes for smoother 'paint' + # if not running_mac(): + try: + root.wm_overrideredirect(True) + except Exception as e: + print('* Error performing wm_overrideredirect while hiding the window during creation in get folder *', e) + root.withdraw() + except: + pass + folder_name = tk.filedialog.askdirectory( + initialdir=initial_folder, + ) # show the 'get folder' dialog box + + root.destroy() + if Window.NumOpenWindows == 1: + Window.NumOpenWindows = 0 + Window.hidden_master_root.destroy() + Window.hidden_master_root = None + + return folder_name + + browse_button = FolderBrowse(initial_folder=initial_folder) + + if image is not None: + if isinstance(image, str): + layout = [[Image(filename=image)]] + else: + layout = [[Image(data=image)]] + else: + layout = [[]] + + layout += [[Text(message, auto_size_text=True, text_color=text_color, background_color=background_color)]] + + if not history: + layout += [[InputText(default_text=default_path, size=size, key='-INPUT-'), browse_button]] + else: + file_list = history_settings.get('-PSG folder list-', []) + last_entry = file_list[0] if file_list else '' + layout += [[Combo(file_list, default_value=last_entry, key='-INPUT-', size=size if size != (None, None) else (80, 1), bind_return_key=True), + browse_button, Button('Clear History', tooltip='Clears the list of folders shown in the combobox')]] + + layout += [[Button('Ok', size=(6, 1), bind_return_key=True), Button('Cancel', size=(6, 1))]] + + window = Window(title=title or message, layout=layout, icon=icon, auto_size_text=True, button_color=button_color, + font=font, background_color=background_color, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, + location=location, relative_location=relative_location, modal=modal) + + while True: + event, values = window.read() + if event in ('Cancel', WIN_CLOSED): + break + elif event == 'Clear History': + history_settings.set('-PSG folder list-', []) + window['-INPUT-'].update('', []) + popup_quick_message('History of Previous Choices Cleared', background_color='red', text_color='white', font='_ 20', keep_on_top=True) + elif event in ('Ok', '-INPUT-'): + if values['-INPUT-'] != '': + if history_settings is not None: + list_of_entries = history_settings.get('-PSG folder list-', []) + if values['-INPUT-'] in list_of_entries: + list_of_entries.remove(values['-INPUT-']) + list_of_entries.insert(0, values['-INPUT-']) + history_settings.set('-PSG folder list-', list_of_entries) + break + + window.close() + del window + if event in ('Cancel', WIN_CLOSED): + return None + + return values['-INPUT-'] + + +# --------------------------- popup_get_file --------------------------- + +def popup_get_file(message, title=None, default_path='', default_extension='', save_as=False, multiple_files=False, + file_types=FILE_TYPES_ALL_FILES, + no_window=False, size=(None, None), button_color=None, background_color=None, text_color=None, + icon=None, font=None, no_titlebar=False, grab_anywhere=False, keep_on_top=None, + location=(None, None), relative_location=(None, None), initial_folder=None, image=None, files_delimiter=BROWSE_FILES_DELIMITER, modal=True, history=False, show_hidden=True, + history_setting_filename=None): + """ + Display popup window with text entry field and browse button so that a file can be chosen by user. + + :param message: message displayed to user + :type message: (str) + :param title: Window title + :type title: (str) + :param default_path: path to display to user as starting point (filled into the input field) + :type default_path: (str) + :param default_extension: If no extension entered by user, add this to filename (only used in saveas dialogs) + :type default_extension: (str) + :param save_as: if True, the "save as" dialog is shown which will verify before overwriting + :type save_as: (bool) + :param multiple_files: if True, then allows multiple files to be selected that are returned with ';' between each filename + :type multiple_files: (bool) + :param file_types: List of extensions to show using wildcards. All files (the default) = (("ALL Files", "*.* *"),) + :type file_types: Tuple[Tuple[str,str]] + :param no_window: if True, no PySimpleGUI window will be shown. Instead just the tkinter dialog is shown + :type no_window: (bool) + :param size: (width, height) of the InputText Element or Combo element if using history feature + :type size: (int, int) + :param button_color: Color of the button (text, background) + :type button_color: (str, str) or str + :param background_color: background color of the entire window + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param icon: filename or base64 string to be used for the window's icon + :type icon: bytes | str + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + :param grab_anywhere: If True: can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param location: Location of upper left corner of the window + :type location: (int, int) + :param relative_location: (x,y) location relative to the default location of the window, in pixels. Normally the window centers. This location is relative to the location the window would be created. Note they can be negative. + :type relative_location: (int, int) + :param initial_folder: location in filesystem to begin browsing + :type initial_folder: (str) + :param image: Image to include at the top of the popup window + :type image: (str) or (bytes) + :param files_delimiter: String to place between files when multiple files are selected. Normally a ; + :type files_delimiter: str + :param modal: If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True + :type modal: bool + :param history: If True then enable a "history" feature that will display previous entries used. Uses settings filename provided or default if none provided + :type history: bool + :param show_hidden: If True then enables the checkbox in the system dialog to select hidden files to be shown + :type show_hidden: bool + :param history_setting_filename: Filename to use for the User Settings. Will store list of previous entries in this settings file + :type history_setting_filename: (str) + :return: string representing the file(s) chosen, None if cancelled or window closed with X + :rtype: str | None + """ + + # First setup the history settings file if history feature is enabled + if history and history_setting_filename is not None: + try: + history_settings = UserSettings(history_setting_filename) + except Exception as e: + _error_popup_with_traceback('popup_get_file - Something is wrong with your supplied history settings filename', + 'Exception: {}'.format(e)) + return None + elif history: + history_settings_filename = os.path.basename(inspect.stack()[1].filename) + history_settings_filename = os.path.splitext(history_settings_filename)[0] + '.json' + history_settings = UserSettings(history_settings_filename) + else: + history_settings = None + + if icon is None: + icon = Window._user_defined_icon or DEFAULT_BASE64_ICON + if no_window: + if not Window.hidden_master_root: + # if first window being created, make a throwaway, hidden master root. This stops one user + # window from becoming the child of another user window. All windows are children of this + # hidden window + Window._IncrementOpenCount() + Window.hidden_master_root = tk.Tk() + Window.hidden_master_root.attributes('-alpha', 0) # HIDE this window really really really + # if not running_mac(): + try: + Window.hidden_master_root.wm_overrideredirect(True) + except Exception as e: + print('* Error performing wm_overrideredirect in get file hiding the master root *', e) + Window.hidden_master_root.withdraw() + root = tk.Toplevel() + + try: + root.attributes('-alpha', 0) # hide window while building it. makes for smoother 'paint' + # if not running_mac(): + try: + root.wm_overrideredirect(True) + except Exception as e: + print('* Error performing wm_overrideredirect in get file *', e) + root.withdraw() + except: + pass + + if show_hidden is False: + try: + # call a dummy dialog with an impossible option to initialize the file + # dialog without really getting a dialog window; this will throw a + # TclError, so we need a try...except : + try: + root.tk.call('tk_getOpenFile', '-foobarbaz') + except tk.TclError: + pass + # now set the magic variables accordingly + root.tk.call('set', '::tk::dialog::file::showHiddenBtn', '1') + root.tk.call('set', '::tk::dialog::file::showHiddenVar', '0') + except: + pass + + if root and icon is not None: + _set_icon_for_tkinter_window(root, icon=icon) + # for Macs, setting parent=None fixes a warning problem. + if save_as: + filename = tk.filedialog.asksaveasfilename(filetypes=file_types, + initialdir=initial_folder, + initialfile=default_path, + parent=root if not running_mac() else None, + defaultextension=default_extension) # show the 'get file' dialog box + elif multiple_files: + filename = tk.filedialog.askopenfilenames(filetypes=file_types, + initialdir=initial_folder, + initialfile=default_path, + parent=root if not running_mac() else None, + defaultextension=default_extension) # show the 'get file' dialog box + else: + filename = tk.filedialog.askopenfilename(filetypes=file_types, + initialdir=initial_folder, + initialfile=default_path, + parent=root if not running_mac() else None, + defaultextension=default_extension) # show the 'get files' dialog box + root.destroy() + if Window.NumOpenWindows == 1: + Window.NumOpenWindows = 0 + Window.hidden_master_root.destroy() + Window.hidden_master_root = None + if not multiple_files and type(filename) in (tuple, list): + if len(filename): # only if not 0 length, otherwise will get an error + filename = filename[0] + return filename + + if save_as: + browse_button = SaveAs(file_types=file_types, initial_folder=initial_folder, default_extension=default_extension) + elif multiple_files: + browse_button = FilesBrowse(file_types=file_types, initial_folder=initial_folder, files_delimiter=files_delimiter) + else: + browse_button = FileBrowse(file_types=file_types, initial_folder=initial_folder) + + if image is not None: + if isinstance(image, str): + layout = [[Image(filename=image)]] + else: + layout = [[Image(data=image)]] + else: + layout = [[]] + + layout += [[Text(message, auto_size_text=True, text_color=text_color, background_color=background_color)]] + + if not history: + layout += [[InputText(default_text=default_path, size=size, key='-INPUT-'), browse_button]] + else: + file_list = history_settings.get("-PSG file list-", []) + last_entry = file_list[0] if file_list else '' + layout += [[Combo(file_list, default_value=last_entry, key='-INPUT-', size=size if size != (None, None) else (80, 1), bind_return_key=True), + browse_button, Button('Clear History', tooltip='Clears the list of files shown in the combobox')]] + + layout += [[Button('Ok', size=(6, 1), bind_return_key=True), Button('Cancel', size=(6, 1))]] + + window = Window(title=title or message, layout=layout, icon=icon, auto_size_text=True, button_color=button_color, + font=font, background_color=background_color, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location, relative_location=relative_location, modal=modal, finalize=True) + + if running_linux() and show_hidden is True: + window.TKroot.tk.eval('catch {tk_getOpenFile -badoption}') # dirty hack to force autoloading of Tk's file dialog code + window.TKroot.setvar('::tk::dialog::file::showHiddenBtn', 1) # enable the "show hidden files" checkbox (it's necessary) + window.TKroot.setvar('::tk::dialog::file::showHiddenVar', 0) # start with the hidden files... well... hidden + + while True: + event, values = window.read() + if event in ('Cancel', WIN_CLOSED): + break + elif event == 'Clear History': + history_settings.set('-PSG file list-', []) + window['-INPUT-'].update('', []) + popup_quick_message('History of Previous Choices Cleared', background_color='red', text_color='white', font='_ 20', keep_on_top=True) + elif event in ('Ok', '-INPUT-'): + if values['-INPUT-'] != '': + if history_settings is not None: + list_of_entries = history_settings.get('-PSG file list-', []) + if values['-INPUT-'] in list_of_entries: + list_of_entries.remove(values['-INPUT-']) + list_of_entries.insert(0, values['-INPUT-']) + history_settings.set('-PSG file list-', list_of_entries) + break + + window.close(); + del window + if event in ('Cancel', WIN_CLOSED): + return None + + return values['-INPUT-'] + + +# --------------------------- popup_get_text --------------------------- + +def popup_get_text(message, title=None, default_text='', password_char='', size=(None, None), button_color=None, + background_color=None, text_color=None, icon=None, font=None, no_titlebar=False, + grab_anywhere=False, keep_on_top=None, location=(None, None), relative_location=(None, None), image=None, modal=True): + """ + Display Popup with text entry field. Returns the text entered or None if closed / cancelled + + :param message: message displayed to user + :type message: (str) + :param title: Window title + :type title: (str) + :param default_text: default value to put into input area + :type default_text: (str) + :param password_char: character to be shown instead of actually typed characters + :type password_char: (str) + :param size: (width, height) of the InputText Element + :type size: (int, int) + :param button_color: Color of the button (text, background) + :type button_color: (str, str) or str + :param background_color: background color of the entire window + :type background_color: (str) + :param text_color: color of the message text + :type text_color: (str) + :param icon: filename or base64 string to be used for the window's icon + :type icon: bytes | str + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: (str or (str, int[, str]) or None) + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + :param grab_anywhere: If True can click and drag anywhere in the window to move the window + :type grab_anywhere: (bool) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param location: (x,y) Location on screen to display the upper left corner of window + :type location: (int, int) + :param relative_location: (x,y) location relative to the default location of the window, in pixels. Normally the window centers. This location is relative to the location the window would be created. Note they can be negative. + :type relative_location: (int, int) + :param image: Image to include at the top of the popup window + :type image: (str) or (bytes) + :param modal: If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True + :type modal: bool + :return: Text entered or None if window was closed or cancel button clicked + :rtype: str | None + """ + + if image is not None: + if isinstance(image, str): + layout = [[Image(filename=image)]] + else: + layout = [[Image(data=image)]] + else: + layout = [[]] + + layout += [[Text(message, auto_size_text=True, text_color=text_color, background_color=background_color, font=font)], + [InputText(default_text=default_text, size=size, key='_INPUT_', password_char=password_char)], + [Button('Ok', size=(6, 1), bind_return_key=True), Button('Cancel', size=(6, 1))]] + + window = Window(title=title or message, layout=layout, icon=icon, auto_size_text=True, button_color=button_color, no_titlebar=no_titlebar, + background_color=background_color, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location, relative_location=relative_location, finalize=True, modal=modal) + + button, values = window.read() + window.close() + del window + if button != 'Ok': + return None + else: + path = values['_INPUT_'] + return path + + +def popup_get_date(start_mon=None, start_day=None, start_year=None, begin_at_sunday_plus=0, no_titlebar=True, title='Choose Date', keep_on_top=True, + location=(None, None), relative_location=(None, None), close_when_chosen=False, icon=None, locale=None, month_names=None, day_abbreviations=None, modal=True): + """ + Display a calendar window, get the user's choice, return as a tuple (mon, day, year) + + :param start_mon: The starting month + :type start_mon: (int) + :param start_day: The starting day - optional. Set to None or 0 if no date to be chosen at start + :type start_day: int | None + :param start_year: The starting year + :type start_year: (int) + :param begin_at_sunday_plus: Determines the left-most day in the display. 0=sunday, 1=monday, etc + :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 + :type icon: (str | bytes) + :param location: (x,y) location on the screen to place the top left corner of your window. Default is to center on screen + :type location: (int, int) + :param relative_location: (x,y) location relative to the default location of the window, in pixels. Normally the window centers. This location is relative to the location the window would be created. Note they can be negative. + :type relative_location: (int, int) + :param title: Title that will be shown on the window + :type title: (str) + :param close_when_chosen: If True, the window will close and function return when a day is clicked + :type close_when_chosen: (bool) + :param locale: locale used to get the day names + :type locale: (str) + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param month_names: optional list of month names to use (should be 12 items) + :type month_names: List[str] + :param day_abbreviations: optional list of abbreviations to display as the day of week + :type day_abbreviations: List[str] + :param modal: If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True + :type modal: bool + :return: Tuple containing (month, day, year) of chosen date or None if was cancelled + :rtype: None | (int, int, int) + """ + + if month_names is not None and len(month_names) != 12: + if not SUPPRESS_ERROR_POPUPS: + popup_error('Incorrect month names list specified. Must have 12 entries.', 'Your list:', month_names) + + if day_abbreviations is not None and len(day_abbreviations) != 7: + if not SUPPRESS_ERROR_POPUPS: + popup_error('Incorrect day abbreviation list. Must have 7 entries.', 'Your list:', day_abbreviations) + + day_font = 'TkFixedFont 9' + mon_year_font = 'TkFixedFont 10' + arrow_font = 'TkFixedFont 7' + + now = datetime.datetime.now() + cur_month, cur_day, cur_year = now.month, now.day, now.year + cur_month = start_mon or cur_month + if start_mon is not None: + cur_day = start_day + else: + cur_day = cur_day + cur_year = start_year or cur_year + + def update_days(window, month, year, begin_at_sunday_plus): + [window[(week, day)].update('') for day in range(7) for week in range(6)] + weeks = calendar.monthcalendar(year, month) + month_days = list(itertools.chain.from_iterable([[0 for _ in range(8 - begin_at_sunday_plus)]] + weeks)) + if month_days[6] == 0: + month_days = month_days[7:] + if month_days[6] == 0: + month_days = month_days[7:] + for i, day in enumerate(month_days): + offset = i + if offset >= 6 * 7: + break + window[(offset // 7, offset % 7)].update(str(day) if day else '') + + def make_days_layout(): + days_layout = [] + for week in range(6): + row = [] + for day in range(7): + row.append(T('', size=(4, 1), justification='c', font=day_font, key=(week, day), enable_events=True, pad=(0, 0))) + days_layout.append(row) + return days_layout + + # Create table of month names and week day abbreviations + + if day_abbreviations is None or len(day_abbreviations) != 7: + fwday = calendar.SUNDAY + try: + if locale is not None: + _cal = calendar.LocaleTextCalendar(fwday, locale) + else: + _cal = calendar.TextCalendar(fwday) + day_names = _cal.formatweekheader(3).split() + except Exception as e: + print('Exception building day names from locale', locale, e) + day_names = ('Sun', 'Mon', 'Tue', 'Wed', 'Th', 'Fri', 'Sat') + else: + day_names = day_abbreviations + + mon_names = month_names if month_names is not None and len(month_names) == 12 else [calendar.month_name[i] for i in range(1, 13)] + days_layout = make_days_layout() + + layout = [[B('◄◄', font=arrow_font, border_width=0, key='-YEAR-DOWN-', pad=((10, 2), 2)), + B('◄', font=arrow_font, border_width=0, key='-MON-DOWN-', pad=(0, 2)), + Text('{} {}'.format(mon_names[cur_month - 1], cur_year), size=(16, 1), justification='c', font=mon_year_font, key='-MON-YEAR-', pad=(0, 2)), + B('►', font=arrow_font, border_width=0, key='-MON-UP-', pad=(0, 2)), + B('►►', font=arrow_font, border_width=0, key='-YEAR-UP-', pad=(2, 2))]] + layout += [[Col([[T(day_names[i - (7 - 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 + if not close_when_chosen: + layout += [[Button('Ok', border_width=0, font='TkFixedFont 8'), Button('Cancel', border_width=0, font='TkFixedFont 8')]] + + window = Window(title, layout, no_titlebar=no_titlebar, grab_anywhere=True, keep_on_top=keep_on_top, font='TkFixedFont 12', use_default_focus=False, + location=location, relative_location=relative_location, finalize=True, icon=icon) + + update_days(window, cur_month, cur_year, begin_at_sunday_plus) + + prev_choice = chosen_mon_day_year = None + + if cur_day: + chosen_mon_day_year = cur_month, cur_day, cur_year + for week in range(6): + for day in range(7): + if window[(week, day)].DisplayText == str(cur_day): + window[(week, day)].update(background_color=theme_text_color(), text_color=theme_background_color()) + prev_choice = (week, day) + break + + if modal: + window.make_modal() + + while True: # Event Loop + event, values = window.read() + if event in (None, 'Cancel'): + chosen_mon_day_year = None + break + if event == 'Ok': + break + if event in ('-MON-UP-', '-MON-DOWN-', '-YEAR-UP-', '-YEAR-DOWN-'): + cur_month += (event == '-MON-UP-') + cur_month -= (event == '-MON-DOWN-') + cur_year += (event == '-YEAR-UP-') + cur_year -= (event == '-YEAR-DOWN-') + if cur_month > 12: + cur_month = 1 + cur_year += 1 + elif cur_month < 1: + cur_month = 12 + cur_year -= 1 + window['-MON-YEAR-'].update('{} {}'.format(mon_names[cur_month - 1], cur_year)) + update_days(window, cur_month, cur_year, begin_at_sunday_plus) + if prev_choice: + window[prev_choice].update(background_color=theme_background_color(), text_color=theme_text_color()) + elif type(event) is tuple: + if window[event].DisplayText != "": + chosen_mon_day_year = cur_month, int(window[event].DisplayText), cur_year + if prev_choice: + window[prev_choice].update(background_color=theme_background_color(), text_color=theme_text_color()) + window[event].update(background_color=theme_text_color(), text_color=theme_background_color()) + prev_choice = event + if close_when_chosen: + break + window.close() + return chosen_mon_day_year + + +# --------------------------- PopupAnimated --------------------------- + +def popup_animated(image_source, message=None, background_color=None, text_color=None, font=None, no_titlebar=True, grab_anywhere=True, keep_on_top=True, + location=(None, None), relative_location=(None, None), alpha_channel=None, time_between_frames=0, transparent_color=None, title='', icon=None): + """ + Show animation one frame at a time. This function has its own internal clocking meaning you can call it at any frequency + and the rate the frames of video is shown remains constant. Maybe your frames update every 30 ms but your + event loop is running every 10 ms. You don't have to worry about delaying, just call it every time through the + loop. + + :param image_source: Either a filename or a base64 string. Use None to close the window. + :type image_source: str | bytes | None + :param message: An optional message to be shown with the animation + :type message: (str) + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: str | tuple + :param no_titlebar: If True then the titlebar and window frame will not be shown + :type no_titlebar: (bool) + :param grab_anywhere: If True then you can move the window just clicking anywhere on window, hold and drag + :type grab_anywhere: (bool) + :param keep_on_top: If True then Window will remain on top of all other windows currently shownn + :type keep_on_top: (bool) + :param location: (x,y) location on the screen to place the top left corner of your window. Default is to center on screen + :type location: (int, int) + :param relative_location: (x,y) location relative to the default location of the window, in pixels. Normally the window centers. This location is relative to the location the window would be created. Note they can be negative. + :type relative_location: (int, int) + :param alpha_channel: Window transparency 0 = invisible 1 = completely visible. Values between are see through + :type alpha_channel: (float) + :param time_between_frames: Amount of time in milliseconds between each frame + :type time_between_frames: (int) + :param transparent_color: This color will be completely see-through in your window. Can even click through + :type transparent_color: (str) + :param title: Title that will be shown on the window + :type title: (str) + :param icon: Same as Window icon parameter. Can be either a filename or Base64 byte string. For Windows if filename, it MUST be ICO format. For Linux, must NOT be ICO + :type icon: str | bytes + :return: True if the window updated OK. False if the window was closed + :rtype: bool + """ + if image_source is None: + for image in Window._animated_popup_dict: + window = Window._animated_popup_dict[image] + window.close() + Window._animated_popup_dict = {} + return + + if image_source not in Window._animated_popup_dict: + if type(image_source) is bytes or len(image_source) > 300: + layout = [[Image(data=image_source, background_color=background_color, key='-IMAGE-')], ] + else: + layout = [[Image(filename=image_source, background_color=background_color, key='-IMAGE-', )], ] + if message: + layout.append([Text(message, background_color=background_color, text_color=text_color, font=font)]) + + window = Window(title, layout, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, + keep_on_top=keep_on_top, background_color=background_color, location=location, + alpha_channel=alpha_channel, element_padding=(0, 0), margins=(0, 0), + transparent_color=transparent_color, finalize=True, element_justification='c', icon=icon, relative_location=relative_location) + Window._animated_popup_dict[image_source] = window + else: + window = Window._animated_popup_dict[image_source] + window['-IMAGE-'].update_animation(image_source, time_between_frames=time_between_frames) + event, values = window.read(1) + if event == WIN_CLOSED: + return False + # window.refresh() # call refresh instead of Read to save significant CPU time + return True + + +# Popup Notify +def popup_notify(*args, title='', icon=SYSTEM_TRAY_MESSAGE_ICON_INFORMATION, display_duration_in_ms=SYSTEM_TRAY_MESSAGE_DISPLAY_DURATION_IN_MILLISECONDS, + fade_in_duration=SYSTEM_TRAY_MESSAGE_FADE_IN_DURATION, alpha=0.9, location=None): + """ + Displays a "notification window", usually in the bottom right corner of your display. Has an icon, a title, and a message. It is more like a "toaster" window than the normal popups. + + The window will slowly fade in and out if desired. Clicking on the window will cause it to move through the end the current "phase". For example, if the window was fading in and it was clicked, then it would immediately stop fading in and instead be fully visible. It's a way for the user to quickly dismiss the window. + + The return code specifies why the call is returning (e.g. did the user click the message to dismiss it) + + :param title: Text to be shown at the top of the window in a larger font + :type title: (str) + :param message: Text message that makes up the majority of the window + :type message: (str) + :param icon: A base64 encoded PNG/GIF image or PNG/GIF filename that will be displayed in the window + :type icon: bytes | str + :param display_duration_in_ms: Number of milliseconds to show the window + :type display_duration_in_ms: (int) + :param fade_in_duration: Number of milliseconds to fade window in and out + :type fade_in_duration: (int) + :param alpha: Alpha channel. 0 - invisible 1 - fully visible + :type alpha: (float) + :param location: Location on the screen to display the window + :type location: (int, int) + :return: reason for returning + :rtype: (int) + """ + + if not args: + args_to_print = [''] + else: + args_to_print = args + output = '' + max_line_total, total_lines, local_line_width = 0, 0, SYSTEM_TRAY_MESSAGE_MAX_LINE_LENGTH + for message in args_to_print: + # fancy code to check if string and convert if not is not need. Just always convert to string :-) + # if not isinstance(message, str): message = str(message) + message = str(message) + if message.count('\n'): + message_wrapped = message + else: + message_wrapped = textwrap.fill(message, local_line_width) + message_wrapped_lines = message_wrapped.count('\n') + 1 + longest_line_len = max([len(l) for l in message.split('\n')]) + width_used = min(longest_line_len, local_line_width) + max_line_total = max(max_line_total, width_used) + # height = _GetNumLinesNeeded(message, width_used) + height = message_wrapped_lines + output += message_wrapped + '\n' + total_lines += height + + message = output + + # def __init__(self, menu=None, filename=None, data=None, data_base64=None, tooltip=None, metadata=None): + return SystemTray.notify(title=title, message=message, icon=icon, display_duration_in_ms=display_duration_in_ms, fade_in_duration=fade_in_duration, + alpha=alpha, location=location) + + +def popup_menu(window, element, menu_def, title=None, location=(None, None)): + """ + Makes a "popup menu" + This type of menu is what you get when a normal menu or a right click menu is torn off + The settings for the menu are obtained from the window parameter's Window + + + :param window: The window associated with the popup menu. The theme and right click menu settings for this window will be used + :type window: Window + :param element: An element in your window to associate the menu to. It can be any element + :type element: Element + :param menu_def: A menu definition. This will be the same format as used for Right Click Menus1 + :type menu_def: List[List[ List[str] | str ]] + :param title: The title that will be shown on the torn off menu window. Defaults to window titlr + :type title: str + :param location: The location on the screen to place the window + :type location: (int, int) | (None, None) + """ + + element._popup_menu_location = location + top_menu = tk.Menu(window.TKroot, tearoff=True, tearoffcommand=element._tearoff_menu_callback) + if window.right_click_menu_background_color not in (COLOR_SYSTEM_DEFAULT, None): + top_menu.config(bg=window.right_click_menu_background_color) + if window.right_click_menu_text_color not in (COLOR_SYSTEM_DEFAULT, None): + top_menu.config(fg=window.right_click_menu_text_color) + if window.right_click_menu_disabled_text_color not in (COLOR_SYSTEM_DEFAULT, None): + top_menu.config(disabledforeground=window.right_click_menu_disabled_text_color) + if window.right_click_menu_font is not None: + top_menu.config(font=window.right_click_menu_font) + if window.right_click_menu_selected_colors[0] != COLOR_SYSTEM_DEFAULT: + top_menu.config(activeforeground=window.right_click_menu_selected_colors[0]) + if window.right_click_menu_selected_colors[1] != COLOR_SYSTEM_DEFAULT: + top_menu.config(activebackground=window.right_click_menu_selected_colors[1]) + top_menu.config(title=window.Title if title is None else title) + AddMenuItem(top_menu, menu_def[1], element, right_click_menu=True) + # element.Widget.bind('', element._RightClickMenuCallback) + top_menu.invoke(0) + + +def popup_error_with_traceback(title, *messages): + """ + Show an error message and as many additoinal lines of messages as you want. + Will show the same error window as PySimpleGUI uses internally. Has a button to + take the user to the line of code you called this popup from + + :param title: The title that will be shown in the popup's titlebar and in the first line of the window + :type title: str + :param messages: A variable number of lines of messages you wish to show your user + :type messages: *Any + """ + + # For now, call the function that PySimpleGUI uses internally + _error_popup_with_traceback(str(title), *messages) + + +def _error_popup_with_traceback(title, *args): + if SUPPRESS_ERROR_POPUPS: + return + trace_details = traceback.format_stack() + error_message = '' + file_info_pysimplegui = None + for line in reversed(trace_details): + if __file__ not in line: + file_info_pysimplegui = line.split(",")[0] + error_message = line + break + if file_info_pysimplegui is None: + _error_popup_with_code(title, None, None, 'Did not find your error info') + return + + error_parts = None + if error_message != '': + error_parts = error_message.split(', ') + if len(error_parts) < 4: + error_message = error_parts[0] + '\n' + error_parts[1] + '\n' + ''.join(error_parts[2:]) + if error_parts is None: + print('*** Error popup attempted but unable to parse error details ***') + print(trace_details) + return + filename = error_parts[0][error_parts[0].index('File ') + 5:] + line_num = error_parts[1][error_parts[1].index('line ') + 5:] + _error_popup_with_code(title, filename, line_num, error_message, *args) + + +def _error_popup_with_code(title, filename=None, line_num=None, *args): + layout = [[Text('ERROR'), Text(title)], + [Image(data=_random_error_emoji())]] + # make max length of line be 90 chars and allow the height to vary based on number of needed lines + lines = [str(msg).split('\n') for msg in args] + max_line_len = 0 + for line in lines: + max_line_len = max(max_line_len, max([len(s) for s in line])) + + layout += [[Text(str(msg), size=(min(max_line_len, 90), None))] for msg in args] + + layout += [[Button('Close'), Button('Take me to error'), Button('Kill Application', button_color='white on red')]] + + window = Window(title, layout, keep_on_top=True) + + while True: + event, values = window.read() + if event in ('Close', WIN_CLOSED): + break + if event == 'Kill Application': + window.close() + popup_quick_message('KILLING APP! BYE!', font='_ 18', keep_on_top=True, text_color='white', background_color='red', non_blocking=False) + sys.exit() + if event == 'Take me to error' and filename is not None and line_num is not None: + execute_editor(filename, line_num) + + window.close() + + +##################################################################### +# Animated window while shell command is executed +##################################################################### + +def _process_thread(*args): + global __shell_process__ + + # start running the command with arugments + try: + __shell_process__ = subprocess.run(args, shell=True, stdout=subprocess.PIPE) + except Exception as e: + print('Exception running process args = {}'.format(args)) + __shell_process__ = None + + +def shell_with_animation(command, args=None, image_source=DEFAULT_BASE64_LOADING_GIF, message=None, background_color=None, text_color=None, font=None, + no_titlebar=True, grab_anywhere=True, keep_on_top=True, location=(None, None), alpha_channel=None, time_between_frames=100, + transparent_color=None): + """ + Execute a "shell command" (anything capable of being launched using subprocess.run) and + while the command is running, show an animated popup so that the user knows that a long-running + command is being executed. Without this mechanism, the GUI appears locked up. + + :param command: The command to run + :type command: (str) + :param args: List of arguments + :type args: List[str] + :param image_source: Either a filename or a base64 string. + :type image_source: str | bytes + :param message: An optional message to be shown with the animation + :type message: (str) + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike + :type font: str | tuple + :param no_titlebar: If True then the titlebar and window frame will not be shown + :type no_titlebar: (bool) + :param grab_anywhere: If True then you can move the window just clicking anywhere on window, hold and drag + :type grab_anywhere: (bool) + :param keep_on_top: If True then Window will remain on top of all other windows currently shownn + :type keep_on_top: (bool) + :param location: (x,y) location on the screen to place the top left corner of your window. Default is to center on screen + :type location: (int, int) + :param alpha_channel: Window transparency 0 = invisible 1 = completely visible. Values between are see through + :type alpha_channel: (float) + :param time_between_frames: Amount of time in milliseconds between each frame + :type time_between_frames: (int) + :param transparent_color: This color will be completely see-through in your window. Can even click through + :type transparent_color: (str) + :return: The resulting string output from stdout + :rtype: (str) + """ + + global __shell_process__ + + real_args = [command] + if args is not None: + for arg in args: + real_args.append(arg) + # real_args.append(args) + thread = threading.Thread(target=_process_thread, args=real_args, daemon=True) + thread.start() + + # Poll to see if the thread is still running. If so, then continue showing the animation + while True: + popup_animated(image_source=image_source, message=message, time_between_frames=time_between_frames, transparent_color=transparent_color, + text_color=text_color, background_color=background_color, font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, + keep_on_top=keep_on_top, location=location, alpha_channel=alpha_channel) + thread.join(timeout=time_between_frames / 1000) + if not thread.is_alive(): + break + popup_animated(None) # stop running the animation + + output = __shell_process__.__str__().replace('\\r\\n', '\n') # fix up the output string + output = output[output.index("stdout=b'") + 9:-2] + return output + + +####################################################################### +# 8888888888 +# 888 +# 888 +# 8888888 888d888 888d888 .d88b. 888d888 +# 888 888P" 888P" d88""88b 888P" +# 888 888 888 888 888 888 +# 888 888 888 Y88..88P 888 +# 8888888888 888 888 "Y88P" 888 +# +# +# +# 888b d888 +# 8888b d8888 +# 88888b.d88888 +# 888Y88888P888 .d88b. .d8888b .d8888b 8888b. .d88b. .d88b. +# 888 Y888P 888 d8P Y8b 88K 88K "88b d88P"88b d8P Y8b +# 888 Y8P 888 88888888 "Y8888b. "Y8888b. .d888888 888 888 88888888 +# 888 " 888 Y8b. X88 X88 888 888 Y88b 888 Y8b. +# 888 888 "Y8888 88888P' 88888P' "Y888888 "Y88888 "Y8888 +# 888 +# Y8b d88P +# "Y88P" +# Code to make messages to help user find errors in their code +####################################################################### + +def _create_error_message(): + """ + Creates an error message containing the filename and line number of the users + code that made the call into PySimpleGUI + :return: Error string to display with file, line number, and line of code + :rtype: str + """ + + called_func = inspect.stack()[1].function + trace_details = traceback.format_stack() + error_message = '' + file_info_pysimplegui = trace_details[-1].split(",")[0] + for line in reversed(trace_details): + if line.split(",")[0] != file_info_pysimplegui: + error_message = line + break + if error_message != '': + error_parts = error_message.split(', ') + if len(error_parts) < 4: + error_message = error_parts[0] + '\n' + error_parts[1] + '\n' + ''.join(error_parts[2:]) + return 'The PySimpleGUI internal reporting function is ' + called_func + '\n' + \ + 'The error originated from:\n' + error_message + + +# .d8888b. 888 888 d8b +# d88P Y88b 888 888 Y8P +# Y88b. 888 888 +# "Y888b. .d88b. 888888 888888 888 88888b. .d88b. .d8888b +# "Y88b. d8P Y8b 888 888 888 888 "88b d88P"88b 88K +# "888 88888888 888 888 888 888 888 888 888 "Y8888b. +# Y88b d88P Y8b. Y88b. Y88b. 888 888 888 Y88b 888 X88 +# "Y8888P" "Y8888 "Y888 "Y888 888 888 888 "Y88888 88888P' +# 888 +# Y8b d88P +# "Y88P" + +# Interface to saving / loading user program settings in json format +# This is a new set of APIs supplied by PySimpleGUI that enables users to easily set/save/load individual +# settings. They are automatically saved to a JSON file. If no file/path is specified then a filename is +# created from the source file filename. + +class UserSettings: + # A reserved settings object for use by the setting functions. It's a way for users + # to access the user settings without diarectly using the UserSettings class + _default_for_function_interface = None # type: UserSettings + + def __init__(self, filename=None, path=None, silent_on_error=False, autosave=True, use_config_file=None, convert_bools_and_none=True): + """ + User Settings + + :param filename: The name of the file to use. Can be a full path and filename or just filename + :type filename: (str or None) + :param path: The folder that the settings file will be stored in. Do not include the filename. + :type path: (str or None) + :param silent_on_error: If True errors will not be reported + :type silent_on_error: (bool) + :param autosave: If True the settings file is saved after every update + :type autosave: (bool) + :param use_config_file: If True then the file format will be a config.ini rather than json + :type use_config_file: (bool) + :param convert_bools_and_none: If True then "True", "False", "None" will be converted to the Python values True, False, None when using INI files. Default is TRUE + :type convert_bools_and_none: (bool) + """ + + self.path = path + self.filename = filename + self.full_filename = None + self.dict = {} + self.default_value = None + self.silent_on_error = silent_on_error + self.autosave = autosave + if filename is not None and filename.endswith('.ini') and use_config_file is None: + warnings.warn('[UserSettings] You have specified a filename with .ini extension but did not set use_config_file. Setting use_config_file for you.', UserWarning) + use_config_file = True + self.use_config_file = use_config_file + # self.retain_config_comments = retain_config_comments + self.convert_bools = convert_bools_and_none + if use_config_file: + self.config = configparser.ConfigParser() + self.config.optionxform = str + # self.config_dict = {} + self.section_class_dict = {} # type: dict[_SectionDict] + if filename is not None or path is not None: + self.load(filename=filename, path=path) + + + ######################################################################################################## + ## FIRST is the _SectionDict helper class + ## It is typically not directly accessed, although it is possible to call delete_section, get, set + ######################################################################################################## + + class _SectionDict: + item_count = 0 + def __init__(self, section_name, section_dict, config, user_settings_parent): # (str, Dict, configparser.ConfigParser) + """ + The Section Dictionary. It holds the values for a section. + + :param section_name: Name of the section + :type section_name: str + :param section_dict: Dictionary of values for the section + :type section_dict: dict + :param config: The configparser object + :type config: configparser.ConfigParser + :param user_settings_parent: The parent UserSettings object that hdas this section + :type user_settings_parent: UserSettings + """ + self.section_name = section_name + self.section_dict = section_dict # type: Dict + self.new_section = False + self.config = config # type: configparser.ConfigParser + self.user_settings_parent = user_settings_parent # type: UserSettings + UserSettings._SectionDict.item_count += 1 + + if self.user_settings_parent.convert_bools: + for key, value in self.section_dict.items(): + if value == 'True': + value = True + self.section_dict[key] = value + elif value == 'False': + value = False + self.section_dict[key] = value + elif value == 'None': + value = None + self.section_dict[key] = value + # print(f'++++++ making a new SectionDict with name = {section_name}') + + + def __repr__(self): + """ + Converts the settings dictionary into a string for easy display + + :return: the dictionary as a string + :rtype: (str) + """ + return_string = '{}:\n'.format(self.section_name) + for entry in self.section_dict.keys(): + return_string += ' {} : {}\n'.format(entry, self.section_dict[entry]) + + return return_string + + + def get(self, key, default=None): + """ + Returns the value of a specified setting. If the setting is not found in the settings dictionary, then + the user specified default value will be returned. It no default is specified and nothing is found, then + the "default value" is returned. This default can be specified in this call, or previously defined + by calling set_default. If nothing specified now or previously, then None is returned as default. + + :param key: Key used to lookup the setting in the settings dictionary + :type key: (Any) + :param default: Value to use should the key not be found in the dictionary + :type default: (Any) + :return: Value of specified settings + :rtype: (Any) + """ + value = self.section_dict.get(key, default) + if self.user_settings_parent.convert_bools: + if value == 'True': + value = True + elif value == 'False': + value = False + return value + + def set(self, key, value): + value = str(value) # all values must be strings + if self.new_section: + self.config.add_section(self.section_name) + self.new_section = False + self.config.set(section=self.section_name, option=key, value=value) + self.section_dict[key] = value + if self.user_settings_parent.autosave: + self.user_settings_parent.save() + + def delete_section(self): + # print(f'** Section Dict deleting section = {self.section_name}') + self.config.remove_section(section=self.section_name) + del self.user_settings_parent.section_class_dict[self.section_name] + if self.user_settings_parent.autosave: + self.user_settings_parent.save() + + def __getitem__(self, item): + # print('*** In SectionDict Get ***') + return self.get(item) + + def __setitem__(self, item, value): + """ + Enables setting a setting by using [ ] notation like a dictionary. + Your code will have this kind of design pattern: + settings = sg.UserSettings() + settings[item] = value + + :param item: The key for the setting to change. Needs to be a hashable type. Basically anything but a list + :type item: Any + :param value: The value to set the setting to + :type value: Any + """ + # print(f'*** In SectionDict SET *** item = {item} value = {value}') + self.set(item, value) + self.section_dict[item] = value + + def __delitem__(self, item): + """ + Delete an individual user setting. This is the same as calling delete_entry. The syntax + for deleting the item using this manner is: + del settings['entry'] + :param item: The key for the setting to delete + :type item: Any + """ + # print(f'** In SectionDict delete! section name = {self.section_name} item = {item} ') + self.config.remove_option(section=self.section_name, option=item) + try: + del self.section_dict[item] + except Exception as e: + pass + # print(e) + if self.user_settings_parent.autosave: + self.user_settings_parent.save() + + + ######################################################################################################## + + def __repr__(self): + """ + Converts the settings dictionary into a string for easy display + + :return: the dictionary as a string + :rtype: (str) + """ + if not self.use_config_file: + return pprint.pformat(self.dict) + else: + # rvalue = '-------------------- Settings ----------------------\n' + rvalue = '' + for name, section in self.section_class_dict.items(): + rvalue += str(section) + + # rvalue += '\n-------------------- Settings End----------------------\n' + rvalue += '\n' + return rvalue + # return str(self.dict) # previouisly returned just a string version of the dictionary + + + def set_default_value(self, default): + """ + Set the value that will be returned if a requested setting is not found + + :param default: value to be returned if a setting is not found in the settings dictionary + :type default: Any + """ + self.default_value = default + + def _compute_filename(self, filename=None, path=None): + """ + Creates the full filename given the path or the filename or both. + + :param filename: The name of the file to use. Can be a full path and filename or just filename + :type filename: (str or None) + :param path: The folder that the settings file will be stored in. Do not include the filename. + :type path: (str or None) + :return: Tuple with (full filename, path, filename) + :rtype: Tuple[str, str, str] + """ + if filename is not None: + dirname_from_filename = os.path.dirname(filename) # see if a path was provided as part of filename + if dirname_from_filename: + path = dirname_from_filename + filename = os.path.basename(filename) + elif self.filename is not None: + filename = self.filename + else: + if not self.use_config_file: + filename = os.path.splitext(os.path.basename(sys.modules["__main__"].__file__))[0] + '.json' + else: + filename = os.path.splitext(os.path.basename(sys.modules["__main__"].__file__))[0] + '.ini' + + if path is None: + if self.path is not None: + # path = self.path + path = os.path.expanduser(self.path) # expand user provided path in case it has user ~ in it. Don't think it'll hurt + elif DEFAULT_USER_SETTINGS_PATH is not None: # if user set the path manually system-wide using set options + path = os.path.expanduser(DEFAULT_USER_SETTINGS_PATH) + elif running_trinket(): + path = os.path.expanduser(DEFAULT_USER_SETTINGS_TRINKET_PATH) + elif running_replit(): + path = os.path.expanduser(DEFAULT_USER_SETTINGS_REPLIT_PATH) + elif running_windows(): + path = os.path.expanduser(DEFAULT_USER_SETTINGS_WIN_PATH) + elif running_linux(): + path = os.path.expanduser(DEFAULT_USER_SETTINGS_LINUX_PATH) + elif running_mac(): + path = os.path.expanduser(DEFAULT_USER_SETTINGS_MAC_PATH) + else: + path = '.' + + full_filename = os.path.join(path, filename) + return (full_filename, path, filename) + + def set_location(self, filename=None, path=None): + """ + Sets the location of the settings file + + :param filename: The name of the file to use. Can be a full path and filename or just filename + :type filename: (str or None) + :param path: The folder that the settings file will be stored in. Do not include the filename. + :type path: (str or None) + """ + cfull_filename, cpath, cfilename = self._compute_filename(filename=filename, path=path) + + self.filename = cfilename + self.path = cpath + self.full_filename = cfull_filename + + def get_filename(self, filename=None, path=None): + """ + Sets the filename and path for your settings file. Either paramter can be optional. + + If you don't choose a path, one is provided for you that is OS specific + Windows path default = users/name/AppData/Local/PySimpleGUI/settings. + + If you don't choose a filename, your application's filename + '.json' will be used. + + Normally the filename and path are split in the user_settings calls. However for this call they + can be combined so that the filename contains both the path and filename. + + :param filename: The name of the file to use. Can be a full path and filename or just filename + :type filename: (str or None) + :param path: The folder that the settings file will be stored in. Do not include the filename. + :type path: (str or None) + :return: The full pathname of the settings file that has both the path and filename combined. + :rtype: (str) + """ + if filename is not None or path is not None or (filename is None and path is None and self.full_filename is None): + self.set_location(filename=filename, path=path) + self.read() + return self.full_filename + + # + # def merge_comments_from_file(self, full_filename): + # print('--- merging comments -----') + # merged_lines = [] + # with open(full_filename, 'r') as f: + # new_file_contents = f.readlines() + # current_section = '' + # for line in new_file_contents: + # if len(line) == 0: # skip blank lines + # merged_lines.append(line) + # continue + # if line[0] == '[': # if a new section + # current_section = line[:line.index(']')] + # merged_lines.append(line) + # continue + # if len(line.lstrip()): + # if line.lstrip()[0] == '#': # if a comment line, save it + # merged_lines.append(line) + # # Process a line with an = in it + # try: + # key = line[:line.index('=')] + # merged_lines.append(line) + # except: + # merged_lines.append(line) + # print('--- merging complete ----') + # print(*merged_lines) + # + + + def save(self, filename=None, path=None): + """ + Saves the current settings dictionary. If a filename or path is specified in the call, then it will override any + previously specitfied filename to create a new settings file. The settings dictionary is then saved to the newly defined file. + + :param filename: The fFilename to save to. Can specify a path or just the filename. If no filename specified, then the caller's filename will be used. + :type filename: (str or None) + :param path: The (optional) path to use to save the file. + :type path: (str or None) + :return: The full path and filename used to save the settings + :rtype: (str) + """ + if filename is not None or path is not None: + self.set_location(filename=filename, path=path) + try: + if not os.path.exists(self.path): + os.makedirs(self.path) + with open(self.full_filename, 'w') as f: + if not self.use_config_file: + json.dump(self.dict, f) + else: + self.config.write(f) + except Exception as e: + if not self.silent_on_error: + _error_popup_with_traceback('UserSettings.save error', '*** UserSettings.save() Error saving settings to file:***\n', self.full_filename, e) + + # if self.use_config_file and self.retain_config_comments: + # self.merge_comments_from_file(self.full_filename) + + return self.full_filename + + + + def load(self, filename=None, path=None): + """ + Specifies the path and filename to use for the settings and reads the contents of the file. + The filename can be a full filename including a path, or the path can be specified separately. + If no filename is specified, then the caller's filename will be used with the extension ".json" + + :param filename: Filename to load settings from (and save to in the future) + :type filename: (str or None) + :param path: Path to the file. Defaults to a specific folder depending on the operating system + :type path: (str or None) + :return: The settings dictionary (i.e. all settings) + :rtype: (dict) + """ + if filename is not None or path is not None or self.full_filename is None: + self.set_location(filename, path) + self.read() + return self.dict + + def delete_file(self, filename=None, path=None): + """ + Deltes the filename and path for your settings file. Either paramter can be optional. + If you don't choose a path, one is provided for you that is OS specific + Windows path default = users/name/AppData/Local/PySimpleGUI/settings. + If you don't choose a filename, your application's filename + '.json' will be used + Also sets your current dictionary to a blank one. + + :param filename: The name of the file to use. Can be a full path and filename or just filename + :type filename: (str or None) + :param path: The folder that the settings file will be stored in. Do not include the filename. + :type path: (str or None) + """ + if filename is not None or path is not None or (filename is None and path is None): + self.set_location(filename=filename, path=path) + try: + os.remove(self.full_filename) + except Exception as e: + if not self.silent_on_error: + _error_popup_with_traceback('UserSettings delete_file warning ***', 'Exception trying to perform os.remove', e) + # print(_create_error_message()) + self.dict = {} + + def write_new_dictionary(self, settings_dict): + """ + Writes a specified dictionary to the currently defined settings filename. + + :param settings_dict: The dictionary to be written to the currently defined settings file + :type settings_dict: (dict) + """ + if self.full_filename is None: + self.set_location() + self.dict = settings_dict + self.save() + + # def as_dict(config): + # """ + # Converts a ConfigParser object into a dictionary. + # + # The resulting dictionary has sections as keys which point to a dict of the + # sections options as key => value pairs. + # """ + # the_dict = {} + # for section in config.sections(): + # the_dict[section] = {} + # for key, val in config.items(section): + # the_dict[section][key] = val + # return the_dict + + def read(self): + """ + Reads settings file and returns the dictionary. + If you have anything changed in an existing settings dictionary, you will lose your changes. + :return: settings dictionary + :rtype: (dict) + """ + if self.full_filename is None: + return {} + try: + if os.path.exists(self.full_filename): + with open(self.full_filename, 'r') as f: + if not self.use_config_file: # if using json + self.dict = json.load(f) + else: # if using a config file + self.config.read_file(f) + # Make a dictionary of SectionDict classses. Keys are the config.sections(). + self.section_class_dict = {} + for section in self.config.sections(): + section_dict = dict(self.config[section]) + self.section_class_dict[section] = self._SectionDict(section, section_dict, self.config, self) + + self.dict = self.section_class_dict + self.config_sections = self.config.sections() + # self.config_dict = {section_name : dict(self.config[section_name]) for section_name in self.config.sections()} + # if self.retain_config_comments: + # self.config_file_contents = f.readlines() + except Exception as e: + if not self.silent_on_error: + _error_popup_with_traceback('User settings read warning', 'Error reading settings from file', self.full_filename, e) + # print('*** UserSettings.read - Error reading settings from file: ***\n', self.full_filename, e) + # print(_create_error_message()) + + return self.dict + + def exists(self, filename=None, path=None): + """ + Check if a particular settings file exists. Returns True if file exists + + :param filename: The name of the file to use. Can be a full path and filename or just filename + :type filename: (str or None) + :param path: The folder that the settings file will be stored in. Do not include the filename. + :type path: (str or None) + """ + cfull_filename, cpath, cfilename = self._compute_filename(filename=filename, path=path) + if os.path.exists(cfull_filename): + return True + return False + + def delete_entry(self, key, section=None): + """ + Deletes an individual entry. If no filename has been specified up to this point, + then a default filename will be used. + After value has been deleted, the settings file is written to disk. + + :param key: Setting to be deleted. Can be any valid dictionary key type (i.e. must be hashable) + :type key: (Any) + """ + if self.full_filename is None: + self.set_location() + self.read() + if not self.use_config_file: # Is using JSON file + if key in self.dict: + del self.dict[key] + if self.autosave: + self.save() + else: + if not self.silent_on_error: + print('*** Warning - key ', key, ' not found in settings ***\n') + print(_create_error_message()) + else: + if section is not None: + section_dict = self.get(section) + # print(f'** Trying to delete an entry with a config file in use ** id of section_dict = {id(section_dict)}') + # section_dict = self.section_class_dict[section] + del self.get(section)[key] + # del section_dict[key] + # del section_dict[key] + + def delete_section(self, section): + """ + Deletes a section with the name provided in the section parameter. Your INI file will be saved afterwards if auto-save enabled (default is ON) + :param section: Name of the section to delete + :type section: str + """ + if not self.use_config_file: + return + + section_dict = self.section_class_dict.get(section, None) + section_dict.delete_section() + del self.section_class_dict[section] + if self.autosave: + self.save() + + def set(self, key, value): + """ + Sets an individual setting to the specified value. If no filename has been specified up to this point, + then a default filename will be used. + After value has been modified, the settings file is written to disk. + Note that this call is not value for a config file normally. If it is, then the key is assumed to be the + Section key and the value written will be the default value. + :param key: Setting to be saved. Can be any valid dictionary key type + :type key: (Any) + :param value: Value to save as the setting's value. Can be anything + :type value: (Any) + :return: value that key was set to + :rtype: (Any) + """ + + if self.full_filename is None: + self.set_location() + # if not autosaving, then don't read the file or else will lose changes + if not self.use_config_file: + if self.autosave or self.dict == {}: + self.read() + self.dict[key] = value + else: + self.section_class_dict[key].set(value, self.default_value) + + if self.autosave: + self.save() + return value + + def get(self, key, default=None): + """ + Returns the value of a specified setting. If the setting is not found in the settings dictionary, then + the user specified default value will be returned. It no default is specified and nothing is found, then + the "default value" is returned. This default can be specified in this call, or previously defined + by calling set_default. If nothing specified now or previously, then None is returned as default. + + :param key: Key used to lookup the setting in the settings dictionary + :type key: (Any) + :param default: Value to use should the key not be found in the dictionary + :type default: (Any) + :return: Value of specified settings + :rtype: (Any) + """ + if self.default_value is not None: + default = self.default_value + + if self.full_filename is None: + self.set_location() + if self.autosave or self.dict == {}: + self.read() + if not self.use_config_file: + value = self.dict.get(key, default) + else: + value = self.section_class_dict.get(key, None) + if key not in list(self.section_class_dict.keys()): + self.section_class_dict[key] = self._SectionDict(key, {}, self.config, self) + value = self.section_class_dict[key] + value.new_section = True + return value + + def get_dict(self): + """ + Returns the current settings dictionary. If you've not setup the filename for the + settings, a default one will be used and then read. + + Note that you can display the dictionary in text format by printing the object itself. + + :return: The current settings dictionary + :rtype: Dict + """ + if self.full_filename is None: + self.set_location() + if self.autosave or self.dict == {}: + self.read() + self.save() + return self.dict + + def __setitem__(self, item, value): + """ + Enables setting a setting by using [ ] notation like a dictionary. + Your code will have this kind of design pattern: + settings = sg.UserSettings() + settings[item] = value + + :param item: The key for the setting to change. Needs to be a hashable type. Basically anything but a list + :type item: Any + :param value: The value to set the setting to + :type value: Any + """ + return self.set(item, value) + + def __getitem__(self, item): + """ + Enables accessing a setting using [ ] notation like a dictionary. + If the entry does not exist, then the default value will be returned. This default + value is None unless user sets by calling UserSettings.set_default_value(default_value) + + :param item: The key for the setting to change. Needs to be a hashable type. Basically anything but a list + :type item: Any + :return: The setting value + :rtype: Any + """ + return self.get(item, self.default_value) + + def __delitem__(self, item): + """ + Delete an individual user setting. This is the same as calling delete_entry. The syntax + for deleting the item using this manner is: + del settings['entry'] + :param item: The key for the setting to delete + :type item: Any + """ + if self.use_config_file: + return self.get(item) + else: + self.delete_entry(key=item) + + +# Create a singleton for the settings information so that the settings functions can be used +if UserSettings._default_for_function_interface is None: + UserSettings._default_for_function_interface = UserSettings() + + +def user_settings_filename(filename=None, path=None): + """ + Sets the filename and path for your settings file. Either paramter can be optional. + + If you don't choose a path, one is provided for you that is OS specific + Windows path default = users/name/AppData/Local/PySimpleGUI/settings. + + If you don't choose a filename, your application's filename + '.json' will be used. + + Normally the filename and path are split in the user_settings calls. However for this call they + can be combined so that the filename contains both the path and filename. + + :param filename: The name of the file to use. Can be a full path and filename or just filename + :type filename: (str) + :param path: The folder that the settings file will be stored in. Do not include the filename. + :type path: (str) + :return: The full pathname of the settings file that has both the path and filename combined. + :rtype: (str) + """ + settings = UserSettings._default_for_function_interface + return settings.get_filename(filename, path) + + +def user_settings_delete_filename(filename=None, path=None): + """ + Deltes the filename and path for your settings file. Either paramter can be optional. + If you don't choose a path, one is provided for you that is OS specific + Windows path default = users/name/AppData/Local/PySimpleGUI/settings. + If you don't choose a filename, your application's filename + '.json' will be used + Also sets your current dictionary to a blank one. + + :param filename: The name of the file to use. Can be a full path and filename or just filename + :type filename: (str) + :param path: The folder that the settings file will be stored in. Do not include the filename. + :type path: (str) + """ + settings = UserSettings._default_for_function_interface + settings.delete_file(filename, path) + + +def user_settings_set_entry(key, value): + """ + Sets an individual setting to the specified value. If no filename has been specified up to this point, + then a default filename will be used. + After value has been modified, the settings file is written to disk. + + :param key: Setting to be saved. Can be any valid dictionary key type + :type key: (Any) + :param value: Value to save as the setting's value. Can be anything + :type value: (Any) + """ + settings = UserSettings._default_for_function_interface + settings.set(key, value) + + +def user_settings_delete_entry(key): + """ + Deletes an individual entry. If no filename has been specified up to this point, + then a default filename will be used. + After value has been deleted, the settings file is written to disk. + + :param key: Setting to be saved. Can be any valid dictionary key type (hashable) + :type key: (Any) + """ + settings = UserSettings._default_for_function_interface + settings.delete_entry(key) + + +def user_settings_get_entry(key, default=None): + """ + Returns the value of a specified setting. If the setting is not found in the settings dictionary, then + the user specified default value will be returned. It no default is specified and nothing is found, then + None is returned. If the key isn't in the dictionary, then it will be added and the settings file saved. + If no filename has been specified up to this point, then a default filename will be assigned and used. + The settings are SAVED prior to returning. + + :param key: Key used to lookup the setting in the settings dictionary + :type key: (Any) + :param default: Value to use should the key not be found in the dictionary + :type default: (Any) + :return: Value of specified settings + :rtype: (Any) + """ + settings = UserSettings._default_for_function_interface + return settings.get(key, default) + + +def user_settings_save(filename=None, path=None): + """ + Saves the current settings dictionary. If a filename or path is specified in the call, then it will override any + previously specitfied filename to create a new settings file. The settings dictionary is then saved to the newly defined file. + + :param filename: The fFilename to save to. Can specify a path or just the filename. If no filename specified, then the caller's filename will be used. + :type filename: (str) + :param path: The (optional) path to use to save the file. + :type path: (str) + :return: The full path and filename used to save the settings + :rtype: (str) + """ + settings = UserSettings._default_for_function_interface + return settings.save(filename, path) + + +def user_settings_load(filename=None, path=None): + """ + Specifies the path and filename to use for the settings and reads the contents of the file. + The filename can be a full filename including a path, or the path can be specified separately. + If no filename is specified, then the caller's filename will be used with the extension ".json" + + :param filename: Filename to load settings from (and save to in the future) + :type filename: (str) + :param path: Path to the file. Defaults to a specific folder depending on the operating system + :type path: (str) + :return: The settings dictionary (i.e. all settings) + :rtype: (dict) + """ + settings = UserSettings._default_for_function_interface + return settings.load(filename, path) + + +def user_settings_file_exists(filename=None, path=None): + """ + Determines if a settings file exists. If so a boolean True is returned. + If either a filename or a path is not included, then the appropriate default + will be used. + + :param filename: Filename to check + :type filename: (str) + :param path: Path to the file. Defaults to a specific folder depending on the operating system + :type path: (str) + :return: True if the file exists + :rtype: (bool) + """ + settings = UserSettings._default_for_function_interface + return settings.exists(filename=filename, path=path) + + +def user_settings_write_new_dictionary(settings_dict): + """ + Writes a specified dictionary to the currently defined settings filename. + + :param settings_dict: The dictionary to be written to the currently defined settings file + :type settings_dict: (dict) + """ + settings = UserSettings._default_for_function_interface + settings.write_new_dictionary(settings_dict) + + +def user_settings_silent_on_error(silent_on_error=False): + """ + Used to control the display of error messages. By default, error messages are displayed to stdout. + + :param silent_on_error: If True then all error messages are silenced (not displayed on the console) + :type silent_on_error: (bool) + """ + settings = UserSettings._default_for_function_interface + settings.silent_on_error = silent_on_error + + +def user_settings(): + """ + Returns the current settings dictionary. If you've not setup the filename for the + settings, a default one will be used and then read. + :return: The current settings dictionary as a dictionary or a nicely formatted string representing it + :rtype: (dict or str) + """ + settings = UserSettings._default_for_function_interface + return settings.get_dict() + + +def user_settings_object(): + """ + Returns the object that is used for the function version of this API. + With this object you can use the object interface, print it out in a nice format, etc. + + :return: The UserSettings obect used for the function level interface + :rtype: (UserSettings) + """ + return UserSettings._default_for_function_interface + + +''' +'########:'##::::'##:'########::'######::'##::::'##:'########:'########: + ##.....::. ##::'##:: ##.....::'##... ##: ##:::: ##:... ##..:: ##.....:: + ##::::::::. ##'##::: ##::::::: ##:::..:: ##:::: ##:::: ##:::: ##::::::: + ######:::::. ###:::: ######::: ##::::::: ##:::: ##:::: ##:::: ######::: + ##...:::::: ## ##::: ##...:::: ##::::::: ##:::: ##:::: ##:::: ##...:::: + ##:::::::: ##:. ##:: ##::::::: ##::: ##: ##:::: ##:::: ##:::: ##::::::: + ########: ##:::. ##: ########:. ######::. #######::::: ##:::: ########: +........::..:::::..::........:::......::::.......::::::..:::::........:: +:::'###::::'########::'####::'######:: +::'## ##::: ##.... ##:. ##::'##... ##: +:'##:. ##:: ##:::: ##:: ##:: ##:::..:: +'##:::. ##: ########::: ##::. ######:: + #########: ##.....:::: ##:::..... ##: + ##.... ##: ##::::::::: ##::'##::: ##: + ##:::: ##: ##::::::::'####:. ######:: +..:::::..::..:::::::::....:::......::: + + + +These are the functions used to implement the subprocess APIs (Exec APIs) of PySimpleGUI + +''' + + +def execute_command_subprocess(command, *args, wait=False, cwd=None, pipe_output=False, merge_stderr_with_stdout=True, stdin=None): + """ + Runs the specified command as a subprocess. + By default the call is non-blocking. + The function will immediately return without waiting for the process to complete running. You can use the returned Popen object to communicate with the subprocess and get the results. + Returns a subprocess Popen object. + + :param command: Filename to load settings from (and save to in the future) + :type command: (str) + :param *args: Variable number of arguments that are passed to the program being started as command line parms + :type *args: (Any) + :param wait: If True then wait for the subprocess to finish + :type wait: (bool) + :param cwd: Working directory to use when executing the subprocess + :type cwd: (str)) + :param pipe_output: If True then output from the subprocess will be piped. You MUST empty the pipe by calling execute_get_results or your subprocess will block until no longer full + :type pipe_output: (bool) + :param merge_stderr_with_stdout: If True then output from the subprocess stderr will be merged with stdout. The result is ALL output will be on stdout. + :type merge_stderr_with_stdout: (bool) + :param stdin: Value passed to the Popen call. Defaults to subprocess.DEVNULL so that the pyinstaller created executable work correctly + :type stdin: (bool) + :return: Popen object + :rtype: (subprocess.Popen) + """ + if stdin is None: + stdin = subprocess.DEVNULL + try: + if args is not None: + expanded_args = ' '.join(args) + # print('executing subprocess command:',command, 'args:',expanded_args) + if command[0] != '"' and ' ' in command: + command = '"' + command + '"' + # print('calling popen with:', command +' '+ expanded_args) + # sp = subprocess.Popen(command +' '+ expanded_args, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, cwd=cwd) + if pipe_output: + if merge_stderr_with_stdout: + sp = subprocess.Popen(command + ' ' + expanded_args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=cwd, stdin=stdin) + else: + sp = subprocess.Popen(command + ' ' + expanded_args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd, stdin=stdin) + else: + sp = subprocess.Popen(command + ' ' + expanded_args, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, cwd=cwd, stdin=stdin) + else: + sp = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd, stdin=stdin) + if wait: + out, err = sp.communicate() + if out: + print(out.decode("utf-8")) + if err: + print(err.decode("utf-8")) + except Exception as e: + warnings.warn('Error in execute_command_subprocess {}'.format(e), UserWarning) + _error_popup_with_traceback('Error in execute_command_subprocess', e, 'command={}'.format(command), 'args={}'.format(args), 'cwd={}'.format(cwd)) + sp = None + return sp + + +def execute_py_file(pyfile, parms=None, cwd=None, interpreter_command=None, wait=False, pipe_output=False, merge_stderr_with_stdout=True): + """ + Executes a Python file. + The interpreter to use is chosen based on this priority order: + 1. interpreter_command paramter + 2. global setting "-python command-" + 3. the interpreter running running PySimpleGUI + :param pyfile: the file to run + :type pyfile: (str) + :param parms: parameters to pass on the command line + :type parms: (str) + :param cwd: the working directory to use + :type cwd: (str) + :param interpreter_command: the command used to invoke the Python interpreter + :type interpreter_command: (str) + :param wait: the working directory to use + :type wait: (bool) + :param pipe_output: If True then output from the subprocess will be piped. You MUST empty the pipe by calling execute_get_results or your subprocess will block until no longer full + :type pipe_output: (bool) + :param merge_stderr_with_stdout: If True then output from the subprocess stderr will be merged with stdout. The result is ALL output will be on stdout. + :type merge_stderr_with_stdout: (bool) + :return: Popen object + :rtype: (subprocess.Popen) | None + """ + + if cwd is None: + # if the specific file is not found (not an absolute path) then assume it's relative to '.' + if not os.path.exists(pyfile): + cwd = '.' + + if pyfile[0] != '"' and ' ' in pyfile: + pyfile = '"' + pyfile + '"' + if interpreter_command is not None: + python_program = interpreter_command + else: + # use the version CURRENTLY RUNNING if nothing is specified. Previously used the one from the settings file + pysimplegui_user_settings.load() # Refresh the settings just in case they've changed via another program + python_program = pysimplegui_user_settings.get('-python command-', '') + if python_program == '': # if no interpreter set in the settings, then use the current one + python_program = sys.executable + # python_program = 'python' if running_windows() else 'python3' + if parms is not None and python_program: + sp = execute_command_subprocess(python_program, pyfile, parms, wait=wait, cwd=cwd, pipe_output=pipe_output, merge_stderr_with_stdout=merge_stderr_with_stdout) + elif python_program: + sp = execute_command_subprocess(python_program, pyfile, wait=wait, cwd=cwd, pipe_output=pipe_output, merge_stderr_with_stdout=merge_stderr_with_stdout) + else: + print('execute_py_file - No interpreter has been configured') + sp = None + return sp + + +def execute_py_get_interpreter(): + """ + Returns the command that is currently running. Previously returned the one from the system settings, but + have determined that the one currently running is the better choice. + + :return: Full path to python interpreter (uses sys.executable) + :rtype: (str) + """ + pysimplegui_user_settings.load() # Refresh the settings just in case they've changed via another program + interpreter = pysimplegui_user_settings.get('-python command-', '') + if interpreter == '': + interpreter = sys.executable + return interpreter + + +def execute_editor(file_to_edit, line_number=None): + """ + Runs the editor that was configured in the global settings and opens the file to a specific line number. + Two global settings keys are used. + '-editor program-' the command line used to startup your editor. It's set + in the global settings window or by directly manipulating the PySimpleGUI settings object + '-editor format string-' a string containing 3 "tokens" that describes the command that is executed + + :param file_to_edit: the full path to the file to edit + :type file_to_edit: (str) + :param line_number: optional line number to place the cursor + :type line_number: (int) + :return: Popen object + :rtype: (subprocess.Popen) | None + """ + if file_to_edit is not None and len(file_to_edit) != 0 and file_to_edit[0] not in ('\"', "\'") and ' ' in file_to_edit: + file_to_edit = '"' + file_to_edit + '"' + pysimplegui_user_settings.load() # Refresh the settings just in case they've changed via another program + editor_program = pysimplegui_user_settings.get('-editor program-', None) + if editor_program is not None: + format_string = pysimplegui_user_settings.get('-editor format string-', None) + # if no format string, then just launch the editor with the filename + if not format_string or line_number is None: + sp = execute_command_subprocess(editor_program, file_to_edit) + else: + command = _create_full_editor_command(file_to_edit, line_number, format_string) + # print('final command line = ', command) + sp = execute_command_subprocess(editor_program, command) + else: + print('No editor has been configured in the global settings') + sp = None + return sp + + +def execute_get_results(subprocess_id, timeout=None): + """ + Get the text results of a previously executed execute call + Returns a tuple of the strings (stdout, stderr) + :param subprocess_id: a Popen subprocess ID returned from a previous execute call + :type subprocess_id: (subprocess.Popen) + :param timeout: Time in fractions of a second to wait. Returns '','' if timeout. Default of None means wait forever + :type timeout: (None | float) + :returns: Tuple with 2 strings (stdout, stderr) + :rtype: (str, str) + """ + + out_decoded = err_decoded = None + if subprocess_id is not None: + try: + out, err = subprocess_id.communicate(timeout=timeout) + if out: + out_decoded = out.decode("utf-8") + if err: + err_decoded = err.decode("utf-8") + except Exception as e: + popup_error('Error in execute_get_results', e) + out_decoded = err_decoded = None + return out_decoded, err_decoded + + +def execute_subprocess_still_running(subprocess_id): + """ + Returns True is the subprocess ID provided is for a process that is still running + + :param subprocess_id: ID previously returned from Exec API calls that indicate this value is returned + :type subprocess_id: (subprocess.Popen) + :return: True if the subproces is running + :rtype: bool + """ + if subprocess_id.poll() == 0: + return False + return True + + +def execute_file_explorer(folder_to_open=''): + """ + The global settings has a setting called - "-explorer program-" + It defines the program to run when this function is called. + The optional folder paramter specified which path should be opened. + + :param folder_to_open: The path to open in the explorer program + :type folder_to_open: str + :return: Popen object + :rtype: (subprocess.Popen) | None + """ + pysimplegui_user_settings.load() # Refresh the settings just in case they've changed via another program + explorer_program = pysimplegui_user_settings.get('-explorer program-', None) + if explorer_program is not None: + sp = execute_command_subprocess(explorer_program, folder_to_open) + else: + print('No file explorer has been configured in the global settings') + sp = None + return sp + + +def execute_find_callers_filename(): + """ + Returns the first filename found in a traceback that is not the nsame of this file (__file__) + Used internally with the debugger for example. + + :return: filename of the caller, asseumed to be the first non PySimpleGUI file + :rtype: str + """ + try: # lots can go wrong so wrapping the entire thing + trace_details = traceback.format_stack() + file_info_pysimplegui, error_message = None, '' + for line in reversed(trace_details): + if __file__ not in line: + file_info_pysimplegui = line.split(",")[0] + error_message = line + break + if file_info_pysimplegui is None: + return '' + error_parts = None + if error_message != '': + error_parts = error_message.split(', ') + if len(error_parts) < 4: + error_message = error_parts[0] + '\n' + error_parts[1] + '\n' + ''.join(error_parts[2:]) + if error_parts is None: + print('*** Error popup attempted but unable to parse error details ***') + print(trace_details) + return '' + filename = error_parts[0][error_parts[0].index('File ') + 5:] + return filename + except: + return '' + + +def _create_full_editor_command(file_to_edit, line_number, edit_format_string): + """ + The global settings has a setting called - "-editor format string-" + It uses 3 "tokens" to describe how to invoke the editor in a way that starts at a specific line # + + + :param file_to_edit: + :type file_to_edit: str + :param edit_format_string: + :type edit_format_string: str + :return: + :rtype: + """ + + command = edit_format_string + command = command.replace('', '') + command = command.replace('', file_to_edit) + command = command.replace('', str(line_number) if line_number is not None else '') + return command + + +def _get_editor(): + """ + Get the path to the editor based on user settings or on PySimpleGUI's global settings + + :return: Path to the editor + :rtype: str + """ + try: # in case running with old version of PySimpleGUI that doesn't have a global PSG settings path + global_editor = pysimplegui_user_settings.get('-editor program-') + except: + global_editor = '' + + return user_settings_get_entry('-editor program-', global_editor) + + +''' +'##::::'##::::'###:::::'######::::::'######::'########::'########::'######::'####:'########:'####::'######:: + ###::'###:::'## ##:::'##... ##::::'##... ##: ##.... ##: ##.....::'##... ##:. ##:: ##.....::. ##::'##... ##: + ####'####::'##:. ##:: ##:::..::::: ##:::..:: ##:::: ##: ##::::::: ##:::..::: ##:: ##:::::::: ##:: ##:::..:: + ## ### ##:'##:::. ##: ##::::::::::. ######:: ########:: ######::: ##:::::::: ##:: ######:::: ##:: ##::::::: + ##. #: ##: #########: ##:::::::::::..... ##: ##.....::: ##...:::: ##:::::::: ##:: ##...::::: ##:: ##::::::: + ##:.:: ##: ##.... ##: ##::: ##::::'##::: ##: ##:::::::: ##::::::: ##::: ##:: ##:: ##:::::::: ##:: ##::: ##: + ##:::: ##: ##:::: ##:. ######:::::. ######:: ##:::::::: ########:. ######::'####: ##:::::::'####:. ######:: +..:::::..::..:::::..:::......:::::::......:::..:::::::::........:::......:::....::..::::::::....:::......::: +''' + +''' +The Mac problems have been significant enough to warrant the addition of a series of settings that allow +users to turn specific patches and features on or off depending on their setup. There is not enough information +available to make this process more atuomatic. + +''' + + +# Dictionary of Mac Patches. Used to find the key in the global settings and the default value +MAC_PATCH_DICT = {'Enable No Titlebar Patch' : ('-mac feature enable no titlebar patch-', False), + 'Disable Modal Windows' : ('-mac feature disable modal windows-', True), + 'Disable Grab Anywhere with Titlebar' : ('-mac feature disable grab anywhere with titlebar-', True)} + +def _read_mac_global_settings(): + """ + Reads the settings from the PySimpleGUI Global Settings and sets variables that + are used at runtime to control how certain features behave + """ + + global ENABLE_MAC_MODAL_DISABLE_PATCH + global ENABLE_MAC_NOTITLEBAR_PATCH + global ENABLE_MAC_DISABLE_GRAB_ANYWHERE_WITH_TITLEBAR + + ENABLE_MAC_MODAL_DISABLE_PATCH = pysimplegui_user_settings.get(MAC_PATCH_DICT['Disable Modal Windows'][0], + MAC_PATCH_DICT['Disable Modal Windows'][1]) + ENABLE_MAC_NOTITLEBAR_PATCH = pysimplegui_user_settings.get(MAC_PATCH_DICT['Enable No Titlebar Patch'][0], + MAC_PATCH_DICT['Enable No Titlebar Patch'][1]) + ENABLE_MAC_DISABLE_GRAB_ANYWHERE_WITH_TITLEBAR = pysimplegui_user_settings.get(MAC_PATCH_DICT['Disable Grab Anywhere with Titlebar'][0], + MAC_PATCH_DICT['Disable Grab Anywhere with Titlebar'][1]) + + +def _mac_should_apply_notitlebar_patch(): + """ + Uses a combination of the tkinter version number and the setting from the global settings + to determine if the notitlebar patch should be applied + + :return: True if should apply the no titlebar patch on the Mac + :rtype: (bool) + """ + + if not running_mac(): + return False + + try: + tver = [int(n) for n in framework_version.split('.')] + if tver[0] == 8 and tver[1] == 6 and tver[2] < 10 and ENABLE_MAC_NOTITLEBAR_PATCH: + return True + except Exception as e: + warnings.warn('Exception while trying to parse tkinter version {} Error = {}'.format(framework_version, e), UserWarning) + + return False + + +def main_mac_feature_control(): + """ + Window to set settings that will be used across all PySimpleGUI programs that choose to use them. + Use set_options to set the path to the folder for all PySimpleGUI settings. + + :return: True if settings were changed + :rtype: (bool) + """ + + current_theme = theme() + theme('dark red') + + layout = [[T('Mac PySimpleGUI Feature Control', font='DEFAIULT 18')], + [T('Use this window to enable / disable features.')], + [T('Unfortunately, on some releases of tkinter on the Mac, there are problems that')], + [T('create the need to enable and disable sets of features. This window facilitates the control.')], + [T('Feature Control / Settings', font='_ 16 bold')], + [T('You are running tkinter version:', font='_ 12 bold'), T(framework_version, font='_ 12 bold')]] + + + for key, value in MAC_PATCH_DICT.items(): + layout += [[Checkbox(key, k=value[0], default=pysimplegui_user_settings.get(value[0], value[1]))]] + layout += [[T('Currently the no titlebar patch ' + ('WILL' if _mac_should_apply_notitlebar_patch() else 'WILL NOT') + ' be applied')], + [T('The no titlebar patch will ONLY be applied on tkinter versions < 8.6.10')]] + layout += [[Button('Ok'), Button('Cancel')]] + + window = Window('Mac Feature Control', layout, keep_on_top=True, finalize=True ) + while True: + event, values = window.read() + if event in ('Cancel', WIN_CLOSED): + break + if event == 'Ok': + for key, value in values.items(): + print('setting {} to {}'.format(key, value)) + pysimplegui_user_settings.set(key, value) + break + window.close() + theme(current_theme) + + +''' +'########::'########:'########::'##::::'##::'######::::'######:::'########:'########:: + ##.... ##: ##.....:: ##.... ##: ##:::: ##:'##... ##::'##... ##:: ##.....:: ##.... ##: + ##:::: ##: ##::::::: ##:::: ##: ##:::: ##: ##:::..::: ##:::..::: ##::::::: ##:::: ##: + ##:::: ##: ######::: ########:: ##:::: ##: ##::'####: ##::'####: ######::: ########:: + ##:::: ##: ##...:::: ##.... ##: ##:::: ##: ##::: ##:: ##::: ##:: ##...:::: ##.. ##::: + ##:::: ##: ##::::::: ##:::: ##: ##:::: ##: ##::: ##:: ##::: ##:: ##::::::: ##::. ##:: + ########:: ########: ########::. #######::. ######:::. ######::: ########: ##:::. ##: +........:::........::........::::.......::::......:::::......::::........::..:::::..:: +''' + +##################################################################################################### +# Debugger +##################################################################################################### + + +red_x = b"R0lGODlhEAAQAPeQAIsAAI0AAI4AAI8AAJIAAJUAAJQCApkAAJoAAJ4AAJkJCaAAAKYAAKcAAKcCAKcDA6cGAKgAAKsAAKsCAKwAAK0AAK8AAK4CAK8DAqUJAKULAKwLALAAALEAALIAALMAALMDALQAALUAALYAALcEALoAALsAALsCALwAAL8AALkJAL4NAL8NAKoTAKwbAbEQALMVAL0QAL0RAKsREaodHbkQELMsALg2ALk3ALs+ALE2FbgpKbA1Nbc1Nb44N8AAAMIWAMsvAMUgDMcxAKVABb9NBbVJErFYEq1iMrtoMr5kP8BKAMFLAMxKANBBANFCANJFANFEB9JKAMFcANFZANZcANpfAMJUEMZVEc5hAM5pAMluBdRsANR8AM9YOrdERMpIQs1UVMR5WNt8X8VgYMdlZcxtYtx4YNF/btp9eraNf9qXXNCCZsyLeNSLd8SSecySf82kd9qqc9uBgdyBgd+EhN6JgtSIiNuJieGHhOGLg+GKhOKamty1ste4sNO+ueenp+inp+HHrebGrefKuOPTzejWzera1O7b1vLb2/bl4vTu7fbw7ffx7vnz8f///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAJAALAAAAAAQABAAAAjUACEJHEiwYEEABniQKfNFgQCDkATQwAMokEU+PQgUFDAjjR09e/LUmUNnh8aBCcCgUeRmzBkzie6EeQBAoAAMXuA8ciRGCaJHfXzUMCAQgYooWN48anTokR8dQk4sELggBhQrU9Q8evSHiJQgLCIIfMDCSZUjhbYuQkLFCRAMAiOQGGLE0CNBcZYmaRIDLqQFGF60eTRoSxc5jwjhACFWIAgMLtgUocJFy5orL0IQRHAiQgsbRZYswbEhBIiCCH6EiJAhAwQMKU5DjHCi9gnZEHMTDAgAOw==" + +COLOR_SCHEME = 'dark grey 13' +DEBUGGER_POPOUT_THEME = 'dark grey 13' +WIDTH_VARIABLES = 23 +WIDTH_RESULTS = 46 + +WIDTH_WATCHER_VARIABLES = 20 +WIDTH_WATCHER_RESULTS = 60 + +WIDTH_LOCALS = 80 +NUM_AUTO_WATCH = 9 + +MAX_LINES_PER_RESULT_FLOATING = 4 +MAX_LINES_PER_RESULT_MAIN = 3 + +POPOUT_WINDOW_FONT = 'Sans 8' +DEBUGGER_VARIABLE_DETAILS_FONT = 'Courier 10' + + +class _Debugger: + debugger = None + ''' + # # ###### + ## ## ## # # # # # ###### ##### # # #### #### ###### ##### + # # # # # # # ## # # # # # # # # # # # # # # # + # # # # # # # # # # # ##### ##### # # # # ##### # # + # # ###### # # # # # # # # # # # # ### # ### # ##### + # # # # # # ## # # # # # # # # # # # # # # + # # # # # # # ###### ###### ##### #### #### #### ###### # # + ''' + def __init__(self): + self.watcher_window = None # type: Window + self.popout_window = None # type: Window + self.local_choices = {} + self.myrc = '' + self.custom_watch = '' + self.locals = {} + self.globals = {} + self.popout_choices = {} + + # Includes the DUAL PANE (now 2 tabs)! Don't forget REPL is there too! + def _build_main_debugger_window(self, location=(None, None)): + old_theme = theme() + theme(COLOR_SCHEME) + + def InVar(key1): + row1 = [T(' '), + I(key=key1, size=(WIDTH_VARIABLES, 1)), + T('', key=key1 + 'CHANGED_', size=(WIDTH_RESULTS, 1)), B('Detail', key=key1 + 'DETAIL_'), + B('Obj', key=key1 + 'OBJ_'), ] + return row1 + + variables_frame = [InVar('_VAR0_'), + InVar('_VAR1_'), + InVar('_VAR2_'), ] + + interactive_frame = [[T('>>> '), In(size=(83, 1), key='_REPL_', + tooltip='Type in any "expression" or "statement"\n and it will be disaplayed below.\nPress RETURN KEY instead of "Go"\nbutton for faster use'), + B('Go', bind_return_key=True, visible=True)], + [Multiline(size=(93, 26), key='_OUTPUT_', autoscroll=True, do_not_clear=True)], ] + + autowatch_frame = [[Button('Choose Variables To Auto Watch', key='_LOCALS_'), + Button('Clear All Auto Watches'), + Button('Show All Variables', key='_SHOW_ALL_'), + Button('Locals', key='_ALL_LOCALS_'), + Button('Globals', key='_GLOBALS_'), + Button('Popout', key='_POPOUT_')]] + + var_layout = [] + for i in range(NUM_AUTO_WATCH): + var_layout.append([T('', size=(WIDTH_WATCHER_VARIABLES, 1), key='_WATCH%s_' % i), + T('', size=(WIDTH_WATCHER_RESULTS, MAX_LINES_PER_RESULT_MAIN), key='_WATCH%s_RESULT_' % i, + )]) + + col1 = [ + # [Frame('Auto Watches', autowatch_frame+variable_values, title_color='blue')] + [Frame('Auto Watches', autowatch_frame + var_layout, title_color=theme_button_color()[0])] + ] + + col2 = [ + [Frame('Variables or Expressions to Watch', variables_frame, title_color=theme_button_color()[0]), ], + [Frame('REPL-Light - Press Enter To Execute Commands', interactive_frame, title_color=theme_button_color()[0]), ] + ] + + # Tab based layout + layout = [[Text('Debugging: ' + self._find_users_code())], + [TabGroup([[Tab('Variables', col1), Tab('REPL & Watches', col2)]])]] + + # ------------------------------- Create main window ------------------------------- + window = Window("PySimpleGUI Debugger", layout, icon=PSG_DEBUGGER_LOGO, margins=(0, 0), location=location, keep_on_top=True, + right_click_menu=[[''], ['Exit', ]]) + + Window._read_call_from_debugger = True + window.finalize() + Window._read_call_from_debugger = False + + window.Element('_VAR1_').SetFocus() + self.watcher_window = window + theme(old_theme) + return window + + ''' + # # ####### # + ## ## ## # # # # # # ###### # # ##### # #### #### ##### + # # # # # # # ## # # # # # ## # # # # # # # # # + # # # # # # # # # ##### # # ##### # # # # # # # # # # # + # # ###### # # # # # # # # # # # # # # # # # ##### + # # # # # # ## # # # # # ## # # # # # # # + # # # # # # # ####### ## ###### # # # ####### #### #### # + ''' + + def _refresh_main_debugger_window(self, mylocals, myglobals): + if not self.watcher_window: # if there is no window setup, nothing to do + return False + event, values = self.watcher_window.read(timeout=1) + if event in (None, 'Exit', '_EXIT_', '-EXIT-'): # EXIT BUTTON / X BUTTON + try: + self.watcher_window.close() + except: + pass + self.watcher_window = None + return False + # ------------------------------- Process events from REPL Tab ------------------------------- + cmd = values['_REPL_'] # get the REPL entered + # BUTTON - GO (NOTE - This button is invisible!!) + if event == 'Go': # GO BUTTON + self.watcher_window.Element('_REPL_').Update('') + self.watcher_window.Element('_OUTPUT_').Update(">>> {}\n".format(cmd), append=True, autoscroll=True) + + try: + result = eval('{}'.format(cmd), myglobals, mylocals) + except Exception as e: + if sys.version_info[0] < 3: + result = 'Not available in Python 2' + else: + try: + result = exec('{}'.format(cmd), myglobals, mylocals) + except Exception as e: + result = 'Exception {}\n'.format(e) + + self.watcher_window.Element('_OUTPUT_').Update('{}\n'.format(result), append=True, autoscroll=True) + # BUTTON - DETAIL + elif event.endswith('_DETAIL_'): # DETAIL BUTTON + var = values['_VAR{}_'.format(event[4])] + try: + result = str(eval(str(var), myglobals, mylocals)) + except: + result = '' + popup_scrolled(str(values['_VAR{}_'.format(event[4])]) + '\n' + result, title=var, non_blocking=True, font=DEBUGGER_VARIABLE_DETAILS_FONT) + # BUTTON - OBJ + elif event.endswith('_OBJ_'): # OBJECT BUTTON + var = values['_VAR{}_'.format(event[4])] + try: + result = ObjToStringSingleObj(mylocals[var]) + except Exception as e: + try: + result = eval('{}'.format(var), myglobals, mylocals) + result = ObjToStringSingleObj(result) + except Exception as e: + result = '{}\nError showing object {}'.format(e, var) + popup_scrolled(str(var) + '\n' + str(result), title=var, non_blocking=True, font=DEBUGGER_VARIABLE_DETAILS_FONT) + # ------------------------------- Process Watch Tab ------------------------------- + # BUTTON - Choose Locals to see + elif event == '_LOCALS_': # Show all locals BUTTON + self._choose_auto_watches(mylocals) + # BUTTON - Locals (quick popup) + elif event == '_ALL_LOCALS_': + self._display_all_vars(mylocals) + # BUTTON - Globals (quick popup) + elif event == '_GLOBALS_': + self._display_all_vars(myglobals) + # BUTTON - clear all + elif event == 'Clear All Auto Watches': + if popup_yes_no('Do you really want to clear all Auto-Watches?', 'Really Clear??') == 'Yes': + self.local_choices = {} + self.custom_watch = '' + # BUTTON - Popout + elif event == '_POPOUT_': + if not self.popout_window: + self._build_floating_window() + # BUTTON - Show All + elif event == '_SHOW_ALL_': + for key in self.locals: + self.local_choices[key] = not key.startswith('_') + + # -------------------- Process the manual "watch list" ------------------ + for i in range(3): + key = '_VAR{}_'.format(i) + out_key = '_VAR{}_CHANGED_'.format(i) + self.myrc = '' + if self.watcher_window.Element(key): + var = values[key] + try: + result = eval(str(var), myglobals, mylocals) + except: + result = '' + self.watcher_window.Element(out_key).Update(str(result)) + else: + self.watcher_window.Element(out_key).Update('') + + # -------------------- Process the automatic "watch list" ------------------ + slot = 0 + for key in self.local_choices: + if key == '_CUSTOM_WATCH_': + continue + if self.local_choices[key]: + self.watcher_window.Element('_WATCH{}_'.format(slot)).Update(key) + try: + self.watcher_window.Element('_WATCH{}_RESULT_'.format(slot), silent_on_error=True).Update(mylocals[key]) + except: + self.watcher_window.Element('_WATCH{}_RESULT_'.format(slot)).Update('') + slot += 1 + + if slot + int(not self.custom_watch in (None, '')) >= NUM_AUTO_WATCH: + break + # If a custom watch was set, display that value in the window + if self.custom_watch: + self.watcher_window.Element('_WATCH{}_'.format(slot)).Update(self.custom_watch) + try: + self.myrc = eval(self.custom_watch, myglobals, mylocals) + except: + self.myrc = '' + self.watcher_window.Element('_WATCH{}_RESULT_'.format(slot)).Update(self.myrc) + slot += 1 + # blank out all of the slots not used (blank) + for i in range(slot, NUM_AUTO_WATCH): + self.watcher_window.Element('_WATCH{}_'.format(i)).Update('') + self.watcher_window.Element('_WATCH{}_RESULT_'.format(i)).Update('') + + return True # return indicating the window stayed open + + def _find_users_code(self): + try: # lots can go wrong so wrapping the entire thing + trace_details = traceback.format_stack() + file_info_pysimplegui, error_message = None, '' + for line in reversed(trace_details): + if __file__ not in line: + file_info_pysimplegui = line.split(",")[0] + error_message = line + break + if file_info_pysimplegui is None: + return '' + error_parts = None + if error_message != '': + error_parts = error_message.split(', ') + if len(error_parts) < 4: + error_message = error_parts[0] + '\n' + error_parts[1] + '\n' + ''.join(error_parts[2:]) + if error_parts is None: + print('*** Error popup attempted but unable to parse error details ***') + print(trace_details) + return '' + filename = error_parts[0][error_parts[0].index('File ') + 5:] + return filename + except: + return + ''' + ###### # # + # # #### ##### # # ##### # # # # # # ##### #### # # + # # # # # # # # # # # # # # ## # # # # # # # + ###### # # # # # # # # # # # # # # # # # # # # # + # # # ##### # # ##### # # # # # # # # # # # # ## # + # # # # # # # # # # # # ## # # # # ## ## + # #### # #### # ## ## # # # ##### #### # # + + ###### # # # + # # # # # # ##### #### # # # # # # ## ##### #### + # # # # ## ## # # # # # # # # # # # # # # + # # # # # ## # # # #### # # # # # # # # # # #### + # # # # # # ##### # ####### # # # # ###### ##### # + # # # # # # # # # # # # # # # # # # # # # + ###### #### # # # #### # # ###### ###### # # # # # #### + ''' + # displays them into a single text box + + def _display_all_vars(self, dict): + num_cols = 3 + output_text = '' + num_lines = 2 + cur_col = 0 + out_text = 'All of your Vars' + longest_line = max([len(key) for key in dict]) + line = [] + sorted_dict = {} + for key in sorted(dict.keys()): + sorted_dict[key] = dict[key] + for key in sorted_dict: + value = dict[key] + wrapped_list = textwrap.wrap(str(value), 60) + wrapped_text = '\n'.join(wrapped_list) + out_text += '{} - {}\n'.format(key, wrapped_text) + if cur_col + 1 == num_cols: + cur_col = 0 + num_lines += len(wrapped_list) + else: + cur_col += 1 + popup_scrolled(out_text, non_blocking=True) + + ''' + ##### # # + # # # # #### #### #### ###### # # # ## ##### #### # # + # # # # # # # # # # # # # # # # # # # + # ###### # # # # #### ##### # # # # # # # ###### + # # # # # # # # # # # # ###### # # # # + # # # # # # # # # # # # # # # # # # # # # + ##### # # #### #### #### ###### ## ## # # # #### # # + + # # # # + # # ## ##### # ## ##### # ###### #### # # # # # # + # # # # # # # # # # # # # # # # # # ## # + # # # # # # # # # ##### # ##### #### # # # # # # # + # # ###### ##### # ###### # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # ## + # # # # # # # # ##### ###### ###### #### ## ## # # # + ''' + + def _choose_auto_watches(self, my_locals): + old_theme = theme() + theme(COLOR_SCHEME) + num_cols = 3 + output_text = '' + num_lines = 2 + cur_col = 0 + layout = [[Text('Choose your "Auto Watch" variables', font='ANY 14', text_color='red')]] + longest_line = max([len(key) for key in my_locals]) + line = [] + sorted_dict = {} + for key in sorted(my_locals.keys()): + sorted_dict[key] = my_locals[key] + for key in sorted_dict: + line.append(CB(key, key=key, size=(longest_line, 1), + default=self.local_choices[key] if key in self.local_choices else False)) + if cur_col + 1 == num_cols: + cur_col = 0 + layout.append(line) + line = [] + else: + cur_col += 1 + if cur_col: + layout.append(line) + + layout += [ + [Text('Custom Watch (any expression)'), Input(default_text=self.custom_watch, size=(40, 1), key='_CUSTOM_WATCH_')]] + layout += [ + [Ok(), Cancel(), Button('Clear All'), Button('Select [almost] All', key='_AUTO_SELECT_')]] + + window = Window('All Locals', layout, icon=PSG_DEBUGGER_LOGO, finalize=True) + + while True: # event loop + event, values = window.read() + if event in (None, 'Cancel', '-EXIT-'): + break + elif event == 'Ok': + self.local_choices = values + self.custom_watch = values['_CUSTOM_WATCH_'] + break + elif event == 'Clear All': + popup_quick_message('Cleared Auto Watches', auto_close=True, auto_close_duration=3, non_blocking=True, + text_color='red', font='ANY 18') + for key in sorted_dict: + window.Element(key).Update(False) + window.Element('_CUSTOM_WATCH_').Update('') + elif event == 'Select All': + for key in sorted_dict: + window.Element(key).Update(False) + elif event == '_AUTO_SELECT_': + for key in sorted_dict: + window.Element(key).Update(not key.startswith('_')) + + # exited event loop + window.Close() + theme(old_theme) + + + ''' + ###### ####### + # # # # # # ##### # # #### ## ##### # # # #### + # # # # # # # # # # # # # # # # ## # # # + ###### # # # # # # ##### # # # # # # # # # # # + # # # # # # # # # # # # ###### # # # # # # ### + # # # # # # # # # # # # # # # # # ## # # + ###### #### # ###### ##### # ###### #### # # # # # # #### + + # # + # # # # # # ##### #### # # + # # # # ## # # # # # # # + # # # # # # # # # # # # # + # # # # # # # # # # # # ## # + # # # # # ## # # # # ## ## + ## ## # # # ##### #### # # + ''' + + def _build_floating_window(self, location=(None, None)): + """ + + :param location: + :type location: + + """ + if self.popout_window: # if floating window already exists, close it first + self.popout_window.Close() + old_theme = theme() + theme(DEBUGGER_POPOUT_THEME) + num_cols = 2 + width_var = 15 + width_value = 30 + layout = [] + line = [] + col = 0 + # self.popout_choices = self.local_choices + self.popout_choices = {} + if self.popout_choices == {}: # if nothing chosen, then choose all non-_ variables + for key in sorted(self.locals.keys()): + self.popout_choices[key] = not key.startswith('_') + + width_var = max([len(key) for key in self.popout_choices]) + for key in self.popout_choices: + if self.popout_choices[key] is True: + value = str(self.locals.get(key)) + h = min(len(value) // width_value + 1, MAX_LINES_PER_RESULT_FLOATING) + line += [Text('{}'.format(key), size=(width_var, 1), font=POPOUT_WINDOW_FONT), + Text(' = ', font=POPOUT_WINDOW_FONT), + Text(value, key=key, size=(width_value, h), font=POPOUT_WINDOW_FONT)] + if col + 1 < num_cols: + line += [VerticalSeparator(), T(' ')] + col += 1 + if col >= num_cols: + layout.append(line) + line = [] + col = 0 + if col != 0: + layout.append(line) + layout = [[T(SYMBOL_X, enable_events=True, key='-EXIT-', font='_ 7')], [Column(layout)]] + + Window._read_call_from_debugger = True + self.popout_window = Window('Floating', layout, alpha_channel=0, no_titlebar=True, grab_anywhere=True, + element_padding=(0, 0), margins=(0, 0), keep_on_top=True, + right_click_menu=['&Right', ['Debugger::RightClick', 'Exit::RightClick']], location=location, finalize=True) + Window._read_call_from_debugger = False + + if location == (None, None): + screen_size = self.popout_window.GetScreenDimensions() + self.popout_window.Move(screen_size[0] - self.popout_window.Size[0], 0) + self.popout_window.SetAlpha(1) + theme(old_theme) + return True + + ''' + ###### + # # ###### ###### ##### ###### #### # # + # # # # # # # # # # + ###### ##### ##### # # ##### #### ###### + # # # # ##### # # # # + # # # # # # # # # # # + # # ###### # # # ###### #### # # + + ####### + # # #### ## ##### # # # #### + # # # # # # # # ## # # # + ##### # # # # # # # # # # # + # # # # ###### # # # # # # ### + # # # # # # # # # ## # # + # ###### #### # # # # # # #### + + # # + # # # # # # ##### #### # # + # # # # ## # # # # # # # + # # # # # # # # # # # # # + # # # # # # # # # # # # ## # + # # # # # ## # # # # ## ## + ## ## # # # ##### #### # # + ''' + + def _refresh_floating_window(self): + if not self.popout_window: + return + for key in self.popout_choices: + if self.popout_choices[key] is True and key in self.locals: + if key is not None and self.popout_window is not None: + self.popout_window.Element(key, silent_on_error=True).Update(self.locals.get(key)) + event, values = self.popout_window.read(timeout=5) + if event in (None, '_EXIT_', 'Exit::RightClick', '-EXIT-'): + self.popout_window.Close() + self.popout_window = None + elif event == 'Debugger::RightClick': + show_debugger_window() + + +# 888 888 .d8888b. d8888 888 888 888 888 +# 888 888 d88P Y88b d88888 888 888 888 888 +# 888 888 888 888 d88P888 888 888 888 888 +# 888 888 .d8888b .d88b. 888d888 888 d88P 888 888 888 8888b. 88888b. 888 .d88b. +# 888 888 88K d8P Y8b 888P" 888 d88P 888 888 888 "88b 888 "88b 888 d8P Y8b +# 888 888 "Y8888b. 88888888 888 888 888 d88P 888 888 888 .d888888 888 888 888 88888888 +# Y88b. .d88P X88 Y8b. 888 Y88b d88P d8888888888 888 888 888 888 888 d88P 888 Y8b. +# "Y88888P" 88888P' "Y8888 888 "Y8888P" d88P 888 888 888 "Y888888 88888P" 888 "Y8888 + +# 8888888888 888 d8b +# 888 888 Y8P +# 888 888 +# 8888888 888 888 88888b. .d8888b 888888 888 .d88b. 88888b. .d8888b +# 888 888 888 888 "88b d88P" 888 888 d88""88b 888 "88b 88K +# 888 888 888 888 888 888 888 888 888 888 888 888 "Y8888b. +# 888 Y88b 888 888 888 Y88b. Y88b. 888 Y88..88P 888 888 X88 +# 888 "Y88888 888 888 "Y8888P "Y888 888 "Y88P" 888 888 88888P' + + +def show_debugger_window(location=(None, None), *args): + """ + Shows the large main debugger window + :param location: Locations (x,y) on the screen to place upper left corner of the window + :type location: (int, int) + :return: None + :rtype: None + """ + if _Debugger.debugger is None: + _Debugger.debugger = _Debugger() + debugger = _Debugger.debugger + frame = inspect.currentframe() + prev_frame = inspect.currentframe().f_back + # frame, *others = inspect.stack()[1] + try: + debugger.locals = frame.f_back.f_locals + debugger.globals = frame.f_back.f_globals + finally: + del frame + + if not debugger.watcher_window: + debugger.watcher_window = debugger._build_main_debugger_window(location=location) + return True + + +def show_debugger_popout_window(location=(None, None), *args): + """ + Shows the smaller "popout" window. Default location is the upper right corner of your screen + + :param location: Locations (x,y) on the screen to place upper left corner of the window + :type location: (int, int) + :return: None + :rtype: None + """ + if _Debugger.debugger is None: + _Debugger.debugger = _Debugger() + debugger = _Debugger.debugger + frame = inspect.currentframe() + prev_frame = inspect.currentframe().f_back + # frame = inspect.getframeinfo(prev_frame) + # frame, *others = inspect.stack()[1] + try: + debugger.locals = frame.f_back.f_locals + debugger.globals = frame.f_back.f_globals + finally: + del frame + if debugger.popout_window: + debugger.popout_window.Close() + debugger.popout_window = None + debugger._build_floating_window(location=location) + + +def _refresh_debugger(): + """ + Refreshes the debugger windows. USERS should NOT be calling this function. Within PySimpleGUI it is called for the USER every time the Window.Read function is called. + + :return: return code False if user closed the main debugger window. + :rtype: (bool) + """ + if _Debugger.debugger is None: + _Debugger.debugger = _Debugger() + debugger = _Debugger.debugger + Window._read_call_from_debugger = True + # frame = inspect.currentframe() + # frame = inspect.currentframe().f_back + frame, *others = inspect.stack()[1] + try: + debugger.locals = frame.f_back.f_locals + debugger.globals = frame.f_back.f_globals + finally: + del frame + debugger._refresh_floating_window() if debugger.popout_window else None + rc = debugger._refresh_main_debugger_window(debugger.locals, debugger.globals) if debugger.watcher_window else False + Window._read_call_from_debugger = False + return rc + + +def get_versions(): + """ + Returns a human-readable string of version numbers for: + + Python version + PySimpleGUI Port (tkinter in this case) + tkinter version + PySimpleGUI version + The location of the PySimpleGUI.py file + + The format is a newline between each value and descriptive text for each line + + :return: + :rtype: str + """ + versions = "Python version: {}.{}.{}\nPort: {}\ntkinter version: {}\nPySimpleGUI version: {}\nPySimpleGUI filename: {}".format(sys.version_info.major, + sys.version_info.minor, + sys.version_info.micro, port, + tclversion_detailed, ver, + __file__) + return versions + + +# ==================================================# +# +# MM""""""""`M oo oo +# MM mmmmmmmM +# M` MMMM 88d8b.d8b. .d8888b. dP dP +# MM MMMMMMMM 88'`88'`88 88' `88 88 88 +# MM MMMMMMMM 88 88 88 88. .88 88 88 +# MM .M dP dP dP `88888P' 88 dP +# MMMMMMMMMMMM 88 +# dP +# M""MMM""MMM""M dP dP +# M MMM MMM M 88 88 +# M MMP MMP M .d8888b. 88d888b. 88 .d888b88 +# M MM' MM' .M 88' `88 88' `88 88 88' `88 +# M `' . '' .MM 88. .88 88 88 88. .88 +# M .d .dMMM `88888P' dP dP `88888P8 +# MMMMMMMMMMMMMM +# +# When things look bleak, show your user an emoji +# and a little hope +# ==================================================# + + +EMOJI_BASE64_FACEPALM = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6REQ2OTE2M0Q2RENEMTFFQkEwODdCNUZBQjI1NEUxQTAiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6REQ2OTE2M0U2RENEMTFFQkEwODdCNUZBQjI1NEUxQTAiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpERDY5MTYzQjZEQ0QxMUVCQTA4N0I1RkFCMjU0RTFBMCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpERDY5MTYzQzZEQ0QxMUVCQTA4N0I1RkFCMjU0RTFBMCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PrG3klYAABf+SURBVHjaxFoJcFzV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' +EMOJI_BASE64_FRUSTRATED = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6Q0YzMDVFRjE2Q0U4MTFFQkFGM0JBRTY5MjFEM0EyRkMiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6Q0YzMDVFRjI2Q0U4MTFFQkFGM0JBRTY5MjFEM0EyRkMiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpDRjMwNUVFRjZDRTgxMUVCQUYzQkFFNjkyMUQzQTJGQyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpDRjMwNUVGMDZDRTgxMUVCQUYzQkFFNjkyMUQzQTJGQyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PrCGivkAABgCSURBVHja3FpneFTX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' +EMOJI_BASE64_NOTUNDERSTANDING = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NTVEMDZBRDE2Q0U5MTFFQjg5MjRENTNGQzVCQkI1N0MiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NTVEMDZBRDI2Q0U5MTFFQjg5MjRENTNGQzVCQkI1N0MiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo1NUQwNkFDRjZDRTkxMUVCODkyNEQ1M0ZDNUJCQjU3QyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo1NUQwNkFEMDZDRTkxMUVCODkyNEQ1M0ZDNUJCQjU3QyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PoEgddAAABw3SURBVHjarFoJdBzV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' +EMOJI_BASE64_PONDER = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RTk4OEJBQUY2RENEMTFFQjk3NEFFODU4Qjk5Qjk2NjAiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RTk4OEJBQjA2RENEMTFFQjk3NEFFODU4Qjk5Qjk2NjAiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpFOTg4QkFBRDZEQ0QxMUVCOTc0QUU4NThCOTlCOTY2MCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpFOTg4QkFBRTZEQ0QxMUVCOTc0QUU4NThCOTlCOTY2MCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PohXc4wAABYiSURBVHjatFoLeFTlmX7PmVvmkkkmk3tCQkgg3OSmCAoqoNaiFahVWimtj7aP3XbrttZ292m3225rd7Xrai/brt21a7XPtqIVtbWsoqIoCnIpd5JwyYWQyySZzDVzn3POvv85E0KAkCD0PM/PmTAz//nf7/J+7/f/I2mahrOvrVu3Yvny5biYS5aAQsCS1jDTCdQ15GGKqmEy3/JCg4N3EyTEOBJ8HeDnu6JZ+Foz8POrPhnozQKDcVz6tWzZMrzzzjv6a/OlTCRAuYCCIhnXecy4dWYN5pWVoGbyZJTW1DosBYUuWPPsMJksgCRBzcahJgeRSiYRHSLKELSuHsQCQQQzGQQGwhg82o12vj6YUHHIl8UJmv9U8hLWaP6owErN8JZL+HJjBe5ZtBANS66vxrS59SisbQRslfQXoStcWsYPpLqAZDuQFn9zAvX0VJyJNtI40pgUiQB9fUAoDBw5CjQdRX9bF1oIenNPGq/Tu3uTf22AAtwcM26fXozHV62xTf34XYvgabwasNdy4YzEBAGFm4Ghg3x9koAGRwBJuXG+i//vZoy7i43XC5fyrqB0wIfStjZc/+52/HDnfuzY14nf+FS8yDiPXHaAzBPMNeFB97LrHrvqwU+Zrlo4lclUikgmjZ5wGKnQB3BGd8GZaaNLohwZOCUrbHJ6/Mk1HZAxzrhKSjkYEIuug2mgB0tfex1LN27CQ0f68WOfht/GlMsE0ESrzpPxVfvq1U/UP/p7uEodeJvxkmLIvUQnvRsSobeS1lfhsCYJbghOLabfxfAgiHLNh3L4Tt9LtX4SU0gfHi0I9/mcks2NHNjPfwG4cTlmPv2/ePbt97HqYAx/F1DQc8kAp5uwxLzkup8U/uB5LC6yQWFCpAn6SeZMS1jnSMPF/CdO0hTjnHCUzreArA7eowmgQRTDj2qtGzXaSdShna+7SMOD8GqDKMkMwJRRUEVu/qcHgClV+NSLr2D2sQjWHk3joKJ9RIB2GZZJbvzk3i84zHMqdsCUkpGV7egINGFlyIcVlkJEpEIurQhRzaWPIc2JmMRh+HLMubNcwgBKMCCVjGkIOyuLDpCfFJ5vyLSiwX4MBbcdw6JKX6P0bMsrwc7ULb0ajn8kgGTLz9x8AxauvTafpHHCoMFkH2aEf4SVpjRUhmiWYWS18S0O1WZFyuwiQIceoBEGH4MQfVIZl8ehlaNHE/cy+LUiDGoeGP7znPf5CULskqrRherRBqBNHLdnUFG5qW7O99b+JuvP3DigIHVRAB0SzNM8eGDNmgIg/1qSAONQYl0b2owjf0njuVeADpKlSsw2grOLYU3DkRdAvjMAjxvw0C6F/HodX88nUzoZvU475+Zdc0lIOYoQlg2ADEZ0E0wnJqFVnYx2tRb9mghcL0cxacsyipjiKQtaF61B/t0PLZn55KNffU/B49rFAKww4ZpFc3DVlAVXcEKv4T31BLb9aScefow4NQfkYprSxCRM0o2xLLQM7wqHmiXniM8rvCun78IIAqAAmu/UUOBi+HkGUc7pyznVXI4b6MwCGsbFobptCJqLCb4YfYyAFqUeTco0tGhT0Z6uhF+pwLFP/D0Wb/nD182HWp+hghqcEEAzQ6HAjLXLrmNQFM4jQNrGoiGwfxN+/qss4jYPzPUz6FEZUjaT43rof6tmQ73gbIAEnsgqiLO09KdZPgJpaD5GFb8v3pNoFPE6j88pcBsgi9wpVJR0o7qsG/Ust/fS1uYyIfiA3Z0y/JZKBPNrsbshWt1yCDdxFc9PCKCIooYyrJg1l08y1RpUmWnC6y8fQI9fhnlWHVTKsFS+F8miSih2FxepwBrqh7OvFXIqAdWax6+ZoZnMevJo0kgSSWdyiqbqXpdyI0WQfZR0vngSWjAF6QSNkeVIJVFToeEr9wNLqC8sLEuV6S40RLpgnQK8IWO1RZogQPqgcUotppbWVnEVlBhyBvFjm/HmFhWypxia1Y7IpJnwLbod0UmzkCit0b8kJ7LI7zyMSW8+DW/zdigCpPCm8LB2oWIrDGEZMUIBDUJAWoK6xWyCLAajoLOzHf/yWBAPf5ceYE7H+XaM8xZXMM+LMd8s67QdGxYnY16VFlw5azqXnE/TyFxk5ij2bz8E6kPIJeX6YgpP7EHjhodR93+/hPfwe7CEIgxPM8KN83Dk/sfRdcNnWbuSRniPq2Y0w5O5sBYelZnbWjIGxd9PWTuArCZDnjoTEcWBDS+OhID4ih7SBaghBUyakAf5uKunNwjqrzX+Cm7BO1tVZG0kFmcBTMkhxMqmoH3VAwhMXwxNNhu6UwymlTBA650P6vlXte33UGzOiakKApUZjpIAS89LLDuZeBwaw1/xU1mUV8FEWdPR2QE/pa+bDM23YGX0FBeTnG2gL9EyJkCykO7aGg9mllbwWxaGaLoV4bYDusqXC4r0UBmqmoYjX3gcyfJyMuioLsG4cjqx9ZMPIi/Yi5L9byCb59SBn1dvE5DMjkNh6EcnzWDI19IoDtgGe5F3YBusfSehWmxQh6Iwu9wI+oD+AZahIgOgiBEvX0sKKi/oQc1YawFpu9xTzCCXyNnRF9DK7rSnn6lS70aGDz5213eRLCuH3sKOdYkHSya0rPsBkoWlKGzbh7zB7hFQglQITNyVPBfzeRXHGkRqZkKz5wzBxVj9vfB+8CdUvfIzWGIRaI5SZCUz+vuzaGwceZyLQeKPoHgiIVpCivbmewkuTbEZ2YmmYyQy2QoL82Jg3s2INswwPHehi/khZ1Nw9HcgNPVq5He16IA0lhIRirGKBv6tIeGtwqkVn0e0ftaIyM5pElM6BjO9Fm1ciNYv/RQ1zz8Cd4rqnt7s78uOepzVqt+cEwFYSIAFcBBgeAcJJoHjrVwTGVG1OjAw96YLM+IZ4aAyKUoObEHNm08xf9nfmg3PyKx5IlyP3vltnYFF+OGMcno6COxOKPn5qH7xcTgZAaqZYSoLVrUgGDyLiE36zXZmi3fei3XU7Smk/RWybXQHsvRUH+NdponSBSVI0uLn5NwFQMbKpxBA3mlweuQRnCgns5/5JrxN7/Nh2THDPOWtwPGv/QLpogo4Ow6R0Lh0zkXu0Rn09JzG6/S4AFnkC4VMQrKNDxhANAp9H0UwWpYkIBY7IQ9O4EpTKAzOWsKwNY89Jz2r5Vlw8rP/jKyjwFD3dJe4ZTK5Mivmyui3+LgA+RyHEM964ycZxVTUW4ktgymdYM1Pjr39cJ48PJNYRjOnhu7r72YY540fEczJocb5iDUs0NlW5PHZ9kgaeRsZF6DIT/kMLSUslebQzFZYAz5jwfLEwCFNXcnc0YnlzLdYalLuYjLm7HO2Ksbc1iCJDE2ZoxOUzr5nfUREGp/SNxGA0tm1URcjjH0tHkXp3tcn5kFGgefobrhPHiI5WM8BmCHAjMtzUfmczS8yYpLFj6IJFsuIUBKk05ViZzwBgCnlDKvqE5mNLFa4mOJdf0ZB837oW7pjXcQjpFvdpl8YXYIknaNYNEk6x7PjRYQpETWMS0HudOo216cWXVo4jFBCYes4HkB+PhofrnEEZGeK5NEbGifVSNFSaBDTn/8B3EcP64yk96HD+zIWg6Vsg/2Y/ux3kH+qSaf2c5zBecyxEMzxyMTzmUZ3nGqByD7RonlymwACZIwkGI+hj5rcN24d9In918gIQLeLzSmHFklCKnIjyzC1+tox+9ffQPeSO+GfswKpglLdNNbYIIpadqBy2x+Q5++k3LKfP9rYPeRRb7l6jiFQUjx+HjIibKc6kN9+0AgpEk1ZxQhAsXHcH0JnkWR0EhcESOeFAkHWE5XTCqnEklHCjrupPw5JBD2TMs2MNlNgT97836jetmEEYMQPy1BAb3pVq/3CEUeiqNi+EYHZ1xpe1C7ACIyQyk2/gnUoqLcONpOCinIj/0SICuHtS2CvSRm9lzvWNRgKYzA9lPsUJ2icylsyoYcHLDQnO/JswI8UC6QWGEAeQ8dOb8jsMhQhqgWpiCefb+RiUvSK3uZtqNr6AnMgF+bn9InQc71k8wsoe/MZqIVeRlIQxV5jr1RwhZiy86TumA+liezJEFM/GckXCNFIVcZ65lAmWtQUVGpLifJJy6T1/k1LxKEkchHG4isxt2CSIVGpSGaT3sgO/58BkO/Jxl0MYYgpm37OvjGB7mWfhuI4Q0QIUolEUb7xaVRv/HddvZhEXxQOYfICpk6+bmekWP86OxHpBQ42jAdQPFuwcesAWvr6ML+8GqCDMJltYTVjvsPXC3NdI5tPBRpFsB4jci4YaE7Rt+nK42wlngMnHiANv855lFyKSb/9Pjxvb0Bw7nLEqhv1NHCeOgzPX7bA0XGY6skqzrJgSsV1Y8zJbRMJG/YQWZcPRzhjx7geHE6FZAbvHW7G3XOv5gRCh3KiG5Zxouf80NoykCtrkbWXQSV1acmEsZM2TIfSGLQomtisdk6qGS2aBsfxvXCybp5NRmqeXZ/b5KRY7zyKSezZ66cYMk10EB3tQHcIr4m9AFmaWA6iT8F7u/chqSaNYjpE1bZwEXDffWyqnWGYTxyEtbsVVnaYFipzuagEksNl5OfpLYgzxihPnm/I+iaVyN/Tg32nEOXCArLHC3OKBBkJYTE5yW43LCPq3+HDyPoy+PNF7WwnJDQfaMFbe/fiE9V1nHdIr624+kpaK23G1u1sMONBxH1BDGWsMNO6ktsDzWlnjXNREEhGntKzetiKocv9Cah0AdiUy18aTHY4YZJUZE8cx5RJGhbMN7wnmpNTp4Bj7dgV03DwogDGmE7dCTz829/j49/6FueyGGsUST0YY954TVh1u4pym4pDTWmcOBZAb28A4R7isNjZedDEJCOI8LIJ0JLe3Wt6+Mp6NA8foUvDIa0Z/9CXhtZknssphlBvH7KhELvwLFat5pR5BkCxJjoAvgiejmvnVtJxd7aZarveOoTvFT+Lf13zKS4k942sIo7UNHhdJAfWouoavreSwEUtotRta03g5MkEgqEAWBYRS4jksOgmFwrGIBtdjxjeyolnI5wVfX9VhIs4fRIRms8O6ZpbgQWMHlEehsGJE+ED+9AxoOLFj3R8Jo6kTip4dMv7KI7G8Y01nwRKKTqKCGx4PUKbUhRgyxbqO6qJaayXN95k5AiNrisMMUKhjD7ISXqjKhY5HLWChEVE2vIMWejKCYueuIytRy1omKZi1Y38bnKk/xM22voO0NyHHw9kEf7I54NxhureOB7yf4j2fh8eXnkbChurVOxqM6MnJKOxWsHOD4E3jtTDW1eLpg+78OHu47jncxrEsYUQxFVVI6klaF2Wca5yMRoEvTXTGxGubtcJ/me7BLtF02vdcFEXIbrtfWD7TmzuyOLXinaJB6BDnLhFxS/8J/B219P47oxp6p0eZ9ZyqNOEa2aocNo1kowNjspKuOnCnt0uvPrnvbjnnhEPiYWJatLnM2SVaG3SOS+K98VpUwOrdEVlDogmtKWkf7/SYyCw5I48tm0DXnoZe/ZHcW9cHWuv4yLP6EVP2K+gaWcU67oP4IliR/Zeb4G08rkg6koYUrZYL4L+ATioNLwzZqJt53EEB6PIdwNHmsl0xwgu4IJqq2U5qYDFXQTNaiIYRScbJZzC9ue3Yf3aIGqZ0wl6rLlbJrFouGKyKggVXSSwrW8DO3fjj/uHcH9AQf9l/xmJOPg/qmDPsRT2FIY1b0sPrnaacYsnP7Y+Ew54E0VFyC8shF9y4eWNUSgWN9K2GShiJ15yRQlBWZFiIiUo8dLpFLnEcEB+bSEG6N721l1onAa8ddiM/qiMG6dn4OvQsIntZ/MRNLf48ZOTGfxPTB2/Tb6kHwKJoAmqGAym8Rr7jtcWSGlvQSa5PsKuM3HsAArIFvbp6+GqrUeCjBRgTPb6eoyamCsNwnsKky5LpvLz/VQ8hJNUJS+/KmHvcZaLcCrxYZvW9jsf9gZTeIls+VZExZA6wQ2vSwI46iSYOVSUb6tPi6OvQ+9jzpLrUbnwenT5Azh+ij0hC75JCHGCSpIt4qTRZDJJQiE4UXOUDPIC3dAGe/a91YoN2h6tOyMpfT0p9BBLO0ElPsom3kUBdMqwVkj4mF1GKRlviE8cpDyKOkywTM3HCi2rXJkf6cM1d65D1luNvYea6B3WMjanYgx7rL+/n4yYIrEYSlFictmSMcS6Tr10IIH1JI3E5TK8+WI8tLQI/7H+nrn319VKiPub0eNLob2LbcopCae6NLiZdwvu+BwGFBMGWpphyQEb2YLRdFDCk+IunSHIjX4CA/znsoG7KIBlKm69Y92N969/aCaXsU3vLDUW6z6W1+f/oCGQqMLMNXfhVDSFGKu9xWweQ2JKo4CdBs8WyONx3bfUnZnWGUw91ZXEVvErRNF1/dV/jCe2Qq6amv+jtevYGLb+Z+4wjotlsd2zGfjgQC3qPnYr25UhZBl6JpNpAkeA2mig0QDU2lkWKZ1avsB1YPlSh9ZDXuqNpxBtG0BbIoF3exS84M8geVkBip9w1Znx+U+vwvxC80ZdJwZYpDe8BPxlH6WU34nqFdcinFWhUIUP59WFgI0S10J2i3NB6i7FYoMW9OOTazTMvgKVhXZU5nGFwSEs27MT9/38d1iwI4ivKxcBcNwNySIZBUun4R9W3szOPTOEza8CX3wA2HeI4pc9WXVpDMe3vI54VztFsXVCnlPPPC0RBolHKL1scJdWkJRUXZPWU82UlwGF1KN19cBd6/i8WVjPJ5TjcgIslfHZu1aj3kY18tNHgIefKcIdd9rw1OME+kXgZ48B624Jov+DLYi0HWW3YblAiyfp4EYDNMMUHYSrvBoeCgRxACNaSLF9ozc/WWOLT+jUpYvhLTNhxWUDSGvlLZyOry5ki/LDbwLPdV2J5ic/wKuf24iwSZz6kl3ZMdz/ZeChv1EQ3Pc+hjpb9XO7sa4MFYyofZLwHMEp/b2wpobgqpnG7oShyigQHYNuA2n0hu/8OUBtEVabLhfAWhvWLF+MGU/8lEwp3YrmJ95AoGI6XojfhpXyJvRIlactfNsdBLpeQ//uD5BiHklnEY3wnsjP6FAMqsg3Ck2powmL60KYdtMKSHa3ftIkune9lVLOPT6rIsfNm4LFNLznkgAKGSQ6kisq8M33dgJhqv67vjePFb3o9LHyDukarDb/Uf+loK7ZWL0+fTdw0+I0fGQE4QKJQGQdmEmPtkAogkDfALInO1GbPY7vP9KAh/7rdsjucqjCq+KzbAhpAyTT5+pCmdFyxUxMqrBgzqUBFIf5EmbFIrgyyod95x+Ze65/w9rEC6M+t0e6Cp8xb6AD8wwjc1GfWQsUqL0It59AlguOiV8rdXWjfc9e+He9i0bLSXzpvgI8uflWTFu2AE89JSEaztIIOXYVx9IRCYnk+cXvvNmQqKiWXlKZsMmwTZZwn9iO+/bX2J9NFh5iV4kv6j+JfFe64fRn35ZW4G/Nv8Qjg1+BbyAF8aOm21cCz/5xPwt+UA/XmioLbrnZiSUr52PW4krY853o6VVwtIne9p0+V9f3YyVOMBCyYogFUP+ZzFkHL7WTyNxluK6pc2JHiv8vwABqm5kIE8asvQAAAABJRU5ErkJggg==' +EMOJI_BASE64_SAD = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QjhEQzE3NTU2Q0U4MTFFQjk0NEJFQkEyMDc5NzVGRjciIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QjhEQzE3NTY2Q0U4MTFFQjk0NEJFQkEyMDc5NzVGRjciPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpCOERDMTc1MzZDRTgxMUVCOTQ0QkVCQTIwNzk3NUZGNyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpCOERDMTc1NDZDRTgxMUVCOTQ0QkVCQTIwNzk3NUZGNyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PqiratEAABX+SURBVHjavFoJcFz1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' +EMOJI_BASE64_SKEPTICAL = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MkM3RkFGNjQ2Q0U5MTFFQjg0NTRGNTdCQTc3ODhGNDUiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MkM3RkFGNjU2Q0U5MTFFQjg0NTRGNTdCQTc3ODhGNDUiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDoyQzdGQUY2MjZDRTkxMUVCODQ1NEY1N0JBNzc4OEY0NSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDoyQzdGQUY2MzZDRTkxMUVCODQ1NEY1N0JBNzc4OEY0NSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PnKdXnkAABU6SURBVHjaxFppdBXn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' +EMOJI_BASE64_THINK = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MDkwMDIzODE2RENFMTFFQkIzQkQ4NjYzRTEwOEUyNUQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MDkwMDIzODI2RENFMTFFQkIzQkQ4NjYzRTEwOEUyNUQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDowOTAwMjM3RjZEQ0UxMUVCQjNCRDg2NjNFMTA4RTI1RCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDowOTAwMjM4MDZEQ0UxMUVCQjNCRDg2NjNFMTA4RTI1RCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PraG6u0AABkKSURBVHjavFoJeFzl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' +EMOJI_BASE64_DREAMING = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6Mzg4NEExODE2Q0U5MTFFQkFDNUU4NkQ5MTIxMzQ2QzAiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6Mzg4NEExODI2Q0U5MTFFQkFDNUU4NkQ5MTIxMzQ2QzAiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDozODg0QTE3RjZDRTkxMUVCQUM1RTg2RDkxMjEzNDZDMCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDozODg0QTE4MDZDRTkxMUVCQUM1RTg2RDkxMjEzNDZDMCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PqXm5wAAABe2SURBVHjazFoJdFzleb3vzb5oZjQz2iVrsSxZ3m2MFxaHsIUSgmMgQEgTE7JxEjhJmiYtCZw0tCcJOS00TRuSQ0rpkoUkQADb4AUIBgM2XvAi25Jt7ctoVmn29b3e/z3JlheKZWjad87v8cxo3vvv/93vfvf735NwAYdsMKBpdlv9kpWXXN8yu/UGq9VySalU8qmqCkVRYTDIBf7Z4Yl48oWdr72yaaD3+Guh0RH8XxzSTH9Q39TivOzKa7/W1j73Dr/fO9ftdkkulwuSJEEA1ECWSshksghHIuI1NjIyuv3Avt0P7Xh5y5ulYvH/B0Ax4eq6BrOiqnWyJJVz6mZnmRsfv+2Ov50zu+Vqf4UfDodD+1sB6szfTn2eTqUQjcYwkUxlNz37zC0vb3pu458SoPE06skGVNbWedrnL7y2tW3uupr6+nl+r7fOarOWc7KySvqVigX4/D44nU4UCoWzwIl3pCuK+QLyhbz2gdFohN1iti5cetGPBnp7e8PB0cPjkfCfNoIer09afcXVd19x9TV/Uen3tQraiW9lSYbZbILZZEQylcbw0DBq62phtVpR5rDDX+6B3WbVgORJv1wuh+j4BGKJJMwWC/PVqC1CoVBEKDyOWCye6evt3bpv15sP7X75xTeypdz/fgTrGpttt67//OMrll90u9vtFLGEzWqB110Gn8cDl9PBKBjQOziiRW18Io6lDfVY1N7KqMunnTCdz6PARcmXgJETPQj0dCPc341SYhh2wzjUYsLmLORuXGkqXte2qLQrEEcmmdLWZKxYwrBBQv9QDoNZIMj1HU0DqfcVwYqqGumWz3zu4auuuuJrTuaUANbECFX7vYya6awfpCgeE/EEvB4XrIzQmccfX3sLb296DsP7NsChdKO1MY+OeT64fR54/W7YHTYYeF4ZjFwxjmI6gkQsxEUrgmsDBh69A0DXcYyn0xg9FkDfwCj2JgvYFSihk+t2YiYxl5auvHTNF75yz8bZLc3OivJyLGhrgclonPFKlfI5/P4ff4g3n30YyxemcPk1C9G4aAVQ3kKeVBAM1TPDUpHu4esJ8nmMn0X5wzhnwWkbznFSFpvxCJkQAPoGgV17EOvuw6FD/Xh+OIeNGZaizHsB/MI3vv3gZatXPjBndjNWLJoPwxmUO58jPjqM7339bvRb07jvcwsxZ/7FsMoeFHMZ5JLH4Ey8DFNyF0HFdRWargDSeyiE4XQpnKA2dXcDr2xHescebD0UwE8DKraklXfPwYwQAb/Xc2HgAsP45udvw/5r7sKNd96FvbzQfgbrcErBtnAaycxiONUr4ZESqDGGUI9h1KnDaMAgatRR+BCBV43CjzDxnK7I2tvi5Jg83G7g4ks4LoV9tA9rf/8s1j67BRsGk3jgeAHvKOqZFF116bw77vzcSx+95sPVHS1NMwKnsmT81frb8Ycla7H+S59BFZWBZMOWceDp4OQE38NKOJGET41oQCsQQpPah9nqCczBMdRyASoQRKUagoN/d9Zh1s//zl7g548j8Won7h8o4Z9SpWkRPLhn1+HNlVUPzmqo+2lb06zzjqJgxG8ffRTW1EY89ec3wJV5lVSwIpwJ48hYPz4hVyImVyCquhHjGIdHG+oZiJMCouREPxrPaT004ARYhTENeId6BO3oQj1ZUJsfQZUUwJLlwPfKUfbYE/jx9rcwe08WX48UtSmeOt3aO9Z/7WM33PDQ9VeuMddUVf6P4HIsFb0nBvD3n1mJHzzgQsWqv6QgiGShDI7+kEIyAoVRLPESJZsBebsHSaMOMIZyDEt1GqBejj51FoKKHyFFIytrguP8/DDnX6uOoBYjmI0edBT2wxs6iENPH8OBjd3ffyuF7wiERpPZjGWr1yxtmNV4qYhdnpMvUPFCkZhWMhws4maz+SwrtuOZ32FVB1d32e1E4RA2iBq/FYd3juDXT+uqJ44yWwll9gg8Zfzbcmij1gss9vO7Mn2oTgMKZT4kzD6S1I9+qQnHpFZ0KW1cgAYElAqMqZXaAp1ikIwhqR5DzOpdoFpbOA+SwPmNOJaod9634Kln3jygYIPxhts+/c3rP3Ltt2++4SOecpHBJ22bjP1Hu5FkFRbmWVV1mTKbzGiorsE7Wx/DfXfzgqYOXo3JJo9g54Yt+O7fUekkFwy+Sqga6BzUaAGSsG2lPCSFCVIqsjIUYTOVaCLoopwljiDBB3luLkD1a1hQBXi5GA5OqcSam7BVIkCiniDww+jAIaUD/QoBqrX8vHrSI5LyRhf23vWotHrfGz9wHh972bj2o9f/6JM3feysol5d4UM5nUwwEkUsntT8ZZxgR0NhqJ2HUGPvQe3CawiOITCoSHRtxE/+OYGExQdT6zyodDNn64sqjCpBFjWQWTIlTc86mstCDeQgDVCl9nARKF5SqYAya4luinnoiqPGH0dz/XE0N+zA6hqCJwvM5TLizloMlOpwuNiK11KLsV9aiJHydqSvu2VB48/+5SPG665cc07HIg4LqdlQU82hvy9ycruPdOOJ+7+F25cL/i0iX/nb0mFsfuoN9I7JMCxo1sBBKb1LbZOhGkl5I12QVTq7FCqKBg4cCVqbeDaH3ijL+Uga0h7hfgqwyHmCVglewfw5Q7j9xiEsbduJqwd/idAESeN0o7OiDP9qx03G3oFBVLH1OS/jykZ3UUsLnLluzJ1n5wf1pGYBme4N2LSZkfFVQ7U43h3cVBTV6a/n+AsjF00sgtUJyTVtAcR5MymtSxkhA4aTWezfFsLWN9J48D6gqo5fJ5iHuQks8kygqRpL5Kc2bNn/TufR8659Iz19sJZ6UDWbGS2T+7kD2PPqARwflGCorMK7znpGBVaAV3RA0wejr0gUpHSGTGeHWu6HaeFSRBQvfvJzgLoIxgB5/txWptG4wRCJhJ/s7u03FVVpvtNht9jYBhnfxYvmmC9b//AMrOHncPGfXcYkoMAEn8DjjwVxLExh8VczoDnIXF0xJEWZVN2pf943cmaECWo2AzWThppOQaXomeihYz0BNHHNq6q1NNeADg3Bauw6+E6sp+vwNxRJHusbGn1oxfIlVDYnKn1eGDkn0QPGafHHwmGMp7LY9vxzuGslr2VrJ+KDCB8/jM4uiqnbhcCqdZhoWgB7oA/28CDME0F60BjMySgMufTpU2VzLVRWZURmCl52OFHK6jZbiY9D8VcQuA0DA2l2LtNsnWvSxjY0tzZfsnr1vR1z23ktWWtOB0ZGkUikCDBJzjMiBlk0xSzDUVTVUERk/jrya3QfUxGIyjDOdiEy73JEVl+q+zVxUBSNVGBzIgRLLAB7sJ/AB2CNDMMUj2jATakYZNEnnQQpnQIvG86tU0IURQkSVKYSaxtdZgsCgdMX0WabBNixaMnyxlkN9bVVFZjb3Ej1NJ1UzQK70CJPQsZTwFS8aY7D5acopdm0pQ7j4BGuotnGWu9G+6+/i9Qrrcj665GubNJG1luNvKsC6ZpmxC5arSuGSFO2sWYBMh7WANuDfRp4sRAi6iYN/IRO80nsQp0FaBEEiRxUC4VJT8z5ma2YmNDpObVWBuMkwCMH93ezpVbam2fJU+CmVFMMItbeR8ZINSUGt4dLM76DK6DgeI+oJzaCtCJPN2KNDsPV9w6MlDOJK1wi+EKZV/su56ki6EakK5qQqWjk+wq+zkKypV03ztA7BzlR0KJuZm9kDw3AFuqHTYAfD2kR1yhfYO3MZjXFFQDBCGbIWjEoI6dvWfQf79r/1JNP3u2wWB65as1qRxXz71xHOkENLmVgN7EpS6t8P6lcJgNiTYtx6EsPQ87kYZkY0yZjCzEqnJygpmV8DGWDh+E9/DoMeYoEl7lIqRMWLV/mZ6RrCL5ZW4CMvwF5tx+JWQsQn7foVDMsKM+00cAHCHykC943noOLryKi1DeIoApqamtVnAQo9iq3PvfUY8lkfOfmLVvuXbV61VVzmpua62ur4bQ7tA0nhbw6caIHJgOvIunUiBNgXHQxdidskSFU7t6sTVJMeHzOLIwvuegUJbmypsQEKRlilEf1fCQtrRQjy0QI5Uf7ULlnk6a+CrlVcHg08DnSW6N8FcEz6mIhNMovacL41Wu0a7l/9lWodrtGz9K0EpzLTeuVFdaZHdtePPDGS1u+8MKzT3kdZa6OjoVLWulJ6wnQaXW6JXtJXd9mLLAW6JMmQ7ShllthCQ+j4z++A8Vk4eTKkXeWo+DyIeurQ9o/S4tMrrwaOXc1Ug2tiFgvn9zr4BqwORa5KIaNgAV4W7AXtuiINlz9Bycpr5DyVg14mnqQc3phZWsm8k8IjnSGLUqlztgX1WusgtDocJRjR1/3kR3Tt+tXLF1xZF6z8sTUSag/2hBnVYSZttq1C5lSUdKIHfrw6QaiZLETuBcFgs+7KzUqppmDYuTdFUjVtCLRNu/UrHhKA92KeSKkjSm62wne0NOJsq63YciyFnr8mpEX5Ztkw9RW7fg48ue9uyQ6ij273zx0a9M5Nla5dAoNs8REl7TaZqTanUPeyRKRi1ZGRVIPnnJuMvPR7tbBl5VTfKo1ERLAM6SnoOHE7GWYWLQMkE+Btw70oeP7t8GWphAU8xBd3dRGnxDfSAThGW2f8Y8Nk8qsTUyIq9Yq8mxCstUsDbHDpdusc/kQYcJZT1XD2ZcVRsCeYUKP9Z7amxH3OehJRcS1qJcJyjMfvbVI+hromth5UE1BN4PkOBxeHaDIQ0FPjrGZ7g9mkmmxoQmL2BBw2PURERdifSrFJyDb7ILPp3hyZhRV0S2UTm7YTBX0qcHZnuVLtdKQiMA53KWzJRFHMRbRvakA56+ClM+iskKvgaKyiZoYiqF/pgBF/5tkrdIAujy6HUIsA8njg5pKoBgNw+D26m7jTIvFSYg8zDECqsGktUUm1hpR1AV9BUAhUmdsH5xOeVFelDi7FruOhr/h0kLKZdAw6+SfIBICRhPYMyOAXJgowx4jk3w2dkVGXqOhFjgwnIRcWUunz2iw0hZzAUjivoTIScFhZr+BAIRXHb78E1pOKQYzS0KB6hhnXgbh6dkDb+frcA4d1Sh8TpsmwOZzUHNZHYVQTp5f4vsySxF1dXruiQj29lHhFeycEUBFQjwQQXB8Aq1Wh74hvZR1eOP2FGSJFyM9hcMXrY1w+6XMpDcUV2QVjntqkJrbqhVssWvNjoelxI1MTQPG51+EgavWo3rnBjS98KjuVCT5NHBi9iWaa43+k35M4kqrwUHUcqGrqnSAQicG+hEM5HFwRju9NC9qTxidYYZf7Doc62UEqao+BwVmpB9Gt4cNqkfLjZM5KCYibqfxs8b//Bs0P/JtOI4eojgoeroZT7kUxWrByJU3I+GogEqOiVxTkgkoNPwKTUIxHNQYMhU9IS5GEeh4DIu40CIrxFqOjRHgKPZScQOGmXZklTJcrXW4acli0mBY563Px/93plCKRGFkKyOSU/Rp2nJOWYvJCLiOvgX/jqfh3bsVZUd3w97XDdNEDJlZrbAEhtD+w8/CeXQnFHYYgoonez/RHgnvNeWkCVBm3htoDnxyDDeu1RVdANy7B9i+D/8wVMTuGd9lGSvhlR07EV13I7xccGSpqRctJyavhH//bQbxoW52MjZeXOwLuqHIZZoVVHP6fkrJ4tB22Jzdb8PZtUvzpYm2ixH90HXw7HsZ3t0vkLZ+vR16125fTwcjPbA6FsDyKymk/InousRlDh3C+FgRL0zqxswOMimhTqC6qQqrm5r5JqXX3hQTdE/EgrpmGStn55ALx5EZDZJaCcickMFmhYE1RRJuR1grqqVKERJdiEwFNMYmUPnqb6i0Gb3MnENgxOdCVGSnS0+H4V5U2OL4xK1iO1PTMvpl4NkteP5YFr9QLwSg5psV7Iv2Y+3cOfCJlBMfDodlvH3ciGVzFNxyjYJFS4D2NqDcXoDMUqCEI8iHWQ7SVFxGUjTQBs5KADeajSjv2Qth6aUyD2Qa/OnDwGhpC2QxEQSb6xzt2VA/zJkobroJmNOqCwtPiRdfhLr7BL4aUdB71j368z1iCoKdQXz6sV9gw62fRMXcNp3/QlvsZp224n0bP29v16kTZocVCBQxOJDA8HBCK8SJKCOflVlWjVp0xDMCWqSmb2EIOir6BpSssm7KJVjZDs2nqKxYCbS06LQU1+slpH0H8OpICX8850MIMzl68tglD+D62GP4t3Ufw4I5C1RUuFVEk9KUnmjAptglJLymBli2TP8uSVcm2ssUO4lkMg8Kpdasit9om2iTlUDQTjSwwlBEcxI2d1owlyy589oCcgU9ciJdhf5s2walJ47vpZWTmyYXDlDUsK4cdoeC+FDol3hg1UL1i56Kkn0wJiPOibhsqjbZSU3AmY/HiKbU4Xh3LTlrE5ozPTDAxevhuZ36uQtF/feiPLy4CXjrAH7cUzgVvQsSmbPMqYrMSAGbe0bwfDGkyFJcbcikJacAKGypWH0h3SI/cDrzTlaR8xni5+/0GnAsIGNNRxE15SrE/rD47kXq5eZt+M3RLO5Jl1B6X086vdczKTUm1FcacTUFc117LZY0NGBWYyNl3Kd7V3E3SSieirPBTkV7+ga4Zp5lkavAz7eZ4WDkv3h1XrtBefw48PJLyOw+ioeZMt+LFFB4349yzeQglopKE+ZaZSyxW7CyyY85zjK0etzwVvr1Gygit/iZ1iuLumqalHtBvSnDIqj44n4TDpKel82iAudUHDyEyIETeCGWxSPdeexVP6hn1WZ6WCVtw8xs4KvLgHy1ET8xNrTeU7I4aZJT2k64oxCCQ84cIJ2LVjPcBGgjQLYbZKaKYiaP/ERaSlJ8wiMRtZOAt9NnvhViKVDPg1UXfPhMMDXIWM+aPT9fRJQTGBrOo8dvhtllxnyu/jJfma3NZrNViBa4kM+NKdlMc8HhqS7ZXLRzFm1P1RzoQSAY/9B4CdvHFZg4aTsn5pT1zcQiX3OkabIgHn1TZ542F3SIpF9Zhgf/+ltXPLBwcQn50D4MDybRSSdx5DAQVNvhbp1H50HbZrFpV1LY6pToL5VsCkX2jgUxMvSw7L8KuVxfrlAciidTXemc8kxfDi9QwJQ/+eOUU0ezhBX3fvaS17/+N/NNCL/K8IywiCVBs4JtFOrf7b4EVUtXaKCm7g6LW9+y1sCeURv4fYqNZiQ4xnYrAQO79/zY4P7h8fSjowU8GStg/ELvWV1QmaAWGC5vNPzyO/c3tzhSz7JihwX/9ChRpDe9JCFmWQazk73a5L1CkUxipzvL1tykFKiaijaKeUV7WM9qIa9pUdIssHm7G8aKumqPWb6hJhu9xWtCG718bZmEipyiaVDkfJ86vaBCX2vEpz71cXVNhfNV/VG5aQEZI9a+MRcsc3wEp0fORKal+O+baEAALizAKBYrY+y4ZVRWsp2Ls9ek/RC37qr5QTAYRIaCb2S0161Da30D7rFzpmQ0uk8g+frb2LZ9BHcRZewDB+imkfhwB+6//jpOPjeN5JK+mdbF2jRRqoVX7EaJvUqCGyKo7WjkbBxagXtDnQWvOYdv3RLD4uUGzaf+6ldsoI8pNAYm2roqjIWijHBWM9KXraDa2CYX0gzn8o34+IkfYDsBPnI+WnH+24YEMceGu+5Yx5dy4DTPwO/iaeAgBUb2NjPf6DQIphfleAVNmIB18vEhQUkZr/Mze52NhV9FM9uuL38Z2rZDgVJpYjH0estRLEniWQXNGIh9ULH9LxizjJ1KRz3W2s5DQ2YE0KzCtbID915+md4Ynvno0yB15tiwG/bKaqjiaQoCHGD0WhFFNZKw02gYhD+RFcTSVnzlvxqQz+jyUc4Fu/lmnHwUWgiSuF0tHiY6zfYQsJOuaEErFqmYejzqAwAootdgwleuvwYtZtdkMKZJVZKAD3aCctcMi9Ou8VVAXIggBgmyyP/bCFCZWnQ2yKq4zz5t8h0demeu70wweooRufw5tlg562WLUV5jwLIPDCArr3NlM9avWj4ZPWVyiE6BuTgwBuw5ZFGtdW1Fzlx7RpBgiuXIFlsQU+PU3gj0+1pySVWvahxVHl/fBxOtzpQP7elBiW1UgS6mKLY/YTAhmRKPjokn+rU4FrQYUnznsdescuPD7zXv/xZgANie7qn/NSCBAAAAAElFTkSuQmCC' +EMOJI_BASE64_WEARY = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RTg0MzYzM0I2Q0U4MTFFQkFDNENFQjAwN0U2RjM1RTYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RTg0MzYzM0M2Q0U4MTFFQkFDNENFQjAwN0U2RjM1RTYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpFODQzNjMzOTZDRTgxMUVCQUM0Q0VCMDA3RTZGMzVFNiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpFODQzNjMzQTZDRTgxMUVCQUM0Q0VCMDA3RTZGMzVFNiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PuojFwAAABVfSURBVHjatFoJkFxX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' +EMOJI_BASE64_YIKES = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NDdDQTU3NTM2Q0U5MTFFQkEzNkM4MDYzQzlCMUIyNTMiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NDdDQTU3NTQ2Q0U5MTFFQkEzNkM4MDYzQzlCMUIyNTMiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo0N0NBNTc1MTZDRTkxMUVCQTM2QzgwNjNDOUIxQjI1MyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo0N0NBNTc1MjZDRTkxMUVCQTM2QzgwNjNDOUIxQjI1MyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pv+eLOAAABVWSURBVHjaxFoJcBzV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' + +EMOJI_BASE64_HAPPY_GASP = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QjdGRDYyQjk3NkRGMTFFQjg5NzdERjY5MzJBQjA1RkMiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QjdGRDYyQkE3NkRGMTFFQjg5NzdERjY5MzJBQjA1RkMiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpCN0ZENjJCNzc2REYxMUVCODk3N0RGNjkzMkFCMDVGQyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpCN0ZENjJCODc2REYxMUVCODk3N0RGNjkzMkFCMDVGQyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Ptkir7oAABWySURBVHjatFoJdF1l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' + +EMOJI_BASE64_HAPPY_IDEA = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RUVEQTM3QTg3NkRGMTFFQjk1QkZCNjE0QUI5MUYwQzciIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RUVEQTM3QTk3NkRGMTFFQjk1QkZCNjE0QUI5MUYwQzciPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpFRURBMzdBNjc2REYxMUVCOTVCRkI2MTRBQjkxRjBDNyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpFRURBMzdBNzc2REYxMUVCOTVCRkI2MTRBQjkxRjBDNyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PjcEIkMAABZPSURBVHjavFoJdBzV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' + +EMOJI_BASE64_HAPPY_JOY = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NjUxQTFBQzI3NkRGMTFFQkI5NDZCQjFDNkFDNjQ2OTUiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NjUxQTFBQzM3NkRGMTFFQkI5NDZCQjFDNkFDNjQ2OTUiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo2NTFBMUFDMDc2REYxMUVCQjk0NkJCMUM2QUM2NDY5NSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo2NTFBMUFDMTc2REYxMUVCQjk0NkJCMUM2QUM2NDY5NSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PoEmG4sAABmjSURBVHjaxFoJeBxn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' + +EMOJI_BASE64_HAPPY_LAUGH = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QkFBNDU4OUE3NkRFMTFFQkJCQzhBRTkwQjJGMzAyNUMiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QkFBNDU4OUI3NkRFMTFFQkJCQzhBRTkwQjJGMzAyNUMiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpCQUE0NTg5ODc2REUxMUVCQkJDOEFFOTBCMkYzMDI1QyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpCQUE0NTg5OTc2REUxMUVCQkJDOEFFOTBCMkYzMDI1QyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Po9obewAABRZSURBVHjaxFoJkBTX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' + +EMOJI_BASE64_HAPPY_STARE = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RDgzMzhCODM3NkRGMTFFQjkwODBENDUzNzk4QzVBOEMiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RDgzMzhCODQ3NkRGMTFFQjkwODBENDUzNzk4QzVBOEMiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpEODMzOEI4MTc2REYxMUVCOTA4MEQ0NTM3OThDNUE4QyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpEODMzOEI4Mjc2REYxMUVCOTA4MEQ0NTM3OThDNUE4QyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PrgNzd4AABMDSURBVHjaxFp5kBz1df66e66dY+97Je0hidWxQhJCgCQgOkBIIgkRVNnYgsQuJaEcKiShHCepBOfElUqVy0kIMRXsEAeM/UcCFAEsMLLE4XBJ6NZqJXalva+Z2dm5z+58r3tmD2lX7IpVpbd+Ndvn732/d33vdSuGYeDy7fDhwxgdHcVctxwfYcxwXNd5LgfYFaDawf38RSr3RzNAmvuaZu1fvmk8pmDuW1VVFbZu3XrFcWUmgNu2bTNBznUrgilMhRNorHdgMYG18ECDuwiVXh9K3XY4edKmalBlOp7PBZLIxlJIhKMIptMYUYG+uI6uwSz6+P/FOBCfBz4T3KFDh644bsM1bh5K4TKwqlbDzmU1uKdlEVbU16OpbU0pquoq4XK54LYH4XOMwKZloVBTNs4mALNZ/lK7BIZwBEimgEQS6B8ATrYjFQig61gXTo6F8cZIDof8OnqNa5TTdi3AalXsavTg9zbfhB27dpe4W1a1oO6GGwFfI9VD6VN9QKydOhA7zFn2O1VCZfK3RsU0W9yrwGnEsbK7DyvPnMOX33gTwx+dwys9STwd0HFKv14AxU8qVCxrc+Pvt2/BA/d9eTnWbL4dqFzPs6VURScw9EsgchzI+C1ACubnSAXcBN20lKMV2L4VNR99jEde/G/sO3Ye3+9K4++CWYQXFKCAa7Phvo1L8Oz+R2urNu29DyhZRyC0u+CnHAeA6KXpoBRc+ybPSVujyEX/uhtY3QLvS/+DPz7wFrZ9HMJvDhlo140FACjRbI2GB2o2tb14z7f3Oipu3olTmQoMxHQcHA2gP1KElH4n0jYPUooLGdiR5dDzCLOcwpgFrcqrNOSsefhr49UOonIYaTj5W8Q440EM7nQczroY9H1heNaP3bz2uddeVzpG7u0H2r8wwJUq1lfesuY/qp562xForMa7DAjdDAj/OkjFpUwprbGQ20zrwTRD1MBOoK7+/eYb/2z3i+mB6NZRHeNXtb6rnfQqsJdUl/xL6k/+03srwakENs4Ff3p4CrhZZTRMDckQzTiRmjZEY4XzczZbGUwegzfejvPf+Od1rW7tCe2LaHCRivtbdq3ZvPVWH9Ykz1IoA/7QUTwR+wQ1zhi8ahwuJBj2UqZJ2fIGqpigcibIy02xsE01XYGZ4xXymzGXw46kLIPi5G8RF9WLUNaDYMaL7rAXkWAZ0us9cKyqfqTqyOAzQzo+mxdAcV5OrS4pxTf+avtFtGivMaDQ23WqLfq32Gn4MUTrHyHZSfFQisEgnrbymfwveS5LPJmslfdywmiy003QzpkVmYRWYNOsfbudVkhTdDmsXx8HyQIa6hnTmqyg0zFisSMHxTm4Bt6e0/j6cBx/bswHoGGZ+6p1K3Fb8/q1fGKZcB5KfByDnX489Sxw5JiAUpnA84mM0hoisZK3W8U6NtWhjJncy8jb3pRf8xphAvzfIJpSj4HdjKT7H+IhAo7RTNM83boSaK7C3qPdeJJKic8LYA1w16aNcCqlrdbkqo5w9//iL79DtnHRBWdTIzS3x/S0AhhFUfL7mASnKFeNHdMACjgBlU6ZABWqV+UIh8fw/H91I57Qsfd+65GixfJyYEkTWp3dWMOHfDRngHLQZ8P21Wu8jN/V+WjSgzde6sCpCyqcbSuhe5jc9dxlyzLDSs14YApUZTqrFv3ptPvcOIMjyatCyqdVL4aTPO/NgxfQuooEoJnGlLFuW7YUat072GLMAnDGOOhT4F1Zi9baBi6RUmZm+tzIUbz/fgpqeQV0dwmXMJM3I33CnK4YuHxcHhKna88aDDVk6IqDTpJJw4iEkRsdhF5aiZRWhOPHLb8tbHX0T7cNm+zKPNIE6ePiqkos8lVXcM/Nq2LoOf0pOklWtPKKmbW1wJvmK7GQcBjJBPQ0o3NJGS5coA/GrFNipiW8rLkcy4qVma1xRoANTtTW1xJZUSX3GNpSnTh7og+RNJ/h8ea1cx038UWnE4rdkZ+LZhuPmQAlco+MWHWk1JseD+mcB1WsSavmDJAVw6IaudxWavlI9BhOnKTzu9wwHEWWSV7vTYIW/W8CMwOPYXciodvR12eJJdidLhNkBUUqnzNAil9TXip2Qv3rUWRHTqNHHsqoOZEGZnpYNg0tnYCaSc1bywoDltwrQ8kHL1X8sBCI6I9CBCQB9vVOZ3WlJXDpCkrmw2TKfD6xTgaYdBeCA8MIjgtA7yzC0T9oL7GaFqRLqmCLj8M7cMHM8IbN/vn+RlBpXyVitS3mvnv4IpwRP7JSIYuz5RdLp9MpziKMjkZM/5uglAwTixTy8nkAdEuZApUrGDmK0LiBECswpdx1RXhRSFFyTje6fu0xjK7fgZzXCzWRRlnHh1j68nfhGhuCbnPMrvVMEsPrd6F79yNI1Cw2j7lG+9B04Ieo/uRV5JgqjGwmb6Zpmq3bDDJxpvWiIusZYqbujETDuZNtp/g3skSVOIMoH5jI0Cc02/QIml/ZC/d/C0Pb7kPORQ3TOgVQYMOdOLfvSYL3TJjcFZojuOCKLeh4+K+RqFssBNUcyZpF6HjoCQTWbIWWTU3pbkkHy2G2N2QUOITDZrqVaz4AFVP2BPNCqh+RGMyka3BMxafR58LNazG64R5eKwJMOrEQp3BrG0bX7jB9c6ZIqWsO9Oz4GgOXZhW4E3mKp20qerd/HboZ1KZMSrOVJE+XnACo6/Mvl+JpWc0Ys6qRM5tDl9Mu5PnieMtNZiaZserhsdDyW2aemKadqKhHvHappbnLN4KI1y1Fomoxr81MEgQGOVGkEPiCOELq1Vm6cLMCTNIEkOyxLrpK3Zd1ea6a983zsxR4ut1lBaFZ7hdT15kaLo/IymVrLRVNXJ8fwGAkOrljpiOz35eh0qb7k9vfexVDZyAY7Z4ZHs3dwUhpi43PfL+UUdEx2Mf9lmsUHsj5pbySUcAt1UVfErE5A+TB4dCURkCxT3omWbOoM5KT3q0z6JR1fACHP2iZ6bQIArOmqTrxNssodUaAzvFRVJx+x2pHXBHmWC2cOgxnoA+GZptMelxkB6935EmOYBwPI8EZwnMGSHUPjgYm/Uhyos8NszbTk3EYeQ83NDtcgX60vPo9qFLiuKb0Tvjk5tefQfGlU5aZzWSCvL/x4HMobj9ptccd+cH/fefb0XjgGat5VbBHmrORSsLttiiaoJNpqcExXhKacx6kukc840jyAS6JjJXM92VkNmMkvXC4oZPha+WVVuRmlKs+egCu0DAGN+1lUFhEswqg9pPXUXHmXfrR7IleNGOPBrH637+Jwc33I9i6yVRT+fkPUffhK1CZD7PqpIjCTZVEHKU1lttIsIlTJIoVYJwIzBmgXcNQYAzDqQgaSRzgJcsj+Ubn+QjU+grk/MMmGVY9xVaw4EXFF0+gpPNTmp7NZDZS3Vuau3qDVLc5YUtG0fjWD7Dk7efM6xVGZ533Z1KZKbamQZOuQiqORYsxEfxiEVaqQfSV6kjN2URzXI3+EfQGAvkr6E83rhbbjcL0d+ai3FiQRWnQqr6zWdPchNHoXGXzV/KXMlntzzpkiRQNOQKVPluOjpXJ5pDh800Gk2fVUh+qegb2XApNTZPRNEgZx1M4kZ1PTyZCv+sN43j/AG6vb7b8cMNaRsyfpGjzSShFbrMQ1cMh01wV8x2YagFSpXWhTvrNFbmz8K6NPFWfUugyWxtSpej6ZHicuNcwib4xPoKqCgMNDVZjS5pUvSwCGPaOKPNJ9Pluyrsnz+Z3uJDLlwOt5MI5/wg0b4lVkOUFNjib8EQJAEYiYdZueixqjWhk+pBjcRlxs5A175FSSLRVYNAF7eaBK6wgNKcDxpgfN7Qyqhdbp4TRdHcjOgicnHfjd4ircvIMxvWEGZnFbHH3Ns4X8ENLjEOrroPi8Zm+MS0Rf55Jfo65Tmtf0BWUklLYKqqhBgbgzCWxYYOlZFlfP82zdxBnKFqXMh8TlYvpWZfOduFI9yXsqF8EnD0PLF0BbLzJwKcn2uEor4DBiXNFZSZtMrWQyWshl51/1S9mTZszCT1/VSY6aQVraWq66zSUWBg7dgKNjZbmGONwsdMMMD+TtquqzAOgXCxrODCOn7zzS+z42m9Z8sqrvocfpqm2Gvj5IT8il/xWSUU6ZmrTxcBic+Wb9vm+NgEbeqExVQiqiuWrquW7Sr77LdHTlD7GlDYSgS0dg2pkUccF3rMPWLXKWj+z/uVlx48jPZTGS9fcug8YePnNg/iL3TvRVEa7949Zb2nvvBNoTzjQdcnALeUpRPwpjIwGER7MN4MlXzGqgtoQMmDeJC1AdZL+C2kQ25d6UjSu8H81l4anyDAbSfX0taxbQXvIibabc7hpXRaxhLXQkgOPsQ7o+AyvxRWcvmaA/hyCx/vxxA9+hOd/93eY6PPuJrVYhvK5y1Xs3KWg2meAeVMoE8aCOkM367xg0txPxK1X1YKnUNaodotLipkJKykTIsFcKw07IRR0O5QT5LGLBHhYMasFeYbM7eC9kr7e+hnCpyL4dix39Raf7fO+nujR8cJb72IjM8Njd++2rEyjsC47o6eumAFIQrbQOVn5xiXT442uXwlQAoS4msM+85cZU+9htQavy8IgCzJG6/3pi9CPXsKjXMszX/j9YJwTnE3hceUAcoxYf7TnV4EmMokbGnS0D2gIxRTUlhjmKudys4RqdTKrTE2H6fRVYg6vHwqppqaX1RlSyOM009brryLycSd+/1waLyzIG17TVDPIHdXxuP8IPu7twd9s3ozlzSt0VBPYp90aWhfppiA5febgOdHonlu30HzTFGUYP9Wnms/Wozp+/ALw0VEc6oniWxfSOKLP8Xlz/gghSu206/hpYAhvnn8FDzVVGg+XVmc2XAqq6gceFatbdLMJ5HReW19YyXd7pHgdGxOWoSExSH+O5SLfP4D3O0N4diCHV2M6ctftMxJZtaEMxkgCnuocwNMlw/r6Bqd++6XT+JWmCrR4vKhn7VjJoKFI8BCwMiQbKPmvmvLkhPzTIhBCZaXElE5ZcAzpaBSjLLYHewK5dl53sDeJD0kdO2LX2Gu+5g+B4iwi4lkcHeRQYvinsyHyYAP1lKOy1o5it4ZiLojPoaC52O3602x5ndtEJwmdyOzB/u5QWn8yYyDG7BFiiRaW74J4dlRTMRjWF+YNiG0BnmFV1YYwVkh/otsv0S+DJTzuLVExVllKGl3iy786Zp7MJOGI6FF/HB9QO0yKiPJwT1yf0pVboG1BAIr/lNlRVGvDLSUafqOixHWXzVfWotpZHTNqSAnkSY1Pv6GhefW6Wv1UTpJ8Jh1X08muUDjydiiNV2gVn4xlxEj+HwBW2OBdpGKfzYGVZGYepgA7CYiPZG2Fr2HxKs/iZbBX1sHuLbbKphnfhlrkOsnKI8CsnUgm3ZqeaytNhNtKAwN/2DDYdzaqGOc0Bys3HZlkCrFsGu19Ofw4kEH0ugEsory3luMfH31s4/7WFQk4Ux0YDWYwzKj34UfAeXUtvM1LoQvxFg5qfmkhk+jmf4WPgwpR1sl8UFtdhVAoRNYTNt9PZFMGtt7Rt+qWjVhVQ4ZTxZFijj3HlP70j7DxsB+/ndCvE0CnjtXb99z20J79tzGcvm12s6V9ECQl6+o0cG44a9Z1hdaimofYi2L+pcyRzKoo1MfJpMEoq6CiosL8OtFPmpIii66uJMe9iXStePJDo6Uk2qc78NAHr+J7nPbMggMUItLqU/bf++tNTnT/GxNjfKKdIeeGAqr1UYJhTICT9+3voAnnUYMSxHBX7jOsqYvjgQdVs2h97z3gF78QsDo8Hg8ctPme0Dj6RxTzK5qJb9bM5ixw7044Xz6E/UcieHyuyXDOH2ExnVVsuVF7cHnVzy0GrU66lrB8/7ibVbf1ctQCBxwywVWbb1TGUYQ3ssvQdmcR2tp0LCFn3ccS6EtfKnwZrJOb2uCk7w4GHOYzp7ltyiqXNrfhQZEFCw2wRsOebVuydZotcEW8kMo6nnHDzuwutZ+cfg+NBFeVj/mK+ZuwF+EPXluKox3OCenvuQfYsiVfLfBep9eLaNKJQPCyhpx8yULysP0O1IksCwrQxYnWNeCrt96M6S9KFIvtD4/Sn4wSaNSAfO4VorYCcOMOXDQ/4fIU7Iym2D/mww8Plk1Tz7Ztk18DO4tciKTd5jPl2dNAMtOKDCKLS1lAgB4FLRtWY3NVgzXJVIBJ7vez0M04qiEfPUmkLEESlfS5s/S9Gv4qhVLekI5bGncsi06TXLin5boGzVRDHGXoG7SefTlAkUFkEZkWDCAT+I7NtzIIznD1OGXtG1DgLKs0A4wFxcAWxs5aRExtRsWDhcSkcviHXZ34yo5JgB0dwPPPT/acNIZYrbgMvf3Ws2eSWGQRmRYEoFuBtrwWX13ZeqV5SqE7Ip2tUR8cFKrw9YU8VEy0j2sSl5cNBFdkZPHdPZ/hm1+hujRr2uFhMAdahNzKjwZPMYIy0HT2FzHHWnNM0yL3RRaRSWT7PPn/T4ABANvwdk4fKpCrAAAAAElFTkSuQmCC' + +ICON_BUY_ME_A_COFFEE = b'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' + +EMOJI_BASE64_HAPPY_RELIEF = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NDBFNzI5NUU3NkRGMTFFQkI0RUZFM0E0MERFOUExQUEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NDBFNzI5NUY3NkRGMTFFQkI0RUZFM0E0MERFOUExQUEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo0MEU3Mjk1Qzc2REYxMUVCQjRFRkUzQTQwREU5QTFBQSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo0MEU3Mjk1RDc2REYxMUVCQjRFRkUzQTQwREU5QTFBQSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PsnMYvAAABTwSURBVHjatFoJdFzV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' + +EMOJI_BASE64_HAPPY_BIG_SMILE = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NEMyMDNFQTY3OTk2MTFFQjg3NzRCNjNENENFODAxNDYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NEMyMDNFQTc3OTk2MTFFQjg3NzRCNjNENENFODAxNDYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo0QzIwM0VBNDc5OTYxMUVCODc3NEI2M0Q0Q0U4MDE0NiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo0QzIwM0VBNTc5OTYxMUVCODc3NEI2M0Q0Q0U4MDE0NiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PrjncAkAABMkSURBVHja3FppcFzVlf7ue713S62tpbZkLbZsS14xDhi8xTgYMEXZmbDMAE4YEjIFsxXDVKZIaqom4UeGGkIVQ4XMhGGqJikPRRKKYnOKxQSCMbFl47EA71hetHdLLam71Xu/9+a777Vai2O7ZcxMFSrd6uW9fu9+95zzne+c+4RhGPgy/yn4kv996QHaZn7xyCOPoLOz85I/1OjZ0rmFXCW+8fFa/G4ODL3GrRj+BhcqDCiVPKOMp6gcTg6dI8uR44gKgZG+NGIpDaN8P6QB4QQvqIjJa6vi0iBWrlyJp556qjSAe/fuRUdHR0mL4wCungOsrfNiw/xGtHrcmBOsR01zs12trFDhtqdho48oijVp+adz5jphZgkxmQSGRoDT55AaG8NQJIaB7rM4QsDvDQIHMsCJUiaSSqVKt6Db7b6oP1craK5Tsb2tHnd9bR1Wrr6+DvXzWjBn/iLaqpqmjfKOXZw955ajTYxcKXN007ZN2XE09fbjup4+fOf9PRjf14l9J4axY0DHyykD8Qv++CJztpXqy5Uq/PNt+N61bXjwtm1VgbWbV6Fq0WrA1UJzpIGxQ8DALoI7TZCFFRWzixeHC5jfxrEY2HgDfN1nsHnXu9j82jt49FgIj/dr+O+E/jlj8DyrcZLtNqxuq8Sz99/nXXnr9pthb1rLI1VA/AwQ+i8gRpfO6ZOgxGUygrxEZvJj03zggYXAumuw5KVXsGNvB27tSOBvhnWMXhGAMsCX27A5uKzpxXu/f2PF6s3b0Gs0IkyDdUQG0M/AyWhfR1bcjZzdTfZwcjg4T4E8L50vXF7i1ejggtShcExkXgfPVni2yqNOIrOTexzmFbL02RS8+QQ8egr2xQk4gzEEroree9ULu+d9OpD8RthA6HMDXKxiWeCqRS9U/uzNivDiedhJYGQ9PDtAb0wXgtL2f8D1kn/rOb4FNLe+tmbVj+761cFIdgtpN3PZedAnYPfXlP9b+h+fr1nTPg92Ml40D/w0NAXcBS+qF4e0irTO1CFtO3FcoAQlZRTcNwGcW7cNXQ/+5IY2p/iB+nksOFfgTxfdtnzDDWv8WJI6zBMNDI0dwGOJ/Qg4U1yAhOlKTiNtOqZacEo5aRtdrujmpnNOZwaN3+qFFTJMd7Y+57kc8ioZeWXhRBouxHUvRvM+RDJenI35kBipQG61B2p79d8FOod/Majj7KwA6taC2lqq8deP3dSDRvVNEggznkYTjj+Gm9JRdH0CDNKSGabsBMdo1novR45W1jTrVeY7JnAzW2gFjHYuu0psUgLbeHeVn+0263sHb+NyWq8OO+D3ANc2AsFFlhWPh3lNXsvBrPDOSvjPHse3Q0n80JgVQA6y9cprlmF148pVnJnfYolcB050RvH0s8DRk/woHBAyg0sEwno1RIFCRYFahHJxvzOFfkESGdKWhVUofG9wZby2LL62AfjLB8xsiQTXOUuQ7Uwl8wK46+A5/AuNkpyVi9YBW9atESrK2qybqTkMHN2Df/ox0B0vh33hPKhOl+leFkALjCh+nkUSLIIsgEqnTTMJXkehadPjcby8qwupdA73brfSlvSQKmqK5ma0Oc9hBX+4r2SSKaerzPVgU/vSCgILWDJS68Krv+5C97AD9kWLYZRVwpBCzWaH4MTUHGMwm+JIQslnLN+UvlTCEFoOaiZZ+H0GgqIhPxJBTo7RMWjl1XAtWojdewU+PWK578TyLVgIhVJx/axcVNFQ3RLEgmBDldQvxEf7d3WgYz/zVU0NDCf9RMtb5+YySNbNR//6O5Coa4U31IX6PS/BEzoN3e68dClDcFlvBQav/wbiTcvgjIUQ7NgJ98fvI0+xaqRT0IcGoAfqoDu9OHRoHG3tkx5eT3ReG9bYZwOQbt9YF0C9qyZQSEDDJJVOnOsn1gXVJCGjOLlksBWfPvg0MrW1khoRXboKw8s2YsV/PEyQZ6CrF761oPVy7nIc/faTiLUvA/KWs4S+sgVLfv4wfB/u5CI5YGSz0DJMLRVVOH16HPG41J4WaZXTyUiGrSQte6FCubSLznWhvmEOgdtrOAveMXUEHx8cRUZxwnB7uXIWEQhasW/Dn1ngUoUiiK9Zfu5df7d5/KLWy2cRJphYG8ElJ3+v+TzoufUhCJerSMNGKkkh72e5QfYetNhXHvJyOh4PAizTAiXHoEdBY6083ea3/GD0AD49KhnMy7hzFsjA+ksGmjAl5U0kOaTk96WUOYEWYKZ45rpkKoLQKwKMb90MNoMW1BnvMjd2d09yk9NpAqziaZUlA+QlayslNht/kw9hvO8zDA7xPl7feT8u6z56vpPzc1nP0ZIAevs/O38GdDZ3pAd2LQNDUS06oTfohmKWG32900/3++HinMtmI9XKvZ6CBdNHEBlKYGSMt/FMByhXtOGDX8F38piZn8xw5avvs2P8/gXz+EU7AmThQOdbqPy4Y9rvHfTD5refYzwWVEDBY4w8ScflwQgL5FzOykbmIvE3XhXu2eRBn3R/09cSHyHGoI4zRhSHrBIm3dNQbHDEhrH8Px/B0MrNZNN5JJaznPQu2BNjlwQIWkfNpLBkxw8QOrIF441L4YwOIHBwFzxhEhTlihQShqYVAQrmXtkFkEPGnwmAt2mwlqdkgIoUKMj00YJdJkCpHYW5mjNyNK9uS8VMS05a1nFpcBO/p5UU5r2GPb+ZFDf8zkwxZlNmioNJ2iSrMmWCIYmygkPZVCulzgZgJm8q98OMwTgVROFGF5BdMk40KQ5NqUUlImbXqJv4vSSUojK6UOHMlc+ThOSYOCYNrODCJckfA5iUK4Txw8WFK0Vu6SQAmRpsqbgFkhaXr0ZBp848XwISum7mQ5l68p5yE6y06HnnF5OnVVxNRSMFfp+B9GwARscTKDaLnI6C73AihmmlP65IklXz0LXt71F9bA/Kzn3K+IywhoyaMkzI+JkgCwmaAkBzec1En/UHEGtZgZFF12HBK0/CO3jadHOTXGZ23bkgMlLUKYUgxbeRcMxCbHO9w2PRKZRaZl0YksW4UGYCnnFjOWl7fMQkmujyq82EbY+NEGCsCFDRstYcVYcZu5rTg5zXjxx1rcme/UNwxCNWapCWou8Z+hT3kStL35RllBwT+GMxJJUajJcMMKmjNxyZTIrl5UymTh1J3lDPUUzb7VajcwZZuKJhlNNykaoNpsFz/irkKqsuXFToBV/TrOTuP9NJgCNWPJuxUSgspbsWikdjfNyUaR6PdQpVHFIpjHJ9R0vOg71phAYGC7qOk6jmAldVWGpCuqk+HjsP4ERcBfe/NqlMtII6zF5g5AvnCOt98MDr01jFvN8UTxFkUEHJVsG5WGnMShcEGFEFBXOpAG0KBoYjCOcSFsAK1l1Byk2DdZlwuaHFojDklZXp5KHZXag++gECB3ZZibuUclBYyT3Y8VtUnuyg9VzWdemaenJ8es6U59LdGxuLhApOCd0j6InqyJcu1RSEe8PoGYlY6p6FO1YsldEcp7hQzXSRHxmCHidQKSlM8S3MSchjC1/+CaoO/cFsC8BxAaBKQbnwnJr9v8d8kosZU4wxKazzI8PWtQvuKRxOk8ikfGueVyRURGi3WBad+dmUSzGmst5RdPb34/q6JsuKq1cBz7+YQo5FqWAASGtqoyPmMgopqRRrA0Kw3BYE3/avf4HBdXcitPFupOa2sQqZvo4ipcFz5ihqf/c8gnte5BqxdGLlYkwUyhMIJtpSHgr9sTBqawzMbbDyoKSCcz2Q+WG/mFXBay36+52H8dDVa6x4aW8DFs0HPhkKQ5m7ABpX2SQATsjQs9O6e5YbpDDn1WcQePd5pBoWIV3bhHxZlWkNO5nSGe6Bu/cEbEwjJqmY4kCfbH9MlAtyMCxUJ9Fw4RaTv8rKLHKR+a/7HMYGOK0Fs20bsuTaR4BjWgoVZmeBZ92yGej86TDsldUQtUFotKIhd3Vm1n1ygkxUmtvHpJ2h+P4IZSf2n6deZMtDc/mm92YmSEVeg6Si0HIqhwh1w6VkcM01VsaS9WAflWT3ADoZGN2zsqCwtgfOHevCvjOnsaWxGThyEmilFTesMdBx4Dgc/krolQHo/nKr6yl9hssqXc0ELGdhGGaXzbC7Lt7QNTcBVbN6kO4uKOoVluiKkYcqVVHfKTj1JG67jaK6waokJIt+xjn1j+EVqYMUMRsXtTYfjVNj+OU772HLQw8WQHPed98DLF8BvPbWKEb6R5GXpnV4oMhKn6WMlD1CdVlqxVSm1ih2zoqxJaYclXfTrOYpYxzRYQiypS2fJGYDrQuBrbfAZE+5jjLcJYkf6sRoKI+XL7uzPajj1dd/h49vvhFX1TAXDg5bF5cA94YdSNNFNs3PIhGJobsnhijTI/M0klnVlGKmFpXMqqgFPaoU24PCJJO8pUNpcZWy0Oc2zPiqpJVaGe+j9IwDfQ4sXKWhdV4eicKOnLTePpL0kTP4RURH92UDTBlInYzgkWeexdsPPwybbA/IFcxlTdUGd5nAV1YJ1Pop4PidbAbJMT6uYWxMA7OIOalkAsUKQBpPxo9s/Uk1Ims6mbjL/dZ7+eqzHAEfdZEeB4V5r1xuYqMTOHEC2PkmjnWl8bhWwrbGRfeGzuTx3huH8FfiGfz8T+6AIput0pvKudrhmCi26yWhytX3+y9cCFxya1Cf3NqWhk5nhJliq3yGWfOxvsZhFjgv/Qa9XWPYPqJh6HNvn8kVOpnDc8pBxPpDePqmm1AnmWzVAh1HelUMjArUVxrIaxZITbsyu2VyjU6HBPwEt7hJhxT/uz8A3n0fezvH8N2IhqOlXuuSu3tyM+Z4Fr+OnMPe0zvwDx178c0VV2sVc/0K9nXZ0N6Yg9dlFC0wwfZTC46p76d29cWU1wnlJ63VNajgVFhFq19Dx24DBz7Cma5B/OxMFv8eyV+4NLrsPXoJkozVHc7jb88extP7T+L2hurcNtWlLH05JiraWwwzlmTjTXYb5G6RrTDMtKhMzwxG4UkLGVvS+jJxSwKVMSybSgePkwMGcj2fJPVD5IGXhjT8Nm4gol/GQ1mz2p+V1w9rXNwUnvisD084hL7geA8WugSWkyzbK8vQHPTBT2AeDieJ1KsrolbYbGKqGak5s4JhTAJNk3wyBDreH0MkmsBp3uRoFvrhUBYniTs024cOPhfAqX8JwxynRjM4xY9vWF/SioW0x38HS8nli+u876cal3tlWpCdckFTuXsOf3wkqm2iVUglyMvcO/4FPTJ3xXbYfYo5lgQdWMcYu06oosIuUOYQOZcy0jVtT0J1iNaWSvsv81IQ5LKjQjP2DWbxYUzD8XH9/xGg5ASmqaBhPRLgkDUECwVlrhtra3yOrb7KqlXuYLPHVV0HYbObPRyt0GCadhVFrarKZO6Ix2PQmFhtucx350T6x7OJ+MHhaPL13hQ6krr1UJQUUbxPH50jbHyRAKUbLXPhm7eu9j6+sN1Z71JGlWTaQIx16bETAsn6r8Ivn+KxtjGLysxpfjr/UQOpUO2JBCJklTSDUKlq8Inh/o3X1v7Pxu2LmFOZV91M+KkMtJMn0PdWJ753JIkXNeMLAki1VnvTmpaf/PNzdwaVzF5S3kfIxzMIMUft3Gng3UGHSZl6Ljvl4jrrNRvr3rzVmTAEJg5Lfe31uOBy1pE5R7lQCWTSeVy3FthyM1BH0aB6zPpNzUTRlPw+nhzoxDtDRukPAQGzeJyy3o7td3xrfVAZf4Uy/kMSSsZsm5fRFOERQS3nKnbBhLmHouMw6qiGl+L3aEGO4Fx2A9u2AffcY4nnFPWgQvoNBGpQW1sLm9uDMDVvucvamjC35eibTrLV1i1oqrPhztm6aEkAaRvnqjbH/Ve3sq4bPTX5K7qL7HyHxlhROD1m+0IULHcIQewmsFE643ECfTvbiq1fF7j9dgO3sDp49FFgDQvqdFqKBAPlZT64fH70D6mm/Jve3QXW8dxlLXjAaT2aeWUBNqjYdMuG7HKX/eT0/TyiGR6RxnTDLlsZhvWo1kHMwR8wbyKtm+2zHls1fryvFf0hpSicH3gAWLzYSvjS+g5fGUbiLoxGZ/RyKAZ8AeDmDbi2XsX6KwpQ3qelBt/ZuJZvtekHJDmGhmRfxE8XtbPs0U2LnUYVVrOSkY+FuCZ2llUNu0/W4Jk3qjCxSlLpbN06pTvh9WA86zavCX0GSKbRTeuhNFbgfvVKAqxS0LB+OTbVN8/YBefNM/zc289XW50px6SDenmSn5C7UU7HTJBFC81PQ/Zb8lhQk54284mHhaSlnU4boloFegYo3fIzAPJezawT1yzDFoZM4IoBDNqw5atrUGPy7QyKHmOK6O4TcFYGTPc0zHjV6EPnUMbAkQ97RWVCkAcyOn54Yxf+/JZ4ceZdzP87dkz2kVVSq+KrQk8PC/vE+TpRtjDXX4dgUMWNVwSgR8C+oA7bly0pdKKnWE8WsJLxesLlcFZUFh9OkH9xghqmLeMFcB5W7E9sOYUf3ReBarduGQ7TvUNTu/MGvUCBvawCJ3uc5qPOmnZ+LK5cDsyvwX22EvnjfwUYAFVUViz+8QynAAAAAElFTkSuQmCC' +EMOJI_BASE64_HAPPY_CONTENT = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QjA0RDRDODM3OTk2MTFFQjk3QzQ5NjQxMjRDQTk0MEMiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QjA0RDRDODQ3OTk2MTFFQjk3QzQ5NjQxMjRDQTk0MEMiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpCMDRENEM4MTc5OTYxMUVCOTdDNDk2NDEyNENBOTQwQyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpCMDRENEM4Mjc5OTYxMUVCOTdDNDk2NDEyNENBOTQwQyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PrB9/b8AABLJSURBVHja3Fp5dB3V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' + +EMOJI_BASE64_HAPPY_HEARTS = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NURFMEJBMjk3OTk2MTFFQjk1MTZENDVGRTM1MDlFRjYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NURFMEJBMkE3OTk2MTFFQjk1MTZENDVGRTM1MDlFRjYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo1REUwQkEyNzc5OTYxMUVCOTUxNkQ0NUZFMzUwOUVGNiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo1REUwQkEyODc5OTYxMUVCOTUxNkQ0NUZFMzUwOUVGNiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PjWLaKkAABhuSURBVHja3FoJcF3V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' + +EMOJI_BASE64_HAPPY_THUMBS_UP = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6N0M3M0ExQkM3OTk2MTFFQkFDREU4QkE2OUQ2Njk5ODUiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6N0M3M0ExQkQ3OTk2MTFFQkFDREU4QkE2OUQ2Njk5ODUiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3QzczQTFCQTc5OTYxMUVCQUNERThCQTY5RDY2OTk4NSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3QzczQTFCQjc5OTYxMUVCQUNERThCQTY5RDY2OTk4NSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PrSTufUAABP3SURBVHja3Fp5cF31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' + +EMOJI_BASE64_HAPPY_WINK = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OTFDMjA3MTk3OTk2MTFFQjg3QzdFQTc4QzI5RjM3OTMiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OTFDMjA3MUE3OTk2MTFFQjg3QzdFQTc4QzI5RjM3OTMiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo5MUMyMDcxNzc5OTYxMUVCODdDN0VBNzhDMjlGMzc5MyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo5MUMyMDcxODc5OTYxMUVCODdDN0VBNzhDMjlGMzc5MyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PhbG1A0AABOISURBVHja3FoJcFz1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' + +EMOJI_BASE64_HAPPY_LIST = [EMOJI_BASE64_HAPPY_STARE, EMOJI_BASE64_HAPPY_LAUGH, EMOJI_BASE64_HAPPY_JOY, EMOJI_BASE64_HAPPY_IDEA, EMOJI_BASE64_HAPPY_GASP, + EMOJI_BASE64_HAPPY_RELIEF, EMOJI_BASE64_HAPPY_WINK, EMOJI_BASE64_HAPPY_THUMBS_UP, EMOJI_BASE64_HAPPY_HEARTS, + EMOJI_BASE64_HAPPY_CONTENT, EMOJI_BASE64_HAPPY_BIG_SMILE] + +EMOJI_BASE64_SAD_LIST = [EMOJI_BASE64_YIKES, EMOJI_BASE64_WEARY, EMOJI_BASE64_DREAMING, EMOJI_BASE64_THINK, EMOJI_BASE64_SKEPTICAL, EMOJI_BASE64_FACEPALM, + EMOJI_BASE64_FRUSTRATED, EMOJI_BASE64_PONDER, EMOJI_BASE64_NOTUNDERSTANDING] + +EMOJI_BASE64_LIST = EMOJI_BASE64_HAPPY_LIST + EMOJI_BASE64_SAD_LIST + + +def _random_error_emoji(): + c = random.choice(EMOJI_BASE64_SAD_LIST) + return c + + +def _random_happy_emoji(): + c = random.choice(EMOJI_BASE64_HAPPY_LIST) + return c + + + +''' +M"""""`'"""`YM +M mm. mm. M +M MMM MMM M .d8888b. 88d888b. .d8888b. +M MMM MMM M 88' `88 88' `88 88ooood8 +M MMM MMM M 88. .88 88 88. ... +M MMM MMM M `88888P' dP `88888P' +MMMMMMMMMMMMMM + +M#"""""""'M .d8888P dP dP +## mmmm. `M 88' 88 88 +#' .M .d8888b. .d8888b. .d8888b. 88baaa. 88aaa88 +M# MMMb.'YM 88' `88 Y8ooooo. 88ooood8 88` `88 88 +M# MMMM' M 88. .88 88 88. ... 8b. .d8 88 +M# .;M `88888P8 `88888P' `88888P' `Y888P' dP +M#########M + +M""M +M M +M M 88d8b.d8b. .d8888b. .d8888b. .d8888b. .d8888b. +M M 88'`88'`88 88' `88 88' `88 88ooood8 Y8ooooo. +M M 88 88 88 88. .88 88. .88 88. ... 88 +M M dP dP dP `88888P8 `8888P88 `88888P' `88888P' +MMMM .88 + d8888P +''' + + + +''' + +90 x 90 pixel images + +These images are intentionally a little large so that you can use the image_subsample to reduce their size. + +This offers more flexibility for use in a main window (larger) or perhaps a titlebar (smaller) + +''' + +HEART_FLAT_BASE64 = b'iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAYAAAA4qEECAAAPjklEQVR4nO2ce3BdxX3Hv7/dPefch96WLMuYAOZRsKc8qmYMpImSJiSmQ2sgtVNKQ0uahnYmwDA4pEAmskjixAkd8qCh0E6ZaaaPWCU2DJ10kja2QhtosIBkYhuM8VN+yHrrXt3HObu/X/+4upbsWG/JstH9zOyM7tU5+/vt9/z2t3vO7rlAiRIlSpQoUaJEiRIlSpQoUaJEiRIlFggC0Hz7MAvMehtmrUIBiAA5+XnFWh9LEUfoXwFS74NSV0FcHEQJCBRA3RA+AfBBQF5C3h7EK60hAW6sOqdkv6nJoM8PULv4N2BxLRT9JgTVIFU+cpL0QcmbEHkdVl5DbzREu1rD6difiBkLXYzgokPSeEctYrjBafUZUuompVQAZwF2gIz2mQClAFKA0mDhvWDeqlj+DdnB3dT+YqZQf7MitPD4PowcIzf+QTko3gjj/RGTulUR1YPdKPtn8EFrMEtegf4LLM/CDr1EL285MbqNMxV8RkKPdkBuuG2x094noIO/1kYvlewQXJQTyaWBVA8w1A/YCHCuYNULAD8OxMuBilooP046SIKVBsRuYZv/dofpfuWStrbc6RdztP3i99J4SwKJxPsdeQ9rbZpgQ9gwCxkaEGT6gaEBIMoDLhqpxQ+AWBJIVoPKFkEHMaJYGSIbHVHiHtcq/+/UtqXj9LZOh2kLXYwiAcjesO6jbMyXfC94b5jqZaS7Bd2HFXo6iHjcYBypL1YuUrtMqGaZ+OU1Gp4PttGTYVa+GW///ju/1nNGfc6tuvUqz4+vV8r/lEQZRKlei57DCl0HFUX5SbYHQNUSkfqLGRWLVVBeQ1EU7hEbfsEPa7ZS+zPRZHrXWExL6JMiN60ty0byYNyLbbBRHlH3kYiO7jYq3UcnqyfCKYFQ/PMUywRIwX8hAtcvZ6pfbmM1S/1cmH+bOXwo+fIPtp4+0BIgQ6s+frv2vScC7b0n19MR4vh+o7oOqJGD1Jntn+LDsI/DqY3LagQNV1iqvcALggTCMPt4Pp/bVNH+Yvd0xZ6y0AIoAjj9/tsayKqNiVjZn2X6j1t07Fa665A6pXEylZ5WvCgoiB4k4JZeEXlLL/ciqBBReF/y51ueFqzVQCsTIKlVtz+ojPmaETa2Y3ekj+7xYKNC3pWp2sew/ZGLzrXLWJZd6RI1F3hDuaGtiuj+xP+2HipqMKWqp3JwMU/J7/xxddrm/qkslrwlc+JARId+5al03/Qb+GteKYgwCICru9hh+TUEE5B14ecrX9n6DQAYXHXrozEv+HI+n2G9/w1R3Ye1AKCChzO0P3zRmSHxcvBFV0eJ+ku8VJT5Scj6rtpXWo8IhAg0aUNTE7qpyRzAxaYqN/BMhZ/4ZPbEwUjtb/cozBWiWKaVvsZ2jQrRxdVL2F3629BeTEXi/gRATaDMt6Mw4/TbO0gNdCooBfDps4qZujB80Twf7pLrbHzJpWYwzD6fyyTvXFJ9aR5tLW6yA6Sa+JAC25qaDLW12apc/xfjxv9kpu+oo32veRTmIESzLDJQSD0MKAXVd1ypvTsoclbA+I4wNuVtyLR3h1IDnUqUApgxqyIDBZGJgCiE2veGyXQfdgntrwnimQ3U1mK3o1lPtqpJRbSsXavR2sr9713zu0J4wbM2ht0/VTqbguC0wW4uIAKJIFpymeDSRmIWqH2viuncT5iNVDGxAyAIXFAGrPwAh8aP2OlP1LU/9/y2pibzobY2O3ENEyCQQh++bHVZT7X3w8CL3chvvcK657DC2RD5JAQQYBsuY4iQObb3LIk8yj4ErvoC1lfeqPJRvj0nvHppe2MvsEEmytcTpo6dK9Z5BHBXhb6bQde7rkOg3g4SEASCYlac+yIQEeijbyt9bC8JAJGzbB8A9R+lqOugiKJrjeBuQgvvXLHOm0jHcYVuBtTKXa3RntWrAyb5w6TyFB95y0GEzq7I506BCMnRtyRGSgvJx/dfs6Zq5a7WSNA8rpbj/vP3Gxs1AVJ+TNY40Vfne4+A8mk1342d76JyaYq6O+CgroxJ+DECpL3xxXEHxnGFbswuJwBgoZsr/VgFnzjgyFma74bOdwE7ct2HXbkXq2QlqwEgNqzVWJix/tEMKNrVGr6zvLGSCctdbgiSSw0bO5uD4LlGYQYiuRQklwazurx/xUdrqna19o53ez5mRG9Yu5YAwEtUX2tJXZxPdQE2pMJsdWHmZxluOwOAy1OU6gIrujBF7moA2N60fUw9x4zo9n37FAAXCV8OoMEN9cEMp40SAJyjKDMIW7a4jsRdBADl6fSY6WPMK1DMORpSpZXyJMwLFnQkn1ogAs5nxNc6TqCG0ZqdiTEjuoiFqylTGs7lnUzi+AUEiQudp0jnSSomOnhM4fwwVZhxOEoaECJnCxdyQQ+ERYYHRGYhAZjFB0Y0OxMTRqgjx1YYABW6TUnnkwgIkTCcsJvo2DGFDv3ygpyMXOQcnFJUWP2cNT/PYwQCCCutLDtAkAVGaXYGxononQAAFvQNuQie9jQDMhzTJQA446msDZkc9wHArmHNzsSYQu8qVkauK3Rh3jNBwCChUkgXIBIxAVnmIUN8AgDW1tWN+VB+TKHrdhVOsk72Efg4x8ouYm1Eu2jBz6UJAGsjCBJg5zpz4vYDANoWTz11bEcbA0As436VS7gOCsouYq1FuagU0wAcGSBWAWF3pKHS/bLwbeuYET3mDUsLwDsaG70VR1/tcWyPiB8HK09mMsl/NxVrfDgdQJw9dEF7e2bzihX+eOuH407vYtksAYCQ7Bm0FrFYuVG5lNC7YyPjtGGQhLFyPeRCQOTNyZwz7mPSlbtWOgDgED/KR/kOLqsDa2/4xmVhFgBw2giX18Ha6ECE8McAgGGtpiU00MrbmprM9Yd//hIxvymxcljtL/j0Yb0YOCiDYrf7ffvfeHVHY6O3Dq3TF5oAKT6Rssz/PeBCzpUt0g60YMV2IMknF6lBmw8t2x+Op9+khQaAxvZbnAAkRv0Azh0Iy+oQah+Cwp6ohVQEgDW+hGV1EGf3O6u3CkCN7e0T3oJPKDShhdsbG80H9r+6hyFbc0q5TOViKhpeSMUBSFc2qCESFpLvNx3dcbi9sdFMZh/e5DbQAITmZvrJ0y9cCE9eCkgtqzq6E8bmF9TsIzIxGVi6EiG7/fEwuPH6E6u7gBaZzLawSW0JI0C2b9+uPnz89YMQ/IsFKFXZcDJ9zHekzXUppo50VQMiERLQszec+L/O7U3b1WT33k0lImkzoMqWXFtjNG9TpFZU9RxEMttHPMWKzicEhbYNJRfJQM2FxMyvDRn68K0HfzFII9diQia9yRGA7ATk946/0UUO6y2zDFQu4UibeY+4uSwAEGkfg+X1bB1bcfqB2w7+ov+0QyZkKkKjBeBmQN10/Jf/yeB/hPZ1T0WDFLoXzfusYLaLA4GJ0FPZIKQ9zXDf/djx13/aXNiIPmmRgWn2+GZANTZcUaPZ/5FSdF0ifUKqU53vsqd6heWqvoolkilbTMzuZT+fvfkjfftSU93tX6htBvx46VXX5RxtU5Cy6sFjqjzbTxYEBZna5T6HKKzUFdowmKiW/vKlAkGvi/iDa/p2j/1kfwKmlDpG0wyom47ufh3CdzNI9yTreDAoF4LAnqdpRADY4UgeDCqkL1nLThih4rvW9O3eKTMIzFl5z3BL3RUPBcpsslHO1qaOmViUxfm4Wi4gaAgyfhI95fVWm5gJObrvtq63v1Ns63TrnnZEAyPv/L3RtefxvA2/bEzM9CbrXGh8AOfbZptCJGdNgJ5kndM6ZiIXfeHWrrefHN3WGWg1YwiAbAa0WXTZY74yj7go66qHOnU8yp0nkT0sshdHb3KxMyau8xI9dnvPOxtoZCo9o0bMKKKHEQFoHeC6/MqvZFz0d2IC3Z2olyETk/MhsgmCIZOQrkS9wAQqI+ETHdW0cfjFjVmJlFn/dYPmFSv8K4/mNgZK3e/Y6pr0CZTbDE15PnSWIAApL8l9ycVKKW0j4a8/95F9X2xthZtpXj7dzqwx2rF/rrrkkRipZifsV2S7uSKfUudiEhkMKnkgsUhpIJ8HN9/Zd2ATUHjzZ7ZEBmYndZyk2NWaAXVn//6NGRs+zCKD/Yla1RtUsqPCPc18P4gCAEtK+mJVrj++SInY/qzjz93Zd2BTM6BmW+RhbeYEagZ0C2C/V3HRHQT5ulFmWSzfbyvygzrGltwcGh/XMQB5ZWQgVsV5v0LnOTpIRA/eNXDouacB7x7AYg463py29Vu4LLgfe/PPVl7wQe1oo6e9G8hmpTrXK0kXqtERNtcMv06PlI5xf7yaoGMUsW2zoEc+lTr0s6Kvc2l/TtkM+OuA8OnY8vcEOnxUSP2FgaOK/ICtiDJGg6f+4GBKFG6nHRQGvIRNBVXGglhgn4rY+8o9mUPHij7OrRdngW2A+VChS+Ifkg33KqgNvjI1XpiKqqNBU0wls+lQsacYABntSb+psJFf5kXiOhm25c/Tx5863be55KylyebhgbcF4L9PNtxETA8EWt/sbI6rbRoVNnsylczUqWIdBGDAJLjfS0LrmArZviDE3/z0UOe20f7M0NykOKvjkQDUCqh1gHs2UbckL+azQnjUCJB0GbsoShtPHGYyUAoADSAijR5TZoe8hLEQ1iJfzmp68v708a7NgF43Mvk5K8zLClQzYFqGu+tTsfp1EDzuK32h4ly+1qaCpIsw4fr9GCgAaR1Ir0mGomJBTtw7RPK5v8qe2HK67bPJvC31NQOq2G2f8epXWiWPBaRuD8W6apuhGpdRhMn36+IvJ3WbJA/oBHzSKmL5V4J67J7w2Jun2zzbzPeaatG+fAs1FX5g7ghFNgWgSsWhW8xpnWA7oTIKQE4ZdKoyy8o3eeCIEnwekTz/WXSlZdSvNc1hW8ZlvoUGcOqt+9/6NVdFov/GA252YKnlDFW77BnPK66G9Og4elVcNBRF4P8QwoMPhD1vnV73fHJOCA2cKsi9QHCpqXlIgIcVVDwpedS7NAxGlsgIQASFTp1ElgJY8BCBvtRve55oGZkTnzOPV84Zoc/EE6ZmlUCeNsA1WhwWc0YSUnhNOkNGulSSLClYwg6B/sv1UXf7fPs8Fues0MVQ/EY9ktRT/V2I3KEBr4YzIiD0qTgxEArhe7Sk/94HO5A9Z8L3DMzq07vZpChYuhPZ9bbvT6249aFIZy8lqI/iFAofc2LvW2/7Pz3Ygfzoc0pMk88AHgBsRPmqr1LFz75K5f+zCYnfAgrz4vn17l3G5sIN34Tfnaucszn6TDQDaiVAO4df9Zuvm4+FQvF5UYkSJUqUKFGiRIkSJd7l/D/zcbmEg5v3VgAAAABJRU5ErkJggg==' + + +HEART_3D_BASE64 = b'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' + +RED_X_BASE64 = b'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' + +GREEN_CHECK_BASE64 = b'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' + + +# ==========================================================================# + +# MP""""""`MM dP dP .8888b +# M mmmmm..M 88 88 88 " +# M. `YM d8888P .d8888b. 88d888b. d8888P .d8888b. 88aaa +# MMMMMMM. M 88 88' `88 88' `88 88 88' `88 88 +# M. .MMM' M 88 88. .88 88 88 88. .88 88 +# Mb. .dM dP `88888P8 dP dP `88888P' dP +# MMMMMMMMMMM +# +# dP dP oo dP dP +# dP dP dP dP +# 88d8b.d8b. .d8888b. dP 88d888b. +# 88'`88'`88 88' `88 88 88' `88 +# 88 88 88 88. .88 88 88 88 +# dP dP dP `88888P8 dP dP dP +# +# +# MM""""""""`M dP +# MM mmmmmmmM 88 +# M` MMMM 88d888b. d8888P 88d888b. dP dP +# MM MMMMMMMM 88' `88 88 88' `88 88 88 +# MM MMMMMMMM 88 88 88 88 88. .88 +# MM .M dP dP dP dP `8888P88 +# MMMMMMMMMMMM .88 +# d8888P +# MM"""""""`YM oo dP +# MM mmmmm M 88 +# M' .M .d8888b. dP 88d888b. d8888P .d8888b. +# MM MMMMMMMM 88' `88 88 88' `88 88 Y8ooooo. +# MM MMMMMMMM 88. .88 88 88 88 88 88 +# MM MMMMMMMM `88888P' dP dP dP dP `88888P' +# MMMMMMMMMMMM + +# ==========================================================================# + + +# M"""""`'"""`YM oo +# M mm. mm. M +# M MMM MMM M .d8888b. dP 88d888b. +# M MMM MMM M 88' `88 88 88' `88 +# M MMM MMM M 88. .88 88 88 88 +# M MMM MMM M `88888P8 dP dP dP +# MMMMMMMMMMMMMM +# +# MM"""""""`YM dP MM'"""""`MM oo dP M""MMMMM""MM dP +# MM mmmmm M 88 M' .mmm. `M 88 M MMMMM MM 88 +# M' .M .d8888b. .d8888b. d8888P M MMMMMMMM dP d8888P M `M dP dP 88d888b. +# MM MMMMMMMM 88' `88 Y8ooooo. 88 M MMM `M 88 88 M MMMMM MM 88 88 88' `88 +# MM MMMMMMMM 88. .88 88 88 M. `MMM' .M 88 88 M MMMMM MM 88. .88 88. .88 +# MM MMMMMMMM `88888P' `88888P' dP MM. .MM dP dP M MMMMM MM `88888P' 88Y8888' +# MMMMMMMMMMMM MMMMMMMMMMM MMMMMMMMMMMM +# +# M""M +# M M +# M M .d8888b. .d8888b. dP dP .d8888b. +# M M Y8ooooo. Y8ooooo. 88 88 88ooood8 +# M M 88 88 88. .88 88. ... +# M M `88888P' `88888P' `88888P' `88888P' +# MMMM + + +def _github_issue_post_make_markdown(issue_type, operating_system, os_ver, psg_port, psg_ver, gui_ver, python_ver, + python_exp, prog_exp, used_gui, gui_notes, + cb_docs, cb_demos, cb_demo_port, cb_readme_other, cb_command_line, cb_issues, cb_github, + detailed_desc, code, project_details): + body = \ +""" +## Type of Issue (Enhancement, Error, Bug, Question) + +{} + +---------------------------------------- + +## Environment + +#### Operating System + +{} version {} + +#### PySimpleGUI Port (tkinter, Qt, Wx, Web) + +{} + +---------------------------------------- + +## Versions + + +#### Python version (`sg.sys.version`) + +{} + +#### PySimpleGUI Version (`sg.__version__`) + +{} + +#### GUI Version (tkinter (`sg.tclversion_detailed`), PySide2, WxPython, Remi) + +{} +""".format(issue_type, operating_system,os_ver, psg_port,python_ver, psg_ver, gui_ver, project_details) + + body2 = \ +""" + + +--------------------- + +## Your Experience In Months or Years (optional) + +{} Years Python programming experience +{} Years Programming experience overall +{} Have used another Python GUI Framework? (tkinter, Qt, etc) (yes/no is fine) +{} + +--------------------- + +## Troubleshooting + +These items may solve your problem. Please check those you've done by changing - [ ] to - [X] + +- [{}] Searched main docs for your problem www.PySimpleGUI.org +- [{}] Looked for Demo Programs that are similar to your goal Demos.PySimpleGUI.org +- [{}] If not tkinter - looked for Demo Programs for specific port +- [{}] For non tkinter - Looked at readme for your specific port if not PySimpleGUI (Qt, WX, Remi) +- [{}] Run your program outside of your debugger (from a command line) +- [{}] Searched through Issues (open and closed) to see if already reported Issues.PySimpleGUI.org +- [{}] Tried using the PySimpleGUI.py file on GitHub. Your problem may have already been fixed but not released + +## Detailed Description + +{} + +#### Code To Duplicate + + +```python +{} + + +``` + +#### Screenshot, Sketch, or Drawing + + +------------------------- + +{} + + + """.format(python_exp, prog_exp, used_gui, gui_notes, + cb_docs, cb_demos, cb_demo_port, cb_readme_other, cb_command_line, cb_issues, cb_github, + detailed_desc, code if len(code) > 10 else '# Paste your code here', + '## Watcha Makin?\n' + str(project_details) if project_details else '') + + return body + body2 + + +def _github_issue_post_make_github_link(title, body): + pysimplegui_url = "https://github.com/PySimpleGUI/PySimpleGUI" + pysimplegui_issues = "{}/issues/new?".format(pysimplegui_url) + + # Fix body cuz urllib can't do it smfh + getVars = {'title': str(title), 'body': str(body)} + return (pysimplegui_issues + urllib.parse.urlencode(getVars).replace("%5Cn", "%0D")) + + +######################################################################################################### + +def _github_issue_post_validate(values, checklist, issue_types): + issue_type = None + for itype in issue_types: + if values[itype]: + issue_type = itype + break + if issue_type is None: + popup_error('Must choose issue type') + return False + if values['-OS WIN-']: + operating_system = 'Windows' + os_ver = values['-OS WIN VER-'] + elif values['-OS LINUX-']: + operating_system = 'Linux' + os_ver = values['-OS LINUX VER-'] + elif values['-OS MAC-']: + operating_system = 'Mac' + os_ver = values['-OS MAC VER-'] + elif values['-OS OTHER-']: + operating_system = 'Other' + os_ver = values['-OS OTHER VER-'] + else: + popup_error('Must choose Operating System') + return False + + if os_ver == '': + popup_error('Must fill in an OS Version') + return False + + checkboxes = any([values[('-CB-', i)] for i in range(len(checklist))]) + if not checkboxes: + popup_error('None of the checkboxes were checked.... you need to have tried something...anything...') + return False + + title = values['-TITLE-'].strip() + if len(title) == 0: + popup_error("Title can't be blank") + return False + elif title[1:len(title) - 1] == issue_type: + popup_error("Title can't be blank (only the type of issue isn't enough)") + return False + + if len(values['-ML DETAILS-']) < 4: + popup_error("A little more details would be awesome") + return False + + return True + + +def _github_issue_help(): + heading_font = '_ 12 bold underline' + text_font = '_ 10' + + def HelpText(text): + return Text(text, size=(80, None), font=text_font) + + help_why = \ +""" Let's start with a review of the Goals of the PySimpleGUI project +1. To have fun +2. For you to be successful + +This form is as important as the documentation and the demo programs to meeting those goals. + +The GitHub Issue GUI is here to help you more easily log issues on the PySimpleGUI GitHub Repo. """ + + help_goals = \ +""" The goals of using GitHub Issues for PySimpleGUI question, problems and suggestions are: +* Give you direct access to engineers with the most knowledge of PySimpleGUI +* Answer your questions in the most precise and correct way possible +* Provide the highest quality solutions possible +* Give you a checklist of things to try that may solve the problem +* A single, searchable database of known problems and their workarounds +* Provide a place for the PySimpleGUI project to directly provide support to users +* A list of requested enhancements +* An easy to use interface to post code and images +* A way to track the status and have converstaions about issues +* Enable multiple people to help users """ + + help_explain = \ +""" GitHub does not provide a "form" that normal bug-tracking-databases provide. As a result, a form was created specifically for the PySimpleGUI project. + +The most obvious questions about this form are +* Why is there a form? Other projects don't have one? +* My question is an easy one, why does it still need a form? + +The answer is: +I want you to get your question answered with the highest quality answer possible as quickly as possible. + +The longer answer - For quite a while there was no form. It resulted the same back and forth, multiple questions comversation. "What version are you running?" "What OS are you using?" These waste precious time. + +If asking nicely helps... PLEASE ... please fill out the form. + +I can assure you that this form is not here to punish you. It doesn't exist to make you angry and frustrated. It's not here for any purpose than to try and get you support and make PySimpleGUI better. """ + + help_experience = \ +""" Not many Bug-tracking systems ask about you as a user. Your experience in programming, programming in Python and programming a GUI are asked to provide you with the best possible answer. Here's why it's helpful. You're a human being, with a past, and a some amount of experience. Being able to taylor the reply to your issue in a way that fits you and your experience will result in a reply that's efficient and clear. It's not something normally done but perhaps it should be. It's meant to provide you with a personal response. + +If you've been programming for a month, the person answering your question can answer your question in a way that's understandable to you. Similarly, if you've been programming for 20 years and have used multiple Python GUI frameworks, then you are unlikely to need as much explanation. You'll also have a richer GUI vocabularly. It's meant to try and give you a peronally crafted response that's on your wavelength. Fun & success... Remember those are our shared goals""" + + help_steps = \ +""" The steps to log an issue are: +1. Fill in the form +2. Click Post Issue """ + + # layout = [ [T('Goals', font=heading_font, pad=(0,0))], + # [HelpText(help_goals)], + # [T('Why?', font=heading_font, pad=(0,0))], + # [HelpText(help_why)], + # [T('FAQ', font=heading_font, pad=(0,0))], + # [HelpText(help_explain)], + # [T('Experience (optional)', font=heading_font)], + # [HelpText(help_experience)], + # [T('Steps', font=heading_font, pad=(0,0))], + # [HelpText(help_steps)], + # [B('Close')]] + + t_goals = Tab('Goals', [[HelpText(help_goals)]]) + t_why = Tab('Why', [[HelpText(help_why)]]) + t_faq = Tab('FAQ', [[HelpText(help_explain)]]) + t_exp = Tab('Experience', [[HelpText(help_experience)]]) + t_steps = Tab('Steps', [[HelpText(help_steps)]]) + + layout = [[TabGroup([[t_goals, t_why, t_faq, t_exp, t_steps]])], + [B('Close')]] + + Window('GitHub Issue GUI Help', layout, keep_on_top=True).read(close=True) + + return + + +def main_open_github_issue(): + font_frame = '_ 14' + issue_types = ('Question', 'Bug', 'Enhancement', 'Error Message') + frame_type = [[Radio(t, 1, size=(10, 1), enable_events=True, k=t)] for t in issue_types] + + v_size = (15, 1) + frame_versions = [[T('Python', size=v_size), In(sys.version, size=(20, 1), k='-VER PYTHON-')], + [T('PySimpleGUI', size=v_size), In(ver, size=(20, 1), k='-VER PSG-')], + [T('tkinter', size=v_size), In(tclversion_detailed, size=(20, 1), k='-VER TK-')]] + + frame_platforms = [[T('OS '), T('Details')], + [Radio('Windows', 2, running_windows(), size=(8, 1), k='-OS WIN-'), In(size=(8, 1), k='-OS WIN VER-')], + [Radio('Linux', 2, running_linux(), size=(8, 1), k='-OS LINUX-'), In(size=(8, 1), k='-OS LINUX VER-')], + [Radio('Mac', 2, running_mac(), size=(8, 1), k='-OS MAC-'), In(size=(8, 1), k='-OS MAC VER-')], + [Radio('Other', 2, size=(8, 1), k='-OS OTHER-'), In(size=(8, 1), k='-OS OTHER VER-')]] + + col_experience = [[T('Optional Experience Info')], + [In(size=(4, 1), k='-EXP PROG-'), T('Years Programming')], + [In(size=(4, 1), k='-EXP PYTHON-'), T('Years Writing Python')], + [CB('Previously programmed a GUI', k='-CB PRIOR GUI-')], + [T('Share more if you want....')], + [In(size=(25, 1), k='-EXP NOTES-', expand_x=True)]] + + checklist = (('Searched main docs for your problem', 'www.PySimpleGUI.org'), + ('Looked for Demo Programs that are similar to your goal ', 'http://Demos.PySimpleGUI.org'), + ('If not tkinter - looked for Demo Programs for specific port', ''), + ('For non tkinter - Looked at readme for your specific port if not PySimpleGUI (Qt, WX, Remi)', ''), + ('Run your program outside of your debugger (from a command line)', ''), + ('Searched through Issues (open and closed) to see if already reported', 'http://Issues.PySimpleGUI.org'), + ('Tried using the PySimpleGUI.py file on GitHub. Your problem may have already been fixed vut not released.', '')) + + checklist_col1 = Col([[CB(c, k=('-CB-', i)), T(t, k='-T{}-'.format(i), enable_events=True)] for i, (c, t) in enumerate(checklist[:4])], k='-C FRAME CBs1-') + checklist_col2 = Col([[CB(c, k=('-CB-', i + 4)), T(t, k='-T{}-'.format(i + 4), enable_events=True)] for i, (c, t) in enumerate(checklist[4:])], pad=(0, 0), + k='-C FRAME CBs2-') + checklist_tabgropup = TabGroup( + [[Tab('Checklist 1 *', [[checklist_col1]], expand_x=True, expand_y=True), Tab('Checklist 2 *', [[checklist_col2]]), Tab('Experience', col_experience, k='-Tab Exp-', pad=(0, 0))]], expand_x=True, expand_y=True) + + frame_details = [[Multiline(size=(65, 10), font='Courier 10', k='-ML DETAILS-', expand_x=True, expand_y=True)]] + tooltip_project_details = 'If you care to share a little about your project,\nthen by all means tell us what you are making!' + frame_project_details = [[Multiline(size=(65, 10), font='Courier 10', k='-ML PROJECT DETAILS-', expand_x=True, expand_y=True, tooltip=tooltip_project_details)]] + frame_code = [[Multiline(size=(80, 10), font='Courier 8', k='-ML CODE-', expand_x=True, expand_y=True)]] + frame_markdown = [[Multiline(size=(80, 10), font='Courier 8', k='-ML MARKDOWN-', expand_x=True, expand_y=True)]] + + top_layout = [[Col([[Text('Open A GitHub Issue (* = Required Info)', font='_ 15')]], expand_x=True), + Col([[B('Help')]]) + ], + [Frame('Title *', [[Input(k='-TITLE-', size=(50, 1), font='_ 14', focus=True)]], font=font_frame)], + # Image(data=EMOJI_BASE64_WEARY)], + vtop([ + Frame('Platform *', frame_platforms, font=font_frame), + Frame('Type of Issue *', frame_type, font=font_frame), + Frame('Versions *', frame_versions, font=font_frame), + ])] + + middle_layout = [ + [Frame('Checklist * (note that you can click the links)', [[checklist_tabgropup]], font=font_frame, k='-CLIST FRAME-', expand_x=True, expand_y=True)], + [HorizontalSeparator()], + [T(SYMBOL_DOWN + ' If you need more room for details grab the dot and drag to expand', background_color='red', text_color='white')]] + + bottom_layout = [[TabGroup([[Tab('Details *', frame_details, pad=(0, 0)), + Tab('SHORT Code to duplicate Program *', frame_code, pad=(0, 0)), + Tab('Your Project Details (optional)', frame_project_details, pad=(0, 0)), + Tab('Markdown Output', frame_markdown, pad=(0, 0)), + ]], k='-TABGROUP-', expand_x=True, expand_y=True), + ]] + + + layout_pane = Pane([Col(middle_layout), Col(bottom_layout)], key='-PANE-', expand_x=True, expand_y=True) + + layout = [ + [pin(B(SYMBOL_DOWN, pad=(0, 0), k='-HIDE CLIST-', tooltip='Hide/show upper sections of window')), pin(Col(top_layout, k='-TOP COL-'))], + [layout_pane], + [Col([[B('Post Issue'), B('Create Markdown Only'), B('Quit')]])]] + + window = Window('Open A GitHub Issue', layout, finalize=True, resizable=True, enable_close_attempted_event=True, margins=(0, 0)) + + # for i in range(len(checklist)): + [window['-T{}-'.format(i)].set_cursor('hand1') for i in range(len(checklist))] + # window['-TABGROUP-'].expand(True, True, True) + # window['-ML CODE-'].expand(True, True, True) + # window['-ML DETAILS-'].expand(True, True, True) + # window['-ML MARKDOWN-'].expand(True, True, True) + # window['-PANE-'].expand(True, True, True) + window.bring_to_front() + while True: # Event Loop + event, values = window.read() + # print(event, values) + if event in (WINDOW_CLOSE_ATTEMPTED_EVENT, 'Quit'): + if popup_yes_no('Do you really want to exit?', + 'If you have not clicked Post Issue button and then clicked "Submit New Issue" button ' + 'then your issue will not have been submitted to GitHub.\n' + 'If you are having trouble with PySimpleGUI opening your browser, consider generating ' + 'the markdown, copying it to a text file, and then using it later to manually paste into a new issue ' + '\n' + 'Are you sure you want to quit?', + image=EMOJI_BASE64_PONDER, + ) == 'Yes': + break + if event == WIN_CLOSED: + break + if event in ['-T{}-'.format(i) for i in range(len(checklist))]: + webbrowser.open_new_tab(window[event].get()) + if event in issue_types: + title = str(values['-TITLE-']) + if len(title) != 0: + if title[0] == '[' and title.find(']'): + title = title[title.find(']') + 1:] + title = title.strip() + window['-TITLE-'].update('[{}] {}'.format(event, title)) + if event == '-HIDE CLIST-': + window['-TOP COL-'].update(visible=not window['-TOP COL-'].visible) + window['-HIDE CLIST-'].update(text=SYMBOL_UP if window['-HIDE CLIST-'].get_text() == SYMBOL_DOWN else SYMBOL_DOWN) + if event == 'Help': + _github_issue_help() + elif event in ('Post Issue', 'Create Markdown Only'): + issue_type = None + for itype in issue_types: + if values[itype]: + issue_type = itype + break + if issue_type is None: + popup_error('Must choose issue type') + continue + if values['-OS WIN-']: + operating_system = 'Windows' + os_ver = values['-OS WIN VER-'] + elif values['-OS LINUX-']: + operating_system = 'Linux' + os_ver = values['-OS LINUX VER-'] + elif values['-OS MAC-']: + operating_system = 'Mac' + os_ver = values['-OS MAC VER-'] + elif values['-OS OTHER-']: + operating_system = 'Other' + os_ver = values['-OS OTHER VER-'] + else: + popup_error('Must choose Operating System') + continue + checkboxes = ['X' if values[('-CB-', i)] else ' ' for i in range(len(checklist))] + + if not _github_issue_post_validate(values, checklist, issue_types): + continue + + cb_dict = {'cb_docs': checkboxes[0], 'cb_demos': checkboxes[1], 'cb_demo_port': checkboxes[2], 'cb_readme_other': checkboxes[3], + 'cb_command_line': checkboxes[4], 'cb_issues': checkboxes[5], 'cb_github': checkboxes[6], 'detailed_desc': values['-ML DETAILS-'], + 'code': values['-ML CODE-'], + 'project_details': values['-ML PROJECT DETAILS-'].rstrip()} + + markdown = _github_issue_post_make_markdown(issue_type, operating_system, os_ver, 'tkinter', values['-VER PSG-'], values['-VER TK-'], + values['-VER PYTHON-'], + values['-EXP PROG-'], values['-EXP PYTHON-'], 'Yes' if values['-CB PRIOR GUI-'] else 'No', + values['-EXP NOTES-'], + **cb_dict) + window['-ML MARKDOWN-'].update(markdown) + link = _github_issue_post_make_github_link(values['-TITLE-'], window['-ML MARKDOWN-'].get()) + if event == 'Post Issue': + webbrowser.open_new_tab(link) + else: + popup('Your markdown code is in the Markdown tab', keep_on_top=True) + + window.close() + + +''' +MM'"""""`MM oo dP M""MMMMM""MM dP +M' .mmm. `M 88 M MMMMM MM 88 +M MMMMMMMM dP d8888P M `M dP dP 88d888b. +M MMM `M 88 88 M MMMMM MM 88 88 88' `88 +M. `MMM' .M 88 88 M MMMMM MM 88. .88 88. .88 +MM. .MM dP dP M MMMMM MM `88888P' 88Y8888' +MMMMMMMMMMM MMMMMMMMMMMM + +M""MMMMM""M dP +M MMMMM M 88 +M MMMMM M 88d888b. .d8888b. 88d888b. .d8888b. .d888b88 .d8888b. +M MMMMM M 88' `88 88' `88 88' `88 88' `88 88' `88 88ooood8 +M `MMM' M 88. .88 88. .88 88 88. .88 88. .88 88. ... +Mb dM 88Y888P' `8888P88 dP `88888P8 `88888P8 `88888P' +MMMMMMMMMMM 88 .88 + dP d8888P + +''' + + +''' +M""""""""M dP dP +Mmmm mmmM 88 88 +MMMM MMMM 88d888b. 88d888b. .d8888b. .d8888b. .d888b88 +MMMM MMMM 88' `88 88' `88 88ooood8 88' `88 88' `88 +MMMM MMMM 88 88 88 88. ... 88. .88 88. .88 +MMMM MMMM dP dP dP `88888P' `88888P8 `88888P8 +MMMMMMMMMM +''' + +def _the_github_upgrade_thread(window, sp): + """ + The thread that's used to run the subprocess so that the GUI can continue and the stdout/stderror is collected + + :param window: + :param sp: + :return: + """ + + window.write_event_value('-THREAD-', (sp, '===THEAD STARTING===')) + window.write_event_value('-THREAD-', (sp, '----- STDOUT & STDERR Follows ----')) + for line in sp.stdout: + oline = line.decode().rstrip() + window.write_event_value('-THREAD-', (sp, oline)) + + # DO NOT CHECK STDERR because it won't exist anymore. The subprocess code now combines stdout and stderr + # window.write_event_value('-THREAD-', (sp, '----- STDERR ----')) + + # for line in sp.stderr: + # oline = line.decode().rstrip() + # window.write_event_value('-THREAD-', (sp, oline)) + window.write_event_value('-THREAD-', (sp, '===THEAD DONE===')) + + + +def _copy_files_from_github(): + """Update the local PySimpleGUI installation from Github""" + + github_url = 'https://raw.githubusercontent.com/PySimpleGUI/PySimpleGUI/master/' + #files = ["PySimpleGUI.py", "setup.py"] + files = ["PySimpleGUI.py"] + + # add a temp directory + temp_dir = tempfile.TemporaryDirectory() + psg_dir = os.path.join(temp_dir.name, 'PySimpleGUI') + path = psg_dir + + + os.mkdir(path) + # path = os.path.abspath('temp') + + # download the files + downloaded = [] + for file in files: + with request.urlopen(github_url + file) as response: + with open(os.path.join(path, file), 'wb') as f: + f.write(response.read()) + downloaded.append(file) + + # get the new version number if possible + with open(os.path.join(path, files[0]), encoding='utf-8') as f: + text_data = f.read() + + package_version = "Unknown" + match = re.search(r'__version__ = \"([\d\.]+)', text_data) + if match: + package_version = match.group(1) + + # create a setup.py file from scratch + setup_text = ''.join([ + "import setuptools\n", + "setuptools.setup(", + "name='PySimpleGUI',", + "author='PySimpleGUI'," + "author_email='PySimpleGUI@PySimpleGUI.org',", + "description='Unreleased Development Version',", + "url='https://github.com/PySimpleGUI/PySimpleGUI'," + "packages=setuptools.find_packages(),", + "version='", package_version, "',", + "entry_points={", + "'gui_scripts': [", + "'psgissue=PySimpleGUI.PySimpleGUI:main_open_github_issue',", + "'psgmain=PySimpleGUI.PySimpleGUI:_main_entry_point',", + "'psgupgrade=PySimpleGUI.PySimpleGUI:_upgrade_entry_point',", + "'psghelp=PySimpleGUI.PySimpleGUI:main_sdk_help',", + "'psgver=PySimpleGUI.PySimpleGUI:main_get_debug_data',", + "'psgsettings=PySimpleGUI.PySimpleGUI:main_global_pysimplegui_settings',", + "],", + "},)" + ]) + + with open(os.path.join(temp_dir.name, 'setup.py'), 'w', encoding='utf-8') as f: + f.write(setup_text) + + # create an __init__.py file + with open(os.path.join(path, '__init__.py'), 'w', encoding='utf-8') as f: + f.writelines([ + 'name="PySimpleGUI"\n', + 'from .PySimpleGUI import *\n', + 'from .PySimpleGUI import __version__' + ]) + + # install the pysimplegui package from local dist + # https://pip.pypa.io/en/stable/user_guide/?highlight=subprocess#using-pip-from-your-program + # subprocess.check_call([sys.executable, '-m', 'pip', 'install', path]) + # python_command = execute_py_get_interpreter() + python_command = sys.executable # always use the currently running interpreter to perform the pip! + if 'pythonw' in python_command: + python_command = python_command.replace('pythonw', 'python') + + layout = [[Text('Pip Upgrade Progress')], + [Multiline(s=(90,30), k='-MLINE-', reroute_cprint=True, write_only=True)], + [Button('Downloading...', k='-EXIT-')]] + + window = Window('Pip Upgrade', layout, finalize=True, keep_on_top=True, modal=True, disable_close=True) + + window.disable_debugger() + + cprint('The value of sys.executable = ', sys.executable, c='white on red') + + # if not python_command: + # python_command = sys.executable + + cprint('Installing with the Python interpreter =', python_command, c='white on purple') + + sp = execute_command_subprocess(python_command, '-m pip install', temp_dir.name, pipe_output=True) + + threading.Thread(target=_the_github_upgrade_thread, args=(window, sp), daemon=True).start() + + while True: + event, values = window.read() + if event == WIN_CLOSED or (event == '-EXIT-' and window['-EXIT-'].ButtonText == 'Done'): + break + if event == '-THREAD-': + cprint(values['-THREAD-'][1]) + if values['-THREAD-'][1] == '===THEAD DONE===': + window['-EXIT-'].update(text='Done', button_color='white on red') + window.close() + # cleanup and remove files + temp_dir.cleanup() + + # return metadata + try: + mod_path = site.getsitepackages()[0] + except IndexError: + mod_path = '' + + return package_version, mod_path or '' + + +def _upgrade_from_github(): + mod_version, mod_path = _copy_files_from_github() + + popup("*** SUCCESS ***", "PySimpleGUI", mod_version, + "successfully installed in ", mod_path, "files copied: ", + "PySimpleGUI.py", keep_on_top=True, background_color='red', + text_color='white') + + +def _upgrade_gui(): + try: + cur_ver = version[:version.index('\n')] + except: + cur_ver = version + + if popup_yes_no('* WARNING *', + 'You are about to upgrade your PySimpleGUI package previously installed via pip to the latest version location on the GitHub server.', + 'You are running verrsion {}'.format(cur_ver), + '', + 'Are you sure you want to overwrite this release?', title='Are you sure you want to overwrite?', + keep_on_top=True) == 'Yes': + _upgrade_from_github() + else: + popup_quick_message('Cancelled upgrade\nNothing overwritten', background_color='red', text_color='white', keep_on_top=True, non_blocking=False) + +# main_upgrade_from_github = _upgrade_gui + +def _upgrade_entry_point(): + """ + This function is entered via the psgupgrade.exe file. + + It is needed so that the exe file will exit and thus allow itself to be overwritten which + is what the upgrade will do. + It simply runs the PySimpleGUI.py file with a command line argument "upgrade" which will + actually do the upgrade. + """ + interpreter = sys.executable + if 'pythonw' in interpreter: + interpreter = interpreter.replace('pythonw', 'python') + execute_py_file(__file__, 'upgrade', interpreter_command=interpreter) + + + +def _main_entry_point(): + # print('Restarting main as a new process...(needed in case you want to GitHub Upgrade)') + # Relaunch using the same python interpreter that was used to run this function + interpreter = sys.executable + if 'pythonw' in interpreter: + interpreter = interpreter.replace('pythonw', 'python') + execute_py_file(__file__, interpreter_command=interpreter) + +main_upgrade_from_github = _upgrade_entry_point + +#################################################################################################### + +# M"""""`'"""`YM oo +# M mm. mm. M +# M MMM MMM M .d8888b. dP 88d888b. +# M MMM MMM M 88' `88 88 88' `88 +# M MMM MMM M 88. .88 88 88 88 +# M MMM MMM M `88888P8 dP dP dP +# MMMMMMMMMMMMMM +# +# MM'"""""`MM dP +# M' .mmm. `M 88 +# M MMMMMMMM .d8888b. d8888P +# M MMM `M 88ooood8 88 +# M. `MMM' .M 88. ... 88 +# MM. .MM `88888P' dP +# MMMMMMMMMMM +# +# M""""""'YMM dP +# M mmmm. `M 88 +# M MMMMM M .d8888b. 88d888b. dP dP .d8888b. +# M MMMMM M 88ooood8 88' `88 88 88 88' `88 +# M MMMM' .M 88. ... 88. .88 88. .88 88. .88 +# M .MM `88888P' 88Y8888' `88888P' `8888P88 +# MMMMMMMMMMM .88 +# d8888P +# M""""""'YMM dP +# M mmmm. `M 88 +# M MMMMM M .d8888b. d8888P .d8888b. +# M MMMMM M 88' `88 88 88' `88 +# M MMMM' .M 88. .88 88 88. .88 +# M .MM `88888P8 dP `88888P8 +# MMMMMMMMMMM + + +def main_get_debug_data(suppress_popup=False): + """ + Collect up and display the data needed to file GitHub issues. + This function will place the information on the clipboard. + You MUST paste the information from the clipboard prior to existing your application (except on Windows). + :param suppress_popup: If True no popup window will be shown. The string will be only returned, not displayed + :type suppress_popup: (bool) + :returns: String containing the information to place into the GitHub Issue + :rtype: (str) + """ + message = \ + """Python version: {} + port: tkinter + tkinter version: {} + PySimpleGUI version: {} + PySimpleGUI filename: {}""".format(sys.version, tclversion_detailed, ver, __file__) + + clipboard_set(message) + # create a temp window so that the clipboard can be set + # root = tk.Tk() + # root.withdraw() + # root.clipboard_clear() + # root.clipboard_append(message) + # root.update() + # root.destroy() + + if not suppress_popup: + popup_scrolled('*** Version information copied to your clipboard. Paste into your GitHub Issue. ***\n', + message, title='Select and copy this info to your GitHub Issue', keep_on_top=True, size=(100, 10)) + + return message + + +# ..######...##........#######..########.....###....##......... +# .##....##..##.......##.....##.##.....##...##.##...##......... +# .##........##.......##.....##.##.....##..##...##..##......... +# .##...####.##.......##.....##.########..##.....##.##......... +# .##....##..##.......##.....##.##.....##.#########.##......... +# .##....##..##.......##.....##.##.....##.##.....##.##......... +# ..######...########..#######..########..##.....##.########... +# ..######..########.########.########.########.####.##....##..######....######. +# .##....##.##..........##.......##.......##.....##..###...##.##....##..##....## +# .##.......##..........##.......##.......##.....##..####..##.##........##...... +# ..######..######......##.......##.......##.....##..##.##.##.##...####..######. +# .......##.##..........##.......##.......##.....##..##..####.##....##........## +# .##....##.##..........##.......##.......##.....##..##...###.##....##..##....## +# ..######..########....##.......##.......##....####.##....##..######....######. + + +def main_global_pysimplegui_settings_erase(): + """ + *** WARNING *** + Deletes the PySimpleGUI settings file without asking for verification + + + """ + print('********** WARNING - you are deleting your PySimpleGUI settings file **********') + print('The file being deleted is:', pysimplegui_user_settings.full_filename) + + +def main_global_pysimplegui_settings(): + """ + Window to set settings that will be used across all PySimpleGUI programs that choose to use them. + Use set_options to set the path to the folder for all PySimpleGUI settings. + + :return: True if settings were changed + :rtype: (bool) + """ + + settings = pysimplegui_user_settings.read() + + editor_format_dict = { + 'pycharm': ' --line ', + 'notepad++': ' -n ', + 'sublime': ' :', + 'vim': ' + ', + 'wing': ' :', + 'visual studio': ' /command "edit.goto "', + 'atom': ' :', + 'spyder': ' ', + 'thonny': ' ', + 'pydev': ' :', + 'idle': ' '} + + tooltip = 'Format strings for some popular editors/IDEs:\n' + \ + 'PyCharm - --line \n' + \ + 'Notepad++ - -n \n' + \ + 'Sublime - :\n' + \ + 'vim - + \n' + \ + 'wing - :\n' + \ + 'Visual Studio - /command "edit.goto "\n' + \ + 'Atom - :\n' + \ + 'Spyder - \n' + \ + 'Thonny - \n' + \ + 'PyDev - :\n' + \ + 'IDLE - \n' + + tooltip_file_explorer = 'This is the program you normally use to "Browse" for files\n' + \ + 'For Windows this is normally "explorer". On Linux "nemo" is sometimes used.' + + tooltip_theme = 'The normal default theme for PySimpleGUI is "Dark Blue 13\n' + \ + 'If you do not call theme("theme name") by your program to change the theme, then the default is used.\n' + \ + 'This setting allows you to set the theme that PySimpleGUI will use for ALL of your programs that\n' + \ + 'do not set a theme specifically.' + + layout = [[T('Global PySimpleGUI Settings', font='DEFAIULT 18')], + + [T('Python Interpreter (normally leave blank)', font='_ 16')], + [T('Command to run a python program:'), In(settings.get('-python command-', ''), k='-PYTHON COMMAND-', enable_events=True), FileBrowse()], + [T('Editor Settings', font='_ 16')], + [T('Command to invoke your editor:'), In(settings.get('-editor program-', ''), k='-EDITOR PROGRAM-', enable_events=True), FileBrowse()], + [T('String to launch your editor to edit at a particular line #.')], + [T('Use tags to specify the string')], + [T('that will be executed to edit python files using your editor')], + [T('Edit Format String (hover for tooltip)', tooltip=tooltip), + In(settings.get('-editor format string-', ' '), k='-EDITOR FORMAT-', tooltip=tooltip)], + [T('File Explorer Program', font='_ 16', tooltip=tooltip_file_explorer)], + [In(settings.get('-explorer program-', ''), k='-EXPLORER PROGRAM-', tooltip=tooltip_file_explorer)], + [T('Theme', font='_ 16')], + [T('Leave blank for "official" PySimpleGUI default theme: {}'.format(OFFICIAL_PYSIMPLEGUI_THEME))], + [T('Default Theme For All Programs:'), + Combo([''] + theme_list(), settings.get('-theme-', None), readonly=True, k='-THEME-', tooltip=tooltip_theme)], + # [T('Buttons (Leave Unchecked To Use Default) NOT YET IMPLEMENTED!', font='_ 16')], + # [Checkbox('Always use TTK buttons'), CBox('Always use TK Buttons')], + [B('Ok', bind_return_key=True), B('Cancel'), B('Mac Patch Control')], + ] + + window = Window('Settings', layout, keep_on_top=True) + while True: + event, values = window.read() + if event in ('Cancel', WIN_CLOSED): + break + if event == 'Ok': + new_theme = OFFICIAL_PYSIMPLEGUI_THEME if values['-THEME-'] == '' else values['-THEME-'] + pysimplegui_user_settings.set('-editor program-', values['-EDITOR PROGRAM-']) + pysimplegui_user_settings.set('-explorer program-', values['-EXPLORER PROGRAM-']) + pysimplegui_user_settings.set('-editor format string-', values['-EDITOR FORMAT-']) + pysimplegui_user_settings.set('-python command-', values['-PYTHON COMMAND-']) + pysimplegui_user_settings.set('-theme-', new_theme) + theme(new_theme) + window.close() + return True + elif event == '-EDITOR PROGRAM-': + for key in editor_format_dict.keys(): + if key in values['-EDITOR PROGRAM-'].lower(): + window['-EDITOR FORMAT-'].update(value=editor_format_dict[key]) + elif event == 'Mac Patch Control': + main_mac_feature_control() + # re-read the settings in case they changed + _read_mac_global_settings() + window.close() + return False + + +# ..######..########..##....##....##.....##.########.##.......########. +# .##....##.##.....##.##...##.....##.....##.##.......##.......##.....## +# .##.......##.....##.##..##......##.....##.##.......##.......##.....## +# ..######..##.....##.#####.......#########.######...##.......########. +# .......##.##.....##.##..##......##.....##.##.......##.......##....... +# .##....##.##.....##.##...##.....##.....##.##.......##.......##....... +# ..######..########..##....##....##.....##.########.########.##....... + + +def main_sdk_help(): + """ + Display a window that will display the docstrings for each PySimpleGUI Element and the Window object + + """ + online_help_links = { + 'Button': r'https://pysimplegui.readthedocs.io/en/latest/call%20reference/#button-element', + 'ButtonMenu': r'https://pysimplegui.readthedocs.io/en/latest/call%20reference/#buttonmenu-element', + 'Canvas': r'https://pysimplegui.readthedocs.io/en/latest/call%20reference/#canvas-element', + 'Checkbox': r'https://pysimplegui.readthedocs.io/en/latest/call%20reference/#checkbox-element', + 'Column': r'https://pysimplegui.readthedocs.io/en/latest/call%20reference/#column-element', + 'Combo': r'https://pysimplegui.readthedocs.io/en/latest/call%20reference/#combo-element', + 'Frame': r'https://pysimplegui.readthedocs.io/en/latest/call%20reference/#frame-element', + 'Graph': r'https://pysimplegui.readthedocs.io/en/latest/call%20reference/#graph-element', + 'HorizontalSeparator': r'https://pysimplegui.readthedocs.io/en/latest/call%20reference/#horizontalseparator-element', + 'Image': r'https://pysimplegui.readthedocs.io/en/latest/call%20reference/#image-element', + 'Input': r'https://pysimplegui.readthedocs.io/en/latest/call%20reference/#input-element', + 'Listbox': r'https://pysimplegui.readthedocs.io/en/latest/call%20reference/#listbox-element', + 'Menu': r'https://pysimplegui.readthedocs.io/en/latest/call%20reference/#menu-element', + 'MenubarCustom': r'https://pysimplegui.readthedocs.io/en/latest/call%20reference/#menubarcustom-element', + 'Multiline': r'https://pysimplegui.readthedocs.io/en/latest/call%20reference/#multiline-element', + 'OptionMenu': r'https://pysimplegui.readthedocs.io/en/latest/call%20reference/#optionmenu-element', + 'Output': r'https://pysimplegui.readthedocs.io/en/latest/call%20reference/#output-element', + 'Pane': r'https://pysimplegui.readthedocs.io/en/latest/call%20reference/#pane-element', + 'ProgressBar': r'https://pysimplegui.readthedocs.io/en/latest/call%20reference/#progressbar-element', + 'Radio': r'https://pysimplegui.readthedocs.io/en/latest/call%20reference/#radio-element', + 'Slider': r'https://pysimplegui.readthedocs.io/en/latest/call%20reference/#slider-element', + 'Spin': r'https://pysimplegui.readthedocs.io/en/latest/call%20reference/#spin-element', + 'StatusBar': r'https://pysimplegui.readthedocs.io/en/latest/call%20reference/#statusbar-element', + 'Tab': r'https://pysimplegui.readthedocs.io/en/latest/call%20reference/#tab-element', + 'TabGroup': r'https://pysimplegui.readthedocs.io/en/latest/call%20reference/#tabgroup-element', + 'Table': r'https://pysimplegui.readthedocs.io/en/latest/call%20reference/#table-element', + 'Text': r'https://pysimplegui.readthedocs.io/en/latest/call%20reference/#text-element', + 'Titlebar': r'https://pysimplegui.readthedocs.io/en/latest/call%20reference/#titlebar-element', + 'Tree': r'https://pysimplegui.readthedocs.io/en/latest/call%20reference/#tree-element', + 'VerticalSeparator': r'https://pysimplegui.readthedocs.io/en/latest/call%20reference/#verticalseparator-element', + 'Window': r'https://pysimplegui.readthedocs.io/en/latest/call%20reference/#window', + } + + element_classes = Element.__subclasses__() + element_names = {element.__name__: element for element in element_classes} + element_names['Window'] = Window + element_classes.append(Window) + element_arg_default_dict, element_arg_default_dict_update = {}, {} + vars3 = [m for m in inspect.getmembers(sys.modules[__name__])] + + functions = [m for m in inspect.getmembers(sys.modules[__name__], inspect.isfunction)] + functions_names_lower = [f for f in functions if f[0][0].islower()] + functions_names_upper = [f for f in functions if f[0][0].isupper()] + functions_names = sorted(functions_names_lower) + sorted(functions_names_upper) + + for element in element_classes: + # Build info about init method + args = inspect.getfullargspec(element.__init__).args[1:] + defaults = inspect.getfullargspec(element.__init__).defaults + # print('------------- {element}----------') + # print(args) + # print(defaults) + if len(args) != len(defaults): + diff = len(args) - len(defaults) + defaults = ('NO DEFAULT',) * diff + defaults + args_defaults = [] + for i, a in enumerate(args): + args_defaults.append((a, defaults[i])) + element_arg_default_dict[element.__name__] = args_defaults + + # Build info about update method + try: + args = inspect.getfullargspec(element.update).args[1:] + defaults = inspect.getfullargspec(element.update).defaults + if args is None or defaults is None: + element_arg_default_dict_update[element.__name__] = (('', ''),) + continue + if len(args) != len(defaults): + diff = len(args) - len(defaults) + defaults = ('NO DEFAULT',) * diff + defaults + args_defaults = [] + for i, a in enumerate(args): + args_defaults.append((a, defaults[i])) + element_arg_default_dict_update[element.__name__] = args_defaults if len(args_defaults) else (('', ''),) + except Exception as e: + pass + + # Add on the pseudo-elements + element_names['MenubarCustom'] = MenubarCustom + element_names['Titlebar'] = Titlebar + + buttons = [[B(e, pad=(0, 0), size=(22, 1), font='Courier 10')] for e in sorted(element_names.keys())] + buttons += [[B('Func Search', pad=(0, 0), size=(22, 1), font='Courier 10')]] + button_col = Col(buttons, vertical_alignment='t') + mline_col = Column([[Multiline(size=(100, 46), key='-ML-', write_only=True, reroute_stdout=True, font='Courier 10', expand_x=True, expand_y=True)], + [T(size=(80, 1), font='Courier 10 underline', k='-DOC LINK-', enable_events=True)]], pad=(0, 0), expand_x=True, expand_y=True, vertical_alignment='t') + layout = [[button_col, mline_col]] + layout += [[CBox('Summary Only', enable_events=True, k='-SUMMARY-'), CBox('Display Only PEP8 Functions', default=True, k='-PEP8-')]] + # layout += [[Button('Exit', size=(15, 1))]] + + window = Window('SDK API Call Reference', layout, resizable=True, use_default_focus=False, keep_on_top=True, icon=EMOJI_BASE64_THINK, finalize=True, right_click_menu=MENU_RIGHT_CLICK_EDITME_EXIT) + window['-DOC LINK-'].set_cursor('hand1') + online_help_link = '' + ml = window['-ML-'] + current_element = '' + try: + while True: # Event Loop + event, values = window.read() + if event in (WIN_CLOSED, 'Exit'): + break + if event == '-DOC LINK-': + if webbrowser_available and online_help_link: + webbrowser.open_new_tab(online_help_link) + if event == '-SUMMARY-': + event = current_element + + if event in element_names.keys(): + current_element = event + window['-ML-'].update('') + online_help_link = online_help_links.get(event, '') + window['-DOC LINK-'].update(online_help_link) + if not values['-SUMMARY-']: + elem = element_names[event] + ml.print(pydoc.help(elem)) + # print the aliases for the class + ml.print('\n--- Shortcut Aliases for Class ---') + for v in vars3: + if elem == v[1] and elem.__name__ != v[0]: + print(v[0]) + ml.print('\n--- Init Parms ---') + else: + elem = element_names[event] + + element_methods = [m[0] for m in inspect.getmembers(Element, inspect.isfunction) if not m[0].startswith('_') and not m[0][0].isupper()] + methods = inspect.getmembers(elem, inspect.isfunction) + methods = [m[0] for m in methods if not m[0].startswith('_') and not m[0][0].isupper()] + + unique_methods = [m for m in methods if m not in element_methods and not m[0][0].isupper()] + + properties = inspect.getmembers(elem, lambda o: isinstance(o, property)) + properties = [p[0] for p in properties if not p[0].startswith('_')] + ml.print('--- Methods ---', background_color='red', text_color='white') + ml.print('\n'.join(methods)) + ml.print('--- Properties ---', background_color='red', text_color='white') + ml.print('\n'.join(properties)) + if issubclass(elem, Element): + ml.print('Methods Unique to This Element', background_color='red', text_color='white') + ml.print('\n'.join(unique_methods)) + ml.print('========== Init Parms ==========', background_color='#FFFF00', text_color='black') + elem_text_name = event + for parm, default in element_arg_default_dict[elem_text_name]: + ml.print('{:18}'.format(parm), end=' = ') + ml.print(default, end=',\n') + if elem_text_name in element_arg_default_dict_update: + ml.print('========== Update Parms ==========', background_color='#FFFF00', text_color='black') + for parm, default in element_arg_default_dict_update[elem_text_name]: + ml.print('{:18}'.format(parm), end=' = ') + ml.print(default, end=',\n') + ml.set_vscroll_position(0) # scroll to top of multoline + elif event == 'Func Search': + search_string = popup_get_text('Search for this in function list:', keep_on_top=True) + if search_string is not None: + online_help_link = '' + window['-DOC LINK-'].update('') + ml.update('') + for f_entry in functions_names: + f = f_entry[0] + if search_string in f.lower() and not f.startswith('_'): + if (values['-PEP8-'] and not f[0].isupper()) or not values['-PEP8-']: + if values['-SUMMARY-']: + ml.print(f) + else: + ml.print('=========== ' + f + '===========', background_color='#FFFF00', text_color='black') + ml.print(pydoc.help(f_entry[1])) + ml.set_vscroll_position(0) # scroll to top of multoline + except Exception as e: + _error_popup_with_traceback('Exception in SDK reference', e) + window.close() + + +# oo +# +# 88d8b.d8b. .d8888b. dP 88d888b. +# 88'`88'`88 88' `88 88 88' `88 +# 88 88 88 88. .88 88 88 88 +# dP dP dP `88888P8 dP dP dP +# +# +# M""MMM""MMM""M oo dP +# M MMM MMM M 88 +# M MMP MMP M dP 88d888b. .d888b88 .d8888b. dP dP dP +# M MM' MM' .M 88 88' `88 88' `88 88' `88 88 88 88 +# M `' . '' .MM 88 88 88 88. .88 88. .88 88.88b.88' +# M .d .dMMM dP dP dP `88888P8 `88888P' 8888P Y8P +# MMMMMMMMMMMMMM +# +# MP""""""`MM dP dP dP +# M mmmmm..M 88 88 88 +# M. `YM d8888P .d8888b. 88d888b. d8888P .d8888b. 88d888b. .d8888b. 88d888b. .d8888b. +# MMMMMMM. M 88 88' `88 88' `88 88 Y8ooooo. 88' `88 88ooood8 88' `88 88ooood8 +# M. .MMM' M 88 88. .88 88 88 88 88 88 88. ... 88 88. ... +# Mb. .dM dP `88888P8 dP dP `88888P' dP dP `88888P' dP `88888P' +# MMMMMMMMMMM + + +def _main_switch_theme(): + layout = [ + [Text('Click a look and feel color to see demo window')], + [Listbox(values=theme_list(), + size=(20, 20), key='-LIST-')], + [Button('Choose'), Button('Cancel')]] + + window = Window('Change Themes', layout) + + event, values = window.read(close=True) + + if event == 'Choose': + theme_name = values['-LIST-'][0] + theme(theme_name) + + +def _create_main_window(): + """ + Creates the main test harness window. + + :return: The test window + :rtype: Window + """ + + # theme('dark blue 3') + # theme('dark brown 2') + # theme('dark') + # theme('dark red') + # theme('Light Green 6') + # theme('Dark Grey 8') + + tkversion = tkinter.TkVersion + tclversion = tkinter.TclVersion + tclversion_detailed = tkinter.Tcl().eval('info patchlevel') + + print('Starting up PySimpleGUI Diagnostic & Help System') + print('PySimpleGUI long version = ', version) + print('PySimpleGUI Version ', ver, '\ntcl ver = {}'.format(tclversion), + 'tkinter version = {}'.format(tkversion), '\nPython Version {}'.format(sys.version)) + print('tcl detailed version = {}'.format(tclversion_detailed)) + print('PySimpleGUI.py location', __file__) + # ------ Menu Definition ------ # + menu_def = [['&File', ['!&Open', '&Save::savekey', '---', '&Properties', 'E&xit']], + ['&Edit', ['&Paste', ['Special', 'Normal', '!Disabled'], 'Undo'], ], + ['&Debugger', ['Popout', 'Launch Debugger']], + ['!&Disabled', ['Popout', 'Launch Debugger']], + ['&Toolbar', ['Command &1', 'Command &2', 'Command &3', 'Command &4']], + ['&Help', '&About...'], ] + + button_menu_def = ['unused', ['&Paste', ['Special', 'Normal', '!Disabled'], 'Undo', 'Exit'], ] + treedata = TreeData() + + treedata.Insert("", '_A_', 'Tree Item 1', [1, 2, 3], ) + treedata.Insert("", '_B_', 'B', [4, 5, 6], ) + treedata.Insert("_A_", '_A1_', 'Sub Item 1', ['can', 'be', 'anything'], ) + treedata.Insert("", '_C_', 'C', [], ) + treedata.Insert("_C_", '_C1_', 'C1', ['or'], ) + treedata.Insert("_A_", '_A2_', 'Sub Item 2', [None, None]) + treedata.Insert("_A1_", '_A3_', 'A30', ['getting deep']) + treedata.Insert("_C_", '_C2_', 'C2', ['nothing', 'at', 'all']) + + for i in range(100): + treedata.Insert('_C_', i, i, []) + + frame1 = [ + [Input('Input Text', size=(25, 1)), ], + [Multiline(size=(30, 5), default_text='Multiline Input')], + ] + + frame2 = [ + # [ProgressBar(100, bar_color=('red', 'green'), orientation='h')], + + [Listbox(['Listbox 1', 'Listbox 2', 'Listbox 3'], select_mode=SELECT_MODE_EXTENDED, size=(20, 5), no_scrollbar=True)], + [Combo(['Combo item %s' % i for i in range(5)], size=(20, 3), default_value='Combo item 2', key='_COMBO1_', )], + [Combo(['Combo item %s' % i for i in range(5)], size=(20, 3), font='Courier 20', default_value='Combo item 2', key='_COMBO2_', )], + # [Combo(['Combo item 1', 2,3,4], size=(20, 3), readonly=False, text_color='blue', background_color='red', key='_COMBO2_')], + [Spin([1, 2, 3, 'a', 'b', 'c'], initial_value='a', size=(4, 3))], + ] + + frame3 = [ + [Checkbox('Checkbox1', True), Checkbox('Checkbox1')], + [Radio('Radio Button1', 1), Radio('Radio Button2', 1, default=True, tooltip='Radio 2')], + [T('', size=(1, 4))], + ] + + frame4 = [ + [Slider(range=(0, 100), orientation='v', size=(7, 15), default_value=40, key='-SLIDER1-'), + Slider(range=(0, 100), orientation='h', size=(11, 15), default_value=40, key='-SLIDER2-'), ], + ] + matrix = [[str(x * y) for x in range(1, 5)] for y in range(1, 8)] + + frame5 = [[ + Table(values=matrix, headings=matrix[0], + auto_size_columns=False, display_row_numbers=True, change_submits=False, justification='right', + num_rows=10, alternating_row_color='lightblue', key='_table_', + col_widths=[5, 5, 5, 5], size=(400, 200), ), + T(' '), + Tree(data=treedata, headings=['col1', 'col2', 'col3'], change_submits=True, auto_size_columns=True, + num_rows=10, col0_width=10, key='_TREE_', show_expanded=True, )],[VStretch()]] + frame7 = [[T('ONE thing.... you had one thing to NOT do. "Do NOT click"')], [Image(data=_random_error_emoji())], + [T("""Well, now what?\nYou could take moment and help this project out by sponsoring.\nAt the moment PySimpleGUI is still free of charge to use.\nYou have no financial responsibility.\nI hope you are enjoying using PySimpleGUI whether you sponsor the product or not.""")], + [T('Click here to help --->>>'), + T('YES - I want to support PySimpleGUI!', enable_events=True, text_color='red', background_color='yellow', k='-SPONSOR-')], ] + + pop_test_tab_layout = [ + [T('Popup tests... good idea!'),Image(EMOJI_BASE64_HAPPY_IDEA), Push(), B('Popup', k='P '), B('No Titlebar', k='P NoTitle'), B('Not Modal', k='P NoModal'), B('Non Blocking', k='P NoBlock'), B('Auto Close', k='P AutoClose')], + [T('Get popups too!'), Push(), B('Get File'), B('Get Folder'), B('Get Date'), B('Get Text')]] + + + graph_elem = Graph((600, 250), (0, 0), (800, 300), key='+GRAPH+') + + frame6 = [[graph_elem]] + + global_settings_tab_layout = [[T('Global Settings:', font='_ 15')], + [T('Settings Filename:'), T(pysimplegui_user_settings.full_filename, s=(50,2))], + [T('Settings Dictionary:'), MLine(pysimplegui_user_settings, size=(50,10))], + ] + + themes_tab_layout = [[T('You can see a preview of the themes, the color swatches, or switch themes for this window')], + [T('If you want to change the default theme for PySimpleGUI, use the Global Settings')], + [B('Themes'), B('Theme Swatches'), B('Switch Themes')]] + + tab1 = Tab('Graph\n', frame6, tooltip='Graph is in here', title_color='red') + tab2 = Tab('CB, Radio\nList, Combo', + [[Frame('Multiple Choice Group', frame2, title_color='#FFFFFF', tooltip='Checkboxes, radio buttons, etc', vertical_alignment='t',), + Frame('Binary Choice Group', frame3, title_color='#FFFFFF', tooltip='Binary Choice', vertical_alignment='t', ), ]]) + # tab3 = Tab('Table and Tree', [[Frame('Structured Data Group', frame5, title_color='red', element_justification='l')]], tooltip='tab 3', title_color='red', ) + tab3 = Tab('Table &\nTree', [[Column(frame5, element_justification='l', vertical_alignment='t')]], tooltip='tab 3', title_color='red', k='-TAB TABLE-') + tab4 = Tab('Sliders\n', [[Frame('Variable Choice Group', frame4, title_color='blue')]], tooltip='tab 4', title_color='red', k='-TAB VAR-') + tab5 = Tab('Input\nMultiline', [[Frame('TextInput', frame1, title_color='blue')]], tooltip='tab 5', title_color='red', k='-TAB TEXT-') + tab6 = Tab('Do NOT\nclick', frame7, k='-TAB NO CLICK-') + tab7 = Tab('Popups\n', pop_test_tab_layout, k='-TAB POPUP-') + tab8 = Tab('Themes\n', themes_tab_layout, k='-TAB THEMES-') + tab9 = Tab('Global\nSettings', global_settings_tab_layout, k='-TAB GlOBAL SETTINGS-') + + def VerLine(version, description, justification='r', size=(40, 1)): + return [T(version, justification=justification, font='Any 12', text_color='yellow', size=size, pad=(0,0)), vtop(T(description, font='Any 12', pad=(0,0)))] + + layout_top = Column([ + [Image(EMOJI_BASE64_HAPPY_BIG_SMILE, enable_events=True, key='-LOGO-', tooltip='This is PySimpleGUI logo'), + Image(data=DEFAULT_BASE64_LOADING_GIF, enable_events=True, key='_IMAGE_'), + Text('PySimpleGUI Test Harness\nYou are running PySimpleGUI.py file instead of importing', font='ANY 15', + tooltip='My tooltip', key='_TEXT1_')], + VerLine(ver, 'PySimpleGUI Version') + [Image(HEART_3D_BASE64, subsample=4)], + VerLine('{}/{}'.format(tkversion, tclversion), 'TK/TCL Versions'), + VerLine(tclversion_detailed, 'detailed tkinter version'), + VerLine(os.path.dirname(os.path.abspath(__file__)), 'PySimpleGUI Location', size=(40, 2)), + VerLine(sys.version, 'Python Version', size=(40, 2))], pad=(0, 0)) + + layout_bottom = [ + [B(SYMBOL_DOWN, pad=(0, 0), k='-HIDE TABS-'), + pin(Col([[TabGroup([[tab1, tab2, tab3, tab6, tab4, tab5, tab7, tab8, tab9]], key='_TAB_GROUP_')]], k='-TAB GROUP-'))], + [B('Button', highlight_colors=('yellow', 'red'),pad=(1, 0)), B('Hide Stuff',pad=(1, 0), metadata='my metadata'), + B('ttk Button', use_ttk_buttons=True, tooltip='This is a TTK Button',pad=(1, 0)), + B('See-through Mode', tooltip='Make the background transparent',pad=(1, 0)), + B('Upgrade PySimpleGUI from GitHub', button_color='white on red', key='-INSTALL-',pad=(1, 0)), + B('Global Settings', tooltip='Settings across all PySimpleGUI programs',pad=(1, 0)), + B('Exit', tooltip='Exit button',pad=(1, 0))], + [B(image_data=ICON_BUY_ME_A_COFFEE,pad=(1, 0), key='-COFFEE-'), + B('SDK Reference', pad=(1, 0)), B('Open GitHub Issue',pad=(1, 0)), B('Versions for GitHub',pad=(1, 0)), + ButtonMenu('ButtonMenu', button_menu_def, pad=(1, 0),key='-BMENU-', tearoff=True) + ]] + + layout = [[]] + + if not USE_CUSTOM_TITLEBAR: + layout += [[Menu(menu_def, key='_MENU_', font='Courier 15', background_color='red', text_color='white', disabled_text_color='yellow', tearoff=True)]] + else: + layout += [[MenubarCustom(menu_def, key='_MENU_', font='Courier 15', bar_background_color=theme_background_color(), bar_text_color=theme_text_color(), + background_color='red', text_color='white', disabled_text_color='yellow')]] + + layout += [[layout_top] + [ProgressBar(max_value=800, size=(20, 25), orientation='v', key='+PROGRESS+')]] + layout += layout_bottom + + window = Window('PySimpleGUI Main Test Harness', layout, + # font=('Helvetica', 18), + # background_color='black', + right_click_menu=['&Right', ['Right', '!&Click', '&Menu', 'E&xit', 'Properties']], + # transparent_color= '#9FB8AD', + resizable=True, + keep_on_top=True, + element_justification='left', # justify contents to the left + metadata='My window metadata', + finalize=True, + grab_anywhere=True, + enable_close_attempted_event=True, + # ttk_theme=THEME_ALT, + # icon=PSG_DEBUGGER_LOGO, + # icon=PSGDebugLogo, + ) + window['-SPONSOR-'].set_cursor(cursor='hand2') + window._see_through = False + return window + + +# M"""""`'"""`YM oo +# M mm. mm. M +# M MMM MMM M .d8888b. dP 88d888b. +# M MMM MMM M 88' `88 88 88' `88 +# M MMM MMM M 88. .88 88 88 88 +# M MMM MMM M `88888P8 dP dP dP +# MMMMMMMMMMMMMM + + +def main(): + """ + The PySimpleGUI "Test Harness". This is meant to be a super-quick test of the Elements. + """ + window = _create_main_window() + set_options(keep_on_top=True) + graph_elem = window['+GRAPH+'] + i = 0 + # Don't use the debug window + # Print('', location=(0, 0), font='Courier 10', size=(100, 20), grab_anywhere=True) + # print(window.element_list()) + while True: # Event Loop + event, values = window.read(timeout=5) + if event != TIMEOUT_KEY: + print(event, values) + # Print(event, text_color='white', background_color='red', end='') + # Print(values) + if event == WIN_CLOSED or event == WIN_CLOSE_ATTEMPTED_EVENT or event == 'Exit' or (event == '-BMENU-' and values['-BMENU-'] == 'Exit'): + break + if i < 800: + graph_elem.DrawLine((i, 0), (i, random.randint(0, 300)), width=1, color='#{:06x}'.format(random.randint(0, 0xffffff))) + else: + graph_elem.Move(-1, 0) + graph_elem.DrawLine((i, 0), (i, random.randint(0, 300)), width=1, color='#{:06x}'.format(random.randint(0, 0xffffff))) + window['+PROGRESS+'].UpdateBar(i % 800) + window.Element('_IMAGE_').UpdateAnimation(DEFAULT_BASE64_LOADING_GIF, time_between_frames=50) + i += 1 + if event == 'Button': + window.Element('_TEXT1_').SetTooltip('NEW TEXT') + window.Element('_MENU_').Update(visible=True) + elif event.startswith('Hide'): + # window.Normal() + window.Element('_MENU_').Update(visible=False) + elif event == 'Popout': + show_debugger_popout_window() + elif event == 'Launch Debugger': + show_debugger_window() + elif event == 'About...': + popup('About this program...', 'You are looking at the test harness for the PySimpleGUI program', version, keep_on_top=True, image=DEFAULT_BASE64_ICON) + elif event.startswith('See'): + window._see_through = not window._see_through + window.set_transparent_color(theme_background_color() if window._see_through else '') + elif event == '-INSTALL-': + _upgrade_gui() + elif event == 'Popup': + popup('This is your basic popup') + elif event == 'Get File': + popup_scrolled('Returned:', popup_get_file('Get File')) + elif event == 'Get Folder': + popup_scrolled('Returned:', popup_get_folder('Get Folder')) + elif event == 'Get Date': + popup_scrolled('Returned:', popup_get_date()) + elif event == 'Get Text': + popup_scrolled('Returned:', popup_get_text('Enter some text')) + elif event.startswith('-SPONSOR-'): + if webbrowser_available: + webbrowser.open_new_tab(r'https://www.paypal.me/psgui') + elif event == '-COFFEE-': + if webbrowser_available: + webbrowser.open_new_tab(r'https://www.buymeacoffee.com/PySimpleGUI') + elif event == 'Themes': + search_string = popup_get_text('Enter a search term or leave blank for all themes', 'Show Available Themes', keep_on_top=True) + if search_string is not None: + theme_previewer(search_string=search_string) + elif event == 'Theme Swatches': + theme_previewer_swatches() + elif event == 'Switch Themes': + window.close() + _main_switch_theme() + window = _create_main_window() + graph_elem = window['+GRAPH+'] + elif event == '-HIDE TABS-': + window['-TAB GROUP-'].update(visible=window['-TAB GROUP-'].metadata == True) + window['-TAB GROUP-'].metadata = not window['-TAB GROUP-'].metadata + window['-HIDE TABS-'].update(text=SYMBOL_UP if window['-TAB GROUP-'].metadata else SYMBOL_DOWN) + elif event == 'SDK Reference': + main_sdk_help() + elif event == 'Global Settings': + if main_global_pysimplegui_settings(): + theme(pysimplegui_user_settings.get('-theme-', OFFICIAL_PYSIMPLEGUI_THEME)) + window.close() + window = _create_main_window() + graph_elem = window['+GRAPH+'] + elif event.startswith('P '): + if event == 'P ': + popup('Normal Popup - Modal', keep_on_top=True) + elif event == 'P NoTitle': + popup_no_titlebar('No titlebar', keep_on_top=True) + elif event == 'P NoModal': + popup('Normal Popup - Not Modal', 'You can interact with main window menubar ', + 'but will have no effect immediately', 'button clicks will happen after you close this popup', modal=False, keep_on_top=True) + elif event == 'P NoBlock': + popup_non_blocking('Non-blocking', 'The background window should still be running', keep_on_top=True) + elif event == 'P AutoClose': + popup_auto_close('Will autoclose in 3 seconds', auto_close_duration=3, keep_on_top=True) + elif event == 'Versions for GitHub': + main_get_debug_data() + elif event == 'Open GitHub Issue': + window.minimize() + main_open_github_issue() + window.normal() + i += 1 + # _refresh_debugger() + print('event = ', event) + window.close() + + +# ------------------------ PEP8-ify The SDK ------------------------# + +ChangeLookAndFeel = change_look_and_feel +ConvertArgsToSingleString = convert_args_to_single_string +EasyPrint = easy_print +Print = easy_print +eprint = easy_print +sgprint = easy_print +PrintClose = easy_print_close +sgprint_close = easy_print_close +EasyPrintClose = easy_print_close +FillFormWithValues = fill_form_with_values +GetComplimentaryHex = get_complimentary_hex +ListOfLookAndFeelValues = list_of_look_and_feel_values +ObjToString = obj_to_string +ObjToStringSingleObj = obj_to_string_single_obj +OneLineProgressMeter = one_line_progress_meter +OneLineProgressMeterCancel = one_line_progress_meter_cancel +Popup = popup +PopupNoFrame = popup_no_titlebar +popup_no_frame = popup_no_titlebar +PopupNoBorder = popup_no_titlebar +popup_no_border = popup_no_titlebar +PopupAnnoying = popup_no_titlebar +popup_annoying = popup_no_titlebar +PopupAnimated = popup_animated +PopupAutoClose = popup_auto_close +PopupCancel = popup_cancel +PopupError = popup_error +PopupGetFile = popup_get_file +PopupGetFolder = popup_get_folder +PopupGetText = popup_get_text +PopupNoButtons = popup_no_buttons +PopupNoTitlebar = popup_no_titlebar +PopupNoWait = popup_non_blocking +popup_no_wait = popup_non_blocking +PopupNonBlocking = popup_non_blocking +PopupOK = popup_ok +PopupOKCancel = popup_ok_cancel +PopupQuick = popup_quick +PopupQuickMessage = popup_quick_message +PopupScrolled = popup_scrolled +PopupTimed = popup_auto_close +popup_timed = popup_auto_close +PopupYesNo = popup_yes_no + +RGB = rgb +SetGlobalIcon = set_global_icon +SetOptions = set_options +sprint = popup_scrolled +ScrolledTextBox = popup_scrolled +TimerStart = timer_start +TimerStop = timer_stop +test = main +sdk_help = main_sdk_help + +pysimplegui_user_settings = UserSettings(filename=DEFAULT_USER_SETTINGS_PYSIMPLEGUI_FILENAME, path=DEFAULT_USER_SETTINGS_PYSIMPLEGUI_PATH) +# ------------------------ Set the "Official PySimpleGUI Theme Colors" ------------------------ + + +theme(theme_global()) + +# See if running on Trinket. If Trinket, then use custom titlebars since Trinket doesn't supply any +if running_trinket(): + USE_CUSTOM_TITLEBAR = True + +if tclversion_detailed.startswith('8.5'): + warnings.warn('You are running a VERY old version of tkinter {}. You cannot use PNG formatted images for example. Please upgrade to 8.6.x'.format(tclversion_detailed), UserWarning) + +_read_mac_global_settings() +# if running_mac(): +# print('Your Mac patches are:') +# print('Modal windows disabled:', ENABLE_MAC_MODAL_DISABLE_PATCH) +# print('No titlebar patch:', ENABLE_MAC_NOTITLEBAR_PATCH) +# print('No grab anywhere allowed with titlebar:', ENABLE_MAC_DISABLE_GRAB_ANYWHERE_WITH_TITLEBAR) +# print('Currently the no titlebar patch ' + ('WILL' if _mac_should_apply_notitlebar_patch() else 'WILL NOT') + ' be applied') + +# -------------------------------- ENTRY POINT IF RUN STANDALONE -------------------------------- # +if __name__ == '__main__': + # To execute the upgrade from command line, type: + # python -m PySimpleGUI.PySimpleGUI upgrade + if len(sys.argv) > 1 and sys.argv[1] == 'upgrade': + _upgrade_gui() + exit(0) + elif len(sys.argv) > 1 and sys.argv[1] == 'help': + main_sdk_help() + exit(0) + main() + exit(0) \ No newline at end of file diff --git a/PySimpleGUIQt/Demo Programs/Demo_Color_Chooser_Custom.py b/PySimpleGUIQt/Demo Programs/Demo_Color_Chooser_Custom.py new file mode 100644 index 000000000..5f09afac9 --- /dev/null +++ b/PySimpleGUIQt/Demo Programs/Demo_Color_Chooser_Custom.py @@ -0,0 +1,710 @@ +import PySimpleGUI as sg + +def color_chooser(): + """ + + :return: Any(str, None) Returns hex string of color chosen or None if nothing was chosen + """ + color_map = { + 'alice blue': '#F0F8FF', + 'AliceBlue': '#F0F8FF', + 'antique white': '#FAEBD7', + 'AntiqueWhite': '#FAEBD7', + 'AntiqueWhite1': '#FFEFDB', + 'AntiqueWhite2': '#EEDFCC', + 'AntiqueWhite3': '#CDC0B0', + 'AntiqueWhite4': '#8B8378', + 'aquamarine': '#7FFFD4', + 'aquamarine1': '#7FFFD4', + 'aquamarine2': '#76EEC6', + 'aquamarine3': '#66CDAA', + 'aquamarine4': '#458B74', + 'azure': '#F0FFFF', + 'azure1': '#F0FFFF', + 'azure2': '#E0EEEE', + 'azure3': '#C1CDCD', + 'azure4': '#838B8B', + 'beige': '#F5F5DC', + 'bisque': '#FFE4C4', + 'bisque1': '#FFE4C4', + 'bisque2': '#EED5B7', + 'bisque3': '#CDB79E', + 'bisque4': '#8B7D6B', + 'black': '#000000', + 'blanched almond': '#FFEBCD', + 'BlanchedAlmond': '#FFEBCD', + 'blue': '#0000FF', + 'blue violet': '#8A2BE2', + 'blue1': '#0000FF', + 'blue2': '#0000EE', + 'blue3': '#0000CD', + 'blue4': '#00008B', + 'BlueViolet': '#8A2BE2', + 'brown': '#A52A2A', + 'brown1': '#FF4040', + 'brown2': '#EE3B3B', + 'brown3': '#CD3333', + 'brown4': '#8B2323', + 'burlywood': '#DEB887', + 'burlywood1': '#FFD39B', + 'burlywood2': '#EEC591', + 'burlywood3': '#CDAA7D', + 'burlywood4': '#8B7355', + 'cadet blue': '#5F9EA0', + 'CadetBlue': '#5F9EA0', + 'CadetBlue1': '#98F5FF', + 'CadetBlue2': '#8EE5EE', + 'CadetBlue3': '#7AC5CD', + 'CadetBlue4': '#53868B', + 'chartreuse': '#7FFF00', + 'chartreuse1': '#7FFF00', + 'chartreuse2': '#76EE00', + 'chartreuse3': '#66CD00', + 'chartreuse4': '#458B00', + 'chocolate': '#D2691E', + 'chocolate1': '#FF7F24', + 'chocolate2': '#EE7621', + 'chocolate3': '#CD661D', + 'chocolate4': '#8B4513', + 'coral': '#FF7F50', + 'coral1': '#FF7256', + 'coral2': '#EE6A50', + 'coral3': '#CD5B45', + 'coral4': '#8B3E2F', + 'cornflower blue': '#6495ED', + 'CornflowerBlue': '#6495ED', + 'cornsilk': '#FFF8DC', + 'cornsilk1': '#FFF8DC', + 'cornsilk2': '#EEE8CD', + 'cornsilk3': '#CDC8B1', + 'cornsilk4': '#8B8878', + 'cyan': '#00FFFF', + 'cyan1': '#00FFFF', + 'cyan2': '#00EEEE', + 'cyan3': '#00CDCD', + 'cyan4': '#008B8B', + 'dark blue': '#00008B', + 'dark cyan': '#008B8B', + 'dark goldenrod': '#B8860B', + 'dark gray': '#A9A9A9', + 'dark green': '#006400', + 'dark grey': '#A9A9A9', + 'dark khaki': '#BDB76B', + 'dark magenta': '#8B008B', + 'dark olive green': '#556B2F', + 'dark orange': '#FF8C00', + 'dark orchid': '#9932CC', + 'dark red': '#8B0000', + 'dark salmon': '#E9967A', + 'dark sea green': '#8FBC8F', + 'dark slate blue': '#483D8B', + 'dark slate gray': '#2F4F4F', + 'dark slate grey': '#2F4F4F', + 'dark turquoise': '#00CED1', + 'dark violet': '#9400D3', + 'DarkBlue': '#00008B', + 'DarkCyan': '#008B8B', + 'DarkGoldenrod': '#B8860B', + 'DarkGoldenrod1': '#FFB90F', + 'DarkGoldenrod2': '#EEAD0E', + 'DarkGoldenrod3': '#CD950C', + 'DarkGoldenrod4': '#8B6508', + 'DarkGray': '#A9A9A9', + 'DarkGreen': '#006400', + 'DarkGrey': '#A9A9A9', + 'DarkKhaki': '#BDB76B', + 'DarkMagenta': '#8B008B', + 'DarkOliveGreen': '#556B2F', + 'DarkOliveGreen1': '#CAFF70', + 'DarkOliveGreen2': '#BCEE68', + 'DarkOliveGreen3': '#A2CD5A', + 'DarkOliveGreen4': '#6E8B3D', + 'DarkOrange': '#FF8C00', + 'DarkOrange1': '#FF7F00', + 'DarkOrange2': '#EE7600', + 'DarkOrange3': '#CD6600', + 'DarkOrange4': '#8B4500', + 'DarkOrchid': '#9932CC', + 'DarkOrchid1': '#BF3EFF', + 'DarkOrchid2': '#B23AEE', + 'DarkOrchid3': '#9A32CD', + 'DarkOrchid4': '#68228B', + 'DarkRed': '#8B0000', + 'DarkSalmon': '#E9967A', + 'DarkSeaGreen': '#8FBC8F', + 'DarkSeaGreen1': '#C1FFC1', + 'DarkSeaGreen2': '#B4EEB4', + 'DarkSeaGreen3': '#9BCD9B', + 'DarkSeaGreen4': '#698B69', + 'DarkSlateBlue': '#483D8B', + 'DarkSlateGray': '#2F4F4F', + 'DarkSlateGray1': '#97FFFF', + 'DarkSlateGray2': '#8DEEEE', + 'DarkSlateGray3': '#79CDCD', + 'DarkSlateGray4': '#528B8B', + 'DarkSlateGrey': '#2F4F4F', + 'DarkTurquoise': '#00CED1', + 'DarkViolet': '#9400D3', + 'deep pink': '#FF1493', + 'deep sky blue': '#00BFFF', + 'DeepPink': '#FF1493', + 'DeepPink1': '#FF1493', + 'DeepPink2': '#EE1289', + 'DeepPink3': '#CD1076', + 'DeepPink4': '#8B0A50', + 'DeepSkyBlue': '#00BFFF', + 'DeepSkyBlue1': '#00BFFF', + 'DeepSkyBlue2': '#00B2EE', + 'DeepSkyBlue3': '#009ACD', + 'DeepSkyBlue4': '#00688B', + 'dim gray': '#696969', + 'dim grey': '#696969', + 'DimGray': '#696969', + 'DimGrey': '#696969', + 'dodger blue': '#1E90FF', + 'DodgerBlue': '#1E90FF', + 'DodgerBlue1': '#1E90FF', + 'DodgerBlue2': '#1C86EE', + 'DodgerBlue3': '#1874CD', + 'DodgerBlue4': '#104E8B', + 'firebrick': '#B22222', + 'firebrick1': '#FF3030', + 'firebrick2': '#EE2C2C', + 'firebrick3': '#CD2626', + 'firebrick4': '#8B1A1A', + 'floral white': '#FFFAF0', + 'FloralWhite': '#FFFAF0', + 'forest green': '#228B22', + 'ForestGreen': '#228B22', + 'gainsboro': '#DCDCDC', + 'ghost white': '#F8F8FF', + 'GhostWhite': '#F8F8FF', + 'gold': '#FFD700', + 'gold1': '#FFD700', + 'gold2': '#EEC900', + 'gold3': '#CDAD00', + 'gold4': '#8B7500', + 'goldenrod': '#DAA520', + 'goldenrod1': '#FFC125', + 'goldenrod2': '#EEB422', + 'goldenrod3': '#CD9B1D', + 'goldenrod4': '#8B6914', + 'green': '#00FF00', + 'green yellow': '#ADFF2F', + 'green1': '#00FF00', + 'green2': '#00EE00', + 'green3': '#00CD00', + 'green4': '#008B00', + 'GreenYellow': '#ADFF2F', + 'grey': '#BEBEBE', + 'grey0': '#000000', + 'grey1': '#030303', + 'grey2': '#050505', + 'grey3': '#080808', + 'grey4': '#0A0A0A', + 'grey5': '#0D0D0D', + 'grey6': '#0F0F0F', + 'grey7': '#121212', + 'grey8': '#141414', + 'grey9': '#171717', + 'grey10': '#1A1A1A', + 'grey11': '#1C1C1C', + 'grey12': '#1F1F1F', + 'grey13': '#212121', + 'grey14': '#242424', + 'grey15': '#262626', + 'grey16': '#292929', + 'grey17': '#2B2B2B', + 'grey18': '#2E2E2E', + 'grey19': '#303030', + 'grey20': '#333333', + 'grey21': '#363636', + 'grey22': '#383838', + 'grey23': '#3B3B3B', + 'grey24': '#3D3D3D', + 'grey25': '#404040', + 'grey26': '#424242', + 'grey27': '#454545', + 'grey28': '#474747', + 'grey29': '#4A4A4A', + 'grey30': '#4D4D4D', + 'grey31': '#4F4F4F', + 'grey32': '#525252', + 'grey33': '#545454', + 'grey34': '#575757', + 'grey35': '#595959', + 'grey36': '#5C5C5C', + 'grey37': '#5E5E5E', + 'grey38': '#616161', + 'grey39': '#636363', + 'grey40': '#666666', + 'grey41': '#696969', + 'grey42': '#6B6B6B', + 'grey43': '#6E6E6E', + 'grey44': '#707070', + 'grey45': '#737373', + 'grey46': '#757575', + 'grey47': '#787878', + 'grey48': '#7A7A7A', + 'grey49': '#7D7D7D', + 'grey50': '#7F7F7F', + 'grey51': '#828282', + 'grey52': '#858585', + 'grey53': '#878787', + 'grey54': '#8A8A8A', + 'grey55': '#8C8C8C', + 'grey56': '#8F8F8F', + 'grey57': '#919191', + 'grey58': '#949494', + 'grey59': '#969696', + 'grey60': '#999999', + 'grey61': '#9C9C9C', + 'grey62': '#9E9E9E', + 'grey63': '#A1A1A1', + 'grey64': '#A3A3A3', + 'grey65': '#A6A6A6', + 'grey66': '#A8A8A8', + 'grey67': '#ABABAB', + 'grey68': '#ADADAD', + 'grey69': '#B0B0B0', + 'grey70': '#B3B3B3', + 'grey71': '#B5B5B5', + 'grey72': '#B8B8B8', + 'grey73': '#BABABA', + 'grey74': '#BDBDBD', + 'grey75': '#BFBFBF', + 'grey76': '#C2C2C2', + 'grey77': '#C4C4C4', + 'grey78': '#C7C7C7', + 'grey79': '#C9C9C9', + 'grey80': '#CCCCCC', + 'grey81': '#CFCFCF', + 'grey82': '#D1D1D1', + 'grey83': '#D4D4D4', + 'grey84': '#D6D6D6', + 'grey85': '#D9D9D9', + 'grey86': '#DBDBDB', + 'grey87': '#DEDEDE', + 'grey88': '#E0E0E0', + 'grey89': '#E3E3E3', + 'grey90': '#E5E5E5', + 'grey91': '#E8E8E8', + 'grey92': '#EBEBEB', + 'grey93': '#EDEDED', + 'grey94': '#F0F0F0', + 'grey95': '#F2F2F2', + 'grey96': '#F5F5F5', + 'grey97': '#F7F7F7', + 'grey98': '#FAFAFA', + 'grey99': '#FCFCFC', + 'grey100': '#FFFFFF', + 'honeydew': '#F0FFF0', + 'honeydew1': '#F0FFF0', + 'honeydew2': '#E0EEE0', + 'honeydew3': '#C1CDC1', + 'honeydew4': '#838B83', + 'hot pink': '#FF69B4', + 'HotPink': '#FF69B4', + 'HotPink1': '#FF6EB4', + 'HotPink2': '#EE6AA7', + 'HotPink3': '#CD6090', + 'HotPink4': '#8B3A62', + 'indian red': '#CD5C5C', + 'IndianRed': '#CD5C5C', + 'IndianRed1': '#FF6A6A', + 'IndianRed2': '#EE6363', + 'IndianRed3': '#CD5555', + 'IndianRed4': '#8B3A3A', + 'ivory': '#FFFFF0', + 'ivory1': '#FFFFF0', + 'ivory2': '#EEEEE0', + 'ivory3': '#CDCDC1', + 'ivory4': '#8B8B83', + 'khaki': '#F0E68C', + 'khaki1': '#FFF68F', + 'khaki2': '#EEE685', + 'khaki3': '#CDC673', + 'khaki4': '#8B864E', + 'lavender': '#E6E6FA', + 'lavender blush': '#FFF0F5', + 'LavenderBlush': '#FFF0F5', + 'LavenderBlush1': '#FFF0F5', + 'LavenderBlush2': '#EEE0E5', + 'LavenderBlush3': '#CDC1C5', + 'LavenderBlush4': '#8B8386', + 'lawn green': '#7CFC00', + 'LawnGreen': '#7CFC00', + 'lemon chiffon': '#FFFACD', + 'LemonChiffon': '#FFFACD', + 'LemonChiffon1': '#FFFACD', + 'LemonChiffon2': '#EEE9BF', + 'LemonChiffon3': '#CDC9A5', + 'LemonChiffon4': '#8B8970', + 'light blue': '#ADD8E6', + 'light coral': '#F08080', + 'light cyan': '#E0FFFF', + 'light goldenrod': '#EEDD82', + 'light goldenrod yellow': '#FAFAD2', + 'light gray': '#D3D3D3', + 'light green': '#90EE90', + 'light grey': '#D3D3D3', + 'light pink': '#FFB6C1', + 'light salmon': '#FFA07A', + 'light sea green': '#20B2AA', + 'light sky blue': '#87CEFA', + 'light slate blue': '#8470FF', + 'light slate gray': '#778899', + 'light slate grey': '#778899', + 'light steel blue': '#B0C4DE', + 'light yellow': '#FFFFE0', + 'LightBlue': '#ADD8E6', + 'LightBlue1': '#BFEFFF', + 'LightBlue2': '#B2DFEE', + 'LightBlue3': '#9AC0CD', + 'LightBlue4': '#68838B', + 'LightCoral': '#F08080', + 'LightCyan': '#E0FFFF', + 'LightCyan1': '#E0FFFF', + 'LightCyan2': '#D1EEEE', + 'LightCyan3': '#B4CDCD', + 'LightCyan4': '#7A8B8B', + 'LightGoldenrod': '#EEDD82', + 'LightGoldenrod1': '#FFEC8B', + 'LightGoldenrod2': '#EEDC82', + 'LightGoldenrod3': '#CDBE70', + 'LightGoldenrod4': '#8B814C', + 'LightGoldenrodYellow': '#FAFAD2', + 'LightGray': '#D3D3D3', + 'LightGreen': '#90EE90', + 'LightGrey': '#D3D3D3', + 'LightPink': '#FFB6C1', + 'LightPink1': '#FFAEB9', + 'LightPink2': '#EEA2AD', + 'LightPink3': '#CD8C95', + 'LightPink4': '#8B5F65', + 'LightSalmon': '#FFA07A', + 'LightSalmon1': '#FFA07A', + 'LightSalmon2': '#EE9572', + 'LightSalmon3': '#CD8162', + 'LightSalmon4': '#8B5742', + 'LightSeaGreen': '#20B2AA', + 'LightSkyBlue': '#87CEFA', + 'LightSkyBlue1': '#B0E2FF', + 'LightSkyBlue2': '#A4D3EE', + 'LightSkyBlue3': '#8DB6CD', + 'LightSkyBlue4': '#607B8B', + 'LightSlateBlue': '#8470FF', + 'LightSlateGray': '#778899', + 'LightSlateGrey': '#778899', + 'LightSteelBlue': '#B0C4DE', + 'LightSteelBlue1': '#CAE1FF', + 'LightSteelBlue2': '#BCD2EE', + 'LightSteelBlue3': '#A2B5CD', + 'LightSteelBlue4': '#6E7B8B', + 'LightYellow': '#FFFFE0', + 'LightYellow1': '#FFFFE0', + 'LightYellow2': '#EEEED1', + 'LightYellow3': '#CDCDB4', + 'LightYellow4': '#8B8B7A', + 'lime green': '#32CD32', + 'LimeGreen': '#32CD32', + 'linen': '#FAF0E6', + 'magenta': '#FF00FF', + 'magenta1': '#FF00FF', + 'magenta2': '#EE00EE', + 'magenta3': '#CD00CD', + 'magenta4': '#8B008B', + 'maroon': '#B03060', + 'maroon1': '#FF34B3', + 'maroon2': '#EE30A7', + 'maroon3': '#CD2990', + 'maroon4': '#8B1C62', + 'medium aquamarine': '#66CDAA', + 'medium blue': '#0000CD', + 'medium orchid': '#BA55D3', + 'medium purple': '#9370DB', + 'medium sea green': '#3CB371', + 'medium slate blue': '#7B68EE', + 'medium spring green': '#00FA9A', + 'medium turquoise': '#48D1CC', + 'medium violet red': '#C71585', + 'MediumAquamarine': '#66CDAA', + 'MediumBlue': '#0000CD', + 'MediumOrchid': '#BA55D3', + 'MediumOrchid1': '#E066FF', + 'MediumOrchid2': '#D15FEE', + 'MediumOrchid3': '#B452CD', + 'MediumOrchid4': '#7A378B', + 'MediumPurple': '#9370DB', + 'MediumPurple1': '#AB82FF', + 'MediumPurple2': '#9F79EE', + 'MediumPurple3': '#8968CD', + 'MediumPurple4': '#5D478B', + 'MediumSeaGreen': '#3CB371', + 'MediumSlateBlue': '#7B68EE', + 'MediumSpringGreen': '#00FA9A', + 'MediumTurquoise': '#48D1CC', + 'MediumVioletRed': '#C71585', + 'midnight blue': '#191970', + 'MidnightBlue': '#191970', + 'mint cream': '#F5FFFA', + 'MintCream': '#F5FFFA', + 'misty rose': '#FFE4E1', + 'MistyRose': '#FFE4E1', + 'MistyRose1': '#FFE4E1', + 'MistyRose2': '#EED5D2', + 'MistyRose3': '#CDB7B5', + 'MistyRose4': '#8B7D7B', + 'moccasin': '#FFE4B5', + 'navajo white': '#FFDEAD', + 'NavajoWhite': '#FFDEAD', + 'NavajoWhite1': '#FFDEAD', + 'NavajoWhite2': '#EECFA1', + 'NavajoWhite3': '#CDB38B', + 'NavajoWhite4': '#8B795E', + 'navy': '#000080', + 'navy blue': '#000080', + 'NavyBlue': '#000080', + 'old lace': '#FDF5E6', + 'OldLace': '#FDF5E6', + 'olive drab': '#6B8E23', + 'OliveDrab': '#6B8E23', + 'OliveDrab1': '#C0FF3E', + 'OliveDrab2': '#B3EE3A', + 'OliveDrab3': '#9ACD32', + 'OliveDrab4': '#698B22', + 'orange': '#FFA500', + 'orange red': '#FF4500', + 'orange1': '#FFA500', + 'orange2': '#EE9A00', + 'orange3': '#CD8500', + 'orange4': '#8B5A00', + 'OrangeRed': '#FF4500', + 'OrangeRed1': '#FF4500', + 'OrangeRed2': '#EE4000', + 'OrangeRed3': '#CD3700', + 'OrangeRed4': '#8B2500', + 'orchid': '#DA70D6', + 'orchid1': '#FF83FA', + 'orchid2': '#EE7AE9', + 'orchid3': '#CD69C9', + 'orchid4': '#8B4789', + 'pale goldenrod': '#EEE8AA', + 'pale green': '#98FB98', + 'pale turquoise': '#AFEEEE', + 'pale violet red': '#DB7093', + 'PaleGoldenrod': '#EEE8AA', + 'PaleGreen': '#98FB98', + 'PaleGreen1': '#9AFF9A', + 'PaleGreen2': '#90EE90', + 'PaleGreen3': '#7CCD7C', + 'PaleGreen4': '#548B54', + 'PaleTurquoise': '#AFEEEE', + 'PaleTurquoise1': '#BBFFFF', + 'PaleTurquoise2': '#AEEEEE', + 'PaleTurquoise3': '#96CDCD', + 'PaleTurquoise4': '#668B8B', + 'PaleVioletRed': '#DB7093', + 'PaleVioletRed1': '#FF82AB', + 'PaleVioletRed2': '#EE799F', + 'PaleVioletRed3': '#CD687F', + 'PaleVioletRed4': '#8B475D', + 'papaya whip': '#FFEFD5', + 'PapayaWhip': '#FFEFD5', + 'peach puff': '#FFDAB9', + 'PeachPuff': '#FFDAB9', + 'PeachPuff1': '#FFDAB9', + 'PeachPuff2': '#EECBAD', + 'PeachPuff3': '#CDAF95', + 'PeachPuff4': '#8B7765', + 'peru': '#CD853F', + 'pink': '#FFC0CB', + 'pink1': '#FFB5C5', + 'pink2': '#EEA9B8', + 'pink3': '#CD919E', + 'pink4': '#8B636C', + 'plum': '#DDA0DD', + 'plum1': '#FFBBFF', + 'plum2': '#EEAEEE', + 'plum3': '#CD96CD', + 'plum4': '#8B668B', + 'powder blue': '#B0E0E6', + 'PowderBlue': '#B0E0E6', + 'purple': '#A020F0', + 'purple1': '#9B30FF', + 'purple2': '#912CEE', + 'purple3': '#7D26CD', + 'purple4': '#551A8B', + 'red': '#FF0000', + 'red1': '#FF0000', + 'red2': '#EE0000', + 'red3': '#CD0000', + 'red4': '#8B0000', + 'rosy brown': '#BC8F8F', + 'RosyBrown': '#BC8F8F', + 'RosyBrown1': '#FFC1C1', + 'RosyBrown2': '#EEB4B4', + 'RosyBrown3': '#CD9B9B', + 'RosyBrown4': '#8B6969', + 'royal blue': '#4169E1', + 'RoyalBlue': '#4169E1', + 'RoyalBlue1': '#4876FF', + 'RoyalBlue2': '#436EEE', + 'RoyalBlue3': '#3A5FCD', + 'RoyalBlue4': '#27408B', + 'saddle brown': '#8B4513', + 'SaddleBrown': '#8B4513', + 'salmon': '#FA8072', + 'salmon1': '#FF8C69', + 'salmon2': '#EE8262', + 'salmon3': '#CD7054', + 'salmon4': '#8B4C39', + 'sandy brown': '#F4A460', + 'SandyBrown': '#F4A460', + 'sea green': '#2E8B57', + 'SeaGreen': '#2E8B57', + 'SeaGreen1': '#54FF9F', + 'SeaGreen2': '#4EEE94', + 'SeaGreen3': '#43CD80', + 'SeaGreen4': '#2E8B57', + 'seashell': '#FFF5EE', + 'seashell1': '#FFF5EE', + 'seashell2': '#EEE5DE', + 'seashell3': '#CDC5BF', + 'seashell4': '#8B8682', + 'sienna': '#A0522D', + 'sienna1': '#FF8247', + 'sienna2': '#EE7942', + 'sienna3': '#CD6839', + 'sienna4': '#8B4726', + 'sky blue': '#87CEEB', + 'SkyBlue': '#87CEEB', + 'SkyBlue1': '#87CEFF', + 'SkyBlue2': '#7EC0EE', + 'SkyBlue3': '#6CA6CD', + 'SkyBlue4': '#4A708B', + 'slate blue': '#6A5ACD', + 'slate gray': '#708090', + 'slate grey': '#708090', + 'SlateBlue': '#6A5ACD', + 'SlateBlue1': '#836FFF', + 'SlateBlue2': '#7A67EE', + 'SlateBlue3': '#6959CD', + 'SlateBlue4': '#473C8B', + 'SlateGray': '#708090', + 'SlateGray1': '#C6E2FF', + 'SlateGray2': '#B9D3EE', + 'SlateGray3': '#9FB6CD', + 'SlateGray4': '#6C7B8B', + 'SlateGrey': '#708090', + 'snow': '#FFFAFA', + 'snow1': '#FFFAFA', + 'snow2': '#EEE9E9', + 'snow3': '#CDC9C9', + 'snow4': '#8B8989', + 'spring green': '#00FF7F', + 'SpringGreen': '#00FF7F', + 'SpringGreen1': '#00FF7F', + 'SpringGreen2': '#00EE76', + 'SpringGreen3': '#00CD66', + 'SpringGreen4': '#008B45', + 'steel blue': '#4682B4', + 'SteelBlue': '#4682B4', + 'SteelBlue1': '#63B8FF', + 'SteelBlue2': '#5CACEE', + 'SteelBlue3': '#4F94CD', + 'SteelBlue4': '#36648B', + 'tan': '#D2B48C', + 'tan1': '#FFA54F', + 'tan2': '#EE9A49', + 'tan3': '#CD853F', + 'tan4': '#8B5A2B', + 'thistle': '#D8BFD8', + 'thistle1': '#FFE1FF', + 'thistle2': '#EED2EE', + 'thistle3': '#CDB5CD', + 'thistle4': '#8B7B8B', + 'tomato': '#FF6347', + 'tomato1': '#FF6347', + 'tomato2': '#EE5C42', + 'tomato3': '#CD4F39', + 'tomato4': '#8B3626', + 'turquoise': '#40E0D0', + 'turquoise1': '#00F5FF', + 'turquoise2': '#00E5EE', + 'turquoise3': '#00C5CD', + 'turquoise4': '#00868B', + 'violet': '#EE82EE', + 'violet red': '#D02090', + 'VioletRed': '#D02090', + 'VioletRed1': '#FF3E96', + 'VioletRed2': '#EE3A8C', + 'VioletRed3': '#CD3278', + 'VioletRed4': '#8B2252', + 'wheat': '#F5DEB3', + 'wheat1': '#FFE7BA', + 'wheat2': '#EED8AE', + 'wheat3': '#CDBA96', + 'wheat4': '#8B7E66', + 'white': '#FFFFFF', + 'white smoke': '#F5F5F5', + 'WhiteSmoke': '#F5F5F5', + 'yellow': '#FFFF00', + 'yellow green': '#9ACD32', + 'yellow1': '#FFFF00', + 'yellow2': '#EEEE00', + 'yellow3': '#CDCD00', + 'yellow4': '#8B8B00', + 'YellowGreen': '#9ACD32', + } + + sg.change_look_and_feel('Dark Blue 3') + + button_size = (1,1) + # button_size = (None,None) # for very compact buttons + + def ColorButton(color): + """ + A User Defined Element - returns a Button that configured in a certain way. + :param color: Tuple[str, str] ( color name, hex string) + :return: sg.Button object + """ + return sg.B(button_color=('white', color[1]), pad=(0,0), size=button_size,key=color, tooltip=f'{color[0]}:{color[1]}', border_width=0) + + num_colors = len(list(color_map.keys())) + row_len=40 + + grid = [[ColorButton(list(color_map.items())[c+j*row_len]) for c in range(0,row_len)] for j in range(0,num_colors//row_len)] + grid += [[ColorButton(list(color_map.items())[c+num_colors-num_colors%row_len]) for c in range(0,num_colors%row_len)]] + + layout = [ [sg.Text('Pick a color', font='Def 18')]] + grid + \ + [[sg.Button('OK'), sg.T(size=(30,1), key='-OUT-')]] + + window = sg.Window('Window Title', layout, no_titlebar=True, grab_anywhere=True, keep_on_top=True, use_ttk_buttons=True) + color_chosen = None + while True: # Event Loop + event, values = window.read() + if event in (None, 'OK'): + if event is None: + color_chosen = None + break + window['-OUT-'](f'You chose {event[0]} : {event[1]}') + color_chosen = event[1] + window.close() + return color_chosen + + +if __name__ == '__main__': + sg.change_look_and_feel('Light Brown 4') + layout = [[sg.In(key='-CHOICE-'), sg.B('Color Picker')], + [sg.Ok(), sg.Cancel()]] + window = sg.Window('My application', layout) + while True: + event, values = window.read() + if event in (None, 'Cancel'): + break + if event.startswith('Color'): + window.hide() + color_chosen = color_chooser() + window['-CHOICE-'].update(color_chosen) + window.un_hide() diff --git a/PySimpleGUIQt/Demo Programs/Demo_Design_Pattern_Multiple_Windows.py b/PySimpleGUIQt/Demo Programs/Demo_Design_Pattern_Multiple_Windows.py new file mode 100644 index 000000000..8f50bf4f6 --- /dev/null +++ b/PySimpleGUIQt/Demo Programs/Demo_Design_Pattern_Multiple_Windows.py @@ -0,0 +1,59 @@ +import sys +if sys.version_info[0] >= 3: + import PySimpleGUIQt as sg +else: + import PySimpleGUI27 as sg + +""" + Demo - Running 2 windows with both being active at the same time + Three important things to note about this design patter: + 1. The layout for window 2 is inside of the while loop, just before the call to window2=sg.Window + 2. The read calls have timeout values of 100 and 0. You can change the 100 to whatever interval you wish + but must keep the second window's timeout at 0 + 3. There is a safeguard to stop from launching multiple copies of window2. Only 1 window2 is visible at a time +""" + +# Window 1 layout +layout = [ + [sg.Text('This is the FIRST WINDOW'), sg.Text(' ', key='_OUTPUT_')], + [sg.Text('')], + [sg.Button('Launch 2nd Window'),sg.Button('Popup'), sg.Button('Exit')] + ] + +window = sg.Window('Window Title', location=(800,600)).Layout(layout) +win2_active = False +i=0 +while True: # Event Loop + event, values = window.Read(timeout=100) + if event != sg.TIMEOUT_KEY: + print(i, event, values) + + if event is None or event == 'Exit': + break + elif event == 'Popup': + sg.Popup('This is a BLOCKING popup','all windows remain inactive while popup active') + i+=1 + if event == 'Launch 2nd Window' and not win2_active: # only run if not already showing a window2 + win2_active = True + # window 2 layout - note - must be "new" every time a window is created + layout2 = [ + [sg.Text('The second window'), sg.Text('', key='_OUTPUT_')], + [sg.Input(do_not_clear=True, key='_IN_')], + [sg.Button('Show'), sg.Button('Exit')] + ] + window2 = sg.Window('Second Window').Layout(layout2) + # Read window 2's events. Must use timeout of 0 + if win2_active: + # print("reading 2") + event, values = window2.Read(timeout=100) + # print("win2 ", event) + if event != sg.TIMEOUT_KEY: + print("win2 ", event) + if event == 'Exit' or event is None: + # print("Closing window 2", event) + win2_active = False + window2.Close() + if event == 'Show': + sg.Popup('You entered ', values['_IN_']) + +window.Close() \ No newline at end of file diff --git a/PySimpleGUIQt/Demo Programs/Demo_Design_Pattern_Multiple_Windows1.py b/PySimpleGUIQt/Demo Programs/Demo_Design_Pattern_Multiple_Windows1.py new file mode 100644 index 000000000..ba3f765e1 --- /dev/null +++ b/PySimpleGUIQt/Demo Programs/Demo_Design_Pattern_Multiple_Windows1.py @@ -0,0 +1,35 @@ +""" + PySimpleGUI The Complete Course + Lesson 7 - Multiple Windows +""" +import PySimpleGUIQt as sg + +# Design pattern 1 - First window does not remain active + +layout = [[ sg.Text('Window 1'),], + [sg.Input(do_not_clear=True)], + [sg.Text('', key='_OUTPUT_')], + [sg.Button('Launch 2')]] + +win1 = sg.Window('Window 1').Layout(layout) +win2_active=False +while True: + ev1, vals1 = win1.Read(timeout=100) + if ev1 is None: + break + win1.FindElement('_OUTPUT_').Update(vals1[0]) + + if ev1 == 'Launch 2' and not win2_active: + win2_active = True + win1.Disappear() + layout2 = [[sg.Text('Window 2')], + [sg.Button('Exit')]] + + win2 = sg.Window('Window 2').Layout(layout2) + while True: + ev2, vals2 = win2.Read() + if ev2 is None or ev2 == 'Exit': + win2.Close() + win2_active = False + win1.Reappear() + break diff --git a/PySimpleGUIQt/Demo Programs/Demo_Design_Pattern_Multiple_Windows2.py b/PySimpleGUIQt/Demo Programs/Demo_Design_Pattern_Multiple_Windows2.py new file mode 100644 index 000000000..a30964d10 --- /dev/null +++ b/PySimpleGUIQt/Demo Programs/Demo_Design_Pattern_Multiple_Windows2.py @@ -0,0 +1,34 @@ +""" + PySimpleGUI The Complete Course + Lesson 7 - Multiple Windows +""" +import PySimpleGUI as sg + +# Design pattern 2 - First window remains active + +layout = [[ sg.Text('Window 1'),], + [sg.Input(do_not_clear=True)], + [sg.Text('', key='_OUTPUT_')], + [sg.Button('Launch 2'), sg.Button('Exit')]] + +win1 = sg.Window('Window 1').Layout(layout) + +win2_active = False +while True: + ev1, vals1 = win1.Read(timeout=100) + win1.FindElement('_OUTPUT_').Update(vals1[0]) + if ev1 is None or ev1 == 'Exit': + break + + if not win2_active and ev1 == 'Launch 2': + win2_active = True + layout2 = [[sg.Text('Window 2')], + [sg.Button('Exit')]] + + win2 = sg.Window('Window 2').Layout(layout2) + + if win2_active: + ev2, vals2 = win2.Read(timeout=100) + if ev2 is None or ev2 == 'Exit': + win2_active = False + win2.Close() diff --git a/PySimpleGUIQt/Demo Programs/Demo_HowDoI.py b/PySimpleGUIQt/Demo Programs/Demo_HowDoI.py new file mode 100644 index 000000000..0eaa947ad --- /dev/null +++ b/PySimpleGUIQt/Demo Programs/Demo_HowDoI.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python +import sys +import PySimpleGUIQt as sg +import subprocess + + +# Test this command in a dos window if you are having trouble. +HOW_DO_I_COMMAND = 'python -m howdoi.howdoi' + +# if you want an icon on your taskbar for this gui, then change this line of code to point to the ICO file +DEFAULT_ICON = 'question.ico' + +def HowDoI(): + ''' + Make and show a window (PySimpleGUI form) that takes user input and sends to the HowDoI web oracle + Excellent example of 2 GUI concepts + 1. Output Element that will show text in a scrolled window + 2. Non-Window-Closing Buttons - These buttons will cause the form to return with the form's values, but doesn't close the form + :return: never returns + ''' + # ------- Make a new Window ------- # + sg.ChangeLookAndFeel('GreenTan') # give our form a spiffy set of colors + + layout = [ + [sg.Text('Ask and your answer will appear here....')], + [sg.Output(size=(900, 500), font=('Courier', 10))], + [ sg.Spin(values=(1, 4), initial_value=1, size=(50, 25), key='Num Answers', font=('Helvetica', 15)), + sg.Text('Num Answers',font=('Helvetica', 15), size=(170,22)), sg.Checkbox('Display Full Text', key='full text', font=('Helvetica', 15), size=(200,22)), + sg.T('Command History', font=('Helvetica', 15)), sg.T('', size=(100,25), text_color=sg.BLUES[0], key='history'), sg.Stretch()], + [sg.Multiline(size=(600, 100), enter_submits=True, focus=True, key='query', do_not_clear=False), sg.Stretch(), + sg.ReadButton('SEND', button_color=(sg.YELLOWS[0], sg.BLUES[0]), bind_return_key=True), + sg.Button('EXIT', button_color=(sg.YELLOWS[0], sg.GREENS[0])), sg.Stretch()] + ] + + window = sg.Window('How Do I ??', + default_element_size=(100, 25), + # element_padding=(10,10), + icon=DEFAULT_ICON, + font=('Helvetica',14), + default_button_element_size=(70,50), + return_keyboard_events=True, + no_titlebar=False, + grab_anywhere=True,) + + window.Layout(layout) + # ---===--- Loop taking in user input and using it to query HowDoI --- # + command_history = [] + history_offset = 0 + while True: + event, values = window.Read() + if event == 'SEND' or event == 'query': + # window.FindElement('+OUTPUT+').Update('test of output') # manually clear input because keyboard events blocks clear + + query = values['query'].rstrip() + # print(query) + QueryHowDoI(query, values['Num Answers'], values['full text']) # send the string to HowDoI + command_history.append(query) + history_offset = len(command_history)-1 + window.FindElement('query').Update('') # manually clear input because keyboard events blocks clear + window.FindElement('history').Update('\n'.join(command_history[-3:])) + elif event == None or event == 'EXIT': # if exit button or closed using X + break + elif 'Up' in event and len(command_history): # scroll back in history + command = command_history[history_offset] + history_offset -= 1 * (history_offset > 0) # decrement is not zero + window.FindElement('query').Update(command) + elif 'Down' in event and len(command_history): # scroll forward in history + history_offset += 1 * (history_offset < len(command_history)-1) # increment up to end of list + command = command_history[history_offset] + window.FindElement('query').Update(command) + elif 'Escape' in event: # clear currently line + window.FindElement('query').Update('') + + +def QueryHowDoI(Query, num_answers, full_text): + ''' + Kicks off a subprocess to send the 'Query' to HowDoI + Prints the result, which in this program will route to a gooeyGUI window + :param Query: text english question to ask the HowDoI web engine + :return: nothing + ''' + howdoi_command = HOW_DO_I_COMMAND + full_text_option = ' -a' if full_text else '' + t = subprocess.Popen(howdoi_command + ' \"'+ Query + '\" -n ' + str(num_answers)+full_text_option, stdout=subprocess.PIPE) + (output, err) = t.communicate() + print('{:^88}'.format(Query.rstrip())) + print('_'*60) + print(output.decode("utf-8") ) + exit_code = t.wait() + +if __name__ == '__main__': + HowDoI() + diff --git a/PySimpleGUIQt/Demo Programs/Demo_Tree_Element.py b/PySimpleGUIQt/Demo Programs/Demo_Tree_Element.py new file mode 100644 index 000000000..c96c9e293 --- /dev/null +++ b/PySimpleGUIQt/Demo Programs/Demo_Tree_Element.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python +import PySimpleGUIQt as sg + +treedata = sg.TreeData() +green = r'C:/Python/PycharmProjects/GooeyGUI/ButtonGraphics/Oct16/Mac/green30.png' +orange = r'C:\Python\PycharmProjects\GooeyGUI\ButtonGraphics\Oct16\Mac\orange30.png' +red = r'C:\Python\PycharmProjects\GooeyGUI\ButtonGraphics\Oct16\Mac\red30.png' +treedata.Insert("", '_A_', 'A', [1,2,3], orange) +treedata.Insert("", '_B_', 'B', [4,5,6], green) +treedata.Insert("_A_", '_A1_', 'A1', ['can','be','anything'], red) +treedata.Insert("", '_C_', 'C', [], red) +treedata.Insert("_C_", '_C1_', 'C1', ['or'], green) +treedata.Insert("_A_", '_A2_', 'A2', [None, None]) +treedata.Insert("_A1_", '_A3_', 'A30', ['getting deep']) +treedata.Insert("_C_", '_C2_', 'C2', ['nothing', 'at', 'all']) + +for i in range(100): + treedata.Insert('_C_', i, i, []) + +layout = [[ sg.Text('Tree Test') ], + [ sg.Tree(data=treedata, headings=['col1', 'col2', 'col3'],change_submits=True, auto_size_columns=True, num_rows=10, col0_width=10, key='_TREE_', show_expanded=True, size=(300,300)), + ], + [ sg.Button('Read'), sg.Button('Update')]] + +window = sg.Window('Tree Element Test').Layout(layout) + +print(treedata) +filename = r'C:/Python/PycharmProjects/GooeyGUI/ButtonGraphics/Oct16/Mac/green30.png' +while True: # Event Loop + event, values = window.Read() + if event is None: + break + if event == 'Update': + treedata = sg.TreeData() + treedata.Insert("", '_A_', 'A', [1, 2, 3], filename ) + treedata.Insert("", '_B_', 'B', [4, 5, 6], filename) + treedata.Insert("_A_", '_A1_', 'A1', ['can', 'be', 'anything'], filename) + treedata.Insert("", '_C_', 'C', [], filename) + treedata.Insert("_C_", '_C1_', 'C1', ['or']) + treedata.Insert("_A_", '_A2_', 'A2', [None, None]) + window.FindElement('_TREE_').Update(treedata) + elif event == 'Read': + print(event, values) diff --git a/PySimpleGUIQt/Demo Programs/Qt_All_Widgets.py b/PySimpleGUIQt/Demo Programs/Qt_All_Widgets.py new file mode 100644 index 000000000..10b31d596 --- /dev/null +++ b/PySimpleGUIQt/Demo Programs/Qt_All_Widgets.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python +import PySimpleGUIQt as sg + +sg.ChangeLookAndFeel('GreenTan') +# sg.SetOptions(text_color='white') +# ------ Column Definition ------ # +column1 = [[sg.Text('Column 1', background_color='lightblue',text_color='black', justification='center', size=(100,22))], + [sg.Spin((1,10), size=(100,22))], + [sg.Spin((1,10), size=(100,22))], + [sg.Spin((1,10), size=(100,22))],] + +layout = [ + [sg.Text('(Almost) All widgets in one Window!',click_submits=True, key='TEXT', justification='c', font=("Helvetica", 25), relief=sg.RELIEF_RAISED, tooltip='Text Element')], + [sg.Text('Here is some text.... and a place to enter text')], + [sg.InputText('This is my text', size=(400,25))], + [sg.Frame(layout=[ + [sg.Checkbox('Checkbox', size=(185,22)), sg.Checkbox('My second checkbox!', default=True)], + [sg.Radio('My first Radio!', "RADIO1", default=True, size=(180,22), ),sg.Radio('My second Radio!', "RADIO1")], + [sg.Radio('Third Radio!', "RADIO2", default=True, size=(180,22), ), + sg.Radio('Fourth Radio!', "RADIO2")]], title='Options',title_color='red', relief=sg.RELIEF_SUNKEN, + tooltip='Use these to set flags', ), sg.Stretch()], + [sg.Multiline(default_text='This is the default Text should you decide not to type anything',focus=True, size=(220, 80)), + sg.Multiline(default_text='A second multi-line', size=(220, 80))], + [sg.InputCombo(('Combobox 1', 'Combobox 2'), size=(150, 25)), sg.Stretch(), + sg.Slider(range=(1, 100), orientation='h', size=(300, 22), default_value=85)], + [sg.InputOptionMenu(('Menu Option 1', 'Menu Option 2', 'Menu Option 3'))], + [sg.Listbox(values=('Listbox 1', 'Listbox 2', 'Listbox 3'), size=(200,100), select_mode=sg.LISTBOX_SELECT_MODE_EXTENDED), sg.Stretch(), + sg.Frame('Labelled Group',[[ + sg.Slider(range=(1, 100), orientation='v', default_value=25, tick_interval=25), + sg.Slider(range=(1, 100), orientation='v', default_value=75), + sg.Slider(range=(1, 100), orientation='v', default_value=10), + sg.Column(column1, background_color='lightblue')]], ), sg.Stretch(), sg.Dial((1,100))], + [sg.Text('_' * 50, justification='c')], + [sg.Text('Choose A Folder')], + [sg.Text('Your Folder'), + sg.InputText('Default Folder', size=(300,22)), sg.FolderBrowse(), sg.Stretch()], + [sg.Submit(tooltip='Click to submit this form',), sg.Cancel()]] + +window = sg.Window('Everything bagel', + grab_anywhere=False, + font=('Helvetica', 12), + no_titlebar=False, + alpha_channel=1, + keep_on_top=False, + element_padding=(2,3), + default_element_size=(100, 23), + default_button_element_size=(120,30), + # background_image='C:\Python\PycharmProjects\GooeyGUI\logo500black.png', + ).Layout(layout) +event, values = window.Read() +print(event, values) +window.Close() + +sg.Popup('Title', + 'The results of the window.', + 'The button clicked was "{}"'.format(event), + 'The values are', values,) + + diff --git a/PySimpleGUIQt/Demo Programs/Qt_Demo_Desktop_Widget_CPU_Dashboard.py b/PySimpleGUIQt/Demo Programs/Qt_Demo_Desktop_Widget_CPU_Dashboard.py new file mode 100644 index 000000000..a2049732d --- /dev/null +++ b/PySimpleGUIQt/Demo Programs/Qt_Demo_Desktop_Widget_CPU_Dashboard.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python +import sys +if sys.version_info[0] >= 3: + import PySimpleGUIQt as sg +else: + import PySimpleGUI27 as sg +import psutil + +""" + Desktop floating widget - CPU Cores + Uses psutil to display: + CPU usage on each individual core + Information is updated once a second and is shown as an area graph that scrolls +""" + +GRAPH_WIDTH = 120 # each individual graph size in pixels +GRAPH_HEIGHT = 60 +TRANSPARENCY = .8 # how transparent the window looks. 0 = invisible, 1 = normal window +NUM_COLS = 4 +POLL_FREQUENCY = 800 # how often to update graphs in milliseconds + +colors = ('#23a0a0', '#56d856', '#be45be', '#5681d8', '#d34545', '#BE7C29') + +# DashGraph does the drawing of each graph +class DashGraph(object): + def __init__(self, graph_elem, text_elem, starting_count, color): + self.graph_current_item = 0 + self.graph_elem = graph_elem + self.text_elem = text_elem + self.prev_value = starting_count + self.max_sent = 1 + self.color = color + + def graph_percentage_abs(self, value): + self.graph_elem.DrawLine((self.graph_current_item, 0), (self.graph_current_item, value), color=self.color) + if self.graph_current_item >= GRAPH_WIDTH: + self.graph_elem.Move(-1,0) + else: + self.graph_current_item += 1 + + def text_display(self, text): + self.text_elem.Update(text) + +def main(): + # A couple of "Uber Elements" that combine several elements and enable bulk edits + def Txt(text, **kwargs): + return(sg.Text(text, font=('Helvetica 8'), **kwargs)) + + def GraphColumn(name, key): + col = sg.Column([[Txt(name, key=key+'_TXT_'), ], + [sg.Graph((GRAPH_WIDTH, GRAPH_HEIGHT), (0, 0), (GRAPH_WIDTH, 100), background_color='black', + key=key+'_GRAPH_')]], pad=(2, 2)) + return col + + + num_cores = len(psutil.cpu_percent(percpu=True)) # get the number of cores in the CPU + + sg.ChangeLookAndFeel('Black') + sg.SetOptions(element_padding=(0,0), margins=(0,0), border_width=0) + + # ---------------- Create Layout ---------------- + layout = [[ sg.Button('', image_data=red_x , button_color=('red', 'black'), key='Exit', tooltip='Closes window'),sg.Stretch(), + sg.Text(' CPU Core Usage'), sg.Stretch()] ] + + # add on the graphs + for rows in range(num_cores//NUM_COLS+1): + row = [] + for cols in range(min(num_cores-rows*NUM_COLS, NUM_COLS)): + row.append(GraphColumn('CPU '+str(rows*NUM_COLS+cols), '_CPU_'+str(rows*NUM_COLS+cols))) + layout.append(row) + + # ---------------- Create Window ---------------- + window = sg.Window('PSG System Dashboard', + keep_on_top=True, + auto_size_buttons=False, + grab_anywhere=True, + no_titlebar=True, + default_button_element_size=(20, 15), + return_keyboard_events=True, + alpha_channel=TRANSPARENCY, + use_default_focus=False, + ).Layout(layout) + + # setup graphs & initial values + graphs = [] + for i in range(num_cores): + graphs.append(DashGraph(window.FindElement('_CPU_'+str(i)+'_GRAPH_'), + window.FindElement('_CPU_'+str(i) + '_TXT_'), + 0, colors[i%6])) + + # ---------------- main loop ---------------- + while (True): + # --------- Read and update window once every Polling Frequency -------- + event, values = window.Read(timeout=POLL_FREQUENCY) + if event in (None, 'Exit'): # Be nice and give an exit + break + # read CPU for each core + stats = psutil.cpu_percent(interval=.2, percpu=True) + # Update each graph + for i in range(num_cores): + graphs[i].graph_percentage_abs(stats[i]) + graphs[i].text_display('{} CPU {:2.0f}'.format(i, stats[i])) + window.Close() + +if __name__ == "__main__": + # the clever Red X graphic + red_x = b"R0lGODlhEAAQAPeQAIsAAI0AAI4AAI8AAJIAAJUAAJQCApkAAJoAAJ4AAJkJCaAAAKYAAKcAAKcCAKcDA6cGAKgAAKsAAKsCAKwAAK0AAK8AAK4CAK8DAqUJAKULAKwLALAAALEAALIAALMAALMDALQAALUAALYAALcEALoAALsAALsCALwAAL8AALkJAL4NAL8NAKoTAKwbAbEQALMVAL0QAL0RAKsREaodHbkQELMsALg2ALk3ALs+ALE2FbgpKbA1Nbc1Nb44N8AAAMIWAMsvAMUgDMcxAKVABb9NBbVJErFYEq1iMrtoMr5kP8BKAMFLAMxKANBBANFCANJFANFEB9JKAMFcANFZANZcANpfAMJUEMZVEc5hAM5pAMluBdRsANR8AM9YOrdERMpIQs1UVMR5WNt8X8VgYMdlZcxtYtx4YNF/btp9eraNf9qXXNCCZsyLeNSLd8SSecySf82kd9qqc9uBgdyBgd+EhN6JgtSIiNuJieGHhOGLg+GKhOKamty1ste4sNO+ueenp+inp+HHrebGrefKuOPTzejWzera1O7b1vLb2/bl4vTu7fbw7ffx7vnz8f///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAJAALAAAAAAQABAAAAjUACEJHEiwYEEABniQKfNFgQCDkATQwAMokEU+PQgUFDAjjR09e/LUmUNnh8aBCcCgUeRmzBkzie6EeQBAoAAMXuA8ciRGCaJHfXzUMCAQgYooWN48anTokR8dQk4sELggBhQrU9Q8evSHiJQgLCIIfMDCSZUjhbYuQkLFCRAMAiOQGGLE0CNBcZYmaRIDLqQFGF60eTRoSxc5jwjhACFWIAgMLtgUocJFy5orL0IQRHAiQgsbRZYswbEhBIiCCH6EiJAhAwQMKU5DjHCi9gnZEHMTDAgAOw==" + + main() + sys.exit(69) \ No newline at end of file diff --git a/PySimpleGUIQt/Demo Programs/Qt_Demo_Desktop_Widget_CPU_Graph.py b/PySimpleGUIQt/Demo Programs/Qt_Demo_Desktop_Widget_CPU_Graph.py new file mode 100644 index 000000000..0d5cdaaf3 --- /dev/null +++ b/PySimpleGUIQt/Demo Programs/Qt_Demo_Desktop_Widget_CPU_Graph.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python +import sys +import sys +if sys.version_info[0] >= 3: + import PySimpleGUIQt as sg +else: + import PySimpleGUI27 as sg +import time +import random +import psutil +from threading import Thread + + +STEP_SIZE=3 +SAMPLES = 300 +SAMPLE_MAX = 500 +CANVAS_SIZE = (300,200) + + +g_interval = .25 +g_cpu_percent = 0 +g_procs = None +g_exit = False + +def CPU_thread(args): + global g_interval, g_cpu_percent, g_procs, g_exit + + while not g_exit: + try: + g_cpu_percent = psutil.cpu_percent(interval=g_interval) + g_procs = psutil.process_iter() + except: + pass + +def main(): + global g_exit, g_response_time + # start ping measurement thread + + sg.ChangeLookAndFeel('Black') + sg.SetOptions(element_padding=(0,0)) + + layout = [ [sg.Quit( button_color=('white','black')), sg.T('', font='Helvetica 25', key='output')], + [sg.Graph(CANVAS_SIZE, (0,0), (SAMPLES,SAMPLE_MAX),background_color='black', key='graph')],] + + window = sg.Window('CPU Graph', grab_anywhere=True, keep_on_top=True, background_color='black', no_titlebar=True, use_default_focus=False, location=(0,0)).Layout(layout) + + graph = window.FindElement('graph') + output = window.FindElement('output') + # start cpu measurement thread + thread = Thread(target=CPU_thread,args=(None,)) + thread.start() + + last_cpu = i = 0 + prev_x, prev_y = 0, 0 + while True: # the Event Loop + event, values = window.Read(timeout=500) + if event == 'Quit' or event is None: # always give ths user a way out + break + # do CPU measurement and graph it + current_cpu = int(g_cpu_percent*10) + if current_cpu == last_cpu: + continue + output.Update(current_cpu/10) # show current cpu usage at top + if current_cpu > SAMPLE_MAX: + current_cpu = SAMPLE_MAX + new_x, new_y = i, current_cpu + if i >= SAMPLES: + graph.Move(-STEP_SIZE,0) # shift graph over if full of data + prev_x = prev_x - STEP_SIZE + graph.DrawLine((prev_x, prev_y), (new_x, new_y), color='white') + prev_x, prev_y = new_x, new_y + i += STEP_SIZE if i < SAMPLES else 0 + last_cpu = current_cpu + + g_exit = True + window.Close() +if __name__ == '__main__': + main() diff --git a/PySimpleGUIQt/Demo Programs/Qt_Demo_Desktop_Widget_Timer.py b/PySimpleGUIQt/Demo Programs/Qt_Demo_Desktop_Widget_Timer.py new file mode 100644 index 000000000..7f108c9c1 --- /dev/null +++ b/PySimpleGUIQt/Demo Programs/Qt_Demo_Desktop_Widget_Timer.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python +import sys + +if sys.version_info[0] >= 3: + import PySimpleGUIQt as sg +else: + import PySimpleGUI27 as sg +import time + +""" + Timer Desktop Widget Creates a floating timer that is always on top of other windows You move it by grabbing anywhere on the window Good example of how to do a non-blocking, polling program using SimpleGUI Can be used to poll hardware when running on a Pi + + While the timer ticks are being generated by PySimpleGUI's "timeout" mechanism, the actual value + of the timer that is displayed comes from the system timer, time.time(). This guarantees an + accurate time value is displayed regardless of the accuracy of the PySimpleGUI timer tick. If + this design were not used, then the time value displayed would slowly drift by the amount of time + it takes to execute the PySimpleGUI read and update calls (not good!) + + NOTE - you will get a warning message printed when you exit using exit button. + It will look something like: invalid command name \"1616802625480StopMove\" +""" + +# ---------------- Create Form ---------------- +sg.ChangeLookAndFeel('Black') +sg.SetOptions(element_padding=(0, 0)) + +layout = [ + [sg.Text('test', size=(222, 90), font=('Any', 24), text_color='white', justification='center', key='text')], + [sg.Button('Pause', key='button', button_color=('white', '#001480')), + sg.Button('Reset', button_color=('white', '#007339'), key='Reset'), + sg.Exit(button_color=('white', '#B22222'), key='Exit')] +] + +window = sg.Window('Running Timer', no_titlebar=True, auto_size_buttons=False, keep_on_top=True, + grab_anywhere=True).Layout(layout) + +# ---------------- main loop ---------------- +current_time = 0 +paused = False +start_time = int(round(time.time() * 100)) +while (True): + # --------- Read and update window -------- + if not paused: + event, values = window.Read(timeout=10) + current_time = int(round(time.time() * 100)) - start_time + else: + event, values = window.Read() + if event == 'button': + event = window.FindElement(event).GetText() + # --------- Do Button Operations -------- + if event in (None, 'Exit'): # ALWAYS give a way out of program + break + if event == 'Reset': + start_time = int(round(time.time() * 100)) + current_time = 0 + paused_time = start_time + elif event == 'Pause': + paused = True + paused_time = int(round(time.time() * 100)) + element = window.FindElement('button') + element.Update(text='Run') + elif event == 'Run': + paused = False + start_time = start_time + int(round(time.time() * 100)) - paused_time + element = window.FindElement('button') + element.Update(text='Pause') + + # --------- Display timer in window -------- + window.FindElement('text').Update('{:02d}:{:02d}.{:02d}'.format((current_time // 100) // 60, + (current_time // 100) % 60, + current_time % 100)) +# --------- After loop -------- diff --git a/PySimpleGUIQt/Demo Programs/Qt_Demo_LED_Clock_Weather.py b/PySimpleGUIQt/Demo Programs/Qt_Demo_LED_Clock_Weather.py new file mode 100644 index 000000000..9787813cd --- /dev/null +++ b/PySimpleGUIQt/Demo Programs/Qt_Demo_LED_Clock_Weather.py @@ -0,0 +1,179 @@ +#!/usr/bin/env python +import sys +import PySimpleGUIQt as sg +import datetime +import calendar +import forecastio + +##### CHANGE these settings to match your location... check Google Maps ##### +MY_LOCATION_LAT = 35.000000 +MY_LOCATION_LON = -79.000000 +##### You need a free dark-sky key. You get 1000 calls a month for free ##### +DARKSKY_KEY = "" # *** INSERT YOUR DARKSKY KEY HERE ** + +NUM_COLS = 5 # Changes number of days in forecast + + +class GUI(): + def __init__(self): + self.api_key = DARKSKY_KEY + self.lat = MY_LOCATION_LAT + self.lng = MY_LOCATION_LON + self.blink_count = 0 + + sg.SetOptions(border_width=0, + text_color='white', + background_color='black', + text_element_background_color='black', + element_padding=(0,0)) + + # Create clock layout + clock = [ + [sg.T('', pad=(0,0)), + sg.Image(data_base64=led0[22:], key='_hour1_', pad=(0,0)), + sg.Image(data_base64=led0[22:], key='_hour2_', pad=(0,0)), + sg.Image(data_base64=ledblank[22:], key='_colon_', pad=(0,0)), + sg.Image(data_base64=ledblank[22:], key='_min1_', pad=(0,0)), + sg.Image(data_base64=ledblank[22:], key='_min2_', pad=(0,0))], ] + + # Create the weather columns layout + weather_cols = [] + for i in range(NUM_COLS): + weather_cols.append( + [[sg.T('', size=(60,30), font='Any 20', justification='center', key='_DAY_' + str(i)), ], + [sg.Image(data_base64=w1[22:], background_color='black', key='_icon_'+str(i), pad=((4, 0), 3)), ], + [sg.T('--', size=(60,50), justification='center', font='Any 20', key='_high_' + str(i), pad=((10, 0), 3))], + [sg.T('--', size=(60,50), justification='center', font='Any 20', key='_low_' + str(i), pad=((10, 0), 3))]]) + + # Create the overall layout + layout = [[sg.Column(clock, background_color='black')], + [sg.Column(weather_cols[x], background_color='black') for x in range(NUM_COLS)], + + [sg.T('', key='_STATUS_'),sg.Stretch(), sg.Button('', button_color=('white', 'black'), key='Exit', + image_data=orangeround[22:], tooltip='close window', )]] + + # Create the window + self.window = sg.Window('My new window', + background_color='black', + grab_anywhere=True, + use_default_focus=False, + no_titlebar=True, + alpha_channel=.8, # set an alpha channel if want transparent + ).Layout(layout).Finalize() + + self.colon_elem = self.window.FindElement('_colon_') + self.hour1 = self.window.FindElement('_hour1_') + self.hour2 = self.window.FindElement('_hour2_') + self.min1 = self.window.FindElement('_min1_') + self.min2 = self.window.FindElement('_min2_') + self.status = self.window.FindElement('_STATUS_') + + + def update_clock(self): + # update the clock + now = datetime.datetime.now() + real_hour = now.hour - 12 if now.hour > 12 else now.hour + hour1_digit = led_digits[real_hour // 10] + self.hour1.Update(data_base64=hour1_digit[22:]) + self.hour2.Update(data_base64=led_digits[real_hour % 10][22:]) + self.min2.Update(data_base64=led_digits[int(now.minute) % 10][22:]) + self.min1.Update(data_base64=led_digits[int(now.minute) // 10][22:]) + # Blink the : + if self.blink_count % 2: + self.colon_elem.Update(data_base64=ledcolon[22:]) + else: + self.colon_elem.Update(data_base64=ledblank[22:]) + self.blink_count += 1 + + def update_weather(self): + self.status.Update('Updating weather') + self.window.Refresh() + forecast = forecastio.load_forecast(self.api_key, self.lat, self.lng) + daily = forecast.daily() + today_weekday = datetime.datetime.today().weekday() + + max_temps = [] + min_temps = [] + daily_icons = [] + for daily_data in daily.data: + daily_icons.append(daily_data.d['icon']) + max_temps.append(int(daily_data.d['temperatureMax'])) + min_temps.append(int(daily_data.d['temperatureMin'])) + + for i in range(NUM_COLS): + day_element = self.window.FindElement('_DAY_' + str(i)) + max_element = self.window.FindElement('_high_' + str(i)) + min_element = self.window.FindElement('_low_' + str(i)) + icon_element = self.window.FindElement('_icon_' + str(i)) + day_element.Update(calendar.day_abbr[(today_weekday + i) % 7]) + max_element.Update(max_temps[i]) + min_element.Update(min_temps[i]) + icon_element.Update(data_base64=weather_icon_dict[daily_icons[i]][22:]) + self.status.Update('') + self.window.Refresh() + +def led_clock(): + + # Get the GUI object that is used to update the window + gui = GUI() + + # ---------- EVENT LOOP ---------- + last_update_time = 0 + while True: + # Wake up once a second to update the clock and weather + event, values = gui.window.Read(timeout=1000) + if event in (None, 'Exit'): + break + # update clock + gui.update_clock() + # update weather once ever 6 hours + now = datetime.datetime.now() + if last_update_time == 0 or (now-last_update_time).seconds >= 60*60*6: + print('*** Updating Weather ***') + last_update_time = now + gui.update_weather() + + +led0 = b'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAAEb0lEQVRoge2Zz4scRRTHP/WqunsDSQjiBvFHSBC8eRJRFAXFgCIYRVBPgrkoiBgU9U/w4iEgHjwEBT2IKHiIiBfBg4oB8SJ4CgHjIXpSE5Ls9HR9PUz1ZGa6dnZ2dmdnlXzh0TPV1a+/9erVq/eqHSB2GWzZBHK4TmpW7EpSIdfokuwE4jrv12QDk40LhNElNmapluFNZtws8bdEsQCCrb69zvEL0FP3DQLk0nUf6P6y1A8hSKAeKG6jNEmnQG8Xhe5cWZE5p5ZHy3mM1GHQz2Z6YGVF33ovgeqkZDukn65vVpVeDUFfr6wIM9k0UgdBa6DfvNc9VaWvErFeGuW80h8Z3Imi0PGqkkCny1KYyY+Q6qw+A64AtzUNn0k8GwI9M56oayLzxxABzjleCgFvxqleb3DDddd5NiT4dL01Rr6oa54pS9aKgqMSl+YgFoG9wFtm7JE42evRkyjJh54sqRZ9YFXi07rmLjMuJEWbXY0B+Ac4Dpysa2qmD6xDavSFnsEoVyVWm4bzEg35gLcRKYA7wuDXRsE561M28R8GVptFYQ5t/yYTj6aSagPnJKlJDNfsJtD2n3Uw3fdnVsNOo0PKwdKJ/YcstSDM71ObeHhR6FpqN04fsHS/2lGfmhU76lNbcvRF5eez7pkbOnpcr+McaPe03KCV6TdsvApccY4KqIESOGvG7yOb6bzT+6MEZvgYqRlkIRdTojypc5iGtnnysbLUFTMJ9Kv3OhLCIGV1Tm5O8c4JMz1fluon3WdC0KrZWDre2kc5Yk+GoJ+KQoeKQjg3mdjPJQGE9zpeFPq+KHRDCDlC6hSjMJjT6BzmPcSIYqSZc8omUQDRDOccagZaJ3V3/NcYJHT3ec8nzrHfORqzbXP02jke854PzSicoyHvo52pu9d7/ZlKq++81w1FIcw6Zt6MeBBmejQEXUw+ddp7VdN8qm280XtdSISupjrtTAja5/3At+Zw8uCccE5Hi0I9M8UR3aeqSjg3VvcNZ6U14T7nOJCWf8lgvu9uGm4fqXO1SWmfe9iMIkb6XItFtwA4N+bYHVfRxBy3NeCsSf809JOOUf2tk4+2zey/25HSWEZHTuvST/Jy9l86qRyWTuq6pWaFMqt6+aQybUsnlcPSSf3/LLUdxUTOqXN6px4vAsPD17bjVg7NQtpmRvfX4YY9K6kmdTjrPefSg3FiR58FbUV0JkZwDpOm6lj3g5HSzfPe82JR8EFdc8iMNTZvqQjsBz4GXi5L3kunw7C+W4xlnYdDGFYyfzinB8tS36Skr2H614Rp0j77elXpRDrYF+jzVJhkk7xRhgG45BzPlSWvNQ0PNQ29dK+ZU8Qg939nbY3LMfJGOinuzxLRA3DZjKfKkhdi5FjTcJVryd5WUQPv1zXnvOfdEDiwTr+xHP1ICHp6zx59lKasv4UpmyrO6ZWq0uNV1Skcxuq+9s9BMx6Jkb+20UKjiAzy/55zfAmdkJAtRrONC8KGX0ZHsQgL5ZCrvHfSKDNjV27I/wIpihClbBNQxAAAAABJRU5ErkJggg==' + +led1 = b'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAACD0lEQVRoge2Yv27UQBCHv9kkRCAhXgAkSh6AmoKCFFBENLwBFQ0PQIPES0BJky4NDR0lJT28A4ICQc7nH4V3FccZ+9zcrAv/pJVP3jntp525+XMGiIUp1QbwtELN1Qo1V1WhLK+hqkEVIC8fVYFKdDB3gLvW3ZUN9qsAmRlnKfEoQ6WBTShQCxybcW7Gk7blt2N3GAVkGegmcA6ctC0AB45tyE2VgL5txifgROLfhH0YFMBH4DGwYdpFIVBtft5XlwA8l/UVGujtbhMgGMrL3p7W2rcrlor2DtV32dHM7+wdSiOfp7TG1FytUHO1Qnllpko7bL3n3N4pJE+VFvhLftf09n/Kz16KXO/NJJBAr8wEKF23i4GxvDDTh5T0OqUxII2NXntRiavGDJM4pOtChwqfZhrgDfDCjA3jnUOY+zDT2xxTf0Gnea9KTJVD36UkgS5ALWgDeugEe+jg8DTPegnY0k009/JetbF92wMoEFu73rmHB/oVOUCuXbS2zrvqUF6RrgIlLmPKy9zrTXlaJNQi3bc8KGmBUCwgphYzOPRVeqdd/1OFQJVDvuVa1y8tcgaHEKhy7EvgsxlHXE401dxXysqFxHO6UevGhH1YTCkf9kfiFPiaXdk4tuG/vgT8Ap4B31PilmMXOmIVHdAF+wMzGuCHdAWkClQ5mJHDq2X0/q0MVe2mplS99nlaJNR/DW4BrSasyZkAAAAASUVORK5CYII=' + +led2 = b'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAADmElEQVRoge2Zz4scRRiGn7d6NlHJQaKoKHgwxGgiIpiTegrI4kEUkdwEQcRF8pdI0INIrorkoqB48SB4EhQUvSoIIkjixaiExdnNTtfrYaqyPZmamZ6e7GQC88JHM71dVU999ev7tgSYFVO41QAlraHaaiWheqWXSrYMxQnt39LVVwLolT64T+Jem22gOgAQM5w3hyV+8bhPisN3GPhU4qTNf5M+WgBIwCFgS+KqxKU4Oohj3ssvHpL4UuLJGKm5OR7LDQl4NQQeBp4A3oiRCqjT38dWX3btJZszwA8SFbCXCnW1AfteerGqOCLxboz00/A1F1ZxS4gMPXMlRjaB7yQ2UsGqgwWGU0DACxKPxMiHdT0GkzVxutSpsn9sNiU+riqetulP6skM9YA303Q4b7MD3DEvFAw9JmDb5pU07l3UA/rAOeC8zd6MhmcurDwPSJV1UZ7gpwrzpxNUrvQ6XAflcqXdu6S5tqCuW39zK2ijlTyQ11BttYZqq6VCSe3W39pTbbWSUK139EWSidzz0jFTOiVaQYVUuO3ZdaNyuRxlNM/RuUOXDBSBu4GjDOOseT3WA/4CvgbeSnA5fPl3QhlPspCexyX/KjmC++DdOa0PNnhL8supHoM/l3xIMmCNtl0GqtLz8RD8u2SD61RZF8sgWyH4tRB8MQRXZaAyVAaS5O8T0G6quKvVqQ6DXwrBgDfKQONQecjOSH5P8mnJlxue6go1SEDvSw6pnQlAo1AZ6JkQfCVV8kEIfqyqfDkEW3KU7DmtTs93koemwBjw9dWXV9mDEl/YHAV2gbdj5M4QOC1xXOoUpwu4BvwUY+uVO+KlU8kb2e0Gb4MfyPNsRi+n2YwhG/dUVt7omvl8c2+qGu/nVT37E6CweZaOkyZIvQBUW63kgbyGaqvbG+qgJ3dTt7enlqk1VFu1guoam3dVq8Qh/wMW9pOILhLtzr+pUANgA/hR4k8Am7gAFOyHSJ2g6gbQuRD4LEbuSfHUvNlMBI4AH0lciJEeww5P00g8dVLyIIW/P4NPhOBvQlg4ccj2eoo+e9NjqlGoEyl0/U3yoyH4q0biMFjA9nKnJJ9NWcwUsFGopyT/EYKPVZU/SUA7qcJFbS8BXgNvJo+FaVA5TD0m+bmq8sU0ZDkLuVmWQ+wdyc9PABu5xco/7geeZZhSH8R9Xw3cBfwt8a09dpVWvFrjxpdLVvG6Vizn/DEreodc0koeyP8DbP/uIBO2okgAAAAASUVORK5CYII=' + +led3 = b'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAADoUlEQVRoge2ZzascRRTFf6d7TCLBaALiImAIRoObJzqu3JiVCzH/QEACLlyI4sdCiArqwp2gG/8BcavgB7gRsgquRRBc+lwEBTExEMzLdB8XVTWv01090zPznPcgc6FopvtO1al7q+qee0uAOWBS7DeAnGxADZUDCWrU92EdaE1+l6nn/dokB2CUUzguccLmJlD+D0Aq4BBQS/zurk267pM4AnwFbAH/ZJVWB1QB54GbwF/cabGO9UqJSuJUXfMDcAao2Zs15jjgBHgWeA44DFwiTHwS9TpjVTalzW8S54Cfo9JOnN2y7XYEdAN4WuIJ4H2CJ/omMG2KzxKM5OOSr4ANruJz0VbH5zXwGcmvN769G8cbNTB0lksycQWUNn9LvAB8ATwK/Jsz7wxx1K+AF4ELwIexnyNxrLmWarcCXEgzdea1ZIV3onV2YjP4vYyl5k66js9VFnraSY8r2EX0WwgG7va+k3eoJACTmVq7stbYV2YOypwcyIB894Jqho8hcvdaalHZgBoqG1BDpRNmJOHWyZuYw9At3ZaSwBLqzLfcGT8o9pXxz7lOh0g1Y7BcDpAF1bRWmuWx2JYBNgL+BL6XuGBP+RrA1dz4ZCyoRDFsaomzwNc2pwm0eBE3JtePgOcljgLfxAl/ArzVAyJLzErJFIXH4KstWrssHTb4PPhl8Gct+t1q3ZdJ8RD4p9jZrdj5sm3SaFux/8M9oLJHggmp1k5R8ApwjZCrrUr0SuAl4KTEm8At+s+krqUkSwoulPwM+PoKLkz/uQg+1+Dnr0XuX3Q9lV/o090nUQEPAw8SKO2i59UI+APYsvmOsIMr4B7gIvA5u7s86fcCgpicxpx/e0EwTVAT4CMJ7OngAKfTuC39uVKz2ome1k1KHJr93M7oD65dLHuaN/+bW9RD3+27bEANlQ2oobJWUEPD1MZSQ2XjvlxUyL0bFGYSF1qWT5WEuJcb7Ebm3VxLNYPpsuXqFIh/zBTNFk6xSqCSeMTmYylcXbA4W6iB+4APbN4APiVUh2cN3mGdsFtHPwn+lb2po++An5J8SZp+e5UhdXQ71L0l7ge+BR4jpFYFy1MYE5jmZZuxxAPA2+SLsx1QhUQtcW9d8yXwZAS0F5dGE0JCe8VmDJwCTsyYxG5qVRQ+Kvnyii6b58pt8FjyWe5M62gnDunHQ8AYuM7e3/eJQIGPAdvAL3Qz5H29GU27uA0gX+BgfXfIuY2z73fIOTmQLOE/hw5ngBNVOEQAAAAASUVORK5CYII=' + +led4 = b'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAADdElEQVRoge2Zu4tkRRSHv3OqukdFxd0FUQRdxESMFgQDBWFBQ/P1LzBREHSNzAwNRPwbVkMDQUMVdIKNfIAYimAgsivjY3fsufUzmKrZftSdvn3t7tvC/OBw+z6q6runHufUbQPEjsmHBqjpDKqrzqC6qgq1TdJaW9X21XZjzXIgtVyf0f3uXAyBBIQtAF0ajYhmC/cFyPLxwRD0/Xisp0MQoJivr9MiCDO9HqO+Go+F2Un72WahHghBN0PQgbueyWCjNQKVul4JQTLT5zEKM/lpUOdD0K8xSqDfzfScmQCFNQCF7KHX3CWQQF+MRsuhLoSgGxlKoD/MdDlGAfMFVzLPQFdz3Ye5/i+7eOpCCLoRggSa5IIH7nrcvTdY8fKV3GWTqbprUAuzz7gzJQPHM+S+lDif0sn9VVXKPJL9ryX1VKFq5+vIb8qatOzFqlC1Qn081LeOzlDbVDWabAqqa71xoaA2mB1XwklN/5/UZWgtQm2y+zqq7qkNgfVeEnZBOwm1sCQox6Y2TcfGrirP1+qtXVuAcmb7vqTF0zGwllefpvJ8Sa81BeqVtWsB6hbwpxn3SkyAMfCDGb+Z8URKOKsH5wAcANeBf8wYSxwCe8DNlkk1m4iBLrvrwEwCfWemSzHq63w+ATUrWsmd3nPXCyHo73z+jbseypltNUefB3vRXfsx6vnRSPs56WtyZX2slH0/Rr0co/Zj1MM5cZwDWoQqYA7CXZ9loNug9B/tVgZ7KwThrj3quX91IiXyQEyJqynxszt7QFN7g47WAHcB10LgW+AaMDKjob6onp7sg550108xSu5q3KUVrZT5MEY9Ox7rl7yb+dRdd1e60Eoftinkt3w0BJ5yZ9LyZqfJgb8Al/g4Jc6lxO3suY9i5ErT4NLMUtNpe1QZjJ2t7LLfyB46nBr4+3k3Y7PPL1cZY31jUgCOuLOITq91TT5Od1knqALWVzZ3XKbBA3KnT0Hbliqxb3ioyrXBoXaz+yrXzqBq2kmoszFVU80rg0PVdjXlt1We26hKwz+agdlMQB7MU01u6JOUeNXsJEcbFAry/lHig5R40529HPMGH1MNx7nSuxJvx+Os6aiy7+ucT61LDRAl3jk64mIIPNbyda93mtvXSup7D+il/DfI3P21fCLvpc7/921TagEY1FNtGjz21bSTUP8C1hqqTm9IJgsAAAAASUVORK5CYII=' + +led5 = b'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAADyUlEQVRoge2Zv4tcVRTHP99zZ6NEggg2iYgWpghKEGNlYaGNYifBgAGbNFaCkCJ/haAiiGDAgOkFKxtttrGKFlaCbJFlwVVEo+5m5t2vxdy3+3bmzcybmXVnA/uFw5v35r37Pu/cX+fcK8AcM8WqAdp0AtVVxxKqN+mPo6I14z1NLdfaLx6hWj0VwLMS/9iYIeRhawCcAbYkfrXHHFF70CrHsxG+npIN3gX3wYNDtB2wwXcifDalA+8uv/cBE1ABNyXuSPwlcbOqyMVbh+GxqrznB4nXgC2bkMje99OB9ly/dAB8mDODnHlHIoBcCsxLWL8ArUfwisSWTYIDQGNQo3C3bE5LvJUSSSKV/2IBA1gDvpV4Hfg9572aGa2BiQ0dYBf4NGfeS4nLEXxs829LIbOUgdPA9zZXgb9zJgoQjPf0ieNUDdcHPqoqrqXEuVL4YE6oWgPApaflKfdNhWr2gvMSVBX3l4Cqa2DWGNgKJWnYaWk0/sb5or2wbfTuDNWm5lf+36P91N63Kh3LKOHBgTqpvhaNQ0lDW6FOqq+rjqWnOo/o9QTaDEXm1ULTTP2AGscaJjXgps3w0xQjZXaCEoDNn+V8wDAwQ2IdeBx4jP04qKvM8KO2Jf6w9yLZWc8cCN7PSP4mwgbfB7+Rkm+U8zqRmMd2S6Lwk+SnSqIQjfe22MELNdjDEf46wlcjfEOywVUpfBGrn/05whckA+51harB1sBIfrukWjvgvKTVHluXjGRN9lg7bUhOkk9F+PMC1i9fvIj1C9AG+MUIf5KSX4qYVJXtUCpfApgIfxZhS64ke07L5XhX8nOSb5fmsBnhF1rA2tcSJDwSDq9JXIqg1/ZAB/WAX2w+sHnTZhd4CNiUuAj8NpK6T+sFe20slca5iNVeOM8wbW+2sz74mZH7Oo3oZjiupFk3TlA9Lpn9tN3s18Jced+o5h00azWrZHSKaptnH5woYdU6geqqlUNVjK9NrByqLT5bOVSbTqC66sihDn19atF1qXru63Usp5On6kXTRZeq6zlzA/hRQkyfR2d6KgGVxPUIruTMva5f0pCBU8AmcC2CL3PmQtlimfZMq/VKnP5+yWQyyycO30m+mJI3SvR5D/zkSDzVDiXtAb1bgOp0aZk9mTpx+CrCz0d4G7wr+VwJIKdCpQJ0OSVn6VCARjeLvpB8KcJ3I/z0LKgoQFfqwH/JamuzQTneivDLvZ6fKFB1ojJxv/FV4BFgh8XD4GmqgEcZ7tVsjyQNq94E3Ru3mhBT95CPYp2qTiiaWrmn2nQsJ+T/AHYfURS2h8j3AAAAAElFTkSuQmCC' + +led6 = b'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAAEBUlEQVRoge2ZP4gdVRTGf9+Z3c1qZJFUChJWLBQigmLQiJYhIkQLwcLWwkYrGy1s0sRC0gQUIljYWCRaaKONJoKNIoJKwEgaBcEuJuwmu/vefBZz7+68P/N23p91X7EfHGbmzsy935x777nfuSPAzBlivwkMwwGptphLUgvDCv8vpmVDueibfQMF+4BtT2UyhyUeBP61Kfao0RK4B7gO3Gl4xtkOgY8WhT+RbPAaeGPGtg42+EKEkVxvv2ZY6WJJ8jcRfjrCFxKxTqpkFpbr+qAojGTV2m4kheRrEb4l+VhR+FyEnb6wM6VtJkLnJCM5mgn1kpLk3xKRG5KPR/i95LHuFB4q0/Fs6rJiNCEPhIQ8uFdsrticjGBD4nXgJuOHizyoz0ucLUsWbLrZHQ1Q8hQGQuKqxMNlSYdqaq5LHAeuAodoji27YQsIu9X7g8HT1TcE0AHutllNpDpAd0JSxRjvDpBS7Tx3Vad2T0yGcTzcQ2q3Rrenxh5jLhfkHlKyJ+6eWWLQU97v5XgIqbnz1DSza5aY/4E+Lzgg1RY9EX23iB273B+FcVaDgWWmft5NRPJDJZOrhNwlbYj1kNoCbkpgs0klVf4Erkk8YLPYstJ+CPhbYiOtGG3qMOBIx2OS/0pK8XfJj0T4UlKft0ckBE12O9X1qeQiJQp1pQsNcrif2GMpgXiiKHwxyeNp5HB+91KElyNcgKOZUC8pKn3sJaok4sOah8opLXvsTNLpi6N1+qCnjkr+WPLjki/XUq1JCeXU6mKEn4zwR5KP9HXlUFL55n0R/il12ffg1Qh/G2FL7kr2mJbf+SzCq0XhX9NHXpa80kBsYDJ8J/GczR1gGfhR4hWJ+6WJ4pSoZvUtmy9tHqrV/XkEL9tDE4qdDBl8nZ1cbSudP5/uF81jYFQOZ8CvJu9v1gb+D2l89XuqJ07Vg6PZCXi5bJINj4Iq8cgernu7KRAPRPRRi2GX8VMs9R09pKwfc7kg7yuppklzQKotDjzVFgeeaou58FR/EG1Faha7C3lJaZOBD/0NUq8ogKV0PYlKyF+dG6ovM2OTKtPNfyR+AUgbqONmM3kX8GdgDThMJWUKmj+wkdQCcEPixQjeKkueklhjst3hFeAL4KUIvirLVnVs65lF8B9J66yDT0T4fNJB0/x5yPrp3Qifiti+vpL0VJbh2XpI1/v7lMRp4I2yZDOVdSc0U3XZmbLkUZvTRaXM3LBBF/0XAl4oCk4A75QlG1RdqSktgE3gfZsjNq9FcJe07YyB7st2L/jZovDbM8j1mqwEW/KbEX4mokrndkscliVOJnHfZvqOC1PNvAL4muFKdoBUMPkmxrhoamvofsNe/RHtR5Pen4dfxgOYS5XwH7eZhqnTFNxUAAAAAElFTkSuQmCC' + +led7 = b'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAACtElEQVRoge2ZwWoUQRCGv+ruFRPx4iOIGPEuETyLGDH4AqII4tN49KQg+AB6jAjiOeBFg5gHEA+KHiQmJpme38P0hN3ZSZysm949zA9NQ2/t9LfdtV1V0waIOZObNUCbeqiumkuocNgHuWjF+D/NWsayylI/DHHoSi2ZUUgUTH/VDNgHzgK/zPgijazOGJQDSmDZjOdAlIhTBiuARWATuG/GjsQPRrdNzeZSfy8ERTMJVII0hRZTv2mmJee0Brqe5vNDLjYGBSikftVMuwlqPz100raXgDa81+XBQK+9l0BXukIBGqT+pnPadu6/VqxeoXXQee/1Lj1PoKsNqEMdHSpnDMBaWXInBJ46R6DyOTvqiw2VwAKwIfGwLHkRI9fS8wct9kdCAQf/vjdFwUXvCUx2hhjwR+ItHAAdNvk/oaD6pQ7Yi5HdCYEEnAEupDF/hH0nqBrMON62NaFKIHaw7wwF0zn6u/youQzIPVRX9VBd1UN1VQ/VVVmh6lDTNj6srFCO0UCsofGm3YlLVDFvG1i3KvoVaUxm/E5janznxJul/pSZXqU0OIIemAmzg7qgZssCNQLmnF6GoEdmI4XKkF3eYtSlFp0DiSCx32KTTXUuVQCPgVWqtLgtC822fYAw05NUS26Z6XYIbVuY0Z/M9Cw5+S5VebXjnC41fOtY6fCkqh13UeJGrLL0ulQ7XZacG7KDzD7VLBxqiGYxkd3R2yZsFhN9QO6qHqqreqiu6qG6aj6gbPT4zF44dEneshcOYxPa+Bur7IXDR1dNORKEZ7l9AHfNeO89A6oMtE3ZoJQm+xkjKxIfzFpfV2eFgiqf8sD3smRF4nMaj7PevpjAvgK3nOOb9yw0bGZ23+epAJdDYAv4VBQHN2gzvYRsu4CEGZ/o9VHRPKlmfl3bpvmIfQ3NJdRfFS/ZxKoPEs0AAAAASUVORK5CYII=' + +led8 = b'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAAEi0lEQVRoge2ZT4gcRRTGf+9Vd/VkIRjxIqggJF5E8JSDF/EQjKAICflDQjAnUdGD6EEQDHrRmwdBD6IIweQkiiIevOTgKSAiiiAiBDxpomhiJLvTVf08TPVkZqdmMz272Z2FfPCoobrr1dev/r1vSgBjwaBbTSCHW6RmxUKSKnKVkuxmw8ivMlld35LZjCU5ra8JUgD3qyJNQ5+bM74R2AGsqPJL02RJGGCSyru9t5NVZf+JmIEFsGYDrQYzsL9U7diOHXavc2P9AzYMhEvlURH2x8iBsuSaKi69KRtgxmAS/y3CwbLkZAg8FuNY/5AZncvAsRA41DQ86T1XRFAgAM06LKTOflflibLkuRjZX9f8I/klZYAVqXy2qsxSiM+UpT3ivV1KQ9mk+q7WtvvNOXuoquwL54bPToiM9Z9+57EMHK9ryqLgcFnyoRlLZkS6bRcGlMCfwDPO8XoIPBojy0BvSpsJUjLyoAYOh0C/LNltxs5EqisUuAp8mQjVieg0TI0UXJ9896lCCFyNsfP+1U5wBfaM+G26kBodmpZAYzbxrCuxBmaO8pqRGnUK04+FWTHrR01sCZtx5t0IC5klbI9ILSSpjYZM+b0WNi1Syvihe6N3Fw6bOqcWbvi6YKYdvT2nlO47envEqMjAj417yPmbIJWbZC4lYs2cpNrjKec7NzITpK6YgQiNGcJgxZwz43Yz7mSQQXZFAfwhwjlV9oRw/WAW4V8RMMsLh6GJ2HtFYZayzTe9tyPeDwVEAIsdLKQM85qqPV5V9s5I1vmW94bImGhgICImdZ+J8EFR0Ae+UeVMv4+kr5lnIbTtVkQ4WhQcEuFi0/ByjEO/uTajLM2DoWoPem8rqhY2QGq17a+o2p6qMkTMr5JWUyOlQCPCKeeIqlw04/0QhonePGgnuQAnvOcBMy4Bb4eAmmWz0LEoIWKnynIw7iL2Qlna096bqVqjatbRRtsc895e837gW9WeL8tWfOYj5Rikq8erijN1TZ3kdAG8UpZ8JcI9ZvTprmYq4IIZJ0R4NQTqtLILVfaL8HWMw/7HItXqrpeS7qtHVs557w3nsuN/I5OR8ufkL3Jdvj+VZPuaui83d9ovaCX8PDDye1yuv0k1k5HR7U4c10Fq1M8YMqS2R+qy2YiLFKl2kuQE6pZHKre9zERqs68ktjxSOdwiNSu2L6mNmuhr/VE2ipnUjKajZ56sc6hmpnRmKUcf628th+2XnY8RzBARrKM1IgN5pcq3xYDW6hRlNaZGKjD49/Z0UXBOle+ahmWRucWqA153jiXgQAgspzoykZpKqgd8UpacLQo+XVlhqWnWLRxO9/scLAp2Ose+GEFktki1Oc/nzvGuCJ8tL7NkRpiTUIsGuMOMszFy1Hs88HCMBJ2cQRM1twHfO8cbzvFxXbPLjHqdhNqO+sBdTcNHdc2LZcmvRcHOKe+PJe/7ej070uvZhSQa5736mGYxlT+q2sFez/YWxYR4GJNYrRDdC+w24zIz7hkdIAxuMnYBP6nyQ+a+b/vcjLbC8WbDyO/yWVJbjYU8kP8HKX/sOnQ6GT4AAAAASUVORK5CYII=' + +led9 = b'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAAEYklEQVRoge2ZT2gkRRTGf+91VXeQJcp6kAVBEFn/ggh7ET0IggjBGBNW1+Bpc1E8uDfPIgqC4OLNu6IL4oJ48+RR0LMXvQgii4d1E4PZdFc9D1M9yWRqJjPpbGbAfFBM0l3d7+tXr+q9r0oAY86gsyaQwympSTGXpFzuoqR2p2HkZ5kcvN6SOYkpOcrWECmAh1XxMbIDFHeATAQqIKjyS4zZPgaYpN9zInapquymqhlYDRaPsTVgBrYlYm+UpT1YlgP2AesHeuuRJTPWQ2CtLLklgks95RiaJTvbqqyWJa/EyEXVAfuQmX03gZeaho0QWPaev0RQoEluP2prkrFbIiyXJZdCYLVp+Nvy0WuAufT7WnKvgV0vCnumLO2PojBL7rcjtPa5G6r2bFnaV973771dVQP209957AArIbAAvO49n4lwFqiZbrkweuvOlggbIlwJgbUQ2AEWRjwzRKp1pk8EXgyBWoRHzThDbyimRQFsAdeAtRCoc4bHkWqDrA1KgIdiRMz4xyy/hkwCVc471yc57uOGSDmR3mjvQ2BvBsL0q70kEmFEUB9KKmew6yrfPjdpoh3uJyeR9cZjiNTsKZ16anLMZZE37Kl5HL55wGlMTYrhvJiJqTZPdfmCtq46iFyWGJmQc50iI4r6CZGrDDTjhH6/1tAmgAhmRkgkf1DlbIzcZ0ZzRDI3gO9FeJJegifZ2RwnHGiLdxH7uCzNRMzArjpny2VpO0lINGBhitakyrMWsVXv7aOy7FWdIvap94bIgGhIPIZ1n6nySVGwKMJ3wLW6xpsNlC/ToH0uAutVxfNmRDPeDAGJMRsOB1n26+XHqsq2i6IvjbpKqwD2r6o9UVWGqpUHpNVIT7XecqrUIrxTFFyta+IxeEpF2PCe+4EmRj5sGpTRs3KgFUVhImIKhnP2lvdmqhZVzTq0y1VlV1olI2LvOme0dsZ5SpM4jGlWFCIEVS6IcK8IzZTeMqAEfhfhZeCD3V3qdM+LcNF7vt7dpWBvVmZFRdw3TYMZzoyfY8QmrLGzUOXzJBw0kcWMc8kJ+z90nNLZI0a31VzoKeQmfdT+4cmJiYlItdO56/bQ0YXDHGAiUp1i6bB3Z67N3FNzSSqHmZOaS0/NjNTYDJCZRP9fT/UxoaY8UVIxM1QTCYccNNXsXVFkPHWk4VMgivRyn8iRWrsV8GP6sLDfwKQJuc3iDmhUWSoK3gd20p7ntDB6xx7vqbLoPet1zU56/yj/D1R9qrq3r61qz3lv20nJdN1H31K1FxYW7Bvn+vcuO3f4PrrR24xtRLjgHNebhrtinLrizL33TIx8efs2K95TqrIUY78K3Y8hUgXQiPCIc3wbAvfEyC7dT7ME2AXOmvFF07DiPQ80DYvjjkFo5Y6qPe6c/dlxyA4byt+Kwl5dWLCnve+FzSjh0P7zlCrnY2ST3snDcVZTQu8k427gVxF+yhwYdNmv6IxR+/PZJUE5mc0zIy9EZ+qpUZh5lZDDfw9J5SDpQQEIAAAAAElFTkSuQmCC' + +ledcolon = b'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAABdklEQVRoge2YQU7DMBBFn9MEVVBYcADEmiVH4BScD3EL7gIcAYEEFSQdFrZRCJGYeBa1qnlSZSuVJz8/k/EkARAqo9m3gDlclBYXpcVFaXFRWlyUFhelpUpRrWVxAFaTYwIMlqApbnX9VJFT+UpOgRugA3ZE195C4EHE7JYs/TVpvAJ5BxGQPo1PTSObEASQUBA7xS/nE/hI8+yMEJ20YBK1G81zwnfWoKXr85MxAF9p3o/+24tT45N2k/EYOLIoovDpy069AvfAOdGxDngR+cmzUg6nTv0XoJ85toQqnapyQ3ZRWlyUFhelpUpR5oo+1xFYq3GVFd3Uo18Cd8CGuN+tgcem4VaErUjxFZtErYFr4ITY8K2AM2ILsy0JnDD36Pnk49a4mh49B2qtQUvX5zzZ8TdnVqVBR5jWD/x2C6Ko6av8UkwloQUuiImd32J64Bnb94TDqVNj5u7/9JYupUqnqtyQXZQWF6XFRWlxUVpclBYXpeUbS+1qOYf8HRgAAAAASUVORK5CYII=' + +ledblank = b'data:image/png;base64,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/GMzLdsAADpEaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzE0NSA3OS4xNjIzMTksIDIwMTgvMDIvMTUtMjA6Mjk6NDMgICAgICAgICI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgICAgICAgICB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgICAgICAgICB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8eG1wOkNyZWF0b3JUb29sPkFkb2JlIFBob3Rvc2hvcCBFbGVtZW50cyAxNy4wIChXaW5kb3dzKTwveG1wOkNyZWF0b3JUb29sPgogICAgICAgICA8eG1wOkNyZWF0ZURhdGU+MjAxOC0xMC0yMFQxNjowOToyNS0wNDowMDwveG1wOkNyZWF0ZURhdGU+CiAgICAgICAgIDx4bXA6TW9kaWZ5RGF0ZT4yMDE4LTEwLTIwVDE2OjM2OjMyLTA0OjAwPC94bXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhtcDpNZXRhZGF0YURhdGU+MjAxOC0xMC0yMFQxNjozNjozMi0wNDowMDwveG1wOk1ldGFkYXRhRGF0ZT4KICAgICAgICAgPGRjOmZvcm1hdD5pbWFnZS9wbmc8L2RjOmZvcm1hdD4KICAgICAgICAgPHBob3Rvc2hvcDpDb2xvck1vZGU+MzwvcGhvdG9zaG9wOkNvbG9yTW9kZT4KICAgICAgICAgPHBob3Rvc2hvcDpJQ0NQcm9maWxlPnNSR0IgSUVDNjE5NjYtMi4xPC9waG90b3Nob3A6SUNDUHJvZmlsZT4KICAgICAgICAgPHhtcE1NOkluc3RhbmNlSUQ+eG1wLmlpZDoxYTc5NDQ5ZC05ZmM0LWZiNGItOTNjYy0xNTcyMjU1MGU5OTk8L3htcE1NOkluc3RhbmNlSUQ+CiAgICAgICAgIDx4bXBNTTpEb2N1bWVudElEPmFkb2JlOmRvY2lkOnBob3Rvc2hvcDpkMGIzZGFmNS1kNGE3LTExZTgtOGI3ZC1jYmQxMWFlODBkMGE8L3htcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ+eG1wLmRpZDowZDlkYjE1OS1lYThmLWQxNDEtYWE4MS04YTY4NzFkNTI4YTc8L3htcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOkhpc3Rvcnk+CiAgICAgICAgICAgIDxyZGY6U2VxPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5jcmVhdGVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6MGQ5ZGIxNTktZWE4Zi1kMTQxLWFhODEtOGE2ODcxZDUyOGE3PC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE4LTEwLTIwVDE2OjA5OjI1LTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgRWxlbWVudHMgMTcuMCAoV2luZG93cyk8L3N0RXZ0OnNvZnR3YXJlQWdlbnQ+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOjFhNzk0NDlkLTlmYzQtZmI0Yi05M2NjLTE1NzIyNTUwZTk5OTwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAxOC0xMC0yMFQxNjozNjozMi0wNDowMDwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIEVsZW1lbnRzIDE3LjAgKFdpbmRvd3MpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICAgICA8c3RFdnQ6Y2hhbmdlZD4vPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgPC9yZGY6U2VxPgogICAgICAgICA8L3htcE1NOkhpc3Rvcnk+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjMxNDAwMDAvMTAwMDA8L3RpZmY6WFJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOllSZXNvbHV0aW9uPjMxNDAwMDAvMTAwMDA8L3RpZmY6WVJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDxleGlmOkNvbG9yU3BhY2U+MTwvZXhpZjpDb2xvclNwYWNlPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+Mzc8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFlEaW1lbnNpb24+NjA8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAKPD94cGFja2V0IGVuZD0idyI/PvnJsBAAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAEZJREFUeNrszkEBACAMAKHT/p1nDPeABJxqWua2kJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSU1G8PAAD//wMAGdkBdyV2S1QAAAAASUVORK5CYII=' + +w1 = b'data:image/png;base64,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' + +w2 = b'data:image/png;base64,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' + +w3 = b'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEYAAABGCAYAAABxLuKEAAAACXBIWXMAAAsSAAALEgHS3X78AAAUBklEQVR4nO1beZBcxXn/fd3vmnv23tUB0molWIjQgZCLCJEEfCAji0oRTAQ4TrBTVCAWMf4j5QQcEhKTlJNAhRSmbMoYMBaJXRAwhyEmICSEJZAMYgWy0O5KWkmr2WN2555573V3/pj3RrOrGUl7CPsPfVVTu/X69fH9+ru7HymlcI5OJvabXsBvK50Dpg6dA6YOnQOmDp0Dpg6dA6YOnQOmDmmf1ERKKcKJjZBEpCa1MwDk/RQRiU9qbbWIzkKAR1X/K6UUEREDMJlR5s9NRAAga7QTEUkAn3gUOqvAKKX4pJ3m5cdKjo2NteXz+YUAyDTNgYaGhiOaVhZYx3FYMplcWCwWFwJguq4PxuPxj4PBYNGTJHgA1Vz/ZOmbDZpNYAiAKhaLgXw+H9M0zYlGo6NjY2MdPT09/wBgnaZpYaUUSSmzruv2LFy48B4icvv6+v5F07TlmqaFAJAQIi+EOBSLxR7t7u5+1DAMWymloayC0tsAQlnKFE5Il8AsSdeMgFFKkbejjIicPXv23DQwMPB1TdO6pJRZy7KeKxaLl0Sj0bXhcFgopbjf1XVdSiQSI0Rktba2hjVNg1IKjDEQEUqlkkwkEgzAU1dcccUdsVgsxRjz1VQBQLFYZFJKMgxD+P2VUhoRKSJS3tpkHWk7O8D4Io6yoVR79+5dt3v37hfmzp3LPJuBfD4PzjlM0xSu6/qGtdKHc85QlhAhpWScc5RKJZRKJQQCARmJRGDbNtc07YCmabva2toemT9//hsHDx78fDKZvEFK2QXAAHA8FAq9vGTJkh9YlmV7AIExVuFxquo2XWAIgMrn85EDBw78fiKRuOTw4cN/FIlEljPGHCmlBgCcc1cpxaSU3AermpQ3ORERYwyFQgGGYWDBggUIBALw2pRSimzbRiqVypRKpe2WZV0diUQ0TdNARJBSqkwmQ67r/nTevHkPjYyMbHAcp9U0zY+7urp+1Nzc3C+l1BhjZ6xqUwbG02WVSqVan3766ceSyeTnTdNUlmUR51yhyitN8jonJiXyGYJSCkIISClhmia6u7vBOYfjONXvSyJSjDHmOA4ZhqGEEMLHFYDSdZ1ls1nKZDIqEokwTdOkbdtsfHz84JVXXrm+o6Njr6fKRETurAMjpeSMMfHss89+a/v27X/f0dFhO47DpJSsyoNMAGYyKEIIuK4LXdehaRosy0JTUxMCgQBM05zQrxpUz/fLWhKolALnXHHOZRkzRbquu5lMxmSMPXHZZZfdH4/Hh8Ph8KgHzikZn3KA5w945MiRRdlsFolEgtm2rflSAABCCDDGUGUQIaUEYwy2bSMYDOLiiy/Geeedh3A4DMYYSqUShoeHMTQ0BE3TfPsAIUQFKMYYEREnopqg+0EklfUPADhjTOZyuS89++yzt3DOf718+fLvrFmz5jGlFDuVUZ4yMFJK4pxj3rx5uzZv3vwnnZ2dLhExIQTzGUmn05BSIhAIgHMOzjksy4LjOGhra8O6deswZ86ciioBQDAYRDweRywWQ09PT8VwBwIBWJYFpRTy+Tzy+TyIqAJ6rb3zDa+UEmXzxRTnHK7rdr/00kvfDwaDIytWrPiZL/2zAgxjTALANddc8/jWrVs//corr3whGo1K0zRBRCgUCmhqakJXVxcaGhoghMDg4CB6e3uh6zpuvvlmtLS0YHx8HNVS5jPZ1NSERYsW4cMPP8QFF1yAlpYWcF728o7jIJlMYv/+/RgaGgLnHJ7HOWmdnmr50kpEBMMwSq7rmvv3779yxYoVP/NUf3aAISIlpWSWZaXvu+++P12xYsWfP//881/q7++/0HEcrFmzhl977bVoaWmBpmmQUsJxHOzYsQPHjx9Ha2srxsbGajIDALZtIxqNYvXq1TBNE67rVgwxYwwtLS2IxWLYvn07+vv7KzbJ/xERcrkcUqkUotEo/A3zqbe3F1dcccUhH7+6fE7DKzHPzlQ6SilZX19f56uvvvrPCxYsuL6hoUHk83k/mAPnHLquo1AogIgq9uN05KnCBKmSUsIwDOTzeTz55JNIJpMVlfVdfqFQ8CVGaprmu3saGRmh1atX73jggQfWhUKhMd/D1pp7ShLj62QqlWrs7e39XDqdvkQIYTQ3N+9qaGjY3dHRsRQARkdHqZr5KuNZzy5MiUqlEnRdR2dnZ8WT9ff3Y3h4GLqug3OuGGNydHSUO46jdF2nlpaW4VtuuWXzrbfeev/pQAGmIDF+gtjT0/O5HTt2PMw579Q0TQEg13VlsVjMRyKRcDAYrOx0jTHqqtB0Sdd1AEAqlcLrr7+Od955BwBUJpOh9evXv7hq1ao3FixY8OulS5fubGxsHMKJjP+UjJ8RML5r279//5oXXnjh5ba2tgjnXCqlfHfHiIhJKZVv6M42+SBLWV6C5+LV5s2bae/evdnbb7/9wTvuuOOfDMMo+kB48Y86k9zptMB42bDOGLN/+MMfvlooFD5jWZbjuq5eI/g6+4jUX6fSNI0SicT4unXrrl2+fPl2IYQGLy/zf2c63iltjJc9E+fcTqVS0WQy2anrOrLZLK/x+lkBpR7WtaJj27YBwOro6Bjxnqt6ccrp6IyM77Zt22557733/jibzc61LAuYQq24Xr50qneBE4ZaCDE5+q0Ejf6z6kAxm80WALjenMqLhv35z1hi6qqSlJIxxuSTTz754FtvvXVnQ0ODNAyDTdWr+AyeST/flVcDEg6H0djYWMm2c7kckskkcrlc5V3LsmCaJjjncnh4mHV2dn73tttuu92rzVQSRs+BnFGptKbE+G65t7f30rfffvu2xsZGIYRQuVyO1YpW6zHNOUcul6ukBL6hrKUGfh6VzWYRCAQQDAaxbNkyLF68GMFgsBL9uq6LTCaD999/H8eOHcOyZcvQ3t4O0zQBgGzbxkcffXTbBx988POlS5c+n06no7ZtR0Oh0HAgEChVxWGnpJoS4wPT19d36V133bUtFouZsVhMoOyameM4lM1mEQwGEQgEajLq5zajo6MgIsTjcQQCgUqFrjoRlFLCtm0kEgkQESKRCK655hosX74cxWJxgsQREXRdh+M4KBQKiMVikFJWQGeMSc45O3bs2CHO+RYp5VoAjUKIwZaWlu9eeumlD3POfV8h6oFUV5V8F/3oo4/e9/jjj9/tGTIKhUKSiGDbNmOMIRAIwDAMcM4rzDqOU6nE+c/83MULwCrRr+u6EEIgn8+jq6sLa9euRTgcRigUqvStVWLw1c513Xr1HmXbNvkpARHJwcFBdv755399zZo1D3q8+/bnJPd9OndNAKinp+fynTt3XjUyMnL+li1b1ieTybZ4PO46jsOFENXG7ZTFqWojWc0gAJimiS9+8Ytob2+HbdsQ4vTO5DQBo1+7IQDEGBOMMS2ZTB7t6Oh4qr29fWd3d/fPA4FAzuNzAhBnAoy3hrIE7dmzZ+0999zzeF9f38JYLKZ0XZdVoj7hTKlq0cpz/az6veogTdM0bNiwAc3NzSiVSmecT02RFAAqFouqWCxSIBDYccMNN2xsbW3tn1yfOaMAz/8BIM65m0gk5j/xxBPfePHFF7+cGBqKM0Bpmkbcq8H6XsVxnIru67oO0zR9G+CfRFakzXEcNXfuXHbZZZdx0zQr/arLoPVUqjoCnhR0VmxalbQqzrk0DEMMDQ0Z3d3dD23cuHGTmnQmNp3SJgPKRm7w+PHz33zjjWvf3fXu7x3o7b8wkxoPF0sli3PuRqPRTGdn54GVK1e+deTIka7du3d/6ujRox3j4+Mttm3TZLUCERgRVq1apS688ELygfBtVjVY1TbGd+uGYVSY98HxTx3y+Tyi0eiE0EHXdSeZTOqLFi3avGnTpptQTmvOXGJqkZKSVLls6AKgN8bkpk6UXg+76ePpfLFJ49yJx+Mj4XB43O9j23bg8OHDXYlEYs7Q0NDckZGR1nw+H3NdaZiGlm1taRrQraCx+cc/vlsp1R4KhZRSihWLRZRKJcRiMViWNUHFfNdt27aKRCLkt/sS4p0swLZtFQwGXa+dpJQsn89TIpGge++998tXXXXVE0IIjXNeiXlmdHxiC2m+OWQ/sCXhfmnThcGLWyx2WAGMvHNoKSX31BCc85NcowKIAJWWqj2t0DqP05677777p88999z1bW1trlfjnVym9CVJKaWU67okhCBd1yURMT9fk1JCCKE0TZNSSjY+Pl7h1TAM0djYOHrTTTf968aNG79TK9uezm0HAkAlCf5uGg8fdI1bGwL6ngCnAqSChCIqi2UlTykDoKCUZFKWDbACiBMJWyrtmYPFx3Ul9928JHrnpjvv/IYrhNr65pvr8/m8pZRSUkpijEHX9eoiOZVKJViWJWKx2Pjg4GBjKBSCVwpRAEhKSZlMhkcikcyNN964uampaciyrPH29vZDF1100S9bW1uPTDa6FSanXMHzJCLloPOVEfwi5WBhZwA/uLoFX6mWlsr7CowIsuCqMCNIk1Pef2/cUW3vZeSTWxPyM7/bwDZd3c4fkgoalFT9/f0XHTlyZIGUUhsYGFi4ffv2zw0MDCzJ5XIRIlLRaHRswYIFH2zYsOGpxYsXf/i9733vm7947bXr0qlUyFeLWCyWW7Vq1davfvWr9y9btmz7ZMnw056auz8tG+OpwFEbN+ZcXDLfxCMBjgGUk8vqiQiAStuy6X8OFf7903PN++cEtX1SwWSE0i/H1Lf35embYwXgC+1Y3xXGi0IqnaBErQWXSqVAOp2OMsZUNBpN6bpeqm4fPHZs/kf79q3MZDLRcDiSvuCCJXvmzZvXDwBeCaJyYMgYqxv1wntxNn40+Zn0YpZxW573zFFn230f5PtGi2KOUgpCKk0phSMFte7VEfXxrrR62JYqUD2WEIL7P9d1uSuEdtIcUjJXCF1JydIlJ551ZHzyO0IIJoTgU+VpZrcdyvdfGAGuF5SoaonKuYhuHZMvHcrTGumqrV9ZyNYZDDm/3XtXo/IRxqkWwgBIP4QHJsQrCgB+1Jv/wdI437ysUf9fVyiDCPK0UnGaCadNBAgCHM9mTGoCJBDPu2xhgAOrm9kbHijaJADd6j4nTwFypdL2p5xPAUTw8iCPW5VzVeyNUfHU/hz7s5CujYIYuMZdzrk7XVCAWbiDpwBOgOhJlq5uDWi9rQF+EN5lnoiGw1e14A+Lks5vMfCsx+mJWOGElCgPpMlEAOT2EfcbH47ZVyyJ6dfKspRKAkgqqJ3j+O5AiW0MmUa2yWKjJ5Y1M5ppQsIIEH1Z8Qc/O+p8vygQ9Jbl33ZCXMPOdgM/4VWATCLyVBK2UFb1c1dCvZeW976bpm8HDWPMH7v69pAExQiEy5vZczEDA6hS05nQtCXGd7kf59RN76TxmGBmLqKzEQAATVgYkwAjBUl00gVEX+Lc144Vv9Zsso+XNRk/Fwo6Jzi9eXyhJ0t/R9AwP6x6J3Yrd1zTiFuzAivjGt5i5c2YldrzdCWGCJB5gfCv0vi3nMuN88Jaf9ykYUzaMVWeRNQCBQApBfeDlPzLraPqfky6txI3MNik48CyRuxY2UCPexP7iZ4CAIsh0azjZU7IVD+fKU1XYhQAsjhyXSF6ZszFZy8I0r1UthWsyrgyAuRwwT0v46iWzqi+yw/4/LZfpdXf7s/jHzk3nSaLJQCAUVnt2gy8++lmupIIRQ0YAybYJX8h5asfJ1+HnRHNxPgqBmBFFF9D2dPYfnnFay9LlYvYMwPOjxaF6JnOqL6rKjomBeB4ia7LO4TuOPZ2BLAvY4uGgMZyGiNbAaQTBoETIcCkNfj2ZtYvS8/U+JJnI+wdQ6UbjxfcLgCQqny/d9RWC7eNy/8bdLS1DZZ+0OvjV6oUAbi8EXesbcb969tx3bG8WPLfBwsP2xKW/44qr7EmKKpG5W22aMZlMlJw9qbETa8cdx9wFfnjEQDsStH9R4u0Mm5q6Tkh3gd42WSZJAA0aNi1JIi/SdlyzqvD8tWs0NsMRgV/DDpxl7dCHlgqa8t4xpENM+WhFs0EGKYA1ZOVf7U7S09pmqlHjXIc4TM/L4AdbSaGrmqjR9ot7IGnXv4AvloNFrHs7RQ9kxHanI6w0auxctBYZ14iQAoFPHO4+PChrLsaqEjprNG0bIw6YT+iH2bYX+ddYFGU7YvpGPEWLgCgO4yHFofovzTCEFW6TqBy7ZcQtyXFWy2oVQ14pbqtxrwq56rmHWPykY8L7Po1Gn9wOjycjqYFjKfvFNSQXhbDf6RcdfWiAH0LOMlICp1wrN7uEyAUQHNMbLm6RW0gAI0a/QITUwUAZYlgBOVK4Jfj+M8jNr8+brLBmEHjwAQVnRWarW8JfCNY/ReTnk11rAp5Bl4CgKugbRvDT44VcN35ATx2eSNuZV6aMMV5Tr2ImQLjh/MoexnpxylSgbHyLp7RBP44VOPzHaEUH8yLRXNC2gEGuCWJ1pxEd5Rjl0bI4ix4p5l7pXKGLQmQEtCIIH897qzZMVS8ESfc7ZmOMxkUDYB8L+ne/PKR0rdZubzBTYahRg1bNELNw7LZoNk61VIAiAFuoqiWvpAQz4866AQANX1vwRTgfpSVf7FtDI/pmu5445EqxzCVjzxmYf0nTz4bg/hxxUBerd2ZVq/npN7YFjQOnWie4nhlMGVvFp99P0MPC2iYE9b7/XYvODyrX77N1jeRBAAHC7QhUaKmOUGMzg9hHzBNb+H1sTTYJkN6SZTGVsTxtDferOZEdZcwS16JAZDjLn7nUAF3NRl4bZ6Jp2qdGkyVchKLOZC3GI7iLKYAk+lsfCw6m1QBok4SedZotj8vZp7bVZMDtGmSV86B+iRBAX77JeY3Rue+1K9D54CpQ+eAqUPngKlD54CpQ/8PuEuH8eJdKe0AAAAASUVORK5CYII=' + +w4 = b'data:image/png;base64,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' + +w5 = b'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEYAAABGCAYAAABxLuKEAAAACXBIWXMAAAsSAAALEgHS3X78AAAS8klEQVR4nO2be5RdVX3HP799zn3OvfNKMmQSAwmBJOQBqICIUgSUtQQUpQrWVit11daqVItLl88lWq0P2mXXshXpWrWrWi2+KghCqeUhyMMoQUICBBLyTmYmmbnvxzln71//OOdOJmEmmZkk1D/yXeusufeefX/nt7/7t3+vfUdUlRN4Mcz/twK/rzhBzBT4PSFGZYrPDTDFveMLOeFjJsdLaTEyuWU4g4aZSb/h6vPQMPviGyocZ0t6KYlRkInmGU/M1RbSXHtDMsQcuIDWuvegjcHknhz8l+Nq6i8BMclEbGkAO7bgwGcTJtpc907s2BIQF38uDm3203rq9UAtEZRYiSiu2ou2csdT6+NEjE6UGxOgQR/VOz+PBvnEcpIV9+oabl9CtOM8AFzlZfHwFy7ScPs5aNQ9UTDaLlK9++vYyikvfpYes/kcJ2I6K9957Xz8gWcJh1ZSu+djALjSKdjd5yLppriqo7XhUrQ5SOu229HmAoItZ2LH+lHSuOGzsENrAKjff71Gu5fjz9sKLrYuEHAmeX1McOyJUesTDS0GSZRVoWMd6cUPU/7xx4lGlqDV5dr88X0arP8rFF+bGy+m/cgXsXvP1Nb/fFuaT7xDVEO1u16pzdt/gt36JmxpAZXb/pbUyfeDtBL9k21pVMMd56HR5I58hvCPhZADUIN4Ec0n34hrDNJz1WcBsKX5SNBPesXdRN+7gdKtX6V45m7RehfhI1/F7xZc/TSiZ0/Dm6Pidl8GdfB6rAQP3YLWcpjhS6j97kJsBUmduhatLMY18njzN4KoVu/+pIgvpBb9Ot5SR2c9x5iYBF3n/4Q9n3gYV87T9+6PQmOQ+o/uxyx6DH8gov7o20hb8OY6tA5pXySoKe3NDg08JG2VQCSV96CVxetT7I6LtfkkmN6WuO3vpPbAzWRf9zG8+Rsp/+AfpbH2HZz0+TWJBodGvxlHsGNDjDqDiI77E1Mcovuqr+nwl7+JC7qk7+pbUJvCPncJPavQ5g6V1maIRgy2BZIGyQtRywMPpOmJRhDsg8Zz4PlCakAl1adkFmSwm65GQ4vkHaXv30TpP69n7oevx+SGwfrgRQcin5mV5Rx95qtBGkkH8Rvng1hceRBJR7r3Cz+R+mOvoev89RQXLUfbPo2NhtY2lCz48xGvDyQVu6SD1lmT9xHYCoR7QBtoZj7kV1vxC0p9T5nG+jlkz1rLvBvehrEWKe4BBIwFlVi/TPslJEbjnCLYvkwbj14uhcu+i9+7D4Dmwx/T6HfvFWtDqmtXYTJKpk+oPAakIbMUvCK4KJ74kSxdfCAFrgntF0DLaPe5oJ5KWBLtesWzeJkS3sCTkr/yfQDY0QGq976X/KtuI71o47i+08RRRCVRcEL65E1IRtn+Z48xduv1uHqOzLK7sKPzVUurtO98VQLYdw+YkyCzDJyFcARsGWwdbOPwV1SGaAS0CZnFkFqCjP4SaW9Du88EyssIt7xK0mf9GFcdoPSDz7Lro0/gFWqzISWe3VEXkc4DYxn9/icZ/rsvkl3zFD1v/iGy/91IfamWf61Sf07oWg0Y0DazX48kL5QU4EHjaTQzD+m/GNQ0YP6/aPWBK6W9aanOu/5z0vPWG+Ncx8x4krMkRqGTnoNA5IEfsf87n2D/N76EjZT+P4BgRLSyDulaCRqAJsOPGonOJgeNZ9H8EqSwWin9WjGeof/dn6H3HX8L1gPPJuPNwRn34XGUFqOCOg9xhurtn8eNrqb9/EVATls7jZQfF/JLQMPp6jNNdMosByaLNrcihZVQOCPChZA97V4k8zxdV92IKQ7PZivN0KYT2bacI3hhOWgaMRZSAZnV67S96QpNFfPq5T0prxNSRYgqiR9pHsMr8T2uCVEJSfWild+hLvA1VTTaXn8ZqaXbx0lRm6O18bWEuxcm8zii2c40j4mTJY3Suv87H5XGE+eRW/kg+Zc/SfaMjZJe9Qhu66vZ95AjKhvSuTjUHtfWiYJJIRrCyL3K/CsM3slbcamnGbv1BppPXkqwdTX5l99B37tunK7UWWylxCw19Cn99D2692ufk2jXQky3I73Q0bXCZ+cPIdcDxk/8yvGHIkh9CBb+IdiypbVd0KYhvfgF5n3gExTfcOtM5M3W+UpcjxhLNLSEvV/5V5qPv478qY7yFsPYb6BnEWjES9ayNSmo7oT8Mhg439HcYciueZyBG67C690ZZ8TGTtfXzCJuOoNqfLmWoX7Ph8hkLtC+C9HsKaLVraiaOFdxLvn7Elw2QvHR6lYwBaPFNU696BWUv/MN7GhvvJbWj9OLY+9jAONiI1CHZJXiFTfp2MiZ4oYvpblXaQwLvg82SrbRS9RsNyAWaI1CbZtKcbFBup6k+y2fxusvxWT401ZmZsS4Rp7Wc8vQKI94XWgQganBvMewWy+mOWKI2goihE3wUi+RjxGIIggDcA5tDildc0Xo+y2N589GtixDTAUNe5AMZJevx5+7icNU3tMlJhFgPZobztXynX9E4/HXEg75YAQ1aHEl0gzBqWAVGjXIF4FOG/cYcTARnXxRBFp1iGyc6DZHjTS3Q+WO65DgOtSiqQV1us59WIqX3U52xRNHnPAsopLBRT7B5pXU115I6Wd/oVpaJcU1yo57hZEnwM+DWkhnIJtJMnk9tuR01DYC7QDaLRADtg3dS2DpVUpjiyD9G+i7+gvkX/4IqQXbpyt+Nv0YxfgR2RVPIG4O4foBcTXAQNQGB7ikZdBsxauYTcekuGRCM0tCD0FivJ02RSuEIExuKVjABqCqZBYKkl6MX8jHpHR6NHLoUc6LMAtiRMF5qAP8Kpnld9PadAXYfjCKIoz7XImVjiykDeonQfBomo4dXpxCYMG6mKQOlE6b2UCmTub0X+D1b0cjD4wgMq2QPcsOnokQFTLLfq3S9XGpb55L+7k3qqScWDyMTnC6ApGLJ+AJ4gl4GicKB6k32T6bRH8rEBLLgwkNrmSrOgcmqxrsEWxmSHquuZnM8ocQ3zKDNufMfIxaD1vpJti2RMv3vUHKv3gLjSfPwdY8ulcJddBtv4JUZvJoNO4XAKOIp+PHaJObkSR1KrEVWDkwbDIexUDYgsGXIwMnQXmdIlZILx6h8OoHKF5yJ13nPEBq3jCSqR9uqtO0mGRfRvv7Gf3x+6k8eKW0d6YgVNKL12L0LIpn5bDb4vDT8SVTIYpnpuOdC8BMkmu6Q09lOUDIZPJF42dnuyG/DLUuFOn6LeJlCPcMaPmuN0qwYzU9V/yI7KmPHq7qnqHFhD4u6MFkHWiA2ibVn3+Ise9/HS+vhIHoUz+DqAniTaH9VLIn0276Xz/oa6veBPk+JSwJvVd/lb53fobELcdS1QOJDidjZj5GUhFeav/4NhEHLugid/aD2NH5mOrpWjhJGdkspLwZJr2S+IsJW2qmHRTbhu4FKrkegdwY+aUbcQ2faDSN31+HKBWfIByeFJh1dQ1xZFIQP9Ko1Me2T9wsjQev0bDP6aZHjPoyjaxXQHwEC64Tcg1ICkXjXGjaMEgUIkvPc9ItRul9QU75h2vJrVwb10ixrkzTAc+iiBx3ChbxI8b++3KeuugR2XPzNYRWZc5iQ2EuJogwajBOJr3EGYwDr9VC22A5CWsW4FwRabXxwhBR70Xfia9D5RlMFEG2G5m31OBAKr9cohsveYhdX7kRDVMxKXqcohIw7rCam87SbV/4FPv+4+2kBhrkz9hGrv90yfYY3feCcU/dD34aRA74S4W4RFCMOpxmaSy8Fln8dkzxVDAZtD2CG3oUf8s3ydaexqUySXfZIhrvAMUD46OqiFoQg4YhsuxVmIVnOA3qSCRPEezwaaxfSX7lRhZ++nP0XfFTkHA6zmuGeUxCSuPpxez55w9KdsEIq+66nPyqp6ne89eMfvcM2k5l7qnI4DCyfWNcSrmYfGNA/fiRIQVq5/w7uWVXkRblAH2nYOefS2PxHxM++n669/wAFcGKj031AoKJmvi2hXgG56eg1UYGFmEWrICgoRINe/S+9VnmXPc+gt2LqD12AdWHLiQ1bzOF8x+Pf2xw+BPK2TWqXCuDSYXgJcIVSnd8BCgQ7DybPd+6Gj+l7c11aabXoL0rQS2mvIHs/l+Rbg6x/5xbyJ/956TbdWyniZ/IEhwm3UW1VoP/fQsmP0i09DpM4WTAwzX3wN77ye34NrnKZrR7Dmb1WQ47bOi98jF6LroTW1Z6Lv8nTHHsQFie/lHKUZ0SqLMpBE9ELJiQqNyrz/zprTJ622Xlvg+69vxPmUx+AJOK09zICuGeR7HP/Rupc75AoauItRaRF5u2Oot4KaqVMul8kUwuj9hkK4nBYqjv30Vm3YfoW7Qfct3K8H1CbslOln3/crpWr4+PT0RRlfhsffrn2EdxriSGpKegKqrhyFLz9LXfY/S+80pdb7L1k7/n9RRSOFsfT9nFeKjXRbMdkjFtxBwppCvG81EXgYti35J8LjhMqkipWqOn/BmK/nbV6p4q1ce7ybxsl6y+603kV607cLY0M8zWYjzA1uv1NbVq5ZrIyZm0d68yI99bmvHLrtr9l6YwZwVi66h4TExXVR1Gkqx3Whlc8oOpycZqiKOb1vBtbpH8vdF5H7lRNHqe7Tfe5JxG5sz7LiRzygvjp6UzwGyIMYAbGhr6QKVa+VI2m+/2jKiYNNYUtd2sm7QXkE4pDjN5aaiJsz3a/owqYnyq5T1K83kxuUXP+oUV3xroie7Ijt38J1pZd7acetOHySx6YaaHbjMiRlU9EbH79++/dGho5J7evl6jzkWxCDWoNWIMqsTbesqndgRO+9FT6wSIGFSyoG1tt6rSatuHFp+67K0F2TKgttklXWvWHjdiVNUAvogEm57ddJvx/Dd7vheq09TBSz+h3XAkAo7UaeikY4eO00PuqZJsOfX8dNBuNTJh0LxjxcpVb/aMN3H0tDHtPEZEFAjGxkbPbDQaq/JdBWzQKQsmpP+TcjTx/hFKBUnmME7IhPdTjek0xUCCsJH2Pc+12tEbKqXSq/v65zysqpLoP20ckZjO9qlWq6dv3rzl8+0geE06nTkpCENU1YhI7DMmCbkTZGCS+24aYwGMCC55HU9ZXjRm/JODOngqzjkXRTYThNGczogjzfNQHIkYEREbBEF+44anb0Hkomw2Z506LwxDjDFYazHGoE5x6l40aVXF931aQRsjBj+VwlobF4kc7IdUFc/zQJV2ZEln0jjnYoImWJkRwXgeThXnHOrcgR6YMWqsM81mI/Q8b2imhIxP/HA+pmMtw8PDq3/zm98+MX9wQWgjm1JVzzpLrVZj38gQPb29zJ07gBGTTDgRjiACzWaT7du34XmGwQULyeXyiUVMXIH4bxgGDO3dQ7VSpX/OXLq7u0lnMhgx463LyFrGSmO0220GBxeQSsoMBcIwxPd912o2Deh/veY1F1xrjAmZoZ85ksUoQKFQGB0ZGd6+Y+eOJT3d3dY5dUHQ1iAIPIBKpcK+kRGKxW4y2Ry+76GqRGFIrVajUinHK6tKqVSiUCjS1dVFJpPBePHYMAhoNBtUKxWCIEBEqNYqeJ5HKpUhlUohIlgb0W634zHA6P59dBUK+H4KZ63WajUVQT3f13KpdOXppy9dMX/+4PqZ+pkjRqXEj7idO3e+/v777//yvn37XhlFkRpjJJfLKUlXzFprnHPxThJB3bhg9X3fTZAn1lpjrRURoeOj4uQPjDHx1lTFGAOq1qmqqnYioxhB4sQbnFOnSZUaBkEcgkS03W7LwMDAs+9617suyufzQ8zQYmaUxwRB0Ds2NnZarVYrrl+//m+eeeaZK51z6vu++L6PEWMRUBR1iqp61lrC2FEjIokFpNTzPJs8+yCnNEEfdc5JGIZeFMU1kuf5+L6nIuJiQh3OqRdFEVEUMTg4uDWbze4OwzAzb9685y644IIb586d+0xncac90ZkQo6oe4Drm6JzLbNmy5dINGzZcu2vXrgvK5fJgEARd41HFGNLpdLlYLO5euHDh+oULF67bu3fvmm3btr2yVCotabfb6fHoklhOh5jO5fu+9vf3bVq9es3PAdm4cePllUrl5CAIss45NcZINputzJkzZ9Py5cvvOO+8876Ry+X2H7JtZpzDzIiYCeM7hYsmqyD1en2wWq3ObzQaJwVBoIBks1mbz+f3FgqFoXw+P9xRrl6vD4yNjZ02MjJy9r59+04ul8uLm82mhGHc2sxkMlIoFGpz587dtGDB4IaBgYFHuroK+wCazeZJ5XL5lFarNSeKItLptM3lcnu7u7u3ZjKZg366FW9rYaaWMltiDoJzzgfUmMMXaM45DzDJFph07ETrmeT7qeQ5kzaxVVVU1Uv0OAaFxlES00HHKSbWNC6wY84TVk0mONGDxkwhU0WkY5mTPif5vs40sz0STvwX7RT4Pfm/698/nCBmCpwgZgqcIGYKnCBmCpwgZgqcIGYKnCBmCpwgZgqcIGYKnCBmCvwfXtNclQ0LjMsAAAAASUVORK5CYII=' + +orangeround = b'data:image/png;base64,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' + +weather_icon_dict = {'clear-day': w1, 'clear-night': w1, 'rain': w3, 'snow': w3, 'sleet': w3, 'wind': w3, 'fog': w3, + 'cloudy': w4, 'partly-cloudy-day': w5, 'partly-cloudy-night': w5} + +led_digits = [led0, led1, led2, led3, led4, led5, led6, led7, led8, led9] + +if __name__ == '__main__': + led_clock() diff --git a/PySimpleGUIQt/Demo Programs/Qt_Demo_Matplotlib_Two_Windows.py b/PySimpleGUIQt/Demo Programs/Qt_Demo_Matplotlib_Two_Windows.py new file mode 100644 index 000000000..15e5fe26b --- /dev/null +++ b/PySimpleGUIQt/Demo Programs/Qt_Demo_Matplotlib_Two_Windows.py @@ -0,0 +1,29 @@ +from matplotlib import use +# import PySimpleGUI as sg # Same program can be used with tkinter port +import PySimpleGUIQt as sg; use('qt5agg') +import matplotlib.pyplot as plt + +""" + Simultaneous PySimpleGUI Window AND a Matplotlib Interactive Window + A number of people have requested the ability to run a normal PySimpleGUI window that + launches a MatplotLib window that is interactive with the usual Matplotlib controls. + It turns out to be a rather simple thing to do. The secret is to add parameter block=False to plt.show() +""" + +def draw_plot(): + plt.plot([0.1, 0.2, 0.5, 0.7]) + plt.show(block=False) + +layout = [[sg.Button('Plot'), sg.Cancel(), sg.Button('Popup')]] + +window = sg.Window('Have some Matplotlib....', layout) + +while True: + event, values = window.read() + if event in (None, 'Cancel'): + break + elif event == 'Plot': + draw_plot() + elif event == 'Popup': + sg.popup('Yes, your application is still running') +window.close() diff --git a/PySimpleGUIQt/Demo Programs/Qt_Demo_OpenCV_Webcam.py b/PySimpleGUIQt/Demo Programs/Qt_Demo_OpenCV_Webcam.py new file mode 100644 index 000000000..57d72f77a --- /dev/null +++ b/PySimpleGUIQt/Demo Programs/Qt_Demo_OpenCV_Webcam.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python +import sys +if sys.version_info[0] >= 3: + import PySimpleGUIQt as sg +else: + import PySimpleGUI27 as sg +import cv2 +import numpy as np +from sys import exit as exit + +""" +Demo program that displays a webcam using OpenCV +""" +def main(): + + sg.ChangeLookAndFeel('LightGreen') + + # define the window layout + layout = [[sg.Text('OpenCV Demo', size=(40, 1), justification='center', font='Helvetica 20')], + [sg.Image(filename='', key='image')], + [sg.Button('Record', size=(10, 1), font='Helvetica 14'), + sg.Button('Stop', size=(10, 1), font='Any 14'), + sg.Button('Exit', size=(10, 1), font='Helvetica 14'), + sg.Button('About', size=(10,1), font='Any 14')]] + + # create the window and show it without the plot + window = sg.Window('Demo Application - OpenCV Integration', + location=(800,400)) + window.Layout(layout) + + # ---===--- Event LOOP Read and display frames, operate the GUI --- # + cap = cv2.VideoCapture(0) + recording = False + while True: + event, values = window.Read(timeout=0, timeout_key='timeout') + if event == 'Exit' or event is None: + sys.exit(0) + pass + elif event == 'Record': + recording = True + elif event == 'Stop': + recording = False + img = np.full((480, 640),255) + imgbytes=cv2.imencode('.png', img)[1].tobytes() #this is faster, shorter and needs less includes + window.FindElement('image').Update(data=imgbytes) + elif event == 'About': + sg.PopupNoWait('Made with PySimpleGUI', + 'www.PySimpleGUI.org', + 'Check out how the video keeps playing behind this window.', + 'I finally figured out how to display frames from a webcam.', + 'ENJOY! Go make something really cool with this... please!', + keep_on_top=True) + if recording: + ret, frame = cap.read() + imgbytes=cv2.imencode('.png', frame)[1].tobytes() #ditto + window.FindElement('image').Update(data=imgbytes) + +main() +exit() \ No newline at end of file diff --git a/PySimpleGUIQt/Demo Programs/Qt_Demo_System_Tray_Icon.py b/PySimpleGUIQt/Demo Programs/Qt_Demo_System_Tray_Icon.py new file mode 100644 index 000000000..f4dcdefee --- /dev/null +++ b/PySimpleGUIQt/Demo Programs/Qt_Demo_System_Tray_Icon.py @@ -0,0 +1,71 @@ +""" + Demonstrates how to use a window in conjunction with a system tray icon to simulate the typical + windows program that uses the system tray + + When the window is showing, there is no system tray icon shown. + When closing the window with X button, the system tray is activated + Clicking the "Minimize to Tray" button causes the window to disappear and the tray icon to appear + Double clicking tray icon causes window to re-appear + Choosing "Restore" from system tray right click menu will retore the window +""" + +logo = b'iVBORw0KGgoAAAANSUhEUgAAADIAAAAtCAMAAADbYcjNAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAADBpmDFqmDBqmTFqmjJrmzJsmzJsnDNtnTRrmjVtmjZsmzRunTRunjVvnzdwnjVwnzpxnzVwoDZxoTdyojlyoThzozhzpDh0pDp1pjp2pj51ozt3qDt4qDx4qDx5qj16qj57rD58rT98rkF1oEB4pUB4pkR6pkJ6qEN8q0B9rUB9rkB+rkV7qUZ8qUp9p0x+p0h/rEB+sEeArkqArEqBr0uCrkKAsUKAskOCs0OCtESCtEWEtkaFuEaGuE2FsUiHukiIukmJvEmKvEqLvkuMvk2KuUyLvEyMv1OErVWDqlWHr1qHrVaIsVCMvFSPvV2LsViOuVSQvmyUtmyXuXKbvXefv3ugv06NwE6OwFmUwl2XxGScyGmbw22hynikxnmmyv/UO//UPP/VPf/UPv/VP//UQP/VQf/VQv/WQP/WQf/WQv/WQ//XRP/WRf/WSf/YRf/YRv/YR//YSP/ZSf/ZSv/aS//aTP/aTf/bTv/YUf/ZUv/bUP/cUP/cUv/dVP/dVv/eVv/bW//dWf/cWv/eWP/fWv/dXf/fXf/eXv/cYP/fYP/dZP/dZv/eZf/fZv/eaP/gW//gXP/gXv/gYP/iYf/iYv/hZP/jZP/iZv/kZv/jaf/ja//kaP/lav/kbP/lb//mbP/mbv/ncP/mcv/iff/ocv/odP/odv/oeP/of//qf4GnxYOox4SoxYSpx4asyo+ux4isyouuyouvzIyuyYyvy4yvzI6wy46wzIyz0pCuyJSxyZWyy5u3zZ24zpW30pG52J250J+60aC60KS90aDC3a3E163F2K3F2bPI2bvO3rzP3qvJ4LHN4rnR5P/qgf/qgv/qiP/sif/sjf/sj//olf/ql//ulv/omf/qnv/tnP/qoP/ro//qpP/sov/upf/tqP/uqP/vrf/vrv/us//wpP/wpv/xrf/wsP/wsv/ys//xtP/ytf/ytv/zuf/zuv/0vP/0vsDS38XZ6cnb6f/xw//zwv/yxf/1w//zyP/1yf/2zP/3z//30wAAAM55ho4AAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAABcQAAAXEAEYYRHbAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjFjKpxLAAADnElEQVRIS62OeVhUZRSHw6IosQzGBgoIszKXqGylghKwbHErNVPbEFQQTXYogzZtt2SmiSEHnBHJPdM2Ldv3xbW91Pay0tT29dc53znfvTP809Pz9P7x3Xvu8773fHvhP/M/JBce0GX/8/WduX3ipDt/1nclNrk4TnhR5y1FVzHX/KqzISY5Uou4uLVm/sgEzF1mFqKTruozL9D8gfrM1aIwbvJaF7WFJ4FJqgtb1XOTN1R1eBqYrLbwvpo2+SF2B/NEbFNY+IWoNum6t0UD4imgTO3CCROKiqaJqsnx8fHx+7ho/RBALsnFxcUlJSWlNxpXkkv2I/a1uPnLWEA626WlU6aUlf3uJomJiccdlJDAoQvFBwPsklw2deq06dNnO8nIbj3oHE4hkWDQ7HVcSzLb5eXlFRWVTtKj+/P8OJDojfO6Wahfi3uMW1FZWVVVVV39jk2Skl6RR9JhwOjunDJUPYfZ1q6uqampvcUmWZ4sOpcnJ9Pj8WQqHYAZ4tbW1tXV19ffbJNXPZ6sUUM8nqOBRzweT7LDBQDZdcYmZlz3rk2wNCUlxes9iXYcwlBmOAq4W12moeE2liXBg9QcA6yiB+P1eqk8FtgmdoOh8SbjaoJlqacAj6ZqYqBffCJyo+GGO0S1CVYDKw8VUg0nAJ87NnOrmk4CPJYmSNeHdjQ2Xm/kmcx9qkUlKzKU9PT0tLSTaYeVZ84i/KpFJQ9nZmYermRknAh8qu6sOU1EUDXCJit6UuJwFu1gm+WmJp/PR7f6xr9NVE2eOYLoaeEdVvb5/H7/XOC7QCDwoXE16d+L4IzpC3xmZLb99wYC9wPbm5mP2ZVkRH9DP0OvK/CLcUkmmpvn0Y5gsKWlJRRykwEOXAJBI5NNBNtoRyhEJxa3bnKS005ltBoAqGz+3E47Qq2tO9gLR+jQJAbaItdgWhdje1tbOPwHe5GFdEhyuiE7O1sTkQ1t4fZwOBKJbCTt6/lfOsllZ0TzE9rZpV8bORKZz2z46q2ODpYlwZmCJFfiTyuL3WHZzK4ma7QRgJ2dZcG4mmBoriEnJ4eSc4BvO9vMe0a1CQZKIwwDdqkWxRIxnWT9QOJsITd3KN1NRRc1nQTrzs3L40y4CNitprLwbxXdBD/mM3nCWPoQs+cBkYioBLi8oMBk+flcAHtUJ942HwwxCd4cM2hQATFO5+81WPSbfmBiE+Cl8ZcOHvusDsBfG+hKm/foJHRO/hXgH831bVAP1oP5AAAAAElFTkSuQmCC' + +import PySimpleGUIQt as sg + +# create and then hide the tray icon +menu_def = ['My Menu Def', ['&Restore', '&Open','---', '&Message','&Save',['1', '2', ['a','b']], '&Properties', 'E&xit']] +tray = sg.SystemTray(menu=menu_def, data_base64=logo) +tray.Hide() + +# create the window +layout = [ + [sg.Text('Tray Icon Demo') ], + [sg.Button('Minimize to Tray')] + ] +window = sg.Window('My window').Layout(layout) + +tray_visible = False +window_visible = True +window_closed = False +while True: # the event loop + # do normal window operations + if window_visible: + event, values = window.Read() + print(event) + if event is None: # if window closed with X + tray.UnHide() + tray_visible = True + window_visible = False + window_closed = True + elif event == 'Minimize to Tray': + print('Minimizing to tray') + window.Hide() + tray.UnHide() + tray_visible = True + window_visible = False + + # do tray icon stuff. Tray events will cause the window.Read call to return with a Timeout event + if tray_visible: + menu_item = tray.Read() + if menu_item == 'Restore' or menu_item == sg.EVENT_SYSTEM_TRAY_ICON_DOUBLE_CLICKED: + print('Restoring') + tray.Hide() + tray_visible = False + window_visible = True + # If the window was completely closed, must get a BRAND NEW WINDOW MADE from scratch. No re-use allowed + if window_closed: + window_closed = False + layout = [ + [sg.Text('Tray Icon Demo')], + [sg.Button('Minimize to Tray')] + ] + window = sg.Window('My window').Layout(layout) + else: + window.UnHide() + else: # some other tray command was received + print('Menu item %s'%menu_item) + if menu_item == 'Exit' or menu_item == sg.EVENT_SYSTEM_TRAY_MESSAGE_CLICKED: + break + elif menu_item == 'Message': + tray.ShowMessage('Title of message', 'This is a tray message\nNote the icon shown in the message too\nIf you click the message it will close the program') \ No newline at end of file diff --git a/PySimpleGUIQt/Demo Programs/Qt_Demo_Table_Element.py b/PySimpleGUIQt/Demo Programs/Qt_Demo_Table_Element.py new file mode 100644 index 000000000..05a411cff --- /dev/null +++ b/PySimpleGUIQt/Demo Programs/Qt_Demo_Table_Element.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python +import sys + +if sys.version_info[0] >= 3: + import PySimpleGUIQt as sg +else: + import PySimpleGUI27 as sg +import csv + +# sg.PopupQuickMessage('Loading...', auto_close_duration=4, keep_on_top=True, location=(800,800)) +# sg.Popup('This is a normal blocking popup','It was called after the PopupQuickMessage call.', location=(1000,800)) + +filename = r'C:\Python\PycharmProjects\GooeyGUI\ProgrammingClassExamples\Win10 versions\AFL2018 (sorted pts and %).csv' +# filename = sg.PopupGetFile('filename to open', no_window=False, file_types=(("CSV Files","*.csv"),)) +# --- populate table with file contents --- # +data = [] +if filename is not None: + with open(filename, "r") as infile: + reader = csv.reader(infile) + try: + data = list(reader) # read everything else into a list of rows + except: + sg.PopupError('Error reading file') + sys.exit(69) +else: + sys.exit() + +# sg.SetOptions(element_padding=(0,0)) +headings = [data[0][x] for x in range(len(data[0]))] +print(data) +layout = [[sg.Table(values=data[1:][:], headings=headings, max_col_width=25, + auto_size_columns=True, display_row_numbers=True, change_submits=True, bind_return_key=True, justification='right', num_rows=20, alternating_row_color='lightblue', key='_table_', text_color='black')], + [sg.Button('Read'), sg.Button('Double')], + [sg.T('Read = read which rows are selected')],[sg.T('Double = double the amount of data in the table')]] +window = sg.Window('Table', grab_anywhere=False, resizable=True).Layout(layout) + +window.FindElement('_table_').StartingRowNumber = 1 +window.FindElement('_table_').RowHeaderText = 'Row' + +while True: + event, values = window.Read() + print(event, values) + if event is None: + break + # sg.Print( event, values, location=(200,200)) + if event == 'Double': + for i in range(len(data)): + data.append(data[i]) + window.FindElement('_table_').Update(values = data) + # sg.Popup(event, values) + # print(event, values) + +sys.exit(69) diff --git a/PySimpleGUIQt/Demo Programs/Qt_Demo_Touch_Keyboard.py b/PySimpleGUIQt/Demo Programs/Qt_Demo_Touch_Keyboard.py new file mode 100644 index 000000000..95bd3b98c --- /dev/null +++ b/PySimpleGUIQt/Demo Programs/Qt_Demo_Touch_Keyboard.py @@ -0,0 +1,98 @@ +import PySimpleGUIQt as sg + + +class keyboard(): + def __init__(self, font=('Arial', 16)): + self.font = font + numberRow = '1234567890' + topRow = 'QWERTYUIOP' + midRow = 'ASDFGHJKL' + bottomRow = 'ZXCVBNM' + keyboard_layout = [[sg.Button(c, key=c, pad=(0, 0), size=(4, 2), font=self.font) for c in numberRow] + [ + sg.Button('⌫', key='back', pad=(0, 0), size=(4, 2), font=self.font), + sg.Button('Esc', key='close', pad=(0, 0), size=(4, 2), font=self.font)], + [sg.T(' ' * 4)] + [sg.Button(c, key=c, pad=(0, 0), size=(4, 2), font=self.font) for c in + topRow] + [sg.Stretch()], + [sg.T(' ' * 11)] + [sg.Button(c, key=c, pad=(0, 0), size=(4, 2), font=self.font) for c in + midRow] + [sg.Stretch()], + [sg.T(' ' * 18)] + [sg.Button(c, key=c, pad=(0, 0), size=(4, 2), font=self.font) for c in + bottomRow] + [sg.Stretch()]] + + self.window = sg.Window('keyboard', + grab_anywhere=True, + keep_on_top=True, + alpha_channel=0, + location=(850,350), + no_titlebar=True, + ).Layout(keyboard_layout).Finalize() + self.hide() + + + def hide(self): + self.visible = False + self.window.Disappear() + + def show(self): + self.visible = True + self.window.Reappear() + + def togglevis(self): + if self.visible: + self.hide() + else: + self.show() + + def update(self, focus): + self.event, _ = self.window.Read(timeout=100) + if focus is not None: + self.focus = focus + if self.event is not None: + if self.event == 'close': + self.hide() + elif len(self.event) == 1: + self.focus.Update(self.focus.Get() + self.event) + elif self.event == 'back': + Text = self.focus.Get() + if len(Text) > 0: + Text = Text[:-1] + self.focus.Update(Text) + + + def close(self): + self.window.Close() + + +class GUI(): + def __init__(self): + layout = [[sg.Text('Enter Text')], + [sg.Input(size=(17, 1), key='input1', do_not_clear=True)], + [sg.InputText(size=(17, 1), key='input2', do_not_clear=True)], + [sg.Button('on-screen keyboard', key='keyboard')], + [sg.Button('close', key='close')]] + + self.mainWindow = sg.Window('On-screen test', + grab_anywhere=True, + no_titlebar=False, + ).Layout(layout).Finalize() + self.keyboard = keyboard() + self.focus = None + + def run(self): + while True: + cur_focus = self.mainWindow.FindElementWithFocus() + if cur_focus is not None: + self.focus = cur_focus + event, values = self.mainWindow.Read(timeout=100, timeout_key='timeout') + if self.focus is not None: + self.keyboard.update(self.focus) + if event == 'keyboard': + self.keyboard.togglevis() + elif event == 'close' or event is None: + break + self.keyboard.close() + self.mainWindow.Close() + + +if __name__ == '__main__': + app = GUI() + app.run() diff --git a/PySimpleGUIQt/Demo Programs/Qt_Demo_imwatchingyou.py b/PySimpleGUIQt/Demo Programs/Qt_Demo_imwatchingyou.py new file mode 100644 index 000000000..ec1ccbd7b --- /dev/null +++ b/PySimpleGUIQt/Demo Programs/Qt_Demo_imwatchingyou.py @@ -0,0 +1,23 @@ +import PySimpleGUIQt as sg +import imwatchingyou + +""" + Combining the imwatchingyou debugger package with PySimpleGUIQt + This enables you to have a live debugger / REPL in a running PySimpleGUIQt program +""" +layout = [[sg.Text('My PySimpleGUIQt layout')], + [sg.B('OK'), sg.B('Debugger'), sg.B('Popout')]] + +window = sg.Window('My window', layout) + +counter = 0 # something to see updating in the popout window +while True: + event, values = window.read(timeout=100) + if event is None: + break + if event == 'Debugger': + imwatchingyou.show_debugger_window() + elif event == 'Popout': + imwatchingyou.show_debugger_popout_window() + imwatchingyou.refresh_debugger() + counter += 1 diff --git a/PySimpleGUIQt/Demo Programs/Qt_Dial.py b/PySimpleGUIQt/Demo Programs/Qt_Dial.py new file mode 100644 index 000000000..fa4ca7c15 --- /dev/null +++ b/PySimpleGUIQt/Demo Programs/Qt_Dial.py @@ -0,0 +1,22 @@ +import PySimpleGUIQt as sg + +layout = [ + [sg.Text('This is the new Dial Element!')], + [sg.T(' ', size=(70,10)), sg.T('0', key='+DIAL_VALUE+', font=('Helvetica', 15))], + [sg.Dial(range=(1,100), key='_DIAL_', change_submits=True)], + [sg.Slider((1,100), orientation='h', key='_SLIDER_', change_submits=True), + sg.T(' 1', key='+SLIDER_VALUE+', font=('Helvetica', 15))], + [sg.T('1' + 30*' ' + '100')], + [sg.Button('Show'), sg.Button('Exit')] + ] + +window = sg.Window('Window Title').Layout(layout) + +while True: # Event Loop + event, values = window.Read() + if event is None or event == 'Exit': + break + window.FindElement('+DIAL_VALUE+').Update(values['_DIAL_']) + window.FindElement('+SLIDER_VALUE+').Update(values['_SLIDER_']) + +window.Close() diff --git a/PySimpleGUIQt/Demo Programs/Qt_Scrape_GitHub_Issues.py b/PySimpleGUIQt/Demo Programs/Qt_Scrape_GitHub_Issues.py new file mode 100644 index 000000000..b1a460d53 --- /dev/null +++ b/PySimpleGUIQt/Demo Programs/Qt_Scrape_GitHub_Issues.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python +import PySimpleGUIQt as sg + +import re +# Import requests (to download the page) +import requests + +# Import BeautifulSoup (to parse what we download) +from bs4 import BeautifulSoup + +# search github for total open issues and Issue Number of first issue +def get_num_issues(): + url = "https://github.com/MikeTheWatchGuy/PySimpleGUI/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc" + # set the headers like we are a browser, + headers = { + 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'} + # download the page + response = requests.get(url, headers=headers) + # parse the downloaded homepage and grab all text, + soup = BeautifulSoup(response.text, "lxml") + # look for phrase "XXX Open" + findopen = re.compile(r"\d+ Open") + # get number of open issues + number_open_string = findopen.search(str(soup)).group(0) + num_open_issues = number_open_string[0:number_open_string.index(' ')] + # find the first issue in the list by earing for "issue-id-XXXX" + find_first_issue = re.compile(r'issue-id-\d+') + first_issue_string = find_first_issue.search(str(soup)).group(0) + first_issue = first_issue_string[9:] + return num_open_issues, first_issue + + +def gui(): + sg.ChangeLookAndFeel('Topanga') + + sg.SetOptions(border_width=0) + + layout = [ + [sg.T('GitHub Issues Watcher' + 5 * ' ', click_submits=True, key='GitHub'), + sg.Button('', size=(25,25), + image_data=red_x, + key='_quit_',button_color=(sg.LOOK_AND_FEEL_TABLE['Topanga']['TEXT'],sg.LOOK_AND_FEEL_TABLE['Topanga']['BACKGROUND']), + tooltip='Closes window')], + [sg.T('', key='_status_', size=(12, 1))], + [sg.T('', key='_numissues_', size=(18, 1))], + ] + + window = sg.Window('Issue watcher', + no_titlebar=True, + grab_anywhere=True, + keep_on_top=True, + alpha_channel=.8, # dim the lights a little + location=(2360,310), # locate in upper right corner of screen + ).Layout(layout).Finalize() + + window.Refresh() + status_elem = window.FindElement('_status_') + issues_elem = window.FindElement('_numissues_') + + initial_issue_count, initial_first_issue = get_num_issues() + # The Event Loop runs every 5000ms + poll_frequncy = 5000 + seconds = 0 + while True: + # read with a 5 second timeout + event, values = window.Read(timeout=poll_frequncy) + # print(event, values) + if event in ('_quit_', None): + break + + if seconds % 60 == 0 or event.startswith('GitHub'): # Every 60 seconds read GitHub + status_elem.Update('Reading...') + window.Refresh() + issues, first_issue = get_num_issues() + issues_elem.Update('{} Issues. {} is first issue'.format(issues, initial_first_issue)) + window.Refresh() + # if something changed, then make a popup + if issues != initial_issue_count or first_issue != initial_first_issue: + sg.PopupNoWait('Issues changed on GitHub ', 'First issue # is {}'.format(first_issue), background_color='red', keep_on_top=True) + initial_issue_count = issues + initial_first_issue = first_issue + status_elem.Update('') + else: + status_elem.Update('.' if seconds%2 else '') # blink a '.' every 2 seconds so know still running + + seconds += poll_frequncy/1000 + +red_x = b"R0lGODlhEAAQAPeQAIsAAI0AAI4AAI8AAJIAAJUAAJQCApkAAJoAAJ4AAJkJCaAAAKYAAKcAAKcCAKcDA6cGAKgAAKsAAKsCAKwAAK0AAK8AAK4CAK8DAqUJAKULAKwLALAAALEAALIAALMAALMDALQAALUAALYAALcEALoAALsAALsCALwAAL8AALkJAL4NAL8NAKoTAKwbAbEQALMVAL0QAL0RAKsREaodHbkQELMsALg2ALk3ALs+ALE2FbgpKbA1Nbc1Nb44N8AAAMIWAMsvAMUgDMcxAKVABb9NBbVJErFYEq1iMrtoMr5kP8BKAMFLAMxKANBBANFCANJFANFEB9JKAMFcANFZANZcANpfAMJUEMZVEc5hAM5pAMluBdRsANR8AM9YOrdERMpIQs1UVMR5WNt8X8VgYMdlZcxtYtx4YNF/btp9eraNf9qXXNCCZsyLeNSLd8SSecySf82kd9qqc9uBgdyBgd+EhN6JgtSIiNuJieGHhOGLg+GKhOKamty1ste4sNO+ueenp+inp+HHrebGrefKuOPTzejWzera1O7b1vLb2/bl4vTu7fbw7ffx7vnz8f///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAJAALAAAAAAQABAAAAjUACEJHEiwYEEABniQKfNFgQCDkATQwAMokEU+PQgUFDAjjR09e/LUmUNnh8aBCcCgUeRmzBkzie6EeQBAoAAMXuA8ciRGCaJHfXzUMCAQgYooWN48anTokR8dQk4sELggBhQrU9Q8evSHiJQgLCIIfMDCSZUjhbYuQkLFCRAMAiOQGGLE0CNBcZYmaRIDLqQFGF60eTRoSxc5jwjhACFWIAgMLtgUocJFy5orL0IQRHAiQgsbRZYswbEhBIiCCH6EiJAhAwQMKU5DjHCi9gnZEHMTDAgAOw==" + + +gui() diff --git a/PySimpleGUIQt/Demo Programs/Qt_Scrape_GitHub_Issues_System_Tray.py b/PySimpleGUIQt/Demo Programs/Qt_Scrape_GitHub_Issues_System_Tray.py new file mode 100644 index 000000000..8f836636d --- /dev/null +++ b/PySimpleGUIQt/Demo Programs/Qt_Scrape_GitHub_Issues_System_Tray.py @@ -0,0 +1,145 @@ +#!/usr/bin/env python +import PySimpleGUIQt as sg +import subprocess +import re +# Import requests (to download the page) +import requests + +# Import BeautifulSoup (to parse what we download) +from bs4 import BeautifulSoup + +# CCNSTANTS - CHANGE THESE TO MATCH YOUR SYSTEM +CHROME = r"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" +DISCORD = r"C:\Users\mike\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Discord Inc\Discord.lnk" +VIEW_ISSUES_URL = r'https://github.com/MikeTheWatchGuy/PySimpleGUI/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc' +PULL_REQUEST_URL = r'https://github.com/MikeTheWatchGuy/PySimpleGUI/compare/master...Dev-latest' + + +# search github for total open issues and Issue Number of first issue +def get_num_issues(): + url = "https://github.com/MikeTheWatchGuy/PySimpleGUI/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc" + # set the headers like we are a browser, + headers = { + 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'} + # download the page + response = requests.get(url, headers=headers) + # parse the downloaded homepage and grab all text, + soup = BeautifulSoup(response.text, "lxml") + # look for phrase "XXX Open" + findopen = re.compile(r"\d+ Open") + # get number of open issues + number_open_string = findopen.search(str(soup)).group(0) + num_open_issues = number_open_string[0:number_open_string.index(' ')] + # find the first issue in the list by earing for "issue-id-XXXX" + find_first_issue = re.compile(r'issue-id-\d+') + first_issue_string = find_first_issue.search(str(soup)).group(0) + first_issue = first_issue_string[9:] + return num_open_issues, first_issue + + +def gui(): + sg.ChangeLookAndFeel('Topanga') + + sg.SetOptions(border_width=0) + + layout = [ + [sg.T('GitHub Issues Watcher' + 5 * ' ', click_submits=True, key='GitHub'), + sg.Button('', size=(25,25), + image_data=red_x, + key='_quit_',button_color=(sg.LOOK_AND_FEEL_TABLE['Topanga']['TEXT'],sg.LOOK_AND_FEEL_TABLE['Topanga']['BACKGROUND']), + tooltip='Closes window')], + [sg.T('', key='_status_', size=(12, 1))], + [sg.T('', key='_numissues_', size=(20, 1))], + ] + + window = sg.Window('Issue watcher', + no_titlebar=True, + grab_anywhere=True, + keep_on_top=True, + alpha_channel=.8, # dim the lights a little + location=(2360,310), # locate in upper right corner of screen + ).Layout(layout).Finalize() + + window.Refresh() + status_elem = window.FindElement('_status_') + issues_elem = window.FindElement('_numissues_') + + initial_issue_count, initial_first_issue = get_num_issues() + seconds = 0 + poll_frequncy = 1000 + while True: + event, values = window.Read(timeout=poll_frequncy) + if event in ('_quit_', None): + break + if seconds % 60 == 0 or event.startswith('GitHub'): # Every 60 seconds read GitHub + status_elem.Update('Reading...') + window.Refresh() + issues, first_issue = get_num_issues() + issues_elem.Update('{} Issues. {} is first issue'.format(issues, initial_first_issue)) + window.Refresh() + # if something changed, then make a popup + if issues != initial_issue_count or first_issue != initial_first_issue: + sg.PopupNoWait('Issues changed on GitHub ', 'First issue # is {}'.format(first_issue), background_color='red', keep_on_top=True) + initial_issue_count = issues + initial_first_issue = first_issue + status_elem.Update('') + else: + status_elem.Update('.' if seconds%2 else '') # blink a '.' every 2 seconds so know still running + + seconds += poll_frequncy/1000 + window.Close() + + + +def system_tray(): + + menu_def = ['Root', + ['E&xit']] + tray = sg.SystemTray(data_base64=logo, tooltip='GitHub Issue Watcher') + + # tray.Hide() + initial_issue_count, initial_first_issue = get_num_issues() + issues = first_issue = 0 + # The Event Loop runs every 5000ms + poll_frequncy = 5000 + seconds = 0 + while True: + menu_item = tray.Read(timeout=5000) + if menu_item == 'Exit': + break + if menu_item == 'Run GUI': + tray.Update(data_base64=red_x) + gui() + tray.Update(data_base64=logo) + elif menu_item == sg.EVENT_SYSTEM_TRAY_ICON_ACTIVATED: + tray.ShowMessage('Issue', '{} Issues\n{} First Issue'.format(issues, first_issue), messageicon=sg.SYSTEM_TRAY_MESSAGE_ICON_INFORMATION, ) + + if seconds % 12 == 0: # Every 60 seconds read GitHub + issues, first_issue = get_num_issues() + menu_def = ['root', + ['{} Issues'.format(issues), '{} First Issue'.format(first_issue), '---','&View Issues Online', '&Pull Request','&Discord', '---','&Run GUI', '&Refresh', 'E&xit']] + tray.Update(menu_def, tooltip='{} First Issue'.format(first_issue)) + # if something changed, then make a popup + if issues != initial_issue_count or first_issue != initial_first_issue: + sg.PopupNoWait('Issues changed on GitHub ', 'First issue # is {}'.format(first_issue), background_color='red', keep_on_top=True) + initial_issue_count = issues + initial_first_issue = first_issue + if menu_item in('Refresh', sg.EVENT_SYSTEM_TRAY_ICON_DOUBLE_CLICKED): + issues, first_issue = get_num_issues() + tray.ShowMessage('Issue', '{} Issues\n{} First Issue'.format(issues, first_issue), messageicon=sg.SYSTEM_TRAY_MESSAGE_ICON_INFORMATION, ) + elif menu_item == sg.EVENT_SYSTEM_TRAY_MESSAGE_CLICKED or menu_item.startswith('View Issues'): + sp = subprocess.Popen([CHROME, VIEW_ISSUES_URL], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + elif menu_item.startswith('Pull'): + sp = subprocess.Popen([CHROME, PULL_REQUEST_URL], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + elif menu_item.startswith('Discord'): + sp = subprocess.Popen([DISCORD, r''], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + seconds += poll_frequncy/1000 + +red_x = b"R0lGODlhEAAQAPeQAIsAAI0AAI4AAI8AAJIAAJUAAJQCApkAAJoAAJ4AAJkJCaAAAKYAAKcAAKcCAKcDA6cGAKgAAKsAAKsCAKwAAK0AAK8AAK4CAK8DAqUJAKULAKwLALAAALEAALIAALMAALMDALQAALUAALYAALcEALoAALsAALsCALwAAL8AALkJAL4NAL8NAKoTAKwbAbEQALMVAL0QAL0RAKsREaodHbkQELMsALg2ALk3ALs+ALE2FbgpKbA1Nbc1Nb44N8AAAMIWAMsvAMUgDMcxAKVABb9NBbVJErFYEq1iMrtoMr5kP8BKAMFLAMxKANBBANFCANJFANFEB9JKAMFcANFZANZcANpfAMJUEMZVEc5hAM5pAMluBdRsANR8AM9YOrdERMpIQs1UVMR5WNt8X8VgYMdlZcxtYtx4YNF/btp9eraNf9qXXNCCZsyLeNSLd8SSecySf82kd9qqc9uBgdyBgd+EhN6JgtSIiNuJieGHhOGLg+GKhOKamty1ste4sNO+ueenp+inp+HHrebGrefKuOPTzejWzera1O7b1vLb2/bl4vTu7fbw7ffx7vnz8f///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAJAALAAAAAAQABAAAAjUACEJHEiwYEEABniQKfNFgQCDkATQwAMokEU+PQgUFDAjjR09e/LUmUNnh8aBCcCgUeRmzBkzie6EeQBAoAAMXuA8ciRGCaJHfXzUMCAQgYooWN48anTokR8dQk4sELggBhQrU9Q8evSHiJQgLCIIfMDCSZUjhbYuQkLFCRAMAiOQGGLE0CNBcZYmaRIDLqQFGF60eTRoSxc5jwjhACFWIAgMLtgUocJFy5orL0IQRHAiQgsbRZYswbEhBIiCCH6EiJAhAwQMKU5DjHCi9gnZEHMTDAgAOw==" + + +logo = b'iVBORw0KGgoAAAANSUhEUgAAADIAAAAtCAMAAADbYcjNAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAADBpmDFqmDBqmTFqmjJrmzJsmzJsnDNtnTRrmjVtmjZsmzRunTRunjVvnzdwnjVwnzpxnzVwoDZxoTdyojlyoThzozhzpDh0pDp1pjp2pj51ozt3qDt4qDx4qDx5qj16qj57rD58rT98rkF1oEB4pUB4pkR6pkJ6qEN8q0B9rUB9rkB+rkV7qUZ8qUp9p0x+p0h/rEB+sEeArkqArEqBr0uCrkKAsUKAskOCs0OCtESCtEWEtkaFuEaGuE2FsUiHukiIukmJvEmKvEqLvkuMvk2KuUyLvEyMv1OErVWDqlWHr1qHrVaIsVCMvFSPvV2LsViOuVSQvmyUtmyXuXKbvXefv3ugv06NwE6OwFmUwl2XxGScyGmbw22hynikxnmmyv/UO//UPP/VPf/UPv/VP//UQP/VQf/VQv/WQP/WQf/WQv/WQ//XRP/WRf/WSf/YRf/YRv/YR//YSP/ZSf/ZSv/aS//aTP/aTf/bTv/YUf/ZUv/bUP/cUP/cUv/dVP/dVv/eVv/bW//dWf/cWv/eWP/fWv/dXf/fXf/eXv/cYP/fYP/dZP/dZv/eZf/fZv/eaP/gW//gXP/gXv/gYP/iYf/iYv/hZP/jZP/iZv/kZv/jaf/ja//kaP/lav/kbP/lb//mbP/mbv/ncP/mcv/iff/ocv/odP/odv/oeP/of//qf4GnxYOox4SoxYSpx4asyo+ux4isyouuyouvzIyuyYyvy4yvzI6wy46wzIyz0pCuyJSxyZWyy5u3zZ24zpW30pG52J250J+60aC60KS90aDC3a3E163F2K3F2bPI2bvO3rzP3qvJ4LHN4rnR5P/qgf/qgv/qiP/sif/sjf/sj//olf/ql//ulv/omf/qnv/tnP/qoP/ro//qpP/sov/upf/tqP/uqP/vrf/vrv/us//wpP/wpv/xrf/wsP/wsv/ys//xtP/ytf/ytv/zuf/zuv/0vP/0vsDS38XZ6cnb6f/xw//zwv/yxf/1w//zyP/1yf/2zP/3z//30wAAAM55ho4AAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAABcQAAAXEAEYYRHbAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjFjKpxLAAADnElEQVRIS62OeVhUZRSHw6IosQzGBgoIszKXqGylghKwbHErNVPbEFQQTXYogzZtt2SmiSEHnBHJPdM2Ldv3xbW91Pay0tT29dc53znfvTP809Pz9P7x3Xvu8773fHvhP/M/JBce0GX/8/WduX3ipDt/1nclNrk4TnhR5y1FVzHX/KqzISY5Uou4uLVm/sgEzF1mFqKTruozL9D8gfrM1aIwbvJaF7WFJ4FJqgtb1XOTN1R1eBqYrLbwvpo2+SF2B/NEbFNY+IWoNum6t0UD4imgTO3CCROKiqaJqsnx8fHx+7ho/RBALsnFxcUlJSWlNxpXkkv2I/a1uPnLWEA626WlU6aUlf3uJomJiccdlJDAoQvFBwPsklw2deq06dNnO8nIbj3oHE4hkWDQ7HVcSzLb5eXlFRWVTtKj+/P8OJDojfO6Wahfi3uMW1FZWVVVVV39jk2Skl6RR9JhwOjunDJUPYfZ1q6uqampvcUmWZ4sOpcnJ9Pj8WQqHYAZ4tbW1tXV19ffbJNXPZ6sUUM8nqOBRzweT7LDBQDZdcYmZlz3rk2wNCUlxes9iXYcwlBmOAq4W12moeE2liXBg9QcA6yiB+P1eqk8FtgmdoOh8SbjaoJlqacAj6ZqYqBffCJyo+GGO0S1CVYDKw8VUg0nAJ87NnOrmk4CPJYmSNeHdjQ2Xm/kmcx9qkUlKzKU9PT0tLSTaYeVZ84i/KpFJQ9nZmYermRknAh8qu6sOU1EUDXCJit6UuJwFu1gm+WmJp/PR7f6xr9NVE2eOYLoaeEdVvb5/H7/XOC7QCDwoXE16d+L4IzpC3xmZLb99wYC9wPbm5mP2ZVkRH9DP0OvK/CLcUkmmpvn0Y5gsKWlJRRykwEOXAJBI5NNBNtoRyhEJxa3bnKS005ltBoAqGz+3E47Qq2tO9gLR+jQJAbaItdgWhdje1tbOPwHe5GFdEhyuiE7O1sTkQ1t4fZwOBKJbCTt6/lfOsllZ0TzE9rZpV8bORKZz2z46q2ODpYlwZmCJFfiTyuL3WHZzK4ma7QRgJ2dZcG4mmBoriEnJ4eSc4BvO9vMe0a1CQZKIwwDdqkWxRIxnWT9QOJsITd3KN1NRRc1nQTrzs3L40y4CNitprLwbxXdBD/mM3nCWPoQs+cBkYioBLi8oMBk+flcAHtUJ942HwwxCd4cM2hQATFO5+81WPSbfmBiE+Cl8ZcOHvusDsBfG+hKm/foJHRO/hXgH831bVAP1oP5AAAAAElFTkSuQmCC' + + +system_tray() diff --git a/PySimpleGUIQt/Demo Programs/Qt_Test.py b/PySimpleGUIQt/Demo Programs/Qt_Test.py new file mode 100644 index 000000000..c0034fa70 --- /dev/null +++ b/PySimpleGUIQt/Demo Programs/Qt_Test.py @@ -0,0 +1,30 @@ +import PySimpleGUIQt as sg +# sg.Popup('test 1') +# sg.Popup('test 2') +sg.ChangeLookAndFeel('GreenTan') +layout = [ + [sg.Text('Hello From PySimpleGUIQt!', text_color='red', tooltip='This is my tooltip', justification='c', font=('Courier', 22), key='_TEXT_')], + [sg.Text('Input something here'),sg.Stretch(), sg.Input('This is an InputText Element', key='_INPUT_', font=('Any', 14))], + [sg.Text('This is the new Dial Element'), sg.Dial(background_color='red'), sg.Stretch()], + [sg.Combo(['Combo 1', 'Combo 2', 'Combo 3'], key='+COMBO+', size=(150,30), text_color='green')], + [sg.Listbox(['Listbox Item 1', 'Listbox Item 2', 'Listbox Item 3'], key='+LIST+', size=(200,150), text_color='blue'),sg.Slider((1,100), orientation='v', key='+SLIDER 1+')], + [sg.Slider((1,10), size=(200,30), orientation='h', key='+SLIDER 2+'), sg.Stretch()], + [sg.Checkbox('Checkbox 1', key='+CB1+'), sg.Checkbox('Checkbox 2', key='+CB2')], + [sg.Checkbox('Checkbox 3'), sg.Checkbox('Checkbox 4')], + [sg.Radio('Radio1', group_id=1),sg.Radio('Radio2', group_id=1)], + [sg.Spin((5,8), size=(100,30))], + [sg.Multiline('This is a Multiline Element', size=(300,300), key='+MULTI+')], + [sg.Button('My Button', size=(120,30)), sg.Exit(), sg.Button('Change', key='_CHANGE_')], + ] + +window = sg.Window('My first QT Window', auto_size_text=True, auto_size_buttons=False, font=('Helvetica', 16)).Layout(layout) + +while True: + event, values = window.Read() + print(event, values) + if event is None or event == 'Exit': + break + + window.FindElement('_TEXT_').Update(values['_INPUT_'], font=('Helvetica', 30)) + if event == '_CHANGE_': + window.FindElement('_CHANGE_').Update('Disabled', disabled=True, button_color=('gray', 'gray20'),) diff --git a/PySimpleGUIQt/Demo Programs/Qt_Widget_Summary.py b/PySimpleGUIQt/Demo Programs/Qt_Widget_Summary.py new file mode 100644 index 000000000..9ea66c244 --- /dev/null +++ b/PySimpleGUIQt/Demo Programs/Qt_Widget_Summary.py @@ -0,0 +1,116 @@ +import PySimpleGUIQt as sg +from random import randint + +def main(): + sg.ChangeLookAndFeel('GreenTan') + # sg.SetOptions(element_padding=(0,0)) + # ------ Menu Definition ------ # + menu_def = [['&File', ['&Open', '&Save', '&Properties', 'E&xit']], + ['&Edit', ['&Paste', ['Special', 'Normal', ], 'Undo'], ], + ['&Toolbar', ['Command &1', 'Command &2', 'Command &3', 'Command &4']], + ['&Help', '&About...'], ] + + treedata = sg.TreeData() + + treedata.Insert("", '_A_', 'Tree Item 1', [1,2,3], ) + treedata.Insert("", '_B_', 'B', [4,5,6], ) + treedata.Insert("_A_", '_A1_', 'Sub Item 1', ['can','be','anything'],) + treedata.Insert("", '_C_', 'C', [], ) + treedata.Insert("_C_", '_C1_', 'C1', ['or'], ) + treedata.Insert("_A_", '_A2_', 'Sub Item 2', [None, None]) + treedata.Insert("_A1_", '_A3_', 'A30', ['getting deep']) + treedata.Insert("_C_", '_C2_', 'C2', ['nothing', 'at', 'all']) + + for i in range(100): + treedata.Insert('_C_', i, i, []) + + + frame1 = [ + [sg.Input('Input Text', size=(250,35)), sg.Stretch()], + [sg.Multiline(size=(250,75),default_text='Multiline Input'), + sg.MultilineOutput(size=(250,75),default_text='Multiline Output')], + ] + + frame2 = [ + [sg.Listbox(['Listbox 1','Listbox 2','Listbox 3'], size=(200,85))], + [sg.Combo(['Combo item 1','Combo item 2','Combo item 3'], size=(200,35))], + [sg.Spin([1,2,3], size=(40,30))], + ] + + frame3 = [ + [sg.Checkbox('Checkbox1', True),sg.Checkbox('Checkbox1')], + [sg.Radio('Radio Button1', 1), sg.Radio('Radio Button2', 1, default=True), sg.Stretch()], + ] + + frame4 = [ + [sg.Slider(range=(0,100), orientation='v', size=(3, 30), default_value=40), sg.Dial(range=(0,100),tick_interval=50, size=(150,150), default_value=40), sg.Stretch()], + ] + matrix = [[str(x*y) for x in range(4)] for y in range(3)] + + frame5 = [ + [sg.Table(values=matrix, max_col_width=25, + auto_size_columns=True, display_row_numbers=True, change_submits=False, bind_return_key=True, justification='right', num_rows=8, alternating_row_color='lightblue', key='_table_', text_color='black'), + sg.Tree(data=treedata, headings=['col1', 'col2', 'col3'],change_submits=True, auto_size_columns=True, num_rows=10, col0_width=10, key='_TREE_', show_expanded=True, size=(200,150)), sg.Stretch()], + ] + + graph_elem = sg.Graph((880,150), (0,0), (600,300), key='+GRAPH+') + + frame6 = [ + [graph_elem, sg.Stretch()], + ] + + tab1 = sg.Tab('Graph Number 1',frame6) + tab2 = sg.Tab('Graph Number 2',[[]]) + + layout = [ + [sg.Menu(menu_def)], + [sg.Image(data_base64=logo),sg.Frame('Input Text Group', frame1, title_color='red'), sg.Stretch()], + [sg.Frame('Multiple Choice Group', frame2, title_color='green'), + sg.Frame('Binary Choice Group', frame3, title_color='purple'), + sg.Frame('Variable Choice Group', frame4, title_color='blue'),sg.Stretch()], + [sg.Frame('Structured Data Group', frame5, title_color='red'), ], + # [sg.Frame('Graphing Group', frame6)], + [sg.TabGroup([[tab1,tab2]])], + [sg.ProgressBar(max_value=600, start_value=400, size=(600,25), key='+PROGRESS+'), sg.Stretch(), + sg.ButtonMenu('&Menu', ['Menu', ['&Pause Graph', 'Menu item']], key='_MENU_'), + sg.Button('Button'), sg.Button('Exit')], + ] + + + window = sg.Window('Window Title', + font=('Helvetica', 13), + default_button_element_size=(100,30), + auto_size_buttons=False, + default_element_size=(200,22) + ).Layout(layout).Finalize() + graph_elem.DrawCircle((200,200), 50, 'blue') + i=0 + graph_paused = False + while True: # Event Loop + # sg.TimerStart() + event, values = window.Read(timeout=0) + if event is None or event == 'Exit' : + break + if event == 'Button': + print(event, values) + if values['_MENU_'] == 'Pause Graph': + graph_paused = not graph_paused + if not graph_paused: + i += 1 + + if i < 600: + graph_elem.DrawLine((i,0),(i,randint(0,300)), width=1, color='#{:06x}'.format(randint(0,0xffffff))) + else: + graph_elem.Move(-1,0) + graph_elem.DrawLine((i,0),(i,randint(0,300)), width=1, color='#{:06x}'.format(randint(0,0xffffff))) + + window.FindElement('+PROGRESS+').UpdateBar(i%600) + + # sg.TimerStop() + window.Close() + + + + +logo = b'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' +main() \ No newline at end of file diff --git a/PySimpleGUIQt/Demo Programs/question.ico b/PySimpleGUIQt/Demo Programs/question.ico new file mode 100644 index 000000000..c5bccb554 Binary files /dev/null and b/PySimpleGUIQt/Demo Programs/question.ico differ diff --git a/PySimpleGUIQt/PySimpleGUIQt.py b/PySimpleGUIQt/PySimpleGUIQt.py new file mode 100644 index 000000000..2535ada1d --- /dev/null +++ b/PySimpleGUIQt/PySimpleGUIQt.py @@ -0,0 +1,9936 @@ +#!/usr/bin/python3 +version = __version__ = "0.35.0.18.1 Unreleased\nMassive update of docstrings (thanks nngogol), default for slider tick interval set automatically now, margins added to Window but not yet hooked up, VSeparator added (spelling error), added Radio.reset_group and removed clearing all when one of them is cleared (recent change), added default key for one_line_progress_meter, auto-add keys to tables & trees, InputText element gets new disabled-readonly foreground and background color settings and also a readonly parameter, InputText gets border_width parameter, fixed up some docstrings, popup gets new image and any_key_closes parms, input type popups also get image parameter, error checks for trying to manipulate a window prior to finalize, added a dummy Element.expand method, added theme_add_new, added Window.set_title, updated to the latest themes from tktiner port, big styles update (thanks nngogol!), more Styles work, changed popup text layout to match tkinter port, fixed vertical alignment in row, added margin to some elements, renamed styles related variables, window margin support but be careful. Added back the truncated portion" + +__version__ = version.split()[0] # For PEP 396 and PEP 345 + +# The shortened version of version +try: + ver = version.split(' ')[0] +except: + ver = '' + + +port = 'PySimpleGUIQt' + +import sys, datetime, textwrap, pickle, random, warnings, time +try: # Because Raspberry Pi is still on 3.4....it's not critical if this module isn't imported on the Pi + 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 +except: + print('*** Skipping import of Typing module. "pip3 install typing" to remove this warning ***') + +###### ##### ##### # # ### ##### +# # # # # # # # # ##### # ###### # # # # # # # ##### +# # # # # # ## ## # # # # # # # # # # # +###### # ##### # # ## # # # # ##### # #### # # # # # # +# # # # # # ##### # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # +# # ##### # # # # ###### ###### ##### ##### ### #### # # +# +# Copyright 2020 PySimpleGUI.org + + +from PySide2.QtWidgets import QApplication, QLabel, QWidget, QLineEdit, QComboBox, QFormLayout, QVBoxLayout, QHBoxLayout, QListWidget, QDial, QTableWidget +from PySide2.QtWidgets import QSlider, QCheckBox, QRadioButton, QSpinBox, QPushButton, QTextEdit, QMainWindow, QDialog, QAbstractItemView +from PySide2.QtWidgets import QSpacerItem, QFrame, QGroupBox, QTextBrowser, QPlainTextEdit, QButtonGroup, QFileDialog, QTableWidget, QTabWidget, QTabBar, QTreeWidget, QTreeWidgetItem, QLayout, QTreeWidgetItemIterator, QProgressBar +from PySide2.QtWidgets import QTableWidgetItem, QGraphicsView, QGraphicsScene, QGraphicsItemGroup, QMenu, QMenuBar, QAction, QSystemTrayIcon, QColorDialog +from PySide2.QtGui import QPainter, QPixmap, QPen, QColor, QBrush, QPainterPath, QFont, QImage, QIcon +from PySide2.QtCore import Qt, QEvent, QSize +import PySide2.QtGui as QtGui +import PySide2.QtCore as QtCore +import PySide2.QtWidgets as QtWidgets + +using_pyqt5 = False + + + +DEFAULT_BASE64_ICON = b'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' + + +FACE_PALM = b'iVBORw0KGgoAAAANSUhEUgAAAEkAAAA8CAMAAAAdQmecAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAAB8SDx4UEiAUDyAUEiMZFSUbGSsUEy8aFiwbGTsUFTkdICwiHTIjHDQrHzsiGysjIjIlIDMqIzMsKjsgIzotID0uKT01IzszMUkYHE0ZIFkbKEQhHkUqH0sgHUUgI0MtIkUoKEsmIEwqIkwqL00rM0I1I0s1JEswKE04J0w7LUc9OVYpJ1omMVM0JVQ1K1I4JVU7KlszK1k6J1s7KVw4NGEdLmQeMWghNmE5LWQ4NXIiPWs2RHkkQnAzRVRENVNDOF1ENFxEOVpKOWNDM2NHPWNMPGxFOWxKPG9QPnJKPHVQP05HRFJMSltUUWpLQ2lUQ2NcWndNQndIU3JUQ3JUSHRZTHxSRHxVSHxZSnlaVH1YYmZgX39gVmZjYnZran14doFURoNWSYNbTYNeUoleUItbaYRgT4VhU4JiWIVoXIpjVIxlWo1oVo1pWpFiVpFlWZJsXZRxX4JmZYVsY4trY4pzaoN9e5NtYpRtaJltY5ZxYpRyaZpzZZx1ap14a5N4eJx1cJp3eJ15cZp6eqB2a6J6baN8cqJ7eax9cah+epx7hImBf5uBeqWAdKOCe6qCdKqDequJfbKJfY2EgpmIiZqVk52Zk6SBhKaFiKyDgqqFiayJgqyNi6aLkayNlKGQi6uRja+QlqySm6qZlLKMhLKOi7SRi76Th7qTi7KTk7KVm7KYk7SZm7iWk7yZk7ucm7Sco7ScqbqeorOfsK2knrmhnKukoqyop7GrqrqhpLqlq7mup7urqrSosbKuubqjsrymubyps7qqub6xrbSxsLizvbe1wr68ycKYi8OcmsCmo8KmqcGup8Ooq8qqqcersMGvv8yutMKxu8uwtM2zusy+v9G3usCwwsS0yca8xsW7y82/x8m9ysm90Ne8wMjAvMPCxsLAyc3Ax8vAy8/IzMbD0c3F08zK2NPLx9DJztnBydLO09LL2tPS19TS29rU29bU4dnT5NzV6NvZ4+Hf5uDd6+Pi7eXj8ejl9Ozp9/Lw+wAAAAAAAAAAAAAAAErQjXwAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAHU0lEQVRYR5WWf1gbZx3A8bw2y7nJVq00ZM9Eq63t0o3QFNKkrLbjoRjXsWFHCI+T0gNNe2nWm4Ndm9xFTLmj1UFONsUU1s2aZRRxdP7otNZN1Omc1inTdbad06danzlkVoR2/hG/7w8gNG/Y9iE/uPf9vp/7vt/37r0UZPLx34nxiYmJNybp4VuSxzQ9MXn5zempqelLlybfpotteu31ifFzfzp7/sL45PT09MS/aPOCME1jZ8+fGxs9Njw0fGLswuT01D/+SjsWgmU6fnJs7IUTx7410N8/MDx64eKlqV++DRXD9M2BkZOnfjicTvV0d/f0Hx09f/HNf//iL7QzP7mmn0XN9BMjR9PpfhOpkkdHz0z97+9PT9DuvOSa7gvHus2vYEzT6E4MDP10/PKlM0/T7rzkmoLBeyORWMwwzf6UaZowvydPX7z8nzPP0v585JhO7pIkWZbvVXUzlUomzYNmcui7L49fvPDs6zQiDzmmr9UHg7vDu8MRVTcOHESq5KEjz7z8yitnfkwj8pBr2njHNjEo7ZbliGFAQsk+eB155vTpc6f/RkPY5JiOr7i1uh5UYUVROw4ehEolk1193zj2k9+NLpxUbsWXrt5YfdfnpDAUS9UgLaCrq2/g6JETT9IINrmmJStWb9wUCKK6K0h1wDCMDs1IHjr8Tk23F63aeOsdooSXUNU6O7QOTdM7937x0NAbNIRJrumrS4tWb64OiFKrJEshWdnXqWr7QqGO/fuHztIQJrmmzKKiFauc9aLYIkp7xHvkfXtCLSG5Y+TU1w8foRFMGKat7y1asbLaH/CLkNeO5h2trZJk/Oq3I/uHh/9IQ1gwTD+4qnBpkbPK5xf9zTua/c1+fyT1WLLnvi+8MPwoDWHBMEWDjuuFpc5P+Hz3iM3Ndb5mPZVOKfU93xnqj/2GxjDINb3q8PicJYUly2vkutZWURR1PdErtwz8+vloQPk+DWLAyMnjWb58ZUnhrsf3SJ9s8fl1TVWlwODzI/HaxrYFpscw1fscxY7Slc7Yc5LkatDhTpZE3YzH133+1EsP0RgGDNOPqm74cJWrtHRbond9Q0LVdSmsmWa4rf3Ffw4/QmMYMEyZ9rIy502u0hpDlRK6HtNN40BCjI68+IeBtndWp0xmU5VrpWttFdqiensff27QjIuxwf6+/Y13v0YjGDBNr25yrV3rqoL7t7fX1A/0Girs6Eqw7fcPfJlGMGCaMt+rdt7k3Natqwkjpmnm4BNpQ27o+fNLD7yL4xYt+/RxGjYPtimTKSxxqYluEOm63psaTBtB89tDfe2LeY7neW7xnT+ncXPkMT109aoaJaYaugY7CmxSj6UHU12haNPV4EFw3I00cpY8psWLVlcHIxFdVTUtFod9Lm0aO+/adSMVAZy1icZSmKb738fzSzY1yJCRYcBGF48qWpdW11j/AapBQMW203gMw7SVRG4ORBKaqsXjWjSqaRGldkvV5utIF8JqFazWB+kQRI5pK4eLyvPVElQbyqRF92rxDll0rK+pXQRd8LK+/6MbNtzidrvXHKOjgCtMTVTD8++uDet6J1RJaVOie5XglrK6xlrUYf3QOo8HLG6v1+uuOEwHXmHajs45w05Fhx3c0JRQOBRUAi7P+pprIJuPrHHY7cXwZ3eAraJ8Nqss01NLqANzTbumxLSIrijhnTvDQWepq+x6oVAQBAuCh7dgs9sryj10dJbpttmJYT7eDlWOaJEwiO5uuRlJLNDMcSgK3lBOjkeyE3Q8NW1fNk8D1WiD9YJnZ1gOB1sCH0MK2oO/LYIF0gO3RWgkBmJ6cG51yRk5vkbR1IgcDisxWWwoIX0ILBAEm2AjCPx7sIeYbpvLx3odmgLPCaFIREY/WGDnrYOM5sAqUNgJNkEgImRaTGN44YPF0AFYhJsDIXicS/I+EC2n3QBHc7LZYO0q0KXgtttmTdfijDhLMQAiGxxYINK3Ax6ccqcq3jCzVrBaWAKdOKNyckk56N5esJ3UBqLQrAGYHg531CGV5ENtuAEDuSDWVKCMvN5Kb6X7s9R0O8poZvZ4FB0n2MrqGhr8vjLSij5JnYnMDSpIqbLS66amZbOiOSB9PNzmqdtSVVhL2rAcXtCHTeVIVQl4yfQKrs0WoWuNDKLp2dZ5eCvVzkGSmlWRpMCEhtORxIqj8TEBH88ja4IoKfxrqAC2wbmxUG0O7id6NAM+no+9GMuo6hZs+gxZKQQaRTPMFjFMUCuaFlo/Mr2CJkgJReNPfIFfmRM+ZIBVFfhS+BLOCZWb3C7kPofLEkM0CNqQy4zKuwGZ7iTRWIURIPW3mt0MMyo0vYL7s64luCt4Hu6ZeR4EHcgAuaBYcJ0XZPATAC0ampyAJ0fHz0IGZTPXiFTgQiYyJwAnh+pNd4QsZrcjgDYB5Bir7BvAhB5vKCvUZ+F4vMQ4cB54EP0/C2ik9/TDBZmnyG6BGqHuWJR9XvqdD2yCXcq+Dna6JtpIYJ15QWB+5W6v+1P/B0gPXHqaGwimAAAAAElFTkSuQmCC' + + +g_time_start = 0 +g_time_end = 0 +g_time_delta = 0 + + + +def TimerStart(): + global g_time_start + + g_time_start = time.time() + + +def TimerStop(): + global g_time_delta, g_time_end + + g_time_end = time.time() + g_time_delta = g_time_end - g_time_start + print(int(g_time_delta*1000)) + + +""" + Welcome to the "core" PySimpleGUI code.... + + It's a mess.... really... it's a mess internally... it's the external-facing interfaces that + are not a mess. The Elements and the methods for them are well-designed. + PEP8 - this code is far far from PEP8 compliant. + It was written PRIOR to learning that PEP8 existed. + + The variable and function naming in particular are not compliant. There is + liberal use of CamelVariableAndFunctionNames. If you've got a serious enough problem with this + that you'll pass on this package, then that's your right and I invite you to do so. However, if + perhaps you're a practical thinker where it's the results that matter, then you'll have no + trouble with this code base. There is consisency however. + + I truly hope you get a lot of enjoyment out of using PySimpleGUI. It came from good intentions. +""" + +# ----====----====----==== Constants the user CAN safely change ====----====----====----# +DEFAULT_WINDOW_ICON = DEFAULT_BASE64_ICON +DEFAULT_ELEMENT_SIZE = (250, 22) # In PIXELS +DEFAULT_BUTTON_ELEMENT_SIZE = (80, 25 ) # In PIXELS +DEFAULT_MARGINS = (0,0) # For Qt, use a Column element with padding to get same effect as tkinter port +DEFAULT_ELEMENT_PADDING = (4, 2) # Padding between elements (row, col) in pixels +# DEFAULT_ELEMENT_PADDING = (0, 0) # Padding between elements (row, col) in pixels +DEFAULT_PIXELS_TO_CHARS_SCALING = (10,35) # 1 character represents x by y pixels +DEFAULT_PIXELS_TO_CHARS_SCALING_MULTILINE_TEXT = (10,20) # 1 character represents x by y pixels +DEFAULT_PIXEL_TO_CHARS_CUTOFF = 15 # number of chars that triggers using pixels instead of chars +DEFAULT_PIXEL_TO_CHARS_CUTOFF_MULTILINE = 70 # number of chars that triggers using pixels instead of chars +DEFAULT_AUTOSIZE_TEXT = True +DEFAULT_AUTOSIZE_BUTTONS = True +DEFAULT_FONT = ("Helvetica", 10) +DEFAULT_TEXT_JUSTIFICATION = 'left' +DEFAULT_BORDER_WIDTH = 1 +DEFAULT_AUTOCLOSE_TIME = 3 # time in seconds to show an autoclose form +DEFAULT_DEBUG_WINDOW_SIZE = (800, 400) +DEFAULT_WINDOW_LOCATION = (None, None) +MAX_SCROLLED_TEXT_BOX_HEIGHT = 50 +DEFAULT_TOOLTIP_TIME = 400 +DEFAULT_TOOLTIP_OFFSET = (20,-20) +#################### COLOR STUFF #################### +BLUES = ("#082567", "#0A37A3", "#00345B") +PURPLES = ("#480656", "#4F2398", "#380474") +GREENS = ("#01826B", "#40A860", "#96D2AB", "#00A949", "#003532") +YELLOWS = ("#F3FB62", "#F0F595") +TANS = ("#FFF9D5", "#F4EFCF", "#DDD8BA") +NICE_BUTTON_COLORS = ((GREENS[3], TANS[0]), + ('#000000', '#FFFFFF'), + ('#FFFFFF', '#000000'), + (YELLOWS[0], PURPLES[1]), + (YELLOWS[0], GREENS[3]), + (YELLOWS[0], BLUES[2])) + +COLOR_SYSTEM_DEFAULT = '1234567890' # Colors should never be this long + +DEFAULT_BUTTON_COLOR = ('white', BLUES[0]) # Foreground, Background (None, None) == System Default +OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR = ('white', BLUES[0]) # Colors should never be this long + + +CURRENT_LOOK_AND_FEEL = 'DarkBlue3' +# CURRENT_LOOK_AND_FEEL = 'Dark Red' + +DEFAULT_ERROR_BUTTON_COLOR = ("#FFFFFF", "#FF0000") +DEFAULT_BACKGROUND_COLOR = None +DEFAULT_ELEMENT_BACKGROUND_COLOR = None +DEFAULT_ELEMENT_TEXT_COLOR = COLOR_SYSTEM_DEFAULT +DEFAULT_TEXT_ELEMENT_BACKGROUND_COLOR = None +DEFAULT_TEXT_COLOR = COLOR_SYSTEM_DEFAULT +DEFAULT_INPUT_ELEMENTS_COLOR = COLOR_SYSTEM_DEFAULT +DEFAULT_INPUT_TEXT_COLOR = COLOR_SYSTEM_DEFAULT +DEFAULT_SCROLLBAR_COLOR = None + +# A transparent button is simply one that matches the background +TRANSPARENT_BUTTON = 'This constant has been depricated. You must set your button background = background it is on for it to be transparent appearing' +# -------------------------------------------------------------------------------- +# Progress Bar Relief Choices +RELIEF_RAISED = 'raised' +RELIEF_SUNKEN = 'sunken' +RELIEF_FLAT = 'flat' +RELIEF_RIDGE = 'ridge' +RELIEF_GROOVE = 'groove' +RELIEF_SOLID = 'solid' + +RELIEF_TICK_POSITION_NO_TICKS = 'none' +RELIEF_TICK_POSITION_BOTH_SIDES = 'both' +RELIEF_TICK_POSITION_ABOVE = 'above' +RELIEF_TICK_POSITION_BELOW = 'below' +RELIEF_TICK_POSITION_LEFT = 'left' +RELIEF_TICK_POSITION_RIGHT = 'right' + +DEFAULT_PROGRESS_BAR_COMPUTE = ('#000000', '#000000') # Means that the progress bar colors should be computed from other colors +DEFAULT_PROGRESS_BAR_COLOR = (GREENS[0], '#D0D0D0') # a nice green progress bar +DEFAULT_PROGRESS_BAR_COLOR_OFFICIAL = (GREENS[0], '#D0D0D0') # a nice green progress bar +DEFAULT_PROGRESS_BAR_SIZE = (200, 20) # Size of Progress Bar (characters for length, pixels for width) +DEFAULT_PROGRESS_BAR_BORDER_WIDTH = 1 +DEFAULT_PROGRESS_BAR_RELIEF = RELIEF_GROOVE +PROGRESS_BAR_STYLES = ('default', 'winnative', 'clam', 'alt', 'classic', 'vista', 'xpnative') +DEFAULT_PROGRESS_BAR_STYLE = 'default' +DEFAULT_METER_ORIENTATION = 'Horizontal' +DEFAULT_SLIDER_ORIENTATION = 'vertical' +DEFAULT_SLIDER_BORDER_WIDTH = 1 + +DEFAULT_SLIDER_RELIEF = RELIEF_TICK_POSITION_BOTH_SIDES +DEFAULT_FRAME_RELIEF = 'groove' + +DEFAULT_LISTBOX_SELECT_MODE = 'extended' +SELECT_MODE_MULTIPLE = 'multiple' +LISTBOX_SELECT_MODE_MULTIPLE = 'multiple' +SELECT_MODE_BROWSE = 'browse' +LISTBOX_SELECT_MODE_BROWSE = 'browse' +SELECT_MODE_EXTENDED = 'extended' +LISTBOX_SELECT_MODE_EXTENDED = 'extended' +SELECT_MODE_SINGLE = 'single' +LISTBOX_SELECT_MODE_SINGLE = 'single' +SELECT_MODE_CONTIGUOUS = 'contiguous' +LISTBOX_SELECT_MODE_CONTIGUOUS = 'contiguous' + +TABLE_SELECT_MODE_NONE = 'NONE' +TABLE_SELECT_MODE_BROWSE = 'BROWSE' +TABLE_SELECT_MODE_EXTENDED = 'EXTENDED' +DEFAULT_TABLE_SECECT_MODE = TABLE_SELECT_MODE_EXTENDED + +TITLE_LOCATION_TOP = 'N' +TITLE_LOCATION_BOTTOM = 'S' +TITLE_LOCATION_LEFT = 'W' +TITLE_LOCATION_RIGHT = 'E' +TITLE_LOCATION_TOP_LEFT = 'NW' +TITLE_LOCATION_TOP_RIGHT = 'NE' +TITLE_LOCATION_BOTTOM_LEFT = 'SW' +TITLE_LOCATION_BOTTOM_RIGHT = 'SE' + +THEME_DEFAULT = 'default' +THEME_WINNATIVE = 'winnative' +THEME_CLAM = 'clam' +THEME_ALT = 'alt' +THEME_CLASSIC = 'classic' +THEME_VISTA = 'vista' +THEME_XPNATIVE = 'xpnative' + +# DEFAULT_METER_ORIENTATION = 'Vertical' +# ----====----====----==== Constants the user should NOT f-with ====----====----====----# +ThisRow = 555666777 # magic number + +# DEFAULT_WINDOW_ICON = '' +MESSAGE_BOX_LINE_WIDTH = 60 + +# Icons for displaying system tray messages +SYSTEM_TRAY_MESSAGE_ICON_INFORMATION = QSystemTrayIcon.Information +SYSTEM_TRAY_MESSAGE_ICON_WARNING = QSystemTrayIcon.Warning +SYSTEM_TRAY_MESSAGE_ICON_CRITICAL = QSystemTrayIcon.Critical +SYSTEM_TRAY_MESSAGE_ICON_NOICON = QSystemTrayIcon.NoIcon + +# "Special" Key Values.. reserved +# Key representing a Read timeout +EVENT_TIMEOUT = TIMEOUT_EVENT = TIMEOUT_KEY = '__TIMEOUT__' +# Window closed event (user closed with X or destroyed using OS) +WIN_CLOSED = WINDOW_CLOSED = None + +# Key indicating should not create any return values for element +WRITE_ONLY_KEY = '__WRITE ONLY__' +EVENT_SYSTEM_TRAY_ICON_DOUBLE_CLICKED = '__DOUBLE_CLICKED__' +EVENT_SYSTEM_TRAY_ICON_ACTIVATED = '__ACTIVATED__' +EVENT_SYSTEM_TRAY_MESSAGE_CLICKED = '__MESSAGE_CLICKED__' + +# Meny key indicator character / string +MENU_KEY_SEPARATOR = '::' +MENU_DISABLED_CHARACTER = '!' + +SUPPRESS_ERROR_POPUPS = False + + +# ====================================================================== # +# One-liner functions that are handy as f_ck # +# ====================================================================== # +def RGB(red, green, blue): return '#%02x%02x%02x' % (red, green, blue) + + +# ====================================================================== # +# Enums for types # +# ====================================================================== # +# ------------------------- Button types ------------------------- # +# todo Consider removing the Submit, Cancel types... they are just 'RETURN' type in reality +# uncomment this line and indent to go back to using Enums +# was an Enum previously ButtonType(Enum): +BUTTON_TYPE_BROWSE_FOLDER = 1 +BUTTON_TYPE_BROWSE_FILE = 2 +BUTTON_TYPE_BROWSE_FILES = 21 +BUTTON_TYPE_SAVEAS_FILE = 3 +BUTTON_TYPE_CLOSES_WIN = 5 +BUTTON_TYPE_CLOSES_WIN_ONLY = 6 +BUTTON_TYPE_READ_FORM = 7 +BUTTON_TYPE_REALTIME = 9 +BUTTON_TYPE_CALENDAR_CHOOSER = 30 +BUTTON_TYPE_COLOR_CHOOSER = 40 + +BROWSE_FILES_DELIMITER = ';' # the delimeter to be used between each file in the returned string + +# ------------------------- Element types ------------------------- # +# Used in Element - Was an enum once ElementType(Enum): +ELEM_TYPE_TEXT = 'text' +ELEM_TYPE_INPUT_TEXT = 'input' +ELEM_TYPE_INPUT_COMBO = 'combo' +ELEM_TYPE_INPUT_OPTION_MENU = 'option menu' +ELEM_TYPE_INPUT_RADIO = 'radio' +ELEM_TYPE_INPUT_MULTILINE = 'multiline' +ELEM_TYPE_MULTILINE_OUTPUT = 'multioutput' +ELEM_TYPE_INPUT_CHECKBOX = 'checkbox' +ELEM_TYPE_INPUT_SPIN = 'spind' +ELEM_TYPE_BUTTON = 'button' +ELEM_TYPE_IMAGE = 'image' +ELEM_TYPE_CANVAS = 'canvas' +ELEM_TYPE_FRAME = 'frame' +ELEM_TYPE_GRAPH = 'graph' +ELEM_TYPE_TAB = 'tab' +ELEM_TYPE_TAB_GROUP = 'tabgroup' +ELEM_TYPE_INPUT_SLIDER = 'slider' +ELEM_TYPE_INPUT_DIAL = 'dial' +ELEM_TYPE_INPUT_LISTBOX = 'listbox' +ELEM_TYPE_OUTPUT = 'output' +ELEM_TYPE_COLUMN = 'column' +ELEM_TYPE_MENUBAR = 'menubar' +ELEM_TYPE_PROGRESS_BAR = 'progressbar' +ELEM_TYPE_BLANK = 'blank' +ELEM_TYPE_TABLE = 'table' +ELEM_TYPE_TREE = 'tree' +ELEM_TYPE_ERROR = 'error' +ELEM_TYPE_SEPARATOR = 'separator' +ELEM_TYPE_STRETCH = 'stretch' +ELEM_TYPE_BUTTONMENU = 'buttonmenu' + +# ------------------------- Popup Buttons Types ------------------------- # +POPUP_BUTTONS_YES_NO = 1 +POPUP_BUTTONS_CANCELLED = 2 +POPUP_BUTTONS_ERROR = 3 +POPUP_BUTTONS_OK_CANCEL = 4 +POPUP_BUTTONS_OK = 0 +POPUP_BUTTONS_NO_BUTTONS = 5 + +# def apply_new_font(css_dict, font_string): +# return css_dict.update({k.strip().replace('_', '-') : v.strip() for k,v in font_string.replace('\n', '').split(';')}) + +# ---------------------------------------------------------------------- # +# Cascading structure.... Objects get larger # +# Button # +# Element # +# Row # +# Form # +# ---------------------------------------------------------------------- # +# ------------------------------------------------------------------------- # +# Element CLASS # +# ------------------------------------------------------------------------- # +class Element(): + def __init__(self, elem_type, size=(None, None), auto_size_text=None, font=None, background_color=None, text_color=None, + key=None, k=None, pad=None, tooltip=None, visible=True, size_px=(None, None), metadata=None): + """ + :param elem_type: ??? + :type elem_type: ??? + :param size: w=characters-wide, h=rows-high + :type size: Tuple[int, int] (width, height) + :param auto_size_text: True if the Widget should be shrunk to exactly fit the number of chars to show + :type auto_size_text: bool + :param font: specifies the font family, size, etc (see docs for exact formats) + :type font: Union[str, Tuple[str, int]] + :param background_color: color of background. Can be in #RRGGBB format or a color name "black" + :type background_color: (str) + :param text_color: element's text color. Can be in #RRGGBB format or a color name "black" + :type text_color: (str) + :param key: Identifies an Element. Should be UNIQUE to this window. + :type key: (Any) + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: Union[str, int, tuple, object] + :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) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param visible: set visibility state of the element (Default = True) + :type visible: (bool) + :param size_px: size in pixels (width, height). Will override the size parameter + :type size_px: Tupple[int, int] (width, height) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + + if size_px != (None, None): + self.Size = size_px + else: + self.Size = _convert_tkinter_size_to_Qt(size) + + self.Type = elem_type + self.AutoSizeText = auto_size_text + # self.Pad = DEFAULT_ELEMENT_PADDING if pad is None else pad + self.Pad = pad + if font is not None and type(font) is not str: + self.Font = font + elif font is not None: + self.Font = font.split(' ') + else: + self.Font = font + + self.TKStringVar = None + self.TKIntVar = None + self.TKText = None + self.TKEntry = None + self.TKImage = None + + self.ParentForm = None + self.ParentContainer = None # will be a Form, Column, or Frame element + self.TextInputDefault = None + self.Position = (0, 0) # Default position Row 0, Col 0 + self.BackgroundColor = background_color if background_color is not None else DEFAULT_ELEMENT_BACKGROUND_COLOR + self.TextColor = text_color if text_color is not None else DEFAULT_ELEMENT_TEXT_COLOR + self.Key = key # dictionary key for return values + self.Tooltip = tooltip + self.TooltipObject = None + self.Visible = visible + self.metadata = metadata # type: Any + self.row_frame = None # type: QHBoxLayout + self.qt_styles = [] # type: List[QtStyle] + self.Widget = None # type: QWidget + + + + def _FindReturnKeyBoundButton(self, form): + for row in form.Rows: + for element in row: + if element.Type == ELEM_TYPE_BUTTON: + if element.BindReturnKey: + return element + if element.Type == ELEM_TYPE_COLUMN: + rc = self._FindReturnKeyBoundButton(element) + if rc is not None: + return rc + if element.Type == ELEM_TYPE_FRAME: + rc = self._FindReturnKeyBoundButton(element) + if rc is not None: + return rc + if element.Type == ELEM_TYPE_TAB_GROUP: + rc = self._FindReturnKeyBoundButton(element) + if rc is not None: + return rc + if element.Type == ELEM_TYPE_TAB: + rc = self._FindReturnKeyBoundButton(element) + if rc is not None: + return rc + return None + + + def _ReturnKeyHandler(self, event): + MyForm = self.ParentForm + button_element = self._FindReturnKeyBoundButton(MyForm) + if button_element is not None: + button_element._ButtonCallBack() + + def _widget_was_created(self): + """ + Determines if a Widget was created for this element. + + :return: True if a Widget has been created previously (Widget is not None) + :rtype: (bool) + """ + if self.Widget is not None: + return True + else: + warnings.warn('You cannot Update element with key = {} until the window has been Read or Finalized'.format(self.Key), UserWarning) + if not SUPPRESS_ERROR_POPUPS: + popup_error('Unable to complete operation on element with key {}'.format(self.Key), + 'You cannot perform operations (such as calling update) on an Element until Window is read or finalized.', + 'Adding a "finalize=True" parameter to your Window creation will likely fix this.', image=_random_error_icon()) + return False + + + def Update(self, widget, background_color=None, text_color=None, font=None, visible=None): + if not self._widget_was_created(): + return + + a_style = self.qt_styles[0] + # print(f'a_style = {a_style}') + if font is not None: #= apply_new_font(css_props_dict, create_style_from_font(font)) + a_style['font'] = create_style_from_font(font) + if text_color is not None: + a_style['color'] = text_color + self.TextColor = text_color + if background_color is not None: + a_style['background-color'] = background_color + self.BackgroundColor = background_color + + # print(f'a_style = {a_style}') + widget.setStyleSheet(a_style.build_css_string()) + set_widget_visiblity(widget, visible) + + + def set_stylesheet(self, stylesheet): + """ + Sets the stylesheet for a Qt Widget + :param stylesheet: Stylesheet (string) to set stylesheet to + :type stylesheet: (str) + """ + try: + self.Widget.setStyleSheet(stylesheet) + except Exception as e: + print('** Error Setting Stylesheet **', e) + + def get_stylesheet(self): + """ + Returns the stylesheet for element's associated Qt Widget + :return: stylesheet + :rtype: (str) + """ + stylesheet = '' + try: + stylesheet = self.Widget.styleSheet() + except Exception as e: + print('** Error Setting Stylesheet **', e) + + return stylesheet + + update = Update + + # ---------------------------------- DUMMY METHODS - They don't do anything! ---------------------------------- + + # These methods are here for porting purposes only. They are meant to allow you to change your import statement + # from PySimpleGUI to PySimpleGUIQt and still be able to run your program. + + def expand(self, expand_x=False, expand_y=False, expand_row=True): + """ + WARNING - NOT USED IN PySimpleGUIQt port. Provided as dummy method + + :param expand_x: If True Element will expand in the Horizontal directions + :type expand_x: (bool) + :param expand_y: If True Element will expand in the Vertical directions + :type expand_y: (bool) + :param expand_row: If True the row containing the element will also expand. Without this your element is "trapped" within the row + :type expand_row: (bool) + :return: None + :rtype: None + """ + + return + + + def __call__(self, *args, **kwargs): + """ + Makes it possible to "call" an already existing element. When you do make the "call", it actually calls + the Update method for the element. + Example: If this text element was in yoiur layout: + sg.Text('foo', key='T') + Then you can call the Update method for that element by writing: + window.FindElement('T')('new text value') + + + :param kwargs: + :return: + """ + return self.Update(*args, **kwargs) + + + + update = Update + + +# ---------------------------------------------------------------------- # +# Input Class # +# ---------------------------------------------------------------------- # +class InputText(Element): + def __init__(self, default_text='', size=(None,None), disabled=False, password_char='', + justification=None, background_color=None, text_color=None, font=None, tooltip=None, disabled_readonly_background_color=None, disabled_readonly_text_color=None, + change_submits=False, enable_events=False, readonly=False, border_width=None, + do_not_clear=True, key=None, k=None, focus=False, pad=None, visible=True, size_px=(None,None), metadata=None): + """ + Input a line of text Element + :param default_text: Text initially shown in the input box as a default value(Default value = '') + :type default_text: (str) + :param size: w=characters-wide, h=rows-high + :type size: Tuple[int, int] (width, height) + :param disabled: set disable state for element (Default = False) + :type disabled: (bool) + :param password_char: Password character if this is a password field (Default value = '') + :type password_char: (char) + :param justification: justification for data display. Valid choices - left, right, center + :type justification: (str) + :param background_color: color of background in one of the color formats + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param disabled_readonly_background_color: If state is set to readonly or disabled, the color to use for the background + :type disabled_readonly_background_color: (str) + :param disabled_readonly_text_color: If state is set to readonly or disabled, the color to use for the text + :type disabled_readonly_text_color: (str) + :param change_submits: * DEPRICATED DO NOT USE. Use `enable_events` instead + :type change_submits: (bool) + :param enable_events: If True then changes to this element are immediately reported as an event. Use this instead of change_submits (Default = False) + :type enable_events: (bool) + :param do_not_clear: If False then the field will be set to blank after ANY event (button, any event) (Default = True) + :type do_not_clear: (bool) + :param readonly: If True then the user cannot modify the field (Default = False) + :type readonly: (bool) + :param border_width: width of border around element in pixels + :type border_width: (int) + :param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window + :type key: (Any) + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: Union[str, int, tuple, object] + :param focus: Determines if initial focus should go to this element. + :type focus: (bool) + :param pad: Amount of padding to put around element. Normally (horizontal pixels, vertical pixels) but can be split apart further into ((horizontal left, horizontal right), (vertical above, vertical below)) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) + :param visible: set visibility state of the element (Default = True) + :type visible: (bool) + :param size_px: size in pixels (width, height). Will override the size parameter + :type size_px: Tupple[int, int] (width, height) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + key = key if key is not None else k + self.DefaultText = default_text + self.PasswordCharacter = password_char + bg = background_color if background_color is not None else DEFAULT_INPUT_ELEMENTS_COLOR + fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR + self.Focus = focus + self.do_not_clear = do_not_clear + self.Justification = justification or 'left' + self.Disabled = disabled + self.ReadOnly = readonly + self.disabled_readonly_background_color = disabled_readonly_background_color + self.disabled_readonly_text_color = disabled_readonly_text_color + self.ChangeSubmits = change_submits or enable_events + self.BorderWidth = border_width if border_width is not None else DEFAULT_BORDER_WIDTH + self.Widget = self.QT_QLineEdit = None # type: QLineEdit + self.ValueWasChanged = False + super().__init__(ELEM_TYPE_INPUT_TEXT, size=size, background_color=bg, text_color=fg, key=key, pad=pad, + font=font, tooltip=tooltip, visible=visible, size_px=size_px, metadata=metadata) + + + def _dragEnterEvent(self, e): + if e.mimeData().hasText(): + e.accept() + else: + e.ignore() + + def _dropEvent(self, e): + self.QT_QLineEdit.setText(e.mimeData().text()) + + + + class InputTextWidget(QWidget): + def __init__(self, qt_qlineedit, element): + self.QT_QLineEdit = qt_qlineedit + self.Element = element + super().__init__() + + def eventFilter(self, widget, event): + # print(f'Got input text event {event}') + if event.type() == QEvent.FocusIn and widget is self.QT_QLineEdit: + self.Element.ParentForm.FocusElement = self.Element + return QWidget.eventFilter(self, widget, event) + + + + def _QtCallbackFocusInEvent(self,value): + return + + + def _QtCallbackFocusInEvent(self, value): + if not self.ChangeSubmits: + return + # if was changed using an "update" call, then skip the next changed callback + if self.ValueWasChanged: + self.ValueWasChanged = False + print('skipping update') + return + _element_callback_quit_mainloop(self) + + def _QtCallbackReturnPressed(self): + self._ReturnKeyHandler(None) + return + + def Update(self, value=None, disabled=None, select=None, background_color=None, text_color=None, font=None, visible=None): + if disabled is True: + self.QT_QLineEdit.setDisabled(True) + elif disabled is False: + self.QT_QLineEdit.setDisabled(False) + if value is not None: + self.QT_QLineEdit.setText(str(value)) + self.DefaultText = value + # was getting into an infinite loop when the update was triggering a text changed callback, but unable + # to dupliate this + # self.ValueWasChanged = True + if select: + self.QT_QLineEdit.setSelection(0,QtGui.QTextCursor.End ) + super().Update(self.QT_QLineEdit, background_color=background_color, text_color=text_color, font=font, visible=visible) + + + + def Get(self): + return self.QT_QLineEdit.text() + # return self.TKStringVar.get() + + def SetFocus(self): + self.QT_QLineEdit.setFocus() + + get = Get + set_focus = SetFocus + update = Update + +# ------------------------- INPUT TEXT lazy functions ------------------------- # +In = InputText +Input = InputText +I = InputText + + +# ---------------------------------------------------------------------- # +# Combo # +# ---------------------------------------------------------------------- # +class Combo(Element): + def __init__(self, values, default_value=None, size=(None, None), auto_size_text=None, background_color=None, + text_color=None, change_submits=False, enable_events=False, disabled=False, key=None, k=None, pad=None, tooltip=None, + readonly=False, visible_items=10, font=None, auto_complete=True, visible=True, size_px=(None,None), metadata=None): + """ + Input Combo Box Element (also called Dropdown box) + + :param values: values to choose. While displayed as text, the items returned are what the caller supplied, not text + :type values: List[Any] or Tuple[Any] + :param default_value: Choice to be displayed as initial value. Must match one of values variable contents + :type default_value: (Any) + :param size: width = characters-wide, height = rows-high + :type size: Tuple[int, int] (width, height) + :param auto_size_text: True if element should be the same size as the contents + :type auto_size_text: (bool) + :param background_color: Color for Element. Text or RGB Hex + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param change_submits: DEPRICATED DO NOT USE. Use `enable_events` instead + :type change_submits: (bool) + :param enable_events: Turns on the element specific events. Combo event is when a choice is made + :type enable_events: (bool) + :param disabled: set disable state for element + :type disabled: (bool) + :param key: Used with window.FindElement and with return values to uniquely identify this element + :type key: (Any) + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: Union[str, int, tuple, object] + :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) + :param tooltip: text that will appear when mouse hovers over this element + :type tooltip: (str) + :param readonly: make element readonly (user can't change). True means user cannot change + :type readonly: (bool) + :param visible_items: ??? + :type visible_items: ??? + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param auto_complete: ??? + :type auto_complete: ??? + :param visible: set visibility state of the element + :type visible: (bool) + :param size_px: size in pixels (width, height). Will override the size parameter + :type size_px: Tupple[int, int] (width, height) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + key = key if key is not None else k + self.Values = values + self.DefaultValue = default_value + self.ChangeSubmits = change_submits or enable_events + self.TKCombo = None + # self.InitializeAsDisabled = disabled + self.Disabled = disabled + self.Readonly = readonly + bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR + fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR + self.VisibleItems = visible_items + self.AutoComplete = auto_complete + self.Widget = self.QT_ComboBox = None # type: QComboBox + super().__init__(ELEM_TYPE_INPUT_COMBO, size=size, auto_size_text=auto_size_text, background_color=bg, + text_color=fg, key=key, pad=pad, tooltip=tooltip, font=font or DEFAULT_FONT, visible=visible, size_px=size_px, metadata=metadata) + + + def _QtCurrentItemChanged(self, state): + if self.ChangeSubmits: + _element_callback_quit_mainloop(self) + + + def Update(self, value=None, values=None, set_to_index=None, disabled=None, readonly=None, background_color=None, text_color=None, font=None, visible=None): + if values is not None: + self.Values = values + for i in range(self.QT_ComboBox.count()): + self.QT_ComboBox.removeItem(0) + self.QT_ComboBox.addItems(values) + if value is not None: + for index, v in enumerate(self.Values): + if v == value: + self.QT_ComboBox.setCurrentIndex(index) + break + if set_to_index is not None: + self.QT_ComboBox.setCurrentIndex(set_to_index) + if disabled == True: + self.QT_ComboBox.setDisabled(True) + elif disabled == False: + self.QT_ComboBox.setDisabled(False) + if readonly is not None: + self.Readonly = readonly + + super().Update(self.QT_ComboBox, background_color=background_color, text_color=text_color, font=font, visible=visible) + + update = Update + + +# ------------------------- INPUT COMBO Element lazy functions ------------------------- # +InputCombo = Combo +DropDown = InputCombo +Drop = InputCombo + + +# ---------------------------------------------------------------------- # +# Option Menu # +# ---------------------------------------------------------------------- # +class OptionMenu(Element): + def __init__(self, values, default_value=None, size=(None, None), disabled=False, auto_size_text=None, + background_color=None, text_color=None, key=None, k=None, pad=None, tooltip=None, visible=True, size_px=(None,None), metadata=None): + """ + InputOptionMenu - NOT USED IN QT + :param values: Values to be displayed + :type values: List[Any] or Tuple[Any] + :param default_value: the value to choose by default + :type default_value: (Any) + :param size: size in characters (wide) and rows (high) + :type size: Tuple[int, int] (width, height) + :param disabled: control enabled / disabled + :type disabled: (bool) + :param auto_size_text: True if size of Element should match the contents of the items + :type auto_size_text: (bool) + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param key: Used with window.FindElement and with return values to uniquely identify this element + :type key: (Any) + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: Union[str, int, tuple, object] + :param pad: Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom)) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) + :param tooltip: text that will appear when mouse hovers over this element + :type tooltip: (str) + :param visible: set visibility state of the element + :type visible: (bool) + :param size_px: size in pixels (width, height). Will override the size parameter + :type size_px: Tupple[int, int] (width, height) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + key = key if key is not None else k + self.Values = values + self.DefaultValue = default_value + self.TKOptionMenu = None + self.Disabled = disabled + bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR + fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR + + super().__init__(ELEM_TYPE_INPUT_OPTION_MENU, size=size, auto_size_text=auto_size_text, background_color=bg, + text_color=fg, key=key, pad=pad, tooltip=tooltip, visible=visible, size_px=size_px, metadata=metadata) + + def Update(self, value=None, values=None, disabled=None): + return + + update = Update + +# ------------------------- OPTION MENU Element lazy functions ------------------------- # +InputOptionMenu = OptionMenu + + +# ---------------------------------------------------------------------- # +# Listbox # +# ---------------------------------------------------------------------- # +class Listbox(Element): + def __init__(self, values, default_values=None, select_mode=None, change_submits=False, enable_events=False, bind_return_key=False, size=(None, None), disabled=False, auto_size_text=None, font=None, background_color=None, + text_color=None, key=None, k=None, pad=None, tooltip=None, visible=True, size_px=(None,None), metadata=None): + """ + :param values: list of values to display. Can be any type including mixed types as long as they have __str__ method + :type values: List[Any] or Tuple[Any] + :param default_values: which values should be initially selected + :type default_values: List[Any] + :param select_mode: Select modes are used to determine if only 1 item can be selected or multiple and how they can be selected. Valid choices begin with "LISTBOX_SELECT_MODE_" and include: LISTBOX_SELECT_MODE_SINGLE LISTBOX_SELECT_MODE_MULTIPLE LISTBOX_SELECT_MODE_BROWSE LISTBOX_SELECT_MODE_EXTENDED + :type select_mode: [enum] + :param change_submits: DO NOT USE. Only listed for backwards compat - Use enable_events instead + :type change_submits: (bool) + :param enable_events: Turns on the element specific events. Listbox generates events when an item is clicked + :type enable_events: (bool) + :param bind_return_key: If True, then the return key will cause a the Listbox to generate an event + :type bind_return_key: (bool) + :param size: width = characters-wide, height = rows-high + :type size: Tuple(int, int) (width, height) + :param disabled: set disable state for element + :type disabled: (bool) + :param auto_size_text: True if element should be the same size as the contents + :type auto_size_text: (bool) + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param key: Used with window.FindElement and with return values to uniquely identify this element + :type key: (Any) + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: Union[str, int, tuple, object] + :param pad: Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom)) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param visible: set visibility state of the element + :type visible: (bool) + :param size_px: size in pixels (width, height). Will override the size parameter + :type size_px: Tupple[int, int] (width, height) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + key = key if key is not None else k + self.Values = values + self.DefaultValues = default_values + self.TKListbox = None + self.ChangeSubmits = change_submits or enable_events + self.BindReturnKey = bind_return_key + self.Disabled = disabled + if select_mode == LISTBOX_SELECT_MODE_BROWSE: + self.SelectMode = SELECT_MODE_BROWSE + elif select_mode == LISTBOX_SELECT_MODE_EXTENDED: + self.SelectMode = SELECT_MODE_EXTENDED + elif select_mode == LISTBOX_SELECT_MODE_MULTIPLE: + self.SelectMode = SELECT_MODE_MULTIPLE + elif select_mode == LISTBOX_SELECT_MODE_SINGLE: + self.SelectMode = SELECT_MODE_SINGLE + elif select_mode == LISTBOX_SELECT_MODE_CONTIGUOUS: + self.SelectMode = SELECT_MODE_CONTIGUOUS + else: + self.SelectMode = DEFAULT_LISTBOX_SELECT_MODE + bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR + fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR + self.Widget = self.QT_ListWidget = None # type: QListWidget + tsize = size # convert tkinter size to pixels + if size[0] is not None and size[0] < 100: + tsize = size[0]*DEFAULT_PIXELS_TO_CHARS_SCALING[0], size[1]*DEFAULT_PIXELS_TO_CHARS_SCALING[1] + + super().__init__(ELEM_TYPE_INPUT_LISTBOX, size=tsize, auto_size_text=auto_size_text, font=font, + background_color=bg, text_color=fg, key=key, pad=pad, tooltip=tooltip, visible=visible, size_px=size_px, metadata=metadata) + + def _QtCurrentRowChanged(self, state): + if self.ChangeSubmits: + _element_callback_quit_mainloop(self) + + + def Update(self, values=None, disabled=None, set_to_index=None,background_color=None, text_color=None, font=None, visible=None): + if values is not None: + self.Values = values + for i in range(self.QT_ListWidget.count()): + self.QT_ListWidget.takeItem(0) + items = [str(v) for v in self.Values] + self.QT_ListWidget.addItems(items) + if disabled == True: + self.QT_ListWidget.setDisabled(True) + elif disabled == False: + self.QT_ListWidget.setDisabled(False) + if set_to_index is not None: + self.QT_ListWidget.setCurrentRow(set_to_index) + super().Update(self.QT_ListWidget, background_color=background_color, text_color=text_color, font=font, visible=visible) + + return + + def SetValue(self, values): + # for index, item in enumerate(self.Values): + for index, value in enumerate(self.Values): + item = self.QT_ListWidget.item(index) + if value in values: + self.QT_ListWidget.setItemSelected(item, True) + + + def GetListValues(self): + return self.Values + + + def get(self): + """ + Gets the current value of the Element as it would be represented in the results dictionary. + Normally you would NOT be using this method, but instead using the return values dictionary + that is returned from reading your window + + :return: (List[Any]) The currently selected items in the listbox + """ + value = [] + selected_items = [item.text() for item in self.QT_ListWidget.selectedItems()] + for v in self.Values: + if str(v) in selected_items: + value.append(v) + return value + + get_list_values = GetListValues + set_value = SetValue + update = Update + + +LBox = Listbox +LB = Listbox + +# ---------------------------------------------------------------------- # +# Radio # +# ---------------------------------------------------------------------- # +class Radio(Element): + def __init__(self, text, group_id, default=False, disabled=False, size=(None, None), auto_size_text=None, + background_color=None, text_color=None, font=None, key=None, k=None, pad=None, tooltip=None, + change_submits=False, enable_events=False, visible=True, size_px=(None,None), metadata=None): + """ + :param text: Text to display next to button + :type text: (str) + :param group_id: Groups together multiple Radio Buttons. Any type works + :type group_id: (Any) + :param default: Set to True for the one element of the group you want initially selected + :type default: (bool) + :param disabled: set disable state + :type disabled: (bool) + :param size: (width, height) width = characters-wide, height = rows-high + :type size: Tuple[int, int] + :param auto_size_text: if True will size the element to match the length of the text + :type auto_size_text: (bool) + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param key: Used with window.FindElement and with return values to uniquely identify this element + :type key: (Any) + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: Union[str, int, tuple, object] + :param pad: Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom)) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param change_submits: DO NOT USE. Only listed for backwards compat - Use enable_events instead + :type change_submits: (bool) + :param enable_events: Turns on the element specific events. Radio Button events happen when an item is selected + :type enable_events: (bool) + :param visible: set visibility state of the element + :type visible: (bool) + :param size_px: size in pixels (width, height). Will override the size parameter + :type size_px: Tupple[int, int] (width, height) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + key = key if key is not None else k + self.InitialState = default + self.Text = text + self.GroupID = group_id + self.Value = None + self.Disabled = disabled + self.TextColor = text_color or DEFAULT_TEXT_COLOR + self.ChangeSubmits = change_submits or enable_events + self.Widget = self.QT_Radio_Button = None # type: QRadioButton + self.QT_RadioButtonGroup = None # type: QButtonGroup + + super().__init__(ELEM_TYPE_INPUT_RADIO, size=size, auto_size_text=auto_size_text, font=font, + background_color=background_color, text_color=self.TextColor, key=key, pad=pad, + tooltip=tooltip, visible=visible, size_px=size_px, metadata=metadata) + + def Update(self, value=None, disabled=None, background_color=None, text_color=None, font=None, visible=None): + if value is not None: + self.InitialState = value + if disabled: + self.QT_Radio_Button.setDisabled(True) + else: + self.QT_Radio_Button.setDisabled(False) + if value is True: + self.QT_Radio_Button.setChecked(True) + if value is False: + self.QT_RadioButtonGroup.setExclusive(False) + self.QT_Radio_Button.setChecked(False) + self.QT_RadioButtonGroup.setExclusive(True) + super().Update(self.QT_Radio_Button, background_color=background_color, text_color=text_color, font=font, visible=visible) + + + def reset_group(self): + self.QT_Radio_Button.setChecked(True) + self.QT_RadioButtonGroup.setExclusive(False) + self.QT_Radio_Button.setChecked(False) + self.QT_RadioButtonGroup.setExclusive(True) + + + def _QtCallbackValueChanged(self, value): + if not self.ChangeSubmits: + return + _element_callback_quit_mainloop(self) + + update = Update + +R = Radio +Rad = Radio + +# ---------------------------------------------------------------------- # +# Checkbox # +# ---------------------------------------------------------------------- # +class Checkbox(Element): + def __init__(self, text, default=False, size=(None, None), auto_size_text=None, font=None, background_color=None, + text_color=None, change_submits=False, enable_events=False, disabled=False, key=None, k=None, pad=None, tooltip=None, visible=True, size_px=(None,None), metadata=None): + """ + :param text: Text to display next to checkbox + :type text: (str) + :param default: Set to True if you want this checkbox initially checked + :type default: (bool) + :param size: (width, height) width = characters-wide, height = rows-high + :type size: Tuple[int, int] + :param auto_size_text: if True will size the element to match the length of the text + :type auto_size_text: (bool) + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param change_submits: DO NOT USE. Only listed for backwards compat - Use enable_events instead + :type change_submits: (bool) + :param enable_events: Turns on the element specific events. Checkbox events happen when an item changes + :type enable_events: (bool) + :param disabled: set disable state + :type disabled: (bool) + :param key: Used with window.FindElement and with return values to uniquely identify this element + :type key: (Any) + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: Union[str, int, tuple, object] + :param pad: Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom)) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param visible: set visibility state of the element + :type visible: (bool) + :param size_px: size in pixels (width, height). Will override the size parameter + :type size_px: Tupple[int, int] (width, height) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + key = key if key is not None else k + self.Text = text + self.InitialState = default + self.Value = None + self.TKCheckbutton = None + self.Disabled = disabled + self.TextColor = text_color if text_color else DEFAULT_TEXT_COLOR + self.ChangeSubmits = change_submits or enable_events + self.Widget = self.QT_Checkbox = None # type: QCheckBox + + super().__init__(ELEM_TYPE_INPUT_CHECKBOX, size=size, auto_size_text=auto_size_text, font=font, + background_color=background_color, text_color=self.TextColor, key=key, pad=pad, + tooltip=tooltip, visible=visible, size_px=size_px, metadata=metadata) + + def QtCallbackStateChanged(self, state): + if self.ChangeSubmits: + _element_callback_quit_mainloop(self) + + + def Get(self): + return self.QT_Checkbox.isChecked() + + def Update(self, value=None, disabled=None, background_color=None, text_color=None, font=None, visible=None): + self.QT_Checkbox.setChecked(value or False) + if disabled == True: + self.QT_Checkbox.setDisabled(True) + elif disabled == False: + self.QT_Checkbox.setDisabled(False) + super().Update(self.QT_Checkbox, background_color=background_color, text_color=text_color, font=font, visible=visible) + + get = Get + update = Update + +# ------------------------- CHECKBOX Element lazy functions ------------------------- # +CB = Checkbox +CBox = Checkbox +Check = Checkbox + + +# ---------------------------------------------------------------------- # +# Spin # +# ---------------------------------------------------------------------- # + +class Spin(Element): + # Values = None + # TKSpinBox = None + def __init__(self, values, initial_value=None, disabled=False, change_submits=False, enable_events=False, size=(None, None), + auto_size_text=None, font=None, background_color=None, text_color=None, key=None, k=None, pad=None, + tooltip=None, visible=True, size_px=(None,None), metadata=None): + """ + Spinner Element + :param values: List of valid values + :type values: Tuple[Any] or List[Any] + :param initial_value: Initial item to show in window. Choose from list of values supplied + :type initial_value: (Any) + :param disabled: set disable state + :type disabled: (bool) + :param change_submits: DO NOT USE. Only listed for backwards compat - Use enable_events instead + :type change_submits: (bool) + :param enable_events: Turns on the element specific events. Spin events happen when an item changes + :type enable_events: (bool) + :param size: (width, height) width = characters-wide, height = rows-high + :type size: Tuple[int, int] + :param auto_size_text: if True will size the element to match the length of the text + :type auto_size_text: (bool) + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param key: Used with window.FindElement and with return values to uniquely identify this element + :type key: (Any) + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: Union[str, int, tuple, object] + :param pad: Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom)) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param visible: set visibility state of the element + :type visible: (bool) + :param size_px: size in pixels (width, height). Will override the size parameter + :type size_px: Tupple[int, int] (width, height) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + key = key if key is not None else k + self.Values = values + self.DefaultValue = initial_value + self.ChangeSubmits = change_submits or enable_events + self.Disabled = disabled + bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR + fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR + self.Widget = self.QT_Spinner = None # type: StringBox + + super().__init__(ELEM_TYPE_INPUT_SPIN, size, auto_size_text, font=font, background_color=bg, text_color=fg, + key=key, pad=pad, tooltip=tooltip, visible=visible, size_px=size_px, metadata=metadata) + return + + class StringBox(QSpinBox): + def __init__(self, strings, parent=None): + super(Spin.StringBox, self).__init__(parent) + self.setStrings(strings) + + def strings(self): + return self._strings + + def setStrings(self, strings): + self._strings = tuple(strings) + self._values = dict(zip(strings, range(len(strings)))) + self.setRange(0, len(strings) - 1) + + def textFromValue(self, value): + return str(self._strings[value]) + + def valueFromText(self, text): + return self._values[text] + + + def _QtCallbackValueChanged(self, value): + if not self.ChangeSubmits: + return + _element_callback_quit_mainloop(self) + + def Update(self, value=None, values=None, disabled=None, background_color=None, text_color=None, font=None, visible=None): + if values != None: + self.Values = values + self.QT_Spinner.setStrings(values) + # self.QT_Spinner.setRange(self.Values[0], self.Values[1]) + if value is not None: + # self.QT_Spinner.setValue(value) + try: + self.QT_Spinner.setValue(self.QT_Spinner.valueFromText(value)) + self.DefaultValue = value + except: + pass + if disabled == True: + self.QT_Spinner.setDisabled(True) + elif disabled == False: + self.QT_Spinner.setDisabled(False) + super().Update(self.QT_Spinner, background_color=background_color, text_color=text_color, font=font, visible=visible) + + def Get(self): + return self.QT_Spinner.value() + + get = Get + update = Update + + +# ---------------------------------------------------------------------- # +# Multiline # +# ---------------------------------------------------------------------- # +class Multiline(Element): + def __init__(self, default_text='', enter_submits=False, disabled=False, autoscroll=False, size=(None, None), + auto_size_text=None, background_color=None, text_color=None, change_submits=False, enable_events=False, do_not_clear=True, + key=None, k=None, write_only=False, focus=False, font=None, pad=None, tooltip=None, visible=True, size_px=(None,None), metadata=None): + + """ + :param default_text: Initial text to show + :type default_text: (str) + :param enter_submits: if True, the Window.Read call will return is enter key is pressed in this element + :type enter_submits: (bool) + :param disabled: set disable state + :type disabled: (bool) + :param autoscroll: If True the contents of the element will automatically scroll as more data added to the end + :type autoscroll: (bool) + :param size: (width, height) width = characters-wide, height = rows-high + :type size: Tuple[int, int] + :param auto_size_text: if True will size the element to match the length of the text + :type auto_size_text: (bool) + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param change_submits: DO NOT USE. Only listed for backwards compat - Use enable_events instead + :type change_submits: (bool) + :param enable_events: Turns on the element specific events. Spin events happen when an item changes + :type enable_events: (bool) + :param do_not_clear: if False the element will be cleared any time the Window.Read call returns + :type do_not_clear: bool + :param key: Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element + :type key: (Any) + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: Union[str, int, tuple, object] + :param write_only: If True then no entry will be added to the values dictionary when the window is read + :type write_only: bool + :param focus: if True initial focus will go to this element + :type focus: (bool) + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param pad: Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom)) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param visible: set visibility state of the element + :type visible: (bool) + :param size_px: size in pixels (width, height). Will override the size parameter + :type size_px: Tupple[int, int] (width, height) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + key = key if key is not None else k + self.DefaultText = default_text + self.EnterSubmits = enter_submits + bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR + self.Focus = focus + self.do_not_clear = do_not_clear + fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR + self.Autoscroll = autoscroll + self.Disabled = disabled + self.ChangeSubmits = change_submits or enable_events + self.WriteOnly = write_only + tsize = _convert_tkinter_size_to_Qt(size, scaling=DEFAULT_PIXELS_TO_CHARS_SCALING_MULTILINE_TEXT,height_cutoff=DEFAULT_PIXEL_TO_CHARS_CUTOFF_MULTILINE) if size[0] is not None else size_px + + self.Widget = self.QT_TextEdit = None # type: QTextEdit + + super().__init__(ELEM_TYPE_INPUT_MULTILINE, size=(None, None), auto_size_text=auto_size_text, background_color=bg, + text_color=fg, key=key, pad=pad, tooltip=tooltip, font=font or DEFAULT_FONT, visible=visible, size_px=tsize, metadata=metadata) + return + + + class MultiQWidget(QWidget): + def __init__(self, qt_textedit, element): + self.QT_TextEdit = qt_textedit + self.Element = element + super().__init__() + + def eventFilter(self, widget, event): + if self.Element.EnterSubmits and event.type() == QEvent.KeyPress and widget is self.QT_TextEdit: + key = event.key() + if key in (Qt.Key_Return, Qt.Key_Enter): + self.Element._ReturnKeyHandler(0) + if event.type() == QEvent.FocusIn and widget is self.QT_TextEdit: + self.Element.ParentForm.FocusElement = self.Element + return QWidget.eventFilter(self, widget, event) + + + def _QtCallbackFocusInEvent(self): + if not self.ChangeSubmits: + return + _element_callback_quit_mainloop(self) + + + + def _dragEnterEvent(self, e): + if e.mimeData().hasText(): + e.accept() + else: + e.ignore() + + def _dropEvent(self, e): + self.Widget.setText(e.mimeData().text()) + + + def Update(self, value=None, disabled=None, append=False, autoscroll=False, background_color=None, text_color=None, font=None, text_color_for_value=None, background_color_for_value=None, visible=None, readonly=None): + """ + Changes some of the settings for the Multiline Element. Must call `Window.read` or `Window.finalize` or "finalize" the window using finalize parameter prior + + :param value: (str) new text to display + :param disabled: (bool) disable or enable state of the element + :param append: (bool) if True then new value will be added onto the end of the current value. if False then contents will be replaced. + :param autoscroll: (bool) if True cursor will be moved to end of element after updating + :param background_color: (str) color of background + :param text_color: (str) color of the text + :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc + :param text_color_for_value: (str) color of the new text being added + :param visible: (bool) set visibility state of the element + :param autoscroll: (bool) if True then contents of element are scrolled down when new text is added to the end + """ + + if value is not None and not append: + self.DefaultText = value + self.QT_TextEdit.setText(str(value)) + elif value is not None and append: + self.DefaultText = value + # self.QT_TextEdit.setText(self.QT_TextEdit.toPlainText() + str(value)) # original code + # self.QT_TextEdit.append(str(value)) # can't use because adds a newline + if text_color_for_value is not None: + self.QT_TextEdit.setTextColor(text_color_for_value) + if background_color_for_value is not None: + self.QT_TextEdit.setTextBackgroundColor(background_color_for_value) + self.QT_TextEdit.insertPlainText(str(value)) + if self.Autoscroll or autoscroll and autoscroll is not False: + self.QT_TextEdit.moveCursor(QtGui.QTextCursor.End) + if text_color_for_value is not None: + self.QT_TextEdit.setTextColor(self.TextColor) + if background_color_for_value is not None: + self.QT_TextEdit.setTextBackgroundColor(self.BackgroundColor) + if disabled is True: + self.QT_TextEdit.setDisabled(True) + elif disabled is False: + self.QT_TextEdit.setDisabled(False) + if readonly is True: + self.QT_TextEdit.setReadOnly(True) + elif readonly is False: + self.QT_TextEdit.setReadOnly(False) + super().Update(self.QT_TextEdit, background_color=background_color, text_color=text_color, font=font, visible=visible) + + + def Get(self): + return self.QT_TextEdit.toPlainText() + + def SetFocus(self): + self.QT_TextEdit.setFocus() + + + def print(self, *args, end=None, sep=None, text_color=None, background_color=None, autoscroll=True): + """ + Print like Python normally prints except route the output to a multline element and also add colors if desired + + :param args: The arguments to print + :type args: List[Any] + :param end: (str) The end char to use just like print uses + :type end: (str) + :param sep: (str) The separation character like print uses + :type sep: (str) + :param text_color: The color of the text + :type text_color: (str) + :param background_color: The background color of the line + :type background_color: (str) + :param autoscroll: (bool) If True cursor is moved to end after print + :type autoscroll: (bool) + """ + _print_to_element(self, *args, end=end, sep=sep, text_color=text_color, background_color=background_color, autoscroll=autoscroll) + + + + + get = Get + set_focus = SetFocus + update = Update + +ML = Multiline +MLine = Multiline + + +# ---------------------------------------------------------------------- # +# ScrolledOutput # +# ---------------------------------------------------------------------- # +class MultilineOutput(Element): + def __init__(self, default_text='', enter_submits=False, disabled=False, autoscroll=False, size=(None, None), auto_size_text=None, background_color=None, text_color=None, change_submits=False, enable_events=False, do_not_clear=True, key=None, k=None, focus=False, font=None, pad=None, tooltip=None, visible=True, size_px=(None,None), metadata=None): + """ + :param default_text: default value to put into input area + :type default_text: (str) + :param enter_submits: if True, the Window.Read call will return is enter key is pressed in this element + :type enter_submits: (bool) + :param disabled: set disable state + :type disabled: (bool) + :param autoscroll: If True cursor is moved to end after print + :typep autoscroll: (bool) + :param size: (width, height) width = characters-wide, height = rows-high + :type size: Tuple[int, int] + :param auto_size_text: if True size of the Text Element will be sized to fit the string provided in 'text' parm + :type auto_size_text: (bool) + :param background_color: color of background in one of the color formats + :type background_color: (str) + ::param text_color: color of the text + :type text_color: (str) + :param change_submits: DO NOT USE. Only listed for backwards compat - Use enable_events instead + :type change_submits: (bool) + :param enable_events: Turns on the element specific events. If this button is a target, should it generate an event when filled in + :type enable_events: (bool) + :param do_not_clear: if False the element will be cleared any time the Window.Read call returns + :type do_not_clear: (bool) + :param focus: if True, initial focus will be put on this button + :type focus: (bool) + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param key: Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element + :type key: (Any) + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: Union[str, int, tuple, object] + :param pad: Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom)) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param visible: set visibility state of the element + :type visible: (bool) + :param size_px: size in pixels (width, height). Will override the size parameter + :type size_px: Tupple[int, int] (width, height) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + key = key if key is not None else k + self.DefaultText = default_text + self.EnterSubmits = enter_submits + bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR + self.Focus = focus + self.do_not_clear = do_not_clear + fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR + self.Autoscroll = autoscroll + self.Disabled = disabled + self.ChangeSubmits = change_submits or enable_events + self.Widget = self.QT_TextBrowser = None # type: QTextBrowser + tsize = _convert_tkinter_size_to_Qt(size, scaling=DEFAULT_PIXELS_TO_CHARS_SCALING_MULTILINE_TEXT,height_cutoff=DEFAULT_PIXEL_TO_CHARS_CUTOFF_MULTILINE) if size[0] is not None else size_px + super().__init__(ELEM_TYPE_MULTILINE_OUTPUT, size=(None, None), auto_size_text=auto_size_text, background_color=bg, + text_color=fg, key=key, pad=pad, tooltip=tooltip, font=font or DEFAULT_FONT, visible=visible, size_px=tsize, metadata=metadata) + return + + + def Update(self, value=None, disabled=None, append=False, autoscroll=None, background_color=None, text_color=None, font=None, text_color_for_value=None, background_color_for_value=None, visible=None): + if value is not None and not append: + self.QT_TextBrowser.setText(str(value)) + elif value is not None and append: + self.QT_TextBrowser.insertPlainText(str(value)) + # self.QT_TextBrowser.moveCursor(QtGui.QTextCursor.End) + if disabled == True: + self.QT_TextBrowser.setDisabled(True) + elif disabled == False: + self.QT_TextBrowser.setDisabled(False) + if self.Autoscroll or autoscroll and autoscroll is not False: + self.QT_TextBrowser.moveCursor(QtGui.QTextCursor.End) + super().Update(self.QT_TextBrowser, background_color=background_color, text_color=text_color, font=font, visible=visible) + + + def Get(self): + return self.QT_TextBrowser.toPlainText() + + + def print(self, *args, end=None, sep=None, text_color=None, background_color=None, autoscroll=True): + """ + Print like Python normally prints except route the output to a multline element and also add colors if desired + + :param args: The arguments to print + :type args: List[Any] + :param end: The end char to use just like print uses + :type end: (str) + :param sep: The separation character like print uses + :type sep: (str) + :param text_color: The color of the text + :type text_color: (str) + :param background_color: The background color of the line + :type background_color: (str) + :param autoscroll: If True cursor is moved to end after print + :typep autoscroll: (bool) + """ + _print_to_element(self, *args, end=end, sep=sep, text_color=text_color, background_color=background_color, autoscroll=autoscroll) + + + + get = Get + update = Update + +MLineOut = Multiline + +# ---------------------------------------------------------------------- # +# Text # +# ---------------------------------------------------------------------- # +class Text(Element): + def __init__(self, text='', size=(None, None), auto_size_text=None, click_submits=None, enable_events=False, relief=None, font=None, text_color=None, background_color=None, justification=None, pad=None, margins=None, key=None, k=None, tooltip=None, visible=True, size_px=(None,None), metadata=None): + + """ + :param text: The text to display. Can include /n to achieve multiple lines. Will convert (optional) parameter into a string + :type text: (Any) + :param size: (width, height) width = characters-wide, height = rows-high + :type size: Tuple[int, int] + :param auto_size_text: if True size of the Text Element will be sized to fit the string provided in 'text' parm + :type auto_size_text: (bool) + :param click_submits: DO NOT USE. Only listed for backwards compat - Use enable_events instead + :type click_submits: (bool) + :param enable_events: Turns on the element specific events. Text events happen when the text is clicked + :type enable_events: (bool) + :param relief: relief style around the text. Values are same as progress meter relief values. Should be a constant that is defined at starting with "RELIEF_" - `RELIEF_RAISED, RELIEF_SUNKEN, RELIEF_FLAT, RELIEF_RIDGE, RELIEF_GROOVE, RELIEF_SOLID` + :type relief: (str/enum) + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param text_color: color of the text + :type text_color: (str) + :param background_color: color of background + :type background_color: (str) + :param justification: how string should be aligned within space provided by size. Valid choices = `left`, `right`, `center` + :type justification: (str) + :param pad: Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom)) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) + :param margins: ??? + :type margins: ??? + :param key: Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element + :type key: (Any) + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: Union[str, int, tuple, object] + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param visible: set visibility state of the element + :type visible: (bool) + :param size_px: size in pixels (width, height). Will override the size parameter + :type size_px: Tupple[int, int] (width, height) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + key = key if key is not None else k + self.DisplayText = str(text) + self.TextColor = text_color if text_color else DEFAULT_TEXT_COLOR + self.Justification = justification or 'left' + self.Relief = relief + self.ClickSubmits = click_submits or enable_events + self.Margins = margins + if background_color is None: + bg = DEFAULT_TEXT_ELEMENT_BACKGROUND_COLOR + else: + bg = background_color + self.Widget = self.QT_Label = None # type: QLabel + + super().__init__(ELEM_TYPE_TEXT, size, auto_size_text, background_color=bg, font=font if font else DEFAULT_FONT, + text_color=self.TextColor, visible=visible, pad=pad, key=key, tooltip=tooltip, size_px=size_px, metadata=metadata) + return + + def _QtCallbackTextClicked(self, event): + if not self.ClickSubmits: + return + _element_callback_quit_mainloop(self) + + def Update(self, value=None, background_color=None, text_color=None, font=None, visible=None): + """ + + :param value: + :param background_color: + :param text_color: + :param font: + :param visible: + :return: + """ + if value is not None: + self.DisplayText = str(value) + self.QT_Label.setText(str(value)) + super().Update(self.QT_Label, background_color=background_color, text_color=text_color, font=font, visible=visible) + + update = Update + +# ------------------------- Text Element lazy functions ------------------------- # +Txt = Text +T = Text + + +# ---------------------------------------------------------------------- # +# Output # +# Routes stdout, stderr to a scrolled window # +# ---------------------------------------------------------------------- # +class Output(Element): + def __init__(self, size=(None, None), background_color=None, text_color=None, pad=None, font=None, tooltip=None, + key=None, k=None, visible=True, size_px=(None,None), metadata=None): + """ + :param size: (width, height) w=characters-wide, h=rows-high + :type size: Tuple[int, int] + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param pad: Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom)) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param key: Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element + :type key: (Any) + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: Union[str, int, tuple, object] + :param visible: set visibility state of the element + :type visible: (bool) + :param size_px: size in pixels (width, height). Will override the size parameter + :type size_px: Tupple[int, int] (width, height) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + key = key if key is not None else k + self._TKOut = None + bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR + fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR + self.Widget = self.QT_TextBrowser = None # type: QTextBrowser + tsize = size_px if size_px != (None,None) else _convert_tkinter_size_to_Qt(size, scaling=DEFAULT_PIXELS_TO_CHARS_SCALING_MULTILINE_TEXT,height_cutoff=DEFAULT_PIXEL_TO_CHARS_CUTOFF_MULTILINE) if size[0] is not None else size + + super().__init__(ELEM_TYPE_OUTPUT, size=(None, None), background_color=bg, text_color=fg, pad=pad, font=font, + tooltip=tooltip, key=key, visible=visible, size_px=tsize, metadata=metadata) + + def _reroute_stdout(self): + self.my_stdout = sys.stdout + self.my_stderr = sys.stderr + sys.stdout = self + sys.stderr = self + + + def write(self, m): + """ + MUST be called write. Don't mess with. It's called by Python itself because of reroute + :param m: + :return: + """ + self.QT_TextBrowser.moveCursor(QtGui.QTextCursor.End) + self.QT_TextBrowser.insertPlainText( str(m)) + + # if self.my_stdout: + # self.my_stdout.write(str(m)) + + + def Update(self,value=None, background_color=None, text_color=None, font=None, visible=None): + if value is not None: + self.QT_TextBrowser.setText(value) + super().Update(self.QT_TextBrowser, background_color=background_color, text_color=text_color, font=font, visible=visible) + + + def __del__(self): + sys.stdout = self.my_stdout + sys.stderr = self.my_stderr + + update = Update + write = write + + +# ---------------------------------------------------------------------- # +# Button Class # +# ---------------------------------------------------------------------- # +class Button(Element): + def __init__(self, button_text='', button_type=BUTTON_TYPE_READ_FORM, target=(None, None), tooltip=None, + file_types=(("ALL Files", "*"),), initial_folder=None, disabled=False, change_submits=False, enable_events=False, + image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, border_width=None, + size=(None, None), auto_size_button=None, button_color=None, font=None, bind_return_key=False, + focus=False, pad=None, key=None, k=None, visible=True, size_px=(None,None), metadata=None): + """ + :param button_text: Text to be displayed on the button + :type button_text: (str) + :param button_type: You should NOT be setting this directly. ONLY the shortcut functions set this + :type button_type: (int) + :param target: key or (row,col) target for the button. Note that -1 for column means 1 element to the left of this one. The constant ThisRow is used to indicate the current row. The Button itself is a valid target for some types of button + :type target: Union[str, Tuple[int, int]] + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param file_types: the filetypes that will be used to match files. To indicate all files: (("ALL Files", "*.*"),). Note - NOT SUPPORTED ON MAC + :type file_types: Tuple[Tuple[str, str], ...] + :param initial_folder: starting path for folders and files + :type initial_folder: (str) + :param disabled: If True button will be created disabled + :type disabled: (bool) + :param change_submits: DO NOT USE. Only listed for backwards compat - Use enable_events instead + :type change_submits: (bool) + :param enable_events: Turns on the element specific events. If this button is a target, should it generate an event when filled in + :type enable_events: (bool) + :param image_filename: image filename if there is a button image. GIFs and PNGs only. + :type image_filename: (str) + :param image_data: Raw or Base64 representation of the image to put on button. Choose either filename or data + :type image_data: Union[bytes, str] + :param image_size: Size of the image in pixels (width, height) + :type image_size: Tuple[int, int] + :param image_subsample: amount to reduce the size of the image. Divides the size by this number. 2=1/2, 3=1/3, 4=1/4, etc + :type image_subsample: (int) + :param border_width: width of border around button in pixels + :type border_width: (int) + :param size: (width, height) of the button in characters wide, rows high + :type size: Tuple[int, int] + :param auto_size_button: if True the button size is sized to fit the text + :type auto_size_button: (bool) + :param button_color: of button. Easy to remember which is which if you say "ON" between colors. "red" on "green". + :type button_color: Tuple[str, str] == (text color, background color) + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param bind_return_key: If True the return key will cause this button to be pressed + :type bind_return_key: (bool) + :param focus: if True, initial focus will be put on this button + :type focus: (bool) + :param pad: Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom)) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) + :param key: Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element + :type key: (Any) + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: Union[str, int, tuple, object] + :param visible: set visibility state of the element + :type visible: (bool) + :param size_px: size in pixels (width, height). Will override the size parameter + :type size_px: Tupple[int, int] (width, height) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + key = key if key is not None else k + self.AutoSizeButton = auto_size_button + self.BType = button_type + self.FileTypes = file_types + self.TKButton = None + self.Target = target + self.ButtonText = str(button_text) + + # Button colors can be a tuple (text, background) or a string with format "text on background" + if button_color is None: + button_color = DEFAULT_BUTTON_COLOR + else: + try: + if isinstance(button_color,str): + button_color = button_color.split(' on ') + except Exception as e: + print('* cprint warning * you messed up with color formatting', e) + + self.ButtonColor = button_color if button_color else DEFAULT_BUTTON_COLOR + self.TextColor = self.ButtonColor[0] + self.BackgroundColor = self.ButtonColor[1] + self.ImageFilename = image_filename + self.ImageData = image_data + self.ImageSize = image_size + self.ImageSubsample = image_subsample + self.UserData = None + self.BorderWidth = border_width if border_width is not None else DEFAULT_BORDER_WIDTH + self.BindReturnKey = bind_return_key + self.Focus = focus + self.TKCal = None + self.CalendarCloseWhenChosen = None + self.DefaultDate_M_D_Y = (None, None, None) + self.InitialFolder = initial_folder + self.Disabled = disabled + self.ChangeSubmits = change_submits or enable_events + self.Widget = self.QT_QPushButton = None # type: QPushButton + self.ColorChosen = None + # self.temp_size = size if size != (NONE, NONE) else + + super().__init__(ELEM_TYPE_BUTTON, size=size, font=font, pad=pad, key=key, tooltip=tooltip, text_color=self.TextColor, background_color=self.BackgroundColor, visible=visible, size_px=size_px, metadata=metadata) + return + + # Realtime button release callback + def _ButtonReleaseCallBack(self, parm): + self.LastButtonClickedWasRealtime = False + self.ParentForm.LastButtonClicked = None + + # Realtime button callback + def _ButtonPressCallBack(self, parm): + self.ParentForm.LastButtonClickedWasRealtime = True + if self.Key is not None: + self.ParentForm.LastButtonClicked = self.Key + else: + self.ParentForm.LastButtonClicked = self.ButtonText + if self.ParentForm.CurrentlyRunningMainloop: + pass # kick out of loop if read was called + + # ------- Button Callback ------- # + def _ButtonCallBack(self): + + # print('Button callback') + + # print(f'Parent = {self.ParentForm} Position = {self.Position}') + # Buttons modify targets or return from the form + # If modifying target, get the element object at the target and modify its StrVar + target = self.Target + target_element = None + if target[0] == ThisRow: + target = [self.Position[0], target[1]] + if target[1] < 0: + target[1] = self.Position[1] + target[1] + strvar = None + should_submit_window = False + if target == (None, None): + strvar = self.TKStringVar + else: + if not isinstance(target, str): + if target[0] < 0: + target = [self.Position[0] + target[0], target[1]] + target_element = self.ParentContainer._GetElementAtLocation(target) + else: + target_element = self.ParentForm.FindElement(target) + try: + strvar = target_element.TKStringVar + except: + pass + try: + if target_element.ChangeSubmits: + should_submit_window = True + except: + pass + filetypes = (("ALL Files", "*"),) if self.FileTypes is None else self.FileTypes + if self.BType == BUTTON_TYPE_BROWSE_FOLDER: + folder_name = QFileDialog.getExistingDirectory(dir=self.InitialFolder) + if folder_name != '': + if target_element.Type == ELEM_TYPE_BUTTON: + target_element.FileOrFolderName = folder_name + else: + target_element.Update(folder_name) + elif self.BType == BUTTON_TYPE_BROWSE_FILE: + qt_types = convert_tkinter_filetypes_to_qt(self.FileTypes) + file_name = QFileDialog.getOpenFileName(dir=self.InitialFolder, filter=qt_types) + if file_name != '': + if target_element.Type == ELEM_TYPE_BUTTON: + target_element.FileOrFolderName = file_name + else: + target_element.Update(file_name[0]) + elif self.BType == BUTTON_TYPE_COLOR_CHOOSER: + qcolor = QColorDialog.getColor() + rgb_color = qcolor.getRgb() + color= '#' + ''.join('%02x'% i for i in rgb_color[:3]) + if self.Target == (None, None): + self.FileOrFolderName = color + else: + target_element.Update(color) + elif self.BType == BUTTON_TYPE_BROWSE_FILES: + qt_types = convert_tkinter_filetypes_to_qt(self.FileTypes) + file_name = QFileDialog.getOpenFileNames(dir=self.InitialFolder, filter=qt_types) + if file_name != '': + file_name = BROWSE_FILES_DELIMITER.join(file_name[0]) + if target_element.Type == ELEM_TYPE_BUTTON: + target_element.FileOrFolderName = file_name + else: + target_element.Update(file_name) + elif self.BType == BUTTON_TYPE_SAVEAS_FILE: + qt_types = convert_tkinter_filetypes_to_qt(self.FileTypes) + file_name = QFileDialog.getSaveFileName(dir=self.InitialFolder, filter=qt_types) + if file_name != '': + if target_element.Type == ELEM_TYPE_BUTTON: + target_element.FileOrFolderName = file_name + else: + target_element.Update(file_name[0]) + elif self.BType == BUTTON_TYPE_CLOSES_WIN: # this is a return type button so GET RESULTS and destroy window + # first, get the results table built + # modify the Results table in the parent FlexForm object + if self.Key is not None: + self.ParentForm.LastButtonClicked = self.Key + else: + self.ParentForm.LastButtonClicked = self.ButtonText + self.ParentForm.FormRemainedOpen = False + self.ParentForm._Close() + if self.ParentForm.CurrentlyRunningMainloop: + self.ParentForm.QTApplication.exit() # Exit the mainloop + self.ParentForm.QT_QMainWindow.close() + if self.ParentForm.NonBlocking: + # TODO DESTROY WIN + Window.DecrementOpenCount() + elif self.BType == BUTTON_TYPE_READ_FORM: # LEAVE THE WINDOW OPEN!! DO NOT CLOSE + # first, get the results table built + # modify the Results table in the parent FlexForm object + if self.Key is not None: + self.ParentForm.LastButtonClicked = self.Key + else: + self.ParentForm.LastButtonClicked = self.ButtonText + self.ParentForm.FormRemainedOpen = True + if self.ParentForm.CurrentlyRunningMainloop: # if this window is running the mainloop, kick out + self.ParentForm.QTApplication.exit() + elif self.BType == BUTTON_TYPE_CLOSES_WIN_ONLY: # special kind of button that does not exit main loop + self.ParentForm._Close() + self.ParentForm.QT_QMainWindow.close() + if self.ParentForm.CurrentlyRunningMainloop: # if this window is running the mainloop, kick out + self.ParentForm.QTApplication.exit() + Window.DecrementOpenCount() + elif self.BType == BUTTON_TYPE_CALENDAR_CHOOSER: # this is a return type button so GET RESULTS and destroy window + should_submit_window = False + + if should_submit_window: + self.ParentForm.LastButtonClicked = target_element.Key + self.ParentForm.FormRemainedOpen = True + if self.ParentForm.CurrentlyRunningMainloop: + self.ParentForm.QTApplication.exit() + pass # TODO # kick the users out of the mainloop + return + + def Update(self, text=None, button_color=(None, None), disabled=None, image_data=None, image_filename=None, font=None, visible=None): + if text is not None: + self.QT_QPushButton.setText(str(text)) + self.ButtonText = text + if self.ParentForm.Font and (self.Font == DEFAULT_FONT or not self.Font): + font = self.ParentForm.Font + elif self.Font is not None: + font = self.Font + else: + font = DEFAULT_FONT + + fg = bg = None + if button_color != (None, None): + self.ButtonColor = button_color + fg, bg = button_color + if self.Disabled != disabled and disabled is not None: + if not disabled: # if enabling buttons, set the color + fg, bg = self.ButtonColor + self.Disabled = disabled + if disabled: + self.QT_QPushButton.setDisabled(True) + else: + self.QT_QPushButton.setDisabled(False) + # fg, bg = self.ButtonColor + # print(f'Button update fg, bg {fg}, {bg}') + super().Update(self.QT_QPushButton, background_color=bg, text_color=fg, font=font, visible=visible) + + + def GetText(self): + return self.ButtonText + + def SetFocus(self): + self.QT_QPushButton.setFocus() + + def Click(self): + if self.Widget is None: + return + try: + self.Widget.click() + except Exception as e: + print('Exception {} \nclicking button {}'.format(e, self.ButtonText)) + + click = Click + get_text = GetText + set_focus = SetFocus + update = Update + +# ------------------------- Button lazy functions ------------------------- # +B = Button +Btn = Button + + + +# ---------------------------------------------------------------------- # +# ButtonMenu Class # +# ---------------------------------------------------------------------- # +class ButtonMenu(Element): + def __init__(self, button_text ,menu_def, tooltip=None,disabled=False, + image_filename=None, image_data=None, image_size=(None, None), image_subsample=None,border_width=None, + size=(None, None), auto_size_button=None, button_color=None, font=None, pad=None, key=None, k=None, visible=True, size_px=(None,None), metadata=None): + """ + :param button_text: Text to be displayed on the button + :type button_text: (str) + :param menu_def: A list of lists of Menu items to show when this element is clicked. See docs for format as they are the same for all menu types + :type menu_def: List[List[str]] + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param disabled: If True button will be created disabled + :type disabled: (bool) + :param image_filename: image filename if there is a button image. GIFs and PNGs only. + :type image_filename: (str) + :param image_data: Raw or Base64 representation of the image to put on button. Choose either filename or data + :type image_data: Union[bytes, str] + :param image_size: Size of the image in pixels (width, height) + :type image_size: Tuple[int, int] + :param image_subsample: amount to reduce the size of the image. Divides the size by this number. 2=1/2, 3=1/3, 4=1/4, etc + :type image_subsample: (int) + :param border_width: width of border around button in pixels + :type border_width: (int) + :param size: (width, height) of the button in characters wide, rows high + :type size: Tuple[int, int] + :param auto_size_button: if True the button size is sized to fit the text + :type auto_size_button: (bool) + :param button_color: of button. Easy to remember which is which if you say "ON" between colors. "red" on "green" + :type button_color: Tuple[str, str] == (text color, background color) + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param pad: Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom)) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) + :param key: Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element + :type key: (Any) + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: Union[str, int, tuple, object] + :param visible: set visibility state of the element + :type visible: (bool) + :param size_px: size in pixels (width, height). Will override the size parameter + :type size_px: Tupple[int, int] (width, height) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + key = key if key is not None else k + self.MenuDefinition = menu_def + self.AutoSizeButton = auto_size_button + self.ButtonText = button_text + self.ButtonColor = button_color if button_color else DEFAULT_BUTTON_COLOR + self.TextColor = self.ButtonColor[0] + self.BackgroundColor = self.ButtonColor[1] + self.BorderWidth = border_width + self.ImageFilename = image_filename + self.ImageData = image_data + self.ImageSize = image_size + self.ImageSubsample = image_subsample + self.Disabled = disabled + self.Widget = self.QT_QPushButton = None # type: QPushButton + self.IsButtonMenu = True + self.MenuItemChosen = None + + # self.temp_size = size if size != (NONE, NONE) else + + super().__init__(ELEM_TYPE_BUTTONMENU, size=size, font=font, pad=pad, key=key, tooltip=tooltip, text_color=self.TextColor, background_color=self.BackgroundColor, visible=visible, size_px=size_px, metadata=metadata) + return + + + def _QT_MenuItemChosenCallback(self, item_chosen): + # print('IN BUTTON MENU ITEM CALLBACK', item_chosen) + self.Key = item_chosen.replace('&','') # fool the quit function into thinking this was a key + _element_callback_quit_mainloop(self) + + + def Update(self, menu_definition=None, text=None, button_color=(None, None), font=None, visible=None): + if menu_definition is not None: + menu_def = menu_definition + qmenu = QMenu(self.QT_QPushButton) + qmenu.setTitle(menu_def[0]) + AddMenuItem(qmenu, menu_def[1], self) + self.QT_QPushButton.setMenu(qmenu) + super().Update(self.QT_QPushButton, background_color=button_color[1], text_color=button_color[0], font=font, visible=visible) + + + def Click(self): + """ """ + try: + self.QT_QPushButton.click() + except Exception as e: + print('Exception {} clicking button. Has your Window been Finalized() or Read()?'.format(e)) + + click = Click + update = Update + +BMenu = ButtonMenu + +# ---------------------------------------------------------------------- # +# ProgreessBar # +# ---------------------------------------------------------------------- # +class ProgressBar(Element): + def __init__(self, max_value, orientation=None, size=(None, None),start_value=0, auto_size_text=None, bar_color=(None, None), + style=None, border_width=None, relief=None, key=None, k=None, pad=None, visible=True, size_px=(None,None), metadata=None): + + """ + :param max_value: max value of progressbar + :type max_value: (int) + :param orientation: 'horizontal' or 'vertical' + :type orientation: (str) + :param size: Size of the bar. If horizontal (chars wide, pixels high), vert (pixels wide, rows high) + :type size: Tuple[int, int] + :param start_value: ??? + :type start_value: ??? + :param auto_size_text: Not sure why this is here + :type auto_size_text: (bool) + :param bar_color: The 2 colors that make up a progress bar. One is the background, the other is the bar + :type bar_color: Tuple[str, str] + :param style: Progress bar style defined as one of these 'default', 'winnative', 'clam', 'alt', 'classic', 'vista', 'xpnative' + :type style: (str) + :param border_width: The amount of pixels that go around the outside of the bar + :type border_width: (int) + :param relief: relief style. Values are same as progress meter relief values. Can be a constant or a string: `RELIEF_RAISED RELIEF_SUNKEN RELIEF_FLAT RELIEF_RIDGE RELIEF_GROOVE RELIEF_SOLID` (Default value = DEFAULT_PROGRESS_BAR_RELIEF) + :type relief: (str) + :param key: Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element + :type key: (Any) + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: Union[str, int, tuple, object] + :param pad: Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom)) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) + :param visible: set visibility state of the element + :type visible: (bool) + :param size_px: size in pixels (width, height). Will override the size parameter + :type size_px: Tupple[int, int] (width, height) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + key = key if key is not None else k + self.MaxValue = max_value + self.TKProgressBar = None + self.Cancelled = False + self.NotRunning = True + self.Orientation = orientation if orientation else DEFAULT_METER_ORIENTATION + self.BarColor = bar_color if bar_color != (None, None) else DEFAULT_PROGRESS_BAR_COLOR + self.BarStyle = style if style else DEFAULT_PROGRESS_BAR_STYLE + self.BorderWidth = border_width if border_width is not None else DEFAULT_PROGRESS_BAR_BORDER_WIDTH + self.Relief = relief if relief else DEFAULT_PROGRESS_BAR_RELIEF + self.BarExpired = False + self.StartValue = start_value + tsize = size + if size[0] is not None and size[0] < 100: + # tsize = size[0] * DEFAULT_PIXELS_TO_CHARS_SCALING[0], size[1] * DEFAULT_PIXELS_TO_CHARS_SCALING[1] + tsize = size[0]*10, size[1] + self.Widget = self.QT_QProgressBar = None # type: QProgressBar + + super().__init__(ELEM_TYPE_PROGRESS_BAR, size=tsize, auto_size_text=auto_size_text, key=key, pad=pad, visible=visible, size_px=size_px, metadata=metadata) + + # returns False if update failed + def UpdateBar(self, current_count, max=None): + if max is not None: + self.QT_QProgressBar.setMaximum(max) + self.QT_QProgressBar.setValue(current_count) + self.ParentForm.QTApplication.processEvents() # refresh the window + return True + + + def Update(self, visible=None): + super().Update(self.QT_QProgressBar, visible=visible) + + update = Update + update_bar = UpdateBar + +PBar = ProgressBar +Prog = ProgressBar + +# ---------------------------------------------------------------------- # +# Image # +# ---------------------------------------------------------------------- # +class Image(Element): + def __init__(self, filename=None, data=None, data_base64=None, background_color=None, size=(None, None), pad=None, key=None, k=None, tooltip=None, click_submits=False, enable_events=False, visible=True, size_px=(None,None), metadata=None): + """ + :param filename: image filename if there is a button image. GIFs and PNGs only. + :type filename: (str) + :param data: Raw or Base64 representation of the image to put on button. Choose either filename or data + :type data: Union[bytes, str] + :param data_base64: ??? + :type data_base64: ??? + :param background_color: color of background + :type background_color: + :param size: (width, height) size of image in pixels + :type size: Tuple[int, int] + :param pad: Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom)) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) + :param key: Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element + :type key: (Any) + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: Union[str, int, tuple, object] + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param click_submits: ??? + :type click_submits: (bool) + :param enable_events: Turns on the element specific events. For an Image element, the event is "image clicked" + :type enable_events: (bool) + :param visible: set visibility state of the element + :type visible: (bool) + :param size_px: size in pixels (width, height). Will override the size parameter + :type size_px: Tupple[int, int] (width, height) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + key = key if key is not None else k + self.Filename = filename + self.Data = data + self.DataBase64 = data_base64 + self.tktext_label = None + self.BackgroundColor = background_color + self.ClickSubmits = click_submits or enable_events + if data is None and filename is None and data_base64 is None: + print('* Warning... no image specified in Image Element! *') + self.Widget = self.QT_QLabel = None # type: QLabel + + super().__init__(ELEM_TYPE_IMAGE, size=size, background_color=background_color, pad=pad, key=key, + tooltip=tooltip, visible=visible, size_px=size_px, metadata=metadata) + return + + + def QtCallbackImageClicked(self, event): + if not self.ClickSubmits: + return + _element_callback_quit_mainloop(self) + + + def Update(self, filename=None, data=None, data_base64=None, size=(None, None), visible=None): + if filename is not None: + qlabel = self.QT_QLabel + qlabel.setText('') + w = QtGui.QPixmap(filename).width() + h = QtGui.QPixmap(filename).height() + qlabel.setGeometry(QtCore.QRect(0, 0, w, h)) + qlabel.setPixmap(QtGui.QPixmap(filename)) + elif data is not None: + qlabel = self.QT_QLabel + qlabel.setText('') + ba = QtCore.QByteArray.fromRawData(data) + pixmap = QtGui.QPixmap() + pixmap.loadFromData(ba) + qlabel.setPixmap(pixmap) + elif data_base64 is not None: + qlabel = self.QT_QLabel + qlabel.setText('') + ba = QtCore.QByteArray.fromBase64(data_base64) + pixmap = QtGui.QPixmap() + pixmap.loadFromData(ba) + qlabel.setPixmap(pixmap) + super().Update(self.QT_QLabel, visible=visible) + + update = Update + + +# ---------------------------------------------------------------------- # +# Canvas # +# ---------------------------------------------------------------------- # +class Canvas(Element): + def __init__(self, canvas=None, background_color=None, size=(None, None), pad=None, key=None, k=None, tooltip=None, metadata=None): + """ + Canvas Element - NOT USED IN QT PORT ? + :param canvas: Your own tk.Canvas if you already created it. Leave blank to create a Canvas + :type canvas: (tk.Canvas) + :param background_color: color of background + :type background_color: (str) + :param size: (width in char, height in rows) size in pixels to make canvas + :type size: Tuple[int,int] + :param pad: Amount of padding to put around element + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) + :param key: Used with window.FindElement and with return values to uniquely identify this element + :type key: (Any) + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: Union[str, int, tuple, object] + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + key = key if key is not None else k + self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR + self._TKCanvas = canvas + + super().__init__(ELEM_TYPE_CANVAS, background_color=background_color, size=size, pad=pad, key=key, + tooltip=tooltip, metadata=metadata) + return + + @property + def TKCanvas(self): + if self._TKCanvas is None: + print('*** Did you forget to call Finalize()? Your code should look something like: ***') + print('*** form = sg.Window("My Form").Layout(layout).Finalize() ***') + return self._TKCanvas + +# ---------------------------------------------------------------------- # +# Graph # +# ---------------------------------------------------------------------- # +class Graph(Element): + def __init__(self, canvas_size, graph_bottom_left, graph_top_right, background_color=None, pad=None, key=None, k=None, + tooltip=None, visible=True, change_submits=False, enable_events=False, drag_submits=False, metadata=None): + """ + :param canvas_size: size of the canvas area in pixels + :type canvas_size: Tuple[int, int] + :param graph_bottom_left: (x,y) The bottoms left corner of your coordinate system + :type graph_bottom_left: Tuple[int, int] + :param graph_top_right: (x,y) The top right corner of your coordinate system + :type graph_top_right: Tuple[int, int] + :param background_color: background color of the drawing area + :type background_color: (str) + :param pad: Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom)) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) + :param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window + :type key: (Any) + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: Union[str, int, tuple, object] + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param visible: set visibility state of the element (Default = True) + :type visible: (bool) + :param change_submits: * DEPRICATED DO NOT USE. Use `enable_events` instead + :type change_submits: (bool) + :param enable_events: If True then clicks on the Graph are immediately reported as an event. Use this instead of change_submits + :type enable_events: (bool) + :param drag_submits: if True and Events are enabled for the Graph, will report Events any time the mouse moves while button down + :type drag_submits: (bool) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + key = key if key is not None else k + self.CanvasSize = canvas_size + self.BottomLeft = graph_bottom_left + self.TopRight = graph_top_right + self.x = self.y = 0 + self.Widget = self.QT_QGraphicsScene = None # type: QGraphicsScene + + super().__init__(ELEM_TYPE_GRAPH, background_color=background_color, size=(None, None), pad=pad, key=key, + tooltip=tooltip, visible=visible, size_px=canvas_size, metadata=metadata) + return + + + + + def _convert_xy_to_canvas_xy(self, x_in, y_in): + scale_x = (self.CanvasSize[0] - 0) / (self.TopRight[0] - self.BottomLeft[0]) + scale_y = (0 - self.CanvasSize[1]) / (self.TopRight[1] - self.BottomLeft[1]) + new_x = 0 + scale_x * (x_in - self.BottomLeft[0]) + new_y = self.CanvasSize[1] + scale_y * (y_in - self.BottomLeft[1]) + return new_x, new_y + + def DrawLine(self, point_from, point_to, color='black', width=1): + converted_point_from = self._convert_xy_to_canvas_xy(point_from[0], point_from[1]) + converted_point_to = self._convert_xy_to_canvas_xy(point_to[0], point_to[1]) + + qcolor = QColor(color) + pen = QPen(qcolor, width) + line = self.QT_QGraphicsScene.addLine(self.x+converted_point_from[0],self.y+ converted_point_from[1], self.x+converted_point_to[0],self.y+ converted_point_to[1], pen=pen) + # self.QT_QGraphicsItemGroup.addToGroup(line) + return line + + def DrawRectangle(self, top_left, bottom_right, fill_color=None, line_color=None): + converted_point_top_left = self._convert_xy_to_canvas_xy(top_left[0], top_left[1]) + converted_point_bottom_right = self._convert_xy_to_canvas_xy(bottom_right[0], bottom_right[1]) + + qcolor = QColor(line_color) + pen = QPen(qcolor, 1) + qcolor = QColor(fill_color) + brush = QBrush(qcolor) + line = self.QT_QGraphicsScene.addRect(converted_point_top_left[0],converted_point_top_left[1], + converted_point_bottom_right[0]-converted_point_top_left[0], + converted_point_bottom_right[1]-converted_point_top_left[1], + pen, brush) + # self.QT_QGraphicsItemGroup.addToGroup(line) + + + def DrawCircle(self, center_location, radius, fill_color=None, line_color='black'): + converted_point = self._convert_xy_to_canvas_xy(center_location[0], center_location[1]) + qcolor = QColor(line_color) + pen = QPen(qcolor) + qcolor = QColor(fill_color) + brush = QBrush(qcolor) + circle_id = self.QT_QGraphicsScene.addEllipse(self.x + converted_point[0] - radius, self.y + converted_point[1] - radius, + radius * 2, radius * 2, pen=pen, brush=brush) + return circle_id # type: QGraphicsEllipseItem + + def RelocateFigure(self, id, x, y): + id=id # type: QtWidgets.QGraphicsEllipseItem + converted_point = self._convert_xy_to_canvas_xy(x, y) + id.setX(converted_point[0]) + id.setY(converted_point[1]) + + + + def DrawText(self, text, location, color='black', font=None, angle=0): + converted_point = self._convert_xy_to_canvas_xy(location[0], location[1]) + + qcolor = QColor(color) + qpath = QPainterPath() + _font = font or ('courier', 12) + qfont = QFont(_font[0], _font[1]) + # qfont.setWeight(.5) + + text_id = qpath.addText(self.x+converted_point[0], self.y+converted_point[1], qfont, str(text)) + self.QT_QGraphicsScene.addPath(qpath, qcolor) + return text_id + + def Move(self, x_direction, y_direction): + x_direction = -x_direction + y_direction = -y_direction + zero_converted = self._convert_xy_to_canvas_xy(0, 0) + shift_converted = self._convert_xy_to_canvas_xy(x_direction, y_direction) + shift_amount = (shift_converted[0] - zero_converted[0], shift_converted[1] - zero_converted[1]) + rect = self.QT_QGraphicsScene.sceneRect() + rect.translate(shift_amount[0], shift_amount[1]) + self.x += shift_amount[0] + self.y += shift_amount[1] + self.QT_QGraphicsScene.setSceneRect(rect) + # items = self.QT_QGraphicsScene.items() + # print(len(items)) + # for item in items: + # if not item.isActive(): + # print('*', end='') + # item.removeFromIndex() + + # print(rect) + + + + def DrawOval(self, top_left, bottom_right, fill_color=None, line_color=None): + converted_top_left = self._convert_xy_to_canvas_xy(top_left[0], top_left[1]) + converted_bottom_right = self._convert_xy_to_canvas_xy(bottom_right[0], bottom_right[1]) + if self._TKCanvas2 is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + return self._TKCanvas2.create_oval(converted_top_left[0], converted_top_left[1], converted_bottom_right[0], + converted_bottom_right[1], fill=fill_color, outline=line_color) + + def DrawPoint(self, point, size=2, color='black'): + converted_point = self._convert_xy_to_canvas_xy(point[0], point[1]) + if self._TKCanvas2 is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + return self._TKCanvas2.create_oval(converted_point[0] - size, converted_point[1] - size, + converted_point[0] + size, converted_point[1] + size, fill=color, + outline=color) + + + def DrawArc(self, top_left, bottom_right, extent, start_angle, style=None, arc_color='black'): + converted_top_left = self._convert_xy_to_canvas_xy(top_left[0], top_left[1]) + converted_bottom_right = self._convert_xy_to_canvas_xy(bottom_right[0], bottom_right[1]) + if self._TKCanvas2 is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + return self._TKCanvas2.create_arc(converted_top_left[0], converted_top_left[1], converted_bottom_right[0], + converted_bottom_right[1], extent=extent, start=start_angle, style='tkstyle', + outline=arc_color) + + def DrawRectangleOld(self, top_left, bottom_right, fill_color=None, line_color=None): + converted_top_left = self._convert_xy_to_canvas_xy(top_left[0], top_left[1]) + converted_bottom_right = self._convert_xy_to_canvas_xy(bottom_right[0], bottom_right[1]) + if self._TKCanvas2 is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + return self._TKCanvas2.create_rectangle(converted_top_left[0], converted_top_left[1], converted_bottom_right[0], + converted_bottom_right[1], fill=fill_color, outline=line_color) + + + def Erase(self): + if self.QT_QGraphicsScene is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + self.QT_QGraphicsScene.clear() + + def Update(self, background_color, visible=None): + # TODO + # if self._TKCanvas2 is None: + # print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + # print('Call Window.Finalize() prior to this operation') + # return None + # self._TKCanvas2.configure(background=background_color) + super().Update(self.QT_QGraphicsScene, visible=visible) + + def MoveFigure(self, figure, x_direction, y_direction): + zero_converted = self._convert_xy_to_canvas_xy(0, 0) + shift_converted = self._convert_xy_to_canvas_xy(x_direction, y_direction) + shift_amount = (shift_converted[0] - zero_converted[0], shift_converted[1] - zero_converted[1]) + if figure is None: + print('*** WARNING - Your figure is None. It most likely means your did not Finalize your Window ***') + print('Call Window.Finalize() prior to all graph operations') + return None + self._TKCanvas2.move(figure, shift_amount[0], shift_amount[1]) + + + def change_coordinates(self, graph_bottom_left, graph_top_right): + """ + Changes the corrdinate system to a new one. The same 2 points in space are used to define the coorinate + system - the bottom left and the top right values of your graph. + + :param graph_bottom_left: Tuple[int, int] (x,y) The bottoms left corner of your coordinate system + :param graph_top_right: Tuple[int, int] (x,y) The top right corner of your coordinate system + """ + self.BottomLeft = graph_bottom_left + self.TopRight = graph_top_right + + + @property + def TKCanvas(self): + if self._TKCanvas2 is None: + print('*** Did you forget to call Finalize()? Your code should look something like: ***') + print('*** form = sg.Window("My Form").Layout(layout).Finalize() ***') + return self._TKCanvas2 + + + draw_arc = DrawArc + draw_circle = DrawCircle + draw_line = DrawLine + draw_oval = DrawOval + draw_point = DrawPoint + draw_rectangle = DrawRectangle + draw_rectangle_old = DrawRectangleOld + draw_text = DrawText + erase = Erase + move = Move + move_figure = MoveFigure + relocate_figure = RelocateFigure + update = Update + + +# ---------------------------------------------------------------------- # +# Frame # +# ---------------------------------------------------------------------- # +class Frame(Element): + def __init__(self, title, layout, title_color=None, background_color=None, title_location=None, frame_color=None, + relief=DEFAULT_FRAME_RELIEF, element_justification='float', size=(None, None), font=None, pad=None, border_width=None, key=None, k=None, + tooltip=None, visible=True, size_px=(None,None), metadata=None): + """ + :param title: text that is displayed as the Frame's "label" or title + :type title: (str) + :param layout: The layout to put inside the Frame + :type layout: List[List[Elements]] + :param title_color: color of the title text + :type title_color: (str) + :param background_color: background color of the Frame + :type background_color: (str) + :param title_location: location to place the text title. Choices include: TITLE_LOCATION_TOP TITLE_LOCATION_BOTTOM TITLE_LOCATION_LEFT TITLE_LOCATION_RIGHT TITLE_LOCATION_TOP_LEFT TITLE_LOCATION_TOP_RIGHT TITLE_LOCATION_BOTTOM_LEFT TITLE_LOCATION_BOTTOM_RIGHT + :type title_location: (enum) + :param frame_color: color of the frame lines + :type frame_color: (str) + :param relief: relief style. Values are same as other elements with reliefs. Choices include RELIEF_RAISED RELIEF_SUNKEN RELIEF_FLAT RELIEF_RIDGE RELIEF_GROOVE RELIEF_SOLID + :type relief: (enum) + :param element_justification: All elements inside the Frame will have this justification 'left', 'right', 'center' are valid values + :type element_justification: (str) + :param size: (width, height) (note this parameter may not always work) + :type size: Tuple[int, int] + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param pad: Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom)) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) + :param border_width: width of border around element in pixels + :type border_width: (int) + :param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window + :type key: (Any) + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: Union[str, int, tuple, object] + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param visible: set visibility state of the element + :type visible: (bool) + :param size_px: size in pixels (width, height). Will override the size parameter + :type size_px: Tupple[int, int] (width, height) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + key = key if key is not None else k + self.UseDictionary = False + self.ReturnValues = None + self.ReturnValuesList = [] + self.ReturnValuesDictionary = {} + self.DictionaryKeyCounter = 0 + self.ParentWindow = None + self.Rows = [] + # self.ParentForm = None + self.TKFrame = None + self.Title = title + self.Relief = relief + self.TitleLocation = title_location + self.BorderWidth = border_width + self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR + self.ElementJustification = element_justification + self.FrameColor = frame_color + self.Widget = self.QT_QGroupBox = None # type: QGroupBox + self.Layout(layout) + + super().__init__(ELEM_TYPE_FRAME, background_color=background_color, text_color=title_color, size=size, + font=font, pad=pad, key=key, tooltip=tooltip, visible=visible, size_px=size_px, metadata=metadata) + return + + def AddRow(self, *args): + """ Parms are a variable number of Elements """ + NumRows = len(self.Rows) # number of existing rows is our row number + CurrentRowNumber = NumRows # this row's number + CurrentRow = [] # start with a blank row and build up + # ------------------------- Add the elements to a row ------------------------- # + for i, element in enumerate(args): # Loop through list of elements and add them to the row + element.Position = (CurrentRowNumber, i) + element.ParentContainer = self + CurrentRow.append(element) + if element.Key is not None: + self.UseDictionary = True + # ------------------------- Append the row to list of Rows ------------------------- # + self.Rows.append(CurrentRow) + + def Layout(self, rows): + for row in rows: + self.AddRow(*row) + + def _GetElementAtLocation(self, location): + (row_num, col_num) = location + row = self.Rows[row_num] + element = row[col_num] + return element + + def Update(self, visible=None): + super().Update(self.QT_QGroupBox, visible=visible) + + add_row = AddRow + layout = Layout + update = Update + + +# ---------------------------------------------------------------------- # +# Separator # +# ---------------------------------------------------------------------- # +class VerticalSeparator(Element): + def __init__(self, pad=None): + """ + VerticalSeperator - A separator that spans only 1 row in a vertical fashion + :param pad: + """ + self.Orientation = 'vertical' # for now only vertical works + + super().__init__(ELEM_TYPE_SEPARATOR, pad=pad) + + + + +VSeperator = VerticalSeparator +VSeparator = VerticalSeparator +VSep = VerticalSeparator + + +# ---------------------------------------------------------------------- # +# Separator # +# ---------------------------------------------------------------------- # +class HorizontalSeparator(Element): + def __init__(self, pad=None, size_px=(None,None)): + """ + VerticalSeperator - A separator that spans only 1 row in a vertical fashion + :param pad: + """ + self.Orientation = 'horizontal' # for now only vertical works + + super().__init__(ELEM_TYPE_SEPARATOR, pad=pad) + + + +HSeperator = HorizontalSeparator +HSep = HorizontalSeparator + + + +# ---------------------------------------------------------------------- # +# Tab # +# ---------------------------------------------------------------------- # +class Tab(Element): + def __init__(self, title, layout, title_color=None, element_justification='float', background_color=None, font=None, pad=None, disabled=False, + border_width=None, key=None, k=None, tooltip=None, visible=True, metadata=None): + """ + :param title: text to show on the tab + :type title: (str) + :param layout: The element layout that will be shown in the tab + :type layout: List[List[Element]] + :param title_color: color of the tab text (note not currently working on tkinter) + :type title_color: (str) + :param element_justification: All elements inside the Tab will have this justification 'left', 'right', 'center' are valid values + :type element_justification: (str) + :param background_color: color of background of the entire layout + :type background_color: (str) + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param pad: Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom)) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) + :param disabled: If True button will be created disabled + :type disabled: (bool) + :param border_width: width of border around element in pixels + :type border_width: (int) + :param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window + :type key: (Any) + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: Union[str, int, tuple, object] + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param visible: set visibility state of the element + :type visible: (bool) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + key = key if key is not None else k + self.UseDictionary = False + self.ReturnValues = None + self.ReturnValuesList = [] + self.ReturnValuesDictionary = {} + self.DictionaryKeyCounter = 0 + self.ParentWindow = None + self.Rows = [] + self.TKFrame = None + self.Title = title + self.BorderWidth = border_width + self.Disabled = disabled + self.ParentTabGroup = None # type: TabGroup + self.TabID = None + self.ElementJustification = element_justification + self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR + self.Widget = self.QT_QWidget = None # type: QWidget + + + + self.Layout(layout) + + super().__init__(ELEM_TYPE_TAB, background_color=background_color, text_color=title_color, font=font, pad=pad, + key=key, tooltip=tooltip, visible=visible, metadata=metadata) + return + + def AddRow(self, *args): + """ Parms are a variable number of Elements """ + NumRows = len(self.Rows) # number of existing rows is our row number + CurrentRowNumber = NumRows # this row's number + CurrentRow = [] # start with a blank row and build up + # ------------------------- Add the elements to a row ------------------------- # + for i, element in enumerate(args): # Loop through list of elements and add them to the row + element.Position = (CurrentRowNumber, i) + element.ParentContainer = self + CurrentRow.append(element) + if element.Key is not None: + self.UseDictionary = True + # ------------------------- Append the row to list of Rows ------------------------- # + self.Rows.append(CurrentRow) + + def Layout(self, rows): + for row in rows: + self.AddRow(*row) + return self + + def Update(self, disabled=None, visible=None): # TODO Disable / enable of tabs is not complete + if disabled is None: + return + self.Disabled = disabled + # state = 'disabled' if disabled is True else 'normal' + # self.ParentNotebook.tab(self.TabID, state=state) + super().Update(self.QT_QWidget, visible=visible) + + return self + + def _GetElementAtLocation(self, location): + (row_num, col_num) = location + row = self.Rows[row_num] + element = row[col_num] + return element + + + def Select(self): + """ + Selects this tab. Mimics user clicking on this tab. Must have called window.Finalize / Read first! + """ + try: + index = self.ParentTabGroup.TabList.index(self) + self.ParentTabGroup.QT_QTabWidget.setCurrentIndex(index) + except: + print('** EXCEPTION while trying to Select tab with key =', self.Key) + + add_row = AddRow + layout = Layout + select = Select + update = Update + +# ---------------------------------------------------------------------- # +# TabGroup # +# ---------------------------------------------------------------------- # +class TabGroup(Element): + def __init__(self, layout, tab_location=None, title_color=None, selected_title_color=None, background_color=None, + font=None, change_submits=False, enable_events=False, pad=None, border_width=None, theme=None, key=None, k=None, tooltip=None, visible=True, metadata=None): + """ + :param layout: Layout of Tabs. Different than normal layouts. ALL Tabs should be on first row + :type layout: List[List[Tab]] + :param tab_location: location that tabs will be displayed. Choices are left, right, top, bottom, lefttop, leftbottom, righttop, rightbottom, bottomleft, bottomright, topleft, topright + :type tab_location: (str) + :param title_color: color of text on tabs + :type title_color: (str) + :param selected_title_color: color of tab text when it is selected + :type selected_title_color: (str) + :param background_color: color of background area that tabs are located on + :type background_color: (str) + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param change_submits: * DEPRICATED DO NOT USE. Use `enable_events` instead + :type change_submits: (bool) + :param enable_events: If True then switching tabs will generate an Event + :type enable_events: (bool) + :param pad: Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom)) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) + :param border_width: width of border around element in pixels + :type border_width: (int) + :param theme: DEPRICATED - You can only specify themes using set options or when window is created. It's not possible to do it on an element basis + :type theme: (enum) + :param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window + :type key: (Any) + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: Union[str, int, tuple, object] + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param visible: set visibility state of the element + :type visible: (bool) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + key = key if key is not None else k + self.UseDictionary = False + self.ReturnValues = None + self.ReturnValuesList = [] + self.ReturnValuesDictionary = {} + self.DictionaryKeyCounter = 0 + self.ParentWindow = None + self.SelectedTitleColor = selected_title_color + self.Rows = [] + self.TKNotebook = None + self.TabCount = 0 + self.BorderWidth = border_width + self.Theme = theme + self.BackgroundColor = background_color if background_color is not None else COLOR_SYSTEM_DEFAULT + self.ChangeSubmits = change_submits or enable_events + self.TabLocation = tab_location + self.TabList = [] # type: List[Tab] + self.Widget = self.QT_QTabWidget = None # type: QTabWidget + self.ElementJustification = 'float' # not actually used, but needed for packer to work + self.Layout(layout) + + super().__init__(ELEM_TYPE_TAB_GROUP, background_color=self.BackgroundColor, text_color=title_color, font=font, + pad=pad, key=key, tooltip=tooltip, visible=visible, metadata=metadata) + return + + def AddRow(self, *args): + """ Parms are a variable number of Elements """ + NumRows = len(self.Rows) # number of existing rows is our row number + CurrentRowNumber = NumRows # this row's number + CurrentRow = [] # start with a blank row and build up + # ------------------------- Add the elements to a row ------------------------- # + for i, element in enumerate(args): # Loop through list of elements and add them to the row + element.Position = (CurrentRowNumber, i) + element.ParentContainer = self + element.ParentTabGroup = self + CurrentRow.append(element) + if element.Key is not None: + self.UseDictionary = True + self.TabList.append(element) + # ------------------------- Append the row to list of Rows ------------------------- # + self.Rows.append(CurrentRow) + + def Layout(self, rows): + for row in rows: + self.AddRow(*row) + + def _GetElementAtLocation(self, location): + (row_num, col_num) = location + row = self.Rows[row_num] + element = row[col_num] + return element + + def FindKeyFromTabName(self, tab_name): + for row in self.Rows: + for element in row: + if element.Title == tab_name: + return element.Key + return None + + + def Update(self, visible=None): + super().Update(self.QT_QTabWidget, visible=visible) + return self + + def QtCallbackStateChanged(self, state): + if self.ChangeSubmits: + _element_callback_quit_mainloop(self) + + def Get(self): + """ + Returns the current value for the Tab Group, which will be the currently selected tab's KEY or the text on + the tab if no key is defined. Returns None if an error occurs. + Note that this is exactly the same data that would be returned from a call to Window.Read. Are you sure you + are using this method correctly? + + :return: Union[Any, None] The key of the currently selected tab or the tab's text if it has no key + """ + value = None + try: + cur_index = self.QT_QTabWidget.currentIndex() + tab_element = self.TabList[cur_index] + value = tab_element.Key + except: + value = None + return value + + add_row = AddRow + find_key_from_tab_name = FindKeyFromTabName + get = Get + update = Update + + +# ---------------------------------------------------------------------- # +# Slider # +# ---------------------------------------------------------------------- # +class Slider(Element): + def __init__(self, range=(None, None), default_value=None, resolution=None, tick_interval=None, orientation=None, + border_width=None, relief=None, change_submits=False, enable_events=False, disabled=False, size=(None, None), font=None, + background_color=None, text_color=None, key=None, k=None, pad=None, tooltip=None, visible=True, size_px=(None,None), metadata=None): + """ + :param range: slider's range (min value, max value) + :type range: Union[Tuple[int, int], Tuple[float, float]] + :param default_value: starting value for the slider + :type default_value: Union[int, float] + :param resolution: the smallest amount the slider can be moved + :type resolution: Union[int, float] + :param tick_interval: how often a visible tick should be shown next to slider + :type tick_interval: Union[int, float] + :param orientation: 'horizontal' or 'vertical' ('h' or 'v' also work) + :type orientation: (str) + :param border_width: width of border around element in pixels + :type border_width: (int) + :param relief: relief style. RELIEF_RAISED RELIEF_SUNKEN RELIEF_FLAT RELIEF_RIDGE RELIEF_GROOVE RELIEF_SOLID + :type relief: (enum) + :param change_submits: * DEPRICATED DO NOT USE. Use `enable_events` instead + :type change_submits: (bool) + :param enable_events: If True then moving the slider will generate an Event + :type enable_events: (bool) + :param disabled: set disable state for element + :type disabled: (bool) + :param size: (w=characters-wide, h=rows-high) + :type size: Tuple[int, int] + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param background_color: color of slider's background + :type background_color: (str) + :param text_color: color of the slider's text + :type text_color: (str) + :param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window + :type key: (Any) + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: Union[str, int, tuple, object] + :param pad: Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom)) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param visible: set visibility state of the element + :type visible: (bool) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + key = key if key is not None else k + self.TKScale = None + self.Range = (1, 10) if range == (None, None) else range + self.DefaultValue = self.Range[0] if default_value is None else default_value + self.Orientation = orientation if orientation else DEFAULT_SLIDER_ORIENTATION + self.BorderWidth = border_width if border_width else DEFAULT_SLIDER_BORDER_WIDTH + self.Relief = relief if relief else DEFAULT_SLIDER_RELIEF + self.Resolution = 1 if resolution is None else resolution + self.ChangeSubmits = change_submits or enable_events + self.Disabled = disabled + self.TickInterval = tick_interval if tick_interval is not None else self.Range[1]//10 + temp_size = size + if temp_size == (None, None): + temp_size = (150, 30) if self.Orientation.startswith('h') else (30, 150) + elif size[0] is not None and size[0] < 100: + temp_size = size[0]*10, size[1]*3 + self.Widget = self.QT_Slider = None # type:QSlider + + super().__init__(ELEM_TYPE_INPUT_SLIDER, size=temp_size, font=font, background_color=background_color, + text_color=text_color, key=key, pad=pad, tooltip=tooltip, visible=visible, size_px=size_px, metadata=metadata) + return + + + def _QtCallbackValueChanged(self, value): + if not self.ChangeSubmits: + return + _element_callback_quit_mainloop(self) + + def Update(self, value=None, range=(None, None), disabled=None, visible=None): + if value is not None: + self.QT_Slider.setValue(int(value)) + self.DefaultValue = value + if disabled == True: + self.QT_Slider.setDisabled(True) + elif disabled == False: + self.QT_Slider.setDisabled(False) + if range != (None, None): + self.Range = range + self.QT_Slider.setMinimum(range[0]) + self.QT_Slider.setMaximum(range[1]) + super().Update(self.QT_Slider, visible=visible) + + + update = Update + + + +# ---------------------------------------------------------------------- # +# Dial # +# ---------------------------------------------------------------------- # +class Dial(Element): + def __init__(self, range=(None, None), default_value=None, resolution=None, tick_interval=None, orientation=None, + border_width=None, relief=None, change_submits=False, enable_events=False, disabled=False, size=(None, None), font=None, + background_color=None, text_color=None, key=None, k=None, pad=None, tooltip=None, visible=True, size_px=(None,None), metadata=None): + """ + :param range: slider's range (min value, max value) + :type range: Union[Tuple[int, int], Tuple[float, float]] + :param default_value: Choice to be displayed as initial value. Must match one of values variable contents + :type default_value: (Any) + :param resolution: the smallest amount the slider can be moved + :type resolution: Union[int, float] + :param tick_interval: how often a visible tick should be shown next to slider + :type tick_interval: Union[int, float] + :param orientation: 'horizontal' or 'vertical' ('h' or 'v' also work) + :type orientation: (str) + :param border_width: width of border around button in pixels + :type border_width: (int) + :param relief: relief style. RELIEF_RAISED RELIEF_SUNKEN RELIEF_FLAT RELIEF_RIDGE RELIEF_GROOVE RELIEF_SOLID + :type relief: (enum) + :param change_submits: DO NOT USE. Only listed for backwards compat - Use enable_events instead + :type change_submits: (bool) + :param enable_events: Turns on the element specific events. If this button is a target, should it generate an event when filled in + :type enable_events: (bool) + :param disabled: set disable state for element + :type disabled: (bool) + :param size: (width, height) of the button in characters wide, rows high + :type size: Tuple[int, int] + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param background_color: color of slider's background + :type background_color: (str) + :param text_color: color of the element's text + :type text_color: (str) + :param key: Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element + :type key: (Any) + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: Union[str, int, tuple, object] + :param pad: Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom)) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param visible: set visibility state of the element + :type visible: (bool) + :param size_px: size in pixels (width, height). Will override the size parameter + :type size_px: Tupple[int, int] (width, height) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + key = key if key is not None else k + self.TKScale = None + self.Range = (1, 10) if range == (None, None) else range + self.DefaultValue = self.Range[0] if default_value is None else default_value + self.Orientation = orientation if orientation else DEFAULT_SLIDER_ORIENTATION + self.BorderWidth = border_width if border_width else DEFAULT_SLIDER_BORDER_WIDTH + self.Relief = relief if relief else DEFAULT_SLIDER_RELIEF + self.Resolution = 1 if resolution is None else resolution + self.ChangeSubmits = change_submits or enable_events + self.Disabled = disabled + self.TickInterval = tick_interval + temp_size = size + if temp_size == (None, None): + temp_size = (20, 20) if self.Orientation.startswith('h') else (8, 20) + self.Widget = self.QT_Dial = None # type: QDial + + super().__init__(ELEM_TYPE_INPUT_DIAL, size=temp_size, font=font, background_color=background_color, + text_color=text_color, key=key, pad=pad, tooltip=tooltip, visible=visible, size_px=size_px, metadata=metadata) + return + + + def Update(self, value=None, range=(None, None), disabled=None, visible=None): + if value is not None: # TODO clearly not done! + pass + self.DefaultValue = value + if disabled == True: + pass + elif disabled == False: + pass + super().Update(self.QT_Dial, visible=visible) + + + def _QtCallbackValueChanged(self, value): + if not self.ChangeSubmits: + return + _element_callback_quit_mainloop(self) + + update = Update + +# ---------------------------------------------------------------------- # +# Stretch # +# ---------------------------------------------------------------------- # +class Stretch(Element): + def __init__(self, size=(None, None), font=None, background_color=None, text_color=None, key=None, k=None, pad=None, tooltip=None): + """ + :param size: (width, height) of the button in characters wide, rows high + :type size: Tuple[int, int] + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param background_color: color of slider's background + :type background_color: (str) + :param text_color: color of the element's text + :type text_color: (str) + :param key: Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element + :type key: (Any) + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: Union[str, int, tuple, object] + :param pad: Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom)) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + """ + key = key if key is not None else k + self.Widget = None # type: Stretch + super().__init__(ELEM_TYPE_STRETCH, size=size, font=font, background_color=background_color, + text_color=text_color, key=key, pad=pad, tooltip=tooltip) + return + + + + +# ---------------------------------------------------------------------- # +# Column # +# ---------------------------------------------------------------------- # +class Column(Element): + def __init__(self, layout, background_color=None, element_justification='float', size=(None, None), pad=None, scrollable=False, key=None, k=None, visible=True, metadata=None): + + """ + :param layout: Layout that will be shown in the Column container + :type layout: List[List[Element]] + :param background_color: color of background of entire Column + :type background_color: (str) + :param element_justification: All elements inside the Column will have this justification 'left', 'right', 'center' are valid values + :type element_justification: (str) + :param size: (width, height) size in pixels (doesn't work quite right, sometimes only 1 dimension is set by tkinter + :type size: Tuple[int, int] + :param pad: Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom)) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) + :param scrollable: if True then scrollbars will be added to the column + :type scrollable: (bool) + :param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window + :type key: (Any) + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: Union[str, int, tuple, object] + :param visible: set visibility state of the element + :type visible: (bool) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + key = key if key is not None else k + self.UseDictionary = False + self.ReturnValues = None + self.ReturnValuesList = [] + self.ReturnValuesDictionary = {} + self.DictionaryKeyCounter = 0 + self.ParentWindow = None + self.Rows = [] + self.TKFrame = None + self.Scrollable = scrollable + # self.ImageFilename = image_filename + # self.ImageData = image_data + # self.ImageSize = image_size + # self.ImageSubsample = image_subsample + bg = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR + self.ElementJustification = element_justification + self.Widget = self.QT_QGroupBox = None # type: QGroupBox + self.vbox_layout = None # type: QVBoxLayout + self.Layout(layout) + + super().__init__(ELEM_TYPE_COLUMN, background_color=bg, size=size, pad=pad, key=key, visible=visible, metadata=metadata) + return + + def AddRow(self, *args): + ''' Parms are a variable number of Elements ''' + NumRows = len(self.Rows) # number of existing rows is our row number + CurrentRowNumber = NumRows # this row's number + CurrentRow = [] # start with a blank row and build up + # ------------------------- Add the elements to a row ------------------------- # + for i, element in enumerate(args): # Loop through list of elements and add them to the row + element.Position = (CurrentRowNumber, i) + element.ParentContainer = self + CurrentRow.append(element) + if element.Key is not None: + self.UseDictionary = True + # ------------------------- Append the row to list of Rows ------------------------- # + self.Rows.append(CurrentRow) + + def Layout(self, rows): + for row in rows: + self.AddRow(*row) + + def _GetElementAtLocation(self, location): + (row_num, col_num) = location + row = self.Rows[row_num] + element = row[col_num] + return element + + + def Update(self, visible=None): + + super().Update(self.QT_QGroupBox, visible=visible) + + add_row = AddRow + layout = Layout + update = Update + +Col = Column + +# ---------------------------------------------------------------------- # +# Menu # +# ---------------------------------------------------------------------- # +class Menu(Element): + def __init__(self, menu_definition, background_color=None, size=(None, None), tearoff=False, pad=None, key=None, k=None, visible=True, metadata=None): + """ + :param menu_definition: a menu definition (in menu definition format) + :type menu_definition: List[List[Tuple[str, List[str]]] + :param background_color: color of the background + :type background_color: (str) + :param size: Not used in the tkinter port + :type size: Tuple[int, int] + :param tearoff: if True, then can tear the menu off from the window ans use as a floating window. Very cool effect + :type tearoff: (bool) + :param pad: Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom)) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) + :param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window + :type key: (Any) + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: Union[str, int, tuple, object] + :param visible: set visibility state of the element + :type visible: (bool) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + key = key if key is not None else k + self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR + self.MenuItemTextColor = theme_text_color() + self.MenuItemBackgroundColor = theme_background_color() + self.MenuDefinition = menu_definition + self.TKMenu = None + self.Tearoff = tearoff + self.IsButtonMenu = False + self.MenuItemChosen = None + self.Widget = self.QT_QMenuBar = None # type: QMenuBar + + super().__init__(ELEM_TYPE_MENUBAR, background_color=background_color, size=size, pad=pad, key=key, visible=visible, metadata=metadata) + + + def _QT_MenuItemChosenCallback(self, item_chosen): + # print('IN MENU ITEM CALLBACK', item_chosen) + self.MenuItemChosen = item_chosen.replace('&','') + _element_callback_quit_mainloop(self) + # self.ParentForm.LastButtonClicked = item_chosen + # self.ParentForm.FormRemainedOpen = True + # if self.ParentForm.CurrentlyRunningMainloop: + # pass # TODO # kick the users out of the mainloop + + def Update(self, menu_definition=None, visible=None): + if menu_definition is not None: + menu_def = menu_definition + self.MenuDefinition = menu_def + self.QT_QMenuBar = QMenuBar(self.ParentForm.QT_QMainWindow) + + for menu_entry in menu_def: + # print(f'Adding a Menubar ENTRY {menu_entry}') + baritem = QMenu(self.QT_QMenuBar) + if menu_entry[0][0] == MENU_DISABLED_CHARACTER: + baritem.setDisabled(True) + baritem.setTitle(menu_entry[0][1:]) + else: + baritem.setTitle(menu_entry[0]) + self.QT_QMenuBar.addAction(baritem.menuAction()) + AddMenuItem(baritem, menu_entry[1], self) + + self.ParentForm.QT_QMainWindow.setMenuBar(self.QT_QMenuBar) + super().Update(self.QT_QMenuBar, visible=visible) + + update = Update + +# ---------------------------------------------------------------------- # +# Table # +# ---------------------------------------------------------------------- # +class Table(Element): + def __init__(self, values, headings=None, visible_column_map=None, col_widths=None, def_col_width=10, + auto_size_columns=True, max_col_width=20, select_mode=None, display_row_numbers=False, num_rows=None, + font=None, justification='right',header_text_color=None, header_background_color=None, header_font=None, text_color=None, background_color=None, alternating_row_color=None, + size=(None, None), change_submits=False, enable_events=False, bind_return_key=False, pad=None, key=None, k=None, tooltip=None, visible=True, size_px=(None,None), metadata=None): + """ + :param values: ??? + :type values: List[List[Union[str, int, float]]] + :param headings: The headings to show on the top line + :type headings: Union[List[str], Tuple[str]] + :param visible_column_map: One entry for each column. False indicates the column is not shown + :type visible_column_map: List[bool] + :param col_widths: Number of characters that each column will occupy + :type col_widths: List[int] + :param def_col_width: Default column width in characters + :type def_col_width: (int) + :param auto_size_columns: if True columns will be sized automatically + :type auto_size_columns: (bool) + :param max_col_width: Maximum width for all columns in characters + :type max_col_width: (int) + :param select_mode: Select Mode. Valid values start with "TABLE_SELECT_MODE_". Valid values are: TABLE_SELECT_MODE_NONE TABLE_SELECT_MODE_BROWSE TABLE_SELECT_MODE_EXTENDED + :type select_mode: (enum) + :param display_row_numbers: if True, the first column of the table will be the row # + :type display_row_numbers: (bool) + :param num_rows: The number of rows of the table to display at a time + :type num_rows: (int) + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param justification: 'left', 'right', 'center' are valid choices + :type justification: (str) + :param header_text_color: sets the text color for the header + :type header_text_color: (str) + :param header_background_color: sets the background color for the header + :type header_background_color: (str) + :param header_font: specifies the font family, size, etc + :type header_font: Union[str, Tuple[str, int]] + :param text_color: color of the text + :type text_color: (str) + :param background_color: color of background + :type background_color: (str) + :param alternating_row_color: if set then every other row will have this color in the background. + :type alternating_row_color: (str) + :param size: DO NOT USE! Use num_rows instead + :type size: Tuple[int, int] + :param change_submits: DO NOT USE. Only listed for backwards compat - Use enable_events instead + :type change_submits: (bool) + :param enable_events: Turns on the element specific events. Table events happen when row is clicked + :type enable_events: (bool) + :param bind_return_key: if True, pressing return key will cause event coming from Table, ALSO a left button double click will generate an event if this parameter is True + :type bind_return_key: (bool) + :param pad: Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom)) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) + :param key: Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element + :type key: (Any) + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: Union[str, int, tuple, object] + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param visible: set visibility state of the element + :type visible: (bool) + :param size_px: size in pixels (width, height). Will override the size parameter + :type size_px: Tupple[int, int] (width, height) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + key = key if key is not None else k + self.Values = values + self.ColumnHeadings = headings + self.ColumnsToDisplay = visible_column_map + self.ColumnWidths = col_widths + self.MaxColumnWidth = max_col_width + self.DefaultColumnWidth = def_col_width + self.AutoSizeColumns = auto_size_columns + self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR + self.TextColor = text_color + self.HeaderTextColor = header_text_color if header_text_color is not None else theme_input_text_color() + self.HeaderBackgroundColor = header_background_color if header_background_color is not None else theme_input_background_color() + self.HeaderFont = header_font + self.Justification = justification + self.InitialState = None + self.SelectMode = select_mode + self.DisplayRowNumbers = display_row_numbers + self.NumRows = num_rows if num_rows is not None else size[1] + self.TKTreeview = None + self.AlternatingRowColor = alternating_row_color + self.SelectedRows = [] + self.ChangeSubmits = change_submits or enable_events + self.BindReturnKey = bind_return_key + self.Widget = self.QT_TableWidget = None # type: QTableWidget + + super().__init__(ELEM_TYPE_TABLE, text_color=text_color, background_color=background_color, font=font, + size=size, pad=pad, key=key, tooltip=tooltip, visible=visible, size_px=size_px, metadata=metadata) + return + + + def _QtCallbackCellActivated(self, value=None): + # print('CELL ACTIVATED ', value) + # first, get the results table built + # modify the Results table in the parent FlexForm object + if not self.ChangeSubmits: + return + _element_callback_quit_mainloop(self) + + + def _QtCallbackVerticalHeader(self, value): + print('Vertical Header value ', value) + + + def Update(self, values=None, num_rows=None, visible=None): + if values is not None: + self.Values = values + self.SelectedRows = [] + self.QT_TableWidget.clearContents() + if len(values) != 0: + self.QT_TableWidget.setRowCount(len(self.Values)) + self.QT_TableWidget.setColumnCount(len(self.Values[0])) + for rownum, rows in enumerate(self.Values): + # self.QT_TableWidget.insertRow(rownum) + for colnum, columns in enumerate(rows): + self.QT_TableWidget.setItem(rownum, colnum, QTableWidgetItem(self.Values[rownum][colnum])) + if num_rows is not None: + self.QT_TableWidget.setFixedHeight(num_rows * 35 + 25) # convert num rows into pixels...crude but effective + + super().Update(self.QT_TableWidget, visible=visible) + + + def Get(self): + num_rows = self.QT_TableWidget.rowCount() + num_cols = self.QT_TableWidget.columnCount() + table = [] + for row in range(num_rows): + row_list = [] + for col in range(num_cols): + item = self.QT_TableWidget.item(row, col).text() + row_list.append(item) + table.append(row_list) + + return table + + def _treeview_selected(self, event): + if self.ChangeSubmits: + MyForm = self.ParentForm + if self.Key is not None: + self.ParentForm.LastButtonClicked = self.Key + else: + self.ParentForm.LastButtonClicked = '' + self.ParentForm.FormRemainedOpen = True + if self.ParentForm.CurrentlyRunningMainloop: + pass # TODO Quit mainloop + + + def treeview_double_click(self, event): + if self.BindReturnKey: + MyForm = self.ParentForm + if self.Key is not None: + self.ParentForm.LastButtonClicked = self.Key + else: + self.ParentForm.LastButtonClicked = '' + self.ParentForm.FormRemainedOpen = True + if self.ParentForm.CurrentlyRunningMainloop: + pass # TODO Quit mainloop + + + class QTTableWidget(QTableWidget): + def __init__(self, enable_key_events, window): + self.KeyEventsEnabled = enable_key_events + self.Window = window + super().__init__() + + def eventFilter(self, widget, event): + # print(event.type()) + if event.type() == QEvent.MouseButtonPress and self.Window.GrabAnywhere: + self.mouse_offset = event.pos() + if event.type() == QEvent.MouseMove and self.Window.GrabAnywhere: + x = event.globalX() + y = event.globalY() + x_w = self.mouse_offset.x() + y_w = self.mouse_offset.y() + self.move(x - x_w, y - y_w) + + if event.type() == QEvent.KeyRelease and self.KeyEventsEnabled: + # print("got key event") + key = event.key() + try: + self.Window.LastButtonClicked = chr(key).lower() + except: + self.Window.LastButtonClicked = "special %s" % key + self.Window.FormRemainedOpen = True + if self.Window.CurrentlyRunningMainloop: + self.Window.QTApplication.exit() + return QWidget.eventFilter(self, widget, event) + + get = Get + update = Update + +# ---------------------------------------------------------------------- # +# Tree # +# ---------------------------------------------------------------------- # +class Tree(Element): + def __init__(self, data=None, headings=None, visible_column_map=None, col_widths=None, col0_width=10, + def_col_width=10, auto_size_columns=True, max_col_width=20, select_mode=None, show_expanded=False, + change_submits=False, enable_events=False, font=None, size=(200,600), + justification='right', header_text_color=None, header_background_color=None, header_font=None, text_color=None, background_color=None, num_rows=None, pad=None, key=None, k=None, + tooltip=None, visible=True, size_px=(None,None), metadata=None): + """ + :param data: The data represented using a PySimpleGUI provided TreeData class + :type data: (TreeData) + :param headings: List of individual headings for each column + :type headings: List[str] + :param visible_column_map: Determines if a column should be visible. If left empty, all columns will be shown + :type visible_column_map: List[bool] + :param col_widths: List of column widths so that individual column widths can be controlled + :type col_widths: List[int] + :param col0_width: Size of Column 0 which is where the row numbers will be optionally shown + :type col0_width: (int) + :param def_col_width: default column width + :type def_col_width: (int) + :param auto_size_columns: if True, the size of a column is determined using the contents of the column + :type auto_size_columns: (bool) + :param max_col_width: the maximum size a column can be + :type max_col_width: (int) + :param select_mode: Use same values as found on Table Element. Valid values include: TABLE_SELECT_MODE_NONE TABLE_SELECT_MODE_BROWSE TABLE_SELECT_MODE_EXTENDED + :type select_mode: (enum) + :param show_expanded: if True then the tree will be initially shown with all nodes completely expanded + :type show_expanded: (bool) + :param change_submits: DO NOT USE. Only listed for backwards compat - Use enable_events instead + :type change_submits: (bool) + :param enable_events: Turns on the element specific events. Tree events happen when row is clicked + :type enable_events: (bool) + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param size: ??? + :type size: ??? + :param justification: 'left', 'right', 'center' are valid choices + :type justification: (str) + :param header_text_color: sets the text color for the header + :type header_text_color: (str) + :param header_background_color: sets the background color for the header + :type header_background_color: (str) + :param header_font: specifies the font family, size, etc + :type header_font: Union[str, Tuple[str, int]] + :param text_color: color of the text + :type text_color: (str) + :param background_color: color of background + :type background_color: (str) + :param num_rows: The number of rows of the table to display at a time + :type num_rows: (int) + :param pad: Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom)) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) + :param key: Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element + :type key: (Any) + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: Union[str, int, tuple, object] + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param visible: set visibility state of the element + :type visible: (bool) + :param size_px: size in pixels (width, height). Will override the size parameter + :type size_px: Tupple[int, int] (width, height) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + key = key if key is not None else k + self.TreeData = data + self.ColumnHeadings = headings + self.ColumnsToDisplay = visible_column_map + self.ColumnWidths = col_widths + self.MaxColumnWidth = max_col_width + self.DefaultColumnWidth = def_col_width + self.AutoSizeColumns = auto_size_columns + self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR + self.TextColor = text_color + self.HeaderTextColor = header_text_color if header_text_color is not None else theme_input_text_color() + self.HeaderBackgroundColor = header_background_color if header_background_color is not None else theme_input_background_color() + self.HeaderFont = header_font + self.Justification = justification + self.InitialState = None + self.SelectMode = select_mode + self.ShowExpanded = show_expanded + self.NumRows = num_rows + self.Col0Width = col0_width + self.TKTreeview = None + self.SelectedRows = [] + self.ChangeSubmits = change_submits or enable_events + self.Size = size + self.Widget = self.QT_QTreeWidget = None # type: QTreeWidget + super().__init__(ELEM_TYPE_TREE, text_color=text_color, background_color=background_color, font=font, pad=pad, + key=key, tooltip=tooltip, size=size, visible=visible, size_px=size_px, metadata=metadata) + return + + def _treeview_selected(self, event): + selections = 000000 + self.SelectedRows = [x for x in selections] + # print('Got selection') + if self.ChangeSubmits: + _element_callback_quit_mainloop(self) + + def _QtCallbackCellActivated(self, value=None): + # print('CELL ACTIVATED ', value) + # first, get the results table built + # modify the Results table in the parent FlexForm object + if not self.ChangeSubmits: + return + _element_callback_quit_mainloop(self) + + # if self.ChangeSubmits: + # MyForm = self.ParentForm + # if self.Key is not None: + # self.ParentForm.LastButtonClicked = self.Key + # else: + # self.ParentForm.LastButtonClicked = '' + # self.ParentForm.FormRemainedOpen = True + # if self.ParentForm.CurrentlyRunningMainloop: + # self.ParentForm.TKroot.quit() + + + def Update(self, values=None, key=None, value=None, text=None, visible=None): + if values is not None: + self.TreeData = values + self.SelectedRows = [] + # self.QT_QTreeWidget = QTreeWidget() + TreeWidgetItems = QTreeWidgetItemIterator(self.QT_QTreeWidget) + + for item in TreeWidgetItems: + item2 = item.value() + self.QT_QTreeWidget.removeItemWidget(item2, 0) + + # def add_treeview_data(node, widget): + # # print(f'Inserting {node.key} under parent {node.parent}') + # child = QTreeWidgetItem(widget) + # if node.key != '': + # child.setText(0, str(node.text)) + # # child.setData(0,0,node.values) + # if node.icon is not None: + # qicon = QIcon(node.icon) + # child.setIcon(0, qicon) + # for node in node.children: + # add_treeview_data(node, child) + + + def add_treeview_data(node, widget): + # print(f'Inserting {node.key} under parent {node.parent}') + if node != self.TreeData.root_node: + child = QTreeWidgetItem(widget) + child.setText(0, str(node.text)) + else: + child = widget + # if node.key != '': + # child.setData(0,0,node.values) + if type(node.icon) is bytes: + ba = QtCore.QByteArray.fromBase64(node.icon) + pixmap = QtGui.QPixmap() + pixmap.loadFromData(ba) + qicon = QIcon(pixmap) + child.setIcon(0, qicon) + elif node.icon is not None: + qicon = QIcon(node.icon) + child.setIcon(0, qicon) + for node in node.children: + add_treeview_data(node, child) + return + + add_treeview_data(self.TreeData.root_node, self.QT_QTreeWidget) + + if key is not None: + pass + super().Update(self.QT_QTreeWidget, visible=visible) + + return self + + update = Update + +class TreeData(object): + class Node(object): + def __init__(self, parent, key, text, values, icon=None): + self.parent = parent + self.children = [] + self.key = key + self.text = text + self.values = values + self.icon = icon + + def _Add(self, node): + self.children.append(node) + + def __init__(self): + self.tree_dict = {} + self.root_node = self.Node("", "", 'root', [], None) + self.tree_dict[""] = self.root_node + + def _AddNode(self, key, node): + self.tree_dict[key] = node + + def Insert(self, parent, key, text, values, icon=None): + node = self.Node(parent, key, text, values, icon) + self.tree_dict[key] = node + parent_node = self.tree_dict[parent] + parent_node._Add(node) + + def __repr__(self): + return self._NodeStr(self.root_node, 1) + + def _NodeStr(self, node, level): + return '\n'.join( + [str(node.key) + ' : ' + str(node.text)] + + [' ' * 4 * level + self._NodeStr(child, level + 1) for child in node.children]) + + insert = Insert + + +# ---------------------------------------------------------------------- # +# Error Element # +# ---------------------------------------------------------------------- # +class ErrorElement(Element): + def __init__(self, key=None, k=None): + """ + Error Element + :param key: key for uniquely identify this element (for window.FindElement) + :type key: (Any) + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: Union[str, int, tuple, object] + """ + self.Key = key + self.Widget = None + + super().__init__(ELEM_TYPE_ERROR, key=key) + return + + def Update(self, *args, **kwargs): + PopupError('Keyword error in Update', + 'You need to stop this madness and check your spelling', + 'Bad key = {}'.format(self.Key), + 'Your bad line of code may resemble this:', + 'window.FindElement("{}")'.format(self.Key)) + return self + + def Get(self): + return 'This is NOT a valid Element!\nSTOP trying to do things with it or I will have to crash at some point!' + + get = Get + update = Update + + +# ---------------------------------------------------------------------- # +# Pane Element # +# ---------------------------------------------------------------------- # + +# This is for source code compatibility with tkinter version. No Qt equivalent +Pane = ErrorElement + +# ------------------------------------------------------------------------- # +# Tray CLASS # +# ------------------------------------------------------------------------- # +class SystemTray: + def __init__(self, menu=None, filename=None, data=None, data_base64=None, tooltip=None, metadata=None): + """ + SystemTray - create an icon in the system tray + :param menu: Menu definition. Example - ['UNUSED', ['My', 'Simple', '---', 'Menu', 'Exit']] + :type menu: List[List[List[str] or str]] + :param filename: filename for icon + :type filename: (str) + :param data: in-ram image for icon (same as data_base64 parm) + :type data: (bytes) + :param data_base64: base-64 data for icon + :type data_base64: (bytes) + :param tooltip: tooltip string + :type tooltip: (str) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + self.Menu = menu + self.TrayIcon = None + self.Shown = False + self.MenuItemChosen = TIMEOUT_KEY + self.LastMessage = None + self.LastTitle = None + self.metadata = metadata + + if Window.QTApplication is None: + Window.QTApplication = QApplication(sys.argv) + self.App = Window.QTApplication + self.Widget = self.QWidget = QWidget() # type: QWidget + + if filename is None and data is None and data_base64 is None: + data_base64 = DEFAULT_BASE64_ICON + qicon = None + if filename is not None: + qicon = QIcon(filename) + elif data is not None: + ba = QtCore.QByteArray.fromRawData(data) + pixmap = QtGui.QPixmap() + pixmap.loadFromData(ba) + qicon = QIcon(pixmap) + elif data_base64 is not None: + ba = QtCore.QByteArray.fromBase64(data_base64) + pixmap = QtGui.QPixmap() + pixmap.loadFromData(ba) + qicon = QIcon(pixmap) + if qicon is None: + PopupError('ERROR - Tray must have one form of Icon specified') + return + self.TrayIcon = QSystemTrayIcon(qicon) + + if self.Menu is not None: + qmenu = QMenu() + qmenu.setTitle(self.Menu[0]) + AddTrayMenuItem(qmenu, self.Menu[1], self) + self.TrayIcon.setContextMenu(qmenu) + + if tooltip is not None: + self.TrayIcon.setToolTip(str(tooltip)) + + self.TrayIcon.messageClicked.connect(self._message_clicked) + self.TrayIcon.activated.connect(self._double_clicked) + + self.TrayIcon.show() + + def _QT_MenuItemChosenCallback(self, item_chosen): + self.MenuItemChosen = item_chosen.replace('&','') + self.App.exit() # kick the users out of the mainloop + + # callback function when message is clicked + def _message_clicked(self): + self.MenuItemChosen = EVENT_SYSTEM_TRAY_MESSAGE_CLICKED + self.App.exit() + + + def _double_clicked(self, reason): + # print(reason) + if reason == QSystemTrayIcon.DoubleClick: + self.MenuItemChosen = EVENT_SYSTEM_TRAY_ICON_DOUBLE_CLICKED + self.App.exit() + if reason == QSystemTrayIcon.Trigger: + self.MenuItemChosen = EVENT_SYSTEM_TRAY_ICON_ACTIVATED + self.App.exit() + + + def Read(self, timeout=None): + """ + Reads the context menu + :param timeout: Optional. Any value other than None indicates a non-blocking read + :return: + """ + if not self.Shown: + self.Shown = True + self.TrayIcon.show() + if timeout is None: + self.App.exec_() + elif timeout == 0: + self.App.processEvents() + else: + self.timer = start_systray_read_timer(self, timeout) + self.App.exec_() + + if self.timer: + stop_timer(self.timer) + + item = self.MenuItemChosen + self.MenuItemChosen = TIMEOUT_KEY + return item + + def _timer_timeout(self): + self.App.exit() # kick the users out of the mainloop + + def Hide(self): + self.TrayIcon.hide() + + + def UnHide(self): + self.TrayIcon.show() + + + def ShowMessage(self, title, message, filename=None, data=None, data_base64=None, messageicon=None, time=10000): + """ + Shows a balloon above icon in system tray + :param title: Title shown in balloon + :param message: Message to be displayed + :param filename: Optional icon filename + :param data: Optional in-ram icon + :param data_base64: Optional base64 icon + :param time: How long to display message in milliseconds + :return: + """ + qicon = None + if filename is not None: + qicon = QIcon(filename) + elif data is not None: + ba = QtCore.QByteArray.fromRawData(data) + pixmap = QtGui.QPixmap() + pixmap.loadFromData(ba) + qicon = QIcon(pixmap) + elif data_base64 is not None: + ba = QtCore.QByteArray.fromBase64(data_base64) + pixmap = QtGui.QPixmap() + pixmap.loadFromData(ba) + qicon = QIcon(pixmap) + + if qicon is not None: + self.TrayIcon.showMessage(title, message, qicon, time) + elif messageicon is not None: + self.TrayIcon.showMessage(title, message, messageicon, time) + else: + self.TrayIcon.showMessage(title, message, QIcon(), time) + + self.LastMessage = message + self.LastTitle = title + return self + + def Close(self): + """ + + :return: + """ + self.Hide() + # Don't close app because windows could be depending on it + # self.App.quit() + + + def Update(self, menu=None, tooltip=None,filename=None, data=None, data_base64=None,): + """ + Updates the menu, tooltip or icon + :param menu: menu defintion + :param tooltip: string representing tooltip + :param filename: icon filename + :param data: icon raw image + :param data_base64: icon base 64 image + :return: + """ + # Menu + if menu is not None: + self.Menu = menu + qmenu = QMenu() + qmenu.setTitle(self.Menu[0]) + AddTrayMenuItem(qmenu, self.Menu[1], self) + self.TrayIcon.setContextMenu(qmenu) + # Tooltip + if tooltip is not None: + self.TrayIcon.setToolTip(str(tooltip)) + # Icon + qicon = None + if filename is not None: + qicon = QIcon(filename) + elif data is not None: + ba = QtCore.QByteArray.fromRawData(data) + pixmap = QtGui.QPixmap() + pixmap.loadFromData(ba) + qicon = QIcon(pixmap) + elif data_base64 is not None: + ba = QtCore.QByteArray.fromBase64(data_base64) + pixmap = QtGui.QPixmap() + pixmap.loadFromData(ba) + qicon = QIcon(pixmap) + if qicon is not None: + self.TrayIcon.setIcon(qicon) + + close = Close + hide = Hide + read = Read + show_message = ShowMessage + un_hide = UnHide + update = Update + +# ------------------------------------------------------------------------- # +# Window CLASS # +# ------------------------------------------------------------------------- # +class Window: + + NumOpenWindows = 0 + user_defined_icon = None + hidden_master_root = None + QTApplication = None + active_popups = {} + + def __init__(self, title, layout=None, default_element_size=DEFAULT_ELEMENT_SIZE, default_button_element_size=(None, None), + auto_size_text=None, auto_size_buttons=None, location=(None, None), size=(None, None), element_padding=None, margins=(None, None),button_color=None, font=None, progress_bar_color=(None, None), background_color=None, border_depth=None, auto_close=False, auto_close_duration=DEFAULT_AUTOCLOSE_TIME, icon=DEFAULT_WINDOW_ICON, force_toplevel=False, alpha_channel=1, return_keyboard_events=False, use_default_focus=True, text_justification=None, element_justification='float', no_titlebar=False, grab_anywhere=False, keep_on_top=False, resizable=True, disable_close=False, disable_minimize=False, background_image=None, finalize=False, metadata=None): + """ + :param title: The title that will be displayed in the Titlebar and on the Taskbar + :type title: (str) + :param layout: The layout for the window. Can also be specified in the Layout method + :type layout: List[List[Elements]] + :param default_element_size: size in characters (wide) and rows (high) for all elements in this window + :type default_element_size: Tuple[int, int] - (width, height) + :param default_button_element_size: (width, height) size in characters (wide) and rows (high) for all Button elements in this window + :type default_button_element_size: Tuple[int, int] + :param auto_size_text: True if Elements in Window should be sized to exactly fir the length of text + :type auto_size_text: (bool) + :param auto_size_buttons: True if Buttons in this Window should be sized to exactly fit the text on this. + :type auto_size_buttons: (bool) + :param location: (x,y) location, in pixels, to locate the upper left corner of the window on the screen. Default is to center on screen. + :type location: Tuple[int, int] + :param size: (width, height) size in pixels for this window. Normally the window is autosized to fit contents, not set to an absolute size by the user + :type size: Tuple[int, int] + :param element_padding: Default amount of padding to put around elements in window (left/right, top/bottom) or ((left, right), (top, bottom)) + :type element_padding: Tuple[int, int] or ((int, int),(int,int)) + :param margins: (left/right, top/bottom) Not yet implemented! Parameter here for potability purposes. + :type margins: Tuple[int, int] + :param button_color: Default button colors for all buttons in the window + :type button_color: Tuple[str, str] == (text color, button color) + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param progress_bar_color: (bar color, background color) Sets the default colors for all progress bars in the window + :type progress_bar_color: Tuple[str, str] + :param background_color: color of background + :type background_color: (str) + :param border_depth: Default border depth (width) for all elements in the window + :type border_depth: (int) + :param auto_close: If True, the window will automatically close itself + :type auto_close: (bool) + :param auto_close_duration: Number of seconds to wait before closing the window + :type auto_close_duration: (int) + :param icon: 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: Union[str, str] + :param force_toplevel: If True will cause this window to skip the normal use of a hidden master window + :type force_toplevel: (bool) + :param alpha_channel: Sets the opacity of the window. 0 = invisible 1 = completely visible. Values bewteen 0 & 1 will produce semi-transparent windows in SOME environments (The Raspberry Pi always has this value at 1 and cannot change. + :type alpha_channel: (float) + :param return_keyboard_events: if True key presses on the keyboard will be returned as Events from Read calls + :type return_keyboard_events: (bool) + :param use_default_focus: If True will use the default focus algorithm to set the focus to the "Correct" element + :type use_default_focus: (bool) + :param text_justification: Default text justification for all Text Elements in window + :type text_justification: Union['left', 'right', 'center'] + :param element_justification: All elements in the Window itself will have this justification 'left', 'right', 'center' are valid values + :type element_justification: (str) + :param no_titlebar: If true, no titlebar nor frame will be shown on window. This means you cannot minimize the window and it will not show up on the taskbar + :type no_titlebar: (bool) + :param grab_anywhere: If True can use mouse to click and drag to move the window. Almost every location of the window will work except input fields on some systems + :type grab_anywhere: (bool) + :param keep_on_top: If True, window will be created on top of all other windows on screen. It can be bumped down if another window created with this parm + :type keep_on_top: (bool) + :param resizable: If True, allows the user to resize the window. Note the not all Elements will change size or location when resizing. + :type resizable: (bool) + :param disable_close: If True, the X button in the top right corner of the window will no work. Use with caution and always give a way out toyour users + :type disable_close: (bool) + :param disable_minimize: if True the user won't be able to minimize window. Good for taking over entire screen and staying that way. + :type disable_minimize: (bool) + :param background_image: ??? + :type background_image: ??? + :param finalize: If True then the Finalize method will be called. Use this rather than chaining .Finalize for cleaner code + :type finalize: (bool) + :param metadata: User metadata that can be set to ANYTHING + :type metadata: (Any) + """ + self.AutoSizeText = auto_size_text if auto_size_text is not None else DEFAULT_AUTOSIZE_TEXT + self.AutoSizeButtons = auto_size_buttons if auto_size_buttons is not None else DEFAULT_AUTOSIZE_BUTTONS + self.Title = title + self.Rows = [] # a list of ELEMENTS for this row + self.DefaultElementSize = _convert_tkinter_size_to_Qt(default_element_size) + self.DefaultButtonElementSize = _convert_tkinter_size_to_Qt(default_button_element_size) if default_button_element_size != ( + None, None) else DEFAULT_BUTTON_ELEMENT_SIZE + self.Location = location + self.ButtonColor = button_color if button_color else DEFAULT_BUTTON_COLOR + self.BackgroundColor = background_color if background_color else DEFAULT_BACKGROUND_COLOR + self.ParentWindow = None + self.Font = font if font else DEFAULT_FONT + self.RadioDict = {} + self.BorderDepth = border_depth + self.WindowIcon = icon if icon is not None else Window.user_defined_icon + self.AutoClose = auto_close + self.NonBlocking = False + self.TKroot = None + self.TKrootDestroyed = False + self.CurrentlyRunningMainloop = False + self.FormRemainedOpen = False + self.TKAfterID = None + self.ProgressBarColor = progress_bar_color + self.AutoCloseDuration = auto_close_duration + self.RootNeedsDestroying = False + self.Shown = False + self.ReturnValues = None + self.ReturnValuesList = [] + self.ReturnValuesDictionary = {} + self.DictionaryKeyCounter = 0 + self.LastButtonClicked = None + self.LastButtonClickedWasRealtime = False + self.UseDictionary = False + self.UseDefaultFocus = use_default_focus + self.ReturnKeyboardEvents = return_keyboard_events + self.LastKeyboardEvent = None + self.TextJustification = text_justification + self.NoTitleBar = no_titlebar + self.GrabAnywhere = grab_anywhere + self.KeepOnTop = keep_on_top + self.ForcefTopLevel = force_toplevel + self.Resizable = resizable + self._AlphaChannel = alpha_channel + self.Timeout = None + self.TimeoutKey = '_timeout_' + self.TimerCancelled = False + self.DisableClose = disable_close + self._Hidden = False + self.QTApplication = None + self.QT_QMainWindow = None + self.QTWindow = None # type Window.QTMainWindow + self._Size=size + self.ElementPadding = element_padding or DEFAULT_ELEMENT_PADDING + self.FocusElement = None + self.BackgroundImage = background_image + self.XFound = False + self.DisableMinimize = disable_minimize + self.UniqueKeyCounter = 0 + self.metadata = metadata + self.ElementJustification = element_justification + self.AllKeysDict = {} + self.margins = margins + + if layout is not None: + self.Layout(layout) + if finalize: + self.Finalize() + + @classmethod + def IncrementOpenCount(self): + self.NumOpenWindows += 1 + # print('+++++ INCREMENTING Num Open Windows = {} ---'.format(Window.NumOpenWindows)) + + @classmethod + def DecrementOpenCount(self): + self.NumOpenWindows -= 1 * (self.NumOpenWindows != 0) # decrement if not 0 + # print('----- DECREMENTING Num Open Windows = {} ---'.format(Window.NumOpenWindows)) + + + # ------------------------- Add ONE Row to Form ------------------------- # + def AddRow(self, *args): + """ Parms are a variable number of Elements """ + NumRows = len(self.Rows) # number of existing rows is our row number + CurrentRowNumber = NumRows # this row's number + CurrentRow = [] # start with a blank row and build up + # ------------------------- Add the elements to a row ------------------------- # + for i, element in enumerate(args): # Loop through list of elements and add them to the row + if type(element) is list: + PopupError('Error creating layout', + 'Layout has a LIST instead of an ELEMENT', + 'This means you have a badly placed ]', + 'The offensive list is:', + element, + 'This list will be stripped from your layout' + ) + continue + elif callable(element) and not isinstance(element, Element): + PopupError('Error creating layout', + 'Layout has a FUNCTION instead of an ELEMENT', + 'This means you are missing () from your layout', + 'The offensive list is:', + element, + 'This item will be stripped from your layout') + continue + if element.ParentContainer is not None: + warnings.warn('*** YOU ARE ATTEMPTING TO RESUSE A LAYOUT! You must not attempt this kind of re-use ***', UserWarning) + PopupError('Error creating layout', + 'The layout specified has already been used', + 'You MUST start witha "clean", unused layout every time you create a window', + 'The offensive Element = ', + element, + 'and has a key = ', element.Key, + 'This item will be stripped from your layout') + continue + element.Position = (CurrentRowNumber, i) + element.ParentContainer = self + CurrentRow.append(element) + # ------------------------- Append the row to list of Rows ------------------------- # + self.Rows.append(CurrentRow) + + # ------------------------- Add Multiple Rows to Form ------------------------- # + def AddRows(self, rows): + for row in rows: + try: + iter(row) + except TypeError: + PopupError('Error creating layout', + 'Your row is not an iterable (e.g. a list)', + 'The offensive row = ', + row, + 'This item will be stripped from your layout') + continue + self.AddRow(*row) + + def Layout(self, rows): + self.AddRows(rows) + self._BuildKeyDict() + return self + + def LayoutAndRead(self, rows, non_blocking=False): + raise DeprecationWarning('LayoutAndRead is no longer supported... change your call to window.Layout(layout).Read()') + # self.AddRows(rows) + # self.Show(non_blocking=non_blocking) + # return self.ReturnValues + + def LayoutAndShow(self, rows): + raise DeprecationWarning('LayoutAndShow is no longer supported... change your call to LayoutAndRead') + + # ------------------------- ShowForm THIS IS IT! ------------------------- # + def Show(self, non_blocking=False): + self.Shown = True + # Compute num rows & num cols (it'll come in handy debugging) + self.NumRows = len(self.Rows) + self.NumCols = max(len(row) for row in self.Rows) + self.NonBlocking = non_blocking + + # Search through entire form to see if any elements set the focus + # if not, then will set the focus to the first input element + found_focus = False + for row in self.Rows: + for element in row: + try: + if element.Focus: + found_focus = True + except: + pass + try: + if element.Key is not None: + self.UseDictionary = True + except: + pass + + if not found_focus and self.UseDefaultFocus: + self.UseDefaultFocus = True + else: + self.UseDefaultFocus = False + # -=-=-=-=-=-=-=-=- RUN the GUI -=-=-=-=-=-=-=-=- ## + StartupTK(self) + # If a button or keyboard event happened but no results have been built, build the results + if self.LastKeyboardEvent is not None or self.LastButtonClicked is not None: + return BuildResults(self, False, self) + return self.ReturnValues + + # ------------------------- SetIcon - set the window's fav icon ------------------------- # + def SetIcon(self, icon=None, pngbase64=None): + pass + + def _GetElementAtLocation(self, location): + (row_num, col_num) = location + row = self.Rows[row_num] + element = row[col_num] + return element + + def _GetDefaultElementSize(self): + return self.DefaultElementSize + + def _AutoCloseAlarmCallback(self): + try: + window = self + if window: + if window.NonBlocking: + self.CloseNonBlockingForm() + else: + window._Close() + if self.CurrentlyRunningMainloop: + self.QTApplication.exit() # kick the users out of the mainloop + self.RootNeedsDestroying = True + self.QT_QMainWindow.close() + + except: + pass + + def _timer_timeout(self): + # first, get the results table built + # modify the Results table in the parent FlexForm object + if self.TimerCancelled: + return + self.LastButtonClicked = self.TimeoutKey + self.FormRemainedOpen = True + if self.CurrentlyRunningMainloop: + self.QTApplication.exit() # kick the users out of the mainloop + + def _autoclose_timer_callback(self): + # print('*** TIMEOUT CALLBACK ***') + self.autoclose_timer.stop() + self.QT_QMainWindow.close() + if self.CurrentlyRunningMainloop: + # print("quitting window") + self.QTApplication.exit() # kick the users out of the mainloop + + + def Read(self, timeout=None, timeout_key=TIMEOUT_KEY, close=False): + """ + THE biggest deal method in the Window class! This is how you get all of your data from your Window. + Pass in a timeout (in milliseconds) to wait for a maximum of timeout milliseconds. Will return timeout_key + if no other GUI events happen first. + Use the close parameter to close the window after reading + + :param timeout: (int) Milliseconds to wait until the Read will return IF no other GUI events happen first + :param timeout_key: (Any) The value that will be returned from the call if the timer expired + :param close: (bool) if True the window will be closed prior to returning + :return: Tuple[(Any), Union[Dict[Any:Any]], List[Any], None] (event, values) + """ + results = self._read(timeout=timeout, timeout_key=timeout_key) + if close: + self.close() + + return results + + + + def _read(self, timeout=None, timeout_key=TIMEOUT_KEY): + if timeout == 0: # timeout of zero runs the old readnonblocking + event, values = self._ReadNonBlocking() + if event is None: + event = timeout_key + if values is None: + event = None + return event, values # make event None if values was None and return + # Read with a timeout + self.Timeout = timeout + self.TimeoutKey = timeout_key + self.NonBlocking = False + if not self.Shown: + self.Show() + else: + # if already have a button waiting, the return previously built results + if self.LastButtonClicked is not None and not self.LastButtonClickedWasRealtime: + # print(f'*** Found previous clicked saved {self.LastButtonClicked}') + results = BuildResults(self, False, self) + self.LastButtonClicked = None + return results + InitializeResults(self) + # if the last button clicked was realtime, emulate a read non-blocking + # the idea is to quickly return realtime buttons without any blocks until released + if self.LastButtonClickedWasRealtime: + # print(f'RTime down {self.LastButtonClicked}' ) + try: + rc = self.TKroot.update() + except: + self.TKrootDestroyed = True + Window.DecrementOpenCount() + results = BuildResults(self, False, self) + if results[0] != None and results[0] != timeout_key: + return results + else: + pass + + # else: + # print("** REALTIME PROBLEM FOUND **", results) + + # normal read blocking code.... + if timeout != None: + self.TimerCancelled = False + timer = start_window_read_timer(self, timeout) + else: + timer = None + self.CurrentlyRunningMainloop = True + # print(f'In main {self.Title}') + ################################# CALL GUI MAINLOOP ############################ + + self.QTApplication.exec_() + # self.LastButtonClicked = 'TEST' + self.CurrentlyRunningMainloop = False + self.TimerCancelled = True + if timer: + stop_timer(timer) + if self.RootNeedsDestroying: + self.LastButtonClicked = None + self.QTApplication.exit() + Window.DecrementOpenCount() + # if form was closed with X + if self.LastButtonClicked is None and self.LastKeyboardEvent is None and self.ReturnValues[0] is None: + Window.DecrementOpenCount() + # Determine return values + if self.LastKeyboardEvent is not None or self.LastButtonClicked is not None: + results = BuildResults(self, False, self) + if not self.LastButtonClickedWasRealtime: + self.LastButtonClicked = None + return results + else: + if not self.XFound and self.Timeout != 0 and self.Timeout is not None and self.ReturnValues[0] is None: # Special Qt case because returning for no reason so fake timeout + self.ReturnValues = self.TimeoutKey, self.ReturnValues[1] # fake a timeout + elif not self.XFound and self.ReturnValues[0] is None: # TODO HIGHLY EXPERIMENTAL... added due to tray icon interaction + # print("*** Faking timeout ***") + self.ReturnValues = self.TimeoutKey, self.ReturnValues[1] # fake a timeout + return self.ReturnValues + + def _ReadNonBlocking(self): + if self.TKrootDestroyed: + return None, None + if not self.Shown: + self.Show(non_blocking=True) + else: + self.QTApplication.processEvents() # refresh the window + if 0: # TODO add window closed with X logic + self.TKrootDestroyed = True + _my_windows.Decrement() + # print("read failed") + # return None, None + return BuildResults(self, False, self) + + + def Finalize(self): + if self.TKrootDestroyed: + return self + if not self.Shown: + self.Show(non_blocking=True) + else: + try: + self.QTApplication.processEvents() # refresh the window + except: + print('* ERROR FINALIZING *') + self.TKrootDestroyed = True + Window.DecrementOpenCount() + return self + + + def Refresh(self): + self.QTApplication.processEvents() # refresh the window + return self + + def VisibilityChanged(self): + self.Refresh() + self.Size = self.Size + self.Refresh() + self.Size = self.Size + self.Refresh() + return self + + def Fill(self, values_dict): + FillFormWithValues(self, values_dict) + return self + + def FindElement(self, key, silent_on_error=False): + try: + element = self.AllKeysDict[key] + except KeyError: + element = None + # element = _FindElementFromKeyInSubForm(self, key) + if element is None: + if not silent_on_error: + print('*** WARNING = FindElement did not find the key. Please check your key\'s spelling ***') + PopupError('Keyword error in FindElement Call', + 'Bad key = {}'.format(key), + 'Your bad line of code may resemble this:', + 'window.FindElement("{}")'.format(key)) + return ErrorElement(key=key) + else: + return False + return element + + Element = FindElement # Shortcut function + + def _BuildKeyDict(self): + dict = {} + self.AllKeysDict = self._BuildKeyDictForWindow(self,self, dict) + + def _BuildKeyDictForWindow(self, top_window, window, key_dict): + for row_num, row in enumerate(window.Rows): + for col_num, element in enumerate(row): + if element.Type == ELEM_TYPE_COLUMN: + key_dict = self._BuildKeyDictForWindow(top_window, element, key_dict) + if element.Type == ELEM_TYPE_FRAME: + key_dict = self._BuildKeyDictForWindow(top_window, element, key_dict) + if element.Type == ELEM_TYPE_TAB_GROUP: + key_dict = self._BuildKeyDictForWindow(top_window, element, key_dict) + if element.Type == ELEM_TYPE_TAB: + key_dict = self._BuildKeyDictForWindow(top_window, element, key_dict) + if element.Key is None: # if no key has been assigned.... create one for input elements + if element.Type == ELEM_TYPE_BUTTON: + element.Key = element.ButtonText + elif element.Type == ELEM_TYPE_TAB: + element.Key = element.Title + if element.Type in (ELEM_TYPE_MENUBAR, ELEM_TYPE_BUTTONMENU, ELEM_TYPE_CANVAS, + ELEM_TYPE_INPUT_SLIDER, ELEM_TYPE_GRAPH, ELEM_TYPE_IMAGE, + ELEM_TYPE_INPUT_CHECKBOX, ELEM_TYPE_INPUT_LISTBOX, ELEM_TYPE_INPUT_COMBO, + ELEM_TYPE_INPUT_MULTILINE, ELEM_TYPE_INPUT_OPTION_MENU, ELEM_TYPE_INPUT_SPIN, + ELEM_TYPE_TABLE, ELEM_TYPE_TREE, + ELEM_TYPE_INPUT_TEXT): + element.Key = top_window.DictionaryKeyCounter + top_window.DictionaryKeyCounter += 1 + if element.Key is not None: + if element.Key in key_dict.keys(): + print('*** Duplicate key found in your layout {} ***'.format(element.Key)) if element.Type != ELEM_TYPE_BUTTON else None + element.Key = str(element.Key) + str(self.UniqueKeyCounter) + self.UniqueKeyCounter += 1 + print('*** Replaced new key with {} ***'.format(element.Key)) if element.Type != ELEM_TYPE_BUTTON else None + key_dict[element.Key] = element + return key_dict + + def FindElementWithFocus(self): + return _FindElementWithFocusInSubForm(self) + # return self.FocusElement + + def SaveToDisk(self, filename): + try: + results = BuildResults(self, False, self) + with open(filename, 'wb') as sf: + pickle.dump(results[1], sf) + except: + print('*** Error saving form to disk ***') + + def LoadFromDisk(self, filename): + try: + with open(filename, 'rb') as df: + self.Fill(pickle.load(df)) + except: + print('*** Error loading form to disk ***') + + def GetScreenDimensions(self): + if Window.QTApplication is None: + Window.QTApplication = QApplication(sys.argv) + try: + screen = Window.QTApplication.primaryScreen() + except: + return None, None + size = screen.size() + screen_width = size.width() + screen_height = size.height() + return screen_width, screen_height + + def Move(self, x, y): + if not self._is_window_created(): + return + self.QT_QMainWindow.move(x, y) + + def Minimize(self): + if not self._is_window_created(): + return + self.QT_QMainWindow.setWindowState(Qt.WindowMinimized) + + def Maximize(self): + if not self._is_window_created(): + return + self.QT_QMainWindow.setWindowState(Qt.WindowMaximized) + + + def StartMove(self, event): + try: + self.TKroot.x = event.x + self.TKroot.y = event.y + except: + pass + + def StopMove(self, event): + try: + self.TKroot.x = None + self.TKroot.y = None + except: + pass + + def OnMotion(self, event): + try: + deltax = event.x - self.TKroot.x + deltay = event.y - self.TKroot.y + x = self.TKroot.winfo_x() + deltax + y = self.TKroot.winfo_y() + deltay + self.TKroot.geometry("+%s+%s" % (x, y)) + except: + pass + + def _KeyboardCallback(self, event): + self.LastButtonClicked = None + self.FormRemainedOpen = True + if event.char != '': + self.LastKeyboardEvent = event.char + else: + self.LastKeyboardEvent = str(event.keysym) + ':' + str(event.keycode) + if not self.NonBlocking: + BuildResults(self, False, self) + if self.CurrentlyRunningMainloop: # quit if this is the current mainloop, otherwise don't quit! + self.TKroot.quit() + + def _MouseWheelCallback(self, event): + self.LastButtonClicked = None + self.FormRemainedOpen = True + self.LastKeyboardEvent = 'MouseWheel:Down' if event.delta < 0 else 'MouseWheel:Up' + if not self.NonBlocking: + BuildResults(self, False, self) + if self.CurrentlyRunningMainloop: # quit if this is the current mainloop, otherwise don't quit! + self.TKroot.quit() + + def _Close(self): + try: + self.TKroot.update() + except: + pass + if not self.NonBlocking: + BuildResults(self, False, self) + if self.TKrootDestroyed: + return None + self.TKrootDestroyed = True + self.RootNeedsDestroying = True + return None + + def Close(self): + if self.TKrootDestroyed: + return + try: + self.QT_QMainWindow.close() + except: + print('error closing window') + + CloseNonBlockingForm = Close + CloseNonBlocking = Close + + + def Disable(self): + if not self._is_window_created(): + return + self.QT_QMainWindow.setEnabled(False) + + def Enable(self): + if not self._is_window_created(): + return + self.QT_QMainWindow.setEnabled(True) + + def Hide(self): + if not self._is_window_created(): + return + self._Hidden = True + self.QT_QMainWindow.hide() + return + + def UnHide(self): + if not self._is_window_created(): + return + if self._Hidden: + self.QT_QMainWindow.show() + self._Hidden = False + + def Disappear(self): + self.AlphaChannel = 0 + + def Reappear(self): + self.AlphaChannel = 255 + + def SetAlpha(self, alpha): + """ + Change the window's transparency + :param alpha: From 0 to 1 with 0 being completely transparent + :return: + """ + if not self._is_window_created(): + return + self._AlphaChannel = alpha + if self._AlphaChannel is not None: + self.QT_QMainWindow.setWindowOpacity(self._AlphaChannel) + + @property + def AlphaChannel(self): + return self._AlphaChannel + + @AlphaChannel.setter + def AlphaChannel(self, alpha): + if not self._is_window_created(): + return + self._AlphaChannel = alpha + if self._AlphaChannel is not None: + self.QT_QMainWindow.setWindowOpacity(self._AlphaChannel) + + def BringToFront(self): + if not self._is_window_created(): + return + self.QTMainWindow.activateWindow(self.QT_QMainWindow) + self.QTMainWindow.raise_(self.QT_QMainWindow) + + + def CurrentLocation(self): + if not self._is_window_created(): + return + location = self.QT_QMainWindow.geometry() + return location.left(), location.top() + + + def set_title(self, title): + """ + Change the title of the window + + :param title: The string to set the title to + :type title: (str) + """ + if not self._is_window_created(): + return + self.Title = str(title) + self.QT_QMainWindow.setWindowTitle(self.Title) + + + + class QTMainWindow(QWidget): + def __init__(self,enable_key_events, window): + self.KeyEventsEnabled = enable_key_events + self.Window = window + super().__init__(window.QT_QMainWindow) + + def eventFilter(self, widget, event): + # print(event.type()) + if event.type() == QEvent.MouseButtonPress and self.Window.GrabAnywhere: + self.mouse_offset = event.pos() + if event.type() == QEvent.MouseMove and self.Window.GrabAnywhere: + x = event.globalX() + y = event.globalY() + x_w = self.mouse_offset.x() + y_w = self.mouse_offset.y() + self.move(x - x_w, y - y_w) + + if event.type() == QEvent.KeyRelease and self.KeyEventsEnabled: + # print("got key event") + key = event.key() + try: + self.Window.LastButtonClicked = chr(key).lower() + except: + self.Window.LastButtonClicked = "special %s" % key + self.Window.FormRemainedOpen = True + if self.Window.CurrentlyRunningMainloop: + self.Window.QTApplication.exit() + return QWidget.eventFilter(self, widget, event) + + + class QT_QMainWindowClass(QMainWindow): + def __init__(self,enable_key_events, window): + self.KeyEventsEnabled = enable_key_events + self.Window = window + super().__init__() + + def eventFilter(self, widget, event): + # print(event.type()) + if event.type() == QEvent.MouseButtonPress and self.Window.GrabAnywhere: + self.mouse_offset = event.pos() + if event.type() == QEvent.MouseMove and self.Window.GrabAnywhere: + x = event.globalX() + y = event.globalY() + x_w = self.mouse_offset.x() + y_w = self.mouse_offset.y() + self.move(x - x_w, y - y_w) + + if event.type() == QEvent.KeyRelease and self.KeyEventsEnabled: + # print("got key event") + key = event.key() + try: + self.Window.LastButtonClicked = chr(key).lower() + except: + self.Window.LastButtonClicked = "special %s" % key + self.Window.FormRemainedOpen = True + if self.Window.CurrentlyRunningMainloop: + self.Window.QTApplication.exit() + return QWidget.eventFilter(self, widget, event) + + def closeEvent(self, event): + if self.Window.DisableClose: + event.ignore() + return + # print('GOT A CLOSE EVENT!', event, self.Window.Title) + self.Window.LastButtonClicked = None + self.Window.XFound = True + if not self.Window.CurrentlyRunningMainloop: # quit if this is the current mainloop, otherwise don't quit! + self.Window.RootNeedsDestroying = True + else: + self.Window.RootNeedsDestroying = True + self.Window.QTApplication.exit() # kick the users out of the mainloop + self.Window.QT_QMainWindow.close() + self.Window.TKrootDestroyed = True + self.Window.RootNeedsDestroying = True + + # if self.CurrentlyRunningMainloop: + # print("quitting window") + # self.QTApplication.exit() # kick the users out of the mainloop + + @property + def Size(self): + if not self._is_window_created(): + return + size = self.QT_QMainWindow.sizeHint() + return [size.width(), size.height()] + + @Size.setter + def Size(self, size): + if not self._is_window_created(): + return + self.QT_QMainWindow.resize(QSize(size[0], size[1])) + + + def _is_window_created(self): + if self.QT_QMainWindow is None: + warnings.warn('You cannot perform operations on a Window until it is read or finalized. Adding a "finalize=True" parameter to your Window creation will fix this', UserWarning) + popup_error('You cannot perform operations on a Window until it is read or finalized.', + 'Yea, I know, it\'s a weird thing, but easy to fix.... ', + 'Adding a "finalize=True" parameter to your Window creation will likely fix this', image=FACE_PALM) + return False + return True + + + + def __getitem__(self, key): + """ + Returns Element that matches the passed in key. + This is "called" by writing code as thus: + window['element key'].Update + + :param key: The key to find + :type key: Union[str, int, tuple, object] + :return: Union[Element, None] The element found or None if no element was found + :rtype: Element + """ + try: + return self.Element(key) + except Exception as e: + print('The key you passed in is no good. Key = {}*'.format(key)) + return None + + def __call__(self, *args, **kwargs): + """ + Call window.Read but without having to type it out. + window() == window.Read() + window(timeout=50) == window.Read(timeout=50) + + :param args: * + :type args: (any) + :param kwargs: ** + :type kaargs: (any) + :return: Tuple[Any, Dict[Any:Any]] The famous event, values that Read returns. + """ + return self.Read(*args, **kwargs) + + + + + + add_row = AddRow + add_rows = AddRows + alpha_channel = AlphaChannel + bring_to_front = BringToFront + close = Close + current_location = CurrentLocation + disable = Disable + disappear = Disappear + element = Element + enable = Enable + fill = Fill + finalize = Finalize + find_element = FindElement + find_element_with_focus = FindElementWithFocus + get_screen_dimensions = GetScreenDimensions + hide = Hide + layout = Layout + load_from_disk = LoadFromDisk + maximize = Maximize + minimize = Minimize + move = Move + read = Read + reappear = Reappear + refresh = Refresh + save_to_disk = SaveToDisk + set_alpha = SetAlpha + set_icon = SetIcon + size = Size + un_hide = UnHide + visibility_changed = VisibilityChanged + +FlexForm = Window + + + + + +class QtStyle(object): + ''' + API + + # step 1 - make a style + ss = QtStyle(QLabel) + + # step 2 - add fields + ss['font'] = create_style_from_font() + ss['background_color'] = (color, color_default) + ss['color'] = (color, color_default) + # step 2.1 - add additions + ss.append_css_to_end.append(" QScrollBar:vertical { ... some css here ... } ") + # step 2.2 - add anchor + ss.my_anchor = '::chunk' + + # step 3 - build result + css_str = ss.build_css_string() + qt_widget.setStyleSheet(css_str) + + ====== Special fields + - font + - margin + Why they are special? Because of the formatting. + + === === === + made by nngogol + ''' + + def __init__(self, widget_name=''): + self.widget_name = widget_name + self.css_props = {} + self.my_anchor = None + + self.logging = True + self.logging = not True + self.append_css_to_end = [] + + self.make_secure_check = True # Check if "css property is valid, i.e. it's present in default names". + # Make makes development safer, if you have a erro in spelling css-property + # In production: it can be disabled, I guess. + + def __setitem__(self, css_prop_name, css_prop_value): + + css_prop_name = css_prop_name.replace('_', '-') + # validation + if not isinstance(css_prop_value, (tuple, list, str)): + raise Exception('Bad value fro css property -> %s.' % css_prop_value) + if self.make_secure_check: + if not is_valid_css_prop(css_prop_name): + raise Exception('Bad css property name: ' % css_prop_name) + + self.css_props[css_prop_name] = css_prop_value + + def build_css_string(self): + # no css props added -> return empty string + if not self.css_props: # empty case + print(f' final_str # {self.widget_name} = ""') + return '' + + css_props_str_list = [] + for key, value in self.css_props.items(): + # special cases: + if key == 'margin' or key == 'padding': + # validation + if not isinstance(value, (tuple, list)): + raise Exception('Cant handle this TYPE for margin property : %s ' % str(type(value))) + + result_css_string = '' + + if len(value) == 4: + # skip all zeros + if value[0] == value[1] == value[2] == value[3] == 0: result_css_string = '' + + result_css_string = '{} : {}px {}px {}px {}px;'.format(key, *value) + elif len(value) == 1: + # skip all zeros + if value[0] == 0: continue + + result_css_string = '{} : {}px;'.format(key, value[0]) + else: + raise Exception('Bad value for margin/padding property: ' % str(value)) + + # # Fix for this case: + # # Wrong: margin: 0px; + # # Right: margin: 0; + # result_css_string = result_css_string.replace(': 0px', ': 0') + + css_props_str_list.append(result_css_string) + + continue + # if key == 'border': ... + + # it's a css string! Format: 'propery: value;'' + if isinstance(value, str): + # is css prop name + css prop value + if ':' in value: + css_props_str_list.append(value) + # is css value + else: + css_props_str_list.append(_to_css_prop(key, value)) + # we continue, because it was 'string type parsing' + continue + + isnot = None + # it's a pair! Format: (val, default_val) + if isinstance(value, (tuple, list)): + user_css_prop_value, isnot = value + + if user_css_prop_value is not None and user_css_prop_value != isnot: + css_props_str_list.append(_to_css_prop(key, user_css_prop_value)) + + # join all props + css_all = ''.join(css_props_str_list) + final_str = css_all + if self.widget_name: + my_anchor = '' if self.my_anchor is None else self.my_anchor + final_str = '%s%s { %s }' % (self.widget_name, my_anchor, css_all) + + # if needed: append some css from self.append_css_to_end + final_str += ' '.join(self.append_css_to_end) + + if self.logging: print(f'final css string (self.widget_name): {final_str}') + return final_str + + def __repr__(self): + return self.build_css_string() + + + + +# =========================================================================== # +# Stops the mainloop and sets the event information # +# =========================================================================== # + +def _element_callback_quit_mainloop(element): + if element.Key is not None: + element.ParentForm.LastButtonClicked = element.Key + else: + element.ParentForm.LastButtonClicked = '' + element.ParentForm.FormRemainedOpen = True + if element.ParentForm.CurrentlyRunningMainloop: + element.ParentForm.QTApplication.exit() # kick the users out of the mainloop + + +# =========================================================================== # +# Convert from characters to pixels # +# =========================================================================== # +def _convert_tkinter_size_to_Qt(size, scaling=DEFAULT_PIXELS_TO_CHARS_SCALING, height_cutoff=DEFAULT_PIXEL_TO_CHARS_CUTOFF): + """ + Converts size in characters to size in pixels + :param size: size in characters, rows + :return: size in pixels, pixels + """ + qtsize = size + if size[1] is not None and size[1] < height_cutoff: # change from character based size to pixels (roughly) + qtsize = size[0]*scaling[0], size[1]*scaling[1] + return qtsize + + + +# =========================================================================== # +# Stops the mainloop and sets the event information # +# =========================================================================== # +def convert_tkinter_filetypes_to_qt(filetypes): + qt_filetypes = '' + for i, item in enumerate(filetypes): + filetype = item[0] + ' (' + item[1] + ')' + (';;' if i != len(filetypes)-1 else '') + qt_filetypes += filetype + return qt_filetypes + +# =========================================================================== # +# Converts a "Font" string or tuple into Qt Style Sheet Entries # +# =========================================================================== # +def create_style_from_font(font): + """ + Convert from font string/tuple into a Qt style sheet string + :param font: "Arial 10 Bold" or ('Arial', 10, 'Bold') + :return: style string that can be combined with other style strings + """ + + if font is None: return '' + _font = font.split(' ') if type(font) is str else font + + # parsing name + size + font_name, font_size = _font[:2] + # parsing options: + is_bold, is_underline = False, False + if len(_font) > 2: + options = _font[2:] + for some_option in options: + if some_option == 'underline': + is_underline = True + else: + is_bold = True + + # build + is_bold_text = 'font-weight : bold;' if is_bold else '' + is_underline_text = 'text-decoration: underline;' if is_underline else '' + + return textwrap.dedent(f''' + {is_underline_text} + {is_bold_text} + font-family: "{font_name}"; + font-size: {font_size}pt; + '''.strip()).replace('\n', '') + + +def set_widget_visiblity(widget, visible): + if visible is False: + widget.setVisible(False) + elif visible is True: + widget.setVisible(True) + + +# ################################################################################ +# ################################################################################ +# END OF ELEMENT DEFINITIONS +# ################################################################################ +# ################################################################################ + + +# =========================================================================== # +# Button Lazy Functions so the caller doesn't have to define a bunch of stuff # +# =========================================================================== # + + +# ------------------------- FOLDER BROWSE Element lazy function ------------------------- # +def FolderBrowse(button_text='Browse', target=(ThisRow, -1), initial_folder=None, tooltip=None, size=(None, None), + auto_size_button=None, button_color=None, disabled=False, change_submits=False, enable_events=False, font=None, pad=None, + key=None, k=None, metadata=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_BROWSE_FOLDER, target=target, + initial_folder=initial_folder, tooltip=tooltip, size=size, auto_size_button=auto_size_button, + disabled=disabled, button_color=button_color, change_submits=change_submits, enable_events=enable_events, font=font, pad=pad, + key=key, k=k, metadata=metadata) + + +# ------------------------- FILE BROWSE Element lazy function ------------------------- # +def FileBrowse(button_text='Browse', target=(ThisRow, -1), file_types=(("ALL Files", "*"),), initial_folder=None, + tooltip=None, size=(None, None), auto_size_button=None, button_color=None, change_submits=False, enable_events=False, + font=None, disabled=False, + pad=None, key=None, k=None, metadata=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_BROWSE_FILE, target=target, file_types=file_types, + initial_folder=initial_folder, tooltip=tooltip, size=size, auto_size_button=auto_size_button, + change_submits=change_submits, enable_events=enable_events, disabled=disabled, button_color=button_color, font=font, pad=pad, + key=key, k=k, metadata=metadata) + + +# ------------------------- FILES BROWSE Element (Multiple file selection) lazy function ------------------------- # +def FilesBrowse(button_text='Browse', target=(ThisRow, -1), file_types=(("ALL Files", "*"),), disabled=False, + initial_folder=None, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, + change_submits=False, enable_events=False, + font=None, pad=None, key=None, k=None, metadata=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_BROWSE_FILES, target=target, file_types=file_types, + initial_folder=initial_folder, change_submits=change_submits, enable_events=enable_events, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, + disabled=disabled, button_color=button_color, font=font, pad=pad, key=key, k=k, metadata=metadata) + + +# ------------------------- FILE BROWSE Element lazy function ------------------------- # +def FileSaveAs(button_text='Save As...', target=(ThisRow, -1), file_types=(("ALL Files", "*"),), initial_folder=None, + disabled=False, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, + change_submits=False, enable_events=False, font=None, + pad=None, key=None, k=None, metadata=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_SAVEAS_FILE, target=target, file_types=file_types, + initial_folder=initial_folder, tooltip=tooltip, size=size, disabled=disabled, + auto_size_button=auto_size_button, button_color=button_color, change_submits=change_submits, enable_events=enable_events, + font=font, pad=pad, key=key, metadata=metadata) + + +# ------------------------- SAVE AS Element lazy function ------------------------- # +def SaveAs(button_text='Save As...', target=(ThisRow, -1), file_types=(("ALL Files", "*"),), initial_folder=None, + disabled=False, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, + change_submits=False, enable_events=False, font=None, + pad=None, key=None, k=None, metadata=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_SAVEAS_FILE, target=target, file_types=file_types, + initial_folder=initial_folder, tooltip=tooltip, size=size, disabled=disabled, + auto_size_button=auto_size_button, button_color=button_color, change_submits=change_submits, enable_events=enable_events, + font=font, pad=pad, key=key, k=k, metadata=metadata) + + +# ------------------------- SAVE BUTTON Element lazy function ------------------------- # +def Save(button_text='Save', size=(None, None), auto_size_button=None, button_color=None, bind_return_key=True, + disabled=False, tooltip=None, font=None, focus=False, pad=None, key=None, k=None, metadata=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, k=k, metadata=metadata) + + +# ------------------------- SUBMIT BUTTON Element lazy function ------------------------- # +def Submit(button_text='Submit', size=(None, None), auto_size_button=None, button_color=None, disabled=False, + bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, key=None, k=None, metadata=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, k=k, metadata=metadata) + + +# ------------------------- OPEN BUTTON Element lazy function ------------------------- # +# ------------------------- OPEN BUTTON Element lazy function ------------------------- # +def Open(button_text='Open', size=(None, None), auto_size_button=None, button_color=None, disabled=False, + bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, key=None, k=None, metadata=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, k=k, metadata=metadata) + + +# ------------------------- OK BUTTON Element lazy function ------------------------- # +def OK(button_text='OK', size=(None, None), auto_size_button=None, button_color=None, disabled=False, + bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, key=None, k=None, metadata=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, k=k, metadata=metadata) + + +# ------------------------- YES BUTTON Element lazy function ------------------------- # +def Ok(button_text='Ok', size=(None, None), auto_size_button=None, button_color=None, disabled=False, + bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, key=None, k=None, metadata=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, k=k, metadata=metadata) + + +# ------------------------- CANCEL BUTTON Element lazy function ------------------------- # +def Cancel(button_text='Cancel', size=(None, None), auto_size_button=None, button_color=None, disabled=False, + tooltip=None, font=None, bind_return_key=False, focus=False, pad=None, key=None, k=None, metadata=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, k=k, metadata=metadata) + + +# ------------------------- QUIT BUTTON Element lazy function ------------------------- # +def Quit(button_text='Quit', size=(None, None), auto_size_button=None, button_color=None, disabled=False, tooltip=None, + font=None, bind_return_key=False, focus=False, pad=None, key=None, k=None, metadata=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, k=k, metadata=metadata) + + +# ------------------------- Exit BUTTON Element lazy function ------------------------- # +def Exit(button_text='Exit', size=(None, None), auto_size_button=None, button_color=None, disabled=False, tooltip=None, + font=None, bind_return_key=False, focus=False, pad=None, key=None, k=None, metadata=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, k=k, metadata=metadata) + + +# ------------------------- YES BUTTON Element lazy function ------------------------- # +def Yes(button_text='Yes', size=(None, None), auto_size_button=None, button_color=None, disabled=False, tooltip=None, + font=None, bind_return_key=True, focus=False, pad=None, key=None, k=None, metadata=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, k=k, metadata=metadata) + + +# ------------------------- NO BUTTON Element lazy function ------------------------- # +def No(button_text='No', size=(None, None), auto_size_button=None, button_color=None, disabled=False, tooltip=None, + font=None, bind_return_key=False, focus=False, pad=None, key=None, k=None, metadata=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, k=k, metadata=metadata) + + +# ------------------------- NO BUTTON Element lazy function ------------------------- # +def Help(button_text='Help', size=(None, None), auto_size_button=None, button_color=None, disabled=False, font=None, + tooltip=None, bind_return_key=False, focus=False, pad=None, key=None, k=None, metadata=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, k=k, metadata=metadata) + + +# ------------------------- GENERIC BUTTON Element lazy function ------------------------- # +def SimpleButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, + border_width=None, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, + font=None, bind_return_key=False, disabled=False, focus=False, pad=None, key=None, k=None, metadata=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_CLOSES_WIN, image_filename=image_filename, + image_data=image_data, image_size=image_size, image_subsample=image_subsample, + border_width=border_width, tooltip=tooltip, disabled=disabled, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, k=k, metadata=metadata) + + +# ------------------------- CLOSE BUTTON Element lazy function ------------------------- # +def CloseButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, + border_width=None, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, font=None, + bind_return_key=False, disabled=False, focus=False, pad=None, key=None, k=None, metadata=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_CLOSES_WIN, image_filename=image_filename, + image_data=image_data, image_size=image_size, image_subsample=image_subsample, + border_width=border_width, tooltip=tooltip, disabled=disabled, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, k=k, metadata=metadata) + + +CButton = CloseButton + + +# ------------------------- GENERIC BUTTON Element lazy function ------------------------- # +def ReadButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, + border_width=None, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, font=None, + bind_return_key=False, disabled=False, focus=False, pad=None, key=None, k=None, metadata=None): + """ + :param button_text: text in the button + :type button_text: (str) + :param image_filename: image filename if there is a button image. GIFs and PNGs only. + :type image_filename: (str) + :param image_data: Raw or Base64 representation of the image to put on button. Choose either filename or data + :type image_data: Union[bytes, str] + :param image_size: Size of the image in pixels (width, height) + :type image_size: Tuple[int, int] + :param image_subsample: amount to reduce the size of the image. Divides the size by this number. 2=1/2, 3=1/3, 4=1/4, etc + :type image_subsample: (int) + :param border_width: width of border around element + :type border_width: (int) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param size: (w,h) w=characters-wide, h=rows-high + :type size: Tuple[int, int] + :param auto_size_button: True if button size is determined by button text + :type auto_size_button: (bool) + :param button_color: button color (foreground, background) + :type button_color: Tuple[str, str] + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param bind_return_key: (Default = False) If True, then the return key will cause a the Listbox to generate an event + :type bind_return_key: (bool) + :param disabled: set disable state for element (Default = False) + :type disabled: (bool) + :param focus: if focus should be set to this + :type focus: idk_yetReally + :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) + :param key: key for uniquely identify this element (for window.FindElement) + :type key: Union[str, int, tuple, object] + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: Union[str, int, tuple, object] + :param metadata: Anything you want to store along with this button + :type metadata: (Any) + """ + + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, image_filename=image_filename, + image_data=image_data, image_size=image_size, image_subsample=image_subsample, + border_width=border_width, tooltip=tooltip, size=size, disabled=disabled, + auto_size_button=auto_size_button, button_color=button_color, font=font, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, k=k, metadata=metadata) + + +ReadFormButton = ReadButton +RButton = ReadFormButton + + +# ------------------------- Realtime BUTTON Element lazy function ------------------------- # +def RealtimeButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, + border_width=None, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, + font=None, disabled=False, bind_return_key=False, focus=False, pad=None, key=None, k=None, metadata=None): + """ + :param button_text: text in the button + :type button_text: (str) + :param image_filename: image filename if there is a button image. GIFs and PNGs only. + :type image_filename: (str) + :param image_data: Raw or Base64 representation of the image to put on button. Choose either filename or data + :type image_data: Union[bytes, str] + :param image_size: Size of the image in pixels (width, height) + :type image_size: Tuple[int, int] + :param image_subsample: amount to reduce the size of the image. Divides the size by this number. 2=1/2, 3=1/3, 4=1/4, etc + :type image_subsample: (int) + :param border_width: width of border around element + :type border_width: (int) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param size: (w,h) w=characters-wide, h=rows-high + :type size: Tuple[int, int] + :param auto_size_button: True if button size is determined by button text + :type auto_size_button: (bool) + :param button_color: button color (foreground, background) + :type button_color: Tuple[str, str] + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param disabled: set disable state for element (Default = False) + :type disabled: (bool) + :param bind_return_key: (Default = False) If True, then the return key will cause a the Listbox to generate an event + :type bind_return_key: (bool) + :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) + :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) + :type key: Union[str, int, tuple, object] + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: Union[str, int, tuple, object] + :param metadata: Anything you want to store along with this button + :type metadata: (Any) + """ + return Button(button_text=button_text, button_type=BUTTON_TYPE_REALTIME, image_filename=image_filename, + image_data=image_data, image_size=image_size, image_subsample=image_subsample, + border_width=border_width, tooltip=tooltip, disabled=disabled, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, k=k, metadata=metadata) + + +# ------------------------- Dummy BUTTON Element lazy function ------------------------- # +def DummyButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, + border_width=None, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, font=None, + disabled=False, bind_return_key=False, focus=False, pad=None, key=None, k=None, metadata=None): + """ + :param button_text: text in the button + :type button_text: (str) + :param image_filename: image filename if there is a button image. GIFs and PNGs only. + :type image_filename: (str) + :param image_data: Raw or Base64 representation of the image to put on button. Choose either filename or data + :type image_data: Union[bytes, str] + :param image_size: Size of the image in pixels (width, height) + :type image_size: Tuple[int, int] + :param image_subsample: amount to reduce the size of the image. Divides the size by this number. 2=1/2, 3=1/3, 4=1/4, etc + :type image_subsample: (int) + :param border_width: width of border around element + :type border_width: (int) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param size: (w,h) w=characters-wide, h=rows-high + :type size: Tuple[int, int] + :param auto_size_button: True if button size is determined by button text + :type auto_size_button: (bool) + :param button_color: button color (foreground, background) + :type button_color: Tuple[str, str] + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param disabled: set disable state for element (Default = False) + :type disabled: (bool) + :param bind_return_key: (Default = False) If True, then the return key will cause a the Listbox to generate an event + :type bind_return_key: (bool) + :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) + :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) + :type key: Union[str, int, tuple, object] + :param k: Same as the Key. You can use either k or key. Which ever is set will be used. + :type k: Union[str, int, tuple, object] + :param metadata: Anything you want to store along with this button + :type metadata: (Any) + """ + return Button(button_text=button_text, button_type=BUTTON_TYPE_CLOSES_WIN_ONLY, image_filename=image_filename, + image_data=image_data, image_size=image_size, image_subsample=image_subsample, + border_width=border_width, tooltip=tooltip, size=size, auto_size_button=auto_size_button, + button_color=button_color, font=font, disabled=disabled, bind_return_key=bind_return_key, focus=focus, + pad=pad, key=key, k=k, metadata=metadata) + + +# ------------------------- Calendar Chooser Button lazy function ------------------------- # +def CalendarButton(button_text, target=(None, None), close_when_date_chosen=True, default_date_m_d_y=(None, 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, + button_color=None, disabled=False, font=None, bind_return_key=False, focus=False, pad=None, + key=None, k=None, metadata=None): + button = Button(button_text=button_text, button_type=BUTTON_TYPE_CALENDAR_CHOOSER, target=target, + image_filename=image_filename, image_data=image_data, image_size=image_size, + image_subsample=image_subsample, border_width=border_width, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, k=k, metadata=metadata) + button.CalendarCloseWhenChosen = close_when_date_chosen + button.DefaultDate_M_D_Y = default_date_m_d_y + return button + + +# ------------------------- Calendar Chooser Button lazy function ------------------------- # +def ColorChooserButton(button_text, target=(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, + button_color=None, disabled=False, font=None, bind_return_key=False, focus=False, pad=None, + key=None, k=None, metadata=None): + """ + :param button_text: text in the button + :type button_text: (str) + :param target: key or (row,col) target for the button. Note that -1 for column means 1 element to the left of this one. The constant ThisRow is used to indicate the current row. The Button itself is a valid target for some types of button + :type target: Union[str, Tuple[int, int]] + :param image_filename: image filename if there is a button image. GIFs and PNGs only. + :type image_filename: (str) + :param image_data: Raw or Base64 representation of the image to put on button. Choose either filename or data + :type image_data: Union[bytes, str] + :param image_size: Size of the image in pixels (width, height) + :type image_size: Tuple[int, int] + :param image_subsample: amount to reduce the size of the image. Divides the size by this number. 2=1/2, 3=1/3, 4=1/4, etc + :type image_subsample: (int) + :param tooltip: text, that will appear when mouse hovers over the element + :type tooltip: (str) + :param border_width: width of border around element + :type border_width: (int) + :param size: (w,h) w=characters-wide, h=rows-high + :type size: Tuple[int, int] + :param auto_size_button: True if button size is determined by button text + :type auto_size_button: (bool) + :param button_color: button color (foreground, background) + :type button_color: Tuple[str, str] + :param disabled: set disable state for element (Default = False) + :type disabled: (bool) + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param bind_return_key: (Default = False) If True, then the return key will cause a the Listbox to generate an event + :type bind_return_key: (bool) + :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) + :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) + :param metadata: Anything you want to store along with this button + :type metadata: (Any) + """ + return Button(button_text=button_text, button_type=BUTTON_TYPE_COLOR_CHOOSER, target=target, + image_filename=image_filename, image_data=image_data, image_size=image_size, + image_subsample=image_subsample, border_width=border_width, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, k=k, metadata=metadata) + + +##################################### ----- RESULTS ------ ################################################## + +def AddToReturnDictionary(form, element, value): + form.ReturnValuesDictionary[element.Key] = value + return + if element.Key is None: + form.ReturnValuesDictionary[form.DictionaryKeyCounter] = value + element.Key = form.DictionaryKeyCounter + form.DictionaryKeyCounter += 1 + else: + form.ReturnValuesDictionary[element.Key] = value + + +def AddToReturnList(form, value): + form.ReturnValuesList.append(value) + + +# ----------------------------------------------------------------------------# +# ------- FUNCTION InitializeResults. Sets up form results matrix --------# +def InitializeResults(form): + BuildResults(form, True, form) + return + + +# ===== Radio Button RadVar encoding and decoding =====# +# ===== The value is simply the row * 1000 + col =====# +def DecodeRadioRowCol(RadValue): + row = RadValue // 1000 + col = RadValue % 1000 + return row, col + + +def EncodeRadioRowCol(row, col): + RadValue = row * 1000 + col + return RadValue + + +# ------- FUNCTION BuildResults. Form exiting so build the results to pass back ------- # +# format of return values is +# (Button Pressed, input_values) +def BuildResults(form, initialize_only, top_level_form): + # Results for elements are: + # TEXT - Nothing + # INPUT - Read value from TK + # Button - Button Text and position as a Tuple + + # Get the initialized results so we don't have to rebuild + form.DictionaryKeyCounter = 0 + form.ReturnValuesDictionary = {} + form.ReturnValuesList = [] + BuildResultsForSubform(form, initialize_only, top_level_form) + if not top_level_form.LastButtonClickedWasRealtime: + top_level_form.LastButtonClicked = None + return form.ReturnValues + + +def BuildResultsForSubform(form, initialize_only, top_level_form): + button_pressed_text = top_level_form.LastButtonClicked + for row_num, row in enumerate(form.Rows): + for col_num, element in enumerate(row): + if element.Key is not None and WRITE_ONLY_KEY in str(element.Key): + continue + value = None + if element.Type == ELEM_TYPE_COLUMN: + element.DictionaryKeyCounter = top_level_form.DictionaryKeyCounter + element.ReturnValuesList = [] + element.ReturnValuesDictionary = {} + BuildResultsForSubform(element, initialize_only, top_level_form) + for item in element.ReturnValuesList: + AddToReturnList(top_level_form, item) + if element.UseDictionary: + top_level_form.UseDictionary = True + if element.ReturnValues[0] is not None: # if a button was clicked + button_pressed_text = element.ReturnValues[0] + + if element.Type == ELEM_TYPE_FRAME: + element.DictionaryKeyCounter = top_level_form.DictionaryKeyCounter + element.ReturnValuesList = [] + element.ReturnValuesDictionary = {} + BuildResultsForSubform(element, initialize_only, top_level_form) + for item in element.ReturnValuesList: + AddToReturnList(top_level_form, item) + if element.UseDictionary: + top_level_form.UseDictionary = True + if element.ReturnValues[0] is not None: # if a button was clicked + button_pressed_text = element.ReturnValues[0] + + if element.Type == ELEM_TYPE_TAB_GROUP: + element.DictionaryKeyCounter = top_level_form.DictionaryKeyCounter + element.ReturnValuesList = [] + element.ReturnValuesDictionary = {} + BuildResultsForSubform(element, initialize_only, top_level_form) + for item in element.ReturnValuesList: + AddToReturnList(top_level_form, item) + if element.UseDictionary: + top_level_form.UseDictionary = True + if element.ReturnValues[0] is not None: # if a button was clicked + button_pressed_text = element.ReturnValues[0] + + if element.Type == ELEM_TYPE_TAB: + element.DictionaryKeyCounter = top_level_form.DictionaryKeyCounter + element.ReturnValuesList = [] + element.ReturnValuesDictionary = {} + BuildResultsForSubform(element, initialize_only, top_level_form) + for item in element.ReturnValuesList: + AddToReturnList(top_level_form, item) + if element.UseDictionary: + top_level_form.UseDictionary = True + if element.ReturnValues[0] is not None: # if a button was clicked + button_pressed_text = element.ReturnValues[0] + + if not initialize_only: + if element.Type == ELEM_TYPE_INPUT_TEXT: + value = element.QT_QLineEdit.text() + if not top_level_form.NonBlocking and not element.do_not_clear and not top_level_form.ReturnKeyboardEvents: + element.QT_QLineEdit.setText('') + + elif element.Type == ELEM_TYPE_INPUT_CHECKBOX: + value = element.QT_Checkbox.isChecked() + elif element.Type == ELEM_TYPE_INPUT_RADIO: + this_rowcol = EncodeRadioRowCol(row_num, col_num) + value = element.QT_Radio_Button.isChecked() + elif element.Type == ELEM_TYPE_BUTTON: + if top_level_form.LastButtonClicked == element.ButtonText: + button_pressed_text = top_level_form.LastButtonClicked + if element.BType != BUTTON_TYPE_REALTIME: # Do not clear realtime buttons + top_level_form.LastButtonClicked = None + if element.BType == BUTTON_TYPE_CALENDAR_CHOOSER: + try: + value = element.TKCal.selection + except: + value = None + else: + try: + value = element.FileOrFolderName + except: + value = None + elif element.Type == ELEM_TYPE_INPUT_COMBO: + element = element # type: Combo + index = element.QT_ComboBox.currentIndex() # index into the list of values, but can be larger if manual entry + if index < len(element.Values): + value = element.Values[index] + else: # if not a valid index, then get what was typed in + value = element.QT_ComboBox.currentText() + elif element.Type == ELEM_TYPE_INPUT_OPTION_MENU: + value = 0 + elif element.Type == ELEM_TYPE_INPUT_LISTBOX: + element = element # type: Listbox + # print(f'selected indexes = {element.QT_ListWidget.selectedIndexes()}') + value = [] + # value = [element.Values[int(i)] for i in element.QT_ListWidget.selectedIndexes()] + # value= [ for i, item in enumerate(element.QT_ListWidget.selectedItems()] + selected_items = [item.text() for item in element.QT_ListWidget.selectedItems()] + for v in element.Values: + if str(v) in selected_items: + value.append(v) + # try: + # value= [item.index() for item in element.QT_ListWidget.selectedItems()] + # # value= [item.text() for item in element.QT_ListWidget.selectedItems()] + # except: + # value = [] + elif element.Type == ELEM_TYPE_INPUT_SPIN: + # value = str(element.QT_Spinner.value()) + # value = str(element.QT_Spinner.textFromValue(element.QT_Spinner.value())) + value = element.Values[element.QT_Spinner.value()] + elif element.Type == ELEM_TYPE_INPUT_DIAL: + value = str(element.QT_Dial.value()) + elif element.Type == ELEM_TYPE_INPUT_SLIDER: + value = element.QT_Slider.value() + elif element.Type == ELEM_TYPE_INPUT_MULTILINE: + if element.WriteOnly: + continue + value = element.QT_TextEdit.toPlainText() + if not top_level_form.NonBlocking and not element.do_not_clear and not top_level_form.ReturnKeyboardEvents: + element.QT_TextEdit.setText('') + elif element.Type == ELEM_TYPE_TAB_GROUP: + element = element # type: TabGroup + cur_index = element.QT_QTabWidget.currentIndex() + tab_element = element.TabList[cur_index] + value = tab_element.Key + elif element.Type == ELEM_TYPE_TABLE: + value = [] + indexes = element.QT_TableWidget.selectionModel().selectedRows() + for index in sorted(indexes): + value.append(index.row()) + elif element.Type == ELEM_TYPE_TREE: + value = [] + indexes = element.QT_QTreeWidget.selectionModel().selectedRows() + for index in sorted(indexes): + value.append(index.row()) + elif element.Type == ELEM_TYPE_BUTTONMENU: + value = element.MenuItemChosen + element.MenuItemChosen = None + elif element.Type == ELEM_TYPE_MENUBAR: + if element.MenuItemChosen is not None: + top_level_form.LastButtonClicked = element.MenuItemChosen + button_pressed_text = top_level_form.LastButtonClicked + value = element.MenuItemChosen + element.MenuItemChosen = None + else: + value = None + + # if an input type element, update the results + if element.Type != ELEM_TYPE_BUTTON and \ + element.Type != ELEM_TYPE_TEXT and \ + element.Type != ELEM_TYPE_IMAGE and \ + element.Type != ELEM_TYPE_OUTPUT and \ + element.Type != ELEM_TYPE_PROGRESS_BAR and \ + element.Type != ELEM_TYPE_COLUMN and \ + element.Type != ELEM_TYPE_FRAME \ + and element.Type != ELEM_TYPE_TAB: + AddToReturnList(form, value) + AddToReturnDictionary(top_level_form, element, value) + elif (element.Type == ELEM_TYPE_BUTTON and + element.BType == BUTTON_TYPE_CALENDAR_CHOOSER and + element.Target == (None, None)) or \ + (element.Type == ELEM_TYPE_BUTTON and + element.BType == BUTTON_TYPE_COLOR_CHOOSER and + element.Target == (None, None)) or \ + (element.Type == ELEM_TYPE_BUTTON + and element.Key is not None and + (element.BType in (BUTTON_TYPE_SAVEAS_FILE, BUTTON_TYPE_BROWSE_FILE, BUTTON_TYPE_BROWSE_FILES, + BUTTON_TYPE_BROWSE_FOLDER))): + AddToReturnList(form, value) + AddToReturnDictionary(top_level_form, element, value) + + # if this is a column, then will fail so need to wrap with tr + try: + if form.ReturnKeyboardEvents and form.LastKeyboardEvent is not None: + button_pressed_text = form.LastKeyboardEvent + form.LastKeyboardEvent = None + except: + pass + + try: + form.ReturnValuesDictionary.pop(None, None) # clean up dictionary include None was included + except: + pass + + if not form.UseDictionary: + form.ReturnValues = button_pressed_text, form.ReturnValuesList + else: + form.ReturnValues = button_pressed_text, form.ReturnValuesDictionary + + return form.ReturnValues + + +def FillFormWithValues(form, values_dict): + FillSubformWithValues(form, values_dict) + + +def FillSubformWithValues(form, values_dict): + for row_num, row in enumerate(form.Rows): + for col_num, element in enumerate(row): + value = None + if element.Type == ELEM_TYPE_COLUMN: + FillSubformWithValues(element, values_dict) + if element.Type == ELEM_TYPE_FRAME: + FillSubformWithValues(element, values_dict) + if element.Type == ELEM_TYPE_TAB_GROUP: + FillSubformWithValues(element, values_dict) + if element.Type == ELEM_TYPE_TAB: + FillSubformWithValues(element, values_dict) + try: + value = values_dict[element.Key] + except: + continue + if element.Type == ELEM_TYPE_INPUT_TEXT: + element.Update(value) + elif element.Type == ELEM_TYPE_INPUT_CHECKBOX: + element.Update(value) + elif element.Type == ELEM_TYPE_INPUT_RADIO: + element.Update(value) + elif element.Type == ELEM_TYPE_INPUT_COMBO: + element.Update(value) + elif element.Type == ELEM_TYPE_INPUT_OPTION_MENU: + element.Update(value) + elif element.Type == ELEM_TYPE_INPUT_LISTBOX: + element.SetValue(value) + elif element.Type == ELEM_TYPE_INPUT_SLIDER: + element.Update(value) + elif element.Type == ELEM_TYPE_INPUT_MULTILINE: + element.Update(value) + elif element.Type == ELEM_TYPE_INPUT_SPIN: + element.Update(value) + elif element.Type == ELEM_TYPE_BUTTON: + element.Update(value) + + +def _FindElementFromKeyInSubForm(form, key): + for row_num, row in enumerate(form.Rows): + for col_num, element in enumerate(row): + if element.Type == ELEM_TYPE_COLUMN: + matching_elem = _FindElementFromKeyInSubForm(element, key) + if matching_elem is not None: + return matching_elem + if element.Type == ELEM_TYPE_FRAME: + matching_elem = _FindElementFromKeyInSubForm(element, key) + if matching_elem is not None: + return matching_elem + if element.Type == ELEM_TYPE_TAB_GROUP: + matching_elem = _FindElementFromKeyInSubForm(element, key) + if matching_elem is not None: + return matching_elem + if element.Type == ELEM_TYPE_TAB: + matching_elem = _FindElementFromKeyInSubForm(element, key) + if matching_elem is not None: + return matching_elem + if element.Key == key: + return element + + +def _FindElementWithFocusInSubForm(form): + for row_num, row in enumerate(form.Rows): + for col_num, element in enumerate(row): + if element.Type == ELEM_TYPE_COLUMN: + matching_elem = _FindElementWithFocusInSubForm(element) + if matching_elem is not None: + return matching_elem + if element.Type == ELEM_TYPE_FRAME: + matching_elem = _FindElementWithFocusInSubForm(element) + if matching_elem is not None: + return matching_elem + if element.Type == ELEM_TYPE_TAB_GROUP: + matching_elem = _FindElementWithFocusInSubForm(element) + if matching_elem is not None: + return matching_elem + if element.Type == ELEM_TYPE_TAB: + matching_elem = _FindElementWithFocusInSubForm(element) + if matching_elem is not None: + return matching_elem + try: + if element.Widget.hasFocus(): + return element + except: + continue + # if element.Type == ELEM_TYPE_INPUT_TEXT: + # if element.QT_QLineEdit is not None: + # if element.QT_QLineEdit is element.TKEntry.focus_get(): + # return element + + +def AddTrayMenuItem(top_menu, sub_menu_info, element, is_sub_menu=False, skip=False): + if type(sub_menu_info) is str: + if not is_sub_menu and not skip: + # print(f'Adding command {sub_menu_info}') + action = QAction(top_menu) + if sub_menu_info == '---': + action.setSeparator(True) + else: + try: + item_without_key = sub_menu_info[:sub_menu_info.index(MENU_KEY_SEPARATOR)] + except: + item_without_key = sub_menu_info + if item_without_key[0] == MENU_DISABLED_CHARACTER: + action.setText(item_without_key[len(MENU_DISABLED_CHARACTER):]) + action.setDisabled(True) + else: + action.setText(item_without_key) + action.triggered.connect(lambda: SystemTray._QT_MenuItemChosenCallback(element, sub_menu_info)) + top_menu.addAction(action) + else: + i = 0 + while i < (len(sub_menu_info)): + item = sub_menu_info[i] + if i != len(sub_menu_info) - 1: + if type(sub_menu_info[i + 1]) is list: + new_menu = QMenu(top_menu) + item = sub_menu_info[i] + try: + item_without_key = item[:item.index(MENU_KEY_SEPARATOR)] + except: + item_without_key = item + if item_without_key[0] == MENU_DISABLED_CHARACTER: + new_menu.setTitle(item_without_key[len(MENU_DISABLED_CHARACTER):]) + new_menu.setDisabled(True) + else: + new_menu.setTitle(item_without_key) + top_menu.addAction(new_menu.menuAction()) + # print(f'Adding submenu {sub_menu_info[i]}') + AddTrayMenuItem(new_menu, sub_menu_info[i + 1], element, is_sub_menu=True) + i += 1 # skip the next one + else: + AddTrayMenuItem(top_menu, item, element) + else: + AddTrayMenuItem(top_menu, item, element) + i += 1 + + +def AddMenuItem(top_menu, sub_menu_info, element, is_sub_menu=False, skip=False): + if type(sub_menu_info) is str: + if not is_sub_menu and not skip: + # print(f'Adding command {sub_menu_info}') + action = QAction(top_menu) + + if sub_menu_info == '---': + action.setSeparator(True) + else: + + # Key handling.... strip off key before setting text + try: + item_without_key = sub_menu_info[:sub_menu_info.index(MENU_KEY_SEPARATOR)] + except: + item_without_key = sub_menu_info + if item_without_key[0] == MENU_DISABLED_CHARACTER: + action.setText(item_without_key[len(MENU_DISABLED_CHARACTER):]) + action.setDisabled(True) + else: + action.setText(item_without_key) + action.triggered.connect(lambda: Menu._QT_MenuItemChosenCallback(element, sub_menu_info)) + top_menu.addAction(action) + else: + i = 0 + while i < (len(sub_menu_info)): + item = sub_menu_info[i] + if i != len(sub_menu_info) - 1: + if type(sub_menu_info[i + 1]) is list: + new_menu = QMenu(top_menu) + # + # # === style === + # menu_style = _Style('QMenu') + # menu_style['font'] = create_style_from_font(element.Font) + # if element.TextColor is not None and element.TextColor != COLOR_SYSTEM_DEFAULT: + # menu_style['color'] = element.TextColor + # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + # menu_style['background-color'] = element.BackgroundColor + # # style['margin'] = full_element_pad + # new_menu.setStyleSheet(menu_style.build_css_string()) + # print(menu_style) + # # element.qt_styles = (style,) + # # === style === end + # + # Key handling.... strip off key before setting text + item = sub_menu_info[i] + try: + item_without_key = item[:item.index(MENU_KEY_SEPARATOR)] + except: + item_without_key = item + if item_without_key[0] == MENU_DISABLED_CHARACTER: + new_menu.setTitle(item_without_key[len(MENU_DISABLED_CHARACTER):]) + new_menu.setDisabled(True) + else: + new_menu.setTitle(item_without_key) + top_menu.addAction(new_menu.menuAction()) + # print(f'Adding submenu {sub_menu_info[i]}') + AddMenuItem(new_menu, sub_menu_info[i + 1], element, is_sub_menu=True) + i += 1 # skip the next one + else: + AddMenuItem(top_menu, item, element) + else: + AddMenuItem(top_menu, item, element) + i += 1 + + +""" + QQQQQQQQQ tttt + QQ:::::::::QQ ttt:::t + QQ:::::::::::::QQ t:::::t +Q:::::::QQQ:::::::Q t:::::t +Q::::::O Q::::::Qttttttt:::::ttttttt +Q:::::O Q:::::Qt:::::::::::::::::t +Q:::::O Q:::::Qt:::::::::::::::::t +Q:::::O Q:::::Qtttttt:::::::tttttt +Q:::::O Q:::::Q t:::::t +Q:::::O Q:::::Q t:::::t +Q:::::O QQQQ:::::Q t:::::t +Q::::::O Q::::::::Q t:::::t tttttt +Q:::::::QQ::::::::Q t::::::tttt:::::t + QQ::::::::::::::Q tt::::::::::::::t + QQ:::::::::::Q tt:::::::::::tt + QQQQQQQQ::::QQ ttttttttttt + Q:::::Q + QQQQQQ +""" + +# My crappy Qt code starts here + +# ░░░░░░░░░░░█▀▀░░█░░░░░░ +# ░░░░░░▄▀▀▀▀░░░░░█▄▄░░░░ +# ░░░░░░█░█░░░░░░░░░░▐░░░ +# ░░░░░░▐▐░░░░░░░░░▄░▐░░░ +# ░░░░░░█░░░░░░░░▄▀▀░▐░░░ +# ░░░░▄▀░░░░░░░░▐░▄▄▀░░░░ +# ░░▄▀░░░▐░░░░░█▄▀░▐░░░░░ +# ░░█░░░▐░░░░░░░░▄░█░░░░░ +# ░░░█▄░░▀▄░░░░▄▀▐░█░░░░░ +# ░░░█▐▀▀▀░▀▀▀▀░░▐░█░░░░░ +# ░░▐█▐▄░░▀░░░░░░▐░█▄▄░░░ +# ░░░▀▀▄░░░░░░░░▄▐▄▄▄▀░░░ +# ░░░░░░░░░░░░░░░░░░░░░░░ + + +# ------------------------------------------------------------------------------------------------------------------ # +# ------------------------------------------------------------------------------------------------------------------ # +# ===================================== Qt CODE STARTS HERE ====================================================== # +# ------------------------------------------------------------------------------------------------------------------ # +# ------------------------------------------------------------------------------------------------------------------ # +# to_css_prop(css_prop.replace('_','-'), value) +def _to_css_prop(key_, val_): + return "{}:{}; ".format(key_.replace('_', '-'), val_) +# def style_generate(qt_element_type, css_props_str): +# return '%s {\n %s \n}' % (qt_element_type, css_props_str) +_valid_css_fields = ['align-content', 'align-items', 'align-self', 'background', 'background-attachment', 'background-color', 'background-image', 'background-position', 'background-size', 'border', 'border-collapse', 'border-image', 'border-radius', 'border-spacing', 'bottom', 'box-decoration-break', 'caret-color', 'clear', 'clip-path', 'color', 'color-adjust', 'column-count', 'column-fill', 'column-gap', 'column-rule', 'column-rule-color', 'column-rule-style', 'column-rule-width', 'column-span', 'column-width', 'columns', 'contain', 'content', 'counter-increment', 'counter-reset', 'counter-set', 'cursor', 'direction', 'display', 'empty-cells', 'fill', 'filter', 'flex', 'flex-basis', 'flex-direction', 'flex-flow', 'flex-grow', 'flex-shrink', 'flex-wrap', 'float', 'font', 'font-display', 'font-family', 'font-feature-settings', 'font-kerning', 'font-optical-sizing', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-synthesis', 'font-variant', 'font-variant-numeric', 'font-weight', 'gap', 'grid-column', 'grid-row', 'grid-template-columns', 'grid-template-rows', 'hanging-punctuation', 'height', 'hyphens', 'image-rendering', 'initial-letter', 'inline-size', 'inset', 'inset-block', 'inset-block-end', 'inset-block-start', 'inset-inline', 'inset-inline-end', 'inset-inline-start', 'isolation', 'justify-content', 'left', 'letter-spacing', 'line-clamp', 'line-height', 'list-style', 'margin', 'mask-image', 'mask-position', 'mask-repeat', 'mask-size', 'max-height', 'max-width', 'min-height', 'min-width', 'mix-blend-mode', 'object-fit', 'object-position', 'offset-anchor', 'offset-distance', 'offset-path', 'offset-rotate', 'opacity', 'order', 'orphans', 'outline', 'outline-offset', 'overflow', 'overflow-anchor', 'overflow-wrap', 'overscroll-behavior', 'padding', 'page-break', 'paint-order', 'perspective', 'perspective-origin', 'place-items', 'pointer-events', 'position', 'quotes', 'resize', 'right', 'row-gap', 'scroll-behavior', 'scroll-margin', 'scroll-padding', 'scroll-snap-align', 'scroll-snap-stop', 'scroll-snap-type', 'scrollbar', 'scrollbar-color', 'scrollbar-gutter', 'scrollbar-width', 'shape-image-threshold', 'shape-margin', 'shape-outside', 'speak', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-width', 'tab-size', 'table-layout', 'text-align', 'text-align-last', 'text-decoration', 'text-decoration-color', 'text-decoration-line', 'text-decoration-skip', 'text-decoration-skip-ink', 'text-decoration-style', 'text-decoration-thickness', 'text-indent', 'text-justify', 'text-overflow', 'text-rendering', 'text-shadow', 'text-stroke', 'text-transform', 'text-underline-offset', 'text-underline-position', 'top', 'touch-action', 'transform', 'transform-origin', 'transform-style', 'transition', 'transition-delay', 'transition-duration', 'transition-property', 'transition-timing-function', 'unicode-bidi', 'unicode-range', 'user-select', 'vertical-align', 'visibility', 'white-space', 'widows', 'width', 'will-change', 'word-break', 'word-spacing', 'writing-mode', 'z-index', 'zoom'] +def is_valid_css_prop(a_css_prop): + '''Check if a given property EXISTS in qt Spec''' + return True + global _valid_css_fields + norm_ = a_css_prop.replace('_', '-') + return norm_ in _valid_css_fields + + +def PackFormIntoFrame(container_elem, containing_frame, toplevel_win): + """ + :param form: a window class + :type form: (Window) + :param containing_frame: ??? + :type containing_frame: ??? + :param toplevel_form: ??? + :type toplevel_form: (Window) + """ + # align2qt_align + align2qt_align = {'c': Qt.AlignCenter, 'l': Qt.AlignLeft, 'r': Qt.AlignRight} + + border_depth = toplevel_win.BorderDepth if toplevel_win.BorderDepth is not None else DEFAULT_BORDER_WIDTH + # --------------------------------------------------------------------------- # + # **************** Use FlexForm to build the tkinter window ********** ----- # + # Building is done row by row. # + # --------------------------------------------------------------------------- # + focus_set = False + ######################### LOOP THROUGH ROWS ######################### + # *********** ------- Loop through ROWS ------- ***********# + for row_num, flex_row in enumerate(container_elem.Rows): + ######################### LOOP THROUGH ELEMENTS ON ROW ######################### + # *********** ------- Loop through ELEMENTS ------- ***********# + # *********** Make TK Row ***********# + qt_row_layout = QHBoxLayout() + elem_align = container_elem.ElementJustification[0] + if elem_align in align2qt_align: + qt_row_layout.setAlignment(align2qt_align[elem_align]) + for col_num, element in enumerate(flex_row): + element.ParentForm = toplevel_win # save the button's parent form object + element.row_frame = qt_row_layout + if toplevel_win.Font and (element.Font == DEFAULT_FONT or not element.Font): + font = toplevel_win.Font + element.Font = font + elif element.Font is not None: + font = element.Font + else: + font = DEFAULT_FONT + # ------- Determine Auto-Size setting on a cascading basis ------- # + if element.AutoSizeText is not None: # if element overide + auto_size_text = element.AutoSizeText + elif toplevel_win.AutoSizeText is not None: # if form override + auto_size_text = toplevel_win.AutoSizeText + else: + auto_size_text = DEFAULT_AUTOSIZE_TEXT + element_type = element.Type + # Set foreground color + text_color = element.TextColor + # Determine Element size + element_size = element.Size + if (element_size == (None, None) and element_type not in (ELEM_TYPE_BUTTON, ELEM_TYPE_BUTTONMENU)): # user did not specify a size + element_size = toplevel_win.DefaultElementSize + elif (element_size == (None, None) and element_type in (ELEM_TYPE_BUTTON, ELEM_TYPE_BUTTONMENU)): + element_size = toplevel_win.DefaultButtonElementSize + else: + auto_size_text = False # if user has specified a size then it shouldn't autosize + full_element_pad = [0,0,0,0] # Top, Right, Bottom, Left + elementpad = element.Pad if element.Pad is not None else toplevel_win.ElementPadding + if type(elementpad[0]) is not tuple: # left and right + full_element_pad[1] = full_element_pad[3] = elementpad[0] + else: + full_element_pad[3], full_element_pad[1] = elementpad[0] + + if type(elementpad[1]) is not tuple: # top and bottom + full_element_pad[0] = full_element_pad[2] = elementpad[1] + else: + full_element_pad[0], full_element_pad[2] = elementpad[1] + + border_depth = toplevel_win.BorderDepth if toplevel_win.BorderDepth is not None else DEFAULT_BORDER_WIDTH + try: + if element.BorderWidth is not None: + border_depth = element.BorderWidth + except: + pass + + # ------------------------- COLUMN placement element ------------------------- # + if element_type == ELEM_TYPE_COLUMN: + element = element # type: Column + # column_widget = QWidget() + column_widget = QGroupBox() + element.Widget = element.QT_QGroupBox = column_widget + # column_widget.setFrameShape(QtWidgets.QFrame.NoFrame) + + # === style === + style = QtStyle('QGroupBox') + style['font'] = create_style_from_font(font) + if element.BackgroundColor is not None: + style['background_color'] = element.BackgroundColor + style['border'] = '0px solid gray' # FIXv2 + column_widget.setStyleSheet(style.build_css_string()) + element.qt_styles = (style,) + # === style === end + + column_layout = QFormLayout() + element.vbox_layout = column_vbox = QVBoxLayout() + PackFormIntoFrame(element, column_layout, toplevel_win) + + scroll = None + if element.Scrollable and (element_size[0] is not None or element_size[1] is not None): + scroll = QtWidgets.QScrollArea() + scroll.setWidget(column_widget) + if element_size[0] is not None: + scroll.setFixedWidth(element_size[0]) + if element_size[1] is not None: + scroll.setFixedHeight(element_size[1]) + scroll.setWidgetResizable(True) + + column_vbox.addLayout(column_layout) + column_widget.setLayout(column_vbox) + + # column_widget.setStyleSheet(style) + if not element.Visible: + column_widget.setVisible(False) + + qt_row_layout.addWidget(scroll if scroll else column_widget, alignment=Qt.AlignVCenter) + # ------------------------- TEXT placement element ------------------------- # + elif element_type == ELEM_TYPE_TEXT: + element.Widget = element.QT_Label = qlabel = QLabel(element.DisplayText, toplevel_win.QTWindow) + if element.Justification is not None: + justification = element.Justification + elif toplevel_win.TextJustification is not None: + justification = toplevel_win.TextJustification + else: + justification = DEFAULT_TEXT_JUSTIFICATION + + if justification[0] in align2qt_align: + element.QT_Label.setAlignment(align2qt_align[justification[0]]) + if not auto_size_text: + if element_size[0] is not None: + element.QT_Label.setFixedWidth(element_size[0]) + if element_size[1] is not None: + element.QT_Label.setFixedHeight(element_size[1]) + # element.QT_Label.setWordWrap(True) + + # === style === + style = QtStyle('QLabel') + style['font'] = create_style_from_font(font) + style['color'] = (element.TextColor, COLOR_SYSTEM_DEFAULT) + style['background_color'] = (element.BackgroundColor, COLOR_SYSTEM_DEFAULT) + style['margin'] = full_element_pad + element.QT_Label.setStyleSheet(str(style)) + element.qt_styles = (style,) + # === style === end + + if element.Relief is not None: + if element.Relief in (RELIEF_RIDGE, RELIEF_RAISED): + qlabel.setFrameStyle(QFrame.Panel | QFrame.Raised) + elif element.Relief in (RELIEF_SUNKEN, RELIEF_GROOVE): + qlabel.setFrameStyle(QFrame.Panel | QFrame.Sunken) + elif element.Relief == RELIEF_FLAT: + qlabel.setFrameStyle(QFrame.Panel | QFrame.NoFrame) + + if element.Margins is not None: + m = element.Margins + qlabel.setContentsMargins(m[0], m[2], m[1], m[3]) # L T B R + if element.Tooltip: element.QT_Label.setToolTip(element.Tooltip) + if element.ClickSubmits: element.QT_Label.mousePressEvent = element._QtCallbackTextClicked + if not element.Visible: + element.QT_Label.setVisible(False) + qt_row_layout.addWidget(element.QT_Label, alignment=Qt.AlignVCenter) + # ------------------------- BUTTON placement element ------------------------- # + elif element_type == ELEM_TYPE_BUTTON: + element = element #type: Button + btext = element.ButtonText + btype = element.BType + element.Widget = element.QT_QPushButton = QPushButton(btext) + # === style === + style = QtStyle('QPushButton') + style['font'] = create_style_from_font(font) + style['color'] = (element.TextColor, COLOR_SYSTEM_DEFAULT) + style['background_color'] = (element.BackgroundColor) + if element.BorderWidth == 0: + style['border'] = 'none' + style['margin'] = full_element_pad + # style['border'] = '{}px solid gray '.format(border_depth) + element.QT_QPushButton.setStyleSheet(style.build_css_string()) + element.qt_styles = (style,) + # === style === end + + # element.QT_QPushButton.setFlat(False) + if (element.AutoSizeButton is False or toplevel_win.AutoSizeButtons is False or element.Size[0] is not None) and element.ImageData is None: + if element_size[0] is not None: + element.QT_QPushButton.setFixedWidth(element_size[0]) + if element_size[1] is not None: + element.QT_QPushButton.setFixedHeight(element_size[1]) + + if element.ImageFilename is not None: + element.QT_QPushButton.setIcon(QtGui.QPixmap(element.ImageFilename)) + element.QT_QPushButton.setIconSize(QtGui.QPixmap(element.ImageFilename).rect().size()) + if element.ImageData: + ba = QtCore.QByteArray.fromBase64(element.ImageData) + pixmap = QtGui.QPixmap(); pixmap.loadFromData(ba) + element.QT_QPushButton.setIcon(pixmap) + element.QT_QPushButton.setIconSize(pixmap.rect().size()) + + if element.Disabled: + element.QT_QPushButton.setDisabled(True) + + if element.Tooltip: + element.QT_QPushButton.setToolTip(element.Tooltip) + element.QT_QPushButton.clicked.connect(element._ButtonCallBack) + if not element.Visible: + element.QT_QPushButton.setVisible(False) + + qt_row_layout.addWidget(element.QT_QPushButton, alignment=Qt.AlignVCenter) + # ------------------------- INPUT placement element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_TEXT: + element = element # type: InputText + default_text = element.DefaultText + element.Widget = element.QT_QLineEdit = qlineedit = QLineEdit() + + qlineedit.setAcceptDrops(True) + qlineedit.dragEnterEvent = element._dragEnterEvent + qlineedit.dropEvent = element._dropEvent + + if element.Justification[0] in align2qt_align: + element.QT_QLineEdit.setAlignment(align2qt_align[element.Justification[0]]) + element.QT_QLineEdit.setText(str(default_text)) + + # === style === + style = QtStyle('QLineEdit') + style['font'] = create_style_from_font(font) + if element.Disabled or element.ReadOnly: + if element.disabled_readonly_background_color: + style['background_color'] = (element.disabled_readonly_background_color, COLOR_SYSTEM_DEFAULT) + else: + style['background_color'] = (element.BackgroundColor, COLOR_SYSTEM_DEFAULT) + if element.disabled_readonly_text_color: + style['color'] = (element.disabled_readonly_text_color, COLOR_SYSTEM_DEFAULT) + else: + style['color'] = (element.TextColor, COLOR_SYSTEM_DEFAULT) + else: + style['background_color'] = (element.BackgroundColor, COLOR_SYSTEM_DEFAULT) + style['color'] = (element.TextColor, COLOR_SYSTEM_DEFAULT) + style['margin'] = full_element_pad + style['border'] = '{}px solid gray '.format(border_depth) + element.QT_QLineEdit.setStyleSheet(style.build_css_string()) + element.qt_styles = (style,) + # === style === end + + if element.AutoSizeText is False or toplevel_win.AutoSizeText is False or element.Size[0] is not None: + if element_size[0] is not None: + element.QT_QLineEdit.setFixedWidth(element_size[0]) + if element_size[1] is not None: + element.QT_QLineEdit.setFixedHeight(element_size[1]) + + if (element.Focus or toplevel_win.UseDefaultFocus) and not focus_set: + focus_set = True + toplevel_win.FocusElement = element.QT_QLineEdit + + if element.Disabled: + element.QT_QLineEdit.setDisabled(True) + + if element.ReadOnly: + element.QT_QLineEdit.setReadOnly(True) + + if element.ChangeSubmits: + element.QT_QLineEdit.textChanged.connect(element._QtCallbackFocusInEvent) + + element.QT_QLineEdit.returnPressed.connect(element._QtCallbackReturnPressed) + + if element.PasswordCharacter != '': + qlineedit.setEchoMode(QLineEdit.Password) + if element.Tooltip: + element.QT_QLineEdit.setToolTip(element.Tooltip) + + element.InputTextWidget = Input.InputTextWidget(element.QT_QLineEdit, element) + element.QT_QLineEdit.installEventFilter(element.InputTextWidget) + if not element.Visible: + element.QT_QLineEdit.setVisible(False) + qt_row_layout.addWidget(element.QT_QLineEdit, alignment=Qt.AlignVCenter) + # ------------------------- COMBO placement BOX (Drop Down) element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_COMBO: + element = element # type: Combo + element.Widget = element.QT_ComboBox = QComboBox() + + items_as_strings = [str(v) for v in element.Values] + # element.QT_ComboBox.addItems(element.Values) + element.QT_ComboBox.addItems(items_as_strings) + + # === style === + style = QtStyle('QComboBox') + style['font'] = create_style_from_font(font) + style['color'] = (element.TextColor, COLOR_SYSTEM_DEFAULT) + style['background_color'] = (element.BackgroundColor, COLOR_SYSTEM_DEFAULT) + style['border'] = '{}px solid gray '.format(border_depth) + style['margin'] = full_element_pad + + style2 = QtStyle('QListView') + style2['color'] = (element.TextColor, COLOR_SYSTEM_DEFAULT) + style2['background_color'] = (element.BackgroundColor, COLOR_SYSTEM_DEFAULT) + + element.QT_ComboBox.setStyleSheet(str(style)+str(style2)) + element.qt_styles = (style, style2) + # === style === end + + if element_size[0] is not None: + element.QT_ComboBox.setFixedWidth(element_size[0]) + if element_size[1] is not None: + element.QT_ComboBox.setFixedHeight(element_size[1]) + + if element.Disabled: + element.QT_ComboBox.setDisabled(True) + + element.QT_ComboBox.setMaxVisibleItems(element.VisibleItems) + if element.DefaultValue is not None: + for index, v in enumerate(element.Values): + if v == element.DefaultValue: + element.QT_ComboBox.setCurrentIndex(index) + break + + if element.ChangeSubmits: + element.QT_ComboBox.currentIndexChanged.connect(element._QtCurrentItemChanged) + if element.Tooltip: + element.QT_ComboBox.setToolTip(element.Tooltip) + if not element.Readonly: + element.QT_ComboBox.setEditable(True) + if not element.AutoComplete: + element.QT_ComboBox.setAutoCompletion(True) + if not element.Visible: + element.QT_ComboBox.setVisible(False) + qt_row_layout.addWidget(element.QT_ComboBox, alignment=Qt.AlignVCenter) + # ------------------------- OPTION MENU (Like ComboBox but different) element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_OPTION_MENU: + pass + # ------------------------- LISTBOX placement element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_LISTBOX: + element = element # type: Listbox + element.Widget = element.QT_ListWidget = QListWidget() + + # === style === + style = QtStyle('QListWidget') + style['font'] = create_style_from_font(font) + if element.TextColor is not None and element.TextColor != COLOR_SYSTEM_DEFAULT: + style['color'] = element.TextColor + if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + style['background-color'] = element.BackgroundColor # example for mike here + style['margin'] = full_element_pad + style['border'] = '{}px solid gray; '.format(border_depth) + element.QT_ListWidget.setStyleSheet(style.build_css_string()) + element.qt_styles = (style,) + # === style === end + + if not auto_size_text: + if element_size[0] is not None: + element.QT_ListWidget.setFixedWidth(element_size[0]) + if element_size[1] is not None: + element.QT_ListWidget.setFixedHeight(element_size[1]) + + if element.SelectMode == SELECT_MODE_MULTIPLE: + element.QT_ListWidget.setSelectionMode(QAbstractItemView.MultiSelection) + elif element.SelectMode == SELECT_MODE_EXTENDED: + element.QT_ListWidget.setSelectionMode(QAbstractItemView.ExtendedSelection) + elif element.SelectMode == SELECT_MODE_CONTIGUOUS: + element.QT_ListWidget.setSelectionMode(QAbstractItemView.ContiguousSelection) + elif element.SelectMode == SELECT_MODE_SINGLE: + element.QT_ListWidget.setSelectionMode(QAbstractItemView.SingleSelection) + if element.Disabled: element.QT_ListWidget.setDisabled(True) + if element.ChangeSubmits: element.QT_ListWidget.currentRowChanged.connect(element._QtCurrentRowChanged) + + # add all Values to the ListWidget + element.QT_ListWidget.addItems([str(v) for v in element.Values]) + # select the default items + for index, value in enumerate(element.Values): + item = element.QT_ListWidget.item(index) + if element.DefaultValues is not None and value in element.DefaultValues: + element.QT_ListWidget.setItemSelected(item, True) + + if element.Tooltip: + element.QT_ListWidget.setToolTip(element.Tooltip) + if not element.Visible: + element.QT_ListWidget.setVisible(False) + qt_row_layout.addWidget(element.QT_ListWidget, alignment=Qt.AlignVCenter) + # ------------------------- INPUT MULTILINE placement element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_MULTILINE: + element = element # type: Multiline + default_text = element.DefaultText + width, height = element_size + element.Widget = element.QT_TextEdit = QTextEdit() + + element.QT_TextEdit.setAcceptDrops(True) + element.QT_TextEdit.dragEnterEvent = element._dragEnterEvent + element.QT_TextEdit.dropEvent = element._dropEvent + + # === style === + style = QtStyle('QTextEdit') + style['font'] = create_style_from_font(font) + if element.TextColor is not None: style['color'] = element.TextColor + if element.BackgroundColor is not None: style['background-color'] = element.BackgroundColor + style['margin'] = full_element_pad + style['border'] = '{}px solid gray; '.format(border_depth) + element.QT_TextEdit.setStyleSheet(style.build_css_string()) + element.qt_styles = (style,) + # === style === end + + + if element.AutoSizeText is False or element.Size[0] is not None: + if element_size[0] is not None: + element.QT_TextEdit.setFixedWidth(element_size[0]) + if element_size[1] is not None: + element.QT_TextEdit.setFixedHeight(element_size[1]) + + if element.Disabled: + element.QT_TextEdit.setDisabled(True) + + element.MultiQWidget = Multiline.MultiQWidget(element.QT_TextEdit, element) + element.QT_TextEdit.installEventFilter(element.MultiQWidget) + + if element.ChangeSubmits: + element.QT_TextEdit.textChanged.connect(element._QtCallbackFocusInEvent) + + if (element.Focus or toplevel_win.UseDefaultFocus) and not focus_set: + focus_set = True + toplevel_win.FocusElement = element.QT_TextEdit + + element.QT_TextEdit.setText(str(default_text)) + element.QT_TextEdit.moveCursor(QtGui.QTextCursor.End) + if element.Tooltip: + element.QT_TextEdit.setToolTip(element.Tooltip) + # qt_row_layout.setContentsMargins(*full_element_pad) + if not element.Visible: + element.QT_TextEdit.setVisible(False) + qt_row_layout.addWidget(element.QT_TextEdit, alignment=Qt.AlignVCenter) + # ------------------------- OUTPUT MULTILINE placement element ------------------------- # + elif element_type == ELEM_TYPE_MULTILINE_OUTPUT: + element = element # type: MultilineOutput + default_text = element.DefaultText + element.Widget = element.QT_TextBrowser = QTextBrowser() + element.QT_TextBrowser.setDisabled(False) + + # === style === + style = QtStyle('QTextBrowser') + style['font'] = create_style_from_font(font) + if element.TextColor is not None: style['color'] = element.TextColor + if element.BackgroundColor is not None: style['background-color'] = element.BackgroundColor + style['margin'] = full_element_pad + style['border'] = '{}px solid gray'.format(border_depth) + element.QT_TextBrowser.setStyleSheet(style.build_css_string()) + element.qt_styles = (style,) + # === style === end + + + if element.AutoSizeText is False or element.Size[0] is not None: + if element_size[0] is not None: + element.QT_TextBrowser.setFixedWidth(element_size[0]) + if element_size[1] is not None: + element.QT_TextBrowser.setFixedHeight(element_size[1]) + + element.QT_TextBrowser.insertPlainText(default_text) + element.QT_TextBrowser.moveCursor(QtGui.QTextCursor.End) + if element.Tooltip: + element.QT_TextBrowser.setToolTip(element.Tooltip) + # qt_row_layout.setContentsMargins(*full_element_pad) + if not element.Visible: + element.QT_TextBrowser.setVisible(False) + qt_row_layout.addWidget(element.QT_TextBrowser, alignment=Qt.AlignVCenter) + # ------------------------- INPUT CHECKBOX placement element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_CHECKBOX: + element = element # type: Checkbox + element.QT_Checkbox = QCheckBox(element.Text) + element.QT_Checkbox.setChecked(element.InitialState) + if element.Disabled: + element.QT_Checkbox.setDisabled(True) + + # === style === + style = QtStyle('QCheckBox') + style['font'] = create_style_from_font(font) + if element.TextColor is not None: style['color'] = element.TextColor + if element.BackgroundColor is not None: style['background-color'] = element.BackgroundColor + style['margin'] = full_element_pad + element.QT_Checkbox.setStyleSheet(style.build_css_string()) + element.qt_styles = (style,) + # === style === end + + + if element.AutoSizeText is False or element.Size[0] is not None: + if element_size[0] is not None: + element.QT_Checkbox.setFixedWidth(element_size[0]) + if element_size[1] is not None: + element.QT_Checkbox.setFixedHeight(element_size[1]) + if element.ChangeSubmits: + element.QT_Checkbox.stateChanged.connect(element.QtCallbackStateChanged) + # qt_row_layout.setContentsMargins(*full_element_pad) + if element.Tooltip: + element.QT_Checkbox.setToolTip(element.Tooltip) + if not element.Visible: + element.QT_Checkbox.setVisible(False) + qt_row_layout.addWidget(element.QT_Checkbox, alignment=Qt.AlignVCenter) + # ------------------------- PROGRESSBAR placement element ------------------------- # + elif element_type == ELEM_TYPE_PROGRESS_BAR: + element.Widget = element.QT_QProgressBar = QProgressBar() + orientation = element.Orientation.lower()[0] + if element.Size[0] is not None: + if element_size[0] is not None: + element.QT_QProgressBar.setFixedWidth(element_size[orientation != 'h']) + if element_size[1] is not None: + element.QT_QProgressBar.setFixedHeight(element_size[orientation == 'h']) + + element.QT_QProgressBar.setMaximum(element.MaxValue) + element.QT_QProgressBar.setValue(element.StartValue) + if element.Orientation.lower().startswith('v'): + element.QT_QProgressBar.setOrientation(QtCore.Qt.Vertical) + + # === style === + style = QtStyle('QProgressBar') + style_chunk = QtStyle('QProgressBar::chunk') + style['margin'] = full_element_pad + # style += 'margin: {}px {}px {}px {}px;'.format(*full_element_pad) + # style += 'border: {}px solid gray; '.format(border_depth) + if element.BarColor != (None, None): + if element.BarColor[0] is not None: + style_chunk['background-color'] = element.BarColor[0] + + style['border'] = '%spx solid grey' % border_depth + style['border-radius'] = '0px' + style['background-color'] = str(element.BarColor[1] \ + if element.BarColor[1] is not None \ + else DEFAULT_PROGRESS_BAR_COLOR[1]) + + + element.QT_QProgressBar.setStyleSheet(style.build_css_string()+style_chunk.build_css_string()) + element.qt_styles = (style, style_chunk) + # === style === end + + element.QT_QProgressBar.setTextVisible(False) + if element.Tooltip: + element.QT_QProgressBar.setToolTip(element.Tooltip) + if not element.Visible: + element.QT_QProgressBar.setVisible(False) + + qt_row_layout.addWidget(element.QT_QProgressBar, alignment=Qt.AlignVCenter) + # ------------------------- INPUT RADIO placement element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_RADIO: + element = element # type: Radio + default_value = element.InitialState + element.Widget = qradio = QRadioButton(element.Text) + element.QT_Radio_Button = qradio + if element.Disabled: + element.QT_Radio_Button.setDisabled(True) + if default_value: qradio.setChecked(True) + + # === style === + style = QtStyle('QRadioButton') + style['font'] = create_style_from_font(font) + if element.TextColor is not None: style['color'] = element.TextColor + if element.BackgroundColor is not None: style['background-color'] = element.BackgroundColor + style['margin'] = full_element_pad + element.QT_Radio_Button.setStyleSheet(style.build_css_string()) + element.qt_styles = (style,) + # === style === end + + if element.AutoSizeText is False or element.Size[0] is not None: + if element_size[0] is not None: + element.QT_Radio_Button.setFixedWidth(element_size[0]) + if element_size[1] is not None: + element.QT_Radio_Button.setFixedHeight(element_size[1]) + + if element.GroupID in toplevel_win.RadioDict: + element.QT_RadioButtonGroup = toplevel_win.RadioDict[element.GroupID] + else: + element.QT_RadioButtonGroup = QButtonGroup(toplevel_win.QTApplication) + toplevel_win.RadioDict[element.GroupID] = element.QT_RadioButtonGroup + element.QT_RadioButtonGroup.setExclusive(True) + + element.QT_RadioButtonGroup.addButton(element.QT_Radio_Button) + + if element.ChangeSubmits: + element.QT_Radio_Button.toggled.connect(element._QtCallbackValueChanged) + + # qt_row_layout.setContentsMargins(*full_element_pad) + if element.Tooltip: + element.QT_Radio_Button.setToolTip(element.Tooltip) + if not element.Visible: + element.QT_Radio_Button.setVisible(False) + qt_row_layout.addWidget(element.QT_Radio_Button, alignment=Qt.AlignVCenter) + # ------------------------- INPUT SPIN placement element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_SPIN: + # element.QT_Spinner = QSpinBox() + element = element # type: Spin + element.Widget = element.QT_Spinner = Spin.StringBox(element.Values) + if element.DefaultValue is not None: # try to set the default value without crashing on error + try: + element.QT_Spinner.setValue(element.QT_Spinner.valueFromText(element.DefaultValue)) + except: + pass + # === style === + style = QtStyle('QSpinBox') + style['font'] = create_style_from_font(font) + if element.TextColor is not None: style['color'] = element.TextColor + if element.BackgroundColor is not None: style['background-color'] = element.BackgroundColor + style['margin'] = full_element_pad + style['border'] = '{}px solid gray'.format(border_depth) + element.QT_Spinner.setStyleSheet(style.build_css_string()) + element.qt_styles = (style,) + # === style === end + + # element.QT_Spinner.setRange(element.Values[0], element.Values[1]) + if not auto_size_text: + if element_size[0] is not None: + element.QT_Spinner.setFixedWidth(element_size[0]) + if element_size[1] is not None: + element.QT_Spinner.setFixedHeight(element_size[1]) + + if element.Disabled: + element.QT_Spinner.setDisabled(True) + if element.ChangeSubmits: + element.QT_Spinner.valueChanged.connect(element._QtCallbackValueChanged) + if element.Tooltip: + element.QT_Spinner.setToolTip(element.Tooltip) + if not element.Visible: + element.QT_Spinner.setVisible(False) + qt_row_layout.addWidget(element.QT_Spinner, alignment=Qt.AlignVCenter) + # ------------------------- OUTPUT placement element ------------------------- # + elif element_type == ELEM_TYPE_OUTPUT: + element = element # type: Output + element.Widget = element.QT_TextBrowser = QTextBrowser() + element.QT_TextBrowser.setDisabled(False) + + # === style === + style = QtStyle('QTextBrowser') + style['font'] = create_style_from_font(font) + if element.TextColor is not None: style['color'] = element.TextColor + if element.BackgroundColor is not None: style['background-color'] = element.BackgroundColor + style['margin'] = full_element_pad + style['border'] = '{}px solid gray'.format(border_depth) + # style += "QScrollBar:vertical {border: none; background:lightgray; width:12px; margin: 0px 0px 0px 0px; } " + element.QT_TextBrowser.setStyleSheet(style.build_css_string()) + element.qt_styles = (style,) + # === style === end + + if element.AutoSizeText is False or element.Size[0] is not None: + if element_size[0] is not None: + element.QT_TextBrowser.setFixedWidth(element_size[0]) + if element_size[1] is not None: + element.QT_TextBrowser.setFixedHeight(element_size[1]) + + element.QT_TextBrowser.moveCursor(QtGui.QTextCursor.End) + element._reroute_stdout() + if element.Tooltip: + element.QT_TextBrowser.setToolTip(element.Tooltip) + if not element.Visible: + element.QT_TextBrowser.setVisible(False) + qt_row_layout.addWidget(element.QT_TextBrowser, alignment=Qt.AlignVCenter) + # ------------------------- IMAGE placement element ------------------------- # + elif element_type == ELEM_TYPE_IMAGE: + element = element # type: Image + element.Widget = element.QT_QLabel = qlabel = QLabel() + if element.Filename is not None: + qlabel.setText('') + w = QtGui.QPixmap(element.Filename).width() + h = QtGui.QPixmap(element.Filename).height() + qlabel.setGeometry(QtCore.QRect(0, 0, w, h)) + qlabel.setPixmap(QtGui.QPixmap(element.Filename)) + elif element.Data is not None: + qlabel.setText('') + ba = QtCore.QByteArray.fromRawData(element.Data) + pixmap = QtGui.QPixmap() + pixmap.loadFromData(ba) + qlabel.setPixmap(pixmap) + elif element.DataBase64: + qlabel.setText('') + ba = QtCore.QByteArray.fromBase64(element.DataBase64) + pixmap = QtGui.QPixmap() + pixmap.loadFromData(ba) + qlabel.setPixmap(pixmap) + + # === style === + style = QtStyle('QLabel') + style['margin'] = full_element_pad + element.QT_QLabel.setStyleSheet(style.build_css_string()) + element.qt_styles = (style,) + # === style === end + + if element.Tooltip: element.QT_QLabel.setToolTip(element.Tooltip) + if element.ClickSubmits: + element.QT_QLabel.mousePressEvent = element.QtCallbackImageClicked + if not element.Visible: + element.QT_QLabel.setVisible(False) + qt_row_layout.addWidget(element.QT_QLabel, alignment=Qt.AlignVCenter) + # ------------------------- Canvas placement element ------------------------- # + elif element_type == ELEM_TYPE_CANVAS: + width, height = element_size + # ------------------------- Graph placement element ------------------------- # + elif element_type == ELEM_TYPE_GRAPH: + element = element # type: Graph + width, height = element_size + # print(f'Graph element size = {element_size}') + element.Widget = element.QT_QGraphicsView = qgraphicsview = QGraphicsView() + # element.QT_QGraphicsView.setGeometry(0,0,element.CanvasSize[0],element.CanvasSize[1]) + # print(f'Graph Canvas size = {element.CanvasSize}') + + element.QT_QGraphicsScene = QGraphicsScene() + element.QT_QGraphicsScene.setSceneRect(0,0,element.CanvasSize[0],element.CanvasSize[1]) + element.QT_QGraphicsView.setScene(element.QT_QGraphicsScene) + + # === style === + style = QtStyle('QGraphicsView') + style['background_color'] = (element.BackgroundColor, COLOR_SYSTEM_DEFAULT) + style['margin'] = full_element_pad + style['border'] = '{}px solid gray '.format(border_depth) + # print(f'style content = {style.content}') + element.QT_QGraphicsView.setStyleSheet(style.build_css_string()) + element.qt_styles = (style,) + # === style === end + + qgraphicsview.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) + qgraphicsview.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) + # qt_row_layout.setContentsMargins(*full_element_pad) + if element.Tooltip: + element.QT_QGraphicsView.setToolTip(element.Tooltip) + if not element.Visible: + element.QT_QGraphicsView.setVisible(False) + qt_row_layout.addWidget(element.QT_QGraphicsView, alignment=Qt.AlignVCenter) + # ------------------------- MENUBAR placement element ------------------------- # + elif element_type == ELEM_TYPE_MENUBAR: + element = element # type: Menu + menu_def = element.MenuDefinition + element.Widget = element.QT_QMenuBar = QMenuBar(toplevel_win.QT_QMainWindow) + + for menu_entry in menu_def: + # print(f'Adding a Menubar ENTRY {menu_entry}') + baritem = QMenu(element.QT_QMenuBar) + if menu_entry[0][0] == MENU_DISABLED_CHARACTER: + baritem.setDisabled(True) + baritem.setTitle(menu_entry[0][1:]) + else: + baritem.setTitle(menu_entry[0]) + element.QT_QMenuBar.addAction(baritem.menuAction()) + AddMenuItem(baritem, menu_entry[1], element) + # === style === + menu_style = QtStyle('QMenu') + menu_style['font'] = create_style_from_font(font) + if element.MenuItemTextColor is not None and element.MenuItemTextColor != COLOR_SYSTEM_DEFAULT: + menu_style['color'] = element.MenuItemTextColor + if element.MenuItemBackgroundColor is not None and element.MenuItemBackgroundColor != COLOR_SYSTEM_DEFAULT: + menu_style['background-color'] = element.MenuItemBackgroundColor + # style['margin'] = full_element_pad + baritem.setStyleSheet(menu_style.build_css_string()) + # === style === end + + + if element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + # === style === + style = QtStyle('QMenuBar') + style['background_color'] = (element.BackgroundColor, COLOR_SYSTEM_DEFAULT) + element.QT_QMenuBar.setStyleSheet(style.build_css_string()) + element.qt_styles = (style,) + # === style === end + + if not element.Visible: + element.QT_QMenuBar.setVisible(False) + toplevel_win.QT_QMainWindow.setMenuBar(element.QT_QMenuBar) + # ------------------------- BUTTONMENU placement element ------------------------- # + elif element_type == ELEM_TYPE_BUTTONMENU: + btext = element.ButtonText + element.Widget = element.QT_QPushButton = QPushButton(btext) + + # === style === + style = QtStyle('QPushButton') + style['font'] = create_style_from_font(font) + if element.TextColor is not None and element.TextColor != COLOR_SYSTEM_DEFAULT: + style['color'] = element.TextColor + if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + style['background-color'] = element.BackgroundColor + if element.BorderWidth == 0: + style['border'] = 'none' + style['margin'] = full_element_pad + element.QT_QPushButton.setStyleSheet(style.build_css_string()) + element.qt_styles = (style,) + # === style === end + + + if (element.AutoSizeButton is False or toplevel_win.AutoSizeButtons is False or element.Size[0] is not None) and element.ImageData is None: + if element_size[0] is not None: + element.QT_QPushButton.setFixedWidth(element_size[0]) + if element_size[1] is not None: + element.QT_QPushButton.setFixedHeight(element_size[1]) + + if element.ImageData: + ba = QtCore.QByteArray.fromBase64(element.ImageData) + pixmap = QtGui.QPixmap() + pixmap.loadFromData(ba) + element.QT_QPushButton.setIcon(pixmap) + element.QT_QPushButton.setIconSize(pixmap.rect().size()) + + if element.Disabled: + element.QT_QPushButton.setDisabled(True) + + if element.Tooltip: + element.QT_QPushButton.setToolTip(element.Tooltip) + # element.QT_QPushButton.clicked.connect(element._ButtonCallBack) + + menu_def = element.MenuDefinition + + qmenu = QMenu(element.QT_QPushButton) + qmenu.setTitle(menu_def[0]) + AddMenuItem(qmenu, menu_def[1], element) + + # === style === + menu_style = QtStyle('QMenu') + menu_style['font'] = create_style_from_font(font) + if element.TextColor is not None and element.TextColor != COLOR_SYSTEM_DEFAULT: + menu_style['color'] = element.TextColor + if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + menu_style['background-color'] = element.BackgroundColor + # style['margin'] = full_element_pad + qmenu.setStyleSheet(menu_style.build_css_string()) + # element.qt_styles = (style,) + # === style === end + + element.QT_QPushButton.setMenu(qmenu) + if element.Tooltip: + element.QT_QPushButton.setToolTip(element.Tooltip) + if not element.Visible: + element.QT_QPushButton.setVisible(False) + qt_row_layout.addWidget(element.QT_QPushButton, alignment=Qt.AlignVCenter) + # ------------------------- Frame placement element ------------------------- # + elif element_type == ELEM_TYPE_FRAME: + element = element # type: Frame + element.Widget = column_widget = QGroupBox() + element.QT_QGroupBox = column_widget + + # === style === + style = QtStyle('QGroupBox') + # style['font'] = create_style_from_font(font) + if element.TextColor is not None: style['color'] = element.TextColor + if element.BackgroundColor is not None: style['background-color'] = element.BackgroundColor + # style['origin'] = 'margin' + style['font'] = create_style_from_font(font) + if element.FrameColor is not None: + style['border'] = '{}px solid {} '.format(border_depth, element.FrameColor) + else: + style['border'] = '{}px solid {} '.format(border_depth, 'gainsboro') # default to a light gray + + + # style['padding'] = (10,10,10,10) + # style['margin'] = full_element_pad + # style['padding'] = (0,15,15,15) + # style['padding'] = (10,10,10,10) + style['margin-top'] = '10px' + # style['top'] = '60px' + # style['margin'] = (0,0,0,0) + style['origin'] = 'margin' + + style_title = QtStyle('QGroupBox::title') + # style_title['padding'] = (0,5,0,5) + style_title['margin'] = (0,0,0,0) + + style_title['left'] = '15px' + # style_title['margin-top'] = '-20px' + # style_title['top'] = '20px' + style_title['subcontrol-origin'] = 'margin' + # style_title['subcontrol-origin'] = 'border' + + # style_title['subcontrol-origin'] = 'padding' + style_title['subcontrol-position'] = 'top left' + + column_widget.setStyleSheet(str(style)+str(style_title)) + # column_widget.setStyleSheet(str(style)) + # print(element.Widget.styleSheet()) + element.qt_styles = (style, ) + # === style === end + + column_widget.setTitle(element.Title) + + column_layout, column_vbox = QFormLayout(), QVBoxLayout() + PackFormIntoFrame(element, column_layout, toplevel_win) + column_vbox.addLayout(column_layout) + column_widget.setLayout(column_vbox) + + # Add a padding groupbox + pad_layout, pad_vbox = QFormLayout(), QVBoxLayout() + pad_groupbox = QGroupBox() + + pad_vbox.addLayout(pad_layout) + pad_groupbox.setLayout(pad_vbox) + pad_vbox.addWidget(column_widget) + + pad_layout.setSpacing(0) + pad_vbox.setSpacing(0) + # === style === + style = QtStyle('QGroupBox') + # style['font'] = create_style_from_font(font) + style['border'] = '0px' + style['margin'] = (0,0,0,0) + # style['margin'] = full_element_pad + + style['padding'] = (0,0,0,0) + style['margin-top'] = '0px' + style['origin'] = 'content' + style_title = QtStyle('QGroupBox::title') + style_title['subcontrol-origin'] = 'content' + + style_title['padding'] = (0,0,0,0) + style_title['margin'] = (0,0,0,0) + pad_groupbox.setStyleSheet(str(style)+str(style_title)) + # === style === end + + + if element.Tooltip: + column_widget.setToolTip(element.Tooltip) + if not element.Visible: + element.QT_QGroupBox.setVisible(False) + + qt_row_layout.addWidget(pad_groupbox) + # qt_row_layout.addWidget(column_widget) + # ------------------------- Tab placement element ------------------------- # + elif element_type == ELEM_TYPE_TAB: + element.Widget = tab_widget = QWidget() + element.QT_QWidget = tab_widget + # tab_widget.setFrameShape(QtWidgets.QFrame.NoFrame) + + # === style === + style = QtStyle('QTabWidget') + style['font'] = create_style_from_font(font) + if element.BackgroundColor is not None: + # style += 'background-color: %s;' % element.BackgroundColor + # style += 'QTabWidget > QWidget > QWidget {background: %s;}'% element.BackgroundColor + style['background-color'] = element.BackgroundColor + style.my_anchor = '::pane' + # style += 'background-color: %s;' % element.BackgroundColor + tab_widget.setAutoFillBackground(True) + palette = tab_widget.palette() + palette.setColor(tab_widget.backgroundRole(), element.BackgroundColor) + tab_widget.setPalette(palette) + + # style += 'border: {}px solid gray; '.format(border_depth) + style['margin'] = full_element_pad + tab_widget.setStyleSheet(style.build_css_string()) + element.qt_styles = (style,) + # === style === end + + + column_layout, column_vbox = QFormLayout(), QVBoxLayout() + + PackFormIntoFrame(element, column_layout, toplevel_win) + + column_vbox.addLayout(column_layout) + tab_widget.setLayout(column_vbox) + if element.Tooltip: + tab_widget.setToolTip(element.Tooltip) + if not element.Visible: + element.QT_QWidget.setVisible(False) + container_elem.QT_QTabWidget.addTab(tab_widget, element.Title) + # ------------------------- TabGroup placement element ------------------------- # + elif element_type == ELEM_TYPE_TAB_GROUP: + element = element # type:TabGroup + element.Widget = element.QT_QTabWidget = qtab =QTabWidget() + + # === style === + style = QtStyle('QTabWidget') + # print(f'qtab.styleSheet() -> {qtab.styleSheet()}') + # style = qtab.styleSheet() # FIXv2 + if element.SelectedTitleColor not in (None, COLOR_SYSTEM_DEFAULT): + style.my_anchor = '::tab:selected' + style['background'] = element.SelectedTitleColor + if element.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT): + style.my_anchor = '::tab' + style['background'] = element.BackgroundColor + if element.TextColor not in (None, COLOR_SYSTEM_DEFAULT): + style.my_anchor = '::tab' + style['color'] = element.TextColor + style['margin'] = full_element_pad + qtab.setStyleSheet(style.build_css_string()) + element.qt_styles = (style,) + # === style === end + + if element.TabLocation is not None: + position_dict = {'left': QtWidgets.QTabWidget.TabPosition.West, 'right': QtWidgets.QTabWidget.TabPosition.East, 'top': QtWidgets.QTabWidget.TabPosition.North, 'bottom': QtWidgets.QTabWidget.TabPosition.South, 'lefttop': QtWidgets.QTabWidget.TabPosition.North, + 'leftbottom': QtWidgets.QTabWidget.TabPosition.South, 'righttop': QtWidgets.QTabWidget.TabPosition.North, 'rightbottom': QtWidgets.QTabWidget.TabPosition.South, 'bottomleft': QtWidgets.QTabWidget.TabPosition.South, + 'bottomright': QtWidgets.QTabWidget.TabPosition.South, 'topleft': QtWidgets.QTabWidget.TabPosition.North, 'topright': QtWidgets.QTabWidget.TabPosition.North} + try: + element.Widget.setTabPosition(position_dict[element.TabLocation]) + except: + print('Bad tab position specified {}', element.TabLocation) + PackFormIntoFrame(element, element.ParentForm.QFormLayout, toplevel_win) + + qt_row_layout.addWidget(element.QT_QTabWidget, alignment=Qt.AlignVCenter) + if not element.Visible: + element.QT_QTabWidget.setVisible(False) + + if element.ChangeSubmits: + element.QT_QTabWidget.currentChanged.connect(element.QtCallbackStateChanged) + # ------------------------- SLIDER placement element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_SLIDER: + element = element # type: Slider + element.Widget = element.QT_Slider = QSlider() + element.QT_Slider.setOrientation(Qt.Horizontal if element.Orientation.startswith('h') else Qt.Vertical) + if element.Disabled: element.QT_Slider.setDisabled(True) + + # === style === + style = QtStyle('QSlider') + style['font'] = create_style_from_font(font) + if element.BackgroundColor is not None: style['background-color'] = element.BackgroundColor + style['margin'] = full_element_pad + style['border'] = '{}px solid gray'.format(border_depth) + element.QT_Slider.setStyleSheet(style.build_css_string()) + element.qt_styles = (style,) + # === style === end + + element.QT_Slider.setMinimum(element.Range[0]); element.QT_Slider.setMaximum(element.Range[1]) + position = QSlider.TicksBothSides + if element.Relief == RELIEF_TICK_POSITION_NO_TICKS: + position = QSlider.NoTicks + elif element.Relief == RELIEF_TICK_POSITION_BOTH_SIDES: + position = QSlider.TicksBothSides + elif element.Relief == RELIEF_TICK_POSITION_ABOVE: + position = QSlider.TicksAbove + elif element.Relief == RELIEF_TICK_POSITION_BELOW: + position = QSlider.TicksBelow + elif element.Relief == RELIEF_TICK_POSITION_LEFT: + position = QSlider.TicksLeft + elif element.Relief == RELIEF_TICK_POSITION_RIGHT: + position = QSlider.TicksRight + element.QT_Slider.setTickPosition(position) + + if element.TickInterval is not None: + element.QT_Slider.setTickInterval(element.TickInterval) + if element_size[0] is not None: element.QT_Slider.setFixedWidth(element_size[0]) + if element_size[1] is not None: element.QT_Slider.setFixedHeight(element_size[1]) + if element.Resolution is not None: + element.QT_Slider.setSingleStep(element.Resolution) + element.QT_Slider.setPageStep(element.Resolution) + element.QT_Slider.setValue(element.DefaultValue) + + if element.ChangeSubmits: + element.QT_Slider.valueChanged.connect(element._QtCallbackValueChanged) + if element.Tooltip: + element.QT_Slider.setToolTip(element.Tooltip) + if not element.Visible: + element.QT_Slider.setVisible(False) + qt_row_layout.addWidget(element.QT_Slider, alignment=Qt.AlignVCenter) + # ------------------------- DIAL placement element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_DIAL: + element.Widget = element.QT_Dial = qdial = QDial() + + # === style === + style = QtStyle('QDial') + style['font'] = create_style_from_font(font) + if element.BackgroundColor is not None: style['background-color'] = element.BackgroundColor + style['margin'] = full_element_pad + style['border'] = '{}px solid gray'.format(border_depth) + element.QT_Dial.setStyleSheet(style.build_css_string()) + element.qt_styles = (style,) + # === style === end + + if element.Disabled: element.QT_Dial.setDisabled(True) + element.QT_Dial.setMinimum(element.Range[0]); element.QT_Dial.setMaximum(element.Range[1]) + element.QT_Dial.setValue(element.DefaultValue) + qdial.setNotchesVisible(True) + if element.TickInterval is not None: qdial.setNotchTarget(element.TickInterval) + if element.Resolution is not None: element.QT_Dial.setSingleStep(element.Resolution) + if element_size[0] is not None: element.QT_Dial.setFixedWidth(element_size[0]) + if element_size[1] is not None: element.QT_Dial.setFixedHeight(element_size[1]) + if element.ChangeSubmits: + element.QT_Dial.valueChanged.connect(element._QtCallbackValueChanged) + if element.Tooltip: + element.QT_Dial.setToolTip(element.Tooltip) + # qt_row_layout.setContentsMargins(*full_element_pad) + if not element.Visible: + element.QT_Dial.setVisible(False) + qt_row_layout.addWidget(element.QT_Dial, alignment=Qt.AlignVCenter) + # ------------------------- Stretch placement element ------------------------- # + elif element_type == ELEM_TYPE_STRETCH: + element = element # type: Stretch + element.Widget = qt_row_layout.addStretch(1) + # ------------------------- TABLE placement element ------------------------- # + elif element_type == ELEM_TYPE_TABLE: + element = element # type: Table + element.Widget = element.QT_TableWidget = Table.QTTableWidget(toplevel_win.ReturnKeyboardEvents, toplevel_win) + if element.NumRows is not None: + element.QT_TableWidget.setFixedHeight(element.NumRows*35+25) + # element.QT_TableWidget = QTableWidget() + # === style === + + style = QtStyle('QTableWidget') + style['font'] = create_style_from_font(font) + if element.TextColor is not None: style['color'] = element.TextColor + if element.BackgroundColor is not None: style['background-color'] = element.BackgroundColor + style['margin'] = full_element_pad + style['border'] = '{}px solid gray'.format(border_depth) + + # more css: ScrollBar + style.append_css_to_end.append(" QScrollBar:vertical {border: none; background:lightgray; width:12px; margin: 0px 0px 0px 0px; } ") + # more css: QHeaderView + header_style = QtStyle('QHeaderView::section') + header_style['font'] = create_style_from_font(element.HeaderFont if element.HeaderFont is not None else font) + header_style['background-color'] = element.HeaderBackgroundColor + header_style['color'] = element.HeaderTextColor + + element.QT_TableWidget.setStyleSheet(style.build_css_string() + header_style.build_css_string()) + element.qt_styles = (style, header_style) + # === style === end + + if element.ChangeSubmits: + element.QT_TableWidget.itemSelectionChanged.connect(element._QtCallbackCellActivated) + element.QT_TableWidget.setRowCount(len(element.Values)) + element.QT_TableWidget.setColumnCount(len(element.Values[0])) + for rownum, rows in enumerate(element.Values): + # element.QT_TableWidget.insertRow(rownum) + for colnum, columns in enumerate(rows): + element.QT_TableWidget.setItem(rownum, colnum, QTableWidgetItem(element.Values[rownum][colnum])) + + if element.ColumnHeadings is not None: + element.QT_TableWidget.setHorizontalHeaderLabels(element.ColumnHeadings) + + element.QT_TableWidget.installEventFilter(element.QT_TableWidget) + element.QT_TableWidget.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents) + if element.Tooltip: + element.QT_TableWidget.setToolTip(element.Tooltip) + if not element.Visible: + element.QT_TableWidget.setVisible(False) + + qt_row_layout.addWidget(element.QT_TableWidget, alignment=Qt.AlignVCenter) + # ------------------------- Tree placement element ------------------------- # + elif element_type == ELEM_TYPE_TREE: + element = element # type: Tree + element.Widget = element.QT_QTreeWidget = QTreeWidget() + if element_size != (None, None): + element.QT_QTreeWidget.setFixedWidth(element_size[0]) + element.QT_QTreeWidget.setFixedHeight(element_size[1]) + height = element.NumRows + element.QT_QTreeWidget.setFixedHeight(height*25) # convert num rows into pixels...crude but effective + + if element.ColumnsToDisplay is None: # Which cols to display + displaycolumns = element.ColumnHeadings + else: + displaycolumns = [] + for i, should_display in enumerate(element.ColumnsToDisplay): + if should_display: + displaycolumns.append(element.ColumnHeadings[i]) + column_headings = element.ColumnHeadings + # ------------- GET THE TREEVIEW WIDGET ------------- + for i, heading in enumerate(element.ColumnHeadings): # Configure cols + headings + # QTree.heading(heading, text=heading) + if element.AutoSizeColumns: + width = min(element.MaxColumnWidth, len(heading) + 1) + else: + try: + width = element.ColumnWidths[i] + except: + width = element.DefaultColumnWidth + # treeview.column(heading, width=width * CharWidthInPixels(), anchor=anchor) + def add_treeview_data(node, widget): + # print(f'Inserting {node.key} under parent {node.parent}') + child = widget + if node != element.TreeData.root_node: + child = QTreeWidgetItem(widget) + child.setText(0, str(node.text)) + # if node.key != '': + # child.setData(0,0,node.values) + if type(node.icon) is bytes: + ba = QtCore.QByteArray.fromBase64(node.icon) + pixmap = QtGui.QPixmap() + pixmap.loadFromData(ba) + qicon = QIcon(pixmap) + child.setIcon(0, qicon) + elif node.icon is not None: + qicon = QIcon(node.icon) + child.setIcon(0, qicon) + + for node in node.children: + add_treeview_data(node, child) + + # for node in element.TreeData.root_node.children: + # add_treeview_data(node, element.QT_QTreeWidget) + + add_treeview_data(element.TreeData.root_node, element.QT_QTreeWidget) + + # === style === + style = QtStyle('QTreeWidget') + style['font'] = create_style_from_font(font) + if element.TextColor is not None: style['color'] = element.TextColor + if element.BackgroundColor is not None: style['background-color'] = element.BackgroundColor + style['margin'] = full_element_pad + style['border'] = '{}px solid gray'.format(border_depth) + style.append_css_to_end.append(" QScrollBar:vertical {border: none; background:lightgray; width:12px; margin: 0px 0px 0px 0px; } ") + + header_style = QtStyle('QHeaderView::section') + header_style['font'] = create_style_from_font(element.HeaderFont if element.HeaderFont is not None else font) + header_style['background-color'] = element.HeaderBackgroundColor + header_style['color'] = element.HeaderTextColor + + element.QT_QTreeWidget.setStyleSheet(style.build_css_string() + header_style.build_css_string()) + element.qt_styles = (style, header_style) + # === style === end + + + if element.ChangeSubmits: + element.QT_QTreeWidget.itemSelectionChanged.connect(element._QtCallbackCellActivated) + + if element.ShowExpanded: + element.QT_QTreeWidget.expandAll() + element.QT_QTreeWidget.show() + if element.Tooltip: + element.QT_QTreeWidget.setToolTip(element.Tooltip) + if not element.Visible: + element.QT_QTreeWidget.setVisible(False) + qt_row_layout.addWidget(element.QT_QTreeWidget, alignment=Qt.AlignVCenter) + # ------------------------- Separator placement element ------------------------- # + elif element_type == ELEM_TYPE_SEPARATOR: + element = element # type: HorizontalSeparator + element.Widget = element.QT_Label = qlabel = QLabel('', toplevel_win.QTWindow) + if not auto_size_text: + if element_size[0] is not None: + element.QT_Label.setFixedWidth(element_size[0]) + if element_size[1] is not None: + element.QT_Label.setFixedHeight(element_size[1]) + style = QtStyle('QLabel') + if element.TextColor is not None and element.TextColor != COLOR_SYSTEM_DEFAULT: + style['color'] = element.TextColor + if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + style['background-color'] = element.BackgroundColor + style['margin'] = full_element_pad + element.QT_Label.setStyleSheet(style.build_css_string()) + element.qt_styles = (style,) + + qlabel.setFrameStyle(QFrame.VLine if element.Orientation[0] =='v' else QFrame.HLine) + + qt_row_layout.addWidget(element.QT_Label, alignment=Qt.AlignVCenter) + + # Align the Element on center in the row + # try: + # element.Widget.setAlignment(element.Widget.alignment() | Qt.AlignVCenter) + # except Exception as e: + # print(f'* Alignment error {e}') + + # ............................DONE WITH ROW pack the row of widgets ..........................# + qt_row_layout.setSpacing(0) + containing_frame.setSpacing(0) + containing_frame.addRow('', qt_row_layout) + + # done with row, pack the row of widgets + # tk_row_frame.grid(row=row_num+2, sticky=tk.NW, padx=DEFAULT_MARGINS[0]) + return + + +def ConvertFlexToTK(window): + InitializeResults(window) + master = 000000 + PackFormIntoFrame(window, window.QFormLayout, window) + # ....................................... DONE creating and laying out window ..........................# + screen_width = 000000 # get window info to move to middle of screen + screen_height = 000000 + if window.Location != (None, None): + window.QT_QMainWindow.move(window.Location[0], window.Location[1]) + x, y = window.Location + elif DEFAULT_WINDOW_LOCATION != (None, None): + x, y = DEFAULT_WINDOW_LOCATION + else: + win_width = 0000000 + win_height = 000000 + x = screen_width / 2 - win_width / 2 + y = screen_height / 2 - win_height / 2 + if y + win_height > screen_height: + y = screen_height - win_height + if x + win_width > screen_width: + x = screen_width - win_width + + + + return + +# ----====----====----====----====----==== Start timer ====----====----====----====----====----# + +def start_window_read_timer(window, amount): + timer = QtCore.QTimer() + timer.timeout.connect(window._timer_timeout) + timer.start(amount) + return timer + + +def start_systray_read_timer(tray, amount): + timer = QtCore.QTimer() + timer.timeout.connect(tray._timer_timeout) + timer.start(amount) + return timer + + +def start_window_autoclose_timer(window, amount): + timer = QtCore.QTimer() + window.autoclose_timer = timer + timer.timeout.connect(window._autoclose_timer_callback) + timer.start(amount) + return timer + +def stop_timer(timer): + timer.stop() + +# ----====----====----====----====----==== STARTUP TK ====----====----====----====----====----# +def StartupTK(window): + """ + Does the building of the window with all the widgets + :param window: you window object + :type window: (Window) + """ + + global using_pyqt5 + + ow = Window.NumOpenWindows + + if Window.QTApplication is None: + Window.QTApplication = QApplication(sys.argv) + + window.QTApplication = Window.QTApplication + + Window.IncrementOpenCount() + + # window.QTWindow = QWidget() + + window.QT_QMainWindow = Window.QT_QMainWindowClass(window.ReturnKeyboardEvents, window) + window.QTWindow = Window.QTMainWindow(window.ReturnKeyboardEvents, window) + window.QT_QMainWindow.setCentralWidget(window.QTWindow) + + window.QT_QMainWindow.installEventFilter(window.QT_QMainWindow) + + window.QTApplication.setActiveWindow(window.QT_QMainWindow) + + flags = QtCore.Qt.WindowFlags() + if window.NoTitleBar: + flags |= Qt.FramelessWindowHint + flags |= QtCore.Qt.Tool + if window.KeepOnTop: + flags |= Qt.WindowStaysOnTopHint + + if not using_pyqt5 and flags is not None: + window.QT_QMainWindow.setWindowFlags(flags) + if window.AlphaChannel: + window.QT_QMainWindow.setWindowOpacity(window.AlphaChannel) + if window.WindowIcon is not None: + if type(window.WindowIcon) is bytes: + ba = QtCore.QByteArray.fromBase64(window.WindowIcon) + pixmap = QtGui.QPixmap() + pixmap.loadFromData(ba) + qicon = QIcon(pixmap) + window.QT_QMainWindow.setWindowIcon(qicon) + else: + window.QT_QMainWindow.setWindowIcon(QtGui.QIcon(window.WindowIcon)) + if window.DisableMinimize: + window.QT_QMainWindow.setWindowFlags(window.QT_QMainWindow.windowFlags()&~Qt.WindowMinimizeButtonHint) + window.QT_QMainWindow.setWindowFlags(window.QT_QMainWindow.windowFlags()&~Qt.WindowMaximizeButtonHint) + if window.DisableClose: + window.QT_QMainWindow.setWindowFlags(window.QT_QMainWindow.windowFlags()&~Qt.WindowCloseButtonHint) + + # window.QTWindow.setAttribute(Qt.WA_TranslucentBackground) + # shadow = QtWidgets.QGraphicsDropShadowEffect() + # shadow.setBlurRadius(9.0) + # shadow.setBlurRadius(50) + # window.QTWindow.setGraphicsEffect(shadow) + + # if window.KeepOnTop: + # window.QTWindow.setWindowFlags(Qt.WindowStaysOnTopHint) + + + style = QtStyle('QMainWindow') + if window.BackgroundColor is not None and window.BackgroundColor != COLOR_SYSTEM_DEFAULT: + style['background-color'] = window.BackgroundColor + window.QT_QMainWindow.setStyleSheet(str(style)) + + if window.margins != (None, None): + margin_left = margin_right = margin_top = margin_bottom = 0 + if isinstance(window.margins[0], tuple): + margin_left = window.margins[0][0] + margin_right = window.margins[0][1] + elif isinstance(window.margins[0], int): + margin_left = window.margins[0] + margin_right = window.margins[0] + if isinstance(window.margins[1], tuple): + margin_top = window.margins[1][0] + margin_bottom = window.margins[1][1] + elif isinstance(window.margins[1], int): + margin_top = window.margins[1] + margin_bottom = window.margins[1] + window.QT_QMainWindow.setContentsMargins(margin_left, margin_top, margin_right, margin_bottom) + + if window.BackgroundImage is not None: + qlabel = QLabel(window.QTWindow) + qlabel.setText('') + w = QtGui.QPixmap(window.BackgroundImage).width() + h = QtGui.QPixmap(window.BackgroundImage).height() + qlabel.setGeometry(QtCore.QRect(0,0, w, h)) + # qlabel.setGeometry(window.QTWindow.geometry()) + qlabel.setPixmap(QtGui.QPixmap(window.BackgroundImage)) + # style += 'background-image: url(%s);' % window.BackgroundImage + + + window.QT_QMainWindow.setWindowTitle(window.Title) + + if (window.GrabAnywhere is not False and not ( + window.NonBlocking and window.GrabAnywhere is not True)): + pass + + window.QFormLayout = QFormLayout() + window.QT_Box_Layout = QVBoxLayout() + ConvertFlexToTK(window) + window.QT_Box_Layout.addLayout(window.QFormLayout) + + + # shadow = QtWidgets.QGraphicsDropShadowEffect( window.QFormLayout) + # window.QTWindow.setGraphicsEffect(shadow) + + + + # Make window visible again + pass + + if window.ReturnKeyboardEvents and not window.NonBlocking: + pass + elif window.ReturnKeyboardEvents: + pass + + # print('..... CALLING MainLoop') + window.CurrentlyRunningMainloop = True + window.QTWindow.setLayout(window.QT_Box_Layout) + + if window.FocusElement is not None: + window.FocusElement.setFocus() + + # Resize the window to the size it should be at... dunno why I need to do this but I do... + # add 5 pixels onto it because stuff was getting cut off + qsize = window.QT_QMainWindow.sizeHint() + size = [qsize.width(), qsize.height()] + size[0] += 10 + window.QT_QMainWindow.resize(*size) + + if window._Size != (None, None): + window.QT_QMainWindow.resize(window._Size[0], window._Size[1]) + + if not window.Resizable: + window.QT_QMainWindow.setFixedSize(*size) + + + + timer = None + if window.AutoClose: + timer = start_window_autoclose_timer(window, window.AutoCloseDuration*1000) + + if not window.NonBlocking: + if window.Timeout: + timer = start_window_read_timer(window, window.Timeout) + window.QT_QMainWindow.show() ####### The thing that causes the window to be visible ###### + #### ------------------------------ RUN MAIN LOOP HERE ------------------------------ ##### + window.QTApplication.exec_() + if timer: + stop_timer(timer) + else: # Non-blocking window + window.QT_QMainWindow.show() ####### The thing that causes the window to be visible ###### + window.QTApplication.processEvents() + + + + window.CurrentlyRunningMainloop = False + window.TimerCancelled = True + # print('..... BACK from MainLoop') + if not window.FormRemainedOpen: + Window.DecrementOpenCount() + if window.RootNeedsDestroying: + # print('** Destroying window **') + window.QT_QMainWindow.close() # destroy the window + window.RootNeedsDestroying = False + return + + +# ==============================_GetNumLinesNeeded ==# +# Helper function for determining how to wrap text # +# ===================================================# +def _GetNumLinesNeeded(text, max_line_width): + if max_line_width == 0: + return 1 + lines = text.split('\n') + num_lines = len(lines) # number of original lines of text + max_line_len = max([len(l) for l in lines]) # longest line + lines_used = [] + for L in lines: + lines_used.append(len(L) // max_line_width + (len(L) % max_line_width > 0)) # fancy math to round up + total_lines_needed = sum(lines_used) + return total_lines_needed + + +# ============================== PROGRESS METER ========================================== # + +def ConvertArgsToSingleString(*args): + max_line_total, width_used, total_lines, = 0, 0, 0 + single_line_message = '' + # loop through args and built a SINGLE string from them + for message in args: + # fancy code to check if string and convert if not is not need. Just always convert to string :-) + # if not isinstance(message, str): message = str(message) + message = str(message) + longest_line_len = max([len(l) for l in message.split('\n')]) + width_used = max(longest_line_len, width_used) + max_line_total = max(max_line_total, width_used) + lines_needed = _GetNumLinesNeeded(message, width_used) + total_lines += lines_needed + single_line_message += message + '\n' + return single_line_message, width_used, total_lines + + +METER_REASON_CANCELLED = 'cancelled' +METER_REASON_CLOSED = 'closed' +METER_REASON_REACHED_MAX = 'finished' +METER_OK = True +METER_STOPPED = False + +class QuickMeter(object): + active_meters = {} + exit_reasons = {} + + def __init__(self, title, current_value, max_value, key, *args, orientation='v', bar_color=(None, None), + button_color=(None, None), size=DEFAULT_PROGRESS_BAR_SIZE, border_width=None, grab_anywhere=False): + self.start_time = datetime.datetime.utcnow() + self.key = key + self.orientation = orientation + self.bar_color = bar_color + self.size = size + self.grab_anywhere = grab_anywhere + self.button_color = button_color + self.border_width = border_width + self.title = title + self.current_value = current_value + self.max_value = max_value + self.close_reason = None + self.window = self.BuildWindow(*args) + + def BuildWindow(self, *args): + layout = [] + if self.orientation.lower().startswith('h'): + col = [[T(''.join(map(lambda x: str(x)+'\n',args)),key='_OPTMSG_')]] ### convert all *args into one string that can be updated + col += [[T('', size=(25,5), key='_STATS_')], + [ProgressBar(max_value=self.max_value, orientation='h', key='_PROG_', size=self.size, + bar_color=self.bar_color)], + [Cancel(button_color=self.button_color), Stretch()]] + layout += [Column(col)] + else: + col = [[ProgressBar(max_value=self.max_value, orientation='v', key='_PROG_', size=self.size, bar_color=self.bar_color)]] + col2 = [[T(''.join(map(lambda x: str(x)+'\n',args)),key='_OPTMSG_')]] ### convert all *args into one string that can be updated + col2 += [[T('', size=(25,5), key='_STATS_')],[Cancel(button_color=self.button_color), Stretch()]] + layout += [Column(col), Column(col2)] + self.window = Window(self.title, grab_anywhere=self.grab_anywhere, border_depth=self.border_width) + self.window.Layout([layout]).Finalize() + + return self.window + + def UpdateMeter(self, current_value, max_value, *args): + self.current_value = current_value + self.max_value = max_value + self.window.Element('_PROG_').UpdateBar(self.current_value, self.max_value) + self.window.Element('_STATS_').Update('\n'.join(self.ComputeProgressStats())) + self.window.Element('_OPTMSG_').Update(value=''.join(map(lambda x: str(x)+'\n',args))) ### update the string with the args + event, values = self.window.Read(timeout=0) + if event in('Cancel', None) or current_value >= max_value: + self.window.Close() + del(QuickMeter.active_meters[self.key]) + QuickMeter.exit_reasons[self.key] = METER_REASON_CANCELLED if event == 'Cancel' else METER_REASON_CLOSED if event is None else METER_REASON_REACHED_MAX + return QuickMeter.exit_reasons[self.key] + return METER_OK + + + def ComputeProgressStats(self): + utc = datetime.datetime.utcnow() + time_delta = utc - self.start_time + total_seconds = time_delta.total_seconds() + if not total_seconds: + total_seconds = 1 + try: + time_per_item = total_seconds / self.current_value + except: + time_per_item = 1 + seconds_remaining = (self.max_value - self.current_value) * time_per_item + time_remaining = str(datetime.timedelta(seconds=seconds_remaining)) + time_remaining_short = (time_remaining).split(".")[0] + time_delta_short = str(time_delta).split(".")[0] + total_time = time_delta + datetime.timedelta(seconds=seconds_remaining) + total_time_short = str(total_time).split(".")[0] + self.stat_messages = [ + '{} of {}'.format(self.current_value, self.max_value), + '{} %'.format(100 * self.current_value // self.max_value), + '', + ' {:6.2f} Iterations per Second'.format(self.current_value / total_seconds), + ' {:6.2f} Seconds per Iteration'.format(total_seconds / (self.current_value if self.current_value else 1)), + '', + '{} Elapsed Time'.format(time_delta_short), + '{} Time Remaining'.format(time_remaining_short), + '{} Estimated Total Time'.format(total_time_short)] + return self.stat_messages + + +def OneLineProgressMeter(title, current_value, max_value, key='OK for 1 meter', *args, orientation='v', bar_color=(None, None), + button_color=None, size=DEFAULT_PROGRESS_BAR_SIZE, border_width=None, grab_anywhere=False): + """ + :param orientation: 'horizontal' or 'vertical' ('h' or 'v' work) (Default value = 'vertical' / 'v') + :type orientation: (str) + :param bar_color: color of a bar line + :type bar_color: Tuple(str, str) + :param button_color: button color (foreground, background) + :type button_color: Tuple[str, str] + :param size: (w,h) w=characters-wide, h=rows-high (Default value = DEFAULT_PROGRESS_BAR_SIZE) + :type size: Tuple[int, int] + :param border_width: width of border around element + :type border_width: (int) + :param grab_anywhere: If True, than can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + """ + if key not in QuickMeter.active_meters: + meter = QuickMeter(title, current_value, max_value, key, *args, orientation=orientation, bar_color=bar_color, + button_color=button_color, size=size, border_width=border_width, grab_anywhere=grab_anywhere) + QuickMeter.active_meters[key] = meter + else: + meter = QuickMeter.active_meters[key] + + rc = meter.UpdateMeter(current_value, max_value, *args) + OneLineProgressMeter.exit_reasons = getattr(OneLineProgressMeter,'exit_reasons', QuickMeter.exit_reasons) + return rc == METER_OK + +def OneLineProgressMeterCancel(key='OK for 1 meter'): + try: + meter = QuickMeter.active_meters[key] + meter.window.Close() + del(QuickMeter.active_meters[key]) + QuickMeter.exit_reasons[key] = METER_REASON_CANCELLED + except: # meter is already deleted + return + + +# input is #RRGGBB +# output is #RRGGBB +def GetComplimentaryHex(color): + """ + :param color: color string, like "#RRGGBB" + :type color: (str) + :return color: color string, like "#RRGGBB" + :type color: (str) + """ + # strip the # from the beginning + color = color[1:] + # convert the string into hex + color = int(color, 16) + # invert the three bytes + # as good as substracting each of RGB component by 255(FF) + comp_color = 0xFFFFFF ^ color + # convert the color back to hex by prefixing a # + comp_color = "#%06X" % comp_color + return comp_color + + +# ======================== EasyPrint =====# +# ===================================================# + +class DebugWin(): + debug_window = None + + def __init__(self, size=(None, None), location=(None, None), font=None, no_titlebar=False, no_button=False, + grab_anywhere=False, keep_on_top=False, title=None, do_not_reroute_stdout=False): + # Show a form that's a running counter + self.size = size + self.location = location + self.font = font + self.no_titlebar = no_titlebar + self.no_button = no_button + self.grab_anywhere = grab_anywhere + self.keep_on_top = keep_on_top + self.do_not_reroute_stdout = do_not_reroute_stdout + + win_size = size if size != (None, None) else DEFAULT_DEBUG_WINDOW_SIZE + self.window = Window(title=title or 'Debug Window', no_titlebar=no_titlebar, auto_size_text=True, location=location, + font=font or ('Courier New', 10), grab_anywhere=grab_anywhere, keep_on_top=keep_on_top) + self.output_element = MultilineOutput(size=win_size, key='_MULTILINE_') if do_not_reroute_stdout else Output(size=win_size) + + if no_button: + self.layout = [[self.output_element]] + else: + self.layout = [ + [self.output_element], + [DummyButton('Quit'), Stretch()] + ] + self.window.AddRows(self.layout) + self.window.Read(timeout=0) # Show a non-blocking form, returns immediately + Window.active_popups[self.window] = 'debug window' + return + + def Print(self, *args, end=None, sep=None): + sepchar = sep if sep is not None else ' ' + endchar = end if end is not None else '\n' + + if self.window is None: # if window was destroyed already, just print + self.__init__(size=self.size, location=self.location, font=self.font, no_titlebar=self.no_titlebar, no_button=self.no_button, grab_anywhere=self.grab_anywhere, keep_on_top=self.keep_on_top, do_not_reroute_stdout=self.do_not_reroute_stdout) + event, values = self.window.Read(timeout=0) + if event == 'Quit' or event is None: + self.Close() + self.__init__(size=self.size, location=self.location, font=self.font, no_titlebar=self.no_titlebar, no_button=self.no_button, grab_anywhere=self.grab_anywhere, keep_on_top=self.keep_on_top, do_not_reroute_stdout=self.do_not_reroute_stdout) + if self.do_not_reroute_stdout: + end_str = str(end) if end is not None else '\n' + sep_str = str(sep) if sep is not None else ' ' + + outstring = '' + num_args = len(args) + for i, arg in enumerate(args): + outstring += str(arg) + if i != num_args - 1: + outstring += sep_str + outstring += end_str + self.output_element.Update(outstring, append=True) + else: + print(*args, sep=sepchar, end=endchar) + + + def Close(self): + self.window.Close() + self.window = None + + +def PrintClose(): + EasyPrintClose() + + +def EasyPrint(*args, size=(None, None), end=None, sep=None, location=(None, None), font=None, no_titlebar=False, + no_button=False, grab_anywhere=False, keep_on_top=False, do_not_reroute_stdout=True): + + """ + :param args: The arguments to display + :type args: List[Any] + :param size: (w,h) w=characters-wide, h=rows-high + :type size: Tuple[int, int] + :param end: The end char to use just like print uses + :type end: (str) + :param sep: end character + :type end: (str) + :param sep: separator character + :type sep: (str) + :param location: Location of upper left corner of the window + :type location: Tuple[int, int] + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + :param no_button: don't show button + :type no_button: (bool) + :param grab_anywhere: If True, than can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param do_not_reroute_stdout: do not reroute stdout + :type do_not_reroute_stdout: (bool) + :param text_color: color of the text + :type text_color: (str) + :param background_color: color of background + :type background_color: (str) + """ + + if DebugWin.debug_window is None: + DebugWin.debug_window = DebugWin(size=size, location=location, font=font, no_titlebar=no_titlebar, + no_button=no_button, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, do_not_reroute_stdout=do_not_reroute_stdout) + DebugWin.debug_window.Print(*args, end=end, sep=sep) + + +Print = EasyPrint +eprint = EasyPrint + + +def EasyPrintClose(): + if DebugWin.debug_window is not None: + DebugWin.debug_window.Close() + DebugWin.debug_window = None + + + + +# d8b 888 +# Y8P 888 +# 888 +# .d8888b 88888b. 888d888 888 88888b. 888888 +# d88P" 888 "88b 888P" 888 888 "88b 888 +# 888 888 888 888 888 888 888 888 +# Y88b. 888 d88P 888 888 888 888 Y88b. +# "Y8888P 88888P" 888 888 888 888 "Y888 +# 888 +# 888 +# 888 + + + +CPRINT_DESTINATION_WINDOW = None +CPRINT_DESTINATION_MULTILINE_ELMENT_KEY = None + +def cprint_set_output_destination(window, multiline_key): + """ + Sets up the color print (cprint) output destination + :param window: The window that the cprint call will route the output to + :type window: (Window) + :param multiline_key: Key for the Multiline Element where output will be sent + :type multiline_key: (Any) + :return: None + :rtype: None + """ + + global CPRINT_DESTINATION_WINDOW, CPRINT_DESTINATION_MULTILINE_ELMENT_KEY + + CPRINT_DESTINATION_WINDOW = window + CPRINT_DESTINATION_MULTILINE_ELMENT_KEY = multiline_key + + + +# def cprint(*args, **kwargs): +def cprint(*args, end=None, sep=' ', text_color=None, t=None, background_color=None, b=None, colors=None, c=None, window=None, key=None): + """ + Color print to a multiline element in a window of your choice. + Must have EITHER called cprint_set_output_destination prior to making this call so that the + window and element key can be saved and used here to route the output, OR used the window + and key parameters to the cprint function to specicy these items. + + args is a variable number of things you want to print. + + end - The end char to use just like print uses + sep - The separation character like print uses + text_color - The color of the text + key - overrides the previously defined Multiline key + window - overrides the previously defined window to output to + background_color - The color of the background + colors -(str, str) or str. A combined text/background color definition in a single parameter + + There are also "aliases" for text_color, background_color and colors (t, b, c) + t - An alias for color of the text (makes for shorter calls) + b - An alias for the background_color parameter + c - Tuple[str, str] - "shorthand" way of specifying color. (foreground, backgrouned) + c - str - can also be a string of the format "foreground on background" ("white on red") + + With the aliases it's possible to write the same print but in more compact ways: + cprint('This will print white text on red background', c=('white', 'red')) + cprint('This will print white text on red background', c='white on red') + cprint('This will print white text on red background', text_color='white', background_color='red') + cprint('This will print white text on red background', t='white', b='red') + + :param *args: stuff to output + :type *args: (Any) + :param text_color: Color of the text + :type text_color: (str) + :param background_color: The background color of the line + :type background_color: (str) + :param colors: Either a tuple or a string that has both the text and background colors + :type colors: (str) or Tuple[str, str] + :param t: Color of the text + :type t: (str) + :param b: The background color of the line + :type b: (str) + :param c: Either a tuple or a string that has both the text and background colors + :type c: (str) or Tuple[str, str] + :param end: end character + :type end: (str) + :param sep: separator character + :type sep: (str) + :param key: key of multiline to output to (if you want to override the one previously set) + :type key: (Any) + :param window: Window containing the multiline to output to (if you want to override the one previously set) + :type window: (Window) + :return: None + :rtype: None + """ + + destination_key = CPRINT_DESTINATION_MULTILINE_ELMENT_KEY if key is None else key + destination_window = window or CPRINT_DESTINATION_WINDOW + + if (destination_window is None and window is None) or (destination_key is None and key is None): + print('** Warning ** Attempting to perform a cprint without a valid window & key', + 'Will instead print on Console', + 'You can specify window and key in this cprint call, or set ahead of time using cprint_set_output_destination') + print(*args) + return + + kw_text_color = text_color or t + kw_background_color = background_color or b + dual_color = colors or c + try: + if isinstance(dual_color, tuple): + kw_text_color = dual_color[0] + kw_background_color = dual_color[1] + elif isinstance(dual_color, str): + kw_text_color = dual_color.split(' on ')[0] + kw_background_color = dual_color.split(' on ')[1] + except Exception as e: + print('* cprint warning * you messed up with color formatting', e) + + mline = destination_window.find_element(destination_key, silent_on_error=True) # type: Multiline + try: + # mline = destination_window[destination_key] # type: # Multiline + if end is None: + mline.print(*args, text_color=kw_text_color, background_color=kw_background_color, end='', sep=sep) + mline.print('') + else: + mline.print(*args,text_color=kw_text_color, background_color=kw_background_color, end=end, sep=sep) + except Exception as e: + print('** cprint error trying to print to the multiline. Printing to console instead **', e) + print(*args, end=end, sep=sep) + + + +# ------------------------------------------------------------------------------------------------ # +# A print-like call that can be used to output to a multiline element as if it's an Output element # +# ------------------------------------------------------------------------------------------------ # + + +def _print_to_element(multiline_element, *args, end=None, sep=None, text_color=None, background_color=None, autoscroll=True): + """ + Print like Python normally prints except route the output to a multline element and also add colors if desired + + :param multiline_element: The multiline element to be output to + :type multiline_element: (Multiline) + :param args: The arguments to print + :type args: List[Any] + :param end: The end char to use just like print uses + :type end: (str) + :param sep: The separation character like print uses + :type sep: (str) + :param text_color: color of the text + :type text_color: (str) + :param background_color: The background color of the line + :type background_color: (str) + :param autoscroll: If True (the default), the element will scroll to bottom after updating + :type autoscroll: Bool + """ + end_str = str(end) if end is not None else '\n' + sep_str = str(sep) if sep is not None else ' ' + + outstring = '' + num_args = len(args) + for i, arg in enumerate(args): + outstring += str(arg) + if i != num_args-1: + outstring += sep_str + outstring += end_str + + multiline_element.update(outstring, append=True, text_color_for_value=text_color, background_color_for_value=background_color, autoscroll=autoscroll) + + + +# ======================== Scrolled Text Box =====# +# ===================================================# +def PopupScrolled(*args, button_color=None, yes_no=False, auto_close=False, auto_close_duration=None, + size=(None, None), location=(None, None), title=None, non_blocking=False): + """ + :param args: The arguments to display + :type args: List[Any] + :param title: Title to display in the window. + :type title: (str) + :param button_color: button color (foreground, background) + :type button_color: Tuple[str, str] + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param yes_no: If True, displays Yes and No buttons instead of Ok + :type yes_no: (bool) + :param auto_close: if True window will close itself + :type auto_close: (bool) + :param auto_close_duration: Older versions only accept int. Time in seconds until window will close + :type auto_close_duration: Union[int, float] + :param size: (w,h) w=characters-wide, h=rows-high + :type size: Tuple[int, int] + :param location: Location on the screen to place the upper left corner of the window + :type location: Tuple[int, int] + :param non_blocking: if True the call will immediately return rather than waiting on user input + :type non_blocking: (bool) + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + :param grab_anywhere: If True, than can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + """ + if not args: return + width, height = size + width = width if width else MESSAGE_BOX_LINE_WIDTH + window = Window(title=title or args[0], auto_size_text=True, button_color=button_color, auto_close=auto_close, + auto_close_duration=auto_close_duration, location=location) + max_line_total, max_line_width, total_lines, height_computed = 0, 0, 0, 0 + complete_output = '' + for message in args: + # fancy code to check if string and convert if not is not need. Just always convert to string :-) + # if not isinstance(message, str): message = str(message) - new + message = str(message) + longest_line_len = max([len(l) for l in message.split('\n')]) + width_used = min(longest_line_len, width) + max_line_total = max(max_line_total, width_used) + max_line_width = width + lines_needed = _GetNumLinesNeeded(message, width_used) + height_computed += lines_needed + complete_output += message + '\n' + total_lines += lines_needed + height_computed = MAX_SCROLLED_TEXT_BOX_HEIGHT if height_computed > MAX_SCROLLED_TEXT_BOX_HEIGHT else height_computed + if height: + height_computed = height + computed_size = (max_line_width*10, height_computed*16) + window.AddRow(MultilineOutput(complete_output, size=computed_size)) + pad = max_line_total - 15 if max_line_total > 15 else 1 + # show either an OK or Yes/No depending on paramater + button = DummyButton if non_blocking else Button + if yes_no: + window.AddRow(Text('', size=(pad, 1), auto_size_text=False), button('Yes'), button('No')) + else: + window.AddRow(Text('', size=(pad, 1), auto_size_text=False), button('OK', size=(5, 1), button_color=button_color)) + + if non_blocking: + button, values = window.Read(timeout=0) + Window.active_popups[window] = title + else: + button, values = window.Read() + return button + + +ScrolledTextBox = PopupScrolled + + +# ============================== SetGlobalIcon ======# +# Sets the icon to be used by default # +# ===================================================# +def SetGlobalIcon(icon): + """ + :param icon: Either a Base64 byte string or a filename + :type icon: Union[bytes, str] + """ + + try: + with open(icon, 'r') as icon_file: + pass + except: + raise FileNotFoundError + Window.user_defined_icon = icon + return True + + +# ============================== SetOptions =========# +# Sets the icon to be used by default # +# ===================================================# +def SetOptions(icon=None, button_color=None, element_size=(None, None), button_element_size=(None, None), + margins=(None, None), + element_padding=(None, None), auto_size_text=None, auto_size_buttons=None, font=None, border_width=None, + slider_border_width=None, slider_relief=None, slider_orientation=None, + autoclose_time=None, message_box_line_width=None, + progress_meter_border_depth=None, progress_meter_style=None, + progress_meter_relief=None, progress_meter_color=None, progress_meter_size=None, + text_justification=None, background_color=None, element_background_color=None, + text_element_background_color=None, input_elements_background_color=None, input_text_color=None, + scrollbar_color=None, text_color=None, element_text_color=None, debug_win_size=(None, None), + window_location=(None, None), error_button_color=(None,None), + tooltip_time=None): + """ + :param icon: filename or base64 string to be used for the window's icon + :type icon: Union[bytes, str] + :param button_color: Color of the button (text, background) + :type button_color: Tuple[str, str] + :param element_size: element size (width, height) in characters + :type element_size: Tuple[int, int] + :param button_element_size: Size of button + :type button_element_size: Tuple[int, int] + :param margins: (left/right, top/bottom) tkinter margins around outsize. Amount of pixels to leave inside the window's frame around the edges before your elements are shown. + :type margins: Tuple[int, int] + :param element_padding: Default amount of padding to put around elements in window (left/right, top/bottom) or ((left, right), (top, bottom)) + :type element_padding: Tuple[int, int] or ((int, int),(int,int)) + :param auto_size_text: True if the Widget should be shrunk to exactly fit the number of chars to show + :type auto_size_text: bool + :param auto_size_buttons: True if Buttons in this Window should be sized to exactly fit the text on this. + :type auto_size_buttons: (bool) + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param border_width: width of border around element + :type border_width: (int) + :param slider_border_width: ??? + :type slider_border_width: ??? + :param slider_relief: ??? + :type slider_relief: ??? + :param slider_orientation: ??? + :type slider_orientation: ??? + :param autoclose_time: ??? + :type autoclose_time: ??? + :param message_box_line_width: ??? + :type message_box_line_width: ??? + :param progress_meter_border_depth: ??? + :type progress_meter_border_depth: ??? + :param progress_meter_style: You can no longer set a progress bar style. All ttk styles must be the same for the window + :type progress_meter_style: ??? + :param progress_meter_relief: + :type progress_meter_relief: ??? + :param progress_meter_color: ??? + :type progress_meter_color: ??? + :param progress_meter_size: ??? + :type progress_meter_size: ??? + :param text_justification: Default text justification for all Text Elements in window + :type text_justification: Union['left', 'right', 'center'] + :param background_color: color of background + :type background_color: (str) + :param element_background_color: element background color + :type element_background_color: (str) + :param text_element_background_color: text element background color + :type text_element_background_color: (str) + :param input_elements_background_color: ??? + :type input_elements_background_color: idk_yetReally + :param input_text_color: ??? + :type input_text_color: ??? + :param scrollbar_color: ??? + :type scrollbar_color: ??? + :param text_color: color of the text + :type text_color: (str) + :param element_text_color: ??? + :type element_text_color: ??? + :param debug_win_size: window size + :type debug_win_size: Tuple[int, int] + :param window_location: (Default = (None)) + :type window_location: ??? + :param error_button_color: (Default = (None)) + :type error_button_color: ??? + :param tooltip_time: time in milliseconds to wait before showing a tooltip. Default is 400ms + :type tooltip_time: (int) + :param tooltip_font: font to use for all tooltips + :type tooltip_font: str or Tuple[str, int] or Tuple[str, int, str] + :param use_ttk_buttons: if True will cause all buttons to be ttk buttons + :type use_ttk_buttons: (bool) + :param ttk_theme: Theme to use with ttk widgets. Choices (on Windows) include - 'default', 'winnative', 'clam', 'alt', 'classic', 'vista', 'xpnative' + :type ttk_theme: (str) + """ + global DEFAULT_ELEMENT_SIZE + global DEFAULT_BUTTON_ELEMENT_SIZE + global DEFAULT_MARGINS # Margins for each LEFT/RIGHT margin is first term + global DEFAULT_ELEMENT_PADDING # Padding between elements (row, col) in pixels + global DEFAULT_AUTOSIZE_TEXT + global DEFAULT_AUTOSIZE_BUTTONS + global DEFAULT_FONT + global DEFAULT_BORDER_WIDTH + global DEFAULT_AUTOCLOSE_TIME + global DEFAULT_BUTTON_COLOR + global MESSAGE_BOX_LINE_WIDTH + global DEFAULT_PROGRESS_BAR_BORDER_WIDTH + global DEFAULT_PROGRESS_BAR_STYLE + global DEFAULT_PROGRESS_BAR_RELIEF + global DEFAULT_PROGRESS_BAR_COLOR + global DEFAULT_PROGRESS_BAR_SIZE + global DEFAULT_TEXT_JUSTIFICATION + global DEFAULT_DEBUG_WINDOW_SIZE + global DEFAULT_SLIDER_BORDER_WIDTH + global DEFAULT_SLIDER_RELIEF + global DEFAULT_SLIDER_ORIENTATION + global DEFAULT_BACKGROUND_COLOR + global DEFAULT_INPUT_ELEMENTS_COLOR + global DEFAULT_ELEMENT_BACKGROUND_COLOR + global DEFAULT_TEXT_ELEMENT_BACKGROUND_COLOR + global DEFAULT_SCROLLBAR_COLOR + global DEFAULT_TEXT_COLOR + global DEFAULT_WINDOW_LOCATION + global DEFAULT_ELEMENT_TEXT_COLOR + global DEFAULT_INPUT_TEXT_COLOR + global DEFAULT_TOOLTIP_TIME + global DEFAULT_ERROR_BUTTON_COLOR + + if icon: + Window.user_defined_icon = icon + + if button_color != None: + DEFAULT_BUTTON_COLOR = button_color + + if element_size != (None, None): + DEFAULT_ELEMENT_SIZE = _convert_tkinter_size_to_Qt(element_size) + + if button_element_size != (None, None): + DEFAULT_BUTTON_ELEMENT_SIZE = _convert_tkinter_size_to_Qt(button_element_size) + + if margins != (None, None): + DEFAULT_MARGINS = margins + + if element_padding != (None, None): + DEFAULT_ELEMENT_PADDING = element_padding + + if auto_size_text != None: + DEFAULT_AUTOSIZE_TEXT = auto_size_text + + if auto_size_buttons != None: + DEFAULT_AUTOSIZE_BUTTONS = auto_size_buttons + + if font != None: + DEFAULT_FONT = font + + if border_width != None: + DEFAULT_BORDER_WIDTH = border_width + + if autoclose_time != None: + DEFAULT_AUTOCLOSE_TIME = autoclose_time + + if message_box_line_width != None: + MESSAGE_BOX_LINE_WIDTH = message_box_line_width + + if progress_meter_border_depth != None: + DEFAULT_PROGRESS_BAR_BORDER_WIDTH = progress_meter_border_depth + + if progress_meter_style != None: + DEFAULT_PROGRESS_BAR_STYLE = progress_meter_style + + if progress_meter_relief != None: + DEFAULT_PROGRESS_BAR_RELIEF = progress_meter_relief + + if progress_meter_color != None: + DEFAULT_PROGRESS_BAR_COLOR = progress_meter_color + + if progress_meter_size != None: + DEFAULT_PROGRESS_BAR_SIZE = progress_meter_size + + if slider_border_width != None: + DEFAULT_SLIDER_BORDER_WIDTH = slider_border_width + + if slider_orientation != None: + DEFAULT_SLIDER_ORIENTATION = slider_orientation + + if slider_relief != None: + DEFAULT_SLIDER_RELIEF = slider_relief + + if text_justification != None: + DEFAULT_TEXT_JUSTIFICATION = text_justification + + if background_color != None: + DEFAULT_BACKGROUND_COLOR = background_color + + if text_element_background_color != None: + DEFAULT_TEXT_ELEMENT_BACKGROUND_COLOR = text_element_background_color + + if input_elements_background_color != None: + DEFAULT_INPUT_ELEMENTS_COLOR = input_elements_background_color + + if element_background_color != None: + DEFAULT_ELEMENT_BACKGROUND_COLOR = element_background_color + + if window_location != (None, None): + DEFAULT_WINDOW_LOCATION = window_location + + if debug_win_size != (None, None): + DEFAULT_DEBUG_WINDOW_SIZE = debug_win_size + + if text_color != None: + DEFAULT_TEXT_COLOR = text_color + + if scrollbar_color != None: + DEFAULT_SCROLLBAR_COLOR = scrollbar_color + + if element_text_color != None: + DEFAULT_ELEMENT_TEXT_COLOR = element_text_color + + if input_text_color is not None: + DEFAULT_INPUT_TEXT_COLOR = input_text_color + + if tooltip_time is not None: + DEFAULT_TOOLTIP_TIME = tooltip_time + + if error_button_color != (None,None): + print('error button') + DEFAULT_ERROR_BUTTON_COLOR = error_button_color + + return True + + +# ----------------------------------------------------------------- # + +# .########.##.....##.########.##.....##.########..######. +# ....##....##.....##.##.......###...###.##.......##....## +# ....##....##.....##.##.......####.####.##.......##...... +# ....##....#########.######...##.###.##.######....######. +# ....##....##.....##.##.......##.....##.##.............## +# ....##....##.....##.##.......##.....##.##.......##....## +# ....##....##.....##.########.##.....##.########..######. + +# ----------------------------------------------------------------- # + +# The official Theme code + +#################### ChangeLookAndFeel ####################### +# Predefined settings that will change the colors and styles # +# of the elements. # +############################################################## +LOOK_AND_FEEL_TABLE = { +"SystemDefault": {"BACKGROUND": COLOR_SYSTEM_DEFAULT,"TEXT": COLOR_SYSTEM_DEFAULT,"INPUT": COLOR_SYSTEM_DEFAULT,"TEXT_INPUT": COLOR_SYSTEM_DEFAULT,"SCROLL": COLOR_SYSTEM_DEFAULT,"BUTTON": OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR,"PROGRESS": COLOR_SYSTEM_DEFAULT,"BORDER": 1,"SLIDER_DEPTH": 1,"PROGRESS_DEPTH": 0,}, +"SystemDefaultForReal": {"BACKGROUND": COLOR_SYSTEM_DEFAULT,"TEXT": COLOR_SYSTEM_DEFAULT,"INPUT": COLOR_SYSTEM_DEFAULT,"TEXT_INPUT": COLOR_SYSTEM_DEFAULT,"SCROLL": COLOR_SYSTEM_DEFAULT,"BUTTON": COLOR_SYSTEM_DEFAULT,"PROGRESS": COLOR_SYSTEM_DEFAULT,"BORDER": 1,"SLIDER_DEPTH": 1,"PROGRESS_DEPTH": 0,}, +"SystemDefault1": {"BACKGROUND": COLOR_SYSTEM_DEFAULT,"TEXT": COLOR_SYSTEM_DEFAULT,"INPUT": COLOR_SYSTEM_DEFAULT,"TEXT_INPUT": COLOR_SYSTEM_DEFAULT,"SCROLL": COLOR_SYSTEM_DEFAULT,"BUTTON": COLOR_SYSTEM_DEFAULT,"PROGRESS": COLOR_SYSTEM_DEFAULT,"BORDER": 1,"SLIDER_DEPTH": 1,"PROGRESS_DEPTH": 0,}, +"Material1": {"BACKGROUND": "#E3F2FD","TEXT": "#000000","INPUT": "#86A8FF","TEXT_INPUT": "#000000","SCROLL": "#86A8FF","BUTTON": ("#FFFFFF", "#5079D3"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 0,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"ACCENT1": "#FF0266","ACCENT2": "#FF5C93","ACCENT3": "#C5003C",}, +"Material2": {"BACKGROUND": "#FAFAFA","TEXT": "#000000","INPUT": "#004EA1","TEXT_INPUT": "#FFFFFF","SCROLL": "#5EA7FF","BUTTON": ("#FFFFFF", "#0079D3"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 0,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"ACCENT1": "#FF0266","ACCENT2": "#FF5C93","ACCENT3": "#C5003C",}, +"Reddit": {"BACKGROUND": "#ffffff","TEXT": "#1a1a1b","INPUT": "#dae0e6","TEXT_INPUT": "#222222","SCROLL": "#a5a4a4","BUTTON": ("#FFFFFF", "#0079d3"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"ACCENT1": "#ff5414","ACCENT2": "#33a8ff","ACCENT3": "#dbf0ff",}, +"Topanga": {"BACKGROUND": "#282923","TEXT": "#E7DB74","INPUT": "#393a32","TEXT_INPUT": "#E7C855","SCROLL": "#E7C855","BUTTON": ("#E7C855", "#284B5A"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"ACCENT1": "#c15226","ACCENT2": "#7a4d5f","ACCENT3": "#889743",}, +"GreenTan": {"BACKGROUND": "#9FB8AD","TEXT": COLOR_SYSTEM_DEFAULT,"INPUT": "#F7F3EC","TEXT_INPUT": "#000000","SCROLL": "#F7F3EC","BUTTON": ("#FFFFFF", "#475841"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"Dark": {"BACKGROUND": "#404040","TEXT": "#FFFFFF","INPUT": "#4D4D4D","TEXT_INPUT": "#FFFFFF","SCROLL": "#707070","BUTTON": ("#FFFFFF", "#004F00"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"LightGreen": {"BACKGROUND": "#B7CECE","TEXT": "#000000","INPUT": "#FDFFF7","TEXT_INPUT": "#000000","SCROLL": "#FDFFF7","BUTTON": ("#FFFFFF", "#658268"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"ACCENT1": "#76506d","ACCENT2": "#5148f1","ACCENT3": "#0a1c84","PROGRESS_DEPTH": 0,}, +"Dark2": {"BACKGROUND": "#404040","TEXT": "#FFFFFF","INPUT": "#FFFFFF","TEXT_INPUT": "#000000","SCROLL": "#707070","BUTTON": ("#FFFFFF", "#004F00"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"Black": {"BACKGROUND": "#000000","TEXT": "#FFFFFF","INPUT": "#4D4D4D","TEXT_INPUT": "#FFFFFF","SCROLL": "#707070","BUTTON": ("#000000", "#FFFFFF"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"Tan": {"BACKGROUND": "#fdf6e3","TEXT": "#268bd1","INPUT": "#eee8d5","TEXT_INPUT": "#6c71c3","SCROLL": "#eee8d5","BUTTON": ("#FFFFFF", "#063542"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"TanBlue": {"BACKGROUND": "#e5dece","TEXT": "#063289","INPUT": "#f9f8f4","TEXT_INPUT": "#242834","SCROLL": "#eee8d5","BUTTON": ("#FFFFFF", "#063289"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"DarkTanBlue": {"BACKGROUND": "#242834","TEXT": "#dfe6f8","INPUT": "#97755c","TEXT_INPUT": "#FFFFFF","SCROLL": "#a9afbb","BUTTON": ("#FFFFFF", "#063289"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"DarkAmber": {"BACKGROUND": "#2c2825","TEXT": "#fdcb52","INPUT": "#705e52","TEXT_INPUT": "#fdcb52","SCROLL": "#705e52","BUTTON": ("#000000", "#fdcb52"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"DarkBlue": {"BACKGROUND": "#1a2835","TEXT": "#d1ecff","INPUT": "#335267","TEXT_INPUT": "#acc2d0","SCROLL": "#1b6497","BUTTON": ("#000000", "#fafaf8"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"Reds": {"BACKGROUND": "#280001","TEXT": "#FFFFFF","INPUT": "#d8d584","TEXT_INPUT": "#000000","SCROLL": "#763e00","BUTTON": ("#000000", "#daad28"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"Green": {"BACKGROUND": "#82a459","TEXT": "#000000","INPUT": "#d8d584","TEXT_INPUT": "#000000","SCROLL": "#e3ecf3","BUTTON": ("#FFFFFF", "#517239"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"BluePurple": {"BACKGROUND": "#A5CADD","TEXT": "#6E266E","INPUT": "#E0F5FF","TEXT_INPUT": "#000000","SCROLL": "#E0F5FF","BUTTON": ("#FFFFFF", "#303952"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"Purple": {"BACKGROUND": "#B0AAC2","TEXT": "#000000","INPUT": "#F2EFE8","SCROLL": "#F2EFE8","TEXT_INPUT": "#000000","BUTTON": ("#000000", "#C2D4D8"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"BlueMono": {"BACKGROUND": "#AAB6D3","TEXT": "#000000","INPUT": "#F1F4FC","SCROLL": "#F1F4FC","TEXT_INPUT": "#000000","BUTTON": ("#FFFFFF", "#7186C7"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"GreenMono": {"BACKGROUND": "#A8C1B4","TEXT": "#000000","INPUT": "#DDE0DE","SCROLL": "#E3E3E3","TEXT_INPUT": "#000000","BUTTON": ("#FFFFFF", "#6D9F85"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"BrownBlue": {"BACKGROUND": "#64778d","TEXT": "#FFFFFF","INPUT": "#f0f3f7","SCROLL": "#A6B2BE","TEXT_INPUT": "#000000","BUTTON": ("#FFFFFF", "#283b5b"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"BrightColors": {"BACKGROUND": "#b4ffb4","TEXT": "#000000","INPUT": "#ffff64","SCROLL": "#ffb482","TEXT_INPUT": "#000000","BUTTON": ("#000000", "#ffa0dc"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"NeutralBlue": {"BACKGROUND": "#92aa9d","TEXT": "#000000","INPUT": "#fcfff6","SCROLL": "#fcfff6","TEXT_INPUT": "#000000","BUTTON": ("#000000", "#d0dbbd"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"Kayak": {"BACKGROUND": "#a7ad7f","TEXT": "#000000","INPUT": "#e6d3a8","SCROLL": "#e6d3a8","TEXT_INPUT": "#000000","BUTTON": ("#FFFFFF", "#5d907d"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"SandyBeach": {"BACKGROUND": "#efeccb","TEXT": "#012f2f","INPUT": "#e6d3a8","SCROLL": "#e6d3a8","TEXT_INPUT": "#012f2f","BUTTON": ("#FFFFFF", "#046380"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"TealMono": {"BACKGROUND": "#a8cfdd","TEXT": "#000000","INPUT": "#dfedf2","SCROLL": "#dfedf2","TEXT_INPUT": "#000000","BUTTON": ("#FFFFFF", "#183440"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"Default": {"BACKGROUND": COLOR_SYSTEM_DEFAULT,"TEXT": COLOR_SYSTEM_DEFAULT,"INPUT": COLOR_SYSTEM_DEFAULT,"TEXT_INPUT": COLOR_SYSTEM_DEFAULT,"SCROLL": COLOR_SYSTEM_DEFAULT,"BUTTON": OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR,"PROGRESS": COLOR_SYSTEM_DEFAULT,"BORDER": 1,"SLIDER_DEPTH": 1,"PROGRESS_DEPTH": 0,}, +"Default1": {"BACKGROUND": COLOR_SYSTEM_DEFAULT,"TEXT": COLOR_SYSTEM_DEFAULT,"INPUT": COLOR_SYSTEM_DEFAULT,"TEXT_INPUT": COLOR_SYSTEM_DEFAULT,"SCROLL": COLOR_SYSTEM_DEFAULT,"BUTTON": COLOR_SYSTEM_DEFAULT,"PROGRESS": COLOR_SYSTEM_DEFAULT,"BORDER": 1,"SLIDER_DEPTH": 1,"PROGRESS_DEPTH": 0,}, +"DefaultNoMoreNagging": {"BACKGROUND": COLOR_SYSTEM_DEFAULT,"TEXT": COLOR_SYSTEM_DEFAULT,"INPUT": COLOR_SYSTEM_DEFAULT,"TEXT_INPUT": COLOR_SYSTEM_DEFAULT,"SCROLL": COLOR_SYSTEM_DEFAULT,"BUTTON": OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR,"PROGRESS": COLOR_SYSTEM_DEFAULT,"BORDER": 1,"SLIDER_DEPTH": 1,"PROGRESS_DEPTH": 0,}, +"LightBlue": {"BACKGROUND": "#E3F2FD","TEXT": "#000000","INPUT": "#86A8FF","TEXT_INPUT": "#000000","SCROLL": "#86A8FF","BUTTON": ("#FFFFFF", "#5079D3"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 0,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"ACCENT1": "#FF0266","ACCENT2": "#FF5C93","ACCENT3": "#C5003C",}, +"LightGrey": {"BACKGROUND": "#FAFAFA","TEXT": "#000000","INPUT": "#004EA1","TEXT_INPUT": "#FFFFFF","SCROLL": "#5EA7FF","BUTTON": ("#FFFFFF", "#0079D3"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 0,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"ACCENT1": "#FF0266","ACCENT2": "#FF5C93","ACCENT3": "#C5003C",}, +"LightGrey1": {"BACKGROUND": "#ffffff","TEXT": "#1a1a1b","INPUT": "#dae0e6","TEXT_INPUT": "#222222","SCROLL": "#a5a4a4","BUTTON": ("#FFFFFF", "#0079d3"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"ACCENT1": "#ff5414","ACCENT2": "#33a8ff","ACCENT3": "#dbf0ff",}, +"DarkBrown": {"BACKGROUND": "#282923","TEXT": "#E7DB74","INPUT": "#393a32","TEXT_INPUT": "#E7C855","SCROLL": "#E7C855","BUTTON": ("#E7C855", "#284B5A"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"ACCENT1": "#c15226","ACCENT2": "#7a4d5f","ACCENT3": "#889743",}, +"LightGreen1": {"BACKGROUND": "#9FB8AD","TEXT": "#000000","INPUT": "#F7F3EC","TEXT_INPUT": "#000000","SCROLL": "#F7F3EC","BUTTON": ("#FFFFFF", "#475841"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"DarkGrey": {"BACKGROUND": "#404040","TEXT": "#FFFFFF","INPUT": "#4D4D4D","TEXT_INPUT": "#FFFFFF","SCROLL": "#707070","BUTTON": ("#FFFFFF", "#004F00"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"LightGreen2": {"BACKGROUND": "#B7CECE","TEXT": "#000000","INPUT": "#FDFFF7","TEXT_INPUT": "#000000","SCROLL": "#FDFFF7","BUTTON": ("#FFFFFF", "#658268"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"ACCENT1": "#76506d","ACCENT2": "#5148f1","ACCENT3": "#0a1c84","PROGRESS_DEPTH": 0,}, +"DarkGrey1": {"BACKGROUND": "#404040","TEXT": "#FFFFFF","INPUT": "#FFFFFF","TEXT_INPUT": "#000000","SCROLL": "#707070","BUTTON": ("#FFFFFF", "#004F00"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"DarkBlack": {"BACKGROUND": "#000000","TEXT": "#FFFFFF","INPUT": "#4D4D4D","TEXT_INPUT": "#FFFFFF","SCROLL": "#707070","BUTTON": ("#000000", "#FFFFFF"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"LightBrown": {"BACKGROUND": "#fdf6e3","TEXT": "#268bd1","INPUT": "#eee8d5","TEXT_INPUT": "#6c71c3","SCROLL": "#eee8d5","BUTTON": ("#FFFFFF", "#063542"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"LightBrown1": {"BACKGROUND": "#e5dece","TEXT": "#063289","INPUT": "#f9f8f4","TEXT_INPUT": "#242834","SCROLL": "#eee8d5","BUTTON": ("#FFFFFF", "#063289"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"DarkBlue1": {"BACKGROUND": "#242834","TEXT": "#dfe6f8","INPUT": "#97755c","TEXT_INPUT": "#FFFFFF","SCROLL": "#a9afbb","BUTTON": ("#FFFFFF", "#063289"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"DarkBrown1": {"BACKGROUND": "#2c2825","TEXT": "#fdcb52","INPUT": "#705e52","TEXT_INPUT": "#fdcb52","SCROLL": "#705e52","BUTTON": ("#000000", "#fdcb52"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"DarkBlue2": {"BACKGROUND": "#1a2835","TEXT": "#d1ecff","INPUT": "#335267","TEXT_INPUT": "#acc2d0","SCROLL": "#1b6497","BUTTON": ("#000000", "#fafaf8"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"DarkBrown2": {"BACKGROUND": "#280001","TEXT": "#FFFFFF","INPUT": "#d8d584","TEXT_INPUT": "#000000","SCROLL": "#763e00","BUTTON": ("#000000", "#daad28"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"DarkGreen": {"BACKGROUND": "#82a459","TEXT": "#000000","INPUT": "#d8d584","TEXT_INPUT": "#000000","SCROLL": "#e3ecf3","BUTTON": ("#FFFFFF", "#517239"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"LightBlue1": {"BACKGROUND": "#A5CADD","TEXT": "#6E266E","INPUT": "#E0F5FF","TEXT_INPUT": "#000000","SCROLL": "#E0F5FF","BUTTON": ("#FFFFFF", "#303952"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"LightPurple": {"BACKGROUND": "#B0AAC2","TEXT": "#000000","INPUT": "#F2EFE8","SCROLL": "#F2EFE8","TEXT_INPUT": "#000000","BUTTON": ("#000000", "#C2D4D8"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"LightBlue2": {"BACKGROUND": "#AAB6D3","TEXT": "#000000","INPUT": "#F1F4FC","SCROLL": "#F1F4FC","TEXT_INPUT": "#000000","BUTTON": ("#FFFFFF", "#7186C7"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"LightGreen3": {"BACKGROUND": "#A8C1B4","TEXT": "#000000","INPUT": "#DDE0DE","SCROLL": "#E3E3E3","TEXT_INPUT": "#000000","BUTTON": ("#FFFFFF", "#6D9F85"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"DarkBlue3": {"BACKGROUND": "#64778d","TEXT": "#FFFFFF","INPUT": "#f0f3f7","SCROLL": "#A6B2BE","TEXT_INPUT": "#000000","BUTTON": ("#FFFFFF", "#283b5b"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"LightGreen4": {"BACKGROUND": "#b4ffb4","TEXT": "#000000","INPUT": "#ffff64","SCROLL": "#ffb482","TEXT_INPUT": "#000000","BUTTON": ("#000000", "#ffa0dc"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"LightGreen5": {"BACKGROUND": "#92aa9d","TEXT": "#000000","INPUT": "#fcfff6","SCROLL": "#fcfff6","TEXT_INPUT": "#000000","BUTTON": ("#000000", "#d0dbbd"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"LightBrown2": {"BACKGROUND": "#a7ad7f","TEXT": "#000000","INPUT": "#e6d3a8","SCROLL": "#e6d3a8","TEXT_INPUT": "#000000","BUTTON": ("#FFFFFF", "#5d907d"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"LightBrown3": {"BACKGROUND": "#efeccb","TEXT": "#012f2f","INPUT": "#e6d3a8","SCROLL": "#e6d3a8","TEXT_INPUT": "#012f2f","BUTTON": ("#FFFFFF", "#046380"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"LightBlue3": {"BACKGROUND": "#a8cfdd","TEXT": "#000000","INPUT": "#dfedf2","SCROLL": "#dfedf2","TEXT_INPUT": "#000000","BUTTON": ("#FFFFFF", "#183440"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"LightBrown4": {"BACKGROUND": "#d7c79e","TEXT": "#a35638","INPUT": "#9dab86","TEXT_INPUT": "#000000","SCROLL": "#a35638","BUTTON": ("#FFFFFF", "#a35638"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#a35638", "#9dab86", "#e08f62", "#d7c79e"],}, +"DarkTeal": {"BACKGROUND": "#003f5c","TEXT": "#fb5b5a","INPUT": "#bc4873","TEXT_INPUT": "#FFFFFF","SCROLL": "#bc4873","BUTTON": ("#FFFFFF", "#fb5b5a"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#003f5c", "#472b62", "#bc4873", "#fb5b5a"],}, +"DarkPurple": {"BACKGROUND": "#472b62","TEXT": "#fb5b5a","INPUT": "#bc4873","TEXT_INPUT": "#FFFFFF","SCROLL": "#bc4873","BUTTON": ("#FFFFFF", "#472b62"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#003f5c", "#472b62", "#bc4873", "#fb5b5a"],}, +"LightGreen6": {"BACKGROUND": "#eafbea","TEXT": "#1f6650","INPUT": "#6f9a8d","TEXT_INPUT": "#FFFFFF","SCROLL": "#1f6650","BUTTON": ("#FFFFFF", "#1f6650"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#1f6650", "#6f9a8d", "#ea5e5e", "#eafbea"],}, +"DarkGrey2": {"BACKGROUND": "#2b2b28","TEXT": "#f8f8f8","INPUT": "#f1d6ab","TEXT_INPUT": "#000000","SCROLL": "#f1d6ab","BUTTON": ("#2b2b28", "#e3b04b"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#2b2b28", "#e3b04b", "#f1d6ab", "#f8f8f8"],}, +"LightBrown6": {"BACKGROUND": "#f9b282","TEXT": "#8f4426","INPUT": "#de6b35","TEXT_INPUT": "#FFFFFF","SCROLL": "#8f4426","BUTTON": ("#FFFFFF", "#8f4426"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#8f4426", "#de6b35", "#64ccda", "#f9b282"],}, +"DarkTeal1": {"BACKGROUND": "#396362","TEXT": "#ffe7d1","INPUT": "#f6c89f","TEXT_INPUT": "#000000","SCROLL": "#f6c89f","BUTTON": ("#ffe7d1", "#4b8e8d"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#396362", "#4b8e8d", "#f6c89f", "#ffe7d1"],}, +"LightBrown7": {"BACKGROUND": "#f6c89f","TEXT": "#396362","INPUT": "#4b8e8d","TEXT_INPUT": "#FFFFFF","SCROLL": "#396362","BUTTON": ("#FFFFFF", "#396362"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#396362", "#4b8e8d", "#f6c89f", "#ffe7d1"],}, +"DarkPurple1": {"BACKGROUND": "#0c093c","TEXT": "#fad6d6","INPUT": "#eea5f6","TEXT_INPUT": "#000000","SCROLL": "#eea5f6","BUTTON": ("#FFFFFF", "#df42d1"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#0c093c", "#df42d1", "#eea5f6", "#fad6d6"],}, +"DarkGrey3": {"BACKGROUND": "#211717","TEXT": "#dfddc7","INPUT": "#f58b54","TEXT_INPUT": "#000000","SCROLL": "#f58b54","BUTTON": ("#dfddc7", "#a34a28"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#211717", "#a34a28", "#f58b54", "#dfddc7"],}, +"LightBrown8": {"BACKGROUND": "#dfddc7","TEXT": "#211717","INPUT": "#a34a28","TEXT_INPUT": "#dfddc7","SCROLL": "#211717","BUTTON": ("#dfddc7", "#a34a28"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#211717", "#a34a28", "#f58b54", "#dfddc7"],}, +"DarkBlue4": {"BACKGROUND": "#494ca2","TEXT": "#e3e7f1","INPUT": "#c6cbef","TEXT_INPUT": "#000000","SCROLL": "#c6cbef","BUTTON": ("#FFFFFF", "#8186d5"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#494ca2", "#8186d5", "#c6cbef", "#e3e7f1"],}, +"LightBlue4": {"BACKGROUND": "#5c94bd","TEXT": "#470938","INPUT": "#1a3e59","TEXT_INPUT": "#FFFFFF","SCROLL": "#470938","BUTTON": ("#FFFFFF", "#470938"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#470938", "#1a3e59", "#5c94bd", "#f2d6eb"],}, +"DarkTeal2": {"BACKGROUND": "#394a6d","TEXT": "#c0ffb3","INPUT": "#52de97","TEXT_INPUT": "#000000","SCROLL": "#52de97","BUTTON": ("#c0ffb3", "#394a6d"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#394a6d", "#3c9d9b", "#52de97", "#c0ffb3"],}, +"DarkTeal3": {"BACKGROUND": "#3c9d9b","TEXT": "#c0ffb3","INPUT": "#52de97","TEXT_INPUT": "#000000","SCROLL": "#52de97","BUTTON": ("#c0ffb3", "#394a6d"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#394a6d", "#3c9d9b", "#52de97", "#c0ffb3"],}, +"DarkPurple5": {"BACKGROUND": "#730068","TEXT": "#f6f078","INPUT": "#01d28e","TEXT_INPUT": "#000000","SCROLL": "#01d28e","BUTTON": ("#f6f078", "#730068"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#730068", "#434982", "#01d28e", "#f6f078"],}, +"DarkPurple2": {"BACKGROUND": "#202060","TEXT": "#b030b0","INPUT": "#602080","TEXT_INPUT": "#FFFFFF","SCROLL": "#602080","BUTTON": ("#FFFFFF", "#202040"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#202040", "#202060", "#602080", "#b030b0"],}, +"DarkBlue5": {"BACKGROUND": "#000272","TEXT": "#ff6363","INPUT": "#a32f80","TEXT_INPUT": "#FFFFFF","SCROLL": "#a32f80","BUTTON": ("#FFFFFF", "#341677"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#000272", "#341677", "#a32f80", "#ff6363"],}, +"LightGrey2": {"BACKGROUND": "#f6f6f6","TEXT": "#420000","INPUT": "#d4d7dd","TEXT_INPUT": "#420000","SCROLL": "#420000","BUTTON": ("#420000", "#d4d7dd"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#420000", "#d4d7dd", "#eae9e9", "#f6f6f6"],}, +"LightGrey3": {"BACKGROUND": "#eae9e9","TEXT": "#420000","INPUT": "#d4d7dd","TEXT_INPUT": "#420000","SCROLL": "#420000","BUTTON": ("#420000", "#d4d7dd"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#420000", "#d4d7dd", "#eae9e9", "#f6f6f6"],}, +"DarkBlue6": {"BACKGROUND": "#01024e","TEXT": "#ff6464","INPUT": "#8b4367","TEXT_INPUT": "#FFFFFF","SCROLL": "#8b4367","BUTTON": ("#FFFFFF", "#543864"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#01024e", "#543864", "#8b4367", "#ff6464"],}, +"DarkBlue7": {"BACKGROUND": "#241663","TEXT": "#eae7af","INPUT": "#a72693","TEXT_INPUT": "#eae7af","SCROLL": "#a72693","BUTTON": ("#eae7af", "#160f30"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#160f30", "#241663", "#a72693", "#eae7af"],}, +"LightBrown9": {"BACKGROUND": "#f6d365","TEXT": "#3a1f5d","INPUT": "#c83660","TEXT_INPUT": "#f6d365","SCROLL": "#3a1f5d","BUTTON": ("#f6d365", "#c83660"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#3a1f5d", "#c83660", "#e15249", "#f6d365"],}, +"DarkPurple3": {"BACKGROUND": "#6e2142","TEXT": "#ffd692","INPUT": "#e16363","TEXT_INPUT": "#ffd692","SCROLL": "#e16363","BUTTON": ("#ffd692", "#943855"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#6e2142", "#943855", "#e16363", "#ffd692"],}, +"LightBrown10": {"BACKGROUND": "#ffd692","TEXT": "#6e2142","INPUT": "#943855","TEXT_INPUT": "#FFFFFF","SCROLL": "#6e2142","BUTTON": ("#FFFFFF", "#6e2142"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#6e2142", "#943855", "#e16363", "#ffd692"],}, +"DarkPurple4": {"BACKGROUND": "#200f21","TEXT": "#f638dc","INPUT": "#5a3d5c","TEXT_INPUT": "#FFFFFF","SCROLL": "#5a3d5c","BUTTON": ("#FFFFFF", "#382039"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#200f21", "#382039", "#5a3d5c", "#f638dc"],}, +"LightBlue5": {"BACKGROUND": "#b2fcff","TEXT": "#3e64ff","INPUT": "#5edfff","TEXT_INPUT": "#000000","SCROLL": "#3e64ff","BUTTON": ("#FFFFFF", "#3e64ff"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#3e64ff", "#5edfff", "#b2fcff", "#ecfcff"],}, +"DarkTeal4": {"BACKGROUND": "#464159","TEXT": "#c7f0db","INPUT": "#8bbabb","TEXT_INPUT": "#000000","SCROLL": "#8bbabb","BUTTON": ("#FFFFFF", "#6c7b95"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#464159", "#6c7b95", "#8bbabb", "#c7f0db"],}, +"LightTeal": {"BACKGROUND": "#c7f0db","TEXT": "#464159","INPUT": "#6c7b95","TEXT_INPUT": "#FFFFFF","SCROLL": "#464159","BUTTON": ("#FFFFFF", "#464159"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#464159", "#6c7b95", "#8bbabb", "#c7f0db"],}, +"DarkTeal5": {"BACKGROUND": "#8bbabb","TEXT": "#464159","INPUT": "#6c7b95","TEXT_INPUT": "#FFFFFF","SCROLL": "#464159","BUTTON": ("#c7f0db", "#6c7b95"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#464159", "#6c7b95", "#8bbabb", "#c7f0db"],}, +"LightGrey4": {"BACKGROUND": "#faf5ef","TEXT": "#672f2f","INPUT": "#99b19c","TEXT_INPUT": "#672f2f","SCROLL": "#672f2f","BUTTON": ("#672f2f", "#99b19c"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#672f2f", "#99b19c", "#d7d1c9", "#faf5ef"],}, +"LightGreen7": {"BACKGROUND": "#99b19c","TEXT": "#faf5ef","INPUT": "#d7d1c9","TEXT_INPUT": "#000000","SCROLL": "#d7d1c9","BUTTON": ("#FFFFFF", "#99b19c"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#672f2f", "#99b19c", "#d7d1c9", "#faf5ef"],}, +"LightGrey5": {"BACKGROUND": "#d7d1c9","TEXT": "#672f2f","INPUT": "#99b19c","TEXT_INPUT": "#672f2f","SCROLL": "#672f2f","BUTTON": ("#FFFFFF", "#672f2f"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#672f2f", "#99b19c", "#d7d1c9", "#faf5ef"],}, +"DarkBrown3": {"BACKGROUND": "#a0855b","TEXT": "#f9f6f2","INPUT": "#f1d6ab","TEXT_INPUT": "#000000","SCROLL": "#f1d6ab","BUTTON": ("#FFFFFF", "#38470b"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#38470b", "#a0855b", "#f1d6ab", "#f9f6f2"],}, +"LightBrown11": {"BACKGROUND": "#f1d6ab","TEXT": "#38470b","INPUT": "#a0855b","TEXT_INPUT": "#FFFFFF","SCROLL": "#38470b","BUTTON": ("#f9f6f2", "#a0855b"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#38470b", "#a0855b", "#f1d6ab", "#f9f6f2"],}, +"DarkRed": {"BACKGROUND": "#83142c","TEXT": "#f9d276","INPUT": "#ad1d45","TEXT_INPUT": "#FFFFFF","SCROLL": "#ad1d45","BUTTON": ("#f9d276", "#ad1d45"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#44000d", "#83142c", "#ad1d45", "#f9d276"],}, +"DarkTeal6": {"BACKGROUND": "#204969","TEXT": "#fff7f7","INPUT": "#dadada","TEXT_INPUT": "#000000","SCROLL": "#dadada","BUTTON": ("#000000", "#fff7f7"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#204969", "#08ffc8", "#dadada", "#fff7f7"],}, +"DarkBrown4": {"BACKGROUND": "#252525","TEXT": "#ff0000","INPUT": "#af0404","TEXT_INPUT": "#FFFFFF","SCROLL": "#af0404","BUTTON": ("#FFFFFF", "#252525"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#252525", "#414141", "#af0404", "#ff0000"],}, +"LightYellow": {"BACKGROUND": "#f4ff61","TEXT": "#27aa80","INPUT": "#32ff6a","TEXT_INPUT": "#000000","SCROLL": "#27aa80","BUTTON": ("#f4ff61", "#27aa80"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#27aa80", "#32ff6a", "#a8ff3e", "#f4ff61"],}, +"DarkGreen1": {"BACKGROUND": "#2b580c","TEXT": "#fdef96","INPUT": "#f7b71d","TEXT_INPUT": "#000000","SCROLL": "#f7b71d","BUTTON": ("#fdef96", "#2b580c"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#2b580c", "#afa939", "#f7b71d", "#fdef96"],}, +"LightGreen8": {"BACKGROUND": "#c8dad3","TEXT": "#63707e","INPUT": "#93b5b3","TEXT_INPUT": "#000000","SCROLL": "#63707e","BUTTON": ("#FFFFFF", "#63707e"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#63707e", "#93b5b3", "#c8dad3", "#f2f6f5"],}, +"DarkTeal7": {"BACKGROUND": "#248ea9","TEXT": "#fafdcb","INPUT": "#aee7e8","TEXT_INPUT": "#000000","SCROLL": "#aee7e8","BUTTON": ("#000000", "#fafdcb"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#248ea9", "#28c3d4", "#aee7e8", "#fafdcb"],}, +"DarkBlue8": {"BACKGROUND": "#454d66","TEXT": "#d9d872","INPUT": "#58b368","TEXT_INPUT": "#000000","SCROLL": "#58b368","BUTTON": ("#000000", "#009975"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#009975", "#454d66", "#58b368", "#d9d872"],}, +"DarkBlue9": {"BACKGROUND": "#263859","TEXT": "#ff6768","INPUT": "#6b778d","TEXT_INPUT": "#FFFFFF","SCROLL": "#6b778d","BUTTON": ("#ff6768", "#263859"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#17223b", "#263859", "#6b778d", "#ff6768"],}, +"DarkBlue10": {"BACKGROUND": "#0028ff","TEXT": "#f1f4df","INPUT": "#10eaf0","TEXT_INPUT": "#000000","SCROLL": "#10eaf0","BUTTON": ("#f1f4df", "#24009c"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#24009c", "#0028ff", "#10eaf0", "#f1f4df"],}, +"DarkBlue11": {"BACKGROUND": "#6384b3","TEXT": "#e6f0b6","INPUT": "#b8e9c0","TEXT_INPUT": "#000000","SCROLL": "#b8e9c0","BUTTON": ("#e6f0b6", "#684949"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#684949", "#6384b3", "#b8e9c0", "#e6f0b6"],}, +"DarkTeal8": {"BACKGROUND": "#71a0a5","TEXT": "#212121","INPUT": "#665c84","TEXT_INPUT": "#FFFFFF","SCROLL": "#212121","BUTTON": ("#fab95b", "#665c84"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#212121", "#665c84", "#71a0a5", "#fab95b"],}, +"DarkRed1": {"BACKGROUND": "#c10000","TEXT": "#eeeeee","INPUT": "#dedede","TEXT_INPUT": "#000000","SCROLL": "#dedede","BUTTON": ("#c10000", "#eeeeee"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#c10000", "#ff4949", "#dedede", "#eeeeee"],}, +"LightBrown5": {"BACKGROUND": "#fff591","TEXT": "#e41749","INPUT": "#f5587b","TEXT_INPUT": "#000000","SCROLL": "#e41749","BUTTON": ("#fff591", "#e41749"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#e41749", "#f5587b", "#ff8a5c", "#fff591"],}, +"LightGreen9": {"BACKGROUND": "#f1edb3","TEXT": "#3b503d","INPUT": "#4a746e","TEXT_INPUT": "#f1edb3","SCROLL": "#3b503d","BUTTON": ("#f1edb3", "#3b503d"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#3b503d", "#4a746e", "#c8cf94", "#f1edb3"],"DESCRIPTION": ["Green", "Turquoise", "Yellow"],}, +"DarkGreen2": {"BACKGROUND": "#3b503d","TEXT": "#f1edb3","INPUT": "#c8cf94","TEXT_INPUT": "#000000","SCROLL": "#c8cf94","BUTTON": ("#f1edb3", "#3b503d"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#3b503d", "#4a746e", "#c8cf94", "#f1edb3"],"DESCRIPTION": ["Green", "Turquoise", "Yellow"],}, +"LightGray1": {"BACKGROUND": "#f2f2f2","TEXT": "#222831","INPUT": "#393e46","TEXT_INPUT": "#FFFFFF","SCROLL": "#222831","BUTTON": ("#f2f2f2", "#222831"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#222831", "#393e46", "#f96d00", "#f2f2f2"],"DESCRIPTION": ["#000000", "Grey", "Orange", "Grey", "Autumn"],}, +"DarkGrey4": {"BACKGROUND": "#52524e","TEXT": "#e9e9e5","INPUT": "#d4d6c8","TEXT_INPUT": "#000000","SCROLL": "#d4d6c8","BUTTON": ("#FFFFFF", "#9a9b94"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#52524e", "#9a9b94", "#d4d6c8", "#e9e9e5"],"DESCRIPTION": ["Grey", "Pastel", "Winter"],}, +"DarkBlue12": {"BACKGROUND": "#324e7b","TEXT": "#f8f8f8","INPUT": "#86a6df","TEXT_INPUT": "#000000","SCROLL": "#86a6df","BUTTON": ("#FFFFFF", "#5068a9"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#324e7b", "#5068a9", "#86a6df", "#f8f8f8"],"DESCRIPTION": ["Blue", "Grey", "Cold", "Winter"],}, +"DarkPurple6": {"BACKGROUND": "#070739","TEXT": "#e1e099","INPUT": "#c327ab","TEXT_INPUT": "#e1e099","SCROLL": "#c327ab","BUTTON": ("#e1e099", "#521477"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#070739", "#521477", "#c327ab", "#e1e099"],"DESCRIPTION": ["#000000", "Purple", "Yellow", "Dark"],}, +"DarkPurple7": {"BACKGROUND": "#191930","TEXT": "#B1B7C5","INPUT": "#232B5C","TEXT_INPUT": "#D0E3E7","SCROLL": "#B1B7C5","BUTTON": ("#272D38", "#B1B7C5"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"DarkBlue13": {"BACKGROUND": "#203562","TEXT": "#e3e8f8","INPUT": "#c0c5cd","TEXT_INPUT": "#000000","SCROLL": "#c0c5cd","BUTTON": ("#FFFFFF", "#3e588f"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#203562", "#3e588f", "#c0c5cd", "#e3e8f8"],"DESCRIPTION": ["Blue", "Grey", "Wedding", "Cold"],}, +"DarkBrown5": {"BACKGROUND": "#3c1b1f","TEXT": "#f6e1b5","INPUT": "#e2bf81","TEXT_INPUT": "#000000","SCROLL": "#e2bf81","BUTTON": ("#3c1b1f", "#f6e1b5"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#3c1b1f", "#b21e4b", "#e2bf81", "#f6e1b5"],"DESCRIPTION": ["Brown", "Red", "Yellow", "Warm"],}, +"DarkGreen3": {"BACKGROUND": "#062121","TEXT": "#eeeeee","INPUT": "#e4dcad","TEXT_INPUT": "#000000","SCROLL": "#e4dcad","BUTTON": ("#eeeeee", "#181810"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#062121", "#181810", "#e4dcad", "#eeeeee"],"DESCRIPTION": ["#000000", "#000000", "Brown", "Grey"],}, +"DarkBlack1": {"BACKGROUND": "#181810","TEXT": "#eeeeee","INPUT": "#e4dcad","TEXT_INPUT": "#000000","SCROLL": "#e4dcad","BUTTON": ("#FFFFFF", "#062121"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#062121", "#181810", "#e4dcad", "#eeeeee"],"DESCRIPTION": ["#000000", "#000000", "Brown", "Grey"],}, +"DarkGrey5": {"BACKGROUND": "#343434","TEXT": "#f3f3f3","INPUT": "#e9dcbe","TEXT_INPUT": "#000000","SCROLL": "#e9dcbe","BUTTON": ("#FFFFFF", "#8e8b82"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#343434", "#8e8b82", "#e9dcbe", "#f3f3f3"],"DESCRIPTION": ["Grey", "Brown"],}, +"LightBrown12": {"BACKGROUND": "#8e8b82","TEXT": "#f3f3f3","INPUT": "#e9dcbe","TEXT_INPUT": "#000000","SCROLL": "#e9dcbe","BUTTON": ("#f3f3f3", "#8e8b82"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#343434", "#8e8b82", "#e9dcbe", "#f3f3f3"],"DESCRIPTION": ["Grey", "Brown"],}, +"DarkTeal9": {"BACKGROUND": "#13445a","TEXT": "#fef4e8","INPUT": "#446878","TEXT_INPUT": "#FFFFFF","SCROLL": "#446878","BUTTON": ("#fef4e8", "#446878"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#13445a", "#970747", "#446878", "#fef4e8"],"DESCRIPTION": ["Red", "Grey", "Blue", "Wedding", "Retro"],}, +"DarkBlue14": {"BACKGROUND": "#21273d","TEXT": "#f1f6f8","INPUT": "#b9d4f1","TEXT_INPUT": "#000000","SCROLL": "#b9d4f1","BUTTON": ("#FFFFFF", "#6a759b"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#21273d", "#6a759b", "#b9d4f1", "#f1f6f8"],"DESCRIPTION": ["Blue", "#000000", "Grey", "Cold", "Winter"],}, +"LightBlue6": {"BACKGROUND": "#f1f6f8","TEXT": "#21273d","INPUT": "#6a759b","TEXT_INPUT": "#FFFFFF","SCROLL": "#21273d","BUTTON": ("#f1f6f8", "#6a759b"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#21273d", "#6a759b", "#b9d4f1", "#f1f6f8"],"DESCRIPTION": ["Blue", "#000000", "Grey", "Cold", "Winter"],}, +"DarkGreen4": {"BACKGROUND": "#044343","TEXT": "#e4e4e4","INPUT": "#045757","TEXT_INPUT": "#e4e4e4","SCROLL": "#045757","BUTTON": ("#e4e4e4", "#045757"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#222222", "#044343", "#045757", "#e4e4e4"],"DESCRIPTION": ["#000000", "Turquoise", "Grey", "Dark"],}, +"DarkGreen5": {"BACKGROUND": "#1b4b36","TEXT": "#e0e7f1","INPUT": "#aebd77","TEXT_INPUT": "#000000","SCROLL": "#aebd77","BUTTON": ("#FFFFFF", "#538f6a"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#1b4b36", "#538f6a", "#aebd77", "#e0e7f1"],"DESCRIPTION": ["Green", "Grey"],}, +"DarkTeal10": {"BACKGROUND": "#0d3446","TEXT": "#d8dfe2","INPUT": "#71adb5","TEXT_INPUT": "#000000","SCROLL": "#71adb5","BUTTON": ("#FFFFFF", "#176d81"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#0d3446", "#176d81", "#71adb5", "#d8dfe2"],"DESCRIPTION": ["Grey", "Turquoise", "Winter", "Cold"],}, +"DarkGrey6": {"BACKGROUND": "#3e3e3e","TEXT": "#ededed","INPUT": "#68868c","TEXT_INPUT": "#ededed","SCROLL": "#68868c","BUTTON": ("#FFFFFF", "#405559"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#3e3e3e", "#405559", "#68868c", "#ededed"],"DESCRIPTION": ["Grey", "Turquoise", "Winter"],}, +"DarkTeal11": {"BACKGROUND": "#405559","TEXT": "#ededed","INPUT": "#68868c","TEXT_INPUT": "#ededed","SCROLL": "#68868c","BUTTON": ("#ededed", "#68868c"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#3e3e3e", "#405559", "#68868c", "#ededed"],"DESCRIPTION": ["Grey", "Turquoise", "Winter"],}, +"LightBlue7": {"BACKGROUND": "#9ed0e0","TEXT": "#19483f","INPUT": "#5c868e","TEXT_INPUT": "#FFFFFF","SCROLL": "#19483f","BUTTON": ("#FFFFFF", "#19483f"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#19483f", "#5c868e", "#ff6a38", "#9ed0e0"],"DESCRIPTION": ["Orange", "Blue", "Turquoise"],}, +"LightGreen10": {"BACKGROUND": "#d8ebb5","TEXT": "#205d67","INPUT": "#639a67","TEXT_INPUT": "#FFFFFF","SCROLL": "#205d67","BUTTON": ("#d8ebb5", "#205d67"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#205d67", "#639a67", "#d9bf77", "#d8ebb5"],"DESCRIPTION": ["Blue", "Green", "Brown", "Vintage"],}, +"DarkBlue15": {"BACKGROUND": "#151680","TEXT": "#f1fea4","INPUT": "#375fc0","TEXT_INPUT": "#f1fea4","SCROLL": "#375fc0","BUTTON": ("#f1fea4", "#1c44ac"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#151680", "#1c44ac", "#375fc0", "#f1fea4"],"DESCRIPTION": ["Blue", "Yellow", "Cold"],}, +"DarkBlue16": {"BACKGROUND": "#1c44ac","TEXT": "#f1fea4","INPUT": "#375fc0","TEXT_INPUT": "#f1fea4","SCROLL": "#375fc0","BUTTON": ("#f1fea4", "#151680"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#151680", "#1c44ac", "#375fc0", "#f1fea4"],"DESCRIPTION": ["Blue", "Yellow", "Cold"],}, +"DarkTeal12": {"BACKGROUND": "#004a7c","TEXT": "#fafafa","INPUT": "#e8f1f5","TEXT_INPUT": "#000000","SCROLL": "#e8f1f5","BUTTON": ("#fafafa", "#005691"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#004a7c", "#005691", "#e8f1f5", "#fafafa"],"DESCRIPTION": ["Grey", "Blue", "Cold", "Winter"],}, +"LightBrown13": {"BACKGROUND": "#ebf5ee","TEXT": "#921224","INPUT": "#bdc6b8","TEXT_INPUT": "#921224","SCROLL": "#921224","BUTTON": ("#FFFFFF", "#921224"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#921224", "#bdc6b8", "#bce0da", "#ebf5ee"],"DESCRIPTION": ["Red", "Blue", "Grey", "Vintage", "Wedding"],}, +"DarkBlue17": {"BACKGROUND": "#21294c","TEXT": "#f9f2d7","INPUT": "#f2dea8","TEXT_INPUT": "#000000","SCROLL": "#f2dea8","BUTTON": ("#f9f2d7", "#141829"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#141829", "#21294c", "#f2dea8", "#f9f2d7"],"DESCRIPTION": ["#000000", "Blue", "Yellow"],}, +"DarkBrown6": {"BACKGROUND": "#785e4d","TEXT": "#f2eee3","INPUT": "#baaf92","TEXT_INPUT": "#000000","SCROLL": "#baaf92","BUTTON": ("#FFFFFF", "#785e4d"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#785e4d", "#ff8426", "#baaf92", "#f2eee3"],"DESCRIPTION": ["Grey", "Brown", "Orange", "Autumn"],}, +"DarkGreen6": {"BACKGROUND": "#5c715e","TEXT": "#f2f9f1","INPUT": "#ddeedf","TEXT_INPUT": "#000000","SCROLL": "#ddeedf","BUTTON": ("#f2f9f1", "#5c715e"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#5c715e", "#b6cdbd", "#ddeedf", "#f2f9f1"],"DESCRIPTION": ["Grey", "Green", "Vintage"],}, +"DarkGreen7": {"BACKGROUND": "#0C231E","TEXT": "#efbe1c","INPUT": "#153C33","TEXT_INPUT": "#efbe1c","SCROLL": "#153C33","BUTTON": ("#efbe1c", "#153C33"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"DarkGrey7": {"BACKGROUND": "#4b586e","TEXT": "#dddddd","INPUT": "#574e6d","TEXT_INPUT": "#dddddd","SCROLL": "#574e6d","BUTTON": ("#dddddd", "#43405d"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#43405d", "#4b586e", "#574e6d", "#dddddd"],"DESCRIPTION": ["Grey", "Winter", "Cold"],}, +"DarkRed2": {"BACKGROUND": "#ab1212","TEXT": "#f6e4b5","INPUT": "#cd3131","TEXT_INPUT": "#f6e4b5","SCROLL": "#cd3131","BUTTON": ("#f6e4b5", "#ab1212"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#ab1212", "#1fad9f", "#cd3131", "#f6e4b5"],"DESCRIPTION": ["Turquoise", "Red", "Yellow"],}, +"LightGrey6": {"BACKGROUND": "#e3e3e3","TEXT": "#233142","INPUT": "#455d7a","TEXT_INPUT": "#e3e3e3","SCROLL": "#233142","BUTTON": ("#e3e3e3", "#455d7a"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,"COLOR_LIST": ["#233142", "#455d7a", "#f95959", "#e3e3e3"],"DESCRIPTION": ["#000000", "Blue", "Red", "Grey"],}, +"HotDogStand": {"BACKGROUND": "red","TEXT": "yellow","INPUT": "yellow","TEXT_INPUT": "#000000","SCROLL": "yellow","BUTTON": ("red", "yellow"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"DarkGrey8": {"BACKGROUND": "#19232D","TEXT": "#ffffff","INPUT": "#32414B","TEXT_INPUT": "#ffffff","SCROLL": "#505F69","BUTTON": ("#ffffff", "#32414B"),"PROGRESS": ("#505F69", "#32414B"),"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"DarkGrey9": {"BACKGROUND": "#36393F","TEXT": "#DCDDDE","INPUT": "#40444B","TEXT_INPUT": "#ffffff","SCROLL": "#202225","BUTTON": ("#202225", "#B9BBBE"),"PROGRESS": ("#202225", "#40444B"),"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"DarkGrey10": {"BACKGROUND": "#1c1e23","TEXT": "#cccdcf","INPUT": "#272a31","TEXT_INPUT": "#8b9fde","SCROLL": "#313641","BUTTON": ("#f5f5f6", "#2e3d5a"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"DarkGrey11": {"BACKGROUND": "#1c1e23","TEXT": "#cccdcf","INPUT": "#313641","TEXT_INPUT": "#cccdcf","SCROLL": "#313641","BUTTON": ("#f5f5f6", "#313641"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"DarkGrey12": {"BACKGROUND": "#1c1e23","TEXT": "#8b9fde","INPUT": "#313641","TEXT_INPUT": "#8b9fde","SCROLL": "#313641","BUTTON": ("#cccdcf", "#2e3d5a"),"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE,"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"DarkGrey13": {"BACKGROUND": "#1c1e23","TEXT": "#cccdcf","INPUT": "#272a31","TEXT_INPUT": "#cccdcf","SCROLL": "#313641","BUTTON": ("#8b9fde", "#313641"),"PROGRESS": ("#cccdcf", "#272a31"),"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"DarkGrey14": {"BACKGROUND": "#24292e","TEXT": "#fafbfc","INPUT": "#1d2125","TEXT_INPUT": "#fafbfc","SCROLL": "#1d2125","BUTTON": ("#fafbfc", "#155398"),"PROGRESS": ("#155398", "#1d2125"),"BORDER": 1,"SLIDER_DEPTH": 0,"PROGRESS_DEPTH": 0,}, +"DarkBrown7": {"BACKGROUND": "#2c2417","TEXT": "#baa379","INPUT": "#baa379","TEXT_INPUT": "#000000","SCROLL": "#392e1c","BUTTON": ("#000000", "#baa379"),"PROGRESS": ("#baa379", "#453923"),"BORDER": 1,"SLIDER_DEPTH": 1,"PROGRESS_DEPTH": 0,}, +"Python": {"BACKGROUND": "#3d7aab","TEXT": "#ffde56","INPUT": "#295273","TEXT_INPUT": "#ffde56","SCROLL": "#295273","BUTTON": ("#ffde56", "#295273"),"PROGRESS": ("#ffde56", "#295273"),"BORDER": 1,"SLIDER_DEPTH": 1,"PROGRESS_DEPTH": 0,}, +} + + + +def ListOfLookAndFeelValues(): + """ + Get a list of the valid values to pass into your call to change_look_and_feel + :return: List[str] - list of valid string values + """ + return sorted(list(LOOK_AND_FEEL_TABLE.keys())) + + +def theme(new_theme=None): + """ + Sets / Gets the current Theme. If none is specified then returns the current theme. + This call replaces the ChangeLookAndFeel / change_look_and_feel call which only sets the theme. + + :param new_theme: (str) the new theme name to use + :return: (str) the currently selected theme + """ + if new_theme is not None: + change_look_and_feel(new_theme) + return CURRENT_LOOK_AND_FEEL + + +def theme_background_color(color=None): + """ + Sets/Returns the background color currently in use + Used for Windows and containers (Column, Frame, Tab) and tables + + :return: (str) - color string of the background color currently in use + """ + if color is not None: + set_options(background_color=color) + return DEFAULT_BACKGROUND_COLOR + + +def theme_element_background_color(color=None): + """ + Sets/Returns the background color currently in use for all elements except containers + + :return: (str) - color string of the element background color currently in use + """ + if color is not None: + set_options(element_background_color=color) + return DEFAULT_ELEMENT_BACKGROUND_COLOR + + +def theme_text_color(color=None): + """ + Sets/Returns the text color currently in use + + :return: (str) - color string of the text color currently in use + """ + if color is not None: + set_options(text_color=color) + return DEFAULT_TEXT_COLOR + + + +def theme_input_background_color(color=None): + """ + Sets/Returns the input element background color currently in use + + :return: (str) - color string of the input element background color currently in use + """ + if color is not None: + set_options(input_elements_background_color=color) + return DEFAULT_INPUT_ELEMENTS_COLOR + + +def theme_input_text_color(color=None): + """ + Sets/Returns the input element entry color (not the text but the thing that's displaying the text) + + :return: (str) - color string of the input element color currently in use + """ + if color is not None: + set_options(input_text_color=color) + return DEFAULT_INPUT_TEXT_COLOR + + + +def theme_button_color(color=None): + """ + Sets/Returns the button color currently in use + + :return: Tuple[str, str] - TUPLE with color strings of the button color currently in use (button text color, button background color) + """ + if color is not None: + set_options(button_color=color) + return DEFAULT_BUTTON_COLOR + + +def theme_progress_bar_color(color=None): + """ + Sets/Returns the progress bar colors by the current color theme + + :return: Tuple[str, str] - TUPLE with color strings of the ProgressBar color currently in use(button text color, button background color) + """ + if color is not None: + set_options(progress_meter_color=color) + return DEFAULT_PROGRESS_BAR_COLOR + + +def theme_slider_color(color=None): + """ + Sets/Returns the slider color (used for sliders) + + :return: (str) - color string of the slider color currently in use + """ + if color is not None: + set_options(scrollbar_color=color) + return DEFAULT_SCROLLBAR_COLOR + + +def theme_border_width(border_width=None): + """ + Sets/Returns the border width currently in use + Used by non ttk elements at the moment + + :return: (int) - border width currently in use + """ + if border_width is not None: + set_options(border_width=border_width) + return DEFAULT_BORDER_WIDTH + + +def theme_slider_border_width(border_width=None): + """ + Sets/Returns the slider border width currently in use + + :return: (int) - border width currently in use + """ + if border_width is not None: + set_options(slider_border_width=border_width) + return DEFAULT_SLIDER_BORDER_WIDTH + + +def theme_progress_bar_border_width(border_width=None): + """ + Sets/Returns the progress meter border width currently in use + + :return: (int) - border width currently in use + """ + if border_width is not None: + set_options(progress_meter_border_depth=border_width) + return DEFAULT_PROGRESS_BAR_BORDER_WIDTH + + + +def theme_element_text_color(color=None): + """ + Sets/Returns the text color used by elements that have text as part of their display (Tables, Trees and Sliders) + + :return: (str) - color string currently in use + """ + if color is not None: + set_options(element_text_color=color) + return DEFAULT_ELEMENT_TEXT_COLOR + + +def theme_list(): + """ + Returns a sorted list of the currently available color themes + + :return: List[str] - A sorted list of the currently available color themes + """ + return list_of_look_and_feel_values() + + + +def theme_add_new(new_theme_name, new_theme_dict): + """ + Add a new theme to the dictionary of themes + + :param new_theme_name: text to display in element + :type new_theme_name: (str) + :param new_theme_dict: text to display in element + :type new_theme_dict: (dict) + """ + global LOOK_AND_FEEL_TABLE + try: + LOOK_AND_FEEL_TABLE[new_theme_name] = new_theme_dict + except Exception as e: + print('Exception during adding new theme {}'.format(e)) + + + + +def theme_previewer(columns=12): + """ + Show a window with all of the color themes - takes a while so be patient + + :param columns: (int) number of themes in a single row + """ + preview_all_look_and_feel_themes(columns) + + +def ChangeLookAndFeel(index, force=False): + """ + Change the "color scheme" of all future PySimpleGUI Windows. + The scheme are string names that specify a group of colors. Background colors, text colors, button colors. + There are 13 different color settings that are changed at one time using a single call to ChangeLookAndFeel + The look and feel table itself has these indexes into the dictionary LOOK_AND_FEEL_TABLE. + The original list was (prior to a major rework and renaming)... these names still work... + In Nov 2019 a new Theme Formula was devised to make choosing a theme easier: + The "Formula" is: + ["Dark" or "Light"] Color Number + Colors can be Blue Brown Grey Green Purple Red Teal Yellow Black + The number will vary for each pair. There are more DarkGrey entries than there are LightYellow for example. + Default = The default settings (only button color is different than system default) + Default1 = The full system default including the button (everything's gray... how sad... don't be all gray... please....) + :param index: the name of the index into the Look and Feel table (does not have to be exact, can be "fuzzy") + :type index: (str) + :param force: no longer used + :type force: (bool) + """ + global CURRENT_LOOK_AND_FEEL + + # if sys.platform.startswith('darwin') and not force: + # print('*** Changing look and feel is not supported on Mac platform ***') + # return + + theme = index + # normalize available l&f values + lf_values = [item.lower() for item in list_of_look_and_feel_values()] + # option 1 + opt1 = theme.replace(' ', '').lower() + + # option 2 (reverse lookup) + optx = theme.lower().split(' ') + optx.reverse() + opt2 = ''.join(optx) + + # search for valid l&f name + if opt1 in lf_values: + ix = lf_values.index(opt1) + elif opt2 in lf_values: + ix = lf_values.index(opt2) + else: + ix = random.random.randint(0, len(lf_values) - 1) + print('** Warning - {} Theme is not a valid theme. Change your theme call. **'.format(index)) + print('valid values are', list_of_look_and_feel_values()) + print('Instead, please enjoy a random Theme named {}'.format(list_of_look_and_feel_values()[ix])) + + selection = list_of_look_and_feel_values()[ix] + CURRENT_LOOK_AND_FEEL = selection + try: + colors = LOOK_AND_FEEL_TABLE[selection] + + # Color the progress bar using button background and input colors...unless they're the same + if colors['PROGRESS'] != COLOR_SYSTEM_DEFAULT: + if colors['BUTTON'][1] != colors['INPUT'] and colors['BUTTON'][1] != colors['BACKGROUND']: + colors['PROGRESS'] = colors['BUTTON'][1], colors['INPUT'] + else: # if the same, then use text input on top of input color + colors['PROGRESS'] = (colors['TEXT_INPUT'], colors['INPUT']) + else: + colors['PROGRESS'] = DEFAULT_PROGRESS_BAR_COLOR_OFFICIAL + # call to change all the colors + SetOptions(background_color=colors['BACKGROUND'], + text_element_background_color=colors['BACKGROUND'], + element_background_color=colors['BACKGROUND'], + text_color=colors['TEXT'], + input_elements_background_color=colors['INPUT'], + # button_color=colors['BUTTON'] if not sys.platform.startswith('darwin') else None, + button_color=colors['BUTTON'], + progress_meter_color=colors['PROGRESS'], + border_width=colors['BORDER'], + slider_border_width=colors['SLIDER_DEPTH'], + progress_meter_border_depth=colors['PROGRESS_DEPTH'], + scrollbar_color=(colors['SCROLL']), + element_text_color=colors['TEXT'], + input_text_color=colors['TEXT_INPUT']) + except: # most likely an index out of range + print('** Warning - Theme value not valid. Change your theme call. **') + print('valid values are', list_of_look_and_feel_values()) + + + +def preview_all_look_and_feel_themes(columns=12): + """ + Displays a "Quick Reference Window" showing all of the different Look and Feel settings that are available. + They are sorted alphabetically. The legacy color names are mixed in, but otherwise they are sorted into Dark and Light halves + :param columns: (int) The number of themes to display per row + """ + + # Show a "splash" type message so the user doesn't give up waiting + popup_quick_message('Hang on for a moment, this will take a bit to create....', background_color='red', text_color='white', auto_close=True, non_blocking=True) + + web = False + + win_bg = 'black' + + def sample_layout(): + return [[Text('Text element'), InputText('Input data here', size=(10, 1))], + [Button('Ok'), Button('Cancel'), Slider((1, 10), orientation='h', size=(5, 15))]] + + layout = [[Text('Here is a complete list of themes', font='Default 18', background_color=win_bg)]] + + names = list_of_look_and_feel_values() + names.sort() + row = [] + for count, theme in enumerate(names): + change_look_and_feel(theme) + if not count % columns: + layout += [row] + row = [] + row += [Frame(theme, sample_layout() if not web else [[T(theme)]] + sample_layout())] + if row: + layout += [row] + + window = Window('Preview of all Look and Feel choices', layout, background_color=win_bg) + window.read() + window.close() + + +# ============================== sprint ======# +# Is identical to the Scrolled Text Box # +# Provides a crude 'print' mechanism but in a # +# GUI environment # +# ============================================# +sprint = ScrolledTextBox + + +# Converts an object's contents into a nice printable string. Great for dumping debug data +def ObjToStringSingleObj(obj): + """ + Dumps an Object's values as a formatted string. Very nicely done. Great way to display an object's member variables in human form + Returns only the top-most object's variables instead of drilling down to dispolay more + :param obj: The object to display + :type obj: (Any) + :return: Formatted output of the object's values + :rtype: (str) + """ + if obj is None: + return 'None' + return str(obj.__class__) + '\n' + '\n'.join( + (repr(item) + ' = ' + repr(obj.__dict__[item]) for item in sorted(obj.__dict__))) + + +def ObjToString(obj, extra=' '): + """ + Dumps an Object's values as a formatted string. Very nicely done. Great way to display an object's member variables in human form + :param obj: The object to display + :type obj: (Any) + :param extra: extra stuff (Default value = ' ') + :type extra: (str) + :return: Formatted output of the object's values + :rtype: (str) + """ + if obj is None: + return 'None' + return str(obj.__class__) + '\n' + '\n'.join( + (extra + (str(item) + ' = ' + + (ObjToString(obj.__dict__[item], extra + ' ') if hasattr(obj.__dict__[item], '__dict__') else str( + obj.__dict__[item]))) + for item in sorted(obj.__dict__))) + + +# ------------------------------------------------------------------------------------------------------------------ # +# ===================================== Upper PySimpleGUI ======================================================== # +# Pre-built dialog boxes for all your needs These are the "high level API calls # +# ------------------------------------------------------------------------------------------------------------------ # + +# ----------------------------------- The mighty Popup! ------------------------------------------------------------ # + +def Popup(*args, title=None, button_color=None, background_color=None, text_color=None, button_type=POPUP_BUTTONS_OK, + auto_close=False, auto_close_duration=None, custom_text=(None, None), non_blocking=False, icon=DEFAULT_WINDOW_ICON, line_width=None, + font=None, no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None), any_key_closes=False, image=None): + """ + Popup - Display a popup box with as many parms as you wish to include + :param *args: Variable number of your arguments. Load up the call with stuff to see! + :type *args: (Any) + :param title: Optional title for the window. If none provided, the first arg will be used instead. + :type title: (str) + :param button_color: Color of the buttons shown (text color, button color) + :type button_color: Tuple[str, str] + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param button_type: NOT USER SET! Determines which pre-defined buttons will be shown (Default value = POPUP_BUTTONS_OK). There are many Popup functions and they call Popup, changing this parameter to get the desired effect. + :type button_type: (int) + :param auto_close: If True the window will automatically close + :type auto_close: (bool) + :param auto_close_duration: time in seconds to keep window open before closing it automatically + :type auto_close_duration: (int) + :param custom_text: A string or pair of strings that contain the text to display on the buttons + :type custom_text: Union[Tuple[str, str], str] + :param non_blocking: If True then will immediately return from the function without waiting for the user's input. + :type non_blocking: (bool) + :param icon: icon to display on the window. Same format as a Window call + :type icon: Union[str, bytes] + :param line_width: Width of lines in characters. Defaults to MESSAGE_BOX_LINE_WIDTH + :type line_width: (int) + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + :param grab_anywhere: If True, than can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param location: Location on screen to display the top left corner of window. Defaults to window centered on screen + :type location: Tuple[int, int] + :param any_key_closes: If True then will turn on return_keyboard_events for the window which will cause window to close as soon as any key is pressed. Normally the return key only will close the window. Default is false. + :type any_key_closes: (bool) + :param image: Image to include at the top of the popup window + :type image: (str) or (bytes) + :return: Returns text of the button that was pressed. None will be returned if user closed window with X + :rtype: Union[str, None] + """ + + if not args: + args_to_print = [''] + else: + args_to_print = args + if line_width != None: + local_line_width = line_width + else: + local_line_width = MESSAGE_BOX_LINE_WIDTH + + _title = title if title is not None else args_to_print[0] + _title = str(_title) + window = Window(_title, auto_size_text=True, background_color=background_color, button_color=button_color, + auto_close=auto_close, auto_close_duration=auto_close_duration, icon=icon, font=font, + no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location, + return_keyboard_events=any_key_closes) + max_line_total, total_lines = 0, 0 + layout = [[]] + if image is not None: + if isinstance(image, str): + layout += [[Image(filename=image)]] + else: + layout += [[Image(data_base64=image)]] + + for message in args_to_print: + # fancy code to check if string and convert if not is not need. Just always convert to string :-) + # if not isinstance(message, str): message = str(message) + message = str(message) + if message.count('\n'): # if there are line breaks, then wrap each segment separately + # message_wrapped = message # used to just do this, but now breaking into smaller pieces + message_wrapped = '' + msg_list = message.split('\n') # break into segments that will each be wrapped + message_wrapped = '\n'.join([textwrap.fill(msg, local_line_width) for msg in msg_list]) + else: + message_wrapped = textwrap.fill(message, local_line_width) + message_wrapped_lines = message_wrapped.count('\n') + 1 + longest_line_len = max([len(l) for l in message.split('\n')]) + width_used = min(longest_line_len, local_line_width) + max_line_total = max(max_line_total, width_used) + # height = _GetNumLinesNeeded(message, width_used) + height = message_wrapped_lines + window.AddRow( + Text(message_wrapped, auto_size_text=True, text_color=text_color, background_color=background_color)) + total_lines += height + + # if total_lines < 3: + # layout.append([Text('',text_color=text_color, background_color=background_color)]) + if non_blocking: + PopupButton = DummyButton # important to use or else button will close other windows too! + else: + PopupButton = Button + # show either an OK or Yes/No depending on paramater + # show either an OK or Yes/No depending on paramater + if custom_text != (None, None): + if type(custom_text) is not tuple: + layout.append([PopupButton(custom_text, button_color=button_color, focus=True, bind_return_key=True)]) + elif custom_text[1] is None: + layout.append([PopupButton(custom_text[0], button_color=button_color, focus=True, bind_return_key=True)]) + else: + layout.append([PopupButton(custom_text[0], button_color=button_color, focus=True, bind_return_key=True), + PopupButton(custom_text[1], button_color=button_color),Stretch()]) + elif button_type is POPUP_BUTTONS_YES_NO: + layout.append([PopupButton('Yes', button_color=button_color, focus=True, bind_return_key=True, size=(60, 20)), PopupButton('No', button_color=button_color, size=(60, 20))]) + elif button_type is POPUP_BUTTONS_CANCELLED: + layout.append([PopupButton('Cancelled', button_color=button_color, focus=True, bind_return_key=True), Stretch()]) + elif button_type is POPUP_BUTTONS_ERROR: + layout.append([PopupButton('Error', size=(60, 20), button_color=button_color, focus=True, bind_return_key=True), Stretch()]) + elif button_type is POPUP_BUTTONS_OK_CANCEL: + layout.append([PopupButton('OK', size=(60, 20), button_color=button_color, focus=True, bind_return_key=True), + PopupButton('Cancel', size=(60, 20), button_color=button_color), Stretch()]) + elif button_type is POPUP_BUTTONS_NO_BUTTONS: + pass + else: + layout.append([PopupButton('OK', size=(60, 20), button_color=button_color, focus=True, bind_return_key=True), Stretch()]) + + window.Layout(layout) + if non_blocking: + button, values = window.Read(timeout=0) + Window.active_popups[window] = title + else: + button, values = window.Read() + window.close() + + return button + + +# ============================== MsgBox============# +# Lazy function. Same as calling Popup with parms # +# This function WILL Disappear perhaps today # +# ==================================================# +# MsgBox is the legacy call and should not be used any longer +def MsgBox(*args): + raise DeprecationWarning('MsgBox is no longer supported... change your call to Popup') + + +# --------------------------- PopupNoButtons --------------------------- +def PopupNoButtons(*args, title=None, button_color=None, background_color=None, text_color=None, auto_close=False, + auto_close_duration=None, non_blocking=False, icon=DEFAULT_WINDOW_ICON, line_width=None, font=None, + no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None), image=None): + """ + Show a Popup but without any buttons + :param *args: Variable number of your arguments. Load up the call with stuff to see! + :type *args: (Any) + :param button_color: button color (foreground, background) + :type button_color: Tuple[str, str] + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param auto_close: if True window will close itself + :type auto_close: (bool) + :param auto_close_duration: Older versions only accept int. Time in seconds until window will close + :type auto_close_duration: Union[int, float] + :param non_blocking: if True the call will immediately return rather than waiting on user input + :type non_blocking: (bool) + :param icon: filename or base64 string to be used for the window's icon + :type icon: Union[bytes, str] + :param line_width: Width of lines in characters + :type line_width: (int) + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + :param grab_anywhere: If True, than can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param image: Image to include at the top of the popup window + :type image: (str) or (bytes) + :param location: Location of upper left corner of the window + :type location: Tuple[int, int] + """ + Popup(*args, title=title, button_color=button_color, background_color=background_color, text_color=text_color, + button_type=POPUP_BUTTONS_NO_BUTTONS, + auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon, + line_width=line_width, + font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location, image=image) + + +# --------------------------- PopupNonBlocking --------------------------- +def PopupNonBlocking(*args, title=None, button_type=POPUP_BUTTONS_OK, button_color=None, background_color=None, text_color=None, + auto_close=False, auto_close_duration=None, non_blocking=True, icon=DEFAULT_WINDOW_ICON, + line_width=None, font=None, no_titlebar=False, grab_anywhere=False, keep_on_top=False, + location=(None, None), image=None): + """ + Show Popup box and immediately return (does not block) + :param *args: Variable number of your arguments. Load up the call with stuff to see! + :type *args: (Any) + :param title: Title to display in the window. + :type title: (str) + :param button_type: + :param button_color: button color (foreground, background) + :type button_color: Tuple[str, str] + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param auto_close: if True window will close itself + :type auto_close: (bool) + :param auto_close_duration: Older versions only accept int. Time in seconds until window will close + :type auto_close_duration: Union[int, float] + :param non_blocking: if True the call will immediately return rather than waiting on user input + :type non_blocking: (bool) + :param icon: filename or base64 string to be used for the window's icon + :type icon: Union[bytes, str] + :param line_width: Width of lines in characters + :type line_width: (int) + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + :param grab_anywhere: If True, than can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param image: Image to include at the top of the popup window + :type image: (str) or (bytes) + :param location: Location of upper left corner of the window + :type location: Tuple[int, int] + """ + Popup(*args, title=title, button_color=button_color, background_color=background_color, text_color=text_color, + button_type=button_type, + auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon, + line_width=line_width, + font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location, image=image) + + +PopupNoWait = PopupNonBlocking + + +# --------------------------- PopupQuick - a NonBlocking, Self-closing Popup --------------------------- +def PopupQuick(*args, title=None, button_type=POPUP_BUTTONS_OK, button_color=None, background_color=None, text_color=None, + auto_close=True, auto_close_duration=2, non_blocking=True, icon=DEFAULT_WINDOW_ICON, line_width=None, + font=None, no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None), image=None): + """ + Show Popup box that doesn't block and closes itself + :param *args: Variable number of your arguments. Load up the call with stuff to see! + :type *args: (Any) + :param title: Title to display in the window. + :type title: (str) + :param button_type: Determines which pre-defined buttons will be shown (Default value = POPUP_BUTTONS_OK). + :type button_type: (int) + :param button_color: button color (foreground, background) + :type button_color: Tuple[str, str] + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param auto_close: if True window will close itself + :type auto_close: (bool) + :param auto_close_duration: Older versions only accept int. Time in seconds until window will close + :type auto_close_duration: Union[int, float] + :param non_blocking: if True the call will immediately return rather than waiting on user input + :type non_blocking: (bool) + :param icon: filename or base64 string to be used for the window's icon + :type icon: Union[bytes, str] + :param line_width: Width of lines in characters + :type line_width: (int) + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + :param grab_anywhere: If True, than can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param location: Location of upper left corner of the window + :type location: Tuple[int, int] + :param image: Image to include at the top of the popup window + :type image: (str) or (bytes) + """ + Popup(*args, title=title, button_color=button_color, background_color=background_color, text_color=text_color, + button_type=button_type, + auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon, + line_width=line_width, + font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location, image=image) + + +# --------------------------- PopupQuick - a NonBlocking, Self-closing Popup with no titlebar and no buttons --------------------------- +def PopupQuickMessage(*args, title=None, button_type=POPUP_BUTTONS_NO_BUTTONS, button_color=None, background_color=None, + text_color=None, + auto_close=True, auto_close_duration=3, non_blocking=True, icon=DEFAULT_WINDOW_ICON, + line_width=None, + font=None, no_titlebar=True, grab_anywhere=False, keep_on_top=False, location=(None, None), image=None): + """ + Show Popup box that doesn't block and closes itself + :param *args: Variable number of your arguments. Load up the call with stuff to see! + :type *args: (Any) + :param title: Title to display in the window. + :type title: (str) + :param button_type: Determines which pre-defined buttons will be shown (Default value = POPUP_BUTTONS_OK). + :type button_type: (int) + :param button_color: button color (foreground, background) + :type button_color: Tuple[str, str] + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param auto_close: if True window will close itself + :type auto_close: (bool) + :param auto_close_duration: Older versions only accept int. Time in seconds until window will close + :type auto_close_duration: Union[int, float] + :param non_blocking: if True the call will immediately return rather than waiting on user input + :type non_blocking: (bool) + :param icon: filename or base64 string to be used for the window's icon + :type icon: Union[bytes, str] + :param line_width: Width of lines in characters + :type line_width: (int) + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + :param grab_anywhere: If True, than can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param location: Location of upper left corner of the window + :type location: Tuple[int, int] + :param image: Image to include at the top of the popup window + :type image: (str) or (bytes) + """ + Popup(*args, title=title, button_color=button_color, background_color=background_color, text_color=text_color, + button_type=button_type, + auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon, + line_width=line_width, + font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location, image=image) + + +# --------------------------- PopupNoTitlebar --------------------------- +def PopupNoTitlebar(*args, title=None, button_type=POPUP_BUTTONS_OK, button_color=None, background_color=None, text_color=None, + auto_close=False, auto_close_duration=None, non_blocking=False, icon=DEFAULT_WINDOW_ICON, + line_width=None, font=None, grab_anywhere=True, keep_on_top=False, location=(None, None), image=None): + """ + Display a Popup without a titlebar. Enables grab anywhere so you can move it + :param *args: Variable number of your arguments. Load up the call with stuff to see! + :type *args: (Any) + :param title: Title to display in the window. + :type title: (str) + :param button_type: Determines which pre-defined buttons will be shown (Default value = POPUP_BUTTONS_OK). + :type button_type: (int) + :param button_color: button color (foreground, background) + :type button_color: Tuple[str, str] + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param auto_close: if True window will close itself + :type auto_close: (bool) + :param auto_close_duration: Older versions only accept int. Time in seconds until window will close + :type auto_close_duration: Union[int, float] + :param non_blocking: if True the call will immediately return rather than waiting on user input + :type non_blocking: (bool) + :param icon: filename or base64 string to be used for the window's icon + :type icon: Union[bytes, str] + :param line_width: Width of lines in characters + :type line_width: (int) + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param grab_anywhere: If True, than can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param location: Location of upper left corner of the window + :type location: Tuple[int, int] + :param image: Image to include at the top of the popup window + :type image: (str) or (bytes) + """ + Popup(*args, title=title, button_color=button_color, background_color=background_color, text_color=text_color, + button_type=button_type, + auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon, + line_width=line_width, + font=font, no_titlebar=True, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location, image=image) + + +PopupNoFrame = PopupNoTitlebar +PopupNoBorder = PopupNoTitlebar +PopupAnnoying = PopupNoTitlebar + + +# --------------------------- PopupAutoClose --------------------------- +def PopupAutoClose(*args, title=None, button_type=POPUP_BUTTONS_OK, button_color=None, background_color=None, text_color=None, + auto_close=True, auto_close_duration=DEFAULT_AUTOCLOSE_TIME, non_blocking=False, icon=DEFAULT_WINDOW_ICON, + line_width=None, font=None, no_titlebar=False, grab_anywhere=False, keep_on_top=False, + location=(None, None), image=None): + """ + Popup that closes itself after some time period + :param *args: Variable number of your arguments. Load up the call with stuff to see! + :type *args: (Any) + :param title: Title to display in the window. + :type title: (str) + :param button_type: Determines which pre-defined buttons will be shown (Default value = POPUP_BUTTONS_OK). + :type button_type: (int) + :param button_color: button color (foreground, background) + :type button_color: Tuple[str, str] + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param auto_close: if True window will close itself + :type auto_close: (bool) + :param auto_close_duration: Older versions only accept int. Time in seconds until window will close + :type auto_close_duration: Union[int, float] + :param non_blocking: if True the call will immediately return rather than waiting on user input + :type non_blocking: (bool) + :param icon: filename or base64 string to be used for the window's icon + :type icon: Union[bytes, str] + :param line_width: Width of lines in characters + :type line_width: (int) + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + :param grab_anywhere: If True, than can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param location: Location of upper left corner of the window + :type location: Tuple[int, int] + :param image: Image to include at the top of the popup window + :type image: (str) or (bytes) + """ + Popup(*args, title=title, button_color=button_color, background_color=background_color, text_color=text_color, + button_type=button_type, + auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon, + line_width=line_width, + font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location, image=image) + + +PopupTimed = PopupAutoClose + + +# --------------------------- PopupError --------------------------- +def PopupError(*args, title=None, button_color=(None, None), background_color=None, text_color=None, auto_close=False, + auto_close_duration=None, non_blocking=False, icon=DEFAULT_WINDOW_ICON, line_width=None, font=None, + no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None), image=None): + """ + Popup with colored button and 'Error' as button text + :param *args: Variable number of your arguments. Load up the call with stuff to see! + :type *args: (Any) + :param title: Title to display in the window. + :type title: (str) + :param button_color: button color (foreground, background) + :type button_color: Tuple[str, str] + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param auto_close: if True window will close itself + :type auto_close: (bool) + :param auto_close_duration: Older versions only accept int. Time in seconds until window will close + :type auto_close_duration: Union[int, float] + :param non_blocking: if True the call will immediately return rather than waiting on user input + :type non_blocking: (bool) + :param icon: filename or base64 string to be used for the window's icon + :type icon: Union[bytes, str] + :param line_width: Width of lines in characters + :type line_width: (int) + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + :param grab_anywhere: If True, than can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param location: Location of upper left corner of the window + :type location: Tuple[int, int] + :param image: Image to include at the top of the popup window + :type image: (str) or (bytes) + """ + tbutton_color = DEFAULT_ERROR_BUTTON_COLOR if button_color == (None, None) else button_color + Popup(*args, title=title, button_type=POPUP_BUTTONS_ERROR, background_color=background_color, text_color=text_color, + non_blocking=non_blocking, icon=icon, line_width=line_width, button_color=tbutton_color, auto_close=auto_close, + auto_close_duration=auto_close_duration, font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, + keep_on_top=keep_on_top, location=location, image=image) + + +# --------------------------- PopupCancel --------------------------- +def PopupCancel(*args, title=None, button_color=None, background_color=None, text_color=None, auto_close=False, + auto_close_duration=None, non_blocking=False, icon=DEFAULT_WINDOW_ICON, line_width=None, font=None, + no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None), image=None): + """ + Display Popup with "cancelled" button text + :param *args: Variable number of your arguments. Load up the call with stuff to see! + :type *args: (Any) + :param title: Title to display in the window. + :type title: (str) + :param button_color: button color (foreground, background) + :type button_color: Tuple[str, str] + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param auto_close: if True window will close itself + :type auto_close: (bool) + :param auto_close_duration: Older versions only accept int. Time in seconds until window will close + :type auto_close_duration: Union[int, float] + :param non_blocking: if True the call will immediately return rather than waiting on user input + :type non_blocking: (bool) + :param icon: filename or base64 string to be used for the window's icon + :type icon: Union[bytes, str] + :param line_width: Width of lines in characters + :type line_width: (int) + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + :param grab_anywhere: If True, than can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param location: Location of upper left corner of the window + :type location: Tuple[int, int] + :param image: Image to include at the top of the popup window + :type image: (str) or (bytes) + """ + Popup(*args, title=title, button_type=POPUP_BUTTONS_CANCELLED, background_color=background_color, text_color=text_color, + non_blocking=non_blocking, icon=icon, line_width=line_width, button_color=button_color, auto_close=auto_close, + auto_close_duration=auto_close_duration, font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, + keep_on_top=keep_on_top, location=location, image=image) + + +# --------------------------- PopupOK --------------------------- +def PopupOK(*args, title=None, button_color=None, background_color=None, text_color=None, auto_close=False, + auto_close_duration=None, non_blocking=False, icon=DEFAULT_WINDOW_ICON, line_width=None, font=None, + no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)): + """ + Display Popup with OK button only + :param *args: Variable number of your arguments. Load up the call with stuff to see! + :type *args: (Any) + :param button_color: button color (foreground, background) + :type button_color: Tuple[str, str] + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param auto_close: if True window will close itself + :type auto_close: (bool) + :param auto_close_duration: Older versions only accept int. Time in seconds until window will close + :type auto_close_duration: Union[int, float] + :param non_blocking: if True the call will immediately return rather than waiting on user input + :type non_blocking: (bool) + :param icon: filename or base64 string to be used for the window's icon + :type icon: Union[bytes, str] + :param line_width: Width of lines in characters + :type line_width: (int) + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + :param grab_anywhere: If True, than can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param location: Location of upper left corner of the window + :type location: Tuple[int, int] + :param image: Image to include at the top of the popup window + :type image: (str) or (bytes) + """ + Popup(*args, title=title, button_type=POPUP_BUTTONS_OK, background_color=background_color, text_color=text_color, + non_blocking=non_blocking, icon=icon, line_width=line_width, button_color=button_color, auto_close=auto_close, + auto_close_duration=auto_close_duration, font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, + keep_on_top=keep_on_top, location=location, image=image) + + +# --------------------------- PopupOKCancel --------------------------- +def PopupOKCancel(*args, title=None, button_color=None, background_color=None, text_color=None, auto_close=False, + auto_close_duration=None, non_blocking=False, icon=DEFAULT_WINDOW_ICON, line_width=None, font=None, + no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None), image=None): + """ + Display popup with OK and Cancel buttons + :param *args: Variable number of your arguments. Load up the call with stuff to see! + :type *args: (Any) + :param button_color: button color (foreground, background) + :type button_color: Tuple[str, str] + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param auto_close: if True window will close itself + :type auto_close: (bool) + :param auto_close_duration: Older versions only accept int. Time in seconds until window will close + :type auto_close_duration: Union[int, float] + :param non_blocking: if True the call will immediately return rather than waiting on user input + :type non_blocking: (bool) + :param icon: filename or base64 string to be used for the window's icon + :type icon: Union[bytes, str] + :param line_width: Width of lines in characters + :type line_width: (int) + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + :param grab_anywhere: If True, than can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param location: Location of upper left corner of the window + :type location: Tuple[int, int] + :param image: Image to include at the top of the popup window + :type image: (str) or (bytes) + :return: OK, Cancel or None + :rtype: Union[str, None] + """ + return Popup(*args, title=title, button_type=POPUP_BUTTONS_OK_CANCEL, background_color=background_color, text_color=text_color, + non_blocking=non_blocking, icon=icon, line_width=line_width, button_color=button_color, + auto_close=auto_close, auto_close_duration=auto_close_duration, font=font, no_titlebar=no_titlebar, + grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location, image=image) + + +# --------------------------- PopupYesNo --------------------------- +def PopupYesNo(*args, title=None, button_color=None, background_color=None, text_color=None, auto_close=False, + auto_close_duration=None, non_blocking=False, icon=DEFAULT_WINDOW_ICON, line_width=None, font=None, + no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None), image=None): + """ + Display Popup with Yes and No buttons + + :param *args: Variable number of your arguments. Load up the call with stuff to see! + :type *args: (Any) + :param button_color: button color (foreground, background) + :type button_color: Tuple[str, str] + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param auto_close: if True window will close itself + :type auto_close: (bool) + :param auto_close_duration: Older versions only accept int. Time in seconds until window will close + :type auto_close_duration: Union[int, float] + :param non_blocking: if True the call will immediately return rather than waiting on user input + :type non_blocking: (bool) + :param icon: filename or base64 string to be used for the window's icon + :type icon: Union[bytes, str] + :param line_width: Width of lines in characters + :type line_width: (int) + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + :param grab_anywhere: If True, than can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param location: Location of upper left corner of the window + :type location: Tuple[int, int] + :param image: Image to include at the top of the popup window + :type image: (str) or (bytes) + :return: Yes, No or None + :rtype: Union[str, None] + """ + return Popup(*args, title=title, button_type=POPUP_BUTTONS_YES_NO, background_color=background_color, text_color=text_color, + non_blocking=non_blocking, icon=icon, line_width=line_width, button_color=button_color, + auto_close=auto_close, auto_close_duration=auto_close_duration, font=font, no_titlebar=no_titlebar, + grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location, image=image) + + +############################################################################## +# The PopupGet_____ functions - Will return user input # +############################################################################## + +# --------------------------- PopupGetFolder --------------------------- + + +def PopupGetFolder(message, title=None, default_path='', no_window=False, size=(None, None), button_color=None, + background_color=None, text_color=None, icon=DEFAULT_WINDOW_ICON, font=None, no_titlebar=False, + grab_anywhere=False, keep_on_top=False, location=(None, None), initial_folder=None, image=None): + """ + Display popup with text entry field and browse button. Browse for folder + :param message: message displayed to user + :type message: (str) + :param title: Window title + :type title: (str) + :param default_path: path to display to user as starting point (filled into the input field) + :type default_path: (str) + :param no_window: if True, no PySimpleGUI window will be shown. Instead just the tkinter dialog is shown + :type no_window: (bool) + :param size: (width, height) of the InputText Element + :type size: Tuple[int, int] + :param button_color: button color (foreground, background) + :type button_color: Tuple[str, str] + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param icon: filename or base64 string to be used for the window's icon + :type icon: Union[bytes, str] + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + :param grab_anywhere: If True, than can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param location: Location of upper left corner of the window + :type location: Tuple[int, int] + :param initial_folder: location in filesystem to begin browsing + :type initial_folder: (str) + :param image: Image to include at the top of the popup window + :type image: (str) or (bytes) + :return: Contents of text field. None if closed using X or cancelled + :rtype: Union[str, None] + """ + + + if no_window: + if Window.QTApplication is None: + Window.QTApplication = QApplication(sys.argv) + + folder_name = QFileDialog.getExistingDirectory(dir=initial_folder) + return folder_name + + if image is not None: + if isinstance(image, str): + layout = [[Image(filename=image)]] + else: + layout = [[Image(data_base64=image)]] + else: + layout = [[]] + layout += [[Text(message, auto_size_text=True, text_color=text_color, background_color=background_color)], + [InputText(default_text=default_path, size=size, key='_INPUT_'), FolderBrowse(initial_folder=initial_folder)], + [Button('Ok', size=(60, 20), bind_return_key=True), Button('Cancel', size=(60, 20))]] + + _title = title if title is not None else message + window = Window(title=_title, layout=layout, icon=icon, auto_size_text=True, button_color=button_color, + background_color=background_color, + font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, + location=location) + + button, values = window.Read() + window.close() + if button != 'Ok': + return None + else: + path = values['_INPUT_'] + return path + + +# --------------------------- PopupGetFile --------------------------- + +def PopupGetFile(message, title=None, default_path='', default_extension='', save_as=False, file_types=(("ALL Files", "*"),), + no_window=False, size=(None, None), button_color=None, background_color=None, text_color=None, + icon=DEFAULT_WINDOW_ICON, font=None, no_titlebar=False, grab_anywhere=False, keep_on_top=False, + location=(None, None), initial_folder=None, image=None): + """ + Display popup with text entry field and browse button. Browse for file + + :param message: message displayed to user + :type message: (str) + :param title: Window title + :type title: (str) + :param default_path: path to display to user as starting point (filled into the input field) + :type default_path: (str) + :param default_extension: If no extension entered by user, add this to filename (only used in saveas dialogs) + :type default_extension: (str) + :param save_as: if True, the "save as" dialog is shown which will verify before overwriting + :type save_as: (bool) + :param multiple_files: if True, then allows multiple files to be selected that are returned with ';' between each filename + :type multiple_files: (bool) + :param file_types: List of extensions to show using wildcards. All files (the default) = (("ALL Files", "*.*"),) + :type file_types: Tuple[Tuple[str,str]] + :param no_window: if True, no PySimpleGUI window will be shown. Instead just the tkinter dialog is shown + :type no_window: (bool) + :param size: (width, height) of the InputText Element + :type size: Tuple[int, int] + :param button_color: Color of the button (text, background) + :type button_color: Tuple[str, str] + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param icon: filename or base64 string to be used for the window's icon + :type icon: Union[bytes, str] + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + :param grab_anywhere: If True, than can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param location: Location of upper left corner of the window + :type location: Tuple[int, int] + :param initial_folder: location in filesystem to begin browsing + :type initial_folder: (str) + :param image: Image to include at the top of the popup window + :type image: (str) or (bytes) + :return: string representing the path chosen, None if cancelled or window closed with X + :rtype: Union[str, None] + """ + + if no_window: + if Window.QTApplication is None: + Window.QTApplication = QApplication(sys.argv) + + if save_as: + qt_types = convert_tkinter_filetypes_to_qt(file_types) + filename = QFileDialog.getSaveFileName(dir=initial_folder, filter=qt_types) + else: + qt_types = convert_tkinter_filetypes_to_qt(file_types) + filename = QFileDialog.getOpenFileName(dir=initial_folder, filter=qt_types) + return filename[0] + + + browse_button = SaveAs(file_types=file_types, initial_folder=initial_folder) if save_as else FileBrowse( + file_types=file_types, initial_folder=initial_folder) + + + if image is not None: + if isinstance(image, str): + layout = [[Image(filename=image)]] + else: + layout = [[Image(data_base64=image)]] + else: + layout = [[]] + + layout += [[Text(message, auto_size_text=True, text_color=text_color, background_color=background_color)], + [InputText(default_text=default_path, size=(30,1), key='_INPUT_'), browse_button], + [Button('Ok', size=(60, 20), bind_return_key=True), Button('Cancel', size=(60, 20))]] + + _title = title if title is not None else message + + window = Window(title=_title, layout=layout, icon=icon, auto_size_text=True, button_color=button_color, font=font, + background_color=background_color, + no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) + + button, values = window.Read() + window.close() + if button != 'Ok': + return None + else: + path = values['_INPUT_'] + return path + + +# --------------------------- PopupGetText --------------------------- + +def PopupGetText(message, title=None, default_text='', password_char='', size=(None, None), button_color=None, + background_color=None, text_color=None, icon=DEFAULT_WINDOW_ICON, font=None, no_titlebar=False, + grab_anywhere=False, keep_on_top=False, location=(None, None), image=None): + """ + Display Popup with text entry field + :param message: message displayed to user + :type message: (str) + :param title: Window title + :type title: (str) + :param default_text: default value to put into input area + :type default_text: (str) + :param password_char: character to be shown instead of actually typed characters + :type password_char: (str) + :param size: (width, height) of the InputText Element + :type size: Tuple[int, int] + :param button_color: Color of the button (text, background) + :type button_color: Tuple[str, str] + :param background_color: color of background + :type background_color: (str) + :param text_color: color of the text + :type text_color: (str) + :param icon: filename or base64 string to be used for the window's icon + :type icon: Union[bytes, str] + :param font: specifies the font family, size, etc + :type font: Union[str, Tuple[str, int]] + :param no_titlebar: If True no titlebar will be shown + :type no_titlebar: (bool) + :param grab_anywhere: If True, than can grab anywhere to move the window (Default = False) + :type grab_anywhere: (bool) + :param keep_on_top: If True the window will remain above all current windows + :type keep_on_top: (bool) + :param location: (x,y) Location on screen to display the upper left corner of window + :type location: Tuple[int, int] + :param image: Image to include at the top of the popup window + :type image: (str) or (bytes) + :return: Text entered or None if window was closed + :rtype: Union[str, None] + """ + + if image is not None: + if isinstance(image, str): + layout = [[Image(filename=image)]] + else: + layout = [[Image(data_base64=image)]] + else: + layout = [[]] + + layout += [[Text(message, auto_size_text=True, text_color=text_color, background_color=background_color, font=font)], + [InputText(default_text=default_text, size=size, password_char=password_char, key='_INPUT_')], + [Button('Ok', size=(60, 20), bind_return_key=True), Button('Cancel', size=(60, 20))]] + + _title = title if title is not None else message + + window = Window(title=_title, layout=layout, icon=icon, auto_size_text=True, button_color=button_color, no_titlebar=no_titlebar, + background_color=background_color, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, + location=location) + + button, values = window.Read() + window.close() + + if button != 'Ok': + return None + else: + return values['_INPUT_'] + + +# --------------------------------------- a few icons in base64 --------------------------------------- + + +ICON_BASE64_BLOB_PALM = b'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/GMzLdsAADpCaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzE0NSA3OS4xNjIzMTksIDIwMTgvMDIvMTUtMjA6Mjk6NDMgICAgICAgICI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgICAgICAgICAgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iCiAgICAgICAgICAgIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAgICAgICAgICAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgICAgICAgICAgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8eG1wOkNyZWF0b3JUb29sPkFkb2JlIFBob3Rvc2hvcCBFbGVtZW50cyAxNy4wIChXaW5kb3dzKTwveG1wOkNyZWF0b3JUb29sPgogICAgICAgICA8eG1wOkNyZWF0ZURhdGU+MjAyMC0wNy0wMlQxNjo1ODowNy0wNDowMDwveG1wOkNyZWF0ZURhdGU+CiAgICAgICAgIDx4bXA6TWV0YWRhdGFEYXRlPjIwMjAtMDctMDJUMTY6NTg6MDctMDQ6MDA8L3htcDpNZXRhZGF0YURhdGU+CiAgICAgICAgIDx4bXA6TW9kaWZ5RGF0ZT4yMDIwLTA3LTAyVDE2OjU4OjA3LTA0OjAwPC94bXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhtcE1NOkluc3RhbmNlSUQ+eG1wLmlpZDo4NWFmYzM1My1hMzMyLWFlNGQtOGE0ZC1lYTExOTk1MDU5M2E8L3htcE1NOkluc3RhbmNlSUQ+CiAgICAgICAgIDx4bXBNTTpEb2N1bWVudElEPmFkb2JlOmRvY2lkOnBob3Rvc2hvcDpiMWM2N2U0Zi1iY2E2LTExZWEtYTEwYi1iMTlmYTMxNTc1YWQ8L3htcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ+eG1wLmRpZDphNzVkMDNmMS1lNjE3LWM0NDktYjYxNy0zZjc4YWFjMDBjNTQ8L3htcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOkhpc3Rvcnk+CiAgICAgICAgICAgIDxyZGY6U2VxPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5jcmVhdGVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6YTc1ZDAzZjEtZTYxNy1jNDQ5LWI2MTctM2Y3OGFhYzAwYzU0PC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDIwLTA3LTAyVDE2OjU4OjA3LTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgRWxlbWVudHMgMTcuMCAoV2luZG93cyk8L3N0RXZ0OnNvZnR3YXJlQWdlbnQ+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOjg1YWZjMzUzLWEzMzItYWU0ZC04YTRkLWVhMTE5OTUwNTkzYTwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAyMC0wNy0wMlQxNjo1ODowNy0wNDowMDwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIEVsZW1lbnRzIDE3LjAgKFdpbmRvd3MpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICAgICA8c3RFdnQ6Y2hhbmdlZD4vPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgPC9yZGY6U2VxPgogICAgICAgICA8L3htcE1NOkhpc3Rvcnk+CiAgICAgICAgIDxkYzpmb3JtYXQ+aW1hZ2UvcG5nPC9kYzpmb3JtYXQ+CiAgICAgICAgIDxwaG90b3Nob3A6Q29sb3JNb2RlPjM8L3Bob3Rvc2hvcDpDb2xvck1vZGU+CiAgICAgICAgIDxwaG90b3Nob3A6SUNDUHJvZmlsZT5zUkdCIElFQzYxOTY2LTIuMTwvcGhvdG9zaG9wOklDQ1Byb2ZpbGU+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjcyMDAwMC8xMDAwMDwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+NzIwMDAwLzEwMDAwPC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpSZXNvbHV0aW9uVW5pdD4yPC90aWZmOlJlc29sdXRpb25Vbml0PgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6UGl4ZWxYRGltZW5zaW9uPjc4PC9leGlmOlBpeGVsWERpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjcxPC9leGlmOlBpeGVsWURpbWVuc2lvbj4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgCjw/eHBhY2tldCBlbmQ9InciPz62g3pFAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAABdqSURBVHja7Jz3c1xXlt+/5977cucANCKRmINAShoqzYxGOzsu79Ta/g/8L/kvsctll721nl1b3t1ZaShRFClRgkiQIAgih250eOkG/9ANEgRBECABSa7Sq+p6XQQL7+LzTj73XDLG4Jfr6Jf4uSxk+tp1Osr/v3Xz85/0jdNPJXF7QNFL7vtdZr/7jw3yRwe3CxgBYLvuvHff+U57AJreRwHQvc/Od7Pr/qNA/FHA7QOLARCcGcvi2rGFcYUwnmtpx3OUF7jacS3NLaE5Z4YBQCKZjlOWhDFL2xEP45RFiaQokRSnkkVKU6INyd0wTxLgiYPrQdsBZtlC24Gr/Jwvc/lAFfK+rOZ9Wcr6shy4qpBxVTbwlO9Yxu6BEzCQiWRIUpaECQvbIe+0It5sRXy9GfKNRlusNjpic7stGs1QtDoJ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' + +ICON_BASE64_BLOB_PAT = b'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/GMzLdsAADpCaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzE0NSA3OS4xNjIzMTksIDIwMTgvMDIvMTUtMjA6Mjk6NDMgICAgICAgICI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgICAgICAgICAgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iCiAgICAgICAgICAgIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAgICAgICAgICAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgICAgICAgICAgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8eG1wOkNyZWF0b3JUb29sPkFkb2JlIFBob3Rvc2hvcCBFbGVtZW50cyAxNy4wIChXaW5kb3dzKTwveG1wOkNyZWF0b3JUb29sPgogICAgICAgICA8eG1wOkNyZWF0ZURhdGU+MjAyMC0wNy0wMlQxNjo1OTowNi0wNDowMDwveG1wOkNyZWF0ZURhdGU+CiAgICAgICAgIDx4bXA6TWV0YWRhdGFEYXRlPjIwMjAtMDctMDJUMTY6NTk6MDYtMDQ6MDA8L3htcDpNZXRhZGF0YURhdGU+CiAgICAgICAgIDx4bXA6TW9kaWZ5RGF0ZT4yMDIwLTA3LTAyVDE2OjU5OjA2LTA0OjAwPC94bXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhtcE1NOkluc3RhbmNlSUQ+eG1wLmlpZDpiMWNmNDU1YS04Yjk4LTFmNDYtYmJlNi1iNmY1ZGMxMGYwYWE8L3htcE1NOkluc3RhbmNlSUQ+CiAgICAgICAgIDx4bXBNTTpEb2N1bWVudElEPmFkb2JlOmRvY2lkOnBob3Rvc2hvcDpkM2FmN2UyNi1iY2E2LTExZWEtYTEwYi1iMTlmYTMxNTc1YWQ8L3htcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ+eG1wLmRpZDo0YjE4ZTE1Mi0yNWMzLWY3NDAtOWU4Yi0zYmRjNjFjMjI5Njk8L3htcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOkhpc3Rvcnk+CiAgICAgICAgICAgIDxyZGY6U2VxPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5jcmVhdGVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6NGIxOGUxNTItMjVjMy1mNzQwLTllOGItM2JkYzYxYzIyOTY5PC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDIwLTA3LTAyVDE2OjU5OjA2LTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgRWxlbWVudHMgMTcuMCAoV2luZG93cyk8L3N0RXZ0OnNvZnR3YXJlQWdlbnQ+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOmIxY2Y0NTVhLThiOTgtMWY0Ni1iYmU2LWI2ZjVkYzEwZjBhYTwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAyMC0wNy0wMlQxNjo1OTowNi0wNDowMDwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIEVsZW1lbnRzIDE3LjAgKFdpbmRvd3MpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICAgICA8c3RFdnQ6Y2hhbmdlZD4vPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgPC9yZGY6U2VxPgogICAgICAgICA8L3htcE1NOkhpc3Rvcnk+CiAgICAgICAgIDxkYzpmb3JtYXQ+aW1hZ2UvcG5nPC9kYzpmb3JtYXQ+CiAgICAgICAgIDxwaG90b3Nob3A6Q29sb3JNb2RlPjM8L3Bob3Rvc2hvcDpDb2xvck1vZGU+CiAgICAgICAgIDxwaG90b3Nob3A6SUNDUHJvZmlsZT5zUkdCIElFQzYxOTY2LTIuMTwvcGhvdG9zaG9wOklDQ1Byb2ZpbGU+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjcyMDAwMC8xMDAwMDwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+NzIwMDAwLzEwMDAwPC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpSZXNvbHV0aW9uVW5pdD4yPC90aWZmOlJlc29sdXRpb25Vbml0PgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6UGl4ZWxYRGltZW5zaW9uPjgxPC9leGlmOlBpeGVsWERpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjc1PC9leGlmOlBpeGVsWURpbWVuc2lvbj4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgCjw/eHBhY2tldCBlbmQ9InciPz6vCsFxAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAABGmSURBVHja7Jx5cJzlfce/z/Meex+SdqWVVpdZWbIlY1lWjIhx42ZIYopT7jFgDCZOAy2QozChSWaShjQpAylkmhCaGHAHN5hjCuWoaaEl0A50SsHGMpaNbQlfyJZk3Vrtvsdz9I93dfpaW7vGJnpmdnTs7rvv+3l/9+/3LJFSYnbNbNFZBLMQZyHOQpxdsxBnIc5CnIU4u46z1PP55Fdf0eiPhXlzUUA0+D2yRFWEX0rCLIbRlEF6+5NKW++w0rbxxdbefJ4HOV8zlrvXNly6amnyPwu8Al5dQFMASiQkCIQAmABMTjGcIjjUp7a2HnQ9+qNf71o/CzGz/uKGhsbLGlNPLptvNuqKhEIlKJl4XgKQEhCSwOZAyqToH6U41Kft3nHItWHHQdf6jf+ybfAPWp3nRO2VF1ZajUG3cCSBnOiV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' + +ICON_BASE64_BLOB_THINK = b'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/GMzLdsAADpCaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzE0NSA3OS4xNjIzMTksIDIwMTgvMDIvMTUtMjA6Mjk6NDMgICAgICAgICI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgICAgICAgICAgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iCiAgICAgICAgICAgIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAgICAgICAgICAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgICAgICAgICAgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8eG1wOkNyZWF0b3JUb29sPkFkb2JlIFBob3Rvc2hvcCBFbGVtZW50cyAxNy4wIChXaW5kb3dzKTwveG1wOkNyZWF0b3JUb29sPgogICAgICAgICA8eG1wOkNyZWF0ZURhdGU+MjAyMC0wNy0wMlQxNzowNjozMi0wNDowMDwveG1wOkNyZWF0ZURhdGU+CiAgICAgICAgIDx4bXA6TWV0YWRhdGFEYXRlPjIwMjAtMDctMDJUMTc6MDY6MzItMDQ6MDA8L3htcDpNZXRhZGF0YURhdGU+CiAgICAgICAgIDx4bXA6TW9kaWZ5RGF0ZT4yMDIwLTA3LTAyVDE3OjA2OjMyLTA0OjAwPC94bXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhtcE1NOkluc3RhbmNlSUQ+eG1wLmlpZDpjZGY4YTM3NS05ODVkLTdhNGQtOTU5OS1iOGJmYjZiZGMwYmI8L3htcE1NOkluc3RhbmNlSUQ+CiAgICAgICAgIDx4bXBNTTpEb2N1bWVudElEPmFkb2JlOmRvY2lkOnBob3Rvc2hvcDpkZWE3YjA5Yi1iY2E3LTExZWEtYTEwYi1iMTlmYTMxNTc1YWQ8L3htcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ+eG1wLmRpZDo5YjY3OTMyNi04MjExLTZjNDgtYjk0NS00NzY2MzI1NDU3M2Y8L3htcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOkhpc3Rvcnk+CiAgICAgICAgICAgIDxyZGY6U2VxPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5jcmVhdGVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6OWI2NzkzMjYtODIxMS02YzQ4LWI5NDUtNDc2NjMyNTQ1NzNmPC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDIwLTA3LTAyVDE3OjA2OjMyLTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgRWxlbWVudHMgMTcuMCAoV2luZG93cyk8L3N0RXZ0OnNvZnR3YXJlQWdlbnQ+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOmNkZjhhMzc1LTk4NWQtN2E0ZC05NTk5LWI4YmZiNmJkYzBiYjwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAyMC0wNy0wMlQxNzowNjozMi0wNDowMDwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIEVsZW1lbnRzIDE3LjAgKFdpbmRvd3MpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICAgICA8c3RFdnQ6Y2hhbmdlZD4vPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgPC9yZGY6U2VxPgogICAgICAgICA8L3htcE1NOkhpc3Rvcnk+CiAgICAgICAgIDxkYzpmb3JtYXQ+aW1hZ2UvcG5nPC9kYzpmb3JtYXQ+CiAgICAgICAgIDxwaG90b3Nob3A6Q29sb3JNb2RlPjM8L3Bob3Rvc2hvcDpDb2xvck1vZGU+CiAgICAgICAgIDxwaG90b3Nob3A6SUNDUHJvZmlsZT5zUkdCIElFQzYxOTY2LTIuMTwvcGhvdG9zaG9wOklDQ1Byb2ZpbGU+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjcyMDAwMC8xMDAwMDwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+NzIwMDAwLzEwMDAwPC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpSZXNvbHV0aW9uVW5pdD4yPC90aWZmOlJlc29sdXRpb25Vbml0PgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6UGl4ZWxYRGltZW5zaW9uPjU0PC9leGlmOlBpeGVsWERpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjUyPC9leGlmOlBpeGVsWURpbWVuc2lvbj4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgCjw/eHBhY2tldCBlbmQ9InciPz7BeLFDAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAArWSURBVHja7FppcFRVFv7ue6/3nXQ20kmAkJgQkjSGpKEhQiEIgkZQQBjEQXRwqUHU2YxDUaWjjFVayhQz4zbMoOWCzjC4MCAG2Q0DhBBMgjEGQkJIyEaW3vu9d+/8CGBQknSHBEeLW9U/Xte7957vnnO++91zH2GM4afYOPxE208WmDAUg86eke0cGS2lJ0RK6ZEmOcGip7E6NTMrBaYCgKBEAh4/6Wh3c40tnXxdXYtQUdMkVGwrPFo0WDaQwcqxSc6cJPuowIwpYwOLUm1Bp8XAFAaNDJXAIAgEHLl8HsoIJIkhIBG4fDzaXUSsrFcW7S1XbSo9pSr8oujIyR8U2I3ZudHjkoK3LJvuWpuRGLRp1Qz8AANcpoDXT1BWq6zfuNPw1LGTys9Kjh5uuubApuaNT192s3vtgjxPvlo5uOzq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' + +ICON_BASE64_BLOB_THINK2 = b'iVBORw0KGgoAAAANSUhEUgAAADoAAAA3CAYAAABdJVn2AAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAADpCaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzE0NSA3OS4xNjIzMTksIDIwMTgvMDIvMTUtMjA6Mjk6NDMgICAgICAgICI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgICAgICAgICAgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iCiAgICAgICAgICAgIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAgICAgICAgICAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgICAgICAgICAgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8eG1wOkNyZWF0b3JUb29sPkFkb2JlIFBob3Rvc2hvcCBFbGVtZW50cyAxNy4wIChXaW5kb3dzKTwveG1wOkNyZWF0b3JUb29sPgogICAgICAgICA8eG1wOkNyZWF0ZURhdGU+MjAyMC0wNy0wMlQxNzowOTozMy0wNDowMDwveG1wOkNyZWF0ZURhdGU+CiAgICAgICAgIDx4bXA6TWV0YWRhdGFEYXRlPjIwMjAtMDctMDJUMTc6MDk6MzMtMDQ6MDA8L3htcDpNZXRhZGF0YURhdGU+CiAgICAgICAgIDx4bXA6TW9kaWZ5RGF0ZT4yMDIwLTA3LTAyVDE3OjA5OjMzLTA0OjAwPC94bXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhtcE1NOkluc3RhbmNlSUQ+eG1wLmlpZDpiYzcxZTAzMC1hY2UwLWFlNGMtYTI2YS1hNGJlM2E4NDNlMDA8L3htcE1NOkluc3RhbmNlSUQ+CiAgICAgICAgIDx4bXBNTTpEb2N1bWVudElEPmFkb2JlOmRvY2lkOnBob3Rvc2hvcDo0OWE4ZGNmZC1iY2E4LTExZWEtYTEwYi1iMTlmYTMxNTc1YWQ8L3htcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ+eG1wLmRpZDpjMWE2NTcxYS1lNGJlLTczNDMtYjAzNy1lYmE3NmRjMTA3YWI8L3htcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOkhpc3Rvcnk+CiAgICAgICAgICAgIDxyZGY6U2VxPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5jcmVhdGVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6YzFhNjU3MWEtZTRiZS03MzQzLWIwMzctZWJhNzZkYzEwN2FiPC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDIwLTA3LTAyVDE3OjA5OjMzLTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgRWxlbWVudHMgMTcuMCAoV2luZG93cyk8L3N0RXZ0OnNvZnR3YXJlQWdlbnQ+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOmJjNzFlMDMwLWFjZTAtYWU0Yy1hMjZhLWE0YmUzYTg0M2UwMDwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAyMC0wNy0wMlQxNzowOTozMy0wNDowMDwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIEVsZW1lbnRzIDE3LjAgKFdpbmRvd3MpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICAgICA8c3RFdnQ6Y2hhbmdlZD4vPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgPC9yZGY6U2VxPgogICAgICAgICA8L3htcE1NOkhpc3Rvcnk+CiAgICAgICAgIDxkYzpmb3JtYXQ+aW1hZ2UvcG5nPC9kYzpmb3JtYXQ+CiAgICAgICAgIDxwaG90b3Nob3A6Q29sb3JNb2RlPjM8L3Bob3Rvc2hvcDpDb2xvck1vZGU+CiAgICAgICAgIDxwaG90b3Nob3A6SUNDUHJvZmlsZT5zUkdCIElFQzYxOTY2LTIuMTwvcGhvdG9zaG9wOklDQ1Byb2ZpbGU+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjcyMDAwMC8xMDAwMDwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+NzIwMDAwLzEwMDAwPC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpSZXNvbHV0aW9uVW5pdD4yPC90aWZmOlJlc29sdXRpb25Vbml0PgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6UGl4ZWxYRGltZW5zaW9uPjU4PC9leGlmOlBpeGVsWERpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjU1PC9leGlmOlBpeGVsWURpbWVuc2lvbj4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgCjw/eHBhY2tldCBlbmQ9InciPz5uOveQAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAqxSURBVHja7Fp5VJTXFf+9b5kFBoYdDciwiMhe0xhFwYQYTdUTl7hErVWJWYptNGoalwQ92mOiydGqaRajiWarRk1jbIItjUHEiNYYRKKgMiMDiCDrMGyzfN/rH+PgAMMyAybmxHvOd2DuvPvN7/fu/d69776PUErxaxAGvxK5R/Qe0XtE7xG9K4S7Uzde9WxsRKi/OSJsgGmom5y6dTe2vJYtvVHHlmpvcppNu/Iv3wk8pD/z6MqnY8Of+V3jclepqFDIqLuLTJzsiH1zK3OkyUAa8zSSs99ekH29eXf+1buKaMqM3yiWTdWtj1aZhgFI7idsmZdK+NytXyjX7Tl0vvFnJ7r/tYj5MxObFvYjwU6ED5503Tt79eWPfhaiqb+P90md0LA6MsgUzxCMvb28SQH3kSCyIEDiDar7HtD/DxCN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' + +ICON_BASE64_BROW = b'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/GMzLdsAADpCaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzE0NSA3OS4xNjIzMTksIDIwMTgvMDIvMTUtMjA6Mjk6NDMgICAgICAgICI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgICAgICAgICAgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iCiAgICAgICAgICAgIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAgICAgICAgICAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgICAgICAgICAgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8eG1wOkNyZWF0b3JUb29sPkFkb2JlIFBob3Rvc2hvcCBFbGVtZW50cyAxNy4wIChXaW5kb3dzKTwveG1wOkNyZWF0b3JUb29sPgogICAgICAgICA8eG1wOkNyZWF0ZURhdGU+MjAyMC0wNy0wMlQxNjo1MzowNC0wNDowMDwveG1wOkNyZWF0ZURhdGU+CiAgICAgICAgIDx4bXA6TWV0YWRhdGFEYXRlPjIwMjAtMDctMDJUMTY6NTM6MDQtMDQ6MDA8L3htcDpNZXRhZGF0YURhdGU+CiAgICAgICAgIDx4bXA6TW9kaWZ5RGF0ZT4yMDIwLTA3LTAyVDE2OjUzOjA0LTA0OjAwPC94bXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhtcE1NOkluc3RhbmNlSUQ+eG1wLmlpZDo5ZGMyYTFmMC02ZWJhLWQ3NDYtOGIzMC1jYzYwMWM0ZGIzMzE8L3htcE1NOkluc3RhbmNlSUQ+CiAgICAgICAgIDx4bXBNTTpEb2N1bWVudElEPmFkb2JlOmRvY2lkOnBob3Rvc2hvcDplNjE1MzI2Zi1iY2E1LTExZWEtYTEwYi1iMTlmYTMxNTc1YWQ8L3htcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ+eG1wLmRpZDpiMzM5ZDA0Mi1mNGFkLTQ5NDUtOTBiZS1hZTg0ZTE2ZGNiZDI8L3htcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOkhpc3Rvcnk+CiAgICAgICAgICAgIDxyZGY6U2VxPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5jcmVhdGVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6YjMzOWQwNDItZjRhZC00OTQ1LTkwYmUtYWU4NGUxNmRjYmQyPC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDIwLTA3LTAyVDE2OjUzOjA0LTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgRWxlbWVudHMgMTcuMCAoV2luZG93cyk8L3N0RXZ0OnNvZnR3YXJlQWdlbnQ+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOjlkYzJhMWYwLTZlYmEtZDc0Ni04YjMwLWNjNjAxYzRkYjMzMTwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAyMC0wNy0wMlQxNjo1MzowNC0wNDowMDwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIEVsZW1lbnRzIDE3LjAgKFdpbmRvd3MpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICAgICA8c3RFdnQ6Y2hhbmdlZD4vPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgPC9yZGY6U2VxPgogICAgICAgICA8L3htcE1NOkhpc3Rvcnk+CiAgICAgICAgIDxkYzpmb3JtYXQ+aW1hZ2UvcG5nPC9kYzpmb3JtYXQ+CiAgICAgICAgIDxwaG90b3Nob3A6Q29sb3JNb2RlPjM8L3Bob3Rvc2hvcDpDb2xvck1vZGU+CiAgICAgICAgIDxwaG90b3Nob3A6SUNDUHJvZmlsZT5zUkdCIElFQzYxOTY2LTIuMTwvcGhvdG9zaG9wOklDQ1Byb2ZpbGU+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjcyMDAwMC8xMDAwMDwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+NzIwMDAwLzEwMDAwPC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpSZXNvbHV0aW9uVW5pdD4yPC90aWZmOlJlc29sdXRpb25Vbml0PgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6UGl4ZWxYRGltZW5zaW9uPjUzPC9leGlmOlBpeGVsWERpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjUzPC9leGlmOlBpeGVsWURpbWVuc2lvbj4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgCjw/eHBhY2tldCBlbmQ9InciPz6xTRINAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAeISURBVHja3Jp7UFTXHce/d3fZZR8sIPJQeSwghFeAsTVBIriWphkMGB9kGmOYaXWa1mQm0VJjCGGmDzdoUtT+0w7Q0GbUkNYHhBUz49iGRwKkolVQoKTA7gIqILIsu3ff9/YP0x3JPi+5IPj7a/fc8zt7Pvs753d/v3N+BE3TeNyEg8dQHksoHtsDHnw1NzEznp8pW8WVRYfyogJEhFTsT4gAwGCiyVmS1mkmbSOqO3ZVn9rae/iPLTfZngPBxp46UiLPKtggLEyV8VIIguAA2OqjaiNN09StYWvvhU6T8u3K5s5HDvXRe3k7ijaJdor9CQkDELeARjNFnm8z1e8+dPnviw71wVubN762VbJPLGQFxgmONNFkdZOhav97/2xeFKj++vyjSdF+SQsA4wTXr7b2J+347NCCQe3fkytT7A1U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' + +ICON_BASE64_BLOB_HEADACHE = b'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/GMzLdsAADpCaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzE0NSA3OS4xNjIzMTksIDIwMTgvMDIvMTUtMjA6Mjk6NDMgICAgICAgICI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgICAgICAgICAgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iCiAgICAgICAgICAgIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAgICAgICAgICAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgICAgICAgICAgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8eG1wOkNyZWF0b3JUb29sPkFkb2JlIFBob3Rvc2hvcCBFbGVtZW50cyAxNy4wIChXaW5kb3dzKTwveG1wOkNyZWF0b3JUb29sPgogICAgICAgICA8eG1wOkNyZWF0ZURhdGU+MjAyMC0wNy0wMlQxNjo1NToyNi0wNDowMDwveG1wOkNyZWF0ZURhdGU+CiAgICAgICAgIDx4bXA6TWV0YWRhdGFEYXRlPjIwMjAtMDctMDJUMTY6NTU6MjYtMDQ6MDA8L3htcDpNZXRhZGF0YURhdGU+CiAgICAgICAgIDx4bXA6TW9kaWZ5RGF0ZT4yMDIwLTA3LTAyVDE2OjU1OjI2LTA0OjAwPC94bXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhtcE1NOkluc3RhbmNlSUQ+eG1wLmlpZDoxYzUxOTkzZi05MjNiLTM2NGItYWY5ZS1mNGE3MzViYjgxYTI8L3htcE1NOkluc3RhbmNlSUQ+CiAgICAgICAgIDx4bXBNTTpEb2N1bWVudElEPmFkb2JlOmRvY2lkOnBob3Rvc2hvcDo1MDgwYWJhOC1iY2E2LTExZWEtYTEwYi1iMTlmYTMxNTc1YWQ8L3htcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ+eG1wLmRpZDo3YWMwMzdjMC03ZmMzLWNhNDgtYmVlYi1lM2Q0ZDJjODJiNTU8L3htcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOkhpc3Rvcnk+CiAgICAgICAgICAgIDxyZGY6U2VxPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5jcmVhdGVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6N2FjMDM3YzAtN2ZjMy1jYTQ4LWJlZWItZTNkNGQyYzgyYjU1PC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDIwLTA3LTAyVDE2OjU1OjI2LTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgRWxlbWVudHMgMTcuMCAoV2luZG93cyk8L3N0RXZ0OnNvZnR3YXJlQWdlbnQ+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOjFjNTE5OTNmLTkyM2ItMzY0Yi1hZjllLWY0YTczNWJiODFhMjwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAyMC0wNy0wMlQxNjo1NToyNi0wNDowMDwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIEVsZW1lbnRzIDE3LjAgKFdpbmRvd3MpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICAgICA8c3RFdnQ6Y2hhbmdlZD4vPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgPC9yZGY6U2VxPgogICAgICAgICA8L3htcE1NOkhpc3Rvcnk+CiAgICAgICAgIDxkYzpmb3JtYXQ+aW1hZ2UvcG5nPC9kYzpmb3JtYXQ+CiAgICAgICAgIDxwaG90b3Nob3A6Q29sb3JNb2RlPjM8L3Bob3Rvc2hvcDpDb2xvck1vZGU+CiAgICAgICAgIDxwaG90b3Nob3A6SUNDUHJvZmlsZT5zUkdCIElFQzYxOTY2LTIuMTwvcGhvdG9zaG9wOklDQ1Byb2ZpbGU+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjcyMDAwMC8xMDAwMDwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+NzIwMDAwLzEwMDAwPC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpSZXNvbHV0aW9uVW5pdD4yPC90aWZmOlJlc29sdXRpb25Vbml0PgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6UGl4ZWxYRGltZW5zaW9uPjcxPC9leGlmOlBpeGVsWERpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjcxPC9leGlmOlBpeGVsWURpbWVuc2lvbj4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgCjw/eHBhY2tldCBlbmQ9InciPz5o6m+QAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAABbGSURBVHja7HxZcGTXed73n3Puvb13oxtrYx1gMJjBLMTOWUiKiiRGcuxS2Y7K5bhsObEdOXmIk5TzkJQqSfkpecxTqpyUK3mwrUiqKHbJkkxRIk1KwyFnBrNzFgwGGKyDrbH0fu9Z8nDRBIboBockhpJcc6pQ/dIXOOe7//J93zkHZIzBs1F9sGcQPAPnGTjPwHkGzs/HED/rCXzmxRFyLEBwQ4IbWBzEyIARiAjQxv9RiozSgNRkPAnjSYKnCD89f/GptVv6NFv50PAYBWzDGuNKNCRUMBnTibqwakpETFs4oJtDjmkJOSZhMRMRDEFi4FoDnoJyPSoWPcoVXbaWLdJytsDmt4psPpNlc2ubbHNti7sbeabGL79rfmHAGR4Zo5BjWGeTDHQ2ynRbvRxJRfVnE2E1Gg2ZdNjRkYBtLEsYZnGQYIYYAxj5z5tK5GhAaYLUZFwPpuSRKbnkZYtsc6vAJtdy7NWldf7DyUXr9vyKyK1lmbp86ZMB9dTAGRsbpURE85akinc2yoEjrd5vdDfLl1uSqiUc0EFHGGYLkGAGRAAIoCf83RXAtAFcSXAlmbxLKpNlW/fnrSsT89b/ur9gvTazLNayJZLvvPPxUu/AwRkZHaOAbXhdRMVPdrlDZ/vLv3P6WPnlsKMbBcGqYEB0sC/DGMAAAEGvbvHcrYdi/PsXQ/99YsF6bXWLb5x/+6L+mYJz9swoa02p8Klu98TQ4fJv9TR7/6ghrlrCjrE5exyPpwGO/4sBqYBCmdRqVmxdfWD94PKE81+uTdm3f/DaZe9TB2doZIyaE8o63um2nTzk/lpfq/fbHQ3ycCKsA5YAg3k6gNQEalfqPVrn3v1F6/b1KeuPz78XfPNb3x0vf2rgnDk9Sqm4Do8dKY2cOVr+o/4O96VUVMc5A2OETwmO2kMbIFciPb/Kp1+/EfzDt28H3viL/3fFe+rgjIyMsfZGWXfueOnLv3a28EctCXnE4nDo5wCUD6abNtAlRde/8Xr4q999J3Trr18dV0+NIY+NjfFTh9ymXxot/OEvjxb+Y0NM9QuOAPDzA0wlxQousLxJbHaJHWtJyX97ur/U8OV/OMieSuS8eG6UH+twm144Xv7acE/5D7qbvUbBwRk9YdF8ioX5sXavgfk1hslHHJOLHBs5ZgouW1nPs6/PLlt/WSix/N++fsUcmHx44ewo62qSDZ8fKn1t5HD5D1qTslEw8H1brAGKLpAvEQplglQExzIIBwyiQQPOfZDoAIFRGsgVCeP3LVy4Y+H+ogAjkDZISoXfK0tzXTA1DsA7EHCGhsdYX5use/lU6Xdf6i/+fiKsGznVBqYyUVcC9+YFrk8J3HookC0wpFMKz3V7OHvMQzxiIPjBRk7ZA+4vcHz/koM7swJt9QqjRz3YwvC5FX78nbv27y7laPaVl089evWN6/oTpdXA0PPU0eiFXzpR+s0vjRT/w6FGr90W4NXSohItmRxheonjxpSFmw8F1rYIxvghohQQDhi0Nyi8MuSiNy2RiJgDSTOlgYUMw1+8HsDlCQvJmMYXx8o41i5hCyCzxfTtGTH/42v2f15c4/9HKVb40VvXzMeOnEhQ28OH3TNjfeV/1dEg26x9gNEGWNkk3JiyMH7fwsQCBwhoSmq0pjQcyyCTZZhZ5nj3roVUdDvFQvJAIqiSUvcXBAwI3c0Ko0c8NMY1LAa0JDRrSuhmxs1Xf3rTvnZ31roGQH4scF44N8oPp73uF08U/92JTrc3aBuxX67nS8D1BxbeuGHj5rRAPGxw7mQZgz0SXU0KFjfYzDO8fdvGN/8ugJszAl3NEoeacSDgaO2z5LJHsIVBPGyQChtwEGCAgAWkU1p8ftAdBPBbuSKbfvHsqcxb56+bjwTO8PAYdbfI+G98Jv/PjrZ5pyOOsff7/maecH1K4P+eD2B+laMlpfDrLxXR3y5RHzOwtxcfCyoUuz3MrXDcnuFYzzKUPULI+eSMnTPAsYCQY7C2xZArEsoSsPgO0SCAUmETPnPU+1Wt6PX/8f3Q3wJwPxLPaaxT1vFO71xfq/eVWNCEGb0voveM9Rzh1kOB7110sJ5jOH7Iw5fPljDQ7aExbhCw/Ilz5keIJQBbGBhD0BXheACDMyAaNOhNS3BmML/KcXdWoOju0Anyv8caYjp9pE1+9XiXTP3KF07SE4MzOjbGOhpl08ku92v1UZW2hWG16kzZAybmOd69Z2Fy0U+TF0+4OH3MRUPMwBHmMUCLLmF1i7CwxuBYBkHHQByQacsYEAkYDPZ4aIhrrGcZrj2wkC0wqA/0paANK53ULwwf9l50bC2eGJxIQNs9zd4X+zvc0wHLCEa168zKJsOFOzYu3rOQjGq8MlzG6aMeUmGAYSfWdgQhw+1ZgfdmBBJhjfqoX6gPaoQCBiO9HvraFAyAG1MCmSyDJ/dEGcVDJjnQ7f1mQ1Qnzzw/SB8KzvDwGOtulumj7fKftDeoeC0RaeCTu+9ecHDpngVbAF8YKqMvrRAPmupCsAycf8/GT2/akAo4cUiivVHBOkBHmxEQDgID3R7a6xUePOJY3iAU3b3LCNpG9LbI0+mkHowEDPtQcGzLWAM97ss9Ld4pRxhejeobA+QKhMlFjqtTFjSAYx0SI30eUlENzvZ+v+QBd+d8MpgvEoYOS5zqkmiMmwOVEkR+7Wmt10inFJQmPFzl2CxQtRpF4SBSh1vVV9IpHdwXnOefH6XGhEqd6HK/kk6qWC1mrzWwusVwfUpgeYOhNaUxcsRDR4OCY+9drPLtA1yfFHiUYUjFND5z0kVnk0I4oJ+KYk1ENBoSPo+aWeFYzzN8sPRvAyl6W+XLHY2qaV9w4iHNTx1yxzoavMFoQHOi6gLRU8BihuHKpAXOgFPdHkaPeLAYoVrllhLvF0cY4Gi7xHCfh3BA1xSmn3TYAoiHNOoiGgsrHFsFqpUvdKhZNbfWq4GBoeepJjhNCRV+6WT51+NBk9zPgtgqMMyucMyscIwccdHfKREN1rZqCy7h0TrDQoajUCbcmRP4b98J4XsXA5he5lBPARzBDSJBg7qIwXqWUCjRvg0o6JjByprFXjtihE4fVZ2Hmr2zgRpMuDKW1hkWMn57PNYhka5T+7Rjg/Usw+QihzGAZfmF/OGShZUNjvsLHH1tEr2tEg1xg0jA+KTtE9oagvucpz6mMLnAUHIJngQsVvW7TDC01QSnLqJFc1K9HA/pZsENVeU125/zawxLGwx1EYO2Bo1oyNQMNAO/Pk3MCUSDGul6Dc4MlCI8XOZ4uMRxc9rCSJ+L450SHQ0K9VH/rcN8BIDMzofSvlVSlj5IUvvdquwRLKdWGUekJjipuA6lk+pLIcsE+IdMaDHDsFUgtKQUoqGdN11Ld/liU6AlqfDZ51x0NkrMLHPcmLZwY0pgekng9mzIr0W9Lp7v83CyW8LhH93r0QDyrk9Mr04K3FsQ2MwzFMo+OJFaMsXArqqtxsZG6TOndGNTnTphiepRU1moVH4kFF3CkTqFkGWwnxOYKxFWtxgyOcKpbo3GuEJLUiMcNIhFDTqbFSbmJMYnLCytM7xxzcHUosDEgoczx1y01+sPBb8CyuoW4d68wLt3LTx8xLGQ4VjdYtgsMJTKBNd9MutYPF7ZDaWi6mgyqusYq/2ylAJWNhgyWQatyWe3ohY4/qxXNjlWNv36lIxpLG1wLG9yLG0wZEuEXMEHr+QSNvMMq5tAZoshk2PQGhjr89DTrMBZdb6ltiXM1BLHzWmB8UkLdx5aKHtA0PF9I6UB1/Nr3T5KTlcHxwJLhPVgXUg5tI8dkC8T7s75StoWBg0xDUtUrwuVKcytcKxsMARsg7qIxt1Z3xm8NyegtiVFpbYwMrAFoeQR7swIWNwgYBm01SsELdTkT7NrHK+N27jwnoWJBQHOgJaUQl+7RE9aoezaKHuE9RzbjcGed18VnIClrUREnYqFdc2eU3SBuVWGH19zkMkxHE5LHGrxSV/VWDP+X1vMcGSyDCEHqItorG0xBB0/nSJBA1sYcDK+F6N9YAolQq5I0NpfvKt8L6banCbmOb75ZhA3pwXWNhkYAY4AGuIa8bCBu62pMjnC8sa+krJYFZxE2AQSId0VtE3VwMmXgDtzAj+5ZeO9GYH2RoWhXg8tSb8eVHtIasJmgTCzypEvE5rrFNpSGg0JF33tEq4kBC3fQ2a0I2TdbbOq6BIcYdBWrxGwqken1oRimbC0ziAlYFl+h9MGmFnyX4pjAUsbDCBgepmjWPY9H8b2BHqxEvCPgZOM6lgkaJoE31lnpfgWyoTbswIX7li4fN9C0DEY7JEY6JaIBE31oNnWUjMrDAurDJyA3rREQ9wvxFIrGAMI9vjuQ6WGKANIRWB+PazZtSxuUB/TGOn1UOggSO2nfyX6skVCtsAQDhjki4SZZY65NY62lELA3gN4bk/knD0zSp8fUHVBx0SIALOdkq703b3pJYHvvuvgxpT/yJdGy3ih30VPs6pZuZXxWfSthxZWNxkaYhoD3RIhx1RNj32Jy372hAMcbVPoaSmAtrd5jAGKHrCV873q27MCi2sM7z0UWMxwXH0gEAv6NskucAyAjT2RwwhIRVVzyNZOZT5SATPLHJcmBH581cHyJkNzUuN0v4vPnnLRFN//VMdGnnBnjuONazYEB/o7JY53SdgWDnwQ+c7i7j4UtoBg3NdVfe0SZQ/41t8FceGOhTdvOOho0AgGJGI71ooBsLYncjgzSMVUXdA2vMIZPAXMrnDc3e4oo0c9HO+UON7poblOw+a1O9R6jnB10q9P61mGc/0uBns8xEL786Fq8UJPCA7tfpgADoBzwBIGYcfAGGCwx0Mmy3B1UuBHV21oGAz1yMpaNICVvZHDQPGIiTsfKMacGyRjBi31HgYPezjUrFAXMuC7lfouyu4pv7Nc2QbmzoxAe73GcK+HnrTa4/E8BobZIXOmysL3I6Xvf1bxVyo+HRFwpE1hI+9heonjyqSAtW3RHmtVsAQkgNU9kUMEODaCu4txwAYGD3vo75KIhg0sZra3N6k6azbARsFX2996K4gHixxNCY0vjpZxrEMhHjbVF7XLPpUSMIYeA0fw7W5WA9TKvrhUOyZX5SV8ENCmuMbQYQ+5IuE7Pw3gjSs2NrOEf/ErBaSixjNApmort7hxdrc2AhCygaC1HSkfomPuzgmMT1h4+7aFbIEw2OPhXL+H4V4XifDejmaMH2krmwyrWwwrmwzLmwxbeULJJRjjF9t0SqGtXqE1pZGMagi+HaXSlzArGwzLmz7DtgWQimqkU9pv/7Y/991BUB/TePGEi5JLuHDHwu1ZC//71RBeGS4XsyXauDr+zuNpRf4b4ozMY2f2BN+9nUGPpxH5BGx1i+HmtMC1BxamH3FoA4we8TDY4xfgVNSvM7vfYq4ILK5zTC5wPFz2ZcTaFsNGnqFYJrjS/7u25S+mJanRXu+DFAoYKE3YzBMWMwyPMgwrW74IFhxIhA3SKYW+VomThyTSSQ0hdmWIBTTXaZztd8EIuDRh4eqkMI5tNhfXRa76ph49aXP10cmXCbMrflt8+5aN5Q2OWEjjXL+H00c9dDWqbRtjBxit/W2Ze/Mc4/ctXLpnYSHDsZHzCZ82ftcJWAaOZVDygLUtgfsLQCRo0JJUiAYMlAbWstsbdh7gKoK7zWuIgFhI496sgKfK4H0e0sltG5b8zmxxoDetILgLyzL43rsOLk9YSxt5vpchGwCuZEpqMga1Sd1OpQamljl+NO7gby44KEvC0GEPXxgs43MDLiy+wz53R4wrgclFjm//JIDz79nIl2iPPdqcUOhtlehoVCAi3JkVeLDIMbdNJnenSLpe4ViHQkNMYz3PcOW+eD9NM1kGTxGUBn71XBlUxYDvblYIBww4g/mrt+2plU3m7gXHAKUSskpij3YgerxGrOcZxictXLjtp1FrSuFUt8Rwr4ej7RKOVb0YSgVs5hku3vWfy5f8SLEtoDGu0d0scaJL4lCzRFNCIxzwUXvhuO84zixxPNrwdVM8bNCc9NMsGTFwhC85jnZYOH/LxtUHFlzPlwzzaxzZIiEa2Ft/mK8M8MIJV91fYHc2C5asBo4plCjjKdL7cQlt/BMMt6YF1rMMzXUaxzsknuv233QibPZtuSXXPx6yVfAPmQZtgyOtCse7PJzolDjaLlEf1wjuovVtWqOridDXqrCW9dMmEjRIRTUSYf3Yfpdt+VGvtS92GxN+l6w1p0oNSqe011qPW4lIFctCG0K2yJZdj1wQnJoAAeDk66HjHRKH0/6+UzziO4EfZmdyBsRCBqmYBmP+5z8YcDHc66GrSSFY5ZiCYH6RTYQVeloe50W72gQAoD2lcbrPRcg2mJgXaEkpHO+UCNr7k0/GkA0FaNKxyFQ9vPRf/01/95dGi6/2t3vdtTp3RYjmigTGfPbpWDt3FfYDp3LKa2GNYXqJw9OE9gaFlu0UEvzJvWKzq2vufqYyv7IEPANY28XXFrXnZwADwvifvRp55Z//yZ3qPOfevL040ON+o7vJ+9dBG6Fq/YvIb+/xsHmfjT7pgir6pyWpEQv5dD4U2AH3o+wyUI3uWpmf4AaGAHofwNrGvyuhMzl+YX5N5GseJJhdEaWJeet/zq2Jt6SGV+tYCJHfiT7qgioCN2ADqZhBfdwgZONxKXJAIpSIwOBf2qoGTOVontbAVoHlr0/Z35ldEV5NcF59/ZK5PmXPXZl0/mSryG4o7Z+0fKq3jgif+snl3bKlUCY1syzeevNG4PKfffOq3vcIyp9+45r84ZXg+I+vB76+WWC3YeAB+Ht5/VwB6vpD+95fXQh9/Z27ztaeRlDtoclF4X7v3dAb2Tz745Nd7n/qapKD8ZAOcgZi9IsNiO9qMrOaZaXr0/b5i3edf39tyr75+puX9lCYfY/afuWXh+yB7vLh57rdf9nVJL+cjOimaFCLgG2e6vWgg0yd3bufuRIzmSzzFjLi4f1F60/P33L+/MEjsfzGW5eq3oP40HPIL50bZa0pGTvR5Z4+dcj9p71t8qV0UqZsbgQjP5IqtuTPEizzQXesUnABeIp0rsTK9+bFzI1p+9s3p+0/vztnTWULrHzxYu2rjk90SPvM6VGKBDSvi+pYc1INHmr2/vFAt/u5wy0y3RBTASHAjNq5gfczA8fsFHhtYIouqYkFa+u9Gfv67Rnr2wsZ/oPVLT6fLbDymz/58KuNH+liyOjoGAUdzZJRHeholOnWlDqbTqpfaqqTg/Ux3ZwI6UA4oLll+RdZOQM4mfd3KT8paLvdQv+Opy8qpQI8RabswmwUuFzLsuzyBr//aJ2/Nr8mvj+3Ku4sZvhWvkTywoUnv+/5se9bDQw9T7YwLBXVgc4mr66zSR1uqZODqah6LhzEkZCjW4KWiTm2cQLCWEIYJrhhjIEYAEb+XvxurrRb4FbubGoDGENm+8KrUYqMJ6FdRarskVtyqVAo03q+zBa28nRncUNcmF0RVx8+4nPzayJf9kiNX35Xf5w1Htgdz6HhMbKF4eGAFomIdlIxE05EdH0spJuiAdUeCZrOcMC0BQOmKWCZekfomC1MyBHG4RyCEzgjkIEhpclIDSkVuWUPRVexfMmjTLHMlotlepQr0nS2yGayRbawkWPL61m2uZ7jxfUcuZ4kpQzMlQO4X/5U75V/7uWR9//LgC0MWcIwwcEEB+fMcMGMENxYRBCMwGn7Bo7SMMbA04ZcqSCVJikVKalIeQralaQ9CUhF5oevX/r78R8JftHGs3/08QycZ+A8A+cZOD8n4/8PAGyz+3O8xelYAAAAAElFTkSuQmCC' + +ICON_BASE64_LEGO_THINK = b'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/GMzLdsAADpEaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzE0NSA3OS4xNjIzMTksIDIwMTgvMDIvMTUtMjA6Mjk6NDMgICAgICAgICI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgICAgICAgICAgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iCiAgICAgICAgICAgIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAgICAgICAgICAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgICAgICAgICAgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8eG1wOkNyZWF0b3JUb29sPkFkb2JlIFBob3Rvc2hvcCBFbGVtZW50cyAxNy4wIChXaW5kb3dzKTwveG1wOkNyZWF0b3JUb29sPgogICAgICAgICA8eG1wOkNyZWF0ZURhdGU+MjAyMC0wNy0wMlQxNzoxNTozNC0wNDowMDwveG1wOkNyZWF0ZURhdGU+CiAgICAgICAgIDx4bXA6TWV0YWRhdGFEYXRlPjIwMjAtMDctMDJUMTc6MTU6MzQtMDQ6MDA8L3htcDpNZXRhZGF0YURhdGU+CiAgICAgICAgIDx4bXA6TW9kaWZ5RGF0ZT4yMDIwLTA3LTAyVDE3OjE1OjM0LTA0OjAwPC94bXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhtcE1NOkluc3RhbmNlSUQ+eG1wLmlpZDpkYzQ2ZDAwNS1hY2U0LTkwNDUtODUzMC1iY2Y4Zjc3Y2U2NjA8L3htcE1NOkluc3RhbmNlSUQ+CiAgICAgICAgIDx4bXBNTTpEb2N1bWVudElEPmFkb2JlOmRvY2lkOnBob3Rvc2hvcDoyM2FiN2M2NS1iY2E5LTExZWEtYTEwYi1iMTlmYTMxNTc1YWQ8L3htcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ+eG1wLmRpZDowNDRhZDA4Zi03ZmQ0LWMwNGItYmY1Yy01MTI4NzQzMjcyNTA8L3htcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOkhpc3Rvcnk+CiAgICAgICAgICAgIDxyZGY6U2VxPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5jcmVhdGVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6MDQ0YWQwOGYtN2ZkNC1jMDRiLWJmNWMtNTEyODc0MzI3MjUwPC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDIwLTA3LTAyVDE3OjE1OjM0LTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgRWxlbWVudHMgMTcuMCAoV2luZG93cyk8L3N0RXZ0OnNvZnR3YXJlQWdlbnQ+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOmRjNDZkMDA1LWFjZTQtOTA0NS04NTMwLWJjZjhmNzdjZTY2MDwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAyMC0wNy0wMlQxNzoxNTozNC0wNDowMDwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIEVsZW1lbnRzIDE3LjAgKFdpbmRvd3MpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICAgICA8c3RFdnQ6Y2hhbmdlZD4vPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgPC9yZGY6U2VxPgogICAgICAgICA8L3htcE1NOkhpc3Rvcnk+CiAgICAgICAgIDxkYzpmb3JtYXQ+aW1hZ2UvcG5nPC9kYzpmb3JtYXQ+CiAgICAgICAgIDxwaG90b3Nob3A6Q29sb3JNb2RlPjM8L3Bob3Rvc2hvcDpDb2xvck1vZGU+CiAgICAgICAgIDxwaG90b3Nob3A6SUNDUHJvZmlsZT5zUkdCIElFQzYxOTY2LTIuMTwvcGhvdG9zaG9wOklDQ1Byb2ZpbGU+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjcyMDAwMC8xMDAwMDwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+NzIwMDAwLzEwMDAwPC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpSZXNvbHV0aW9uVW5pdD4yPC90aWZmOlJlc29sdXRpb25Vbml0PgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6UGl4ZWxYRGltZW5zaW9uPjEwMzwvZXhpZjpQaXhlbFhEaW1lbnNpb24+CiAgICAgICAgIDxleGlmOlBpeGVsWURpbWVuc2lvbj4xMTI8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAKPD94cGFja2V0IGVuZD0idyI/PnSBBO0AAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAADbNJREFUeNrsnXuMXFUdxz/nznNn3y92u215s9tSrEXEF1BwqdgVJchDJSKaYKJEjZoYgxhEJSYSefhIJBgSjDS8o/KyJkClLSpt0ZRKlb62tLYWumz3PTu7M/ce//idW/Yuu8PM7szuLT2/ZHP23jn3zp3z+33P73nOVVprLIWTHDsEljmWLHMscyxZ5liyzAkxRcP2QD/65kXOLb943tv6aJcCVG1NBIBkTAEQi4jpH3Pk2FFy7Jjj6cjzNID2tPTLyjFZV44zWTkeGHIV4Dy+cdQF1C2/eN6br7FQYfZztj7adXVtTSQJuMmYcgE3FtHSOsoDco7SHuA5jsqZy1zAm/Tnep7WgOtppQGd9XTOMMcFdCYr9xkYcvWKq9buC8PvDy1z9EufigA7gYVmgPWEwc6BmnisDVP0pL7+OT2B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' + +ICON_BASE64_THINK = b'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/GMzLdsAAD+paVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzE0NSA3OS4xNjIzMTksIDIwMTgvMDIvMTUtMjA6Mjk6NDMgICAgICAgICI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgICAgICAgICB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIKICAgICAgICAgICAgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIKICAgICAgICAgICAgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiCiAgICAgICAgICAgIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIj4KICAgICAgICAgPHhtcDpDcmVhdG9yVG9vbD5BZG9iZSBQaG90b3Nob3AgRWxlbWVudHMgMTcuMCAoV2luZG93cyk8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgICAgPHhtcDpDcmVhdGVEYXRlPjIwMjAtMDctMDJUMTc6MDI6MDUtMDQ6MDA8L3htcDpDcmVhdGVEYXRlPgogICAgICAgICA8eG1wOk1ldGFkYXRhRGF0ZT4yMDIwLTA3LTAyVDE3OjAyOjUxLTA0OjAwPC94bXA6TWV0YWRhdGFEYXRlPgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAyMC0wNy0wMlQxNzowMjo1MS0wNDowMDwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDxkYzpmb3JtYXQ+aW1hZ2UvcG5nPC9kYzpmb3JtYXQ+CiAgICAgICAgIDx4bXBNTTpJbnN0YW5jZUlEPnhtcC5paWQ6NGZjMmNkMTQtYjBhZi05ODQ0LTkyNTAtZTk1NTRhYjMzYzJmPC94bXBNTTpJbnN0YW5jZUlEPgogICAgICAgICA8eG1wTU06RG9jdW1lbnRJRD5hZG9iZTpkb2NpZDpwaG90b3Nob3A6NTU3OWQyOWUtYmNhNy0xMWVhLWExMGItYjE5ZmEzMTU3NWFkPC94bXBNTTpEb2N1bWVudElEPgogICAgICAgICA8eG1wTU06T3JpZ2luYWxEb2N1bWVudElEPnhtcC5kaWQ6OWUzNGE0MWQtOTM2YS1jZTRhLTgzNTMtZWVhYWEyYWQ2NjU1PC94bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpIaXN0b3J5PgogICAgICAgICAgICA8cmRmOlNlcT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDphY3Rpb24+Y3JlYXRlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOjllMzRhNDFkLTkzNmEtY2U0YS04MzUzLWVlYWFhMmFkNjY1NTwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAyMC0wNy0wMlQxNzowMjowNS0wNDowMDwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIEVsZW1lbnRzIDE3LjAgKFdpbmRvd3MpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDphY3Rpb24+c2F2ZWQ8L3N0RXZ0OmFjdGlvbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0Omluc3RhbmNlSUQ+eG1wLmlpZDoxMGZiMmQwMi04NmUzLTAyNDMtYTc0Ny1hOGVkODM3NDU3NDk8L3N0RXZ0Omluc3RhbmNlSUQ+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDp3aGVuPjIwMjAtMDctMDJUMTc6MDI6NTEtMDQ6MDA8L3N0RXZ0OndoZW4+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpzb2Z0d2FyZUFnZW50PkFkb2JlIFBob3Rvc2hvcCBFbGVtZW50cyAxNy4wIChXaW5kb3dzKTwvc3RFdnQ6c29mdHdhcmVBZ2VudD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmNoYW5nZWQ+Lzwvc3RFdnQ6Y2hhbmdlZD4KICAgICAgICAgICAgICAgPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGkgcmRmOnBhcnNlVHlwZT0iUmVzb3VyY2UiPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6YWN0aW9uPmNvbnZlcnRlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6cGFyYW1ldGVycz5mcm9tIGFwcGxpY2F0aW9uL3ZuZC5hZG9iZS5waG90b3Nob3AgdG8gaW1hZ2UvcG5nPC9zdEV2dDpwYXJhbWV0ZXJzPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDphY3Rpb24+ZGVyaXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6cGFyYW1ldGVycz5jb252ZXJ0ZWQgZnJvbSBhcHBsaWNhdGlvbi92bmQuYWRvYmUucGhvdG9zaG9wIHRvIGltYWdlL3BuZzwvc3RFdnQ6cGFyYW1ldGVycz4KICAgICAgICAgICAgICAgPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGkgcmRmOnBhcnNlVHlwZT0iUmVzb3VyY2UiPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6YWN0aW9uPnNhdmVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6NGZjMmNkMTQtYjBhZi05ODQ0LTkyNTAtZTk1NTRhYjMzYzJmPC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDIwLTA3LTAyVDE3OjAyOjUxLTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgRWxlbWVudHMgMTcuMCAoV2luZG93cyk8L3N0RXZ0OnNvZnR3YXJlQWdlbnQ+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpjaGFuZ2VkPi88L3N0RXZ0OmNoYW5nZWQ+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICA8L3JkZjpTZXE+CiAgICAgICAgIDwveG1wTU06SGlzdG9yeT4KICAgICAgICAgPHhtcE1NOkRlcml2ZWRGcm9tIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgPHN0UmVmOmluc3RhbmNlSUQ+eG1wLmlpZDoxMGZiMmQwMi04NmUzLTAyNDMtYTc0Ny1hOGVkODM3NDU3NDk8L3N0UmVmOmluc3RhbmNlSUQ+CiAgICAgICAgICAgIDxzdFJlZjpkb2N1bWVudElEPnhtcC5kaWQ6OWUzNGE0MWQtOTM2YS1jZTRhLTgzNTMtZWVhYWEyYWQ2NjU1PC9zdFJlZjpkb2N1bWVudElEPgogICAgICAgICAgICA8c3RSZWY6b3JpZ2luYWxEb2N1bWVudElEPnhtcC5kaWQ6OWUzNGE0MWQtOTM2YS1jZTRhLTgzNTMtZWVhYWEyYWQ2NjU1PC9zdFJlZjpvcmlnaW5hbERvY3VtZW50SUQ+CiAgICAgICAgIDwveG1wTU06RGVyaXZlZEZyb20+CiAgICAgICAgIDxwaG90b3Nob3A6Q29sb3JNb2RlPjM8L3Bob3Rvc2hvcDpDb2xvck1vZGU+CiAgICAgICAgIDxwaG90b3Nob3A6SUNDUHJvZmlsZT5zUkdCIElFQzYxOTY2LTIuMTwvcGhvdG9zaG9wOklDQ1Byb2ZpbGU+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjcyMDAwMC8xMDAwMDwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+NzIwMDAwLzEwMDAwPC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpSZXNvbHV0aW9uVW5pdD4yPC90aWZmOlJlc29sdXRpb25Vbml0PgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6UGl4ZWxYRGltZW5zaW9uPjUwPC9leGlmOlBpeGVsWERpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjUwPC9leGlmOlBpeGVsWURpbWVuc2lvbj4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg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' + + +ICON_BASE64_PALM = b'iVBORw0KGgoAAAANSUhEUgAAAEkAAAA8CAMAAAAdQmecAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAAB8SDx4UEiAUDyAUEiMZFSUbGSsUEy8aFiwbGTsUFTkdICwiHTIjHDQrHzsiGysjIjIlIDMqIzMsKjsgIzotID0uKT01IzszMUkYHE0ZIFkbKEQhHkUqH0sgHUUgI0MtIkUoKEsmIEwqIkwqL00rM0I1I0s1JEswKE04J0w7LUc9OVYpJ1omMVM0JVQ1K1I4JVU7KlszK1k6J1s7KVw4NGEdLmQeMWghNmE5LWQ4NXIiPWs2RHkkQnAzRVRENVNDOF1ENFxEOVpKOWNDM2NHPWNMPGxFOWxKPG9QPnJKPHVQP05HRFJMSltUUWpLQ2lUQ2NcWndNQndIU3JUQ3JUSHRZTHxSRHxVSHxZSnlaVH1YYmZgX39gVmZjYnZran14doFURoNWSYNbTYNeUoleUItbaYRgT4VhU4JiWIVoXIpjVIxlWo1oVo1pWpFiVpFlWZJsXZRxX4JmZYVsY4trY4pzaoN9e5NtYpRtaJltY5ZxYpRyaZpzZZx1ap14a5N4eJx1cJp3eJ15cZp6eqB2a6J6baN8cqJ7eax9cah+epx7hImBf5uBeqWAdKOCe6qCdKqDequJfbKJfY2EgpmIiZqVk52Zk6SBhKaFiKyDgqqFiayJgqyNi6aLkayNlKGQi6uRja+QlqySm6qZlLKMhLKOi7SRi76Th7qTi7KTk7KVm7KYk7SZm7iWk7yZk7ucm7Sco7ScqbqeorOfsK2knrmhnKukoqyop7GrqrqhpLqlq7mup7urqrSosbKuubqjsrymubyps7qqub6xrbSxsLizvbe1wr68ycKYi8OcmsCmo8KmqcGup8Ooq8qqqcersMGvv8yutMKxu8uwtM2zusy+v9G3usCwwsS0yca8xsW7y82/x8m9ysm90Ne8wMjAvMPCxsLAyc3Ax8vAy8/IzMbD0c3F08zK2NPLx9DJztnBydLO09LL2tPS19TS29rU29bU4dnT5NzV6NvZ4+Hf5uDd6+Pi7eXj8ejl9Ozp9/Lw+wAAAAAAAAAAAAAAAErQjXwAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAHU0lEQVRYR5WWf1gbZx3A8bw2y7nJVq00ZM9Eq63t0o3QFNKkrLbjoRjXsWFHCI+T0gNNe2nWm4Ndm9xFTLmj1UFONsUU1s2aZRRxdP7otNZN1Omc1inTdbad06danzlkVoR2/hG/7w8gNG/Y9iE/uPf9vp/7vt/37r0UZPLx34nxiYmJNybp4VuSxzQ9MXn5zempqelLlybfpotteu31ifFzfzp7/sL45PT09MS/aPOCME1jZ8+fGxs9Njw0fGLswuT01D/+SjsWgmU6fnJs7IUTx7410N8/MDx64eKlqV++DRXD9M2BkZOnfjicTvV0d/f0Hx09f/HNf//iL7QzP7mmn0XN9BMjR9PpfhOpkkdHz0z97+9PT9DuvOSa7gvHus2vYEzT6E4MDP10/PKlM0/T7rzkmoLBeyORWMwwzf6UaZowvydPX7z8nzPP0v585JhO7pIkWZbvVXUzlUomzYNmcui7L49fvPDs6zQiDzmmr9UHg7vDu8MRVTcOHESq5KEjz7z8yitnfkwj8pBr2njHNjEo7ZbliGFAQsk+eB155vTpc6f/RkPY5JiOr7i1uh5UYUVROw4ehEolk1193zj2k9+NLpxUbsWXrt5YfdfnpDAUS9UgLaCrq2/g6JETT9IINrmmJStWb9wUCKK6K0h1wDCMDs1IHjr8Tk23F63aeOsdooSXUNU6O7QOTdM7937x0NAbNIRJrumrS4tWb64OiFKrJEshWdnXqWr7QqGO/fuHztIQJrmmzKKiFauc9aLYIkp7xHvkfXtCLSG5Y+TU1w8foRFMGKat7y1asbLaH/CLkNeO5h2trZJk/Oq3I/uHh/9IQ1gwTD+4qnBpkbPK5xf9zTua/c1+fyT1WLLnvi+8MPwoDWHBMEWDjuuFpc5P+Hz3iM3Ndb5mPZVOKfU93xnqj/2GxjDINb3q8PicJYUly2vkutZWURR1PdErtwz8+vloQPk+DWLAyMnjWb58ZUnhrsf3SJ9s8fl1TVWlwODzI/HaxrYFpscw1fscxY7Slc7Yc5LkatDhTpZE3YzH133+1EsP0RgGDNOPqm74cJWrtHRbond9Q0LVdSmsmWa4rf3Ffw4/QmMYMEyZ9rIy502u0hpDlRK6HtNN40BCjI68+IeBtndWp0xmU5VrpWttFdqiensff27QjIuxwf6+/Y13v0YjGDBNr25yrV3rqoL7t7fX1A/0Girs6Eqw7fcPfJlGMGCaMt+rdt7k3Natqwkjpmnm4BNpQ27o+fNLD7yL4xYt+/RxGjYPtimTKSxxqYluEOm63psaTBtB89tDfe2LeY7neW7xnT+ncXPkMT109aoaJaYaugY7CmxSj6UHU12haNPV4EFw3I00cpY8psWLVlcHIxFdVTUtFod9Lm0aO+/adSMVAZy1icZSmKb738fzSzY1yJCRYcBGF48qWpdW11j/AapBQMW203gMw7SVRG4ORBKaqsXjWjSqaRGldkvV5utIF8JqFazWB+kQRI5pK4eLyvPVElQbyqRF92rxDll0rK+pXQRd8LK+/6MbNtzidrvXHKOjgCtMTVTD8++uDet6J1RJaVOie5XglrK6xlrUYf3QOo8HLG6v1+uuOEwHXmHajs45w05Fhx3c0JRQOBRUAi7P+pprIJuPrHHY7cXwZ3eAraJ8Nqss01NLqANzTbumxLSIrijhnTvDQWepq+x6oVAQBAuCh7dgs9sryj10dJbpttmJYT7eDlWOaJEwiO5uuRlJLNDMcSgK3lBOjkeyE3Q8NW1fNk8D1WiD9YJnZ1gOB1sCH0MK2oO/LYIF0gO3RWgkBmJ6cG51yRk5vkbR1IgcDisxWWwoIX0ILBAEm2AjCPx7sIeYbpvLx3odmgLPCaFIREY/WGDnrYOM5sAqUNgJNkEgImRaTGN44YPF0AFYhJsDIXicS/I+EC2n3QBHc7LZYO0q0KXgtttmTdfijDhLMQAiGxxYINK3Ax6ccqcq3jCzVrBaWAKdOKNyckk56N5esJ3UBqLQrAGYHg531CGV5ENtuAEDuSDWVKCMvN5Kb6X7s9R0O8poZvZ4FB0n2MrqGhr8vjLSij5JnYnMDSpIqbLS66amZbOiOSB9PNzmqdtSVVhL2rAcXtCHTeVIVQl4yfQKrs0WoWuNDKLp2dZ5eCvVzkGSmlWRpMCEhtORxIqj8TEBH88ja4IoKfxrqAC2wbmxUG0O7id6NAM+no+9GMuo6hZs+gxZKQQaRTPMFjFMUCuaFlo/Mr2CJkgJReNPfIFfmRM+ZIBVFfhS+BLOCZWb3C7kPofLEkM0CNqQy4zKuwGZ7iTRWIURIPW3mt0MMyo0vYL7s64luCt4Hu6ZeR4EHcgAuaBYcJ0XZPATAC0ampyAJ0fHz0IGZTPXiFTgQiYyJwAnh+pNd4QsZrcjgDYB5Bir7BvAhB5vKCvUZ+F4vMQ4cB54EP0/C2ik9/TDBZmnyG6BGqHuWJR9XvqdD2yCXcq+Dna6JtpIYJ15QWB+5W6v+1P/B0gPXHqaGwimAAAAAElFTkSuQmCC' + + +ICON_BASE64_LIST = [ICON_BASE64_BLOB_HEADACHE, ICON_BASE64_BLOB_PALM, ICON_BASE64_BLOB_PAT, ICON_BASE64_BLOB_THINK, ICON_BASE64_BLOB_THINK2, ICON_BASE64_BROW, ICON_BASE64_LEGO_THINK, ICON_BASE64_PALM, ICON_BASE64_THINK] + +def _random_error_icon(): + return random.choice(ICON_BASE64_LIST) + + + +# d8b +# Y8P +# +# 88888b.d88b. 8888b. 888 88888b. +# 888 "888 "88b "88b 888 888 "88b +# 888 888 888 .d888888 888 888 888 +# 888 888 888 888 888 888 888 888 +# 888 888 888 "Y888888 888 888 888 + + +def main(): + # theme('SystemDefaultForReal') + + # preview_all_look_and_feel_themes() + # ChangeLookAndFeel('Dark Red') + # theme('Dark Red') + # SetOptions(progress_meter_color=(COLOR_SYSTEM_DEFAULT)) + # SetOptions(element_padding=(0,0)) + # ------ Menu Definition ------ # + + ver = version.split('\n')[0] + + + menu_def = [['&File', ['!&Open::KeyOpen', '&Save::KeySave', '---', '&Properties::KeyProp', 'E&xit']], + ['&Edit', ['&Paste', ['Special::KeySpecial', '!Normal', ], 'Undo'], ], + ['!&Toolbar', ['Command &1', 'Command &2', 'Command &3', 'Command &4']], + ['&Help', '&About...'], ] + + treedata = TreeData() + + treedata.Insert("", '_A_', 'Tree Item 1', [1, 2, 3], ) + treedata.Insert("", '_B_', 'B', [4, 5, 6], ) + treedata.Insert("_A_", '_A1_', 'Sub Item 1', ['can', 'be', 'anything'], ) + treedata.Insert("", '_C_', 'C', [], ) + treedata.Insert("_C_", '_C1_', 'C1', ['or'], ) + treedata.Insert("_A_", '_A2_', 'Sub Item 2', [None, None]) + treedata.Insert("_A1_", '_A3_', 'A30', ['getting deep']) + treedata.Insert("_C_", '_C2_', 'C2', ['nothing', 'at', 'all']) + + for i in range(100): + treedata.Insert('_C_', i, i, []) + + frame1 = [ + [Input('Input Text', do_not_clear=True, size=(250, 35), tooltip='Input'), FileBrowse(), Stretch()], + [Multiline(size=(250, 75), do_not_clear=True, default_text='Multiline Input', tooltip='Multiline input'), + MultilineOutput(size=(250, 75), default_text='Multiline Output', tooltip='Multiline output', key='-MLINE-')], + ] + + frame2 = [ + [Listbox(['Listbox 1', 'Listbox 2', 'Listbox 3', 'Item 4', 'Item 5'], default_values=['Listbox 2', 'Listbox 3'], size=(200, 85), tooltip='Listbox', + key='_LISTBOX_', font='Courier 12', text_color='red',)], + [Combo([1,2,3], size=(200, 35), tooltip='Combo', visible_items=2, key='_COMBO_')], + [Spin([1, 2, 3], size=(40, 30), tooltip='Spinner', key='_SPIN1_')], + [Spin(['Spin item 1', 'Spin item 2', 'Spin item 3'], size=(240, 30), tooltip='Spinner', key='_SPIN2_')], + ] + + frame3 = [ + [Checkbox('Checkbox1', True, tooltip='Checkbox'), Checkbox('Checkbox1')], + [Radio('Radio Button1', 1, tooltip='Radio'), Radio('Radio Button2', 1, default=True), Stretch()], + ] + + frame4 = [ + [Slider(range=(0, 100), tick_interval=None, orientation='v', size=(3, 30), default_value=40, tooltip='Slider'), + Dial(range=(0, 100), tick_interval=1, resolution=1, size=(150, 150), default_value=40, tooltip='Dial'), + Stretch()], + ] + matrix = [[str(x * y) for x in range(4)] for y in range(8)] + + frame5 = [ + [Table(values=matrix, max_col_width=25, headings=('aaa', 'bbb', 'ccc', 'ddd'), + auto_size_columns=True, display_row_numbers=True, enable_events=True, bind_return_key=True, + justification='right', num_rows=6, alternating_row_color='lightblue', key='_table_', + tooltip='Table'), + Tree(data=treedata, headings=['col1', 'col2', 'col3'], enable_events=True, auto_size_columns=True, + num_rows=10, col0_width=10, key='_TREE_', show_expanded=True, size=(200, 150), tooltip='Tree'), + Stretch()], + ] + + graph_elem = Graph((880, 150), (0, 0), (600, 300), key='+GRAPH+', tooltip='Graph') + + frame6 = [ + [graph_elem, Stretch()], + ] + + tab1 = Tab('Graph Number 1', frame6, tooltip='Tab 1') + tab2 = Tab('Graph Number 2', [[]]) + + layout = [ + [Menu(menu_def, key='_REALMENU_', background_color='white')], + [Text('You are running the PySimpleGUI.py file itself', font=('ANY', 15, 'Bold'), text_color='yellow')], + [Text('You should be importing it rather than running it', font='ANY 15')], + [Text('VERSION {}'.format(ver), size=(85,1), text_color='yellow', font='ANY 18')], + + # [Image(data_base64=logo, tooltip='Image', click_submits=True, key='_IMAGE_'), + [Frame('Input Text Group', frame1, title_color='yellow', tooltip='Text Group', frame_color='yellow', pad=(0,0)), Stretch()], + [Frame('Multiple Choice Group', frame2, title_color=theme_text_color(), frame_color='yellow'), + # Column([[Frame('Binary Choice Group', frame3, frame_color='white', title_color='white')]], pad=(0,0)), + Frame('Binary Choice Group', frame3, frame_color='white', title_color='white'), + Frame('Variable Choice Group', frame4, title_color='blue'), Stretch()], + [Frame('Structured Data Group', frame5, title_color='yellow'), ], + # [Frame('Graphing Group', frame6)], + [TabGroup([[tab1, tab2]],title_color='black')], + [ProgressBar(max_value=600, start_value=400, size=(600, 25), key='+PROGRESS+'), + Text('', key='_PROGTEXT_'), Stretch(), + ButtonMenu('&Menu', ['Menu', ['&Pause Graph', 'Menu item::optional_key']], key='_MENU_', + tooltip='Button Menu'), + Button('Button'), Button('Exit', tooltip='Exit button')], + ] + + window = Window('Window Title', layout, + font=('Helvetica', 13), + # default_button_element_size=(100, 30), + # auto_size_buttons=False, + default_element_size=(200, 22), + # margins = (40,40), + # border_depth=1, + ) + # graph_elem.DrawCircle((200, 200), 50, 'blue') + i = 0 + graph_paused = False + + # window.Element('_LISTBOX_').SetValue(['Listbox 1','Listbox 3']) + while True: # Event Loop + # TimerStart() + event, values = window.read(timeout=10) + print(event, values) if event != TIMEOUT_KEY else None + window['-MLINE-'].update(value=str(values), append=True) if event != TIMEOUT_KEY else None + if event is None or event == 'Exit': + break + if values['_MENU_'] == 'Pause Graph': + graph_paused = not graph_paused + if event == 'About...': + Popup('You are running PySimpleGUIQt', 'The version number is', version) + if not graph_paused: + + if i < 600: + graph_elem.DrawLine((i, 0), (i, random.randint(0, 300)), width=1, + color='#{:06x}'.format(random.randint(0, 0xffffff))) + else: + graph_elem.Move(-1, 0) + graph_elem.DrawLine((i, 0), (i, random.randint(0, 300)), width=1, + color='#{:06x}'.format(random.randint(0, 0xffffff))) + + window.FindElement('+PROGRESS+').UpdateBar(i % 600) + window.FindElement('_PROGTEXT_').Update((i % 600) // 6) + i += 1 + + # TimerStop() + window.close() + + + + # layout = [[Text('You are running the PySimpleGUI.py file itself')], + # [Text('You should be importing it rather than running it')], + # [Text('Here is your sample input window....')], + # [Text('Source File', size=(150, 25), justification='right'), InputText('Source', focus=True), FileBrowse()], + # [Text('Destination Folder', size=(150, 25), justification='right'), InputText('Dest'), FolderBrowse()], + # [Ok(bind_return_key=True), Cancel()]] + # + # window = Window('Demo window..', + # auto_size_buttons=False, + # default_element_size=(280,22), + # auto_size_text=False, + # default_button_element_size=(80,22) + # ).Layout(layout) + # event, values = window.Read() + # print(event, values) + # window.Close() + +#------------------------------------------------------------------# +#------------------------ PEP8-ify The SDK ------------------------# +#------------------------------------------------------------------# + +change_look_and_feel = ChangeLookAndFeel +easy_print = EasyPrint +easy_print_close = EasyPrintClose +get_complimentary_hex = GetComplimentaryHex +list_of_look_and_feel_values = ListOfLookAndFeelValues +obj_to_string = ObjToString +obj_to_string_single_obj = ObjToStringSingleObj +one_line_progress_meter = OneLineProgressMeter +one_line_progress_meter_cancel = OneLineProgressMeterCancel +popup = Popup +popup_annoying = PopupAnnoying +popup_auto_close = PopupAutoClose +popup_cancel = PopupCancel +popup_error = PopupError +popup_get_file = PopupGetFile +popup_get_folder = PopupGetFolder +popup_get_text = PopupGetText +popup_no_border = PopupNoBorder +popup_no_buttons = PopupNoButtons +popup_no_frame = PopupNoFrame +popup_no_titlebar = PopupNoTitlebar +popup_no_wait = PopupNoWait +popup_non_blocking = PopupNonBlocking +popup_ok = PopupOK +popup_ok_cancel = PopupOKCancel +popup_quick = PopupQuick +popup_quick_message = PopupQuickMessage +popup_scrolled = PopupScrolled +popup_timed = PopupTimed +popup_yes_no = PopupYesNo +rgb = RGB +scrolled_text_box = ScrolledTextBox +set_global_icon = SetGlobalIcon +set_options = SetOptions +timer_start = TimerStart +timer_stop = TimerStop + + +#------------------------ Set the "Official PySimpleGUI Theme Colors" ------------------------ +theme(CURRENT_LOOK_AND_FEEL) + + +if __name__ == '__main__': + main() + exit(69) diff --git a/PySimpleGUIQt/readme.md b/PySimpleGUIQt/readme.md new file mode 100644 index 000000000..f98d82267 --- /dev/null +++ b/PySimpleGUIQt/readme.md @@ -0,0 +1,847 @@ + +![pysimplegui_logo](https://user-images.githubusercontent.com/13696193/43165867-fe02e3b2-8f62-11e8-9fd0-cc7c86b11772.png) + +[![Downloads](http://pepy.tech/badge/pysimpleguiqt)](http://pepy.tech/project/pysimplegui) + + + ![Awesome Meter](https://img.shields.io/badge/Awesome_meter-1000-yellow.svg) + + ![Python Version](https://img.shields.io/badge/Python-3.x-yellow.svg) + +PySimpleGUIQt on PyPI... + +[![PyPI Version](https://img.shields.io/pypi/v/pysimpleguiqt.svg?style=for-the-badge)](https://pypi.org/project/pysimpleguiqt/) + + +# PySimpleGUIQt + +"Qt without the ugly" + +(For newbies... "Qt" is prouncounced "Cute") + +## The Alpha Release + [Announcements of Latest Developments](https://github.com/MikeTheWatchGuy/PySimpleGUI/issues/142) + + + + ----- +## Getting Started with PySimpleGUIQt + +Welcome to the Alpha Release of PySimpleGUI for Qt! + +You can use the exact same code that you are running on the older, tkinter, version of PySimpleGUI. + +PySimpleGUIQt uses **PySide2** OR **PyQt5** for access to Qt. **PyQt5 has been having a number of problems recently however so tread lightly.** + +## To minimize potential problems and broken features, if at all possible, use pyside2 instead of PyQt5. + +## Porting your PySimpleGUI code to PySimpleGUIQt + + +To "port" your code from the tkinter implementation. Follow these steps: + +1. Change `import PySimpleGUI` to `PySimpleGUIQt` + +That's it! OK, maybe I should have said step instead of steps. It may not be that simple in all cases, but it's pretty simple generally speaking. + + +## Differences between PySimpleGUI and PySimpleGUIQt + +#### Sizes + +While you can use "Character-based" sizes like you did in tkinter, it's best to use pixel based sizes as that is what Qt uses. PySimpleGUIQt does some very rough / basic conversions from the character sizes to pixel sizes. It's enough that your elements will at least be visible. But the conversion is likely to not be ideal. + +#### Fonts + +Fonts should be in the format (font family, size). You can use the older string based too, but it will not work with setting like bold and italics. PySimpleGUIQt converts from the string 'Courier 20' to the tuple ('Courier', 20) for you. + + +### Installing PySimpleGUIQt for Python 3 + + pip install --upgrade PySimpleGUIQt + On Linux systems you need to run pip3. + + pip3 install --upgrade --no-cache-dir PySimpleGUIQt + +### Installing PySide2 for Python 3 + +It is _highly_ recommended that you use PySide2. The code will attempt to use PyQt5 is pyside2 isn't found. PyQt5 is **not** recommended. + +To install Pyside2: + +```pip install PySide2``` + + +**PyQt5 is no longer supported. Only PySide2 is supported** + +Too many differences were causing a lot of headaches. Supporting just 1 Qt port is difficult enough. Parsing out the differences between pyside2 and pyqt5 was simply getting to be too much + + + +## Testing your installation +Once you have installed, or copied the .py file to your app folder, you can test the installation using python. At the command prompt start up Python. + +``` + python3 + >>> import PySimpleGUIQt + >>> PySimpleGUIQt.main() +``` + +You will see a sample window in the center of your screen. If it's not installed correctly you are likely to get an error message during one of those commands + +Here is the window you should see: + +![image](https://user-images.githubusercontent.com/46163555/71421852-7c6ad400-264b-11ea-9adc-15f6aa4248e8.png) + + + + +## Prerequisites Python 3 +PySide2 or PyQt5 (experimental) + + +## Using - Python 3 + To use in your code, simply import.... + `import PySimpleGUIQt as sg` + Then use the exact same code as any other PySimpleGUI program that runs on tkinter. + + +## Status + +### Documentation + +For the primary PySimpleGUI documentation go to http://www.PySimpleGUI.org. HOWEVER, bear in mind that is the tkinter version. But it's the best documentation for the package at the moment. Docstrings are coming to this Qt Release, but it's going to take some time to get them done. When they are, then this readme will also be fabulous.s + +### FEATURE COMPLETE! (Sorta... all elements are available) +All of the major features are DONE. They may not have all of their options working, but they can be added to your windows. It's been an amazing week to get here. + +I hope you enjoy this ALPHA release! Please post a screenshot on the GitHub site. There is an Issue where users have been posting their applications. It's a place for you to show-off and a place for others to learn from your designs. Your window does not have to be complex.... all GUIs, no matter how simple, are something we can learn from. + + +### Functioning features +Features are being added daily to this Qt port of PySimpleGUI. +These Elements are "complete" (a relative term... more are more complete than others): +* Text +* Input single line +* Input multiline +* Output multiline (new) +* Dial (new) +* Output - reroute stdout +* Spinner +* Sliders +* Buttons - RButtons, CButtons, Short-cut Buttons +* Checkbox +* Radio Buttons +* Listbox +* ComboBox +* Labeled Frames +* Columns - enables you to make pretty much any layout! +* Alpha channel for windows +* No Title Bar setting +* Enter submits for multiline +* Fonts +* Colors for text and background +* Timeouts for Read calls +* Change Submits parameters for most Elements +* Table + * Basic display + * Read selected rows + * change_submits events + * Updates +* Image as a background (new feature) +* Graph - Draw line, draw circle, draw text +* Image Element +* Tree Element +* Tabs +* Menus +* Menu Button Element + + + +## Missing Features + +Notable MISSING features at the moment include: +* Graphs Element Methods - erasing, draw arc, etc +* Tree element - returns rows selected, but a little difficult to map those values to something meaningful for the user. + +# New PySimpleGUI Features only in Qt (or first introduced in Qt) + +There are a number of new features that are only available in PySimpleGUIQt. These include: +* ButtonMenu Element +* Dial Element +* Stretcher Element (used to "push elements around" within a widnow) +* SystemTray feature +* "Dynamic" windows that grow and shrink (uses invisible elements) + +## SystemTray + +This is a PySimpleGUIQt only feature. Don't know of a way to do it using tkinter. It looks likely to work on WxPython however. + +In addition to running normal windows, it's now also possible to have an icon down in the system tray that you can read to get menu events. There is a new SystemTray object that is used much like a Window object. You first get one, then you perform Reads in order to get events. + +Here is the definition of the SystemTray object. + +```python +SystemTray(menu=None, filename=None, data=None, data_base64=None, tooltip=None): + ''' + SystemTray - create an icon in the system tray + :param menu: Menu definition + :param filename: filename for icon + :param data: in-ram image for icon + :param data_base64: basee-64 data for icon + :param tooltip: tooltip string ''' +``` + +You'll notice that there are 3 different ways to specify the icon image. The base-64 parameter allows you to define a variable in your .py code that is the encoded image so that you do not need any additional files. Very handy feature. + +## System Tray Design Pattern + +Here is a design pattern you can use to get a jump-start. + +This program will create a system tray icon and perform a blocking Read. If the item "Open" is chosen from the system tray, then a popup is shown. + +```python +import PySimpleGUIQt as sg + +menu_def = ['BLANK', ['&Open', '---', '&Save', ['1', '2', ['a', 'b']], '&Properties', 'E&xit']] + +tray = sg.SystemTray(menu=menu_def, filename=r'default_icon.ico') + +while True: # The event loop + menu_item = tray.Read() + print(menu_item) + if menu_item == 'Exit': + break + elif menu_item == 'Open': + sg.Popup('Menu item chosen', menu_item) + +``` +The design pattern creates an icon that will display this menu: +![snag-0293](https://user-images.githubusercontent.com/13696193/49057441-8bbfe980-f1cd-11e8-93e7-1aeda9ccd173.jpg) + +### Icons + +When specifying "icons", you can use 3 different formats. +* `filename`- filename +* `data_base64` - base64 byte string +* '`data` - in-ram bitmap or other "raw" image + +You will find 3 parameters used to specify these 3 options on both the initialize statement and on the Update method. + +## Menu Definition +```python +menu_def = ['BLANK', ['&Open', '&Save', ['1', '2', ['a', 'b']], '!&Properties', 'E&xit']] +``` + +A menu is defined using a list. A "Menu entry" is a string that specifies: +* text shown +* keyboard shortcut +* key + +See section on Menu Keys for more information on using keys with menus. + +An entry without a key and keyboard shortcut is a simple string +`'Menu Item'` + +If you want to make the "M" be a keyboard shortcut, place an `&` in front of the letter that is the shortcut. +`'&Menu Item'` + +You can add "keys" to make menu items unique or as another way of identifying a menu item than the text shown. The key is added to the text portion by placing `::` after the text. + +`'Menu Item::key'` + +The first entry can be ignored.`'BLANK`' was chosen for this example. It's this way because normally you would specify these menus under some heading on a menu-bar. But here there is no heading so it's filled in with any value you want. + +**Separators** +If you want a separator between 2 items, add the entry `'---'` and it will add a separator item at that place in your menu. + +**Disabled menu entries** + +If you want to disable a menu entry, place a `!` before the menu entry + + +## Stretch Element for Justifying Elements + +Use the `Stretch` Element to left justify, right justify or center justify one or more elements within their container. + +If a single `Stretch` Element is on a row, then it will push the other elements on the row to either the left or right. If `Stretch` is on the left, then the elements to the rigth will be pushed to the right. + +To center elements, place a `Stretch` Element on each side of them (2 `Stretch` Elements will be on the same row) + +## SystemTray Methods + +### Read - Read the context menu or check for events + +```python +def Read(timeout=None) + ''' + Reads the context menu + :param timeout: Optional. Any value other than None indicates a non-blocking read + :return: String representing meny item chosen. None if nothing read. + ''' +``` +The `timeout` parameter specifies how long to wait for an event to take place. If nothing happens within the timeout period, then a "timeout event" is returned. These types of reads make it possible to run asynchronously. To run non-blocked, specify `timeout=0`on the Read call. + +Read returns the menu text, complete with key, for the menu item chosen. If you specified `Open::key` as the menu entry, and the user clicked on `Open`, then you will receive the string `Open::key` upon completion of the Read. + +#### Read special return values + +In addition to Menu Items, the Read call can return several special values. They include: + +EVENT_SYSTEM_TRAY_ICON_DOUBLE_CLICKED - Tray icon was double clicked +EVENT_SYSTEM_TRAY_ICON_ACTIVATED - Tray icon was single clicked +EVENT_SYSTEM_TRAY_MESSAGE_CLICKED - a message balloon was clicked +TIMEOUT_KEY is returned if no events are available if the timeout value is set in the Read call + + +### Hide + +Hides the icon. Note that no message balloons are shown while an icon is hidden. + +```python +def Hide() +``` + +### Close + +Does the same thing as hide +```python +def Close() +``` + + +### UnHide + +Shows a previously hidden icon + +```python +def UnHide() +``` + +### ShowMessage + +Shows a balloon above the icon in the system tray area. You can specify your own icon to be shown in the balloon, or you can set `messageicon` to one of the preset values. + +This message has a custom icon. + +![snag-0286](https://user-images.githubusercontent.com/13696193/49057459-a85c2180-f1cd-11e8-9a66-aa331d7e034c.jpg) + +The preset `messageicon` values are: + + SYSTEM_TRAY_MESSAGE_ICON_INFORMATION + SYSTEM_TRAY_MESSAGE_ICON_WARNING + SYSTEM_TRAY_MESSAGE_ICON_CRITICAL + SYSTEM_TRAY_MESSAGE_ICON_NOICON + +```python +ShowMessage(title, message, filename=None, data=None, data_base64=None, messageicon=None, time=10000): + ''' + Shows a balloon above icon in system tray + :param title: Title shown in balloon + :param message: Message to be displayed + :param filename: Optional icon filename + :param data: Optional in-ram icon + :param data_base64: Optional base64 icon + :param time: How long to display message in milliseconds :return: + ''' +``` +Note, on windows it may be necessary to make a registry change to enable message balloons to be seen. To fix this, you must create the DWORD you see in this screenshot. + +![snag-0285](https://user-images.githubusercontent.com/13696193/49056144-6381bc00-f1c8-11e8-9f44-199394823369.jpg) + + +### Update + +You can update any of these items within a SystemTray object +* Menu definition +* Icon +* Tooltip + + Change them all or just 1. + +```python +Update(menu=None, tooltip=None,filename=None, data=None, data_base64=None,) + ''' + Updates the menu, tooltip or icon + :param menu: menu defintion + :param tooltip: string representing tooltip + :param filename: icon filename + :param data: icon raw image + :param data_base64: icon base 64 image + :return: + ''' +``` +## Menus with Keys + +PySimpleGUIQt offers the ability to add a key to your menu items. To do so, you add :: and the key value to the end of your menu definition. + +`menu_def = ['File', ['Hide::key', '&Open::key', '&Save',['1', '2', ['a','b']], '&Properties', 'E&xit']]` + +The menu definition adds a key "key" to the menu entries Hide and Open. + +If you want to change the separator characters from :: top something else,change the variable `MENU_KEY_SEPARATOR` + +When a menu item has a key and it is chosen, then entire string is returned. If Hide were selected, then Hide::key would be returned from the Read. Note that the shortcut character & is NOT returned from Reads. + + +## Dynamic Windows (Element Visibility) + +Finally, the ability to grow and shrink has been added as of release 0.20.0 + +While the window **appears** to be dynamic, the reality is that the elements are created up front, when you define the window layout. You will create these "extra" elements with the flag `visible=False`. Then, when you wish to show those elements, call the element's `Update` method setting `visible=True`. + +After you call the `Update` method, it's important to call `window.VisibilityChanged()` so that your window can change sizes. Without that call your window will not shrink. It will grow properly, but it will not shrink. While this could have been done by PySimpleGUI on the user's behalf, the thought was that perhaps the user wants the window size to remain the same and the element simply appears and disappears, leaving a blank spot. If the window automatically grew and shrank, this would not be possible. Just buck-up and make the call to `VisibilityChanged`. + +## `enable_events` Parameter + +All elements that are capable of producing events now have a parameter `enable_events`. This is *identical* to the old parameter `change_submits` or `click_submits`. The idea is to standardize on 1 name that all elements use. The old parameters will continue to work, but the documentation and sample programs will steer you away from them and towards enable_events. + +# Release Notes: + +### 0.12.0 - 20-Nov-2018 +Correctly restore stdout when Output Element is deleted +Added Finalize ability +**Better multi-window handling... maybe it's finally fixed!** +Radio button default value +Dial element default value +Show expanded option for trees +Titles for popups + +### 0.13.0 - 22-Nov-2018 + +Focus for Input Text and Multiline Input + + - Get focus + - Set focus +Window.FindElementWithFocus works +Multiline input + + - Change submits + - Update - disabled, append + +Multiline output - Update value, append, disabled, get value +Text clicked submits +File types for open files +Initial folder, file types, for browse buttons +File types standardized on tkinter data format +Find Element With Focus now works for input and multiline input +Yet more multiwindow handling +Relief for Text element +Input text disable +Correct sizing of Comboboxes using visible items parm +Correct default values for input and multiline input +Change submits for multiline +Horizontal and Vertical separators +PopupGetFile and PopupGetFolder - no_window option works + +### 0.14.0 - 24-Nov-2018 + +Slider tick positions set using relief parm +ButtonMenu Element +Multiline.Update font parm +Text.Update color and font now work +Button.Update font support +Window.Element = Window.FindElement +Better font support for all elements - underline, bold +Element padding - complete rework +Text element padding +Button padding +Input Text padding +Input Text password char +Listbox padding +Combobox padding +Multiline padding +Checkbox padding +Radio padding +Progress Bar padding +Output padding +Image padding +Graph padding +Slider - set tick marks using relief parm +Dial - set tick information using resolution and tick interval +Table padding +Tree padding +Separator padding +Force window sizing should mean windows are better sized +Popup - better layout + + +### 0.15.0 24-Nov-2018 + +New SystemTray feature! +margin paramter for Text Element. Takes 4 ints +Corrected button colors when disabled. For now am restoring them to original colors +Border Depth for all elements that support it (inputs, slider, table, tree, etc) +Fix for Element padding done incorrectly!! Sorry about this one + + +### 0.16.0 24-Nov-2018 + +Easier forcing to use PyQt5 for testing +Predefined events for Tray Icons +* Double Clicked +* Icon Activated +* Message Clicked +* Timeout key for polling + +Tray icon tooltip +Menu keys with programmable separator +Better element padding hierarchy +Menubar now returns values as does the ButtonMenu + +### 0.17.0 24-Nov-2018 + +Window.Hide and UnHide methods + +### 0.18.0 26-Nov-2018 + +Tooltips for all elements +Completion of all SystemTray features +Read with or without timeout +Specify icons from 3 sources +Show message with custom or preset icons +Update +* Menu +* Tooltip +* Icon +PopupScrolled - new location parameter, fixed bug that wasn't closing window when completed + +### 0.19.0 28-Nov-2018 + +Ability to disable menu items by adding ! to the front +Disable menu works for menus, button menus, system tray menus +Combo - Update Method - Value, values, disabled, font +Listbox - Update Method - Values, disabled +Listbox - SetValue Method - sets the selected items +Radio Button - Update Method - value, disabled +Checkbox - Update Method - value, disabled +Spinner - Update Method - value, values, disabled +Spinner - change_submits works +Image - New feature! click_submits option (acts like a button in a way) +Window - Get screen dimensions +Slider - disable +Dial - disable + +### 0.20.0 6-Dec-2018 + +* Ability to change calculations between characters and pixels +* size_px added to ALL elements that have a size parameter +* General Element.Update(widget, background_color, text_color, font, visible) +* visible parameter added to ALL elements +* enable_events flag +* Input text - enable events, visibility, size_px +* Input text update added capabilities + * ability to highlight the input string + * background, text colors and font +* Combo - enable events, visibility, size_px +* Combo - auto complete feature +* Combo - added to Update - background color, text color, font, visible +* Listbox - enable events, visibility, size_px +* Listbox - better scaling from characters to pixels +* Listbox - ability to Update with set to index, text color, font, visibility +* Radio - enable events, visibility, size_px +* Radio - Update additions - background_color, text_color, font, visibility +* Checkbox - enable events, visibility, size_px +* Checkbox - Update additions - background_color, text_color, font, visibility +* Spin - enable events, visibility, size_px +* Spin - Update additions - background_color, text_color, font, visibility +* Multiline input - enable events, visibility, size_px +* Multiline input - Update additions - background_color, text_color, font, visibility +* Multiline input better character to pixel scaling +* Multiline output - enable events, visibility, size_px +* Multiline output - Update additions - background_color, text_color, visibility +* Text - enable events, size in pixels +* Text - Update addition of visibility +* Output - visible, size_px +* Output - added update capability with new value, background_color, text_color, font, visibility +* Button - enable events, visible, size_px +* Button - Color Chooser feature completed +* Button - Color Chooser can target (None, None) which will store the value to be returned with the values from Read() +* Button - fixed bug in SaveAs button code. Bad filter variable +* Button - Updated added font, visibility +* Button - new SetFocus() method will set the focus onto the button +* ButtonMenu - Update method implemented that includes menu definition changes, text, button color, font, visibility +* ProgressBar - added visibility, size_px +* ProgressBar - added Update method for changing the visibility +* Images - events, size_pix, visibility +* Images - can now get click events for images! +* Images - Update added visibility +* Graph - visibility, size_px +* Graph - Update method for changing visibility +* Frame - visibility, size_px +* Frame - Update method added that controls visibility +* ALL elements inside of a Frame that's invisible will also be invisible +* Tab - visible parameter added, however not yet functional! +* TabGroup - enable events, visibility +* TabGroup - Update for controlling visibility +* Slider - enable events, size_px +* Slider - Update method now includes visibility +* Dial - enable events, size_px, visibility +* Dial - Update method added visibilty control +* Column - visibility added +* Column - Added Update method to control visibility +* ALL elements inside of an invisible Column Element will also be invisible +* MenuBar - added visibility +* MenuBar - Update can now change menu definitions at runtime, and control visibility +* Table - enable events, size_px, visibility +* Table - Update method can control visibility +* Tree - enable events, size_px, visibility +* Tree - Update method can control visibility +* VisibilityChanged() function that must be called when using Qt so that the window will shrink or grow +* window.GetScreenDimensions can now be called prior to window creation +* window.Size property +* enable_events added to all of the shortcut buttons and browse buttons +* Ability to set a button image from a file +* Combo - ability to set a default value +* Combo - Read only setting. Allows for user editing of value +* Menus - Ability to disable / enable any part of a menu by adding a ! before the entry name +* Tabs - ability to set tab text color, background color, background color of selected tab +* Tabs - ability to set widget area's background color +* Sliders - paging works properly (using page-up page-down or slider slider area to advance slider) +* Tree - Setting number of visible rows implemented +* Added 5 pixels to every window. Have been having issues with text being cutoff on the right side +* SetOptions - ability to change default error button color for popups + +### 0.21.0 - 9-Dec-2018 + +* Removed use of global variabels - using static class variabels instead +* Listbox.Get() will return current listbox value +* Progressbar now has color support +* Progressbar can be vertical now +* Can change bar or back and background color +* (barcolor, background color - None if use default) +* Table num_rows parameter implemented +* Table.Update - can change number of visible rows +* Window resizable parm - implemented, default changed from False to True +* Window.Move - implemented +* Window.Minimize - implemented +* Window.Disable - implemented +* Window.Enable - implemented +* Window.CurrentLocation - implemented +* Fixed too small scrollbar in Combobox +* Fixed too small scrollbar in Listbox +* Changed "text" window to a complex one for quick regression testing (try running PySimpleGUIQt.py by itself) + +### 0.22.0 - 9-Dec-2018 + +* Spin.Get method - get the current spinner value + +### 0.23.0 PySimpleGUIQt + +* Fixed crash that was happening with latest pyside2 release!!!! +* Huge update to OneLineProgressMeter +* Debug window got title and do-not-reroute-std-out option +* Popups get a title option +* PopupScrolled getr non-blocking option +* Default logo included in Base64 Format +* Changed Chars to pixels scaling. Went from (10,25) to (10,35) +* Changed pixel to chars cutoff from 10 to 12 +* Change progress bar default size to 200 from 250 +* Reworked the _my_windows global variable / class to use Window class variables +* Change in how Elements / Widgets are updated. Need to use {} correctly +* InputText supports drag and drop +* Support for Checkbox.Get() +* Support for strings in spinbox +* Added Update method to Output element +* Changed Button default file_types from *.* to * +* Support for Tab enable_events so they now generate events +* Table.Update can change the number of rows of table +* Window class now manages the list of active popups, user defined icon, QTApplication, num open windows +* Window resizable parameter default changed from False to True +* Window new parameter - disable_minimize +* Window.GetScreenDimensions added +* Window.Move added +* Window.Minimize added +* Window.Maximize added +* Window.Disable added +* Window.Enable added +* Window.BringToFront added +* Window.CurrentLocation added +* TabGroup now returns which tab is selected in the return values +* Completely new Style generation class and functions (I hope it works!!!!) +* Style reworked for Column, Text, Button, Input, Combobox, Listbox, Input Multiline, Output Multiline, Progress Bar, Spinbox, Output, +* Progress Bar colors are now correct +* Events generated when tabs are changed +* "Better" Table support. Uses num_rows now and styles the scrollbar +* Tree element can support multiple types of icons including base64 +* Fixed tree element scroll bar +* Icon ccan be set using SetOptions +* main for PySimpleGUIQt.py gets a nice test harness that shows lots of Elements + + +## 0.24.0 PySimpleGUIQt + +* do_not_clear defaults to TRUE! for Input and MultilineInput/Output +* Key events for tables (unsure what's actually implemented) +* Tree icons can now be bytes in addition to filename! (More Base64 support) + + +## 0.25.0 PySimpleGUIQt 5-Apr-2019 + +* Uses built-in Default Base64 Logo! (no more .ico file needed) +* New shortcuts for Elements + * I = InputText + * B = Butt = Btn = Button +* Convert user supplied button text to string just in case not a string +* Parameter `icon` in `Window` call can be Base64 byte string in addition to filename + + +## 0.26.0 11-Apr-2019 PySimpleGUIQt + +* NEW Window parameter layout so can skip calling Layout + +## 0.28.0 PySimpleGUIQt 5-Sep-2019 + +It's been a LONG LONG LONG time coming + +* PEP8-ified! All methods and functions have PEP8 equivalents!! It's a BFD +* Version numbers in the code +* New key dictionary - Window.AllKeysDict has all of the windows keys in 1 place for FASTER lookups +* Element.Widget provides access to low level Qt Widget +* Multiline scaling in addition to single line +* Raised default pixel cutoff for single line scaling to 15 from 12 +* Pixel conversion done in Elements and passed through to Element class as size_px +* Renamed lots of private functions and methods to begin with _ +* "Callable" Elements - element(new_value) will cause element.update(new_value) to be called +* Removed all __del__ except for the Output Element one +* Button - Click method added. Your program can click a button as if a user did +* ButtonbMenu - Click mehtod also added like in Button element +* Graph Element + * Added DrawRectangle method + * Added RelocateFigure method + * Added return of ID to DrawLine, DrawCircle, DrawText + * Added Erase method to erase entire graph +* Tab - added Select method so can select a Tab as if user clicked it +* TabGroup - added Get method. Returns key of currently selected Tab, or text of Tab if no key set +* Table - Get method returns the table - GREAT way to enable users to edit a table and get the results +* SystemTray - uses default base64 icon if no icon supplied when creating +* Window - new finalize parameter removes need to add chained call to finalize +* Window.FindElement - added silent_on_error parameter +* Window[key] is the same as Window.FindElement(key) +* Calling a Window object calls Read for that window +* Fix for filetypes. Bug caused (*) to be added onto filetypes when browsing for files +* Combo returns exact value that was provided using an index into Values list instead of string from Qt +* Listbox returns actual supplied items +* Spinner returns avtual supplied item +* Tabgroup returns Tab key +* Finding element with focus now returns element regardless of type (any type of element can be returned) +* Radio Buttons now return events if enabled +* Graph element background colors added, uses new style class +* Table headings supported (where not supported before??) +* Popups switched to using new layout parm in Window call and uses keys too + + +## 0.30.0 PySimpleGUIQt 16-Nov-2019 + +* THEMES!! Over 100 new Look and Feel themes to choose from! +* New func preview_all_look_and_feel_themes() that will display a large window with all possible themes shown +* Metadata! Now available on all elements when creating and accessable directly by program +* Metadata added to SystemTray objects and Window objects +* Metadata parameter added to all shortcut buttons and funcs +* Completed removal of PyQt5 code +* ML, MLine shortcuts added for Multiline (input) +* MLineOut shortcut for MultilineOutput +* Text element text is optional now +* Fixed bug in BrowseFiles button. Was only getting first item in list instead of full list of filenames +* BMenu shortcut for ButtonMenu +* PBar, Prog shortcuts for ProgressBar +* Range is now properly set in Slider.Update +* Background color supported for MenuBars now +* Added 5 extra pixels to window size. Now adding a total of 10 so things don't get cut off + + +## 0.31.0 PySimpleGUIQt 23-Dec-2019 + +Themes and more! + +* Added port string so can identify which port is being used (PySimpleGUIQt) +* Removed the Mac speific button and system color settings. Not sure why they existed at all since it's Qt, not tkinter +* Like all PySimpleGUI ports, the default theme is now "DarkBlue3" +* TRANSPARENT_BUTTON redefined as an a string explaining that if you're using it, you're not getting what you thought you were +* BROWSE_FILES_DELIMETER so that it can be changed to something other than ';' for systems that ';' is a valid char for filenames +* Can drag and drop into a Multiline Input Element! +* Colored text output for Multiline (hmmm...but not MultilineOutput.. may have to add it) +* Tree Element + * Support for enable_events + * Returns selected rows when reading +* Window - better error checking and warnings for window layouts +* Button - changes to help with getting animations back +* TabGroup - Tab positions now supporrted + * left, right, top, bottom, lefttop, leftbottom, righttop, rightbottom, bottomleft, bottomright, topleft, topright +* Tables & Trees - text color and background color now work. Don't appear to have worked before + + +## 0.32.0 PySimpleGUIQt 4-Apr-2020 + +The "Jeez... it's been way too LONG since a release" release + +Highlights - Read with close (Single line GUIs!), Print to Multiline, Scrollable columns + +* Listbox.update fix +* Added Graph.change_coordinates +* Added Image.Widget +* Return correct value when Comboxbox has manual data entered +* Multiline.print - new printing capabilities +* Multiline move cursor to end +* Scrollable columns +* Added Listbox.get +* Fix for visible ignored in Text Element +* Window.read - close parameter (YES! Single line GUIs again) +* Multiline readonly parm on update +* Print fixed sep char to act line normal print +* Print (Multiline) added autoscroll parm + + +## 0.33.0 PySimpleGUIQt 6-May-2020 + + +* Added expansion capabilities + * Element.row_frame - The QHBoxLayout the element is contained within + * Column.vbox_layout - The QVBoxLayout contained in Column element + +## 0.34.0 PySimpleGUIQt 10-May-2020 + +This time for REAL added the constants. I don't know how to changes got lost but they did. + +* Added constants + * WIN_CLOSED and WINDOW_CLOSED + * EVENT_TIMEOUT and TIMEOUT_EVENT + + +## 0.35.0 PySimpleGUIQt 6-Jun-2020 + +Element justification within Window and Containers! Finally a unified justification + +* When any Radio element is updated to be False, the entire GROUP is reset so nothing is selected +* Fixed Multiline.get so that it correctly returns the value, was always returning None +* Fixed MultilineOutput.get so that it correctly returns the value, was always returning None +* Notes say I fixed a Frame Element background color bug but I don't see where / how +* element_jutification added so that all elements inside these will be justified accordingly. + * For PySimpleGUIQt only, the default is "float" which sets nothing. Buttons will stretch across the window as result + * Valid values are 'l', 'r', 'c'. You can spell it out, but only first letter is used. + * Window + * Frame + * Column + * Tab +* Table Element addition + * Header background color + * Header text color + * Header Font (not yet hooked up) + + +# Design + +## Author + +The PySimpleGUI Organization +PySimpleGUI.org + +# Demo Code Contributors + +# License + +GNU Lesser General Public License (LGPL 3) + + +Copytight 2018, 2019, 2020 PySimpleGUI + +# Acknowledgments \ No newline at end of file diff --git a/PySimpleGUIWeb/Demo Programs/Demo_Graph_pymunk_2D_Graphics.py b/PySimpleGUIWeb/Demo Programs/Demo_Graph_pymunk_2D_Graphics.py new file mode 100644 index 000000000..65d8faed7 --- /dev/null +++ b/PySimpleGUIWeb/Demo Programs/Demo_Graph_pymunk_2D_Graphics.py @@ -0,0 +1,81 @@ +import PySimpleGUIWeb as sg +import pymunk +import random +import socket + +""" + Demo that shows integrating PySimpleGUI with the pymunk library. This combination + of PySimpleGUI and pymunk could be used to build games. + Note this exact same demo runs with PySimpleGUIWeb by changing the import statement +""" + + +class Ball(): + def __init__(self, x, y, r, *args, **kwargs): + mass = 10 + self.body = pymunk.Body(mass, + pymunk.moment_for_circle(mass, 0, r, (0, 0))) # Create a Body with mass and moment + self.body.position = x, y + # Create a box shape and attach to body + self.shape = pymunk.Circle(self.body, r, offset=(0, 0)) + self.shape.elasticity = 0.99999 + self.shape.friction = 0.8 + self.gui_circle_figure = None + + +class Playfield(): + def __init__(self): + self.space = pymunk.Space() + self.space.gravity = 0, 200 + self.add_wall(self.space, (0, 400), (600, 400)) # ground + self.add_wall(self.space, (0, 0), (0, 600)) # Left side + self.add_wall(self.space, (600, 0), (600, 400)) # right side + + def add_wall(self, space, pt_from, pt_to): + body = pymunk.Body(body_type=pymunk.Body.STATIC) + ground_shape = pymunk.Segment(body, pt_from, pt_to, 0.0) + ground_shape.friction = 0.8 + ground_shape.elasticity = .99 + self.space.add(ground_shape) + + def add_balls(self): + self.arena_balls = [] + for i in range(1, 200): + x = random.randint(0, 600) + y = random.randint(0, 400) + r = random.randint(1, 10) + ball = Ball(x, y, r) + self.arena_balls.append(ball) + area.space.add(ball.body, ball.shape) + ball.gui_circle_figure = graph_elem.draw_circle( + (x, y), r, fill_color='black', line_color='red') + + +# ------------------- Build and show the GUI Window ------------------- +graph_elem = sg.Graph((600, 400), (0, 400), (600, 0), + enable_events=True, key='_GRAPH_', background_color='lightblue') + +layout = [[sg.Text('Ball Test'), sg.Text('My IP {}'.format(socket.gethostbyname(socket.gethostname())))], + [graph_elem], + [sg.Button('Kick'), sg.Button('Exit')]] + +window = sg.Window('Window Title', layout, finalize=True) +area = Playfield() +area.add_balls() + +# ------------------- GUI Event Loop ------------------- +while True: # Event Loop + event, values = window.read(timeout=0) + # print(event, values) + if event in (None, 'Exit'): + break + area.space.step(0.02) + + for ball in area.arena_balls: + if event == 'Kick': + ball.body.position = ball.body.position[0], ball.body.position[1]-random.randint( + 1, 200) + graph_elem.relocate_figure( + ball.gui_circle_figure, ball.body.position[0], ball.body.position[1]) + +window.close() diff --git a/PySimpleGUIWeb/Demo Programs/Web_Color_Names.py b/PySimpleGUIWeb/Demo Programs/Web_Color_Names.py new file mode 100644 index 000000000..7bdb82d39 --- /dev/null +++ b/PySimpleGUIWeb/Demo Programs/Web_Color_Names.py @@ -0,0 +1,710 @@ +#!/usr/bin/env python +import PySimpleGUIWeb as sg + +""" + + Shows a big chart of colors... + Once large window is shown, you can click on any color and another window will popup + showing both white and black text on that color + Uses TOOLTIPS to show the hex values for the colors. Hover over a color and a tooltip will show you the RGB + You will find the list of tkinter colors here: + http://www.tcl.tk/man/tcl8.5/TkCmd/colors.htm + Really shows off the PySimpleGUIWeb capabilities +""" + +color_map = { + 'alice blue': '#F0F8FF', + 'AliceBlue': '#F0F8FF', + 'antique white': '#FAEBD7', + 'AntiqueWhite': '#FAEBD7', + 'AntiqueWhite1': '#FFEFDB', + 'AntiqueWhite2': '#EEDFCC', + 'AntiqueWhite3': '#CDC0B0', + 'AntiqueWhite4': '#8B8378', + 'aquamarine': '#7FFFD4', + 'aquamarine1': '#7FFFD4', + 'aquamarine2': '#76EEC6', + 'aquamarine3': '#66CDAA', + 'aquamarine4': '#458B74', + 'azure': '#F0FFFF', + 'azure1': '#F0FFFF', + 'azure2': '#E0EEEE', + 'azure3': '#C1CDCD', + 'azure4': '#838B8B', + 'beige': '#F5F5DC', + 'bisque': '#FFE4C4', + 'bisque1': '#FFE4C4', + 'bisque2': '#EED5B7', + 'bisque3': '#CDB79E', + 'bisque4': '#8B7D6B', + 'black': '#000000', + 'blanched almond': '#FFEBCD', + 'BlanchedAlmond': '#FFEBCD', + 'blue': '#0000FF', + 'blue violet': '#8A2BE2', + 'blue1': '#0000FF', + 'blue2': '#0000EE', + 'blue3': '#0000CD', + 'blue4': '#00008B', + 'BlueViolet': '#8A2BE2', + 'brown': '#A52A2A', + 'brown1': '#FF4040', + 'brown2': '#EE3B3B', + 'brown3': '#CD3333', + 'brown4': '#8B2323', + 'burlywood': '#DEB887', + 'burlywood1': '#FFD39B', + 'burlywood2': '#EEC591', + 'burlywood3': '#CDAA7D', + 'burlywood4': '#8B7355', + 'cadet blue': '#5F9EA0', + 'CadetBlue': '#5F9EA0', + 'CadetBlue1': '#98F5FF', + 'CadetBlue2': '#8EE5EE', + 'CadetBlue3': '#7AC5CD', + 'CadetBlue4': '#53868B', + 'chartreuse': '#7FFF00', + 'chartreuse1': '#7FFF00', + 'chartreuse2': '#76EE00', + 'chartreuse3': '#66CD00', + 'chartreuse4': '#458B00', + 'chocolate': '#D2691E', + 'chocolate1': '#FF7F24', + 'chocolate2': '#EE7621', + 'chocolate3': '#CD661D', + 'chocolate4': '#8B4513', + 'coral': '#FF7F50', + 'coral1': '#FF7256', + 'coral2': '#EE6A50', + 'coral3': '#CD5B45', + 'coral4': '#8B3E2F', + 'cornflower blue': '#6495ED', + 'CornflowerBlue': '#6495ED', + 'cornsilk': '#FFF8DC', + 'cornsilk1': '#FFF8DC', + 'cornsilk2': '#EEE8CD', + 'cornsilk3': '#CDC8B1', + 'cornsilk4': '#8B8878', + 'cyan': '#00FFFF', + 'cyan1': '#00FFFF', + 'cyan2': '#00EEEE', + 'cyan3': '#00CDCD', + 'cyan4': '#008B8B', + 'dark blue': '#00008B', + 'dark cyan': '#008B8B', + 'dark goldenrod': '#B8860B', + 'dark gray': '#A9A9A9', + 'dark green': '#006400', + 'dark grey': '#A9A9A9', + 'dark khaki': '#BDB76B', + 'dark magenta': '#8B008B', + 'dark olive green': '#556B2F', + 'dark orange': '#FF8C00', + 'dark orchid': '#9932CC', + 'dark red': '#8B0000', + 'dark salmon': '#E9967A', + 'dark sea green': '#8FBC8F', + 'dark slate blue': '#483D8B', + 'dark slate gray': '#2F4F4F', + 'dark slate grey': '#2F4F4F', + 'dark turquoise': '#00CED1', + 'dark violet': '#9400D3', + 'DarkBlue': '#00008B', + 'DarkCyan': '#008B8B', + 'DarkGoldenrod': '#B8860B', + 'DarkGoldenrod1': '#FFB90F', + 'DarkGoldenrod2': '#EEAD0E', + 'DarkGoldenrod3': '#CD950C', + 'DarkGoldenrod4': '#8B6508', + 'DarkGray': '#A9A9A9', + 'DarkGreen': '#006400', + 'DarkGrey': '#A9A9A9', + 'DarkKhaki': '#BDB76B', + 'DarkMagenta': '#8B008B', + 'DarkOliveGreen': '#556B2F', + 'DarkOliveGreen1': '#CAFF70', + 'DarkOliveGreen2': '#BCEE68', + 'DarkOliveGreen3': '#A2CD5A', + 'DarkOliveGreen4': '#6E8B3D', + 'DarkOrange': '#FF8C00', + 'DarkOrange1': '#FF7F00', + 'DarkOrange2': '#EE7600', + 'DarkOrange3': '#CD6600', + 'DarkOrange4': '#8B4500', + 'DarkOrchid': '#9932CC', + 'DarkOrchid1': '#BF3EFF', + 'DarkOrchid2': '#B23AEE', + 'DarkOrchid3': '#9A32CD', + 'DarkOrchid4': '#68228B', + 'DarkRed': '#8B0000', + 'DarkSalmon': '#E9967A', + 'DarkSeaGreen': '#8FBC8F', + 'DarkSeaGreen1': '#C1FFC1', + 'DarkSeaGreen2': '#B4EEB4', + 'DarkSeaGreen3': '#9BCD9B', + 'DarkSeaGreen4': '#698B69', + 'DarkSlateBlue': '#483D8B', + 'DarkSlateGray': '#2F4F4F', + 'DarkSlateGray1': '#97FFFF', + 'DarkSlateGray2': '#8DEEEE', + 'DarkSlateGray3': '#79CDCD', + 'DarkSlateGray4': '#528B8B', + 'DarkSlateGrey': '#2F4F4F', + 'DarkTurquoise': '#00CED1', + 'DarkViolet': '#9400D3', + 'deep pink': '#FF1493', + 'deep sky blue': '#00BFFF', + 'DeepPink': '#FF1493', + 'DeepPink1': '#FF1493', + 'DeepPink2': '#EE1289', + 'DeepPink3': '#CD1076', + 'DeepPink4': '#8B0A50', + 'DeepSkyBlue': '#00BFFF', + 'DeepSkyBlue1': '#00BFFF', + 'DeepSkyBlue2': '#00B2EE', + 'DeepSkyBlue3': '#009ACD', + 'DeepSkyBlue4': '#00688B', + 'dim gray': '#696969', + 'dim grey': '#696969', + 'DimGray': '#696969', + 'DimGrey': '#696969', + 'dodger blue': '#1E90FF', + 'DodgerBlue': '#1E90FF', + 'DodgerBlue1': '#1E90FF', + 'DodgerBlue2': '#1C86EE', + 'DodgerBlue3': '#1874CD', + 'DodgerBlue4': '#104E8B', + 'firebrick': '#B22222', + 'firebrick1': '#FF3030', + 'firebrick2': '#EE2C2C', + 'firebrick3': '#CD2626', + 'firebrick4': '#8B1A1A', + 'floral white': '#FFFAF0', + 'FloralWhite': '#FFFAF0', + 'forest green': '#228B22', + 'ForestGreen': '#228B22', + 'gainsboro': '#DCDCDC', + 'ghost white': '#F8F8FF', + 'GhostWhite': '#F8F8FF', + 'gold': '#FFD700', + 'gold1': '#FFD700', + 'gold2': '#EEC900', + 'gold3': '#CDAD00', + 'gold4': '#8B7500', + 'goldenrod': '#DAA520', + 'goldenrod1': '#FFC125', + 'goldenrod2': '#EEB422', + 'goldenrod3': '#CD9B1D', + 'goldenrod4': '#8B6914', + 'green': '#00FF00', + 'green yellow': '#ADFF2F', + 'green1': '#00FF00', + 'green2': '#00EE00', + 'green3': '#00CD00', + 'green4': '#008B00', + 'GreenYellow': '#ADFF2F', + 'grey': '#BEBEBE', + 'grey0': '#000000', + 'grey1': '#030303', + 'grey2': '#050505', + 'grey3': '#080808', + 'grey4': '#0A0A0A', + 'grey5': '#0D0D0D', + 'grey6': '#0F0F0F', + 'grey7': '#121212', + 'grey8': '#141414', + 'grey9': '#171717', + 'grey10': '#1A1A1A', + 'grey11': '#1C1C1C', + 'grey12': '#1F1F1F', + 'grey13': '#212121', + 'grey14': '#242424', + 'grey15': '#262626', + 'grey16': '#292929', + 'grey17': '#2B2B2B', + 'grey18': '#2E2E2E', + 'grey19': '#303030', + 'grey20': '#333333', + 'grey21': '#363636', + 'grey22': '#383838', + 'grey23': '#3B3B3B', + 'grey24': '#3D3D3D', + 'grey25': '#404040', + 'grey26': '#424242', + 'grey27': '#454545', + 'grey28': '#474747', + 'grey29': '#4A4A4A', + 'grey30': '#4D4D4D', + 'grey31': '#4F4F4F', + 'grey32': '#525252', + 'grey33': '#545454', + 'grey34': '#575757', + 'grey35': '#595959', + 'grey36': '#5C5C5C', + 'grey37': '#5E5E5E', + 'grey38': '#616161', + 'grey39': '#636363', + 'grey40': '#666666', + 'grey41': '#696969', + 'grey42': '#6B6B6B', + 'grey43': '#6E6E6E', + 'grey44': '#707070', + 'grey45': '#737373', + 'grey46': '#757575', + 'grey47': '#787878', + 'grey48': '#7A7A7A', + 'grey49': '#7D7D7D', + 'grey50': '#7F7F7F', + 'grey51': '#828282', + 'grey52': '#858585', + 'grey53': '#878787', + 'grey54': '#8A8A8A', + 'grey55': '#8C8C8C', + 'grey56': '#8F8F8F', + 'grey57': '#919191', + 'grey58': '#949494', + 'grey59': '#969696', + 'grey60': '#999999', + 'grey61': '#9C9C9C', + 'grey62': '#9E9E9E', + 'grey63': '#A1A1A1', + 'grey64': '#A3A3A3', + 'grey65': '#A6A6A6', + 'grey66': '#A8A8A8', + 'grey67': '#ABABAB', + 'grey68': '#ADADAD', + 'grey69': '#B0B0B0', + 'grey70': '#B3B3B3', + 'grey71': '#B5B5B5', + 'grey72': '#B8B8B8', + 'grey73': '#BABABA', + 'grey74': '#BDBDBD', + 'grey75': '#BFBFBF', + 'grey76': '#C2C2C2', + 'grey77': '#C4C4C4', + 'grey78': '#C7C7C7', + 'grey79': '#C9C9C9', + 'grey80': '#CCCCCC', + 'grey81': '#CFCFCF', + 'grey82': '#D1D1D1', + 'grey83': '#D4D4D4', + 'grey84': '#D6D6D6', + 'grey85': '#D9D9D9', + 'grey86': '#DBDBDB', + 'grey87': '#DEDEDE', + 'grey88': '#E0E0E0', + 'grey89': '#E3E3E3', + 'grey90': '#E5E5E5', + 'grey91': '#E8E8E8', + 'grey92': '#EBEBEB', + 'grey93': '#EDEDED', + 'grey94': '#F0F0F0', + 'grey95': '#F2F2F2', + 'grey96': '#F5F5F5', + 'grey97': '#F7F7F7', + 'grey98': '#FAFAFA', + 'grey99': '#FCFCFC', + 'grey100': '#FFFFFF', + 'honeydew': '#F0FFF0', + 'honeydew1': '#F0FFF0', + 'honeydew2': '#E0EEE0', + 'honeydew3': '#C1CDC1', + 'honeydew4': '#838B83', + 'hot pink': '#FF69B4', + 'HotPink': '#FF69B4', + 'HotPink1': '#FF6EB4', + 'HotPink2': '#EE6AA7', + 'HotPink3': '#CD6090', + 'HotPink4': '#8B3A62', + 'indian red': '#CD5C5C', + 'IndianRed': '#CD5C5C', + 'IndianRed1': '#FF6A6A', + 'IndianRed2': '#EE6363', + 'IndianRed3': '#CD5555', + 'IndianRed4': '#8B3A3A', + 'ivory': '#FFFFF0', + 'ivory1': '#FFFFF0', + 'ivory2': '#EEEEE0', + 'ivory3': '#CDCDC1', + 'ivory4': '#8B8B83', + 'khaki': '#F0E68C', + 'khaki1': '#FFF68F', + 'khaki2': '#EEE685', + 'khaki3': '#CDC673', + 'khaki4': '#8B864E', + 'lavender': '#E6E6FA', + 'lavender blush': '#FFF0F5', + 'LavenderBlush': '#FFF0F5', + 'LavenderBlush1': '#FFF0F5', + 'LavenderBlush2': '#EEE0E5', + 'LavenderBlush3': '#CDC1C5', + 'LavenderBlush4': '#8B8386', + 'lawn green': '#7CFC00', + 'LawnGreen': '#7CFC00', + 'lemon chiffon': '#FFFACD', + 'LemonChiffon': '#FFFACD', + 'LemonChiffon1': '#FFFACD', + 'LemonChiffon2': '#EEE9BF', + 'LemonChiffon3': '#CDC9A5', + 'LemonChiffon4': '#8B8970', + 'light blue': '#ADD8E6', + 'light coral': '#F08080', + 'light cyan': '#E0FFFF', + 'light goldenrod': '#EEDD82', + 'light goldenrod yellow': '#FAFAD2', + 'light gray': '#D3D3D3', + 'light green': '#90EE90', + 'light grey': '#D3D3D3', + 'light pink': '#FFB6C1', + 'light salmon': '#FFA07A', + 'light sea green': '#20B2AA', + 'light sky blue': '#87CEFA', + 'light slate blue': '#8470FF', + 'light slate gray': '#778899', + 'light slate grey': '#778899', + 'light steel blue': '#B0C4DE', + 'light yellow': '#FFFFE0', + 'LightBlue': '#ADD8E6', + 'LightBlue1': '#BFEFFF', + 'LightBlue2': '#B2DFEE', + 'LightBlue3': '#9AC0CD', + 'LightBlue4': '#68838B', + 'LightCoral': '#F08080', + 'LightCyan': '#E0FFFF', + 'LightCyan1': '#E0FFFF', + 'LightCyan2': '#D1EEEE', + 'LightCyan3': '#B4CDCD', + 'LightCyan4': '#7A8B8B', + 'LightGoldenrod': '#EEDD82', + 'LightGoldenrod1': '#FFEC8B', + 'LightGoldenrod2': '#EEDC82', + 'LightGoldenrod3': '#CDBE70', + 'LightGoldenrod4': '#8B814C', + 'LightGoldenrodYellow': '#FAFAD2', + 'LightGray': '#D3D3D3', + 'LightGreen': '#90EE90', + 'LightGrey': '#D3D3D3', + 'LightPink': '#FFB6C1', + 'LightPink1': '#FFAEB9', + 'LightPink2': '#EEA2AD', + 'LightPink3': '#CD8C95', + 'LightPink4': '#8B5F65', + 'LightSalmon': '#FFA07A', + 'LightSalmon1': '#FFA07A', + 'LightSalmon2': '#EE9572', + 'LightSalmon3': '#CD8162', + 'LightSalmon4': '#8B5742', + 'LightSeaGreen': '#20B2AA', + 'LightSkyBlue': '#87CEFA', + 'LightSkyBlue1': '#B0E2FF', + 'LightSkyBlue2': '#A4D3EE', + 'LightSkyBlue3': '#8DB6CD', + 'LightSkyBlue4': '#607B8B', + 'LightSlateBlue': '#8470FF', + 'LightSlateGray': '#778899', + 'LightSlateGrey': '#778899', + 'LightSteelBlue': '#B0C4DE', + 'LightSteelBlue1': '#CAE1FF', + 'LightSteelBlue2': '#BCD2EE', + 'LightSteelBlue3': '#A2B5CD', + 'LightSteelBlue4': '#6E7B8B', + 'LightYellow': '#FFFFE0', + 'LightYellow1': '#FFFFE0', + 'LightYellow2': '#EEEED1', + 'LightYellow3': '#CDCDB4', + 'LightYellow4': '#8B8B7A', + 'lime green': '#32CD32', + 'LimeGreen': '#32CD32', + 'linen': '#FAF0E6', + 'magenta': '#FF00FF', + 'magenta1': '#FF00FF', + 'magenta2': '#EE00EE', + 'magenta3': '#CD00CD', + 'magenta4': '#8B008B', + 'maroon': '#B03060', + 'maroon1': '#FF34B3', + 'maroon2': '#EE30A7', + 'maroon3': '#CD2990', + 'maroon4': '#8B1C62', + 'medium aquamarine': '#66CDAA', + 'medium blue': '#0000CD', + 'medium orchid': '#BA55D3', + 'medium purple': '#9370DB', + 'medium sea green': '#3CB371', + 'medium slate blue': '#7B68EE', + 'medium spring green': '#00FA9A', + 'medium turquoise': '#48D1CC', + 'medium violet red': '#C71585', + 'MediumAquamarine': '#66CDAA', + 'MediumBlue': '#0000CD', + 'MediumOrchid': '#BA55D3', + 'MediumOrchid1': '#E066FF', + 'MediumOrchid2': '#D15FEE', + 'MediumOrchid3': '#B452CD', + 'MediumOrchid4': '#7A378B', + 'MediumPurple': '#9370DB', + 'MediumPurple1': '#AB82FF', + 'MediumPurple2': '#9F79EE', + 'MediumPurple3': '#8968CD', + 'MediumPurple4': '#5D478B', + 'MediumSeaGreen': '#3CB371', + 'MediumSlateBlue': '#7B68EE', + 'MediumSpringGreen': '#00FA9A', + 'MediumTurquoise': '#48D1CC', + 'MediumVioletRed': '#C71585', + 'midnight blue': '#191970', + 'MidnightBlue': '#191970', + 'mint cream': '#F5FFFA', + 'MintCream': '#F5FFFA', + 'misty rose': '#FFE4E1', + 'MistyRose': '#FFE4E1', + 'MistyRose1': '#FFE4E1', + 'MistyRose2': '#EED5D2', + 'MistyRose3': '#CDB7B5', + 'MistyRose4': '#8B7D7B', + 'moccasin': '#FFE4B5', + 'navajo white': '#FFDEAD', + 'NavajoWhite': '#FFDEAD', + 'NavajoWhite1': '#FFDEAD', + 'NavajoWhite2': '#EECFA1', + 'NavajoWhite3': '#CDB38B', + 'NavajoWhite4': '#8B795E', + 'navy': '#000080', + 'navy blue': '#000080', + 'NavyBlue': '#000080', + 'old lace': '#FDF5E6', + 'OldLace': '#FDF5E6', + 'olive drab': '#6B8E23', + 'OliveDrab': '#6B8E23', + 'OliveDrab1': '#C0FF3E', + 'OliveDrab2': '#B3EE3A', + 'OliveDrab3': '#9ACD32', + 'OliveDrab4': '#698B22', + 'orange': '#FFA500', + 'orange red': '#FF4500', + 'orange1': '#FFA500', + 'orange2': '#EE9A00', + 'orange3': '#CD8500', + 'orange4': '#8B5A00', + 'OrangeRed': '#FF4500', + 'OrangeRed1': '#FF4500', + 'OrangeRed2': '#EE4000', + 'OrangeRed3': '#CD3700', + 'OrangeRed4': '#8B2500', + 'orchid': '#DA70D6', + 'orchid1': '#FF83FA', + 'orchid2': '#EE7AE9', + 'orchid3': '#CD69C9', + 'orchid4': '#8B4789', + 'pale goldenrod': '#EEE8AA', + 'pale green': '#98FB98', + 'pale turquoise': '#AFEEEE', + 'pale violet red': '#DB7093', + 'PaleGoldenrod': '#EEE8AA', + 'PaleGreen': '#98FB98', + 'PaleGreen1': '#9AFF9A', + 'PaleGreen2': '#90EE90', + 'PaleGreen3': '#7CCD7C', + 'PaleGreen4': '#548B54', + 'PaleTurquoise': '#AFEEEE', + 'PaleTurquoise1': '#BBFFFF', + 'PaleTurquoise2': '#AEEEEE', + 'PaleTurquoise3': '#96CDCD', + 'PaleTurquoise4': '#668B8B', + 'PaleVioletRed': '#DB7093', + 'PaleVioletRed1': '#FF82AB', + 'PaleVioletRed2': '#EE799F', + 'PaleVioletRed3': '#CD687F', + 'PaleVioletRed4': '#8B475D', + 'papaya whip': '#FFEFD5', + 'PapayaWhip': '#FFEFD5', + 'peach puff': '#FFDAB9', + 'PeachPuff': '#FFDAB9', + 'PeachPuff1': '#FFDAB9', + 'PeachPuff2': '#EECBAD', + 'PeachPuff3': '#CDAF95', + 'PeachPuff4': '#8B7765', + 'peru': '#CD853F', + 'pink': '#FFC0CB', + 'pink1': '#FFB5C5', + 'pink2': '#EEA9B8', + 'pink3': '#CD919E', + 'pink4': '#8B636C', + 'plum': '#DDA0DD', + 'plum1': '#FFBBFF', + 'plum2': '#EEAEEE', + 'plum3': '#CD96CD', + 'plum4': '#8B668B', + 'powder blue': '#B0E0E6', + 'PowderBlue': '#B0E0E6', + 'purple': '#A020F0', + 'purple1': '#9B30FF', + 'purple2': '#912CEE', + 'purple3': '#7D26CD', + 'purple4': '#551A8B', + 'red': '#FF0000', + 'red1': '#FF0000', + 'red2': '#EE0000', + 'red3': '#CD0000', + 'red4': '#8B0000', + 'rosy brown': '#BC8F8F', + 'RosyBrown': '#BC8F8F', + 'RosyBrown1': '#FFC1C1', + 'RosyBrown2': '#EEB4B4', + 'RosyBrown3': '#CD9B9B', + 'RosyBrown4': '#8B6969', + 'royal blue': '#4169E1', + 'RoyalBlue': '#4169E1', + 'RoyalBlue1': '#4876FF', + 'RoyalBlue2': '#436EEE', + 'RoyalBlue3': '#3A5FCD', + 'RoyalBlue4': '#27408B', + 'saddle brown': '#8B4513', + 'SaddleBrown': '#8B4513', + 'salmon': '#FA8072', + 'salmon1': '#FF8C69', + 'salmon2': '#EE8262', + 'salmon3': '#CD7054', + 'salmon4': '#8B4C39', + 'sandy brown': '#F4A460', + 'SandyBrown': '#F4A460', + 'sea green': '#2E8B57', + 'SeaGreen': '#2E8B57', + 'SeaGreen1': '#54FF9F', + 'SeaGreen2': '#4EEE94', + 'SeaGreen3': '#43CD80', + 'SeaGreen4': '#2E8B57', + 'seashell': '#FFF5EE', + 'seashell1': '#FFF5EE', + 'seashell2': '#EEE5DE', + 'seashell3': '#CDC5BF', + 'seashell4': '#8B8682', + 'sienna': '#A0522D', + 'sienna1': '#FF8247', + 'sienna2': '#EE7942', + 'sienna3': '#CD6839', + 'sienna4': '#8B4726', + 'sky blue': '#87CEEB', + 'SkyBlue': '#87CEEB', + 'SkyBlue1': '#87CEFF', + 'SkyBlue2': '#7EC0EE', + 'SkyBlue3': '#6CA6CD', + 'SkyBlue4': '#4A708B', + 'slate blue': '#6A5ACD', + 'slate gray': '#708090', + 'slate grey': '#708090', + 'SlateBlue': '#6A5ACD', + 'SlateBlue1': '#836FFF', + 'SlateBlue2': '#7A67EE', + 'SlateBlue3': '#6959CD', + 'SlateBlue4': '#473C8B', + 'SlateGray': '#708090', + 'SlateGray1': '#C6E2FF', + 'SlateGray2': '#B9D3EE', + 'SlateGray3': '#9FB6CD', + 'SlateGray4': '#6C7B8B', + 'SlateGrey': '#708090', + 'snow': '#FFFAFA', + 'snow1': '#FFFAFA', + 'snow2': '#EEE9E9', + 'snow3': '#CDC9C9', + 'snow4': '#8B8989', + 'spring green': '#00FF7F', + 'SpringGreen': '#00FF7F', + 'SpringGreen1': '#00FF7F', + 'SpringGreen2': '#00EE76', + 'SpringGreen3': '#00CD66', + 'SpringGreen4': '#008B45', + 'steel blue': '#4682B4', + 'SteelBlue': '#4682B4', + 'SteelBlue1': '#63B8FF', + 'SteelBlue2': '#5CACEE', + 'SteelBlue3': '#4F94CD', + 'SteelBlue4': '#36648B', + 'tan': '#D2B48C', + 'tan1': '#FFA54F', + 'tan2': '#EE9A49', + 'tan3': '#CD853F', + 'tan4': '#8B5A2B', + 'thistle': '#D8BFD8', + 'thistle1': '#FFE1FF', + 'thistle2': '#EED2EE', + 'thistle3': '#CDB5CD', + 'thistle4': '#8B7B8B', + 'tomato': '#FF6347', + 'tomato1': '#FF6347', + 'tomato2': '#EE5C42', + 'tomato3': '#CD4F39', + 'tomato4': '#8B3626', + 'turquoise': '#40E0D0', + 'turquoise1': '#00F5FF', + 'turquoise2': '#00E5EE', + 'turquoise3': '#00C5CD', + 'turquoise4': '#00868B', + 'violet': '#EE82EE', + 'violet red': '#D02090', + 'VioletRed': '#D02090', + 'VioletRed1': '#FF3E96', + 'VioletRed2': '#EE3A8C', + 'VioletRed3': '#CD3278', + 'VioletRed4': '#8B2252', + 'wheat': '#F5DEB3', + 'wheat1': '#FFE7BA', + 'wheat2': '#EED8AE', + 'wheat3': '#CDBA96', + 'wheat4': '#8B7E66', + 'white': '#FFFFFF', + 'white smoke': '#F5F5F5', + 'WhiteSmoke': '#F5F5F5', + 'yellow': '#FFFF00', + 'yellow green': '#9ACD32', + 'yellow1': '#FFFF00', + 'yellow2': '#EEEE00', + 'yellow3': '#CDCD00', + 'yellow4': '#8B8B00', + 'YellowGreen': '#9ACD32', +} + + +def detailed_view(window): + layout2 = [[sg.Button(event, button_color=('white', color_map[event]), + key=event, tooltip=color_map[color]), + sg.Button(event, button_color=('black', color_map[event]), + key=event+'1', tooltip=color_map[color])], + [sg.Text('Hover over button to see color value. Click to clocse and return to main interface.')], ] + sg.Window('Buttons with white and black text', + layout2, keep_on_top=True).Read() + window.close() + return + + +sg.set_options(button_element_size=(16, 1), + auto_size_buttons=False, border_width=0, tooltip_time=100) + +# start layout with the tittle +layout = [[sg.Text('Hover mouse to see RGB value. Click to see Button with White or Black text.', + text_color='blue', background_color='#90EE90', + font=('Hevletica', 20), + relief=sg.RELIEF_SUNKEN, justification='center', + size=(90, 2), pad=(0, 0))]] + +# -- Create primary color viewer window by building rows and appending to layout -- +color_list = [key for key in color_map] +for rows in range(40): + row = [] + for i in range(12): + try: + color = color_list[rows+40*i] + row.append(sg.Button(color, + button_color=('black', color_map[color]), key=color, tooltip=color_map[color]),) + except: + pass + layout.append(row) + +while True: + window = sg.Window('Color Viewer', layout, font=('any 12'), + default_button_element_size=(12, 1), element_padding=(0, 0)) + event, values = window.read() + if event is None: + break + detailed_view(window) diff --git a/PySimpleGUIWeb/Demo Programs/Web_Color_Names_Smaller_List.py b/PySimpleGUIWeb/Demo Programs/Web_Color_Names_Smaller_List.py new file mode 100644 index 000000000..51f9f3d2e --- /dev/null +++ b/PySimpleGUIWeb/Demo Programs/Web_Color_Names_Smaller_List.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python +import PySimpleGUIWeb as sg + +""" + Color names courtesy of Big Daddy's Wiki-Python + http://www.wikipython.com/tkinter-ttk-tix/summary-information/colors/ + + Shows a big chart of colors... give it a few seconds to create it + Once large window is shown, you can click on any color and another window will popup + showing both white and black text on that color +""" + + +COLORS = ['snow', 'ghost white', 'white smoke', 'gainsboro', 'floral white', 'old lace', + 'linen', 'antique white', 'papaya whip', 'blanched almond', 'bisque', 'peach puff', + 'navajo white', 'lemon chiffon', 'mint cream', 'azure', 'alice blue', 'lavender', + 'lavender blush', 'misty rose', 'dark slate gray', 'dim gray', 'slate gray', + 'light slate gray', 'gray', 'light gray', 'midnight blue', 'navy', 'cornflower blue', 'dark slate blue', + 'slate blue', 'medium slate blue', 'light slate blue', 'medium blue', 'royal blue', 'blue', + 'dodger blue', 'deep sky blue', 'sky blue', 'light sky blue', 'steel blue', 'light steel blue', + 'light blue', 'powder blue', 'pale turquoise', 'dark turquoise', 'medium turquoise', 'turquoise', + 'cyan', 'light cyan', 'cadet blue', 'medium aquamarine', 'aquamarine', 'dark green', 'dark olive green', + 'dark sea green', 'sea green', 'medium sea green', 'light sea green', 'pale green', 'spring green', + 'lawn green', 'medium spring green', 'green yellow', 'lime green', 'yellow green', + 'forest green', 'olive drab', 'dark khaki', 'khaki', 'pale goldenrod', 'light goldenrod yellow', + 'light yellow', 'yellow', 'gold', 'light goldenrod', 'goldenrod', 'dark goldenrod', 'rosy brown', + 'indian red', 'saddle brown', 'sandy brown', + 'dark salmon', 'salmon', 'light salmon', 'orange', 'dark orange', + 'coral', 'light coral', 'tomato', 'orange red', 'red', 'hot pink', 'deep pink', 'pink', 'light pink', + 'pale violet red', 'maroon', 'medium violet red', 'violet red', + 'medium orchid', 'dark orchid', 'dark violet', 'blue violet', 'purple', 'medium purple', + 'thistle', 'snow2', 'snow3', + 'snow4', 'seashell2', 'seashell3', 'seashell4', 'AntiqueWhite1', 'AntiqueWhite2', + 'AntiqueWhite3', 'AntiqueWhite4', 'bisque2', 'bisque3', 'bisque4', 'PeachPuff2', + 'PeachPuff3', 'PeachPuff4', 'NavajoWhite2', 'NavajoWhite3', 'NavajoWhite4', + 'LemonChiffon2', 'LemonChiffon3', 'LemonChiffon4', 'cornsilk2', 'cornsilk3', + 'cornsilk4', 'ivory2', 'ivory3', 'ivory4', 'honeydew2', 'honeydew3', 'honeydew4', + 'LavenderBlush2', 'LavenderBlush3', 'LavenderBlush4', 'MistyRose2', 'MistyRose3', + 'MistyRose4', 'azure2', 'azure3', 'azure4', 'SlateBlue1', 'SlateBlue2', 'SlateBlue3', + 'SlateBlue4', 'RoyalBlue1', 'RoyalBlue2', 'RoyalBlue3', 'RoyalBlue4', 'blue2', 'blue4', + 'DodgerBlue2', 'DodgerBlue3', 'DodgerBlue4', 'SteelBlue1', 'SteelBlue2', + 'SteelBlue3', 'SteelBlue4', 'DeepSkyBlue2', 'DeepSkyBlue3', 'DeepSkyBlue4', + 'SkyBlue1', 'SkyBlue2', 'SkyBlue3', 'SkyBlue4', 'LightSkyBlue1', 'LightSkyBlue2', + 'LightSkyBlue3', 'LightSkyBlue4', 'Slategray1', 'Slategray2', 'Slategray3', + 'Slategray4', 'LightSteelBlue1', 'LightSteelBlue2', 'LightSteelBlue3', + 'LightSteelBlue4', 'LightBlue1', 'LightBlue2', 'LightBlue3', 'LightBlue4', + 'LightCyan2', 'LightCyan3', 'LightCyan4', 'PaleTurquoise1', 'PaleTurquoise2', + 'PaleTurquoise3', 'PaleTurquoise4', 'CadetBlue1', 'CadetBlue2', 'CadetBlue3', + 'CadetBlue4', 'turquoise1', 'turquoise2', 'turquoise3', 'turquoise4', 'cyan2', 'cyan3', + 'cyan4', 'DarkSlategray1', 'DarkSlategray2', 'DarkSlategray3', 'DarkSlategray4', + 'aquamarine2', 'aquamarine4', 'DarkSeaGreen1', 'DarkSeaGreen2', 'DarkSeaGreen3', + 'DarkSeaGreen4', 'SeaGreen1', 'SeaGreen2', 'SeaGreen3', 'PaleGreen1', 'PaleGreen2', + 'PaleGreen3', 'PaleGreen4', 'SpringGreen2', 'SpringGreen3', 'SpringGreen4', + 'green2', 'green3', 'green4', 'chartreuse2', 'chartreuse3', 'chartreuse4', + 'OliveDrab1', 'OliveDrab2', 'OliveDrab4', 'DarkOliveGreen1', 'DarkOliveGreen2', + 'DarkOliveGreen3', 'DarkOliveGreen4', 'khaki1', 'khaki2', 'khaki3', 'khaki4', + 'LightGoldenrod1', 'LightGoldenrod2', 'LightGoldenrod3', 'LightGoldenrod4', + 'LightYellow2', 'LightYellow3', 'LightYellow4', 'yellow2', 'yellow3', 'yellow4', + 'gold2', 'gold3', 'gold4', 'goldenrod1', 'goldenrod2', 'goldenrod3', 'goldenrod4', + 'DarkGoldenrod1', 'DarkGoldenrod2', 'DarkGoldenrod3', 'DarkGoldenrod4', + 'RosyBrown1', 'RosyBrown2', 'RosyBrown3', 'RosyBrown4', 'IndianRed1', 'IndianRed2', + 'IndianRed3', 'IndianRed4', 'sienna1', 'sienna2', 'sienna3', 'sienna4', 'burlywood1', + 'burlywood2', 'burlywood3', 'burlywood4', 'wheat1', 'wheat2', 'wheat3', 'wheat4', 'tan1', + 'tan2', 'tan4', 'chocolate1', 'chocolate2', 'chocolate3', 'firebrick1', 'firebrick2', + 'firebrick3', 'firebrick4', 'brown1', 'brown2', 'brown3', 'brown4', 'salmon1', 'salmon2', + 'salmon3', 'salmon4', 'LightSalmon2', 'LightSalmon3', 'LightSalmon4', 'orange2', + 'orange3', 'orange4', 'DarkOrange1', 'DarkOrange2', 'DarkOrange3', 'DarkOrange4', + 'coral1', 'coral2', 'coral3', 'coral4', 'tomato2', 'tomato3', 'tomato4', 'OrangeRed2', + 'OrangeRed3', 'OrangeRed4', 'red2', 'red3', 'red4', 'DeepPink2', 'DeepPink3', 'DeepPink4', + 'HotPink1', 'HotPink2', 'HotPink3', 'HotPink4', 'pink1', 'pink2', 'pink3', 'pink4', + 'LightPink1', 'LightPink2', 'LightPink3', 'LightPink4', 'PaleVioletRed1', + 'PaleVioletRed2', 'PaleVioletRed3', 'PaleVioletRed4', 'maroon1', 'maroon2', + 'maroon3', 'maroon4', 'VioletRed1', 'VioletRed2', 'VioletRed3', 'VioletRed4', + 'magenta2', 'magenta3', 'magenta4', 'orchid1', 'orchid2', 'orchid3', 'orchid4', 'plum1', + 'plum2', 'plum3', 'plum4', 'MediumOrchid1', 'MediumOrchid2', 'MediumOrchid3', + 'MediumOrchid4', 'DarkOrchid1', 'DarkOrchid2', 'DarkOrchid3', 'DarkOrchid4', + 'purple1', 'purple2', 'purple3', 'purple4', 'MediumPurple1', 'MediumPurple2', + 'MediumPurple3', 'MediumPurple4', 'thistle1', 'thistle2', 'thistle3', 'thistle4', + 'grey1', 'grey2', 'grey3', 'grey4', 'grey5', 'grey6', 'grey7', 'grey8', 'grey9', 'grey10', + 'grey11', 'grey12', 'grey13', 'grey14', 'grey15', 'grey16', 'grey17', 'grey18', 'grey19', + 'grey20', 'grey21', 'grey22', 'grey23', 'grey24', 'grey25', 'grey26', 'grey27', 'grey28', + 'grey29', 'grey30', 'grey31', 'grey32', 'grey33', 'grey34', 'grey35', 'grey36', 'grey37', + 'grey38', 'grey39', 'grey40', 'grey42', 'grey43', 'grey44', 'grey45', 'grey46', 'grey47', + 'grey48', 'grey49', 'grey50', 'grey51', 'grey52', 'grey53', 'grey54', 'grey55', 'grey56', + 'grey57', 'grey58', 'grey59', 'grey60', 'grey61', 'grey62', 'grey63', 'grey64', 'grey65', + 'grey66', 'grey67', 'grey68', 'grey69', 'grey70', 'grey71', 'grey72', 'grey73', 'grey74', + 'grey75', 'grey76', 'grey77', 'grey78', 'grey79', 'grey80', 'grey81', 'grey82', 'grey83', + 'grey84', 'grey85', 'grey86', 'grey87', 'grey88', 'grey89', 'grey90', 'grey91', 'grey92', + 'grey93', 'grey94', 'grey95', 'grey97', 'grey98', 'grey99'] + + +sg.set_options(button_element_size=(12, 1), + element_padding=(0, 0), auto_size_buttons=False, border_width=0) + +layout = [[sg.Text('Click on a color square to see both white and black text on that color', + text_color='blue', font='Any 15')]] +row = [] +layout = [] +# -- Create primary color viewer window -- +for rows in range(40): + + row = [] + for i in range(12): + try: + color = COLORS[rows+40*i] + row.append(sg.Button(color, button_color=('black', color), key=color)) + except: + pass + layout.append(row) + + +# for i, color in enumerate(COLORS): +# row.append(sg.Button(color, button_color=('black', color), key=color)) +# if (i+1) % 12 == 0: +# layout.append(row) +# row = [] + +window = sg.Window('Color Viewer', layout, + grab_anywhere=False, font=('any 9')) + +# -- Event loop -- +while True: + event, values = window.read() + if event is None: + break + # -- Create a secondary window that shows white and black text on chosen color + layout2 = [[sg.DummyButton(event, button_color=('white', event)), + sg.DummyButton(event, button_color=('black', event))]] + sg.Window('Buttons with white and black text', + layout2, keep_on_top=True).read(timeout=0) diff --git a/PySimpleGUIWeb/Demo Programs/Web_Demo_Font_Sizer.py b/PySimpleGUIWeb/Demo Programs/Web_Demo_Font_Sizer.py new file mode 100644 index 000000000..c07a9b716 --- /dev/null +++ b/PySimpleGUIWeb/Demo Programs/Web_Demo_Font_Sizer.py @@ -0,0 +1,38 @@ +import PySimpleGUIWeb as sg + +""" +Simple Demo that shows how Elements can effect other elements in the Window +In this case, the slider controls the size of the text font and the value shown in the spinner +Additionally, if the spinner is changed, the text size is changed and so is the slider +In other words, the slider and the spinner are essentially connected together +""" + +fontsize = 12 # initial and smallest font size to show + +layout = [ + [sg.Spin([sz for sz in range(6, 172)], size=(6, 1), + font=('Helvetica 20'), initial_value=fontsize, + change_submits=True, key='spin'), + sg.Slider(range=(6, 172), orientation='h', size=(10, 20), + change_submits=True, key='slider', font=('Helvetica 20')), + sg.Text("Aa", size=(2, 1), font="Helvetica " + str(fontsize), key='text')] + ] + +window = sg.Window("Font size selector", layout) + +while True: # the event loop + event, values = window.read() + if event is None or event == 'Quit': + break + + if int(values['spin']) != fontsize: + fontsize = int(values['spin']) + else: + fontsize = int(values['slider']) + + window['text'].update(font="Helvetica " + str(fontsize)) + window['slider'].update(fontsize, range=(10, 20)) + window['spin'].update(fontsize) +window.close() + +print("Done.") diff --git a/PySimpleGUIWeb/Demo Programs/Web_Demo_HowDoI.py b/PySimpleGUIWeb/Demo Programs/Web_Demo_HowDoI.py new file mode 100644 index 000000000..e8f80ec00 --- /dev/null +++ b/PySimpleGUIWeb/Demo Programs/Web_Demo_HowDoI.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python +import PySimpleGUIWeb as sg +import subprocess +import howdoi + +# Test this command in a dos window if you are having trouble. +HOW_DO_I_COMMAND = 'python -m howdoi.howdoi' + +def HowDoI(): + ''' + Make and show a window (PySimpleGUI form) that takes user input and sends to the HowDoI web oracle + Excellent example of 2 GUI concepts + 1. Output Element that will show text in a scrolled window + 2. Non-Window-Closing Buttons - These buttons will cause the form to return with the form's values, but doesn't close the form + :return: never returns + ''' + # ------- Make a new Window ------- # + sg.change_look_and_feel('GreenTan') # give our form a spiffy set of colors + + layout = [ + [sg.Text('Ask and your answer will appear here....', size=(40, 1))], + [sg.MLineOutput(size_px=(980, 400),key='_OUTPUT_' )], + # [ sg.Spin(values=(1, 2, 3, 4), initial_value=1, size=(2, 1), key='Num Answers', font='Helvetica 15'), + [ sg.CBox('Display Full Text', key='full text', font='Helvetica 15'), + sg.Text('Command History', font='Helvetica 15'), sg.Text('', size=(40,3), text_color=sg.BLUES[0], key='history')], + [sg.MLine(size=(85, 5), enter_submits=True, key='query', do_not_clear=False), + sg.ReadButton('SEND', button_color=(sg.YELLOWS[0], sg.BLUES[0]), bind_return_key=True), + sg.Button('EXIT', button_color=(sg.YELLOWS[0], sg.GREENS[0]))] + ] + + window = sg.Window('How Do I?', layout, default_element_size=(30,1), + font=('Helvetica',' 17'), default_button_element_size=(8,2), + return_keyboard_events=False) + + # ---===--- Loop taking in user input and using it to query HowDoI --- # + command_history = [] + history_offset = 0 + while True: + + event, values = window.Read() + # print(event, values) + if type(event) is int: + event = str(event) + if event == 'SEND': + query = values['query'].rstrip() + window['_OUTPUT_'].update(query, append=True) + print(query) + QueryHowDoI(query, 1, values['full text'], window) # send the string to HowDoI + command_history.append(query) + history_offset = len(command_history)-1 + + # manually clear input because keyboard events blocks clear + window['query'].update('') + window['history'].update('\n'.join(command_history[-3:])) + + # if exit button or closed using X + elif event == None or event == 'EXIT': + break + + # scroll back in history + elif 'Up' in event and len(command_history): + command = command_history[history_offset] + + # decrement is not zero + history_offset -= 1 * (history_offset > 0) + window['query'].update(command) + + # scroll forward in history + elif 'Down' in event and len(command_history): + + # increment up to end of list + history_offset += 1 * (history_offset < len(command_history)-1) + command = command_history[history_offset] + window['query'].update(command) + + # clear currently line + elif 'Escape' in event: + window['query'].update('') + + window.close() + +def QueryHowDoI(Query, num_answers, full_text, window:sg.Window): + ''' + Kicks off a subprocess to send the 'Query' to HowDoI + Prints the result, which in this program will route to a gooeyGUI window + :param Query: text english question to ask the HowDoI web engine + :return: nothing + ''' + howdoi_command = HOW_DO_I_COMMAND + full_text_option = ' -a' if full_text else '' + t = subprocess.Popen(howdoi_command + ' \"'+ Query + '\" -n ' + str(num_answers)+full_text_option, stdout=subprocess.PIPE) + (output, err) = t.communicate() + window['_OUTPUT_'].update('{:^88}'.format(Query.rstrip()), append=True) + window['_OUTPUT_'].update('_'*60, append=True) + window['_OUTPUT_'].update(output.decode("utf-8"), append=True) + exit_code = t.wait() + +if __name__ == '__main__': + HowDoI() + diff --git a/PySimpleGUIWeb/Demo Programs/Web_Desktop_Widget_CPU_Utilization.py b/PySimpleGUIWeb/Demo Programs/Web_Desktop_Widget_CPU_Utilization.py new file mode 100644 index 000000000..b77fd4512 --- /dev/null +++ b/PySimpleGUIWeb/Demo Programs/Web_Desktop_Widget_CPU_Utilization.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python +import PySimpleGUIWeb as sg +import psutil +import time +from threading import Thread +import operator + + +""" + PSUTIL Desktop Widget + Creates a floating CPU utilization window that is always on top of other windows + You move it by grabbing anywhere on the window + Good example of how to do a non-blocking, polling program using PySimpleGUI + Use the spinner to adjust the number of seconds between readings of the CPU utilizaiton + + NOTE - you will get a warning message printed when you exit using exit button. + It will look something like: + invalid command name "1616802625480StopMove" +""" + +# globale used to communicate with thread.. yea yea... it's working fine +g_interval = 1 +g_cpu_percent = 0 +g_procs = None +g_exit = False + + +def CPU_thread(args): + global g_interval, g_cpu_percent, g_procs, g_exit + + while not g_exit: + try: + g_cpu_percent = psutil.cpu_percent(interval=g_interval) + g_procs = psutil.process_iter() + except: + pass + + +def main(): + global g_interval, g_procs, g_exit + + # ---------------- Create Form ---------------- + sg.change_look_and_feel('Black') + layout = [[sg.Text('', size=(8, 1), font=('Helvetica', 20), text_color=sg.YELLOWS[0], + justification='center', key='text')], + [sg.Text('', size=(30, 8), font=('Courier New', 12), + text_color='white', justification='left', key='processes')], + [sg.Exit(button_color=('white', 'firebrick4'), + pad=((15, 0), 0), size=(9, 1)), ] + ] + + window = sg.Window('CPU Utilization', layout, + no_titlebar=True, keep_on_top=True, alpha_channel=.8, grab_anywhere=True) + + # start cpu measurement thread + thread = Thread(target=CPU_thread, args=(None,), daemon=True) + thread.start() + timeout_value = 1 # make first read really quick + g_interval = 1 + # ---------------- main loop ---------------- + while True: + # --------- Read and update window -------- + event, values = window.read( + timeout=timeout_value, timeout_key='Timeout') + # --------- Do Button Operations -------- + if event in (None, 'Exit'): + break + + timeout_value = 1000 + + cpu_percent = g_cpu_percent + display_string = '' + if g_procs: + # --------- Create list of top % CPU porocesses -------- + try: + top = {proc.name(): proc.cpu_percent() for proc in g_procs} + except: + pass + + top_sorted = sorted( + top.items(), key=operator.itemgetter(1), reverse=True) + if top_sorted: + top_sorted.pop(0) + display_string = '' + for proc, cpu in top_sorted: + display_string += '{:2.2f} {}\n'.format(cpu/10, proc) + + # --------- Display timer and proceses in window -------- + window['text'].update('CPU {}'.format(cpu_percent)) + window['processes'].update(display_string) + + window.close() + + +if __name__ == "__main__": + main() diff --git a/PySimpleGUIWeb/Demo Programs/Web_Matplotlib.py b/PySimpleGUIWeb/Demo Programs/Web_Matplotlib.py new file mode 100644 index 000000000..37b62f6c6 --- /dev/null +++ b/PySimpleGUIWeb/Demo Programs/Web_Matplotlib.py @@ -0,0 +1,195 @@ +import PySimpleGUIWeb as sg +import numpy as np +from matplotlib.backends.backend_tkagg import FigureCanvasAgg +import matplotlib.figure +import matplotlib.pyplot as plt +import io + + +from matplotlib import cm +from mpl_toolkits.mplot3d.axes3d import get_test_data +from matplotlib.ticker import NullFormatter # useful for `logit` scale + + +def create_axis_grid(): + from mpl_toolkits.axes_grid1.axes_rgb import RGBAxes + + plt.close('all') + + def get_demo_image(): + # prepare image + delta = 0.5 + + extent = (-3, 4, -4, 3) + x = np.arange(-3.0, 4.001, delta) + y = np.arange(-4.0, 3.001, delta) + X, Y = np.meshgrid(x, y) + Z1 = np.exp(-X ** 2 - Y ** 2) + Z2 = np.exp(-(X - 1) ** 2 - (Y - 1) ** 2) + Z = (Z1 - Z2) * 2 + + return Z, extent + + def get_rgb(): + Z, extent = get_demo_image() + + Z[Z < 0] = 0. + Z = Z / Z.max() + + R = Z[:13, :13] + G = Z[2:, 2:] + B = Z[:13, 2:] + + return R, G, B + + fig = plt.figure(1) + ax = RGBAxes(fig, [0.1, 0.1, 0.8, 0.8]) + + r, g, b = get_rgb() + kwargs = dict(origin="lower", interpolation="nearest") + ax.imshow_rgb(r, g, b, **kwargs) + + ax.RGB.set_xlim(0., 9.5) + ax.RGB.set_ylim(0.9, 10.6) + + plt.draw() + return plt.gcf() + + + +def create_figure(): + # ------------------------------- START OF YOUR MATPLOTLIB CODE ------------------------------- + fig = matplotlib.figure.Figure(figsize=(5, 4), dpi=100) + t = np.arange(0, 3, .01) + fig.add_subplot(111).plot(t, 2 * np.sin(2 * np.pi * t)) + + return fig + + +def create_subplot_3d(): + + + fig = plt.figure() + + ax = fig.add_subplot(1, 2, 1, projection='3d') + X = np.arange(-5, 5, 0.25) + Y = np.arange(-5, 5, 0.25) + X, Y = np.meshgrid(X, Y) + R = np.sqrt(X ** 2 + Y ** 2) + Z = np.sin(R) + surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.jet, + linewidth=0, antialiased=False) + ax.set_zlim3d(-1.01, 1.01) + + fig.colorbar(surf, shrink=0.5, aspect=5) + + ax = fig.add_subplot(1, 2, 2, projection='3d') + X, Y, Z = get_test_data(0.05) + ax.plot_wireframe(X, Y, Z, rstride=10, cstride=10) + return fig + + + + +def create_pyplot_scales(): + + plt.close('all') + # Fixing random state for reproducibility + np.random.seed(19680801) + + # make up some data in the interval ]0, 1[ + y = np.random.normal(loc=0.5, scale=0.4, size=1000) + y = y[(y > 0) & (y < 1)] + y.sort() + x = np.arange(len(y)) + + # plot with various axes scales + plt.figure(1) + + # linear + plt.subplot(221) + plt.plot(x, y) + plt.yscale('linear') + plt.title('linear') + plt.grid(True) + + # log + plt.subplot(222) + plt.plot(x, y) + plt.yscale('log') + plt.title('log') + plt.grid(True) + + # symmetric log + plt.subplot(223) + plt.plot(x, y - y.mean()) + plt.yscale('symlog', linthreshy=0.01) + plt.title('symlog') + plt.grid(True) + + # logit + plt.subplot(224) + plt.plot(x, y) + plt.yscale('logit') + plt.title('logit') + plt.grid(True) + # Format the minor tick labels of the y-axis into empty strings with + # `NullFormatter`, to avoid cumbering the axis with too many labels. + plt.gca().yaxis.set_minor_formatter(NullFormatter()) + # Adjust the subplot layout, because the logit one may take more space + # than usual, due to y-tick labels like "1 - 10^{-3}" + plt.subplots_adjust(top=0.92, bottom=0.08, left=0.10, right=0.95, hspace=0.25, + wspace=0.35) + return plt.gcf() + +# ----------------------------- The draw figure helpful function ----------------------------- + +def draw_figure(fig, element): + """ + Draws the previously created "figure" in the supplied Image Element + + :param fig: a Matplotlib figure + :param element: an Image Element + :return: The figure canvas + """ + + plt.close('all') # erases previously drawn plots + canv = FigureCanvasAgg(fig) + buf = io.BytesIO() + canv.print_figure(buf, format='png') + if buf is None: + return None + buf.seek(0) + element.update(data=buf.read()) + return canv + +# ----------------------------- The GUI Section ----------------------------- + +def main(): + dictionary_of_figures = {'Axis Grid': create_axis_grid, + 'Subplot 3D': create_subplot_3d, + 'Scales': create_pyplot_scales, + 'Basic Figure': create_figure} + + layout = [ + [sg.T('Matplotlib Example', font='Any 20')], + [sg.Listbox(dictionary_of_figures.keys(), size=(15, 5), key='-LB-'), sg.Image(key='-IMAGE-')], + [sg.B('Draw'), sg.B('Exit')], + ] + + window = sg.Window('Title', layout, finalize=True) + + image_element = window['-IMAGE-'] # type: sg.Image + + while True: + event, values = window.read() + if event == 'Exit' or event == sg.WIN_CLOSED: + break + if event == 'Draw': + func = dictionary_of_figures[values['-LB-'][0]] + draw_figure(func(), image_element) + window.close() + + +if __name__ == "__main__": + main() diff --git a/PySimpleGUIWeb/Demo Programs/Web_Matplotlib_Browser.py b/PySimpleGUIWeb/Demo Programs/Web_Matplotlib_Browser.py new file mode 100644 index 000000000..355abdb26 --- /dev/null +++ b/PySimpleGUIWeb/Demo Programs/Web_Matplotlib_Browser.py @@ -0,0 +1,900 @@ +#!/usr/bin/env python +import inspect + +import PySimpleGUIWeb as sg +import numpy as np +from matplotlib.backends.backend_tkagg import FigureCanvasAgg +import matplotlib.figure +import io +import numpy as np +import matplotlib.pyplot as plt + +""" + Demonstrates one way of embedding Matplotlib figures into a PySimpleGUIWeb window. + + Basic steps are: + * Create a window with an Image Element + * Get a selection from user from list of available figures to be drawn + * Create figure using Matplotlib + * Update Image Element with generated plot + + Each plotting function was copied directly from Matplot examples page + + Copyright 2020 PySimpleGUI.org +""" + + +def PyplotSimple(): + import numpy as np + import matplotlib.pyplot as plt + + # evenly sampled time .2 intervals + t = np.arange(0., 5., 0.2) # go from 0 to 5 using .2 intervals + + # red dashes, blue squares and green triangles + plt.plot(t, t, 'r--', t, t ** 2, 'bs', t, t ** 3, 'g^') + + fig = plt.gcf() # get the figure to show + return fig + + +def PyplotHistogram(): + """ + ============================================================= + Demo of the histogram (hist) function with multiple data sets + ============================================================= + + Plot histogram with multiple sample sets and demonstrate: + + * Use of legend with multiple sample sets + * Stacked bars + * Step curve with no fill + * Data sets of different sample sizes + + Selecting different bin counts and sizes can significantly affect the + shape of a histogram. The Astropy docs have a great section on how to + select these parameters: + http://docs.astropy.org/en/stable/visualization/histogram.html + """ + + import numpy as np + import matplotlib.pyplot as plt + + np.random.seed(0) + + n_bins = 10 + x = np.random.randn(1000, 3) + + fig, axes = plt.subplots(nrows=2, ncols=2) + ax0, ax1, ax2, ax3 = axes.flatten() + + colors = ['red', 'tan', 'lime'] + ax0.hist(x, n_bins, normed=1, histtype='bar', color=colors, label=colors) + ax0.legend(prop={'size': 10}) + ax0.set_title('bars with legend') + + ax1.hist(x, n_bins, normed=1, histtype='bar', stacked=True) + ax1.set_title('stacked bar') + + ax2.hist(x, n_bins, histtype='step', stacked=True, fill=False) + ax2.set_title('stack step (unfilled)') + + # Make a multiple-histogram of data-sets with different length. + x_multi = [np.random.randn(n) for n in [10000, 5000, 2000]] + ax3.hist(x_multi, n_bins, histtype='bar') + ax3.set_title('different sample sizes') + + fig.tight_layout() + return fig + + +def PyplotArtistBoxPlots(): + """ + ========================================= + Demo of artist customization in box plots + ========================================= + + This example demonstrates how to use the various kwargs + to fully customize box plots. The first figure demonstrates + how to remove and add individual components (note that the + mean is the only value not shown by default). The second + figure demonstrates how the styles of the artists can + be customized. It also demonstrates how to set the limit + of the whiskers to specific percentiles (lower right axes) + + A good general reference on boxplots and their history can be found + here: http://vita.had.co.nz/papers/boxplots.pdf + + """ + + import numpy as np + import matplotlib.pyplot as plt + + # fake data + np.random.seed(937) + data = np.random.lognormal(size=(37, 4), mean=1.5, sigma=1.75) + labels = list('ABCD') + fs = 10 # fontsize + + # demonstrate how to toggle the display of different elements: + fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(6, 6), sharey=True) + axes[0, 0].boxplot(data, labels=labels) + axes[0, 0].set_title('Default', fontsize=fs) + + axes[0, 1].boxplot(data, labels=labels, showmeans=True) + axes[0, 1].set_title('showmeans=True', fontsize=fs) + + axes[0, 2].boxplot(data, labels=labels, showmeans=True, meanline=True) + axes[0, 2].set_title('showmeans=True,\nmeanline=True', fontsize=fs) + + axes[1, 0].boxplot(data, labels=labels, showbox=False, showcaps=False) + tufte_title = 'Tufte Style \n(showbox=False,\nshowcaps=False)' + axes[1, 0].set_title(tufte_title, fontsize=fs) + + axes[1, 1].boxplot(data, labels=labels, notch=True, bootstrap=10000) + axes[1, 1].set_title('notch=True,\nbootstrap=10000', fontsize=fs) + + axes[1, 2].boxplot(data, labels=labels, showfliers=False) + axes[1, 2].set_title('showfliers=False', fontsize=fs) + + for ax in axes.flatten(): + ax.set_yscale('log') + ax.set_yticklabels([]) + + fig.subplots_adjust(hspace=0.4) + return fig + + +def ArtistBoxplot2(): + # fake data + np.random.seed(937) + data = np.random.lognormal(size=(37, 4), mean=1.5, sigma=1.75) + labels = list('ABCD') + fs = 10 # fontsize + + # demonstrate how to customize the display different elements: + boxprops = dict(linestyle='--', linewidth=3, color='darkgoldenrod') + flierprops = dict(marker='o', markerfacecolor='green', markersize=12, + linestyle='none') + medianprops = dict(linestyle='-.', linewidth=2.5, color='firebrick') + meanpointprops = dict(marker='D', markeredgecolor='black', + markerfacecolor='firebrick') + meanlineprops = dict(linestyle='--', linewidth=2.5, color='purple') + + fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(6, 6), sharey=True) + axes[0, 0].boxplot(data, boxprops=boxprops) + axes[0, 0].set_title('Custom boxprops', fontsize=fs) + + axes[0, 1].boxplot(data, flierprops=flierprops, medianprops=medianprops) + axes[0, 1].set_title('Custom medianprops\nand flierprops', fontsize=fs) + + axes[0, 2].boxplot(data, whis='range') + axes[0, 2].set_title('whis="range"', fontsize=fs) + + axes[1, 0].boxplot(data, meanprops=meanpointprops, meanline=False, + showmeans=True) + axes[1, 0].set_title('Custom mean\nas point', fontsize=fs) + + axes[1, 1].boxplot(data, meanprops=meanlineprops, meanline=True, + showmeans=True) + axes[1, 1].set_title('Custom mean\nas line', fontsize=fs) + + axes[1, 2].boxplot(data, whis=[15, 85]) + axes[1, 2].set_title('whis=[15, 85]\n#percentiles', fontsize=fs) + + for ax in axes.flatten(): + ax.set_yscale('log') + ax.set_yticklabels([]) + + fig.suptitle("I never said they'd be pretty") + fig.subplots_adjust(hspace=0.4) + return fig + + +def PyplotScatterWithLegend(): + import matplotlib.pyplot as plt + from numpy.random import rand + + fig, ax = plt.subplots() + for color in ['red', 'green', 'blue']: + n = 750 + x, y = rand(2, n) + scale = 200.0 * rand(n) + ax.scatter(x, y, c=color, s=scale, label=color, + alpha=0.3, edgecolors='none') + + ax.legend() + ax.grid(True) + return fig + + +def PyplotLineStyles(): + """ + ========== + Linestyles + ========== + + This examples showcases different linestyles copying those of Tikz/PGF. + """ + import numpy as np + import matplotlib.pyplot as plt + from collections import OrderedDict + from matplotlib.transforms import blended_transform_factory + + linestyles = OrderedDict( + [('solid', (0, ())), + ('loosely dotted', (0, (1, 10))), + ('dotted', (0, (1, 5))), + ('densely dotted', (0, (1, 1))), + + ('loosely dashed', (0, (5, 10))), + ('dashed', (0, (5, 5))), + ('densely dashed', (0, (5, 1))), + + ('loosely dashdotted', (0, (3, 10, 1, 10))), + ('dashdotted', (0, (3, 5, 1, 5))), + ('densely dashdotted', (0, (3, 1, 1, 1))), + + ('loosely dashdotdotted', (0, (3, 10, 1, 10, 1, 10))), + ('dashdotdotted', (0, (3, 5, 1, 5, 1, 5))), + ('densely dashdotdotted', (0, (3, 1, 1, 1, 1, 1)))]) + + plt.figure(figsize=(10, 6)) + ax = plt.subplot(1, 1, 1) + + X, Y = np.linspace(0, 100, 10), np.zeros(10) + for i, (name, linestyle) in enumerate(linestyles.items()): + ax.plot(X, Y + i, linestyle=linestyle, linewidth=1.5, color='black') + + ax.set_ylim(-0.5, len(linestyles) - 0.5) + plt.yticks(np.arange(len(linestyles)), linestyles.keys()) + plt.xticks([]) + + # For each line style, add a text annotation with a small offset from + # the reference point (0 in Axes coords, y tick value in Data coords). + reference_transform = blended_transform_factory(ax.transAxes, ax.transData) + for i, (name, linestyle) in enumerate(linestyles.items()): + ax.annotate(str(linestyle), xy=(0.0, i), xycoords=reference_transform, + xytext=(-6, -12), textcoords='offset points', color="blue", + fontsize=8, ha="right", family="monospace") + + plt.tight_layout() + return plt.gcf() + + +def PyplotLinePolyCollection(): + import matplotlib.pyplot as plt + from matplotlib import collections, colors, transforms + import numpy as np + + nverts = 50 + npts = 100 + + # Make some spirals + r = np.arange(nverts) + theta = np.linspace(0, 2 * np.pi, nverts) + xx = r * np.sin(theta) + yy = r * np.cos(theta) + spiral = np.column_stack([xx, yy]) + + # Fixing random state for reproducibility + rs = np.random.RandomState(19680801) + + # Make some offsets + xyo = rs.randn(npts, 2) + + # Make a list of colors cycling through the default series. + colors = [colors.to_rgba(c) + for c in plt.rcParams['axes.prop_cycle'].by_key()['color']] + + fig, axes = plt.subplots(2, 2) + fig.subplots_adjust(top=0.92, left=0.07, right=0.97, + hspace=0.3, wspace=0.3) + ((ax1, ax2), (ax3, ax4)) = axes # unpack the axes + + col = collections.LineCollection([spiral], offsets=xyo, + transOffset=ax1.transData) + trans = fig.dpi_scale_trans + transforms.Affine2D().scale(1.0 / 72.0) + col.set_transform(trans) # the points to pixels transform + # Note: the first argument to the collection initializer + # must be a list of sequences of x,y tuples; we have only + # one sequence, but we still have to put it in a list. + ax1.add_collection(col, autolim=True) + # autolim=True enables autoscaling. For collections with + # offsets like this, it is neither efficient nor accurate, + # but it is good enough to generate a plot that you can use + # as a starting point. If you know beforehand the range of + # x and y that you want to show, it is better to set them + # explicitly, leave out the autolim kwarg (or set it to False), + # and omit the 'ax1.autoscale_view()' call below. + + # Make a transform for the line segments such that their size is + # given in points: + col.set_color(colors) + + ax1.autoscale_view() # See comment above, after ax1.add_collection. + ax1.set_title('LineCollection using offsets') + + # The same data as above, but fill the curves. + col = collections.PolyCollection([spiral], offsets=xyo, + transOffset=ax2.transData) + trans = transforms.Affine2D().scale(fig.dpi / 72.0) + col.set_transform(trans) # the points to pixels transform + ax2.add_collection(col, autolim=True) + col.set_color(colors) + + ax2.autoscale_view() + ax2.set_title('PolyCollection using offsets') + + # 7-sided regular polygons + + col = collections.RegularPolyCollection( + 7, sizes=np.abs(xx) * 10.0, offsets=xyo, transOffset=ax3.transData) + trans = transforms.Affine2D().scale(fig.dpi / 72.0) + col.set_transform(trans) # the points to pixels transform + ax3.add_collection(col, autolim=True) + col.set_color(colors) + ax3.autoscale_view() + ax3.set_title('RegularPolyCollection using offsets') + + # Simulate a series of ocean current profiles, successively + # offset by 0.1 m/s so that they form what is sometimes called + # a "waterfall" plot or a "stagger" plot. + + nverts = 60 + ncurves = 20 + offs = (0.1, 0.0) + + yy = np.linspace(0, 2 * np.pi, nverts) + ym = np.max(yy) + xx = (0.2 + (ym - yy) / ym) ** 2 * np.cos(yy - 0.4) * 0.5 + segs = [] + for i in range(ncurves): + xxx = xx + 0.02 * rs.randn(nverts) + curve = np.column_stack([xxx, yy * 100]) + segs.append(curve) + + col = collections.LineCollection(segs, offsets=offs) + ax4.add_collection(col, autolim=True) + col.set_color(colors) + ax4.autoscale_view() + ax4.set_title('Successive data offsets') + ax4.set_xlabel('Zonal velocity component (m/s)') + ax4.set_ylabel('Depth (m)') + # Reverse the y-axis so depth increases downward + ax4.set_ylim(ax4.get_ylim()[::-1]) + return fig + + +def PyplotGGPlotSytleSheet(): + import numpy as np + import matplotlib.pyplot as plt + + plt.style.use('ggplot') + + # Fixing random state for reproducibility + np.random.seed(19680801) + + fig, axes = plt.subplots(ncols=2, nrows=2) + ax1, ax2, ax3, ax4 = axes.ravel() + + # scatter plot (Note: `plt.scatter` doesn't use default colors) + x, y = np.random.normal(size=(2, 200)) + ax1.plot(x, y, 'o') + + # sinusoidal lines with colors from default color cycle + L = 2 * np.pi + x = np.linspace(0, L) + ncolors = len(plt.rcParams['axes.prop_cycle']) + shift = np.linspace(0, L, ncolors, endpoint=False) + for s in shift: + ax2.plot(x, np.sin(x + s), '-') + ax2.margins(0) + + # bar graphs + x = np.arange(5) + y1, y2 = np.random.randint(1, 25, size=(2, 5)) + width = 0.25 + ax3.bar(x, y1, width) + ax3.bar(x + width, y2, width, + color=list(plt.rcParams['axes.prop_cycle'])[2]['color']) + ax3.set_xticks(x + width) + ax3.set_xticklabels(['a', 'b', 'c', 'd', 'e']) + + # circles with colors from default color cycle + for i, color in enumerate(plt.rcParams['axes.prop_cycle']): + xy = np.random.normal(size=2) + ax4.add_patch(plt.Circle(xy, radius=0.3, color=color['color'])) + ax4.axis('equal') + ax4.margins(0) + fig = plt.gcf() # get the figure to show + return fig + + +def PyplotBoxPlot(): + import numpy as np + import matplotlib.pyplot as plt + + # Fixing random state for reproducibility + np.random.seed(19680801) + + # fake up some data + spread = np.random.rand(50) * 100 + center = np.ones(25) * 50 + flier_high = np.random.rand(10) * 100 + 100 + flier_low = np.random.rand(10) * -100 + data = np.concatenate((spread, center, flier_high, flier_low), 0) + fig1, ax1 = plt.subplots() + ax1.set_title('Basic Plot') + ax1.boxplot(data) + return fig1 + + +def PyplotRadarChart(): + import numpy as np + + import matplotlib.pyplot as plt + from matplotlib.path import Path + from matplotlib.spines import Spine + from matplotlib.projections.polar import PolarAxes + from matplotlib.projections import register_projection + + def radar_factory(num_vars, frame='circle'): + """Create a radar chart with `num_vars` axes. + + This function creates a RadarAxes projection and registers it. + + Parameters + ---------- + num_vars : int + Number of variables for radar chart. + frame : {'circle' | 'polygon'} + Shape of frame surrounding axes. + + """ + # calculate evenly-spaced axis angles + theta = np.linspace(0, 2 * np.pi, num_vars, endpoint=False) + + def draw_poly_patch(self): + # rotate theta such that the first axis is at the top + verts = unit_poly_verts(theta + np.pi / 2) + return plt.Polygon(verts, closed=True, edgecolor='k') + + def draw_circle_patch(self): + # unit circle centered on (0.5, 0.5) + return plt.Circle((0.5, 0.5), 0.5) + + patch_dict = {'polygon': draw_poly_patch, 'circle': draw_circle_patch} + if frame not in patch_dict: + raise ValueError('unknown value for `frame`: %s' % frame) + + class RadarAxes(PolarAxes): + + name = 'radar' + # use 1 line segment to connect specified points + RESOLUTION = 1 + # define draw_frame method + draw_patch = patch_dict[frame] + + def __init__(self, *args, **kwargs): + super(RadarAxes, self).__init__(*args, **kwargs) + # rotate plot such that the first axis is at the top + self.set_theta_zero_location('N') + + def fill(self, *args, **kwargs): + """Override fill so that line is closed by default""" + closed = kwargs.pop('closed', True) + return super(RadarAxes, self).fill(closed=closed, *args, **kwargs) + + def plot(self, *args, **kwargs): + """Override plot so that line is closed by default""" + lines = super(RadarAxes, self).plot(*args, **kwargs) + for line in lines: + self._close_line(line) + + def _close_line(self, line): + x, y = line.get_data() + # FIXME: markers at x[0], y[0] get doubled-up + if x[0] != x[-1]: + x = np.concatenate((x, [x[0]])) + y = np.concatenate((y, [y[0]])) + line.set_data(x, y) + + def set_varlabels(self, labels): + self.set_thetagrids(np.degrees(theta), labels) + + def _gen_axes_patch(self): + return self.draw_patch() + + def _gen_axes_spines(self): + if frame == 'circle': + return PolarAxes._gen_axes_spines(self) + # The following is a hack to get the spines (i.e. the axes frame) + # to draw correctly for a polygon frame. + + # spine_type must be 'left', 'right', 'top', 'bottom', or `circle`. + spine_type = 'circle' + verts = unit_poly_verts(theta + np.pi / 2) + # close off polygon by repeating first vertex + verts.append(verts[0]) + path = Path(verts) + + spine = Spine(self, spine_type, path) + spine.set_transform(self.transAxes) + return {'polar': spine} + + register_projection(RadarAxes) + return theta + + def unit_poly_verts(theta): + """Return vertices of polygon for subplot axes. + + This polygon is circumscribed by a unit circle centered at (0.5, 0.5) + """ + x0, y0, r = [0.5] * 3 + verts = [(r * np.cos(t) + x0, r * np.sin(t) + y0) for t in theta] + return verts + + def example_data(): + # The following data is from the Denver Aerosol Sources and Health study. + # See doi:10.1016/j.atmosenv.2008.12.017 + # + # The data are pollution source profile estimates for five modeled + # pollution sources (e.g., cars, wood-burning, etc) that emit 7-9 chemical + # species. The radar charts are experimented with here to see if we can + # nicely visualize how the modeled source profiles change across four + # scenarios: + # 1) No gas-phase species present, just seven particulate counts on + # Sulfate + # Nitrate + # Elemental Carbon (EC) + # Organic Carbon fraction 1 (OC) + # Organic Carbon fraction 2 (OC2) + # Organic Carbon fraction 3 (OC3) + # Pyrolized Organic Carbon (OP) + # 2)Inclusion of gas-phase specie carbon monoxide (CO) + # 3)Inclusion of gas-phase specie ozone (O3). + # 4)Inclusion of both gas-phase species is present... + data = [ + ['Sulfate', 'Nitrate', 'EC', 'OC1', 'OC2', 'OC3', 'OP', 'CO', 'O3'], + ('Basecase', [ + [0.88, 0.01, 0.03, 0.03, 0.00, 0.06, 0.01, 0.00, 0.00], + [0.07, 0.95, 0.04, 0.05, 0.00, 0.02, 0.01, 0.00, 0.00], + [0.01, 0.02, 0.85, 0.19, 0.05, 0.10, 0.00, 0.00, 0.00], + [0.02, 0.01, 0.07, 0.01, 0.21, 0.12, 0.98, 0.00, 0.00], + [0.01, 0.01, 0.02, 0.71, 0.74, 0.70, 0.00, 0.00, 0.00]]), + ('With CO', [ + [0.88, 0.02, 0.02, 0.02, 0.00, 0.05, 0.00, 0.05, 0.00], + [0.08, 0.94, 0.04, 0.02, 0.00, 0.01, 0.12, 0.04, 0.00], + [0.01, 0.01, 0.79, 0.10, 0.00, 0.05, 0.00, 0.31, 0.00], + [0.00, 0.02, 0.03, 0.38, 0.31, 0.31, 0.00, 0.59, 0.00], + [0.02, 0.02, 0.11, 0.47, 0.69, 0.58, 0.88, 0.00, 0.00]]), + ('With O3', [ + [0.89, 0.01, 0.07, 0.00, 0.00, 0.05, 0.00, 0.00, 0.03], + [0.07, 0.95, 0.05, 0.04, 0.00, 0.02, 0.12, 0.00, 0.00], + [0.01, 0.02, 0.86, 0.27, 0.16, 0.19, 0.00, 0.00, 0.00], + [0.01, 0.03, 0.00, 0.32, 0.29, 0.27, 0.00, 0.00, 0.95], + [0.02, 0.00, 0.03, 0.37, 0.56, 0.47, 0.87, 0.00, 0.00]]), + ('CO & O3', [ + [0.87, 0.01, 0.08, 0.00, 0.00, 0.04, 0.00, 0.00, 0.01], + [0.09, 0.95, 0.02, 0.03, 0.00, 0.01, 0.13, 0.06, 0.00], + [0.01, 0.02, 0.71, 0.24, 0.13, 0.16, 0.00, 0.50, 0.00], + [0.01, 0.03, 0.00, 0.28, 0.24, 0.23, 0.00, 0.44, 0.88], + [0.02, 0.00, 0.18, 0.45, 0.64, 0.55, 0.86, 0.00, 0.16]]) + ] + return data + + N = 9 + theta = radar_factory(N, frame='polygon') + + data = example_data() + spoke_labels = data.pop(0) + + fig, axes = plt.subplots(figsize=(9, 9), nrows=2, ncols=2, + subplot_kw=dict(projection='radar')) + fig.subplots_adjust(wspace=0.25, hspace=0.20, top=0.85, bottom=0.05) + + colors = ['b', 'r', 'g', 'm', 'y'] + # Plot the four cases from the example data on separate axes + for ax, (title, case_data) in zip(axes.flatten(), data): + ax.set_rgrids([0.2, 0.4, 0.6, 0.8]) + ax.set_title(title, weight='bold', size='medium', position=(0.5, 1.1), + horizontalalignment='center', verticalalignment='center') + for d, color in zip(case_data, colors): + ax.plot(theta, d, color=color) + ax.fill(theta, d, facecolor=color, alpha=0.25) + ax.set_varlabels(spoke_labels) + + # add legend relative to top-left plot + ax = axes[0, 0] + labels = ('Factor 1', 'Factor 2', 'Factor 3', 'Factor 4', 'Factor 5') + legend = ax.legend(labels, loc=(0.9, .95), + labelspacing=0.1, fontsize='small') + + fig.text(0.5, 0.965, '5-Factor Solution Profiles Across Four Scenarios', + horizontalalignment='center', color='black', weight='bold', + size='large') + return fig + + +def DifferentScales(): + import numpy as np + import matplotlib.pyplot as plt + + # Create some mock data + t = np.arange(0.01, 10.0, 0.01) + data1 = np.exp(t) + data2 = np.sin(2 * np.pi * t) + + fig, ax1 = plt.subplots() + + color = 'tab:red' + ax1.set_xlabel('time (s)') + ax1.set_ylabel('exp', color=color) + ax1.plot(t, data1, color=color) + ax1.tick_params(axis='y', labelcolor=color) + + ax2 = ax1.twinx() # instantiate a second axes that shares the same x-axis + + color = 'tab:blue' + ax2.set_ylabel('sin', color=color) # we already handled the x-label with ax1 + ax2.plot(t, data2, color=color) + ax2.tick_params(axis='y', labelcolor=color) + + fig.tight_layout() # otherwise the right y-label is slightly clipped + return fig + + +def ExploringNormalizations(): + import matplotlib.pyplot as plt + import matplotlib.colors as mcolors + import numpy as np + from numpy.random import multivariate_normal + + data = np.vstack([ + multivariate_normal([10, 10], [[3, 2], [2, 3]], size=100000), + multivariate_normal([30, 20], [[2, 3], [1, 3]], size=1000) + ]) + + gammas = [0.8, 0.5, 0.3] + + fig, axes = plt.subplots(nrows=2, ncols=2) + + axes[0, 0].set_title('Linear normalization') + axes[0, 0].hist2d(data[:, 0], data[:, 1], bins=100) + + for ax, gamma in zip(axes.flat[1:], gammas): + ax.set_title(r'Power law $(\gamma=%1.1f)$' % gamma) + ax.hist2d(data[:, 0], data[:, 1], + bins=100, norm=mcolors.PowerNorm(gamma)) + + fig.tight_layout() + return fig + + +def PyplotFormatstr(): + def f(t): + return np.exp(-t) * np.cos(2 * np.pi * t) + + t1 = np.arange(0.0, 5.0, 0.1) + t2 = np.arange(0.0, 5.0, 0.02) + + plt.figure(1) + plt.subplot(211) + plt.plot(t1, f(t1), 'bo', t2, f(t2), 'k') + + plt.subplot(212) + plt.plot(t2, np.cos(2 * np.pi * t2), 'r--') + fig = plt.gcf() # get the figure to show + return fig + + +def UnicodeMinus(): + import numpy as np + import matplotlib + import matplotlib.pyplot as plt + + # Fixing random state for reproducibility + np.random.seed(19680801) + + matplotlib.rcParams['axes.unicode_minus'] = False + fig, ax = plt.subplots() + ax.plot(10 * np.random.randn(100), 10 * np.random.randn(100), 'o') + ax.set_title('Using hyphen instead of Unicode minus') + return fig + + +def Subplot3d(): + from mpl_toolkits.mplot3d.axes3d import Axes3D + from matplotlib import cm + # from matplotlib.ticker import LinearLocator, FixedLocator, FormatStrFormatter + import matplotlib.pyplot as plt + import numpy as np + + fig = plt.figure() + + ax = fig.add_subplot(1, 2, 1, projection='3d') + X = np.arange(-5, 5, 0.25) + Y = np.arange(-5, 5, 0.25) + X, Y = np.meshgrid(X, Y) + R = np.sqrt(X ** 2 + Y ** 2) + Z = np.sin(R) + surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.jet, + linewidth=0, antialiased=False) + ax.set_zlim3d(-1.01, 1.01) + + # ax.w_zaxis.set_major_locator(LinearLocator(10)) + # ax.w_zaxis.set_major_formatter(FormatStrFormatter('%.03f')) + + fig.colorbar(surf, shrink=0.5, aspect=5) + + from mpl_toolkits.mplot3d.axes3d import get_test_data + ax = fig.add_subplot(1, 2, 2, projection='3d') + X, Y, Z = get_test_data(0.05) + ax.plot_wireframe(X, Y, Z, rstride=10, cstride=10) + return fig + + +def PyplotScales(): + import numpy as np + import matplotlib.pyplot as plt + + from matplotlib.ticker import NullFormatter # useful for `logit` scale + + # Fixing random state for reproducibility + np.random.seed(19680801) + + # make up some data in the interval ]0, 1[ + y = np.random.normal(loc=0.5, scale=0.4, size=1000) + y = y[(y > 0) & (y < 1)] + y.sort() + x = np.arange(len(y)) + + # plot with various axes scales + plt.figure(1) + + # linear + plt.subplot(221) + plt.plot(x, y) + plt.yscale('linear') + plt.title('linear') + plt.grid(True) + + # log + plt.subplot(222) + plt.plot(x, y) + plt.yscale('log') + plt.title('log') + plt.grid(True) + + # symmetric log + plt.subplot(223) + plt.plot(x, y - y.mean()) + plt.yscale('symlog', linthreshy=0.01) + plt.title('symlog') + plt.grid(True) + + # logit + plt.subplot(224) + plt.plot(x, y) + plt.yscale('logit') + plt.title('logit') + plt.grid(True) + # Format the minor tick labels of the y-axis into empty strings with + # `NullFormatter`, to avoid cumbering the axis with too many labels. + plt.gca().yaxis.set_minor_formatter(NullFormatter()) + # Adjust the subplot layout, because the logit one may take more space + # than usual, due to y-tick labels like "1 - 10^{-3}" + plt.subplots_adjust(top=0.92, bottom=0.08, left=0.10, right=0.95, hspace=0.25, + wspace=0.35) + return plt.gcf() + + +def AxesGrid(): + import numpy as np + import matplotlib.pyplot as plt + from mpl_toolkits.axes_grid1.axes_rgb import RGBAxes + + def get_demo_image(): + # prepare image + delta = 0.5 + + extent = (-3, 4, -4, 3) + x = np.arange(-3.0, 4.001, delta) + y = np.arange(-4.0, 3.001, delta) + X, Y = np.meshgrid(x, y) + Z1 = np.exp(-X ** 2 - Y ** 2) + Z2 = np.exp(-(X - 1) ** 2 - (Y - 1) ** 2) + Z = (Z1 - Z2) * 2 + + return Z, extent + + def get_rgb(): + Z, extent = get_demo_image() + + Z[Z < 0] = 0. + Z = Z / Z.max() + + R = Z[:13, :13] + G = Z[2:, 2:] + B = Z[:13, 2:] + + return R, G, B + + fig = plt.figure(1) + ax = RGBAxes(fig, [0.1, 0.1, 0.8, 0.8]) + + r, g, b = get_rgb() + kwargs = dict(origin="lower", interpolation="nearest") + ax.imshow_rgb(r, g, b, **kwargs) + + ax.RGB.set_xlim(0., 9.5) + ax.RGB.set_ylim(0.9, 10.6) + + plt.draw() + return plt.gcf() + + +# ---------------------------- Beginning of PySimpleGUI program ---------------------------- + +# ---------------------------- draw_figure (the helper function) ---------------------------- +def draw_figure(fig, element): + """ + Draws the previously created "figure" in the supplied Image Element + + :param fig: a Matplotlib figure + :param element: an Image Element + :return: The figure canvas + """ + + plt.close('all') # erases previously drawn plots + canv = FigureCanvasAgg(fig) + buf = io.BytesIO() + canv.print_figure(buf, format='png') + if buf is None: + return None + buf.seek(0) + element.update(data=buf.read()) + return canv + + +# -------------------------------- GUI Starts Here -------------------------------# +def main(): + + fig_dict = {'Pyplot Simple': PyplotSimple, 'Pyplot Formatstr': PyplotFormatstr, 'PyPlot Three': Subplot3d, + 'Unicode Minus': UnicodeMinus, 'Pyplot Scales': PyplotScales, 'Axes Grid': AxesGrid, + 'Exploring Normalizations': ExploringNormalizations, 'Different Scales': DifferentScales, + 'Pyplot Box Plot': PyplotBoxPlot, 'Pyplot ggplot Style Sheet': PyplotGGPlotSytleSheet, + 'Pyplot Line Poly Collection': PyplotLinePolyCollection, 'Pyplot Line Styles': PyplotLineStyles, + 'Pyplot Scatter With Legend': PyplotScatterWithLegend, 'Artist Customized Box Plots': PyplotArtistBoxPlots, + 'Artist Customized Box Plots 2': ArtistBoxplot2, 'Pyplot Histogram': PyplotHistogram} + + # define the layout + + col_listbox = [[sg.Listbox(values=fig_dict.keys(), enable_events=True, size=(25, len(fig_dict.keys())), key='-LISTBOX-')], + [sg.Exit(size=(5, 2))]] + + layout = [[sg.Text('Matplotlib Plot Browser', font=('current 25'))], + [sg.Text('Choose a plot from the list to see the plot and the source code used to make it.')], + [sg.Column(col_listbox, element_justification='c'), sg.Image(key='-IMAGE-'), + sg.MLine(size=(40, 20), font='Courier 12', key='-MULTILINE-')], ] + + # create the window + window = sg.Window('Embedding Matplotlib In PySimpleGUIWeb', layout) + + while True: # The event loop + event, values = window.read() + # print(event, values) # helps greatly when debugging + if event in (sg.WIN_CLOSED, 'Exit'): # if user closed window or clicked Exit button + break + + choice = values['-LISTBOX-'][0] # get first listbox item chosen (returned as a list) + the_plotting_func = fig_dict[choice] # get function to call from the dictionary + window['-MULTILINE-'].update(inspect.getsource(the_plotting_func)) # show source code to function in multiline + draw_figure(the_plotting_func(), window['-IMAGE-']) # draw the figure + window.close() + + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/PySimpleGUIWeb/Demo Programs/Web_Matplotlib_Simple.py b/PySimpleGUIWeb/Demo Programs/Web_Matplotlib_Simple.py new file mode 100644 index 000000000..88b4cca94 --- /dev/null +++ b/PySimpleGUIWeb/Demo Programs/Web_Matplotlib_Simple.py @@ -0,0 +1,58 @@ +import PySimpleGUIWeb as sg +import numpy as np +from matplotlib.backends.backend_tkagg import FigureCanvasAgg +import matplotlib.figure +import matplotlib.pyplot as plt +import io + + +def create_figure(): + # ------------------------------- START OF YOUR MATPLOTLIB CODE ------------------------------- + fig = matplotlib.figure.Figure(figsize=(5, 4), dpi=100) + t = np.arange(0, 3, .01) + fig.add_subplot(111).plot(t, 2 * np.sin(2 * np.pi * t)) + + return fig + + +def draw_figure(element, fig): + """ + Draws the previously created "figure" in the supplied Image Element + + :param element: an Image Element + :param fig: a Matplotlib figure + :return: The figure canvas + """ + + plt.close('all') # erases previously drawn plots + canv = FigureCanvasAgg(fig) + buf = io.BytesIO() + canv.print_figure(buf, format='png') + if buf is None: + return None + buf.seek(0) + element.update(data=buf.read()) + return canv + + +def main(): + + layout = [ + [sg.T('Matplotlib Example', font='Any 20')], + [sg.Image(key='-IMAGE-')], + [sg.B('Draw'), sg.B('Exit')], + ] + + window = sg.Window('Title', layout) + + while True: + event, values = window.read() + if event == 'Exit' or event == sg.WIN_CLOSED: + break + if event == 'Draw': + draw_figure(window['-IMAGE-'], create_figure()) + window.close() + + +if __name__ == "__main__": + main() diff --git a/PySimpleGUIWeb/Demo Programs/Web_Matplotlib_Simple_PyPlot.py b/PySimpleGUIWeb/Demo Programs/Web_Matplotlib_Simple_PyPlot.py new file mode 100644 index 000000000..2148b3e5d --- /dev/null +++ b/PySimpleGUIWeb/Demo Programs/Web_Matplotlib_Simple_PyPlot.py @@ -0,0 +1,45 @@ +import PySimpleGUIWeb as sg +import numpy as np +from matplotlib.backends.backend_tkagg import FigureCanvasAgg +import matplotlib.pyplot as plt +import io + + +def draw_figure(fig, element): + """ + Draws the previously created "figure" in the supplied Image Element + + :param fig: a Matplotlib figure + :param element: an Image Element + :return: The figure canvas + """ + + plt.close('all') # erases previously drawn plots + canv = FigureCanvasAgg(fig) + buf = io.BytesIO() + canv.print_figure(buf, format='png') + if buf is None: + return None + buf.seek(0) + element.update(data=buf.read()) + return canv + + +def main(): + layout = [[sg.Text('Matplotlib Simple Plot', font='Any 20')], + [sg.Image(key='-IMAGE-')], + [sg.Button('Exit')]] + + window = sg.Window('Matplotlib Example', layout, finalize=True) + + fig = plt.figure() + x = np.arange(0, 5, 0.1) + y = np.sin(x) + plt.plot(x, y) + draw_figure(fig, window['-IMAGE-']) + + window.read(close=True) + + +if __name__ == "__main__": + main() diff --git a/PySimpleGUIWeb/Demo Programs/Web_Popup.py b/PySimpleGUIWeb/Demo Programs/Web_Popup.py new file mode 100644 index 000000000..c6d7a6eba --- /dev/null +++ b/PySimpleGUIWeb/Demo Programs/Web_Popup.py @@ -0,0 +1,35 @@ +import PySimpleGUIWeb as sg + +""" + ____ + | _ \ ___ _ __ _ _ _ __ + | |_) / _ \| '_ \| | | | '_ \ + | __/ (_) | |_) | |_| | |_) | + |_| \___/| .__/ \__,_| .__/ + |_| |_| + +A Popup demonstration. A "Popup" window is shown over the main +window. Clicking OK will close the Popup and you return to main again. +""" + +print('Starting up...') + +layout = [ + [sg.Text('Your typed chars appear here:'), sg.Text('', key='_OUTPUT_')], + [sg.Input('', key='_IN_')], + [sg.Button('Show'), sg.Button('Exit'), sg.Button('Blank')] +] + +window = sg.Window('Window Title', layout) + +while True: # Event Loop + print('in event loop') + event, values = window.read() + + print(event, values) + if event in (None, 'Exit'): + break + if event == 'Show': + sg.popup('A popup!', ' You typed ', values['_IN_']) + +window.close() diff --git a/PySimpleGUIWeb/Demo Programs/Web_Simple.py b/PySimpleGUIWeb/Demo Programs/Web_Simple.py new file mode 100644 index 000000000..dd4d39a35 --- /dev/null +++ b/PySimpleGUIWeb/Demo Programs/Web_Simple.py @@ -0,0 +1,28 @@ +import PySimpleGUIWeb as sg + +# Basic example of PSGWeb + +def main(): + layout = [ + [sg.Text('This is a text element')], + [sg.Input()], + [sg.Combo(['Combo 1'])], + [sg.Text('If you close the browser tab, the app will exit gracefully')], + [sg.InputText('Source')], + [sg.InputText('Dest')], + [sg.Ok(), sg.Cancel()] + ] + + window = sg.Window('Demo window..', layout) + i = 0 + while True: + event, values = window.read(timeout=1) + if event != sg.TIMEOUT_KEY: + print(event, values) + if event is None: + break + i += 1 + window.close() + +main() +print('Program terminating normally') diff --git a/PySimpleGUIWeb/Demo Programs/Web_Table_Element.py b/PySimpleGUIWeb/Demo Programs/Web_Table_Element.py new file mode 100644 index 000000000..eb3ef8865 --- /dev/null +++ b/PySimpleGUIWeb/Demo Programs/Web_Table_Element.py @@ -0,0 +1,43 @@ +import PySimpleGUIWeb as sg +import random +import string + +# Example with Table element + +def word(): + return ''.join(random.choice(string.ascii_lowercase) for i in range(10)) + +def number(max_val=1000): + return random.randint(0,max_val) + + +def make_table(num_rows, num_cols): + data = [[j for j in range(num_cols)] for i in range(num_rows)] + data[0] = [word() for _ in range(num_cols)] + for i in range(1, num_rows): + data[i] = [word(), *[number() for i in range(num_cols - 1)]] + return data + +table_data = make_table(num_rows=15, num_cols=6) + +# ------------------ Create a window layout ------------------ +layout = [[sg.Table(values=table_data, enable_events=True, + display_row_numbers=True, font='Courier 14', + row_header_text='Row #', key='_table_', text_color='red')], + [sg.Button('Exit')], + [sg.Text('Selected rows = '), sg.Text('', size=(30,1), key='_selected_rows_')], + [sg.Text('Selected value = '), sg.Text('', size=(30,1), key='_selected_value_')]] + +# ------------------ Create the window ------------------ +window = sg.Window('Table Element Example', layout) + +# ------------------ The Event Loop ------------------ +while True: + event, values = window.read() + print(event, values) + if event in (None, 'Exit'): + break + window['_selected_rows_'].update(values['_table_']) + window['_selected_value_'].update(window['_table_'].SelectedItem) +# ------------------ User closed window so exit ------------------ +window.close() diff --git a/PySimpleGUIWeb/Demo Programs/Web_Timer.py b/PySimpleGUIWeb/Demo Programs/Web_Timer.py new file mode 100644 index 000000000..51e475897 --- /dev/null +++ b/PySimpleGUIWeb/Demo Programs/Web_Timer.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python +import PySimpleGUIWeb as sg +import time + +# ---------------- Create Form ---------------- +layout = [ + [sg.Text('', background_color='black')], + [sg.Text('00:00', size=(30, 1), font=('Helvetica', 30), justification='center', + text_color='white', key='text', background_color='black')], + [sg.Text('', background_color='black')], + [sg.Button('Pause', key='button', button_color=('white', '#001480')), + sg.Button('Reset', button_color=('white', '#007339'), key='Reset'), + sg.Exit(button_color=('white', '#8B1A1A'), key='Exit', )], +] + +window = sg.Window('Running Timer', layout, + background_color='black', font='Helvetica 18') + +# ---------------- main loop ---------------- +current_time = 0 +paused = False +start_time = int(round(time.time() * 100)) +while True: + # --------- read and update window -------- + if not paused: + event, values = window.read(timeout=0) + current_time = int(round(time.time() * 100)) - start_time + else: + event, values = window.read() + print(event, values) if event != sg.TIMEOUT_KEY else None + + if event == 'button': + event = window[event].GetText() + # --------- Do Button Operations -------- + + if event in (None, 'Exit'): # ALWAYS give a way out of program + break + + if event == 'Reset': + start_time = int(round(time.time() * 100)) + current_time = 0 + paused_time = start_time + + elif event == 'Pause': + paused = True + paused_time = int(round(time.time() * 100)) + element = window['button'] + element.update(text='Run') + + elif event == 'Run': + paused = False + start_time = start_time + int(round(time.time() * 100)) - paused_time + element = window['button'] + element.update(text='Pause') + + # --------- Display timer in window -------- + window['text'].update('{:02d}:{:02d}.{:02d}'.format((current_time // 100) // 60, + (current_time // + 100) % 60, + current_time % 100)) +# --------- After loop -------- +window.close() diff --git a/PySimpleGUIWeb/Demo Programs/Web_Widget_Summary.py b/PySimpleGUIWeb/Demo Programs/Web_Widget_Summary.py new file mode 100644 index 000000000..5377a50cd --- /dev/null +++ b/PySimpleGUIWeb/Demo Programs/Web_Widget_Summary.py @@ -0,0 +1,50 @@ +import PySimpleGUIWeb as sg +import datetime + +DEFAULT_BASE64_ICON = b'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' + +layout = [ + [sg.Text('PySimpleGUIWeb running on the web and in your browser!', + size=(60, 1), font=('Comic sans ms', 20), text_color='red')], + [sg.Text('This program has been running for... ', size=(30, 1)), + sg.Text('', size=(30, 1), key='_DATE_')], + + [sg.Text('', size=(30, 1), key='_TEXT_')], + [sg.Input('Single Line Input', enable_events=True, size=(30, 1))], + # [sg.MultiLine('Multiline Input', size=(40, 4), enable_events=True)], + # [sg.MultiLine('Multiline Output', size=(80, 8), + # key='_MULTIOUT_', font='Courier 12')], + + [sg.CBox('Checkbox 1', enable_events=True, key='_CB1_'), + sg.CBox('Checkbox 2', default=True, + enable_events=True, key='_CB2_')], + + [sg.Combo(values=['Combo 1', 'Combo 2', 'Combo 3'], default_value='Combo 2', key='_COMBO_', + enable_events=True, readonly=False, tooltip='Combo box', disabled=False, size=(12, 1))], + + [sg.Listbox(values=('Listbox 1', 'Listbox 2', + 'Listbox 3'), size=(10, 3))], + + [sg.Slider((1, 100), default_value=80, key='_SLIDER_', + visible=True, enable_events=True, orientation='h')], + + [sg.Spin(values=(1, 2, 3), initial_value=2, size=(4, 1))], + [sg.Image(filename=r'dot:logo.jpg')], + [sg.OK(), sg.Button('Exit', button_color=('white', 'red'))] +] + +window = sg.Window('My PySimpleGUIWeb Window', layout, + default_element_size=(30, 1), font='Helvetica 18') + +start_time = datetime.datetime.now() +while True: + event, values = window.read(timeout=10) + if event != sg.TIMEOUT_KEY: + print(event, values) + window['_MULTIOUT_'].update( + str(event) + '\n' + str(values), append=True) + if event in (None, 'Exit'): + break + window['_DATE_'].update(str(datetime.datetime.now()-start_time)) + +window.close() diff --git a/PySimpleGUIWeb/Demo Programs/Web_psutil_Kill_Processes.py b/PySimpleGUIWeb/Demo Programs/Web_psutil_Kill_Processes.py new file mode 100644 index 000000000..204c4507c --- /dev/null +++ b/PySimpleGUIWeb/Demo Programs/Web_psutil_Kill_Processes.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python +import PySimpleGUIWeb as sg +import os +import signal +import psutil +import operator + + +""" + Utility to show running processes, CPU usage and provides way to kill processes. + Based on psutil package that is easily installed using pip +""" + + +def kill_proc_tree(pid, sig=signal.SIGTERM, include_parent=True, + timeout=None, on_terminate=None): + """Kill a process tree (including grandchildren) with signal + "sig" and return a (gone, still_alive) tuple. + "on_terminate", if specified, is a callabck function which is + called as soon as a child terminates. + """ + if pid == os.getpid(): + raise RuntimeError("I refuse to kill myself") + parent = psutil.Process(pid) + children = parent.children(recursive=True) + if include_parent: + children.append(parent) + for p in children: + p.send_signal(sig) + gone, alive = psutil.wait_procs(children, timeout=timeout, + callback=on_terminate) + return (gone, alive) + + +def main(): + + layout = [[sg.Text('Process Killer - Choose one or more processes', + size=(45, 1), font=('Helvetica', 15), text_color='red')], + + [sg.Listbox(values=[' '], size=(50, 30), + select_mode=sg.SELECT_MODE_EXTENDED, font=('Courier', 12), key='_processes_')], + + [sg.Text('Click refresh once or twice.. once for list, second to get CPU usage')], + [sg.Text('Filter by typing name', font='ANY 14'), sg.Input( + size=(15, 1), font='any 14', key='_filter_')], + + [sg.Button('Sort by Name', ), + sg.Button('Sort by % CPU', button_color=('white', 'DarkOrange2')), + sg.Button('Kill', button_color=('white', 'red'), bind_return_key=True), + sg.Exit(button_color=('white', 'sea green'))]] + + window = sg.Window('Process Killer', layout, + keep_on_top=True, auto_size_buttons=False, + default_button_element_size=(12, 1), return_keyboard_events=True) + + display_list = None + # ---------------- main loop ---------------- + while True: + # --------- Read and update window -------- + event, values = window.Read() + if event in (None, 'Exit'): + break + + # skip mouse, control key and shift key events entirely + if 'Mouse' in event or 'Control' in event or 'Shift' in event: + continue + print(event, values) + # --------- Do Button Operations -------- + if event == 'Sort by Name': + psutil.cpu_percent(interval=.1) + procs = psutil.process_iter() + all_procs = [[proc.cpu_percent(), proc.name(), proc.pid] + for proc in procs] + sorted_by_cpu_procs = sorted( + all_procs, key=operator.itemgetter(1), reverse=False) + display_list = [] + for process in sorted_by_cpu_procs: + display_list.append('{:5d} {:5.2f} {}\n'.format( + process[2], process[0]/10, process[1])) + window['_processes_'].update(display_list) + print(display_list) + elif event == 'Kill': + processes_to_kill = values['_processes_'] + for proc in processes_to_kill: + pid = int(proc[0:5]) + # if sg.popupYesNo('About to kill {} {}'.format(pid, proc[12:]), keep_on_top=True) == 'Yes': + try: + kill_proc_tree(pid=pid) + except: + sg.popup_auto_close( + 'Error killing process', auto_close_duration=1) + elif event == 'Sort by % CPU': + psutil.cpu_percent(interval=.1) + procs = psutil.process_iter() + all_procs = [[proc.cpu_percent(), proc.name(), proc.pid] + for proc in procs] + sorted_by_cpu_procs = sorted( + all_procs, key=operator.itemgetter(0), reverse=True) + display_list = [] + for process in sorted_by_cpu_procs: + display_list.append('{:5d} {:5.2f} {}\n'.format( + process[2], process[0]/10, process[1])) + window['_processes_'].update(display_list) + else: # was a typed character + if display_list is not None: + new_output = [] + for line in display_list: + if values['_filter_'] in line.lower(): + new_output.append(line) + window['_processes_'].update(new_output) + window.close() + +if __name__ == "__main__": + main() diff --git a/PySimpleGUIWeb/Demo Programs/logo.jpg b/PySimpleGUIWeb/Demo Programs/logo.jpg new file mode 100644 index 000000000..ead39fe58 Binary files /dev/null and b/PySimpleGUIWeb/Demo Programs/logo.jpg differ diff --git a/PySimpleGUIWeb/Demo Programs/widgets_overview_app.py b/PySimpleGUIWeb/Demo Programs/widgets_overview_app.py new file mode 100644 index 000000000..6eca2d964 --- /dev/null +++ b/PySimpleGUIWeb/Demo Programs/widgets_overview_app.py @@ -0,0 +1,361 @@ +""" + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +""" + +import remi.gui as gui +from remi import start, App +from threading import Timer + + +class MyApp(App): + def __init__(self, *args): + super(MyApp, self).__init__(*args) + + def idle(self): + self.counter.set_text('Running Time: ' + str(self.count)) + self.progress.set_value(self.count % 100) + + def main(self): + # the margin 0px auto centers the main container + verticalContainer = gui.Widget(width=540, margin='0px auto', style={ + 'display': 'block', 'overflow': 'hidden'}) + + horizontalContainer = gui.Widget(width='100%', layout_orientation=gui.Widget.LAYOUT_HORIZONTAL, + margin='0px', style={'display': 'block', 'overflow': 'auto'}) + + subContainerLeft = gui.Widget(width=320, + style={'display': 'block', 'overflow': 'auto', 'text-align': 'center'}) + self.img = gui.Image('/res:logo.png', height=100, margin='10px') + self.img.onclick.connect(self.on_img_clicked) + + self.table = gui.Table.new_from_list([('ID', 'First Name', 'Last Name'), + ('101', 'Danny', 'Young'), + ('102', 'Christine', 'Holand'), + ('103', 'Lars', 'Gordon'), + ('104', 'Roberto', 'Robitaille'), + ('105', 'Maria', 'Papadopoulos')], + width=300, height=200, margin='10px') + self.table.on_table_row_click.connect(self.on_table_row_click) + + # the arguments are width - height - layoutOrientationOrizontal + subContainerRight = gui.Widget( + style={'width': '220px', 'display': 'block', + 'overflow': 'auto', 'text-align': 'center'}) + self.count = 0 + self.counter = gui.Label('', width=200, height=30, margin='10px') + + self.lbl = gui.Label('This is a LABEL!', width=200, + height=30, margin='10px') + + self.bt = gui.Button('Press me!', width=200, height=30, margin='10px') + # setting the listener for the onclick event of the button + self.bt.onclick.connect(self.on_button_pressed) + + self.txt = gui.TextInput(width=200, height=30, margin='10px') + self.txt.set_text('This is a TEXTAREA') + self.txt.onchange.connect(self.on_text_area_change) + + self.spin = gui.SpinBox(1, 0, 100, width=200, height=30, margin='10px') + self.spin.onchange.connect(self.on_spin_change) + + self.progress = gui.Progress(1, 100, width=200, height=5) + + self.check = gui.CheckBoxLabel( + 'Label checkbox', True, width=200, height=30, margin='10px') + self.check.onchange.connect(self.on_check_change) + + self.btInputDiag = gui.Button( + 'Open InputDialog', width=200, height=30, margin='10px') + self.btInputDiag.onclick.connect(self.open_input_dialog) + + self.btFileDiag = gui.Button( + 'File Selection Dialog', width=200, height=30, margin='10px') + self.btFileDiag.onclick.connect(self.open_fileselection_dialog) + + self.btUploadFile = gui.FileUploader( + './', width=200, height=30, margin='10px') + self.btUploadFile.onsuccess.connect(self.fileupload_on_success) + self.btUploadFile.onfailed.connect(self.fileupload_on_failed) + + items = ('Danny Young', 'Christine Holand', + 'Lars Gordon', 'Roberto Robitaille') + self.listView = gui.ListView.new_from_list( + items, width=300, height=120, margin='10px') + self.listView.onselection.connect(self.list_view_on_selected) + + self.link = gui.Link("http://localhost:8081", "A link to here", + width=200, height=30, margin='10px') + + self.dropDown = gui.DropDown.new_from_list( + ('DropDownItem 0', 'DropDownItem 1'), width=200, height=20, margin='10px') + self.dropDown.onchange.connect(self.drop_down_changed) + self.dropDown.select_by_value('DropDownItem 0') + + self.slider = gui.Slider( + 10, 0, 100, 5, width=200, height=20, margin='10px') + self.slider.onchange.connect(self.slider_changed) + + self.colorPicker = gui.ColorPicker( + '#ffbb00', width=200, height=20, margin='10px') + self.colorPicker.onchange.connect(self.color_picker_changed) + + self.date = gui.Date('2015-04-13', width=200, height=20, margin='10px') + self.date.onchange.connect(self.date_changed) + + self.video = gui.Widget(_type='iframe', width=290, + height=200, margin='10px') + self.video.attributes['src'] = "https://drive.google.com/file/d/0B0J9Lq_MRyn4UFRsblR3UTBZRHc/preview" + self.video.attributes['width'] = '100%' + self.video.attributes['height'] = '100%' + self.video.attributes['controls'] = 'true' + self.video.style['border'] = 'none' + + self.tree = gui.TreeView(width='100%', height=300) + ti1 = gui.TreeItem("Item1") + ti2 = gui.TreeItem("Item2") + ti3 = gui.TreeItem("Item3") + subti1 = gui.TreeItem("Sub Item1") + subti2 = gui.TreeItem("Sub Item2") + subti3 = gui.TreeItem("Sub Item3") + subti4 = gui.TreeItem("Sub Item4") + subsubti1 = gui.TreeItem("Sub Sub Item1") + subsubti2 = gui.TreeItem("Sub Sub Item2") + subsubti3 = gui.TreeItem("Sub Sub Item3") + self.tree.append([ti1, ti2, ti3]) + ti2.append([subti1, subti2, subti3, subti4]) + subti4.append([subsubti1, subsubti2, subsubti3]) + + # appending a widget to another, the first argument is a string key + subContainerRight.append([self.counter, self.lbl, self.bt, self.txt, + self.spin, self.progress, self.check, self.btInputDiag, self.btFileDiag]) + # use a defined key as we replace this widget later + fdownloader = gui.FileDownloader( + 'download test', '../remi/res/logo.png', width=200, height=30, margin='10px') + subContainerRight.append(fdownloader, key='file_downloader') + subContainerRight.append( + [self.btUploadFile, self.dropDown, self.slider, self.colorPicker, self.date, self.tree]) + self.subContainerRight = subContainerRight + + subContainerLeft.append( + [self.img, self.table, self.listView, self.link, self.video]) + + horizontalContainer.append([subContainerLeft, subContainerRight]) + + menu = gui.Menu(width='100%', height='30px') + m1 = gui.MenuItem('File', width=100, height=30) + m2 = gui.MenuItem('View', width=100, height=30) + m2.onclick.connect(self.menu_view_clicked) + m11 = gui.MenuItem('Save', width=100, height=30) + m12 = gui.MenuItem('Open', width=100, height=30) + m12.onclick.connect(self.menu_open_clicked) + m111 = gui.MenuItem('Save', width=100, height=30) + m111.onclick.connect(self.menu_save_clicked) + m112 = gui.MenuItem('Save as', width=100, height=30) + m112.onclick.connect(self.menu_saveas_clicked) + m3 = gui.MenuItem('Dialog', width=100, height=30) + m3.onclick.connect(self.menu_dialog_clicked) + + menu.append([m1, m2, m3]) + m1.append([m11, m12]) + m11.append([m111, m112]) + + menubar = gui.MenuBar(width='100%', height='30px') + menubar.append(menu) + + verticalContainer.append([menubar, horizontalContainer]) + + # this flag will be used to stop the display_counter Timer + self.stop_flag = False + + # kick of regular display of counter + self.display_counter() + + # returning the root widget + return verticalContainer + + def display_counter(self): + self.count += 1 + if not self.stop_flag: + Timer(1, self.display_counter).start() + + def menu_dialog_clicked(self, widget): + self.dialog = gui.GenericDialog( + title='Dialog Box', + message='Click Ok to transfer content to main page', width='500px') + self.dtextinput = gui.TextInput(width=200, height=30) + self.dtextinput.set_value('Initial Text') + self.dialog.add_field_with_label( + 'dtextinput', 'Text Input', self.dtextinput) + + self.dcheck = gui.CheckBox(False, width=200, height=30) + self.dialog.add_field_with_label( + 'dcheck', 'Label Checkbox', self.dcheck) + values = ('Danny Young', 'Christine Holand', + 'Lars Gordon', 'Roberto Robitaille') + self.dlistView = gui.ListView.new_from_list( + values, width=200, height=120) + self.dialog.add_field_with_label( + 'dlistView', 'Listview', self.dlistView) + + self.ddropdown = gui.DropDown.new_from_list(('DropDownItem 0', 'DropDownItem 1'), + width=200, height=20) + self.dialog.add_field_with_label( + 'ddropdown', 'Dropdown', self.ddropdown) + + self.dspinbox = gui.SpinBox(min=0, max=5000, width=200, height=20) + self.dspinbox.set_value(50) + self.dialog.add_field_with_label('dspinbox', 'Spinbox', self.dspinbox) + + self.dslider = gui.Slider(10, 0, 100, 5, width=200, height=20) + self.dspinbox.set_value(50) + self.dialog.add_field_with_label('dslider', 'Slider', self.dslider) + + self.dcolor = gui.ColorPicker(width=200, height=20) + self.dcolor.set_value('#ffff00') + self.dialog.add_field_with_label( + 'dcolor', 'Colour Picker', self.dcolor) + + self.ddate = gui.Date(width=200, height=20) + self.ddate.set_value('2000-01-01') + self.dialog.add_field_with_label('ddate', 'Date', self.ddate) + + self.dialog.confirm_dialog.connect(self.dialog_confirm) + self.dialog.show(self) + + def dialog_confirm(self, widget): + result = self.dialog.get_field('dtextinput').get_value() + self.txt.set_value(result) + + result = self.dialog.get_field('dcheck').get_value() + self.check.set_value(result) + + result = self.dialog.get_field('ddropdown').get_value() + self.dropDown.select_by_value(result) + + result = self.dialog.get_field('dspinbox').get_value() + self.spin.set_value(result) + + result = self.dialog.get_field('dslider').get_value() + self.slider.set_value(result) + + result = self.dialog.get_field('dcolor').get_value() + self.colorPicker.set_value(result) + + result = self.dialog.get_field('ddate').get_value() + self.date.set_value(result) + + result = self.dialog.get_field('dlistView').get_value() + self.listView.select_by_value(result) + + # listener function + def on_img_clicked(self, widget): + self.lbl.set_text('Image clicked!') + + def on_table_row_click(self, table, row, item): + self.lbl.set_text('Table Item clicked: ' + item.get_text()) + + def on_button_pressed(self, widget): + self.lbl.set_text('Button pressed! ') + self.bt.set_text('Hi!') + + def on_text_area_change(self, widget, newValue): + self.lbl.set_text('Text Area value changed!') + + def on_spin_change(self, widget, newValue): + self.lbl.set_text('SpinBox changed, new value: ' + str(newValue)) + + def on_check_change(self, widget, newValue): + self.lbl.set_text('CheckBox changed, new value: ' + str(newValue)) + + def open_input_dialog(self, widget): + self.inputDialog = gui.InputDialog('Input Dialog', 'Your name?', + initial_value='type here', width=500, height=160) + self.inputDialog.confirm_value.connect( + self.on_input_dialog_confirm) + + # here is returned the Input Dialog widget, and it will be shown + self.inputDialog.show(self) + + def on_input_dialog_confirm(self, widget, value): + self.lbl.set_text('Hello ' + value) + + def open_fileselection_dialog(self, widget): + self.fileselectionDialog = gui.FileSelectionDialog('File Selection Dialog', + 'Select files and folders', False, '.') + self.fileselectionDialog.confirm_value.connect( + self.on_fileselection_dialog_confirm) + + # here is returned the Input Dialog widget, and it will be shown + self.fileselectionDialog.show(self) + + def on_fileselection_dialog_confirm(self, widget, filelist): + # a list() of filenames and folders is returned + self.lbl.set_text('Selected files: %s' % ','.join(filelist)) + if len(filelist): + f = filelist[0] + # replace the last download link + fdownloader = gui.FileDownloader( + "download selected", f, width=200, height=30) + self.subContainerRight.append(fdownloader, key='file_downloader') + + def list_view_on_selected(self, widget, selected_item_key): + """ The selection event of the listView, returns a key of the clicked event. + You can retrieve the item rapidly + """ + self.lbl.set_text('List selection: ' + + self.listView.children[selected_item_key].get_text()) + + def drop_down_changed(self, widget, value): + self.lbl.set_text('New Combo value: ' + value) + + def slider_changed(self, widget, value): + self.lbl.set_text('New slider value: ' + str(value)) + + def color_picker_changed(self, widget, value): + self.lbl.set_text('New color value: ' + value) + + def date_changed(self, widget, value): + self.lbl.set_text('New date value: ' + value) + + def menu_save_clicked(self, widget): + self.lbl.set_text('Menu clicked: Save') + + def menu_saveas_clicked(self, widget): + self.lbl.set_text('Menu clicked: Save As') + + def menu_open_clicked(self, widget): + self.lbl.set_text('Menu clicked: Open') + + def menu_view_clicked(self, widget): + self.lbl.set_text('Menu clicked: View') + + def fileupload_on_success(self, widget, filename): + self.lbl.set_text('File upload success: ' + filename) + + def fileupload_on_failed(self, widget, filename): + self.lbl.set_text('File upload failed: ' + filename) + + def on_close(self): + """ Overloading App.on_close event to stop the Timer. + """ + self.stop_flag = True + super(MyApp, self).on_close() + + +if __name__ == "__main__": + # starts the webserver + # optional parameters + # start(MyApp,address='127.0.0.1', port=8081, multiple_instance=False,enable_file_cache=True, update_interval=0.1, start_browser=True) + import ssl + start(MyApp, debug=True, address='0.0.0.0', port=8081, + start_browser=True, multiple_instance=True) diff --git a/PySimpleGUIWeb/PySimpleGUIWeb.py b/PySimpleGUIWeb/PySimpleGUIWeb.py new file mode 100644 index 000000000..e89619b87 --- /dev/null +++ b/PySimpleGUIWeb/PySimpleGUIWeb.py @@ -0,0 +1,8199 @@ +#usr/bin/python3 + +version = __version__ = "0.39.0.6 Unreleased\n , VSeparator added (spelling error), added default key for one_line_progress_meter, auto-add keys to tables & trees, Graph.draw_image now uses image_data property instead of calling set_image, added theme_add_new, changed Remi call menu_item.set_on_click_listener to menu_item.onclick.connect so it can run with latest Remi" + +port = 'PySimpleGUIWeb' + +import sys +import datetime +import textwrap +import pickle +import threading +from queue import Queue +import remi +import logging +import traceback +import os +import base64, binascii +import mimetypes +from random import randint +import time +import pkg_resources + + +# from typing import List, Any, Union, Tuple, Dict # For doing types in comments. perhaps not required + + +try: + from io import StringIO +except: + from cStringIO import StringIO + +###### ##### ##### # # ### # # +# # # # # # # # # ##### # ###### # # # # # # # # ###### ##### +# # # # # # ## ## # # # # # # # # # # # # # # +###### # ##### # # ## # # # # ##### # #### # # # # # # ##### ##### +# # # # # # ##### # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # +# # ##### # # # # ###### ###### ##### ##### ### ## ## ###### ##### + +""" + Welcome to the "core" PySimpleGUIWeb code.... + + This special port of the PySimpleGUI SDK to the browser is made possible by the magic of Remi + + https://github.com/dddomodossola/remi + + To be clear, PySimpleGUI would not be able to run in a web browser without this important GUI Framework + It may not be as widely known at tkinter or Qt, but it should be. Just as those are the best of the desktop + GUI frameworks, Remi is THE framework for doing Web Page GUIs in Python. Nothing else like it exists. + + ::::::::: :::::::::: ::: ::: ::::::::::: + :+: :+: :+: :+:+: :+:+: :+: + +:+ +:+ +:+ +:+ +:+:+ +:+ +:+ + +#++:++#: +#++:++# +#+ +:+ +#+ +#+ + +#+ +#+ +#+ +#+ +#+ +#+ + #+# #+# #+# #+# #+# #+# + ### ### ########## ### ### ########### + +""" + +g_time_start = 0 +g_time_end = 0 +g_time_delta = 0 + + + +def TimerStart(): + global g_time_start + + g_time_start = time.time() + + +def TimerStop(): + global g_time_delta, g_time_end + + g_time_end = time.time() + g_time_delta = g_time_end - g_time_start + print(g_time_delta*1000) + +# Because looks matter... +DEFAULT_BASE64_ICON = b'iVBORw0KGgoAAAANSUhEUgAAACEAAAAgCAMAAACrZuH4AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAMGmYMGqZMWqaMmubMmycM22dNGuZNm2bNm6bNG2dN26cNG6dNG6eNW+fN3CfOHCeOXGfNXCgNnGhN3KiOHOjOXSjOHSkOnWmOnamOnanPHSiPXakPnalO3eoPnimO3ioPHioPHmpPHmqPXqqPnurPnusPnytP3yuQHimQnurQn2sQH2uQX6uQH6vR32qRn+sSXujSHynTH2mTn+nSX6pQH6wTIGsTYKuTYSvQoCxQoCyRIK0R4S1RYS2Roa4SIe4SIe6SIi7Soq7SYm8SYq8Sou+TY2/UYStUYWvVIWtUYeyVoewUIi0VIizUI6+Vo+8WImxXJG5YI2xZI+xZ5CzZJC0ZpG1b5a3apW4aZm/cZi4dJ2/eJ69fJ+9XZfEZZnCZJzHaZ/Jdp/AeKTI/tM8/9Q7/9Q8/9Q9/9Q+/tQ//9VA/9ZA/9ZB/9ZC/9dD/9ZE/tdJ/9dK/9hF/9hG/9hH/9hI/9hJ/9hK/9lL/9pK/9pL/thO/9pM/9pN/9tO/9tP/9xP/tpR/9xQ/9xR/9xS/9xT/91U/91V/t1W/95W/95X/95Y/95Z/99a/99b/txf/txh/txk/t5l/t1q/t5v/+Bb/+Bc/+Bd/+Be/+Bf/+Bg/+Fh/+Fi/+Jh/+Ji/uJk/uJl/+Jm/+Rm/uJo/+Ro/+Rr/+Zr/+Vs/+Vu/+Zs/+Zu/uF0/uVw/+dw/+dz/+d2/uB5/uB6/uJ9/uR7/uR+/uV//+hx/+hy/+h0/+h2/+l4/+l7/+h8gKXDg6vLgazOhKzMiqrEj6/KhK/Qka/Hk7HJlLHJlLPMmLTLmbbOkLXSmLvXn77XoLrPpr/Tn8DaocLdpcHYrcjdssfZus/g/uOC/uOH/uaB/uWE/uaF/uWK/+qA/uqH/uqI/uuN/uyM/ueS/ueW/ueY/umQ/uqQ/uuS/uuW/uyU/uyX/uqa/uue/uye/uyf/u6f/uyq/u+r/u+t/vCm/vCp/vCu/vCy/vC2/vK2/vO8/vO/wtTjwtXlzdrl/vTA/vPQAAAAiNpY5gAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAAFw8AABcPASe7rwsAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuMWMqnEsAAAKUSURBVDhPhdB3WE1xHMdxt5JV0dANoUiyd8kqkey996xclUuTlEKidO3qVnTbhIyMW/bee5NskjJLmR/f3++cK/94vP76Ps/n/Zx7z6mE/6koJowcK154vvHOL/GsKCZXkUgkWlf4vWGWq5tsDz+JWIzSokAiqXGe7nWu3HxhEYof7fhOqp1GtptQuMruVhQdxZ05U5G47tYUHbQ4oah6Fg9Z4ubm7i57JhQjdHS0RSzUPoG17u6zZTKZh8c8XlytqW9YWUOH1LqFOZ6enl5ec+XybFb0rweM1tPTM6yuq6vLs0lYJJfLvb19fHwDWGF0jh5lYNAe4/QFemOwxtfXz8/fPyBgwVMqzAcCF4ybAZ2MRCexJGBhYGBQUHDw4u1UHDG1G2ZqB/Q1MTHmzAE+kpCwL1RghlTaBt/6SaXS2kx9YH1IaOjSZST8vfA9JtoDnSngGgL7wkg4WVkofA9mcF1Sx8zMzBK4v3wFiYiMVLxlEy9u21syFhYNmgN7IyJXEYViNZvEYoCVVWOmUVvgQVSUQqGIjolRFvOAFd8HWVs34VoA+6OjY2JjY5Vxm4BC1UuhGG5jY9OUaQXci1MqlfHx8YmqjyhOViW9ZsUN29akJRmPFwkJCZsTSXIpilJffXiTzorLXYgtcxRJKpUqKTklJQ0oSt9FP/EonxVdNY4jla1kK4q2ZB6mIr+AipvduzFUzMSOtLT09IyMzMxtJKug/F0u/6dTexAWDcXXLGEjapKjfsILOLKEuYiSnTQeYCt3UHhbwEHjGMrETfBJU5zq5dSTcXC8hLJccSWP2cgLXHPu7cQNAcpyxF1dyjehAKb0cSYUAOXCUw6V8OFPgevTXFymC+fPPLU677Nw/1X8A/AbfAKGulaqFlIAAAAASUVORK5CYII=' + + + +# ----====----====----==== Constants the user CAN safely change ====----====----====----# +DEFAULT_WINDOW_ICON = 'default_icon.ico' +DEFAULT_ELEMENT_SIZE = (250, 26) # In pixels +DEFAULT_BUTTON_ELEMENT_SIZE = (10, 1) # In CHARACTERS +DEFAULT_MARGINS = (10, 5) # Margins for each LEFT/RIGHT margin is first term +DEFAULT_ELEMENT_PADDING = (5, 3) # Padding between elements (row, col) in pixels +DEFAULT_AUTOSIZE_TEXT = True +DEFAULT_AUTOSIZE_BUTTONS = True +DEFAULT_FONT = ("Helvetica", 15) +DEFAULT_TEXT_JUSTIFICATION = 'left' +DEFAULT_BORDER_WIDTH = 1 +DEFAULT_AUTOCLOSE_TIME = 3 # time in seconds to show an autoclose form +DEFAULT_DEBUG_WINDOW_SIZE = (80, 20) +DEFAULT_OUTPUT_ELEMENT_SIZE = (40, 10) +DEFAULT_WINDOW_LOCATION = (None, None) +MAX_SCROLLED_TEXT_BOX_HEIGHT = 50 +DEFAULT_TOOLTIP_TIME = 400 + +DEFAULT_PIXELS_TO_CHARS_SCALING = (10,26) # 1 character represents x by y pixels +DEFAULT_PIXEL_TO_CHARS_CUTOFF = 20 # number of chars that triggers using pixels instead of chars + +#################### COLOR STUFF #################### +BLUES = ("#082567", "#0A37A3", "#00345B") +PURPLES = ("#480656", "#4F2398", "#380474") +GREENS = ("#01826B", "#40A860", "#96D2AB", "#00A949", "#003532") +YELLOWS = ("#F3FB62", "#F0F595") +TANS = ("#FFF9D5", "#F4EFCF", "#DDD8BA") +NICE_BUTTON_COLORS = ((GREENS[3], TANS[0]), + ('#000000', '#FFFFFF'), + ('#FFFFFF', '#000000'), + (YELLOWS[0], PURPLES[1]), + (YELLOWS[0], GREENS[3]), + (YELLOWS[0], BLUES[2])) + +COLOR_SYSTEM_DEFAULT = '1234567890' # Colors should never be this long + +DEFAULT_BUTTON_COLOR = ('white', BLUES[0]) # Foreground, Background (None, None) == System Default +OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR = ('white', BLUES[0]) # Colors should never be this long + +CURRENT_LOOK_AND_FEEL = 'DarkBlue3' + + +DEFAULT_ERROR_BUTTON_COLOR = ("#FFFFFF", "#FF0000") +DEFAULT_BACKGROUND_COLOR = None +DEFAULT_ELEMENT_BACKGROUND_COLOR = None +DEFAULT_ELEMENT_TEXT_COLOR = COLOR_SYSTEM_DEFAULT +DEFAULT_TEXT_ELEMENT_BACKGROUND_COLOR = None +DEFAULT_TEXT_COLOR = COLOR_SYSTEM_DEFAULT +DEFAULT_INPUT_ELEMENTS_COLOR = COLOR_SYSTEM_DEFAULT +DEFAULT_INPUT_TEXT_COLOR = COLOR_SYSTEM_DEFAULT +DEFAULT_SCROLLBAR_COLOR = None +# DEFAULT_BUTTON_COLOR = (YELLOWS[0], PURPLES[0]) # (Text, Background) or (Color "on", Color) as a way to remember +# DEFAULT_BUTTON_COLOR = (GREENS[3], TANS[0]) # Foreground, Background (None, None) == System Default +# DEFAULT_BUTTON_COLOR = (YELLOWS[0], GREENS[4]) # Foreground, Background (None, None) == System Default +# DEFAULT_BUTTON_COLOR = ('white', 'black') # Foreground, Background (None, None) == System Default +# DEFAULT_BUTTON_COLOR = (YELLOWS[0], PURPLES[2]) # Foreground, Background (None, None) == System Default +# DEFAULT_PROGRESS_BAR_COLOR = (GREENS[2], GREENS[0]) # a nice green progress bar +# DEFAULT_PROGRESS_BAR_COLOR = (BLUES[1], BLUES[1]) # a nice green progress bar +# DEFAULT_PROGRESS_BAR_COLOR = (BLUES[0], BLUES[0]) # a nice green progress bar +# DEFAULT_PROGRESS_BAR_COLOR = (PURPLES[1],PURPLES[0]) # a nice purple progress bar + +# A transparent button is simply one that matches the background +TRANSPARENT_BUTTON = 'This constant has been depricated. You must set your button background = background it is on for it to be transparent appearing' +# -------------------------------------------------------------------------------- +# Progress Bar Relief Choices +RELIEF_RAISED = 'raised' +RELIEF_SUNKEN = 'sunken' +RELIEF_FLAT = 'flat' +RELIEF_RIDGE = 'ridge' +RELIEF_GROOVE = 'groove' +RELIEF_SOLID = 'solid' + +DEFAULT_PROGRESS_BAR_COLOR = (GREENS[0], '#D0D0D0') # a nice green progress bar +DEFAULT_PROGRESS_BAR_COLOR_OFFICIAL = (GREENS[0], '#D0D0D0') # a nice green progress bar +DEFAULT_PROGRESS_BAR_SIZE = (25, 20) # Size of Progress Bar (characters for length, pixels for width) +DEFAULT_PROGRESS_BAR_BORDER_WIDTH = 1 +DEFAULT_PROGRESS_BAR_RELIEF = RELIEF_GROOVE +PROGRESS_BAR_STYLES = ('default', 'winnative', 'clam', 'alt', 'classic', 'vista', 'xpnative') +DEFAULT_PROGRESS_BAR_STYLE = 'default' +DEFAULT_METER_ORIENTATION = 'horizontal' +DEFAULT_SLIDER_ORIENTATION = 'vertical' +DEFAULT_SLIDER_BORDER_WIDTH = 1 +DEFAULT_SLIDER_RELIEF = 00000 +DEFAULT_FRAME_RELIEF = 00000 + + +DEFAULT_LISTBOX_SELECT_MODE = 'extended' +SELECT_MODE_MULTIPLE = 'multiple' +LISTBOX_SELECT_MODE_MULTIPLE = 'multiple' +SELECT_MODE_BROWSE = 'browse' +LISTBOX_SELECT_MODE_BROWSE = 'browse' +SELECT_MODE_EXTENDED = 'extended' +LISTBOX_SELECT_MODE_EXTENDED = 'extended' +SELECT_MODE_SINGLE = 'single' +LISTBOX_SELECT_MODE_SINGLE = 'single' +SELECT_MODE_CONTIGUOUS = 'contiguous' +LISTBOX_SELECT_MODE_CONTIGUOUS = 'contiguous' + +TABLE_SELECT_MODE_NONE = 00000 +TABLE_SELECT_MODE_BROWSE = 00000 +TABLE_SELECT_MODE_EXTENDED = 00000 +DEFAULT_TABLE_SECECT_MODE = TABLE_SELECT_MODE_EXTENDED + +TITLE_LOCATION_TOP = 00000 +TITLE_LOCATION_BOTTOM = 00000 +TITLE_LOCATION_LEFT = 00000 +TITLE_LOCATION_RIGHT = 00000 +TITLE_LOCATION_TOP_LEFT = 00000 +TITLE_LOCATION_TOP_RIGHT = 00000 +TITLE_LOCATION_BOTTOM_LEFT = 00000 +TITLE_LOCATION_BOTTOM_RIGHT = 00000 + +THEME_DEFAULT = 'default' +THEME_WINNATIVE = 'winnative' +THEME_CLAM = 'clam' +THEME_ALT = 'alt' +THEME_CLASSIC = 'classic' +THEME_VISTA = 'vista' +THEME_XPNATIVE = 'xpnative' + +# DEFAULT_METER_ORIENTATION = 'Vertical' +# ----====----====----==== Constants the user should NOT f-with ====----====----====----# +ThisRow = 555666777 # magic number + +# DEFAULT_WINDOW_ICON = '' +MESSAGE_BOX_LINE_WIDTH = 60 + +# "Special" Key Values.. reserved +# Key representing a Read timeout +EVENT_TIMEOUT = TIMEOUT_EVENT = TIMEOUT_KEY = '__TIMEOUT__' +# Window closed event (user closed with X or destroyed using OS) +WIN_CLOSED = WINDOW_CLOSED = None + +# Key indicating should not create any return values for element +WRITE_ONLY_KEY = '__WRITE ONLY__' + +# MENU Constants, can be changed by user if desired +MENU_DISABLED_CHARACTER = '!' +MENU_KEY_SEPARATOR = '::' + + + + +# a shameful global variable. This represents the top-level window information. Needed because opening a second window is different than opening the first. +class MyWindows(): + def __init__(self): + self._NumOpenWindows = 0 + self.user_defined_icon = None + self.hidden_master_root = None + + def Decrement(self): + self._NumOpenWindows -= 1 * (self._NumOpenWindows != 0) # decrement if not 0 + # print('---- DECREMENTING Num Open Windows = {} ---'.format(self._NumOpenWindows)) + + def Increment(self): + self._NumOpenWindows += 1 + # print('++++ INCREMENTING Num Open Windows = {} ++++'.format(self._NumOpenWindows)) + + +_my_windows = MyWindows() # terrible hack using globals... means need a class for collecing windows + + +# ====================================================================== # +# One-liner functions that are handy as f_ck # +# ====================================================================== # +def RGB(red, green, blue): return '#%02x%02x%02x' % (red, green, blue) + + +# ====================================================================== # +# Enums for types # +# ====================================================================== # +# ------------------------- Button types ------------------------- # +# todo Consider removing the Submit, Cancel types... they are just 'RETURN' type in reality +# uncomment this line and indent to go back to using Enums +# Was enum previously ButtonType(Enum): +BUTTON_TYPE_BROWSE_FOLDER = 1 +BUTTON_TYPE_BROWSE_FILE = 2 +BUTTON_TYPE_BROWSE_FILES = 21 +BUTTON_TYPE_SAVEAS_FILE = 3 +BUTTON_TYPE_CLOSES_WIN = 5 +BUTTON_TYPE_CLOSES_WIN_ONLY = 6 +BUTTON_TYPE_READ_FORM = 7 +BUTTON_TYPE_REALTIME = 9 +BUTTON_TYPE_CALENDAR_CHOOSER = 30 +BUTTON_TYPE_COLOR_CHOOSER = 40 + +BROWSE_FILES_DELIMITER = ';' # the delimeter to be used between each file in the returned string + +# ------------------------- Element types ------------------------- # +# These used to be enums ElementType(Enum): +ELEM_TYPE_TEXT = 'text' +ELEM_TYPE_INPUT_TEXT = 'input' +ELEM_TYPE_INPUT_COMBO = 'combo' +ELEM_TYPE_INPUT_OPTION_MENU = 'option menu' +ELEM_TYPE_INPUT_RADIO = 'radio' +ELEM_TYPE_INPUT_MULTILINE = 'multiline' +ELEM_TYPE_MULTILINE_OUTPUT = 'multioutput' +ELEM_TYPE_INPUT_CHECKBOX = 'checkbox' +ELEM_TYPE_INPUT_SPIN = 'spin' +ELEM_TYPE_BUTTON = 'button' +ELEM_TYPE_BUTTONMENU = 'buttonmenu' +ELEM_TYPE_IMAGE = 'image' +ELEM_TYPE_CANVAS = 'canvas' +ELEM_TYPE_FRAME = 'frame' +ELEM_TYPE_GRAPH = 'graph' +ELEM_TYPE_TAB = 'tab' +ELEM_TYPE_TAB_GROUP = 'tabgroup' +ELEM_TYPE_INPUT_SLIDER = 'slider' +ELEM_TYPE_INPUT_LISTBOX = 'listbox' +ELEM_TYPE_OUTPUT = 'output' +ELEM_TYPE_COLUMN = 'column' +ELEM_TYPE_MENUBAR = 'menubar' +ELEM_TYPE_PROGRESS_BAR = 'progressbar' +ELEM_TYPE_BLANK = 'blank' +ELEM_TYPE_TABLE = 'table' +ELEM_TYPE_TREE = 'tree' +ELEM_TYPE_ERROR = 'error' +ELEM_TYPE_SEPARATOR = 'separator' + +# ------------------------- Popup Buttons Types ------------------------- # +POPUP_BUTTONS_YES_NO = 1 +POPUP_BUTTONS_CANCELLED = 2 +POPUP_BUTTONS_ERROR = 3 +POPUP_BUTTONS_OK_CANCEL = 4 +POPUP_BUTTONS_OK = 0 +POPUP_BUTTONS_NO_BUTTONS = 5 + + +# ---------------------------------------------------------------------- # +# Cascading structure.... Objects get larger # +# Button # +# Element # +# Row # +# Form # +# ---------------------------------------------------------------------- # +# ------------------------------------------------------------------------- # +# Element CLASS # +# ------------------------------------------------------------------------- # +class Element(): + def __init__(self, elem_type, size=(None, None), auto_size_text=None, font=None, background_color=None, text_color=None, + key=None, pad=None, tooltip=None, visible=True, size_px=(None, None), metadata=None): + + if elem_type != ELEM_TYPE_GRAPH: + self.Size = convert_tkinter_size_to_Wx(size) + else: + self.Size = size + if size_px != (None, None): + self.Size = size_px + self.Type = elem_type + self.AutoSizeText = auto_size_text + # self.Pad = DEFAULT_ELEMENT_PADDING if pad is None else pad + self.Pad = pad + if font is not None and type(font) is not str: + self.Font = font + elif font is not None: + self.Font = font.split(' ') + else: + self.Font = font + + self.TKStringVar = None + self.TKIntVar = None + self.TKText = None + self.TKEntry = None + self.TKImage = None + + self.ParentForm = None # type: Window + self.ParentContainer = None # will be a Form, Column, or Frame element + self.TextInputDefault = None + self.Position = (0, 0) # Default position Row 0, Col 0 + self.BackgroundColor = background_color if background_color is not None else DEFAULT_ELEMENT_BACKGROUND_COLOR + self.TextColor = text_color if text_color is not None else DEFAULT_ELEMENT_TEXT_COLOR + self.Key = key # dictionary key for return values + self.Tooltip = tooltip + self.TooltipObject = None + self.Visible = visible + self.metadata = metadata # type: Any + + + # ------------------------- REMI CHANGED CALLBACK ----------------------- + # called when a widget has changed and the element has events enabled + def _ChangedCallback(self, widget, *args): + # type: (Element, remi.Widget, Any) -> None + # print(f'Callback {args}') + self.ParentForm.LastButtonClicked = self.Key if self.Key is not None else '' + self.ParentForm.MessageQueue.put(self.ParentForm.LastButtonClicked) + + def Update(self, widget, background_color=None, text_color=None, font=None, visible=None, disabled=None, tooltip=None): + if font is not None: + font_info = font_parse_string(font) # family, point size, other + widget.style['font-family'] = font_info[0] + widget.style['font-size'] = '{}px'.format(font_info[1]) + + if background_color not in (None, COLOR_SYSTEM_DEFAULT): + widget.style['background-color'] = background_color + if text_color not in (None, COLOR_SYSTEM_DEFAULT): + widget.style['color'] = text_color + + if disabled: + widget.set_enabled(False) + elif disabled is False: + widget.set_enabled(True) + if visible is False: + widget.attributes['hidden'] = 'true' + elif visible is True: + del(widget.attributes['hidden']) + if tooltip is not None: + widget.attributes['title'] = tooltip + + + # if font: + # widget.SetFont(font_to_wx_font(font)) + # if text_color not in (None, COLOR_SYSTEM_DEFAULT): + # widget.SetForegroundColour(text_color) + # if background_color not in (None, COLOR_SYSTEM_DEFAULT): + # widget.SetBackgroundColour(background_color) + # if visible is True: + # widget.Show() + # self.ParentForm.VisibilityChanged() + # elif visible is False: + # widget.Hide() + # self.ParentForm.VisibilityChanged() + # if disabled: + # widget.Enable(False) + # elif disabled is False: + # widget.Enable(True) + # if tooltip is not None: + # widget.SetToolTip(tooltip) + if visible is False: + widget.attributes['hidden'] = 'true' + elif visible is True: + del(widget.attributes['hidden']) + + + def __call__(self, *args, **kwargs): + """ + Makes it possible to "call" an already existing element. When you do make the "call", it actually calls + the Update method for the element. + Example: If this text element was in your layout: + sg.Text('foo', key='T') + Then you can call the Update method for that element by writing: + window.FindElement('T')('new text value') + + :param args: + :param kwargs: + :return: + """ + return self.Update(*args, **kwargs) + + +# ---------------------------------------------------------------------- # +# Input Class # +# ---------------------------------------------------------------------- # +class InputText(Element): + def __init__(self, default_text='', size=(None, None), disabled=False, password_char='', + justification=None, background_color=None, text_color=None, font=None, tooltip=None, + change_submits=False, enable_events=False, + do_not_clear=True, key=None, focus=False, pad=None, visible=True, size_px=(None, None)): + ''' + Input a line of text Element + :param default_text: Default value to display + :param size: Size of field in characters + :param password_char: If non-blank, will display this character for every character typed + :param background_color: Color for Element. Text or RGB Hex + ''' + self.DefaultText = default_text + self.PasswordCharacter = password_char + bg = background_color if background_color is not None else DEFAULT_INPUT_ELEMENTS_COLOR + fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR + self.Focus = focus + self.do_not_clear = do_not_clear + self.Justification = justification or 'left' + self.Disabled = disabled + self.ChangeSubmits = change_submits or enable_events + self.QT_QLineEdit = None + self.ValueWasChanged = False + self.Widget = None # type: remi.gui.TextInput + super().__init__(ELEM_TYPE_INPUT_TEXT, size=size, background_color=bg, text_color=fg, key=key, pad=pad, + font=font, tooltip=tooltip, visible=visible, size_px=size_px) + + def _InputTextCallback(self,widget, key, keycode, ctrl, shift, alt): + # print(f'text widget value = {widget.get_value()}') + # widget.set_value('') + # widget.set_value(value) + self.ParentForm.LastButtonClicked = key + self.ParentForm.MessageQueue.put(self.ParentForm.LastButtonClicked) + widget.set_value(widget.get_value()+key) + return (key, keycode, ctrl, shift, alt) + + def Update(self, value=None, disabled=None, select=None, background_color=None, text_color=None, font=None, visible=None): + if value is not None: + self.Widget.set_value(str(value)) + if disabled is True: + self.Widget.set_enabled(False) + elif disabled is False: + self.Widget.set_enabled(True) + + def Get(self): + return self.Widget.get_value() + + + get = Get + update = Update + + class TextInput_raw_onkeyup(remi.gui.TextInput): + @remi.gui.decorate_set_on_listener("(self, emitter, key, keycode, ctrl, shift, alt)") + @remi.gui.decorate_event_js("""var params={};params['key']=event.key; + params['keycode']=(event.which||event.keyCode); + params['ctrl']=event.ctrlKey; + params['shift']=event.shiftKey; + params['alt']=event.altKey; + sendCallbackParam('%(emitter_identifier)s','%(event_name)s',params); + event.stopPropagation();event.preventDefault();return false;""") + def onkeyup(self, key, keycode, ctrl, shift, alt): + return (key, keycode, ctrl, shift, alt) + + @remi.gui.decorate_set_on_listener("(self, emitter, key, keycode, ctrl, shift, alt)") + @remi.gui.decorate_event_js("""var params={};params['key']=event.key; + params['keycode']=(event.which||event.keyCode); + params['ctrl']=event.ctrlKey; + params['shift']=event.shiftKey; + params['alt']=event.altKey; + sendCallbackParam('%(emitter_identifier)s','%(event_name)s',params); + event.stopPropagation();event.preventDefault();return false;""") + def onkeydown(self, key, keycode, ctrl, shift, alt): + return (key, keycode, ctrl, shift, alt) + + +# ------------------------- INPUT TEXT Element lazy functions ------------------------- # +In = InputText +Input = InputText +I = InputText + +# ---------------------------------------------------------------------- # +# Combo # +# ---------------------------------------------------------------------- # +class Combo(Element): + def __init__(self, values, default_value=None, size=(None, None), auto_size_text=None, background_color=None, + text_color=None, change_submits=False, enable_events=False, disabled=False, key=None, pad=None, tooltip=None, + readonly=False, visible_items=10, font=None, auto_complete=True, visible=True, size_px=(None,None)): + ''' + Input Combo Box Element (also called Dropdown box) + :param values: + :param size: Size of field in characters + :param auto_size_text: True if should shrink field to fit the default text + :param background_color: Color for Element. Text or RGB Hex + ''' + self.Values = [str(v) for v in values] + self.DefaultValue = default_value + self.ChangeSubmits = change_submits or enable_events + # self.InitializeAsDisabled = disabled + self.Disabled = disabled + self.Readonly = readonly + bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR + fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR + self.VisibleItems = visible_items + self.AutoComplete = auto_complete + self.Widget = None # type: remi.gui.DropDown + super().__init__(ELEM_TYPE_INPUT_COMBO, size=size, auto_size_text=auto_size_text, background_color=bg, + text_color=fg, key=key, pad=pad, tooltip=tooltip, font=font or DEFAULT_FONT, visible=visible, size_px=size_px) + + + + def Update(self, value=None, values=None, set_to_index=None, disabled=None, readonly=None, background_color=None, text_color=None, font=None, visible=None): + if values is not None: + self.Widget.empty() + for i, item in enumerate(values): + self.Widget.append(value=item, key=str(i)) + if value: + self.Widget.select_by_value(value) + if set_to_index is not None: + try: # just in case a bad index is passed in + self.Widget.select_by_key(str(set_to_index)) + except: + pass + + super().Update(self.Widget, background_color=background_color, text_color=text_color, font=font, visible=visible, disabled=disabled) + + update = Update + + +# ------------------------- INPUT COMBO Element lazy functions ------------------------- # +InputCombo = Combo +DropDown = Combo +Drop = Combo + + +# ---------------------------------------------------------------------- # +# Option Menu # +# ---------------------------------------------------------------------- # +class OptionMenu(Element): + def __init__(self, values, default_value=None, size=(None, None), disabled=False, auto_size_text=None, + background_color=None, text_color=None, key=None, pad=None, tooltip=None): + ''' + InputOptionMenu + :param values: + :param default_value: + :param size: + :param disabled: + :param auto_size_text: + :param background_color: + :param text_color: + :param key: + :param pad: + :param tooltip: + ''' + self.Values = values + self.DefaultValue = default_value + self.TKOptionMenu = None + self.Disabled = disabled + bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR + fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR + + super().__init__(ELEM_TYPE_INPUT_OPTION_MENU, size=size, auto_size_text=auto_size_text, background_color=bg, + text_color=fg, key=key, pad=pad, tooltip=tooltip) + + def Update(self, value=None, values=None, disabled=None): + if values is not None: + self.Values = values + if self.Values is not None: + for index, v in enumerate(self.Values): + if v == value: + try: + self.TKStringVar.set(value) + except: + pass + self.DefaultValue = value + break + if disabled == True: + self.TKOptionMenu['state'] = 'disabled' + elif disabled == False: + self.TKOptionMenu['state'] = 'normal' + + + +# ------------------------- OPTION MENU Element lazy functions ------------------------- # +InputOptionMenu = OptionMenu + + + +# ---------------------------------------------------------------------- # +# Listbox # +# ---------------------------------------------------------------------- # +class Listbox(Element): + def __init__(self, values, default_values=None, select_mode=None, change_submits=False, enable_events=False, bind_return_key=False, size=(None, None), disabled=False, auto_size_text=None, font=None, background_color=None, text_color=None, key=None, pad=None, tooltip=None, visible=True, size_px=(None,None)): + """ + + :param values: + :param default_values: + :param select_mode: + :param change_submits: + :param enable_events: + :param bind_return_key: + :param size: + :param disabled: + :param auto_size_text: + :param font: + :param background_color: + :param text_color: + :param key: + :param pad: + :param tooltip: + :param visible: + :param size_px: + """ + self.Values = values + self.DefaultValues = default_values + self.TKListbox = None + self.ChangeSubmits = change_submits or enable_events + self.BindReturnKey = bind_return_key + self.Disabled = disabled + if select_mode == LISTBOX_SELECT_MODE_BROWSE: + self.SelectMode = SELECT_MODE_BROWSE + elif select_mode == LISTBOX_SELECT_MODE_EXTENDED: + self.SelectMode = SELECT_MODE_EXTENDED + elif select_mode == LISTBOX_SELECT_MODE_MULTIPLE: + self.SelectMode = SELECT_MODE_MULTIPLE + elif select_mode == LISTBOX_SELECT_MODE_SINGLE: + self.SelectMode = SELECT_MODE_SINGLE + elif select_mode == LISTBOX_SELECT_MODE_CONTIGUOUS: + self.SelectMode = SELECT_MODE_CONTIGUOUS + else: + self.SelectMode = DEFAULT_LISTBOX_SELECT_MODE + bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR + fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR + self.Widget = None # type: remi.gui.ListView + tsize = size # convert tkinter size to pixels + if size[0] is not None and size[0] < 100: + tsize = size[0]*DEFAULT_PIXELS_TO_CHARS_SCALING[0], size[1]*DEFAULT_PIXELS_TO_CHARS_SCALING[1] + + super().__init__(ELEM_TYPE_INPUT_LISTBOX, size=tsize, auto_size_text=auto_size_text, font=font, + background_color=bg, text_color=fg, key=key, pad=pad, tooltip=tooltip, visible=visible, size_px=size_px) + + def Update(self, values=None, disabled=None, set_to_index=None,background_color=None, text_color=None, font=None, visible=None): + if values is not None: + self.Values = values + self.Widget.empty() + for item in values: + self.Widget.append(remi.gui.ListItem(item)) + # if disabled == True: + # self.QT_ListWidget.setDisabled(True) + # elif disabled == False: + # self.QT_ListWidget.setDisabled(False) + # if set_to_index is not None: + # self.QT_ListWidget.setCurrentRow(set_to_index) + super().Update(self.Widget, background_color=background_color, text_color=text_color, font=font, visible=visible, disabled=disabled) + + return + + # def SetValue(self, values): + # # for index, item in enumerate(self.Values): + # for index, value in enumerate(self.Values): + # item = self.QT_ListWidget.item(index) + # if value in values: + # self.QT_ListWidget.setItemSelected(item, True) + + + def GetListValues(self): + return self.Values + + get_list_values = GetListValues + update = Update + + +# ---------------------------------------------------------------------- # +# Radio # +# ---------------------------------------------------------------------- # +class Radio(Element): + def __init__(self, text, group_id, default=False, disabled=False, size=(None, None), auto_size_text=None, + background_color=None, text_color=None, font=None, key=None, pad=None, tooltip=None, + change_submits=False): + ''' + Radio Button Element + :param text: + :param group_id: + :param default: + :param disabled: + :param size: + :param auto_size_text: + :param background_color: + :param text_color: + :param font: + :param key: + :param pad: + :param tooltip: + :param change_submits: + ''' + self.InitialState = default + self.Text = text + self.TKRadio = None + self.GroupID = group_id + self.Value = None + self.Disabled = disabled + self.TextColor = text_color or DEFAULT_TEXT_COLOR + self.ChangeSubmits = change_submits + + print('*** WARNING - Radio Buttons are not yet available on PySimpleGUIWeb ***') + + super().__init__(ELEM_TYPE_INPUT_RADIO, size=size, auto_size_text=auto_size_text, font=font, + background_color=background_color, text_color=self.TextColor, key=key, pad=pad, + tooltip=tooltip) + + def Update(self, value=None, disabled=None): + print('*** NOT IMPLEMENTED ***') + location = EncodeRadioRowCol(self.Position[0], self.Position[1]) + if value is not None: + try: + self.TKIntVar.set(location) + except: + pass + self.InitialState = value + if disabled == True: + self.TKRadio['state'] = 'disabled' + elif disabled == False: + self.TKRadio['state'] = 'normal' + + update = Update + + +# ---------------------------------------------------------------------- # +# Checkbox # +# ---------------------------------------------------------------------- # +class Checkbox(Element): + def __init__(self, text, default=False, size=(None, None), auto_size_text=None, font=None, background_color=None, + text_color=None, change_submits=False, enable_events=False, disabled=False, key=None, pad=None, tooltip=None, visible=True, size_px=(None,None)): + ''' + Checkbox Element + :param text: + :param default: + :param size: + :param auto_size_text: + :param font: + :param background_color: + :param text_color: + :param change_submits: + :param disabled: + :param key: + :param pad: + :param tooltip: + ''' + self.Text = text + self.InitialState = default + self.Disabled = disabled + self.TextColor = text_color if text_color else DEFAULT_TEXT_COLOR + self.ChangeSubmits = change_submits or enable_events + self.Widget = None # type: remi.gui.CheckBox + + super().__init__(ELEM_TYPE_INPUT_CHECKBOX, size=size, auto_size_text=auto_size_text, font=font, + background_color=background_color, text_color=self.TextColor, key=key, pad=pad, + tooltip=tooltip, visible=visible, size_px=size_px) + + def _ChangedCallback(self, widget, value): + # type: (remi.Widget, Any) -> None + # print(f'text widget value = {widget.get_value()}') + self.ParentForm.LastButtonClicked = self.Key + self.ParentForm.MessageQueue.put(self.ParentForm.LastButtonClicked) + + + def Get(self): + return self.Widget.get_value() + + def Update(self, value=None, disabled=None): + if value is not None: + self.Widget.set_value(value) + if disabled == True: + self.Widget.set_enabled(False) + elif disabled == False: + self.Widget.set_enabled(True) + + get = Get + update = Update + + +# ------------------------- CHECKBOX Element lazy functions ------------------------- # +CB = Checkbox +CBox = Checkbox +Check = Checkbox + + +# ---------------------------------------------------------------------- # +# Spin # +# ---------------------------------------------------------------------- # + +class Spin(Element): + # Values = None + # TKSpinBox = None + def __init__(self, values, initial_value=None, disabled=False, change_submits=False, enable_events=False, size=(None, None), readonly=True, auto_size_text=None, font=None, background_color=None, text_color=None, key=None, pad=None, + tooltip=None, visible=True, size_px=(None,None)): + ''' + Spinner Element + :param values: + :param initial_value: + :param disabled: + :param change_submits: + :param size: + :param auto_size_text: + :param font: + :param background_color: + :param text_color: + :param key: + :param pad: + :param tooltip: + ''' + self.Values = values + self.DefaultValue = initial_value or values[0] + self.ChangeSubmits = change_submits or enable_events + self.Disabled = disabled + bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR + fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR + self.CurrentValue = self.DefaultValue + self.ReadOnly = readonly + self.Widget = None # type: remi.gui.SpinBox + super().__init__(ELEM_TYPE_INPUT_SPIN, size, auto_size_text, font=font, background_color=bg, text_color=fg, + key=key, pad=pad, tooltip=tooltip, visible=visible, size_px=size_px) + return + + + def Update(self, value=None, values=None, disabled=None, background_color=None, text_color=None, font=None, visible=None): + if value is not None: + self.Widget.set_value(value) + super().Update(self.Widget, background_color=background_color, text_color=text_color, font=font,visible=visible) + + def Get(self): + return self.Widget.get_value() + + get = Get + update = Update + + +# ---------------------------------------------------------------------- # +# Multiline # +# ---------------------------------------------------------------------- # +class Multiline(Element): + def __init__(self, default_text='', enter_submits=False, disabled=False, autoscroll=False, size=(None, None), + auto_size_text=None, background_color=None, text_color=None, change_submits=False, enable_events=False, do_not_clear=True, + key=None, write_only=False, focus=False, font=None, pad=None, tooltip=None, visible=True, size_px=(None,None)): + ''' + Multiline Element + :param default_text: + :param enter_submits: + :param disabled: + :param autoscroll: + :param size: + :param auto_size_text: + :param background_color: + :param text_color: + :param do_not_clear: + :param key: + :param focus: + :param pad: + :param tooltip: + :param font: + ''' + self.DefaultText = default_text + self.EnterSubmits = enter_submits + bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR + self.Focus = focus + self.do_not_clear = do_not_clear + fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR + self.Autoscroll = autoscroll + self.Disabled = disabled + self.ChangeSubmits = change_submits or enable_events + self.WriteOnly = write_only + if size[0] is not None and size[0] < 100: + size = size[0]*DEFAULT_PIXELS_TO_CHARS_SCALING[0], size[1]*DEFAULT_PIXELS_TO_CHARS_SCALING[1] + self.Widget = None # type: remi.gui.TextInput + + super().__init__(ELEM_TYPE_INPUT_MULTILINE, size=size, auto_size_text=auto_size_text, background_color=bg, + text_color=fg, key=key, pad=pad, tooltip=tooltip, font=font or DEFAULT_FONT, visible=visible, size_px=size_px) + return + + def _InputTextCallback(self, widget:remi.Widget, value, keycode): + # print(f'text widget value = {widget.get_value()}') + self.ParentForm.LastButtonClicked = chr(int(keycode)) + self.ParentForm.MessageQueue.put(self.ParentForm.LastButtonClicked) + + def Update(self, value=None, disabled=None, append=False, background_color=None, text_color=None, font=None, visible=None, autoscroll=None): + if value is not None and not append: + self.Widget.set_value(value) + elif value is not None and append: + text = self.Widget.get_value() + str(value) + self.Widget.set_value(text) + # if background_color is not None: + # self.WxTextCtrl.SetBackgroundColour(background_color) + # if text_color is not None: + # self.WxTextCtrl.SetForegroundColour(text_color) + # if font is not None: + # self.WxTextCtrl.SetFont(font) + # if disabled: + # self.WxTextCtrl.Enable(True) + # elif disabled is False: + # self.WxTextCtrl.Enable(False) + super().Update(self.Widget, background_color=background_color, text_color=text_color, font=font, visible=visible) + + + def print(self, *args, end=None, sep=None, text_color=None, background_color=None): + """ + Print like Python normally prints except route the output to a multline element and also add colors if desired + + :param args: List[Any] The arguments to print + :param end: (str) The end char to use just like print uses + :param sep: (str) The separation character like print uses + :param text_color: The color of the text + :param background_color: The background color of the line + """ + _print_to_element(self, *args, end=end, sep=sep, text_color=text_color, background_color=background_color) + + + + update = Update + +ML = Multiline +MLine = Multiline + + +# ---------------------------------------------------------------------- # +# Multiline Output # +# ---------------------------------------------------------------------- # +class MultilineOutput(Element): + def __init__(self, default_text='', enter_submits=False, disabled=False, autoscroll=False, size=(None, None), auto_size_text=None, background_color=None, + text_color=None, change_submits=False, enable_events=False, do_not_clear=True, key=None, focus=False, font=None, pad=None, tooltip=None, + visible=True, size_px=(None, None)): + ''' + Multiline Element + :param default_text: + :param enter_submits: + :param disabled: + :param autoscroll: + :param size: + :param auto_size_text: + :param background_color: + :param text_color: + :param do_not_clear: + :param key: + :param focus: + :param pad: + :param tooltip: + :param font: + ''' + self.DefaultText = default_text + self.EnterSubmits = enter_submits + bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR + self.Focus = focus + self.do_not_clear = do_not_clear + fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR + self.Autoscroll = autoscroll + self.Disabled = disabled + self.ChangeSubmits = change_submits or enable_events + tsize = size # convert tkinter size to pixels + if size[0] is not None and size[0] < 100: + tsize = size[0] * DEFAULT_PIXELS_TO_CHARS_SCALING[0], size[1] * DEFAULT_PIXELS_TO_CHARS_SCALING[1] + self.Widget = None # type: remi.gui.TextInput + self.CurrentValue = '' + + super().__init__(ELEM_TYPE_MULTILINE_OUTPUT, size=tsize, auto_size_text=auto_size_text, background_color=bg, + text_color=fg, key=key, pad=pad, tooltip=tooltip, font=font or DEFAULT_FONT, visible=visible, size_px=size_px) + return + + def Update(self, value=None, disabled=None, append=False, background_color=None, text_color=None, font=None, visible=None, autoscroll=None): + autoscroll = self.Autoscroll if autoscroll is None else autoscroll + if value is not None and not append: + self.Widget.set_value(str(value)) + self.CurrentValue = str(value) + elif value is not None and append: + self.CurrentValue = self.CurrentValue + str(value) + self.Widget.set_value(self.CurrentValue) + self.Widget._set_updated() + app = self.ParentForm.App + + if hasattr(app, "websockets"): + app.execute_javascript( + 'element=document.getElementById("%(id)s"); element.innerHTML=`%(content)s`; if(%(autoscroll)s){element.scrollTop=999999;} ' % { + "id": self.Widget.identifier, "content": self.Widget.get_value(), "autoscroll": 'true' if autoscroll else 'false'}) + + super().Update(self.Widget, background_color=background_color, text_color=text_color, font=font, visible=visible) + + def print(self, *args, end=None, sep=None, text_color=None, background_color=None): + """ + Print like Python normally prints except route the output to a multline element and also add colors if desired + + :param args: List[Any] The arguments to print + :param end: (str) The end char to use just like print uses + :param sep: (str) The separation character like print uses + :param text_color: The color of the text + :param background_color: The background color of the line + """ + _print_to_element(self, *args, end=end, sep=sep, text_color=text_color, background_color=background_color) + + + + + + update = Update + + +# ---------------------------------------------------------------------- # +# Text # +# ---------------------------------------------------------------------- # +class Text(Element): + def __init__(self, text='', size=(None, None), auto_size_text=None, click_submits=None, enable_events=False, relief=None, border_width=None, font=None, text_color=None, background_color=None, justification=None, pad=None, margins=None, key=None, tooltip=None, visible=True, size_px=(None,None), metadata=None): + """ + Text + :param text: + :param size: + :param auto_size_text: + :param click_submits: + :param enable_events: + :param relief: + :param font: + :param text_color: + :param background_color: + :param justification: + :param pad: + :param margins: + :param key: + :param tooltip: + :param visible: + :param size_px: + """ + self.DisplayText = str(text) + self.TextColor = text_color if text_color else DEFAULT_TEXT_COLOR + self.Justification = justification + self.Relief = relief + self.ClickSubmits = click_submits or enable_events + self.Margins = margins + self.size_px = size_px + if background_color is None: + bg = DEFAULT_TEXT_ELEMENT_BACKGROUND_COLOR + else: + bg = background_color + pixelsize = size + if size[1] is not None and size[1] < 10: + pixelsize = size[0]*10, size[1]*20 + self.BorderWidth = border_width if border_width is not None else DEFAULT_BORDER_WIDTH + self.Disabled = False + self.Widget = None #type: remi.gui.Label + + super().__init__(ELEM_TYPE_TEXT, pixelsize, auto_size_text, background_color=bg, font=font if font else DEFAULT_FONT, + text_color=self.TextColor, pad=pad, key=key, tooltip=tooltip, size_px=size_px, visible=visible, metadata=metadata) + return + + def Update(self, value=None, background_color=None, text_color=None, font=None, visible=None): + if value is not None: + self.Widget.set_text(str(value)) + super().Update(self.Widget, background_color=background_color, text_color=text_color, font=font, visible=visible) + + update = Update + +# ------------------------- Text Element lazy functions ------------------------- # +Txt = Text +T = Text + + + +# ---------------------------------------------------------------------- # +# Output # +# Routes stdout, stderr to a scrolled window # +# ---------------------------------------------------------------------- # +class Output(Element): + def __init__(self, size=(None, None), background_color=None, text_color=None, pad=None, font=None, tooltip=None, + key=None, visible=True, size_px=(None,None), disabled=False): + ''' + Output Element + :param size: + :param background_color: + :param text_color: + :param pad: + :param font: + :param tooltip: + :param key: + ''' + bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR + # fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR + fg = text_color if text_color is not None else 'black' if DEFAULT_INPUT_TEXT_COLOR == COLOR_SYSTEM_DEFAULT else DEFAULT_INPUT_TEXT_COLOR + self.Disabled = disabled + self.Widget = None # type: remi.gui.TextInput + if size_px == (None, None) and size == (None, None): + size = DEFAULT_OUTPUT_ELEMENT_SIZE + if size[0] is not None and size[0] < 100: + size = size[0]*DEFAULT_PIXELS_TO_CHARS_SCALING[0], size[1]*DEFAULT_PIXELS_TO_CHARS_SCALING[1] + super().__init__(ELEM_TYPE_OUTPUT, size=size, size_px=size_px, visible=visible, background_color=bg, text_color=fg, pad=pad, font=font, tooltip=tooltip, key=key) + + + def Update(self, value=None, disabled=None, append=False, background_color=None, text_color=None, font=None, visible=None): + if value is not None and not append: + self.Widget.set_value(str(value)) + self.CurrentValue = str(value) + elif value is not None and append: + self.CurrentValue = self.CurrentValue + '\n' + str(value) + self.Widget.set_value(self.CurrentValue) + self.Widget._set_updated() + app = self.ParentForm.App + if hasattr(app, "websockets"): + app.execute_javascript('element=document.getElementById("%(id)s"); element.innerHTML=`%(content)s`; element.scrollTop=999999; ' % { + "id":self.Widget.identifier, "content":self.Widget.get_value()}) + + super().Update(self.Widget, background_color=background_color, text_color=text_color, font=font, visible=visible) + + update = Update + + +# ---------------------------------------------------------------------- # +# Button Class # +# ---------------------------------------------------------------------- # +class Button(Element): + def __init__(self, button_text='', button_type=BUTTON_TYPE_READ_FORM, target=(None, None), tooltip=None, + file_types=(("ALL Files", "*"),), initial_folder=None, disabled=False, change_submits=False, enable_events=False, + image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, border_width=None, + size=(None, None), auto_size_button=None, button_color=None, font=None, bind_return_key=False, + focus=False, pad=None, key=None, visible=True, size_px=(None,None)): + ''' + Button Element + :param button_text: + :param button_type: + :param target: + :param tooltip: + :param file_types: + :param initial_folder: + :param disabled: + :param image_filename: + :param image_size: + :param image_subsample: + :param border_width: + :param size: + :param auto_size_button: + :param button_color: + :param default_value: + :param font: + :param bind_return_key: + :param focus: + :param pad: + :param key: + ''' + self.AutoSizeButton = auto_size_button + self.BType = button_type + self.FileTypes = file_types + self.TKButton = None + self.Target = target + self.ButtonText = str(button_text) + self.ButtonColor = button_color if button_color else DEFAULT_BUTTON_COLOR + self.TextColor = self.ButtonColor[0] + self.BackgroundColor = self.ButtonColor[1] + self.ImageFilename = image_filename + self.ImageData = image_data + self.ImageSize = image_size + self.ImageSubsample = image_subsample + self.UserData = None + self.BorderWidth = border_width if border_width is not None else DEFAULT_BORDER_WIDTH + self.BindReturnKey = bind_return_key + self.Focus = focus + self.TKCal = None + self.CalendarCloseWhenChosen = None + self.DefaultDate_M_D_Y = (None, None, None) + self.InitialFolder = initial_folder + self.Disabled = disabled + self.ChangeSubmits = change_submits or enable_events + self.QT_QPushButton = None + self.ColorChosen = None + self.Relief = None + # self.temp_size = size if size != (NONE, NONE) else + self.Widget = None # type: remi.gui.Button + super().__init__(ELEM_TYPE_BUTTON, size=size, font=font, pad=pad, key=key, tooltip=tooltip, text_color=self.TextColor, background_color=self.BackgroundColor, visible=visible, size_px=size_px) + return + + + + # ------- Button Callback ------- # + def _ButtonCallBack(self, event): + + # print('Button callback') + + # print(f'Parent = {self.ParentForm} Position = {self.Position}') + # Buttons modify targets or return from the form + # If modifying target, get the element object at the target and modify its StrVar + target = self.Target + target_element = None + if target[0] == ThisRow: + target = [self.Position[0], target[1]] + if target[1] < 0: + target[1] = self.Position[1] + target[1] + strvar = None + should_submit_window = False + if target == (None, None): + strvar = self.TKStringVar + else: + if not isinstance(target, str): + if target[0] < 0: + target = [self.Position[0] + target[0], target[1]] + target_element = self.ParentContainer._GetElementAtLocation(target) + else: + target_element = self.ParentForm.FindElement(target) + try: + strvar = target_element.TKStringVar + except: + pass + try: + if target_element.ChangeSubmits: + should_submit_window = True + except: + pass + filetypes = (("ALL Files", "*"),) if self.FileTypes is None else self.FileTypes + if self.BType == BUTTON_TYPE_BROWSE_FOLDER: # Browse Folder + wx_types = convert_tkinter_filetypes_to_wx(self.FileTypes) + if self.InitialFolder: + dialog = wx.DirDialog(self.ParentForm.MasterFrame, style=wx.FD_OPEN) + else: + dialog = wx.DirDialog(self.ParentForm.MasterFrame) + folder_name = '' + if dialog.ShowModal() == wx.ID_OK: + folder_name = dialog.GetPath() + if folder_name != '': + if target_element.Type == ELEM_TYPE_BUTTON: + target_element.FileOrFolderName = folder_name + else: + target_element.Update(folder_name) + elif self.BType == BUTTON_TYPE_BROWSE_FILE: # Browse File + qt_types = convert_tkinter_filetypes_to_wx(self.FileTypes) + if self.InitialFolder: + dialog = wx.FileDialog(self.ParentForm.MasterFrame,defaultDir=self.InitialFolder, wildcard=qt_types, style=wx.FD_OPEN) + else: + dialog = wx.FileDialog(self.ParentForm.MasterFrame, wildcard=qt_types, style=wx.FD_OPEN) + file_name = '' + if dialog.ShowModal() == wx.ID_OK: + file_name = dialog.GetPath() + else: + file_name = '' + if file_name != '': + if target_element.Type == ELEM_TYPE_BUTTON: + target_element.FileOrFolderName = file_name + else: + target_element.Update(file_name) + elif self.BType == BUTTON_TYPE_BROWSE_FILES: # Browse Files + qt_types = convert_tkinter_filetypes_to_wx(self.FileTypes) + if self.InitialFolder: + dialog = wx.FileDialog(self.ParentForm.MasterFrame,defaultDir=self.InitialFolder, wildcard=qt_types, style=wx.FD_MULTIPLE) + else: + dialog = wx.FileDialog(self.ParentForm.MasterFrame, wildcard=qt_types, style=wx.FD_MULTIPLE) + file_names = '' + if dialog.ShowModal() == wx.ID_OK: + file_names = dialog.GetPaths() + else: + file_names = '' + if file_names != '': + file_names = BROWSE_FILES_DELIMITER.join(file_names) + if target_element.Type == ELEM_TYPE_BUTTON: + target_element.FileOrFolderName = file_names + else: + target_element.Update(file_names) + elif self.BType == BUTTON_TYPE_SAVEAS_FILE: # Save As File + qt_types = convert_tkinter_filetypes_to_wx(self.FileTypes) + if self.InitialFolder: + dialog = wx.FileDialog(self.ParentForm.MasterFrame,defaultDir=self.InitialFolder, wildcard=qt_types, style=wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) + else: + dialog = wx.FileDialog(self.ParentForm.MasterFrame, wildcard=qt_types, style=wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) + file_name = '' + if dialog.ShowModal() == wx.ID_OK: + file_name = dialog.GetPath() + else: + file_name = '' + if file_name != '': + if target_element.Type == ELEM_TYPE_BUTTON: + target_element.FileOrFolderName = file_name + else: + target_element.Update(file_name) + elif self.BType == BUTTON_TYPE_COLOR_CHOOSER: # Color Chooser + qcolor = QColorDialog.getColor() + rgb_color = qcolor.getRgb() + color= '#' + ''.join('%02x'% i for i in rgb_color[:3]) + if self.Target == (None, None): + self.FileOrFolderName = color + else: + target_element.Update(color) + elif self.BType == BUTTON_TYPE_CLOSES_WIN: # Closes Window + # first, get the results table built + # modify the Results table in the parent FlexForm object + if self.Key is not None: + self.ParentForm.LastButtonClicked = self.Key + else: + self.ParentForm.LastButtonClicked = self.ButtonText + self.ParentForm.FormRemainedOpen = False + if self.ParentForm.CurrentlyRunningMainloop: + self.ParentForm.App.ExitMainLoop() + self.ParentForm.IgnoreClose = True + self.ParentForm.MasterFrame.Close() + if self.ParentForm.NonBlocking: + Window._DecrementOpenCount() + self.ParentForm._Close() + elif self.BType == BUTTON_TYPE_READ_FORM: # Read Button + # first, get the results table built + # modify the Results table in the parent FlexForm object + # if self.Key is not None: + # self.ParentForm.LastButtonClicked = self.Key + # else: + # self.ParentForm.LastButtonClicked = self.ButtonText + self.ParentForm.FormRemainedOpen = True + element_callback_quit_mainloop(self) + elif self.BType == BUTTON_TYPE_CLOSES_WIN_ONLY: # special kind of button that does not exit main loop + element_callback_quit_mainloop(self) + self.ParentForm._Close() + Window._DecrementOpenCount() + elif self.BType == BUTTON_TYPE_CALENDAR_CHOOSER: # this is a return type button so GET RESULTS and destroy window + should_submit_window = False + + if should_submit_window: + self.ParentForm.LastButtonClicked = target_element.Key + self.ParentForm.FormRemainedOpen = True + self.ParentForm.MessageQueue.put(self.ParentForm.LastButtonClicked) + return + + + def Update(self, text=None, button_color=(None, None), disabled=None, image_data=None, image_filename=None, font=None, visible=None, image_subsample=None, image_size=(None,None)): + if text is not None: + self.Widget.set_text(str(text)) + fg, bg = button_color + if image_data: + self.Widget.empty() + simage = SuperImage(image_data) + if image_size is not (None, None): + simage.set_size(image_size[0], image_size[1]) + self.Widget.append(simage) + if image_filename: + self.Widget.empty() + simage = SuperImage(image_filename) + if image_size is not (None, None): + simage.set_size(image_size[0], image_size[1]) + self.Widget.append(simage) + + super().Update(self.Widget, background_color=bg, text_color=fg, disabled=disabled, font=font, visible=visible) + + + def GetText(self): + return self.Widget.get_text() + + get_text = GetText + update = Update + +# ------------------------- Button lazy functions ------------------------- # +B = Button +Btn = Button +Butt = Button + + +def convert_tkinter_filetypes_to_wx(filetypes): + wx_filetypes = '' + for item in filetypes: + filetype = item[0] + ' (' + item[1] + ')|'+ item[1] + wx_filetypes += filetype + return wx_filetypes + + + + + +# ---------------------------------------------------------------------- # +# ProgreessBar # +# ---------------------------------------------------------------------- # +class ProgressBar(Element): + def __init__(self, max_value, orientation=None, size=(None, None), auto_size_text=None, bar_color=(None, None), + style=None, border_width=None, relief=None, key=None, pad=None): + ''' + ProgressBar Element + :param max_value: + :param orientation: + :param size: + :param auto_size_text: + :param bar_color: + :param style: + :param border_width: + :param relief: + :param key: + :param pad: + ''' + self.MaxValue = max_value + self.TKProgressBar = None + self.Cancelled = False + self.NotRunning = True + self.Orientation = orientation if orientation else DEFAULT_METER_ORIENTATION + self.BarColor = bar_color + self.BarStyle = style if style else DEFAULT_PROGRESS_BAR_STYLE + self.BorderWidth = border_width if border_width else DEFAULT_PROGRESS_BAR_BORDER_WIDTH + self.Relief = relief if relief else DEFAULT_PROGRESS_BAR_RELIEF + self.BarExpired = False + super().__init__(ELEM_TYPE_PROGRESS_BAR, size=size, auto_size_text=auto_size_text, key=key, pad=pad) + + # returns False if update failed + def UpdateBar(self, current_count, max=None): + print('*** NOT IMPLEMENTED ***') + return + if self.ParentForm.TKrootDestroyed: + return False + self.TKProgressBar.Update(current_count, max=max) + try: + self.ParentForm.TKroot.update() + except: + _my_windows.Decrement() + return False + return True + + update_bar = UpdateBar + +# ---------------------------------------------------------------------- # +# Image # +# ---------------------------------------------------------------------- # +class Image(Element): + def __init__(self, filename=None, data=None, background_color=None, size=(None, None), pad=None, key=None, + tooltip=None, right_click_menu=None, visible=True, enable_events=False): + ''' + Image Element + :param filename: + :param data: + :param background_color: + :param size: + :param pad: + :param key: + :param tooltip: + ''' + self.Filename = filename if filename else None # note that Remi expects a / at the front of resource files + self.Data = data + self.tktext_label = None + self.BackgroundColor = background_color + self.Disabled = False + self.EnableEvents = enable_events + sz = (0,0) if size == (None, None) else size + self.Widget = None #type: SuperImage + # if data is None and filename is None: # it is OK to have no image specified when intially creating + # print('* Warning... no image specified in Image Element! *') + super().__init__(ELEM_TYPE_IMAGE, size=sz, background_color=background_color, pad=pad, key=key, + tooltip=tooltip, visible=visible) + return + + def Update(self, filename=None, data=None, size=(None,None), visible=None): + if data is not None: + self.Widget.load(data) + # decoded = base64.b64decode(data) + # with open(r'.\decoded.out', 'wb') as f: + # f.write(decoded) + # filename = r'.\decoded.out' + if filename is not None: + self.Widget.load(filename) + # self.Widget.set_image(filename=filename) + # if size != (None, None): + # self.Widget.style['height'] = '{}px'.format(size[1]) + # self.Widget.style['width'] = '{}px'.format(size[0]) + super().Update(self.Widget, visible=visible) + + update = Update + + + +# class SuperImageOld(remi.gui.Image): +# def __init__(self, file_path_name=None, **kwargs): +# image = file_path_name +# super(SuperImage, self).__init__(image, **kwargs) +# +# self.imagedata = None +# self.mimetype = None +# self.encoding = None +# if image is None: +# return +# self.load(image) +# +# def load(self, file_path_name): +# if type(file_path_name) is bytes or len(file_path_name) > 200: +# try: +# self.imagedata = base64.b64decode(file_path_name, validate=True) +# except binascii.Error: +# self.imagedata = file_path_name +# else: +# self.mimetype, self.encoding = mimetypes.guess_type(file_path_name) +# with open(file_path_name, 'rb') as f: +# self.imagedata = f.read() +# self.refresh() +# +# def refresh(self): +# i = int(time.time() * 1e6) +# self.attributes['src'] = "/%s/get_image_data?update_index=%d" % (id(self), i) +# +# def get_image_data(self, update_index): +# headers = {'Content-type': self.mimetype if self.mimetype else 'application/octet-stream'} +# return [self.imagedata, headers] + + +class SuperImage(remi.gui.Image): + def __init__(self, file_path_name=None, **kwargs): + """ + This new app_instance variable is causing lots of problems. I do not know the value of the App + when I create this image. + :param app_instance: + :param file_path_name: + :param kwargs: + """ + # self.app_instance = app_instance + image = file_path_name + super(SuperImage, self).__init__(image, **kwargs) + + self.imagedata = None + self.mimetype = None + self.encoding = None + if not image: return + self.load(image) + + def load(self, file_path_name): + if type(file_path_name) is bytes: + try: + #here a base64 image is received + self.imagedata = base64.b64decode(file_path_name, validate=True) + self.attributes['src'] = "/%s/get_image_data?update_index=%s" % (id(self), str(time.time())) + except binascii.Error: + #here an image data is received (opencv image) + self.imagedata = file_path_name + self.refresh() + self.refresh() + else: + #here a filename is received + self.attributes['src'] = remi.gui.load_resource(file_path_name) + """print(f'***** Loading file = {file_path_name}') + self.mimetype, self.encoding = mimetypes.guess_type(file_path_name) + with open(file_path_name, 'rb') as f: + self.imagedata = f.read()""" + self.refresh() + + def refresh(self): + i = int(time.time() * 1e6) + # self.app_instance.execute_javascript(""" + if Window.App is not None: + Window.App.execute_javascript(""" + var url = '/%(id)s/get_image_data?update_index=%(frame_index)s'; + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, true); + xhr.responseType = 'blob' + xhr.onload = function(e){ + var urlCreator = window.URL || window.webkitURL; + var imageUrl = urlCreator.createObjectURL(this.response); + document.getElementById('%(id)s').src = imageUrl; + } + xhr.send(); + """ % {'id': id(self), 'frame_index':i}) + + def get_image_data(self, update_index): + headers = {'Content-type': self.mimetype if self.mimetype else 'application/octet-stream'} + return [self.imagedata, headers] + + +# ---------------------------------------------------------------------- # +# Graph # +# ---------------------------------------------------------------------- # +class Graph(Element): + def __init__(self, canvas_size, graph_bottom_left, graph_top_right, background_color=None, pad=None, + change_submits=False, drag_submits=False, size_px=(None,None), enable_events=False, key=None, visible=True, disabled=False, tooltip=None): + ''' + Graph Element + :param canvas_size: + :param graph_bottom_left: + :param graph_top_right: + :param background_color: + :param pad: + :param key: + :param tooltip: + ''' + self.CanvasSize = canvas_size + self.BottomLeft = graph_bottom_left + self.TopRight = graph_top_right + self.ChangeSubmits = change_submits or enable_events + self.DragSubmits = drag_submits + self.ClickPosition = (None, None) + self.MouseButtonDown = False + self.Disabled = disabled + self.Widget = None # type: remi.gui.Svg + self.SvgGroup = None # type: remi.gui.SvgSubcontainer + super().__init__(ELEM_TYPE_GRAPH, size=canvas_size, size_px=size_px, visible=visible, background_color=background_color, pad=pad, tooltip=tooltip, key=key) + return + + def _convert_xy_to_canvas_xy(self, x_in, y_in): + if None in (x_in, y_in): + return None, None + scale_x = (self.CanvasSize[0] - 0) / (self.TopRight[0] - self.BottomLeft[0]) + scale_y = (0 - self.CanvasSize[1]) / (self.TopRight[1] - self.BottomLeft[1]) + new_x = 0 + scale_x * (x_in - self.BottomLeft[0]) + new_y = self.CanvasSize[1] + scale_y * (y_in - self.BottomLeft[1]) + return new_x, new_y + + def _convert_canvas_xy_to_xy(self, x_in, y_in): + if None in (x_in, y_in): + return None, None + x_in, y_in = int(x_in), int(y_in) + scale_x = (self.CanvasSize[0] - 0) / (self.TopRight[0] - self.BottomLeft[0]) + scale_y = (0 - self.CanvasSize[1]) / (self.TopRight[1] - self.BottomLeft[1]) + new_x = x_in / scale_x + self.BottomLeft[0] + new_y = (y_in - self.CanvasSize[1]) / scale_y + self.BottomLeft[1] + return int(new_x), int(new_y) + + def DrawLine(self, point_from, point_to, color='black', width=1): + if point_from == (None, None) or color is None: + return + converted_point_from = self._convert_xy_to_canvas_xy(point_from[0], point_from[1]) + converted_point_to = self._convert_xy_to_canvas_xy(point_to[0], point_to[1]) + if self.Widget is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + line = remi.gui.SvgLine(converted_point_from[0], converted_point_from[1], converted_point_to[0], converted_point_to[1]) + line.set_stroke(width, color) + self.SvgGroup.append([line,]) + return line + + def DrawPoint(self, point, size=2, color='black'): + if point == (None, None): + return + converted_point = self._convert_xy_to_canvas_xy(point[0], point[1]) + if self.Widget is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + rpoint = remi.gui.SvgCircle(converted_point[0], converted_point[1], size) + rpoint.set_stroke(size, color) + rpoint.set_fill(color) + self.SvgGroup.append([rpoint,]) + return rpoint + + + def DrawCircle(self, center_location, radius, fill_color=None, line_color='black'): + if center_location == (None, None): + return + converted_point = self._convert_xy_to_canvas_xy(center_location[0], center_location[1]) + if self.Widget is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + rpoint = remi.gui.SvgCircle(converted_point[0], converted_point[1], radius=radius) + rpoint.set_fill(fill_color) + rpoint.set_stroke(color=line_color) + self.SvgGroup.append([rpoint,]) + return rpoint + + + def DrawOval(self, top_left, bottom_right, fill_color=None, line_color=None): + converted_top_left = self._convert_xy_to_canvas_xy(top_left[0], top_left[1]) + converted_bottom_right = self._convert_xy_to_canvas_xy(bottom_right[0], bottom_right[1]) + if self.Widget is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + return + + + # def DrawArc(self, top_left, bottom_right, extent, start_angle, style=None, arc_color='black'): + # converted_top_left = self._convert_xy_to_canvas_xy(top_left[0], top_left[1]) + # converted_bottom_right = self._convert_xy_to_canvas_xy(bottom_right[0], bottom_right[1]) + # tkstyle = tk.PIESLICE if style is None else style + # if self._TKCanvas2 is None: + # print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + # print('Call Window.Finalize() prior to this operation') + # return None + # return + + def DrawRectangle(self, top_left, bottom_right, fill_color=None, line_color='black'): + converted_top_left = self._convert_xy_to_canvas_xy(top_left[0], top_left[1]) + converted_bottom_right = self._convert_xy_to_canvas_xy(bottom_right[0], bottom_right[1]) + if self.Widget is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + + rpoint = remi.gui.SvgRectangle(converted_top_left[0], converted_top_left[1], abs(converted_bottom_right[0]-converted_top_left[0]), abs(converted_top_left[1] - converted_bottom_right[1])) + rpoint.set_stroke(width=1, color=line_color) + if fill_color is not None: + rpoint.set_fill(fill_color) + else: + rpoint.set_fill('transparent') + self.SvgGroup.append([rpoint,]) + return rpoint + + + + def DrawText(self, text, location, color='black', font=None, angle=0): + text = str(text) + if location == (None, None): + return + converted_point = self._convert_xy_to_canvas_xy(location[0], location[1]) + if self.Widget is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + + rpoint = remi.gui.SvgText(converted_point[0], converted_point[1], text) + self.SvgGroup.append([rpoint,]) + # self.SvgGroup.redraw() + return rpoint + + + def DrawImage(self, data=None, image_source=None, location=(None, None), size=(100, 100)): + if location == (None, None): + return + if data is not None: + image_source = data.decode('utf-8') if type(data) is bytes else data + converted_point = self._convert_xy_to_canvas_xy(location[0], location[1]) + if self.Widget is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + + rpoint = remi.gui.SvgImage('', converted_point[0], converted_point[0], size[0], size[1]) + + if type(image_source) is bytes or len(image_source) > 200: + # rpoint.set_image("data:image/svg;base64,%s"%image_source) + rpoint.image_data = "data:image/svg;base64,%s"%image_source + else: + mimetype, encoding = mimetypes.guess_type(image_source) + with open(image_source, 'rb') as f: + data = f.read() + b64 = base64.b64encode(data) + b64_str = b64.decode("utf-8") + image_string = "data:image/svg;base64,%s"%b64_str + # rpoint.set_image(image_string) + rpoint.image_data = image_string + self.SvgGroup.append([rpoint,]) + rpoint.redraw() + self.SvgGroup.redraw() + return rpoint + + def Erase(self): + if self.Widget is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + self.Widget.empty() + self.SvgGroup = remi.gui.SvgSubcontainer(0, 0, "100%", "100%") + self.Widget.append(self.SvgGroup) + + def Update(self, background_color): + if self.Widget is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + if self.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT): + self.Widget.style['background-color'] = self.BackgroundColor + + def Move(self, x_direction, y_direction): + # TODO - IT's still not working yet! I'm trying!! + + # self.MoveFigure(self.SvgGroup, x_direction,y_direction) + # return + zero_converted = self._convert_xy_to_canvas_xy(0, 0) + shift_converted = self._convert_xy_to_canvas_xy(x_direction, y_direction) + shift_amount = (shift_converted[0] - zero_converted[0], shift_converted[1] - zero_converted[1]) + if self.Widget is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + print(self.SvgGroup.attributes) + cur_x = float(self.SvgGroup.attributes['x']) + cur_y = float(self.SvgGroup.attributes['y']) + self.SvgGroup.set_position(cur_x - x_direction,cur_y - y_direction) + self.SvgGroup.redraw() + + + def Relocate(self, x, y): + shift_converted = self._convert_xy_to_canvas_xy(x, y) + if self.Widget is None: + print('*** WARNING - Your figure is None. It most likely means your did not Finalize your Window ***') + print('Call Window.Finalize() prior to all graph operations') + return None + # figure.empty() + self.SvgGroup.set_position(shift_converted[0], shift_converted[1]) + self.SvgGroup.redraw() + + + def MoveFigure(self, figure, x_direction, y_direction): + figure = figure # type: remi.gui.SvgCircle + zero_converted = self._convert_xy_to_canvas_xy(0, 0) + shift_converted = self._convert_xy_to_canvas_xy(x_direction, y_direction) + shift_amount = (shift_converted[0] - zero_converted[0], shift_converted[1] - zero_converted[1]) + if figure is None: + print('*** WARNING - Your figure is None. It most likely means your did not Finalize your Window ***') + print('Call Window.Finalize() prior to all graph operations') + return None + print(figure.attributes) + try: + cur_x = float(figure.attributes['x']) + cur_y = float(figure.attributes['y']) + figure.set_position(cur_x - x_direction,cur_y - y_direction) + except: + cur_x1 = float(figure.attributes['x1']) + cur_x2 = float(figure.attributes['x2']) + cur_y1 = float(figure.attributes['y1']) + cur_y2 = float(figure.attributes['y2']) + figure.set_coords(cur_x1-x_direction, cur_y1-y_direction, cur_x2-x_direction, cur_y2-x_direction) + figure.redraw() + + def RelocateFigure(self, figure, x, y): + figure = figure #type: remi.gui.SvgCircle + zero_converted = self._convert_xy_to_canvas_xy(0, 0) + shift_converted = self._convert_xy_to_canvas_xy(x, y) + shift_amount = (shift_converted[0] - zero_converted[0], shift_converted[1] - zero_converted[1]) + if figure is None: + print('*** WARNING - Your figure is None. It most likely means your did not Finalize your Window ***') + print('Call Window.Finalize() prior to all graph operations') + return None + # figure.empty() + figure.set_position(shift_converted[0], shift_converted[1]) + figure.redraw() + + + def DeleteFigure(self, figure): + figure = figure # type: remi.gui.SvgCircle + if figure is None: + print('*** WARNING - Your figure is None. It most likely means your did not Finalize your Window ***') + print('Call Window.Finalize() prior to all graph operations') + return None + self.SvgGroup.remove_child(figure) + del figure + + def change_coordinates(self, graph_bottom_left, graph_top_right): + """ + Changes the corrdinate system to a new one. The same 2 points in space are used to define the coorinate + system - the bottom left and the top right values of your graph. + + :param graph_bottom_left: Tuple[int, int] (x,y) The bottoms left corner of your coordinate system + :param graph_top_right: Tuple[int, int] (x,y) The top right corner of your coordinate system + """ + self.BottomLeft = graph_bottom_left + self.TopRight = graph_top_right + + + def _MouseDownCallback(self, widget, x,y, *args): + # print(f'Mouse down {x,y}') + self.MouseButtonDown = True + + def _MouseUpCallback(self, widget, x,y, *args): + self.ClickPosition = self._convert_canvas_xy_to_xy(int(x), int(y)) + self.MouseButtonDown = False + if self.ChangeSubmits: + # self.ClickPosition = (None, None) + self.ParentForm.LastButtonClicked = self.Key if self.Key is not None else '' + self.ParentForm.MessageQueue.put(self.ParentForm.LastButtonClicked) + + # def ClickCallback(self, emitter, x, y): + def ClickCallback(self, widget:remi.gui.Svg, *args): + return + self.ClickPosition = (None, None) + self.ParentForm.LastButtonClicked = self.Key if self.Key is not None else '' + self.ParentForm.MessageQueue.put(self.ParentForm.LastButtonClicked) + + def _DragCallback(self, emitter, x, y): + if not self.MouseButtonDown: # only return drag events when mouse is down + return + # print(f'In Drag Callback') + self.ClickPosition = self._convert_canvas_xy_to_xy(x, y) + # print(f'Position {self.ClickPosition}') + self.ParentForm.LastButtonClicked = self.Key if self.Key is not None else '' + self.ParentForm.MessageQueue.put(self.ParentForm.LastButtonClicked) + + + + click_callback = ClickCallback + delete_figure = DeleteFigure + draw_circle = DrawCircle + draw_image = DrawImage + draw_line = DrawLine + draw_oval = DrawOval + draw_point = DrawPoint + draw_rectangle = DrawRectangle + draw_text = DrawText + erase = Erase + move = Move + move_figure = MoveFigure + relocate = Relocate + relocate_figure = RelocateFigure + update = Update + + +# ---------------------------------------------------------------------- # +# Frame # +# ---------------------------------------------------------------------- # + +# First the REMI implementation of a frame + +class CLASSframe( remi.gui.VBox ): + def __init__(self, title, *args, **kwargs): + super( CLASSframe, self ).__init__(*args, **kwargs) + self.style.update({"overflow":"visible","border-width":"1px","border-style":"solid","border-color":"#7d7d7d"}) + self.frame_label = remi.gui.Label('frame label') + self.frame_label.style.update({"position":"relative","overflow":"auto","background-color":"#ffffff","border-width":"1px","border-style":"solid","top":"-7px","width":"0px","height":"0px","left":"10px"}) + self.append(self.frame_label,'frame_label') + self.set_title(title) + + def set_title(self, title): + self.frame_label.set_text(title) + + +class Frame(Element): + def __init__(self, title, layout, title_color=None, background_color=None, title_location=None, + relief=DEFAULT_FRAME_RELIEF, element_justification='left', size=(None, None), font=None, pad=None, border_width=None, key=None, + tooltip=None): + ''' + Frame Element + :param title: + :param layout: + :param title_color: + :param background_color: + :param title_location: + :param relief: + :param size: + :param font: + :param pad: + :param border_width: + :param key: + :param tooltip: + ''' + self.UseDictionary = False + self.ReturnValues = None + self.ReturnValuesList = [] + self.ReturnValuesDictionary = {} + self.DictionaryKeyCounter = 0 + self.ParentWindow = None + self.Rows = [] + # self.ParentForm = None + self.TKFrame = None + self.Title = title + self.Relief = relief + self.TitleLocation = title_location + self.BorderWidth = border_width + self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR + self.Justification = 'left' + self.ElementJustification = element_justification + self.Widget = None # type: CLASSframe + + + + self.Layout(layout) + + super().__init__(ELEM_TYPE_FRAME, background_color=background_color, text_color=title_color, size=size, + font=font, pad=pad, key=key, tooltip=tooltip) + return + + def AddRow(self, *args): + ''' Parms are a variable number of Elements ''' + NumRows = len(self.Rows) # number of existing rows is our row number + CurrentRowNumber = NumRows # this row's number + CurrentRow = [] # start with a blank row and build up + # ------------------------- Add the elements to a row ------------------------- # + for i, element in enumerate(args): # Loop through list of elements and add them to the row + element.Position = (CurrentRowNumber, i) + element.ParentContainer = self + CurrentRow.append(element) + if element.Key is not None: + self.UseDictionary = True + # ------------------------- Append the row to list of Rows ------------------------- # + self.Rows.append(CurrentRow) + + def Layout(self, rows): + for row in rows: + self.AddRow(*row) + + def _GetElementAtLocation(self, location): + (row_num, col_num) = location + row = self.Rows[row_num] + element = row[col_num] + return element + + add_row = AddRow + layout = Layout + + +# ---------------------------------------------------------------------- # +# Separator # +# Routes stdout, stderr to a scrolled window # +# ---------------------------------------------------------------------- # +class VerticalSeparator(Element): + def __init__(self, pad=None): + ''' + VerticalSeperator - A separator that spans only 1 row in a vertical fashion + :param pad: + ''' + self.Orientation = 'vertical' # for now only vertical works + + super().__init__(ELEM_TYPE_SEPARATOR, pad=pad) + + +VSeperator = VerticalSeparator +VSeparator = VerticalSeparator +VSep = VerticalSeparator + + +# ---------------------------------------------------------------------- # +# Tab # +# ---------------------------------------------------------------------- # +class Tab(Element): + def __init__(self, title, layout, title_color=None, background_color=None, font=None, pad=None, disabled=False, element_justification='left', border_width=None, key=None, tooltip=None): + ''' + Tab Element + :param title: + :param layout: + :param title_color: + :param background_color: + :param font: + :param pad: + :param disabled: + :param border_width: + :param key: + :param tooltip: + ''' + self.UseDictionary = False + self.ReturnValues = None + self.ReturnValuesList = [] + self.ReturnValuesDictionary = {} + self.DictionaryKeyCounter = 0 + self.ParentWindow = None + self.Rows = [] + self.TKFrame = None + self.Title = title + self.BorderWidth = border_width + self.Disabled = disabled + self.ParentNotebook = None + self.Justification = 'left' + self.ElementJustification = element_justification + self.TabID = None + self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR + self.Widget = None # type: remi.gui.HBox + self._Layout(layout) + + super().__init__(ELEM_TYPE_TAB, background_color=background_color, text_color=title_color, font=font, pad=pad, + key=key, tooltip=tooltip) + return + + def _AddRow(self, *args): + ''' Parms are a variable number of Elements ''' + NumRows = len(self.Rows) # number of existing rows is our row number + CurrentRowNumber = NumRows # this row's number + CurrentRow = [] # start with a blank row and build up + # ------------------------- Add the elements to a row ------------------------- # + for i, element in enumerate(args): # Loop through list of elements and add them to the row + element.Position = (CurrentRowNumber, i) + element.ParentContainer = self + CurrentRow.append(element) + if element.Key is not None: + self.UseDictionary = True + # ------------------------- Append the row to list of Rows ------------------------- # + self.Rows.append(CurrentRow) + + def _Layout(self, rows): + for row in rows: + self._AddRow(*row) + return self + + # def Update(self, disabled=None): # TODO Disable / enable of tabs is not complete + # print('*** Tab.Update is not implemented ***') + # return + # if disabled is None: + # return + # self.Disabled = disabled + # state = 'disabled' if disabled is True else 'normal' + # self.ParentNotebook.tab(self.TabID, state=state) + # return self + + def _GetElementAtLocation(self, location): + (row_num, col_num) = location + row = self.Rows[row_num] + element = row[col_num] + return element + + +# ---------------------------------------------------------------------- # +# TabGroup # +# ---------------------------------------------------------------------- # +class TabGroup(Element): + def __init__(self, layout, tab_location=None, title_color=None, selected_title_color=None, background_color=None, + font=None, change_submits=False, enable_events=False,pad=None, border_width=None, theme=None, key=None, tooltip=None, visible=True): + ''' + TabGroup Element + :param layout: + :param tab_location: + :param title_color: + :param selected_title_color: + :param background_color: + :param font: + :param change_submits: + :param pad: + :param border_width: + :param theme: + :param key: + :param tooltip: + ''' + self.UseDictionary = False + self.ReturnValues = None + self.ReturnValuesList = [] + self.ReturnValuesDictionary = {} + self.DictionaryKeyCounter = 0 + self.ParentWindow = None + self.SelectedTitleColor = selected_title_color + self.Rows = [] + self.TKNotebook = None + self.Widget = None # type: remi.gui.TabBox + self.Justification = 'left' + self.TabCount = 0 + self.BorderWidth = border_width + self.Theme = theme + self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR + self.ChangeSubmits = enable_events or change_submits + self.TabLocation = tab_location + self.Visible = visible + self.Disabled = False + self._Layout(layout) + + super().__init__(ELEM_TYPE_TAB_GROUP, background_color=background_color, text_color=title_color, font=font, + pad=pad, key=key, tooltip=tooltip) + return + + def _AddRow(self, *args): + ''' Parms are a variable number of Elements ''' + NumRows = len(self.Rows) # number of existing rows is our row number + CurrentRowNumber = NumRows # this row's number + CurrentRow = [] # start with a blank row and build up + # ------------------------- Add the elements to a row ------------------------- # + for i, element in enumerate(args): # Loop through list of elements and add them to the row + element.Position = (CurrentRowNumber, i) + element.ParentContainer = self + CurrentRow.append(element) + if element.Key is not None: + self.UseDictionary = True + # ------------------------- Append the row to list of Rows ------------------------- # + self.Rows.append(CurrentRow) + + def _Layout(self, rows): + for row in rows: + self._AddRow(*row) + + def _GetElementAtLocation(self, location): + (row_num, col_num) = location + row = self.Rows[row_num] + element = row[col_num] + return element + + def FindKeyFromTabName(self, tab_name): + for row in self.Rows: + for element in row: + if element.Title == tab_name: + return element.Key + return None + + find_key_from_tab_name = FindKeyFromTabName + + +# ---------------------------------------------------------------------- # +# Slider # +# ---------------------------------------------------------------------- # +class Slider(Element): + def __init__(self, range=(None, None), default_value=None, resolution=None, tick_interval=None, orientation=None, + border_width=None, relief=None, change_submits=False, enable_events=False, disabled=False, size=(None, None), font=None, + background_color=None, text_color=None, key=None, pad=None, tooltip=None, visible=True, size_px=(None,None)): + """ + + :param range: + :param default_value: + :param resolution: + :param tick_interval: + :param orientation: + :param border_width: + :param relief: + :param change_submits: + :param enable_events: + :param disabled: + :param visible: + :param size_px: + """ + self.TKScale = None + self.Range = (1, 10) if range == (None, None) else range + self.DefaultValue = self.Range[0] if default_value is None else default_value + self.Orientation = orientation if orientation else DEFAULT_SLIDER_ORIENTATION + self.BorderWidth = border_width if border_width else DEFAULT_SLIDER_BORDER_WIDTH + self.Relief = relief if relief else DEFAULT_SLIDER_RELIEF + self.Resolution = 1 if resolution is None else resolution + self.ChangeSubmits = change_submits or enable_events + self.Disabled = disabled + self.TickInterval = tick_interval + temp_size = size + if temp_size == (None, None): + temp_size = (200, 20) if self.Orientation.startswith('h') else (200, 20) + elif size[0] is not None and size[0] < 100: + temp_size = size[0]*10, size[1]*3 + self.Widget = None # type: remi.gui.Slider + + super().__init__(ELEM_TYPE_INPUT_SLIDER, size=temp_size, font=font, background_color=background_color, + text_color=text_color, key=key, pad=pad, tooltip=tooltip, visible=visible, size_px=size_px) + return + + def Update(self, value=None, range=(None, None), disabled=None, visible=None): + if value is not None: + self.Widget.set_value(value) + self.DefaultValue = value + if range != (None, None): + self.Widget.attributes['min'] = '{}'.format(range[0]) + self.Widget.attributes['max'] = '{}'.format(range[1]) + super().Update(self.Widget, disabled=disabled, visible=visible) + + def _SliderCallback(self, widget:remi.Widget, value): + self.ParentForm.LastButtonClicked = self.Key if self.Key is not None else '' + self.ParentForm.MessageQueue.put(self.ParentForm.LastButtonClicked) + + update = Update + +# +# ---------------------------------------------------------------------- # +# Column # +# ---------------------------------------------------------------------- # +class Column(Element): + def __init__(self, layout, background_color=None, size=(None, None), pad=None, scrollable=False, vertical_scroll_only=False, element_justification='left', key=None): + ''' + Column Element + :param layout: + :param background_color: + :param size: + :param pad: + :param scrollable: + :param key: + ''' + self.UseDictionary = False + self.ReturnValues = None + self.ReturnValuesList = [] + self.ReturnValuesDictionary = {} + self.DictionaryKeyCounter = 0 + self.ParentWindow = None + self.Rows = [] + self.TKFrame = None + self.Scrollable = scrollable + self.VerticalScrollOnly = vertical_scroll_only + self.ElementJustification = element_justification + # self.ImageFilename = image_filename + # self.ImageData = image_data + # self.ImageSize = image_size + # self.ImageSubsample = image_subsample + # bg = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR + + self.Layout(layout) + + super().__init__(ELEM_TYPE_COLUMN, background_color=background_color, size=size, pad=pad, key=key) + return + + def AddRow(self, *args): + ''' Parms are a variable number of Elements ''' + NumRows = len(self.Rows) # number of existing rows is our row number + CurrentRowNumber = NumRows # this row's number + CurrentRow = [] # start with a blank row and build up + # ------------------------- Add the elements to a row ------------------------- # + for i, element in enumerate(args): # Loop through list of elements and add them to the row + element.Position = (CurrentRowNumber, i) + element.ParentContainer = self + CurrentRow.append(element) + if element.Key is not None: + self.UseDictionary = True + # ------------------------- Append the row to list of Rows ------------------------- # + self.Rows.append(CurrentRow) + + def Layout(self, rows): + for row in rows: + self.AddRow(*row) + + def _GetElementAtLocation(self, location): + (row_num, col_num) = location + row = self.Rows[row_num] + element = row[col_num] + return element + + add_row = AddRow + layout = Layout + + +Col = Column + + +# ---------------------------------------------------------------------- # +# Menu # +# ---------------------------------------------------------------------- # +class Menu(Element): + def __init__(self, menu_definition, background_color=COLOR_SYSTEM_DEFAULT, text_color=None, size=(None, None), tearoff=False, pad=None, key=None, disabled=False, font=None): + ''' + Menu Element + :param menu_definition: + :param background_color: + :param size: + :param tearoff: + :param pad: + :param key: + ''' + back_color = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR + self.MenuDefinition = menu_definition + self.TKMenu = None + self.Tearoff = tearoff + self.Widget = None # type: remi.gui.MenuBar + self.MenuItemChosen = None + self.Disabled = disabled + + super().__init__(ELEM_TYPE_MENUBAR, background_color=back_color, text_color=text_color, size=size, pad=pad, key=key, font=font) + return + + + + def _ChangedCallbackMenu(self, widget, *user_data): + widget = widget # type: remi.gui.MenuItem + chosen = user_data[0] + self.MenuItemChosen = chosen + self.ParentForm.LastButtonClicked = chosen + self.ParentForm.MessageQueue.put(chosen) + + +# ---------------------------------------------------------------------- # +# Table # +# ---------------------------------------------------------------------- # +class Table(Element): + def __init__(self, values, headings=None, visible_column_map=None, col_widths=None, def_col_width=10, + auto_size_columns=True, max_col_width=20, select_mode=None, display_row_numbers=False, row_header_text='Row', starting_row_num=0, num_rows=None, row_height=None, font=None, justification='right', text_color=None, background_color=None, alternating_row_color=None, row_colors=None, vertical_scroll_only=True, disabled=False, + size=(None, None), change_submits=False, enable_events=False, bind_return_key=False, pad=None, key=None, tooltip=None, right_click_menu=None, visible=True, size_px=(None, None)): + ''' + Table + :param values: + :param headings: + :param visible_column_map: + :param col_widths: + :param def_col_width: + :param auto_size_columns: + :param max_col_width: + :param select_mode: + :param display_row_numbers: + :param num_rows: + :param row_height: + :param font: + :param justification: + :param text_color: + :param background_color: + :param alternating_row_color: + :param size: + :param change_submits: + :param enable_events: + :param bind_return_key: + :param pad: + :param key: + :param tooltip: + :param right_click_menu: + :param visible: + ''' + self.Values = values + self.ColumnHeadings = headings + self.ColumnsToDisplay = visible_column_map + self.ColumnWidths = col_widths + self.MaxColumnWidth = max_col_width + self.DefaultColumnWidth = def_col_width + self.AutoSizeColumns = auto_size_columns + self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR + self.TextColor = text_color + self.Justification = justification + self.InitialState = None + self.SelectMode = select_mode + self.DisplayRowNumbers = display_row_numbers + self.NumRows = num_rows if num_rows is not None else size[1] + self.RowHeight = row_height + self.TKTreeview = None + self.AlternatingRowColor = alternating_row_color + self.VerticalScrollOnly = vertical_scroll_only + self.SelectedRows = [] + self.ChangeSubmits = change_submits or enable_events + self.BindReturnKey = bind_return_key + self.StartingRowNumber = starting_row_num # When displaying row numbers, where to start + self.RowHeaderText = row_header_text + self.RightClickMenu = right_click_menu + self.RowColors = row_colors + self.Disabled = disabled + self.SelectedItem = None + self.SelectedRow = None + self.Widget = None # type: remi.Table + + super().__init__(ELEM_TYPE_TABLE, text_color=text_color, background_color=background_color, font=font, + size=size, pad=pad, key=key, tooltip=tooltip, visible=visible, size_px=size_px) + return + + def Update(self, values=None): + print('*** Table Update not yet supported ***') + return + if values is not None: + children = self.TKTreeview.get_children() + for i in children: + self.TKTreeview.detach(i) + self.TKTreeview.delete(i) + children = self.TKTreeview.get_children() + # self.TKTreeview.delete(*self.TKTreeview.get_children()) + for i, value in enumerate(values): + if self.DisplayRowNumbers: + value = [i + self.StartingRowNumber] + value + id = self.TKTreeview.insert('', 'end', text=i, iid=i + 1, values=value, tag=i % 2) + if self.AlternatingRowColor is not None: + self.TKTreeview.tag_configure(1, background=self.AlternatingRowColor) + self.Values = values + self.SelectedRows = [] + + + def _on_table_row_click(self, table, row, item): + # self.SelectedRow = row # type: remi.gui.TableRow + self.SelectedItem = item.get_text() + index = -1 + # each widget (and specifically in this case the table) has a _render_children_list attribute that + # is an ordered list of the children keys + # first, we search for the row in the children dictionary + for key, value in table.children.items(): + if value == row: + # if the row is found, we get the index in the ordered list + index = table._render_children_list.index(key) + break + self.SelectedRow = index + if self.ChangeSubmits: + self.ParentForm.LastButtonClicked = self.Key if self.Key is not None else '' + self.ParentForm.MessageQueue.put(self.ParentForm.LastButtonClicked) + else: + self.ParentForm.LastButtonClicked = '' + + + + +# ---------------------------------------------------------------------- # +# Tree # +# ---------------------------------------------------------------------- # +class Tree(Element): + def __init__(self, data=None, headings=None, visible_column_map=None, col_widths=None, col0_width=10, + def_col_width=10, auto_size_columns=True, max_col_width=20, select_mode=None, show_expanded=False, + change_submits=False, font=None, + justification='right', text_color=None, background_color=None, num_rows=None, pad=None, key=None, + tooltip=None): + ''' + Tree Element + :param headings: + :param visible_column_map: + :param col_widths: + :param def_col_width: + :param auto_size_columns: + :param max_col_width: + :param select_mode: + :param font: + :param justification: + :param text_color: + :param background_color: + :param num_rows: + :param pad: + :param key: + :param tooltip: + ''' + self.TreeData = data + self.ColumnHeadings = headings + self.ColumnsToDisplay = visible_column_map + self.ColumnWidths = col_widths + self.MaxColumnWidth = max_col_width + self.DefaultColumnWidth = def_col_width + self.AutoSizeColumns = auto_size_columns + self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR + self.TextColor = text_color + self.Justification = justification + self.InitialState = None + self.SelectMode = select_mode + self.ShowExpanded = show_expanded + self.NumRows = num_rows + self.Col0Width = col0_width + self.TKTreeview = None + self.SelectedRows = [] + self.ChangeSubmits = change_submits + + print('*** Tree Element not yet supported ***') + + super().__init__(ELEM_TYPE_TREE, text_color=text_color, background_color=background_color, font=font, pad=pad, + key=key, tooltip=tooltip) + + + def add_treeview_data(self, node): + # print(f'Inserting {node.key} under parent {node.parent}') + if node.key != '': + self.TKTreeview.insert(node.parent, 'end', node.key, text=node.text, values=node.values, + open=self.ShowExpanded) + for node in node.children: + self.add_treeview_data(node) + + def Update(self, values=None, key=None, value=None, text=None): + print('*** Tree Element not yet supported ***') + if values is not None: + children = self.TKTreeview.get_children() + for i in children: + self.TKTreeview.detach(i) + self.TKTreeview.delete(i) + children = self.TKTreeview.get_children() + self.TreeData = values + self.add_treeview_data(self.TreeData.root_node) + self.SelectedRows = [] + if key is not None: + item = self.TKTreeview.item(key) + if value is not None: + self.TKTreeview.item(key, values=value) + if text is not None: + self.TKTreeview.item(key, text=text) + item = self.TKTreeview.item(key) + return self + + update = Update + + +class TreeData(object): + class Node(object): + def __init__(self, parent, key, text, values): + self.parent = parent + self.children = [] + self.key = key + self.text = text + self.values = values + + def _Add(self, node): + self.children.append(node) + + def __init__(self): + self.tree_dict = {} + self.root_node = self.Node("", "", 'root', []) + self.tree_dict[""] = self.root_node + + def _AddNode(self, key, node): + self.tree_dict[key] = node + + def Insert(self, parent, key, text, values): + node = self.Node(parent, key, text, values) + self.tree_dict[key] = node + parent_node = self.tree_dict[parent] + parent_node._Add(node) + + def __repr__(self): + return self._NodeStr(self.root_node, 1) + + def _NodeStr(self, node, level): + return '\n'.join( + [str(node.key) + ' : ' + str(node.text)] + + [' ' * 4 * level + self._NodeStr(child, level + 1) for child in node.children]) + + insert = Insert + +# ---------------------------------------------------------------------- # +# Error Element # +# ---------------------------------------------------------------------- # +class ErrorElement(Element): + def __init__(self, key=None): + ''' + Error Element + :param key: + ''' + self.Key = key + + super().__init__(ELEM_TYPE_ERROR, key=key) + return + + def Update(self, *args, **kwargs): + PopupError('Keyword error in Update', + 'You need to stop this madness and check your spelling', + 'Bad key = {}'.format(self.Key), + 'Your bad line of code may resemble this:', + 'window.FindElement("{}")'.format(self.Key)) + return self + + def Get(self): + return 'This is NOT a valid Element!\nSTOP trying to do things with it or I will have to crash at some point!' + + get = Get + update = Update + + +# ------------------------------------------------------------------------- # +# Window CLASS # +# ------------------------------------------------------------------------- # +class Window: + + _NumOpenWindows = 0 + user_defined_icon = None + hidden_master_root = None + QTApplication = None + active_popups = {} + highest_level_app = None + stdout_is_rerouted = False + stdout_string_io = None + stdout_location = None + port_number = 6900 + active_windows = [ ] # type: [Window] + App = None # type: remi.App + + def __init__(self, title, layout=None, default_element_size=DEFAULT_ELEMENT_SIZE, default_button_element_size=(None, None), + auto_size_text=None, auto_size_buttons=None, location=(None, None), size=(None, None), + element_padding=None, button_color=None, font=None, + progress_bar_color=(None, None), background_color=None, border_depth=None, auto_close=False, + auto_close_duration=None, icon=DEFAULT_BASE64_ICON, force_toplevel=False, + alpha_channel=1, return_keyboard_events=False, return_key_down_events=False, use_default_focus=True, text_justification=None, + no_titlebar=False, grab_anywhere=False, keep_on_top=False, resizable=True, disable_close=False,margins=(None, None), element_justification='left', + disable_minimize=False, background_image=None, finalize=False, + web_debug=False, web_ip='0.0.0.0', web_port=0, web_start_browser=True, web_update_interval=.0000001, web_multiple_instance=False ): + ''' + + :param title: + :param default_element_size: + :param default_button_element_size: + :param auto_size_text: + :param auto_size_buttons: + :param location: + :param size: + :param element_padding: + :param button_color: + :param font: + :param progress_bar_color: + :param background_color: + :param border_depth: + :param auto_close: + :param auto_close_duration: + :param icon: + :param force_toplevel: + :param alpha_channel: + :param return_keyboard_events: + :param use_default_focus: + :param text_justification: + :param no_titlebar: + :param grab_anywhere: + :param keep_on_top: + :param resizable: + :param disable_close: + :param background_image: + ''' + self.AutoSizeText = auto_size_text if auto_size_text is not None else DEFAULT_AUTOSIZE_TEXT + self.AutoSizeButtons = auto_size_buttons if auto_size_buttons is not None else DEFAULT_AUTOSIZE_BUTTONS + self.Title = title + self.Rows = [] # a list of ELEMENTS for this row + self.DefaultElementSize = convert_tkinter_size_to_Wx(default_element_size) + self.DefaultButtonElementSize = convert_tkinter_size_to_Wx( + default_button_element_size) if default_button_element_size != ( + None, None) else DEFAULT_BUTTON_ELEMENT_SIZE + self.Location = location + self.ButtonColor = button_color if button_color else DEFAULT_BUTTON_COLOR + self.BackgroundColor = background_color if background_color else DEFAULT_BACKGROUND_COLOR + self.ParentWindow = None + self.Font = font if font else DEFAULT_FONT + self.RadioDict = {} + self.BorderDepth = border_depth + self.WindowIcon = icon if icon is not None else Window.user_defined_icon + self.AutoClose = auto_close + self.NonBlocking = False + self.TKroot = None + self.TKrootDestroyed = False + self.CurrentlyRunningMainloop = False + self.FormRemainedOpen = False + self.TKAfterID = None + self.ProgressBarColor = progress_bar_color + self.AutoCloseDuration = auto_close_duration + self.RootNeedsDestroying = False + self.Shown = False + self.ReturnValues = None + self.ReturnValuesList = [] + self.ReturnValuesDictionary = {} + self.DictionaryKeyCounter = 0 + self.AllKeysDict = {} + self.LastButtonClicked = None + self.LastButtonClickedWasRealtime = False + self.UseDictionary = False + self.UseDefaultFocus = use_default_focus + self.ReturnKeyboardEvents = return_keyboard_events + self.ReturnKeyDownEvents = return_key_down_events + self.KeyInfoDict = {} + self.LastKeyboardEvent = None + self.TextJustification = text_justification + self.NoTitleBar = no_titlebar + self.GrabAnywhere = grab_anywhere + self.KeepOnTop = keep_on_top + self.ForcefTopLevel = force_toplevel + self.Resizable = resizable + self._AlphaChannel = alpha_channel + self.Timeout = None + self.TimeoutKey = TIMEOUT_KEY + self.TimerCancelled = False + self.DisableClose = disable_close + self._Hidden = False + # self.QTApplication = None + # self.QT_QMainWindow = None + self._Size = size + self.ElementPadding = element_padding or DEFAULT_ELEMENT_PADDING + self.FocusElement = None + self.BackgroundImage = background_image + self.XFound = False + self.DisableMinimize = disable_minimize + self.OutputElementForStdOut = None # type: Output + self.Justification = 'left' + self.ElementJustification = element_justification + self.IgnoreClose = False + self.thread_id = None + self.App = None # type: Window.MyApp + self.web_debug = web_debug + self.web_ip = web_ip + self.web_port = web_port + self.web_start_browser = web_start_browser + self.web_update_interval = web_update_interval + self.web_multiple_instance = web_multiple_instance + self.MessageQueue = Queue() + self.master_widget = None # type: remi.gui.VBox + self.UniqueKeyCounter = 0 + + if layout is not None: + self.Layout(layout) + if finalize: + self.Finalize() + + @classmethod + def IncrementOpenCount(self): + self._NumOpenWindows += 1 + # print('+++++ INCREMENTING Num Open Windows = {} ---'.format(Window._NumOpenWindows)) + + @classmethod + def _DecrementOpenCount(self): + self._NumOpenWindows -= 1 * (self._NumOpenWindows != 0) # decrement if not 0 + # print('----- DECREMENTING Num Open Windows = {} ---'.format(Window._NumOpenWindows)) + + # ------------------------- Add ONE Row to Form ------------------------- # + def AddRow(self, *args): + ''' Parms are a variable number of Elements ''' + NumRows = len(self.Rows) # number of existing rows is our row number + CurrentRowNumber = NumRows # this row's number + CurrentRow = [] # start with a blank row and build up + # ------------------------- Add the elements to a row ------------------------- # + for i, element in enumerate(args): # Loop through list of elements and add them to the row + element.Position = (CurrentRowNumber, i) + element.ParentContainer = self + CurrentRow.append(element) + # ------------------------- Append the row to list of Rows ------------------------- # + self.Rows.append(CurrentRow) + + # ------------------------- Add Multiple Rows to Form ------------------------- # + def AddRows(self, rows): + for row in rows: + self.AddRow(*row) + + def Layout(self, rows): + self.AddRows(rows) + self._BuildKeyDict() + return self + + def LayoutAndRead(self, rows, non_blocking=False): + raise DeprecationWarning( + 'LayoutAndRead is no longer supported... change your call to window.Layout(layout).Read()') + # self.AddRows(rows) + # self.Show(non_blocking=non_blocking) + # return self.ReturnValues + + def LayoutAndShow(self, rows): + raise DeprecationWarning('LayoutAndShow is no longer supported... change your call to LayoutAndRead') + + # ------------------------- ShowForm THIS IS IT! ------------------------- # + def Show(self, non_blocking=False): + self.Shown = True + # Compute num rows & num cols (it'll come in handy debugging) + self.NumRows = len(self.Rows) + self.NumCols = max(len(row) for row in self.Rows) + self.NonBlocking = non_blocking + + # Search through entire form to see if any elements set the focus + # if not, then will set the focus to the first input element + found_focus = False + for row in self.Rows: + for element in row: + try: + if element.Focus: + found_focus = True + except: + pass + try: + if element.Key is not None: + self.UseDictionary = True + except: + pass + + if not found_focus and self.UseDefaultFocus: + self.UseDefaultFocus = True + else: + self.UseDefaultFocus = False + # -=-=-=-=-=-=-=-=- RUN the GUI -=-=-=-=-=-=-=-=- ## + StartupTK(self) + + + + + def Read(self, timeout=None, timeout_key=TIMEOUT_KEY, close=False): + """ + THE biggest deal method in the Window class! This is how you get all of your data from your Window. + Pass in a timeout (in milliseconds) to wait for a maximum of timeout milliseconds. Will return timeout_key + if no other GUI events happen first. + Use the close parameter to close the window after reading + + :param timeout: (int) Milliseconds to wait until the Read will return IF no other GUI events happen first + :param timeout_key: (Any) The value that will be returned from the call if the timer expired + :param close: (bool) if True the window will be closed prior to returning + :return: Tuple[(Any), Union[Dict[Any:Any]], List[Any], None] (event, values) + """ + results = self._read(timeout=timeout, timeout_key=timeout_key) + if close: + self.close() + + return results + + + + def _read(self, timeout=None, timeout_key=TIMEOUT_KEY): + # if timeout == 0: # timeout of zero runs the old readnonblocking + # event, values = self._ReadNonBlocking() + # if event is None: + # event = timeout_key + # if values is None: + # event = None + # return event, values # make event None if values was None and return + # Read with a timeout + self.Timeout = timeout + self.TimeoutKey = timeout_key + self.NonBlocking = False + if not self.Shown: + self.Show() + # if already have a button waiting, the return previously built results + if self.LastButtonClicked is not None and not self.LastButtonClickedWasRealtime: + # print(f'*** Found previous clicked saved {self.LastButtonClicked}') + results = BuildResults(self, False, self) + self.LastButtonClicked = None + return results + InitializeResults(self) + # if the last button clicked was realtime, emulate a read non-blocking + # the idea is to quickly return realtime buttons without any blocks until released + if self.LastButtonClickedWasRealtime: + # print(f'RTime down {self.LastButtonClicked}' ) + try: + rc = self.TKroot.update() + except: + self.TKrootDestroyed = True + Window._DecrementOpenCount() + results = BuildResults(self, False, self) + if results[0] != None and results[0] != timeout_key: + return results + else: + pass + + # else: + # print("** REALTIME PROBLEM FOUND **", results) + # print('****************** CALLING MESSAGE QUEUE GET ***********************') + self.CurrentlyRunningMainloop = True + if timeout is not None: + try: + self.LastButtonClicked = self.MessageQueue.get(timeout=(timeout if timeout else .001)/1000) + # print(f'Got event {self.LastButtonClicked}') + except: # timeout + self.LastButtonClicked = timeout_key + else: + self.LastButtonClicked = self.MessageQueue.get() + # print(f'Got event {self.LastButtonClicked}') + # print('--------------------- BACK FROM MESSAGE QUEUE GET ----------------------') + + results = BuildResults(self, False, self) + return results + # print(f'In main {self.Title}') + ################################# CALL GUWxTextCtrlI MAINLOOP ############################ + # self.App.MainLoop() + # self.CurrentlyRunningMainloop = False + # self.TimerCancelled = True + # if timer: + # timer.Stop() + # if Window.stdout_is_rerouted: + # sys.stdout = Window.stdout_location + # if self.RootNeedsDestroying: + # self.LastButtonClicked = None + # self.App.Close() + # try: + # self.MasterFrame.Close() + # except: + # pass + # Window._DecrementOpenCount() + # if form was closed with X + # if self.LastButtonClicked is None and self.LastKeyboardEvent is None and self.ReturnValues[0] is None: + # Window._DecrementOpenCount() + # Determine return values + # if self.LastKeyboardEvent is not None or self.LastButtonClicked is not None: + # results = BuildResults(self, False, self) + # if not self.LastButtonClickedWasRealtime: + # self.LastButtonClicked = None + # return results + # else: + # if not self.XFound and self.Timeout != 0 and self.Timeout is not None and self.ReturnValues[ + # 0] is None: # Special Qt case because returning for no reason so fake timeout + # self.ReturnValues = self.TimeoutKey, self.ReturnValues[1] # fake a timeout + # elif not self.XFound and self.ReturnValues[ + # 0] is None: # TODO HIGHLY EXPERIMENTAL... added due to tray icon interaction + # print("*** Faking timeout ***") + # self.ReturnValues = self.TimeoutKey, self.ReturnValues[1] # fake a timeout + # return self.ReturnValues + + def _ReadNonBlocking(self): + if self.TKrootDestroyed: + return None, None + if not self.Shown: + self.Show(non_blocking=True) + # event = wx.Event() + # self.App.QueueEvent(event) + timer = wx.Timer(self.App) + self.App.Bind(wx.EVT_TIMER, self.timer_timeout) + timer.Start(milliseconds=0, oneShot=wx.TIMER_ONE_SHOT) + self.CurrentlyRunningMainloop = True + # print(f'In main {self.Title}') + ################################# CALL GUWxTextCtrlI MAINLOOP ############################ + + self.App.MainLoop() + if Window.stdout_is_rerouted: + sys.stdout = Window.stdout_location + # self.LastButtonClicked = 'TEST' + self.CurrentlyRunningMainloop = False + timer.Stop() + # while self.App.HasPendingEvents(): + # self.App.ProcessPendingEvents() + return BuildResults(self, False, self) + + + # ------------------------- SetIcon - set the window's fav icon ------------------------- # + def SetIcon(self, icon=None, pngbase64=None): + pass + + def _GetElementAtLocation(self, location): + (row_num, col_num) = location + row = self.Rows[row_num] + element = row[col_num] + return element + + def _GetDefaultElementSize(self): + return self.DefaultElementSize + + def _AutoCloseAlarmCallback(self): + try: + window = self + if window: + if window.NonBlocking: + self.CloseNonBlockingForm() + else: + window._Close() + if self.CurrentlyRunningMainloop: + self.QTApplication.exit() # kick the users out of the mainloop + self.RootNeedsDestroying = True + self.QT_QMainWindow.close() + + except: + pass + + def timer_timeout(self, event): + # first, get the results table built + # modify the Results table in the parent FlexForm object + # print('timer timeout') + if self.TimerCancelled: + return + self.LastButtonClicked = self.TimeoutKey + self.FormRemainedOpen = True + if self.CurrentlyRunningMainloop: + self.App.ExitMainLoop() + + def non_block_timer_timeout(self, event): + # print('non-blocking timer timeout') + self.App.ExitMainLoop() + + def autoclose_timer_callback(self, frame): + # print('*** AUTOCLOSE TIMEOUT CALLBACK ***', frame) + try: + frame.Close() + except: + pass # if user has already closed the frame will get an error + + if self.CurrentlyRunningMainloop: + self.App.ExitMainLoop() + + def on_key_down(self, emitter, key, keycode, ctrl, shift, alt): + self.LastButtonClicked = 'DOWN'+key + self.MessageQueue.put(self.LastButtonClicked) + self.KeyInfoDict = { 'key':key, 'keycode':keycode, 'ctrl': ctrl, 'shift':shift, 'alt':alt } + + def on_key_up(self, emitter, key, keycode, ctrl, shift, alt): + self.LastButtonClicked = key + self.MessageQueue.put(self.LastButtonClicked) + self.KeyInfoDict = { 'key':key, 'keycode':keycode, 'ctrl': ctrl, 'shift':shift, 'alt':alt } + + + def callback_keyboard_char(self, event): + self.LastButtonClicked = None + self.FormRemainedOpen = True + if event.ClassName == 'wxMouseEvent': + if event.WheelRotation < 0: + self.LastKeyboardEvent = 'MouseWheel:Down' + else: + self.LastKeyboardEvent = 'MouseWheel:Up' + else: + self.LastKeyboardEvent = event.GetKeyCode() + if not self.NonBlocking: + BuildResults(self, False, self) + if self.CurrentlyRunningMainloop: # quit if this is the current mainloop, otherwise don't quit! + self.App.ExitMainLoop() # kick the users out of the mainloop + if event.ClassName != 'wxMouseEvent': + event.DoAllowNextEvent() + + def Finalize(self): + if self.TKrootDestroyed: + return self + if not self.Shown: + self.Show(non_blocking=True) + # else: + # try: + # self.QTApplication.processEvents() # refresh the window + # except: + # print('* ERROR FINALIZING *') + # self.TKrootDestroyed = True + # Window._DecrementOpenCount() + return self + + def Refresh(self): + # self.QTApplication.processEvents() # refresh the window + return self + + def VisibilityChanged(self): + self.SizeChanged() + return self + + def Fill(self, values_dict): + _FillFormWithValues(self, values_dict) + return self + + def FindElement(self, key, silent_on_error=False): + try: + element = self.AllKeysDict[key] + except KeyError: + element = None + if element is None: + if not silent_on_error: + print('*** WARNING = FindElement did not find the key. Please check your key\'s spelling ***') + PopupError('Keyword error in FindElement Call', + 'Bad key = {}'.format(key), + 'Your bad line of code may resemble this:', + 'window.FindElement("{}")'.format(key)) + return ErrorElement(key=key) + else: + return False + return element + + Element = FindElement # shortcut function definition + + def _BuildKeyDict(self): + dict = {} + self.AllKeysDict = self._BuildKeyDictForWindow(self,self, dict) + # print(f'keys built = {self.AllKeysDict}') + + def _BuildKeyDictForWindow(self, top_window, window, key_dict): + for row_num, row in enumerate(window.Rows): + for col_num, element in enumerate(row): + if element.Type == ELEM_TYPE_COLUMN: + key_dict = self._BuildKeyDictForWindow(top_window, element, key_dict) + if element.Type == ELEM_TYPE_FRAME: + key_dict = self._BuildKeyDictForWindow(top_window, element, key_dict) + if element.Type == ELEM_TYPE_TAB_GROUP: + key_dict = self._BuildKeyDictForWindow(top_window, element, key_dict) + if element.Type == ELEM_TYPE_TAB: + key_dict = self._BuildKeyDictForWindow(top_window, element, key_dict) + if element.Key is None: # if no key has been assigned.... create one for input elements + if element.Type == ELEM_TYPE_BUTTON: + element.Key = element.ButtonText + if element.Type in (ELEM_TYPE_MENUBAR, ELEM_TYPE_BUTTONMENU, ELEM_TYPE_CANVAS, + ELEM_TYPE_INPUT_SLIDER, ELEM_TYPE_GRAPH, ELEM_TYPE_IMAGE, + ELEM_TYPE_INPUT_CHECKBOX, ELEM_TYPE_INPUT_LISTBOX, ELEM_TYPE_INPUT_COMBO, + ELEM_TYPE_INPUT_MULTILINE, ELEM_TYPE_INPUT_OPTION_MENU, ELEM_TYPE_INPUT_SPIN, + ELEM_TYPE_TABLE, ELEM_TYPE_TREE, + ELEM_TYPE_INPUT_TEXT): + element.Key = top_window.DictionaryKeyCounter + top_window.DictionaryKeyCounter += 1 + if element.Key is not None: + if element.Key in key_dict.keys(): + print('*** Duplicate key found in your layout {} ***'.format(element.Key)) if element.Type != ELEM_TYPE_BUTTON else None + element.Key = element.Key + str(self.UniqueKeyCounter) + self.UniqueKeyCounter += 1 + print('*** Replaced new key with {} ***'.format(element.Key)) if element.Type != ELEM_TYPE_BUTTON else None + key_dict[element.Key] = element + return key_dict + + def FindElementWithFocus(self): + return self.FocusElement + # element = _FindElementWithFocusInSubForm(self) + # return element + + def SaveToDisk(self, filename): + try: + results = BuildResults(self, False, self) + with open(filename, 'wb') as sf: + pickle.dump(results[1], sf) + except: + print('*** Error saving form to disk ***') + + def LoadFromDisk(self, filename): + try: + with open(filename, 'rb') as df: + self.Fill(pickle.load(df)) + except: + print('*** Error loading form to disk ***') + + def GetScreenDimensions(self): # TODO - Not sure what to return so (0,0) for now + size = (0,0) + return size + + def Move(self, x, y): + self.MasterFrame.SetPosition((x, y)) + + def Minimize(self): + self.MasterFrame.Iconize() + + def Maximize(self): + self.MasterFrame.Maximize() + + def _Close(self): + if not self.NonBlocking: + BuildResults(self, False, self) + if self.TKrootDestroyed: + return None + self.TKrootDestroyed = True + self.RootNeedsDestroying = True + self.Close() + + def Close(self): + if len(Window.active_windows) != 0: + del(Window.active_windows[-1]) # delete current window from active windows + if len(Window.active_windows) != 0: + window = Window.active_windows[-1] # get prior window to change to + Window.App.set_root_widget(window.master_widget) + else: + self.App.close() + self.App.server.server_starter_instance._alive = False + self.App.server.server_starter_instance._sserver.shutdown() + return + + self.App.close() + self.App.server.server_starter_instance._alive = False + self.App.server.server_starter_instance._sserver.shutdown() + + CloseNonBlockingForm = Close + CloseNonBlocking = Close + + def Disable(self): + self.MasterFrame.Enable(False) + + def Enable(self): + self.MasterFrame.Enable(True) + + def Hide(self): + self._Hidden = True + self.master_widget.attributes['hidden'] = 'true' + # self.MasterFrame.Hide() + return + + def UnHide(self): + if self._Hidden: + del(self.master_widget.attributes['hidden']) + self._Hidden = False + + def Disappear(self): + self.MasterFrame.SetTransparent(0) + + def Reappear(self): + self.MasterFrame.SetTransparent(255) + + def SetAlpha(self, alpha): + ''' + Change the window's transparency + :param alpha: From 0 to 1 with 0 being completely transparent + :return: + ''' + self._AlphaChannel = alpha * 255 + if self._AlphaChannel is not None: + self.MasterFrame.SetTransparent(self._AlphaChannel) + + @property + def AlphaChannel(self): + return self._AlphaChannel + + @AlphaChannel.setter + def AlphaChannel(self, alpha): + self.SetAlpha(alpha) + + def BringToFront(self): + self.MasterFrame.ToggleWindowStyle(wx.STAY_ON_TOP) + + def CurrentLocation(self): + location = self.MasterFrame.GetPosition() + return location + + + @property + def Size(self): + size = self.MasterFrame.GetSize() + return size + + @Size.setter + def Size(self, size): + self.MasterFrame.SetSize(size[0], size[1]) + + def SizeChanged(self): + size = self.Size + self.Size = size[0] + 1, size[1] + 1 + self.Size = size + self.MasterFrame.SetSizer(self.OuterSizer) + self.OuterSizer.Fit(self.MasterFrame) + + def __getitem__(self, key): + """ + Returns Element that matches the passed in key. + This is "called" by writing code as thus: + window['element key'].Update + + :param key: (Any) The key to find + :return: Union[Element, None] The element found or None if no element was found + """ + try: + return self.Element(key) + except Exception as e: + print('The key you passed in is no good. Key = {}*'.format(key)) + return None + + def __call__(self, *args, **kwargs): + """ + Call window.Read but without having to type it out. + window() == window.Read() + window(timeout=50) == window.Read(timeout=50) + + :param args: + :param kwargs: + :return: Tuple[Any, Dict[Any:Any]] The famous event, values that Read returns. + """ + return self.Read(*args, **kwargs) + + + + add_row = AddRow + add_rows = AddRows + alpha_channel = AlphaChannel + bring_to_front = BringToFront + close = Close + current_location = CurrentLocation + disable = Disable + disappear = Disappear + element = Element + enable = Enable + fill = Fill + finalize = Finalize + find_element = FindElement + find_element_with_focus = FindElementWithFocus + get_screen_dimensions = GetScreenDimensions + hide = Hide + increment_open_count = IncrementOpenCount + layout = Layout + layout_and_read = LayoutAndRead + layout_and_show = LayoutAndShow + load_from_disk = LoadFromDisk + maximize = Maximize + minimize = Minimize + move = Move + num_open_windows = _NumOpenWindows + read = Read + reappear = Reappear + refresh = Refresh + save_to_disk = SaveToDisk + set_alpha = SetAlpha + set_icon = SetIcon + show = Show + size = Size + size_changed = SizeChanged + un_hide = UnHide + visibility_changed = VisibilityChanged + + + + + + def remi_thread(self): + # print('Remi Thread started') + logging.getLogger('remi').setLevel(logging.CRITICAL) + logging.getLogger('remi').disabled = True + logging.getLogger('remi.server.ws').disabled = True + logging.getLogger('remi.server').disabled = True + logging.getLogger('remi.request').disabled = True + # use this code to start the application instead of the **start** call + # s = remi.Server(self.MyApp, start=True, title=self.Title, address='0.0.0.0', port=8081, start_browser=True, userdata=(self,), multiple_instance=False, update_interval=.001) + + # logging.getLogger('remi').setLevel(level=logging.CRITICAL) + # logging.getLogger('remi').disabled = True + # logging.disable(logging.CRITICAL) + # s = remi.server.StandaloneServer(self.MyApp, width=1100, height=600) + # s.start() + Window.port_number += 1 + try: + remi.start(self.MyApp, + title=self.Title, + debug=self.web_debug, + address=self.web_ip, + port=self.web_port, + multiple_instance=self.web_multiple_instance, + start_browser=self.web_start_browser, + update_interval=self.web_update_interval, userdata=(self,)) + + except: + print('*** ERROR Caught inside Remi ***') + print(traceback.format_exc()) + # remi.start(self.MyApp, title=self.Title ,debug=False, userdata=(self,), standalone=True) # standalone=True) + + # remi.start(self.MyApp, standalone=True, debug=True, userdata=(self,) ) # Can't do this because of a threading problem + print('Returned from Remi Start command... now sending None event') + + self.MessageQueue.put(None) # if returned from start call, then the window has been destroyed and a None event should be generated + + class MyApp(remi.App): + def __init__(self,*args, userdata2=None): + # self.window = window # type: Window + # print(args[-1]) + if userdata2 is None: + userdata = args[-1].userdata + self.window = userdata[0] # type: Window + else: + self.window = userdata2 # type: Window + self.master_widget = None + # print("new App instance %s" % str(id(self))) + # self.window.App = self + #Window.App = self + self.lines_shown = [] + + if userdata2 is None: + # res_path = os.path.dirname(os.path.abspath(__file__)) + # print('res path', res_path) + super(Window.MyApp, self).__init__(*args, static_file_path={'C':'c:','c':'c:','D':'d:', 'd':'d:', 'E':'e:', 'e':'e:', 'dot':'.', '.':'.'}) + + def _instance(self): + remi.App._instance(self) + self.window.App = remi.server.clients[self.session] + + def log_message(self, *args, **kwargs): + pass + + def idle(self): + if Window.stdout_is_rerouted: + Window.stdout_string_io.seek(0) + lines = Window.stdout_string_io.readlines() + # lines.reverse() + # self.window.OutputElementForStdOut.Widget.set_text("".join(lines)) + # self.window.OutputElementForStdOut.Update("".join(lines)) + if lines != self.lines_shown: + self.window.OutputElementForStdOut.Update("".join(lines)) + self.lines_shown = lines + + def main(self, name='world'): + # margin 0px auto allows to center the app to the screen + # self.master_widget = remi.gui.VBox() + # self.master_widget.style['justify-content'] = 'flex-start' + # self.master_widget.style['align-items'] = 'baseline' + # if self.window.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT): + # self.master_widget.style['background-color'] = self.window.BackgroundColor + # try: + # PackFormIntoFrame(self.window, self.master_widget, self.window) + # except: + # print('* ERROR PACKING FORM *') + # print(traceback.format_exc()) + # + # if self.window.BackgroundImage: + # self.master_widget.style['background-image'] = "url('{}')".format('/'+self.window.BackgroundImage) + # # print(f'background info',self.master_widget.attributes['background-image'] ) + # + # if not self.window.DisableClose: + # # add the following 3 lines to your app and the on_window_close method to make the console close automatically + # tag = remi.gui.Tag(_type='script') + # tag.add_child("javascript", """window.onunload=function(e){sendCallback('%s','%s');return "close?";};""" % ( + # str(id(self)), "on_window_close")) + # self.master_widget.add_child("onunloadevent", tag) + + self.master_widget = setup_remi_window(self, self.window) + self.window.master_widget = self.master_widget + # if self.window.WindowIcon: + # print('placing icon') + # self.page.children['head'].set_icon_file("/res:logo.png") + # self.page.children['head'].set_icon_data( base64_data=self.window.WindowIcon, mimetype="image/png" ) + + self.window.MessageQueue.put('Layout complete') # signal the main code that the layout is all done + return self.master_widget # returning the root widget + + + def on_window_close(self): + # here you can handle the unload + print("app closing") + self.close() + self.server.server_starter_instance._alive = False + self.server.server_starter_instance._sserver.shutdown() + # self.window.MessageQueue.put(None) + print("server stopped") + +FlexForm = Window + + + + +# =========================================================================== # +# Stops the mainloop and sets the event information # +# =========================================================================== # + +def element_callback_quit_mainloop(element): + if element.Key is not None: + element.ParentForm.LastButtonClicked = element.Key + else: + element.ParentForm.LastButtonClicked = '' + try: + element.ParentForm.LastButtonClicked = element.Key if element.Key is not None else element.ButtonText + except: + element.ParentForm.LastButtonClicked = element.Key + # print(f'Putting into message queue {element.ParentForm.LastButtonClicked}') + element.ParentForm.MessageQueue.put(element.ParentForm.LastButtonClicked) + + +def quit_mainloop(window): + window.App.ExitMainLoop() + + +# =========================================================================== # +# Stops the mainloop and sets the event information # +# =========================================================================== # +def convert_tkinter_size_to_Wx(size): + """ + Converts size in characters to size in pixels + :param size: size in characters, rows + :return: size in pixels, pixels + """ + qtsize = size + if size[1] is not None and size[1] < DEFAULT_PIXEL_TO_CHARS_CUTOFF: # change from character based size to pixels (roughly) + qtsize = size[0]*DEFAULT_PIXELS_TO_CHARS_SCALING[0], size[1]*DEFAULT_PIXELS_TO_CHARS_SCALING[1] + return qtsize + + +def base64_to_style_image(base64_image): + x ="url('data:image/png;base64," + x += str(base64_image) + x += "')" + # print(x) + return x + + +def font_parse_string(font): + """ + Convert from font string/tyuple into a Qt style sheet string + :param font: "Arial 10 Bold" or ('Arial', 10, 'Bold) + :return: style string that can be combined with other style strings + """ + + if font is None: + return '' + + if type(font) is str: + _font = font.split(' ') + else: + _font = font + family = _font[0] + point_size = int(_font[1]) + + style = _font[2:] if len(_font) > 1 else None + + # underline = 'underline' in _font[2:] + # bold = 'bold' in _font + + return family, point_size, style + + + + +# ################################################################################ +# ################################################################################ +# END OF ELEMENT DEFINITIONS +# ################################################################################ +# ################################################################################ + + +# =========================================================================== # +# Button Lazy Functions so the caller doesn't have to define a bunch of stuff # +# =========================================================================== # + + +# ------------------------- FOLDER BROWSE Element lazy function ------------------------- # +def FolderBrowse(button_text='Browse', target=(ThisRow, -1), initial_folder=None, tooltip=None, size=(None, None), + auto_size_button=None, button_color=None, disabled=False, change_submits=False, font=None, pad=None, + key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_BROWSE_FOLDER, target=target, + initial_folder=initial_folder, tooltip=tooltip, size=size, auto_size_button=auto_size_button, + disabled=disabled, button_color=button_color, change_submits=change_submits, font=font, pad=pad, + key=key) + + +# ------------------------- FILE BROWSE Element lazy function ------------------------- # +def FileBrowse(button_text='Browse', target=(ThisRow, -1), file_types=(("ALL Files", "*.*"),), initial_folder=None, + tooltip=None, size=(None, None), auto_size_button=None, button_color=None, change_submits=False, + font=None, disabled=False, + pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_BROWSE_FILE, target=target, file_types=file_types, + initial_folder=initial_folder, tooltip=tooltip, size=size, auto_size_button=auto_size_button, + change_submits=change_submits, disabled=disabled, button_color=button_color, font=font, pad=pad, + key=key) + + +# ------------------------- FILES BROWSE Element (Multiple file selection) lazy function ------------------------- # +def FilesBrowse(button_text='Browse', target=(ThisRow, -1), file_types=(("ALL Files", "*.*"),), disabled=False, + initial_folder=None, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, + change_submits=False, + font=None, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_BROWSE_FILES, target=target, file_types=file_types, + initial_folder=initial_folder, change_submits=change_submits, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, + disabled=disabled, button_color=button_color, font=font, pad=pad, key=key) + + +# ------------------------- FILE BROWSE Element lazy function ------------------------- # +def FileSaveAs(button_text='Save As...', target=(ThisRow, -1), file_types=(("ALL Files", "*.*"),), initial_folder=None, + disabled=False, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, + change_submits=False, font=None, + pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_SAVEAS_FILE, target=target, file_types=file_types, + initial_folder=initial_folder, tooltip=tooltip, size=size, disabled=disabled, + auto_size_button=auto_size_button, button_color=button_color, change_submits=change_submits, + font=font, pad=pad, key=key) + + +# ------------------------- SAVE AS Element lazy function ------------------------- # +def SaveAs(button_text='Save As...', target=(ThisRow, -1), file_types=(("ALL Files", "*.*"),), initial_folder=None, + disabled=False, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, + change_submits=False, font=None, + pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_SAVEAS_FILE, target=target, file_types=file_types, + initial_folder=initial_folder, tooltip=tooltip, size=size, disabled=disabled, + auto_size_button=auto_size_button, button_color=button_color, change_submits=change_submits, + font=font, pad=pad, key=key) + + +# ------------------------- SAVE BUTTON Element lazy function ------------------------- # +def Save(button_text='Save', size=(None, None), auto_size_button=None, button_color=None, bind_return_key=True, + disabled=False, tooltip=None, font=None, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + +# ------------------------- SUBMIT BUTTON Element lazy function ------------------------- # +def Submit(button_text='Submit', size=(None, None), auto_size_button=None, button_color=None, disabled=False, + bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + +# ------------------------- OPEN BUTTON Element lazy function ------------------------- # +def Open(button_text='Open', size=(None, None), auto_size_button=None, button_color=None, disabled=False, + bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + +# ------------------------- OK BUTTON Element lazy function ------------------------- # +def OK(button_text='OK', size=(None, None), auto_size_button=None, button_color=None, disabled=False, + bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + +# ------------------------- YES BUTTON Element lazy function ------------------------- # +def Ok(button_text='Ok', size=(None, None), auto_size_button=None, button_color=None, disabled=False, + bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + +# ------------------------- CANCEL BUTTON Element lazy function ------------------------- # +def Cancel(button_text='Cancel', size=(None, None), auto_size_button=None, button_color=None, disabled=False, + tooltip=None, font=None, bind_return_key=False, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + +# ------------------------- QUIT BUTTON Element lazy function ------------------------- # +def Quit(button_text='Quit', size=(None, None), auto_size_button=None, button_color=None, disabled=False, tooltip=None, + font=None, bind_return_key=False, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + +# ------------------------- Exit BUTTON Element lazy function ------------------------- # +def Exit(button_text='Exit', size=(None, None), auto_size_button=None, button_color=None, disabled=False, tooltip=None, + font=None, bind_return_key=False, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + + +# ------------------------- Up arrow BUTTON Element lazy function ------------------------- # +def Up(button_text='▲', size=(None, None), auto_size_button=None, button_color=None, disabled=False, tooltip=None, + font=None, bind_return_key=True, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + +# ------------------------- Down arrow BUTTON Element lazy function ------------------------- # +def Down(button_text='▼', size=(None, None), auto_size_button=None, button_color=None, disabled=False, tooltip=None, + font=None, bind_return_key=True, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + +# ------------------------- Left arrow BUTTON Element lazy function ------------------------- # +def Left(button_text='◄', size=(None, None), auto_size_button=None, button_color=None, disabled=False, tooltip=None, + font=None, bind_return_key=True, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + +# ------------------------- Right arrow BUTTON Element lazy function ------------------------- # +def Right(button_text='►', size=(None, None), auto_size_button=None, button_color=None, disabled=False, tooltip=None, + font=None, bind_return_key=True, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + + +# ------------------------- YES BUTTON Element lazy function ------------------------- # +def Yes(button_text='Yes', size=(None, None), auto_size_button=None, button_color=None, disabled=False, tooltip=None, + font=None, bind_return_key=True, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + +# ------------------------- NO BUTTON Element lazy function ------------------------- # +def No(button_text='No', size=(None, None), auto_size_button=None, button_color=None, disabled=False, tooltip=None, + font=None, bind_return_key=False, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + +# ------------------------- NO BUTTON Element lazy function ------------------------- # +def Help(button_text='Help', size=(None, None), auto_size_button=None, button_color=None, disabled=False, font=None, + tooltip=None, bind_return_key=False, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + +# ------------------------- GENERIC BUTTON Element lazy function ------------------------- # +def SimpleButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, + border_width=None, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, + font=None, bind_return_key=False, disabled=False, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_CLOSES_WIN, image_filename=image_filename, + image_data=image_data, image_size=image_size, image_subsample=image_subsample, + border_width=border_width, tooltip=tooltip, disabled=disabled, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + +# ------------------------- CLOSE BUTTON Element lazy function ------------------------- # +def CloseButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, + border_width=None, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, font=None, + bind_return_key=False, disabled=False, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_CLOSES_WIN, image_filename=image_filename, + image_data=image_data, image_size=image_size, image_subsample=image_subsample, + border_width=border_width, tooltip=tooltip, disabled=disabled, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + +CButton = CloseButton + + +# ------------------------- GENERIC BUTTON Element lazy function ------------------------- # +def ReadButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, + border_width=None, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, font=None, + bind_return_key=False, disabled=False, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, image_filename=image_filename, + image_data=image_data, image_size=image_size, image_subsample=image_subsample, + border_width=border_width, tooltip=tooltip, size=size, disabled=disabled, + auto_size_button=auto_size_button, button_color=button_color, font=font, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + +ReadFormButton = ReadButton +RButton = ReadFormButton + + +# ------------------------- Realtime BUTTON Element lazy function ------------------------- # +def RealtimeButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, + border_width=None, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, + font=None, disabled=False, bind_return_key=False, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_REALTIME, image_filename=image_filename, + image_data=image_data, image_size=image_size, image_subsample=image_subsample, + border_width=border_width, tooltip=tooltip, disabled=disabled, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + +# ------------------------- Dummy BUTTON Element lazy function ------------------------- # +def DummyButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, + border_width=None, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, font=None, + disabled=False, bind_return_key=False, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_CLOSES_WIN_ONLY, image_filename=image_filename, + image_data=image_data, image_size=image_size, image_subsample=image_subsample, + border_width=border_width, tooltip=tooltip, size=size, auto_size_button=auto_size_button, + button_color=button_color, font=font, disabled=disabled, bind_return_key=bind_return_key, focus=focus, + pad=pad, key=key) + + +# ------------------------- Calendar Chooser Button lazy function ------------------------- # +def CalendarButton(button_text, target=(None, None), close_when_date_chosen=True, default_date_m_d_y=(None, 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, + button_color=None, disabled=False, font=None, bind_return_key=False, focus=False, pad=None, + key=None): + button = Button(button_text=button_text, button_type=BUTTON_TYPE_CALENDAR_CHOOSER, target=target, + image_filename=image_filename, image_data=image_data, image_size=image_size, + image_subsample=image_subsample, border_width=border_width, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + button.CalendarCloseWhenChosen = close_when_date_chosen + button.DefaultDate_M_D_Y = default_date_m_d_y + return button + + +# ------------------------- Calendar Chooser Button lazy function ------------------------- # +def ColorChooserButton(button_text, target=(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, + button_color=None, disabled=False, font=None, bind_return_key=False, focus=False, pad=None, + key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_COLOR_CHOOSER, target=target, + image_filename=image_filename, image_data=image_data, image_size=image_size, + image_subsample=image_subsample, border_width=border_width, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + +##################################### ----- RESULTS ------ ################################################## + +def AddToReturnDictionary(form, element, value): + form.ReturnValuesDictionary[element.Key] = value + return + if element.Key is None: + form.ReturnValuesDictionary[form.DictionaryKeyCounter] = value + element.Key = form.DictionaryKeyCounter + form.DictionaryKeyCounter += 1 + else: + form.ReturnValuesDictionary[element.Key] = value + + +def AddToReturnList(form, value): + form.ReturnValuesList.append(value) + + +# ----------------------------------------------------------------------------# +# ------- FUNCTION InitializeResults. Sets up form results matrix --------# +def InitializeResults(form): + BuildResults(form, True, form) + return + + +# ===== Radio Button RadVar encoding and decoding =====# +# ===== The value is simply the row * 1000 + col =====# +def DecodeRadioRowCol(RadValue): + row = RadValue // 1000 + col = RadValue % 1000 + return row, col + + +def EncodeRadioRowCol(row, col): + RadValue = row * 1000 + col + return RadValue + + +# ------- FUNCTION BuildResults. Form exiting so build the results to pass back ------- # +# format of return values is +# (Button Pressed, input_values) +def BuildResults(form, initialize_only, top_level_form): + # Results for elements are: + # TEXT - Nothing + # INPUT - Read value from TK + # Button - Button Text and position as a Tuple + + # Get the initialized results so we don't have to rebuild + form.DictionaryKeyCounter = 0 + form.ReturnValuesDictionary = {} + form.ReturnValuesList = [] + BuildResultsForSubform(form, initialize_only, top_level_form) + if not top_level_form.LastButtonClickedWasRealtime: + top_level_form.LastButtonClicked = None + return form.ReturnValues + + +def BuildResultsForSubform(form, initialize_only, top_level_form): + button_pressed_text = top_level_form.LastButtonClicked + for row_num, row in enumerate(form.Rows): + for col_num, element in enumerate(row): + if element.Key is not None and WRITE_ONLY_KEY in str(element.Key): + continue + value = None + if element.Type == ELEM_TYPE_COLUMN: + element.DictionaryKeyCounter = top_level_form.DictionaryKeyCounter + element.ReturnValuesList = [] + element.ReturnValuesDictionary = {} + BuildResultsForSubform(element, initialize_only, top_level_form) + for item in element.ReturnValuesList: + AddToReturnList(top_level_form, item) + if element.UseDictionary: + top_level_form.UseDictionary = True + if element.ReturnValues[0] is not None: # if a button was clicked + button_pressed_text = element.ReturnValues[0] + + if element.Type == ELEM_TYPE_FRAME: + element.DictionaryKeyCounter = top_level_form.DictionaryKeyCounter + element.ReturnValuesList = [] + element.ReturnValuesDictionary = {} + BuildResultsForSubform(element, initialize_only, top_level_form) + for item in element.ReturnValuesList: + AddToReturnList(top_level_form, item) + if element.UseDictionary: + top_level_form.UseDictionary = True + if element.ReturnValues[0] is not None: # if a button was clicked + button_pressed_text = element.ReturnValues[0] + + if element.Type == ELEM_TYPE_TAB_GROUP: + element.DictionaryKeyCounter = top_level_form.DictionaryKeyCounter + element.ReturnValuesList = [] + element.ReturnValuesDictionary = {} + BuildResultsForSubform(element, initialize_only, top_level_form) + for item in element.ReturnValuesList: + AddToReturnList(top_level_form, item) + if element.UseDictionary: + top_level_form.UseDictionary = True + if element.ReturnValues[0] is not None: # if a button was clicked + button_pressed_text = element.ReturnValues[0] + + if element.Type == ELEM_TYPE_TAB: + element.DictionaryKeyCounter = top_level_form.DictionaryKeyCounter + element.ReturnValuesList = [] + element.ReturnValuesDictionary = {} + BuildResultsForSubform(element, initialize_only, top_level_form) + for item in element.ReturnValuesList: + AddToReturnList(top_level_form, item) + if element.UseDictionary: + top_level_form.UseDictionary = True + if element.ReturnValues[0] is not None: # if a button was clicked + button_pressed_text = element.ReturnValues[0] + + if not initialize_only: + if element.Type == ELEM_TYPE_INPUT_TEXT: + element = element # type: InputText + value = element.Widget.get_value() + if not top_level_form.NonBlocking and not element.do_not_clear and not top_level_form.ReturnKeyboardEvents: + element.Widget.set_value('') + elif element.Type == ELEM_TYPE_INPUT_CHECKBOX: + element = element # type: Checkbox + value = element.Widget.get_value() + elif element.Type == ELEM_TYPE_INPUT_RADIO: + # RadVar = element.TKIntVar.get() + # this_rowcol = EncodeRadioRowCol(row_num, col_num) + value = False + elif element.Type == ELEM_TYPE_BUTTON: + if top_level_form.LastButtonClicked == element.ButtonText: + button_pressed_text = top_level_form.LastButtonClicked + if element.BType != BUTTON_TYPE_REALTIME: # Do not clear realtime buttons + top_level_form.LastButtonClicked = None + if element.BType == BUTTON_TYPE_CALENDAR_CHOOSER: + try: + value = element.TKCal.selection + except: + value = None + else: + try: + value = element.TKStringVar.get() + except: + value = None + elif element.Type == ELEM_TYPE_INPUT_COMBO: + element = element # type: Combo + value = element.Widget.get_value() + elif element.Type == ELEM_TYPE_INPUT_OPTION_MENU: + # value = element.TKStringVar.get() + value = None + elif element.Type == ELEM_TYPE_INPUT_LISTBOX: + element = element # type: Listbox + value = element.Widget.get_value() + value = [value,] + # items = element.TKListbox.curselection() + # value = [element.Values[int(item)] for item in items] + elif element.Type == ELEM_TYPE_INPUT_SPIN: + element = element # type: Spin + value = element.Widget.get_value() + elif element.Type == ELEM_TYPE_INPUT_SLIDER: + element = element # type: Slider + value = element.Widget.get_value() + elif element.Type == ELEM_TYPE_INPUT_MULTILINE: + element = element # type: Multiline + if element.WriteOnly: + continue + value = element.Widget.get_value() + elif element.Type == ELEM_TYPE_TAB_GROUP: + try: + value = element.TKNotebook.tab(element.TKNotebook.index('current'))['text'] + tab_key = element.FindKeyFromTabName(value) + if tab_key is not None: + value = tab_key + except: + value = None + elif element.Type == ELEM_TYPE_TABLE: + element = element # type:Table + value = [element.SelectedRow,] + elif element.Type == ELEM_TYPE_TREE: + value = element.SelectedRows + elif element.Type == ELEM_TYPE_GRAPH: + value = element.ClickPosition + elif element.Type == ELEM_TYPE_MENUBAR: + value = element.MenuItemChosen + else: + value = None + + # if an input type element, update the results + if element.Type != ELEM_TYPE_BUTTON and \ + element.Type != ELEM_TYPE_TEXT and \ + element.Type != ELEM_TYPE_IMAGE and \ + element.Type != ELEM_TYPE_OUTPUT and \ + element.Type != ELEM_TYPE_PROGRESS_BAR and \ + element.Type != ELEM_TYPE_COLUMN and \ + element.Type != ELEM_TYPE_FRAME \ + and element.Type != ELEM_TYPE_TAB: + AddToReturnList(form, value) + AddToReturnDictionary(top_level_form, element, value) + elif (element.Type == ELEM_TYPE_BUTTON and + element.BType == BUTTON_TYPE_CALENDAR_CHOOSER and + element.Target == (None, None)) or \ + (element.Type == ELEM_TYPE_BUTTON and + element.BType == BUTTON_TYPE_COLOR_CHOOSER and + element.Target == (None, None)) or \ + (element.Type == ELEM_TYPE_BUTTON + and element.Key is not None and + (element.BType in (BUTTON_TYPE_SAVEAS_FILE, BUTTON_TYPE_BROWSE_FILE, BUTTON_TYPE_BROWSE_FILES, + BUTTON_TYPE_BROWSE_FOLDER))): + AddToReturnList(form, value) + AddToReturnDictionary(top_level_form, element, value) + + # if this is a column, then will fail so need to wrap with tr + try: + if form.ReturnKeyboardEvents and form.LastKeyboardEvent is not None: + button_pressed_text = form.LastKeyboardEvent + form.LastKeyboardEvent = None + except: + pass + + try: + form.ReturnValuesDictionary.pop(None, None) # clean up dictionary include None was included + except: + pass + + if not form.UseDictionary: + form.ReturnValues = button_pressed_text, form.ReturnValuesList + else: + form.ReturnValues = button_pressed_text, form.ReturnValuesDictionary + + return form.ReturnValues + + +def _FillFormWithValues(form, values_dict): + _FillSubformWithValues(form, values_dict) + + +def _FillSubformWithValues(form, values_dict): + for row_num, row in enumerate(form.Rows): + for col_num, element in enumerate(row): + value = None + if element.Type == ELEM_TYPE_COLUMN: + _FillSubformWithValues(element, values_dict) + if element.Type == ELEM_TYPE_FRAME: + _FillSubformWithValues(element, values_dict) + if element.Type == ELEM_TYPE_TAB_GROUP: + _FillSubformWithValues(element, values_dict) + if element.Type == ELEM_TYPE_TAB: + _FillSubformWithValues(element, values_dict) + try: + value = values_dict[element.Key] + except: + continue + if element.Type == ELEM_TYPE_INPUT_TEXT: + element.Update(value) + elif element.Type == ELEM_TYPE_INPUT_CHECKBOX: + element.Update(value) + elif element.Type == ELEM_TYPE_INPUT_RADIO: + element.Update(value) + elif element.Type == ELEM_TYPE_INPUT_COMBO: + element.Update(value) + elif element.Type == ELEM_TYPE_INPUT_OPTION_MENU: + element.Update(value) + elif element.Type == ELEM_TYPE_INPUT_LISTBOX: + element.SetValue(value) + elif element.Type == ELEM_TYPE_INPUT_SLIDER: + element.Update(value) + elif element.Type == ELEM_TYPE_INPUT_MULTILINE: + element.Update(value) + elif element.Type == ELEM_TYPE_INPUT_SPIN: + element.Update(value) + elif element.Type == ELEM_TYPE_BUTTON: + element.Update(value) + + +def _FindElementFromKeyInSubForm(form, key): + for row_num, row in enumerate(form.Rows): + for col_num, element in enumerate(row): + if element.Type == ELEM_TYPE_COLUMN: + matching_elem = _FindElementFromKeyInSubForm(element, key) + if matching_elem is not None: + return matching_elem + if element.Type == ELEM_TYPE_FRAME: + matching_elem = _FindElementFromKeyInSubForm(element, key) + if matching_elem is not None: + return matching_elem + if element.Type == ELEM_TYPE_TAB_GROUP: + matching_elem = _FindElementFromKeyInSubForm(element, key) + if matching_elem is not None: + return matching_elem + if element.Type == ELEM_TYPE_TAB: + matching_elem = _FindElementFromKeyInSubForm(element, key) + if matching_elem is not None: + return matching_elem + if element.Key == key: + return element + + +def _FindElementWithFocusInSubForm(form): + for row_num, row in enumerate(form.Rows): + for col_num, element in enumerate(row): + if element.Type == ELEM_TYPE_COLUMN: + matching_elem = _FindElementWithFocusInSubForm(element) + if matching_elem is not None: + return matching_elem + if element.Type == ELEM_TYPE_FRAME: + matching_elem = _FindElementWithFocusInSubForm(element) + if matching_elem is not None: + return matching_elem + if element.Type == ELEM_TYPE_TAB_GROUP: + matching_elem = _FindElementWithFocusInSubForm(element) + if matching_elem is not None: + return matching_elem + if element.Type == ELEM_TYPE_TAB: + matching_elem = _FindElementWithFocusInSubForm(element) + if matching_elem is not None: + return matching_elem + if element.Type == ELEM_TYPE_INPUT_TEXT: + if element.TKEntry is not None: + if element.TKEntry is element.TKEntry.focus_get(): + return element + if element.Type == ELEM_TYPE_INPUT_MULTILINE: + if element.TKText is not None: + if element.TKText is element.TKText.focus_get(): + return element + + +def AddMenuItem(top_menu, sub_menu_info, element, is_sub_menu=False, skip=False): + # m3 = gui.MenuItem('Dialog', width=100, height=30) + # m3.onclick.connect(self.menu_dialog_clicked) + # menu.append([m1, m2, m3]) + + return_val = None + if type(sub_menu_info) is str: + if not is_sub_menu and not skip: + # print(f'Adding command {sub_menu_info}') + pos = sub_menu_info.find('&') + if pos != -1: + if pos == 0 or sub_menu_info[pos - 1] != "\\": + sub_menu_info = sub_menu_info[:pos] + sub_menu_info[pos + 1:] + if sub_menu_info == '---': + # top_menu.add('separator') + pass + else: + try: + item_without_key = sub_menu_info[:sub_menu_info.index(MENU_KEY_SEPARATOR)] + except: + item_without_key = sub_menu_info + if item_without_key[0] == MENU_DISABLED_CHARACTER: + menu_item = remi.gui.MenuItem(item_without_key[1:], width=100, height=30) + menu_item.set_enabled(False) + top_menu.append([menu_item,]) + + # TODO add callback here! + # TODO disable entry + else: + menu_item = remi.gui.MenuItem(item_without_key, width=100, height=30) + top_menu.append([menu_item,]) + # menu_item.set_on_click_listener(element._ChangedCallbackMenu, sub_menu_info) + menu_item.onclick.connect(element._ChangedCallbackMenu, sub_menu_info) + else: + i = 0 + while i < (len(sub_menu_info)): + item = sub_menu_info[i] + if i != len(sub_menu_info) - 1: + if type(sub_menu_info[i + 1]) == list: + pos = sub_menu_info[i].find('&') + if pos != -1: + if pos == 0 or sub_menu_info[i][pos - 1] != "\\": + sub_menu_info[i] = sub_menu_info[i][:pos] + sub_menu_info[i][pos + 1:] + if sub_menu_info[i][0] == MENU_DISABLED_CHARACTER: + new_menu = remi.gui.MenuItem(sub_menu_info[i][len(MENU_DISABLED_CHARACTER):], width=100, height=30) + new_menu.set_enabled(False) + + # TODO Disable Entry + else: + new_menu = remi.gui.MenuItem(sub_menu_info[i], width=100, height=30) + + top_menu.append([new_menu,]) + return_val = new_menu + AddMenuItem(new_menu, sub_menu_info[i + 1], element, is_sub_menu=True) + i += 1 # skip the next one + else: + AddMenuItem(top_menu, item, element) + else: + AddMenuItem(top_menu, item, element) + i += 1 + return return_val + +""" + ::::::::: :::::::::: ::: ::: ::::::::::: + :+: :+: :+: :+:+: :+:+: :+: + +:+ +:+ +:+ +:+ +:+:+ +:+ +:+ + +#++:++#: +#++:++# +#+ +:+ +#+ +#+ + +#+ +#+ +#+ +#+ +#+ +#+ + #+# #+# #+# #+# #+# #+# + ### ### ########## ### ### ########### +""" +# ------------------------------------------------------------------------------------------------------------ # +# ===================================== REMI CODE STARTS HERE ================================================ # +# ------------------------------------------------------------------------------------------------------------ # + + + + +def PackFormIntoFrame(form, containing_frame, toplevel_form): + def CharWidthInPixels(): + return tkinter.font.Font().measure('A') # single character width + + def pad_widget(widget): + lrsizer = wx.BoxSizer(wx.HORIZONTAL) + if full_element_pad[1] == full_element_pad[3]: # if right = left + lrsizer.Add(widget, 0, wx.LEFT | wx.RIGHT, border=full_element_pad[1]) + else: + sizer = wx.BoxSizer(wx.HORIZONTAL) + sizer.Add(widget, 0, wx.LEFT, border=full_element_pad[3]) + lrsizer.Add(sizer, 0, wx.RIGHT, border=full_element_pad[1]) + + top_bottom_sizer = wx.BoxSizer(wx.HORIZONTAL) + if full_element_pad[0] == full_element_pad[2]: # if top = bottom + top_bottom_sizer.Add(lrsizer, 0, wx.TOP | wx.BOTTOM, border=full_element_pad[0]) + else: + sizer = wx.BoxSizer(wx.HORIZONTAL) + sizer.Add(lrsizer, 0, wx.TOP, border=full_element_pad[0]) + top_bottom_sizer.Add(sizer, 0, wx.BOTTOM, border=full_element_pad[2]) + return top_bottom_sizer + + # + # font, text color, background color, size, disabled, visible, tooltip + # + def do_font_and_color(widget): + font_info = font_parse_string(font) # family, point size, other + widget.style['font-family'] = font_info[0] + if element.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT): + widget.style['background-color'] = element.BackgroundColor + if element.TextColor not in (None, COLOR_SYSTEM_DEFAULT): + widget.style['color'] = element.TextColor + widget.style['font-size'] = '{}px'.format(font_info[1]) + if element_size[0]: # if size is zero, don't set any sizes + size = convert_tkinter_size_to_Wx(element_size) + widget.style['height'] = '{}px'.format(size[1]) + widget.style['width'] = '{}px'.format(size[0]) + widget.style['margin'] = '{}px {}px {}px {}px'.format(*full_element_pad) + if element.Disabled: + widget.set_enabled(False) + if not element.Visible: + widget.attributes['hidden'] = 'true' + if element.Tooltip is not None: + widget.attributes['title'] = element.Tooltip + + border_depth = toplevel_form.BorderDepth if toplevel_form.BorderDepth is not None else DEFAULT_BORDER_WIDTH + # --------------------------------------------------------------------------- # + # **************** Use FlexForm to build the tkinter window ********** ----- # + # Building is done row by row. # + # --------------------------------------------------------------------------- # + focus_set = False + ######################### LOOP THROUGH ROWS ######################### + # *********** ------- Loop through ROWS ------- ***********# + for row_num, flex_row in enumerate(form.Rows): + ######################### LOOP THROUGH ELEMENTS ON ROW ######################### + # *********** ------- Loop through ELEMENTS ------- ***********# + # *********** Make TK Row ***********# + tk_row_frame = remi.gui.HBox() + tk_row_frame.style['align-items'] = 'flex-start' + if form.ElementJustification.startswith('c'): + tk_row_frame.style['margin-left'] = 'auto' + tk_row_frame.style['margin-right'] = 'auto' + # tk_row_frame.style['justify-content'] = 'center' + elif form.ElementJustification.startswith('r'): + # tk_row_frame.style['justify-content'] = 'flex-end' + tk_row_frame.style['margin-left'] = 'auto' + else: # everything else is left justified + # tk_row_frame.style['justify-content'] = 'flex-flexstart' + tk_row_frame.style['margin-right'] = 'auto' + + if form.BackgroundColor not in(None, COLOR_SYSTEM_DEFAULT): + tk_row_frame.style['background-color'] = form.BackgroundColor + + for col_num, element in enumerate(flex_row): + element.ParentForm = toplevel_form # save the button's parent form object + if toplevel_form.Font and (element.Font == DEFAULT_FONT or not element.Font): + font = toplevel_form.Font + elif element.Font is not None: + font = element.Font + else: + font = DEFAULT_FONT + # ------- Determine Auto-Size setting on a cascading basis ------- # + if element.AutoSizeText is not None: # if element overide + auto_size_text = element.AutoSizeText + elif toplevel_form.AutoSizeText is not None: # if form override + auto_size_text = toplevel_form.AutoSizeText + else: + auto_size_text = DEFAULT_AUTOSIZE_TEXT + element_type = element.Type + # Set foreground color + text_color = element.TextColor + # Determine Element size + element_size = element.Size + if (element_size == (None, None) and element_type != ELEM_TYPE_BUTTON): # user did not specify a size + element_size = toplevel_form.DefaultElementSize + elif (element_size == (None, None) and element_type == ELEM_TYPE_BUTTON): + element_size = toplevel_form.DefaultButtonElementSize + else: + auto_size_text = False # if user has specified a size then it shouldn't autosize + + full_element_pad = [0, 0, 0, 0] # Top, Right, Bottom, Left + elementpad = element.Pad if element.Pad is not None else toplevel_form.ElementPadding + if type(elementpad[0]) != tuple: # left and right + full_element_pad[1] = full_element_pad[3] = elementpad[0] + else: + full_element_pad[3], full_element_pad[1] = elementpad[0] + if type(elementpad[1]) != tuple: # top and bottom + full_element_pad[0] = full_element_pad[2] = elementpad[1] + else: + full_element_pad[0], full_element_pad[2] = elementpad[1] + + # ------------------------- COLUMN element ------------------------- # + if element_type == ELEM_TYPE_COLUMN: + element = element # type: Column + element.Widget = column_widget = remi.gui.VBox() + if element.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT): + column_widget.style['background-color'] = element.BackgroundColor + PackFormIntoFrame(element, column_widget, toplevel_form) + tk_row_frame.append(element.Widget) + + # ------------------------- TEXT element ------------------------- # + elif element_type == ELEM_TYPE_TEXT: + element = element # type: Text + element.Widget = remi.gui.Label(element.DisplayText) + do_font_and_color(element.Widget) + if auto_size_text and element.Size == (None, None): + del(element.Widget.style['width']) + if element.Justification: + if element.Justification.startswith('c'): + element.Widget.style['text-align'] = 'center' + elif element.Justification.startswith('r'): + element.Widget.style['text-align'] = 'right' + if element.ClickSubmits: + element.Widget.onclick.connect(element._ChangedCallback) + tk_row_frame.append(element.Widget) + + # ------------------------- BUTTON element ------------------------- # + elif element_type == ELEM_TYPE_BUTTON: + element = element # type: Button + size = convert_tkinter_size_to_Wx(element_size) + element.Widget = remi.gui.Button(element.ButtonText, width=size[0], height=size[1], margin='10px') + element.Widget.onclick.connect(element._ButtonCallBack) + do_font_and_color(element.Widget) + if element.AutoSizeButton or (toplevel_form.AutoSizeButtons and element.AutoSizeButton is not False) and element.Size == (None, None): + del (element.Widget.style['width']) + if element.ImageFilename: + element.ImageWidget = SuperImage(element.ImageFilename if element.ImageFilename is not None else element.ImageData) + element.Widget.append(element.ImageWidget) + tk_row_frame.append(element.Widget) + + # stringvar = tk.StringVar() + # element.TKStringVar = stringvar + # element.Location = (row_num, col_num) + # btext = element.ButtonText + # btype = element.BType + # if element.AutoSizeButton is not None: + # auto_size = element.AutoSizeButton + # else: + # auto_size = toplevel_form.AutoSizeButtons + # if auto_size is False or element.Size[0] is not None: + # width, height = element_size + # else: + # width = 0 + # height = toplevel_form.DefaultButtonElementSize[1] + # if element.ButtonColor != (None, None) and element.ButtonColor != DEFAULT_BUTTON_COLOR: + # bc = element.ButtonColor + # elif toplevel_form.ButtonColor != (None, None) and toplevel_form.ButtonColor != DEFAULT_BUTTON_COLOR: + # bc = toplevel_form.ButtonColor + # else: + # bc = DEFAULT_BUTTON_COLOR + # border_depth = element.BorderWidth + # if btype != BUTTON_TYPE_REALTIME: + # tkbutton = tk.Button(tk_row_frame, text=btext, width=width, height=height, + # command=element.ButtonCallBack, justify=tk.LEFT, bd=border_depth, font=font) + # else: + # tkbutton = tk.Button(tk_row_frame, text=btext, width=width, height=height, justify=tk.LEFT, + # bd=border_depth, font=font) + # tkbutton.bind('', element.ButtonReleaseCallBack) + # tkbutton.bind('', element.ButtonPressCallBack) + # if bc != (None, None) and bc != COLOR_SYSTEM_DEFAULT and bc[1] != COLOR_SYSTEM_DEFAULT: + # tkbutton.config(foreground=bc[0], background=bc[1], activebackground=bc[1]) + # elif bc[1] == COLOR_SYSTEM_DEFAULT: + # tkbutton.config(foreground=bc[0]) + # + # element.TKButton = tkbutton # not used yet but save the TK button in case + # wraplen = tkbutton.winfo_reqwidth() # width of widget in Pixels + # if element.ImageFilename: # if button has an image on it + # tkbutton.config(highlightthickness=0) + # photo = tk.PhotoImage(file=element.ImageFilename) + # if element.ImageSize != (None, None): + # width, height = element.ImageSize + # if element.ImageSubsample: + # photo = photo.subsample(element.ImageSubsample) + # else: + # width, height = photo.width(), photo.height() + # tkbutton.config(image=photo, compound=tk.CENTER, width=width, height=height) + # tkbutton.image = photo + # if element.ImageData: # if button has an image on it + # tkbutton.config(highlightthickness=0) + # photo = tk.PhotoImage(data=element.ImageData) + # if element.ImageSize != (None, None): + # width, height = element.ImageSize + # if element.ImageSubsample: + # photo = photo.subsample(element.ImageSubsample) + # else: + # width, height = photo.width(), photo.height() + # tkbutton.config(image=photo, compound=tk.CENTER, width=width, height=height) + # tkbutton.image = photo + # if width != 0: + # tkbutton.configure(wraplength=wraplen + 10) # set wrap to width of widget + # tkbutton.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) + # if element.BindReturnKey: + # element.TKButton.bind('', element.ReturnKeyHandler) + # if element.Focus is True or (toplevel_form.UseDefaultFocus and not focus_set): + # focus_set = True + # element.TKButton.bind('', element.ReturnKeyHandler) + # element.TKButton.focus_set() + # toplevel_form.TKroot.focus_force() + # if element.Disabled == True: + # element.TKButton['state'] = 'disabled' + # if element.Tooltip is not None: + # element.TooltipObject = ToolTip(element.TKButton, text=element.Tooltip, + # timeout=DEFAULT_TOOLTIP_TIME) + # # ------------------------- INPUT element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_TEXT: + element = element # type: InputText + element.Widget = InputText.TextInput_raw_onkeyup(hint=element.DefaultText) + # element.Widget = remi.gui.TextInput(hint=element.DefaultText) + do_font_and_color(element.Widget) + if element.ChangeSubmits: + element.Widget.onkeyup.connect(element._InputTextCallback) + # element.Widget.onkeydown.connect(element._InputTextCallback) + tk_row_frame.append(element.Widget) + + # show = element.PasswordCharacter if element.PasswordCharacter else "" + # if element.Justification is not None: + # justification = element.Justification + # else: + # justification = DEFAULT_TEXT_JUSTIFICATION + # justify = tk.LEFT if justification == 'left' else tk.CENTER if justification == 'center' else tk.RIGHT + # # anchor = tk.NW if justification == 'left' else tk.N if justification == 'center' else tk.NE + # element.TKEntry = tk.Entry(tk_row_frame, width=element_size[0], textvariable=element.TKStringVar, + # bd=border_depth, font=font, show=show, justify=justify) + # if element.ChangeSubmits: + # element.TKEntry.bind('', element.KeyboardHandler) + # element.TKEntry.bind('', element.ReturnKeyHandler) + # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + # element.TKEntry.configure(background=element.BackgroundColor) + # if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT: + # element.TKEntry.configure(fg=text_color) + # element.TKEntry.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1], expand=True, fill='x') + # if element.Focus is True or (toplevel_form.UseDefaultFocus and not focus_set): + # focus_set = True + # element.TKEntry.focus_set() + # if element.Disabled: + # element.TKEntry['state'] = 'disabled' + # if element.Tooltip is not None: + # element.TooltipObject = ToolTip(element.TKEntry, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) + # ------------------------- COMBO element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_COMBO: + element = element # type: Combo + element.Widget = remi.gui.DropDown.new_from_list(element.Values) + if element.DefaultValue is not None: + element.Widget.select_by_value(element.DefaultValue) + do_font_and_color(element.Widget) + if element.ChangeSubmits: + element.Widget.onchange.connect(element._ChangedCallback) + tk_row_frame.append(element.Widget) + + # ------------------------- OPTION MENU (Like ComboBox but different) element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_OPTION_MENU: + element.Widget = remi.gui.FileUploader('./', width=200, height=30, margin='10px') + + # element.Widget = remi.gui.FileFolderNavigator(False, r'a:\TEMP', True, False) + tk_row_frame.append(element.Widget) + pass + # ------------------------- LISTBOX element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_LISTBOX: + element = element # type: Listbox + element.Widget = remi.gui.ListView.new_from_list(element.Values) + do_font_and_color(element.Widget) + if element.ChangeSubmits: + element.Widget.onselection.connect(element._ChangedCallback) + tk_row_frame.append(element.Widget) + # max_line_len = max([len(str(l)) for l in element.Values]) if len(element.Values) != 0 else 0 + # if auto_size_text is False: + # width = element_size[0] + # else: + # width = max_line_len + # listbox_frame = tk.Frame(tk_row_frame) + # element.TKStringVar = tk.StringVar() + # element.TKListbox = tk.Listbox(listbox_frame, height=element_size[1], width=width, + # selectmode=element.SelectMode, font=font) + # for index, item in enumerate(element.Values): + # element.TKListbox.insert(tk.END, item) + # if element.DefaultValues is not None and item in element.DefaultValues: + # element.TKListbox.selection_set(index) + # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + # element.TKListbox.configure(background=element.BackgroundColor) + # if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT: + # element.TKListbox.configure(fg=text_color) + # if element.ChangeSubmits: + # element.TKListbox.bind('<>', element.ListboxSelectHandler) + # vsb = tk.Scrollbar(listbox_frame, orient="vertical", command=element.TKListbox.yview) + # element.TKListbox.configure(yscrollcommand=vsb.set) + # element.TKListbox.pack(side=tk.LEFT) + # vsb.pack(side=tk.LEFT, fill='y') + # listbox_frame.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) + # if element.BindReturnKey: + # element.TKListbox.bind('', element.ListboxSelectHandler) + # element.TKListbox.bind('', element.ListboxSelectHandler) + # if element.Disabled == True: + # element.TKListbox['state'] = 'disabled' + # if element.Tooltip is not None: + # element.TooltipObject = ToolTip(element.TKListbox, text=element.Tooltip, + # timeout=DEFAULT_TOOLTIP_TIME) + # ------------------------- INPUT MULTILINE element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_MULTILINE: + element = element # type: Multiline + element.Widget = remi.gui.TextInput(single_line=False, hint=element.DefaultText) + do_font_and_color(element.Widget) + if element.ChangeSubmits: + element.Widget.onkeydown.connect(element._InputTextCallback) + tk_row_frame.append(element.Widget) + # default_text = element.DefaultText + # width, height = element_size + # element.TKText = tk.scrolledtext.ScrolledText(tk_row_frame, width=width, height=height, wrap='word', + # bd=border_depth, font=font) + # element.TKText.insert(1.0, default_text) # set the default text + # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + # element.TKText.configure(background=element.BackgroundColor) + # element.TKText.vbar.config(troughcolor=DEFAULT_SCROLLBAR_COLOR) + # element.TKText.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1], expand=True, fill='both') + # if element.ChangeSubmits: + # element.TKText.bind('', element.KeyboardHandler) + # if element.EnterSubmits: + # element.TKText.bind('', element.ReturnKeyHandler) + # if element.Focus is True or (toplevel_form.UseDefaultFocus and not focus_set): + # focus_set = True + # element.TKText.focus_set() + # if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT: + # element.TKText.configure(fg=text_color) + # if element.Disabled == True: + # element.TKText['state'] = 'disabled' + # if element.Tooltip is not None: + # element.TooltipObject = ToolTip(element.TKText, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) + + # ------------------------- INPUT CHECKBOX element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_CHECKBOX: + element = element # type: Checkbox + element.Widget = remi.gui.CheckBoxLabel(element.Text) + if element.InitialState: + element.Widget.set_value(element.InitialState) + if element.ChangeSubmits: + element.Widget.onchange.connect(element._ChangedCallback) + do_font_and_color(element.Widget) + tk_row_frame.append(element.Widget) + + # width = 0 if auto_size_text else element_size[0] + # default_value = element.InitialState + # element.TKIntVar = tk.IntVar() + # element.TKIntVar.set(default_value if default_value is not None else 0) + # if element.ChangeSubmits: + # element.TKCheckbutton = tk.Checkbutton(tk_row_frame, anchor=tk.NW, text=element.Text, width=width, + # variable=element.TKIntVar, bd=border_depth, font=font, + # command=element.CheckboxHandler) + # else: + # element.TKCheckbutton = tk.Checkbutton(tk_row_frame, anchor=tk.NW, text=element.Text, width=width, + # variable=element.TKIntVar, bd=border_depth, font=font) + # if default_value is None or element.Disabled: + # element.TKCheckbutton.configure(state='disable') + # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + # element.TKCheckbutton.configure(background=element.BackgroundColor) + # element.TKCheckbutton.configure(selectcolor=element.BackgroundColor) + # element.TKCheckbutton.configure(activebackground=element.BackgroundColor) + # if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT: + # element.TKCheckbutton.configure(fg=text_color) + # element.TKCheckbutton.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) + # if element.Tooltip is not None: + # element.TooltipObject = ToolTip(element.TKCheckbutton, text=element.Tooltip, + # timeout=DEFAULT_TOOLTIP_TIME) + # # ------------------------- PROGRESS BAR element ------------------------- # + elif element_type == ELEM_TYPE_PROGRESS_BAR: + pass + # # save this form because it must be 'updated' (refreshed) solely for the purpose of updating bar + # width = element_size[0] + # fnt = tkinter.font.Font() + # char_width = fnt.measure('A') # single character width + # progress_length = width * char_width + # progress_width = element_size[1] + # direction = element.Orientation + # if element.BarColor != (None, None): # if element has a bar color, use it + # bar_color = element.BarColor + # else: + # bar_color = DEFAULT_PROGRESS_BAR_COLOR + # element.TKProgressBar = TKProgressBar(tk_row_frame, element.MaxValue, progress_length, progress_width, + # orientation=direction, BarColor=bar_color, + # border_width=element.BorderWidth, relief=element.Relief, + # style=element.BarStyle, key=element.Key) + # element.TKProgressBar.TKProgressBarForReal.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) + # ------------------------- INPUT RADIO BUTTON element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_RADIO: + pass + # width = 0 if auto_size_text else element_size[0] + # default_value = element.InitialState + # ID = element.GroupID + # # see if ID has already been placed + # value = EncodeRadioRowCol(row_num, col_num) # value to set intvar to if this radio is selected + # if ID in toplevel_form.RadioDict: + # RadVar = toplevel_form.RadioDict[ID] + # else: + # RadVar = tk.IntVar() + # toplevel_form.RadioDict[ID] = RadVar + # element.TKIntVar = RadVar # store the RadVar in Radio object + # if default_value: # if this radio is the one selected, set RadVar to match + # element.TKIntVar.set(value) + # if element.ChangeSubmits: + # element.TKRadio = tk.Radiobutton(tk_row_frame, anchor=tk.NW, text=element.Text, width=width, + # variable=element.TKIntVar, value=value, bd=border_depth, font=font, + # command=element.RadioHandler) + # else: + # element.TKRadio = tk.Radiobutton(tk_row_frame, anchor=tk.NW, text=element.Text, width=width, + # variable=element.TKIntVar, value=value, bd=border_depth, font=font) + # if not element.BackgroundColor in (None, COLOR_SYSTEM_DEFAULT): + # element.TKRadio.configure(background=element.BackgroundColor) + # element.TKRadio.configure(selectcolor=element.BackgroundColor) + # if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT: + # element.TKRadio.configure(fg=text_color) + # if element.Disabled: + # element.TKRadio['state'] = 'disabled' + # element.TKRadio.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) + # if element.Tooltip is not None: + # element.TooltipObject = ToolTip(element.TKRadio, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) + # ------------------------- INPUT SPIN element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_SPIN: + element = element # type: Spin + element.Widget = remi.gui.SpinBox(50, 0, 100) + if element.DefaultValue is not None: + element.Widget.set_value(element.DefaultValue) + do_font_and_color(element.Widget) + if element.ChangeSubmits: + element.Widget.onchange.connect(element._ChangedCallback) + tk_row_frame.append(element.Widget) + # width, height = element_size + # width = 0 if auto_size_text else element_size[0] + # element.TKStringVar = tk.StringVar() + # element.TKSpinBox = tk.Spinbox(tk_row_frame, values=element.Values, textvariable=element.TKStringVar, + # width=width, bd=border_depth) + # element.TKStringVar.set(element.DefaultValue) + # element.TKSpinBox.configure(font=font) # set wrap to width of widget + # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + # element.TKSpinBox.configure(background=element.BackgroundColor) + # element.TKSpinBox.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) + # if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT: + # element.TKSpinBox.configure(fg=text_color) + # if element.ChangeSubmits: + # element.TKSpinBox.bind('', element.SpinChangedHandler) + # if element.Disabled == True: + # element.TKSpinBox['state'] = 'disabled' + # if element.Tooltip is not None: + # element.TooltipObject = ToolTip(element.TKSpinBox, text=element.Tooltip, + # timeout=DEFAULT_TOOLTIP_TIME) + # ------------------------- OUTPUT element ------------------------- # + elif element_type == ELEM_TYPE_OUTPUT: + element=element # type: Output + element.Widget = remi.gui.TextInput(single_line=False) + element.Disabled = True + do_font_and_color(element.Widget) + tk_row_frame.append(element.Widget) + toplevel_form.OutputElementForStdOut = element + Window.stdout_is_rerouted = True + Window.stdout_string_io = StringIO() + sys.stdout = Window.stdout_string_io + + # width, height = element_size + # element._TKOut = TKOutput(tk_row_frame, width=width, height=height, bd=border_depth, + # background_color=element.BackgroundColor, text_color=text_color, font=font, + # pad=element.Pad) + # element._TKOut.pack(side=tk.LEFT, expand=True, fill='both') + # if element.Tooltip is not None: + # element.TooltipObject = ToolTip(element._TKOut, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) + # ------------------------- OUTPUT MULTILINE element ------------------------- # + elif element_type == ELEM_TYPE_MULTILINE_OUTPUT: + element = element # type: MultilineOutput + element.Widget = remi.gui.TextInput(single_line=False) + element.Disabled = True + do_font_and_color(element.Widget) + tk_row_frame.append(element.Widget) + if element.DefaultText: + element.Widget.set_value(element.DefaultText) + # ------------------------- IMAGE element ------------------------- # + elif element_type == ELEM_TYPE_IMAGE: + element = element # type: Image + # element.Widget = remi.gui.Image(element.Filename) + element.Widget = SuperImage(element.Filename if element.Filename is not None else element.Data) + if element.Filename is not None: + # print(f'loading image filename in pack frame {element.Filename}') + element.Widget.load(element.Filename) + do_font_and_color(element.Widget) + if element.EnableEvents: + element.Widget.onclick.connect(element._ChangedCallback) + tk_row_frame.append(element.Widget) + # if element.Filename is not None: + # photo = tk.PhotoImage(file=element.Filename) + # elif element.Data is not None: + # photo = tk.PhotoImage(data=element.Data) + # else: + # photo = None + # print('*ERROR laying out form.... Image Element has no image specified*') + # + # if photo is not None: + # if element_size == ( + # None, None) or element_size == None or element_size == toplevel_form.DefaultElementSize: + # width, height = photo.width(), photo.height() + # else: + # width, height = element_size + # if photo is not None: + # element.tktext_label = tk.Label(tk_row_frame, image=photo, width=width, height=height, + # bd=border_depth) + # else: + # element.tktext_label = tk.Label(tk_row_frame, width=width, height=height, bd=border_depth) + # if element.BackgroundColor is not None: + # element.tktext_label.config(background=element.BackgroundColor); + # + # element.tktext_label.image = photo + # # tktext_label.configure(anchor=tk.NW, image=photo) + # element.tktext_label.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) + # if element.Tooltip is not None: + # element.TooltipObject = ToolTip(element.tktext_label, text=element.Tooltip, + # timeout=DEFAULT_TOOLTIP_TIME) + # ------------------------- Canvas element ------------------------- # + elif element_type == ELEM_TYPE_CANVAS: + pass + # width, height = element_size + # if element._TKCanvas is None: + # element._TKCanvas = tk.Canvas(tk_row_frame, width=width, height=height, bd=border_depth) + # else: + # element._TKCanvas.master = tk_row_frame + # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + # element._TKCanvas.configure(background=element.BackgroundColor, highlightthickness=0) + # element._TKCanvas.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) + # if element.Tooltip is not None: + # element.TooltipObject = ToolTip(element._TKCanvas, text=element.Tooltip, + # timeout=DEFAULT_TOOLTIP_TIME) + + # ------------------------- Graph element ------------------------- # + elif element_type == ELEM_TYPE_GRAPH: + element = element # type: Graph + element.Widget = remi.gui.Svg(width=element.CanvasSize[0], height=element.CanvasSize[1]) + element.SvgGroup = remi.gui.SvgSubcontainer(0,0, "100%", "100%") + element.Widget.append([element.SvgGroup,]) + do_font_and_color(element.Widget) + if element.ChangeSubmits: + element.Widget.onmouseup.connect(element._MouseUpCallback) + # element.Widget.onclick.connect(element.ClickCallback) + if element.DragSubmits: + element.Widget.onmousedown.connect(element._MouseDownCallback) + element.Widget.onmouseup.connect(element._MouseUpCallback) + element.Widget.onmousemove.connect(element._DragCallback) + + tk_row_frame.append(element.Widget) + # width, height = element_size + # if element._TKCanvas is None: + # element._TKCanvas = tk.Canvas(tk_row_frame, width=width, height=height, bd=border_depth) + # else: + # element._TKCanvas.master = tk_row_frame + # element._TKCanvas2 = tk.Canvas(element._TKCanvas, width=width, height=height, bd=border_depth) + # element._TKCanvas2.pack(side=tk.LEFT) + # element._TKCanvas2.addtag_all('mytag') + # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + # element._TKCanvas2.configure(background=element.BackgroundColor, highlightthickness=0) + # element._TKCanvas.configure(background=element.BackgroundColor, highlightthickness=0) + # element._TKCanvas.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) + # if element.Tooltip is not None: + # element.TooltipObject = ToolTip(element._TKCanvas, text=element.Tooltip, + # timeout=DEFAULT_TOOLTIP_TIME) + # if element.ChangeSubmits: + # element._TKCanvas2.bind('', element.ButtonReleaseCallBack) + # element._TKCanvas2.bind('', element.ButtonPressCallBack) + # if element.DragSubmits: + # element._TKCanvas2.bind('', element.MotionCallBack) + # ------------------------- MENUBAR element ------------------------- # + elif element_type == ELEM_TYPE_MENUBAR: + element = element # type: Menu + menu = remi.gui.Menu(width='100%', height=str(element_size[1])) + element_size = (0,0) # makes the menu span across the top + do_font_and_color(menu) + + menu_def = element.MenuDefinition + for menu_entry in menu_def: + # print(f'Adding a Menubar ENTRY {menu_entry}') + pos = menu_entry[0].find('&') + # print(pos) + if pos != -1: + if pos == 0 or menu_entry[0][pos - 1] != "\\": + menu_entry[0] = menu_entry[0][:pos] + menu_entry[0][pos + 1:] + if menu_entry[0][0] == MENU_DISABLED_CHARACTER: + item = remi.gui.MenuItem(menu_entry[0][1:], width=100, height=element_size[1]) + item.set_enabled(False) + else: + item = remi.gui.MenuItem(menu_entry[0], width=100, height=element_size[1]) + do_font_and_color(item) + menu.append([item,]) + if len(menu_entry) > 1: + AddMenuItem(item, menu_entry[1], element) + + element.Widget = menubar = remi.gui.MenuBar(width='100%', height='30px') + element.Widget.style['z-index'] = '1' + menubar.append(menu) + # tk_row_frame.append(element.Widget) + containing_frame.append(element.Widget) + + # ------------------------- Frame element ------------------------- # + elif element_type == ELEM_TYPE_FRAME: + element = element # type: Frame + # element.Widget = column_widget = remi.gui.VBox() + element.Widget = column_widget = CLASSframe(element.Title) + if element.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT): + column_widget.style['background-color'] = element.BackgroundColor + PackFormIntoFrame(element, column_widget, toplevel_form) + tk_row_frame.append(element.Widget) + + # + # element = element # type: Frame + # element.Widget = column_widget = remi.gui.VBox() + # if element.Justification.startswith('c'): + # column_widget.style['align-items'] = 'center' + # column_widget.style['justify-content'] = 'center' + # else: + # column_widget.style['justify-content'] = 'flex-start' + # column_widget.style['align-items'] = 'baseline' + # if element.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT): + # column_widget.style['background-color'] = element.BackgroundColor + # PackFormIntoFrame(element, column_widget, toplevel_form) + # tk_row_frame.append(element.Widget) + + # labeled_frame = tk.LabelFrame(tk_row_frame, text=element.Title, relief=element.Relief) + # PackFormIntoFrame(element, labeled_frame, toplevel_form) + # labeled_frame.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) + # if element.BackgroundColor != COLOR_SYSTEM_DEFAULT and element.BackgroundColor is not None: + # labeled_frame.configure(background=element.BackgroundColor, + # highlightbackground=element.BackgroundColor, + # highlightcolor=element.BackgroundColor) + # if element.TextColor != COLOR_SYSTEM_DEFAULT and element.TextColor is not None: + # labeled_frame.configure(foreground=element.TextColor) + # if font is not None: + # labeled_frame.configure(font=font) + # if element.TitleLocation is not None: + # labeled_frame.configure(labelanchor=element.TitleLocation) + # if element.BorderWidth is not None: + # labeled_frame.configure(borderwidth=element.BorderWidth) + # if element.Tooltip is not None: + # element.TooltipObject = ToolTip(labeled_frame, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) + # ------------------------- Tab element ------------------------- # + elif element_type == ELEM_TYPE_TAB: + element = element # type: Tab + element.Widget = remi.gui.VBox() + if element.Justification.startswith('c'): + # print('CENTERING') + element.Widget.style['align-items'] = 'center' + element.Widget.style['justify-content'] = 'center' + else: + element.Widget.style['justify-content'] = 'flex-start' + element.Widget.style['align-items'] = 'baseline' + if element.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT): + element.Widget.style['background-color'] = element.BackgroundColor + if element.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT): + element.Widget.style['background-color'] = element.BackgroundColor + PackFormIntoFrame(element, element.Widget, toplevel_form) + # tk_row_frame.append(element.Widget) + containing_frame.add_tab(element.Widget, element.Title, None) + + # element.TKFrame = tk.Frame(form.TKNotebook) + # PackFormIntoFrame(element, element.TKFrame, toplevel_form) + # if element.Disabled: + # form.TKNotebook.add(element.TKFrame, text=element.Title, state='disabled') + # else: + # form.TKNotebook.add(element.TKFrame, text=element.Title) + # form.TKNotebook.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) + # element.ParentNotebook = form.TKNotebook + # element.TabID = form.TabCount + # form.TabCount += 1 + # if element.BackgroundColor != COLOR_SYSTEM_DEFAULT and element.BackgroundColor is not None: + # element.TKFrame.configure(background=element.BackgroundColor, + # highlightbackground=element.BackgroundColor, + # highlightcolor=element.BackgroundColor) + # # if element.TextColor != COLOR_SYSTEM_DEFAULT and element.TextColor is not None: + # # element.TKFrame.configure(foreground=element.TextColor) + # + # # ttk.Style().configure("TNotebook", background='red') + # # ttk.Style().map("TNotebook.Tab", background=[("selected", 'orange')], + # # foreground=[("selected", 'green')]) + # # ttk.Style().configure("TNotebook.Tab", background='blue', foreground='yellow') + # + # if element.BorderWidth is not None: + # element.TKFrame.configure(borderwidth=element.BorderWidth) + # if element.Tooltip is not None: + # element.TooltipObject = ToolTip(element.TKFrame, text=element.Tooltip, + # timeout=DEFAULT_TOOLTIP_TIME) + # ------------------------- TabGroup element ------------------------- # + elif element_type == ELEM_TYPE_TAB_GROUP: + element = element # type: TabGroup + element.Widget = remi.gui.TabBox() + # do_font_and_color(element.Widget) + PackFormIntoFrame(element ,element.Widget, toplevel_form) + tk_row_frame.append(element.Widget) + + # custom_style = str(element.Key) + 'customtab.TNotebook' + # style = ttk.Style(tk_row_frame) + # if element.Theme is not None: + # style.theme_use(element.Theme) + # if element.TabLocation is not None: + # position_dict = {'left': 'w', 'right': 'e', 'top': 'n', 'bottom': 's', 'lefttop': 'wn', + # 'leftbottom': 'ws', 'righttop': 'en', 'rightbottom': 'es', 'bottomleft': 'sw', + # 'bottomright': 'se', 'topleft': 'nw', 'topright': 'ne'} + # try: + # tab_position = position_dict[element.TabLocation] + # except: + # tab_position = position_dict['top'] + # style.configure(custom_style, tabposition=tab_position) + # + # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + # style.configure(custom_style, background=element.BackgroundColor, foreground='purple') + # + # # style.theme_create("yummy", parent="alt", settings={ + # # "TNotebook": {"configure": {"tabmargins": [2, 5, 2, 0]}}, + # # "TNotebook.Tab": { + # # "configure": {"padding": [5, 1], "background": mygreen}, + # # "map": {"background": [("selected", myred)], + # # "expand": [("selected", [1, 1, 1, 0])]}}}) + # + # # style.configure(custom_style+'.Tab', background='red') + # if element.SelectedTitleColor != None: + # style.map(custom_style + '.Tab', foreground=[("selected", element.SelectedTitleColor)]) + # if element.TextColor is not None and element.TextColor != COLOR_SYSTEM_DEFAULT: + # style.configure(custom_style + '.Tab', foreground=element.TextColor) + # # style.configure(custom_style, background='blue', foreground='yellow') + # + # element.TKNotebook = ttk.Notebook(tk_row_frame, style=custom_style) + # + # PackFormIntoFrame(element, toplevel_form.TKroot, toplevel_form) + # + # if element.ChangeSubmits: + # element.TKNotebook.bind('<>', element.TabGroupSelectHandler) + # if element.BorderWidth is not None: + # element.TKNotebook.configure(borderwidth=element.BorderWidth) + # if element.Tooltip is not None: + # element.TooltipObject = ToolTip(element.TKNotebook, text=element.Tooltip, + # timeout=DEFAULT_TOOLTIP_TIME) + # ------------------------- SLIDER element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_SLIDER: + element = element # type: Slider + orient = remi.gui.Container.LAYOUT_HORIZONTAL if element.Orientation.lower().startswith('h') else remi.gui.Container.LAYOUT_VERTICAL + # print(f'slider orient = {orient}') + element.Widget = remi.gui.Slider(layout_orientation=orient, default_value=element.DefaultValue, min=element.Range[0], max=element.Range[1],step=element.Resolution) + if element.DefaultValue: + element.Widget.set_value(element.DefaultValue) + # if element.Orientation.startswith('v'): + # element.Container.LAYOUT_orientation = remi.gui.Container.LAYOUT_VERTICAL + do_font_and_color(element.Widget) + if element.ChangeSubmits: + element.Widget.onchange.connect(element._SliderCallback) + element.Widget.style['orientation'] = 'vertical' + element.Widget.attributes['orientation'] = 'vertical' + # print(f'slider = {element.Widget.style, element.Widget.attributes}') + tk_row_frame.append(element.Widget) # slider_length = element_size[0] * CharWidthInPixels() + + # ------------------------- TABLE element ------------------------- # + elif element_type == ELEM_TYPE_TABLE: + element = element # type: Table + new_table = [] + for row_num, row in enumerate(element.Values): # convert entire table to strings + new_row= [str(item) for item in row] + if element.DisplayRowNumbers: + new_row = [element.RowHeaderText if row_num == 0 else str(row_num+element.StartingRowNumber) ,] + new_row + new_table.append(new_row) + element.Widget = remi.gui.Table.new_from_list(new_table) + do_font_and_color(element.Widget) + tk_row_frame.append(element.Widget) + element.Widget.on_table_row_click.connect(element._on_table_row_click) + # frame = tk.Frame(tk_row_frame) + # + # height = element.NumRows + # if element.Justification == 'left': + # anchor = tk.W + # elif element.Justification == 'right': + # anchor = tk.E + # else: + # anchor = tk.CENTER + # column_widths = {} + # for row in element.Values: + # for i, col in enumerate(row): + # col_width = min(len(str(col)), element.MaxColumnWidth) + # try: + # if col_width > column_widths[i]: + # column_widths[i] = col_width + # except: + # column_widths[i] = col_width + # if element.ColumnsToDisplay is None: + # displaycolumns = element.ColumnHeadings if element.ColumnHeadings is not None else element.Values[0] + # else: + # displaycolumns = [] + # for i, should_display in enumerate(element.ColumnsToDisplay): + # if should_display: + # displaycolumns.append(element.ColumnHeadings[i]) + # column_headings = element.ColumnHeadings + # if element.DisplayRowNumbers: # if display row number, tack on the numbers to front of columns + # displaycolumns = [element.RowHeaderText, ] + displaycolumns + # column_headings = [element.RowHeaderText, ] + element.ColumnHeadings + # element.TKTreeview = ttk.Treeview(frame, columns=column_headings, + # displaycolumns=displaycolumns, show='headings', height=height, + # selectmode=element.SelectMode,) + # treeview = element.TKTreeview + # if element.DisplayRowNumbers: + # treeview.heading(element.RowHeaderText, text=element.RowHeaderText) # make a dummy heading + # treeview.column(element.RowHeaderText, width=50, anchor=anchor) + # + # headings = element.ColumnHeadings if element.ColumnHeadings is not None else element.Values[0] + # for i, heading in enumerate(headings): + # treeview.heading(heading, text=heading) + # if element.AutoSizeColumns: + # width = max(column_widths[i], len(heading)) + # else: + # try: + # width = element.ColumnWidths[i] + # except: + # width = element.DefaultColumnWidth + # treeview.column(heading, width=width * CharWidthInPixels(), anchor=anchor) + # + # # Insert values into the tree + # for i, value in enumerate(element.Values): + # if element.DisplayRowNumbers: + # value = [i+element.StartingRowNumber] + value + # id = treeview.insert('', 'end', text=value, iid=i + 1, values=value, tag=i) + # if element.AlternatingRowColor is not None: # alternating colors + # for row in range(0, len(element.Values), 2): + # treeview.tag_configure(row, background=element.AlternatingRowColor) + # if element.RowColors is not None: # individual row colors + # for row_def in element.RowColors: + # if len(row_def) == 2: # only background is specified + # treeview.tag_configure(row_def[0], background=row_def[1]) + # else: + # treeview.tag_configure(row_def[0], background=row_def[2], foreground=row_def[1]) + # + # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + # ttk.Style().configure("Treeview", background=element.BackgroundColor, + # fieldbackground=element.BackgroundColor) + # if element.TextColor is not None and element.TextColor != COLOR_SYSTEM_DEFAULT: + # ttk.Style().configure("Treeview", foreground=element.TextColor) + # if element.RowHeight is not None: + # ttk.Style().configure("Treeview", rowheight=element.RowHeight) + # ttk.Style().configure("Treeview", font=font) + # # scrollable_frame.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=True, fill='both') + # treeview.bind("<>", element.treeview_selected) + # if element.BindReturnKey: + # treeview.bind('', element.treeview_double_click) + # treeview.bind('', element.treeview_double_click) + # + # scrollbar = tk.Scrollbar(frame) + # scrollbar.pack(side=tk.RIGHT, fill='y') + # scrollbar.config(command=treeview.yview) + # + # if not element.VerticalScrollOnly: + # hscrollbar = tk.Scrollbar(frame, orient=tk.HORIZONTAL) + # hscrollbar.pack(side=tk.BOTTOM, fill='x') + # hscrollbar.config(command=treeview.xview) + # treeview.configure(xscrollcommand=hscrollbar.set) + # + # treeview.configure(yscrollcommand=scrollbar.set) + # + # element.TKTreeview.pack(side=tk.LEFT, expand=True, padx=0, pady=0, fill='both') + # if element.Visible is False: + # element.TKTreeview.pack_forget() + # frame.pack(side=tk.LEFT, expand=True, padx=0, pady=0) + # if element.Tooltip is not None: + # element.TooltipObject = ToolTip(element.TKTreeview, text=element.Tooltip, + # timeout=DEFAULT_TOOLTIP_TIME) + # if element.RightClickMenu or toplevel_form.RightClickMenu: + # menu = element.RightClickMenu or toplevel_form.RightClickMenu + # top_menu = tk.Menu(toplevel_form.TKroot, tearoff=False) + # AddMenuItem(top_menu, menu[1], element) + # element.TKRightClickMenu = top_menu + # element.TKTreeview.bind('', element.RightClickMenuCallback) + pass + # frame = tk.Frame(tk_row_frame) + # + # height = element.NumRows + # if element.Justification == 'left': + # anchor = tk.W + # elif element.Justification == 'right': + # anchor = tk.E + # else: + # anchor = tk.CENTER + # column_widths = {} + # for row in element.Values: + # for i, col in enumerate(row): + # col_width = min(len(str(col)), element.MaxColumnWidth) + # try: + # if col_width > column_widths[i]: + # column_widths[i] = col_width + # except: + # column_widths[i] = col_width + # if element.ColumnsToDisplay is None: + # displaycolumns = element.ColumnHeadings + # else: + # displaycolumns = [] + # for i, should_display in enumerate(element.ColumnsToDisplay): + # if should_display: + # displaycolumns.append(element.ColumnHeadings[i]) + # column_headings = element.ColumnHeadings + # if element.DisplayRowNumbers: # if display row number, tack on the numbers to front of columns + # displaycolumns = [element.RowHeaderText, ] + displaycolumns + # column_headings = [element.RowHeaderText, ] + element.ColumnHeadings + # element.TKTreeview = ttk.Treeview(frame, columns=column_headings, + # displaycolumns=displaycolumns, show='headings', height=height, + # selectmode=element.SelectMode) + # treeview = element.TKTreeview + # if element.DisplayRowNumbers: + # treeview.heading(element.RowHeaderText, text=element.RowHeaderText) # make a dummy heading + # treeview.column(element.RowHeaderText, width=50, anchor=anchor) + # for i, heading in enumerate(element.ColumnHeadings): + # treeview.heading(heading, text=heading) + # if element.AutoSizeColumns: + # width = max(column_widths[i], len(heading)) + # else: + # try: + # width = element.ColumnWidths[i] + # except: + # width = element.DefaultColumnWidth + # + # treeview.column(heading, width=width * CharWidthInPixels(), anchor=anchor) + # # Insert values into the tree + # for i, value in enumerate(element.Values): + # if element.DisplayRowNumbers: + # value = [i + element.StartingRowNumber] + value + # id = treeview.insert('', 'end', text=value, iid=i + 1, values=value, tag=i % 2) + # if element.AlternatingRowColor is not None: + # treeview.tag_configure(1, background=element.AlternatingRowColor) + # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + # ttk.Style().configure("Treeview", background=element.BackgroundColor, + # fieldbackground=element.BackgroundColor) + # if element.TextColor is not None and element.TextColor != COLOR_SYSTEM_DEFAULT: + # ttk.Style().configure("Treeview", foreground=element.TextColor) + # # scrollable_frame.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1], expand=True, fill='both') + # treeview.bind("<>", element.treeview_selected) + # if element.BindReturnKey: + # treeview.bind('', element.treeview_double_click) + # treeview.bind('', element.treeview_double_click) + # scrollbar = tk.Scrollbar(frame) + # scrollbar.pack(side=tk.RIGHT, fill='y') + # scrollbar.config(command=treeview.yview) + # treeview.configure(yscrollcommand=scrollbar.set) + # + # element.TKTreeview.pack(side=tk.LEFT, expand=True, padx=0, pady=0, fill='both') + # frame.pack(side=tk.LEFT, expand=True, padx=0, pady=0) + # if element.Tooltip is not None: + # element.TooltipObject = ToolTip(element.TKTreeview, text=element.Tooltip, + # timeout=DEFAULT_TOOLTIP_TIME) + # ------------------------- Tree element ------------------------- # + elif element_type == ELEM_TYPE_TREE: + pass + # frame = tk.Frame(tk_row_frame) + # + # height = element.NumRows + # if element.Justification == 'left': # justification + # anchor = tk.W + # elif element.Justification == 'right': + # anchor = tk.E + # else: + # anchor = tk.CENTER + # + # if element.ColumnsToDisplay is None: # Which cols to display + # displaycolumns = element.ColumnHeadings + # else: + # displaycolumns = [] + # for i, should_display in enumerate(element.ColumnsToDisplay): + # if should_display: + # displaycolumns.append(element.ColumnHeadings[i]) + # column_headings = element.ColumnHeadings + # # ------------- GET THE TREEVIEW WIDGET ------------- + # element.TKTreeview = ttk.Treeview(frame, columns=column_headings, + # displaycolumns=displaycolumns, show='tree headings', height=height, + # selectmode=element.SelectMode, ) + # treeview = element.TKTreeview + # for i, heading in enumerate(element.ColumnHeadings): # Configure cols + headings + # treeview.heading(heading, text=heading) + # if element.AutoSizeColumns: + # width = min(element.MaxColumnWidth, len(heading) + 1) + # else: + # try: + # width = element.ColumnWidths[i] + # except: + # width = element.DefaultColumnWidth + # treeview.column(heading, width=width * CharWidthInPixels(), anchor=anchor) + # + # def add_treeview_data(node): + # # print(f'Inserting {node.key} under parent {node.parent}') + # if node.key != '': + # treeview.insert(node.parent, 'end', node.key, text=node.text, values=node.values, + # open=element.ShowExpanded) + # for node in node.children: + # add_treeview_data(node) + # + # add_treeview_data(element.TreeData.root_node) + # treeview.column('#0', width=element.Col0Width * CharWidthInPixels(), anchor=anchor) + # # ----- configure colors ----- + # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + # ttk.Style().configure("Treeview", background=element.BackgroundColor, + # fieldbackground=element.BackgroundColor) + # if element.TextColor is not None and element.TextColor != COLOR_SYSTEM_DEFAULT: + # ttk.Style().configure("Treeview", foreground=element.TextColor) + # + # scrollbar = tk.Scrollbar(frame) + # scrollbar.pack(side=tk.RIGHT, fill='y') + # scrollbar.config(command=treeview.yview) + # treeview.configure(yscrollcommand=scrollbar.set) + # element.TKTreeview.pack(side=tk.LEFT, expand=True, padx=0, pady=0, fill='both') + # frame.pack(side=tk.LEFT, expand=True, padx=0, pady=0) + # treeview.bind("<>", element.treeview_selected) + # if element.Tooltip is not None: # tooltip + # element.TooltipObject = ToolTip(element.TKTreeview, text=element.Tooltip, + # timeout=DEFAULT_TOOLTIP_TIME) + # ------------------------- Separator element ------------------------- # + elif element_type == ELEM_TYPE_SEPARATOR: + pass + # separator = ttk.Separator(tk_row_frame, orient=element.Orientation, ) + # separator.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1], fill='both', expand=True) + # + # # ............................DONE WITH ROW pack the row of widgets ..........................# + # done with row, pack the row of widgets + # tk_row_frame.grid(row=row_num+2, sticky=tk.NW, padx=DEFAULT_MARGINS[0]) + # tk_row_frame.pack(side=tk.TOP, anchor='nw', padx=DEFAULT_MARGINS[0], expand=False) + # if form.BackgroundColor is not None and form.BackgroundColor != COLOR_SYSTEM_DEFAULT: + # tk_row_frame.configure(background=form.BackgroundColor) + # toplevel_form.TKroot.configure(padx=DEFAULT_MARGINS[0], pady=DEFAULT_MARGINS[1]) + if not type(containing_frame) == remi.gui.TabBox: + containing_frame.append(tk_row_frame) + return + + +def setup_remi_window(app:Window.MyApp, window:Window): + master_widget = remi.gui.VBox() + master_widget.style['justify-content'] = 'flex-start' + master_widget.style['align-items'] = 'baseline' + if window.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT): + master_widget.style['background-color'] = window.BackgroundColor + try: + PackFormIntoFrame(window, master_widget, window) + except: + print('* ERROR PACKING FORM *') + print(traceback.format_exc()) + + + if window.BackgroundImage: + master_widget.style['background-image'] = "url('{}')".format('/' + window.BackgroundImage) + # print(f'background info',self.master_widget.attributes['background-image'] ) + + if not window.DisableClose: + # add the following 3 lines to your app and the on_window_close method to make the console close automatically + tag = remi.gui.Tag(_type='script') + tag.add_child("javascript", """window.onunload=function(e){sendCallback('%s','%s');return "close?";};""" % ( + str(id(app)), "on_window_close")) + master_widget.add_child("onunloadevent", tag) + + if window.ReturnKeyboardEvents: + app.page.children['body'].onkeyup.connect(window.on_key_up) + if window.ReturnKeyDownEvents: + app.page.children['body'].onkeydown.connect(window.on_key_down) + + + # if window.WindowIcon: + # if type(window.WindowIcon) is bytes or len(window.WindowIcon) > 200: + # app.page.children['head'].set_icon_data( base64_data=str(window.WindowIcon), mimetype="image/gif" ) + # else: + # app.page.children['head'].set_icon_file("/res:{}".format(window.WindowIcon)) + # pass + # mimetype, encoding = mimetypes.guess_type(image_source) + # with open(image_source, 'rb') as f: + # data = f.read() + # b64 = base64.b64encode(data) + # b64_str = b64.decode("utf-8") + # image_string = "data:image/svg;base64,%s"%b64_str + # rpoint.set_image(image_string) + + + return master_widget + +# ----====----====----====----====----==== STARTUP TK ====----====----====----====----====----# +def StartupTK(window:Window): + global _my_windows + + + # print('Starting TK open Windows = {}'.format(ow)) + + _my_windows.Increment() + + # if not my_flex_form.Resizable: + # root.resizable(False, False) + + # if my_flex_form.KeepOnTop: + # root.wm_attributes("-topmost", 1) + # master = window.TKroot + # Set Title + # master.title(MyFlexForm.Title) + # master = 00000 + + InitializeResults(window) + + # Does all of the window setup, starting up Remi + # if no windows exist, start Remi thread which will call same setup_remi_window call as shown below + if len(Window.active_windows) == 0: + window.thread_id = threading.Thread(target=window.remi_thread, daemon=True) + window.thread_id.daemon = True + window.thread_id.start() + item = window.MessageQueue.get() # Get the layout complete message + Window.active_windows.append(window) + Window.App = window.App + else: + # print('Starting second page') + # margin 0px auto allows to center the app to the screen + # master_widget = remi.gui.VBox() + # master_widget.style['justify-content'] = 'flex-start' + # master_widget.style['align-items'] = 'baseline' + # if window.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT): + # master_widget.style['background-color'] = window.BackgroundColor + # PackFormIntoFrame(window, master_widget, window) + master_widget = setup_remi_window(Window.App, window) + window.master_widget = master_widget + Window.active_windows.append(window) + Window.App.set_root_widget(master_widget) + + return + +# ==============================_GetNumLinesNeeded ==# +# Helper function for determining how to wrap text # +# ===================================================# +def _GetNumLinesNeeded(text, max_line_width): + if max_line_width == 0: + return 1 + lines = text.split('\n') + num_lines = len(lines) # number of original lines of text + max_line_len = max([len(l) for l in lines]) # longest line + lines_used = [] + for L in lines: + lines_used.append(len(L) // max_line_width + (len(L) % max_line_width > 0)) # fancy math to round up + total_lines_needed = sum(lines_used) + return total_lines_needed + + +# ============================== PROGRESS METER ========================================== # + +def ConvertArgsToSingleString(*args): + max_line_total, width_used, total_lines, = 0, 0, 0 + single_line_message = '' + # loop through args and built a SINGLE string from them + for message in args: + # fancy code to check if string and convert if not is not need. Just always convert to string :-) + # if not isinstance(message, str): message = str(message) + message = str(message) + longest_line_len = max([len(l) for l in message.split('\n')]) + width_used = max(longest_line_len, width_used) + max_line_total = max(max_line_total, width_used) + lines_needed = _GetNumLinesNeeded(message, width_used) + total_lines += lines_needed + single_line_message += message + '\n' + return single_line_message, width_used, total_lines + + +# ============================== ProgressMeter =====# +# ===================================================# +def _ProgressMeter(title, max_value, *args, orientation=None, bar_color=(None, None), button_color=None, + size=DEFAULT_PROGRESS_BAR_SIZE, border_width=None, grab_anywhere=False): + ''' + Create and show a form on tbe caller's behalf. + :param title: + :param max_value: + :param args: ANY number of arguments the caller wants to display + :param orientation: + :param bar_color: + :param size: + :param Style: + :param StyleOffset: + :return: ProgressBar object that is in the form + ''' + local_orientation = DEFAULT_METER_ORIENTATION if orientation is None else orientation + local_border_width = DEFAULT_PROGRESS_BAR_BORDER_WIDTH if border_width is None else border_width + bar2 = ProgressBar(max_value, orientation=local_orientation, size=size, bar_color=bar_color, + border_width=local_border_width, relief=DEFAULT_PROGRESS_BAR_RELIEF) + form = Window(title, auto_size_text=True, grab_anywhere=grab_anywhere) + + # Form using a horizontal bar + if local_orientation[0].lower() == 'h': + single_line_message, width, height = ConvertArgsToSingleString(*args) + bar2.TextToDisplay = single_line_message + bar2.TextToDisplay = single_line_message + bar2.MaxValue = max_value + bar2.CurrentValue = 0 + bar_text = Text(single_line_message, size=(width, height + 3), auto_size_text=True) + form.AddRow(bar_text) + form.AddRow((bar2)) + form.AddRow((CloseButton('Cancel', button_color=button_color))) + else: + single_line_message, width, height = ConvertArgsToSingleString(*args) + bar2.TextToDisplay = single_line_message + bar2.MaxValue = max_value + bar2.CurrentValue = 0 + bar_text = Text(single_line_message, size=(width, height + 3), auto_size_text=True) + form.AddRow(bar2, bar_text) + form.AddRow((CloseButton('Cancel', button_color=button_color))) + + form.NonBlocking = True + form.Show(non_blocking=True) + return bar2, bar_text + + +# ============================== ProgressMeterUpdate =====# +def _ProgressMeterUpdate(bar, value, text_elem, *args): + ''' + Update the progress meter for a form + :param form: class ProgressBar + :param value: int + :return: True if not cancelled, OK....False if Error + ''' + global _my_windows + if bar == None: return False + if bar.BarExpired: return False + message, w, h = ConvertArgsToSingleString(*args) + text_elem.Update(message) + # bar.TextToDisplay = message + bar.CurrentValue = value + rc = bar.UpdateBar(value) + if value >= bar.MaxValue or not rc: + bar.BarExpired = True + bar.ParentForm._Close() + if rc: # if update was OK but bar expired, decrement num windows + _my_windows.Decrement() + if bar.ParentForm.RootNeedsDestroying: + try: + bar.ParentForm.TKroot.destroy() + # there is a bug with progress meters not decrementing the number of windows + # correctly when the X is used to close the window + # uncommenting this line fixes that problem, but causes a double-decrement when + # the cancel button is used... damned if you do, damned if you don't, so I'm choosing + # don't, as in don't decrement too many times. It's OK now to have a mismatch in + # number of windows because of the "hidden" master window. This ensures all windows + # will be toplevel. Sorry about the bug, but the user never sees any problems as a result + # _my_windows.Decrement() + except: + pass + bar.ParentForm.RootNeedsDestroying = False + return False + + return rc + + +# ============================== EASY PROGRESS METER ========================================== # +# class to hold the easy meter info (a global variable essentialy) +class EasyProgressMeterDataClass(): + def __init__(self, title='', current_value=1, max_value=10, start_time=None, stat_messages=()): + self.Title = title + self.CurrentValue = current_value + self.MaxValue = max_value + self.StartTime = start_time + self.StatMessages = stat_messages + self.ParentForm = None + self.MeterID = None + self.MeterText = None + + # =========================== COMPUTE PROGRESS STATS ======================# + def ComputeProgressStats(self): + utc = datetime.datetime.utcnow() + time_delta = utc - self.StartTime + total_seconds = time_delta.total_seconds() + if not total_seconds: + total_seconds = 1 + try: + time_per_item = total_seconds / self.CurrentValue + except: + time_per_item = 1 + seconds_remaining = (self.MaxValue - self.CurrentValue) * time_per_item + time_remaining = str(datetime.timedelta(seconds=seconds_remaining)) + time_remaining_short = (time_remaining).split(".")[0] + time_delta_short = str(time_delta).split(".")[0] + total_time = time_delta + datetime.timedelta(seconds=seconds_remaining) + total_time_short = str(total_time).split(".")[0] + self.StatMessages = [ + '{} of {}'.format(self.CurrentValue, self.MaxValue), + '{} %'.format(100 * self.CurrentValue // self.MaxValue), + '', + ' {:6.2f} Iterations per Second'.format(self.CurrentValue / total_seconds), + ' {:6.2f} Seconds per Iteration'.format(total_seconds / (self.CurrentValue if self.CurrentValue else 1)), + '', + '{} Elapsed Time'.format(time_delta_short), + '{} Time Remaining'.format(time_remaining_short), + '{} Estimated Total Time'.format(total_time_short)] + return + + +# ============================== EasyProgressMeter =====# +def EasyProgressMeter(title, current_value, max_value, *args, orientation=None, bar_color=(None, None), + button_color=None, size=DEFAULT_PROGRESS_BAR_SIZE, border_width=None): + ''' + A ONE-LINE progress meter. Add to your code where ever you need a meter. No need for a second + function call before your loop. You've got enough code to write! + :param title: Title will be shown on the window + :param current_value: Current count of your items + :param max_value: Max value your count will ever reach. This indicates it should be closed + :param args: VARIABLE number of arguements... you request it, we'll print it no matter what the item! + :param orientation: + :param bar_color: + :param size: + :param Style: + :param StyleOffset: + :return: False if should stop the meter + ''' + local_border_width = DEFAULT_PROGRESS_BAR_BORDER_WIDTH if not border_width else border_width + # STATIC VARIABLE! + # This is a very clever form of static variable using a function attribute + # If the variable doesn't yet exist, then it will create it and initialize with the 3rd parameter + EasyProgressMeter.Data = getattr(EasyProgressMeter, 'Data', EasyProgressMeterDataClass()) + # if no meter currently running + if EasyProgressMeter.Data.MeterID is None: # Starting a new meter + print( + "Please change your call of EasyProgressMeter to use OneLineProgressMeter. EasyProgressMeter will be removed soon") + if int(current_value) >= int(max_value): + return False + del (EasyProgressMeter.Data) + EasyProgressMeter.Data = EasyProgressMeterDataClass(title, 1, int(max_value), datetime.datetime.utcnow(), []) + EasyProgressMeter.Data.ComputeProgressStats() + message = "\n".join([line for line in EasyProgressMeter.Data.StatMessages]) + EasyProgressMeter.Data.MeterID, EasyProgressMeter.Data.MeterText = _ProgressMeter(title, int(max_value), + message, *args, + orientation=orientation, + bar_color=bar_color, + size=size, + button_color=button_color, + border_width=local_border_width) + EasyProgressMeter.Data.ParentForm = EasyProgressMeter.Data.MeterID.ParentForm + return True + # if exactly the same values as before, then ignore. + if EasyProgressMeter.Data.MaxValue == max_value and EasyProgressMeter.Data.CurrentValue == current_value: + return True + if EasyProgressMeter.Data.MaxValue != int(max_value): + EasyProgressMeter.Data.MeterID = None + EasyProgressMeter.Data.ParentForm = None + del (EasyProgressMeter.Data) + EasyProgressMeter.Data = EasyProgressMeterDataClass() # setup a new progress meter + return True # HAVE to return TRUE or else the new meter will thing IT is failing when it hasn't + EasyProgressMeter.Data.CurrentValue = int(current_value) + EasyProgressMeter.Data.MaxValue = int(max_value) + EasyProgressMeter.Data.ComputeProgressStats() + message = '' + for line in EasyProgressMeter.Data.StatMessages: + message = message + str(line) + '\n' + message = "\n".join(EasyProgressMeter.Data.StatMessages) + args = args + (message,) + rc = _ProgressMeterUpdate(EasyProgressMeter.Data.MeterID, current_value, + EasyProgressMeter.Data.MeterText, *args) + # if counter >= max then the progress meter is all done. Indicate none running + if current_value >= EasyProgressMeter.Data.MaxValue or not rc: + EasyProgressMeter.Data.MeterID = None + del (EasyProgressMeter.Data) + EasyProgressMeter.Data = EasyProgressMeterDataClass() # setup a new progress meter + return False # even though at the end, return True so don't cause error with the app + return rc # return whatever the update told us + + +def EasyProgressMeterCancel(title, *args): + EasyProgressMeter.EasyProgressMeterData = getattr(EasyProgressMeter, 'EasyProgressMeterData', + EasyProgressMeterDataClass()) + if EasyProgressMeter.EasyProgressMeterData.MeterID is not None: + # tell the normal meter update that we're at max value which will close the meter + rc = EasyProgressMeter(title, EasyProgressMeter.EasyProgressMeterData.MaxValue, + EasyProgressMeter.EasyProgressMeterData.MaxValue, ' *** CANCELLING ***', + 'Caller requested a cancel', *args) + return rc + return True + + +# global variable containing dictionary will all currently running one-line progress meters. +_one_line_progress_meters = {} + + +# ============================== OneLineProgressMeter =====# +def OneLineProgressMeter(title, current_value, max_value, key='OK for 1 meter', *args, orientation=None, bar_color=(None, None), + button_color=None, size=DEFAULT_PROGRESS_BAR_SIZE, border_width=None, grab_anywhere=False): + global _one_line_progress_meters + + local_border_width = DEFAULT_PROGRESS_BAR_BORDER_WIDTH if border_width is not None else border_width + try: + meter_data = _one_line_progress_meters[key] + except: # a new meater is starting + if int(current_value) >= int(max_value): # if already expired then it's an old meter, ignore + return False + meter_data = EasyProgressMeterDataClass(title, 1, int(max_value), datetime.datetime.utcnow(), []) + _one_line_progress_meters[key] = meter_data + meter_data.ComputeProgressStats() + message = "\n".join([line for line in meter_data.StatMessages]) + meter_data.MeterID, meter_data.MeterText = _ProgressMeter(title, int(max_value), message, *args, + orientation=orientation, bar_color=bar_color, + size=size, button_color=button_color, + border_width=local_border_width, + grab_anywhere=grab_anywhere) + meter_data.ParentForm = meter_data.MeterID.ParentForm + return True + + # if exactly the same values as before, then ignore, return success. + if meter_data.MaxValue == max_value and meter_data.CurrentValue == current_value: + return True + meter_data.CurrentValue = int(current_value) + meter_data.MaxValue = int(max_value) + meter_data.ComputeProgressStats() + message = '' + for line in meter_data.StatMessages: + message = message + str(line) + '\n' + message = "\n".join(meter_data.StatMessages) + args = args + (message,) + rc = _ProgressMeterUpdate(meter_data.MeterID, current_value, + meter_data.MeterText, *args) + # if counter >= max then the progress meter is all done. Indicate none running + if current_value >= meter_data.MaxValue or not rc: + del _one_line_progress_meters[key] + return False + return rc # return whatever the update told us + + +def OneLineProgressMeterCancel(key='OK for 1 meter'): + global _one_line_progress_meters + + try: + meter_data = _one_line_progress_meters[key] + except: # meter is already deleted + return + OneLineProgressMeter('', meter_data.MaxValue, meter_data.MaxValue, key=key) + + +# input is #RRGGBB +# output is #RRGGBB +def GetComplimentaryHex(color): + # strip the # from the beginning + color = color[1:] + # convert the string into hex + color = int(color, 16) + # invert the three bytes + # as good as substracting each of RGB component by 255(FF) + comp_color = 0xFFFFFF ^ color + # convert the color back to hex by prefixing a # + comp_color = "#%06X" % comp_color + return comp_color + + +# ======================== EasyPrint =====# +# ===================================================# +_easy_print_data = None # global variable... I'm cheating + + +class DebugWin(): + def __init__(self, size=(None, None), location=(None, None), font=None, no_titlebar=False, no_button=False, + grab_anywhere=False, keep_on_top=False): + # Show a form that's a running counter + win_size = size if size != (None, None) else DEFAULT_DEBUG_WINDOW_SIZE + self.window = Window('Debug Window', no_titlebar=no_titlebar, auto_size_text=True, location=location, + font=font or ('Courier New', 10), grab_anywhere=grab_anywhere, keep_on_top=keep_on_top) + self.output_element = Output(size=win_size) + if no_button: + self.layout = [[self.output_element]] + else: + self.layout = [ + [self.output_element], + [DummyButton('Quit')] + ] + self.window.AddRows(self.layout) + self.window.Read(timeout=0) # Show a non-blocking form, returns immediately + return + + def Print(self, *args, end=None, sep=None): + sepchar = sep if sep is not None else ' ' + endchar = end if end is not None else '\n' + + if self.window is None: # if window was destroyed already, just print + print(*args, sep=sepchar, end=endchar) + return + + event, values = self.window.Read(timeout=0) + if event == 'Quit' or event is None: + self.Close() + print(*args, sep=sepchar, end=endchar) + # Add extra check to see if the window was closed... if closed by X sometimes am not told + try: + state = self.window.TKroot.state() + except: + self.Close() + + def Close(self): + self.window.Close() + self.window = None + + +def PrintClose(): + EasyPrintClose() + + +def EasyPrint(*args, size=(None, None), end=None, sep=None, location=(None, None), font=None, no_titlebar=False, + no_button=False, grab_anywhere=False, keep_on_top=False): + global _easy_print_data + + if _easy_print_data is None: + _easy_print_data = DebugWin(size=size, location=location, font=font, no_titlebar=no_titlebar, + no_button=no_button, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top) + _easy_print_data.Print(*args, end=end, sep=sep) + + +Print = EasyPrint +eprint = EasyPrint + + +def EasyPrintClose(): + global _easy_print_data + if _easy_print_data is not None: + _easy_print_data.Close() + _easy_print_data = None + + +# d8b 888 +# Y8P 888 +# 888 +# .d8888b 88888b. 888d888 888 88888b. 888888 +# d88P" 888 "88b 888P" 888 888 "88b 888 +# 888 888 888 888 888 888 888 888 +# Y88b. 888 d88P 888 888 888 888 Y88b. +# "Y8888P 88888P" 888 888 888 888 "Y888 +# 888 +# 888 +# 888 + + +CPRINT_DESTINATION_WINDOW = None +CPRINT_DESTINATION_MULTILINE_ELMENT_KEY = None + +def cprint_set_output_destination(window, multiline_key): + """ + Sets up the color print (cprint) output destination + :param window: The window that the cprint call will route the output to + :type window: (Window) + :param multiline_key: Key for the Multiline Element where output will be sent + :type multiline_key: (Any) + :return: None + :rtype: None + """ + + global CPRINT_DESTINATION_WINDOW, CPRINT_DESTINATION_MULTILINE_ELMENT_KEY + + CPRINT_DESTINATION_WINDOW = window + CPRINT_DESTINATION_MULTILINE_ELMENT_KEY = multiline_key + + + +# def cprint(*args, **kwargs): +def cprint(*args, end=None, sep=' ', text_color=None, t=None, background_color=None, b=None, colors=None, c=None, window=None, key=None): + """ + Color print to a multiline element in a window of your choice. + Must have EITHER called cprint_set_output_destination prior to making this call so that the + window and element key can be saved and used here to route the output, OR used the window + and key parameters to the cprint function to specicy these items. + + args is a variable number of things you want to print. + + end - The end char to use just like print uses + sep - The separation character like print uses + text_color - The color of the text + key - overrides the previously defined Multiline key + window - overrides the previously defined window to output to + background_color - The color of the background + colors -(str, str) or str. A combined text/background color definition in a single parameter + + There are also "aliases" for text_color, background_color and colors (t, b, c) + t - An alias for color of the text (makes for shorter calls) + b - An alias for the background_color parameter + c - Tuple[str, str] - "shorthand" way of specifying color. (foreground, backgrouned) + c - str - can also be a string of the format "foreground on background" ("white on red") + + With the aliases it's possible to write the same print but in more compact ways: + cprint('This will print white text on red background', c=('white', 'red')) + cprint('This will print white text on red background', c='white on red') + cprint('This will print white text on red background', text_color='white', background_color='red') + cprint('This will print white text on red background', t='white', b='red') + + :param *args: stuff to output + :type *args: (Any) + :param text_color: Color of the text + :type text_color: (str) + :param background_color: The background color of the line + :type background_color: (str) + :param colors: Either a tuple or a string that has both the text and background colors + :type colors: (str) or Tuple[str, str] + :param t: Color of the text + :type t: (str) + :param b: The background color of the line + :type b: (str) + :param c: Either a tuple or a string that has both the text and background colors + :type c: (str) or Tuple[str, str] + :param end: end character + :type end: (str) + :param sep: separator character + :type sep: (str) + :param key: key of multiline to output to (if you want to override the one previously set) + :type key: (Any) + :param window: Window containing the multiline to output to (if you want to override the one previously set) + :type window: (Window) + :return: None + :rtype: None + """ + + destination_key = CPRINT_DESTINATION_MULTILINE_ELMENT_KEY if key is None else key + destination_window = window or CPRINT_DESTINATION_WINDOW + + if (destination_window is None and window is None) or (destination_key is None and key is None): + print('** Warning ** Attempting to perform a cprint without a valid window & key', + 'Will instead print on Console', + 'You can specify window and key in this cprint call, or set ahead of time using cprint_set_output_destination') + print(*args) + return + + kw_text_color = text_color or t + kw_background_color = background_color or b + dual_color = colors or c + try: + if isinstance(dual_color, tuple): + kw_text_color = dual_color[0] + kw_background_color = dual_color[1] + elif isinstance(dual_color, str): + kw_text_color = dual_color.split(' on ')[0] + kw_background_color = dual_color.split(' on ')[1] + except Exception as e: + print('* cprint warning * you messed up with color formatting', e) + + mline = destination_window.find_element(destination_key, silent_on_error=True) # type: Multiline + try: + # mline = destination_window[destination_key] # type: Multiline + if end is None: + mline.print(*args, text_color=kw_text_color, background_color=kw_background_color, end='', sep=sep) + mline.print('') + else: + mline.print(*args,text_color=kw_text_color, background_color=kw_background_color, end=end, sep=sep) + except Exception as e: + print('** cprint error trying to print to the multiline. Printing to console instead **', e) + print(*args, end=end, sep=sep) + + + +# ------------------------------------------------------------------------------------------------ # +# A print-like call that can be used to output to a multiline element as if it's an Output element # +# ------------------------------------------------------------------------------------------------ # +def _print_to_element(multiline_element, *args, end=None, sep=None, text_color=None, background_color=None, autoscroll=True): + """ + Print like Python normally prints except route the output to a multline element and also add colors if desired + + :param multiline_element: The multiline element to be output to + :type multiline_element: Multiline or MultilineOutput + :param args: The arguments to print + :type args: List[Any] + :param end: The end char to use just like print uses + :type end: (str) + :param sep: The separation character like print uses + :type sep: (str) + :param text_color: color of the text + :type text_color: (str) + :param background_color: The background color of the line + :type background_color: (str) + :param autoscroll: If True (the default), the element will scroll to bottom after updating + :type autoscroll: Bool + """ + end_str = str(end) if end is not None else '\n' + sep_str = str(sep) if sep is not None else ' ' + + outstring = '' + num_args = len(args) + for i, arg in enumerate(args): + outstring += str(arg) + if i != num_args-1: + outstring += sep_str + outstring += end_str + + multiline_element.update(outstring, append=True, text_color=text_color, background_color=background_color, autoscroll=autoscroll) + + + +# ======================== Scrolled Text Box =====# +# ===================================================# +def PopupScrolled(*args, button_color=None, yes_no=False, auto_close=False, auto_close_duration=None, + size=(None, None)): + if not args: return + width, height = size + width = width if width else MESSAGE_BOX_LINE_WIDTH + form = Window(args[0], auto_size_text=True, button_color=button_color, auto_close=auto_close, + auto_close_duration=auto_close_duration) + max_line_total, max_line_width, total_lines, height_computed = 0, 0, 0, 0 + complete_output = '' + for message in args: + # fancy code to check if string and convert if not is not need. Just always convert to string :-) + # if not isinstance(message, str): message = str(message) + message = str(message) + longest_line_len = max([len(l) for l in message.split('\n')]) + width_used = min(longest_line_len, width) + max_line_total = max(max_line_total, width_used) + max_line_width = width + lines_needed = _GetNumLinesNeeded(message, width_used) + height_computed += lines_needed + complete_output += message + '\n' + total_lines += lines_needed + height_computed = MAX_SCROLLED_TEXT_BOX_HEIGHT if height_computed > MAX_SCROLLED_TEXT_BOX_HEIGHT else height_computed + if height: + height_computed = height + form.AddRow(Multiline(complete_output, size=(max_line_width, height_computed))) + pad = max_line_total - 15 if max_line_total > 15 else 1 + # show either an OK or Yes/No depending on paramater + if yes_no: + form.AddRow(Text('', size=(pad, 1), auto_size_text=False), Yes(), No()) + button, values = form.Read() + return button + else: + form.AddRow(Text('', size=(pad, 1), auto_size_text=False), Button('OK', size=(5, 1), button_color=button_color)) + button, values = form.Read() + form.Close() + return button + + +ScrolledTextBox = PopupScrolled + + +# ============================== SetGlobalIcon ======# +# Sets the icon to be used by default # +# ===================================================# +def SetGlobalIcon(icon): + global _my_windows + + try: + with open(icon, 'r') as icon_file: + pass + except: + raise FileNotFoundError + _my_windows.user_defined_icon = icon + return True + + +# ============================== SetOptions =========# +# Sets the icon to be used by default # +# ===================================================# +def SetOptions(icon=None, button_color=None, element_size=(None, None), button_element_size=(None, None), + margins=(None, None), + element_padding=(None, None), auto_size_text=None, auto_size_buttons=None, font=None, border_width=None, + slider_border_width=None, slider_relief=None, slider_orientation=None, + autoclose_time=None, message_box_line_width=None, + progress_meter_border_depth=None, progress_meter_style=None, + progress_meter_relief=None, progress_meter_color=None, progress_meter_size=None, + text_justification=None, background_color=None, element_background_color=None, + text_element_background_color=None, input_elements_background_color=None, input_text_color=None, + scrollbar_color=None, text_color=None, element_text_color=None, debug_win_size=(None, None), + window_location=(None, None), + tooltip_time=None): + global DEFAULT_ELEMENT_SIZE + global DEFAULT_BUTTON_ELEMENT_SIZE + global DEFAULT_MARGINS # Margins for each LEFT/RIGHT margin is first term + global DEFAULT_ELEMENT_PADDING # Padding between elements (row, col) in pixels + global DEFAULT_AUTOSIZE_TEXT + global DEFAULT_AUTOSIZE_BUTTONS + global DEFAULT_FONT + global DEFAULT_BORDER_WIDTH + global DEFAULT_AUTOCLOSE_TIME + global DEFAULT_BUTTON_COLOR + global MESSAGE_BOX_LINE_WIDTH + global DEFAULT_PROGRESS_BAR_BORDER_WIDTH + global DEFAULT_PROGRESS_BAR_STYLE + global DEFAULT_PROGRESS_BAR_RELIEF + global DEFAULT_PROGRESS_BAR_COLOR + global DEFAULT_PROGRESS_BAR_SIZE + global DEFAULT_TEXT_JUSTIFICATION + global DEFAULT_DEBUG_WINDOW_SIZE + global DEFAULT_SLIDER_BORDER_WIDTH + global DEFAULT_SLIDER_RELIEF + global DEFAULT_SLIDER_ORIENTATION + global DEFAULT_BACKGROUND_COLOR + global DEFAULT_INPUT_ELEMENTS_COLOR + global DEFAULT_ELEMENT_BACKGROUND_COLOR + global DEFAULT_TEXT_ELEMENT_BACKGROUND_COLOR + global DEFAULT_SCROLLBAR_COLOR + global DEFAULT_TEXT_COLOR + global DEFAULT_WINDOW_LOCATION + global DEFAULT_ELEMENT_TEXT_COLOR + global DEFAULT_INPUT_TEXT_COLOR + global DEFAULT_TOOLTIP_TIME + global _my_windows + + if icon: + try: + with open(icon, 'r') as icon_file: + pass + except: + raise FileNotFoundError + _my_windows.user_defined_icon = icon + + if button_color != None: + DEFAULT_BUTTON_COLOR = button_color + + if element_size != (None, None): + DEFAULT_ELEMENT_SIZE = element_size + + if button_element_size != (None, None): + DEFAULT_BUTTON_ELEMENT_SIZE = button_element_size + + if margins != (None, None): + DEFAULT_MARGINS = margins + + if element_padding != (None, None): + DEFAULT_ELEMENT_PADDING = element_padding + + if auto_size_text != None: + DEFAULT_AUTOSIZE_TEXT = auto_size_text + + if auto_size_buttons != None: + DEFAULT_AUTOSIZE_BUTTONS = auto_size_buttons + + if font != None: + DEFAULT_FONT = font + + if border_width != None: + DEFAULT_BORDER_WIDTH = border_width + + if autoclose_time != None: + DEFAULT_AUTOCLOSE_TIME = autoclose_time + + if message_box_line_width != None: + MESSAGE_BOX_LINE_WIDTH = message_box_line_width + + if progress_meter_border_depth != None: + DEFAULT_PROGRESS_BAR_BORDER_WIDTH = progress_meter_border_depth + + if progress_meter_style != None: + DEFAULT_PROGRESS_BAR_STYLE = progress_meter_style + + if progress_meter_relief != None: + DEFAULT_PROGRESS_BAR_RELIEF = progress_meter_relief + + if progress_meter_color != None: + DEFAULT_PROGRESS_BAR_COLOR = progress_meter_color + + if progress_meter_size != None: + DEFAULT_PROGRESS_BAR_SIZE = progress_meter_size + + if slider_border_width != None: + DEFAULT_SLIDER_BORDER_WIDTH = slider_border_width + + if slider_orientation != None: + DEFAULT_SLIDER_ORIENTATION = slider_orientation + + if slider_relief != None: + DEFAULT_SLIDER_RELIEF = slider_relief + + if text_justification != None: + DEFAULT_TEXT_JUSTIFICATION = text_justification + + if background_color != None: + DEFAULT_BACKGROUND_COLOR = background_color + + if text_element_background_color != None: + DEFAULT_TEXT_ELEMENT_BACKGROUND_COLOR = text_element_background_color + + if input_elements_background_color != None: + DEFAULT_INPUT_ELEMENTS_COLOR = input_elements_background_color + + if element_background_color != None: + DEFAULT_ELEMENT_BACKGROUND_COLOR = element_background_color + + if window_location != (None, None): + DEFAULT_WINDOW_LOCATION = window_location + + if debug_win_size != (None, None): + DEFAULT_DEBUG_WINDOW_SIZE = debug_win_size + + if text_color != None: + DEFAULT_TEXT_COLOR = text_color + + if scrollbar_color != None: + DEFAULT_SCROLLBAR_COLOR = scrollbar_color + + if element_text_color != None: + DEFAULT_ELEMENT_TEXT_COLOR = element_text_color + + if input_text_color is not None: + DEFAULT_INPUT_TEXT_COLOR = input_text_color + + if tooltip_time is not None: + DEFAULT_TOOLTIP_TIME = tooltip_time + + return True + + + +# ----------------------------------------------------------------- # + +# .########.##.....##.########.##.....##.########..######. +# ....##....##.....##.##.......###...###.##.......##....## +# ....##....##.....##.##.......####.####.##.......##...... +# ....##....#########.######...##.###.##.######....######. +# ....##....##.....##.##.......##.....##.##.............## +# ....##....##.....##.##.......##.....##.##.......##....## +# ....##....##.....##.########.##.....##.########..######. + +# ----------------------------------------------------------------- # + +# The official Theme code + +#################### ChangeLookAndFeel ####################### +# Predefined settings that will change the colors and styles # +# of the elements. # +############################################################## +LOOK_AND_FEEL_TABLE = {'SystemDefault': + {'BACKGROUND': COLOR_SYSTEM_DEFAULT, + 'TEXT': COLOR_SYSTEM_DEFAULT, + 'INPUT': COLOR_SYSTEM_DEFAULT, + 'TEXT_INPUT': COLOR_SYSTEM_DEFAULT, + 'SCROLL': COLOR_SYSTEM_DEFAULT, + 'BUTTON': OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR, + 'PROGRESS': COLOR_SYSTEM_DEFAULT, + 'BORDER': 1, 'SLIDER_DEPTH': 1, + 'PROGRESS_DEPTH': 0}, + + 'SystemDefaultForReal': + {'BACKGROUND': COLOR_SYSTEM_DEFAULT, + 'TEXT': COLOR_SYSTEM_DEFAULT, + 'INPUT': COLOR_SYSTEM_DEFAULT, + 'TEXT_INPUT': COLOR_SYSTEM_DEFAULT, + 'SCROLL': COLOR_SYSTEM_DEFAULT, + 'BUTTON': COLOR_SYSTEM_DEFAULT, + 'PROGRESS': COLOR_SYSTEM_DEFAULT, + 'BORDER': 1, 'SLIDER_DEPTH': 1, + 'PROGRESS_DEPTH': 0}, + + 'SystemDefault1': + {'BACKGROUND': COLOR_SYSTEM_DEFAULT, + 'TEXT': COLOR_SYSTEM_DEFAULT, + 'INPUT': COLOR_SYSTEM_DEFAULT, + 'TEXT_INPUT': COLOR_SYSTEM_DEFAULT, + 'SCROLL': COLOR_SYSTEM_DEFAULT, + 'BUTTON': COLOR_SYSTEM_DEFAULT, + 'PROGRESS': COLOR_SYSTEM_DEFAULT, + 'BORDER': 1, 'SLIDER_DEPTH': 1, + 'PROGRESS_DEPTH': 0}, + + 'Material1': {'BACKGROUND': '#E3F2FD', + 'TEXT': '#000000', + 'INPUT': '#86A8FF', + 'TEXT_INPUT': '#000000', + 'SCROLL': '#86A8FF', + 'BUTTON': ('#FFFFFF', '#5079D3'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 0, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'ACCENT1': '#FF0266', + 'ACCENT2': '#FF5C93', + 'ACCENT3': '#C5003C'}, + + 'Material2': {'BACKGROUND': '#FAFAFA', + 'TEXT': '#000000', + 'INPUT': '#004EA1', + 'TEXT_INPUT': '#FFFFFF', + 'SCROLL': '#5EA7FF', + 'BUTTON': ('#FFFFFF', '#0079D3'), # based on Reddit color + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 0, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'ACCENT1': '#FF0266', + 'ACCENT2': '#FF5C93', + 'ACCENT3': '#C5003C'}, + + 'Reddit': {'BACKGROUND': '#ffffff', + 'TEXT': '#1a1a1b', + 'INPUT': '#dae0e6', + 'TEXT_INPUT': '#222222', + 'SCROLL': '#a5a4a4', + 'BUTTON': ('#FFFFFF', '#0079d3'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'ACCENT1': '#ff5414', + 'ACCENT2': '#33a8ff', + 'ACCENT3': '#dbf0ff'}, + + 'Topanga': {'BACKGROUND': '#282923', + 'TEXT': '#E7DB74', + 'INPUT': '#393a32', + 'TEXT_INPUT': '#E7C855', + 'SCROLL': '#E7C855', + 'BUTTON': ('#E7C855', '#284B5A'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'ACCENT1': '#c15226', + 'ACCENT2': '#7a4d5f', + 'ACCENT3': '#889743'}, + + 'GreenTan': {'BACKGROUND': '#9FB8AD', + 'TEXT': COLOR_SYSTEM_DEFAULT, + 'INPUT': '#F7F3EC', 'TEXT_INPUT': '#000000', + 'SCROLL': '#F7F3EC', + 'BUTTON': ('#FFFFFF', '#475841'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'Dark': {'BACKGROUND': '#404040', + 'TEXT': '#FFFFFF', + 'INPUT': '#4D4D4D', + 'TEXT_INPUT': '#FFFFFF', + 'SCROLL': '#707070', + 'BUTTON': ('#FFFFFF', '#004F00'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'LightGreen': {'BACKGROUND': '#B7CECE', + 'TEXT': '#000000', + 'INPUT': '#FDFFF7', + 'TEXT_INPUT': '#000000', + 'SCROLL': '#FDFFF7', + 'BUTTON': ('#FFFFFF', '#658268'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'ACCENT1': '#76506d', + 'ACCENT2': '#5148f1', + 'ACCENT3': '#0a1c84', + 'PROGRESS_DEPTH': 0}, + + 'Dark2': {'BACKGROUND': '#404040', + 'TEXT': '#FFFFFF', + 'INPUT': '#FFFFFF', + 'TEXT_INPUT': '#000000', + 'SCROLL': '#707070', + 'BUTTON': ('#FFFFFF', '#004F00'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'Black': {'BACKGROUND': '#000000', + 'TEXT': '#FFFFFF', + 'INPUT': '#4D4D4D', + 'TEXT_INPUT': '#FFFFFF', + 'SCROLL': '#707070', + 'BUTTON': ('#000000', '#FFFFFF'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'Tan': {'BACKGROUND': '#fdf6e3', + 'TEXT': '#268bd1', + 'INPUT': '#eee8d5', + 'TEXT_INPUT': '#6c71c3', + 'SCROLL': '#eee8d5', + 'BUTTON': ('#FFFFFF', '#063542'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'TanBlue': {'BACKGROUND': '#e5dece', + 'TEXT': '#063289', + 'INPUT': '#f9f8f4', + 'TEXT_INPUT': '#242834', + 'SCROLL': '#eee8d5', + 'BUTTON': ('#FFFFFF', '#063289'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'DarkTanBlue': {'BACKGROUND': '#242834', + 'TEXT': '#dfe6f8', + 'INPUT': '#97755c', + 'TEXT_INPUT': '#FFFFFF', + 'SCROLL': '#a9afbb', + 'BUTTON': ('#FFFFFF', '#063289'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'DarkAmber': {'BACKGROUND': '#2c2825', + 'TEXT': '#fdcb52', + 'INPUT': '#705e52', + 'TEXT_INPUT': '#fdcb52', + 'SCROLL': '#705e52', + 'BUTTON': ('#000000', '#fdcb52'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'DarkBlue': {'BACKGROUND': '#1a2835', + 'TEXT': '#d1ecff', + 'INPUT': '#335267', + 'TEXT_INPUT': '#acc2d0', + 'SCROLL': '#1b6497', + 'BUTTON': ('#000000', '#fafaf8'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'Reds': {'BACKGROUND': '#280001', + 'TEXT': '#FFFFFF', + 'INPUT': '#d8d584', + 'TEXT_INPUT': '#000000', + 'SCROLL': '#763e00', + 'BUTTON': ('#000000', '#daad28'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'Green': {'BACKGROUND': '#82a459', + 'TEXT': '#000000', + 'INPUT': '#d8d584', + 'TEXT_INPUT': '#000000', + 'SCROLL': '#e3ecf3', + 'BUTTON': ('#FFFFFF', '#517239'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'BluePurple': {'BACKGROUND': '#A5CADD', + 'TEXT': '#6E266E', + 'INPUT': '#E0F5FF', + 'TEXT_INPUT': '#000000', + 'SCROLL': '#E0F5FF', + 'BUTTON': ('#FFFFFF', '#303952'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'Purple': {'BACKGROUND': '#B0AAC2', + 'TEXT': '#000000', + 'INPUT': '#F2EFE8', + 'SCROLL': '#F2EFE8', + 'TEXT_INPUT': '#000000', + 'BUTTON': ('#000000', '#C2D4D8'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'BlueMono': {'BACKGROUND': '#AAB6D3', + 'TEXT': '#000000', + 'INPUT': '#F1F4FC', + 'SCROLL': '#F1F4FC', + 'TEXT_INPUT': '#000000', + 'BUTTON': ('#FFFFFF', '#7186C7'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'GreenMono': {'BACKGROUND': '#A8C1B4', + 'TEXT': '#000000', + 'INPUT': '#DDE0DE', + 'SCROLL': '#E3E3E3', + 'TEXT_INPUT': '#000000', + 'BUTTON': ('#FFFFFF', '#6D9F85'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'BrownBlue': {'BACKGROUND': '#64778d', + 'TEXT': '#FFFFFF', + 'INPUT': '#f0f3f7', + 'SCROLL': '#A6B2BE', + 'TEXT_INPUT': '#000000', + 'BUTTON': ('#FFFFFF', '#283b5b'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'BrightColors': {'BACKGROUND': '#b4ffb4', + 'TEXT': '#000000', + 'INPUT': '#ffff64', + 'SCROLL': '#ffb482', + 'TEXT_INPUT': '#000000', + 'BUTTON': ('#000000', '#ffa0dc'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'NeutralBlue': {'BACKGROUND': '#92aa9d', + 'TEXT': '#000000', + 'INPUT': '#fcfff6', + 'SCROLL': '#fcfff6', + 'TEXT_INPUT': '#000000', + 'BUTTON': ('#000000', '#d0dbbd'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'Kayak': {'BACKGROUND': '#a7ad7f', + 'TEXT': '#000000', + 'INPUT': '#e6d3a8', + 'SCROLL': '#e6d3a8', + 'TEXT_INPUT': '#000000', + 'BUTTON': ('#FFFFFF', '#5d907d'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'SandyBeach': {'BACKGROUND': '#efeccb', + 'TEXT': '#012f2f', + 'INPUT': '#e6d3a8', + 'SCROLL': '#e6d3a8', + 'TEXT_INPUT': '#012f2f', + 'BUTTON': ('#FFFFFF', '#046380'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'TealMono': {'BACKGROUND': '#a8cfdd', + 'TEXT': '#000000', + 'INPUT': '#dfedf2', + 'SCROLL': '#dfedf2', + 'TEXT_INPUT': '#000000', + 'BUTTON': ('#FFFFFF', '#183440'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + ################################## Renamed Original Themes ################################## + 'Default': # plain gray but blue buttons + {'BACKGROUND': COLOR_SYSTEM_DEFAULT, + 'TEXT': COLOR_SYSTEM_DEFAULT, + 'INPUT': COLOR_SYSTEM_DEFAULT, + 'TEXT_INPUT': COLOR_SYSTEM_DEFAULT, + 'SCROLL': COLOR_SYSTEM_DEFAULT, + 'BUTTON': OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR, + 'PROGRESS': COLOR_SYSTEM_DEFAULT, + 'BORDER': 1, 'SLIDER_DEPTH': 1, + 'PROGRESS_DEPTH': 0}, + + 'Default1': # everything is gray + {'BACKGROUND': COLOR_SYSTEM_DEFAULT, + 'TEXT': COLOR_SYSTEM_DEFAULT, + 'INPUT': COLOR_SYSTEM_DEFAULT, + 'TEXT_INPUT': COLOR_SYSTEM_DEFAULT, + 'SCROLL': COLOR_SYSTEM_DEFAULT, + 'BUTTON': COLOR_SYSTEM_DEFAULT, + 'PROGRESS': COLOR_SYSTEM_DEFAULT, + 'BORDER': 1, 'SLIDER_DEPTH': 1, + 'PROGRESS_DEPTH': 0}, + + 'DefaultNoMoreNagging': # a duplicate of "Default" for users that are tired of the nag screen + {'BACKGROUND': COLOR_SYSTEM_DEFAULT, + 'TEXT': COLOR_SYSTEM_DEFAULT, + 'INPUT': COLOR_SYSTEM_DEFAULT, + 'TEXT_INPUT': COLOR_SYSTEM_DEFAULT, + 'SCROLL': COLOR_SYSTEM_DEFAULT, + 'BUTTON': OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR, + 'PROGRESS': COLOR_SYSTEM_DEFAULT, + 'BORDER': 1, 'SLIDER_DEPTH': 1, + 'PROGRESS_DEPTH': 0}, + + 'LightBlue': {'BACKGROUND': '#E3F2FD', + 'TEXT': '#000000', + 'INPUT': '#86A8FF', + 'TEXT_INPUT': '#000000', + 'SCROLL': '#86A8FF', + 'BUTTON': ('#FFFFFF', '#5079D3'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 0, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'ACCENT1': '#FF0266', + 'ACCENT2': '#FF5C93', + 'ACCENT3': '#C5003C'}, + + 'LightGrey': {'BACKGROUND': '#FAFAFA', + 'TEXT': '#000000', + 'INPUT': '#004EA1', + 'TEXT_INPUT': '#FFFFFF', + 'SCROLL': '#5EA7FF', + 'BUTTON': ('#FFFFFF', '#0079D3'), # based on Reddit color + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 0, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'ACCENT1': '#FF0266', + 'ACCENT2': '#FF5C93', + 'ACCENT3': '#C5003C'}, + + 'LightGrey1': {'BACKGROUND': '#ffffff', + 'TEXT': '#1a1a1b', + 'INPUT': '#dae0e6', + 'TEXT_INPUT': '#222222', + 'SCROLL': '#a5a4a4', + 'BUTTON': ('#FFFFFF', '#0079d3'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'ACCENT1': '#ff5414', + 'ACCENT2': '#33a8ff', + 'ACCENT3': '#dbf0ff'}, + + 'DarkBrown': {'BACKGROUND': '#282923', + 'TEXT': '#E7DB74', + 'INPUT': '#393a32', + 'TEXT_INPUT': '#E7C855', + 'SCROLL': '#E7C855', + 'BUTTON': ('#E7C855', '#284B5A'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'ACCENT1': '#c15226', + 'ACCENT2': '#7a4d5f', + 'ACCENT3': '#889743'}, + + 'LightGreen1': {'BACKGROUND': '#9FB8AD', + 'TEXT': COLOR_SYSTEM_DEFAULT, + 'INPUT': '#F7F3EC', 'TEXT_INPUT': '#000000', + 'SCROLL': '#F7F3EC', + 'BUTTON': ('#FFFFFF', '#475841'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'DarkGrey': {'BACKGROUND': '#404040', + 'TEXT': '#FFFFFF', + 'INPUT': '#4D4D4D', + 'TEXT_INPUT': '#FFFFFF', + 'SCROLL': '#707070', + 'BUTTON': ('#FFFFFF', '#004F00'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'LightGreen2': {'BACKGROUND': '#B7CECE', + 'TEXT': '#000000', + 'INPUT': '#FDFFF7', + 'TEXT_INPUT': '#000000', + 'SCROLL': '#FDFFF7', + 'BUTTON': ('#FFFFFF', '#658268'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'ACCENT1': '#76506d', + 'ACCENT2': '#5148f1', + 'ACCENT3': '#0a1c84', + 'PROGRESS_DEPTH': 0}, + + 'DarkGrey1': {'BACKGROUND': '#404040', + 'TEXT': '#FFFFFF', + 'INPUT': '#FFFFFF', + 'TEXT_INPUT': '#000000', + 'SCROLL': '#707070', + 'BUTTON': ('#FFFFFF', '#004F00'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'DarkBlack': {'BACKGROUND': '#000000', + 'TEXT': '#FFFFFF', + 'INPUT': '#4D4D4D', + 'TEXT_INPUT': '#FFFFFF', + 'SCROLL': '#707070', + 'BUTTON': ('#000000', '#FFFFFF'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'LightBrown': {'BACKGROUND': '#fdf6e3', + 'TEXT': '#268bd1', + 'INPUT': '#eee8d5', + 'TEXT_INPUT': '#6c71c3', + 'SCROLL': '#eee8d5', + 'BUTTON': ('#FFFFFF', '#063542'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'LightBrown1': {'BACKGROUND': '#e5dece', + 'TEXT': '#063289', + 'INPUT': '#f9f8f4', + 'TEXT_INPUT': '#242834', + 'SCROLL': '#eee8d5', + 'BUTTON': ('#FFFFFF', '#063289'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'DarkBlue1': {'BACKGROUND': '#242834', + 'TEXT': '#dfe6f8', + 'INPUT': '#97755c', + 'TEXT_INPUT': '#FFFFFF', + 'SCROLL': '#a9afbb', + 'BUTTON': ('#FFFFFF', '#063289'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'DarkBrown1': {'BACKGROUND': '#2c2825', + 'TEXT': '#fdcb52', + 'INPUT': '#705e52', + 'TEXT_INPUT': '#fdcb52', + 'SCROLL': '#705e52', + 'BUTTON': ('#000000', '#fdcb52'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'DarkBlue2': {'BACKGROUND': '#1a2835', + 'TEXT': '#d1ecff', + 'INPUT': '#335267', + 'TEXT_INPUT': '#acc2d0', + 'SCROLL': '#1b6497', + 'BUTTON': ('#000000', '#fafaf8'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'DarkBrown2': {'BACKGROUND': '#280001', + 'TEXT': '#FFFFFF', + 'INPUT': '#d8d584', + 'TEXT_INPUT': '#000000', + 'SCROLL': '#763e00', + 'BUTTON': ('#000000', '#daad28'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'DarkGreen': {'BACKGROUND': '#82a459', + 'TEXT': '#000000', + 'INPUT': '#d8d584', + 'TEXT_INPUT': '#000000', + 'SCROLL': '#e3ecf3', + 'BUTTON': ('#FFFFFF', '#517239'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'LightBlue1': {'BACKGROUND': '#A5CADD', + 'TEXT': '#6E266E', + 'INPUT': '#E0F5FF', + 'TEXT_INPUT': '#000000', + 'SCROLL': '#E0F5FF', + 'BUTTON': ('#FFFFFF', '#303952'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'LightPurple': {'BACKGROUND': '#B0AAC2', + 'TEXT': '#000000', + 'INPUT': '#F2EFE8', + 'SCROLL': '#F2EFE8', + 'TEXT_INPUT': '#000000', + 'BUTTON': ('#000000', '#C2D4D8'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'LightBlue2': {'BACKGROUND': '#AAB6D3', + 'TEXT': '#000000', + 'INPUT': '#F1F4FC', + 'SCROLL': '#F1F4FC', + 'TEXT_INPUT': '#000000', + 'BUTTON': ('#FFFFFF', '#7186C7'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'LightGreen3': {'BACKGROUND': '#A8C1B4', + 'TEXT': '#000000', + 'INPUT': '#DDE0DE', + 'SCROLL': '#E3E3E3', + 'TEXT_INPUT': '#000000', + 'BUTTON': ('#FFFFFF', '#6D9F85'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'DarkBlue3': {'BACKGROUND': '#64778d', + 'TEXT': '#FFFFFF', + 'INPUT': '#f0f3f7', + 'SCROLL': '#A6B2BE', + 'TEXT_INPUT': '#000000', + 'BUTTON': ('#FFFFFF', '#283b5b'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'LightGreen4': {'BACKGROUND': '#b4ffb4', + 'TEXT': '#000000', + 'INPUT': '#ffff64', + 'SCROLL': '#ffb482', + 'TEXT_INPUT': '#000000', + 'BUTTON': ('#000000', '#ffa0dc'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'LightGreen5': {'BACKGROUND': '#92aa9d', + 'TEXT': '#000000', + 'INPUT': '#fcfff6', + 'SCROLL': '#fcfff6', + 'TEXT_INPUT': '#000000', + 'BUTTON': ('#000000', '#d0dbbd'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'LightBrown2': {'BACKGROUND': '#a7ad7f', + 'TEXT': '#000000', + 'INPUT': '#e6d3a8', + 'SCROLL': '#e6d3a8', + 'TEXT_INPUT': '#000000', + 'BUTTON': ('#FFFFFF', '#5d907d'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'LightBrown3': {'BACKGROUND': '#efeccb', + 'TEXT': '#012f2f', + 'INPUT': '#e6d3a8', + 'SCROLL': '#e6d3a8', + 'TEXT_INPUT': '#012f2f', + 'BUTTON': ('#FFFFFF', '#046380'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'LightBlue3': {'BACKGROUND': '#a8cfdd', + 'TEXT': '#000000', + 'INPUT': '#dfedf2', + 'SCROLL': '#dfedf2', + 'TEXT_INPUT': '#000000', + 'BUTTON': ('#FFFFFF', '#183440'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + ################################## End Renamed Original Themes ################################## + + # + 'LightBrown4': {'BACKGROUND': '#d7c79e', 'TEXT': '#a35638', 'INPUT': '#9dab86', 'TEXT_INPUT': '#000000', 'SCROLL': '#a35638', + 'BUTTON': ('#FFFFFF', '#a35638'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#a35638', '#9dab86', '#e08f62', '#d7c79e'], }, + 'DarkTeal': {'BACKGROUND': '#003f5c', 'TEXT': '#fb5b5a', 'INPUT': '#bc4873', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#bc4873', + 'BUTTON': ('#FFFFFF', '#fb5b5a'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#003f5c', '#472b62', '#bc4873', '#fb5b5a'], }, + 'DarkPurple': {'BACKGROUND': '#472b62', 'TEXT': '#fb5b5a', 'INPUT': '#bc4873', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#bc4873', + 'BUTTON': ('#FFFFFF', '#472b62'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#003f5c', '#472b62', '#bc4873', '#fb5b5a'], }, + 'LightGreen6': {'BACKGROUND': '#eafbea', 'TEXT': '#1f6650', 'INPUT': '#6f9a8d', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#1f6650', + 'BUTTON': ('#FFFFFF', '#1f6650'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#1f6650', '#6f9a8d', '#ea5e5e', '#eafbea'], }, + 'DarkGrey2': {'BACKGROUND': '#2b2b28', 'TEXT': '#f8f8f8', 'INPUT': '#f1d6ab', 'TEXT_INPUT': '#000000', 'SCROLL': '#f1d6ab', + 'BUTTON': ('#2b2b28', '#e3b04b'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#2b2b28', '#e3b04b', '#f1d6ab', '#f8f8f8'], }, + 'LightBrown6': {'BACKGROUND': '#f9b282', 'TEXT': '#8f4426', 'INPUT': '#de6b35', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#8f4426', + 'BUTTON': ('#FFFFFF', '#8f4426'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#8f4426', '#de6b35', '#64ccda', '#f9b282'], }, + 'DarkTeal1': {'BACKGROUND': '#396362', 'TEXT': '#ffe7d1', 'INPUT': '#f6c89f', 'TEXT_INPUT': '#000000', 'SCROLL': '#f6c89f', + 'BUTTON': ('#ffe7d1', '#4b8e8d'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#396362', '#4b8e8d', '#f6c89f', '#ffe7d1'], }, + 'LightBrown7': {'BACKGROUND': '#f6c89f', 'TEXT': '#396362', 'INPUT': '#4b8e8d', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#396362', + 'BUTTON': ('#FFFFFF', '#396362'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#396362', '#4b8e8d', '#f6c89f', '#ffe7d1'], }, + 'DarkPurple1': {'BACKGROUND': '#0c093c', 'TEXT': '#fad6d6', 'INPUT': '#eea5f6', 'TEXT_INPUT': '#000000', 'SCROLL': '#eea5f6', + 'BUTTON': ('#FFFFFF', '#df42d1'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#0c093c', '#df42d1', '#eea5f6', '#fad6d6'], }, + 'DarkGrey3': {'BACKGROUND': '#211717', 'TEXT': '#dfddc7', 'INPUT': '#f58b54', 'TEXT_INPUT': '#000000', 'SCROLL': '#f58b54', + 'BUTTON': ('#dfddc7', '#a34a28'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#211717', '#a34a28', '#f58b54', '#dfddc7'], }, + 'LightBrown8': {'BACKGROUND': '#dfddc7', 'TEXT': '#211717', 'INPUT': '#a34a28', 'TEXT_INPUT': '#dfddc7', 'SCROLL': '#211717', + 'BUTTON': ('#dfddc7', '#a34a28'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#211717', '#a34a28', '#f58b54', '#dfddc7'], }, + 'DarkBlue4': {'BACKGROUND': '#494ca2', 'TEXT': '#e3e7f1', 'INPUT': '#c6cbef', 'TEXT_INPUT': '#000000', 'SCROLL': '#c6cbef', + 'BUTTON': ('#FFFFFF', '#8186d5'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#494ca2', '#8186d5', '#c6cbef', '#e3e7f1'], }, + 'LightBlue4': {'BACKGROUND': '#5c94bd', 'TEXT': '#470938', 'INPUT': '#1a3e59', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#470938', + 'BUTTON': ('#FFFFFF', '#470938'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#470938', '#1a3e59', '#5c94bd', '#f2d6eb'], }, + 'DarkTeal2': {'BACKGROUND': '#394a6d', 'TEXT': '#c0ffb3', 'INPUT': '#52de97', 'TEXT_INPUT': '#000000', 'SCROLL': '#52de97', + 'BUTTON': ('#c0ffb3', '#394a6d'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#394a6d', '#3c9d9b', '#52de97', '#c0ffb3'], }, + 'DarkTeal3': {'BACKGROUND': '#3c9d9b', 'TEXT': '#c0ffb3', 'INPUT': '#52de97', 'TEXT_INPUT': '#000000', 'SCROLL': '#52de97', + 'BUTTON': ('#c0ffb3', '#394a6d'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#394a6d', '#3c9d9b', '#52de97', '#c0ffb3'], }, + 'DarkPurple5': {'BACKGROUND': '#730068', 'TEXT': '#f6f078', 'INPUT': '#01d28e', 'TEXT_INPUT': '#000000', 'SCROLL': '#01d28e', + 'BUTTON': ('#f6f078', '#730068'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#730068', '#434982', '#01d28e', '#f6f078'], }, + 'DarkPurple2': {'BACKGROUND': '#202060', 'TEXT': '#b030b0', 'INPUT': '#602080', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#602080', + 'BUTTON': ('#FFFFFF', '#202040'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#202040', '#202060', '#602080', '#b030b0'], }, + 'DarkBlue5': {'BACKGROUND': '#000272', 'TEXT': '#ff6363', 'INPUT': '#a32f80', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#a32f80', + 'BUTTON': ('#FFFFFF', '#341677'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#000272', '#341677', '#a32f80', '#ff6363'], }, + 'LightGrey2': {'BACKGROUND': '#f6f6f6', 'TEXT': '#420000', 'INPUT': '#d4d7dd', 'TEXT_INPUT': '#420000', 'SCROLL': '#420000', + 'BUTTON': ('#420000', '#d4d7dd'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#420000', '#d4d7dd', '#eae9e9', '#f6f6f6'], }, + 'LightGrey3': {'BACKGROUND': '#eae9e9', 'TEXT': '#420000', 'INPUT': '#d4d7dd', 'TEXT_INPUT': '#420000', 'SCROLL': '#420000', + 'BUTTON': ('#420000', '#d4d7dd'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#420000', '#d4d7dd', '#eae9e9', '#f6f6f6'], }, + 'DarkBlue6': {'BACKGROUND': '#01024e', 'TEXT': '#ff6464', 'INPUT': '#8b4367', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#8b4367', + 'BUTTON': ('#FFFFFF', '#543864'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#01024e', '#543864', '#8b4367', '#ff6464'], }, + 'DarkBlue7': {'BACKGROUND': '#241663', 'TEXT': '#eae7af', 'INPUT': '#a72693', 'TEXT_INPUT': '#eae7af', 'SCROLL': '#a72693', + 'BUTTON': ('#eae7af', '#160f30'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#160f30', '#241663', '#a72693', '#eae7af'], }, + 'LightBrown9': {'BACKGROUND': '#f6d365', 'TEXT': '#3a1f5d', 'INPUT': '#c83660', 'TEXT_INPUT': '#f6d365', 'SCROLL': '#3a1f5d', + 'BUTTON': ('#f6d365', '#c83660'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#3a1f5d', '#c83660', '#e15249', '#f6d365'], }, + 'DarkPurple3': {'BACKGROUND': '#6e2142', 'TEXT': '#ffd692', 'INPUT': '#e16363', 'TEXT_INPUT': '#ffd692', 'SCROLL': '#e16363', + 'BUTTON': ('#ffd692', '#943855'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#6e2142', '#943855', '#e16363', '#ffd692'], }, + 'LightBrown10': {'BACKGROUND': '#ffd692', 'TEXT': '#6e2142', 'INPUT': '#943855', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#6e2142', + 'BUTTON': ('#FFFFFF', '#6e2142'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#6e2142', '#943855', '#e16363', '#ffd692'], }, + 'DarkPurple4': {'BACKGROUND': '#200f21', 'TEXT': '#f638dc', 'INPUT': '#5a3d5c', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#5a3d5c', + 'BUTTON': ('#FFFFFF', '#382039'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#200f21', '#382039', '#5a3d5c', '#f638dc'], }, + 'LightBlue5': {'BACKGROUND': '#b2fcff', 'TEXT': '#3e64ff', 'INPUT': '#5edfff', 'TEXT_INPUT': '#000000', 'SCROLL': '#3e64ff', + 'BUTTON': ('#FFFFFF', '#3e64ff'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#3e64ff', '#5edfff', '#b2fcff', '#ecfcff'], }, + 'DarkTeal4': {'BACKGROUND': '#464159', 'TEXT': '#c7f0db', 'INPUT': '#8bbabb', 'TEXT_INPUT': '#000000', 'SCROLL': '#8bbabb', + 'BUTTON': ('#FFFFFF', '#6c7b95'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#464159', '#6c7b95', '#8bbabb', '#c7f0db'], }, + 'LightTeal': {'BACKGROUND': '#c7f0db', 'TEXT': '#464159', 'INPUT': '#6c7b95', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#464159', + 'BUTTON': ('#FFFFFF', '#464159'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#464159', '#6c7b95', '#8bbabb', '#c7f0db'], }, + 'DarkTeal5': {'BACKGROUND': '#8bbabb', 'TEXT': '#464159', 'INPUT': '#6c7b95', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#464159', + 'BUTTON': ('#c7f0db', '#6c7b95'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#464159', '#6c7b95', '#8bbabb', '#c7f0db'], }, + 'LightGrey4': {'BACKGROUND': '#faf5ef', 'TEXT': '#672f2f', 'INPUT': '#99b19c', 'TEXT_INPUT': '#672f2f', 'SCROLL': '#672f2f', + 'BUTTON': ('#672f2f', '#99b19c'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#672f2f', '#99b19c', '#d7d1c9', '#faf5ef'], }, + 'LightGreen7': {'BACKGROUND': '#99b19c', 'TEXT': '#faf5ef', 'INPUT': '#d7d1c9', 'TEXT_INPUT': '#000000', 'SCROLL': '#d7d1c9', + 'BUTTON': ('#FFFFFF', '#99b19c'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#672f2f', '#99b19c', '#d7d1c9', '#faf5ef'], }, + 'LightGrey5': {'BACKGROUND': '#d7d1c9', 'TEXT': '#672f2f', 'INPUT': '#99b19c', 'TEXT_INPUT': '#672f2f', 'SCROLL': '#672f2f', + 'BUTTON': ('#FFFFFF', '#672f2f'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#672f2f', '#99b19c', '#d7d1c9', '#faf5ef'], }, + 'DarkBrown3': {'BACKGROUND': '#a0855b', 'TEXT': '#f9f6f2', 'INPUT': '#f1d6ab', 'TEXT_INPUT': '#000000', 'SCROLL': '#f1d6ab', + 'BUTTON': ('#FFFFFF', '#38470b'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#38470b', '#a0855b', '#f1d6ab', '#f9f6f2'], }, + 'LightBrown11': {'BACKGROUND': '#f1d6ab', 'TEXT': '#38470b', 'INPUT': '#a0855b', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#38470b', + 'BUTTON': ('#f9f6f2', '#a0855b'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#38470b', '#a0855b', '#f1d6ab', '#f9f6f2'], }, + 'DarkRed': {'BACKGROUND': '#83142c', 'TEXT': '#f9d276', 'INPUT': '#ad1d45', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#ad1d45', + 'BUTTON': ('#f9d276', '#ad1d45'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#44000d', '#83142c', '#ad1d45', '#f9d276'], }, + 'DarkTeal6': {'BACKGROUND': '#204969', 'TEXT': '#fff7f7', 'INPUT': '#dadada', 'TEXT_INPUT': '#000000', 'SCROLL': '#dadada', + 'BUTTON': ('#000000', '#fff7f7'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#204969', '#08ffc8', '#dadada', '#fff7f7'], }, + 'DarkBrown4': {'BACKGROUND': '#252525', 'TEXT': '#ff0000', 'INPUT': '#af0404', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#af0404', + 'BUTTON': ('#FFFFFF', '#252525'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#252525', '#414141', '#af0404', '#ff0000'], }, + 'LightYellow': {'BACKGROUND': '#f4ff61', 'TEXT': '#27aa80', 'INPUT': '#32ff6a', 'TEXT_INPUT': '#000000', 'SCROLL': '#27aa80', + 'BUTTON': ('#f4ff61', '#27aa80'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#27aa80', '#32ff6a', '#a8ff3e', '#f4ff61'], }, + 'DarkGreen1': {'BACKGROUND': '#2b580c', 'TEXT': '#fdef96', 'INPUT': '#f7b71d', 'TEXT_INPUT': '#000000', 'SCROLL': '#f7b71d', + 'BUTTON': ('#fdef96', '#2b580c'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#2b580c', '#afa939', '#f7b71d', '#fdef96'], }, + + 'LightGreen8': {'BACKGROUND': '#c8dad3', 'TEXT': '#63707e', 'INPUT': '#93b5b3', 'TEXT_INPUT': '#000000', 'SCROLL': '#63707e', + 'BUTTON': ('#FFFFFF', '#63707e'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#63707e', '#93b5b3', '#c8dad3', '#f2f6f5'], }, + + 'DarkTeal7': {'BACKGROUND': '#248ea9', 'TEXT': '#fafdcb', 'INPUT': '#aee7e8', 'TEXT_INPUT': '#000000', 'SCROLL': '#aee7e8', + 'BUTTON': ('#000000', '#fafdcb'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#248ea9', '#28c3d4', '#aee7e8', '#fafdcb'], }, + 'DarkBlue8': {'BACKGROUND': '#454d66', 'TEXT': '#d9d872', 'INPUT': '#58b368', 'TEXT_INPUT': '#000000', 'SCROLL': '#58b368', + 'BUTTON': ('#000000', '#009975'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#009975', '#454d66', '#58b368', '#d9d872'], }, + 'DarkBlue9': {'BACKGROUND': '#263859', 'TEXT': '#ff6768', 'INPUT': '#6b778d', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#6b778d', + 'BUTTON': ('#ff6768', '#263859'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#17223b', '#263859', '#6b778d', '#ff6768'], }, + 'DarkBlue10': {'BACKGROUND': '#0028ff', 'TEXT': '#f1f4df', 'INPUT': '#10eaf0', 'TEXT_INPUT': '#000000', 'SCROLL': '#10eaf0', + 'BUTTON': ('#f1f4df', '#24009c'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#24009c', '#0028ff', '#10eaf0', '#f1f4df'], }, + 'DarkBlue11': {'BACKGROUND': '#6384b3', 'TEXT': '#e6f0b6', 'INPUT': '#b8e9c0', 'TEXT_INPUT': '#000000', 'SCROLL': '#b8e9c0', + 'BUTTON': ('#e6f0b6', '#684949'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#684949', '#6384b3', '#b8e9c0', '#e6f0b6'], }, + + 'DarkTeal8': {'BACKGROUND': '#71a0a5', 'TEXT': '#212121', 'INPUT': '#665c84', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#212121', + 'BUTTON': ('#fab95b', '#665c84'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#212121', '#665c84', '#71a0a5', '#fab95b']}, + 'DarkRed1': {'BACKGROUND': '#c10000', 'TEXT': '#eeeeee', 'INPUT': '#dedede', 'TEXT_INPUT': '#000000', 'SCROLL': '#dedede', + 'BUTTON': ('#c10000', '#eeeeee'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#c10000', '#ff4949', '#dedede', '#eeeeee'], }, + 'LightBrown5': {'BACKGROUND': '#fff591', 'TEXT': '#e41749', 'INPUT': '#f5587b', 'TEXT_INPUT': '#000000', 'SCROLL': '#e41749', + 'BUTTON': ('#fff591', '#e41749'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#e41749', '#f5587b', '#ff8a5c', '#fff591']}, + 'LightGreen9': {'BACKGROUND': '#f1edb3', 'TEXT': '#3b503d', 'INPUT': '#4a746e', 'TEXT_INPUT': '#f1edb3', 'SCROLL': '#3b503d', + 'BUTTON': ('#f1edb3', '#3b503d'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#3b503d', '#4a746e', '#c8cf94', '#f1edb3'], 'DESCRIPTION': ['Green', 'Turquoise', 'Yellow']}, + 'DarkGreen2': {'BACKGROUND': '#3b503d', 'TEXT': '#f1edb3', 'INPUT': '#c8cf94', 'TEXT_INPUT': '#000000', 'SCROLL': '#c8cf94', + 'BUTTON': ('#f1edb3', '#3b503d'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#3b503d', '#4a746e', '#c8cf94', '#f1edb3'], 'DESCRIPTION': ['Green', 'Turquoise', 'Yellow']}, + 'LightGray1': {'BACKGROUND': '#f2f2f2', 'TEXT': '#222831', 'INPUT': '#393e46', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#222831', + 'BUTTON': ('#f2f2f2', '#222831'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#222831', '#393e46', '#f96d00', '#f2f2f2'], + 'DESCRIPTION': ['#000000', 'Grey', 'Orange', 'Grey', 'Autumn']}, + 'DarkGrey4': {'BACKGROUND': '#52524e', 'TEXT': '#e9e9e5', 'INPUT': '#d4d6c8', 'TEXT_INPUT': '#000000', 'SCROLL': '#d4d6c8', + 'BUTTON': ('#FFFFFF', '#9a9b94'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#52524e', '#9a9b94', '#d4d6c8', '#e9e9e5'], + 'DESCRIPTION': ['Grey', 'Pastel', 'Winter']}, + 'DarkBlue12': {'BACKGROUND': '#324e7b', 'TEXT': '#f8f8f8', 'INPUT': '#86a6df', 'TEXT_INPUT': '#000000', 'SCROLL': '#86a6df', + 'BUTTON': ('#FFFFFF', '#5068a9'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#324e7b', '#5068a9', '#86a6df', '#f8f8f8'], + 'DESCRIPTION': ['Blue', 'Grey', 'Cold', 'Winter']}, + 'DarkPurple6': {'BACKGROUND': '#070739', 'TEXT': '#e1e099', 'INPUT': '#c327ab', 'TEXT_INPUT': '#e1e099', 'SCROLL': '#c327ab', + 'BUTTON': ('#e1e099', '#521477'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#070739', '#521477', '#c327ab', '#e1e099'], + 'DESCRIPTION': ['#000000', 'Purple', 'Yellow', 'Dark']}, + 'DarkBlue13': {'BACKGROUND': '#203562', 'TEXT': '#e3e8f8', 'INPUT': '#c0c5cd', 'TEXT_INPUT': '#000000', 'SCROLL': '#c0c5cd', + 'BUTTON': ('#FFFFFF', '#3e588f'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#203562', '#3e588f', '#c0c5cd', '#e3e8f8'], + 'DESCRIPTION': ['Blue', 'Grey', 'Wedding', 'Cold']}, + 'DarkBrown5': {'BACKGROUND': '#3c1b1f', 'TEXT': '#f6e1b5', 'INPUT': '#e2bf81', 'TEXT_INPUT': '#000000', 'SCROLL': '#e2bf81', + 'BUTTON': ('#3c1b1f', '#f6e1b5'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#3c1b1f', '#b21e4b', '#e2bf81', '#f6e1b5'], + 'DESCRIPTION': ['Brown', 'Red', 'Yellow', 'Warm']}, + 'DarkGreen3': {'BACKGROUND': '#062121', 'TEXT': '#eeeeee', 'INPUT': '#e4dcad', 'TEXT_INPUT': '#000000', 'SCROLL': '#e4dcad', + 'BUTTON': ('#eeeeee', '#181810'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#062121', '#181810', '#e4dcad', '#eeeeee'], + 'DESCRIPTION': ['#000000', '#000000', 'Brown', 'Grey']}, + 'DarkBlack1': {'BACKGROUND': '#181810', 'TEXT': '#eeeeee', 'INPUT': '#e4dcad', 'TEXT_INPUT': '#000000', 'SCROLL': '#e4dcad', + 'BUTTON': ('#FFFFFF', '#062121'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#062121', '#181810', '#e4dcad', '#eeeeee'], + 'DESCRIPTION': ['#000000', '#000000', 'Brown', 'Grey']}, + 'DarkGrey5': {'BACKGROUND': '#343434', 'TEXT': '#f3f3f3', 'INPUT': '#e9dcbe', 'TEXT_INPUT': '#000000', 'SCROLL': '#e9dcbe', + 'BUTTON': ('#FFFFFF', '#8e8b82'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#343434', '#8e8b82', '#e9dcbe', '#f3f3f3'], 'DESCRIPTION': ['Grey', 'Brown']}, + 'LightBrown12': {'BACKGROUND': '#8e8b82', 'TEXT': '#f3f3f3', 'INPUT': '#e9dcbe', 'TEXT_INPUT': '#000000', 'SCROLL': '#e9dcbe', + 'BUTTON': ('#f3f3f3', '#8e8b82'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#343434', '#8e8b82', '#e9dcbe', '#f3f3f3'], 'DESCRIPTION': ['Grey', 'Brown']}, + 'DarkTeal9': {'BACKGROUND': '#13445a', 'TEXT': '#fef4e8', 'INPUT': '#446878', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#446878', + 'BUTTON': ('#fef4e8', '#446878'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#13445a', '#970747', '#446878', '#fef4e8'], + 'DESCRIPTION': ['Red', 'Grey', 'Blue', 'Wedding', 'Retro']}, + 'DarkBlue14': {'BACKGROUND': '#21273d', 'TEXT': '#f1f6f8', 'INPUT': '#b9d4f1', 'TEXT_INPUT': '#000000', 'SCROLL': '#b9d4f1', + 'BUTTON': ('#FFFFFF', '#6a759b'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#21273d', '#6a759b', '#b9d4f1', '#f1f6f8'], + 'DESCRIPTION': ['Blue', '#000000', 'Grey', 'Cold', 'Winter']}, + 'LightBlue6': {'BACKGROUND': '#f1f6f8', 'TEXT': '#21273d', 'INPUT': '#6a759b', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#21273d', + 'BUTTON': ('#f1f6f8', '#6a759b'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#21273d', '#6a759b', '#b9d4f1', '#f1f6f8'], + 'DESCRIPTION': ['Blue', '#000000', 'Grey', 'Cold', 'Winter']}, + 'DarkGreen4': {'BACKGROUND': '#044343', 'TEXT': '#e4e4e4', 'INPUT': '#045757', 'TEXT_INPUT': '#e4e4e4', 'SCROLL': '#045757', + 'BUTTON': ('#e4e4e4', '#045757'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#222222', '#044343', '#045757', '#e4e4e4'], + 'DESCRIPTION': ['#000000', 'Turquoise', 'Grey', 'Dark']}, + 'DarkGreen5': {'BACKGROUND': '#1b4b36', 'TEXT': '#e0e7f1', 'INPUT': '#aebd77', 'TEXT_INPUT': '#000000', 'SCROLL': '#aebd77', + 'BUTTON': ('#FFFFFF', '#538f6a'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#1b4b36', '#538f6a', '#aebd77', '#e0e7f1'], 'DESCRIPTION': ['Green', 'Grey']}, + 'DarkTeal10': {'BACKGROUND': '#0d3446', 'TEXT': '#d8dfe2', 'INPUT': '#71adb5', 'TEXT_INPUT': '#000000', 'SCROLL': '#71adb5', + 'BUTTON': ('#FFFFFF', '#176d81'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#0d3446', '#176d81', '#71adb5', '#d8dfe2'], + 'DESCRIPTION': ['Grey', 'Turquoise', 'Winter', 'Cold']}, + 'DarkGrey6': {'BACKGROUND': '#3e3e3e', 'TEXT': '#ededed', 'INPUT': '#68868c', 'TEXT_INPUT': '#ededed', 'SCROLL': '#68868c', + 'BUTTON': ('#FFFFFF', '#405559'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#3e3e3e', '#405559', '#68868c', '#ededed'], + 'DESCRIPTION': ['Grey', 'Turquoise', 'Winter']}, + 'DarkTeal11': {'BACKGROUND': '#405559', 'TEXT': '#ededed', 'INPUT': '#68868c', 'TEXT_INPUT': '#ededed', 'SCROLL': '#68868c', + 'BUTTON': ('#ededed', '#68868c'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#3e3e3e', '#405559', '#68868c', '#ededed'], + 'DESCRIPTION': ['Grey', 'Turquoise', 'Winter']}, + 'LightBlue7': {'BACKGROUND': '#9ed0e0', 'TEXT': '#19483f', 'INPUT': '#5c868e', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#19483f', + 'BUTTON': ('#FFFFFF', '#19483f'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#19483f', '#5c868e', '#ff6a38', '#9ed0e0'], + 'DESCRIPTION': ['Orange', 'Blue', 'Turquoise']}, + 'LightGreen10': {'BACKGROUND': '#d8ebb5', 'TEXT': '#205d67', 'INPUT': '#639a67', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#205d67', + 'BUTTON': ('#d8ebb5', '#205d67'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#205d67', '#639a67', '#d9bf77', '#d8ebb5'], + 'DESCRIPTION': ['Blue', 'Green', 'Brown', 'Vintage']}, + 'DarkBlue15': {'BACKGROUND': '#151680', 'TEXT': '#f1fea4', 'INPUT': '#375fc0', 'TEXT_INPUT': '#f1fea4', 'SCROLL': '#375fc0', + 'BUTTON': ('#f1fea4', '#1c44ac'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#151680', '#1c44ac', '#375fc0', '#f1fea4'], + 'DESCRIPTION': ['Blue', 'Yellow', 'Cold']}, + 'DarkBlue16': {'BACKGROUND': '#1c44ac', 'TEXT': '#f1fea4', 'INPUT': '#375fc0', 'TEXT_INPUT': '#f1fea4', 'SCROLL': '#375fc0', + 'BUTTON': ('#f1fea4', '#151680'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#151680', '#1c44ac', '#375fc0', '#f1fea4'], + 'DESCRIPTION': ['Blue', 'Yellow', 'Cold']}, + 'DarkTeal12': {'BACKGROUND': '#004a7c', 'TEXT': '#fafafa', 'INPUT': '#e8f1f5', 'TEXT_INPUT': '#000000', 'SCROLL': '#e8f1f5', + 'BUTTON': ('#fafafa', '#005691'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#004a7c', '#005691', '#e8f1f5', '#fafafa'], + 'DESCRIPTION': ['Grey', 'Blue', 'Cold', 'Winter']}, + 'LightBrown13': {'BACKGROUND': '#ebf5ee', 'TEXT': '#921224', 'INPUT': '#bdc6b8', 'TEXT_INPUT': '#921224', 'SCROLL': '#921224', + 'BUTTON': ('#FFFFFF', '#921224'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#921224', '#bdc6b8', '#bce0da', '#ebf5ee'], + 'DESCRIPTION': ['Red', 'Blue', 'Grey', 'Vintage', 'Wedding']}, + 'DarkBlue17': {'BACKGROUND': '#21294c', 'TEXT': '#f9f2d7', 'INPUT': '#f2dea8', 'TEXT_INPUT': '#000000', 'SCROLL': '#f2dea8', + 'BUTTON': ('#f9f2d7', '#141829'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#141829', '#21294c', '#f2dea8', '#f9f2d7'], + 'DESCRIPTION': ['#000000', 'Blue', 'Yellow']}, + 'DarkBrown6': {'BACKGROUND': '#785e4d', 'TEXT': '#f2eee3', 'INPUT': '#baaf92', 'TEXT_INPUT': '#000000', 'SCROLL': '#baaf92', + 'BUTTON': ('#FFFFFF', '#785e4d'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#785e4d', '#ff8426', '#baaf92', '#f2eee3'], + 'DESCRIPTION': ['Grey', 'Brown', 'Orange', 'Autumn']}, + 'DarkGreen6': {'BACKGROUND': '#5c715e', 'TEXT': '#f2f9f1', 'INPUT': '#ddeedf', 'TEXT_INPUT': '#000000', 'SCROLL': '#ddeedf', + 'BUTTON': ('#f2f9f1', '#5c715e'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#5c715e', '#b6cdbd', '#ddeedf', '#f2f9f1'], + 'DESCRIPTION': ['Grey', 'Green', 'Vintage']}, + 'DarkGrey7': {'BACKGROUND': '#4b586e', 'TEXT': '#dddddd', 'INPUT': '#574e6d', 'TEXT_INPUT': '#dddddd', 'SCROLL': '#574e6d', + 'BUTTON': ('#dddddd', '#43405d'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#43405d', '#4b586e', '#574e6d', '#dddddd'], + 'DESCRIPTION': ['Grey', 'Winter', 'Cold']}, + 'DarkRed2': {'BACKGROUND': '#ab1212', 'TEXT': '#f6e4b5', 'INPUT': '#cd3131', 'TEXT_INPUT': '#f6e4b5', 'SCROLL': '#cd3131', + 'BUTTON': ('#f6e4b5', '#ab1212'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#ab1212', '#1fad9f', '#cd3131', '#f6e4b5'], + 'DESCRIPTION': ['Turquoise', 'Red', 'Yellow']}, + 'LightGrey6': {'BACKGROUND': '#e3e3e3', 'TEXT': '#233142', 'INPUT': '#455d7a', 'TEXT_INPUT': '#e3e3e3', 'SCROLL': '#233142', + 'BUTTON': ('#e3e3e3', '#455d7a'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#233142', '#455d7a', '#f95959', '#e3e3e3'], + 'DESCRIPTION': ['#000000', 'Blue', 'Red', 'Grey']}, + 'HotDogStand': {'BACKGROUND': 'red', 'TEXT': 'yellow', 'INPUT': 'yellow', 'TEXT_INPUT': '#000000', 'SCROLL': 'yellow', + 'BUTTON': ('red', 'yellow'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + }, + } + + +def ListOfLookAndFeelValues(): + """ + Get a list of the valid values to pass into your call to change_look_and_feel + :return: List[str] - list of valid string values + """ + return sorted(list(LOOK_AND_FEEL_TABLE.keys())) + + +def theme(new_theme=None): + """ + Sets / Gets the current Theme. If none is specified then returns the current theme. + This call replaces the ChangeLookAndFeel / change_look_and_feel call which only sets the theme. + + :param new_theme: (str) the new theme name to use + :return: (str) the currently selected theme + """ + if new_theme is not None: + change_look_and_feel(new_theme) + return CURRENT_LOOK_AND_FEEL + + +def theme_background_color(color=None): + """ + Sets/Returns the background color currently in use + Used for Windows and containers (Column, Frame, Tab) and tables + + :return: (str) - color string of the background color currently in use + """ + if color is not None: + set_options(background_color=color) + return DEFAULT_BACKGROUND_COLOR + + +def theme_element_background_color(color=None): + """ + Sets/Returns the background color currently in use for all elements except containers + + :return: (str) - color string of the element background color currently in use + """ + if color is not None: + set_options(element_background_color=color) + return DEFAULT_ELEMENT_BACKGROUND_COLOR + + +def theme_text_color(color=None): + """ + Sets/Returns the text color currently in use + + :return: (str) - color string of the text color currently in use + """ + if color is not None: + set_options(text_color=color) + return DEFAULT_TEXT_COLOR + + +def theme_text_element_background_color(color=None): + """ + Sets/Returns the background color for text elements + + :return: (str) - color string of the text background color currently in use + """ + if color is not None: + set_options(text_element_background_color=color) + return DEFAULT_TEXT_ELEMENT_BACKGROUND_COLOR + +def theme_input_background_color(color=None): + """ + Sets/Returns the input element background color currently in use + + :return: (str) - color string of the input element background color currently in use + """ + if color is not None: + set_options(input_elements_background_color=color) + return DEFAULT_INPUT_ELEMENTS_COLOR + + +def theme_input_text_color(color=None): + """ + Sets/Returns the input element entry color (not the text but the thing that's displaying the text) + + :return: (str) - color string of the input element color currently in use + """ + if color is not None: + set_options(input_text_color=color) + return DEFAULT_INPUT_TEXT_COLOR + + + +def theme_button_color(color=None): + """ + Sets/Returns the button color currently in use + + :return: Tuple[str, str] - TUPLE with color strings of the button color currently in use (button text color, button background color) + """ + if color is not None: + set_options(button_color=color) + return DEFAULT_BUTTON_COLOR + + +def theme_progress_bar_color(color=None): + """ + Sets/Returns the progress bar colors by the current color theme + + :return: Tuple[str, str] - TUPLE with color strings of the ProgressBar color currently in use(button text color, button background color) + """ + if color is not None: + set_options(progress_meter_color=color) + return DEFAULT_PROGRESS_BAR_COLOR + + +def theme_slider_color(color=None): + """ + Sets/Returns the slider color (used for sliders) + + :return: (str) - color string of the slider color currently in use + """ + if color is not None: + set_options(scrollbar_color=color) + return DEFAULT_SCROLLBAR_COLOR + + +def theme_border_width(border_width=None): + """ + Sets/Returns the border width currently in use + Used by non ttk elements at the moment + + :return: (int) - border width currently in use + """ + if border_width is not None: + set_options(border_width=border_width) + return DEFAULT_BORDER_WIDTH + + +def theme_slider_border_width(border_width=None): + """ + Sets/Returns the slider border width currently in use + + :return: (int) - border width currently in use + """ + if border_width is not None: + set_options(slider_border_width=border_width) + return DEFAULT_SLIDER_BORDER_WIDTH + + +def theme_progress_bar_border_width(border_width=None): + """ + Sets/Returns the progress meter border width currently in use + + :return: (int) - border width currently in use + """ + if border_width is not None: + set_options(progress_meter_border_depth=border_width) + return DEFAULT_PROGRESS_BAR_BORDER_WIDTH + + + +def theme_element_text_color(color=None): + """ + Sets/Returns the text color used by elements that have text as part of their display (Tables, Trees and Sliders) + + :return: (str) - color string currently in use + """ + if color is not None: + set_options(element_text_color=color) + return DEFAULT_ELEMENT_TEXT_COLOR + + +def theme_list(): + """ + Returns a sorted list of the currently available color themes + + :return: List[str] - A sorted list of the currently available color themes + """ + return list_of_look_and_feel_values() + + +def theme_add_new(new_theme_name, new_theme_dict): + """ + Add a new theme to the dictionary of themes + + :param new_theme_name: text to display in element + :type new_theme_name: (str) + :param new_theme_dict: text to display in element + :type new_theme_dict: (dict) + """ + global LOOK_AND_FEEL_TABLE + try: + LOOK_AND_FEEL_TABLE[new_theme_name] = new_theme_dict + except Exception as e: + print('Exception during adding new theme {}'.format(e)) + + +def theme_previewer(columns=12): + """ + Show a window with all of the color themes - takes a while so be patient + + :param columns: (int) number of themes in a single row + """ + preview_all_look_and_feel_themes(columns) + +def ChangeLookAndFeel(index, force=False): + """ + Change the "color scheme" of all future PySimpleGUI Windows. + The scheme are string names that specify a group of colors. Background colors, text colors, button colors. + There are 13 different color settings that are changed at one time using a single call to ChangeLookAndFeel + The look and feel table itself has these indexes into the dictionary LOOK_AND_FEEL_TABLE. + The original list was (prior to a major rework and renaming)... these names still work... + In Nov 2019 a new Theme Formula was devised to make choosing a theme easier: + The "Formula" is: + ["Dark" or "Light"] Color Number + Colors can be Blue Brown Grey Green Purple Red Teal Yellow Black + The number will vary for each pair. There are more DarkGrey entries than there are LightYellow for example. + Default = The default settings (only button color is different than system default) + Default1 = The full system default including the button (everything's gray... how sad... don't be all gray... please....) + :param index: (str) the name of the index into the Look and Feel table (does not have to be exact, can be "fuzzy") + :param force: (bool) no longer used + """ + + global CURRENT_LOOK_AND_FEEL + + # if sys.platform.startswith('darwin') and not force: + # print('*** Changing look and feel is not supported on Mac platform ***') + # return + + theme = index + # normalize available l&f values + lf_values = [item.lower() for item in list_of_look_and_feel_values()] + + # option 1 + opt1 = theme.replace(' ', '').lower() + + # option 2 (reverse lookup) + optx = theme.lower().split(' ') + optx.reverse() + opt2 = ''.join(optx) + + # search for valid l&f name + if opt1 in lf_values: + ix = lf_values.index(opt1) + elif opt2 in lf_values: + ix = lf_values.index(opt2) + else: + ix = randint(0, len(lf_values) - 1) + print('** Warning - {} Theme is not a valid theme. Change your theme call. **'.format(index)) + print('valid values are', list_of_look_and_feel_values()) + print('Instead, please enjoy a random Theme named {}'.format(list_of_look_and_feel_values()[ix])) + + selection = list_of_look_and_feel_values()[ix] + CURRENT_LOOK_AND_FEEL = selection + try: + colors = LOOK_AND_FEEL_TABLE[selection] + + # Color the progress bar using button background and input colors...unless they're the same + if colors['PROGRESS'] != COLOR_SYSTEM_DEFAULT: + if colors['BUTTON'][1] != colors['INPUT'] and colors['BUTTON'][1] != colors['BACKGROUND']: + colors['PROGRESS'] = colors['BUTTON'][1], colors['INPUT'] + else: # if the same, then use text input on top of input color + colors['PROGRESS'] = (colors['TEXT_INPUT'], colors['INPUT']) + else: + colors['PROGRESS'] = DEFAULT_PROGRESS_BAR_COLOR_OFFICIAL + # call to change all the colors + SetOptions(background_color=colors['BACKGROUND'], + text_element_background_color=colors['BACKGROUND'], + element_background_color=colors['BACKGROUND'], + text_color=colors['TEXT'], + input_elements_background_color=colors['INPUT'], + # button_color=colors['BUTTON'] if not sys.platform.startswith('darwin') else None, + button_color=colors['BUTTON'], + progress_meter_color=colors['PROGRESS'], + border_width=colors['BORDER'], + slider_border_width=colors['SLIDER_DEPTH'], + progress_meter_border_depth=colors['PROGRESS_DEPTH'], + scrollbar_color=(colors['SCROLL']), + element_text_color=colors['TEXT'], + input_text_color=colors['TEXT_INPUT']) + except: # most likely an index out of range + print('** Warning - Theme value not valid. Change your theme call. **') + print('valid values are', list_of_look_and_feel_values()) + + +def preview_all_look_and_feel_themes(columns=12): + """ + Displays a "Quick Reference Window" showing all of the different Look and Feel settings that are available. + They are sorted alphabetically. The legacy color names are mixed in, but otherwise they are sorted into Dark and Light halves + :param columns: (int) The number of themes to display per row + """ + + # Show a "splash" type message so the user doesn't give up waiting + popup_quick_message('Hang on for a moment, this will take a bit to create....', background_color='red', text_color='#FFFFFF', auto_close=True, non_blocking=True) + + web = False + + win_bg = 'black' + + def sample_layout(): + return [[Text('Text element'), InputText('Input data here', size=(10, 1))], + [Button('Ok'), Button('Cancel'), Slider((1, 10), orientation='h', size=(5, 15))]] + + layout = [[Text('Here is a complete list of themes', font='Default 18', background_color=win_bg)]] + + names = list_of_look_and_feel_values() + names.sort() + row = [] + for count, theme in enumerate(names): + change_look_and_feel(theme) + if not count % columns: + layout += [row] + row = [] + row += [Frame(theme, sample_layout() if not web else [[T(theme)]] + sample_layout())] + if row: + layout += [row] + + window = Window('Preview of all Look and Feel choices', layout, background_color=win_bg) + window.read() + window.close() + + +# ============================== sprint ======# +# Is identical to the Scrolled Text Box # +# Provides a crude 'print' mechanism but in a # +# GUI environment # +# ============================================# +sprint = ScrolledTextBox + + +# Converts an object's contents into a nice printable string. Great for dumping debug data +def ObjToStringSingleObj(obj): + if obj is None: + return 'None' + return str(obj.__class__) + '\n' + '\n'.join( + (repr(item) + ' = ' + repr(obj.__dict__[item]) for item in sorted(obj.__dict__))) + + +def ObjToString(obj, extra=' '): + if obj is None: + return 'None' + return str(obj.__class__) + '\n' + '\n'.join( + (extra + (str(item) + ' = ' + + (ObjToString(obj.__dict__[item], extra + ' ') if hasattr(obj.__dict__[item], '__dict__') else str( + obj.__dict__[item]))) + for item in sorted(obj.__dict__))) + + +# ------------------------------------------------------------------------------------------------------------------ # +# ===================================== Upper PySimpleGUI ======================================================== # +# Pre-built dialog boxes for all your needs These are the "high level API calls # +# ------------------------------------------------------------------------------------------------------------------ # + +# ----------------------------------- The mighty Popup! ------------------------------------------------------------ # + +def Popup(*args, button_color=None, background_color=None, text_color=None, button_type=POPUP_BUTTONS_OK, + auto_close=False, auto_close_duration=None, custom_text=(None, None), non_blocking=False, + icon=DEFAULT_WINDOW_ICON, line_width=None, + font=None, no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)): + """ + Popup - Display a popup box with as many parms as you wish to include + :param args: + :param button_color: + :param background_color: + :param text_color: + :param button_type: + :param auto_close: + :param auto_close_duration: + :param non_blocking: + :param icon: + :param line_width: + :param font: + :param no_titlebar: + :param grab_anywhere: + :param keep_on_top: + :param location: + :return: + """ + if not args: + args_to_print = [''] + else: + args_to_print = args + if line_width != None: + local_line_width = line_width + else: + local_line_width = MESSAGE_BOX_LINE_WIDTH + title = args_to_print[0] if args_to_print[0] is not None else 'None' + window = Window(title, auto_size_text=True, background_color=background_color, button_color=button_color, + auto_close=auto_close, auto_close_duration=auto_close_duration, icon=icon, font=font, + no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) + max_line_total, total_lines = 0, 0 + for message in args_to_print: + # fancy code to check if string and convert if not is not need. Just always convert to string :-) + # if not isinstance(message, str): message = str(message) + message = str(message) + if message.count('\n'): + message_wrapped = message + else: + message_wrapped = textwrap.fill(message, local_line_width) + message_wrapped_lines = message_wrapped.count('\n') + 1 + longest_line_len = max([len(l) for l in message.split('\n')]) + width_used = min(longest_line_len, local_line_width) + max_line_total = max(max_line_total, width_used) + # height = _GetNumLinesNeeded(message, width_used) + height = message_wrapped_lines + window.AddRow( + Text(message_wrapped, auto_size_text=True, text_color=text_color, background_color=background_color)) + total_lines += height + + if non_blocking: + PopupButton = DummyButton # important to use or else button will close other windows too! + else: + PopupButton = Button + # show either an OK or Yes/No depending on paramater + if custom_text != (None, None): + if type(custom_text) is not tuple: + window.AddRow(PopupButton(custom_text, size=(len(custom_text), 1), button_color=button_color, focus=True, + bind_return_key=True)) + elif custom_text[1] is None: + window.AddRow( + PopupButton(custom_text[0], size=(len(custom_text[0]), 1), button_color=button_color, focus=True, + bind_return_key=True)) + else: + window.AddRow(PopupButton(custom_text[0], button_color=button_color, focus=True, bind_return_key=True, + size=(len(custom_text[0]), 1)), + PopupButton(custom_text[1], button_color=button_color, size=(len(custom_text[0]), 1))) + elif button_type is POPUP_BUTTONS_YES_NO: + window.AddRow(PopupButton('Yes', button_color=button_color, focus=True, bind_return_key=True, pad=((20, 5), 3), + size=(5, 1)), PopupButton('No', button_color=button_color, size=(5, 1))) + elif button_type is POPUP_BUTTONS_CANCELLED: + window.AddRow( + PopupButton('Cancelled', button_color=button_color, focus=True, bind_return_key=True, pad=((20, 0), 3))) + elif button_type is POPUP_BUTTONS_ERROR: + window.AddRow(PopupButton('Error', size=(6, 1), button_color=button_color, focus=True, bind_return_key=True, + pad=((20, 0), 3))) + elif button_type is POPUP_BUTTONS_OK_CANCEL: + window.AddRow(PopupButton('OK', size=(6, 1), button_color=button_color, focus=True, bind_return_key=True), + PopupButton('Cancel', size=(6, 1), button_color=button_color)) + elif button_type is POPUP_BUTTONS_NO_BUTTONS: + pass + else: + window.AddRow(PopupButton('OK', size=(5, 1), button_color=button_color, focus=True, bind_return_key=True, + pad=((20, 0), 3))) + + if non_blocking: + button, values = window.Read(timeout=0) + else: + button, values = window.Read() + window.Close() + return button + + +# ============================== MsgBox============# +# Lazy function. Same as calling Popup with parms # +# This function WILL Disappear perhaps today # +# ==================================================# +# MsgBox is the legacy call and should not be used any longer +def MsgBox(*args): + raise DeprecationWarning('MsgBox is no longer supported... change your call to Popup') + + +# --------------------------- PopupNoButtons --------------------------- +def PopupNoButtons(*args, button_color=None, background_color=None, text_color=None, auto_close=False, + auto_close_duration=None, non_blocking=False, icon=DEFAULT_WINDOW_ICON, line_width=None, font=None, + no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)): + """ + Show a Popup but without any buttons + :param args: + :param button_color: + :param background_color: + :param text_color: + :param auto_close: + :param auto_close_duration: + :param non_blocking: + :param icon: + :param line_width: + :param font: + :param no_titlebar: + :param grab_anywhere: + :param keep_on_top: + :param location: + :return: + """ + Popup(*args, button_color=button_color, background_color=background_color, text_color=text_color, + button_type=POPUP_BUTTONS_NO_BUTTONS, + auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon, + line_width=line_width, + font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) + + +# --------------------------- PopupNonBlocking --------------------------- +def PopupNonBlocking(*args, button_type=POPUP_BUTTONS_OK, button_color=None, background_color=None, text_color=None, + auto_close=False, auto_close_duration=None, non_blocking=True, icon=DEFAULT_WINDOW_ICON, + line_width=None, font=None, no_titlebar=False, grab_anywhere=False, keep_on_top=False, + location=(None, None)): + """ + Show Popup box and immediately return (does not block) + :param args: + :param button_type: + :param button_color: + :param background_color: + :param text_color: + :param auto_close: + :param auto_close_duration: + :param non_blocking: + :param icon: + :param line_width: + :param font: + :param no_titlebar: + :param grab_anywhere: + :param keep_on_top: + :param location: + :return: + """ + Popup(*args, button_color=button_color, background_color=background_color, text_color=text_color, + button_type=button_type, + auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon, + line_width=line_width, + font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) + + +PopupNoWait = PopupNonBlocking + + +# --------------------------- PopupQuick - a NonBlocking, Self-closing Popup --------------------------- +def PopupQuick(*args, button_type=POPUP_BUTTONS_OK, button_color=None, background_color=None, text_color=None, + auto_close=True, auto_close_duration=2, non_blocking=True, icon=DEFAULT_WINDOW_ICON, line_width=None, + font=None, no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)): + """ + Show Popup box that doesn't block and closes itself + :param args: + :param button_type: + :param button_color: + :param background_color: + :param text_color: + :param auto_close: + :param auto_close_duration: + :param non_blocking: + :param icon: + :param line_width: + :param font: + :param no_titlebar: + :param grab_anywhere: + :param keep_on_top: + :param location: + :return: + """ + Popup(*args, button_color=button_color, background_color=background_color, text_color=text_color, + button_type=button_type, + auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon, + line_width=line_width, + font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) + + +# --------------------------- PopupQuick - a NonBlocking, Self-closing Popup with no titlebar and no buttons --------------------------- +def PopupQuickMessage(*args, button_type=POPUP_BUTTONS_NO_BUTTONS, button_color=None, background_color=None, + text_color=None, + auto_close=True, auto_close_duration=2, non_blocking=True, icon=DEFAULT_WINDOW_ICON, + line_width=None, + font=None, no_titlebar=True, grab_anywhere=False, keep_on_top=False, location=(None, None)): + """ + Show Popup box that doesn't block and closes itself + :param args: + :param button_type: + :param button_color: + :param background_color: + :param text_color: + :param auto_close: + :param auto_close_duration: + :param non_blocking: + :param icon: + :param line_width: + :param font: + :param no_titlebar: + :param grab_anywhere: + :param keep_on_top: + :param location: + :return: + """ + Popup(*args, button_color=button_color, background_color=background_color, text_color=text_color, + button_type=button_type, + auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon, + line_width=line_width, + font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) + + +# --------------------------- PopupNoTitlebar --------------------------- +def PopupNoTitlebar(*args, button_type=POPUP_BUTTONS_OK, button_color=None, background_color=None, text_color=None, + auto_close=False, auto_close_duration=None, non_blocking=False, icon=DEFAULT_WINDOW_ICON, + line_width=None, font=None, grab_anywhere=True, keep_on_top=False, location=(None, None)): + """ + Display a Popup without a titlebar. Enables grab anywhere so you can move it + :param args: + :param button_type: + :param button_color: + :param background_color: + :param text_color: + :param auto_close: + :param auto_close_duration: + :param non_blocking: + :param icon: + :param line_width: + :param font: + :param grab_anywhere: + :param keep_on_top: + :param location: + :return: + """ + Popup(*args, button_color=button_color, background_color=background_color, text_color=text_color, + button_type=button_type, + auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon, + line_width=line_width, + font=font, no_titlebar=True, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) + + +PopupNoFrame = PopupNoTitlebar +PopupNoBorder = PopupNoTitlebar +PopupAnnoying = PopupNoTitlebar + + +# --------------------------- PopupAutoClose --------------------------- +def PopupAutoClose(*args, button_type=POPUP_BUTTONS_OK, button_color=None, background_color=None, text_color=None, + auto_close=True, auto_close_duration=None, non_blocking=False, icon=DEFAULT_WINDOW_ICON, + line_width=None, font=None, no_titlebar=False, grab_anywhere=False, keep_on_top=False, + location=(None, None)): + """ + Popup that closes itself after some time period + :param args: + :param button_type: + :param button_color: + :param background_color: + :param text_color: + :param auto_close: + :param auto_close_duration: + :param non_blocking: + :param icon: + :param line_width: + :param font: + :param no_titlebar: + :param grab_anywhere: + :param keep_on_top: + :param location: + :return: + """ + Popup(*args, button_color=button_color, background_color=background_color, text_color=text_color, + button_type=button_type, + auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon, + line_width=line_width, + font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) + + +PopupTimed = PopupAutoClose + + +# --------------------------- PopupError --------------------------- +def PopupError(*args, button_color=DEFAULT_ERROR_BUTTON_COLOR, background_color=None, text_color=None, auto_close=False, + auto_close_duration=None, non_blocking=False, icon=DEFAULT_WINDOW_ICON, line_width=None, font=None, + no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)): + """ + Popup with colored button and 'Error' as button text + :param args: + :param button_color: + :param background_color: + :param text_color: + :param auto_close: + :param auto_close_duration: + :param non_blocking: + :param icon: + :param line_width: + :param font: + :param no_titlebar: + :param grab_anywhere: + :param keep_on_top: + :param location: + :return: + """ + Popup(*args, button_type=POPUP_BUTTONS_ERROR, background_color=background_color, text_color=text_color, + non_blocking=non_blocking, icon=icon, line_width=line_width, button_color=button_color, auto_close=auto_close, + auto_close_duration=auto_close_duration, font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, + keep_on_top=keep_on_top, location=location) + + +# --------------------------- PopupCancel --------------------------- +def PopupCancel(*args, button_color=None, background_color=None, text_color=None, auto_close=False, + auto_close_duration=None, non_blocking=False, icon=DEFAULT_WINDOW_ICON, line_width=None, font=None, + no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)): + """ + Display Popup with "cancelled" button text + :param args: + :param button_color: + :param background_color: + :param text_color: + :param auto_close: + :param auto_close_duration: + :param non_blocking: + :param icon: + :param line_width: + :param font: + :param no_titlebar: + :param grab_anywhere: + :param keep_on_top: + :param location: + :return: + """ + Popup(*args, button_type=POPUP_BUTTONS_CANCELLED, background_color=background_color, text_color=text_color, + non_blocking=non_blocking, icon=icon, line_width=line_width, button_color=button_color, auto_close=auto_close, + auto_close_duration=auto_close_duration, font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, + keep_on_top=keep_on_top, location=location) + + +# --------------------------- PopupOK --------------------------- +def PopupOK(*args, button_color=None, background_color=None, text_color=None, auto_close=False, + auto_close_duration=None, non_blocking=False, icon=DEFAULT_WINDOW_ICON, line_width=None, font=None, + no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)): + """ + Display Popup with OK button only + :param args: + :param button_color: + :param background_color: + :param text_color: + :param auto_close: + :param auto_close_duration: + :param non_blocking: + :param icon: + :param line_width: + :param font: + :param no_titlebar: + :param grab_anywhere: + :param keep_on_top: + :param location: + :return: + """ + Popup(*args, button_type=POPUP_BUTTONS_OK, background_color=background_color, text_color=text_color, + non_blocking=non_blocking, icon=icon, line_width=line_width, button_color=button_color, auto_close=auto_close, + auto_close_duration=auto_close_duration, font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, + keep_on_top=keep_on_top, location=location) + + +# --------------------------- PopupOKCancel --------------------------- +def PopupOKCancel(*args, button_color=None, background_color=None, text_color=None, auto_close=False, + auto_close_duration=None, non_blocking=False, icon=DEFAULT_WINDOW_ICON, line_width=None, font=None, + no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)): + """ + Display popup with OK and Cancel buttons + :param args: + :param button_color: + :param background_color: + :param text_color: + :param auto_close: + :param auto_close_duration: + :param non_blocking: + :param icon: + :param line_width: + :param font: + :param no_titlebar: + :param grab_anywhere: + :param keep_on_top: + :param location: + :return: OK, Cancel or None + """ + return Popup(*args, button_type=POPUP_BUTTONS_OK_CANCEL, background_color=background_color, text_color=text_color, + non_blocking=non_blocking, icon=icon, line_width=line_width, button_color=button_color, + auto_close=auto_close, auto_close_duration=auto_close_duration, font=font, no_titlebar=no_titlebar, + grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) + + +# --------------------------- PopupYesNo --------------------------- +def PopupYesNo(*args, button_color=None, background_color=None, text_color=None, auto_close=False, + auto_close_duration=None, non_blocking=False, icon=DEFAULT_WINDOW_ICON, line_width=None, font=None, + no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)): + """ + Display Popup with Yes and No buttons + :param args: + :param button_color: + :param background_color: + :param text_color: + :param auto_close: + :param auto_close_duration: + :param non_blocking: + :param icon: + :param line_width: + :param font: + :param no_titlebar: + :param grab_anywhere: + :param keep_on_top: + :param location: + :return: Yes, No or None + """ + return Popup(*args, button_type=POPUP_BUTTONS_YES_NO, background_color=background_color, text_color=text_color, + non_blocking=non_blocking, icon=icon, line_width=line_width, button_color=button_color, + auto_close=auto_close, auto_close_duration=auto_close_duration, font=font, no_titlebar=no_titlebar, + grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) + + +############################################################################## +# The PopupGet_____ functions - Will return user input # +############################################################################## + +# --------------------------- PopupGetFolder --------------------------- + + +def PopupGetFolder(message, default_path='', no_window=False, size=(None, None), button_color=None, + background_color=None, text_color=None, icon=DEFAULT_WINDOW_ICON, font=None, no_titlebar=False, + grab_anywhere=False, keep_on_top=False, location=(None, None), initial_folder=None): + """ + Display popup with text entry field and browse button. Browse for folder + :param message: + :param default_path: + :param no_window: + :param size: + :param button_color: + :param background_color: + :param text_color: + :param icon: + :param font: + :param no_titlebar: + :param grab_anywhere: + :param keep_on_top: + :param location: + :return: Contents of text field. None if closed using X or cancelled + """ + + global _my_windows + + if no_window: + if _my_windows._NumOpenWindows: + root = tk.Toplevel() + else: + root = tk.Tk() + try: + root.attributes('-alpha', 0) # hide window while building it. makes for smoother 'paint' + except: + pass + folder_name = tk.filedialog.askdirectory() # show the 'get folder' dialog box + root.destroy() + return folder_name + + layout = [[Text(message, auto_size_text=True, text_color=text_color, background_color=background_color)], + [InputText(default_text=default_path, size=size, key='_INPUT_'), FolderBrowse(initial_folder=initial_folder)], + [Button('Ok', size=(5, 1), bind_return_key=True), Button('Cancel', size=(5, 1))]] + + window = Window(title=message, layout=layout, icon=icon, auto_size_text=True, button_color=button_color, + background_color=background_color, + font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, + location=location) + + button, values = window.Read() + window.Close() + if button != 'Ok': + return None + else: + path = values['_INPUT_'] + return path + + +# --------------------------- PopupGetFile --------------------------- + +def PopupGetFile(message, default_path='', default_extension='', save_as=False, file_types=(("ALL Files", "*.*"),), + no_window=False, size=(None, None), button_color=None, background_color=None, text_color=None, + icon=DEFAULT_WINDOW_ICON, font=None, no_titlebar=False, grab_anywhere=False, keep_on_top=False, + location=(None, None), initial_folder=None): + """ + Display popup with text entry field and browse button. Browse for file + :param message: + :param default_path: + :param default_extension: + :param save_as: + :param file_types: + :param no_window: + :param size: + :param button_color: + :param background_color: + :param text_color: + :param icon: + :param font: + :param no_titlebar: + :param grab_anywhere: + :param keep_on_top: + :param location: + :return: string representing the path chosen, None if cancelled or window closed with X + """ + + global _my_windows + + if no_window: + if _my_windows._NumOpenWindows: + root = tk.Toplevel() + else: + root = tk.Tk() + try: + root.attributes('-alpha', 0) # hide window while building it. makes for smoother 'paint' + except: + pass + if save_as: + filename = tk.filedialog.asksaveasfilename(filetypes=file_types, + defaultextension=default_extension) # show the 'get file' dialog box + else: + filename = tk.filedialog.askopenfilename(filetypes=file_types, + defaultextension=default_extension) # show the 'get file' dialog box + root.destroy() + return filename + + browse_button = SaveAs(file_types=file_types, initial_folder=initial_folder) if save_as else FileBrowse( + file_types=file_types, initial_folder=initial_folder) + + layout = [[Text(message, auto_size_text=True, text_color=text_color, background_color=background_color)], + [InputText(default_text=default_path, size=size, key='_INPUT_'), browse_button], + [Button('Ok', size=(6, 1), bind_return_key=True), Button('Cancel', size=(6, 1))]] + + window = Window(title=message, layout = layout, icon=icon, auto_size_text=True, button_color=button_color, font=font, + background_color=background_color, + no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) + + button, values = window.Read() + window.Close() + if button != 'Ok': + return None + else: + path = values['_INPUT_'] + return path + + + +# --------------------------- PopupGetText --------------------------- + +def PopupGetText(message, default_text='', password_char='', size=(None, None), button_color=None, + background_color=None, text_color=None, icon=DEFAULT_WINDOW_ICON, font=None, no_titlebar=False, + grab_anywhere=False, keep_on_top=False, location=(None, None)): + """ + Display Popup with text entry field + :param message: + :param default_text: + :param password_char: + :param size: + :param button_color: + :param background_color: + :param text_color: + :param icon: + :param font: + :param no_titlebar: + :param grab_anywhere: + :param keep_on_top: + :param location: + :return: Text entered or None if window was closed + """ + + layout = [[Text(message, auto_size_text=True, text_color=text_color, background_color=background_color, font=font)], + [InputText(default_text=default_text, size=size, key='_INPUT_', password_char=password_char)], + [Button('Ok', size=(5, 1), bind_return_key=True), Button('Cancel', size=(5, 1))]] + + window = Window(title=message, layout=layout, icon=icon, auto_size_text=True, button_color=button_color, no_titlebar=no_titlebar, + background_color=background_color, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, + location=location) + + button, values = window.Read() + window.Close() + if button != 'Ok': + return None + else: + path = values['_INPUT_'] + return path + + +change_look_and_feel = ChangeLookAndFeel +easy_print = EasyPrint +easy_print_close = EasyPrintClose +get_complimentary_hex = GetComplimentaryHex +list_of_look_and_feel_values = ListOfLookAndFeelValues +obj_to_string = ObjToString +obj_to_string_single_obj = ObjToStringSingleObj +one_line_progress_meter = OneLineProgressMeter +one_line_progress_meter_cancel = OneLineProgressMeterCancel +popup = Popup +popup_annoying = PopupAnnoying +popup_auto_close = PopupAutoClose +popup_cancel = PopupCancel +popup_error = PopupError +popup_get_file = PopupGetFile +popup_get_folder = PopupGetFolder +popup_get_text = PopupGetText +popup_no_border = PopupNoBorder +popup_no_buttons = PopupNoButtons +popup_no_frame = PopupNoFrame +popup_no_titlebar = PopupNoTitlebar +popup_no_wait = PopupNoWait +popup_non_blocking = PopupNonBlocking +popup_ok = PopupOK +popup_ok_cancel = PopupOKCancel +popup_quick = PopupQuick +popup_quick_message = PopupQuickMessage +popup_scrolled = PopupScrolled +popup_timed = PopupTimed +popup_yes_no = PopupYesNo +print_close = PrintClose +rgb = RGB +scrolled_text_box = ScrolledTextBox +set_global_icon = SetGlobalIcon +set_options = SetOptions +timer_start = TimerStart +timer_stop = TimerStop +sprint = sprint + +#------------------------ Set the "Official PySimpleGUI Theme Colors" ------------------------ +theme(CURRENT_LOOK_AND_FEEL) +# theme_previewer() +# -------------------------------- ENTRY POINT IF RUN STANDALONE -------------------------------- # + + + + +def main(): + # ChangeLookAndFeel('light green 6' ) + + # Popup('Popup Test') + + # SetOptions(background_color='blue', text_element_background_color='blue', text_color='white') + # layout = [[Text('You are running the PySimpleGUI.py file itself', font='Any 25', size=(60,1), tooltip='My tooltip!')], + # [Text('You should be importing it rather than running it', size=(60, 1))], + # [Text('Here is your sample window....')], + # [Text('Source Folder', justification='right', size=(40,1)), InputText('Source', focus=True, disabled=True), + # FolderBrowse()], + # [Text('Destination Folder', justification='right', size=(40,1)), InputText('Dest'), FolderBrowse()], + # [Ok(), Cancel(disabled=True), Exit(tooltip='Exit button'), Button('Hidden Button', visible=False)]] + + ver = version.split('\n')[0] + + + def VerLine(version, description, size=(30,1)): + return [Column([[T(description, font='Courier 18', text_color='yellow')], [T(version, font='Courier 18', size=size)]])] + + + menu_def = [['&File', ['&Open', '&Save', 'E&xit', 'Properties']], + ['&Edit', ['Paste', ['Special', 'Normal', ], '!Undo'], ], + ['!&Disabled', ['Paste', ['Special', 'Normal', ], '!Undo'], ], + ['&Help', '&About...'], ] + + + menu_def = [['File', ['&Open::mykey', '&Save', 'E&xit', 'Properties']], + ['Edit', ['!Paste', ['Special', 'Normal', ], '!Undo'], ], + ['!Disabled', ['Has Sub', ['Item1', 'Item2', ], 'No Sub'], ], + ['Help', 'About...'], ] + + col1 = [[Text('Column 1 line 1', background_color='red')], [Text('Column 1 line 2')]] + + layout = [ + [Menu(menu_def, key='_MENU_', text_color='yellow', background_color='#475841', font='Courier 14')], + # [T('123435', size=(1,8))], + [Text('PySimpleGUIWeb Welcomes You...', tooltip='text', font=('Comic sans ms', 20),size=(40,1), text_color='yellow', enable_events=False, key='_PySimpleGUIWeb_')], + # [OptionMenu([])], + [T('System platform = %s'%sys.platform)], + [Image(data=DEFAULT_BASE64_ICON, enable_events=False)], + # [Image(filename=r'C:\Python\PycharmProjects\PSG\logo500.png', key='-IMAGE-')], + VerLine(ver, 'PySimpleGUI Version'), + VerLine(os.path.dirname(os.path.abspath(__file__)), 'PySimpleGUI Location'), + VerLine(sys.version, 'Python Version', size=(60,2)), + VerLine(pkg_resources.get_distribution("remi").version, 'Remi Version'), + # [Text('VERSION {}'.format(version), text_color='red', font='Courier 24')], + [T('Current Time '), Text('Text', key='_TEXT_', font='Arial 18', text_color='black', size=(30,1)), Column(col1, background_color='red')], + [T('Up Time'), Text('Text', key='_TEXT_UPTIME_', font='Arial 18', text_color='black', size=(30,1))], + [Input('Single Line Input', do_not_clear=True, enable_events=False, size=(30, 1), text_color='red', key='_IN_')], + [Multiline('Multiline Input', do_not_clear=True, size=(40, 4), enable_events=False, key='_MULTI_IN_')], + # [Output(size=(60,10))], + [MultilineOutput('Multiline Output', size=(80, 8), text_color='blue', font='Courier 12', key='_MULTIOUT_', autoscroll=True)], + [Checkbox('Checkbox 1', enable_events=True, key='_CB1_'), Checkbox('Checkbox 2', default=True, key='_CB2_', enable_events=True)], + [Combo(values=['Combo 1', 'Combo 2', 'Combo 3'], default_value='Combo 2', key='_COMBO_', enable_events=True, + readonly=False, tooltip='Combo box', disabled=False, size=(12, 1))], + [Listbox(values=('Listbox 1', 'Listbox 2', 'Listbox 3'), enable_events =True, size=(10, 3), key='_LIST_')], + # [Image(filename=r'C:\Python\PycharmProjects\PSG\logo200.png', enable_events=False)], + [Slider((1, 100), default_value=80, key='_SLIDER_', visible=True, enable_events=True, orientation='v')], + [Spin(values=(1, 2, 3), initial_value='2', size=(4, 1), key='_SPIN_', enable_events=True)], + [OK(), Button('Hidden', visible=False, key='_HIDDEN_'), Button('Values'), Button('Exit', button_color=('white', 'red')), Button('UnHide'), B('Popup')] + ] + + window = Window('PySimpleGUIWeb Test Harness Window', layout, + font='Arial 18', + icon=DEFAULT_BASE64_ICON, + default_element_size=(12,1), + auto_size_buttons=False) + + start_time = datetime.datetime.now() + while True: + event, values = window.Read(timeout=100) + window.Element('_TEXT_').Update(str(datetime.datetime.now())) + window.Element('_TEXT_UPTIME_').Update(str(datetime.datetime.now()-start_time)) + print(event, values) if event != TIMEOUT_KEY else None + if event in (None, 'Exit'): + break + elif event == 'OK': + + window.Element('_MULTIOUT_').print('You clicked the OK button') + # window.Element('_MULTIOUT_').Update('You clicked the OK button', append=True, autoscroll=True) + window.Element('_PySimpleGUIWeb_').Widget.style['background-image'] = "url('/my_resources:mine.png')" + + elif event == 'Values': + window.Element('_MULTIOUT_').Update(str(values)+'\n', append=True) + # nav = remi.gui.FileFolderNavigator(False,r'a:\TEMP', True, False) + # here is returned the Input Dialog widget, and it will be shown + # fileselectionDialog.show(window.Element('_IN_').Widget) + + elif event != TIMEOUT_KEY: + window.Element('_MULTIOUT_').print('EVENT: ' + str(event)) + if event == 'Popup': + Popup('This is a popup!') + if event == 'UnHide': + print('Unhiding...') + window.Element('_HIDDEN_').Update(visible=True) + + window.Close() + + +if __name__ == '__main__': + main() + exit(0) diff --git a/PySimpleGUIWeb/readme.md b/PySimpleGUIWeb/readme.md new file mode 100644 index 000000000..5f18865a5 --- /dev/null +++ b/PySimpleGUIWeb/readme.md @@ -0,0 +1,501 @@ + +![pysimplegui_logo](https://user-images.githubusercontent.com/13696193/43165867-fe02e3b2-8f62-11e8-9fd0-cc7c86b11772.png) + +![Downloads](http://pepy.tech/badge/pysimpleguiweb) + + + ![Awesome Meter](https://img.shields.io/badge/Awesome_meter-10,000-yellow.svg) + + ![Python Version](https://img.shields.io/badge/Python-3.x-yellow.svg) + + +[![PyPI Version](https://img.shields.io/pypi/v/pysimpleguiweb.svg?style=for-the-badge)](https://pypi.org/project/pysimpleguiweb/) + +# PySimpleGUIWeb + +PySimpleGUI running in your web browser! + +Your source code will work on tkinter, Qt, WxPython and now in a browser (thanks to Remi) + +Check out [repl.it](https://repl.it/@PySimpleGUI/PySimpleGUIWeb-Demos), the new way to run your PySimpleGUI code in a browser! + +## Primary PySimpleGUI Documentation + +To get instructions on how use PySimpleGUI's APIs, please reference the [main documentation](http://www.PySimpleGUI.org). +This Readme is for information ***specific to*** the Web port of PySimpleGUI. + + +## What is PySimpleGUIWeb? + +PySimpleGUIWeb enables you to run your PySimpleGUI programs in your web browser. It utilizes a package called Remi to achieve this amazing package. + + +## Engineering Pre-Release + +Be aware you are running a "Pre-Rlease" version of PySimpleGUIWeb. This means sh*t doesn't work in many places. This also means that you get to have fun with the many things that DO work and that are being added to every week. + + [Announcements of Latest Developments](https://github.com/MikeTheWatchGuy/PySimpleGUI/issues/142) + + +Having trouble? Visit the [GitHub site ](http://www.PySimpleGUI.com) and log an Issue. + + + +## Installation + +Installation is quite simple: + +`pip install pysimpleguiweb` + +Should this not work, you can copy and paste the file PySimpleGUIWeb.py into your application folder. + +## Using PySimpleGUIWeb + +There are a lot of examples in the PySimpleGUI Cookbook as well as on the GitHub site. At the moment very few will work due to the limited number of features of the 0.1.0 release. It shouldn't be too long before they'll work. + +To use PySimpleGUIWeb you need to import it: +`import PySimpleGUIWeb as sg` + +From there follow the code examples in the Cookbook and the Demo Programs. The only difference in those programs is the import statement. The remainder of the code should work without modification. + + +## Requirements + +PySimpleGUIWeb is based on the Remi project. You will need to install Remi prior to running PySimpleGUIWeb: + +`pip install remi` + +You can learn more about Remi on its homepage. + +https://github.com/dddomodossola/remi + +PySimpleGUIWeb runs only on Python 3. Legacy Python (2.7) is not supported. + + +## What Works + +* Text Element +* Input Text Element +* Button Element +* Combobox Element +* Checkbox Element +* Listbox Element +* Spinner Element (sorta... numbers 0 to 100 only now) +* Column Element +* Image Element +* Multiline Input Element +* Multiline Output Element +* Output Element (redirect STDOUT) +* Graph Element (your canvas to paint on) +* Table Element (yes, tables! even if limited) +* Window background color +* Element padding +* Read with timeout +* Read with timeout = 0 +* Popup Windows +* Multiple windows +* Update methods for many of the elements (Text is 100% complete), others have some of their parameters working. + + +# Running online using repl.it + +This is something truly unique and amazing. You can run your PySimpleGUI code in a web browser on a computer, phone, tablet without having Python installed on that computer. Through the magic of repl.it and Remi you can run PySimpleGUI code anywhere you can run a browser. Not only that, but you can embed these programs into web pages. In fact, this markdown document has one of these programs embedded in it. + +Here is where the iframe is inserted. You may not see the page in some instances (like on GitHub). + +Here's your sample program: + + + +# Release Notes: + +## 0.1.0 PySimpleGUIWeb 22-Jan-2019 + +* Initial release +* Text Element +* Input Text Element +* Button Element +* Window class + + +## 0.2.0 PySimpleGUIWeb 23-Jan-2019 + +Day 2 of development brings fonts, sizes, and colors... + +* For all elements (Text, Input Text, Button): + * Font family + * Font size + * Text Color + * Background Color + * Disable + * Size +* Button Color +* Read timeouts (zero, non-zero, None/pend) +* Window close +* Window background color + +## 0.3.0 PySimpleGUIWeb 24-Jan-2019 + +* Checkbox Element +* Combobox Element +* Listbox Element +* Element padding for all elements + +## 0.4.0 PySimpleGUIWeb 26-Jan-2019 + +Functioning Elements +* Text +* Single line text input +* Multiline Input +* Multiline Output +* Listbox +* Combobox +* Checkbox +* Slider +* Spinner (numbers only...hardcoded to 0 to 100) + +New features +* Tooltips for all elements (so cool this works) +* Input Text events +* Text clicked event +* Listbox selected event +* Combobox selected event +* Checkbox Update +* Disable parameter for all elements +* Window.Close shuts down the server +* Enabled exceptions during packing operation +* New test harness exercises all element types + +## 0.5.0 PySimpleGUIWeb 1-Feb-2019 + +* New default font size. Was Helvetica 10, now Helvetica 15 +* InputText Element single character events working! (Finally) +* Listbox simple Update (values only) +* Column Element! New! +* Column element experimental justification setting doesn't work yet +* Element background colors now picked up from container, not top level window +* Autosize Text +* Autosize Button Text + + +## 0.6.0 PySimpleGUIWeb 3-Feb-2019 + +* Changed Remi port to 0 so will always get a new free port + +## 0.7.0 PySimpleGUIWeb 3-Feb-2019 + +* Completed `InputText.Update` method so that more demos can be run + +## 0.8.0 PySimpleGUIWeb 8-Feb-2019 + +* Popup support! +* Support for multiple windows + +## 0.9.0 PySimpleGUIWeb 14-Feb-2019 + +* Support for Window.Hide, Window.UnHide (better multi-window support) + +## 0.9.1 PySimpleGUIWeb + +* Emergency release due to some code to do scrolling of multiline not being right and sometimes crashed programs + +## 0.10.0 PySimpleGUIWeb 16-Feb-2019 + +* Completed Text.Update method. Can now change: + * Text + * Font family & size + * Background color + * Text Color + * Visibility +* Completed Button.Update with exception of images +* Completed Spin.Update with except of range. This element still pretty crippled +* Completed Slider.Update - Can update value, visibility, disabled, but not the range +* Image Element! +* Events for Image Element +* Image.Update to change image + +## 0.11.0 PySimpleGUIWeb 25-Feb-2019 + +* Slider - Can update range using .Update method +* NEW Window paramters that allow control over all Remi startup settings +* New Window paramters and default values: + * web_debug=False + * web_ip='0.0.0.0' + * web_port=0 + * web_start_broswer=True + * web_update_interval=.00001 +* Can set the Window backaground image (sorta works sometimes) + * Struggling to get the "resources" settings understood so can work with files + * I have a ways to go + +## 0.12.0 PySimpleGUIWeb 28-Feb-2019 + +* Combo.Update now fully functional + + +## 0.13.0 PySimpleGUIWeb 5-Mar-2019 + +* Added new parameter to Window - web_multiple_instance + * Like other Window web parameters, this value is passsed Remi upon start + * The default value is TRUE (Previously I think default was False by Remi) + * Was made as a result of comment on repl.it. + +## 0.15.0 PySimpleGUIWeb 5-Mar-2019 + +* Made the multiple_instance parameter FALSE by default (was messing up badly with True) + +## 0.16.0 13-Mar-2019 + +* TABLES! + * The bare minimum, basic tables are supported + * Things like alternating colors are not done + * Enabling Events DOES work so that you can get immediate clicks + * Value returned is a list of 1ength 1 and contains the value of the cell that was clicked +* Removed use of CloseButton from Popups + +## 0.17.0 14-Mar-2019 + +* More Table features supported + * Option to display row numbers + * New parameter `row_header_text` + * Can turn on / off displaying row numbers + * `enable_events` + * `text_color` + * Font + * Can get the value of the item clicked using Table.SelectedItem. Can be coded as window.Element('_table_').SelectedItem + + +## 0.18.0 15-Mar-2019 + +* Hotfix for bug that causes Popups / secondary windows to crash +* Table gets `starting_row_num` parameter + +## 0.19.0 23-Mar-2019 PySimpleGUIWeb + +* do_not_clear defaults to TRUE! for Input and Multiline Input/output +* a few type hints + +## 0.20.0 07-Apr-2019 PySimpleGUIWeb + +* Output Element WORKS!! Can re-route stdout to window +* Added Idle function to Remi MyApp for stdout re-route (thanks Davide!!) +* New Shortcuts: + * I = InputText + * B = Btn = Butt = Button +* Removed temp size in Multiline setup +* Button - convert button text passed in into a string +* Added support for base64 Images in Image.Update but it's not working! Don't use! +* Changed web_update_interval=.0000001 from 0 (YIKES I HOPE SOMETHING DIDN'T BREAK!) + + +## 0.21.0 10-Apr-2019 PySimpleGUIWeb + +* If `disable_close` parameter set in Window call, then Remi will not disconnect when browser closed. Great for reconnecting. + + +## 0.22.0 11-Apr-2019 PySimpleGUIWeb + +* NEW Window parameter layout so can skip calling Layout + +## 0.23.0 21-Apr-2019 PySimpleGUIWeb + +* GRAPH ELEMENT almost done! + * DrawLine + * DrawRectangle + * DrawPoint + * DrawCicle + * DrawText + * Erase + * Move + * MoveFigure (by a delta amount) + * RelocateFigure (draw to a new spot) + * Update - for background color change + * Enable events works for single clicks (no drags yet) +* Changed Image element to use SuperImage class + * Image element works better? + * Base64 not yet working + +## 0.23.1 21-Apr-2019 +One-time patch to remove a debug print + +# 0.24.0 PySimpleGUIWeb 23-Apr-2019 + +* Enabled SuperImage class to accept base64 imagees +* Now use an SvgGroup to hold all of the drawing items +* Circle can now set outline color +* DrawImage still isn't working +* Move isn't working +* Added Relocate for group +* Lazy buttons - Up, Down, Left, Right(() + * Creates buttons with arrows on them as text +* Base64 support for Image Element + + +## 0.25.0 PySimpleGUIWeb 25-Apr-19 + +* DrawImage method WORKS! DrawImage now takes BOTH filenames and base64 variables +* Fix for DrawRectangle (wasn't passing the right parms) + +## 0.26.0 PySimpleGUIWeb 1-May-2019 + +* Combo - converts values into a list of strings +* Image.Update is working with both filename and base64 (but no size controls yet) +* Window - new parameter - return_key_down_events. Normally it's key up events that are returned from Read calls +* Returning keyboard input works! +* Turned off Remi Logging completely (may be a bad idea. can change it back) +* Rearranged code so that same code is used for first window and following windows +* Window disable_close parameter controls wether or not server keeps running after user disconnects + +## 0.27.0 PySimpleGUIWeb 8-May-2019 + +* Changed default icon from string to bytes +* New Text Update to match newer call parameters +* Added image_subsample, image_size parms to be backward compat. Note - not enabled +* SuperImage changes - load both base64 images and files +* Fix for DrawRectangle +* Added data parm to DrawImage +* Added DeleteFigure +* Tab Support + * Just barely beginning + * May or may not work +* Window new class variable - AllKeysDict + * Contains dictionary of all elements and keys + * Now used by FindElement / Element calls for quick lookup +* Fix for Column elements and rows that didn't line up. Changed tk_row_frame style +* Graph Element + * enable_events works + * drag events works + * click events works + + +## 0.28.1 PySimpleGUIWeb 15-May-2019 + +* Menus + * Yes, the full Menu Bar across the top of the window! + * PLUS, you get more controls to set the colors and fonts + * Works with menu keys too + * Disabled items are not working however + * Correctly returns menu events +* Listbox + * Correctly handling Update calls that change the list + * Correctly returns a LIST of items (even if only 1) +* Button Graphics! + * Can specify either a filename or image data as the source + * Update parameters image_data and image_filename work! +* Fix in DrawLine. Wasn't returning the id +* DrawRectangle fixes - transparent fill color is default. Correctly draws coordinates now +* DrawImage seems to work with both data and files +* enable_events parameter for TabGroups +* Frame Element + * Behaves like a Column element for now since no official Remi Frame +* Fix for popups that get data - New dictionary return values messed up popups. Needed to use keys internally + +## 0.31.0 PySimpleGUIWeb 04-Nov-2019 + +* PEP8 bindings! +* Window - NEW way of finding elements + * Use window[key] instead of window.FindElement(key)!! +* Winow - "calling" an existing window object will call its read method +* Version number added both dunder version and version work +* Renamed some variables to be private by adding _ to the front +* METADATA added to all elements and Window +* Ability to "call" an element. The effect is to call that element's update method +* Removed all delete functions in the classes. Were poorly done and not consistent +* Output element - fix for color defaults, CurrentValue contains all of the text currently shown +* Image Element + * Rewrite done by Remi team!!! + * Fixes flicker when using with OpenCV +* Removed quite a bit of unused code +* Added prints where items are not yet implemented +* Window - finalize parameter added +* Get screen dimensions always returns (0,0) for now until can figure it out +* Made return values computation easier +* Two new look and feel color settings - Material1, Material2 + +## 0.32.0 PySimpleGUIWeb 08-Nov-2019 + +* Fix for Output Element scrolling. Now cursor stays at end +* Fix for Multiline Output scrolling. Appends correctly and autoscrolls if enabled + +## 0.33.0 PySimpleGUIWeb 17-Nov-2019 + +* Added autoscroll parameter to the MultilineOutput.update method +* TONS of new Look and Feel Themes +* Fuzzy name matcher for change_loo_and_feel call - string doesn't have to perfectly match now +* New preview_all_look_and_feel_themes function displays all of the colors for the Themes + +## 0.34.0 PySimpleGUIWeb 24-Dec-2019 + +Themes + + +* New theme apis that replace the change_look_and_feel call (see primary PySimpleGUI port for more info) +* New default theme is Dark Blue 3 +* Added ported string so can tell this is the "PySimpleGUIWeb" port +* Removed platform specific code that was barring Macs from using colors, even for the web +* Changed "TRANSPARENT_BUTTON" string to invalidate it. It was misunderstood and should not bave been inlucded in anything +* Ability to change the files delimeter for browse files to filenames can have ; in them + + +## 0.35.0 PySimpleGUIWeb 16-Jan-2020 + +* Fixed Slider crash caused by latest Remi releaese +* Brought over latest Theme code from PySimpleGUI-tk (text background color, changed all black and white refs to hex) +* New Graph.change_coordinates method +* Removed check for no image specified in Image.update (so cal specify visibilty without changing image for example) + +## 0.36.0 PySimpleGUIWeb 20-Feb-2020 + +* Allow empty value to be specified when creating Image element +* Fix for Text element crashing following the Remi 2020.2.5 release + * Crash will show trying to use method "set_layout_orientation" + +## 0.37.0 PySimpleGUIWeb 14-Apr-2020 + +Catching up to latest Remi releases. + +* NO LONGER ADDING \n TO MULTILINE, MULTILINE_OUTPUT UPDATES + * This may cause some of your problems. Sorry about this, but it's the right thing to do so that prints work correctly +* Multiline.print capability +* MultilineOutput.print capability +* Fix for MultilineOutput not autoscrolling +* Fix for image update flicker +* Printing sep char fixed +* Fix for extra Tab +* Replaced SvgGroup with SvgSubcontainer (Requires Remi 2020.3.10) +* BIG Thank You owed to Remi creator Davide (for this and many other releases too) + + +## 0.38.0 PySimpleGUIWeb 6-May-2020 + +* Added constants + * WIN_CLOSED and WINDOW_CLOSED + * EVENT_TIMEOUT and TIMEOUT_EVENT + + + +## 0.39.0 PySimpleGUIWeb 6-Jun-2020 + +Element justification within Window and Containers! Finally a unified justification + +* Frame support, but without any labels yet.... only makes a frame... hey, it's a start +* element_jutification added so that all elements inside these will be justified accordingly. + * For PySimpleGUIQt only, the default is "float" which sets nothing. Buttons will stretch across the window as result + * Valid values are 'l', 'r', 'c'. You can spell it out, but only first letter is used. + * Window + * Frame + * Column + * Tab +* New main() that shows Remi version and more info + + +# Design + +# Author + Mike B. + + +# License + GNU Lesser General Public License (LGPL 3) + + +# Acknowledgments +This could not be possible without the Remi project! Thank you Remi!!!! diff --git a/PySimpleGUIWx/Demo Programs/Wx_Demo_Popups.py b/PySimpleGUIWx/Demo Programs/Wx_Demo_Popups.py new file mode 100644 index 000000000..2d0fd3197 --- /dev/null +++ b/PySimpleGUIWx/Demo Programs/Wx_Demo_Popups.py @@ -0,0 +1,43 @@ +import PySimpleGUIWx as sg +import sys +import time + +sg.Popup('Test'*10, title='My title') +# sg.Print('test', location=(400,200)) +# sg.PopupScrolled(sg.ObjToString(sg.Window), title='My scrolled popup', non_blocking=True) +# sg.Print('Outputting to another line\n') +sg.PopupNonBlocking('Issues changed on GitHub ', 'First issue # is {}'.format(1), background_color='red', + keep_on_top=False) +file = sg.PopupGetFile('Get file', save_as=False,file_types=(("ALL Files", "*.jpg"),), no_window=False) +folder = sg.PopupGetFolder('Getting a folder', no_window=False) +sg.Popup('Test'*10, title='My title') +sg.Print('file = ', file) +sg.Print('folder = ', folder) +sg.Print(file) +# sg.Print(file) +sg.PopupQuickMessage('This is a quick message', location=(1000,600)) +# Here, have some windows on me.... +[sg.PopupNoWait('No-wait Popup', location=(500+100*x,500)) for x in range(10)] + +answer = sg.PopupYesNo('Do not worry about all those open windows... they will disappear at the end', 'Are you OK with that?') +print('answer=',answer) +if answer == 'No': + # sg.PopupCancel('OK, we will destroy those windows as soon as you close this window', auto_close_duration=2, auto_close=True) + sys.exit() + +sg.PopupNonBlocking('Your answer was',answer, location=(1000,600)) + +text = sg.PopupGetText('This is a call to PopopGetText', location=(1000,200)) +print(text) +sg.PopupGetFile('Get file') +sg.PopupGetFolder('Get folder') + + +sg.Popup('Simple popup') + +sg.PopupNoTitlebar('No titlebar') +sg.PopupNoBorder('No border') +sg.PopupNoFrame('No frame') +sg.PopupCancel('Cancel') +sg.PopupOKCancel('OK Cancel') +sg.PopupAutoClose('Autoclose') diff --git a/PySimpleGUIWx/Demo Programs/Wx_Scrape_GitHub_Issues_System_Tray.py b/PySimpleGUIWx/Demo Programs/Wx_Scrape_GitHub_Issues_System_Tray.py new file mode 100644 index 000000000..97f13ce78 --- /dev/null +++ b/PySimpleGUIWx/Demo Programs/Wx_Scrape_GitHub_Issues_System_Tray.py @@ -0,0 +1,193 @@ +#!/usr/bin/env python +import PySimpleGUIWx as sg +import subprocess +import re +# Import requests (to download the page) +import requests +import datetime +import time + +# Import BeautifulSoup (to parse what we download) +from bs4 import BeautifulSoup + +# CCNSTANTS - CHANGE THESE TO MATCH YOUR SYSTEM +CHROME = r"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" +DISCORD = r"C:\Users\mike\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Discord Inc\Discord.lnk" +VIEW_ISSUES_URL = r'https://github.com/MikeTheWatchGuy/PySimpleGUI/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc' +PULL_REQUEST_URL = r'https://github.com/MikeTheWatchGuy/PySimpleGUI/compare/master...Dev-latest' +ANNOUCEMENTS = r'https://github.com/MikeTheWatchGuy/PySimpleGUI/issues/142' +TRAFFIC = r'https://github.com/MikeTheWatchGuy/PySimpleGUI/graphs/traffic' +SEARCH = r'https://github.com/search?o=desc&q=pysimplegui&s=indexed&type=Code' +PYPI_STATS = r'https://pepy.tech/project/pysimplegui' +ICON_FILE = r'C:\Python\PycharmProjects\GooeyGUI\default_icon.ico' + +# search github for total open issues and Issue Number of first issue +def get_num_issues(): + url = "https://github.com/MikeTheWatchGuy/PySimpleGUI/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc" + # set the headers like we are a browser, + headers = { + 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'} + # download the page + requests.adapters.DEFAULT_RETRIES = 25 + try: + response = requests.get(url, headers=headers) + except: + return 0,0 + # parse the downloaded homepage and grab all text, + soup = BeautifulSoup(response.text, "lxml") + # look for phrase "XXX Open" + # print(soup) + findopen = re.compile(r"\d+ Open") + # get number of open issues + number_open_string = findopen.search(str(soup)).group() + num_open_issues = number_open_string[0:number_open_string.index(' ')] + # find the first issue in the list by earing for "issue-id-XXXX" + soup = str(soup).replace('\n', '') + find_first_issue = re.compile(r'#\d+\s+opened') + first_issue_string = find_first_issue.search(str(soup)).group() + first_issue = first_issue_string[1:first_issue_string.find(' ')] + return num_open_issues, first_issue + + +def gui(): + sg.ChangeLookAndFeel('Topanga') + + sg.SetOptions(border_width=0) + + layout = [ + [sg.T('GitHub Issues Watcher' + 5 * ' ', click_submits=True, key='GitHub'), + sg.Button('', size=(25,25), + image_data=red_x, + key='_quit_',button_color=(sg.LOOK_AND_FEEL_TABLE['Topanga']['TEXT'],sg.LOOK_AND_FEEL_TABLE['Topanga']['BACKGROUND']), + tooltip='Closes window')], + [sg.T('', key='_status_', size=(12, 1))], + [sg.T('', key='_numissues_', size=(20, 1))], + ] + + window = sg.Window('Issue watcher', + no_titlebar=True, + grab_anywhere=True, + keep_on_top=True, + alpha_channel=.8, # dim the lights a little + location=(2360,310), # locate in upper right corner of screen + ).Layout(layout).Finalize() + + window.Refresh() + status_elem = window.FindElement('_status_') + issues_elem = window.FindElement('_numissues_') + + initial_issue_count, initial_first_issue = get_num_issues() + seconds = 0 + poll_frequncy = 1000 + + while True: + event, values = window.Read(timeout=poll_frequncy) + if event in ('_quit_', None): + break + if seconds % 60 == 0 or event.startswith('GitHub'): # Every 60 seconds read GitHub + status_elem.Update('Reading...') + window.Refresh() + issues, first_issue = get_num_issues() + if issues == 0 and first_issue == 0: + print('Read error', time.time()) + continue + issues_elem.Update('{} Issues. {} is first issue'.format(issues, first_issue)) + window.Refresh() + # if something changed, then make a popup + if issues != initial_issue_count or first_issue != initial_first_issue: + sg.PopupNoWait('Issues changed on GitHub ', 'First issue # is {}'.format(first_issue), background_color='red', keep_on_top=True) + initial_issue_count = issues + initial_first_issue = first_issue + status_elem.Update('') + else: + status_elem.Update('.' if seconds%2 else '') # blink a '.' every 2 seconds so know still running + + seconds += poll_frequncy/1000 + window.Close() + + + +def system_tray(): + + menu_def = ['Root', + ['E&xit']] + tray = sg.SystemTray(menu=menu_def, data_base64=logo, tooltip='GitHub Issue Watcher') + # tray = SystemTray(menu=menu_def, filename= ICON_FILE, tooltip='GitHub Issue Watcher') + + # tray.Hide() + initial_issue_count, initial_first_issue = get_num_issues() + tray.ShowMessage('Starting up...', '{} Issues\n{} First Issue'.format(initial_issue_count, initial_first_issue), + messageicon=sg.SYSTEM_TRAY_MESSAGE_ICON_CRITICAL, ) + issues = first_issue = 0 + # The Event Loop runs every 5000ms + poll_frequncy = 5000 + seconds = 0 + print('Starting', datetime.datetime.now()) + while True: + menu_item = tray.Read(timeout=poll_frequncy) + if menu_item == 'Exit': + break + if menu_item == 'Run GUI': + tray.Update(data_base64=red_x) + gui() + tray.Update(data_base64=logo) + elif menu_item.startswith('View Issues'): + sg.PopupNoWait('Refreshing issue data...', auto_close=True, auto_close_duration=3) + issues, first_issue = get_num_issues() + tray.ShowMessage('Refreshed', '{} Issues\n{} First Issue'.format(issues, first_issue), messageicon=sg.SYSTEM_TRAY_MESSAGE_ICON_INFORMATION, ) + sp = subprocess.Popen([CHROME, VIEW_ISSUES_URL], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + elif menu_item in('Refresh', sg.EVENT_SYSTEM_TRAY_ICON_DOUBLE_CLICKED): + tray.ShowMessage('Refreshing', 'Old values are\n{} Issues\n{} First Issue'.format(issues, first_issue), messageicon=sg.SYSTEM_TRAY_MESSAGE_ICON_NOICON ) + tray.Update(data_base64=red_x) + issues, first_issue = get_num_issues() + tray.ShowMessage('Refreshed', '{} Issues\n{} First Issue'.format(issues, first_issue), messageicon=sg.SYSTEM_TRAY_MESSAGE_ICON_CRITICAL, ) + tray.Update(data_base64=logo) + # elif menu_item == sg.EVENT_SYSTEM_TRAY_ICON_ACTIVATED: + # tray.ShowMessage('Last check', '{} Issues\n{} First Issue'.format(issues, first_issue), messageicon=sg.SYSTEM_TRAY_MESSAGE_ICON_INFORMATION, ) + elif menu_item == sg.EVENT_SYSTEM_TRAY_MESSAGE_CLICKED : + tray.Update(data_base64=logo) + sp = subprocess.Popen([CHROME, VIEW_ISSUES_URL], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + elif menu_item.startswith('Pull'): + sp = subprocess.Popen([CHROME, PULL_REQUEST_URL], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + elif menu_item.startswith('Announcements'): + sp = subprocess.Popen([CHROME, ANNOUCEMENTS], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + elif menu_item.startswith('Traffic'): + sp = subprocess.Popen([CHROME, TRAFFIC], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + elif menu_item.startswith('Search'): + sp = subprocess.Popen([CHROME, SEARCH], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + elif menu_item.startswith('Discord'): + sp = subprocess.Popen([DISCORD, r''], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + elif menu_item.startswith('PyPI'): + sp = subprocess.Popen([CHROME, PYPI_STATS], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + + if seconds % 12 == 0: # Every 60 seconds read GitHub + issues, first_issue = get_num_issues() + if issues != 0: + menu_def = ['root', + ['{} Issues'.format(issues), '{} First Issue'.format(first_issue), '---','&View Issues Online', '&Pull Request','---', 'Announcements', 'Traffic', 'PyPI Stats', 'Search for Project' , '&Discord', '---','&Run GUI', '&Refresh', 'E&xit']] + tray.Update(menu_def, tooltip='{} First Issue'.format(first_issue)) + # if something changed, then make a popup + if issues != initial_issue_count or first_issue != initial_first_issue: + sg.PopupNonBlocking('Issues changed on GitHub ', 'First issue # is {}'.format(first_issue), background_color='red', keep_on_top=True, grab_anywhere=True) + initial_issue_count = issues + initial_first_issue = first_issue + tray.Update(data_base64=logo32x32red) + tray.ShowMessage('Issues changes!', '{} Issues\n{} First Issue'.format(issues, first_issue), messageicon=sg.SYSTEM_TRAY_MESSAGE_ICON_CRITICAL, ) + + else: + + sg.PopupNonBlocking('Update error at: ', datetime.datetime.now(), + background_color='red', keep_on_top=True, grab_anywhere=True) + print('Update failed', datetime.datetime.now()) + + seconds += poll_frequncy/1000 + +red_x = b"R0lGODlhEAAQAPeQAIsAAI0AAI4AAI8AAJIAAJUAAJQCApkAAJoAAJ4AAJkJCaAAAKYAAKcAAKcCAKcDA6cGAKgAAKsAAKsCAKwAAK0AAK8AAK4CAK8DAqUJAKULAKwLALAAALEAALIAALMAALMDALQAALUAALYAALcEALoAALsAALsCALwAAL8AALkJAL4NAL8NAKoTAKwbAbEQALMVAL0QAL0RAKsREaodHbkQELMsALg2ALk3ALs+ALE2FbgpKbA1Nbc1Nb44N8AAAMIWAMsvAMUgDMcxAKVABb9NBbVJErFYEq1iMrtoMr5kP8BKAMFLAMxKANBBANFCANJFANFEB9JKAMFcANFZANZcANpfAMJUEMZVEc5hAM5pAMluBdRsANR8AM9YOrdERMpIQs1UVMR5WNt8X8VgYMdlZcxtYtx4YNF/btp9eraNf9qXXNCCZsyLeNSLd8SSecySf82kd9qqc9uBgdyBgd+EhN6JgtSIiNuJieGHhOGLg+GKhOKamty1ste4sNO+ueenp+inp+HHrebGrefKuOPTzejWzera1O7b1vLb2/bl4vTu7fbw7ffx7vnz8f///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAJAALAAAAAAQABAAAAjUACEJHEiwYEEABniQKfNFgQCDkATQwAMokEU+PQgUFDAjjR09e/LUmUNnh8aBCcCgUeRmzBkzie6EeQBAoAAMXuA8ciRGCaJHfXzUMCAQgYooWN48anTokR8dQk4sELggBhQrU9Q8evSHiJQgLCIIfMDCSZUjhbYuQkLFCRAMAiOQGGLE0CNBcZYmaRIDLqQFGF60eTRoSxc5jwjhACFWIAgMLtgUocJFy5orL0IQRHAiQgsbRZYswbEhBIiCCH6EiJAhAwQMKU5DjHCi9gnZEHMTDAgAOw==" + + +logo = b'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' + +logo32x32red = b'R0lGODlhIQAgAPcAAAAAADBpmDBqmTFqmjJrmzJsnDNtnTRrmTZtmzZumzRtnTdunDRunTRunjVvnzdwnzhwnjlxnzVwoDZxoTdyojhzozl0ozh0pDp1pjp2pjp2pzx0oj12pD52pTt3qD54pjt4qDx4qDx5qTx5qj16qj57qz57rD58rT98rkB4pkJ7q0J9rEB9rkF+rkB+r0d9qkZ/rEl7o0h8p0x9pk5/p0l+qUB+sEyBrE2Crk2Er0KAsUKAskSCtEeEtUWEtkaGuEiHuEiHukiIu0qKu0mJvEmKvEqLvk2Nv1GErVGFr1SFrVGHslaHsFCItFSIs1COvlaPvFiJsVyRuWCNsWSPsWeQs2SQtGaRtW+Wt2qVuGmZv3GYuHSdv3ievXyfvV2XxGWZwmScx2mfyXafwHikyP9gWP5pYJmdt6GbrqakuamgsayovYClw4Ory4SszI+vyoSv0JGvx5SzzJi0y5m2zp++16C6z6a/05/A2qHC3aXB2K3I3brP4MKxvsLU48LV5c3a5QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAP8ALAAAAAAhACAAAAj/AP8JHEiwoMGDCA1uoYIFYZmHZhIe9HIggEUBdgo+3FhGIsEqAiyKXDBnIEeOHgHFEMkyQII4/07KTEijpU01MWWiNDhDgM+fNhHg1Llz4BQCBAYoXar0p4ABaHISJXjnQYMIBbJq1YoUKYQ+UnUOVLJBoBUGaCMoMMB2a4EuYWcKlCBnoAMHMv5lacC3bwMGV+LK5cBEIJ0JKQTWkMC4MeM3gk8KZGPhRpTKApFQoDChs2cOAoluHDjmwoUX//wkMX2hgmvXHUKL7kiQSw6BOFjrvvBBtuiETjQI15ABg/EQvqce5JMjhHPnIEB4UJFcLsIlJEiM2L5dBIzq1gv+p2liwkSJ8+hXgN85mqAUFPBPyJffYj1KyQL12HDB3wWL/yxoEdl9+P1Thw4I6mDDggu2MSBt7eUkUB07VGihhW48GJZJtO3RAw8ggmghGQ/+NhAYPqToQ4g8QFGicgMBoeKMPqTxYoEE/aDjjjuecWOEBMExhBBBFFnkD0Cs8WNCeBRBhBBQRvmEfUAi9IURRWRZxJQciuWRQHmEccQRYhgU3pdofhkQADs=' + +system_tray() diff --git a/PySimpleGUIWx/Demo Programs/Wx_System_Tray_Launcher.py b/PySimpleGUIWx/Demo Programs/Wx_System_Tray_Launcher.py new file mode 100644 index 000000000..90c0ae034 --- /dev/null +++ b/PySimpleGUIWx/Demo Programs/Wx_System_Tray_Launcher.py @@ -0,0 +1,41 @@ +import PySimpleGUIQt as sg +import webbrowser +import subprocess + +# Destinations +VIEW_ISSUES_URL = r'https://github.com/MikeTheWatchGuy/PySimpleGUI/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc' +PULL_REQUEST_URL = r'https://github.com/MikeTheWatchGuy/PySimpleGUI/compare/master...Dev-latest' +DISCORD = r"C:\Users\mike\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Discord Inc\Discord.lnk" + +def system_tray(): + + menu_def = ['UNUSED', + ['Discord', 'Chrome', 'Open Issues', 'Pull Request', 'Exit']] + # tray = sg.SystemTray(menu=menu_def, filename='myicon.ico', tooltip='My System Tray Launcher') + tray = sg.SystemTray(menu=menu_def, data_base64=logo, tooltip='My System Tray Launcher') + + # The Event Loop runs every 5000ms + poll_frequncy = 5000 + + tray.ShowMessage('Starup', 'System tray launcher has started') + + while True: + menu_item = tray.Read(timeout=poll_frequncy) + + if menu_item == 'Exit': + break + if menu_item == sg.EVENT_SYSTEM_TRAY_ICON_ACTIVATED: + # TODO Insert code to get number of emails... this is a demo only... + tray.ShowMessage('You clicked me', 'You have 18 new emails') + elif menu_item.startswith('Chrome'): # The launches do work however + webbrowser.open_new('http://') + elif menu_item.startswith('Open'): + webbrowser.open_new_tab(VIEW_ISSUES_URL) + elif menu_item.startswith('Pull'): + webbrowser.open_new_tab(PULL_REQUEST_URL) + elif menu_item == 'Discord': + sp = subprocess.Popen([DISCORD, ''], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + +logo = b'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' + +system_tray() \ No newline at end of file diff --git a/PySimpleGUIWx/Demo Programs/Wx_System_Tray_Simple.py b/PySimpleGUIWx/Demo Programs/Wx_System_Tray_Simple.py new file mode 100644 index 000000000..3b79dbaae --- /dev/null +++ b/PySimpleGUIWx/Demo Programs/Wx_System_Tray_Simple.py @@ -0,0 +1,28 @@ +import PySimpleGUIWx as sg + +""" + System Tray Icon + Your very own peronsal status monitor in your system tray + Super easy to use. + 1. Find an icon file or use this default + 2. Create your menu defintion + 3. Add if statements to take action based on your input + +""" + +logo = b'iVBORw0KGgoAAAANSUhEUgAAACEAAAAgCAMAAACrZuH4AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAMGmYMGqZMWqaMmubMmycM22dNGuZNm2bNm6bNG2dN26cNG6dNG6eNW+fN3CfOHCeOXGfNXCgNnGhN3KiOHOjOXSjOHSkOnWmOnamOnanPHSiPXakPnalO3eoPnimO3ioPHioPHmpPHmqPXqqPnurPnusPnytP3yuQHimQnurQn2sQH2uQX6uQH6vR32qRn+sSXujSHynTH2mTn+nSX6pQH6wTIGsTYKuTYSvQoCxQoCyRIK0R4S1RYS2Roa4SIe4SIe6SIi7Soq7SYm8SYq8Sou+TY2/UYStUYWvVIWtUYeyVoewUIi0VIizUI6+Vo+8WImxXJG5YI2xZI+xZ5CzZJC0ZpG1b5a3apW4aZm/cZi4dJ2/eJ69fJ+9XZfEZZnCZJzHaZ/Jdp/AeKTI/tM8/9Q7/9Q8/9Q9/9Q+/tQ//9VA/9ZA/9ZB/9ZC/9dD/9ZE/tdJ/9dK/9hF/9hG/9hH/9hI/9hJ/9hK/9lL/9pK/9pL/thO/9pM/9pN/9tO/9tP/9xP/tpR/9xQ/9xR/9xS/9xT/91U/91V/t1W/95W/95X/95Y/95Z/99a/99b/txf/txh/txk/t5l/t1q/t5v/+Bb/+Bc/+Bd/+Be/+Bf/+Bg/+Fh/+Fi/+Jh/+Ji/uJk/uJl/+Jm/+Rm/uJo/+Ro/+Rr/+Zr/+Vs/+Vu/+Zs/+Zu/uF0/uVw/+dw/+dz/+d2/uB5/uB6/uJ9/uR7/uR+/uV//+hx/+hy/+h0/+h2/+l4/+l7/+h8gKXDg6vLgazOhKzMiqrEj6/KhK/Qka/Hk7HJlLHJlLPMmLTLmbbOkLXSmLvXn77XoLrPpr/Tn8DaocLdpcHYrcjdssfZus/g/uOC/uOH/uaB/uWE/uaF/uWK/+qA/uqH/uqI/uuN/uyM/ueS/ueW/ueY/umQ/uqQ/uuS/uuW/uyU/uyX/uqa/uue/uye/uyf/u6f/uyq/u+r/u+t/vCm/vCp/vCu/vCy/vC2/vK2/vO8/vO/wtTjwtXlzdrl/vTA/vPQAAAAiNpY5gAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAAFw8AABcPASe7rwsAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuMWMqnEsAAAKUSURBVDhPhdB3WE1xHMdxt5JV0dANoUiyd8kqkey996xclUuTlEKidO3qVnTbhIyMW/bee5NskjJLmR/f3++cK/94vP76Ps/n/Zx7z6mE/6koJowcK154vvHOL/GsKCZXkUgkWlf4vWGWq5tsDz+JWIzSokAiqXGe7nWu3HxhEYof7fhOqp1GtptQuMruVhQdxZ05U5G47tYUHbQ4oah6Fg9Z4ubm7i57JhQjdHS0RSzUPoG17u6zZTKZh8c8XlytqW9YWUOH1LqFOZ6enl5ec+XybFb0rweM1tPTM6yuq6vLs0lYJJfLvb19fHwDWGF0jh5lYNAe4/QFemOwxtfXz8/fPyBgwVMqzAcCF4ybAZ2MRCexJGBhYGBQUHDw4u1UHDG1G2ZqB/Q1MTHmzAE+kpCwL1RghlTaBt/6SaXS2kx9YH1IaOjSZST8vfA9JtoDnSngGgL7wkg4WVkofA9mcF1Sx8zMzBK4v3wFiYiMVLxlEy9u21syFhYNmgN7IyJXEYViNZvEYoCVVWOmUVvgQVSUQqGIjolRFvOAFd8HWVs34VoA+6OjY2JjY5Vxm4BC1UuhGG5jY9OUaQXci1MqlfHx8YmqjyhOViW9ZsUN29akJRmPFwkJCZsTSXIpilJffXiTzorLXYgtcxRJKpUqKTklJQ0oSt9FP/EonxVdNY4jla1kK4q2ZB6mIr+AipvduzFUzMSOtLT09IyMzMxtJKug/F0u/6dTexAWDcXXLGEjapKjfsILOLKEuYiSnTQeYCt3UHhbwEHjGMrETfBJU5zq5dSTcXC8hLJccSWP2cgLXHPu7cQNAcpyxF1dyjehAKb0cSYUAOXCUw6V8OFPgevTXFymC+fPPLU677Nw/1X8A/AbfAKGulaqFlIAAAAASUVORK5CYII=' + + +menu_def = ['UNUSED', ['My', 'Simple', '---', 'Menu', 'Exit']] + +tray = sg.SystemTray(menu=menu_def, data_base64=logo) + +tray.ShowMessage('Starting', 'Now Starting the application') + +while True: + event = tray.Read() + if event == 'Exit': + break + elif event == 'Menu': # add your checks here + pass + tray.ShowMessage('Event', '{}'.format(event)) \ No newline at end of file diff --git a/PySimpleGUIWx/Demo Programs/Wx_Widget_Summary.py b/PySimpleGUIWx/Demo Programs/Wx_Widget_Summary.py new file mode 100644 index 000000000..c97a60727 --- /dev/null +++ b/PySimpleGUIWx/Demo Programs/Wx_Widget_Summary.py @@ -0,0 +1,44 @@ +import PySimpleGUIWx as sg +import time + +sg.ChangeLookAndFeel('GreenTan') +buttons = [sg.Radio('Radio Button 1',1, size=(12,1), default=True, enable_events=True, tooltip='radio buttton', key='_RADIO1_'), + sg.Radio('Radio Button 2',1, default=False, key='_RADIO2_', enable_events=True, visible=True), + sg.Radio('Radio Button 3',1, enable_events=True, key='_RADIO3_')] + +layout = [ [sg.Text('PySimpleGUIWx ', tooltip='text', font='Arial 18', text_color='red', enable_events=True, key='_Wx_') , + sg.Text('', key='_TEXT_', font='Arial 18', text_color='black')], + [sg.Input('Single Line Input', do_not_clear=True, enable_events=True)], + [sg.Multiline('Multiline Input', do_not_clear=True, size=(40,4), enable_events=True)], + [sg.MultilineOutput('Multiline Output', size=(40,5), text_color='blue')], + [sg.Output(size=(40,5))], + [sg.Checkbox('Checkbox 1', enable_events=True), sg.Checkbox('Checkbox 2', default=True, enable_events=True)], + [sg.Column([buttons], visible=True, key='COL')], + [sg.Combo(values=['Combo 1', 'Combo 2', 'Combo 3'], default_value='Combo 2', enable_events=True, key='_COMBO_', visible=True, readonly=False, tooltip='Combo box', disabled=False, font='Courier 18', size=(12,1))], + [sg.OK(), sg.Button('Popup')] + ] + +window = sg.Window('My PySimpleGUIWx Window', + default_element_size=(12,1), + ).Layout(layout).Finalize() + +print('This is the output element where STDOUT it being routed') +start_time = int(round(time.time() * 100)) +while True: + event, values = window.Read(timeout=None) + if event is None: + break + if event != sg.TIMEOUT_KEY: + print(event, values) + if event == 'Popup': + sg.Popup('Here is your popup') + current_time = int(round(time.time() * 100)) - start_time + + window.FindElement('_TEXT_').Update('{:02d}:{:02d}.{:02d}'.format((current_time // 100) // 60, + (current_time // 100) % 60, + current_time % 100)) +window.Close() + + + + diff --git a/PySimpleGUIWx/PySimpleGUIWx.py b/PySimpleGUIWx/PySimpleGUIWx.py new file mode 100644 index 000000000..c0a821f2b --- /dev/null +++ b/PySimpleGUIWx/PySimpleGUIWx.py @@ -0,0 +1,8056 @@ +#!/usr/bin/python3 +version = __version__ = "0.17.1.5 Unreleased\n VSeparator added (spelling error), Radio.reset_group added and removed the clearing all when one cleared, added default key for one_line_progress_meter, auto-add keys to tables & trees, added theme_add_new" + +port = 'PySimpleGUIWx' + +import sys +import wx +import wx.adv +import wx.lib.inspection +from wx.lib.embeddedimage import PyEmbeddedImage +import wx.lib.scrolledpanel +import types +import datetime +import textwrap +import pickle +import os +import time +from random import randint + +RUN_INSPECTION_TOOL = False + + + +###### ##### ##### # # ### # # +# # # # # # # # # ##### # ###### # # # # # # # # # # +# # # # # # ## ## # # # # # # # # # # # # # +###### # ##### # # ## # # # # ##### # #### # # # # # # ## +# # # # # # ##### # # # # # # # # # # ## +# # # # # # # # # # # # # # # # # # # # +# # ##### # # # # ###### ###### ##### ##### ### ## ## # # + +""" + + 21-Dec-2018 + Welcome to the "core" PySimpleGUIWx port! + +::: ::: ::: ::: ::::::::: ::: ::: ::::::::::: ::: ::: :::::::: :::: ::: +:+: :+: :+: :+: :+: :+: :+: :+: :+: :+: :+: :+: :+: :+:+: :+: ++:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ :+:+:+ +:+ ++#+ +:+ +#+ +#++:+ +#++:++#+ +#++: +#+ +#++:++#++ +#+ +:+ +#+ +:+ +#+ ++#+ +#+#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+#+# + #+#+# #+#+# #+# #+# #+# #+# #+# #+# #+# #+# #+# #+# #+#+# + ### ### ### ### ### ### ### ### ### ######## ### #### + + + + This marks the 3rd port of the PySimpleGUI GUI SDK. Each port gets a little better than + the previous, in theory. + + It will take a while for this Wx port to be completed, but should be running with a fully selection + of widgets fairly quickly. The Qt port required 1 week to get to "Alpha" condition + + Enjoy! +""" + +g_time_start = 0 +g_time_end = 0 +g_time_delta = 0 + + +# Because looks matter... +DEFAULT_BASE64_ICON = b'iVBORw0KGgoAAAANSUhEUgAAACEAAAAgCAMAAACrZuH4AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAMGmYMGqZMWqaMmubMmycM22dNGuZNm2bNm6bNG2dN26cNG6dNG6eNW+fN3CfOHCeOXGfNXCgNnGhN3KiOHOjOXSjOHSkOnWmOnamOnanPHSiPXakPnalO3eoPnimO3ioPHioPHmpPHmqPXqqPnurPnusPnytP3yuQHimQnurQn2sQH2uQX6uQH6vR32qRn+sSXujSHynTH2mTn+nSX6pQH6wTIGsTYKuTYSvQoCxQoCyRIK0R4S1RYS2Roa4SIe4SIe6SIi7Soq7SYm8SYq8Sou+TY2/UYStUYWvVIWtUYeyVoewUIi0VIizUI6+Vo+8WImxXJG5YI2xZI+xZ5CzZJC0ZpG1b5a3apW4aZm/cZi4dJ2/eJ69fJ+9XZfEZZnCZJzHaZ/Jdp/AeKTI/tM8/9Q7/9Q8/9Q9/9Q+/tQ//9VA/9ZA/9ZB/9ZC/9dD/9ZE/tdJ/9dK/9hF/9hG/9hH/9hI/9hJ/9hK/9lL/9pK/9pL/thO/9pM/9pN/9tO/9tP/9xP/tpR/9xQ/9xR/9xS/9xT/91U/91V/t1W/95W/95X/95Y/95Z/99a/99b/txf/txh/txk/t5l/t1q/t5v/+Bb/+Bc/+Bd/+Be/+Bf/+Bg/+Fh/+Fi/+Jh/+Ji/uJk/uJl/+Jm/+Rm/uJo/+Ro/+Rr/+Zr/+Vs/+Vu/+Zs/+Zu/uF0/uVw/+dw/+dz/+d2/uB5/uB6/uJ9/uR7/uR+/uV//+hx/+hy/+h0/+h2/+l4/+l7/+h8gKXDg6vLgazOhKzMiqrEj6/KhK/Qka/Hk7HJlLHJlLPMmLTLmbbOkLXSmLvXn77XoLrPpr/Tn8DaocLdpcHYrcjdssfZus/g/uOC/uOH/uaB/uWE/uaF/uWK/+qA/uqH/uqI/uuN/uyM/ueS/ueW/ueY/umQ/uqQ/uuS/uuW/uyU/uyX/uqa/uue/uye/uyf/u6f/uyq/u+r/u+t/vCm/vCp/vCu/vCy/vC2/vK2/vO8/vO/wtTjwtXlzdrl/vTA/vPQAAAAiNpY5gAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAAFw8AABcPASe7rwsAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuMWMqnEsAAAKUSURBVDhPhdB3WE1xHMdxt5JV0dANoUiyd8kqkey996xclUuTlEKidO3qVnTbhIyMW/bee5NskjJLmR/f3++cK/94vP76Ps/n/Zx7z6mE/6koJowcK154vvHOL/GsKCZXkUgkWlf4vWGWq5tsDz+JWIzSokAiqXGe7nWu3HxhEYof7fhOqp1GtptQuMruVhQdxZ05U5G47tYUHbQ4oah6Fg9Z4ubm7i57JhQjdHS0RSzUPoG17u6zZTKZh8c8XlytqW9YWUOH1LqFOZ6enl5ec+XybFb0rweM1tPTM6yuq6vLs0lYJJfLvb19fHwDWGF0jh5lYNAe4/QFemOwxtfXz8/fPyBgwVMqzAcCF4ybAZ2MRCexJGBhYGBQUHDw4u1UHDG1G2ZqB/Q1MTHmzAE+kpCwL1RghlTaBt/6SaXS2kx9YH1IaOjSZST8vfA9JtoDnSngGgL7wkg4WVkofA9mcF1Sx8zMzBK4v3wFiYiMVLxlEy9u21syFhYNmgN7IyJXEYViNZvEYoCVVWOmUVvgQVSUQqGIjolRFvOAFd8HWVs34VoA+6OjY2JjY5Vxm4BC1UuhGG5jY9OUaQXci1MqlfHx8YmqjyhOViW9ZsUN29akJRmPFwkJCZsTSXIpilJffXiTzorLXYgtcxRJKpUqKTklJQ0oSt9FP/EonxVdNY4jla1kK4q2ZB6mIr+AipvduzFUzMSOtLT09IyMzMxtJKug/F0u/6dTexAWDcXXLGEjapKjfsILOLKEuYiSnTQeYCt3UHhbwEHjGMrETfBJU5zq5dSTcXC8hLJccSWP2cgLXHPu7cQNAcpyxF1dyjehAKb0cSYUAOXCUw6V8OFPgevTXFymC+fPPLU677Nw/1X8A/AbfAKGulaqFlIAAAAASUVORK5CYII=' + + +def TimerStart(): + global g_time_start + + g_time_start = time.time() + + +def TimerStop(): + global g_time_delta, g_time_end + + g_time_end = time.time() + g_time_delta = g_time_end - g_time_start + print(g_time_delta) + + +# ----====----====----==== Constants the user CAN safely change ====----====----====----# +DEFAULT_WINDOW_ICON = 'default_icon.ico' +DEFAULT_ELEMENT_SIZE = (250, 26) # In pixels +DEFAULT_BUTTON_ELEMENT_SIZE = (10, 1) # In CHARACTERS +DEFAULT_MARGINS = (10, 5) # Margins for each LEFT/RIGHT margin is first term +DEFAULT_ELEMENT_PADDING = (3, 2) # Padding between elements (row, col) in pixels +DEFAULT_AUTOSIZE_TEXT = True +DEFAULT_AUTOSIZE_BUTTONS = True +DEFAULT_FONT = ("Helvetica", 10) +DEFAULT_TEXT_JUSTIFICATION = 'left' +DEFAULT_BORDER_WIDTH = 1 +DEFAULT_AUTOCLOSE_TIME = 3 # time in seconds to show an autoclose form +DEFAULT_DEBUG_WINDOW_SIZE = (80, 20) +DEFAULT_WINDOW_LOCATION = (None, None) +MAX_SCROLLED_TEXT_BOX_HEIGHT = 50 +DEFAULT_TOOLTIP_TIME = 400 +DEFAULT_PIXELS_TO_CHARS_SCALING = (10,26) # 1 character represents x by y pixels +DEFAULT_PIXELS_TO_CHARS_SCALING_MULTILINE_TEXT = (10,20) # 1 character represents x by y pixels +DEFAULT_PIXEL_TO_CHARS_CUTOFF = 20 # number of chars that triggers using pixels instead of chars +DEFAULT_PIXEL_TO_CHARS_CUTOFF_MULTILINE = 70 # number of chars that triggers using pixels instead of chars +MENU_DISABLED_CHARACTER = '!' +MENU_KEY_SEPARATOR = '::' + +#################### COLOR STUFF #################### +BLUES = ("#082567", "#0A37A3", "#00345B") +PURPLES = ("#480656", "#4F2398", "#380474") +GREENS = ("#01826B", "#40A860", "#96D2AB", "#00A949", "#003532") +YELLOWS = ("#F3FB62", "#F0F595") +TANS = ("#FFF9D5", "#F4EFCF", "#DDD8BA") +NICE_BUTTON_COLORS = ((GREENS[3], TANS[0]), + ('#000000', '#FFFFFF'), + ('#FFFFFF', '#000000'), + (YELLOWS[0], PURPLES[1]), + (YELLOWS[0], GREENS[3]), + (YELLOWS[0], BLUES[2])) + +COLOR_SYSTEM_DEFAULT = '1234567890' # Colors should never be this long +DEFAULT_BUTTON_COLOR = ('white', BLUES[0]) # Foreground, Background (None, None) == System Default +OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR = ('white', BLUES[0]) # Colors should never be this long + + +CURRENT_LOOK_AND_FEEL = 'DarkBlue3' + + + + +DEFAULT_ERROR_BUTTON_COLOR = ("#FFFFFF", "#FF0000") +DEFAULT_BACKGROUND_COLOR = None +DEFAULT_ELEMENT_BACKGROUND_COLOR = None +DEFAULT_ELEMENT_TEXT_COLOR = COLOR_SYSTEM_DEFAULT +DEFAULT_TEXT_ELEMENT_BACKGROUND_COLOR = None +DEFAULT_TEXT_COLOR = COLOR_SYSTEM_DEFAULT +DEFAULT_INPUT_ELEMENTS_COLOR = COLOR_SYSTEM_DEFAULT +DEFAULT_INPUT_TEXT_COLOR = COLOR_SYSTEM_DEFAULT +DEFAULT_SCROLLBAR_COLOR = None +# DEFAULT_BUTTON_COLOR = (YELLOWS[0], PURPLES[0]) # (Text, Background) or (Color "on", Color) as a way to remember +# DEFAULT_BUTTON_COLOR = (GREENS[3], TANS[0]) # Foreground, Background (None, None) == System Default +# DEFAULT_BUTTON_COLOR = (YELLOWS[0], GREENS[4]) # Foreground, Background (None, None) == System Default +# DEFAULT_BUTTON_COLOR = ('white', 'black') # Foreground, Background (None, None) == System Default +# DEFAULT_BUTTON_COLOR = (YELLOWS[0], PURPLES[2]) # Foreground, Background (None, None) == System Default +# DEFAULT_PROGRESS_BAR_COLOR = (GREENS[2], GREENS[0]) # a nice green progress bar +# DEFAULT_PROGRESS_BAR_COLOR = (BLUES[1], BLUES[1]) # a nice green progress bar +# DEFAULT_PROGRESS_BAR_COLOR = (BLUES[0], BLUES[0]) # a nice green progress bar +# DEFAULT_PROGRESS_BAR_COLOR = (PURPLES[1],PURPLES[0]) # a nice purple progress bar + +# A transparent button is simply one that matches the background +TRANSPARENT_BUTTON = 'This constant has been depricated. You must set your button background = background it is on for it to be transparent appearing' +# -------------------------------------------------------------------------------- +# Progress Bar Relief Choices +RELIEF_RAISED = 'raised' +RELIEF_SUNKEN = 'sunken' +RELIEF_FLAT = 'flat' +RELIEF_RIDGE = 'ridge' +RELIEF_GROOVE = 'groove' +RELIEF_SOLID = 'solid' + +DEFAULT_PROGRESS_BAR_COLOR = (GREENS[0], '#D0D0D0') # a nice green progress bar +DEFAULT_PROGRESS_BAR_COLOR_OFFICIAL = (GREENS[0], '#D0D0D0') # a nice green progress bar +DEFAULT_PROGRESS_BAR_SIZE = (20, 20) # Size of Progress Bar (characters for length, pixels for width) +DEFAULT_PROGRESS_BAR_BORDER_WIDTH = 1 +DEFAULT_PROGRESS_BAR_RELIEF = RELIEF_GROOVE +PROGRESS_BAR_STYLES = ('default', 'winnative', 'clam', 'alt', 'classic', 'vista', 'xpnative') +DEFAULT_PROGRESS_BAR_STYLE = 'default' +DEFAULT_METER_ORIENTATION = 'Horizontal' +DEFAULT_SLIDER_ORIENTATION = 'vertical' +DEFAULT_SLIDER_BORDER_WIDTH = 1 +DEFAULT_SLIDER_RELIEF = 00000 +DEFAULT_FRAME_RELIEF = 00000 + +DEFAULT_LISTBOX_SELECT_MODE = 00000 +SELECT_MODE_MULTIPLE = 00000 +LISTBOX_SELECT_MODE_MULTIPLE = 'multiple' +SELECT_MODE_BROWSE = 00000 +LISTBOX_SELECT_MODE_BROWSE = 'browse' +SELECT_MODE_EXTENDED =00000 +LISTBOX_SELECT_MODE_EXTENDED = 'extended' +SELECT_MODE_SINGLE = 00000 +LISTBOX_SELECT_MODE_SINGLE = 'single' + +TABLE_SELECT_MODE_NONE = 00000 +TABLE_SELECT_MODE_BROWSE = 00000 +TABLE_SELECT_MODE_EXTENDED = 00000 +DEFAULT_TABLE_SECECT_MODE = TABLE_SELECT_MODE_EXTENDED + +TITLE_LOCATION_TOP = 00000 +TITLE_LOCATION_BOTTOM = 00000 +TITLE_LOCATION_LEFT = 00000 +TITLE_LOCATION_RIGHT = 00000 +TITLE_LOCATION_TOP_LEFT = 00000 +TITLE_LOCATION_TOP_RIGHT = 00000 +TITLE_LOCATION_BOTTOM_LEFT = 00000 +TITLE_LOCATION_BOTTOM_RIGHT = 00000 + +THEME_DEFAULT = 'default' +THEME_WINNATIVE = 'winnative' +THEME_CLAM = 'clam' +THEME_ALT = 'alt' +THEME_CLASSIC = 'classic' +THEME_VISTA = 'vista' +THEME_XPNATIVE = 'xpnative' + +# DEFAULT_METER_ORIENTATION = 'Vertical' +# ----====----====----==== Constants the user should NOT f-with ====----====----====----# +ThisRow = 555666777 # magic number + +# DEFAULT_WINDOW_ICON = '' +MESSAGE_BOX_LINE_WIDTH = 60 + +# "Special" Key Values.. reserved +# Key representing a Read timeout +EVENT_TIMEOUT = TIMEOUT_EVENT = TIMEOUT_KEY = '__TIMEOUT__' +# Window closed event (user closed with X or destroyed using OS) +WIN_CLOSED = WINDOW_CLOSED = None + +# Key indicating should not create any return values for element +WRITE_ONLY_KEY = '__WRITE ONLY__' +EVENT_SYSTEM_TRAY_ICON_DOUBLE_CLICKED = '__DOUBLE_CLICKED__' +EVENT_SYSTEM_TRAY_ICON_ACTIVATED = '__ACTIVATED__' +EVENT_SYSTEM_TRAY_ICON_RIGHT_CLICK = '__RIGHT_CLICK__' +EVENT_SYSTEM_TRAY_MESSAGE_CLICKED = '__MESSAGE_CLICKED__' + +# Icons for displaying system tray messages +SYSTEM_TRAY_MESSAGE_ICON_INFORMATION = wx.ICON_INFORMATION +SYSTEM_TRAY_MESSAGE_ICON_WARNING = wx.ICON_WARNING +SYSTEM_TRAY_MESSAGE_ICON_CRITICAL = wx.ICON_ERROR +SYSTEM_TRAY_MESSAGE_ICON_NOICON = None + +ICON_SCREEN_DEPTH = -1 + +ICON_STOP = 512 + +# a shameful global variable. This represents the top-level window information. Needed because opening a second window is different than opening the first. +class MyWindows(): + def __init__(self): + self.NumOpenWindows = 0 + self.user_defined_icon = None + self.hidden_master_root = None + + def Decrement(self): + self.NumOpenWindows -= 1 * (self.NumOpenWindows != 0) # decrement if not 0 + # print('---- DECREMENTING Num Open Windows = {} ---'.format(self.NumOpenWindows)) + + def Increment(self): + self.NumOpenWindows += 1 + # print('++++ INCREMENTING Num Open Windows = {} ++++'.format(self.NumOpenWindows)) + + +_my_windows = MyWindows() # terrible hack using globals... means need a class for collecing windows + + +# ====================================================================== # +# One-liner functions that are handy as f_ck # +# ====================================================================== # +def RGB(red, green, blue): return '#%02x%02x%02x' % (red, green, blue) + + +# ====================================================================== # +# Enums for types # +# ====================================================================== # +# ------------------------- Button types ------------------------- # +# todo Consider removing the Submit, Cancel types... they are just 'RETURN' type in reality +# uncomment this line and indent to go back to using Enums +# class ButtonType(Enum): +BUTTON_TYPE_BROWSE_FOLDER = 1 +BUTTON_TYPE_BROWSE_FILE = 2 +BUTTON_TYPE_BROWSE_FILES = 21 +BUTTON_TYPE_SAVEAS_FILE = 3 +BUTTON_TYPE_CLOSES_WIN = 5 +BUTTON_TYPE_CLOSES_WIN_ONLY = 6 +BUTTON_TYPE_READ_FORM = 7 +BUTTON_TYPE_REALTIME = 9 +BUTTON_TYPE_CALENDAR_CHOOSER = 30 +BUTTON_TYPE_COLOR_CHOOSER = 40 + +BROWSE_FILES_DELIMITER = ';' # the delimeter to be used between each file in the returned string + +# ------------------------- Element types ------------------------- # +# class ElementType(Enum): +ELEM_TYPE_TEXT = 'text' +ELEM_TYPE_INPUT_TEXT = 'input' +ELEM_TYPE_INPUT_COMBO = 'combo' +ELEM_TYPE_INPUT_OPTION_MENU = 'option menu' +ELEM_TYPE_INPUT_RADIO = 'radio' +ELEM_TYPE_INPUT_MULTILINE = 'multiline' +ELEM_TYPE_MULTILINE_OUTPUT = 'multioutput' +ELEM_TYPE_INPUT_CHECKBOX = 'checkbox' +ELEM_TYPE_INPUT_SPIN = 'spin' +ELEM_TYPE_BUTTON = 'button' +ELEM_TYPE_BUTTONMENU = 'buttonmenu' +ELEM_TYPE_IMAGE = 'image' +ELEM_TYPE_CANVAS = 'canvas' +ELEM_TYPE_FRAME = 'frame' +ELEM_TYPE_GRAPH = 'graph' +ELEM_TYPE_TAB = 'tab' +ELEM_TYPE_TAB_GROUP = 'tabgroup' +ELEM_TYPE_INPUT_SLIDER = 'slider' +ELEM_TYPE_INPUT_LISTBOX = 'listbox' +ELEM_TYPE_OUTPUT = 'output' +ELEM_TYPE_COLUMN = 'column' +ELEM_TYPE_MENUBAR = 'menubar' +ELEM_TYPE_PROGRESS_BAR = 'progressbar' +ELEM_TYPE_BLANK = 'blank' +ELEM_TYPE_TABLE = 'table' +ELEM_TYPE_TREE = 'tree' +ELEM_TYPE_ERROR = 'error' +ELEM_TYPE_SEPARATOR = 'separator' + +# ------------------------- Popup Buttons Types ------------------------- # +POPUP_BUTTONS_YES_NO = 1 +POPUP_BUTTONS_CANCELLED = 2 +POPUP_BUTTONS_ERROR = 3 +POPUP_BUTTONS_OK_CANCEL = 4 +POPUP_BUTTONS_OK = 0 +POPUP_BUTTONS_NO_BUTTONS = 5 + + +# ---------------------------------------------------------------------- # +# Cascading structure.... Objects get larger # +# Button # +# Element # +# Row # +# Form # +# ---------------------------------------------------------------------- # +# ---------------------------------------------------------------------- # +# Element CLASS # +# ---------------------------------------------------------------------- # +class Element(): + def __init__(self, elem_type, size=(None, None), auto_size_text=None, font=None, background_color=None, text_color=None, + key=None, pad=None, tooltip=None, visible=True, size_px=(None, None)): + + + # if elem_type != ELEM_TYPE_GRAPH: + # self.Size = convert_tkinter_size_to_Wx(size) + # else: + # self.Size = size + self.Size = size_px + if size_px == (None, None) and size != (None, None): + if elem_type in (ELEM_TYPE_MULTILINE_OUTPUT, ELEM_TYPE_INPUT_MULTILINE, ELEM_TYPE_OUTPUT, ELEM_TYPE_TABLE, ELEM_TYPE_TREE, ELEM_TYPE_TAB, ELEM_TYPE_COLUMN): + self.Size = _convert_tkinter_size_to_Wx(size, DEFAULT_PIXELS_TO_CHARS_SCALING_MULTILINE_TEXT, DEFAULT_PIXEL_TO_CHARS_CUTOFF_MULTILINE) + else: + self.Size = _convert_tkinter_size_to_Wx(size, DEFAULT_PIXELS_TO_CHARS_SCALING, DEFAULT_PIXEL_TO_CHARS_CUTOFF) + self.Type = elem_type + self.AutoSizeText = auto_size_text + # self.Pad = DEFAULT_ELEMENT_PADDING if pad is None else pad + self.Pad = pad + if font is not None and type(font) is not str: + self.Font = font + elif font is not None: + self.Font = font.split(' ') + else: + self.Font = font + + self.TKStringVar = None + self.TKIntVar = None + self.TKText = None + self.TKEntry = None + self.TKImage = None + + self.ParentForm = None # type: Window + self.ParentContainer = None # will be a Form, Column, or Frame element + self.TextInputDefault = None + self.Position = (0, 0) # Default position Row 0, Col 0 + self.BackgroundColor = background_color if background_color is not None else DEFAULT_ELEMENT_BACKGROUND_COLOR + self.TextColor = text_color if text_color is not None else DEFAULT_ELEMENT_TEXT_COLOR + self.Key = key # dictionary key for return values + self.Tooltip = tooltip + self.TooltipObject = None + self.Visible = visible + self.metadata = None # type: Any + + + + def FindReturnKeyBoundButton(self, form): + for row in form.Rows: + for element in row: + if element.Type == ELEM_TYPE_BUTTON: + if element.BindReturnKey: + return element + if element.Type == ELEM_TYPE_COLUMN: + rc = self.FindReturnKeyBoundButton(element) + if rc is not None: + return rc + if element.Type == ELEM_TYPE_FRAME: + rc = self.FindReturnKeyBoundButton(element) + if rc is not None: + return rc + if element.Type == ELEM_TYPE_TAB_GROUP: + rc = self.FindReturnKeyBoundButton(element) + if rc is not None: + return rc + if element.Type == ELEM_TYPE_TAB: + rc = self.FindReturnKeyBoundButton(element) + if rc is not None: + return rc + return None + + def _TextClickedHandler(self, event): + if self.Key is not None: + self.ParentForm.LastButtonClicked = self.Key + else: + self.ParentForm.LastButtonClicked = self.DisplayText + self.ParentForm.FormRemainedOpen = True + if self.ParentForm.CurrentlyRunningMainloop: + self.ParentForm.TKroot.quit() # kick the users out of the mainloop + + def _ReturnKeyHandler(self, event): + MyForm = self.ParentForm + button_element = self.FindReturnKeyBoundButton(MyForm) + if button_element is not None: + button_element.ButtonCallBack(event) + + def _ListboxSelectHandler(self, event): + # first, get the results table built + # modify the Results table in the parent FlexForm object + if self.Key is not None: + self.ParentForm.LastButtonClicked = self.Key + else: + self.ParentForm.LastButtonClicked = '' + self.ParentForm.FormRemainedOpen = True + if self.ParentForm.CurrentlyRunningMainloop: + self.ParentForm.TKroot.quit() # kick the users out of the mainloop + + def _ComboboxSelectHandler(self, event): + # first, get the results table built + # modify the Results table in the parent FlexForm object + if self.Key is not None: + self.ParentForm.LastButtonClicked = self.Key + else: + self.ParentForm.LastButtonClicked = '' + self.ParentForm.FormRemainedOpen = True + if self.ParentForm.CurrentlyRunningMainloop: + self.ParentForm.TKroot.quit() # kick the users out of the mainloop + + def _RadioHandler(self): + if self.Key is not None: + self.ParentForm.LastButtonClicked = self.Key + else: + self.ParentForm.LastButtonClicked = '' + self.ParentForm.FormRemainedOpen = True + if self.ParentForm.CurrentlyRunningMainloop: + self.ParentForm.TKroot.quit() + + def _CheckboxHandler(self): + if self.Key is not None: + self.ParentForm.LastButtonClicked = self.Key + else: + self.ParentForm.LastButtonClicked = '' + self.ParentForm.FormRemainedOpen = True + if self.ParentForm.CurrentlyRunningMainloop: + self.ParentForm.TKroot.quit() + + def _TabGroupSelectHandler(self, event): + if self.Key is not None: + self.ParentForm.LastButtonClicked = self.Key + else: + self.ParentForm.LastButtonClicked = '' + self.ParentForm.FormRemainedOpen = True + if self.ParentForm.CurrentlyRunningMainloop: + self.ParentForm.TKroot.quit() + + + def _KeyboardHandler(self, event): + if self.Key is not None: + self.ParentForm.LastButtonClicked = self.Key + else: + self.ParentForm.LastButtonClicked = '' + self.ParentForm.FormRemainedOpen = True + if self.ParentForm.CurrentlyRunningMainloop: + self.ParentForm.TKroot.quit() + + + def _WxCallbackKeyboard(self, value): + element_callback_quit_mainloop(self) + + + def Update(self, widget, background_color=None, text_color=None, font=None, visible=None, disabled=None, tooltip=None): + if font: + widget.SetFont(font_to_wx_font(font)) + if text_color not in (None, COLOR_SYSTEM_DEFAULT): + widget.SetForegroundColour(text_color) + if background_color not in (None, COLOR_SYSTEM_DEFAULT): + widget.SetBackgroundColour(background_color) + if visible is True: + widget.Show() + self.ParentForm.VisibilityChanged() + elif visible is False: + widget.Hide() + self.ParentForm.VisibilityChanged() + if disabled: + widget.Enable(False) + elif disabled is False: + widget.Enable(True) + if tooltip is not None: + widget.SetToolTip(tooltip) + + def __call__(self, *args, **kwargs): + """ + Makes it possible to "call" an already existing element. When you do make the "call", it actually calls + the Update method for the element. + Example: If this text element was in yoiur layout: + sg.Text('foo', key='T') + Then you can call the Update method for that element by writing: + window.FindElement('T')('new text value') + + :param args: + :param kwargs: + :return: + """ + return self.Update(*args, **kwargs) + + update = Update + +# ---------------------------------------------------------------------- # +# Input Class # +# ---------------------------------------------------------------------- # +class InputText(Element): + def __init__(self, default_text='', size=(None,None), disabled=False, password_char='', + justification=None, background_color=None, text_color=None, font=None, tooltip=None, + change_submits=False, enable_events=False, + do_not_clear=True, key=None, focus=False, pad=None, visible=True, size_px=(None,None)): + ''' + Input a line of text Element + :param default_text: Default value to display + :param size: Size of field in characters + :param password_char: If non-blank, will display this character for every character typed + :param background_color: Color for Element. Text or RGB Hex + ''' + self.DefaultText = str(default_text) + self.PasswordCharacter = str(password_char) + bg = background_color if background_color is not None else DEFAULT_INPUT_ELEMENTS_COLOR + fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR + self.Focus = focus + self.do_not_clear = do_not_clear + self.Justification = justification or 'left' + self.Disabled = disabled + self.ChangeSubmits = change_submits or enable_events + self.QT_QLineEdit = None + self.ValueWasChanged = False + self.WxTextCtrl = None + + + super().__init__(ELEM_TYPE_INPUT_TEXT,size=size, background_color=bg, text_color=fg, key=key, pad=pad, + font=font, tooltip=tooltip, visible=visible, size_px=size_px) + + + def Update(self, value=None, disabled=None, select=None, background_color=None, text_color=None, font=None, visible=None): + if disabled is True: + self.WxTextCtrl.Enable(True) + elif disabled is False: + self.WxTextCtrl.Enable(False) + if value is not None: + self.WxTextCtrl.SetValue(str(value)) + self.DefaultText = value + if select: + self.WxTextCtrl.SelectAll() + # if visible: + # self.WxTextCtrl.Show() + # self.ParentForm.VisibilityChanged() + # elif visible is False: + # self.WxTextCtrl.Hide() + super().Update(self.WxTextCtrl, background_color=background_color, text_color=text_color, font=font, visible=visible) + + + def Get(self): + return self.WxTextCtrl.GetValue() + + def SetFocus(self): + self.WxTextCtrl.SetFocus() + + get = Get + set_focus = SetFocus + update = Update + + +# ------------------------- INPUT TEXT Element lazy functions ------------------------- # +In = InputText +Input = InputText +I = InputText + +# ---------------------------------------------------------------------- # +# Combo # +# ---------------------------------------------------------------------- # +class Combo(Element): + def __init__(self, values, default_value=None, size=(None, None), auto_size_text=None, background_color=None, + text_color=None, change_submits=False, enable_events=False, disabled=False, key=None, pad=None, tooltip=None, + readonly=False, visible_items=10, font=None, auto_complete=True, visible=True, size_px=(None,None)): + ''' + Input Combo Box Element (also called Dropdown box) + :param values: + :param size: Size of field in characters + :param auto_size_text: True if should shrink field to fit the default text + :param background_color: Color for Element. Text or RGB Hex + ''' + self.Values = values + self.DefaultValue = default_value + self.ChangeSubmits = change_submits or enable_events + # self.InitializeAsDisabled = disabled + self.Disabled = disabled + self.Readonly = readonly + bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR + fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR + self.VisibleItems = visible_items + self.AutoComplete = auto_complete + self.WxComboBox = None # type: wx.ComboBox + + super().__init__(ELEM_TYPE_INPUT_COMBO, size=size, auto_size_text=auto_size_text, background_color=bg, + text_color=fg, key=key, pad=pad, tooltip=tooltip, font=font or DEFAULT_FONT, visible=visible, size_px=size_px) + + + + + def Update(self, value=None, values=None, set_to_index=None, disabled=None, readonly=None, background_color=None, text_color=None, font=None, visible=None): + if values is not None: + self.WxComboBox.Set(values) + if value: + self.WxComboBox.SetSelection(self.WxComboBox.FindString(value)) + if set_to_index is not None: + self.WxComboBox.SetSelection(set_to_index) + if disabled is True: + self.WxComboBox.Enable(False) + elif disabled is False: + self.WxComboBox.Enable(True) + if readonly is not None: + self.WxComboBox.SetWindowStyle(wx.CB_READONLY) + + super().Update(self.WxComboBox, background_color=background_color, text_color=text_color, font=font, visible=visible) + + update = Update + + +# ------------------------- INPUT COMBO Element lazy functions ------------------------- # +InputCombo = Combo +DropDown = InputCombo +Drop = InputCombo + + + +# ---------------------------------------------------------------------- # +# Option Menu # +# ---------------------------------------------------------------------- # +class OptionMenu(Element): + def __init__(self, values, default_value=None, size=(None, None), disabled=False, auto_size_text=None, + background_color=None, text_color=None, key=None, pad=None, tooltip=None): + ''' + InputOptionMenu + :param values: + :param default_value: + :param size: + :param disabled: + :param auto_size_text: + :param background_color: + :param text_color: + :param key: + :param pad: + :param tooltip: + ''' + self.Values = values + self.DefaultValue = default_value + self.TKOptionMenu = None + self.Disabled = disabled + bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR + fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR + + super().__init__(ELEM_TYPE_INPUT_OPTION_MENU, size=size, auto_size_text=auto_size_text, background_color=bg, + text_color=fg, key=key, pad=pad, tooltip=tooltip) + + def Update(self, value=None, values=None, disabled=None): + if values is not None: + self.Values = values + if self.Values is not None: + for index, v in enumerate(self.Values): + if v == value: + try: + self.TKStringVar.set(value) + except: + pass + self.DefaultValue = value + break + if disabled == True: + self.TKOptionMenu['state'] = 'disabled' + elif disabled == False: + self.TKOptionMenu['state'] = 'normal' + + update = Update + + +# ------------------------- OPTION MENU Element lazy functions ------------------------- # +InputOptionMenu = OptionMenu + + +# ---------------------------------------------------------------------- # +# Listbox # +# ---------------------------------------------------------------------- # +class Listbox(Element): + def __init__(self, values, default_values=None, select_mode=None, change_submits=False, bind_return_key=False, + size=(None, None), disabled=False, auto_size_text=None, font=None, background_color=None, size_px=(None, None), + text_color=None, key=None, pad=None, tooltip=None): + ''' + Listbox Element + :param values: + :param default_values: + :param select_mode: + :param change_submits: + :param bind_return_key: + :param size: + :param disabled: + :param auto_size_text: + :param font: + :param background_color: + :param text_color: + :param key: + :param pad: + :param tooltip: + ''' + self.Values = values + self.DefaultValues = default_values + self.TKListbox = None + self.ChangeSubmits = change_submits + self.BindReturnKey = bind_return_key + self.Disabled = disabled + if select_mode == LISTBOX_SELECT_MODE_BROWSE: + self.SelectMode = SELECT_MODE_BROWSE + elif select_mode == LISTBOX_SELECT_MODE_EXTENDED: + self.SelectMode = SELECT_MODE_EXTENDED + elif select_mode == LISTBOX_SELECT_MODE_MULTIPLE: + self.SelectMode = SELECT_MODE_MULTIPLE + elif select_mode == LISTBOX_SELECT_MODE_SINGLE: + self.SelectMode = SELECT_MODE_SINGLE + else: + self.SelectMode = DEFAULT_LISTBOX_SELECT_MODE + bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR + fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR + + super().__init__(ELEM_TYPE_INPUT_LISTBOX, size=size, auto_size_text=auto_size_text, font=font, + background_color=bg, text_color=fg, key=key, pad=pad, size_px=size_px, tooltip=tooltip) + + def Update(self, values=None, disabled=None): + if disabled == True: + self.TKListbox.configure(state='disabled') + elif disabled == False: + self.TKListbox.configure(state='normal') + if values is not None: + self.TKListbox.delete(0, 'end') + for item in values: + self.TKListbox.insert(tk.END, item) + self.TKListbox.selection_set(0, 0) + self.Values = values + + def SetValue(self, values): + for index, item in enumerate(self.Values): + try: + if item in values: + self.TKListbox.selection_set(index) + else: + self.TKListbox.selection_clear(index) + except: + pass + self.DefaultValues = values + + def GetListValues(self): + return self.Values + + get_list_values = GetListValues + set_value = SetValue + update = Update + +# ---------------------------------------------------------------------- # +# Radio # +# ---------------------------------------------------------------------- # +class Radio(Element): + def __init__(self, text, group_id, default=False, disabled=False, size=(None, None), auto_size_text=None, + background_color=None, text_color=None, font=None, key=None, pad=None, tooltip=None, + change_submits=False, enable_events=False, visible=True, size_px=(None, None)): + """ + + :param text: + :param group_id: + :param default: + :param disabled: + :param size: + :param auto_size_text: + :param background_color: + :param text_color: + :param font: + :param key: + :param pad: + :param tooltip: + :param change_submits: + :param enable_events: + :param visible: + :param size_px: + """ + self.InitialState = default + self.Text = text + self.GroupID = group_id + self.Value = None + self.Disabled = disabled + self.TextColor = text_color or DEFAULT_TEXT_COLOR + self.ChangeSubmits = change_submits or enable_events + self.WxRadioButton = None # type: wx.RadioButton + + super().__init__(ELEM_TYPE_INPUT_RADIO, size=size, auto_size_text=auto_size_text, font=font, + background_color=background_color, text_color=self.TextColor, key=key, pad=pad, + tooltip=tooltip, visible=visible, size_px=size_px) + + + def Update(self, value=None, disabled=None, background_color=None, text_color=None, font=None, visible=None): + if value is True: + self.WxRadioButton.SetValue(True) + elif value is False: + self.WxRadioButton.SetValue(False) + super().Update(self.WxRadioButton, background_color=background_color, text_color=text_color, font=font, visible=visible) + + + def reset_group(self): + self.WxRadioButton.SetValue(True) + self.WxRadioButton.SetValue(False) + + update = Update + +# ---------------------------------------------------------------------- # +# Checkbox # +# ---------------------------------------------------------------------- # +class Checkbox(Element): + def __init__(self, text, default=False, size=(None, None), auto_size_text=None, font=None, background_color=None, + text_color=None, change_submits=False, enable_events=False, disabled=False, key=None, pad=None, tooltip=None, visible=True, size_px=(None,None)): + ''' + Checkbox Element + :param text: + :param default: + :param size: + :param auto_size_text: + :param font: + :param background_color: + :param text_color: + :param change_submits: + :param disabled: + :param key: + :param pad: + :param tooltip: + ''' + self.Text = text + self.InitialState = default + self.WxCheckbox = None # type:wx.CheckBox + self.Disabled = disabled + self.TextColor = text_color if text_color else DEFAULT_TEXT_COLOR + self.ChangeSubmits = change_submits or enable_events + + + super().__init__(ELEM_TYPE_INPUT_CHECKBOX, size=size, auto_size_text=auto_size_text, font=font, + background_color=background_color, text_color=self.TextColor, key=key, pad=pad, + tooltip=tooltip, visible=visible, size_px=size_px) + + def Get(self): + return self.WxCheckbox.GetValue() + + def Update(self, value=None, disabled=None): + if value is not None: + try: + self.WxCheckbox.SetValue(value) + self.InitialState = value + except: + pass + if disabled == True: + self.WxCheckbox.Disable() + elif disabled == False: + self.WxCheckbox.Enable() + + get = Get + update = Update + + +# ------------------------- CHECKBOX Element lazy functions ------------------------- # +CB = Checkbox +CBox = Checkbox +Check = Checkbox + + +# ---------------------------------------------------------------------- # +# Spin # +# ---------------------------------------------------------------------- # + +class Spin(Element): + # Values = None + # TKSpinBox = None + def __init__(self, values, initial_value=None, disabled=False, change_submits=False, enable_events=False, size=(None, None), readonly=True, auto_size_text=None, font=None, background_color=None, text_color=None, key=None, pad=None, tooltip=None, visible=True, size_px=(None,None)): + ''' + Spinner Element + :param values: + :param initial_value: + :param disabled: + :param change_submits: + :param size: + :param auto_size_text: + :param font: + :param background_color: + :param text_color: + :param key: + :param pad: + :param tooltip: + ''' + self.Values = values + self.DefaultValue = initial_value or values[0] + self.ChangeSubmits = change_submits or enable_events + self.Disabled = disabled + bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR + fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR + self.WxSpinCtrl : wx.SpinCtrl = None + self.WxTextCtrl = None # type : wx.TextCtrl + self.CurrentValue = self.DefaultValue + self.ReadOnly = readonly + + + super().__init__(ELEM_TYPE_INPUT_SPIN, size=size, auto_size_text=auto_size_text, font=font, background_color=bg, text_color=fg, + key=key, pad=pad, tooltip=tooltip, visible=visible, size_px=size_px) + return + + + def _WxSpinCallback(self, event): + event = event # type:wx.SpinEvent + print(f'spin event {event.GetInt()} {self.WxSpinCtrl.GetValue()}') + offset = event.GetInt() + self.WxTextCtrl.SetValue(self.Values[offset]) + self.CurrentValue = self.Values[offset] + if self.ChangeSubmits: + element_callback_quit_mainloop(self) + + def Update(self, value=None, values=None, disabled=None, background_color=None, text_color=None, font=None, visible=None): + if values != None: + self.Values = values + self.QT_Spinner.setStrings(values) + # self.QT_Spinner.setRange(self.Values[0], self.Values[1]) + if value is not None: + # self.QT_Spinner.setValue(value) + try: + self.QT_Spinner.setValue(self.QT_Spinner.valueFromText(value)) + self.DefaultValue = value + except: + pass + if disabled == True: + self.QT_Spinner.setDisabled(True) + elif disabled == False: + self.QT_Spinner.setDisabled(False) + super().Update(self.QT_Spinner, background_color=background_color, text_color=text_color, font=font, visible=visible) + + def Get(self): + return self.WxSpinCtrl.GetValue() + + get = Get + update = Update + + + +# ---------------------------------------------------------------------- # +# Multiline # +# ---------------------------------------------------------------------- # +class Multiline(Element): + def __init__(self, default_text='', enter_submits=False, disabled=False, autoscroll=False, size=(None, None), + auto_size_text=None, background_color=None, text_color=None, change_submits=False, enable_events=False, do_not_clear=True, + key=None, write_only=False, focus=False, font=None, pad=None, tooltip=None, visible=True, size_px=(None,None)): + ''' + Multiline Element + :param default_text: + :param enter_submits: + :param disabled: + :param autoscroll: + :param size: + :param auto_size_text: + :param background_color: + :param text_color: + :param do_not_clear: + :param key: + :param focus: + :param pad: + :param tooltip: + :param font: + ''' + self.DefaultText = default_text + self.EnterSubmits = enter_submits + bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR + self.Focus = focus + self.do_not_clear = do_not_clear + fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR + self.Autoscroll = autoscroll + self.Disabled = disabled + self.ChangeSubmits = change_submits or enable_events + self.WriteOnly = write_only + + self.Widget = self.WxTextCtrl = None + + super().__init__(ELEM_TYPE_INPUT_MULTILINE, size=size, auto_size_text=auto_size_text, background_color=bg, + text_color=fg, key=key, pad=pad, tooltip=tooltip, font=font or DEFAULT_FONT, visible=visible, size_px=size_px) + return + + + def Update(self, value=None, disabled=None, append=False, background_color=None, text_color=None, font=None, visible=None): + try: # added in case the widget has already been deleted for some readon. + if value is not None and not append: + self.WxTextCtrl.SetValue(value) + elif value is not None and append: + self.WxTextCtrl.AppendText(value) + if background_color is not None: + self.WxTextCtrl.SetBackgroundColour(background_color) + if text_color is not None: + self.WxTextCtrl.SetForegroundColour(text_color) + if font is not None: + self.WxTextCtrl.SetFont(font) + if disabled: + self.WxTextCtrl.Enable(True) + elif disabled is False: + self.WxTextCtrl.Enable(False) + except: + pass + + super().Update(self.WxTextCtrl, background_color=background_color, text_color=text_color, font=font, visible=visible) + + # + # def Update(self, value=None, disabled=None, append=False, background_color=None, text_color=None, font=None, visible=None): + # if value is not None and not append: + # self.DefaultText = value + # self.QT_TextEdit.setText(str(value)) + # elif value is not None and append: + # self.DefaultText = value + # self.QT_TextEdit.setText(self.QT_TextEdit.toPlainText() + str(value)) + # if disabled == True: + # self.QT_TextEdit.setDisabled(True) + # elif disabled == False: + # self.QT_TextEdit.setDisabled(False) + # super().Update(self.QT_TextEdit, background_color=background_color, text_color=text_color, font=font, visible=visible) + + + def Get(self): + self.WxTextCtrl.GetValue() + + def SetFocus(self): + self.WxTextCtrl.SetFocus() + + get = Get + set_focus = SetFocus + update = Update + + + +# ---------------------------------------------------------------------- # +# Multiline Output # +# ---------------------------------------------------------------------- # +class MultilineOutput(Element): + def __init__(self, default_text='', enter_submits=False, disabled=False, autoscroll=False, size=(None, None), auto_size_text=None, background_color=None, text_color=None, change_submits=False, enable_events=False, do_not_clear=True, key=None, focus=False, font=None, pad=None, tooltip=None, visible=True, size_px=(None,None)): + ''' + Multiline Element + :param default_text: + :param enter_submits: + :param disabled: + :param autoscroll: + :param size: + :param auto_size_text: + :param background_color: + :param text_color: + :param do_not_clear: + :param key: + :param focus: + :param pad: + :param tooltip: + :param font: + ''' + self.DefaultText = default_text + self.EnterSubmits = enter_submits + bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR + self.Focus = focus + self.do_not_clear = do_not_clear + fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR + self.Autoscroll = autoscroll + self.Disabled = disabled + self.ChangeSubmits = change_submits or enable_events + + self.WxTextCtrl = None + + super().__init__(ELEM_TYPE_MULTILINE_OUTPUT, size=size, auto_size_text=auto_size_text, background_color=bg, + text_color=fg, key=key, pad=pad, tooltip=tooltip, font=font or DEFAULT_FONT, visible=visible, size_px=size_px) + return + + + def Update(self, value=None, disabled=None, append=False, background_color=None, text_color=None, font=None, visible=None): + if value is not None and not append: + self.WxTextCtrl.SetLabel(value) + elif value is not None and append: + self.WxTextCtrl.AppendText(value) + if background_color is not None: + self.WxTextCtrl.SetBackgroundColour(background_color) + if text_color is not None: + self.WxTextCtrl.SetForegroundColour(text_color) + if font is not None: + self.WxTextCtrl.SetFont(font) + if disabled: + self.WxTextCtrl.Enable(True) + elif disabled is False: + self.WxTextCtrl.Enable(False) + super().Update(self.WxTextCtrl, background_color=background_color, text_color=text_color, font=font, visible=visible) + + + def Get(self): + self.WxTextCtrl.GetValue() + + def SetFocus(self): + self.WxTextCtrl.SetFocus() + + get = Get + set_focus = SetFocus + update = Update + +# ---------------------------------------------------------------------- # +# Text # +# ---------------------------------------------------------------------- # +class Text(Element): + def __init__(self, text='', size=(None, None), auto_size_text=None, click_submits=None, enable_events=False, relief=None, border_width=None, font=None, text_color=None, background_color=None, justification=None, pad=None, margins=None, key=None, tooltip=None, visible=True, size_px=(None,None)): + """ + Text + :param text: + :param size: + :param auto_size_text: + :param click_submits: + :param enable_events: + :param relief: + :param font: + :param text_color: + :param background_color: + :param justification: + :param pad: + :param margins: + :param key: + :param tooltip: + :param visible: + :param size_px: + """ + self.DisplayText = str(text) + self.TextColor = text_color if text_color else DEFAULT_TEXT_COLOR + self.Justification = justification + self.Relief = relief + self.ClickSubmits = click_submits or enable_events + self.Margins = margins + self.size_px = size_px + if background_color is None: + bg = DEFAULT_TEXT_ELEMENT_BACKGROUND_COLOR + else: + bg = background_color + pixelsize = size + if size[1] is not None and size[1] < 10: + pixelsize = size[0]*10, size[1]*20 + self.WxStaticText = None # type: wx.StaticText # wx.StaticText(form.MasterPanel, -1, element.DisplayText) + self.BorderWidth = border_width if border_width is not None else DEFAULT_BORDER_WIDTH + + super().__init__(ELEM_TYPE_TEXT, pixelsize, auto_size_text, background_color=bg, font=font if font else DEFAULT_FONT, + text_color=self.TextColor, pad=pad, key=key, tooltip=tooltip, size_px=size_px, visible=visible) + return + + def Update(self, value=None, background_color=None, text_color=None, font=None, visible=None): + if self.ParentForm.TKrootDestroyed: + return + if value is not None: + self.WxStaticText.SetLabel(str(value)) + self.DisplayText = str(value) + if background_color is not None: + self.WxStaticText.SetBackgroundColour(background_color) + if text_color is not None: + self.WxStaticText.SetForegroundColour(text_color) + if font is not None: + self.WxStaticText.SetFont(font) + super().Update(self.WxStaticText, background_color=background_color, text_color=text_color, font=font, visible=visible) + + + update = Update + + +# ------------------------- Text Element lazy functions ------------------------- # +Txt = Text +T = Text + + +class RedirectText(object): + def __init__(self, aWxTextCtrl): + self.out = aWxTextCtrl + + def write(self, string): + self.out.AppendText(string) + + def flush(self): + return + +# ---------------------------------------------------------------------- # +# Output # +# Routes stdout, stderr to a scrolled window # +# ---------------------------------------------------------------------- # +class Output(Element): + def __init__(self, size=(None, None), background_color=None, text_color=None, pad=None, font=None, tooltip=None, + key=None, visible=True, size_px=(None,None), disabled=False): + ''' + Output Element + :param size: + :param background_color: + :param text_color: + :param pad: + :param font: + :param tooltip: + :param key: + ''' + self._TKOut = None + bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR + fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR + self.WxTextCtrl = None # type: wx.TextCtrl + self.redir = None + self.output = None + self.Disabled = disabled + + super().__init__(ELEM_TYPE_OUTPUT, size=size, background_color=bg, text_color=fg, pad=pad, font=font, + tooltip=tooltip, key=key, visible=visible, size_px=size_px) + + def _reroute_stdout(self): + self.my_stdout = sys.stdout + self.my_stderr = sys.stderr + self.redir = RedirectText(self.WxTextCtrl) + sys.stdout = self.redir + sys.stderr = self.redir + Window.stdout_is_rerouted = True + Window.stdout_location = self.redir + + def _reroute_again(self): + sys.stdout = self.redir + + def Update(self,value=None, background_color=None, text_color=None, font=None, visible=None): + if value is not None: + self.WxTextCtrl.AppendText(value) + super().Update(self.WxTextCtrl, background_color=background_color, text_color=text_color, font=font, visible=visible) + + + def __del__(self): + try: + sys.stdout = self.my_stdout + sys.stderr = self.my_stderr + except: pass + # super().__del__() + + + + update = Update + +# ---------------------------------------------------------------------- # +# Button Class # +# ---------------------------------------------------------------------- # +class Button(Element): + def __init__(self, button_text='', button_type=BUTTON_TYPE_READ_FORM, target=(None, None), tooltip=None, + file_types=(("ALL Files", "*"),), initial_folder=None, disabled=False, change_submits=False, enable_events=False, + image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, border_width=None, + size=(None, None), auto_size_button=None, button_color=None, font=None, bind_return_key=False, + focus=False, pad=None, key=None, visible=True, size_px=(None,None)): + ''' + Button Element + :param button_text: + :param button_type: + :param target: + :param tooltip: + :param file_types: + :param initial_folder: + :param disabled: + :param image_filename: + :param image_size: + :param image_subsample: + :param border_width: + :param size: + :param auto_size_button: + :param button_color: + :param default_value: + :param font: + :param bind_return_key: + :param focus: + :param pad: + :param key: + ''' + self.AutoSizeButton = auto_size_button + self.BType = button_type + self.FileTypes = file_types + self.TKButton = None + self.Target = target + self.ButtonText = str(button_text) + self.ButtonColor = button_color if button_color else DEFAULT_BUTTON_COLOR + self.TextColor = self.ButtonColor[0] + self.BackgroundColor = self.ButtonColor[1] + self.ImageFilename = image_filename + self.ImageData = image_data + self.ImageSize = image_size + self.ImageSubsample = image_subsample + self.UserData = None + self.BorderWidth = border_width if border_width is not None else DEFAULT_BORDER_WIDTH + self.BindReturnKey = bind_return_key + self.Focus = focus + self.TKCal = None + self.CalendarCloseWhenChosen = None + self.DefaultDate_M_D_Y = (None, None, None) + self.InitialFolder = initial_folder + self.Disabled = disabled + self.ChangeSubmits = change_submits or enable_events + self.QT_QPushButton = None + self.ColorChosen = None + self.Relief = None + self.WxButton = None # type: wx.Button + # self.temp_size = size if size != (NONE, NONE) else + + super().__init__(ELEM_TYPE_BUTTON, size=size, font=font, pad=pad, key=key, tooltip=tooltip, text_color=self.TextColor, background_color=self.BackgroundColor, visible=visible, size_px=size_px) + return + + # Realtime button release callback + def ButtonReleaseCallBack(self, parm): + self.LastButtonClickedWasRealtime = False + self.ParentForm.LastButtonClicked = None + + # Realtime button callback + def ButtonPressCallBack(self, parm): + self.ParentForm.LastButtonClickedWasRealtime = True + if self.Key is not None: + self.ParentForm.LastButtonClicked = self.Key + else: + self.ParentForm.LastButtonClicked = self.ButtonText + if self.ParentForm.CurrentlyRunningMainloop: + pass # kick out of loop if read was called + + # ------- Button Callback ------- # + def ButtonCallBack(self, event): + + # print('Button callback') + + # print(f'Parent = {self.ParentForm} Position = {self.Position}') + # Buttons modify targets or return from the form + # If modifying target, get the element object at the target and modify its StrVar + target = self.Target + target_element = None + if target[0] == ThisRow: + target = [self.Position[0], target[1]] + if target[1] < 0: + target[1] = self.Position[1] + target[1] + strvar = None + should_submit_window = False + if target == (None, None): + strvar = self.TKStringVar + else: + if not isinstance(target, str): + if target[0] < 0: + target = [self.Position[0] + target[0], target[1]] + target_element = self.ParentContainer._GetElementAtLocation(target) + else: + target_element = self.ParentForm.FindElement(target) + try: + strvar = target_element.TKStringVar + except: + pass + try: + if target_element.ChangeSubmits: + should_submit_window = True + except: + pass + filetypes = (("ALL Files", "*"),) if self.FileTypes is None else self.FileTypes + if self.BType == BUTTON_TYPE_BROWSE_FOLDER: # Browse Folder + wx_types = convert_tkinter_filetypes_to_wx(self.FileTypes) + if self.InitialFolder: + dialog = wx.DirDialog(self.ParentForm.MasterFrame, style=wx.FD_OPEN) + else: + dialog = wx.DirDialog(self.ParentForm.MasterFrame) + folder_name = '' + if dialog.ShowModal() == wx.ID_OK: + folder_name = dialog.GetPath() + if folder_name != '': + if target_element.Type == ELEM_TYPE_BUTTON: + target_element.FileOrFolderName = folder_name + else: + target_element.Update(folder_name) + elif self.BType == BUTTON_TYPE_BROWSE_FILE: # Browse File + qt_types = convert_tkinter_filetypes_to_wx(self.FileTypes) + if self.InitialFolder: + dialog = wx.FileDialog(self.ParentForm.MasterFrame,defaultDir=self.InitialFolder, wildcard=qt_types, style=wx.FD_OPEN) + else: + dialog = wx.FileDialog(self.ParentForm.MasterFrame, wildcard=qt_types, style=wx.FD_OPEN) + file_name = '' + if dialog.ShowModal() == wx.ID_OK: + file_name = dialog.GetPath() + else: + file_name = '' + if file_name != '': + if target_element.Type == ELEM_TYPE_BUTTON: + target_element.FileOrFolderName = file_name + else: + target_element.Update(file_name) + elif self.BType == BUTTON_TYPE_BROWSE_FILES: # Browse Files + qt_types = convert_tkinter_filetypes_to_wx(self.FileTypes) + if self.InitialFolder: + dialog = wx.FileDialog(self.ParentForm.MasterFrame,defaultDir=self.InitialFolder, wildcard=qt_types, style=wx.FD_MULTIPLE) + else: + dialog = wx.FileDialog(self.ParentForm.MasterFrame, wildcard=qt_types, style=wx.FD_MULTIPLE) + file_names = '' + if dialog.ShowModal() == wx.ID_OK: + file_names = dialog.GetPaths() + else: + file_names = '' + if file_names != '': + file_names = BROWSE_FILES_DELIMITER.join(file_names) + if target_element.Type == ELEM_TYPE_BUTTON: + target_element.FileOrFolderName = file_names + else: + target_element.Update(file_names) + elif self.BType == BUTTON_TYPE_SAVEAS_FILE: # Save As File + qt_types = convert_tkinter_filetypes_to_wx(self.FileTypes) + if self.InitialFolder: + dialog = wx.FileDialog(self.ParentForm.MasterFrame,defaultDir=self.InitialFolder, wildcard=qt_types, style=wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) + else: + dialog = wx.FileDialog(self.ParentForm.MasterFrame, wildcard=qt_types, style=wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) + file_name = '' + if dialog.ShowModal() == wx.ID_OK: + file_name = dialog.GetPath() + else: + file_name = '' + if file_name != '': + if target_element.Type == ELEM_TYPE_BUTTON: + target_element.FileOrFolderName = file_name + else: + target_element.Update(file_name) + elif self.BType == BUTTON_TYPE_COLOR_CHOOSER: # Color Chooser + qcolor = QColorDialog.getColor() + rgb_color = qcolor.getRgb() + color= '#' + ''.join('%02x'% i for i in rgb_color[:3]) + if self.Target == (None, None): + self.FileOrFolderName = color + else: + target_element.Update(color) + elif self.BType == BUTTON_TYPE_CLOSES_WIN: # Closes Window + # first, get the results table built + # modify the Results table in the parent FlexForm object + if self.Key is not None: + self.ParentForm.LastButtonClicked = self.Key + else: + self.ParentForm.LastButtonClicked = self.ButtonText + self.ParentForm.FormRemainedOpen = False + if self.ParentForm.CurrentlyRunningMainloop: + self.ParentForm.App.ExitMainLoop() + self.ParentForm.IgnoreClose = True + self.ParentForm.MasterFrame.Close() + if self.ParentForm.NonBlocking: + Window.DecrementOpenCount() + self.ParentForm._Close() + elif self.BType == BUTTON_TYPE_READ_FORM: # Read Button + # first, get the results table built + # modify the Results table in the parent FlexForm object + if self.Key is not None: + self.ParentForm.LastButtonClicked = self.Key + else: + self.ParentForm.LastButtonClicked = self.ButtonText + self.ParentForm.FormRemainedOpen = True + if self.ParentForm.CurrentlyRunningMainloop: # if this window is running the mainloop, kick out + self.ParentForm.App.ExitMainLoop() + elif self.BType == BUTTON_TYPE_CLOSES_WIN_ONLY: # special kind of button that does not exit main loop + if self.Key is not None: + self.ParentForm.LastButtonClicked = self.Key + else: + self.ParentForm.LastButtonClicked = self.ButtonText + if self.ParentForm.CurrentlyRunningMainloop: # if this window is running the mainloop, kick out + self.ParentForm.App.ExitMainLoop() + self.ParentForm.IgnoreClose = True + self.ParentForm.MasterFrame.Close() + self.ParentForm._Close() + Window.DecrementOpenCount() + elif self.BType == BUTTON_TYPE_CALENDAR_CHOOSER: # this is a return type button so GET RESULTS and destroy window + should_submit_window = False + + if should_submit_window: + self.ParentForm.LastButtonClicked = target_element.Key + self.ParentForm.FormRemainedOpen = True + if self.ParentForm.CurrentlyRunningMainloop: + self.ParentForm.App.ExitMainLoop() + return + + def Update(self, text=None, button_color=(None, None), disabled=None, image_data=None, image_filename=None, font=None, visible=None): + if text is not None: + self.WxButton.SetLabelText(text) + self.ButtonText = text + fg = bg = None + if button_color != (None, None): + self.ButtonColor = button_color + fg, bg = button_color + super().Update(self.WxButton, background_color=bg, text_color=fg, font=font, visible=visible, disabled=disabled) + + + def GetText(self): + return self.ButtonText + + def SetFocus(self): + self.QT_QPushButton.setFocus() + + get_text = GetText + set_focus = SetFocus + update = Update + + + +def convert_tkinter_filetypes_to_wx(filetypes): + wx_filetypes = '' + for item in filetypes: + filetype = item[0] + ' (' + item[1] + ')|'+ item[1] + wx_filetypes += filetype + return wx_filetypes + + +# ------------------------- Button lazy functions ------------------------- # +B = Button +Btn = Button + + +# ---------------------------------------------------------------------- # +# ProgreessBar # +# ---------------------------------------------------------------------- # +class ProgressBar(Element): + def __init__(self, max_value, orientation=None, size=(None, None),start_value=0, auto_size_text=None, bar_color=(None, None), + style=None, border_width=None, relief=None, key=None, pad=None, disabled=False, visible=True, size_px=(None,None)): + ''' + ProgressBar Element + :param max_value: + :param orientation: + :param size: + :param auto_size_text: + :param bar_color: + :param style: + :param border_width: + :param relief: + :param key: + :param pad: + ''' + self.MaxValue = max_value + self.TKProgressBar = None + self.Cancelled = False + self.NotRunning = True + self.Orientation = orientation if orientation else DEFAULT_METER_ORIENTATION + self.BarColor = bar_color if bar_color != (None, None) else DEFAULT_PROGRESS_BAR_COLOR + self.BarStyle = style if style else DEFAULT_PROGRESS_BAR_STYLE + self.BorderWidth = border_width if border_width is not None else DEFAULT_PROGRESS_BAR_BORDER_WIDTH + self.Relief = relief if relief else DEFAULT_PROGRESS_BAR_RELIEF + self.BarExpired = False + self.StartValue = start_value + self.Disabled = disabled + tsize = size + if size[0] is not None and size[0] < 100: + # tsize = size[0] * DEFAULT_PIXELS_TO_CHARS_SCALING[0], size[1] * DEFAULT_PIXELS_TO_CHARS_SCALING[1] + tsize = size[0]*10, size[1] + self.WxGauge = None # type: wx.Gauge + + super().__init__(ELEM_TYPE_PROGRESS_BAR, size=tsize, auto_size_text=auto_size_text, key=key, pad=pad, visible=visible, size_px=size_px) + + # returns False if update failed + def UpdateBar(self, current_count, max=None): + try: # Could havae been destroyed by user + if max is not None: + self.WxGauge.SetRange(max) + self.WxGauge.SetValue(current_count) + except: pass + return True + + + def Update(self, visible=None): + super().Update(self.WxGauge, visible=visible) + + update = Update + update_bar = UpdateBar + + +# ---------------------------------------------------------------------- # +# Image # +# ---------------------------------------------------------------------- # +class Image(Element): + def __init__(self, filename=None, data=None, background_color=None, size=(None, None), pad=None, key=None, + tooltip=None): + ''' + Image Element + :param filename: + :param data: + :param background_color: + :param size: + :param pad: + :param key: + :param tooltip: + ''' + self.Filename = filename + self.Data = data + self.tktext_label = None + self.BackgroundColor = background_color + if data is None and filename is None: + print('* Warning... no image specified in Image Element! *') + super().__init__(ELEM_TYPE_IMAGE, size=size, background_color=background_color, pad=pad, key=key, + tooltip=tooltip, size_px=size) + return + + def Update(self, filename=None, data=None, size=(None, None)): + if filename is not None: + image = tk.PhotoImage(file=filename) + elif data is not None: + # if type(data) is bytes: + try: + image = tk.PhotoImage(data=data) + except: + return # an error likely means the window has closed so exit + # else: + # image = data + else: + return + width, height = size[0] or image.width(), size[1] or image.height() + self.tktext_label.configure(image=image, width=width, height=height) + self.tktext_label.image = image + + + update = Update + + +# ---------------------------------------------------------------------- # +# Canvas # +# ---------------------------------------------------------------------- # +class Canvas(Element): + def __init__(self, canvas=None, background_color=None, size=(None, None), pad=None, key=None, tooltip=None): + ''' + Canvas Element + :param canvas: + :param background_color: + :param size: + :param pad: + :param key: + :param tooltip: + ''' + self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR + self._TKCanvas = canvas + + super().__init__(ELEM_TYPE_CANVAS, background_color=background_color, size=size, pad=pad, key=key, + tooltip=tooltip) + return + + @property + def TKCanvas(self): + if self._TKCanvas is None: + print('*** Did you forget to call Finalize()? Your code should look something like: ***') + print('*** form = sg.Window("My Form").Layout(layout).Finalize() ***') + return self._TKCanvas + + + + +# ---------------------------------------------------------------------- # +# Graph # +# ---------------------------------------------------------------------- # +class Graph(Element): + def __init__(self, canvas_size, graph_bottom_left, graph_top_right, background_color=None, pad=None, + change_submits=False, drag_submits=False, key=None, tooltip=None): + ''' + Graph Element + :param canvas_size: + :param graph_bottom_left: + :param graph_top_right: + :param background_color: + :param pad: + :param key: + :param tooltip: + ''' + self.CanvasSize = canvas_size + self.BottomLeft = graph_bottom_left + self.TopRight = graph_top_right + self._TKCanvas = None + self._TKCanvas2 = None + self.ChangeSubmits = change_submits + self.DragSubmits = drag_submits + self.ClickPosition = (None, None) + self.MouseButtonDown = False + super().__init__(ELEM_TYPE_GRAPH, background_color=background_color, size_px=canvas_size, pad=pad, key=key, + tooltip=tooltip) + return + + def _convert_xy_to_canvas_xy(self, x_in, y_in): + if None in (x_in, y_in): + return None, None + scale_x = (self.CanvasSize[0] - 0) / (self.TopRight[0] - self.BottomLeft[0]) + scale_y = (0 - self.CanvasSize[1]) / (self.TopRight[1] - self.BottomLeft[1]) + new_x = 0 + scale_x * (x_in - self.BottomLeft[0]) + new_y = self.CanvasSize[1] + scale_y * (y_in - self.BottomLeft[1]) + return new_x, new_y + + def _convert_canvas_xy_to_xy(self, x_in, y_in): + if None in (x_in, y_in): + return None, None + scale_x = (self.CanvasSize[0] - 0) / (self.TopRight[0] - self.BottomLeft[0]) + scale_y = (0 - self.CanvasSize[1]) / (self.TopRight[1] - self.BottomLeft[1]) + + new_x = x_in / scale_x + self.BottomLeft[0] + new_y = (y_in - self.CanvasSize[1]) / scale_y + self.BottomLeft[1] + return int(new_x), int(new_y) + + def DrawLine(self, point_from, point_to, color='black', width=1): + if point_from == (None, None): + return + converted_point_from = self._convert_xy_to_canvas_xy(point_from[0], point_from[1]) + converted_point_to = self._convert_xy_to_canvas_xy(point_to[0], point_to[1]) + if self._TKCanvas2 is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + return self._TKCanvas2.create_line(converted_point_from, converted_point_to, width=width, fill=color) + + def DrawPoint(self, point, size=2, color='black'): + if point == (None, None): + return + converted_point = self._convert_xy_to_canvas_xy(point[0], point[1]) + if self._TKCanvas2 is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + return self._TKCanvas2.create_oval(converted_point[0] - size, converted_point[1] - size, + converted_point[0] + size, converted_point[1] + size, fill=color, + outline=color) + + def DrawCircle(self, center_location, radius, fill_color=None, line_color='black'): + if center_location == (None, None): + return + converted_point = self._convert_xy_to_canvas_xy(center_location[0], center_location[1]) + if self._TKCanvas2 is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + return self._TKCanvas2.create_oval(converted_point[0] - radius, converted_point[1] - radius, + converted_point[0] + radius, converted_point[1] + radius, fill=fill_color, + outline=line_color) + + def DrawOval(self, top_left, bottom_right, fill_color=None, line_color=None): + converted_top_left = self._convert_xy_to_canvas_xy(top_left[0], top_left[1]) + converted_bottom_right = self._convert_xy_to_canvas_xy(bottom_right[0], bottom_right[1]) + if self._TKCanvas2 is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + return self._TKCanvas2.create_oval(converted_top_left[0], converted_top_left[1], converted_bottom_right[0], + converted_bottom_right[1], fill=fill_color, outline=line_color) + + def DrawArc(self, top_left, bottom_right, extent, start_angle, style=None, arc_color='black'): + converted_top_left = self._convert_xy_to_canvas_xy(top_left[0], top_left[1]) + converted_bottom_right = self._convert_xy_to_canvas_xy(bottom_right[0], bottom_right[1]) + tkstyle = tk.PIESLICE if style is None else style + if self._TKCanvas2 is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + return self._TKCanvas2.create_arc(converted_top_left[0], converted_top_left[1], converted_bottom_right[0], + converted_bottom_right[1], extent=extent, start=start_angle, style=tkstyle, + outline=arc_color) + + def DrawRectangle(self, top_left, bottom_right, fill_color=None, line_color=None): + converted_top_left = self._convert_xy_to_canvas_xy(top_left[0], top_left[1]) + converted_bottom_right = self._convert_xy_to_canvas_xy(bottom_right[0], bottom_right[1]) + if self._TKCanvas2 is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + return self._TKCanvas2.create_rectangle(converted_top_left[0], converted_top_left[1], converted_bottom_right[0], + converted_bottom_right[1], fill=fill_color, outline=line_color) + + def DrawText(self, text, location, color='black', font=None, angle=0): + if location == (None, None): + return + converted_point = self._convert_xy_to_canvas_xy(location[0], location[1]) + if self._TKCanvas2 is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + text_id = self._TKCanvas2.create_text(converted_point[0], converted_point[1], text=text, font=font, fill=color, + angle=angle) + return text_id + + def Erase(self): + if self._TKCanvas2 is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + self._TKCanvas2.delete('all') + + def Update(self, background_color): + if self._TKCanvas2 is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + self._TKCanvas2.configure(background=background_color) + + def Move(self, x_direction, y_direction): + zero_converted = self._convert_xy_to_canvas_xy(0, 0) + shift_converted = self._convert_xy_to_canvas_xy(x_direction, y_direction) + shift_amount = (shift_converted[0] - zero_converted[0], shift_converted[1] - zero_converted[1]) + if self._TKCanvas2 is None: + print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') + print('Call Window.Finalize() prior to this operation') + return None + self._TKCanvas2.move('all', shift_amount[0], shift_amount[1]) + + def MoveFigure(self, figure, x_direction, y_direction): + zero_converted = self._convert_xy_to_canvas_xy(0, 0) + shift_converted = self._convert_xy_to_canvas_xy(x_direction, y_direction) + shift_amount = (shift_converted[0] - zero_converted[0], shift_converted[1] - zero_converted[1]) + if figure is None: + print('*** WARNING - Your figure is None. It most likely means your did not Finalize your Window ***') + print('Call Window.Finalize() prior to all graph operations') + return None + self._TKCanvas2.move(figure, shift_amount[0], shift_amount[1]) + + def change_coordinates(self, graph_bottom_left, graph_top_right): + """ + Changes the corrdinate system to a new one. The same 2 points in space are used to define the coorinate + system - the bottom left and the top right values of your graph. + + :param graph_bottom_left: Tuple[int, int] (x,y) The bottoms left corner of your coordinate system + :param graph_top_right: Tuple[int, int] (x,y) The top right corner of your coordinate system + """ + self.BottomLeft = graph_bottom_left + self.TopRight = graph_top_right + + + @property + def TKCanvas(self): + if self._TKCanvas2 is None: + print('*** Did you forget to call Finalize()? Your code should look something like: ***') + print('*** form = sg.Window("My Form").Layout(layout).Finalize() ***') + return self._TKCanvas2 + + # Realtime button release callback + def ButtonReleaseCallBack(self, event): + self.ClickPosition = (None, None) + self.LastButtonClickedWasRealtime = not self.DragSubmits + if self.Key is not None: + self.ParentForm.LastButtonClicked = self.Key + else: + self.ParentForm.LastButtonClicked = '__GRAPH__' # need to put something rather than None + if self.ParentForm.CurrentlyRunningMainloop: + self.ParentForm.TKroot.quit() + if self.DragSubmits: + self.ParentForm.LastButtonClicked = None + self.MouseButtonDown = False + + # Realtime button callback + def ButtonPressCallBack(self, event): + self.ClickPosition = self._convert_canvas_xy_to_xy(event.x, event.y) + self.ParentForm.LastButtonClickedWasRealtime = self.DragSubmits + if self.Key is not None: + self.ParentForm.LastButtonClicked = self.Key + else: + self.ParentForm.LastButtonClicked = '__GRAPH__' # need to put something rather than None + if self.ParentForm.CurrentlyRunningMainloop: + self.ParentForm.TKroot.quit() # kick out of loop if read was called + self.MouseButtonDown = True + + # Realtime button callback + def MotionCallBack(self, event): + if not self.MouseButtonDown: + return + self.ClickPosition = self._convert_canvas_xy_to_xy(event.x, event.y) + self.ParentForm.LastButtonClickedWasRealtime = self.DragSubmits + if self.Key is not None: + self.ParentForm.LastButtonClicked = self.Key + else: + self.ParentForm.LastButtonClicked = '__GRAPH__' # need to put something rather than None + if self.ParentForm.CurrentlyRunningMainloop: + self.ParentForm.TKroot.quit() # kick out of loop if read was called + +# ---------------------------------------------------------------------- # +# Frame # +# ---------------------------------------------------------------------- # +class Frame(Element): + def __init__(self, title, layout, title_color=None, background_color=None, title_location=None,element_justification='left', + relief=DEFAULT_FRAME_RELIEF, size=(None, None), size_px=(None,None), font=None, pad=None, border_width=None, key=None, + tooltip=None): + ''' + Frame Element + :param title: + :param layout: + :param title_color: + :param background_color: + :param title_location: + :param relief: + :param size: + :param font: + :param pad: + :param border_width: + :param key: + :param tooltip: + ''' + self.UseDictionary = False + self.ReturnValues = None + self.ReturnValuesList = [] + self.ReturnValuesDictionary = {} + self.DictionaryKeyCounter = 0 + self.ParentWindow = None + self.Rows = [] + # self.ParentForm = None + self.TKFrame = None + self.Title = title + self.Relief = relief + self.TitleLocation = title_location + self.BorderWidth = border_width + self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR + self.ElementJustification = element_justification + + self._Layout(layout) + + super().__init__(ELEM_TYPE_FRAME, background_color=background_color, text_color=title_color, size=size, + font=font, pad=pad, key=key, tooltip=tooltip, size_px=size_px) + return + + def _AddRow(self, *args): + ''' Parms are a variable number of Elements ''' + NumRows = len(self.Rows) # number of existing rows is our row number + CurrentRowNumber = NumRows # this row's number + CurrentRow = [] # start with a blank row and build up + # ------------------------- Add the elements to a row ------------------------- # + for i, element in enumerate(args): # Loop through list of elements and add them to the row + element.Position = (CurrentRowNumber, i) + element.ParentContainer = self + CurrentRow.append(element) + if element.Key is not None: + self.UseDictionary = True + # ------------------------- Append the row to list of Rows ------------------------- # + self.Rows.append(CurrentRow) + + def _Layout(self, rows): + for row in rows: + self._AddRow(*row) + + def _GetElementAtLocation(self, location): + (row_num, col_num) = location + row = self.Rows[row_num] + element = row[col_num] + return element + + + + +# ---------------------------------------------------------------------- # +# Separator # +# Routes stdout, stderr to a scrolled window # +# ---------------------------------------------------------------------- # +class VerticalSeparator(Element): + def __init__(self, size=(None, None), size_px=None, pad=None): + ''' + VerticalSeperator - A separator that spans only 1 row in a vertical fashion + :param pad: + ''' + self.Orientation = 'vertical' # for now only vertical works + self.Disabled = None + self.WxStaticLine = None # type: wx.StaticLine + super().__init__(ELEM_TYPE_SEPARATOR, pad=pad, size=size, size_px=size_px) + + + +VSeparator = VerticalSeparator +VSeparator = VerticalSeparator +VSep = VerticalSeparator + + + +# ---------------------------------------------------------------------- # +# Separator # +# ---------------------------------------------------------------------- # +class HorizontalSeparator(Element): + def __init__(self, pad=None, size=(None, None), size_px=(None,None)): + ''' + VerticalSeperator - A separator that spans only 1 row in a vertical fashion + :param pad: + ''' + self.Orientation = 'horizontal' # for now only vertical works + self.Disabled = None + self.WxStaticLine = None # type: wx.StaticLine + + super().__init__(ELEM_TYPE_SEPARATOR, pad=pad, size=size, size_px=size_px) + + + +HSeperator = HorizontalSeparator +HSep = HorizontalSeparator + + + + +# ---------------------------------------------------------------------- # +# Tab # +# ---------------------------------------------------------------------- # +class Tab(Element): + def __init__(self, title, layout, title_color=None, background_color=None, font=None, element_justification='left', pad=None, disabled=False, + border_width=None, key=None, tooltip=None): + ''' + Tab Element + :param title: + :param layout: + :param title_color: + :param background_color: + :param font: + :param pad: + :param disabled: + :param border_width: + :param key: + :param tooltip: + ''' + self.UseDictionary = False + self.ReturnValues = None + self.ReturnValuesList = [] + self.ReturnValuesDictionary = {} + self.DictionaryKeyCounter = 0 + self.ParentWindow = None + self.Rows = [] + self.TKFrame = None + self.Title = title + self.BorderWidth = border_width + self.Disabled = disabled + self.ParentNotebook = None + self.TabID = None + self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR + self.ElementJustification = element_justification + + self._Layout(layout) + + super().__init__(ELEM_TYPE_TAB, background_color=background_color, text_color=title_color, font=font, pad=pad, + key=key, tooltip=tooltip) + return + + def _AddRow(self, *args): + ''' Parms are a variable number of Elements ''' + NumRows = len(self.Rows) # number of existing rows is our row number + CurrentRowNumber = NumRows # this row's number + CurrentRow = [] # start with a blank row and build up + # ------------------------- Add the elements to a row ------------------------- # + for i, element in enumerate(args): # Loop through list of elements and add them to the row + element.Position = (CurrentRowNumber, i) + element.ParentContainer = self + CurrentRow.append(element) + if element.Key is not None: + self.UseDictionary = True + # ------------------------- Append the row to list of Rows ------------------------- # + self.Rows.append(CurrentRow) + + def _Layout(self, rows): + for row in rows: + self._AddRow(*row) + return self + + def Update(self, disabled=None): # TODO Disable / enable of tabs is not complete + if disabled is None: + return + self.Disabled = disabled + state = 'disabled' if disabled is True else 'normal' + self.ParentNotebook.tab(self.TabID, state=state) + return self + + def _GetElementAtLocation(self, location): + (row_num, col_num) = location + row = self.Rows[row_num] + element = row[col_num] + return element + + update = Update + + +# ---------------------------------------------------------------------- # +# TabGroup # +# ---------------------------------------------------------------------- # +class TabGroup(Element): + def __init__(self, layout, tab_location=None, title_color=None, selected_title_color=None, background_color=None, + font=None, change_submits=False, pad=None, border_width=None, theme=None, key=None, tooltip=None): + ''' + TabGroup Element + :param layout: + :param tab_location: + :param title_color: + :param selected_title_color: + :param background_color: + :param font: + :param change_submits: + :param pad: + :param border_width: + :param theme: + :param key: + :param tooltip: + ''' + self.UseDictionary = False + self.ReturnValues = None + self.ReturnValuesList = [] + self.ReturnValuesDictionary = {} + self.DictionaryKeyCounter = 0 + self.ParentWindow = None + self.SelectedTitleColor = selected_title_color + self.Rows = [] + self.TKNotebook = None + self.TabCount = 0 + self.BorderWidth = border_width + self.Theme = theme + self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR + self.ChangeSubmits = change_submits + self.TabLocation = tab_location + + self._Layout(layout) + + super().__init__(ELEM_TYPE_TAB_GROUP, background_color=background_color, text_color=title_color, font=font, + pad=pad, key=key, tooltip=tooltip) + return + + def _AddRow(self, *args): + ''' Parms are a variable number of Elements ''' + NumRows = len(self.Rows) # number of existing rows is our row number + CurrentRowNumber = NumRows # this row's number + CurrentRow = [] # start with a blank row and build up + # ------------------------- Add the elements to a row ------------------------- # + for i, element in enumerate(args): # Loop through list of elements and add them to the row + element.Position = (CurrentRowNumber, i) + element.ParentContainer = self + CurrentRow.append(element) + if element.Key is not None: + self.UseDictionary = True + # ------------------------- Append the row to list of Rows ------------------------- # + self.Rows.append(CurrentRow) + + def _Layout(self, rows): + for row in rows: + self._AddRow(*row) + + def _GetElementAtLocation(self, location): + (row_num, col_num) = location + row = self.Rows[row_num] + element = row[col_num] + return element + + def FindKeyFromTabName(self, tab_name): + for row in self.Rows: + for element in row: + if element.Title == tab_name: + return element.Key + return None + + find_key_from_tab_name = FindKeyFromTabName + + +# ---------------------------------------------------------------------- # +# Slider # +# ---------------------------------------------------------------------- # +class Slider(Element): + def __init__(self, range=(None, None), default_value=None, resolution=None, tick_interval=None, orientation=None, + border_width=None, relief=None, change_submits=False, disabled=False, size=(None, None), size_px=(None,None), font=None, + background_color=None, text_color=None, key=None, pad=None, tooltip=None): + ''' + Slider Element + :param range: + :param default_value: + :param resolution: + :param orientation: + :param border_width: + :param relief: + :param change_submits: + :param disabled: + :param size: + :param font: + :param background_color: + :param text_color: + :param key: + :param pad: + :param tooltip: + ''' + self.TKScale = None + self.Range = (1, 10) if range == (None, None) else range + self.DefaultValue = self.Range[0] if default_value is None else default_value + self.Orientation = orientation if orientation else DEFAULT_SLIDER_ORIENTATION + self.BorderWidth = border_width if border_width else DEFAULT_SLIDER_BORDER_WIDTH + self.Relief = relief if relief else DEFAULT_SLIDER_RELIEF + self.Resolution = 1 if resolution is None else resolution + self.ChangeSubmits = change_submits + self.Disabled = disabled + self.TickInterval = tick_interval + temp_size = size + if temp_size == (None, None): + temp_size = (20, 20) if orientation.startswith('h') else (8, 20) + + super().__init__(ELEM_TYPE_INPUT_SLIDER, size=temp_size, font=font, background_color=background_color, + text_color=text_color, key=key, pad=pad, tooltip=tooltip, size_px=size_px) + return + + def Update(self, value=None, range=(None, None), disabled=None): + if value is not None: + try: + self.TKIntVar.set(value) + if range != (None, None): + self.TKScale.config(from_=range[0], to_=range[1]) + except: + pass + self.DefaultValue = value + if disabled == True: + self.TKScale['state'] = 'disabled' + elif disabled == False: + self.TKScale['state'] = 'normal' + + + update = Update + + + +# +# ---------------------------------------------------------------------- # +# Column # +# ---------------------------------------------------------------------- # +class Column(Element): + def __init__(self, layout, background_color=None, element_justification='left', size=(None, None), size_px=(None, None), pad=None, scrollable=False, vertical_scroll_only=False, right_click_menu=None, key=None, visible=True): + ''' + Column Element + :param layout: + :param background_color: + :param size: + :param pad: + :param scrollable: + :param key: + ''' + self.UseDictionary = False + self.ReturnValues = None + self.ReturnValuesList = [] + self.ReturnValuesDictionary = {} + self.DictionaryKeyCounter = 0 + self.ParentWindow = None + self.Rows = [] + self.Scrollable = scrollable + self.VerticalScrollOnly = vertical_scroll_only + self.RightClickMenu = right_click_menu + bg = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR + self.WxBoxSizer = None # type: wx.BoxSizer + self.WxHSizer = None # type: wx.BoxSizer + self._Layout(layout) + self.ElementJustification = element_justification + tsize = size_px if size_px != (None, None) else size + + super().__init__(ELEM_TYPE_COLUMN, background_color=background_color, size_px=tsize, pad=pad, key=key, visible=visible) + return + + def _AddRow(self, *args): + ''' Parms are a variable number of Elements ''' + NumRows = len(self.Rows) # number of existing rows is our row number + CurrentRowNumber = NumRows # this row's number + CurrentRow = [] # start with a blank row and build up + # ------------------------- Add the elements to a row ------------------------- # + for i, element in enumerate(args): # Loop through list of elements and add them to the row + element.Position = (CurrentRowNumber, i) + element.ParentContainer = self + CurrentRow.append(element) + if element.Key is not None: + self.UseDictionary = True + # ------------------------- Append the row to list of Rows ------------------------- # + self.Rows.append(CurrentRow) + + def _Layout(self, rows): + for row in rows: + self._AddRow(*row) + + def _GetElementAtLocation(self, location): + (row_num, col_num) = location + row = self.Rows[row_num] + element = row[col_num] + return element + + + def Update(self, visible=None): + if visible: + self.WxHSizer.Show(self.WxBoxSizer, recursive=True) + self.ParentForm.VisibilityChanged() + elif visible is False: + self.WxHSizer.Hide(self.WxBoxSizer, recursive=True) + self.ParentForm.VisibilityChanged() + + update = Update + + +# ---------------------------------------------------------------------- # +# Menu # +# ---------------------------------------------------------------------- # +class Menu(Element): + def __init__(self, menu_definition, background_color=None, size=(None, None), tearoff=False, pad=None, key=None): + ''' + Menu Element + :param menu_definition: + :param background_color: + :param size: + :param tearoff: + :param pad: + :param key: + ''' + self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR + self.MenuDefinition = menu_definition + self.TKMenu = None + self.Tearoff = tearoff + + super().__init__(ELEM_TYPE_MENUBAR, background_color=background_color, size=size, pad=pad, key=key) + return + + def _MenuItemChosenCallback(self, item_chosen): + # print('IN MENU ITEM CALLBACK', item_chosen) + self.ParentForm.LastButtonClicked = item_chosen + self.ParentForm.FormRemainedOpen = True + if self.ParentForm.CurrentlyRunningMainloop: + self.ParentForm.TKroot.quit() # kick the users out of the mainloop + + + +# ---------------------------------------------------------------------- # +# Table # +# ---------------------------------------------------------------------- # +class Table(Element): + def __init__(self, values, headings=None, visible_column_map=None, col_widths=None, def_col_width=10, + auto_size_columns=True, max_col_width=20, select_mode=None, display_row_numbers=False, num_rows=None, + font=None, justification='right', text_color=None, background_color=None, alternating_row_color=None, + size=(None, None), change_submits=False, bind_return_key=False, pad=None, key=None, tooltip=None): + ''' + Table Element + :param values: + :param headings: + :param visible_column_map: + :param col_widths: + :param def_col_width: + :param auto_size_columns: + :param max_col_width: + :param select_mode: + :param display_row_numbers: + :param font: + :param justification: + :param text_color: + :param background_color: + :param size: + :param pad: + :param key: + :param tooltip: + ''' + self.Values = values + self.ColumnHeadings = headings + self.ColumnsToDisplay = visible_column_map + self.ColumnWidths = col_widths + self.MaxColumnWidth = max_col_width + self.DefaultColumnWidth = def_col_width + self.AutoSizeColumns = auto_size_columns + self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR + self.TextColor = text_color + self.Justification = justification + self.InitialState = None + self.SelectMode = select_mode + self.DisplayRowNumbers = display_row_numbers + self.NumRows = num_rows if num_rows is not None else size[1] + self.TKTreeview = None + self.AlternatingRowColor = alternating_row_color + self.SelectedRows = [] + self.ChangeSubmits = change_submits + self.BindReturnKey = bind_return_key + self.StartingRowNumber = 0 # When displaying row numbers, where to start + self.RowHeaderText = 'Row' + super().__init__(ELEM_TYPE_TABLE, text_color=text_color, background_color=background_color, font=font, + size=size, pad=pad, key=key, tooltip=tooltip) + return + + def Update(self, values=None): + if values is not None: + children = self.TKTreeview.get_children() + for i in children: + self.TKTreeview.detach(i) + self.TKTreeview.delete(i) + children = self.TKTreeview.get_children() + # self.TKTreeview.delete(*self.TKTreeview.get_children()) + for i, value in enumerate(values): + if self.DisplayRowNumbers: + value = [i + self.StartingRowNumber] + value + id = self.TKTreeview.insert('', 'end', text=i, iid=i + 1, values=value, tag=i % 2) + if self.AlternatingRowColor is not None: + self.TKTreeview.tag_configure(1, background=self.AlternatingRowColor) + self.Values = values + self.SelectedRows = [] + + update = Update + + +# ---------------------------------------------------------------------- # +# Tree # +# ---------------------------------------------------------------------- # +class Tree(Element): + def __init__(self, data=None, headings=None, visible_column_map=None, col_widths=None, col0_width=10, + def_col_width=10, auto_size_columns=True, max_col_width=20, select_mode=None, show_expanded=False, + change_submits=False, font=None, justification='right', text_color=None, background_color=None, num_rows=None, pad=None, key=None, + tooltip=None): + ''' + Tree Element + :param headings: + :param visible_column_map: + :param col_widths: + :param def_col_width: + :param auto_size_columns: + :param max_col_width: + :param select_mode: + :param font: + :param justification: + :param text_color: + :param background_color: + :param num_rows: + :param pad: + :param key: + :param tooltip: + ''' + self.TreeData = data + self.ColumnHeadings = headings + self.ColumnsToDisplay = visible_column_map + self.ColumnWidths = col_widths + self.MaxColumnWidth = max_col_width + self.DefaultColumnWidth = def_col_width + self.AutoSizeColumns = auto_size_columns + self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR + self.TextColor = text_color + self.Justification = justification + self.InitialState = None + self.SelectMode = select_mode + self.ShowExpanded = show_expanded + self.NumRows = num_rows + self.Col0Width = col0_width + self.TKTreeview = None + self.SelectedRows = [] + self.ChangeSubmits = change_submits + + super().__init__(ELEM_TYPE_TREE, text_color=text_color, background_color=background_color, font=font, pad=pad, + key=key, tooltip=tooltip) + return + + def add_treeview_data(self, node): + # print(f'Inserting {node.key} under parent {node.parent}') + if node.key != '': + self.TKTreeview.insert(node.parent, 'end', node.key, text=node.text, values=node.values, + open=self.ShowExpanded) + for node in node.children: + self.add_treeview_data(node) + + def Update(self, values=None, key=None, value=None, text=None): + if values is not None: + children = self.TKTreeview.get_children() + for i in children: + self.TKTreeview.detach(i) + self.TKTreeview.delete(i) + children = self.TKTreeview.get_children() + self.TreeData = values + self.add_treeview_data(self.TreeData.root_node) + self.SelectedRows = [] + if key is not None: + item = self.TKTreeview.item(key) + if value is not None: + self.TKTreeview.item(key, values=value) + if text is not None: + self.TKTreeview.item(key, text=text) + item = self.TKTreeview.item(key) + return self + + update = Update + + +class TreeData(object): + class Node(object): + def __init__(self, parent, key, text, values): + self.parent = parent + self.children = [] + self.key = key + self.text = text + self.values = values + + def _Add(self, node): + self.children.append(node) + + def __init__(self): + self.tree_dict = {} + self.root_node = self.Node("", "", 'root', []) + self.tree_dict[""] = self.root_node + + def _AddNode(self, key, node): + self.tree_dict[key] = node + + def Insert(self, parent, key, text, values): + node = self.Node(parent, key, text, values) + self.tree_dict[key] = node + parent_node = self.tree_dict[parent] + parent_node._Add(node) + + def __repr__(self): + return self._NodeStr(self.root_node, 1) + + def _NodeStr(self, node, level): + return '\n'.join( + [str(node.key) + ' : ' + str(node.text)] + + [' ' * 4 * level + self._NodeStr(child, level + 1) for child in node.children]) + + +# ---------------------------------------------------------------------- # +# Error Element # +# ---------------------------------------------------------------------- # +class ErrorElement(Element): + def __init__(self, key=None): + ''' + Error Element + :param key: + ''' + self.Key = key + + super().__init__(ELEM_TYPE_ERROR, key=key) + return + + def Update(self, *args, **kwargs): + PopupError('Keyword error in Update', + 'You need to stop this madness and check your spelling', + 'Bad key = {}'.format(self.Key), + 'Your bad line of code may resemble this:', + 'window.FindElement("{}")'.format(self.Key)) + return self + + def Get(self): + return 'This is NOT a valid Element!\nSTOP trying to do things with it or I will have to crash at some point!' + + update = Update + get = Get + +Stretch = ErrorElement + + +# ------------------------------------------------------------------------- # +# Tray CLASS # +# ------------------------------------------------------------------------- # +class SystemTray: + def __init__(self, menu=None, filename=None, data=None, data_base64=None, tooltip=None): + ''' + SystemTray - create an icon in the system tray + :param menu: Menu definition + :param filename: filename for icon + :param data: in-ram image for icon + :param data_base64: basee-64 data for icon + :param tooltip: tooltip string + ''' + self.Menu = menu + self.TrayIcon = None + self.Shown = False + self.MenuItemChosen = TIMEOUT_KEY + self.LastMessage = None + self.LastTitle = None + self.App = None + self.Filename = filename + self.timer = None + self.DataBase64 = data_base64 + if Window.highest_level_app is None: + self.App = Window.highest_level_app = wx.App(False) + # This could be a very dangerous thing to add! + # It was needed in order for an application to run the Tray in a Thread + self.App.SetAssertMode(wx.APP_ASSERT_SUPPRESS) + else: + self.App = Window.highest_level_app + self.Tooltip = tooltip + + frame = wx.Frame(None, title='Tray icon frame') + if filename: + self.icon = wx.Icon(filename, wx.BITMAP_TYPE_ANY) + elif data_base64: + self.icon = PyEmbeddedImage(data_base64).GetIcon() + else: + self.icon = PyEmbeddedImage(DEFAULT_BASE64_ICON).GetIcon() + self.TaskBarIcon = self.CustomTaskBarIcon(frame, self.App, self.Menu, self.icon, tooltip=tooltip) + + # self.App.MainLoop() + + + class CustomTaskBarIcon(wx.adv.TaskBarIcon): + def __init__(self, frame, app, menu, icon, tooltip=None): + wx.adv.TaskBarIcon.__init__(self) + self.frame = frame + self.app = app + self.menu_item_chosen = None + self.menu = menu + self.id_to_text = {} + self.tooltip = tooltip or wx.EmptyString + + + self.SetIcon(icon, tooltip=self.tooltip) + self.Bind(wx.adv.EVT_TASKBAR_LEFT_DOWN, self.OnTaskBarLeftClick) + self.Bind(wx.adv.EVT_TASKBAR_LEFT_DCLICK, self.OnTaskBarLeftDoubleClick) + self.Bind(wx.adv.EVT_TASKBAR_RIGHT_DOWN, self.OnTaskBarRightClick) + self.Bind(wx.adv.EVT_TASKBAR_BALLOON_CLICK, self.OnTaskBarMessageClick) + self.Bind(wx.EVT_MENU, self.OnMenu) + + def OnTaskBarActivate(self, evt): + pass + + def OnTaskBarClose(self, evt): + self.frame.Close() + + def OnTaskBarLeftClick(self, evt): + # print('Got a LEFT click!') + self.menu_item_chosen = EVENT_SYSTEM_TRAY_ICON_ACTIVATED + self.app.ExitMainLoop() + + def OnTaskBarMessageClick(self, evt): + # print('Got a LEFT click!') + self.menu_item_chosen = EVENT_SYSTEM_TRAY_MESSAGE_CLICKED + self.app.ExitMainLoop() + + def OnTaskBarLeftDoubleClick(self, evt): + # print('Got a double click!') + self.menu_item_chosen = EVENT_SYSTEM_TRAY_ICON_DOUBLE_CLICKED + self.app.ExitMainLoop() + + def CreatePopupMenu(self): + # print(f'Popup menu = {self.menu}') + menu = wx.Menu() + AddMenuItem(menu, self.menu[1], self) + return menu + + def OnTaskBarRightClick(self, evt): + # print('Got a right click!') + self.menu_item_chosen = EVENT_SYSTEM_TRAY_ICON_RIGHT_CLICK + # self.app.ExitMainLoop() + + def OnMenu(self, event): + # print(f'On Menu {event}') + menu = event.EventObject + text='' + item = menu.FindItemById(event.Id) + # for item in menu.MenuItems: + # if item.Id == event.Id: + # print('** FOUND MENU ENTRY! **') + # print(f'item = {item}') + text = self.id_to_text[item] + # text = self.id_to_text[item.Id] + self.menu_item_chosen = text + self.app.ExitMainLoop() + + + + def Read(self, timeout=None): + ''' + Reads the context menu + :param timeout: Optional. Any value other than None indicates a non-blocking read + :return: + ''' + # if not self.Shown: + # self.Shown = True + # self.TrayIcon.show() + timeout1 = timeout + # if timeout1 == 0: + # timeout1 = 1 + # if wx.GetApp(): + # wx.GetApp().ProcessPendingEvents() + # self.App.ProcessPendingEvents() + # self.App.ProcessIdle() + # return self.MenuItemChosen + if timeout1 is not None: + try: + self.timer = wx.Timer(self.TaskBarIcon) + self.TaskBarIcon.Bind(wx.EVT_TIMER, self.timer_timeout) + self.timer.Start(milliseconds=timeout1, oneShot=wx.TIMER_ONE_SHOT) + except: + print('*** Got error in Read ***') + self.RunningMainLoop = True + self.App.MainLoop() + self.RunningMainLoop = False + if self.timer: + self.timer.Stop() + self.TaskBarIcon.Unbind(wx.EVT_TIMER) + del(self.timer) + self.timer = None + self.MenuItemChosen = self.TaskBarIcon.menu_item_chosen + return self.MenuItemChosen + + def timer_timeout(self, event): + self.TaskBarIcon.Unbind(wx.EVT_TIMER) + del (self.timer) + self.timer = None + self.TaskBarIcon.menu_item_chosen = TIMEOUT_KEY + self.App.ExitMainLoop() + + + def Hide(self): + self.TaskBarIcon.RemoveIcon() + + + def UnHide(self): + self.TaskBarIcon.SetIcon(icon=self.TaskBarIcon.icon, tooltip=self.TaskBarIcon.tooltip) + + + def ShowMessage(self, title, message, filename=None, data=None, data_base64=None, messageicon=None, time=10000): + ''' + Shows a balloon above icon in system tray + :param title: Title shown in balloon + :param message: Message to be displayed + :param filename: Optional icon filename + :param data: Optional in-ram icon + :param data_base64: Optional base64 icon + :param time: How long to display message in milliseconds + :return: + ''' + if messageicon is None: + self.TaskBarIcon.ShowBalloon(title, message, msec=time) + else: + self.TaskBarIcon.ShowBalloon(title, message, msec=time, flags=messageicon) + + return self + + def Close(self): + ''' + + :return: + ''' + self.Hide() + # Don't close app because windows could be depending on it + # self.App.quit() + + def _DisableAsserts(self): + wx.DisableAsserts() + + + def Update(self, menu=None, tooltip=None,filename=None, data=None, data_base64=None,): + ''' + Updates the menu, tooltip or icon + :param menu: menu defintion + :param tooltip: string representing tooltip + :param filename: icon filename + :param data: icon raw image + :param data_base64: icon base 64 image + :return: + ''' + # Menu + if menu is not None: + self.TaskBarIcon.menu = menu + if filename: + self.icon = wx.Icon(filename, wx.BITMAP_TYPE_ANY) + elif data_base64: + self.icon = PyEmbeddedImage(data_base64).GetIcon() + elif not self.icon: + self.icon = PyEmbeddedImage(DEFAULT_BASE64_ICON).GetIcon() + if self.icon: + self.Tooltip = tooltip or self.Tooltip or self.TaskBarIcon.tooltip or wx.EmptyString + self.TaskBarIcon.SetIcon(self.icon, tooltip=self.Tooltip) + # Tooltip + # if tooltip is not None: + # self.TrayIcon.setToolTip(str(tooltip)) + # Icon + # qicon = None + # if filename is not None: + # icon = wx.Icon(filename, wx.BITMAP_TYPE_ICO) + # self.TaskBarIcon.SetIcon(icon, tooltip=tooltip) + # elif data is not None: + # ba = QtCore.QByteArray.fromRawData(data) + # pixmap = QtGui.QPixmap() + # pixmap.loadFromData(ba) + # qicon = QIcon(pixmap) + # elif data_base64 is not None: + # ico1 = base64.b64decode(data_base64) + # fout = open("zzztemp_icon.ico", "wb") + # fout.write(ico1) + # fout.close() + # icon = wx.Icon('zzztemp_icon.ico', wx.BITMAP_TYPE_ICO) + # self.TrayIcon.SetIcon(icon, tooltip=tooltip) + # os.remove("zzztemp_icon.ico") + # if qicon is not None: + # self.TrayIcon.setIcon(qicon) + + close = Close + hide = Hide + read = Read + show_message = ShowMessage + un_hide = UnHide + update = Update + + +class DragFrame(wx.Frame): + def __init__(self, title=''): + wx.Frame.__init__(self, None, title=title) + + def on_mouse(self, event): + ''' + implement dragging + ''' + # print('on_mouse') + if not event.Dragging(): + self._dragPos = None + return + # self.CaptureMouse() + if not self._dragPos: + self._dragPos = event.GetPosition() + else: + pos = event.GetPosition() + displacement = self._dragPos - pos + self.SetPosition( self.GetPosition() - displacement ) + + +# ------------------------------------------------------------------------- # +# Window CLASS # +# ------------------------------------------------------------------------- # +class Window: + + NumOpenWindows = 0 + user_defined_icon = None + hidden_master_root = None + QTApplication = None + active_popups = {} + highest_level_app = None + stdout_is_rerouted = False + stdout_location = None + + def __init__(self, title, layout=None, default_element_size=DEFAULT_ELEMENT_SIZE, default_button_element_size=(None, None), + auto_size_text=None, auto_size_buttons=None, location=(None, None), size=(None, None), element_padding=None, button_color=None, font=None, + progress_bar_color=(None, None), background_color=None, border_depth=None, auto_close=False, + auto_close_duration=None, icon=DEFAULT_BASE64_ICON, force_toplevel=False, element_justification='left', + alpha_channel=1, return_keyboard_events=False, use_default_focus=True, text_justification=None, + no_titlebar=False, grab_anywhere=False, keep_on_top=False, resizable=True, disable_close=False, disable_minimize=False, background_image=None, finalize=False): + ''' + + :param title: + :param default_element_size: + :param default_button_element_size: + :param auto_size_text: + :param auto_size_buttons: + :param location: + :param size: + :param element_padding: + :param button_color: + :param font: + :param progress_bar_color: + :param background_color: + :param border_depth: + :param auto_close: + :param auto_close_duration: + :param icon: + :param force_toplevel: + :param alpha_channel: + :param return_keyboard_events: + :param use_default_focus: + :param text_justification: + :param no_titlebar: + :param grab_anywhere: + :param keep_on_top: + :param resizable: + :param disable_close: + :param background_image: + ''' + self.AutoSizeText = auto_size_text if auto_size_text is not None else DEFAULT_AUTOSIZE_TEXT + self.AutoSizeButtons = auto_size_buttons if auto_size_buttons is not None else DEFAULT_AUTOSIZE_BUTTONS + self.Title = title + self.Rows = [] # a list of ELEMENTS for this row + self.DefaultElementSize = _convert_tkinter_size_to_Wx(default_element_size) + self.DefaultButtonElementSize = _convert_tkinter_size_to_Wx(default_button_element_size) if default_button_element_size != ( + None, None) else _convert_tkinter_size_to_Wx(DEFAULT_BUTTON_ELEMENT_SIZE) + self.Location = location + self.ButtonColor = button_color if button_color else DEFAULT_BUTTON_COLOR + self.BackgroundColor = background_color if background_color else DEFAULT_BACKGROUND_COLOR + self.ParentWindow = None + self.Font = font if font else DEFAULT_FONT + self.RadioDict = {} + self.BorderDepth = border_depth + self.WindowIcon = Window.user_defined_icon if Window.user_defined_icon is not None else icon if icon is not None else DEFAULT_WINDOW_ICON + self.AutoClose = auto_close + self.NonBlocking = False + self.TKroot = None + self.TKrootDestroyed = False + self.CurrentlyRunningMainloop = False + self.FormRemainedOpen = False + self.TKAfterID = None + self.ProgressBarColor = progress_bar_color + self.AutoCloseDuration = auto_close_duration + self.RootNeedsDestroying = False + self.Shown = False + self.ReturnValues = None + self.ReturnValuesList = [] + self.ReturnValuesDictionary = {} + self.DictionaryKeyCounter = 0 + self.LastButtonClicked = None + self.LastButtonClickedWasRealtime = False + self.UseDictionary = False + self.UseDefaultFocus = use_default_focus + self.ReturnKeyboardEvents = return_keyboard_events + self.LastKeyboardEvent = None + self.TextJustification = text_justification + self.NoTitleBar = no_titlebar + self.GrabAnywhere = grab_anywhere + self.KeepOnTop = keep_on_top + self.ForcefTopLevel = force_toplevel + self.Resizable = resizable + self._AlphaChannel = alpha_channel + self.Timeout = None + self.TimeoutKey = TIMEOUT_KEY + self.TimerCancelled = False + self.DisableClose = disable_close + self._Hidden = False + # self.QTApplication = None + # self.QT_QMainWindow = None + self._Size=size + self.ElementPadding = element_padding or DEFAULT_ELEMENT_PADDING + self.FocusElement = None + self.ElementJustification = element_justification + self.BackgroundImage = background_image + self.XFound = False + self.DisableMinimize = disable_minimize + self.App = None # type: wx.App + self.MasterFrame = None # type: wx.Frame + self.MasterPanel = None # type: wx.Panel + self.IgnoreClose = False + self.UniqueKeyCounter = 0 + self.AllKeysDict = {} # dictionary containing all the keys and elements in this window + + if layout is not None: + self.Layout(layout) + if finalize: + self.Finalize() + + @classmethod + def IncrementOpenCount(self): + self.NumOpenWindows += 1 + # print('+++++ INCREMENTING Num Open Windows = {} ---'.format(Window.NumOpenWindows)) + + @classmethod + def DecrementOpenCount(self): + self.NumOpenWindows -= 1 * (self.NumOpenWindows != 0) # decrement if not 0 + # print('----- DECREMENTING Num Open Windows = {} ---'.format(Window.NumOpenWindows)) + + + # ------------------------- Add ONE Row to Form ------------------------- # + def AddRow(self, *args): + ''' Parms are a variable number of Elements ''' + NumRows = len(self.Rows) # number of existing rows is our row number + CurrentRowNumber = NumRows # this row's number + CurrentRow = [] # start with a blank row and build up + # ------------------------- Add the elements to a row ------------------------- # + for i, element in enumerate(args): # Loop through list of elements and add them to the row + element.Position = (CurrentRowNumber, i) + element.ParentContainer = self + CurrentRow.append(element) + # ------------------------- Append the row to list of Rows ------------------------- # + self.Rows.append(CurrentRow) + + # ------------------------- Add Multiple Rows to Form ------------------------- # + def AddRows(self, rows): + for row in rows: + self.AddRow(*row) + + def Layout(self, rows): + self.AddRows(rows) + self.BuildKeyDict() + return self + + def LayoutAndRead(self, rows, non_blocking=False): + raise DeprecationWarning('LayoutAndRead is no longer supported... change your call to window.Layout(layout).Read()') + # self.AddRows(rows) + # self.Show(non_blocking=non_blocking) + # return self.ReturnValues + + def LayoutAndShow(self, rows): + raise DeprecationWarning('LayoutAndShow is no longer supported... change your call to LayoutAndRead') + + # ------------------------- ShowForm THIS IS IT! ------------------------- # + def Show(self, non_blocking=False): + self.Shown = True + # Compute num rows & num cols (it'll come in handy debugging) + self.NumRows = len(self.Rows) + self.NumCols = max(len(row) for row in self.Rows) + self.NonBlocking = non_blocking + + # Search through entire form to see if any elements set the focus + # if not, then will set the focus to the first input element + found_focus = False + for row in self.Rows: + for element in row: + try: + if element.Focus: + found_focus = True + except: + pass + try: + if element.Key is not None: + self.UseDictionary = True + except: + pass + + if not found_focus and self.UseDefaultFocus: + self.UseDefaultFocus = True + else: + self.UseDefaultFocus = False + # -=-=-=-=-=-=-=-=- RUN the GUI -=-=-=-=-=-=-=-=- ## + StartupTK(self) + # If a button or keyboard event happened but no results have been built, build the results + if self.LastKeyboardEvent is not None or self.LastButtonClicked is not None: + return BuildResults(self, False, self) + + return self.ReturnValues + + # ------------------------- SetIcon - set the window's fav icon ------------------------- # + def SetIcon(self, icon=None, pngbase64=None): + pass + + def _GetElementAtLocation(self, location): + (row_num, col_num) = location + row = self.Rows[row_num] + element = row[col_num] + return element + + def _GetDefaultElementSize(self): + return self.DefaultElementSize + + def _AutoCloseAlarmCallback(self): + try: + window = self + if window: + if window.NonBlocking: + self.CloseNonBlockingForm() + else: + window._Close() + if self.CurrentlyRunningMainloop: + self.QTApplication.exit() # kick the users out of the mainloop + self.RootNeedsDestroying = True + self.QT_QMainWindow.close() + + except: + pass + + def timer_timeout(self, event): + # first, get the results table built + # modify the Results table in the parent FlexForm object + # print('timer timeout') + if self.TimerCancelled: + return + self.LastButtonClicked = self.TimeoutKey + self.FormRemainedOpen = True + if self.CurrentlyRunningMainloop: + self.App.ExitMainLoop() + + + def non_block_timer_timeout(self, event): + # print('non-blocking timer timeout') + self.App.ExitMainLoop() + + + def autoclose_timer_callback(self, frame): + # print('*** AUTOCLOSE TIMEOUT CALLBACK ***', frame) + try: + frame.Close() + except: + pass # if user has already closed the frame will get an error + # TODO Sept - does this need adding back? + # if self.CurrentlyRunningMainloop: + # self.App.ExitMainLoop() + + def callback_keyboard_char(self, event): + event = event # type:wx.KeyEvent + self.LastButtonClicked = None + self.FormRemainedOpen = True + if event.ClassName == 'wxMouseEvent': + if event.WheelRotation < 0: + self.LastKeyboardEvent = 'MouseWheel:Down' + else: + self.LastKeyboardEvent = 'MouseWheel:Up' + else: + self.LastKeyboardEvent = event.GetKeyCode() + if not self.NonBlocking: + BuildResults(self, False, self) + if self.CurrentlyRunningMainloop: # quit if this is the current mainloop, otherwise don't quit! + self.App.ExitMainLoop() # kick the users out of the mainloop + if event.ClassName != 'wxMouseEvent': + event.DoAllowNextEvent() + + + + def Read(self, timeout=None, timeout_key=TIMEOUT_KEY, close=False): + """ + THE biggest deal method in the Window class! This is how you get all of your data from your Window. + Pass in a timeout (in milliseconds) to wait for a maximum of timeout milliseconds. Will return timeout_key + if no other GUI events happen first. + Use the close parameter to close the window after reading + + :param timeout: (int) Milliseconds to wait until the Read will return IF no other GUI events happen first + :param timeout_key: (Any) The value that will be returned from the call if the timer expired + :param close: (bool) if True the window will be closed prior to returning + :return: Tuple[(Any), Union[Dict[Any:Any]], List[Any], None] (event, values) + """ + results = self._read(timeout=timeout, timeout_key=timeout_key) + if close: + self.close() + + return results + + + + + def _read(self, timeout=None, timeout_key=TIMEOUT_KEY): + if timeout == 0: # timeout of zero runs the old readnonblocking + event, values = self._ReadNonBlocking() + if event is None: + event = timeout_key + if values is None: + event = None + return event, values # make event None if values was None and return + # Read with a timeout + self.Timeout = timeout + self.TimeoutKey = timeout_key + self.NonBlocking = False + if not self.Shown: + self.Show() + else: + # if already have a button waiting, the return previously built results + if self.LastButtonClicked is not None and not self.LastButtonClickedWasRealtime: + # print(f'*** Found previous clicked saved {self.LastButtonClicked}') + results = BuildResults(self, False, self) + self.LastButtonClicked = None + return results + InitializeResults(self) + # if the last button clicked was realtime, emulate a read non-blocking + # the idea is to quickly return realtime buttons without any blocks until released + if self.LastButtonClickedWasRealtime: + # print(f'RTime down {self.LastButtonClicked}' ) + try: + rc = self.TKroot.update() + except: + self.TKrootDestroyed = True + Window.DecrementOpenCount() + results = BuildResults(self, False, self) + if results[0] != None and results[0] != timeout_key: + return results + else: + pass + + # else: + # print("** REALTIME PROBLEM FOUND **", results) + + # normal read blocking code.... + if timeout != None: + self.TimerCancelled = False + timer = wx.Timer(self.App) + self.App.Bind(wx.EVT_TIMER, self.timer_timeout) + timer.Start(milliseconds=timeout, oneShot=wx.TIMER_ONE_SHOT) + else: + timer = None + self.CurrentlyRunningMainloop = True + # print(f'In main {self.Title}') + ################################# CALL GUWxTextCtrlI MAINLOOP ############################ + self.App.MainLoop() + self.CurrentlyRunningMainloop = False + self.TimerCancelled = True + if timer: + timer.Stop() + if Window.stdout_is_rerouted: + sys.stdout = Window.stdout_location + if self.RootNeedsDestroying: + # self.LastButtonClicked = None + # self.App.Close() + try: + self.MasterFrame.Close() + except: pass + Window.DecrementOpenCount() + # if form was closed with X + if self.LastButtonClicked is None and self.LastKeyboardEvent is None and self.ReturnValues[0] is None: + Window.DecrementOpenCount() + # Determine return values + if self.LastKeyboardEvent is not None or self.LastButtonClicked is not None: + results = BuildResults(self, False, self) + if not self.LastButtonClickedWasRealtime: + self.LastButtonClicked = None + return results + else: + if not self.XFound and self.Timeout != 0 and self.Timeout is not None and self.ReturnValues[0] is None: # Special Qt case because returning for no reason so fake timeout + self.ReturnValues = self.TimeoutKey, self.ReturnValues[1] # fake a timeout + elif not self.XFound and self.ReturnValues[0] is None: # TODO HIGHLY EXPERIMENTAL... added due to tray icon interaction + # print("*** Faking timeout ***") + self.ReturnValues = self.TimeoutKey, self.ReturnValues[1] # fake a timeout + return self.ReturnValues + + def _ReadNonBlocking(self): + if self.TKrootDestroyed: + return None, None + if not self.Shown: + self.Show(non_blocking=True) + else: + # event = wx.Event() + # self.App.QueueEvent(event) + timer = wx.Timer(self.App) + self.App.Bind(wx.EVT_TIMER, self.timer_timeout) + timer.Start(milliseconds=0, oneShot=wx.TIMER_ONE_SHOT) + self.CurrentlyRunningMainloop = True + # print(f'In main {self.Title}') + ################################# CALL GUWxTextCtrlI MAINLOOP ############################ + + self.App.MainLoop() + if Window.stdout_is_rerouted: + sys.stdout = Window.stdout_location + # self.LastButtonClicked = 'TEST' + self.CurrentlyRunningMainloop = False + timer.Stop() + # while self.App.HasPendingEvents(): + # self.App.ProcessPendingEvents() + return BuildResults(self, False, self) + + + def Finalize(self): + if self.TKrootDestroyed: + return self + if not self.Shown: + self.Show(non_blocking=True) + # else: + # try: + # self.QTApplication.processEvents() # refresh the window + # except: + # print('* ERROR FINALIZING *') + # self.TKrootDestroyed = True + # Window.DecrementOpenCount() + return self + + + def Refresh(self): + # self.QTApplication.processEvents() # refresh the window + return self + + def VisibilityChanged(self): + self.SizeChanged() + return self + + def Fill(self, values_dict): + FillFormWithValues(self, values_dict) + return self + + def FindElement(self, key, silent_on_error=False): + try: + element = self.AllKeysDict[key] + except KeyError: + element = None + # element = _FindElementFromKeyInSubForm(self, key) + if element is None: + if not silent_on_error: + print('*** WARNING = FindElement did not find the key. Please check your key\'s spelling ***') + PopupError('Keyword error in FindElement Call', + 'Bad key = {}'.format(key), + 'Your bad line of code may resemble this:', + 'window.FindElement("{}")'.format(key)) + return ErrorElement(key=key) + else: + return False + return element + + Element = FindElement # shortcut function definition + + + def BuildKeyDict(self): + dict = {} + self.AllKeysDict = self._BuildKeyDictForWindow(self,self, dict) + # print(f'keys built = {self.AllKeysDict}') + + def _BuildKeyDictForWindow(self, top_window, window, key_dict): + for row_num, row in enumerate(window.Rows): + for col_num, element in enumerate(row): + if element.Type == ELEM_TYPE_COLUMN: + key_dict = self._BuildKeyDictForWindow(top_window, element, key_dict) + if element.Type == ELEM_TYPE_FRAME: + key_dict = self._BuildKeyDictForWindow(top_window, element, key_dict) + if element.Type == ELEM_TYPE_TAB_GROUP: + key_dict = self._BuildKeyDictForWindow(top_window, element, key_dict) + if element.Type == ELEM_TYPE_TAB: + key_dict = self._BuildKeyDictForWindow(top_window, element, key_dict) + if element.Key is None: # if no key has been assigned.... create one for input elements + if element.Type == ELEM_TYPE_BUTTON: + element.Key = element.ButtonText + if element.Type in (ELEM_TYPE_MENUBAR, ELEM_TYPE_BUTTONMENU, ELEM_TYPE_CANVAS, + ELEM_TYPE_INPUT_SLIDER, ELEM_TYPE_GRAPH, ELEM_TYPE_IMAGE, + ELEM_TYPE_INPUT_CHECKBOX, ELEM_TYPE_INPUT_LISTBOX, ELEM_TYPE_INPUT_COMBO, + ELEM_TYPE_INPUT_MULTILINE, ELEM_TYPE_INPUT_OPTION_MENU, ELEM_TYPE_INPUT_SPIN, + ELEM_TYPE_TABLE, ELEM_TYPE_TREE, + ELEM_TYPE_INPUT_TEXT): + element.Key = top_window.DictionaryKeyCounter + top_window.DictionaryKeyCounter += 1 + if element.Key is not None: + if element.Key in key_dict.keys(): + print('*** Duplicate key found in your layout {} ***'.format(element.Key)) if element.Type != ELEM_TYPE_BUTTON else None + element.Key = element.Key + str(self.UniqueKeyCounter) + self.UniqueKeyCounter += 1 + print('*** Replaced new key with {} ***'.format(element.Key)) if element.Type != ELEM_TYPE_BUTTON else None + key_dict[element.Key] = element + return key_dict + + def FindElementWithFocus(self): + return self.FocusElement + # element = _FindElementWithFocusInSubForm(self) + # return element + + def SaveToDisk(self, filename): + try: + results = BuildResults(self, False, self) + with open(filename, 'wb') as sf: + pickle.dump(results[1], sf) + except: + print('*** Error saving form to disk ***') + + def LoadFromDisk(self, filename): + try: + with open(filename, 'rb') as df: + self.Fill(pickle.load(df)) + except: + print('*** Error loading form to disk ***') + + def GetScreenDimensions(self): + size = wx.GetDisplaySize() + return size + + def Move(self, x, y): + self.MasterFrame.SetPosition((x,y)) + + def Minimize(self): + self.MasterFrame.Iconize() + + + def Maximize(self): + self.MasterFrame.Maximize() + + + def _Close(self): + try: + self.TKroot.update() + except: + pass + if not self.NonBlocking: + BuildResults(self, False, self) + if self.TKrootDestroyed: + return None + self.TKrootDestroyed = True + self.RootNeedsDestroying = True + # self.__del__() + return None + + def Close(self): + if self.TKrootDestroyed: + return + try: + self.MasterFrame.Close() + except: + print('error closing window') + + CloseNonBlockingForm = Close + CloseNonBlocking = Close + + def Disable(self): + self.MasterFrame.Enable(False) + + def Enable(self): + self.MasterFrame.Enable(True) + + def Hide(self): + self._Hidden = True + self.MasterFrame.Hide() + return + + def UnHide(self): + if self._Hidden: + self.MasterFrame.Show() + self._Hidden = False + + def Disappear(self): + self.MasterFrame.SetTransparent(0) + + def Reappear(self): + self.MasterFrame.SetTransparent(255) + + def SetAlpha(self, alpha): + ''' + Change the window's transparency + :param alpha: From 0 to 1 with 0 being completely transparent + :return: + ''' + self._AlphaChannel = alpha * 255 + if self._AlphaChannel is not None: + self.MasterFrame.SetTransparent(self._AlphaChannel) + + @property + def AlphaChannel(self): + return self._AlphaChannel + + @AlphaChannel.setter + def AlphaChannel(self, alpha): + self.SetAlpha(alpha) + + def BringToFront(self): + self.MasterFrame.ToggleWindowStyle(wx.STAY_ON_TOP) + + + def CurrentLocation(self): + location = self.MasterFrame.GetPosition() + return location + + def OnClose(self, event): + # print(f'CLOSE EVENT! event = {event}') + if self.DisableClose: + return + # print('GOT A CLOSE EVENT!', event, self.Window.Title) + if not self.IgnoreClose: + self.LastButtonClicked = None + self.XFound = True + if not self.CurrentlyRunningMainloop: # quit if this is the current mainloop, otherwise don't quit! + self.RootNeedsDestroying = True + else: + self.RootNeedsDestroying = True + self.App.ExitMainLoop() # kick the users out of the mainloop + # print('exiting mainloop') + + self.MasterFrame.Destroy() + # TODO - Sept - This is all new from prior release... comment out? + """ + timer = wx.Timer(self.App) + self.App.Bind(wx.EVT_TIMER, self.timer_timeout) + timer.Start(milliseconds=100, oneShot=wx.TIMER_ONE_SHOT) + # self.CurrentlyRunningMainloop = True + # print(f'In main {self.Title}') + ################################# CALL GUWxTextCtrlI MAINLOOP ############################ + + self.App.MainLoop() + # self.CurrentlyRunningMainloop = False + timer.Stop() + print('after mainloop in close') + # TODO end + """ + + self.TKrootDestroyed = True + self.RootNeedsDestroying = True + + + @property + def Size(self): + size = self.MasterFrame.GetSize() + return size + + @Size.setter + def Size(self, size): + self.MasterFrame.SetSize(size[0], size[1]) + + def SizeChanged(self): + size = self.Size + self.Size = size[0] + 1, size[1] + 1 + self.Size = size + self.MasterFrame.SetSizer(self.OuterSizer) + self.OuterSizer.Fit(self.MasterFrame) + + def __getitem__(self, key): + """ + Returns Element that matches the passed in key. + This is "called" by writing code as thus: + window['element key'].Update + + :param key: (Any) The key to find + :return: Union[Element, None] The element found or None if no element was found + """ + try: + return self.Element(key) + except Exception as e: + print('The key you passed in is no good. Key = {}*'.format(key)) + return None + + + def __call__(self, *args, **kwargs): + """ + Call window.Read but without having to type it out. + window() == window.Read() + window(timeout=50) == window.Read(timeout=50) + + :param args: + :param kwargs: + :return: Tuple[Any, Dict[Any:Any]] The famous event, values that Read returns. + """ + return self.Read(*args, **kwargs) + + add_row = AddRow + add_rows = AddRows + alpha_channel = AlphaChannel + bring_to_front = BringToFront + close = Close + current_location = CurrentLocation + disable = Disable + disappear = Disappear + element = Element + enable = Enable + fill = Fill + finalize = Finalize + find_element = FindElement + find_element_with_focus = FindElementWithFocus + get_screen_dimensions = GetScreenDimensions + hide = Hide + layout = Layout + load_from_disk = LoadFromDisk + maximize = Maximize + minimize = Minimize + move = Move + read = Read + reappear = Reappear + refresh = Refresh + save_to_disk = SaveToDisk + set_alpha = SetAlpha + set_icon = SetIcon + size = Size + size_changed = SizeChanged + un_hide = UnHide + visibility_changed = VisibilityChanged + +FlexForm = Window + +# =========================================================================== # +# Stops the mainloop and sets the event information # +# =========================================================================== # + +def element_callback_quit_mainloop(element): + if element.Key is not None: + element.ParentForm.LastButtonClicked = element.Key + else: + element.ParentForm.LastButtonClicked = '' + element.ParentForm.FormRemainedOpen = True + if element.ParentForm.CurrentlyRunningMainloop: + element.ParentForm.App.ExitMainLoop() # kick the users out of the mainloop + + +def quit_mainloop(window): + window.App.ExitMainLoop() + + +# =========================================================================== # +# Convert from characters to pixels # +# =========================================================================== # +# def convert_tkinter_size_to_Wx(size): +# """ +# Converts size in characters to size in pixels +# :param size: size in characters, rows +# :return: size in pixels, pixels +# """ +# qtsize = size +# if size[1] is not None and size[1] < DEFAULT_PIXEL_TO_CHARS_CUTOFF: # change from character based size to pixels (roughly) +# qtsize = size[0]*DEFAULT_PIXELS_TO_CHARS_SCALING[0], size[1]*DEFAULT_PIXELS_TO_CHARS_SCALING[1] +# return qtsize + + +# =========================================================================== # +# Convert from characters to pixels # +# =========================================================================== # +def _convert_tkinter_size_to_Wx(size, scaling=DEFAULT_PIXELS_TO_CHARS_SCALING, height_cutoff=DEFAULT_PIXEL_TO_CHARS_CUTOFF): + """ + Converts size in characters to size in pixels + :param size: size in characters, rows + :return: size in pixels, pixels + """ + qtsize = size + if size[1] is not None and size[1] < height_cutoff: # change from character based size to pixels (roughly) + qtsize = size[0]*scaling[0], size[1]*scaling[1] + return qtsize + + + +def font_to_wx_font(font): + """ + Convert from font string/tyuple into a Qt style sheet string + :param font: "Arial 10 Bold" or ('Arial', 10, 'Bold) + :return: style string that can be combined with other style strings + """ + + if font is None: + return '' + + if type(font) is str: + _font = font.split(' ') + else: + _font = font + name = _font[0] + family = _font[0] + point_size = int(_font[1]) + + # style = _font[2] + + underline = 'underline' in _font[2:] + bold = 'bold' in _font + + wxfont = wx.Font(point_size, + wx.FONTFAMILY_DEFAULT, + wx.FONTSTYLE_NORMAL, + wx.FONTWEIGHT_BOLD if bold else wx.FONTWEIGHT_NORMAL, + underline, + faceName=family) + + return wxfont + + + +def preprocess_radio_elements(top_window, window): + for row in window.Rows: + for element in row: + if element.Type == ELEM_TYPE_INPUT_RADIO: + if element.WxRadioButton is None: + element.WxRadioButton = wx.RadioButton(top_window.MasterPanel, id=wx.ID_ANY, label=element.Text, style=wx.RB_GROUP) + create_wx_radio_buttons(top_window, top_window, element.GroupID) + if element.Type in (ELEM_TYPE_COLUMN, ELEM_TYPE_FRAME,ELEM_TYPE_TAB_GROUP, ELEM_TYPE_TAB) : + preprocess_radio_elements(top_window, element) + + +def create_wx_radio_buttons(top_window, window, group_id): + for row in window.Rows: + for element in row: + if element.Type == ELEM_TYPE_INPUT_RADIO: + if element.GroupID == group_id and element.WxRadioButton is None: + element.WxRadioButton = wx.RadioButton(top_window.MasterPanel, id=wx.ID_ANY, label=element.Text ) + if element.Type in (ELEM_TYPE_COLUMN, ELEM_TYPE_FRAME,ELEM_TYPE_TAB_GROUP, ELEM_TYPE_TAB) : + create_wx_radio_buttons(top_window, element, group_id) + + +# ################################################################################ +# ################################################################################ +# END OF ELEMENT DEFINITIONS +# ################################################################################ +# ################################################################################ + + +# =========================================================================== # +# Button Lazy Functions so the caller doesn't have to define a bunch of stuff # +# =========================================================================== # + + +# ------------------------- FOLDER BROWSE Element lazy function ------------------------- # +def FolderBrowse(button_text='Browse', target=(ThisRow, -1), initial_folder=None, tooltip=None, size=(None, None), + auto_size_button=None, button_color=None, disabled=False, change_submits=False, font=None, pad=None, + key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_BROWSE_FOLDER, target=target, + initial_folder=initial_folder, tooltip=tooltip, size=size, auto_size_button=auto_size_button, + disabled=disabled, button_color=button_color, change_submits=change_submits, font=font, pad=pad, + key=key) + + +# ------------------------- FILE BROWSE Element lazy function ------------------------- # +def FileBrowse(button_text='Browse', target=(ThisRow, -1), file_types=(("ALL Files", "*.*"),), initial_folder=None, + tooltip=None, size=(None, None), auto_size_button=None, button_color=None, change_submits=False, + font=None, disabled=False, + pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_BROWSE_FILE, target=target, file_types=file_types, + initial_folder=initial_folder, tooltip=tooltip, size=size, auto_size_button=auto_size_button, + change_submits=change_submits, disabled=disabled, button_color=button_color, font=font, pad=pad, + key=key) + + +# ------------------------- FILES BROWSE Element (Multiple file selection) lazy function ------------------------- # +def FilesBrowse(button_text='Browse', target=(ThisRow, -1), file_types=(("ALL Files", "*.*"),), disabled=False, + initial_folder=None, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, + change_submits=False, + font=None, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_BROWSE_FILES, target=target, file_types=file_types, + initial_folder=initial_folder, change_submits=change_submits, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, + disabled=disabled, button_color=button_color, font=font, pad=pad, key=key) + + +# ------------------------- FILE BROWSE Element lazy function ------------------------- # +def FileSaveAs(button_text='Save As...', target=(ThisRow, -1), file_types=(("ALL Files", "*.*"),), initial_folder=None, + disabled=False, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, + change_submits=False, font=None, + pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_SAVEAS_FILE, target=target, file_types=file_types, + initial_folder=initial_folder, tooltip=tooltip, size=size, disabled=disabled, + auto_size_button=auto_size_button, button_color=button_color, change_submits=change_submits, + font=font, pad=pad, key=key) + + +# ------------------------- SAVE AS Element lazy function ------------------------- # +def SaveAs(button_text='Save As...', target=(ThisRow, -1), file_types=(("ALL Files", "*.*"),), initial_folder=None, + disabled=False, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, + change_submits=False, font=None, + pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_SAVEAS_FILE, target=target, file_types=file_types, + initial_folder=initial_folder, tooltip=tooltip, size=size, disabled=disabled, + auto_size_button=auto_size_button, button_color=button_color, change_submits=change_submits, + font=font, pad=pad, key=key) + + +# ------------------------- SAVE BUTTON lazy function ------------------------- # +def Save(button_text='Save', size=(None, None), auto_size_button=None, button_color=None, bind_return_key=True, + disabled=False, tooltip=None, font=None, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + +# ------------------------- SUBMIT BUTTON lazy function ------------------------- # +def Submit(button_text='Submit', size=(None, None), auto_size_button=None, button_color=None, disabled=False, + bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + +# ------------------------- OPEN BUTTON lazy function ------------------------- # +def Open(button_text='Open', size=(None, None), auto_size_button=None, button_color=None, disabled=False, + bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + +# ------------------------- OK BUTTON lazy function ------------------------- # +def OK(button_text='OK', size=(None, None), auto_size_button=None, button_color=None, disabled=False, + bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + +# ------------------------- YES BUTTON lazy function ------------------------- # +def Ok(button_text='Ok', size=(None, None), auto_size_button=None, button_color=None, disabled=False, + bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + +# ------------------------- CANCEL BUTTON lazy function ------------------------- # +def Cancel(button_text='Cancel', size=(None, None), auto_size_button=None, button_color=None, disabled=False, + tooltip=None, font=None, bind_return_key=False, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + +# ------------------------- QUIT BUTTON lazy function ------------------------- # +def Quit(button_text='Quit', size=(None, None), auto_size_button=None, button_color=None, disabled=False, tooltip=None, + font=None, bind_return_key=False, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + +# ------------------------- Exit BUTTON lazy function ------------------------- # +def Exit(button_text='Exit', size=(None, None), auto_size_button=None, button_color=None, disabled=False, tooltip=None, + font=None, bind_return_key=False, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + +# ------------------------- YES BUTTON lazy function ------------------------- # +def Yes(button_text='Yes', size=(None, None), auto_size_button=None, button_color=None, disabled=False, tooltip=None, + font=None, bind_return_key=True, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + +# ------------------------- NO BUTTON lazy function ------------------------- # +def No(button_text='No', size=(None, None), auto_size_button=None, button_color=None, disabled=False, tooltip=None, + font=None, bind_return_key=False, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + +# ------------------------- NO BUTTON lazy function ------------------------- # +def Help(button_text='Help', size=(None, None), auto_size_button=None, button_color=None, disabled=False, font=None, + tooltip=None, bind_return_key=False, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + +# ------------------------- GENERIC BUTTON lazy function ------------------------- # +def SimpleButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, + border_width=None, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, + font=None, bind_return_key=False, disabled=False, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_CLOSES_WIN, image_filename=image_filename, + image_data=image_data, image_size=image_size, image_subsample=image_subsample, + border_width=border_width, tooltip=tooltip, disabled=disabled, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + +# ------------------------- CLOSE BUTTON lazy function ------------------------- # +def CloseButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, + border_width=None, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, font=None, + bind_return_key=False, disabled=False, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_CLOSES_WIN, image_filename=image_filename, + image_data=image_data, image_size=image_size, image_subsample=image_subsample, + border_width=border_width, tooltip=tooltip, disabled=disabled, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + +CButton = CloseButton + + +# ------------------------- GENERIC BUTTON lazy function ------------------------- # +def ReadButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, + border_width=None, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, font=None, + bind_return_key=False, disabled=False, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, image_filename=image_filename, + image_data=image_data, image_size=image_size, image_subsample=image_subsample, + border_width=border_width, tooltip=tooltip, size=size, disabled=disabled, + auto_size_button=auto_size_button, button_color=button_color, font=font, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + +ReadFormButton = ReadButton +RButton = ReadFormButton + + +# ------------------------- Realtime BUTTON lazy function ------------------------- # +def RealtimeButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, + border_width=None, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, + font=None, disabled=False, bind_return_key=False, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_REALTIME, image_filename=image_filename, + image_data=image_data, image_size=image_size, image_subsample=image_subsample, + border_width=border_width, tooltip=tooltip, disabled=disabled, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + +# ------------------------- Dummy BUTTON lazy function ------------------------- # +def DummyButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, + border_width=None, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, font=None, + disabled=False, bind_return_key=False, focus=False, pad=None, key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_CLOSES_WIN_ONLY, image_filename=image_filename, + image_data=image_data, image_size=image_size, image_subsample=image_subsample, + border_width=border_width, tooltip=tooltip, size=size, auto_size_button=auto_size_button, + button_color=button_color, font=font, disabled=disabled, bind_return_key=bind_return_key, focus=focus, + pad=pad, key=key) + + +# ------------------------- Calendar Chooser Button lazy function ------------------------- # +def CalendarButton(button_text, target=(None, None), close_when_date_chosen=True, default_date_m_d_y=(None, 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, + button_color=None, disabled=False, font=None, bind_return_key=False, focus=False, pad=None, + key=None): + button = Button(button_text=button_text, button_type=BUTTON_TYPE_CALENDAR_CHOOSER, target=target, + image_filename=image_filename, image_data=image_data, image_size=image_size, + image_subsample=image_subsample, border_width=border_width, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + button.CalendarCloseWhenChosen = close_when_date_chosen + button.DefaultDate_M_D_Y = default_date_m_d_y + return button + + +# ------------------------- Calendar Chooser Button lazy function ------------------------- # +def ColorChooserButton(button_text, target=(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, + button_color=None, disabled=False, font=None, bind_return_key=False, focus=False, pad=None, + key=None): + return Button(button_text=button_text, button_type=BUTTON_TYPE_COLOR_CHOOSER, target=target, + image_filename=image_filename, image_data=image_data, image_size=image_size, + image_subsample=image_subsample, border_width=border_width, tooltip=tooltip, size=size, + auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + + +##################################### ----- RESULTS ------ ################################################## + +def AddToReturnDictionary(form, element, value): + form.ReturnValuesDictionary[element.Key] = value + return + if element.Key is None: + form.ReturnValuesDictionary[form.DictionaryKeyCounter] = value + element.Key = form.DictionaryKeyCounter + form.DictionaryKeyCounter += 1 + else: + form.ReturnValuesDictionary[element.Key] = value + + +def AddToReturnList(form, value): + form.ReturnValuesList.append(value) + + +# ----------------------------------------------------------------------------# +# ------- FUNCTION InitializeResults. Sets up form results matrix --------# +def InitializeResults(form): + BuildResults(form, True, form) + return + + +# ===== Radio Button RadVar encoding and decoding =====# +# ===== The value is simply the row * 1000 + col =====# +def DecodeRadioRowCol(RadValue): + row = RadValue // 1000 + col = RadValue % 1000 + return row, col + + +def EncodeRadioRowCol(row, col): + RadValue = row * 1000 + col + return RadValue + + +# ------- FUNCTION BuildResults. Form exiting so build the results to pass back ------- # +# format of return values is +# (Button Pressed, input_values) +def BuildResults(form, initialize_only, top_level_form): + # Results for elements are: + # TEXT - Nothing + # INPUT - Read value from TK + # Button - Button Text and position as a Tuple + + # Get the initialized results so we don't have to rebuild + form.DictionaryKeyCounter = 0 + form.ReturnValuesDictionary = {} + form.ReturnValuesList = [] + BuildResultsForSubform(form, initialize_only, top_level_form) + # try: + # BuildResultsForSubform(form, initialize_only, top_level_form) + # except: + # print('Error building return values') + if not top_level_form.LastButtonClickedWasRealtime: + top_level_form.LastButtonClicked = None + return form.ReturnValues + + +def BuildResultsForSubform(form, initialize_only, top_level_form): + button_pressed_text = top_level_form.LastButtonClicked + for row_num, row in enumerate(form.Rows): + for col_num, element in enumerate(row): + if element.Key is not None and WRITE_ONLY_KEY in str(element.Key): + continue + value = None + if element.Type == ELEM_TYPE_COLUMN: + element.DictionaryKeyCounter = top_level_form.DictionaryKeyCounter + element.ReturnValuesList = [] + element.ReturnValuesDictionary = {} + BuildResultsForSubform(element, initialize_only, top_level_form) + for item in element.ReturnValuesList: + AddToReturnList(top_level_form, item) + if element.UseDictionary: + top_level_form.UseDictionary = True + if element.ReturnValues[0] is not None: # if a button was clicked + button_pressed_text = element.ReturnValues[0] + + if element.Type == ELEM_TYPE_FRAME: + element.DictionaryKeyCounter = top_level_form.DictionaryKeyCounter + element.ReturnValuesList = [] + element.ReturnValuesDictionary = {} + BuildResultsForSubform(element, initialize_only, top_level_form) + for item in element.ReturnValuesList: + AddToReturnList(top_level_form, item) + if element.UseDictionary: + top_level_form.UseDictionary = True + if element.ReturnValues[0] is not None: # if a button was clicked + button_pressed_text = element.ReturnValues[0] + + if element.Type == ELEM_TYPE_TAB_GROUP: + element.DictionaryKeyCounter = top_level_form.DictionaryKeyCounter + element.ReturnValuesList = [] + element.ReturnValuesDictionary = {} + BuildResultsForSubform(element, initialize_only, top_level_form) + for item in element.ReturnValuesList: + AddToReturnList(top_level_form, item) + if element.UseDictionary: + top_level_form.UseDictionary = True + if element.ReturnValues[0] is not None: # if a button was clicked + button_pressed_text = element.ReturnValues[0] + + if element.Type == ELEM_TYPE_TAB: + element.DictionaryKeyCounter = top_level_form.DictionaryKeyCounter + element.ReturnValuesList = [] + element.ReturnValuesDictionary = {} + BuildResultsForSubform(element, initialize_only, top_level_form) + for item in element.ReturnValuesList: + AddToReturnList(top_level_form, item) + if element.UseDictionary: + top_level_form.UseDictionary = True + if element.ReturnValues[0] is not None: # if a button was clicked + button_pressed_text = element.ReturnValues[0] + + if not initialize_only: + if element.Type == ELEM_TYPE_INPUT_TEXT: + value = element.WxTextCtrl.GetValue() + if not top_level_form.NonBlocking and not element.do_not_clear and not top_level_form.ReturnKeyboardEvents: + element.WxTextCtrl.SetValue('') + elif element.Type == ELEM_TYPE_INPUT_CHECKBOX: + value = element.WxCheckbox.GetValue() + value = (value != 0) + elif element.Type == ELEM_TYPE_INPUT_RADIO: + value = element.WxRadioButton.GetValue() + elif element.Type == ELEM_TYPE_BUTTON: + if top_level_form.LastButtonClicked == element.ButtonText: + button_pressed_text = top_level_form.LastButtonClicked + if element.BType != BUTTON_TYPE_REALTIME: # Do not clear realtime buttons + top_level_form.LastButtonClicked = None + if element.BType == BUTTON_TYPE_CALENDAR_CHOOSER: + try: + value = element.TKCal.selection + except: + value = None + else: + try: + value = element.TKStringVar.get() + except: + value = None + elif element.Type == ELEM_TYPE_INPUT_COMBO: + value = element.WxComboBox.GetValue() + elif element.Type == ELEM_TYPE_INPUT_OPTION_MENU: + value = element.TKStringVar.get() + elif element.Type == ELEM_TYPE_INPUT_LISTBOX: + try: + items = element.TKListbox.curselection() + value = [element.Values[int(item)] for item in items] + except: + value = '' + elif element.Type == ELEM_TYPE_INPUT_SPIN: + value = element.WxTextCtrl.GetValue() + # value = element.CurrentValue + elif element.Type == ELEM_TYPE_INPUT_SLIDER: + try: + value = element.TKIntVar.get() + except: + value = 0 + elif element.Type == ELEM_TYPE_INPUT_MULTILINE: + if element.WriteOnly: + continue + try: + value = element.WxTextCtrl.GetValue() + except: + pass + + if not top_level_form.NonBlocking and not element.do_not_clear and not top_level_form.ReturnKeyboardEvents: + element.WxTextCtrl.SetValue('') + elif element.Type == ELEM_TYPE_TAB_GROUP: + try: + value = element.TKNotebook.tab(element.TKNotebook.index('current'))['text'] + tab_key = element.FindKeyFromTabName(value) + if tab_key is not None: + value = tab_key + except: + value = None + elif element.Type == ELEM_TYPE_TABLE: + value = element.SelectedRows + elif element.Type == ELEM_TYPE_TREE: + value = element.SelectedRows + elif element.Type == ELEM_TYPE_GRAPH: + value = element.ClickPosition + else: + value = None + + # if an input type element, update the results + if element.Type != ELEM_TYPE_BUTTON and \ + element.Type != ELEM_TYPE_TEXT and \ + element.Type != ELEM_TYPE_IMAGE and \ + element.Type != ELEM_TYPE_OUTPUT and \ + element.Type != ELEM_TYPE_PROGRESS_BAR and \ + element.Type != ELEM_TYPE_COLUMN and \ + element.Type != ELEM_TYPE_FRAME \ + and element.Type != ELEM_TYPE_TAB: + AddToReturnList(form, value) + AddToReturnDictionary(top_level_form, element, value) + elif (element.Type == ELEM_TYPE_BUTTON and + element.BType == BUTTON_TYPE_CALENDAR_CHOOSER and + element.Target == (None, None)) or \ + (element.Type == ELEM_TYPE_BUTTON and + element.BType == BUTTON_TYPE_COLOR_CHOOSER and + element.Target == (None, None)) or \ + (element.Type == ELEM_TYPE_BUTTON + and element.Key is not None and + (element.BType in (BUTTON_TYPE_SAVEAS_FILE, BUTTON_TYPE_BROWSE_FILE, BUTTON_TYPE_BROWSE_FILES, + BUTTON_TYPE_BROWSE_FOLDER))): + AddToReturnList(form, value) + AddToReturnDictionary(top_level_form, element, value) + + # if this is a column, then will fail so need to wrap with tr + try: + if form.ReturnKeyboardEvents and form.LastKeyboardEvent is not None: + button_pressed_text = form.LastKeyboardEvent + form.LastKeyboardEvent = None + except: + pass + + try: + form.ReturnValuesDictionary.pop(None, None) # clean up dictionary include None was included + except: + pass + + if not form.UseDictionary: + form.ReturnValues = button_pressed_text, form.ReturnValuesList + else: + form.ReturnValues = button_pressed_text, form.ReturnValuesDictionary + + return form.ReturnValues + + +def FillFormWithValues(form, values_dict): + FillSubformWithValues(form, values_dict) + + +def FillSubformWithValues(form, values_dict): + for row_num, row in enumerate(form.Rows): + for col_num, element in enumerate(row): + value = None + if element.Type == ELEM_TYPE_COLUMN: + FillSubformWithValues(element, values_dict) + if element.Type == ELEM_TYPE_FRAME: + FillSubformWithValues(element, values_dict) + if element.Type == ELEM_TYPE_TAB_GROUP: + FillSubformWithValues(element, values_dict) + if element.Type == ELEM_TYPE_TAB: + FillSubformWithValues(element, values_dict) + try: + value = values_dict[element.Key] + except: + continue + if element.Type == ELEM_TYPE_INPUT_TEXT: + element.Update(value) + elif element.Type == ELEM_TYPE_INPUT_CHECKBOX: + element.Update(value) + elif element.Type == ELEM_TYPE_INPUT_RADIO: + element.Update(value) + elif element.Type == ELEM_TYPE_INPUT_COMBO: + element.Update(value) + elif element.Type == ELEM_TYPE_INPUT_OPTION_MENU: + element.Update(value) + elif element.Type == ELEM_TYPE_INPUT_LISTBOX: + element.SetValue(value) + elif element.Type == ELEM_TYPE_INPUT_SLIDER: + element.Update(value) + elif element.Type == ELEM_TYPE_INPUT_MULTILINE: + element.Update(value) + elif element.Type == ELEM_TYPE_INPUT_SPIN: + element.Update(value) + elif element.Type == ELEM_TYPE_BUTTON: + element.Update(value) + + +def _FindElementFromKeyInSubForm(form, key): + for row_num, row in enumerate(form.Rows): + for col_num, element in enumerate(row): + if element.Type == ELEM_TYPE_COLUMN: + matching_elem = _FindElementFromKeyInSubForm(element, key) + if matching_elem is not None: + return matching_elem + if element.Type == ELEM_TYPE_FRAME: + matching_elem = _FindElementFromKeyInSubForm(element, key) + if matching_elem is not None: + return matching_elem + if element.Type == ELEM_TYPE_TAB_GROUP: + matching_elem = _FindElementFromKeyInSubForm(element, key) + if matching_elem is not None: + return matching_elem + if element.Type == ELEM_TYPE_TAB: + matching_elem = _FindElementFromKeyInSubForm(element, key) + if matching_elem is not None: + return matching_elem + if element.Key == key: + return element + + +def _FindElementWithFocusInSubForm(form): + for row_num, row in enumerate(form.Rows): + for col_num, element in enumerate(row): + if element.Type == ELEM_TYPE_COLUMN: + matching_elem = _FindElementWithFocusInSubForm(element) + if matching_elem is not None: + return matching_elem + if element.Type == ELEM_TYPE_FRAME: + matching_elem = _FindElementWithFocusInSubForm(element) + if matching_elem is not None: + return matching_elem + if element.Type == ELEM_TYPE_TAB_GROUP: + matching_elem = _FindElementWithFocusInSubForm(element) + if matching_elem is not None: + return matching_elem + if element.Type == ELEM_TYPE_TAB: + matching_elem = _FindElementWithFocusInSubForm(element) + if matching_elem is not None: + return matching_elem + if element.Type == ELEM_TYPE_INPUT_TEXT: + if element.TKEntry is not None: + if element.TKEntry is element.TKEntry.focus_get(): + return element + if element.Type == ELEM_TYPE_INPUT_MULTILINE: + if element.TKText is not None: + if element.TKText is element.TKText.focus_get(): + return element + + +if sys.version_info[0] >= 3: + def AddMenuItem(top_menu, sub_menu_info, element, is_sub_menu=False, skip=False): + return_val = None + if type(sub_menu_info) is str: + if not is_sub_menu and not skip: + # print(f'Adding command {sub_menu_info}') + pos = sub_menu_info.find('&') + if pos != -1: + if pos == 0 or sub_menu_info[pos - 1] != "\\": + sub_menu_info = sub_menu_info[:pos] + sub_menu_info[pos + 1:] + if sub_menu_info == '---': + top_menu.Append(wx.ID_SEPARATOR) + else: + try: + item_without_key = sub_menu_info[:sub_menu_info.index(MENU_KEY_SEPARATOR)] + except: + item_without_key = sub_menu_info + + if item_without_key[0] == MENU_DISABLED_CHARACTER: + id = top_menu.Append(wx.ID_ANY, item_without_key[len(MENU_DISABLED_CHARACTER):]) + element.id_to_text[id] = sub_menu_info[1:] + top_menu.Enable(id.Id, False) + else: + id = top_menu.Append(wx.ID_ANY, item_without_key) + element.id_to_text[id] = sub_menu_info + + else: + i = 0 + while i < (len(sub_menu_info)): + item = sub_menu_info[i] + if i != len(sub_menu_info) - 1: + if type(sub_menu_info[i + 1]) == list: + new_menu = wx.Menu() + return_val = new_menu + pos = sub_menu_info[i].find('&') + if pos != -1: + if pos == 0 or sub_menu_info[i][pos - 1] != "\\": + sub_menu_info[i] = sub_menu_info[i][:pos] + sub_menu_info[i][pos + 1:] + if sub_menu_info[i][0] == MENU_DISABLED_CHARACTER: + id = top_menu.AppendSubMenu(new_menu, sub_menu_info[i][len(MENU_DISABLED_CHARACTER):]) + top_menu.Enable(id.Id, False) + else: + top_menu.AppendSubMenu(new_menu, sub_menu_info[i]) + AddMenuItem(new_menu, sub_menu_info[i + 1], element, is_sub_menu=True) + i += 1 # skip the next one + else: + AddMenuItem(top_menu, item, element) + else: + AddMenuItem(top_menu, item, element) + i += 1 + return return_val + +if sys.version_info[0] >= 3: + def AddMenuItem2(top_menu, sub_menu_info, element, is_sub_menu=False, skip=False): + if type(sub_menu_info) is str: + if not is_sub_menu and not skip: + # print(f'Adding command {sub_menu_info}') + pos = sub_menu_info.find('&') + if pos != -1: + if pos == 0 or sub_menu_info[pos - 1] != "\\": + sub_menu_info = sub_menu_info[:pos] + sub_menu_info[pos + 1:] + if sub_menu_info == '---': + top_menu.Append(wx.ID_SEPARATOR) + else: + top_menu.Append(wx.ID_ANY, sub_menu_info) + else: + i = 0 + while i < (len(sub_menu_info)): + item = sub_menu_info[i] + if i != len(sub_menu_info) - 1: + if type(sub_menu_info[i + 1]) == list: + new_menu = wx.Menu() + pos = sub_menu_info[i].find('&') + if pos != -1: + if pos == 0 or sub_menu_info[i][pos - 1] != "\\": + sub_menu_info[i] = sub_menu_info[i][:pos] + sub_menu_info[i][pos + 1:] + top_menu.AppendSubMenu(new_menu, sub_menu_info[i]) + AddMenuItem(new_menu, sub_menu_info[i + 1], element, is_sub_menu=True) + i += 1 # skip the next one + else: + AddMenuItem(top_menu, item, element) + else: + AddMenuItem(top_menu, item, element) + i += 1 +else: + def AddMenuItem(top_menu, sub_menu_info, element, is_sub_menu=False, skip=False): + if isinstance(sub_menu_info, types.StringType): + if not is_sub_menu and not skip: + # print(f'Adding command {sub_menu_info}') + pos = sub_menu_info.find('&') + if pos != -1: + if pos == 0 or sub_menu_info[pos - 1] != "\\": + sub_menu_info = sub_menu_info[:pos] + sub_menu_info[pos + 1:] + if sub_menu_info == '---': + top_menu.add('separator') + else: + top_menu.add_command(label=sub_menu_info, underline=pos, + command=lambda: Menu._MenuItemChosenCallback(element, sub_menu_info)) + else: + i = 0 + while i < (len(sub_menu_info)): + item = sub_menu_info[i] + if i != len(sub_menu_info) - 1: + if not isinstance(sub_menu_info[i + 1], types.StringType): + new_menu = tk.Menu(top_menu, tearoff=element.Tearoff) + pos = sub_menu_info[i].find('&') + if pos != -1: + if pos == 0 or sub_menu_info[i][pos - 1] != "\\": + sub_menu_info[i] = sub_menu_info[i][:pos] + sub_menu_info[i][pos + 1:] + top_menu.add_cascade(label=sub_menu_info[i], menu=new_menu, underline=pos) + AddMenuItem(new_menu, sub_menu_info[i + 1], element, is_sub_menu=True) + i += 1 # skip the next one + else: + AddMenuItem(top_menu, item, element) + else: + AddMenuItem(top_menu, item, element) + i += 1 + + + + # # ###### + # # # # # # # # # ##### # # #### # # + # # # # # # # # # # # # # # ## # + # # # ## ###### # # ###### # # # # # + # # # ## # # # # # # # # # # + # # # # # # # # # # # # # ## + ## ## # # # # # # # #### # # + +# My crappy WxPython code + +# ░░░░░░░░░░░█▀▀░░█░░░░░░ +# ░░░░░░▄▀▀▀▀░░░░░█▄▄░░░░ +# ░░░░░░█░█░░░░░░░░░░▐░░░ +# ░░░░░░▐▐░░░░░░░░░▄░▐░░░ +# ░░░░░░█░░░░░░░░▄▀▀░▐░░░ +# ░░░░▄▀░░░░░░░░▐░▄▄▀░░░░ +# ░░▄▀░░░▐░░░░░█▄▀░▐░░░░░ +# ░░█░░░▐░░░░░░░░▄░█░░░░░ +# ░░░█▄░░▀▄░░░░▄▀▐░█░░░░░ +# ░░░█▐▀▀▀░▀▀▀▀░░▐░█░░░░░ +# ░░▐█▐▄░░▀░░░░░░▐░█▄▄░░░ +# ░░░▀▀▄░░░░░░░░▄▐▄▄▄▀░░░ +# ░░░░░░░░░░░░░░░░░░░░░░░ + + + +# ------------------------------------------------------------------------------------------------------------------ # +# ------------------------------------------------------------------------------------------------------------------ # +# ===================================== WxPython CODE STARTS HERE ================================================ # +# ------------------------------------------------------------------------------------------------------------------ # +# ------------------------------------------------------------------------------------------------------------------ # + +def PackFormIntoFrame(container_elem, containing_frame, toplevel_form): + """ + + :param container_elem: + :type container_elem: Window or Column or Tab or Frame + :param containing_frame: + :type containing_frame: wx.BoxSizer + :param toplevel_form: + :type toplevel_form: Window + :return: + """ + def pad_widget(widget): + lrsizer = wx.BoxSizer(wx.HORIZONTAL) + if full_element_pad[1] == full_element_pad[3]: # if right = left + lrsizer.Add(widget, 0, wx.LEFT | wx.RIGHT, border=full_element_pad[1]) + else: + sizer = wx.BoxSizer(wx.HORIZONTAL) + sizer.Add(widget, 0, wx.LEFT, border=full_element_pad[3]) + lrsizer.Add(sizer, 0, wx.RIGHT, border=full_element_pad[1]) + + top_bottom_sizer = wx.BoxSizer(wx.HORIZONTAL) + if full_element_pad[0] == full_element_pad[2]: # if top = bottom + top_bottom_sizer.Add(lrsizer, 0, wx.TOP | wx.BOTTOM, border=full_element_pad[0]) + else: + sizer = wx.BoxSizer(wx.HORIZONTAL) + sizer.Add(lrsizer, 0, wx.TOP, border=full_element_pad[0]) + top_bottom_sizer.Add(sizer, 0, wx.BOTTOM, border=full_element_pad[2]) + return top_bottom_sizer + + # + # font, text color, background color, size, disabled, visible, tooltip + # + def do_font_and_color(widget): + if font: + widget.SetFont(font_to_wx_font(font)) + if element.TextColor not in (None, COLOR_SYSTEM_DEFAULT): + widget.SetForegroundColour(element.TextColor) + if element.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT): + widget.SetBackgroundColour(element.BackgroundColor) + widget.SetMinSize(element_size) + if element.Disabled: + widget.Enable(False) + if not element.Visible: + widget.Hide() + if element.Tooltip: + widget.SetToolTip(element.Tooltip) + + def CharWidthInPixels(): + return tkinter.font.Font().measure('A') # single character width + + border_depth = toplevel_form.BorderDepth if toplevel_form.BorderDepth is not None else DEFAULT_BORDER_WIDTH + # --------------------------------------------------------------------------- # + # **************** Use FlexForm to build the tkinter window ********** ----- # + # Building is done row by row. # + # --------------------------------------------------------------------------- # + focus_set = False + ######################### LOOP THROUGH ROWS ######################### + # *********** ------- Loop through ROWS ------- ***********# + for row_num, flex_row in enumerate(container_elem.Rows): + ######################### LOOP THROUGH ELEMENTS ON ROW ######################### + # *********** ------- Loop through ELEMENTS ------- ***********# + # *********** Make TK Row ***********# + hsizer = wx.BoxSizer(wx.HORIZONTAL) + for col_num, element in enumerate(flex_row): + element.ParentForm = toplevel_form # save the button's parent form object + if toplevel_form.Font and (element.Font == DEFAULT_FONT or not element.Font): + font = toplevel_form.Font + element.Font = font + elif element.Font is not None: + font = element.Font + else: + font = DEFAULT_FONT + # ------- Determine Auto-Size setting on a cascading basis ------- # + if element.AutoSizeText is not None: # if element overide + auto_size_text = element.AutoSizeText + elif toplevel_form.AutoSizeText is not None: # if form override + auto_size_text = toplevel_form.AutoSizeText + else: + auto_size_text = DEFAULT_AUTOSIZE_TEXT + element_type = element.Type + # Set foreground color + text_color = element.TextColor + # Determine Element size + element_size = element.Size + if (element_size == (None, None) and element_type not in (ELEM_TYPE_BUTTON, ELEM_TYPE_BUTTONMENU)): # user did not specify a size + element_size = toplevel_form.DefaultElementSize + elif (element_size == (None, None) and element_type in (ELEM_TYPE_BUTTON, ELEM_TYPE_BUTTONMENU)): + element_size = toplevel_form.DefaultButtonElementSize + else: + auto_size_text = False # if user has specified a size then it shouldn't autosize + full_element_pad = [0, 0, 0, 0] # Top, Right, Bottom, Left + elementpad = element.Pad if element.Pad is not None else toplevel_form.ElementPadding + if type(elementpad[0]) != tuple: # left and right + full_element_pad[1] = full_element_pad[3] = elementpad[0] + else: + full_element_pad[3], full_element_pad[1] = elementpad[0] + if type(elementpad[1]) != tuple: # top and bottom + full_element_pad[0] = full_element_pad[2] = elementpad[1] + else: + full_element_pad[0], full_element_pad[2] = elementpad[1] + + border_depth = toplevel_form.BorderDepth if toplevel_form.BorderDepth is not None else DEFAULT_BORDER_WIDTH + try: + if element.BorderWidth is not None: + border_depth = element.BorderWidth + except: + pass + + # ------------------------- COLUMN element ------------------------- # + if element_type == ELEM_TYPE_COLUMN: + element = element # type: Column + element.WxBoxSizer = vsizer = wx.BoxSizer(wx.VERTICAL) + element.WxHSizer = hsizer + # element.WxScrollBar = wx.ScrollBar(toplevel_form.MasterFrame, id=wx.ID_ANY, style=wx.SB_VERTICAL) + # vsizer.Add(element.WxScrollBar) + PackFormIntoFrame(element, vsizer, toplevel_form) + + hsizer.Add(pad_widget(vsizer), 0) + if not element.Visible: + hsizer.Hide(vsizer, recursive=True) + + # # column_widget = QWidget() + # column_widget = QGroupBox() + # element.QT_QGroupBox = column_widget + # # column_widget.setFrameShape(QtWidgets.QFrame.NoFrame) + # style = create_style_from_font(font) + # if element.BackgroundColor is not None: + # style = style_entry(background_color=element.BackgroundColor) + # style += 'background-color: %s;' % element.BackgroundColor + # style += style_entry(border='0px solid gray') + # # style += 'border: 0px solid gray; ' + # style = style_generate('QGroupBox', style) + # column_widget.setStyleSheet(style) + # + # column_layout = QFormLayout() + # column_vbox = QVBoxLayout() + # + # PackFormIntoFrame(element, column_layout, toplevel_win) + # + # column_vbox.addLayout(column_layout) + # column_widget.setLayout(column_vbox) + # + # # column_widget.setStyleSheet(style) + # if not element.Visible: + # column_widget.setVisible(False) + # + # qt_row_layout.addWidget(column_widget) + + + # if element.Scrollable: + # col_frame = TkScrollableFrame(tk_row_frame, + # element.VerticalScrollOnly) # do not use yet! not working + # PackFormIntoFrame(element, col_frame.TKFrame, toplevel_form) + # col_frame.TKFrame.update() + # if element.Size == (None, None): # if no size specified, use column width x column height/2 + # col_frame.canvas.config(width=col_frame.TKFrame.winfo_reqwidth(), + # height=col_frame.TKFrame.winfo_reqheight() / 2) + # else: + # col_frame.canvas.config(width=element.Size[0], height=element.Size[1]) + # + # if not element.BackgroundColor in (None, COLOR_SYSTEM_DEFAULT): + # col_frame.canvas.config(background=element.BackgroundColor) + # col_frame.TKFrame.config(background=element.BackgroundColor, borderwidth=0, + # highlightthickness=0) + # col_frame.config(background=element.BackgroundColor, borderwidth=0, highlightthickness=0) + # else: + # col_frame = tk.Frame(tk_row_frame) + # PackFormIntoFrame(element, col_frame, toplevel_form) + # + # col_frame.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1], expand=True, fill='both') + # if element.BackgroundColor != COLOR_SYSTEM_DEFAULT and element.BackgroundColor is not None: + # col_frame.configure(background=element.BackgroundColor, highlightbackground=element.BackgroundColor, + # highlightcolor=element.BackgroundColor) + # ------------------------- TEXT element ------------------------- # + elif element_type == ELEM_TYPE_TEXT: + element = element # type: Text + if element.Justification is not None: + justification = element.Justification + elif toplevel_form.TextJustification is not None: + justification = toplevel_form.TextJustification + else: + justification = DEFAULT_TEXT_JUSTIFICATION + style = wx.ALIGN_LEFT if justification.startswith('l') else wx.ALIGN_CENTER if justification.startswith('c') else wx.ALIGN_RIGHT + # print(border_depth, element.BorderWidth) + if border_depth: + if element.Relief: + if element.Relief in (RELIEF_SOLID, RELIEF_FLAT): + style |= wx.SIMPLE_BORDER + elif element.Relief == RELIEF_SUNKEN: + style |= wx.SUNKEN_BORDER + elif element.Relief in(RELIEF_RAISED, RELIEF_RIDGE): + style |= wx.RAISED_BORDER + elif element.Relief in (RELIEF_SUNKEN, RELIEF_SUNKEN): + style |= wx.SUNKEN_BORDER + statictext = element.WxStaticText = wx.StaticText(toplevel_form.MasterPanel, -1, element.DisplayText, style=style) + if font: + statictext.SetFont(font_to_wx_font(font)) + if element.TextColor not in (None, COLOR_SYSTEM_DEFAULT): + statictext.SetForegroundColour(element.TextColor) + if element.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT): + statictext.SetBackgroundColour(element.BackgroundColor) + display_text = element.DisplayText # text to display + if auto_size_text is False: + width, height = element_size + else: + lines = display_text.split('\n') + max_line_len = max([len(l) for l in lines]) + num_lines = len(lines) + if max_line_len > element_size[0]: # if text exceeds element size, the will have to wrap + width = element_size[0] + else: + width = max_line_len + height = num_lines + + if element.ClickSubmits: # bind events + statictext.Bind(wx.EVT_LEFT_UP, element._WxCallbackKeyboard) + + hsizer.Add(pad_widget(element.WxStaticText), 0) + + if not auto_size_text: + statictext.SetMinSize((width,height)) + + if element.Tooltip: + statictext.SetToolTip(element.Tooltip) + if not element.Visible: + statictext.Hide() + + + # Set wrap-length for text (in PIXELS) == PAIN IN THE ASS + # wraplen = tktext_label.winfo_reqwidth() + 40 # width of widget in Pixels + # if not auto_size_text and height == 1: + # wraplen = 0 + # ------------------------- BUTTON element ------------------------- # + elif element_type == ELEM_TYPE_BUTTON: + element = element # type: Button + element.WxButton = button = wx.Button(toplevel_form.MasterPanel, style=wx.NO_BORDER) + button.SetLabelText(element.ButtonText) + if font: + button.SetFont(font_to_wx_font(font)) + button.Bind(wx.EVT_BUTTON, element.ButtonCallBack) + + element.Location = (row_num, col_num) + if element.AutoSizeButton is not None: + auto_size = element.AutoSizeButton + else: + auto_size = toplevel_form.AutoSizeButtons + if auto_size is False or element.Size[0] is not None: + width, height = element_size + else: + width = 0 + height = toplevel_form.DefaultButtonElementSize[1] + + if auto_size: + element.WxButton.SetWindowStyleFlag(element.WxButton.GetWindowStyleFlag() | wx.BU_EXACTFIT) + else: + element.WxButton.SetMinSize(_convert_tkinter_size_to_Wx((width,height), DEFAULT_PIXEL_TO_CHARS_CUTOFF)) + if element.ButtonColor != (None, None) and element.ButtonColor != DEFAULT_BUTTON_COLOR: + bc = element.ButtonColor + elif toplevel_form.ButtonColor != (None, None) and toplevel_form.ButtonColor != DEFAULT_BUTTON_COLOR: + bc = toplevel_form.ButtonColor + else: + bc = DEFAULT_BUTTON_COLOR + + button.SetBackgroundColour(bc[1]) + button.SetForegroundColour(bc[0]) + + sizer = pad_widget(button) + hsizer.Add(sizer, 0) + + if not element.Visible: + button.Hide() + if element.Tooltip: + button.SetToolTip(element.Tooltip) + + + # if btype != BUTTON_TYPE_REALTIME: + # tkbutton = tk.Button(tk_row_frame, text=btext, width=width, height=height, + # command=element.ButtonCallBack, justify=tk.LEFT, bd=border_depth, font=font) + # else: + # tkbutton = tk.Button(tk_row_frame, text=btext, width=width, height=height, justify=tk.LEFT, + # bd=border_depth, font=font) + # tkbutton.bind('', element.ButtonReleaseCallBack) + # tkbutton.bind('', element.ButtonPressCallBack) + # if element.ImageFilename: # if button has an image on it + # tkbutton.config(highlightthickness=0) + # photo = tk.PhotoImage(file=element.ImageFilename) + # if element.ImageSize != (None, None): + # width, height = element.ImageSize + # if element.ImageSubsample: + # photo = photo.subsample(element.ImageSubsample) + # else: + # width, height = photo.width(), photo.height() + # tkbutton.config(image=photo, compound=tk.CENTER, width=width, height=height) + # tkbutton.image = photo + # if element.ImageData: # if button has an image on it + # tkbutton.config(highlightthickness=0) + # photo = tk.PhotoImage(data=element.ImageData) + # if element.ImageSize != (None, None): + # width, height = element.ImageSize + # if element.ImageSubsample: + # photo = photo.subsample(element.ImageSubsample) + # else: + # width, height = photo.width(), photo.height() + # tkbutton.config(image=photo, compound=tk.CENTER, width=width, height=height) + # tkbutton.image = photo + # if width != 0: + # tkbutton.configure(wraplength=wraplen + 10) # set wrap to width of widget + # tkbutton.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) + # if element.BindReturnKey: + # element.TKButton.bind('', element._ReturnKeyHandler) + # if element.Focus is True or (toplevel_form.UseDefaultFocus and not focus_set): + # focus_set = True + # element.TKButton.bind('', element._ReturnKeyHandler) + # element.TKButton.focus_set() + # toplevel_form.TKroot.focus_force() + # if element.Disabled == True: + # element.TKButton['state'] = 'disabled' + # if element.Tooltip is not None: + # element.TooltipObject = ToolTip(element.TKButton, text=element.Tooltip, + # timeout=DEFAULT_TOOLTIP_TIME) + + # # ------------------------- INPUT element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_TEXT: + element = element # type: InputText + if element.Justification is not None: + justification = element.Justification + elif toplevel_form.TextJustification is not None: + justification = toplevel_form.TextJustification + else: + justification = DEFAULT_TEXT_JUSTIFICATION + justify = wx.ALIGN_LEFT if justification.startswith('l') else wx.ALIGN_CENTER_HORIZONTAL if justification.startswith('c') else wx.ALIGN_RIGHT + if element.PasswordCharacter: + justify |= wx.TE_PASSWORD + + element.WxTextCtrl = text_ctrl = wx.TextCtrl(toplevel_form.MasterPanel, style=justify) + + if element.DefaultText: + text_ctrl.SetValue(element.DefaultText) + if font: + text_ctrl.SetFont(font_to_wx_font(font)) + if element.TextColor not in (None, COLOR_SYSTEM_DEFAULT): + text_ctrl.SetForegroundColour(element.TextColor) + if element.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT): + text_ctrl.SetBackgroundColour(element.BackgroundColor) + text_ctrl.SetMinSize(element_size) + if element.Disabled: + text_ctrl.Enable(False) + if element.ChangeSubmits: + text_ctrl.Bind(wx.EVT_KEY_UP, element._WxCallbackKeyboard) + text_ctrl.Bind(wx.EVT_TEXT_ENTER, element._ReturnKeyHandler) + + sizer = pad_widget(text_ctrl) + + hsizer.Add(sizer, 0) + + if not element.Visible: + text_ctrl.Hide() + if element.Tooltip: + text_ctrl.SetToolTip(element.Tooltip) + + if element.Focus is True or (toplevel_form.UseDefaultFocus and not focus_set): + focus_set = True + element.SetFocus() + + # ------------------------- COMBO BOX (Drop Down) element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_COMBO: + element = element # type: Combo + if element.Readonly: + element.WxComboBox = wx.Choice(toplevel_form.MasterPanel, + id=wx.ID_ANY, + choices=element.Values) + else: + element.WxComboBox = wx.ComboBox(toplevel_form.MasterPanel, + id=wx.ID_ANY, + choices=element.Values) + if element.DefaultValue: + element.WxComboBox.SetSelection(element.WxComboBox.FindString(element.DefaultValue)) + if element.Readonly: + element.WxComboBox.SetWindowStyle(wx.CB_READONLY) + + do_font_and_color(element.WxComboBox) + sizer = pad_widget(element.WxComboBox) + + if element.ChangeSubmits: + element.WxComboBox.Bind(wx.EVT_COMBOBOX, element._WxCallbackKeyboard) + + hsizer.Add(sizer, 0) + + # max_line_len = max([len(str(l)) for l in element.Values]) + # if auto_size_text is False: + # width = element_size[0] + # else: + # width = max_line_len + # element.TKStringVar = tk.StringVar() + # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + # combostyle = ttk.Style() + # try: + # combostyle.theme_create('combostyle', + # settings={'TCombobox': + # {'configure': + # {'selectbackground': element.BackgroundColor, + # 'fieldbackground': element.BackgroundColor, + # 'foreground': text_color, + # 'background': element.BackgroundColor} + # }}) + # except: + # try: + # combostyle.theme_settings('combostyle', + # settings={'TCombobox': + # {'configure': + # {'selectbackground': element.BackgroundColor, + # 'fieldbackground': element.BackgroundColor, + # 'foreground': text_color, + # 'background': element.BackgroundColor} + # }}) + # except: + # pass + # # ATTENTION: this applies the new style 'combostyle' to all ttk.Combobox + # combostyle.theme_use('combostyle') + # element.TKCombo = ttk.Combobox(tk_row_frame, width=width, textvariable=element.TKStringVar, font=font) + # if element.Size[1] != 1 and element.Size[1] is not None: + # element.TKCombo.configure(height=element.Size[1]) + # # element.TKCombo['state']='readonly' + # element.TKCombo['values'] = element.Values + # + # # if element.InitializeAsDisabled: + # # element.TKCombo['state'] = 'disabled' + # # if element.BackgroundColor is not None: + # # element.TKCombo.configure(background=element.BackgroundColor) + # element.TKCombo.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) + # if element.DefaultValue: + # for i, v in enumerate(element.Values): + # if v == element.DefaultValue: + # element.TKCombo.current(i) + # break + # else: + # element.TKCombo.current(0) + # if element.ChangeSubmits: + # element.TKCombo.bind('<>', element.ComboboxSelectHandler) + # if element.Readonly: + # element.TKCombo['state'] = 'readonly' + # if element.Disabled is True: # note overrides readonly if disabled + # element.TKCombo['state'] = 'disabled' + # if element.Tooltip is not None: + # element.TooltipObject = ToolTip(element.TKCombo, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) + # # ------------------------- LISTBOX element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_LISTBOX: + pass + # max_line_len = max([len(str(l)) for l in element.Values]) if len(element.Values) != 0 else 0 + # if auto_size_text is False: + # width = element_size[0] + # else: + # width = max_line_len + # listbox_frame = tk.Frame(tk_row_frame) + # element.TKStringVar = tk.StringVar() + # element.TKListbox = tk.Listbox(listbox_frame, height=element_size[1], width=width, + # selectmode=element.SelectMode, font=font) + # for index, item in enumerate(element.Values): + # element.TKListbox.insert(tk.END, item) + # if element.DefaultValues is not None and item in element.DefaultValues: + # element.TKListbox.selection_set(index) + # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + # element.TKListbox.configure(background=element.BackgroundColor) + # if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT: + # element.TKListbox.configure(fg=text_color) + # if element.ChangeSubmits: + # element.TKListbox.bind('<>', element.ListboxSelectHandler) + # vsb = tk.Scrollbar(listbox_frame, orient="vertical", command=element.TKListbox.yview) + # element.TKListbox.configure(yscrollcommand=vsb.set) + # element.TKListbox.pack(side=tk.LEFT) + # vsb.pack(side=tk.LEFT, fill='y') + # listbox_frame.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) + # if element.BindReturnKey: + # element.TKListbox.bind('', element.ListboxSelectHandler) + # element.TKListbox.bind('', element.ListboxSelectHandler) + # if element.Disabled == True: + # element.TKListbox['state'] = 'disabled' + # if element.Tooltip is not None: + # element.TooltipObject = ToolTip(element.TKListbox, text=element.Tooltip, + # timeout=DEFAULT_TOOLTIP_TIME) + # ------------------------- INPUT MULTILINE element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_MULTILINE: + element = element # type: Multiline + justify = 0 + if element.EnterSubmits: + justify |= wx.TE_PROCESS_ENTER + justify |= wx.TE_MULTILINE + element.WxTextCtrl = text_ctrl = wx.TextCtrl(toplevel_form.MasterPanel, style=justify) + + if element.DefaultText: + text_ctrl.SetValue(element.DefaultText) + if font: + text_ctrl.SetFont(font_to_wx_font(font)) + if element.TextColor not in (None, COLOR_SYSTEM_DEFAULT): + text_ctrl.SetForegroundColour(element.TextColor) + if element.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT): + text_ctrl.SetBackgroundColour(element.BackgroundColor) + text_ctrl.SetMinSize(element_size) + if element.Disabled: + text_ctrl.Enable(False) + if element.ChangeSubmits: + text_ctrl.Bind(wx.EVT_KEY_UP, element._WxCallbackKeyboard) + if element.EnterSubmits: + text_ctrl.Bind(wx.EVT_TEXT_ENTER, element._ReturnKeyHandler) + + sizer = pad_widget(text_ctrl) + hsizer.Add(sizer, 0) + + if not element.Visible: + text_ctrl.Hide() + if element.Tooltip: + text_ctrl.SetToolTip(element.Tooltip) + + if element.Focus is True or (toplevel_form.UseDefaultFocus and not focus_set): + focus_set = True + element.SetFocus() + # ------------------------- OUTPUT MULTILINE element ------------------------- # + elif element_type == ELEM_TYPE_MULTILINE_OUTPUT: + element = element # type: MultilineOutput + style = 0 + if element.EnterSubmits: + style |= wx.TE_PROCESS_ENTER + style |= wx.TE_MULTILINE | wx.TE_READONLY + element.WxTextCtrl = text_ctrl = wx.TextCtrl(toplevel_form.MasterPanel, style=style) + if element.DefaultText: + text_ctrl.SetValue(element.DefaultText) + + do_font_and_color(element.WxTextCtrl) + + if element.ChangeSubmits: + text_ctrl.Bind(wx.EVT_KEY_UP, element._WxCallbackKeyboard) + if element.EnterSubmits: + text_ctrl.Bind(wx.EVT_TEXT_ENTER, element._ReturnKeyHandler) + + sizer = pad_widget(text_ctrl) + + hsizer.Add(sizer, 0) + + + if element.Focus is True or (toplevel_form.UseDefaultFocus and not focus_set): + focus_set = True + element.SetFocus() + # ------------------------- OUTPUT element -----------------fd-------- # + elif element_type == ELEM_TYPE_OUTPUT: + element = element # type: Output + style = 0 + style |= wx.TE_MULTILINE | wx.TE_READONLY + style = wx.TE_MULTILINE | wx.TE_READONLY | wx.HSCROLL + element.WxTextCtrl = text_ctrl = wx.TextCtrl(toplevel_form.MasterPanel, style=style) + + do_font_and_color(element.WxTextCtrl) + + sizer = pad_widget(text_ctrl) + + hsizer.Add(sizer, 0) + + element._reroute_stdout() + # ------------------------- INPUT CHECKBOX element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_CHECKBOX: + element = element # type:Checkbox + element.WxCheckbox = widget = wx.CheckBox(toplevel_form.MasterPanel) + if element.Text: + widget.SetLabel(element.Text) + do_font_and_color(element.WxCheckbox) + sizer = pad_widget(widget) + + if element.ChangeSubmits: + widget.Bind(wx.EVT_CHECKBOX, element._WxCallbackKeyboard) + + hsizer.Add(sizer, 0) + + if element.InitialState: + widget.SetValue(True) + element.WxCheckbox = widget + + # # ------------------------- PROGRESS BAR element ------------------------- # + elif element_type == ELEM_TYPE_PROGRESS_BAR: + element = element # type: ProgressBar + style = wx.GA_HORIZONTAL if element.Orientation.startswith('h') else wx.GA_VERTICAL + element_size = element_size[::-1] if element.Orientation.startswith('v') else element_size + element_size = wx.Size((element_size[0], element_size[1])) + element.WxGauge = gauge = wx.Gauge(toplevel_form.MasterPanel, wx.ID_ANY, range=element.MaxValue, style=style, size=element_size) + if element.StartValue is not None: + gauge.SetValue(element.StartValue) + do_font_and_color(element.WxGauge) + sizer = pad_widget(gauge) + hsizer.Add(sizer, 0) + # ------------------------- INPUT RADIO BUTTON element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_RADIO: + element = element # type: Radio + widget = element.WxRadioButton # type: wx.RadioButton + do_font_and_color(element.WxRadioButton) + sizer = pad_widget(widget) + if element.ChangeSubmits: + widget.Bind(wx.EVT_RADIOBUTTON, element._WxCallbackKeyboard) + hsizer.Add(sizer, 0) + if element.InitialState: + widget.SetValue(True) + else: + widget.SetValue(False) + + # ------------------------- INPUT SPINNER element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_SPIN: + element = element # type:Spin + ######## First make an Input widget that will be used to display the text ######## + style = wx.ALIGN_RIGHT + if element.ReadOnly: + style |= wx.TE_READONLY + element.WxTextCtrl = text_ctrl = wx.TextCtrl(toplevel_form.MasterPanel, style=style) + do_font_and_color(element.WxTextCtrl) + if element.ChangeSubmits: + text_ctrl.Bind(wx.EVT_KEY_UP, element._WxCallbackKeyboard) + text_ctrl.Bind(wx.EVT_TEXT_ENTER, element._ReturnKeyHandler) + if element.DefaultValue: + text_ctrl.SetValue(str(element.DefaultValue)) + element.CurrentValue = element.DefaultValue + saved_pad = full_element_pad + full_element_pad[3] = 0 # set right padding to 0 + hsizer.Add(pad_widget(text_ctrl), 0) + + full_element_pad = saved_pad + ######## Now make a "Spin Button" that has the arrows ######## + # element.WxSpinCtrl = widget = wx.SpinCtrl(toplevel_form.MasterPanel, style=wx.SP_WRAP|wx.SP_ARROW_KEYS) + element.WxSpinCtrl = widget = wx.SpinButton(toplevel_form.MasterPanel, style=wx.SP_WRAP|wx.SP_ARROW_KEYS) + do_font_and_color(element.WxSpinCtrl) + element.WxSpinCtrl.SetRange(0, len(element.Values)-1) + if element.DefaultValue: + element.WxSpinCtrl.SetValue(element.Values.index(element.DefaultValue)) + widget.SetMinSize((25,25)) + + widget.Bind(wx.EVT_SPIN, element._WxSpinCallback) + saved_pad = full_element_pad + full_element_pad[1] = 0 # trying to set left pad to 0 but doesn't seem to work + hsizer.Add(pad_widget(widget), 0) + full_element_pad = saved_pad + + # ------------------------- IMAGE element ------------------------- # + elif element_type == ELEM_TYPE_IMAGE: + pass + # if element.Filename is not None: + # photo = tk.PhotoImage(file=element.Filename) + # elif element.Data is not None: + # photo = tk.PhotoImage(data=element.Data) + # else: + # photo = None + # print('*ERROR laying out form.... Image Element has no image specified*') + # + # if photo is not None: + # if element_size == ( + # None, None) or element_size == None or element_size == toplevel_form.DefaultElementSize: + # width, height = photo.width(), photo.height() + # else: + # width, height = element_size + # if photo is not None: + # element.tktext_label = tk.Label(tk_row_frame, image=photo, width=width, height=height, + # bd=border_depth) + # else: + # element.tktext_label = tk.Label(tk_row_frame, width=width, height=height, bd=border_depth) + # if element.BackgroundColor is not None: + # element.tktext_label.config(background=element.BackgroundColor); + # + # element.tktext_label.image = photo + # # tktext_label.configure(anchor=tk.NW, image=photo) + # element.tktext_label.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) + # if element.Tooltip is not None: + # element.TooltipObject = ToolTip(element.tktext_label, text=element.Tooltip, + # timeout=DEFAULT_TOOLTIP_TIME) + # ------------------------- Canvas element ------------------------- # + elif element_type == ELEM_TYPE_CANVAS: + pass + # width, height = element_size + # if element._TKCanvas is None: + # element._TKCanvas = tk.Canvas(tk_row_frame, width=width, height=height, bd=border_depth) + # else: + # element._TKCanvas.master = tk_row_frame + # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + # element._TKCanvas.configure(background=element.BackgroundColor, highlightthickness=0) + # element._TKCanvas.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) + # if element.Tooltip is not None: + # element.TooltipObject = ToolTip(element._TKCanvas, text=element.Tooltip, + # timeout=DEFAULT_TOOLTIP_TIME) + + # ------------------------- Graph element ------------------------- # + elif element_type == ELEM_TYPE_GRAPH: + pass + # width, height = element_size + # if element._TKCanvas is None: + # element._TKCanvas = tk.Canvas(tk_row_frame, width=width, height=height, bd=border_depth) + # else: + # element._TKCanvas.master = tk_row_frame + # element._TKCanvas2 = tk.Canvas(element._TKCanvas, width=width, height=height, bd=border_depth) + # element._TKCanvas2.pack(side=tk.LEFT) + # element._TKCanvas2.addtag_all('mytag') + # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + # element._TKCanvas2.configure(background=element.BackgroundColor, highlightthickness=0) + # element._TKCanvas.configure(background=element.BackgroundColor, highlightthickness=0) + # element._TKCanvas.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) + # if element.Tooltip is not None: + # element.TooltipObject = ToolTip(element._TKCanvas, text=element.Tooltip, + # timeout=DEFAULT_TOOLTIP_TIME) + # if element.ChangeSubmits: + # element._TKCanvas2.bind('', element.ButtonReleaseCallBack) + # element._TKCanvas2.bind('', element.ButtonPressCallBack) + # if element.DragSubmits: + # element._TKCanvas2.bind('', element.MotionCallBack) + # ------------------------- MENUBAR element ------------------------- # + elif element_type == ELEM_TYPE_MENUBAR: + pass + # menu_def = element.MenuDefinition + # element.TKMenu = tk.Menu(toplevel_form.TKroot, tearoff=element.Tearoff) # create the menubar + # menubar = element.TKMenu + # for menu_entry in menu_def: + # # print(f'Adding a Menubar ENTRY {menu_entry}') + # baritem = tk.Menu(menubar, tearoff=element.Tearoff) + # pos = menu_entry[0].find('&') + # # print(pos) + # if pos != -1: + # if pos == 0 or menu_entry[0][pos - 1] != "\\": + # menu_entry[0] = menu_entry[0][:pos] + menu_entry[0][pos + 1:] + # menubar.add_cascade(label=menu_entry[0], menu=baritem, underline=pos) + # if len(menu_entry) > 1: + # AddMenuItem(baritem, menu_entry[1], element) + # toplevel_form.TKroot.configure(menu=element.TKMenu) + # ------------------------- Frame element ------------------------- # + elif element_type == ELEM_TYPE_FRAME: + element = element # type: Frame + # ----- code from column as a pattern to follow ----- + # element = element # type: Column + # element.WxBoxSizer = vsizer = wx.BoxSizer(wx.VERTICAL) + # element.WxHSizer = hsizer + # PackFormIntoFrame(element, vsizer, toplevel_form) + # + # hsizer.Add(pad_widget(vsizer), 0) + # if not element.Visible: + # hsizer.Hide(vsizer, recursive=True) + # element.panel = panel = wx.Panel(toplevel_form.MasterFrame) + element.WxBoxSizer = vsizer = wx.StaticBoxSizer(orient=wx.VERTICAL, parent=toplevel_form.MasterFrame.panel, label=element.Title) + element.WxHSizer = hsizer + PackFormIntoFrame(element, vsizer, toplevel_form) + + hsizer.Add(pad_widget(vsizer), 0) + if not element.Visible: + hsizer.Hide(vsizer, recursive=True) + + + # labeled_frame = tk.LabelFrame(tk_row_frame, text=element.Title, relief=element.Relief) + # PackFormIntoFrame(element, labeled_frame, toplevel_form) + # labeled_frame.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) + # if element.BackgroundColor != COLOR_SYSTEM_DEFAULT and element.BackgroundColor is not None: + # labeled_frame.configure(background=element.BackgroundColor, + # highlightbackground=element.BackgroundColor, + # highlightcolor=element.BackgroundColor) + # if element.TextColor != COLOR_SYSTEM_DEFAULT and element.TextColor is not None: + # labeled_frame.configure(foreground=element.TextColor) + # if font is not None: + # labeled_frame.configure(font=font) + # if element.TitleLocation is not None: + # labeled_frame.configure(labelanchor=element.TitleLocation) + # if element.BorderWidth is not None: + # labeled_frame.configure(borderwidth=element.BorderWidth) + # if element.Tooltip is not None: + # element.TooltipObject = ToolTip(labeled_frame, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) + # ------------------------- Tab element ------------------------- # + elif element_type == ELEM_TYPE_TAB: + pass + # element.TKFrame = tk.Frame(form.TKNotebook) + # PackFormIntoFrame(element, element.TKFrame, toplevel_form) + # if element.Disabled: + # form.TKNotebook.add(element.TKFrame, text=element.Title, state='disabled') + # else: + # form.TKNotebook.add(element.TKFrame, text=element.Title) + # form.TKNotebook.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) + # element.ParentNotebook = form.TKNotebook + # element.TabID = form.TabCount + # form.TabCount += 1 + # if element.BackgroundColor != COLOR_SYSTEM_DEFAULT and element.BackgroundColor is not None: + # element.TKFrame.configure(background=element.BackgroundColor, + # highlightbackground=element.BackgroundColor, + # highlightcolor=element.BackgroundColor) + # # if element.TextColor != COLOR_SYSTEM_DEFAULT and element.TextColor is not None: + # # element.TKFrame.configure(foreground=element.TextColor) + # + # # ttk.Style().configure("TNotebook", background='red') + # # ttk.Style().map("TNotebook.Tab", background=[("selected", 'orange')], + # # foreground=[("selected", 'green')]) + # # ttk.Style().configure("TNotebook.Tab", background='blue', foreground='yellow') + # + # if element.BorderWidth is not None: + # element.TKFrame.configure(borderwidth=element.BorderWidth) + # if element.Tooltip is not None: + # element.TooltipObject = ToolTip(element.TKFrame, text=element.Tooltip, + # timeout=DEFAULT_TOOLTIP_TIME) + # ------------------------- TabGroup element ------------------------- # + elif element_type == ELEM_TYPE_TAB_GROUP: + pass + + # custom_style = str(element.Key) + 'customtab.TNotebook' + # style = ttk.Style(tk_row_frame) + # if element.Theme is not None: + # style.theme_use(element.Theme) + # if element.TabLocation is not None: + # position_dict = {'left': 'w', 'right': 'e', 'top': 'n', 'bottom': 's', 'lefttop': 'wn', + # 'leftbottom': 'ws', 'righttop': 'en', 'rightbottom': 'es', 'bottomleft': 'sw', + # 'bottomright': 'se', 'topleft': 'nw', 'topright': 'ne'} + # try: + # tab_position = position_dict[element.TabLocation] + # except: + # tab_position = position_dict['top'] + # style.configure(custom_style, tabposition=tab_position) + # + # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + # style.configure(custom_style, background=element.BackgroundColor, foreground='purple') + # + # # style.theme_create("yummy", parent="alt", settings={ + # # "TNotebook": {"configure": {"tabmargins": [2, 5, 2, 0]}}, + # # "TNotebook.Tab": { + # # "configure": {"padding": [5, 1], "background": mygreen}, + # # "map": {"background": [("selected", myred)], + # # "expand": [("selected", [1, 1, 1, 0])]}}}) + # + # # style.configure(custom_style+'.Tab', background='red') + # if element.SelectedTitleColor != None: + # style.map(custom_style + '.Tab', foreground=[("selected", element.SelectedTitleColor)]) + # if element.TextColor is not None and element.TextColor != COLOR_SYSTEM_DEFAULT: + # style.configure(custom_style + '.Tab', foreground=element.TextColor) + # # style.configure(custom_style, background='blue', foreground='yellow') + # + # element.TKNotebook = ttk.Notebook(tk_row_frame, style=custom_style) + # + # PackFormIntoFrame(element, toplevel_form.TKroot, toplevel_form) + # + # if element.ChangeSubmits: + # element.TKNotebook.bind('<>', element.TabGroupSelectHandler) + # if element.BorderWidth is not None: + # element.TKNotebook.configure(borderwidth=element.BorderWidth) + # if element.Tooltip is not None: + # element.TooltipObject = ToolTip(element.TKNotebook, text=element.Tooltip, + # timeout=DEFAULT_TOOLTIP_TIME) + # ------------------------- SLIDER Box element ------------------------- # + elif element_type == ELEM_TYPE_INPUT_SLIDER: + pass + # slider_length = element_size[0] * CharWidthInPixels() + # slider_width = element_size[1] + # element.TKIntVar = tk.IntVar() + # element.TKIntVar.set(element.DefaultValue) + # if element.Orientation[0] == 'v': + # range_from = element.Range[1] + # range_to = element.Range[0] + # slider_length += DEFAULT_MARGINS[1] * (element_size[0] * 2) # add in the padding + # else: + # range_from = element.Range[0] + # range_to = element.Range[1] + # if element.ChangeSubmits: + # tkscale = tk.Scale(tk_row_frame, orient=element.Orientation, variable=element.TKIntVar, + # from_=range_from, to_=range_to, resolution=element.Resolution, + # length=slider_length, width=slider_width, bd=element.BorderWidth, + # relief=element.Relief, font=font, tickinterval=element.TickInterval, + # command=element.SliderChangedHandler) + # else: + # tkscale = tk.Scale(tk_row_frame, orient=element.Orientation, variable=element.TKIntVar, + # from_=range_from, to_=range_to, resolution=element.Resolution, + # length=slider_length, width=slider_width, bd=element.BorderWidth, + # relief=element.Relief, font=font, tickinterval=element.TickInterval) + # tkscale.config(highlightthickness=0) + # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + # tkscale.configure(background=element.BackgroundColor) + # if DEFAULT_SCROLLBAR_COLOR != COLOR_SYSTEM_DEFAULT: + # tkscale.config(troughcolor=DEFAULT_SCROLLBAR_COLOR) + # if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT: + # tkscale.configure(fg=text_color) + # tkscale.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) + # element.TKScale = tkscale + # if element.Disabled == True: + # element.TKScale['state'] = 'disabled' + # if element.Tooltip is not None: + # element.TooltipObject = ToolTip(element.TKScale, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) + # ------------------------- TABLE element ------------------------- # + elif element_type == ELEM_TYPE_TABLE: + pass + # frame = tk.Frame(tk_row_frame) + # + # height = element.NumRows + # if element.Justification == 'left': + # anchor = tk.W + # elif element.Justification == 'right': + # anchor = tk.E + # else: + # anchor = tk.CENTER + # column_widths = {} + # for row in element.Values: + # for i, col in enumerate(row): + # col_width = min(len(str(col)), element.MaxColumnWidth) + # try: + # if col_width > column_widths[i]: + # column_widths[i] = col_width + # except: + # column_widths[i] = col_width + # if element.ColumnsToDisplay is None: + # displaycolumns = element.ColumnHeadings + # else: + # displaycolumns = [] + # for i, should_display in enumerate(element.ColumnsToDisplay): + # if should_display: + # displaycolumns.append(element.ColumnHeadings[i]) + # column_headings = element.ColumnHeadings + # if element.DisplayRowNumbers: # if display row number, tack on the numbers to front of columns + # displaycolumns = [element.RowHeaderText, ] + displaycolumns + # column_headings = [element.RowHeaderText, ] + element.ColumnHeadings + # element.TKTreeview = ttk.Treeview(frame, columns=column_headings, + # displaycolumns=displaycolumns, show='headings', height=height, + # selectmode=element.SelectMode) + # treeview = element.TKTreeview + # if element.DisplayRowNumbers: + # treeview.heading(element.RowHeaderText, text=element.RowHeaderText) # make a dummy heading + # treeview.column(element.RowHeaderText, width=50, anchor=anchor) + # for i, heading in enumerate(element.ColumnHeadings): + # treeview.heading(heading, text=heading) + # if element.AutoSizeColumns: + # width = max(column_widths[i], len(heading)) + # else: + # try: + # width = element.ColumnWidths[i] + # except: + # width = element.DefaultColumnWidth + # + # treeview.column(heading, width=width * CharWidthInPixels(), anchor=anchor) + # # Insert values into the tree + # for i, value in enumerate(element.Values): + # if element.DisplayRowNumbers: + # value = [i + element.StartingRowNumber] + value + # id = treeview.insert('', 'end', text=value, iid=i + 1, values=value, tag=i % 2) + # if element.AlternatingRowColor is not None: + # treeview.tag_configure(1, background=element.AlternatingRowColor) + # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + # ttk.Style().configure("Treeview", background=element.BackgroundColor, + # fieldbackground=element.BackgroundColor) + # if element.TextColor is not None and element.TextColor != COLOR_SYSTEM_DEFAULT: + # ttk.Style().configure("Treeview", foreground=element.TextColor) + # # scrollable_frame.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1], expand=True, fill='both') + # treeview.bind("<>", element.treeview_selected) + # if element.BindReturnKey: + # treeview.bind('', element.treeview_double_click) + # treeview.bind('', element.treeview_double_click) + # scrollbar = tk.Scrollbar(frame) + # scrollbar.pack(side=tk.RIGHT, fill='y') + # scrollbar.config(command=treeview.yview) + # treeview.configure(yscrollcommand=scrollbar.set) + # + # element.TKTreeview.pack(side=tk.LEFT, expand=True, padx=0, pady=0, fill='both') + # frame.pack(side=tk.LEFT, expand=True, padx=0, pady=0) + # if element.Tooltip is not None: + # element.TooltipObject = ToolTip(element.TKTreeview, text=element.Tooltip, + # timeout=DEFAULT_TOOLTIP_TIME) + # ------------------------- Tree element ------------------------- # + elif element_type == ELEM_TYPE_TREE: + pass + # frame = tk.Frame(tk_row_frame) + # + # height = element.NumRows + # if element.Justification == 'left': # justification + # anchor = tk.W + # elif element.Justification == 'right': + # anchor = tk.E + # else: + # anchor = tk.CENTER + # + # if element.ColumnsToDisplay is None: # Which cols to display + # displaycolumns = element.ColumnHeadings + # else: + # displaycolumns = [] + # for i, should_display in enumerate(element.ColumnsToDisplay): + # if should_display: + # displaycolumns.append(element.ColumnHeadings[i]) + # column_headings = element.ColumnHeadings + # # ------------- GET THE TREEVIEW WIDGET ------------- + # element.TKTreeview = ttk.Treeview(frame, columns=column_headings, + # displaycolumns=displaycolumns, show='tree headings', height=height, + # selectmode=element.SelectMode, ) + # treeview = element.TKTreeview + # for i, heading in enumerate(element.ColumnHeadings): # Configure cols + headings + # treeview.heading(heading, text=heading) + # if element.AutoSizeColumns: + # width = min(element.MaxColumnWidth, len(heading) + 1) + # else: + # try: + # width = element.ColumnWidths[i] + # except: + # width = element.DefaultColumnWidth + # treeview.column(heading, width=width * CharWidthInPixels(), anchor=anchor) + # + # def add_treeview_data(node): + # # print(f'Inserting {node.key} under parent {node.parent}') + # if node.key != '': + # treeview.insert(node.parent, 'end', node.key, text=node.text, values=node.values, + # open=element.ShowExpanded) + # for node in node.children: + # add_treeview_data(node) + # + # add_treeview_data(element.TreeData.root_node) + # treeview.column('#0', width=element.Col0Width * CharWidthInPixels(), anchor=anchor) + # # ----- configure colors ----- + # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: + # ttk.Style().configure("Treeview", background=element.BackgroundColor, + # fieldbackground=element.BackgroundColor) + # if element.TextColor is not None and element.TextColor != COLOR_SYSTEM_DEFAULT: + # ttk.Style().configure("Treeview", foreground=element.TextColor) + # + # scrollbar = tk.Scrollbar(frame) + # scrollbar.pack(side=tk.RIGHT, fill='y') + # scrollbar.config(command=treeview.yview) + # treeview.configure(yscrollcommand=scrollbar.set) + # element.TKTreeview.pack(side=tk.LEFT, expand=True, padx=0, pady=0, fill='both') + # frame.pack(side=tk.LEFT, expand=True, padx=0, pady=0) + # treeview.bind("<>", element.treeview_selected) + # if element.Tooltip is not None: # tooltip + # element.TooltipObject = ToolTip(element.TKTreeview, text=element.Tooltip, + # timeout=DEFAULT_TOOLTIP_TIME) + # ------------------------- Separator element ------------------------- # + elif element_type == ELEM_TYPE_SEPARATOR: + element = element # type: VerticalSeparator + if element.Orientation.lower().startswith('v'): + element.WxStaticLine = static_line = wx.StaticLine(toplevel_form.MasterPanel, style=wx.LI_VERTICAL) + else: + element.WxStaticLine = static_line = wx.StaticLine(toplevel_form.MasterPanel, style=wx.LI_HORIZONTAL) + + do_font_and_color(element.WxStaticLine) + + sizer = pad_widget(static_line) + + hsizer.Add(sizer, 0) + + #.................DONE WITH ROW pack the row of widgets ..................# + + # Add the row to the layout. Justify the row depending on the settings for its container + if container_elem.ElementJustification.startswith('c'): + containing_frame.Add(hsizer, 0,wx.ALIGN_CENTER, border=0) + elif container_elem.ElementJustification.startswith('r'): + containing_frame.Add(hsizer,0, wx.ALIGN_RIGHT, border=0) + else: + containing_frame.Add(hsizer, 0, wx.TOP|wx.BOTTOM, border=0) + + + return + + +# ----====----====----====----====----==== STARTUP TK ====----====----====----====----====----# +def StartupTK(window:Window): + + ow = Window.NumOpenWindows + if Window.highest_level_app is None: + app = Window.highest_level_app = wx.App(False) + else: + app = Window.highest_level_app + Window.IncrementOpenCount() + + # -------- grab anywhere -------- + if window.GrabAnywhere: + frame = DragFrame(title=window.Title) + else: + frame = wx.Frame(None, title=window.Title) + + panel = wx.Panel(frame, -1, style=wx.TRANSPARENT_WINDOW) + # panel.SetTransparent(.5) + if window.GrabAnywhere: + panel.Bind(wx.EVT_MOTION, frame.on_mouse) + + window.App = app + window.MasterFrame = frame + window.MasterPanel = panel + window.MasterFrame.panel = panel + frame.Bind(wx.EVT_CLOSE, window.OnClose) + + # ----------------------------- Icon ----------------------------- + if window.WindowIcon: + if type(window.WindowIcon) is bytes: + icon = PyEmbeddedImage(window.WindowIcon).GetIcon() + else: + if os.path.exists(window.WindowIcon): + icon = wx.Icon(window.WindowIcon, wx.BITMAP_TYPE_ANY) + else: + icon = PyEmbeddedImage(DEFAULT_BASE64_ICON).GetIcon() + if icon: + frame.SetIcon(icon) + + # ----------------------------- Background ----------------------------- + if window.BackgroundColor is not None and window.BackgroundColor != COLOR_SYSTEM_DEFAULT: + panel.SetBackgroundColour(window.BackgroundColor) + + if window.BackgroundImage: + if type(window.BackgroundImage) is bytes: + pic = PyEmbeddedImage(window.BackgroundImage).GetBitmap() + else: + if os.path.exists(window.BackgroundImage): + pic = wx.Image(window.BackgroundImage, wx.BITMAP_TYPE_ANY).ConvertToBitmap() + else: + pic = PyEmbeddedImage(DEFAULT_BASE64_ICON).GetBitmap() + window.bitmap1 = wx.StaticBitmap(window.MasterPanel, -1, pic, (0, 0)) + + + + InitializeResults(window) + + # ----------------------------- ----------------------------- + # ----------------------------- ----------------------------- + # ----------------------------- handle settings using Style Flags ----------------------------- + style = 0 + if window.NoTitleBar: + style |= wx.BORDER_NONE + else: + style |= wx.BORDER_DEFAULT + if window.KeepOnTop: + style |= wx.STAY_ON_TOP + if style: + window.MasterFrame.SetWindowStyleFlag(style) + + if window.ReturnKeyboardEvents: + # style |= wx.WANTS_CHARS + window.App.Bind(wx.EVT_CHAR_HOOK, window.callback_keyboard_char) + window.App.Bind(wx.EVT_MOUSEWHEEL, window.callback_keyboard_char) + + # ----------------------------- Sizer creation and PACK FORM ----------------------------- + vsizer = wx.BoxSizer(wx.VERTICAL) + + preprocess_radio_elements(window, window) + + # ----------------------------- Do the packing of the elements ----------------------------- + + PackFormIntoFrame(window, vsizer, window) + + # ----------------------------- Sizers to create margins ----------------------------- + outersizer = wx.BoxSizer(wx.VERTICAL) + outersizer.Fit(window.MasterFrame) + outersizer.Add(vsizer, 1, wx.TOP|wx.BOTTOM|wx.EXPAND, border=DEFAULT_MARGINS[1]) + + window.OuterSizer = wx.BoxSizer(wx.VERTICAL) + window.OuterSizer.Fit(window.MasterFrame) + window.OuterSizer.Add(outersizer, 1, wx.LEFT|wx.RIGHT|wx.EXPAND, border=DEFAULT_MARGINS[0]) + + window.MasterPanel.SetSizer(window.OuterSizer) + + window.OuterSizer.Fit(window.MasterFrame) + + # ----------------------------- window location, size and alpha ----------------------------- + if window.Location != (None, None): + window.MasterFrame.Move(window.Location[0], window.Location[1]) + else: + window.MasterFrame.Center(wx.BOTH) + + if window._Size != (None, None): + window.MasterFrame.SetSize(window._Size[0], window._Size[1]) + + if window._AlphaChannel is not None: + window.SetAlpha(window._AlphaChannel) + + # ----------------------------- DISPLAY the window ----------------------------- + window.MasterFrame.Show() + + # ....................................... DONE creating and laying out window ..........................# + if RUN_INSPECTION_TOOL: + wx.lib.inspection.InspectionTool().Show() + window.CurrentlyRunningMainloop = True + + if window.Timeout: + timer = wx.Timer(window.App) + window.App.Bind(wx.EVT_TIMER, window.timer_timeout) + timer.Start(milliseconds=window.Timeout, oneShot=wx.TIMER_ONE_SHOT) + else: + timer = None + + if window.AutoClose: + window.timer = wx.Timer(window.App, id=Window.NumOpenWindows) + window.App.Bind(wx.EVT_TIMER, lambda frame: window.autoclose_timer_callback(window.MasterFrame), id=Window.NumOpenWindows) + window.timer.Start(milliseconds=window.AutoCloseDuration*1000, oneShot=wx.TIMER_ONE_SHOT) + # ------------------------------------ MAINLOOP ------------------------------------ + + + if not window.NonBlocking: + window.App.MainLoop() + else: + window.non_block_timer = wx.Timer(window.App, id=5678) + window.App.Bind(wx.EVT_TIMER, window.non_block_timer_timeout, id=5678) + window.non_block_timer.Start(milliseconds=0, oneShot=wx.TIMER_ONE_SHOT) + window.App.MainLoop() + + if Window.stdout_is_rerouted: + sys.stdout = Window.stdout_location + window.CurrentlyRunningMainloop = False + if timer: + timer.Stop() + + # if not window.FormRemainedOpen: + # _my_windows.Decrement() + # if window.RootNeedsDestroying: + # window.TKroot.destroy() + # window.RootNeedsDestroying = False + return + + +# ==============================_GetNumLinesNeeded ==# +# Helper function for determining how to wrap text # +# ===================================================# +def _GetNumLinesNeeded(text, max_line_width): + if max_line_width == 0: + return 1 + lines = text.split('\n') + num_lines = len(lines) # number of original lines of text + max_line_len = max([len(l) for l in lines]) # longest line + lines_used = [] + for L in lines: + lines_used.append(len(L) // max_line_width + (len(L) % max_line_width > 0)) # fancy math to round up + total_lines_needed = sum(lines_used) + return total_lines_needed + + +# ============================== PROGRESS METER ========================================== # + +def ConvertArgsToSingleString(*args): + max_line_total, width_used, total_lines, = 0, 0, 0 + single_line_message = '' + # loop through args and built a SINGLE string from them + for message in args: + # fancy code to check if string and convert if not is not need. Just always convert to string :-) + # if not isinstance(message, str): message = str(message) + message = str(message) + longest_line_len = max([len(l) for l in message.split('\n')]) + width_used = max(longest_line_len, width_used) + max_line_total = max(max_line_total, width_used) + lines_needed = _GetNumLinesNeeded(message, width_used) + total_lines += lines_needed + single_line_message += message + '\n' + return single_line_message, width_used, total_lines + + +METER_REASON_CANCELLED = 'cancelled' +METER_REASON_CLOSED = 'closed' +METER_REASON_REACHED_MAX = 'finished' +METER_OK = True +METER_STOPPED = False + +class QuickMeter(object): + active_meters = {} + exit_reasons = {} + + def __init__(self, title, current_value, max_value, key, *args, orientation='v', bar_color=(None, None), + button_color=(None, None), size=DEFAULT_PROGRESS_BAR_SIZE, border_width=None, grab_anywhere=False): + self.start_time = datetime.datetime.utcnow() + self.key = key + self.orientation = orientation + self.bar_color = bar_color + self.size = size + self.grab_anywhere = grab_anywhere + self.button_color = button_color + self.border_width = border_width + self.title = title + self.current_value = current_value + self.max_value = max_value + self.close_reason = None + self.window = self.BuildWindow(*args) + + def BuildWindow(self, *args): + layout = [] + if self.orientation.lower().startswith('h'): + col = [] + col += [[T(''.join(map(lambda x: str(x)+'\n',args)),key='_OPTMSG_')]] ### convert all *args into one string that can be updated + col += [[T('', size=(25,8), key='_STATS_')], + [ProgressBar(max_value=self.max_value, orientation='h', key='_PROG_', size=self.size)], + [Cancel(button_color=self.button_color), Stretch()]] + layout = [Column(col)] + else: + col = [[ProgressBar(max_value=self.max_value, orientation='v', key='_PROG_', size=self.size)]] + col2 = [] + col2 += [[T(''.join(map(lambda x: str(x)+'\n',args)),key='_OPTMSG_')]] ### convert all *args into one string that can be updated + col2 += [[T('', size=(25,8), key='_STATS_')], + [Cancel(button_color=self.button_color), Stretch()]] + layout = [Column(col), Column(col2)] + self.window = Window(self.title, grab_anywhere=self.grab_anywhere, border_depth=self.border_width) + self.window.Layout([layout]).Finalize() + + return self.window + + def UpdateMeter(self, current_value, max_value, *args): + self.current_value = current_value + self.max_value = max_value + self.window.Element('_PROG_').UpdateBar(self.current_value, self.max_value) + self.window.Element('_STATS_').Update('\n'.join(self.ComputeProgressStats())) + self.window.Element('_OPTMSG_').Update(value=''.join(map(lambda x: str(x)+'\n',args))) ### update the string with the args + event, values = self.window.Read(timeout=0) + if event in('Cancel', None) or current_value >= max_value: + self.window.Close() + del(QuickMeter.active_meters[self.key]) + QuickMeter.exit_reasons[self.key] = METER_REASON_CANCELLED if event == 'Cancel' else METER_REASON_CLOSED if event is None else METER_REASON_REACHED_MAX + return QuickMeter.exit_reasons[self.key] + return METER_OK + + + def ComputeProgressStats(self): + utc = datetime.datetime.utcnow() + time_delta = utc - self.start_time + total_seconds = time_delta.total_seconds() + if not total_seconds: + total_seconds = 1 + try: + time_per_item = total_seconds / self.current_value + except: + time_per_item = 1 + seconds_remaining = (self.max_value - self.current_value) * time_per_item + time_remaining = str(datetime.timedelta(seconds=seconds_remaining)) + time_remaining_short = (time_remaining).split(".")[0] + time_delta_short = str(time_delta).split(".")[0] + total_time = time_delta + datetime.timedelta(seconds=seconds_remaining) + total_time_short = str(total_time).split(".")[0] + self.stat_messages = [ + '{} of {}'.format(self.current_value, self.max_value), + '{} %'.format(100 * self.current_value // self.max_value), + '', + ' {:6.2f} Iterations per Second'.format(self.current_value / total_seconds), + ' {:6.2f} Seconds per Iteration'.format(total_seconds / (self.current_value if self.current_value else 1)), + '', + '{} Elapsed Time'.format(time_delta_short), + '{} Time Remaining'.format(time_remaining_short), + '{} Estimated Total Time'.format(total_time_short)] + return self.stat_messages + + +def OneLineProgressMeter(title, current_value, max_value, key='OK for 1 meter', *args, orientation='v', bar_color=(None, None), + button_color=None, size=DEFAULT_PROGRESS_BAR_SIZE, border_width=None, grab_anywhere=False): + if key not in QuickMeter.active_meters: + meter = QuickMeter(title, current_value, max_value, key, *args, orientation=orientation, bar_color=bar_color, + button_color=button_color, size=size, border_width=border_width, grab_anywhere=grab_anywhere) + QuickMeter.active_meters[key] = meter + else: + meter = QuickMeter.active_meters[key] + + rc = meter.UpdateMeter(current_value, max_value, *args) + OneLineProgressMeter.exit_reasons = getattr(OneLineProgressMeter,'exit_reasons', QuickMeter.exit_reasons) + return rc == METER_OK + +def OneLineProgressMeterCancel(key='OK for 1 meter'): + try: + meter = QuickMeter.active_meters[key] + meter.window.Close() + del(QuickMeter.active_meters[key]) + QuickMeter.exit_reasons[key] = METER_REASON_CANCELLED + except: # meter is already deleted + return + + + +# input is #RRGGBB +# output is #RRGGBB +def GetComplimentaryHex(color): + # strip the # from the beginning + color = color[1:] + # convert the string into hex + color = int(color, 16) + # invert the three bytes + # as good as substracting each of RGB component by 255(FF) + comp_color = 0xFFFFFF ^ color + # convert the color back to hex by prefixing a # + comp_color = "#%06X" % comp_color + return comp_color + + +# ======================== EasyPrint =====# +# ===================================================# + +class DebugWin(): + debug_window = None + + def __init__(self, size=(None, None), location=(None, None), font=None, no_titlebar=False, no_button=False, + grab_anywhere=False, keep_on_top=False, title=None, do_not_reroute_stdout=False): + # Show a form that's a running counter + self.size = size + self.location = location + self.font = font + self.no_titlebar = no_titlebar + self.no_button = no_button + self.grab_anywhere = grab_anywhere + self.keep_on_top = keep_on_top + self.do_not_reroute_stdout = do_not_reroute_stdout + + win_size = size if size != (None, None) else DEFAULT_DEBUG_WINDOW_SIZE + self.window = Window(title=title or 'Debug Window', no_titlebar=no_titlebar, auto_size_text=True, location=location, + font=font or ('Courier New', 10), grab_anywhere=grab_anywhere, keep_on_top=keep_on_top) + self.output_element = MultilineOutput(size=win_size, key='_MULTILINE_') if do_not_reroute_stdout else Output(size=win_size) + + if no_button: + self.layout = [[self.output_element]] + else: + self.layout = [ + [self.output_element], + [DummyButton('Quit'), Stretch()] + ] + self.window.AddRows(self.layout) + self.window.Read(timeout=0) # Show a non-blocking form, returns immediately + Window.active_popups[self.window] = 'debug window' + return + + def Print(self, *args, end=None, sep=None): + sepchar = sep if sep is not None else ' ' + endchar = end if end is not None else '\n' + + if self.window is None: # if window was destroyed already, just print + self.__init__(size=self.size, location=self.location, font=self.font, no_titlebar=self.no_titlebar, no_button=self.no_button, grab_anywhere=self.grab_anywhere, keep_on_top=self.keep_on_top, do_not_reroute_stdout=self.do_not_reroute_stdout) + event, values = self.window.Read(timeout=0) + if event == 'Quit' or event is None: + self.Close() + self.__init__(size=self.size, location=self.location, font=self.font, no_titlebar=self.no_titlebar, no_button=self.no_button, grab_anywhere=self.grab_anywhere, keep_on_top=self.keep_on_top, do_not_reroute_stdout=self.do_not_reroute_stdout) + if self.do_not_reroute_stdout: + outstring = '' + for arg in args: + outstring += str(arg) + sepchar + outstring += endchar + self.output_element.Update(outstring, append=True) + else: + print(*args, sep=sepchar, end=endchar) + + + def Close(self): + self.window.Close() + self.window = None + + +def PrintClose(): + EasyPrintClose() + + +def EasyPrint(*args, size=(None, None), end=None, sep=None, location=(None, None), font=None, no_titlebar=False, + no_button=False, grab_anywhere=False, keep_on_top=False, do_not_reroute_stdout=True): + + + if DebugWin.debug_window is None: + DebugWin.debug_window = DebugWin(size=size, location=location, font=font, no_titlebar=no_titlebar, + no_button=no_button, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, do_not_reroute_stdout=do_not_reroute_stdout) + DebugWin.debug_window.Print(*args, end=end, sep=sep) + + +Print = EasyPrint +eprint = EasyPrint + + +def EasyPrintClose(): + if DebugWin.debug_window is not None: + DebugWin.debug_window.Close() + DebugWin.debug_window = None + + +# ======================== Scrolled Text Box =====# +# ===================================================# +def PopupScrolled(*args, button_color=None, yes_no=False, auto_close=False, auto_close_duration=None, + size=(None, None)): + if not args: return + width, height = size + width = width if width else MESSAGE_BOX_LINE_WIDTH + form = Window(args[0], auto_size_text=True, button_color=button_color, auto_close=auto_close, + auto_close_duration=auto_close_duration) + max_line_total, max_line_width, total_lines, height_computed = 0, 0, 0, 0 + complete_output = '' + for message in args: + # fancy code to check if string and convert if not is not need. Just always convert to string :-) + # if not isinstance(message, str): message = str(message) + message = str(message) + longest_line_len = max([len(l) for l in message.split('\n')]) + width_used = min(longest_line_len, width) + max_line_total = max(max_line_total, width_used) + max_line_width = width + lines_needed = _GetNumLinesNeeded(message, width_used) + height_computed += lines_needed + complete_output += message + '\n' + total_lines += lines_needed + height_computed = MAX_SCROLLED_TEXT_BOX_HEIGHT if height_computed > MAX_SCROLLED_TEXT_BOX_HEIGHT else height_computed + if height: + height_computed = height + form.AddRow(Multiline(complete_output, size=(max_line_width, height_computed))) + pad = max_line_total - 15 if max_line_total > 15 else 1 + # show either an OK or Yes/No depending on paramater + if yes_no: + form.AddRow(Text('', size=(pad, 1), auto_size_text=False), Yes(), No()) + button, values = form.Read() + return button + else: + form.AddRow(Text('', size=(pad, 1), auto_size_text=False), Button('OK', size=(5, 1), button_color=button_color)) + button, values = form.Read() + return button + + +ScrolledTextBox = PopupScrolled + + +# ============================== SetGlobalIcon ======# +# Sets the icon to be used by default # +# ===================================================# +def SetGlobalIcon(icon): + if icon is not None: + Window.user_defined_icon = icon + return True + + +# ============================== SetOptions =========# +# Sets the icon to be used by default # +# ===================================================# +def SetOptions(icon=None, button_color=None, element_size=(None, None), button_element_size=(None, None), + margins=(None, None), + element_padding=(None, None), auto_size_text=None, auto_size_buttons=None, font=None, border_width=None, + slider_border_width=None, slider_relief=None, slider_orientation=None, + autoclose_time=None, message_box_line_width=None, + progress_meter_border_depth=None, progress_meter_style=None, + progress_meter_relief=None, progress_meter_color=None, progress_meter_size=None, + text_justification=None, background_color=None, element_background_color=None, + text_element_background_color=None, input_elements_background_color=None, input_text_color=None, + scrollbar_color=None, text_color=None, element_text_color=None, debug_win_size=(None, None), + window_location=(None, None), + tooltip_time=None): + global DEFAULT_ELEMENT_SIZE + global DEFAULT_BUTTON_ELEMENT_SIZE + global DEFAULT_MARGINS # Margins for each LEFT/RIGHT margin is first term + global DEFAULT_ELEMENT_PADDING # Padding between elements (row, col) in pixels + global DEFAULT_AUTOSIZE_TEXT + global DEFAULT_AUTOSIZE_BUTTONS + global DEFAULT_FONT + global DEFAULT_BORDER_WIDTH + global DEFAULT_AUTOCLOSE_TIME + global DEFAULT_BUTTON_COLOR + global MESSAGE_BOX_LINE_WIDTH + global DEFAULT_PROGRESS_BAR_BORDER_WIDTH + global DEFAULT_PROGRESS_BAR_STYLE + global DEFAULT_PROGRESS_BAR_RELIEF + global DEFAULT_PROGRESS_BAR_COLOR + global DEFAULT_PROGRESS_BAR_SIZE + global DEFAULT_TEXT_JUSTIFICATION + global DEFAULT_DEBUG_WINDOW_SIZE + global DEFAULT_SLIDER_BORDER_WIDTH + global DEFAULT_SLIDER_RELIEF + global DEFAULT_SLIDER_ORIENTATION + global DEFAULT_BACKGROUND_COLOR + global DEFAULT_INPUT_ELEMENTS_COLOR + global DEFAULT_ELEMENT_BACKGROUND_COLOR + global DEFAULT_TEXT_ELEMENT_BACKGROUND_COLOR + global DEFAULT_SCROLLBAR_COLOR + global DEFAULT_TEXT_COLOR + global DEFAULT_WINDOW_LOCATION + global DEFAULT_ELEMENT_TEXT_COLOR + global DEFAULT_INPUT_TEXT_COLOR + global DEFAULT_TOOLTIP_TIME + + if icon is not None: + Window.user_defined_icon = icon + + if button_color != None: + DEFAULT_BUTTON_COLOR = button_color + + if element_size != (None, None): + DEFAULT_ELEMENT_SIZE = element_size + + if button_element_size != (None, None): + DEFAULT_BUTTON_ELEMENT_SIZE = button_element_size + + if margins != (None, None): + DEFAULT_MARGINS = margins + + if element_padding != (None, None): + DEFAULT_ELEMENT_PADDING = element_padding + + if auto_size_text != None: + DEFAULT_AUTOSIZE_TEXT = auto_size_text + + if auto_size_buttons != None: + DEFAULT_AUTOSIZE_BUTTONS = auto_size_buttons + + if font != None: + DEFAULT_FONT = font + + if border_width != None: + DEFAULT_BORDER_WIDTH = border_width + + if autoclose_time != None: + DEFAULT_AUTOCLOSE_TIME = autoclose_time + + if message_box_line_width != None: + MESSAGE_BOX_LINE_WIDTH = message_box_line_width + + if progress_meter_border_depth != None: + DEFAULT_PROGRESS_BAR_BORDER_WIDTH = progress_meter_border_depth + + if progress_meter_style != None: + DEFAULT_PROGRESS_BAR_STYLE = progress_meter_style + + if progress_meter_relief != None: + DEFAULT_PROGRESS_BAR_RELIEF = progress_meter_relief + + if progress_meter_color != None: + DEFAULT_PROGRESS_BAR_COLOR = progress_meter_color + + if progress_meter_size != None: + DEFAULT_PROGRESS_BAR_SIZE = progress_meter_size + + if slider_border_width != None: + DEFAULT_SLIDER_BORDER_WIDTH = slider_border_width + + if slider_orientation != None: + DEFAULT_SLIDER_ORIENTATION = slider_orientation + + if slider_relief != None: + DEFAULT_SLIDER_RELIEF = slider_relief + + if text_justification != None: + DEFAULT_TEXT_JUSTIFICATION = text_justification + + if background_color != None: + DEFAULT_BACKGROUND_COLOR = background_color + + if text_element_background_color != None: + DEFAULT_TEXT_ELEMENT_BACKGROUND_COLOR = text_element_background_color + + if input_elements_background_color != None: + DEFAULT_INPUT_ELEMENTS_COLOR = input_elements_background_color + + if element_background_color != None: + DEFAULT_ELEMENT_BACKGROUND_COLOR = element_background_color + + if window_location != (None, None): + DEFAULT_WINDOW_LOCATION = window_location + + if debug_win_size != (None, None): + DEFAULT_DEBUG_WINDOW_SIZE = debug_win_size + + if text_color != None: + DEFAULT_TEXT_COLOR = text_color + + if scrollbar_color != None: + DEFAULT_SCROLLBAR_COLOR = scrollbar_color + + if element_text_color != None: + DEFAULT_ELEMENT_TEXT_COLOR = element_text_color + + if input_text_color is not None: + DEFAULT_INPUT_TEXT_COLOR = input_text_color + + if tooltip_time is not None: + DEFAULT_TOOLTIP_TIME = tooltip_time + + return True + + +# ----------------------------------------------------------------- # + +# .########.##.....##.########.##.....##.########..######. +# ....##....##.....##.##.......###...###.##.......##....## +# ....##....##.....##.##.......####.####.##.......##...... +# ....##....#########.######...##.###.##.######....######. +# ....##....##.....##.##.......##.....##.##.............## +# ....##....##.....##.##.......##.....##.##.......##....## +# ....##....##.....##.########.##.....##.########..######. + +# ----------------------------------------------------------------- # + +# The official Theme code + +#################### ChangeLookAndFeel ####################### +# Predefined settings that will change the colors and styles # +# of the elements. # +############################################################## +LOOK_AND_FEEL_TABLE = {'SystemDefault': + {'BACKGROUND': COLOR_SYSTEM_DEFAULT, + 'TEXT': COLOR_SYSTEM_DEFAULT, + 'INPUT': COLOR_SYSTEM_DEFAULT, + 'TEXT_INPUT': COLOR_SYSTEM_DEFAULT, + 'SCROLL': COLOR_SYSTEM_DEFAULT, + 'BUTTON': OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR, + 'PROGRESS': COLOR_SYSTEM_DEFAULT, + 'BORDER': 1, 'SLIDER_DEPTH': 1, + 'PROGRESS_DEPTH': 0}, + + 'SystemDefaultForReal': + {'BACKGROUND': COLOR_SYSTEM_DEFAULT, + 'TEXT': COLOR_SYSTEM_DEFAULT, + 'INPUT': COLOR_SYSTEM_DEFAULT, + 'TEXT_INPUT': COLOR_SYSTEM_DEFAULT, + 'SCROLL': COLOR_SYSTEM_DEFAULT, + 'BUTTON': COLOR_SYSTEM_DEFAULT, + 'PROGRESS': COLOR_SYSTEM_DEFAULT, + 'BORDER': 1, 'SLIDER_DEPTH': 1, + 'PROGRESS_DEPTH': 0}, + + 'SystemDefault1': + {'BACKGROUND': COLOR_SYSTEM_DEFAULT, + 'TEXT': COLOR_SYSTEM_DEFAULT, + 'INPUT': COLOR_SYSTEM_DEFAULT, + 'TEXT_INPUT': COLOR_SYSTEM_DEFAULT, + 'SCROLL': COLOR_SYSTEM_DEFAULT, + 'BUTTON': COLOR_SYSTEM_DEFAULT, + 'PROGRESS': COLOR_SYSTEM_DEFAULT, + 'BORDER': 1, 'SLIDER_DEPTH': 1, + 'PROGRESS_DEPTH': 0}, + + 'Material1': {'BACKGROUND': '#E3F2FD', + 'TEXT': '#000000', + 'INPUT': '#86A8FF', + 'TEXT_INPUT': '#000000', + 'SCROLL': '#86A8FF', + 'BUTTON': ('#FFFFFF', '#5079D3'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 0, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'ACCENT1': '#FF0266', + 'ACCENT2': '#FF5C93', + 'ACCENT3': '#C5003C'}, + + 'Material2': {'BACKGROUND': '#FAFAFA', + 'TEXT': '#000000', + 'INPUT': '#004EA1', + 'TEXT_INPUT': '#FFFFFF', + 'SCROLL': '#5EA7FF', + 'BUTTON': ('#FFFFFF', '#0079D3'), # based on Reddit color + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 0, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'ACCENT1': '#FF0266', + 'ACCENT2': '#FF5C93', + 'ACCENT3': '#C5003C'}, + + 'Reddit': {'BACKGROUND': '#ffffff', + 'TEXT': '#1a1a1b', + 'INPUT': '#dae0e6', + 'TEXT_INPUT': '#222222', + 'SCROLL': '#a5a4a4', + 'BUTTON': ('white', '#0079d3'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'ACCENT1': '#ff5414', + 'ACCENT2': '#33a8ff', + 'ACCENT3': '#dbf0ff'}, + + 'Topanga': {'BACKGROUND': '#282923', + 'TEXT': '#E7DB74', + 'INPUT': '#393a32', + 'TEXT_INPUT': '#E7C855', + 'SCROLL': '#E7C855', + 'BUTTON': ('#E7C855', '#284B5A'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'ACCENT1': '#c15226', + 'ACCENT2': '#7a4d5f', + 'ACCENT3': '#889743'}, + + 'GreenTan': {'BACKGROUND': '#9FB8AD', + 'TEXT': COLOR_SYSTEM_DEFAULT, + 'INPUT': '#F7F3EC', 'TEXT_INPUT': 'black', + 'SCROLL': '#F7F3EC', + 'BUTTON': ('white', '#475841'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'Dark': {'BACKGROUND': '#404040', + 'TEXT': 'white', + 'INPUT': '#4D4D4D', + 'TEXT_INPUT': 'white', + 'SCROLL': '#707070', + 'BUTTON': ('white', '#004F00'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'LightGreen': {'BACKGROUND': '#B7CECE', + 'TEXT': 'black', + 'INPUT': '#FDFFF7', + 'TEXT_INPUT': 'black', + 'SCROLL': '#FDFFF7', + 'BUTTON': ('white', '#658268'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'ACCENT1': '#76506d', + 'ACCENT2': '#5148f1', + 'ACCENT3': '#0a1c84', + 'PROGRESS_DEPTH': 0}, + + 'Dark2': {'BACKGROUND': '#404040', + 'TEXT': 'white', + 'INPUT': 'white', + 'TEXT_INPUT': 'black', + 'SCROLL': '#707070', + 'BUTTON': ('white', '#004F00'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'Black': {'BACKGROUND': 'black', + 'TEXT': 'white', + 'INPUT': '#4D4D4D', + 'TEXT_INPUT': 'white', + 'SCROLL': '#707070', + 'BUTTON': ('black', 'white'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'Tan': {'BACKGROUND': '#fdf6e3', + 'TEXT': '#268bd1', + 'INPUT': '#eee8d5', + 'TEXT_INPUT': '#6c71c3', + 'SCROLL': '#eee8d5', + 'BUTTON': ('white', '#063542'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'TanBlue': {'BACKGROUND': '#e5dece', + 'TEXT': '#063289', + 'INPUT': '#f9f8f4', + 'TEXT_INPUT': '#242834', + 'SCROLL': '#eee8d5', + 'BUTTON': ('white', '#063289'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'DarkTanBlue': {'BACKGROUND': '#242834', + 'TEXT': '#dfe6f8', + 'INPUT': '#97755c', + 'TEXT_INPUT': 'white', + 'SCROLL': '#a9afbb', + 'BUTTON': ('white', '#063289'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'DarkAmber': {'BACKGROUND': '#2c2825', + 'TEXT': '#fdcb52', + 'INPUT': '#705e52', + 'TEXT_INPUT': '#fdcb52', + 'SCROLL': '#705e52', + 'BUTTON': ('black', '#fdcb52'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'DarkBlue': {'BACKGROUND': '#1a2835', + 'TEXT': '#d1ecff', + 'INPUT': '#335267', + 'TEXT_INPUT': '#acc2d0', + 'SCROLL': '#1b6497', + 'BUTTON': ('black', '#fafaf8'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'Reds': {'BACKGROUND': '#280001', + 'TEXT': 'white', + 'INPUT': '#d8d584', + 'TEXT_INPUT': 'black', + 'SCROLL': '#763e00', + 'BUTTON': ('black', '#daad28'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'Green': {'BACKGROUND': '#82a459', + 'TEXT': 'black', + 'INPUT': '#d8d584', + 'TEXT_INPUT': 'black', + 'SCROLL': '#e3ecf3', + 'BUTTON': ('white', '#517239'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'BluePurple': {'BACKGROUND': '#A5CADD', + 'TEXT': '#6E266E', + 'INPUT': '#E0F5FF', + 'TEXT_INPUT': 'black', + 'SCROLL': '#E0F5FF', + 'BUTTON': ('white', '#303952'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'Purple': {'BACKGROUND': '#B0AAC2', + 'TEXT': 'black', + 'INPUT': '#F2EFE8', + 'SCROLL': '#F2EFE8', + 'TEXT_INPUT': 'black', + 'BUTTON': ('black', '#C2D4D8'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'BlueMono': {'BACKGROUND': '#AAB6D3', + 'TEXT': 'black', + 'INPUT': '#F1F4FC', + 'SCROLL': '#F1F4FC', + 'TEXT_INPUT': 'black', + 'BUTTON': ('white', '#7186C7'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'GreenMono': {'BACKGROUND': '#A8C1B4', + 'TEXT': 'black', + 'INPUT': '#DDE0DE', + 'SCROLL': '#E3E3E3', + 'TEXT_INPUT': 'black', + 'BUTTON': ('white', '#6D9F85'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'BrownBlue': {'BACKGROUND': '#64778d', + 'TEXT': 'white', + 'INPUT': '#f0f3f7', + 'SCROLL': '#A6B2BE', + 'TEXT_INPUT': 'black', + 'BUTTON': ('white', '#283b5b'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'BrightColors': {'BACKGROUND': '#b4ffb4', + 'TEXT': 'black', + 'INPUT': '#ffff64', + 'SCROLL': '#ffb482', + 'TEXT_INPUT': 'black', + 'BUTTON': ('black', '#ffa0dc'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'NeutralBlue': {'BACKGROUND': '#92aa9d', + 'TEXT': 'black', + 'INPUT': '#fcfff6', + 'SCROLL': '#fcfff6', + 'TEXT_INPUT': 'black', + 'BUTTON': ('black', '#d0dbbd'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'Kayak': {'BACKGROUND': '#a7ad7f', + 'TEXT': 'black', + 'INPUT': '#e6d3a8', + 'SCROLL': '#e6d3a8', + 'TEXT_INPUT': 'black', + 'BUTTON': ('white', '#5d907d'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'SandyBeach': {'BACKGROUND': '#efeccb', + 'TEXT': '#012f2f', + 'INPUT': '#e6d3a8', + 'SCROLL': '#e6d3a8', + 'TEXT_INPUT': '#012f2f', + 'BUTTON': ('white', '#046380'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'TealMono': {'BACKGROUND': '#a8cfdd', + 'TEXT': 'black', + 'INPUT': '#dfedf2', + 'SCROLL': '#dfedf2', + 'TEXT_INPUT': 'black', + 'BUTTON': ('white', '#183440'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + ################################## Renamed Original Themes ################################## + 'Default': # plain gray but blue buttons + {'BACKGROUND': COLOR_SYSTEM_DEFAULT, + 'TEXT': COLOR_SYSTEM_DEFAULT, + 'INPUT': COLOR_SYSTEM_DEFAULT, + 'TEXT_INPUT': COLOR_SYSTEM_DEFAULT, + 'SCROLL': COLOR_SYSTEM_DEFAULT, + 'BUTTON': OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR, + 'PROGRESS': COLOR_SYSTEM_DEFAULT, + 'BORDER': 1, 'SLIDER_DEPTH': 1, + 'PROGRESS_DEPTH': 0}, + + 'Default1': # everything is gray + {'BACKGROUND': COLOR_SYSTEM_DEFAULT, + 'TEXT': COLOR_SYSTEM_DEFAULT, + 'INPUT': COLOR_SYSTEM_DEFAULT, + 'TEXT_INPUT': COLOR_SYSTEM_DEFAULT, + 'SCROLL': COLOR_SYSTEM_DEFAULT, + 'BUTTON': COLOR_SYSTEM_DEFAULT, + 'PROGRESS': COLOR_SYSTEM_DEFAULT, + 'BORDER': 1, 'SLIDER_DEPTH': 1, + 'PROGRESS_DEPTH': 0}, + + 'DefaultNoMoreNagging': # a duplicate of "Default" for users that are tired of the nag screen + {'BACKGROUND': COLOR_SYSTEM_DEFAULT, + 'TEXT': COLOR_SYSTEM_DEFAULT, + 'INPUT': COLOR_SYSTEM_DEFAULT, + 'TEXT_INPUT': COLOR_SYSTEM_DEFAULT, + 'SCROLL': COLOR_SYSTEM_DEFAULT, + 'BUTTON': OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR, + 'PROGRESS': COLOR_SYSTEM_DEFAULT, + 'BORDER': 1, 'SLIDER_DEPTH': 1, + 'PROGRESS_DEPTH': 0}, + + 'LightBlue': {'BACKGROUND': '#E3F2FD', + 'TEXT': '#000000', + 'INPUT': '#86A8FF', + 'TEXT_INPUT': '#000000', + 'SCROLL': '#86A8FF', + 'BUTTON': ('#FFFFFF', '#5079D3'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 0, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'ACCENT1': '#FF0266', + 'ACCENT2': '#FF5C93', + 'ACCENT3': '#C5003C'}, + + 'LightGrey': {'BACKGROUND': '#FAFAFA', + 'TEXT': '#000000', + 'INPUT': '#004EA1', + 'TEXT_INPUT': '#FFFFFF', + 'SCROLL': '#5EA7FF', + 'BUTTON': ('#FFFFFF', '#0079D3'), # based on Reddit color + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 0, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'ACCENT1': '#FF0266', + 'ACCENT2': '#FF5C93', + 'ACCENT3': '#C5003C'}, + + 'LightGrey1': {'BACKGROUND': '#ffffff', + 'TEXT': '#1a1a1b', + 'INPUT': '#dae0e6', + 'TEXT_INPUT': '#222222', + 'SCROLL': '#a5a4a4', + 'BUTTON': ('white', '#0079d3'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'ACCENT1': '#ff5414', + 'ACCENT2': '#33a8ff', + 'ACCENT3': '#dbf0ff'}, + + 'DarkBrown': {'BACKGROUND': '#282923', + 'TEXT': '#E7DB74', + 'INPUT': '#393a32', + 'TEXT_INPUT': '#E7C855', + 'SCROLL': '#E7C855', + 'BUTTON': ('#E7C855', '#284B5A'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'ACCENT1': '#c15226', + 'ACCENT2': '#7a4d5f', + 'ACCENT3': '#889743'}, + + 'LightGreen1': {'BACKGROUND': '#9FB8AD', + 'TEXT': COLOR_SYSTEM_DEFAULT, + 'INPUT': '#F7F3EC', 'TEXT_INPUT': 'black', + 'SCROLL': '#F7F3EC', + 'BUTTON': ('white', '#475841'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'DarkGrey': {'BACKGROUND': '#404040', + 'TEXT': 'white', + 'INPUT': '#4D4D4D', + 'TEXT_INPUT': 'white', + 'SCROLL': '#707070', + 'BUTTON': ('white', '#004F00'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'LightGreen2': {'BACKGROUND': '#B7CECE', + 'TEXT': 'black', + 'INPUT': '#FDFFF7', + 'TEXT_INPUT': 'black', + 'SCROLL': '#FDFFF7', + 'BUTTON': ('white', '#658268'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'ACCENT1': '#76506d', + 'ACCENT2': '#5148f1', + 'ACCENT3': '#0a1c84', + 'PROGRESS_DEPTH': 0}, + + 'DarkGrey1': {'BACKGROUND': '#404040', + 'TEXT': 'white', + 'INPUT': 'white', + 'TEXT_INPUT': 'black', + 'SCROLL': '#707070', + 'BUTTON': ('white', '#004F00'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'DarkBlack': {'BACKGROUND': 'black', + 'TEXT': 'white', + 'INPUT': '#4D4D4D', + 'TEXT_INPUT': 'white', + 'SCROLL': '#707070', + 'BUTTON': ('black', 'white'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'LightBrown': {'BACKGROUND': '#fdf6e3', + 'TEXT': '#268bd1', + 'INPUT': '#eee8d5', + 'TEXT_INPUT': '#6c71c3', + 'SCROLL': '#eee8d5', + 'BUTTON': ('white', '#063542'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'LightBrown1': {'BACKGROUND': '#e5dece', + 'TEXT': '#063289', + 'INPUT': '#f9f8f4', + 'TEXT_INPUT': '#242834', + 'SCROLL': '#eee8d5', + 'BUTTON': ('white', '#063289'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'DarkBlue1': {'BACKGROUND': '#242834', + 'TEXT': '#dfe6f8', + 'INPUT': '#97755c', + 'TEXT_INPUT': 'white', + 'SCROLL': '#a9afbb', + 'BUTTON': ('white', '#063289'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'DarkBrown1': {'BACKGROUND': '#2c2825', + 'TEXT': '#fdcb52', + 'INPUT': '#705e52', + 'TEXT_INPUT': '#fdcb52', + 'SCROLL': '#705e52', + 'BUTTON': ('black', '#fdcb52'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'DarkBlue2': {'BACKGROUND': '#1a2835', + 'TEXT': '#d1ecff', + 'INPUT': '#335267', + 'TEXT_INPUT': '#acc2d0', + 'SCROLL': '#1b6497', + 'BUTTON': ('black', '#fafaf8'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'DarkBrown2': {'BACKGROUND': '#280001', + 'TEXT': 'white', + 'INPUT': '#d8d584', + 'TEXT_INPUT': 'black', + 'SCROLL': '#763e00', + 'BUTTON': ('black', '#daad28'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'DarkGreen': {'BACKGROUND': '#82a459', + 'TEXT': 'black', + 'INPUT': '#d8d584', + 'TEXT_INPUT': 'black', + 'SCROLL': '#e3ecf3', + 'BUTTON': ('white', '#517239'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'LightBlue1': {'BACKGROUND': '#A5CADD', + 'TEXT': '#6E266E', + 'INPUT': '#E0F5FF', + 'TEXT_INPUT': 'black', + 'SCROLL': '#E0F5FF', + 'BUTTON': ('white', '#303952'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'LightPurple': {'BACKGROUND': '#B0AAC2', + 'TEXT': 'black', + 'INPUT': '#F2EFE8', + 'SCROLL': '#F2EFE8', + 'TEXT_INPUT': 'black', + 'BUTTON': ('black', '#C2D4D8'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'LightBlue2': {'BACKGROUND': '#AAB6D3', + 'TEXT': 'black', + 'INPUT': '#F1F4FC', + 'SCROLL': '#F1F4FC', + 'TEXT_INPUT': 'black', + 'BUTTON': ('white', '#7186C7'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'LightGreen3': {'BACKGROUND': '#A8C1B4', + 'TEXT': 'black', + 'INPUT': '#DDE0DE', + 'SCROLL': '#E3E3E3', + 'TEXT_INPUT': 'black', + 'BUTTON': ('white', '#6D9F85'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'DarkBlue3': {'BACKGROUND': '#64778d', + 'TEXT': 'white', + 'INPUT': '#f0f3f7', + 'SCROLL': '#A6B2BE', + 'TEXT_INPUT': 'black', + 'BUTTON': ('white', '#283b5b'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'LightGreen4': {'BACKGROUND': '#b4ffb4', + 'TEXT': 'black', + 'INPUT': '#ffff64', + 'SCROLL': '#ffb482', + 'TEXT_INPUT': 'black', + 'BUTTON': ('black', '#ffa0dc'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'LightGreen5': {'BACKGROUND': '#92aa9d', + 'TEXT': 'black', + 'INPUT': '#fcfff6', + 'SCROLL': '#fcfff6', + 'TEXT_INPUT': 'black', + 'BUTTON': ('black', '#d0dbbd'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'LightBrown2': {'BACKGROUND': '#a7ad7f', + 'TEXT': 'black', + 'INPUT': '#e6d3a8', + 'SCROLL': '#e6d3a8', + 'TEXT_INPUT': 'black', + 'BUTTON': ('white', '#5d907d'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'LightBrown3': {'BACKGROUND': '#efeccb', + 'TEXT': '#012f2f', + 'INPUT': '#e6d3a8', + 'SCROLL': '#e6d3a8', + 'TEXT_INPUT': '#012f2f', + 'BUTTON': ('white', '#046380'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + 'LightBlue3': {'BACKGROUND': '#a8cfdd', + 'TEXT': 'black', + 'INPUT': '#dfedf2', + 'SCROLL': '#dfedf2', + 'TEXT_INPUT': 'black', + 'BUTTON': ('white', '#183440'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, + + ################################## End Renamed Original Themes ################################## + + # + 'LightBrown4': {'BACKGROUND': '#d7c79e', 'TEXT': '#a35638', 'INPUT': '#9dab86', 'TEXT_INPUT': '#000000', 'SCROLL': '#a35638', + 'BUTTON': ('white', '#a35638'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#a35638', '#9dab86', '#e08f62', '#d7c79e'], }, + 'DarkTeal': {'BACKGROUND': '#003f5c', 'TEXT': '#fb5b5a', 'INPUT': '#bc4873', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#bc4873', + 'BUTTON': ('white', '#fb5b5a'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#003f5c', '#472b62', '#bc4873', '#fb5b5a'], }, + 'DarkPurple': {'BACKGROUND': '#472b62', 'TEXT': '#fb5b5a', 'INPUT': '#bc4873', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#bc4873', + 'BUTTON': ('#FFFFFF', '#472b62'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#003f5c', '#472b62', '#bc4873', '#fb5b5a'], }, + 'LightGreen6': {'BACKGROUND': '#eafbea', 'TEXT': '#1f6650', 'INPUT': '#6f9a8d', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#1f6650', + 'BUTTON': ('white', '#1f6650'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#1f6650', '#6f9a8d', '#ea5e5e', '#eafbea'], }, + 'DarkGrey2': {'BACKGROUND': '#2b2b28', 'TEXT': '#f8f8f8', 'INPUT': '#f1d6ab', 'TEXT_INPUT': '#000000', 'SCROLL': '#f1d6ab', + 'BUTTON': ('#2b2b28', '#e3b04b'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#2b2b28', '#e3b04b', '#f1d6ab', '#f8f8f8'], }, + 'LightBrown6': {'BACKGROUND': '#f9b282', 'TEXT': '#8f4426', 'INPUT': '#de6b35', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#8f4426', + 'BUTTON': ('white', '#8f4426'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#8f4426', '#de6b35', '#64ccda', '#f9b282'], }, + 'DarkTeal1': {'BACKGROUND': '#396362', 'TEXT': '#ffe7d1', 'INPUT': '#f6c89f', 'TEXT_INPUT': '#000000', 'SCROLL': '#f6c89f', + 'BUTTON': ('#ffe7d1', '#4b8e8d'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#396362', '#4b8e8d', '#f6c89f', '#ffe7d1'], }, + 'LightBrown7': {'BACKGROUND': '#f6c89f', 'TEXT': '#396362', 'INPUT': '#4b8e8d', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#396362', + 'BUTTON': ('white', '#396362'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#396362', '#4b8e8d', '#f6c89f', '#ffe7d1'], }, + 'DarkPurple1': {'BACKGROUND': '#0c093c', 'TEXT': '#fad6d6', 'INPUT': '#eea5f6', 'TEXT_INPUT': '#000000', 'SCROLL': '#eea5f6', + 'BUTTON': ('#FFFFFF', '#df42d1'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#0c093c', '#df42d1', '#eea5f6', '#fad6d6'], }, + 'DarkGrey3': {'BACKGROUND': '#211717', 'TEXT': '#dfddc7', 'INPUT': '#f58b54', 'TEXT_INPUT': '#000000', 'SCROLL': '#f58b54', + 'BUTTON': ('#dfddc7', '#a34a28'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#211717', '#a34a28', '#f58b54', '#dfddc7'], }, + 'LightBrown8': {'BACKGROUND': '#dfddc7', 'TEXT': '#211717', 'INPUT': '#a34a28', 'TEXT_INPUT': '#dfddc7', 'SCROLL': '#211717', + 'BUTTON': ('#dfddc7', '#a34a28'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#211717', '#a34a28', '#f58b54', '#dfddc7'], }, + 'DarkBlue4': {'BACKGROUND': '#494ca2', 'TEXT': '#e3e7f1', 'INPUT': '#c6cbef', 'TEXT_INPUT': '#000000', 'SCROLL': '#c6cbef', + 'BUTTON': ('#FFFFFF', '#8186d5'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#494ca2', '#8186d5', '#c6cbef', '#e3e7f1'], }, + 'LightBlue4': {'BACKGROUND': '#5c94bd', 'TEXT': '#470938', 'INPUT': '#1a3e59', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#470938', + 'BUTTON': ('white', '#470938'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#470938', '#1a3e59', '#5c94bd', '#f2d6eb'], }, + 'DarkTeal2': {'BACKGROUND': '#394a6d', 'TEXT': '#c0ffb3', 'INPUT': '#52de97', 'TEXT_INPUT': '#000000', 'SCROLL': '#52de97', + 'BUTTON': ('#c0ffb3', '#394a6d'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#394a6d', '#3c9d9b', '#52de97', '#c0ffb3'], }, + 'DarkTeal3': {'BACKGROUND': '#3c9d9b', 'TEXT': '#c0ffb3', 'INPUT': '#52de97', 'TEXT_INPUT': '#000000', 'SCROLL': '#52de97', + 'BUTTON': ('#c0ffb3', '#394a6d'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#394a6d', '#3c9d9b', '#52de97', '#c0ffb3'], }, + 'DarkPurple5': {'BACKGROUND': '#730068', 'TEXT': '#f6f078', 'INPUT': '#01d28e', 'TEXT_INPUT': '#000000', 'SCROLL': '#01d28e', + 'BUTTON': ('#f6f078', '#730068'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#730068', '#434982', '#01d28e', '#f6f078'], }, + 'DarkPurple2': {'BACKGROUND': '#202060', 'TEXT': '#b030b0', 'INPUT': '#602080', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#602080', + 'BUTTON': ('white', '#202040'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#202040', '#202060', '#602080', '#b030b0'], }, + 'DarkBlue5': {'BACKGROUND': '#000272', 'TEXT': '#ff6363', 'INPUT': '#a32f80', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#a32f80', + 'BUTTON': ('#FFFFFF', '#341677'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#000272', '#341677', '#a32f80', '#ff6363'], }, + 'LightGrey2': {'BACKGROUND': '#f6f6f6', 'TEXT': '#420000', 'INPUT': '#d4d7dd', 'TEXT_INPUT': '#420000', 'SCROLL': '#420000', + 'BUTTON': ('#420000', '#d4d7dd'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#420000', '#d4d7dd', '#eae9e9', '#f6f6f6'], }, + 'LightGrey3': {'BACKGROUND': '#eae9e9', 'TEXT': '#420000', 'INPUT': '#d4d7dd', 'TEXT_INPUT': '#420000', 'SCROLL': '#420000', + 'BUTTON': ('#420000', '#d4d7dd'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#420000', '#d4d7dd', '#eae9e9', '#f6f6f6'], }, + 'DarkBlue6': {'BACKGROUND': '#01024e', 'TEXT': '#ff6464', 'INPUT': '#8b4367', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#8b4367', + 'BUTTON': ('#FFFFFF', '#543864'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#01024e', '#543864', '#8b4367', '#ff6464'], }, + 'DarkBlue7': {'BACKGROUND': '#241663', 'TEXT': '#eae7af', 'INPUT': '#a72693', 'TEXT_INPUT': '#eae7af', 'SCROLL': '#a72693', + 'BUTTON': ('#eae7af', '#160f30'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#160f30', '#241663', '#a72693', '#eae7af'], }, + 'LightBrown9': {'BACKGROUND': '#f6d365', 'TEXT': '#3a1f5d', 'INPUT': '#c83660', 'TEXT_INPUT': '#f6d365', 'SCROLL': '#3a1f5d', + 'BUTTON': ('#f6d365', '#c83660'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#3a1f5d', '#c83660', '#e15249', '#f6d365'], }, + 'DarkPurple3': {'BACKGROUND': '#6e2142', 'TEXT': '#ffd692', 'INPUT': '#e16363', 'TEXT_INPUT': '#ffd692', 'SCROLL': '#e16363', + 'BUTTON': ('#ffd692', '#943855'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#6e2142', '#943855', '#e16363', '#ffd692'], }, + 'LightBrown10': {'BACKGROUND': '#ffd692', 'TEXT': '#6e2142', 'INPUT': '#943855', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#6e2142', + 'BUTTON': ('white', '#6e2142'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#6e2142', '#943855', '#e16363', '#ffd692'], }, + 'DarkPurple4': {'BACKGROUND': '#200f21', 'TEXT': '#f638dc', 'INPUT': '#5a3d5c', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#5a3d5c', + 'BUTTON': ('#FFFFFF', '#382039'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#200f21', '#382039', '#5a3d5c', '#f638dc'], }, + 'LightBlue5': {'BACKGROUND': '#b2fcff', 'TEXT': '#3e64ff', 'INPUT': '#5edfff', 'TEXT_INPUT': '#000000', 'SCROLL': '#3e64ff', + 'BUTTON': ('white', '#3e64ff'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#3e64ff', '#5edfff', '#b2fcff', '#ecfcff'], }, + 'DarkTeal4': {'BACKGROUND': '#464159', 'TEXT': '#c7f0db', 'INPUT': '#8bbabb', 'TEXT_INPUT': '#000000', 'SCROLL': '#8bbabb', + 'BUTTON': ('#FFFFFF', '#6c7b95'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#464159', '#6c7b95', '#8bbabb', '#c7f0db'], }, + 'LightTeal': {'BACKGROUND': '#c7f0db', 'TEXT': '#464159', 'INPUT': '#6c7b95', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#464159', + 'BUTTON': ('white', '#464159'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#464159', '#6c7b95', '#8bbabb', '#c7f0db'], }, + 'DarkTeal5': {'BACKGROUND': '#8bbabb', 'TEXT': '#464159', 'INPUT': '#6c7b95', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#464159', + 'BUTTON': ('#c7f0db', '#6c7b95'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#464159', '#6c7b95', '#8bbabb', '#c7f0db'], }, + 'LightGrey4': {'BACKGROUND': '#faf5ef', 'TEXT': '#672f2f', 'INPUT': '#99b19c', 'TEXT_INPUT': '#672f2f', 'SCROLL': '#672f2f', + 'BUTTON': ('#672f2f', '#99b19c'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#672f2f', '#99b19c', '#d7d1c9', '#faf5ef'], }, + 'LightGreen7': {'BACKGROUND': '#99b19c', 'TEXT': '#faf5ef', 'INPUT': '#d7d1c9', 'TEXT_INPUT': '#000000', 'SCROLL': '#d7d1c9', + 'BUTTON': ('#FFFFFF', '#99b19c'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#672f2f', '#99b19c', '#d7d1c9', '#faf5ef'], }, + 'LightGrey5': {'BACKGROUND': '#d7d1c9', 'TEXT': '#672f2f', 'INPUT': '#99b19c', 'TEXT_INPUT': '#672f2f', 'SCROLL': '#672f2f', + 'BUTTON': ('white', '#672f2f'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#672f2f', '#99b19c', '#d7d1c9', '#faf5ef'], }, + 'DarkBrown3': {'BACKGROUND': '#a0855b', 'TEXT': '#f9f6f2', 'INPUT': '#f1d6ab', 'TEXT_INPUT': '#000000', 'SCROLL': '#f1d6ab', + 'BUTTON': ('white', '#38470b'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#38470b', '#a0855b', '#f1d6ab', '#f9f6f2'], }, + 'LightBrown11': {'BACKGROUND': '#f1d6ab', 'TEXT': '#38470b', 'INPUT': '#a0855b', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#38470b', + 'BUTTON': ('#f9f6f2', '#a0855b'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#38470b', '#a0855b', '#f1d6ab', '#f9f6f2'], }, + 'DarkRed': {'BACKGROUND': '#83142c', 'TEXT': '#f9d276', 'INPUT': '#ad1d45', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#ad1d45', + 'BUTTON': ('#f9d276', '#ad1d45'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#44000d', '#83142c', '#ad1d45', '#f9d276'], }, + 'DarkTeal6': {'BACKGROUND': '#204969', 'TEXT': '#fff7f7', 'INPUT': '#dadada', 'TEXT_INPUT': '#000000', 'SCROLL': '#dadada', + 'BUTTON': ('black', '#fff7f7'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#204969', '#08ffc8', '#dadada', '#fff7f7'], }, + 'DarkBrown4': {'BACKGROUND': '#252525', 'TEXT': '#ff0000', 'INPUT': '#af0404', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#af0404', + 'BUTTON': ('white', '#252525'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#252525', '#414141', '#af0404', '#ff0000'], }, + 'LightYellow': {'BACKGROUND': '#f4ff61', 'TEXT': '#27aa80', 'INPUT': '#32ff6a', 'TEXT_INPUT': '#000000', 'SCROLL': '#27aa80', + 'BUTTON': ('#f4ff61', '#27aa80'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#27aa80', '#32ff6a', '#a8ff3e', '#f4ff61'], }, + 'DarkGreen1': {'BACKGROUND': '#2b580c', 'TEXT': '#fdef96', 'INPUT': '#f7b71d', 'TEXT_INPUT': '#000000', 'SCROLL': '#f7b71d', + 'BUTTON': ('#fdef96', '#2b580c'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#2b580c', '#afa939', '#f7b71d', '#fdef96'], }, + + 'LightGreen8': {'BACKGROUND': '#c8dad3', 'TEXT': '#63707e', 'INPUT': '#93b5b3', 'TEXT_INPUT': '#000000', 'SCROLL': '#63707e', + 'BUTTON': ('white', '#63707e'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#63707e', '#93b5b3', '#c8dad3', '#f2f6f5'], }, + + 'DarkTeal7': {'BACKGROUND': '#248ea9', 'TEXT': '#fafdcb', 'INPUT': '#aee7e8', 'TEXT_INPUT': '#000000', 'SCROLL': '#aee7e8', + 'BUTTON': ('black', '#fafdcb'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#248ea9', '#28c3d4', '#aee7e8', '#fafdcb'], }, + 'DarkBlue8': {'BACKGROUND': '#454d66', 'TEXT': '#d9d872', 'INPUT': '#58b368', 'TEXT_INPUT': '#000000', 'SCROLL': '#58b368', + 'BUTTON': ('black', '#009975'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#009975', '#454d66', '#58b368', '#d9d872'], }, + 'DarkBlue9': {'BACKGROUND': '#263859', 'TEXT': '#ff6768', 'INPUT': '#6b778d', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#6b778d', + 'BUTTON': ('#ff6768', '#263859'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#17223b', '#263859', '#6b778d', '#ff6768'], }, + 'DarkBlue10': {'BACKGROUND': '#0028ff', 'TEXT': '#f1f4df', 'INPUT': '#10eaf0', 'TEXT_INPUT': '#000000', 'SCROLL': '#10eaf0', + 'BUTTON': ('#f1f4df', '#24009c'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#24009c', '#0028ff', '#10eaf0', '#f1f4df'], }, + 'DarkBlue11': {'BACKGROUND': '#6384b3', 'TEXT': '#e6f0b6', 'INPUT': '#b8e9c0', 'TEXT_INPUT': '#000000', 'SCROLL': '#b8e9c0', + 'BUTTON': ('#e6f0b6', '#684949'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#684949', '#6384b3', '#b8e9c0', '#e6f0b6'], }, + + 'DarkTeal8': {'BACKGROUND': '#71a0a5', 'TEXT': '#212121', 'INPUT': '#665c84', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#212121', + 'BUTTON': ('#fab95b', '#665c84'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#212121', '#665c84', '#71a0a5', '#fab95b']}, + 'DarkRed1': {'BACKGROUND': '#c10000', 'TEXT': '#eeeeee', 'INPUT': '#dedede', 'TEXT_INPUT': '#000000', 'SCROLL': '#dedede', + 'BUTTON': ('#c10000', '#eeeeee'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#c10000', '#ff4949', '#dedede', '#eeeeee'], }, + 'LightBrown5': {'BACKGROUND': '#fff591', 'TEXT': '#e41749', 'INPUT': '#f5587b', 'TEXT_INPUT': '#000000', 'SCROLL': '#e41749', + 'BUTTON': ('#fff591', '#e41749'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#e41749', '#f5587b', '#ff8a5c', '#fff591']}, + 'LightGreen9': {'BACKGROUND': '#f1edb3', 'TEXT': '#3b503d', 'INPUT': '#4a746e', 'TEXT_INPUT': '#f1edb3', 'SCROLL': '#3b503d', + 'BUTTON': ('#f1edb3', '#3b503d'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#3b503d', '#4a746e', '#c8cf94', '#f1edb3'], 'DESCRIPTION': ['Green', 'Turquoise', 'Yellow']}, + 'DarkGreen2': {'BACKGROUND': '#3b503d', 'TEXT': '#f1edb3', 'INPUT': '#c8cf94', 'TEXT_INPUT': '#000000', 'SCROLL': '#c8cf94', + 'BUTTON': ('#f1edb3', '#3b503d'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#3b503d', '#4a746e', '#c8cf94', '#f1edb3'], 'DESCRIPTION': ['Green', 'Turquoise', 'Yellow']}, + 'LightGray1': {'BACKGROUND': '#f2f2f2', 'TEXT': '#222831', 'INPUT': '#393e46', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#222831', + 'BUTTON': ('#f2f2f2', '#222831'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#222831', '#393e46', '#f96d00', '#f2f2f2'], + 'DESCRIPTION': ['Black', 'Grey', 'Orange', 'Grey', 'Autumn']}, + 'DarkGrey4': {'BACKGROUND': '#52524e', 'TEXT': '#e9e9e5', 'INPUT': '#d4d6c8', 'TEXT_INPUT': '#000000', 'SCROLL': '#d4d6c8', + 'BUTTON': ('#FFFFFF', '#9a9b94'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#52524e', '#9a9b94', '#d4d6c8', '#e9e9e5'], + 'DESCRIPTION': ['Grey', 'Pastel', 'Winter']}, + 'DarkBlue12': {'BACKGROUND': '#324e7b', 'TEXT': '#f8f8f8', 'INPUT': '#86a6df', 'TEXT_INPUT': '#000000', 'SCROLL': '#86a6df', + 'BUTTON': ('#FFFFFF', '#5068a9'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#324e7b', '#5068a9', '#86a6df', '#f8f8f8'], + 'DESCRIPTION': ['Blue', 'Grey', 'Cold', 'Winter']}, + 'DarkPurple6': {'BACKGROUND': '#070739', 'TEXT': '#e1e099', 'INPUT': '#c327ab', 'TEXT_INPUT': '#e1e099', 'SCROLL': '#c327ab', + 'BUTTON': ('#e1e099', '#521477'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#070739', '#521477', '#c327ab', '#e1e099'], + 'DESCRIPTION': ['Black', 'Purple', 'Yellow', 'Dark']}, + 'DarkBlue13': {'BACKGROUND': '#203562', 'TEXT': '#e3e8f8', 'INPUT': '#c0c5cd', 'TEXT_INPUT': '#000000', 'SCROLL': '#c0c5cd', + 'BUTTON': ('#FFFFFF', '#3e588f'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#203562', '#3e588f', '#c0c5cd', '#e3e8f8'], + 'DESCRIPTION': ['Blue', 'Grey', 'Wedding', 'Cold']}, + 'DarkBrown5': {'BACKGROUND': '#3c1b1f', 'TEXT': '#f6e1b5', 'INPUT': '#e2bf81', 'TEXT_INPUT': '#000000', 'SCROLL': '#e2bf81', + 'BUTTON': ('#3c1b1f', '#f6e1b5'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#3c1b1f', '#b21e4b', '#e2bf81', '#f6e1b5'], + 'DESCRIPTION': ['Brown', 'Red', 'Yellow', 'Warm']}, + 'DarkGreen3': {'BACKGROUND': '#062121', 'TEXT': '#eeeeee', 'INPUT': '#e4dcad', 'TEXT_INPUT': '#000000', 'SCROLL': '#e4dcad', + 'BUTTON': ('#eeeeee', '#181810'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#062121', '#181810', '#e4dcad', '#eeeeee'], + 'DESCRIPTION': ['Black', 'Black', 'Brown', 'Grey']}, + 'DarkBlack1': {'BACKGROUND': '#181810', 'TEXT': '#eeeeee', 'INPUT': '#e4dcad', 'TEXT_INPUT': '#000000', 'SCROLL': '#e4dcad', + 'BUTTON': ('white', '#062121'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#062121', '#181810', '#e4dcad', '#eeeeee'], + 'DESCRIPTION': ['Black', 'Black', 'Brown', 'Grey']}, + 'DarkGrey5': {'BACKGROUND': '#343434', 'TEXT': '#f3f3f3', 'INPUT': '#e9dcbe', 'TEXT_INPUT': '#000000', 'SCROLL': '#e9dcbe', + 'BUTTON': ('#FFFFFF', '#8e8b82'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#343434', '#8e8b82', '#e9dcbe', '#f3f3f3'], 'DESCRIPTION': ['Grey', 'Brown']}, + 'LightBrown12': {'BACKGROUND': '#8e8b82', 'TEXT': '#f3f3f3', 'INPUT': '#e9dcbe', 'TEXT_INPUT': '#000000', 'SCROLL': '#e9dcbe', + 'BUTTON': ('#f3f3f3', '#8e8b82'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#343434', '#8e8b82', '#e9dcbe', '#f3f3f3'], 'DESCRIPTION': ['Grey', 'Brown']}, + 'DarkTeal9': {'BACKGROUND': '#13445a', 'TEXT': '#fef4e8', 'INPUT': '#446878', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#446878', + 'BUTTON': ('#fef4e8', '#446878'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#13445a', '#970747', '#446878', '#fef4e8'], + 'DESCRIPTION': ['Red', 'Grey', 'Blue', 'Wedding', 'Retro']}, + 'DarkBlue14': {'BACKGROUND': '#21273d', 'TEXT': '#f1f6f8', 'INPUT': '#b9d4f1', 'TEXT_INPUT': '#000000', 'SCROLL': '#b9d4f1', + 'BUTTON': ('#FFFFFF', '#6a759b'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#21273d', '#6a759b', '#b9d4f1', '#f1f6f8'], + 'DESCRIPTION': ['Blue', 'Black', 'Grey', 'Cold', 'Winter']}, + 'LightBlue6': {'BACKGROUND': '#f1f6f8', 'TEXT': '#21273d', 'INPUT': '#6a759b', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#21273d', + 'BUTTON': ('#f1f6f8', '#6a759b'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#21273d', '#6a759b', '#b9d4f1', '#f1f6f8'], + 'DESCRIPTION': ['Blue', 'Black', 'Grey', 'Cold', 'Winter']}, + 'DarkGreen4': {'BACKGROUND': '#044343', 'TEXT': '#e4e4e4', 'INPUT': '#045757', 'TEXT_INPUT': '#e4e4e4', 'SCROLL': '#045757', + 'BUTTON': ('#e4e4e4', '#045757'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#222222', '#044343', '#045757', '#e4e4e4'], + 'DESCRIPTION': ['Black', 'Turquoise', 'Grey', 'Dark']}, + 'DarkGreen5': {'BACKGROUND': '#1b4b36', 'TEXT': '#e0e7f1', 'INPUT': '#aebd77', 'TEXT_INPUT': '#000000', 'SCROLL': '#aebd77', + 'BUTTON': ('#FFFFFF', '#538f6a'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#1b4b36', '#538f6a', '#aebd77', '#e0e7f1'], 'DESCRIPTION': ['Green', 'Grey']}, + 'DarkTeal10': {'BACKGROUND': '#0d3446', 'TEXT': '#d8dfe2', 'INPUT': '#71adb5', 'TEXT_INPUT': '#000000', 'SCROLL': '#71adb5', + 'BUTTON': ('#FFFFFF', '#176d81'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#0d3446', '#176d81', '#71adb5', '#d8dfe2'], + 'DESCRIPTION': ['Grey', 'Turquoise', 'Winter', 'Cold']}, + 'DarkGrey6': {'BACKGROUND': '#3e3e3e', 'TEXT': '#ededed', 'INPUT': '#68868c', 'TEXT_INPUT': '#ededed', 'SCROLL': '#68868c', + 'BUTTON': ('#FFFFFF', '#405559'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#3e3e3e', '#405559', '#68868c', '#ededed'], + 'DESCRIPTION': ['Grey', 'Turquoise', 'Winter']}, + 'DarkTeal11': {'BACKGROUND': '#405559', 'TEXT': '#ededed', 'INPUT': '#68868c', 'TEXT_INPUT': '#ededed', 'SCROLL': '#68868c', + 'BUTTON': ('#ededed', '#68868c'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#3e3e3e', '#405559', '#68868c', '#ededed'], + 'DESCRIPTION': ['Grey', 'Turquoise', 'Winter']}, + 'LightBlue7': {'BACKGROUND': '#9ed0e0', 'TEXT': '#19483f', 'INPUT': '#5c868e', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#19483f', + 'BUTTON': ('white', '#19483f'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#19483f', '#5c868e', '#ff6a38', '#9ed0e0'], + 'DESCRIPTION': ['Orange', 'Blue', 'Turquoise']}, + 'LightGreen10': {'BACKGROUND': '#d8ebb5', 'TEXT': '#205d67', 'INPUT': '#639a67', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#205d67', + 'BUTTON': ('#d8ebb5', '#205d67'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#205d67', '#639a67', '#d9bf77', '#d8ebb5'], + 'DESCRIPTION': ['Blue', 'Green', 'Brown', 'Vintage']}, + 'DarkBlue15': {'BACKGROUND': '#151680', 'TEXT': '#f1fea4', 'INPUT': '#375fc0', 'TEXT_INPUT': '#f1fea4', 'SCROLL': '#375fc0', + 'BUTTON': ('#f1fea4', '#1c44ac'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#151680', '#1c44ac', '#375fc0', '#f1fea4'], + 'DESCRIPTION': ['Blue', 'Yellow', 'Cold']}, + 'DarkBlue16': {'BACKGROUND': '#1c44ac', 'TEXT': '#f1fea4', 'INPUT': '#375fc0', 'TEXT_INPUT': '#f1fea4', 'SCROLL': '#375fc0', + 'BUTTON': ('#f1fea4', '#151680'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#151680', '#1c44ac', '#375fc0', '#f1fea4'], + 'DESCRIPTION': ['Blue', 'Yellow', 'Cold']}, + 'DarkTeal12': {'BACKGROUND': '#004a7c', 'TEXT': '#fafafa', 'INPUT': '#e8f1f5', 'TEXT_INPUT': '#000000', 'SCROLL': '#e8f1f5', + 'BUTTON': ('#fafafa', '#005691'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#004a7c', '#005691', '#e8f1f5', '#fafafa'], + 'DESCRIPTION': ['Grey', 'Blue', 'Cold', 'Winter']}, + 'LightBrown13': {'BACKGROUND': '#ebf5ee', 'TEXT': '#921224', 'INPUT': '#bdc6b8', 'TEXT_INPUT': '#921224', 'SCROLL': '#921224', + 'BUTTON': ('white', '#921224'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#921224', '#bdc6b8', '#bce0da', '#ebf5ee'], + 'DESCRIPTION': ['Red', 'Blue', 'Grey', 'Vintage', 'Wedding']}, + 'DarkBlue17': {'BACKGROUND': '#21294c', 'TEXT': '#f9f2d7', 'INPUT': '#f2dea8', 'TEXT_INPUT': '#000000', 'SCROLL': '#f2dea8', + 'BUTTON': ('#f9f2d7', '#141829'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#141829', '#21294c', '#f2dea8', '#f9f2d7'], + 'DESCRIPTION': ['Black', 'Blue', 'Yellow']}, + 'DarkBrown6': {'BACKGROUND': '#785e4d', 'TEXT': '#f2eee3', 'INPUT': '#baaf92', 'TEXT_INPUT': '#000000', 'SCROLL': '#baaf92', + 'BUTTON': ('white', '#785e4d'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#785e4d', '#ff8426', '#baaf92', '#f2eee3'], + 'DESCRIPTION': ['Grey', 'Brown', 'Orange', 'Autumn']}, + 'DarkGreen6': {'BACKGROUND': '#5c715e', 'TEXT': '#f2f9f1', 'INPUT': '#ddeedf', 'TEXT_INPUT': '#000000', 'SCROLL': '#ddeedf', + 'BUTTON': ('#f2f9f1', '#5c715e'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#5c715e', '#b6cdbd', '#ddeedf', '#f2f9f1'], + 'DESCRIPTION': ['Grey', 'Green', 'Vintage']}, + 'DarkGrey7': {'BACKGROUND': '#4b586e', 'TEXT': '#dddddd', 'INPUT': '#574e6d', 'TEXT_INPUT': '#dddddd', 'SCROLL': '#574e6d', + 'BUTTON': ('#dddddd', '#43405d'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#43405d', '#4b586e', '#574e6d', '#dddddd'], + 'DESCRIPTION': ['Grey', 'Winter', 'Cold']}, + 'DarkRed2': {'BACKGROUND': '#ab1212', 'TEXT': '#f6e4b5', 'INPUT': '#cd3131', 'TEXT_INPUT': '#f6e4b5', 'SCROLL': '#cd3131', + 'BUTTON': ('#f6e4b5', '#ab1212'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#ab1212', '#1fad9f', '#cd3131', '#f6e4b5'], + 'DESCRIPTION': ['Turquoise', 'Red', 'Yellow']}, + 'LightGrey6': {'BACKGROUND': '#e3e3e3', 'TEXT': '#233142', 'INPUT': '#455d7a', 'TEXT_INPUT': '#e3e3e3', 'SCROLL': '#233142', + 'BUTTON': ('#e3e3e3', '#455d7a'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#233142', '#455d7a', '#f95959', '#e3e3e3'], + 'DESCRIPTION': ['Black', 'Blue', 'Red', 'Grey']}, + 'HotDogStand': {'BACKGROUND': 'red', 'TEXT': 'yellow', 'INPUT': 'yellow', 'TEXT_INPUT': 'black', 'SCROLL': 'yellow', + 'BUTTON': ('red', 'yellow'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + }, + } + + +def ListOfLookAndFeelValues(): + """ + Get a list of the valid values to pass into your call to change_look_and_feel + :return: List[str] - list of valid string values + """ + return sorted(list(LOOK_AND_FEEL_TABLE.keys())) + + +def theme(new_theme=None): + """ + Sets / Gets the current Theme. If none is specified then returns the current theme. + This call replaces the ChangeLookAndFeel / change_look_and_feel call which only sets the theme. + + :param new_theme: (str) the new theme name to use + :return: (str) the currently selected theme + """ + if new_theme is not None: + change_look_and_feel(new_theme) + return CURRENT_LOOK_AND_FEEL + + +def theme_background_color(color=None): + """ + Sets/Returns the background color currently in use + Used for Windows and containers (Column, Frame, Tab) and tables + + :return: (str) - color string of the background color currently in use + """ + if color is not None: + set_options(background_color=color) + return DEFAULT_BACKGROUND_COLOR + + +def theme_element_background_color(color=None): + """ + Sets/Returns the background color currently in use for all elements except containers + + :return: (str) - color string of the element background color currently in use + """ + if color is not None: + set_options(element_background_color=color) + return DEFAULT_ELEMENT_BACKGROUND_COLOR + + +def theme_text_color(color=None): + """ + Sets/Returns the text color currently in use + + :return: (str) - color string of the text color currently in use + """ + if color is not None: + set_options(text_color=color) + return DEFAULT_TEXT_COLOR + + + +def theme_input_background_color(color=None): + """ + Sets/Returns the input element background color currently in use + + :return: (str) - color string of the input element background color currently in use + """ + if color is not None: + set_options(input_elements_background_color=color) + return DEFAULT_INPUT_ELEMENTS_COLOR + + +def theme_input_text_color(color=None): + """ + Sets/Returns the input element entry color (not the text but the thing that's displaying the text) + + :return: (str) - color string of the input element color currently in use + """ + if color is not None: + set_options(input_text_color=color) + return DEFAULT_INPUT_TEXT_COLOR + + + +def theme_button_color(color=None): + """ + Sets/Returns the button color currently in use + + :return: Tuple[str, str] - TUPLE with color strings of the button color currently in use (button text color, button background color) + """ + if color is not None: + set_options(button_color=color) + return DEFAULT_BUTTON_COLOR + + +def theme_progress_bar_color(color=None): + """ + Sets/Returns the progress bar colors by the current color theme + + :return: Tuple[str, str] - TUPLE with color strings of the ProgressBar color currently in use(button text color, button background color) + """ + if color is not None: + set_options(progress_meter_color=color) + return DEFAULT_PROGRESS_BAR_COLOR + + +def theme_slider_color(color=None): + """ + Sets/Returns the slider color (used for sliders) + + :return: (str) - color string of the slider color currently in use + """ + if color is not None: + set_options(scrollbar_color=color) + return DEFAULT_SCROLLBAR_COLOR + + +def theme_border_width(border_width=None): + """ + Sets/Returns the border width currently in use + Used by non ttk elements at the moment + + :return: (int) - border width currently in use + """ + if border_width is not None: + set_options(border_width=border_width) + return DEFAULT_BORDER_WIDTH + + +def theme_slider_border_width(border_width=None): + """ + Sets/Returns the slider border width currently in use + + :return: (int) - border width currently in use + """ + if border_width is not None: + set_options(slider_border_width=border_width) + return DEFAULT_SLIDER_BORDER_WIDTH + + +def theme_progress_bar_border_width(border_width=None): + """ + Sets/Returns the progress meter border width currently in use + + :return: (int) - border width currently in use + """ + if border_width is not None: + set_options(progress_meter_border_depth=border_width) + return DEFAULT_PROGRESS_BAR_BORDER_WIDTH + + + +def theme_element_text_color(color=None): + """ + Sets/Returns the text color used by elements that have text as part of their display (Tables, Trees and Sliders) + + :return: (str) - color string currently in use + """ + if color is not None: + set_options(element_text_color=color) + return DEFAULT_ELEMENT_TEXT_COLOR + + +def theme_list(): + """ + Returns a sorted list of the currently available color themes + + :return: List[str] - A sorted list of the currently available color themes + """ + return list_of_look_and_feel_values() + + +def theme_add_new(new_theme_name, new_theme_dict): + """ + Add a new theme to the dictionary of themes + + :param new_theme_name: text to display in element + :type new_theme_name: (str) + :param new_theme_dict: text to display in element + :type new_theme_dict: (dict) + """ + global LOOK_AND_FEEL_TABLE + try: + LOOK_AND_FEEL_TABLE[new_theme_name] = new_theme_dict + except Exception as e: + print('Exception during adding new theme {}'.format(e)) + + + +def theme_previewer(columns=12): + """ + Show a window with all of the color themes - takes a while so be patient + + :param columns: (int) number of themes in a single row + """ + preview_all_look_and_feel_themes(columns) + +def ChangeLookAndFeel(index, force=False): + """ + Change the "color scheme" of all future PySimpleGUI Windows. + The scheme are string names that specify a group of colors. Background colors, text colors, button colors. + There are 13 different color settings that are changed at one time using a single call to ChangeLookAndFeel + The look and feel table itself has these indexes into the dictionary LOOK_AND_FEEL_TABLE. + The original list was (prior to a major rework and renaming)... these names still work... + In Nov 2019 a new Theme Formula was devised to make choosing a theme easier: + The "Formula" is: + ["Dark" or "Light"] Color Number + Colors can be Blue Brown Grey Green Purple Red Teal Yellow Black + The number will vary for each pair. There are more DarkGrey entries than there are LightYellow for example. + Default = The default settings (only button color is different than system default) + Default1 = The full system default including the button (everything's gray... how sad... don't be all gray... please....) + :param index: (str) the name of the index into the Look and Feel table (does not have to be exact, can be "fuzzy") + :param force: (bool) no longer used + """ + + global CURRENT_LOOK_AND_FEEL + + # if sys.platform.startswith('darwin') and not force: + # print('*** Changing look and feel is not supported on Mac platform ***') + # return + + theme = index + # normalize available l&f values + lf_values = [item.lower() for item in list_of_look_and_feel_values()] + + # option 1 + opt1 = theme.replace(' ', '').lower() + + # option 2 (reverse lookup) + optx = theme.lower().split(' ') + optx.reverse() + opt2 = ''.join(optx) + + # search for valid l&f name + if opt1 in lf_values: + ix = lf_values.index(opt1) + elif opt2 in lf_values: + ix = lf_values.index(opt2) + else: + ix = randint(0, len(lf_values) - 1) + print('** Warning - {} Theme is not a valid theme. Change your theme call. **'.format(index)) + print('valid values are', list_of_look_and_feel_values()) + print('Instead, please enjoy a random Theme named {}'.format(list_of_look_and_feel_values()[ix])) + + selection = list_of_look_and_feel_values()[ix] + CURRENT_LOOK_AND_FEEL = selection + try: + colors = LOOK_AND_FEEL_TABLE[selection] + + # Color the progress bar using button background and input colors...unless they're the same + if colors['PROGRESS'] != COLOR_SYSTEM_DEFAULT: + if colors['BUTTON'][1] != colors['INPUT'] and colors['BUTTON'][1] != colors['BACKGROUND']: + colors['PROGRESS'] = colors['BUTTON'][1], colors['INPUT'] + else: # if the same, then use text input on top of input color + colors['PROGRESS'] = (colors['TEXT_INPUT'], colors['INPUT']) + else: + colors['PROGRESS'] = DEFAULT_PROGRESS_BAR_COLOR_OFFICIAL + # call to change all the colors + SetOptions(background_color=colors['BACKGROUND'], + text_element_background_color=colors['BACKGROUND'], + element_background_color=colors['BACKGROUND'], + text_color=colors['TEXT'], + input_elements_background_color=colors['INPUT'], + # button_color=colors['BUTTON'] if not sys.platform.startswith('darwin') else None, + button_color=colors['BUTTON'], + progress_meter_color=colors['PROGRESS'], + border_width=colors['BORDER'], + slider_border_width=colors['SLIDER_DEPTH'], + progress_meter_border_depth=colors['PROGRESS_DEPTH'], + scrollbar_color=(colors['SCROLL']), + element_text_color=colors['TEXT'], + input_text_color=colors['TEXT_INPUT']) + except: # most likely an index out of range + print('** Warning - Theme value not valid. Change your theme call. **') + print('valid values are', list_of_look_and_feel_values()) + + + +def preview_all_look_and_feel_themes(columns=12): + """ + Displays a "Quick Reference Window" showing all of the different Look and Feel settings that are available. + They are sorted alphabetically. The legacy color names are mixed in, but otherwise they are sorted into Dark and Light halves + :param columns: (int) The number of themes to display per row + """ + + # Show a "splash" type message so the user doesn't give up waiting + popup_quick_message('Hang on for a moment, this will take a bit to create....', background_color='red', text_color='white', auto_close=True, non_blocking=True) + + web = False + + win_bg = 'black' + + def sample_layout(): + return [[Text('Text element'), InputText('Input data here', size=(10, 1))], + [Button('Ok'), Button('Cancel'), Slider((1, 10), orientation='h', size=(5, 15))]] + + layout = [[Text('Here is a complete list of themes', font='Default 18', background_color=win_bg)]] + + names = list_of_look_and_feel_values() + names.sort() + row = [] + for count, theme in enumerate(names): + change_look_and_feel(theme) + if not count % columns: + layout += [row] + row = [] + row += [Frame(theme, sample_layout() if not web else [[T(theme)]] + sample_layout())] + if row: + layout += [row] + + window = Window('Preview of all Look and Feel choices', layout, background_color=win_bg) + window.read() + window.close() + + +# ============================== sprint ======# +# Is identical to the Scrolled Text Box # +# Provides a crude 'print' mechanism but in a # +# GUI environment # +# ============================================# +sprint = ScrolledTextBox + + +# Converts an object's contents into a nice printable string. Great for dumping debug data +def ObjToStringSingleObj(obj): + if obj is None: + return 'None' + return str(obj.__class__) + '\n' + '\n'.join( + (repr(item) + ' = ' + repr(obj.__dict__[item]) for item in sorted(obj.__dict__))) + + +def ObjToString(obj, extra=' '): + if obj is None: + return 'None' + return str(obj.__class__) + '\n' + '\n'.join( + (extra + (str(item) + ' = ' + + (ObjToString(obj.__dict__[item], extra + ' ') if hasattr(obj.__dict__[item], '__dict__') else str( + obj.__dict__[item]))) + for item in sorted(obj.__dict__))) + + +# ------------------------------------------------------------------------------------------------------------------ # +# ===================================== Upper PySimpleGUI ======================================================== # +# Pre-built dialog boxes for all your needs These are the "high level API calls # +# ------------------------------------------------------------------------------------------------------------------ # + +###### +# # #### ##### # # ##### #### +# # # # # # # # # # # +###### # # # # # # # # #### +# # # ##### # # ##### # +# # # # # # # # # +# #### # #### # #### + + + +# ----------------------------------- The mighty Popup! ------------------------------------------------------------ # + + +def Popup(*args, title=None, button_color=None, background_color=None, text_color=None, button_type=POPUP_BUTTONS_OK, + auto_close=False, auto_close_duration=None, custom_text=(None, None), non_blocking=False, icon=DEFAULT_WINDOW_ICON, line_width=None, + font=None, no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)): + """ + Popup - Display a popup box with as many parms as you wish to include + :param args: + :param button_color: + :param background_color: + :param text_color: + :param button_type: + :param auto_close: + :param auto_close_duration: + :param non_blocking: + :param icon: + :param line_width: + :param font: + :param no_titlebar: + :param grab_anywhere: + :param keep_on_top: + :param location: + :return: + """ + if not args: + args_to_print = [''] + else: + args_to_print = args + if line_width != None: + local_line_width = line_width + else: + local_line_width = MESSAGE_BOX_LINE_WIDTH + _title = title if title is not None else args_to_print[0] + window = Window(_title, auto_size_text=True, background_color=background_color, button_color=button_color, + auto_close=auto_close, auto_close_duration=auto_close_duration, icon=icon, font=font, + no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) + max_line_total, total_lines = 0, 0 + for message in args_to_print: + # fancy code to check if string and convert if not is not need. Just always convert to string :-) + # if not isinstance(message, str): message = str(message) + message = str(message) + if message.count('\n'): + message_wrapped = message + else: + message_wrapped = textwrap.fill(message, local_line_width) + message_wrapped_lines = message_wrapped.count('\n') + 1 + longest_line_len = max([len(l) for l in message.split('\n')]) + width_used = min(longest_line_len, local_line_width) + max_line_total = max(max_line_total, width_used) + # height = _GetNumLinesNeeded(message, width_used) + height = message_wrapped_lines + window.AddRow( + Text(message_wrapped, auto_size_text=True, text_color=text_color, background_color=background_color)) + total_lines += height + + if non_blocking: + PopupButton = DummyButton # important to use or else button will close other windows too! + else: + PopupButton = Button + # show either an OK or Yes/No depending on paramater + if custom_text != (None, None): + if type(custom_text) is not tuple: + window.AddRow(PopupButton(custom_text,size=(len(custom_text),1), button_color=button_color, focus=True, bind_return_key=True)) + elif custom_text[1] is None: + window.AddRow(PopupButton(custom_text[0],size=(len(custom_text[0]),1), button_color=button_color, focus=True, bind_return_key=True)) + else: + window.AddRow(PopupButton(custom_text[0], button_color=button_color, focus=True, bind_return_key=True, size=(len(custom_text[0]), 1)), + PopupButton(custom_text[1], button_color=button_color, size=(len(custom_text[0]), 1))) + elif button_type is POPUP_BUTTONS_YES_NO: + window.AddRow(PopupButton('Yes', button_color=button_color, focus=True, bind_return_key=True, pad=((20, 5), 3), + size=(5, 1)), PopupButton('No', button_color=button_color, size=(5, 1))) + elif button_type is POPUP_BUTTONS_CANCELLED: + window.AddRow( + PopupButton('Cancelled', button_color=button_color, focus=True, bind_return_key=True, pad=((20, 0), 3))) + elif button_type is POPUP_BUTTONS_ERROR: + window.AddRow(PopupButton('Error', size=(6, 1), button_color=button_color, focus=True, bind_return_key=True, + pad=((20, 0), 3))) + elif button_type is POPUP_BUTTONS_OK_CANCEL: + window.AddRow(PopupButton('OK', size=(6, 1), button_color=button_color, focus=True, bind_return_key=True), + PopupButton('Cancel', size=(6, 1), button_color=button_color)) + elif button_type is POPUP_BUTTONS_NO_BUTTONS: + pass + else: + window.AddRow(PopupButton('OK', size=(5, 1), button_color=button_color, focus=True, bind_return_key=True, + pad=((20, 0), 3))) + + if non_blocking: + button, values = window.Read(timeout=0) + return button, window + else: + button, values = window.Read() + window.Close() + return button + + +# ============================== MsgBox============# +# Lazy function. Same as calling Popup with parms # +# This function WILL Disappear perhaps today # +# ==================================================# +# MsgBox is the legacy call and should not be used any longer +def MsgBox(*args): + raise DeprecationWarning('MsgBox is no longer supported... change your call to Popup') + + +# --------------------------- PopupNoButtons --------------------------- +def PopupNoButtons(*args, button_color=None, background_color=None, text_color=None, auto_close=False, + auto_close_duration=None, non_blocking=False, icon=DEFAULT_WINDOW_ICON, line_width=None, font=None, + no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)): + """ + Show a Popup but without any buttons + :param args: + :param button_color: + :param background_color: + :param text_color: + :param auto_close: + :param auto_close_duration: + :param non_blocking: + :param icon: + :param line_width: + :param font: + :param no_titlebar: + :param grab_anywhere: + :param keep_on_top: + :param location: + :return: + """ + Popup(*args, button_color=button_color, background_color=background_color, text_color=text_color, + button_type=POPUP_BUTTONS_NO_BUTTONS, + auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon, + line_width=line_width, + font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) + + +# --------------------------- PopupNonBlocking --------------------------- +def PopupNonBlocking(*args, button_type=POPUP_BUTTONS_OK, button_color=None, background_color=None, text_color=None, + auto_close=False, auto_close_duration=None, non_blocking=True, icon=DEFAULT_WINDOW_ICON, + line_width=None, font=None, no_titlebar=False, grab_anywhere=False, keep_on_top=False, + location=(None, None)): + """ + Show Popup box and immediately return (does not block) + :param args: + :param button_type: + :param button_color: + :param background_color: + :param text_color: + :param auto_close: + :param auto_close_duration: + :param non_blocking: + :param icon: + :param line_width: + :param font: + :param no_titlebar: + :param grab_anywhere: + :param keep_on_top: + :param location: + :return: + """ + return Popup(*args, button_color=button_color, background_color=background_color, text_color=text_color, + button_type=button_type, + auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon, + line_width=line_width, + font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) + + +PopupNoWait = PopupNonBlocking + + +# --------------------------- PopupQuick - a NonBlocking, Self-closing Popup --------------------------- +def PopupQuick(*args, button_type=POPUP_BUTTONS_OK, button_color=None, background_color=None, text_color=None, + auto_close=True, auto_close_duration=2, non_blocking=True, icon=DEFAULT_WINDOW_ICON, line_width=None, + font=None, no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)): + """ + Show Popup box that doesn't block and closes itself + :param args: + :param button_type: + :param button_color: + :param background_color: + :param text_color: + :param auto_close: + :param auto_close_duration: + :param non_blocking: + :param icon: + :param line_width: + :param font: + :param no_titlebar: + :param grab_anywhere: + :param keep_on_top: + :param location: + :return: + """ + Popup(*args, button_color=button_color, background_color=background_color, text_color=text_color, + button_type=button_type, + auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon, + line_width=line_width, + font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) + + +# --------------------------- PopupQuick - a NonBlocking, Self-closing Popup with no titlebar and no buttons --------------------------- +def PopupQuickMessage(*args, button_type=POPUP_BUTTONS_NO_BUTTONS, button_color=None, background_color=None, + text_color=None, + auto_close=True, auto_close_duration=2, non_blocking=True, icon=DEFAULT_WINDOW_ICON, + line_width=None, + font=None, no_titlebar=True, grab_anywhere=False, keep_on_top=False, location=(None, None)): + """ + Show Popup box that doesn't block and closes itself + :param args: + :param button_type: + :param button_color: + :param background_color: + :param text_color: + :param auto_close: + :param auto_close_duration: + :param non_blocking: + :param icon: + :param line_width: + :param font: + :param no_titlebar: + :param grab_anywhere: + :param keep_on_top: + :param location: + :return: + """ + Popup(*args, button_color=button_color, background_color=background_color, text_color=text_color, + button_type=button_type, + auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon, + line_width=line_width, + font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) + + +# --------------------------- PopupNoTitlebar --------------------------- +def PopupNoTitlebar(*args, button_type=POPUP_BUTTONS_OK, button_color=None, background_color=None, text_color=None, + auto_close=False, auto_close_duration=None, non_blocking=False, icon=DEFAULT_WINDOW_ICON, + line_width=None, font=None, grab_anywhere=True, keep_on_top=False, location=(None, None)): + """ + Display a Popup without a titlebar. Enables grab anywhere so you can move it + :param args: + :param button_type: + :param button_color: + :param background_color: + :param text_color: + :param auto_close: + :param auto_close_duration: + :param non_blocking: + :param icon: + :param line_width: + :param font: + :param grab_anywhere: + :param keep_on_top: + :param location: + :return: + """ + Popup(*args, button_color=button_color, background_color=background_color, text_color=text_color, + button_type=button_type, + auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon, + line_width=line_width, + font=font, no_titlebar=True, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) + + +PopupNoFrame = PopupNoTitlebar +PopupNoBorder = PopupNoTitlebar +PopupAnnoying = PopupNoTitlebar + + +# --------------------------- PopupAutoClose --------------------------- +def PopupAutoClose(*args, button_type=POPUP_BUTTONS_OK, button_color=None, background_color=None, text_color=None, + auto_close=True, auto_close_duration=DEFAULT_AUTOCLOSE_TIME, non_blocking=False, icon=DEFAULT_WINDOW_ICON, + line_width=None, font=None, no_titlebar=False, grab_anywhere=False, keep_on_top=False, + location=(None, None)): + """ + Popup that closes itself after some time period + :param args: + :param button_type: + :param button_color: + :param background_color: + :param text_color: + :param auto_close: + :param auto_close_duration: + :param non_blocking: + :param icon: + :param line_width: + :param font: + :param no_titlebar: + :param grab_anywhere: + :param keep_on_top: + :param location: + :return: + """ + Popup(*args, button_color=button_color, background_color=background_color, text_color=text_color, + button_type=button_type, + auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon, + line_width=line_width, + font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) + + +PopupTimed = PopupAutoClose + + +# --------------------------- PopupError --------------------------- +def PopupError(*args, button_color=DEFAULT_ERROR_BUTTON_COLOR, background_color=None, text_color=None, auto_close=False, + auto_close_duration=None, non_blocking=False, icon=DEFAULT_WINDOW_ICON, line_width=None, font=None, + no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)): + """ + Popup with colored button and 'Error' as button text + :param args: + :param button_color: + :param background_color: + :param text_color: + :param auto_close: + :param auto_close_duration: + :param non_blocking: + :param icon: + :param line_width: + :param font: + :param no_titlebar: + :param grab_anywhere: + :param keep_on_top: + :param location: + :return: + """ + Popup(*args, button_type=POPUP_BUTTONS_ERROR, background_color=background_color, text_color=text_color, + non_blocking=non_blocking, icon=icon, line_width=line_width, button_color=button_color, auto_close=auto_close, + auto_close_duration=auto_close_duration, font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, + keep_on_top=keep_on_top, location=location) + + +# --------------------------- PopupCancel --------------------------- +def PopupCancel(*args, button_color=None, background_color=None, text_color=None, auto_close=False, + auto_close_duration=None, non_blocking=False, icon=DEFAULT_WINDOW_ICON, line_width=None, font=None, + no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)): + """ + Display Popup with "cancelled" button text + :param args: + :param button_color: + :param background_color: + :param text_color: + :param auto_close: + :param auto_close_duration: + :param non_blocking: + :param icon: + :param line_width: + :param font: + :param no_titlebar: + :param grab_anywhere: + :param keep_on_top: + :param location: + :return: + """ + Popup(*args, button_type=POPUP_BUTTONS_CANCELLED, background_color=background_color, text_color=text_color, + non_blocking=non_blocking, icon=icon, line_width=line_width, button_color=button_color, auto_close=auto_close, + auto_close_duration=auto_close_duration, font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, + keep_on_top=keep_on_top, location=location) + + +# --------------------------- PopupOK --------------------------- +def PopupOK(*args, button_color=None, background_color=None, text_color=None, auto_close=False, + auto_close_duration=None, non_blocking=False, icon=DEFAULT_WINDOW_ICON, line_width=None, font=None, + no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)): + """ + Display Popup with OK button only + :param args: + :param button_color: + :param background_color: + :param text_color: + :param auto_close: + :param auto_close_duration: + :param non_blocking: + :param icon: + :param line_width: + :param font: + :param no_titlebar: + :param grab_anywhere: + :param keep_on_top: + :param location: + :return: + """ + Popup(*args, button_type=POPUP_BUTTONS_OK, background_color=background_color, text_color=text_color, + non_blocking=non_blocking, icon=icon, line_width=line_width, button_color=button_color, auto_close=auto_close, + auto_close_duration=auto_close_duration, font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, + keep_on_top=keep_on_top, location=location) + + +# --------------------------- PopupOKCancel --------------------------- +def PopupOKCancel(*args, button_color=None, background_color=None, text_color=None, auto_close=False, + auto_close_duration=None, non_blocking=False, icon=DEFAULT_WINDOW_ICON, line_width=None, font=None, + no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)): + """ + Display popup with OK and Cancel buttons + :param args: + :param button_color: + :param background_color: + :param text_color: + :param auto_close: + :param auto_close_duration: + :param non_blocking: + :param icon: + :param line_width: + :param font: + :param no_titlebar: + :param grab_anywhere: + :param keep_on_top: + :param location: + :return: OK, Cancel or None + """ + return Popup(*args, button_type=POPUP_BUTTONS_OK_CANCEL, background_color=background_color, text_color=text_color, + non_blocking=non_blocking, icon=icon, line_width=line_width, button_color=button_color, + auto_close=auto_close, auto_close_duration=auto_close_duration, font=font, no_titlebar=no_titlebar, + grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) + + +# --------------------------- PopupYesNo --------------------------- +def PopupYesNo(*args, button_color=None, background_color=None, text_color=None, auto_close=False, + auto_close_duration=None, non_blocking=False, icon=DEFAULT_WINDOW_ICON, line_width=None, font=None, + no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)): + """ + Display Popup with Yes and No buttons + :param args: + :param button_color: + :param background_color: + :param text_color: + :param auto_close: + :param auto_close_duration: + :param non_blocking: + :param icon: + :param line_width: + :param font: + :param no_titlebar: + :param grab_anywhere: + :param keep_on_top: + :param location: + :return: Yes, No or None + """ + return Popup(*args, button_type=POPUP_BUTTONS_YES_NO, background_color=background_color, text_color=text_color, + non_blocking=non_blocking, icon=icon, line_width=line_width, button_color=button_color, + auto_close=auto_close, auto_close_duration=auto_close_duration, font=font, no_titlebar=no_titlebar, + grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) + + +############################################################################## +# The PopupGet_____ functions - Will return user input # +############################################################################## + + +# --------------------------- PopupGetFolder --------------------------- + + +def PopupGetFolder(message, title=None, default_path='', no_window=False, size=(None, None), button_color=None, + background_color=None, text_color=None, icon=DEFAULT_WINDOW_ICON, font=None, no_titlebar=False, + grab_anywhere=False, keep_on_top=False, location=(None, None), initial_folder=None): + """ + Display popup with text entry field and browse button. Browse for folder + :param message: + :param default_path: + :param no_window: + :param size: + :param button_color: + :param background_color: + :param text_color: + :param icon: + :param font: + :param no_titlebar: + :param grab_anywhere: + :param keep_on_top: + :param location: + :return: Contents of text field. None if closed using X or cancelled + """ + + + if no_window: + app = wx.App(False) + frame = wx.Frame() + + if initial_folder: + dialog = wx.DirDialog(frame, style=wx.FD_OPEN) + else: + dialog = wx.DirDialog(frame) + folder_name = '' + if dialog.ShowModal() == wx.ID_OK: + folder_name = dialog.GetPath() + return folder_name + + + + layout = [[Text(message, auto_size_text=True, text_color=text_color, background_color=background_color)], + [InputText(default_text=default_path, size=size, key='_INPUT_'), FolderBrowse(initial_folder=initial_folder)], + [Button('Ok', size=(60, 20), bind_return_key=True), Button('Cancel', size=(60, 20))]] + + _title = title if title is not None else message + window = Window(title=_title, layout=layout, icon=icon, auto_size_text=True, button_color=button_color, + background_color=background_color, + font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, + location=location) + + button, values = window.Read() + window.Close() + if button != 'Ok': + return None + else: + path = values['_INPUT_'] + return path + + + + +# --------------------------- PopupGetFile --------------------------- + +def PopupGetFile(message, title=None, default_path='', default_extension='', save_as=False, file_types=(("ALL Files", "*"),), + no_window=False, size=(None, None), button_color=None, background_color=None, text_color=None, + icon=DEFAULT_WINDOW_ICON, font=None, no_titlebar=False, grab_anywhere=False, keep_on_top=False, + location=(None, None), initial_folder=None): + """ + Display popup with text entry field and browse button. Browse for file + :param message: + :param default_path: + :param default_extension: + :param save_as: + :param file_types: + :param no_window: + :param size: + :param button_color: + :param background_color: + :param text_color: + :param icon: + :param font: + :param no_titlebar: + :param grab_anywhere: + :param keep_on_top: + :param location: + :return: string representing the path chosen, None if cancelled or window closed with X + """ + + if no_window: + app = wx.App(False) + frame = wx.Frame() + + qt_types = convert_tkinter_filetypes_to_wx(file_types) + style = wx.FD_SAVE if save_as else wx.FD_OPEN + if initial_folder: + dialog = wx.FileDialog(frame, defaultDir=initial_folder, wildcard=qt_types, + style=style) + else: + dialog = wx.FileDialog(frame, wildcard=qt_types, style=style) + if dialog.ShowModal() == wx.ID_OK: + file_name = dialog.GetPath() + else: + file_name = '' + return file_name + + browse_button = SaveAs(file_types=file_types, initial_folder=initial_folder) if save_as else FileBrowse( + file_types=file_types, initial_folder=initial_folder) + + layout = [[Text(message, auto_size_text=True, text_color=text_color, background_color=background_color)], + [InputText(default_text=default_path, size=(30,1), key='_INPUT_'), browse_button], + [Button('Ok', size=(60, 20), bind_return_key=True), Button('Cancel', size=(60, 20))]] + + _title = title if title is not None else message + + window = Window(title=_title, layout=layout, icon=icon, auto_size_text=True, button_color=button_color, font=font, + background_color=background_color, + no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) + + button, values = window.Read() + window.Close() + if button != 'Ok': + return None + else: + path = values['_INPUT_'] + return path + + + + +# --------------------------- PopupGetText --------------------------- + +def PopupGetText(message, title=None, default_text='', password_char='', size=(None, None), button_color=None, + background_color=None, text_color=None, icon=DEFAULT_WINDOW_ICON, font=None, no_titlebar=False, + grab_anywhere=False, keep_on_top=False, location=(None, None)): + """ + Display Popup with text entry field + :param message: + :param default_text: + :param password_char: + :param size: + :param button_color: + :param background_color: + :param text_color: + :param icon: + :param font: + :param no_titlebar: + :param grab_anywhere: + :param keep_on_top: + :param location: + :return: Text entered or None if window was closed + """ + + layout = [[Text(message, auto_size_text=True, text_color=text_color, background_color=background_color, font=font)], + [InputText(default_text=default_text, size=size, key='_INPUT_', password_char=password_char)], + [CloseButton('Ok', size=(60, 20), bind_return_key=True), CloseButton('Cancel', size=(60, 20))]] + + _title = title if title is not None else message + + window = Window(title=_title, layout=layout, icon=icon, auto_size_text=True, button_color=button_color, no_titlebar=no_titlebar, + background_color=background_color, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, + location=location) + + button, values = window.Read() + window.Close() + if button != 'Ok': + return None + else: + path = values['_INPUT_'] + return path + + + + +# ------------------------ PEP8-ify The SDK ------------------------# +change_look_and_feel = ChangeLookAndFeel +easy_print = EasyPrint +easy_print_close = EasyPrintClose +fill_form_with_values = FillFormWithValues +get_complimentary_hex = GetComplimentaryHex +list_of_look_and_feel_values = ListOfLookAndFeelValues +obj_to_string = ObjToString +obj_to_string_single_obj = ObjToStringSingleObj +one_line_progress_meter = OneLineProgressMeter +one_line_progress_meter_cancel = OneLineProgressMeterCancel +popup = Popup +popup_annoying = PopupAnnoying +popup_auto_close = PopupAutoClose +popup_cancel = PopupCancel +popup_error = PopupError +popup_get_file = PopupGetFile +popup_get_folder = PopupGetFolder +popup_get_text = PopupGetText +popup_no_border = PopupNoBorder +popup_no_buttons = PopupNoButtons +popup_no_frame = PopupNoFrame +popup_no_titlebar = PopupNoTitlebar +popup_no_wait = PopupNoWait +popup_non_blocking = PopupNonBlocking +popup_ok = PopupOK +popup_ok_cancel = PopupOKCancel +popup_quick = PopupQuick +popup_quick_message = PopupQuickMessage +popup_scrolled = PopupScrolled +popup_timed = PopupTimed +popup_yes_no = PopupYesNo +print_close = PrintClose +scrolled_text_box = ScrolledTextBox +set_global_icon = SetGlobalIcon +set_options = SetOptions +timer_start = TimerStart +timer_stop = TimerStop + + +#------------------------ Set the "Official PySimpleGUI Theme Colors" ------------------------ +theme(CURRENT_LOOK_AND_FEEL) + +# theme_previewer() + + +""" + d8b + Y8P + +88888b.d88b. 8888b. 888 88888b. +888 "888 "88b "88b 888 888 "88b +888 888 888 .d888888 888 888 888 +888 888 888 888 888 888 888 888 +888 888 888 "Y888888 888 888 888 + +""" + + +def main(): + + def VerLine(version, description, justification='r', size=(30,1)): + return [T(version, justification=justification, font='Any 12', text_color='yellow', size=size), T(description, font='Any 12')] + ver = version.split('\n')[0] + + # ChangeLookAndFeel('Light Brown 11') + frame_contents = [[T('Inside my frame')], + [Input(size=(5,1))], + [Input()]] + layout = [ + [Text('Welcome to PySimpleGUI!', font='Arial 15', text_color='yellow')], + VerLine(ver, 'PySimpleGUI Version'), + + VerLine(os.path.dirname(os.path.abspath(__file__)), 'PySimpleGUI Location', justification='l', size=(30, 2)), + VerLine(sys.version, 'Python Version', justification='l', size=(40, 2)), + + [Text('You should be importing this module rather than running it', justification='l', size=(50, 1))], + [Text('Here is your sample input window....')], + [Frame('FRAME with Centered Contents', frame_contents, element_justification='c')], + [InputText('Source', focus=True, size_px=(200,80)), FileBrowse()], + [InputText('Dest'), FolderBrowse()], + [Checkbox('Checkbox 1', size=(15,1)), Checkbox('Checkbox 2')], + [Radio('Radio 1', 'group', size=(15,1)), Radio('Radio 2', 'group')], + [Multiline('Multiline Input', do_not_clear=True, size=(40,4), enable_events=True)], + + [MultilineOutput('Multiline Output', size=(40,5), text_color='blue')], + [Combo(values=['Combo 1', 'Combo 2', 'Combo 3'], default_value='Combo 2', key='_COMBO_', + enable_events=True, readonly=False, tooltip='Combo box', disabled=False, font='Courier 18', + size=(12, 1))], + [Spin(values=['Spin a', 'Spin b', 'Spin c'], font='ANY 15', key='_SPIN_', size=(10, 1), enable_events=True)], + [Button('Ok'), Button('Exit')]] + + window = Window('Demo window..', layout, + # default_element_size=(35,1), + auto_size_text=True, + auto_size_buttons=True, + no_titlebar=False, + disable_close=False, + disable_minimize=True, + grab_anywhere=True, + # element_justification='r' + ) + + while True: + event, values = window.Read() + print(event, values) + + if event in (None, 'Exit'): + break + window.Close() + + +if __name__ == '__main__': + + main() + sys.exit(69) diff --git a/PySimpleGUIWx/readme.md b/PySimpleGUIWx/readme.md new file mode 100644 index 000000000..cdf8dfe2b --- /dev/null +++ b/PySimpleGUIWx/readme.md @@ -0,0 +1,459 @@ + +![pysimplegui_logo](https://user-images.githubusercontent.com/13696193/43165867-fe02e3b2-8f62-11e8-9fd0-cc7c86b11772.png) + +![Downloads](http://pepy.tech/badge/pysimpleguiwx) + + ![Awesome Meter](https://img.shields.io/badge/Awesome_meter-1000-yellow.svg) + + ![Python Version](https://img.shields.io/badge/Python-3.x-yellow.svg) + + +[![PyPI Version](https://img.shields.io/pypi/v/pysimpleguiwx.svg?style=for-the-badge)](https://pypi.org/project/pysimpleguiwx/) + + +# PySimpleGUIWx + +The WxPython port of PySimpleGUI + +## Primary PySimpleGUI Documentation + +To get instructions on how use PySimpleGUI's APIs, please reference the [main documentation](http://www.PySimpleGUI.org). +This Readme is for information ***specific to*** the WxPython port of PySimpleGUI. + + +## Why Use PySimpleGUIWx Over The Other Ports? + +PySimpleGUIWx brings the number of PySimpleGUI ports to 3. + +Why use PySimpleGUIWx over PySimpleGUIQt PySimpleGUI (tkinter version)? + +There are a couple of easy reasons to use PySimpleGUIWx over PySimpleGUIQt. One is footprint. PyInstaller EXE for PySimpleGUIWx is 9 MB, on Qt it's 240 MB. Another is cool widgets. + +WxPython has some nice advanced widgets that will be offered though PySimpleGUIWx, hopefully sooner than later. + +The System Tray feature works well with a feature set identical to PySimpleGUIQt. If you are looking for a System Tray feature, PySimpleGUIWx is recommended over PySimpleGUIQt ; the primary reason being size of the WxPython framework versus the size of Qt. They both give you very similar features. They look and behave in an ***identical*** fashion when using PySimpleGUI. That's the beauty of the PSG SDK, the function calls are the same for all implementations of PySimpleGUI. The source code is highly portable between the GUI frameworks. + +This simple list is another way of looking at the question.... + +1. It's simple and easy to program GUIs +2. You can move between the GUI frameworks tkinter, Qt and WxPython by changing a single line of code, the import statement. +3. Get the same custom layout and access to the same widgets but in a simple, easy to use and understand interface. +4. It's fun to program GUIs again + + + ## Engineering Pre-Release Version 0.13.0 + + [Announcements of Latest Developments](https://github.com/MikeTheWatchGuy/PySimpleGUI/issues/142) + +Having trouble? Visit the [GitHub site ](http://www.PySimpleGUI.com) and log an Issue. + + +## What Works + +Remember, these are Engineering Releases. Not all features are complete, but generally speaking those that are marked as completed and working are working quite well. It's not an "Engineering Quality". The completed features are at about a Beta level. + +### Ready to use + +#### Elements + +* Text +* Input Text +* Buttons including file/folder browse +* Input multiline +* Output multiline +* Output +* Columns +* Frames - except cannot set colors yet +* Progress Meters +* Checkbox +* Radio Button +* Combobox +* Spinner +* Vertical and Horizontal Separators + + +#### Features + +* System Tray +* Debug Print +* Invisible/Visible Elements +* All Popups +* Check box +* Keyboard key events +* Mouse wheel events +* Multiple windows +* Read with timeout +* Background images +* One Line Progress Meter (tm) +* Auto-closing windows +* No titlebar windows +* Grab anywhere windows +* Alpha channel +* Window size +* Window disappear/reappear +* Get screen size +* Get window location +* Change window size +* Window move +* Window minimize +* Window maximize +* Window Disable +* Window Enable +* Window Hide +* Window UnHide +* Window Bring to front +* Look and Feel settings +* Default Icon +* Base64 Icons +* PEP8 bindings for all element methods and functions + + +It won't take long to poke at these and hit errors. For example, the code to do Button Updates is not complete. Most of the time you won't be doing this. + +Due to the small size of the development team, features may feel a little "thin" for a while. The idea is to implement with enough depth that 80% of the uses are covered. It's a multi-pass, iterative approach. + +If you, the reader, are having problems or have hit a spot where something is not yet implemented, then open an Issue. They are often completed in a day. This process of users pushing the boundaries is what drives the priorities for development. It's "real world" kinds of problems that have made PySimpleGUI what it is today. + + + +## SystemTray + +This was the first fully functioning feature of PySimpleGUIWx. Previously only the Qt port supported the System Tray. Why use Wx? The footprint is much much smaller. An EXE file created using PyInstaller is 9 MB for PySimpleGUIWx, when using Qt it's 240 MB. + +Now it's possible to "tack on" the System Tray to your PySimpleGUI application. + +If you're unable to upgrade to Qt but want the System Tray feature, then adding PySimpleGUIWx to your project may be the way to go. + +You can mix your System Tray's event loop with your normal Window event loop by adding a timeout to both your Window.Read call and your SystemTray.Read call. + +### Source code compatibility + +PySimpleGUIWx's System Tray feature has been tested against the same PySimpleGUIQt feature. As long as you don't use features that are not yet supported you'll find your source code will run on either PySimpleGUIQt or PySimpleGUIWx by changing the import statement. + + +## System Tray Design Pattern + +Here is a design pattern you can use to get a jump-start. + +This program will create a system tray icon and perform a blocking Read. + +```python +import PySimpleGUIWx as sg + +tray = sg.SystemTray(menu= ['menu',['Open', ['&Save::KEY', '---', 'Issues', '!Disabled'], 'E&xit']], + filename=r'C:\Python\PycharmProjects\GooeyGUI\default_icon.ico') +tray.ShowMessage('My Message', 'The tray icon is up and runnning!') +while True: + event = tray.Read() + print(event) + if event == 'Exit': + break +``` + + +## Menu Definitions + +See the original, full documentation for PySimpleGUI to get an understanding of how menus are defined. + + +## SystemTray Methods + +### Read - Read the context menu or check for events + +```python +def Read(timeout=None) + ''' + Reads the context menu + :param timeout: Optional. Any value other than None indicates a non-blocking read + :return: String representing meny item chosen. None if nothing read. + ''' +``` +The `timeout` parameter specifies how long to wait for an event to take place. If nothing happens within the timeout period, then a "timeout event" is returned. These types of reads make it possible to run asynchronously. To run non-blocked, specify `timeout=0`on the Read call (not yet supported). + +Read returns the menu text, complete with key, for the menu item chosen. If you specified `Open::key` as the menu entry, and the user clicked on `Open`, then you will receive the string `Open::key` upon completion of the Read. + +#### Read special return values + +In addition to Menu Items, the Read call can return several special values. They include: + +EVENT_SYSTEM_TRAY_ICON_DOUBLE_CLICKED - Tray icon was double clicked +EVENT_SYSTEM_TRAY_ICON_ACTIVATED - Tray icon was single clicked +EVENT_SYSTEM_TRAY_MESSAGE_CLICKED - a message balloon was clicked +TIMEOUT_KEY is returned if no events are available if the timeout value is set in the Read call + + +### ShowMessage + +Just like Qt, you can create a pop-up message. Unlike Qt, you cannot set your own custom icon in the message, at least you can't at the moment. + +The preset `messageicon` values are: + + SYSTEM_TRAY_MESSAGE_ICON_INFORMATION + SYSTEM_TRAY_MESSAGE_ICON_WARNING + SYSTEM_TRAY_MESSAGE_ICON_CRITICAL + SYSTEM_TRAY_MESSAGE_ICON_NOICON + +```python +ShowMessage(title, message, filename=None, data=None, data_base64=None, messageicon=None, time=10000): + ''' + Shows a balloon above icon in system tray + :param title: Title shown in balloon + :param message: Message to be displayed + :param filename: Optional icon filename + :param data: Optional in-ram icon + :param data_base64: Optional base64 icon + :param time: How long to display message in milliseconds :return: + ''' +``` + +### Update + +You can update any of these items within a SystemTray object +* Menu definition +* Icon (not working yet) +* Tooltip + + Change them all or just 1. + +```python +Update(menu=None, tooltip=None,filename=None, data=None, data_base64=None,) + ''' + Updates the menu, tooltip or icon + :param menu: menu defintion + :param tooltip: string representing tooltip + :param filename: icon filename + :param data: icon raw image + :param data_base64: icon base 64 image + :return: + ''' +``` +## Menus with Keys + +You can add a key to your menu items. To do so, you add :: and the key value to the end of your menu definition. + +`menu_def = ['File', ['Hide::key', '&Open::key', '&Save',['1', '2', ['a','b']], '&Properties', 'E&xit']]` + +The menu definition adds a key "key" to the menu entries Hide and Open. + +If you want to change the separator characters from :: top something else,change the variable `MENU_KEY_SEPARATOR` + +When a menu item has a key and it is chosen, then entire string is returned. If Hide were selected, then Hide::key would be returned from the Read. Note that the shortcut character & is NOT returned from Reads. + + +## Popups + +Starting with release 0.4.0, most of the Popup functions work. This means you can do things like show information in a window when there's a choice made in a System Tray menu. Or if your program finds some event it wishes to inform the user about. For example, when new Issues are posted on a GitHub project. + + +# Release Notes: + +### 0.1.0 - 25-Dec-2018 + +* Support for SystemTray + * Read, with or without a timeout + * Catch single click, double click events + * Source code compatiable with Qt + +### 0.2.0 - 26-Dec-2018 + +* Correctly handling base64 images +* Support for clicking message balloon +* Can Hide and UnHide the icon + + +### 0.3.0 - 27-Dec-2018 + +* Hooked up buttons! +* Browse file button is only file/folder button that works +* Text, Input and Button elements are the only working elements +* SystemTray can take any kind of image as icon +* Read with Timeout (non-zero) works +* Popups + + +### 0.4.0 PySimpleGUIWx 30-Dec-2018 + +* Text Element - colors, font work +* Text Update method works +* Button - Close button implemented +* Button - Implemented basic button, correctly presented Values on Read +* Button - Can now set font +* Changed overall "App" variable usage for better mainloop control +* Windows - Timeouts and non-blocking Reads work +* Windows - Autoclose works +* Windows - Non-blocking calls supported (timeout=0) +* Windows - Grab anywhere works +* Windows - No title-bar works +* Windows - Location and Size working correctly +* Correctly adding element padding to Text, Input, Buttons +* Popups - most Popups work (except for the input type that involve folders) + +### 0.5.0 PySimpleGUIWx 6-Jan-2019 + +* New element - Multiline input +* New element - Multiline output +* Borderless Windows +* Grab anywhere windows +* Alpha channel for windows +* Finishing up the Text and Input Text Elements +* Visibility for all Elements +* Input Get / Set focus +* Output element - unable to get stdout to re-route +* Debug window works + + +### 0.6.0 9-Jan-2019 + +* Column Element +* Checkbox Element with events +* Output Element +* Background Image (I think works) +* Debug Print +* One Line Progress Meter +* All Popups works + +### 0.7.0 PySimpleGUIWx 21-Jan-2019 + +* Element.Update support for disabled and tooltip +* Combo Element +* Newest Combo parameters +* Radio Element +* Newest Radio parameters (size_px, visible, enable_events) +* Type hints on Wx widgets +* Spinner Element +* Newest Spinner parameters +* Text Element visibility +* Column Element size_px parameter (unclear if works... likely does not) +* Column visibility +* Column Update method added +* System Tray - support for any kind of image format for icons +* Window.Move +* Window.Minimize +* Window.Maximize +* Window.Disable +* Window.Enable +* Window.Hide +* Window.UnHide +* Window.BringToFront +* Popup non_blocking - returns window and button not just button +* More comprehensive test harness when running PySimpleGUIWx.py + +### 0.8.0 20-Feb-2019 PySimpleGUIWx + +* Big Try/Except block around Update method for multiline in case window closed +* Text - convert incoming text to string right away +* Text.Update - convert incoming value to string +* Completed Button.Update method. Can now change text, color, etc. +* Added Try around reading multiline input value - not sure why needed +* OneLineProgressMeter - can update text on every call now + +### 0.9.0 06-Mar-2019 PySimpleGUIWx + +* Addition of Assert Suppression + * This was needed for a multi-threaded version of PySimpleGUIWx + * Complained when exiting a system tray if did not make this change and ran the tray in a thread +* Tray.Close now correctly Hides the icon +* SetGlobalIcon functional +* Can also now set icon using SetOptions call + + +### 0.10.0 23-Mar-2019 PySimpleGUIWx + +* `do_not_clear` is now TRUE by default on Input and Multiline elements!! + + +## 0.11.0 11-Apr-2019 PySimpleGUIWx + +* NEW Window parameter layout so can skip calling Layout + +## 0.13.0 1-OCT-2019 PySimpleGUIWx + +* Version numbering using sg.version string +* PEP8 bindings! +* Improved scaling of character to pixel sizes of elements that are multilined +* Added Metadata variable to all elements +* Renamed element callback functions to start with _ +* Removed __del__ methods everywhere except Output Element +* Can "Call" an element which will call its Update method +* InputText element - convert default text and password char to string +* Removed old code such as tkinter's tooltip and drag and drop from Qt +* Shortcut I for InputText +* Listbox added size_px parm +* Changed type checking to use the comment style types +* Added Element.Widget to all Elements so can access the Wx widgets directly +* Text Element now defaults to '' so no need to specify anything if a blank Text Element (often used for output) +* Button text converted to string when creating button +* New Button shortcuts - B, Btn +* VerticalSeparator - Newly supported Element +* HorizontalSeparator - Newly supported Element +* Slider - added size_px parm +* Fixed leak caused by System Tray not cleaning up the timer +* Window - added finalize paramter so can skip using chained .Finalize() +* Window - AllKeysDict now used like other PySimpleGUI ports. Has all the keys and elements in a window +* Window.FindElement - added silent_on_error parm like other ports have +* Window[key] construct added that calls FindElement +* window() - can "Call" a window you've created. Will call Window.Read() +* Popup buttons no longer use CloseButtons for normal popups. Calls window.Close manually +* PopupGetFolder changed to use keys, normal button, new window design patterns +* PopupGetFile changed to use keys, normal buttons, new window design patterns +* PopupGetText changed to use keys, normal buttons, new window design patterns +* Default application (PySimpleGUI.main) now shows the version number like other PySimpleGUI ports + +## 0.13.0 17-Nov-2019 PySimpleGUIWx + +* 105 Look and Feel Themes to choose from! +* New "Fuzzy" look and feel selection +* Preview all look and feels not yet supported due to lack of Frame support + +## 0.15.0 PySimpleGUIWx 24-Dec-2019 + +Themes! + +* Picked up the new "theme" APIs like all 4 ports got +* Dark Blue 3 is the new official color theme for PySimpleGUI +* Added "port" string so that your code can detect which port of PySimpleGUI is being executed +* Removed restriction on Macs (totally didn't make sense that it was there as it blocked a tkinter problem, not a Wx one) +* Depricated the TRANSPARENT_BUTTON variable as it was being misunderstood by users and was misleading +* BROWSE_FILES_DELIMITER can be changed to change the default ';' delimeter between filenames in FilesBrowse button +* Frame Element! BUT, it's only a partial solution as I am unable to set the background color (need to understand how panels work). It's better than nothing + + +## 0.16.0 PySimpleGUIWx 6-May-2020 + +* Added constants + * WIN_CLOSED and WINDOW_CLOSED + * EVENT_TIMEOUT and TIMEOUT_EVENT +* Added Graph.change_coordinates method +* Added close parameter to Window.read + + +## 0.17.0 PySimpleGUIWx 6-Jun-2020 + +Element justification within Window and Containers! Finally a unified justification + +* When any Radio element is updated to be False, the entire GROUP is reset so nothing is selected +* element_jutification added so that all elements inside these will be justified accordingly. + * For PySimpleGUIQt only, the default is "float" which sets nothing. Buttons will stretch across the window as result + * Valid values are 'l', 'r', 'c'. You can spell it out, but only first letter is used. + * Window + * Frame + * Column + * Tab + +## 0.17.1 PySimpleGUIWx 7-Jun-2020 + +* Quick patch of Multiline.update so that newlines are recognized correctly + + +# Design +# Author + Mike B. + + +# License + GNU Lesser General Public License (LGPL 3) + + +# Acknowledgments + \ No newline at end of file diff --git a/PySimpleGUI_Logo_640.png b/PySimpleGUI_Logo_640.png new file mode 100644 index 000000000..0de414a32 Binary files /dev/null and b/PySimpleGUI_Logo_640.png differ diff --git a/PySimpleGUIdebugger/readme.md b/PySimpleGUIdebugger/readme.md new file mode 100644 index 000000000..f1b09c709 --- /dev/null +++ b/PySimpleGUIdebugger/readme.md @@ -0,0 +1,28 @@ + +![PySimpleGUI_Debugger_Logo](https://user-images.githubusercontent.com/13696193/58375496-38cbb280-7f22-11e9-99b8-286fe1fa41b5.png) + +## is no more.... but `imwatching` you now the same thing + + +# Project renamed to: +# `imwatchingyou` + +So head over to that project page. +https://github.com/PySimpleGUI/imwatchingyou + +---------------------- + +To install it: + +`pip install imwatchingyou` + +To use it, check out the Demo Program on the project's page. + +---------------------- + +About the creepy title + +Don't worry, I'm not watching YOU... + +#### I'm not watching you, YOU are watching YOUR CODE + diff --git a/README.md b/README.md deleted file mode 100644 index 53aacd02e..000000000 --- a/README.md +++ /dev/null @@ -1,177 +0,0 @@ - -

- - -

- -![](https://PySimpleGUI.net/images/emojis/news_112.png) - -# 2026 PySimpleGUI Closure in January 2026 - -The PySimpleGUI project’s planned shutdown was first announced in February 2025. At that time, we committed to supporting our Commercial customers through the end of 2025. PySimpleGUI 5 remained a very stable product throughout the year, with no significant issues reported. - -Now that we’ve reached the end of that support period, the project is entering its final stage. During January 2026, the PySimpleGUI website, documentation, and PyPI servers will be taken offline as we officially close the project. - -## Private PyPI Server *** GOING OFFLINE JAN 2026 *** - -The private PyPI server will be shut down in **January 2026** -. -If you currently install PySimpleGUI 5 using `pip`, you’ll need to switch to installing from a local wheel file instead. You can do this using the command: - -`python -m pip install wheelfile.whl` - - -### Downloading Wheels - -To prepare for the server shutdown please download the wheel file for the version of PySimpleGUI you're currently running. The latest release is 5.0.10 and is located here: - -[PySimpleGUI 5.0.10](https://pysimplegui.net/install/pysimplegui/PySimpleGUI-5.0.10-py3-none-any.whl) - -Here are some older releases (but everyone should be on 5.0.10 now anyway): - -[PySimpleGUI 5.0.9](https://pysimplegui.net/install/pysimplegui/PySimpleGUI-5.0.9-py3-none-any.whl) -[PySimpleGUI 5.0.8](https://pysimplegui.net/install/pysimplegui/PySimpleGUI-5.0.8-py3-none-any.whl) -[PySimpleGUI 5.0.7](https://pysimplegui.net/install/pysimplegui/PySimpleGUI-5.0.7-py3-none-any.whl) -[PySimpleGUI 5.0.6](https://pysimplegui.net/install/pysimplegui/PySimpleGUI-5.0.6-py3-none-any.whl) - -### Installing a Wheel - -After you've downloaded the wheel file and saved it to your local machine, install it using this pip command: - -`python -m pip install PySimpleGUI-5.0.10-py3-none-any.whl` - - -## Final Build of PySimpleGUI 5 - - - ### Commercial Licensees - -A final version, **PySimpleGUI 5.0.2026.0**, has been produced for Commercial users. This release includes relaxed security and licensing restrictions to help ensure it will continue to run indefinitely, and to allow you to make fixes if ever needed. - - -It will be available for download **soon** by logging into your account on [PySimpleGUI.com](https://pysimplegui.com). After logging in, you’ll find a download link to the wheel file. To install the downloaded wheel file, run the command: - -`python -m pip install PySimpleGUI-5.0.2026.0-py3-none-any.whl` - -**Important:** -This final release is licensed for Commercial users only. Please do not share or post it publicly. - - - -### Hobbyist users - -Please note that Hobbyist keys have been discontinued and will expire this year (if they haven’t already). If you wish to continue running your PySimpleGUI code, you have a few options: - -- Port your code to use PySimpleGUI 4 (or compatible projects such as *FreeSimpleGUI*). -- Upgrade to a Commercial License to access version 5.0.2026.0, which does not include key restrictions. - - -## PySimpleGUI 5 Documentation - -The PySimpleGUI 5 documentation hosted on ReadTheDocs will go offline this month. -An archived copy of the final documentation will remain available on GitHub at: - -[https://pysimplegui.github.io/PSG5Docs/](https://pysimplegui.github.io/PSG5Docs/) - -The PySimpleGUI.com Documentation link will be pointed to the offline version once we shutdown the ReadTheDocs account. - -## PySimpleGUI GitHub Repos - -All PySimpleGUI GitHub repositories will be set to read-only mode but will remain publicly accessible for reference. - -# Thank you - -Thank you to everyone who used, supported, and contributed to PySimpleGUI over the years. It’s been a rewarding journey, and your enthusiasm made this project possible. - - --------------------------------- - - # Announcement from Feb 2025 - -## Two Important updates about PySimpleGUI - -![](https://PySimpleGUI.net/images/emojis/search_56.png) - -## 1. New Package Location - -We were recently informed by PyPI that PySimpleGUI does not meet updated PyPI Terms of Service, that it needs to be removed, and hosted on a private server. As a result, you’ll need to add a parameter to your pip install commands in order to access the PySimpleGUI private PyPI server. -The parameter to add is: - -`--extra-index-url https://PySimpleGUI.net/install ` - -### To force a reinstall of PySimpleGUI from new server - -`python -m pip install --force-reinstall --extra-index-url https://PySimpleGUI.net/install PySimpleGUI` - - -### Performing an upgrade - -This command will also install needed modules like rsa from PyPI automatically - -The basic install/upgrade command **was**: - -`python -m pip install –-upgrade PySimpleGUI` - -or for Linux/Mac - -`python3 -m pip install –-upgrade PySimpleGUI` - -The **new command** with the new parameter is: - -`python -m pip install --upgrade --extra-index-url https://PySimpleGUI.net/install PySimpleGUI` - -### Uninstall May Be Needed If Error - -If you're getting errors, please uninstall PySimpleGUI entirely and install again using the new parameter. - - -### BUG - Commercial Key Expiration - Upgrade to 5.0.10 - -There is a bug in versions of PySimpleGUI older than 5.0.10 that causes an erroneous expired error when using a Commercial Developer key. These keys do not expire and shouldn't not be generating the error. - -A fix was released in version 5.0.10 on 2-Apr-2025. **Please upgrade to version 5.0.10** so that your key doesn't generate an expiration error. - -![](https://PySimpleGUI.net/images/emojis/wave_56.png) - - -## 2. PySimpleGUI Shutdown - -We gave it our best shot…. After 7 years of attempting to make the PySimpleGUI project sustainable, we are stopping the PySimpleGUI project. - -If you've followed the project over the years, you'll have read about the difficulties that all open-source projects face in generating enough income to pay for the project, seen the requests for sponsorships, and attempts to generate income via a Udemy course. There was not enough income to cover the costs of running a business and, of course, wasn’t able to generate any income for our small team. This isn’t a sustainable situation. - -## One Year Update PySimpleGUI 5 - -It's been a little over a year since the release of PySimpleGUI 5. Of the 100,000’s of Version 5 users, 10,000's of which were large corporate users, only 600 people paid the $99 for a commercial license. - -## End of PySimpleGUI Project - -The revenue generated was not enough to cover the basic costs, so we've made the difficult decision to end the PySimpleGUI project. - -## Support for Commercial Users - -Unlike traditional software companies, where stopping business means support ends immediately, we thought it would be classier to go the extra mile by continuing to provide support to Commercial License users this year as a way of saying "thank you" for your help in trying to give the project a viable future. Please provide your Priority Support code or your submission will be automatically blocked. We'll do the best we can to help with the limited resources we've got. - -Your license doesn’t expire so you’ll be able to continue to run your applications at the end of the year we’re providing maintenance and beyond. We’ll be distributing an offline version of the documentation so that you’ll have it for the future. - -## Hobbyists - -Hobbyists can continue to use PySimpleGUI 5 until their keys expire. After that you'll need to switch to version 4, which you'll find 1,000s of copies on GitHub with at least 1 being community supported. - -If you wish to use PySimpleGUI without the key expiring or want support, then you can buy a Commercial License which is good perpetually. - -## Websites Availability - -The PySimpleGUI registration and documentation websites will continue to operate for a couple of months to give commercial customers an opportunity to create distribution keys. No new Hobbyist keys will be available. - -![](https://PySimpleGUI.net/images/emojis/pray_56.png) - -## Thank you to everyone - -PySimpleGUI has been an experience of a lifetime, and we’ve -enjoyed watching & helping people create incredible applications. - -## Business Partnership Inquires - -If you're a business with a serious partnership that you wish to discuss, email mike@PySimpleGUI.com. - - diff --git a/ThemeMaker/Theme_Maker.py b/ThemeMaker/Theme_Maker.py new file mode 100644 index 000000000..ff8c3130f --- /dev/null +++ b/ThemeMaker/Theme_Maker.py @@ -0,0 +1,262 @@ +import PySimpleGUI as sg +import color_themes + +""" + Program that is used to create new themes for use with PySimpleGUI's "Look and Feel" settings. + You are presented with a grid of mini-windows that is created for color palettes downloaded from https://colorhunt.co/palettes + The file color_themes.py contains a large dictionary of approx 1780 palettes. + + For each palette you are shown 4 candidate themes, 2 "light" and 2 "dark". The window shows 5 palettes so you'll have a + total of 20 candidate themes displayed in total. + Each candidate theme has a 3 options - The button color (text and background), the text color for Input/Multiline elements, + and the name of the theme when you save it. These you choose using the radio buttons and one input field. + To "save" one of these candidate themes, check the checkbox to the left of the layout, choose the radio buttons for button + & text settings and optionally change the theme name that is shown above the grid of OK buttons. By default the name starts + with either "Dark" or "Light" and is followed by the first 2 "tags" that were posted with the palette on the colorhunt site. + + After you've selected the themes you want to save from the window of 20 click any "OK" button in the window or close the + window with the "X". You will see the dictionary text in the Debug Window and the values will also be written to a file. + You'll then be shown the next group of 20 candidate themes. + + If you want to exit the program entirely, click any "Cancel" button the page. Note - cliicking "Cancel" will not save any + theme you have checked with the checkbox. You should only exit from a window you have not selected any themes for saving + + If a Theme is selected for saving, then the values for the LOOK_AND_FEEL dictionary are displayed in a debug window and are + also appended to the file new_theme_dict.py. You will need to edit the new_theme_dict.py file to get the syntax correct. + A "," or "}" may need to be added in order to make the table be correct. + + If you're using this program it's assumed you know what you're doing and understand the LOOK_AND_FEEL dictionary and can + figure out how to get the syntax correct for adding it to the main dictionary of themes. +""" + +#----------------- Window to get layout for window ---------# + +CANDIDATES_PER_ROW = 4 +PALETTES_PER_WINDOW = 5 +STARTING_PALETTE = 0 +sg.change_look_and_feel('Dark Blue 3') +layout = [ + [sg.T('Choose your window layout (default is a huge window)')], + [sg.In(default_text=CANDIDATES_PER_ROW),sg.T('Candidates Per Row')], + [sg.In(default_text=PALETTES_PER_WINDOW),sg.T('Palettes Per Window (4 candidates for each)')], + [sg.In(default_text=0),sg.T(f'Starting palette number of {len(color_themes.themes)} palettes')], + [sg.OK()]] +window = sg.Window('Choose Theme Layout', layout,default_element_size=(4,1)) +event, values = window.read() +window.close() + +if event is None: + sg.popup_no_buttons('Aborting....', no_titlebar=True, auto_close=True, keep_on_top=True) + exit() +try: + CANDIDATES_PER_ROW = int(values[0]) + PALETTES_PER_WINDOW = int(values[1]) + STARTING_PALETTE = int(values[2]) +except: + sg.popup_no_buttons('Bad input... Aborting....', no_titlebar=True, auto_close=True, keep_on_top=True) + exit() + +TOTAL_CANDIDATES_PER_PAGE = PALETTES_PER_WINDOW * 4 +#-----------------------------------------------------------# + +def rgb_to_hsl(r, g, b): + r = float(r) + g = float(g) + b = float(b) + high = max(r, g, b) + low = min(r, g, b) + h, s, v = ((high + low) / 2,)*3 + if high == low: + h = s = 0.0 + else: + d = high - low + l = (high + low) / 2 + s = d / (2 - high - low) if l > 0.5 else d / (high + low) + h = { + r: (g - b) / d + (6 if g < b else 0), + g: (b - r) / d + 2, + b: (r - g) / d + 4, + }[high] + h /= 6 + return h, s, v + +def hex_to_rgb(hex): + hex = hex.lstrip('#') + hlen = len(hex) + return tuple(int(hex[i:i + hlen // 3], 16) for i in range(0, hlen, hlen // 3)) + + +def sorted_tuple(tup, position): + tup.sort(key=lambda x: x[position]) + return tup + +sg.popup_quick_message('Hang on this could me a few moments....', background_color='red', text_color='white', keep_on_top=True) + +sg.LOOK_AND_FEEL_TABLE = {} # Entirely replace the look and feel table in PySimpleGUI +palette_counter = 0 +for key, colors in color_themes.themes.items(): + if palette_counter < STARTING_PALETTE: + palette_counter += 1 + continue + # Sort the colors from darkest to lightest + color_lightness_pairs = [] + for color in colors: + if type(color) in (tuple, list): + continue + r,g,b = hex_to_rgb(color) + lightness = (rgb_to_hsl(r=r, g=g, b=b))[2] + color_lightness_pairs.append((lightness, color)) + sorted_colors_tuples = sorted_tuple(color_lightness_pairs, 0) # sort the pairs by the first item (lightness) + scolors = [c for l, c in sorted_colors_tuples] # Colors sorted from darkest to lightest + # Create a "Dark" and a "Light" theme based on the sorted colors + sg.LOOK_AND_FEEL_TABLE['Dark'+key] = {'BACKGROUND': scolors[0], + 'TEXT': scolors[3], + 'INPUT': scolors[2], + 'TEXT_INPUT': '#000000', + 'SCROLL': scolors[2], + 'BUTTON': ('#FFFFFF', scolors[1]), + 'PROGRESS': sg.DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST':scolors, + 'DESCRIPTION':colors[4]} + + sg.LOOK_AND_FEEL_TABLE['Light'+key] = {'BACKGROUND': scolors[3], + 'TEXT': scolors[0], + 'INPUT': scolors[1], + 'TEXT_INPUT': '#FFFFFF', + 'SCROLL': scolors[0], + 'BUTTON': ('#FFFFFF', scolors[2]), + 'PROGRESS': sg.DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': scolors, + 'DESCRIPTION':colors[4]} + + sg.LOOK_AND_FEEL_TABLE['Dark2'+key] = {'BACKGROUND': scolors[1], + 'TEXT': scolors[3], + 'INPUT': scolors[2], + 'TEXT_INPUT': '#000000', + 'SCROLL': scolors[2], + 'BUTTON': ('#FFFFFF', scolors[1]), + 'PROGRESS': sg.DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST':scolors, + 'DESCRIPTION':colors[4]} + + + sg.LOOK_AND_FEEL_TABLE['Light2'+key] = {'BACKGROUND': scolors[2], + 'TEXT': scolors[0], + 'INPUT': scolors[1], + 'TEXT_INPUT': '#FFFFFF', + 'SCROLL': scolors[0], + 'BUTTON': ('#FFFFFF', scolors[2]), + 'PROGRESS': sg.DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': scolors, + 'DESCRIPTION':colors[4]} + + +WINDOW_BACKGROUND = 'lightblue' + +def sample_layout(theme_name, colors, description): + name = 'Dark' if theme_name.startswith('D') else 'Light' + name += "".join(description[:2]) + layout = [[sg.Text('Text element', size=(12,1)), sg.InputText(' '.join(colors),text_color='#000000' ),sg.Radio('',theme+'1', key='-INPUT_RAD0-'+theme, default=True, metadata='#000000'), + sg.Slider((0,10),size=(10,20), orientation='h')], + [sg.T(size=(12,1)), sg.InputText(colors[0], text_color='#FFFFFF'),sg.Radio('',theme+'1', key='-INPUT_RAD1-'+theme, metadata='#FFFFFF')], + [sg.T(size=(12,1)), sg.InputText(colors[0], text_color=colors[0]),sg.Radio('',theme+'1', key='-INPUT_RAD2-'+theme, metadata=colors[0])], + [sg.T(size=(12,1)),sg.InputText(colors[3], text_color=colors[3]),sg.Radio('',theme+'1', key='-INPUT_RAD3-'+theme, metadata=colors[3])], + [sg.T(', '.join(description)), sg.In(name, key='-NEW_THEME_NAME-'+theme)], + [sg.Button('OK'), sg.Radio('',theme+'2',key='-BTN_RAD1-'+theme, default=True, metadata=sg.DEFAULT_BUTTON_COLOR), + sg.Button('OK', button_color=('white', colors[0])),sg.Radio('',theme+'2',key='-BTN_RAD2-'+theme, metadata=('white', colors[0])), + sg.Button('OK', button_color=('black', colors[0])),sg.Radio('',theme+'2',key='-BTN_RAD9-'+theme, metadata=('black', colors[0])), + sg.Button('OK', button_color=('white', colors[3])),sg.Radio('', theme+'2', key='-BTN_RAD10-' + theme, metadata=('white', colors[3])), + sg.Button('OK', button_color=('black', colors[3])),sg.Radio('', theme+'2', key='-BTN_RAD11-' + theme, metadata=('black', colors[3]))], + [sg.Button('OK', button_color=(colors[0],colors[1])),sg.Radio('',theme+'2',key='-BTN_RAD3-'+theme, metadata=(colors[0], colors[1])), + sg.Button('OK', button_color=(colors[2],colors[1])),sg.Radio('',theme+'2',key='-BTN_RAD4-'+theme, metadata=(colors[2], colors[1])), + sg.Button('OK', button_color=(colors[3],colors[1])),sg.Radio('',theme+'2',key='-BTN_RAD5-'+theme, metadata=(colors[3], colors[1])), + sg.Button('OK', button_color=(colors[3],colors[0])),sg.Radio('',theme+'2',key='-BTN_RAD7-'+theme, metadata=(colors[3], colors[0])), + sg.Button('OK', button_color=(colors[0],colors[3])),sg.Radio('',theme+'2',key='-BTN_RAD8-'+theme, metadata=(colors[0], colors[3])), + sg.Button('Cancel', button_color=(colors[3], colors[2])),sg.Radio('',theme+'2',key='-BTN_RAD6-'+theme, metadata=(colors[3], colors[2])), + ] ] + return layout +# layout = [[sg.Text('Here is list of some themes', font='Default 18', background_color=WINDOW_BACKGROUND)]] +layout = [] +row = [] +layouts = [] +for count, theme in enumerate(sg.LOOK_AND_FEEL_TABLE.keys()): + sg.change_look_and_feel(theme) + if count and not(count % CANDIDATES_PER_ROW): + layout += [row] + row = [] + row += [sg.CB('',text_color='black', background_color=WINDOW_BACKGROUND, key='-CB-'+theme)] + row += [sg.Frame(theme, sample_layout(theme, sg.LOOK_AND_FEEL_TABLE[theme]['COLOR_LIST'], sg.LOOK_AND_FEEL_TABLE[theme]['DESCRIPTION']))] + if count and not (count % TOTAL_CANDIDATES_PER_PAGE): + if layout: + layouts.append(layout) + layout = [] +if row: + layout += [row] +if layout: + layouts.append(layout) + +for layout in layouts: + window = sg.Window('PySimpleGUI Theme Maker', layout, background_color=WINDOW_BACKGROUND, default_element_size=(30,1)) + event, values = window.read() + if event is not None and event.startswith('Cancel'): + break + for key, value in values.items(): + if type(key) is str and key.startswith('-CB-') and value: + theme = key[4:] + theme_entry = sg.LOOK_AND_FEEL_TABLE[theme] + if values['-INPUT_RAD1-'+theme]: + input_text_color = window['-INPUT_RAD1-'+theme].metadata + elif values['-INPUT_RAD2-'+theme]: + input_text_color = window['-INPUT_RAD2-'+theme].metadata + elif values['-INPUT_RAD3-'+theme]: + input_text_color = window['-INPUT_RAD3-'+theme].metadata + elif values['-INPUT_RAD0-'+theme]: + input_text_color = window['-INPUT_RAD0-'+theme].metadata + else: + print('** ERROR none of the radio buttons are true for input text **') + continue + + if values['-BTN_RAD1-'+theme]: + b_color = window['-BTN_RAD1-'+theme].metadata + elif values['-BTN_RAD2-'+theme]: + b_color = window['-BTN_RAD2-'+theme].metadata + elif values['-BTN_RAD3-'+theme]: + b_color = window['-BTN_RAD3-'+theme].metadata + elif values['-BTN_RAD4-'+theme]: + b_color = window['-BTN_RAD4-'+theme].metadata + elif values['-BTN_RAD5-'+theme]: + b_color = window['-BTN_RAD5-'+theme].metadata + elif values['-BTN_RAD6-'+theme]: + b_color = window['-BTN_RAD6-'+theme].metadata + elif values['-BTN_RAD7-'+theme]: + b_color = window['-BTN_RAD7-'+theme].metadata + elif values['-BTN_RAD8-'+theme]: + b_color = window['-BTN_RAD8-'+theme].metadata + elif values['-BTN_RAD9-'+theme]: + b_color = window['-BTN_RAD9-'+theme].metadata + elif values['-BTN_RAD10-'+theme]: + b_color = window['-BTN_RAD10-'+theme].metadata + elif values['-BTN_RAD11-'+theme]: + b_color = window['-BTN_RAD11-'+theme].metadata + else: + print('** ERROR none of the radio buttons are true for button color **') + continue + sg.LOOK_AND_FEEL_TABLE[theme]['TEXT_INPUT'] = input_text_color + sg.LOOK_AND_FEEL_TABLE[theme]['BUTTON'] = b_color + with open('new_theme_dict.py', 'a') as outfile: + outfile.write(f"'{values['-NEW_THEME_NAME-'+theme]}' : {sg.LOOK_AND_FEEL_TABLE[theme]},\n") + sg.Print(f"'{values['-NEW_THEME_NAME-'+theme]}' : {sg.LOOK_AND_FEEL_TABLE[theme]}\n") + window.close() + del window diff --git a/ThemeMaker/color_themes.py b/ThemeMaker/color_themes.py new file mode 100644 index 000000000..8aa98567e --- /dev/null +++ b/ThemeMaker/color_themes.py @@ -0,0 +1,1782 @@ +themes = { + '163372': ('#f4efd3', '#cccccc', '#c2b0c9', '#9656a1', ['Yellow', 'Grey', 'Purple', 'Pastel']), + '163318': ('#594a4e', '#e78fb3', '#ffc0ad', '#6fc1a5', ['Brown', 'Pink', 'Green', 'Vintage']), + '163537': ('#ff8ba7', '#ffc6c7', '#faeee7', '#c3f0ca', ['Pink', 'Green', 'Bright', 'Summer']), + '163154': ('#10316b', '#000000', '#e25822', '#ececeb', ['Blue', 'Orange', 'Retro']), + '163151': ('#a35638', '#e08f62', '#d7c79e', '#9dab86', ['Brown', 'Autumn', 'Summer', 'Warm']), + '163063': ('#ffac8e', '#fd7792', '#3f4d71', '#55ae95', ['Pink', 'Green', 'Retro']), + '162867': ('#1b2a49', '#465881', '#00909e', '#c9d1d3', ['Blue', 'Cold', 'Winter']), + '162930': ('#3fc5f0', '#42dee1', '#6decb9', '#eef5b2', ['Blue', 'Green', 'Yellow', 'Bright', 'Neon', 'Summer']), + '162807': ('#003f5c', '#472b62', '#bc4873', '#fb5b5a', ['Purple', 'Orange', 'Neon']), + '162836': ('#9be3de', '#beebe9', '#fffdf9', '#ffe3ed', ['Turquoise', 'Bright']), + '162790': ('#110133', '#00918e', '#4dd599', '#ffdc34', ['Turquoise', 'Green', 'Yellow']), + '162677': ('#bd574e', '#fa877f', '#ffad87', '#dedef0', ['Red', 'Pink', 'Skin', 'Pastel']), + '162174': ('#f45905', '#c70d3a', '#512c62', '#45969b', ['Orange', 'Turquoise']), + '162777': ('#eafbea', '#6f9a8d', '#1f6650', '#ea5e5e', ['Green']), + '162734': ('#010038', '#293a80', '#537ec5', '#f39422', ['Blue', 'Orange']), + '162116': ('#fff4e4', '#f88020', '#d1274b', '#3d0e1e', ['Orange']), + '162076': ('#f35588', '#ffbbb4', '#71a95a', '#007944', ['Pink', 'Green']), + '161920': ('#39375b', '#745c97', '#d597ce', '#f5b0cb', ['Purple', 'Pastel']), + '161696': ('#f8f8f8', '#f1d6ab', '#e3b04b', '#2b2b28', ['Grey', 'Yellow']), + '161649': ('#380e7f', '#6915cf', '#d62196', '#e497cd', ['Purple']), + '161263': ('#dcffcc', '#9fdfcd', '#baabda', '#d79abc', ['Green', 'Purple', 'Bright', 'Summer', 'Pastel']), + '160952': ('#8f4426', '#de6b35', '#f9b282', '#64ccda', ['Brown', 'Orange', 'Warm']), + '160620': ('#851de0', '#aa26da', '#c355f5', '#f1fa3c', ['Purple', 'Yellow', 'Neon']), + '160646': ('#ffe7d1', '#f6c89f', '#4b8e8d', '#396362', ['Skin', 'Turquoise']), + '160243': ('#0c093c', '#df42d1', '#eea5f6', '#fad6d6', ['Purple']), + '160589': ('#e5d8bf', '#94aa2a', '#e47312', '#d55252', ['Green', 'Orange', 'Summer', 'Vintage']), + '160292': ('#c2e8ce', '#f2eee5', '#f6ad7b', '#be7575', ['Green', 'Orange', 'Brown', 'Pastel', 'Summer']), + '160127': ('#090057', '#57007e', '#c400c6', '#ffa069', ['Purple']), + '160163': ('#5eb7b7', '#96d1c7', '#fc7978', '#ffafb0', ['Turquoise', 'Red']), + '161876': ('#dfddc7', '#f58b54', '#a34a28', '#211717', ['Grey', 'Orange', 'Autumn', 'Halloween']), + '162500': ('#6807f9', '#9852f9', '#c299fc', '#ffd739', ['Purple', 'Yellow']), + '160018': ('#293462', '#00818a', '#ec9b3b', '#f7be16', ['Blue', 'Turquoise', 'Orange', 'Yellow']), + '159891': ('#efe9cc', '#eadea6', '#f6cd90', '#deb881', ['Yellow', 'Bright', 'Pastel', 'Summer', 'Skin']), + '159652': ('#003f5c', '#58508d', '#bc5090', '#ff6361', ['Purple', 'Orange']), + '159621': ('#494ca2', '#8186d5', '#c6cbef', '#e3e7f1', ['Blue']), + '159988': ('#ffd369', '#e26241', '#940a37', '#5b0909', ['Yellow', 'Orange', 'Warm']), + '159620': ('#f54291', '#ff78ae', '#ffa0d2', '#fff8cd', ['Pink', 'Bright']), + '159618': ('#f1d4d4', '#ddb6c6', '#ac8daf', '#484c7f', ['Skin', 'Pink', 'Purple', 'Pastel']), + '159679': ('#f0134d', '#ff6f5e', '#f5f0e3', '#40bfc1', ['Red', 'Orange', 'Turquoise']), + '159617': ('#ecfcff', '#b2fcff', '#5edfff', '#3e64ff', ['Blue', 'Neon']), + '159378': ('#fff1e9', '#ffd5d5', '#fc7fb2', '#45454d', ['Pink', 'Wedding', 'Skin']), + '159233': ('#3c4245', '#5f6769', '#719192', '#dfcdc3', ['Grey', 'Turquoise', 'Cold']), + '159131': ('#7c0a02', '#b22222', '#e25822', '#f1bc31', ['Red', 'Orange', 'Warm']), + '159619': ('#e6f8f9', '#b1e8ed', '#edb5f5', '#e86ed0', ['Blue', 'Pink', 'Bright']), + '158462': ('#443737', '#272121', '#ff0000', '#ff4d00', ['Brown', 'Red', 'Dark', 'Warm', 'Halloween']), + '158806': ('#5d1451', '#2f416d', '#14868c', '#94ceca', ['Blue', 'Cold']), + '158845': ('#ffe7ad', '#db75c5', '#a05f96', '#6a1051', ['Yellow', 'Purple']), + '158955': ('#2a1a5e', '#f45905', '#fb9224', '#fbe555', ['Blue', 'Orange', 'Yellow', 'Sunset']), + '159070': ('#f9d5bb', '#f66767', '#d35656', '#3c3d47', ['Orange', 'Red', 'Warm']), + '158356': ('#470938', '#1a3e59', '#5c94bd', '#f2d6eb', ['Blue', 'Cold']), + '158058': ('#5026a7', '#8d448b', '#cc6a87', '#eccd8f', ['Purple', 'Sunset']), + '158271': ('#233714', '#6b591d', '#efcfb6', '#fdeced', ['Brown', 'Skin']), + '158349': ('#6d0c74', '#7f78d2', '#d2d0fe', '#fdecff', ['Purple', 'Pink']), + '158293': ('#42b883', '#347474', '#35495e', '#ff7e67', ['Green', 'Orange']), + '158245': ('#ffdfdf', '#fbc1bc', '#315b96', '#233567', ['Pink', 'Blue', 'Skin']), + '157808': ('#512c96', '#3c6f9c', '#dd6892', '#f9c6ba', ['Purple', 'Turquoise', 'Pink', 'Vintage']), + '158095': ('#445c3c', '#fda77f', '#c9d99e', '#fae8c8', ['Green', 'Orange', 'Summer', 'Pastel']), + '157642': ('#ffbbcc', '#ffcccc', '#ffddcc', '#ffeecc', ['Pink', 'Bright', 'Skin', 'Pastel']), + '157748': ('#1a2849', '#505bda', '#b063c5', '#ffaac3', ['Blue', 'Purple', 'Pink', 'Cold']), + '157673': ('#43ab92', '#f75f00', '#c93838', '#512c62', ['Turquoise', 'Orange', 'Retro']), + '157400': ('#f9f9f9', '#f6ecbf', '#caadde', '#c886e5', ['Yellow', 'Purple', 'Bright', 'Pastel']), + '157216': ('#504658', '#f0decb', '#ffb5b5', '#ce2e6c', ['Grey', 'Pink', 'Skin']), + '157179': ('#394a6d', '#3c9d9b', '#52de97', '#c0ffb3', ['Turquoise', 'Green', 'Cold']), + '157118': ('#23374d', '#1089ff', '#e5e5e5', '#eeeeee', ['Blue', 'Grey', 'Cold']), + '156896': ('#3b064d', '#8105d8', '#ed0cef', '#fe59d7', ['Purple', 'Neon']), + '157018': ('#bbeaa6', '#e3c878', '#ed9a73', '#e688a1', ['Green', 'Orange', 'Pastel', 'Summer', 'Warm']), + '156898': ('#f7e8f6', '#f1c6e7', '#e5b0ea', '#bd83ce', ['Pink', 'Purple', 'Pastel', 'Wedding']), + '156759': ('#d9eeec', '#64b2cd', '#3c70a4', '#da9833', ['Blue', 'Summer']), + '156692': ('#b2e4d5', '#f2a6a6', '#b18ea6', '#e7f3ee', ['Turquoise', 'Pink', 'Pastel', 'Bright']), + '156569': ('#f6f078', '#01d28e', '#434982', '#730068', ['Yellow', 'Green', 'Blue', 'Summer']), + '156488': ('#fcf9ea', '#badfdb', '#f8a978', '#ffc5a1', ['Orange', 'Bright', 'Pastel', 'Summer']), + '156620': ('#202040', '#202060', '#602080', '#b030b0', ['Black', 'Purple', 'Dark']), + '156447': ('#4baea0', '#b6e6bd', '#f1f0cf', '#f0c9c9', ['Green', 'Pastel', 'Bright']), + '156357': ('#c70d3a', '#ed5107', '#230338', '#02383c', ['Red', 'Orange', 'Warm']), + '156338': ('#ddf796', '#f3fe7e', '#979797', '#757575', ['Yellow', 'Grey']), + '156289': ('#47e4bb', '#ec9b3b', '#e8647c', '#000000', ['Turquoise', 'Orange', 'Retro']), + '156039': ('#ecf4f3', '#d1eecc', '#76dbd1', '#57a99a', ['Green', 'Turquoise']), + '155973': ('#e4f2f0', '#99d8d0', '#70416d', '#170a19', ['Turquoise', 'Purple', 'Pastel', 'Cold']), + '156179': ('#fb0091', '#fb8691', '#fb9e91', '#fbda91', ['Pink', 'Orange', 'Skin']), + '156086': ('#f7f7f7', '#5d5d5d', '#a0c334', '#e5d429', ['Grey', 'Green']), + '155497': ('#d2fafb', '#51dacf', '#41aaa8', '#2c003e', ['Blue', 'Turquoise', 'Cold']), + '156010': ('#91b029', '#e6a400', '#eaebd8', '#ffffea', ['Green', 'Orange', 'Summer']), + '155912': ('#fa5477', '#ef4b4b', '#f2e3c9', '#7ecfc0', ['Red']), + '155496': ('#d2fafb', '#6bc5d2', '#105e62', '#b5525c', ['Blue', 'Winter', 'Cold']), + '155144': ('#000272', '#341677', '#a32f80', '#ff6363', ['Blue', 'Dark', 'Neon']), + '154853': ('#f77754', '#584b42', '#537d91', '#a4d1c8', ['Orange', 'Brown', 'Turquoise', 'Vintage']), + '155460': ('#1fab89', '#ff8080', '#ffba92', '#c6f1d6', ['Green', 'Red']), + '155435': ('#010a43', '#f3d3d3', '#eda593', '#ff3f98', ['Pink', 'Skin']), + '154559': ('#b7e778', '#40dab2', '#be6283', '#ed7575', ['Green', 'Red', 'Vintage', 'Spring']), + '155182': ('#45454d', '#ff4893', '#ffd5d5', '#fff1e9', ['Pink']), + '155146': ('#ebefd0', '#32dbc6', '#49beb7', '#ff502f', ['Turquoise', 'Orange', 'Vintage']), + '156756': ('#f6f6f6', '#eae9e9', '#d4d7dd', '#420000', ['Grey']), + '155139': ('#01024e', '#543864', '#8b4367', '#ff6464', ['Dark']), + '155241': ('#f0dd92', '#ffffc5', '#d6e4aa', '#83b582', ['Yellow', 'Summer', 'Pastel']), + '153787': ('#eb7070', '#fec771', '#e6e56c', '#64e291', ['Red', 'Orange', 'Green', 'Summer']), + '155006': ('#f0d78c', '#fcfafa', '#64c4ed', '#4f81c7', ['Yellow', 'Blue', 'Summer']), + '154852': ('#160f30', '#241663', '#a72693', '#eae7af', ['Black', 'Blue', 'Purple', 'Dark']), + '154258': ('#c5f0a4', '#35b0ab', '#226b80', '#f34573', ['Green']), + '155005': ('#b6ffea', '#fce2ae', '#ffb3b3', '#ffdcf7', ['Turquoise', 'Bright', 'Pastel', 'Skin']), + '154644': ('#3a1f5d', '#c83660', '#e15249', '#f6d365', ['Blue', 'Red', 'Yellow', 'Sunset']), + '154242': ('#207561', '#589167', '#a0cc78', '#da4302', ['Green']), + '154922': ('#61f2f5', '#ffffff', '#e0e0e0', '#723881', ['Blue', 'Grey', 'Purple', 'Neon', 'Bright']), + '154209': ('#6e2142', '#943855', '#e16363', '#ffd692', ['Warm', 'Skin']), + '153879': ('#ffcbcb', '#ffb5b5', '#407088', '#132743', ['Pink', 'Blue', 'Vintage']), + '154142': ('#fcf9ea', '#badfdb', '#49beb7', '#ff8a5c', ['Blue', 'Orange', 'Summer']), + '154222': ('#200f21', '#382039', '#5a3d5c', '#f638dc', ['Black', 'Purple', 'Dark']), + '153705': ('#9cf196', '#eceba7', '#ebce95', '#edaaaa', ['Green', 'Yellow', 'Pastel']), + '153606': ('#042f4b', '#fff6da', '#fbc99d', '#ed1250', ['Orange', 'Skin']), + '154210': ('#ecfcff', '#b2fcff', '#5edfff', '#3e64ff', ['Blue', 'Cold', 'Neon']), + '153362': ('#ebfffb', '#ff5858', '#61234e', '#032535', ['Red', 'Retro']), + '153353': ('#7ecfc0', '#f2e3c9', '#ec8f6a', '#ef4b4b', ['Turquoise', 'Orange']), + '152950': ('#f9e090', '#ff935c', '#dc5353', '#a72461', ['Yellow', 'Orange', 'Warm', 'Gold']), + '154144': ('#c7f0db', '#8bbabb', '#6c7b95', '#464159', ['Turquoise', 'Cold']), + '152872': ('#faf5ef', '#d7d1c9', '#99b19c', '#672f2f', ['Grey', 'Winter']), + '152856': ('#ffb997', '#f67e7d', '#843b62', '#0b032d', ['Warm', 'Orange']), + '153796': ('#293462', '#216583', '#00818a', '#f7be16', ['Blue', 'Turquoise', 'Cold']), + '152973': ('#696464', '#e9e5dd', '#d04925', '#992e24', ['Grey', 'Orange', 'Skin']), + '152863': ('#007065', '#00a79d', '#f5c181', '#ffeecf', ['Turquoise', 'Yellow', 'Summer']), + '152733': ('#cf455c', '#ffdd67', '#ff8a5c', '#444444', ['Red', 'Yellow', 'Orange', 'Warm']), + '152777': ('#f6edcf', '#f0dab1', '#daf1f9', '#a4d7e1', ['Blue', 'Skin', 'Pastel', 'Bright', 'Summer']), + '152664': ('#ff8080', '#ffba92', '#e0f5b9', '#c6f1d6', ['Red', 'Pastel', 'Bright', 'Summer']), + '152420': ('#f9f6f2', '#f1d6ab', '#a0855b', '#38470b', ['Brown', 'Skin']), + '152310': ('#eaeaea', '#a1dd70', '#00bdaa', '#8559a5', ['Grey', 'Green']), + '153118': ('#44000d', '#83142c', '#ad1d45', '#f9d276', ['Brown', 'Dark', 'Warm']), + '152232': ('#08ffc8', '#fff7f7', '#dadada', '#204969', ['Turquoise', 'Neon', 'Grey', 'Cold']), + '152139': ('#ffb6b9', '#fae3d9', '#bbded6', '#8ac6d1', ['Pink', 'Pastel']), + '152965': ('#252525', '#ff0000', '#af0404', '#414141', ['Black', 'Red', 'Neon', 'Dark']), + '151744': ('#fffcc1', '#fdeaab', '#cba1d2', '#ab72c0', ['Yellow', 'Purple', 'Summer']), + '152688': ('#2d3561', '#c05c7e', '#f3826f', '#ffb961', ['Orange', 'Warm', 'Sunset']), + '153137': ('#f4f6f6', '#ff9c91', '#cd3f3e', '#1c2938', ['Grey', 'Orange', 'Skin', 'Wedding']), + '151774': ('#f5b5fc', '#96f7d2', '#f0f696', '#fcb1b1', ['Purple', 'Neon', 'Pastel', 'Retro', 'Summer']), + '152714': ('#f8f8f8', '#50b6bb', '#45969b', '#f96d15', ['Turquoise', 'Orange', 'Retro']), + '152509': ('#bb1542', '#eb5f5d', '#fabc74', '#239f95', ['Red']), + '151338': ('#fff1ac', '#f9bcdd', '#d5a4cf', '#b689b0', ['Yellow', 'Pink', 'Purple', 'Pastel', 'Spring']), + '152246': ('#540e33', '#de356a', '#fdc8b7', '#6e9086', ['Red', 'Vintage']), + '151359': ('#f38eff', '#ff00c8', '#ffcece', '#fff0f0', ['Pink', 'Neon', 'Bright']), + '152282': ('#f9f3ec', '#63aabc', '#ed3833', '#60204b', ['Turquoise', 'Red', 'Vintage']), + '152027': ('#d3f6f3', '#f9fce1', '#fee9b2', '#fbd1b7', ['Blue', 'Yellow', 'Bright', 'Pastel', 'Summer']), + '151976': ('#293462', '#216583', '#f76262', '#fff1c1', ['Blue', 'Retro']), + '151885': ('#f4ff61', '#a8ff3e', '#32ff6a', '#27aa80', ['Yellow', 'Green', 'Neon', 'Bright', 'Summer']), + '151784': ('#60a9a6', '#caf2d7', '#f5fec0', '#fddede', ['Turquoise', 'Bright', 'Summer', 'Pastel']), + '151197': ('#f7e8e8', '#f2a2e4', '#f090d9', '#ea7dc7', ['Pink', 'Skin']), + '152058': ('#e42c64', '#614ad3', '#2d248a', '#121b74', ['Red', 'Blue']), + '151637': ('#aeeff0', '#f1f0d1', '#f0e3c4', '#daa592', ['Blue', 'Beach', 'Pastel']), + '151883': ('#ca5fa6', '#f36886', '#fa8282', '#ffaf65', ['Purple', 'Red', 'Warm', 'Wedding']), + '151737': ('#fdef96', '#f7b71d', '#afa939', '#2b580c', ['Yellow', 'Orange', 'Green', 'Summer', 'Warm']), + '151393': ('#f2f6f5', '#c8dad3', '#93b5b3', '#63707e', ['Grey', 'Vintage']), + '151198': ('#fac0e1', '#caa5f1', '#59d4e8', '#39bdc8', ['Pink', 'Turquoise', 'Paste']), + '150983': ('#dff0ea', '#95adbe', '#574f7d', '#4f3a65', ['Blue', 'Cold', 'Winter', 'Grey']), + '150928': ('#010059', '#52437b', '#ff7a8a', '#fcf594', ['Purple']), + '150643': ('#fafdcb', '#aee7e8', '#28c3d4', '#248ea9', ['Yellow', 'Blue', 'Summer']), + '150168': ('#17223b', '#263859', '#6b778d', '#ff6768', ['Dark']), + '149737': ('#f1d4d4', '#ddb6c6', '#ac8daf', '#484c7f', ['Pink', 'Purple', 'Skin', 'Pastel']), + '149522': ('#f6ef98', '#23eae6', '#1b7fbd', '#112f91', ['Blue', 'Summer']), + '149558': ('#e6f8f9', '#b1e8ed', '#edb5f5', '#e86ed0', ['Blue', 'Purple', 'Cold']), + '149559': ('#525252', '#414141', '#313131', '#ca3e47', ['Grey', 'Dark']), + '149560': ('#f4f4f4', '#eadca6', '#e2c275', '#c36a2d', ['Grey', 'Brown', 'Skin', 'Pastel']), + '149616': ('#090088', '#930077', '#e4007c', '#ffbd39', ['Blue', 'Red']), + '148495': ('#f2f4d1', '#b2d3be', '#89a3b2', '#5e6073', ['Grey']), + '148705': ('#f5f687', '#fcfdd8', '#e2bebe', '#b96b9f', ['Green', 'Purple']), + '148116': ('#f2f4f6', '#1ee3cf', '#6b48ff', '#0d3f67', ['Grey', 'Turquoise', 'Purple', 'Neon']), + '148970': ('#ff487e', '#ff9776', '#ffd5be', '#ffedff', ['Pink', 'Orange', 'Skin', 'Spring']), + '148452': ('#c1f6e7', '#ffcbcb', '#bb7171', '#4e3440', ['Turquoise', 'Pink', 'Skin', 'Vintage']), + '148361': ('#fff78f', '#22b9ca', '#0c99c1', '#f30cd4', ['Yellow', 'Turquoise', 'Purple', 'Retro']), + '148314': ('#ffc6be', '#ffa1c5', '#a773c3', '#854777', ['Pink', 'Purple', 'Warm']), + '147884': ('#f1f4df', '#10eaf0', '#0028ff', '#24009c', ['Blue', 'Cold', 'Neon']), + '148160': ('#e6f0b6', '#b8e9c0', '#6384b3', '#684949', ['Green']), + '147708': ('#064acb', '#366ed8', '#f3a953', '#f2f3f3', ['Blue']), + '147876': ('#293462', '#a64942', '#fe5f55', '#fff1c1', ['Red', 'Warm']), + '148315': ('#8a00d4', '#d527b7', '#ff82c3', '#ffc46b', ['Purple']), + '147615': ('#553c8b', '#9ea9f0', '#ccc1ff', '#ffeafe', ['Purple']), + '147574': ('#f6f6f6', '#bdf2d5', '#7ad9f5', '#5d13e7', ['Grey', 'Green', 'Turquoise']), + '147387': ('#454d66', '#009975', '#58b368', '#d9d872', ['Green']), + '147578': ('#fcf9ec', '#b0f4e6', '#67eaca', '#12d3cf', ['Turquoise', 'Bright', 'Summer']), + '147532': ('#2d132c', '#801336', '#c72c41', '#ee4540', ['Dark', 'Black', 'Red']), + '147323': ('#5bd1d7', '#348498', '#004d61', '#ff502f', ['Blue']), + '147389': ('#b0deff', '#ffc5a1', '#ffd19a', '#fff8a6', ['Blue', 'Orange', 'Skin', 'Bright', 'Pastel']), + '147169': ('#fab95b', '#71a0a5', '#665c84', '#212121', ['Orange', 'Turquoise']), + '147205': ('#f7ff56', '#94fc13', '#4be3ac', '#032d3c', ['Yellow', 'Green', 'Bright', 'Neon', 'Summer']), + '147179': ('#004a2f', '#002f35', '#ff6337', '#ffa323', ['Green', 'Orange']), + '147250': ('#eeeeee', '#dedede', '#ff4949', '#c10000', ['Grey', 'Red']), + '145544': ('#8adfdc', '#313848', '#735372', '#8f758e', ['Turquoise', 'Vintage']), + '145468': ('#22eaca', '#b31e6f', '#ee5a5a', '#ff9e74', ['Turquoise', 'Orange', 'Retro', 'Neon']), + '147299': ('#d2f3e0', '#feb9c8', '#f6a7ba', '#f5fbf1', ['Green', 'Pink', 'Bright', 'Pastel']), + '145393': ('#e41749', '#f5587b', '#ff8a5c', '#fff591', ['Red', 'Pink', 'Orange', 'Yellow', 'Neon']), + '145446': ('#beeef7', '#6fc2d0', '#373a6d', '#ff8246', ['Blue', 'Orange']), + '145389': ('#b206b0', '#e41749', '#f5587b', '#ff8a5c', ['Purple', 'Red', 'Warm']), + '145355': ('#33313b', '#4592af', '#e3c4a8', '#f6f5f5', ['Black', 'Turquoise', 'Grey', 'Vintage']), + '145454': ('#f3c1c6', '#f0f69f', '#b0e0a8', '#d8eff0', ['Pink', 'Bright', 'Pastel', 'Spring']), + '145313': ('#bfcd7e', '#ee7777', '#8e2e6a', '#311054', ['Orange', 'Vintage', 'Wedding']), + '145229': ('#211717', '#a34a28', '#f58b54', '#dfddc7', ['Black', 'Brown', 'Orange', 'Skin', 'Warm']), + '144444': ('#ffeaa5', '#226b80', '#40a798', '#ffebd3', ['Yellow', 'Turquoise', 'Retro']), + '145322': ('#fff3a3', '#ff7bb0', '#ff3e6d', '#7572f4', ['Yellow', 'Red', 'Spring', 'Bright', 'Neon']), + '145088': ('#6c5ce7', '#7b88ff', '#fdcb6e', '#fff3b1', ['Blue', 'Yellow', 'Summer']), + '144698': ('#103c42', '#02576c', '#05a19c', '#ffe837', ['Turquoise']), + '144599': ('#e6d385', '#5c7658', '#681313', '#d25959', ['Yellow', 'Green', 'Red']), + '144615': ('#866ec7', '#8f71ff', '#82acff', '#b7fbff', ['Purple', 'Blue', 'Cold']), + '144758': ('#7fa99b', '#f6e79c', '#f79c1d', '#9c2c2c', ['Yellow', 'Orange', 'Vintage']), + '144942': ('#010059', '#107595', '#fdbfb3', '#fcf594', ['Blue']), + '144598': ('#ab93c9', '#d698b9', '#eda1ab', '#ffbea3', ['Pastel', 'Skin']), + '144332': ('#560d0d', '#76a21e', '#c6cf65', '#f3ff93', ['Brown', 'Green', 'Vintage']), + '144426': ('#7189bf', '#df7599', '#ffc785', '#72d6c9', ['Blue', 'Pastel', 'Vintage']), + '144330': ('#ebefd0', '#32dbc6', '#49beb7', '#085f63', ['Turquoise', 'Cold']), + '145074': ('#ff0b55', '#d61d4e', '#323232', '#ffdee6', ['Red']), + '144399': ('#222831', '#393e46', '#d65a31', '#eeeeee', ['Black', 'Grey', 'Orange', 'Dark', 'Halloween']), + '144327': ('#f5e1da', '#f1f1f1', '#49beb7', '#085f63', ['Pink', 'Skin', 'Turquoise']), + '144191': ('#e8e8e8', '#5588a3', '#145374', '#00334e', ['Grey', 'Blue', 'Cold', 'Winter']), + '143744': ('#a9eec2', '#fad284', '#f38181', '#705772', ['Green', 'Orange', 'Vintage', 'Summer']), + '144541': ('#7f4782', '#aa5c9f', '#e2598b', '#fdd043', ['Purple']), + '143675': ('#616f39', '#ffd98e', '#ffb677', '#ff8364', ['Green', 'Orange', 'Summer', 'Skin', 'Pastel']), + '143590': ('#0c084c', '#096386', '#00b7a8', '#f0eec8', ['Blue', 'Turquoise', 'Cold', 'Winter']), + '143563': ('#f9f8eb', '#76b39d', '#05004e', '#fd5f00', ['Green', 'Orange', 'Retro']), + '143360': ('#eaf5ff', '#a9c6de', '#247e6c', '#e4c666', ['Blue']), + '143564': ('#240041', '#900048', '#ff4057', '#ff8260', ['Red', 'Warm']), + '143359': ('#fffde8', '#f7e0a3', '#f09c67', '#4c8492', ['Yellow', 'Orange', 'Skin']), + '143259': ('#f2eee0', '#c8e6f5', '#5ca0d3', '#5e0a0a', ['Blue']), + '144179': ('#f1e4e4', '#15cda8', '#099a97', '#9764c7', ['Grey', 'Green', 'Purple', 'Vintage']), + '144326': ('#085f63', '#49beb7', '#facf5a', '#ff5959', ['Turquoise', 'Yellow', 'Red', 'Retro']), + '143269': ('#305f72', '#f1d1b5', '#f0b7a4', '#f18c8e', ['Skin', 'Pastel']), + '143225': ('#fff5eb', '#f6e0b3', '#dbcc8f', '#4e4e4e', ['Yellow', 'Skin']), + '142991': ('#d7f7f5', '#75cac3', '#2a6171', '#f34573', ['Turquoise', 'Cold']), + '142837': ('#f0e9e9', '#c19191', '#aa7070', '#8b5d5d', ['Brown', 'Skin']), + '142663': ('#ececec', '#9fd3c7', '#385170', '#142d4c', ['Grey', 'Turquoise', 'Blue', 'Cold', 'Winter', 'Pastel']), + '142721': ('#f2eee0', '#c8e6f5', '#5ca0d3', '#6d3939', ['Blue', 'Summer']), + '142797': ('#fffbbe', '#eec1ea', '#be97dc', '#a374d5', ['Yellow', 'Pink', 'Purple', 'Pastel', 'Bright']), + '142073': ('#eaeaea', '#00bdaa', '#257aa6', '#621e81', ['Grey', 'Turquoise']), + '142677': ('#444444', '#f30067', '#00d1cd', '#eaeaea', ['Grey', 'Red', 'Turquoise', 'Neon']), + '142173': ('#c5fad9', '#aceacf', '#f77fee', '#db66e4', ['Green', 'Purple']), + '141859': ('#fffeec', '#aeddcd', '#e4508f', '#556fb5', ['Yellow', 'Green', 'Red', 'Blue', 'Pastel', 'Spring']), + '141761': ('#00028c', '#21aa93', '#01676b', '#ffc3e7', ['Blue', 'Green', 'Pink', 'Vintage']), + '141715': ('#5a3921', '#6b8c42', '#7bc67b', '#ffffb5', ['Brown', 'Green']), + '142059': ('#ffc15e', '#8158fc', '#692db7', '#34314f', ['Purple']), + '141682': ('#480032', '#df0054', '#ff8b6a', '#ffd6c2', ['Brown', 'Red', 'Orange', 'Warm', 'Halloween']), + '141714': ('#302387', '#ff3796', '#00faac', '#fffdaf', ['Blue', 'Pink', 'Green', 'Neon', 'Retro']), + '141668': ('#ff62a5', '#ffe5ae', '#6b76ff', '#dee0d9', ['Pink', 'Yellow', 'Grey', 'Retro']), + '141642': ('#f5c7f7', '#c54fa7', '#8d309b', '#3426a4', ['Pink', 'Purple']), + '141641': ('#f9fd50', '#85ef47', '#00bd56', '#207dff', ['Yellow', 'Green', 'Blue', 'Neon', 'Bright', 'Summer']), + '141534': ('#183661', '#1c4b82', '#dd6b4d', '#dae1e7', ['Blue', 'Orange']), + '141624': ('#7fe7cc', '#dfe38e', '#efca8c', '#f17e7e', ['Turquoise', 'Yellow', 'Red', 'Pastel']), + '141287': ('#e7eaf6', '#a2a8d3', '#38598b', '#113f67', ['Blue', 'Grey', 'Cold', 'Winter']), + '141416': ('#11144c', '#3a9679', '#fabc60', '#e16262', ['Green', 'Yellow', 'Red', 'Retro']), + '141096': ('#e3c4a8', '#4592af', '#226089', '#000000', ['Brown', 'Blue']), + '141219': ('#f6f5f5', '#e9e4e6', '#3bb4c1', '#048998', ['Grey', 'Turquoise']), + '140793': ('#dadddf', '#f69314', '#c40b13', '#621295', ['Grey', 'Orange', 'Purple']), + '140815': ('#ffd7e8', '#f2c0ff', '#bf9fee', '#866ec7', ['Pink', 'Purple']), + '140770': ('#f8b739', '#f3dcad', '#e44985', '#bd245f', ['Yellow', 'Pink']), + '141031': ('#f54291', '#ff78ae', '#ffa0d2', '#fff8cd', ['Pink', 'Yellow']), + '141288': ('#f3f9fb', '#87c0cd', '#226597', '#113f67', ['Blue', 'Cold', 'Winter']), + '141044': ('#1d1919', '#ffce76', '#0075f6', '#0900c3', ['Black', 'Yellow', 'Blue']), + '140056': ('#eeeeee', '#d8cbbb', '#bb8fa9', '#560764', ['Grey', 'Purple', 'Pastel']), + '139817': ('#cdffeb', '#ffaaaa', '#c7004c', '#8f1537', ['Red', 'Bright']), + '139648': ('#494ca2', '#8186d5', '#c6cbef', '#e3e7f1', ['Purple', 'Cold', 'Winter']), + '139838': ('#ff5d9e', '#8f71ff', '#82acff', '#8bffff', ['Pink', 'Purple', 'Blue', 'Bright', 'Neon']), + '140436': ('#33313b', '#62374e', '#007880', '#fdc57b', ['Vintage']), + '140707': ('#fcd307', '#1c1259', '#ee4266', '#d5daeb', ['Yellow', 'Red', 'Grey', 'Retro']), + '140769': ('#dbe9b7', '#fdfdf6', '#f4dada', '#b8b2a6', ['Green', 'Pink', 'Bright', 'Pastel', 'Spring', 'Wedding']), + '141021': ('#b7fbff', '#fff6be', '#ffe0a3', '#ffa1ac', ['Blue', 'Yellow', 'Summer', 'Bright', 'Spring']), + '139632': ('#421b9b', '#a06ee1', '#cbbcf6', '#cef9e2', ['Purple', 'Green', 'Retro']), + '141100': ('#022c43', '#053f5e', '#115173', '#ffd700', ['Blue', 'Dark', 'Yellow', 'Night']), + '140495': ('#faf562', '#f36a7b', '#b824a4', '#aaaaaa', ['Yellow', 'Purple', 'Grey']), + '140172': ('#352961', '#774181', '#e6b2c6', '#f6e5e5', ['Purple', 'Pink']), + '140155': ('#f8f1f1', '#d2c8c8', '#a3816a', '#0a065d', ['Grey', 'Winter', 'Skin']), + '140154': ('#1b1919', '#616f39', '#a7d129', '#f8eeb4', ['Black', 'Green']), + '140700': ('#ffe6eb', '#defcfc', '#cbf1f5', '#a6e3e9', ['Pink', 'Blue', 'Bright', 'Pastel']), + '139667': ('#070d59', '#1f3c88', '#5893d4', '#f7b633', ['Blue', 'Cold']), + '139670': ('#f857b5', '#f781bc', '#fdffdc', '#c5ecbe', ['Pink', 'Green', 'Spring']), + '139970': ('#6f0765', '#4c0045', '#bd512f', '#ffb228', ['Purple', 'Orange']), + '140057': ('#eeeeee', '#acc6aa', '#71a0a5', '#77628c', ['Grey', 'Green', 'Purple', 'Pastel', 'Vintage']), + '139633': ('#5d3a3a', '#905858', '#b5e0ba', '#f7ffbd', ['Brown']), + '139458': ('#99235c', '#df4d19', '#a43737', '#572121', ['Purple', 'Orange', 'Brown', 'Warm']), + '139521': ('#b4e9e2', '#32dbc6', '#309286', '#ebefd0', ['Turquoise']), + '139409': ('#35477d', '#6c5b7b', '#c06c84', '#f67280', ['Blue', 'Red']), + '139362': ('#a1dd70', '#fdfff0', '#e8ecd6', '#a23131', ['Green', 'Red', 'Spring']), + '139296': ('#00a8b5', '#774898', '#de4383', '#f3ae4b', ['Turquoise', 'Purple', 'Orange', 'Retro']), + '139297': ('#6d3580', '#cc4165', '#e4734f', '#ffe26f', ['Purple', 'Red', 'Orange', 'Yellow', 'Sunset', 'Warm']), + '139181': ('#010101', '#69779b', '#acdbdf', '#f0ece2', ['Black', 'Blue', 'Winter', 'Dark', 'Cold']), + '139410': ('#51eaea', '#fffde1', '#ff9d76', '#fb3569', ['Blue', 'Orange', 'Red', 'Summer', 'Bright', 'Spring']), + '139257': ('#f68787', '#f8a978', '#f1eb9a', '#a4f6a5', ['Red', 'Orange', 'Yellow', 'Green', 'Bright', 'Neon', 'Spring']), + '139088': ('#d9d9d9', '#e88a1a', '#cf3030', '#141414', ['Grey', 'Orange', 'Autumn', 'Halloween']), + '139087': ('#10316b', '#0b8457', '#eac100', '#dee1ec', ['Blue', 'Green', 'Yellow', 'Grey', 'Vintage']), + '138719': ('#5e0606', '#831212', '#970690', '#ffa400', ['Brown', 'Purple', 'Orange', 'Warm']), + '139015': ('#ffcece', '#ffc1c8', '#ffe3b0', '#8ed6ff', ['Pink', 'Yellow', 'Blue', 'Pastel', 'Bright', 'Skin']), + '138663': ('#233142', '#4f9da6', '#facf5a', '#ff5959', ['Blue', 'Yellow', 'Red']), + '138966': ('#f3f8ff', '#deecff', '#c6cfff', '#e8d3ff', ['Blue', 'Ping', 'Pastel', 'Wedding', 'Bright']), + '138572': ('#ffa900', '#9d8221', '#014441', '#01252a', ['Orange', 'Turquoise']), + '138947': ('#df0e62', '#fac70b', '#127681', '#21174a', ['Red', 'Yellow', 'Turquoise', 'Retro']), + '138573': ('#e8e2db', '#fab95b', '#f16821', '#1a3263', ['Grey', 'Orange', 'Autumn', 'Gold', 'Skin']), + '138358': ('#1c819e', '#005542', '#ffbe00', '#dfdfdf', ['Turquoise', 'Yellow']), + '138363': ('#ffd3de', '#f6b8d1', '#5dc0a6', '#3f8f8d', ['Pink', 'Turquoise', 'Spring']), + '138365': ('#6927ff', '#837dff', '#bf81ff', '#ffd581', ['Purple', 'Neon']), + '138308': ('#f77754', '#018790', '#0a516d', '#2b2726', ['Orange', 'Turquoise']), + '138147': ('#3c415e', '#738598', '#dfe2e2', '#1cb3c8', ['Grey', 'Blue', 'Winter', 'Cold']), + '138409': ('#f9989f', '#fccb8f', '#faf096', '#c5f8c8', ['Red', 'Orange', 'Yellow', 'Green', 'Bright', 'Spring', 'Summer']), + '137864': ('#113f67', '#34699a', '#408ab4', '#65c6c4', ['Blue', 'Turquoise', 'Cold']), + '138325': ('#fcf9ed', '#ffba5a', '#ff7657', '#665c84', ['Orange', 'Skin']), + '138016': ('#f5f5f5', '#30e3ca', '#2f89fc', '#40514e', ['Grey', 'Turquoise', 'Blue', 'Cold', 'Retro', 'Neon']), + '137905': ('#283148', '#913535', '#bbbbbb', '#e9eec9', ['Brown', 'Grey', 'Autumn', 'Vintage']), + '138039': ('#fff4e3', '#ffcdab', '#ffa45c', '#5d5d5a', ['Orange', 'Warm', 'Autumn', 'Skin']), + '137655': ('#074684', '#0ea5c6', '#a0edf7', '#f2efb6', ['Blue']), + '138132': ('#eef2f5', '#ea168e', '#612570', '#1eafed', ['Grey', 'Pink', 'Purple', 'Blue', 'Retro', 'Neon']), + '137927': ('#feffdb', '#ffc60b', '#ff8b00', '#444444', ['Yellow', 'Orange', 'Summer', 'Autumn', 'Warm', 'Gold']), + '137721': ('#00204a', '#005792', '#448ef6', '#fdb44b', ['Blue', 'Orange', 'Winter', 'Cold']), + '137525': ('#900c3f', '#c70039', '#ff5733', '#ffc300', ['Blue', 'Orange', 'Yellow', 'Warm']), + '137229': ('#f4f9f4', '#a7d7c5', '#74b49b', '#5c8d89', ['Green', 'White']), + '137415': ('#33313b', '#3c4f65', '#834c69', '#e6f5ff', ['Black', 'Dark']), + '137086': ('#fffafa', '#ffe0e0', '#ffc0d0', '#efdfbf', ['Pink', 'Pastel', 'Bright', 'Spring', 'White', 'Skin']), + '137660': ('#a2eae2', '#41aaa8', '#105e62', '#b5525c', ['Turquoise', 'Cold', 'Winter']), + '137720': ('#d34848', '#ff8162', '#ffcd60', '#fffa67', ['Red', 'Yellow', 'Warm']), + '137739': ('#ffcccc', '#caabd8', '#9873b9', '#714288', ['Pink', 'Purple', 'Pastel', 'Wedding']), + '137537': ('#0c005a', '#bc2525', '#ff0000', '#eaeaea', ['Blue', 'Red', 'Neon']), + '137357': ('#cdffeb', '#009f9d', '#07456f', '#0f0a3c', ['Turquoise', 'Blue', 'Cold', 'Winter']), + '137439': ('#ffefe0', '#fed9ca', '#c5c5c5', '#7d7d7d', ['Grey', 'Skin']), + '137194': ('#c82121', '#dee1ec', '#becbff', '#0d0cb5', ['Red', 'Blue', 'Retro']), + '137170': ('#ff8484', '#d84c73', '#5c3b6f', '#35234b', ['Pink', 'Purple']), + '137109': ('#f4f3f3', '#dfdfdf', '#bfd8d5', '#b1bed5', ['Grey', 'Pastel', 'Bright', 'White']), + '137195': ('#3a0088', '#930077', '#e61c5d', '#ffe98a', ['Purple', 'Red', 'Yellow', 'Sunset']), + '137244': ('#ef6c57', '#7ed3b2', '#b9e6d3', '#f2f2f2', ['Red', 'Green', 'Pastel']), + '137001': ('#4e2161', '#9bbfab', '#ebf0c2', '#774e26', ['Purple', 'Brown', 'Vintage']), + '136945': ('#cd4545', '#f16821', '#f3a333', '#fffe9a', ['Red', 'Orange', 'Yellow', 'Warm', 'Halloween', 'Summer']), + '137211': ('#eeeeee', '#cde8f6', '#d195f9', '#0033c7', ['Grey', 'Blue', 'Purple']), + '136806': ('#f59aa3', '#f5e4c3', '#34a7b2', '#5b2e35', ['Pink', 'Yellow', 'Turquoise', 'Brown']), + '136567': ('#222831', '#393e46', '#b55400', '#eeeeee', ['Black', 'Grey', 'Brown', 'Dark', 'Winter']), + '136570': ('#fafafa', '#e3e3e3', '#ee6f57', '#cb3737', ['Grey', 'Orange', 'Vintage', 'Retro', 'White', 'Skin']), + '136572': ('#d1d1d1', '#c8e8ed', '#f7fdb1', '#ded473', ['Grey', 'Blue', 'Yellow', 'Bright']), + '136769': ('#fe9191', '#e4406f', '#ca2374', '#9c297f', ['Orange', 'Red', 'Warm', 'Wedding']), + '136716': ('#6e3b3b', '#ac3f21', '#be6a15', '#f3cf7a', ['Brown', 'Warm', 'Gold', 'Skin']), + '135813': ('#6effbf', '#dcaee8', '#ffc5e6', '#fcf2db', ['Green', 'Purple', 'Pink', 'Bright', 'Neon']), + '136053': ('#d6f8b8', '#acdeaa', '#8fbbaf', '#6b7b8e', ['Green', 'Pastel', 'Cold']), + '136873': ('#e6dedd', '#8f1d14', '#1b120f', '#f89d13', ['Grey', 'Red', 'Black', 'Orange', 'Warm', 'Halloween', 'Autumn']), + '136330': ('#ebfffb', '#7efaff', '#13abc4', '#3161a3', ['Blue', 'Cold', 'Winter', 'Neon']), + '136145': ('#5c4d4d', '#915b4a', '#a96851', '#f2f1e7', ['Grey', 'Brown', 'Warm', 'Vintage', 'Skin']), + '135566': ('#fa86be', '#a275e3', '#9aebed', '#fffcab', ['Pink', 'Purple', 'Yellow', 'Bright', 'Neon']), + '135842': ('#c9f658', '#dbff3d', '#55968f', '#8acbbb', ['Green', 'Turquoise', 'Bright', 'Neon']), + '136148': ('#ffaaaa', '#e37070', '#c7004c', '#8f1537', ['Pink', 'Red', 'Warm', 'Skin']), + '135960': ('#69779b', '#9692af', '#acdbdf', '#d7eaea', ['Grey', 'Blue', 'Pastel', 'Cold', 'Winter']), + '136290': ('#ffedc6', '#cdeeaa', '#96dae4', '#6d70c6', ['Yellow', 'Green', 'Blue', 'Summer']), + '136149': ('#f185b3', '#d52484', '#90007f', '#3d0043', ['Pink', 'Purple']), + '135873': ('#ffe6eb', '#defcfc', '#cbf1f5', '#a6e3e9', ['Pink', 'Blue', 'Pastel', 'Bright']), + '135814': ('#1b335f', '#ff6bd6', '#ffb0fe', '#ffecd3', ['Pink', 'Yellow']), + '135904': ('#fbfad3', '#c6e377', '#729d39', '#36622b', ['Green']), + '135910': ('#e8e2db', '#fab95b', '#f5564e', '#1a3263', ['Grey', 'Orange', 'Warm', 'Autumn', 'Gold']), + '135151': ('#f9f8eb', '#76b39d', '#05004e', '#fd5f00', ['Green', 'Orange', 'Retro', 'Vintage']), + '135383': ('#5d50c6', '#f85e9f', '#f18fac', '#facd49', ['Purple', 'Pink', 'Yellow']), + '135565': ('#f05a28', '#f7931e', '#fff0bc', '#fefcdb', ['Orange', 'Yellow', 'Warm', 'Summer', 'Autumn', 'Gold', 'Skin']), + '134291': ('#f3f9fb', '#474f85', '#51e3d4', '#f3ecd3', ['Blue', 'Turquoise', 'Cold', 'White']), + '135431': ('#3e3838', '#ae7c7c', '#6cbbb3', '#efe784', ['Brown', 'Turquoise', 'Yellow', 'Retro']), + '134056': ('#ffb4ac', '#679186', '#264e70', '#ffebd3', ['Pink', 'Green', 'Blue', 'Vintage', 'Wedding', 'Pastel']), + '134309': ('#a8026f', '#db2d43', '#e76838', '#fbd5af', ['Purple', 'Orange', 'Sunset', 'Warm']), + '135437': ('#fcf8f3', '#aedadd', '#db996c', '#6e7da2', ['Blue', 'Brown', 'Vintage']), + '135573': ('#b5edba', '#f06f32', '#a44444', '#594129', ['Orange', 'Brown']), + '135057': ('#ffeed0', '#f79f24', '#f12d2d', '#7c064d', ['Orange', 'Red', 'Sunset', 'Warm', 'Summer']), + '134245': ('#182952', '#2b3595', '#7045af', '#e14594', ['Blue', 'Purple', 'Dark']), + '133895': ('#d7f7f5', '#75cac3', '#2a6171', '#f3d516', ['Turquoise', 'Yellow']), + '134927': ('#070d59', '#1f3c88', '#5893d4', '#ceddef', ['Blue', 'Cold', 'Winter']), + '133828': ('#fafafa', '#e0bb20', '#841818', '#000000', ['Orange', 'Red', 'Black', 'Autumn', 'Halloween', 'White']), + '133859': ('#20716a', '#23a393', '#ffc0c2', '#f7e9e3', ['Turquoise', 'Pink']), + '133655': ('#db2d43', '#87e5da', '#c7f2e3', '#f7aa00', ['Red', 'Turquoise', 'Orange', 'Retro']), + '133330': ('#587850', '#709078', '#78b0a0', '#f8d0b0', ['Green', 'Pastel']), + '133349': ('#ff8f56', '#ff5959', '#984a59', '#60424c', ['Orange', 'Warm', 'Brown']), + '133164': ('#f2f4fb', '#d22780', '#f8b500', '#5e227f', ['Grey', 'Purple', 'White']), + '133103': ('#ebebe3', '#2b2b28', '#4a4a48', '#c19898', ['Grey', 'Black', 'Skin']), + '134419': ('#feffdf', '#ffe79a', '#ffa952', '#ef5a5a', ['Yellow', 'Orange', 'Red', 'Warm', 'Bright', 'Spring']), + '134510': ('#ebf0f6', '#98ccd3', '#364e68', '#132238', ['Grey', 'Blue', 'Cold', 'Winter']), + '132460': ('#fdf1db', '#a6cb12', '#e00543', '#84253e', ['Green', 'Red', 'Summer', 'Neon']), + '133340': ('#1d5464', '#207e82', '#298f9b', '#d8d860', ['Turquoise']), + '133192': ('#c1224f', '#f16f6f', '#94d2e6', '#fff78f', ['Red', 'Blue', 'Yellow']), + '133430': ('#f3f6c8', '#ea9c1b', '#5f685a', '#362207', ['Yellow', 'Orange', 'Grey', 'Autumn']), + '133121': ('#0b032d', '#843b62', '#f67e7d', '#ffb997', ['Black', 'Purple', 'Orange', 'Halloween']), + '133026': ('#ece493', '#84a1be', '#5c7893', '#535962', ['Yellow', 'Blue']), + '132892': ('#f3f0d1', '#e29c68', '#c85108', '#a20e0e', ['Orange', 'Red', 'Autumn', 'Skin']), + '132843': ('#260c1a', '#f05d23', '#c5d86d', '#f7f7f2', ['Black', 'Orange', 'Green', 'Autumn', 'Halloween']), + '132595': ('#faf9f9', '#add2c9', '#5ea3a3', '#488b8f', ['Grey', 'Turquoise', 'White']), + '132296': ('#eaec96', '#43c0ac', '#a93199', '#fa0559', ['Yellow', 'Turquoise', 'Purple', 'Neon']), + '131930': ('#f9ecec', '#f0d9da', '#c8d9eb', '#ecf2f9', ['Pink', 'Blue', 'Pastel', 'Skin']), + '132247': ('#071e3d', '#1f4287', '#278ea5', '#21e6c1', ['Blue', 'Turquoise', 'Dark', 'Winter']), + '132003': ('#edfffa', '#8bd5cb', '#c56868', '#974949', ['Turquoise', 'Brown', 'Winter']), + '132031': ('#6b76ff', '#a5aeff', '#c8e4fe', '#feffe0', ['Blue', 'Yellow', 'Summer']), + '132222': ('#fbeed7', '#ffba5a', '#ff7657', '#665c84', ['Orange']), + '131913': ('#1d2323', '#5c848e', '#decdc3', '#e0e0ec', ['Black', 'Turquoise', 'Grey', 'Winter']), + '131456': ('#f9f8eb', '#a7d7c5', '#74b49b', '#5c8d89', ['Green', 'Pastel']), + '132032': ('#05004e', '#ff0000', '#fb7777', '#ffcccc', ['Blue', 'Red', 'Halloween']), + '131949': ('#612147', '#509aaf', '#7dd8c7', '#f5ffc3', ['Turquoise']), + '132045': ('#fcf5ee', '#fbe8e7', '#f7ddde', '#ffc4d0', ['Skin', 'Pastel', 'White', 'Skin']), + '131527': ('#45b7b8', '#706381', '#2c3848', '#f7de1c', ['Turquoise', 'Grey', 'Yellow']), + '131278': ('#ffffd2', '#e4e4e4', '#8293ff', '#503bff', ['Yellow', 'Blue', 'Summer', 'Bright']), + '131852': ('#fdf0f6', '#951555', '#771144', '#1e0411', ['Pink', 'Purple', 'Black', 'Wedding']), + '131743': ('#d1f6c1', '#45b7b7', '#8b4c8c', '#f57665', ['Green', 'Turquoise', 'Purple', 'Orange', 'Retro']), + '131504': ('#ff9234', '#ffcd3c', '#fefed5', '#35d0ba', ['Orange', 'Turquoise', 'Bright']), + '131839': ('#adccc7', '#144c52', '#053220', '#d34c26', ['Turquoise', 'Orange', 'Brown', 'Winter', 'Cold']), + '130905': ('#64638f', '#9795cf', '#aba9e9', '#cbc9ff', ['Purple', 'Cold', 'Winter']), + '131842': ('#fbf9fa', '#fd0054', '#a80038', '#2b2024', ['Grey', 'Red', 'Black', 'White']), + '131404': ('#373640', '#63686e', '#7e97a6', '#b6f7c1', ['Black', 'Grey', 'Green']), + '131306': ('#f2f4b2', '#cce490', '#0c907d', '#0d627a', ['Green']), + '131234': ('#f9f9f9', '#bcbab8', '#9d8f8f', '#625757', ['Grey']), + '131292': ('#a26ea1', '#f18a9b', '#ffb480', '#ffff9d', ['Sunset', 'Purple', 'Orange', 'Yellow']), + '131235': ('#fff0f8', '#ffc2e9', '#cca2e1', '#543e5c', ['Pink', 'Wedding']), + '131403': ('#373331', '#605a56', '#80ac7b', '#e8eaa1', ['Black', 'Grey', 'Green']), + '130857': ('#7acfdf', '#f47645', '#f9ad8d', '#fde3d9', ['Blue', 'Orange']), + '130847': ('#deecfc', '#b9ceeb', '#87a8d0', '#c3b4d2', ['Blue', 'Grey', 'Winter', 'Pastel']), + '131265': ('#f2f7ff', '#0b409c', '#10316b', '#ffe867', ['Blue', 'Yellow', 'Winter', 'Cold']), + '131233': ('#c7f2e3', '#9ed9c5', '#eeddd2', '#b73535', ['Turquoise', 'Red']), + '130541': ('#9fe8fa', '#26baee', '#73d2f3', '#fff4e0', ['Blue', 'Summer', 'Bright']), + '130807': ('#f7f7f7', '#eeeeee', '#393e46', '#929aab', ['Grey', 'White']), + '132357': ('#a8026f', '#db2d43', '#e76838', '#fbf9af', ['Purple', 'Orange', 'Yellow', 'Sunset']), + '130836': ('#b8ffd0', '#ecffc1', '#ffe6cc', '#dfbaf7', ['Green', 'Yellow', 'Purple', 'Bright', 'Spring', 'Neon']), + '130904': ('#f8b500', '#ece8d9', '#00adb5', '#393e46', ['Orange', 'Turquoise']), + '130476': ('#005792', '#53cde2', '#d1f4fa', '#edf9fc', ['Blue', 'Cold', 'Winter']), + '130941': ('#1fe5bd', '#41a7b3', '#5e227f', '#d22780', ['Turquoise', 'Purple']), + '131266': ('#f2f4fb', '#ff9280', '#ff2400', '#45315d', ['Grey', 'Orange']), + '130199': ('#033fff', '#4a9ff5', '#5ff4ee', '#c2fcf6', ['Blue', 'Cold', 'Winter']), + '130498': ('#ccf0c3', '#bca3ca', '#7c4789', '#4a0e5c', ['Green', 'Purple', 'Retro']), + '130443': ('#000000', '#3e432e', '#616f39', '#a7d129', ['Black', 'Green', 'Dark', 'Winter']), + '130852': ('#73dbc4', '#faf7e6', '#ff008b', '#fff8a1', ['Turquoise', 'Pink', 'Yellow', 'Spring', 'Neon']), + '130428': ('#2d3999', '#9a1ba0', '#f08181', '#ebbb91', ['Purple']), + '130136': ('#f5efe3', '#e6e7e5', '#f7d3ba', '#a6aa9c', ['Grey', 'Pastel', 'Skin']), + '129370': ('#dfe2fe', '#b1cbfa', '#8e98f5', '#7874f2', ['Purple', 'Cold', 'Winter']), + '130871': ('#ff1f5a', '#ffd615', '#f9ff21', '#1e2a78', ['Red', 'Yellow', 'Bright', 'Neon']), + '130221': ('#d1f4fa', '#005792', '#ffe6eb', '#ffcdcd', ['Blue', 'Pink']), + '130422': ('#ddf516', '#12e2a3', '#389168', '#0f117a', ['Yellow', 'Turquoise', 'Blue']), + '130172': ('#343434', '#e6b31e', '#fcfaf1', '#cacaca', ['Grey', 'Orange', 'Gold']), + '130345': ('#0000ff', '#6a5acd', '#add8e6', '#e6e6fa', ['Blue', 'Purple', 'Cold']), + '130295': ('#cb9b42', '#b1d1c5', '#f2f3ee', '#dbd7cb', ['Brown', 'Grey', 'Pastel']), + '130374': ('#ff8000', '#d3560e', '#851e52', '#521168', ['Orange', 'Purple', 'Warm']), + '129119': ('#dcb5ff', '#d9f2ff', '#a5bdfd', '#77529e', ['Pink', 'Blue', 'Purple']), + '129199': ('#f7f4e3', '#d2e1c8', '#fee4a6', '#f9c4aa', ['Green', 'Yellow', 'Pastel', 'Summer']), + '130118': ('#12e6c8', '#a287f4', '#414141', '#000000', ['Turquoise', 'Purple', 'Grey', 'Black']), + '129031': ('#bae5d5', '#d7acd4', '#eec2c2', '#f2f2b0', ['Turquoise', 'Purple', 'Yellow', 'Pastel', 'Retro']), + '130108': ('#573697', '#933f99', '#e88c5d', '#fadbac', ['Purple', 'Orange', 'Wedding']), + '129160': ('#f1fff1', '#c4f0c5', '#be3737', '#6a0000', ['Green', 'Red']), + '128881': ('#ffdfd3', '#fec8d8', '#d291bc', '#957dad', ['Pink', 'Purple', 'Pastel', 'Vintage', 'Warm', 'Skin']), + '129865': ('#a3f3eb', '#f1ffab', '#fbd341', '#fb9a40', ['Blue', 'Yellow', 'Orange', 'Gold', 'Summer', 'Bright']), + '130038': ('#2c2828', '#3b2c85', '#219897', '#85cfcb', ['Black', 'Purple', 'Turquoise', 'Dark', 'Winter']), + '129857': ('#faf6e9', '#ece8d9', '#fffdf6', '#494949', ['Grey', 'Pastel', 'Wedding', 'White', 'Skin']), + '129890': ('#5f1854', '#8b104e', '#1abb9c', '#f7f7f7', ['Purple', 'Turquoise']), + '129673': ('#20716a', '#23a393', '#f4a9c7', '#fff78c', ['Green', 'Pink', 'Yellow', 'Wedding']), + '129495': ('#6bd5e1', '#ffd98e', '#ffb677', '#ff8364', ['Blue', 'Yellow', 'Orange', 'Summer']), + '130290': ('#612c83', '#509aaf', '#7dd8c7', '#f5ffc3', ['Purple', 'Turquoise', 'Yellow']), + '129982': ('#c3f1ff', '#f87d42', '#db3951', '#00136c', ['Blue', 'Orange']), + '128882': ('#f0ece2', '#dfd3c3', '#c7b198', '#596e79', ['Grey', 'Brown', 'Pastel', 'Vintage', 'Skin']), + '127205': ('#fb929e', '#ffdfdf', '#fff6f6', '#aedefc', ['Pink', 'Blue']), + '129224': ('#f5e965', '#ff9668', '#db456f', '#a74faf', ['Yellow', 'Orange', 'Purple', 'Sunset', 'Neon']), + '128764': ('#dbf1f2', '#cd5555', '#882042', '#efedbb', ['Blue', 'Red', 'Yellow', 'Vintage', 'Wedding']), + '126476': ('#d3d5fd', '#929aab', '#474a56', '#0b0b0d', ['Purple', 'Grey', 'Black', 'Winter', 'Cold']), + '126653': ('#35013f', '#b643cd', '#ff5da2', '#99ddcc', ['Black', 'Purple', 'Pink', 'Turquoise', 'Wedding', 'Retro', 'Neon']), + '126189': ('#eeeeee', '#7971ea', '#393e46', '#222831', ['Grey', 'Purple', 'Black', 'Wedding']), + '128556': ('#a1c45a', '#fff9e0', '#f1c550', '#ea4c4c', ['Green', 'Yellow', 'Red', 'Summer']), + '126603': ('#481380', '#742dd2', '#efb1ff', '#ffe2ff', ['Purple', 'Pink', 'Cold']), + '126547': ('#00a8b5', '#774898', '#e62a76', '#fbb901', ['Turquoise', 'Purple', 'Pink', 'Yellow', 'Retro']), + '125778': ('#fdfdc4', '#ffe8cf', '#ffdede', '#ccffec', ['Yellow', 'Pink', 'Turquoise', 'Bright', 'Pastel', 'Summer']), + '125409': ('#ecf4f3', '#76dbd1', '#57a99a', '#555151', ['Grey', 'Turquoise']), + '125435': ('#f0f2eb', '#b5592a', '#f09027', '#8cbeaa', ['Grey', 'Brown', 'Turquoise', 'Autumn', 'Skin']), + '126369': ('#f30e5c', '#f6f3a7', '#f6c523', '#228c7b', ['Red', 'Yellow', 'Green', 'Spring']), + '125519': ('#b6e1e0', '#9cd3d3', '#e8630a', '#2b4353', ['Blue', 'Orange']), + '125408': ('#363434', '#5c5757', '#62929a', '#efecec', ['Black', 'Grey', 'Turquoise', 'Winter']), + '125661': ('#e9e2d0', '#ea9085', '#6e5773', '#4f323b', ['Orange', 'Purple', 'Vintage', 'Wedding']), + '125679': ('#a3a7e4', '#bae2be', '#f0f1b3', '#c5e5e3', ['Purple', 'Green', 'Yellow', 'Blue', 'Summer']), + '126188': ('#ff5959', '#ffad5a', '#4f9da6', '#1a0841', ['Red', 'Orange', 'Turquoise', 'Retro']), + '125424': ('#89f8ce', '#f5fac7', '#dec8ed', '#cc99f9', ['Green', 'Yellow', 'Purple', 'Bright', 'Neon']), + '125434': ('#7b3c3c', '#db5f29', '#f0f0e4', '#68bde1', ['Brown', 'Orange', 'Blue', 'Retro']), + '125272': ('#e0ffcd', '#fdffcd', '#ffebbb', '#ffcab0', ['Green', 'Yellow', 'Orange', 'Pastel', 'Bright', 'Summer']), + '125503': ('#182952', '#2b3595', '#7045af', '#e14594', ['Blue', 'Purple', 'Dark']), + '124846': ('#f7f7f7', '#393e46', '#5c636e', '#f8b500', ['Grey', 'Yellow', 'White']), + '125267': ('#ffd96a', '#f34949', '#ff9090', '#ffb6b9', ['Yellow', 'Red', 'Pink', 'Warm', 'Summer']), + '125004': ('#155e63', '#76b39d', '#f9f8eb', '#eae7e7', ['Turquoise', 'Green', 'Grey']), + '125241': ('#ff9900', '#ca431d', '#8b104e', '#520556', ['Orange', 'Purple', 'Warm', 'Sunset']), + '125016': ('#f9499e', '#fff0db', '#bbbbbb', '#5e5e5e', ['Pink', 'Yellow', 'Grey', 'Wedding']), + '125270': ('#f7aa00', '#235784', '#40a8c4', '#bcdbdf', ['Orange', 'Blue', 'Vintage']), + '124844': ('#f7f7f7', '#3b0944', '#5f1854', '#1abb9c', ['Grey', 'Purple', 'Turquoise', 'Wedding', 'Retro', 'White']), + '124795': ('#f5f4e8', '#c50d66', '#f07810', '#eec60a', ['Grey', 'Red', 'Orange', 'Yellow']), + '124945': ('#fef9d9', '#ce7d00', '#935900', '#00541a', ['Yellow', 'Brown', 'Green', 'Vintage', 'Skin']), + '125279': ('#fad3cf', '#a696c8', '#2470a0', '#060608', ['Pink', 'Purple', 'Blue', 'Black', 'Wedding']), + '124759': ('#f2f2f2', '#ebd5d5', '#ea8a8a', '#685454', ['Grey', 'Pink', 'Brown', 'Pastel', 'White', 'Skin']), + '125017': ('#ff6473', '#757882', '#5cc1b3', '#6ef7c8', ['Red', 'Grey', 'Turquoise']), + '124691': ('#fff6da', '#84f2d6', '#fc6b3f', '#262525', ['Yellow', 'Turquoise', 'Orange', 'Black', 'Retro', 'Neon']), + '124981': ('#87e5da', '#92a4c0', '#f4adad', '#e58cdb', ['Turquoise', 'Pink', 'Purple', 'Vintage']), + '124653': ('#ffffe3', '#87e0ff', '#53c7f0', '#1d97c1', ['Yellow', 'Blue', 'Summer']), + '124611': ('#13334c', '#005792', '#f6f6e9', '#fd5f00', ['Blue', 'Orange']), + '124591': ('#e01171', '#ab0e86', '#59057b', '#0f0766', ['Red', 'Purple']), + '124558': ('#d5eeff', '#f7ca44', '#a2792f', '#5c3c10', ['Blue', 'Yellow', 'Brown']), + '124494': ('#de5b7b', '#eccfd1', '#f0e3c4', '#98ded3', ['Red', 'Pink', 'Yellow', 'Turquoise']), + '124492': ('#1b3764', '#4ab8b8', '#fafccb', '#efa35c', ['Blue', 'Turquoise', 'Yellow', 'Orange']), + '124440': ('#0e0220', '#e40475', '#48e0e4', '#d7fbf6', ['Black', 'Pink', 'Blue', 'Retro', 'Wedding']), + '124219': ('#2e99b0', '#fcd77f', '#ff2e4c', '#1e1548', ['Blue', 'Yellow', 'Red']), + '124355': ('#7a4579', '#d56073', '#ec9e69', '#ffff8f', ['Purple', 'Red', 'Orange', 'Yellow', 'Sunset']), + '124155': ('#dd0a35', '#e4d1d3', '#1687a7', '#014955', ['Red', 'Blue']), + '124065': ('#d0efb5', '#eb7878', '#2f3e75', '#f3e595', ['Green', 'Red', 'Blue', 'Yellow', 'Vintage']), + '124180': ('#0e3150', '#6dc9c8', '#ffc0c2', '#f7e9e3', ['Blue', 'Turquoise', 'Pink']), + '123915': ('#fff6f6', '#ffe5ab', '#a1c45a', '#ffcdb5', ['Pink', 'Yellow', 'Green', 'White']), + '123973': ('#233142', '#455d7a', '#f95959', '#facf5a', ['Black', 'Blue', 'Red', 'Yellow', 'Halloween']), + '123883': ('#d1478c', '#ff7a5c', '#f7f9ff', '#53d397', ['Purple', 'Orange', 'Grey', 'Green']), + '123619': ('#ff9393', '#ff6767', '#ff3434', '#0c317a', ['Pink', 'Red', 'Blue']), + '123723': ('#edf0c7', '#4e9525', '#2e5a1c', '#ff5c00', ['Green', 'Orange', 'Christmas']), + '123522': ('#ffd3ad', '#ffa96a', '#005585', '#15005d', ['Orange', 'Blue']), + '123266': ('#35d0ba', '#f8c43a', '#c93d1b', '#04322e', ['Turquoise', 'Yellow', 'Orange', 'Retro']), + '123079': ('#feb062', '#575151', '#3f3b3b', '#e7b3b3', ['Orange', 'Grey', 'Pink', 'Vintage']), + '123388': ('#efff9d', '#2aa9d2', '#1874c3', '#2931b3', ['Yellow', 'Blue']), + '122811': ('#232931', '#f73859', '#f1d18a', '#ededed', ['Black', 'Red', 'Yellow', 'Grey']), + '123063': ('#005874', '#1c819e', '#e6e6d4', '#ffbe00', ['Blue', 'Yellow', 'Retro']), + '122132': ('#fbd685', '#63aebb', '#7a5d7e', '#312b30', ['Yellow', 'Turquoise', 'Purple', 'Wedding']), + '122076': ('#7c203a', '#f85959', '#ff9f68', '#feff89', ['Red', 'Orange', 'Yellow', 'Warm', 'Sunset', 'Neon']), + '122308': ('#f5f5c6', '#7da87b', '#326765', '#27253d', ['Yellow', 'Green', 'Black']), + '124272': ('#99e1e5', '#f3e8cb', '#f2c6b4', '#fbafaf', ['Blue', 'Yellow', 'Orange', 'Pink', 'Pastel', 'Summer']), + '122131': ('#f5b17b', '#4e709d', '#89a4c7', '#cdd5e0', ['Orange', 'Blue', 'Grey']), + '121992': ('#db3b61', '#ef3f61', '#3a3a59', '#555574', ['Red', 'Grey']), + '121977': ('#f5eee6', '#f3d7ca', '#e6a4b4', '#c86b85', ['Orange', 'Pink', 'Pastel', 'Skin']), + '121928': ('#2d095c', '#20366b', '#dd7777', '#eae3e3', ['Purple', 'Blue', 'Red', 'Grey']), + '121927': ('#aa530e', '#df8931', '#f5c16c', '#f3eded', ['Brown', 'Orange', 'Grey', 'Autumn', 'Gold', 'Skin']), + '121899': ('#860f44', '#bb3939', '#ea5f2d', '#eec89f', ['Red', 'Orange', 'Warm', 'Halloween']), + '121900': ('#17bebb', '#2e282a', '#cd5334', '#edb88b', ['Turquoise', 'Black', 'Orange']), + '121795': ('#ffeaa5', '#fe5f55', '#c7efcf', '#eef5db', ['Yellow', 'Red', 'Green', 'Summer', 'Spring']), + '121870': ('#35477d', '#6c5b7b', '#c06c84', '#f67280', ['Blue', 'Red']), + '123653': ('#eda1c1', '#fab2ac', '#bee4d2', '#d7f8f7', ['Pink', 'Orange', 'Green', 'Blue', 'Pastel', 'Spring']), + '122050': ('#1a2c5b', '#3e4e88', '#7971ea', '#b8dff0', ['Blue', 'Purple', 'Winter', 'Cold']), + '123528': ('#fffdb7', '#aef4a4', '#79b8d1', '#e36488', ['Yellow', 'Green', 'Blue', 'Pink']), + '121829': ('#2b007b', '#2f89fc', '#e7e6fc', '#dd7c1b', ['Blue', 'Purple', 'Orange', 'Wedding']), + '124879': ('#eaa81b', '#c95501', '#7d0000', '#012c0b', ['Orange', 'Warm', 'Autumn', 'Gold', 'Skin']), + '121517': ('#2d4059', '#ffb400', '#f6f6f6', '#ea5455', ['Orange', 'Grey', 'Red', 'Retro']), + '121859': ('#f9fa9b', '#ff7777', '#ceecf0', '#f0f3f3', ['Yellow', 'Red', 'Blue', 'Grey', 'Spring', 'Bright']), + '122310': ('#5e8b6f', '#436e4f', '#fa8f4d', '#f87829', ['Green', 'Orange']), + '121496': ('#fee9d7', '#f9bf8f', '#e2434b', '#34222e', ['Orange', 'Red', 'Warm', 'Autumn', 'Halloween', 'Skin']), + '122094': ('#535238', '#4bbb8b', '#6ddabe', '#c9ffc7', ['Brown', 'Green', 'Turquoise']), + '121460': ('#424153', '#fdadc7', '#ea4c88', '#993399', ['Pink', 'Purple']), + '121096': ('#1b3c59', '#456173', '#a6ed8e', '#f2f2f0', ['Blue', 'Green', 'Grey']), + '121558': ('#ffffc1', '#ffd2a5', '#d38cad', '#8a79af', ['Yellow', 'Orange', 'Purple', 'Pastel', 'Sunset']), + '120781': ('#0d7e83', '#13293d', '#ffaf87', '#eef0f2', ['Turquoise', 'Orange', 'Grey', 'Retro']), + '120467': ('#fd5f00', '#00204a', '#005792', '#d9faff', ['Orange', 'Blue']), + '120199': ('#f76262', '#216583', '#65c0ba', '#cffdf8', ['Red', 'Blue', 'Turquoise']), + '120122': ('#ff7517', '#3e3939', '#2c2727', '#f6f4f4', ['Orange', 'Grey', 'Black']), + '120121': ('#f9f8ed', '#c4e3cb', '#6a9c78', '#fff1bc', ['Yellow', 'Green']), + '120066': ('#480032', '#df0054', '#ff8b6a', '#ffd2bb', ['Red', 'Orange', 'Halloween']), + '120172': ('#ffa258', '#fff7c2', '#a02a63', '#4b125c', ['Orange', 'Yellow', 'Purple', 'Autumn', 'Halloween']), + '119977': ('#003545', '#00454a', '#3c6562', '#ed6363', ['Navy', 'Dark', 'Turquoise', 'Red', 'Dark']), + '119891': ('#90aeff', '#cefc86', '#60efb8', '#f9f7f7', ['Blue', 'Green', 'Grey', 'Bright']), + '119477': ('#6900ff', '#9951ff', '#ffd700', '#faf7ff', ['Purple', 'Yellow', 'Wedding', 'Bright']), + '119402': ('#203541', '#374955', '#f62a66', '#ffd933', ['Black', 'Red', 'Yellow']), + '118963': ('#f4f9f4', '#c4e3cb', '#8aae92', '#616161', ['Grey', 'Green']), + '119315': ('#333366', '#ff5f5f', '#f9e75e', '#f0f0f0', ['Red', 'Yellow', 'Grey']), + '119560': ('#fbffa8', '#74dac6', '#20c1bd', '#33354a', ['Yellow', 'Turquoise', 'Black']), + '118964': ('#092a35', '#658525', '#cfee91', '#f8eeb4', ['Black', 'Green', 'Yellow']), + '119215': ('#92e6e6', '#fff9af', '#d65d7a', '#524c84', ['Blue', 'Yellow', 'Red']), + '119059': ('#bad7df', '#ffe2e2', '#f6f6f6', '#99ddcc', ['Blue', 'Pink', 'Grey', 'Green', 'Pastel', 'Wedding', 'Spring']), + '118962': ('#283149', '#404b69', '#00818a', '#dbedf3', ['Black', 'Turquoise', 'Dark', 'Winter']), + '120110': ('#fff9e0', '#f1c550', '#ff6600', '#ce2525', ['Yellow', 'Orange', 'Red', 'Warm', 'Autumn', 'Gold']), + '118872': ('#323643', '#606470', '#93deff', '#f7f7f7', ['Black', 'Grey', 'Blue', 'Cold', 'Winter']), + '118869': ('#5ba19b', '#fceaea', '#f5d9d9', '#fbead1', ['Turquoise', 'Pink', 'Yellow', 'Wedding', 'Pastel']), + '118850': ('#404b69', '#283149', '#f73859', '#f3ecc8', ['Blue', 'Red', 'Yellow']), + '118847': ('#eeeeee', '#ff7100', '#be3030', '#222222', ['Grey', 'Orange', 'Black', 'Autumn']), + '118762': ('#eaafaf', '#a2738c', '#645c84', '#427996', ['Pink', 'Purple', 'Pastel', 'Wedding', 'Pastel']), + '118629': ('#e9fadd', '#b8e4c9', '#3f5468', '#42291c', ['Green', 'Blue', 'Black']), + '118795': ('#a8e6cf', '#fdffab', '#ffd3b6', '#ffaaa5', ['Green', 'Yellow', 'Orange', 'Red', 'Pastel', 'Spring', 'Bright']), + '118927': ('#e7759a', '#ffa35f', '#ba78cd', '#755da3', ['Pink', 'Orange', 'Purple']), + '118594': ('#062743', '#113a5d', '#c4ffdd', '#f9f9f9', ['Blue', 'Green', 'Grey', 'Cold']), + '118766': ('#ef7b7b', '#fcf3ca', '#c4eada', '#919190', ['Red', 'Yellow', 'Grey']), + '118677': ('#feffdf', '#dde0ab', '#97cba9', '#668ba4', ['Yellow', 'Green', 'Turquoise', 'Blue', 'Wedding']), + '118591': ('#062743', '#113a5d', '#ff7a8a', '#f9f9f9', ['Blue', 'Pink', 'Grey']), + '118622': ('#fce8aa', '#97de95', '#08c299', '#571179', ['Yellow', 'Green', 'Purple', 'Spring']), + '118585': ('#083358', '#0f4471', '#fc3c3c', '#f6f6f6', ['Blue', 'Red', 'Grey', 'Winter']), + '118479': ('#ffd3ad', '#ffa96a', '#005585', '#15005d', ['Orange', 'Blue']), + '118376': ('#f2f2f0', '#ff5e3a', '#2c365d', '#272e4f', ['Grey', 'Orange', 'Blue', 'Halloween', 'White']), + '118368': ('#feeb97', '#4fb783', '#409d9b', '#034561', ['Yellow', 'Green', 'Turquoise', 'Blue']), + '118331': ('#f8b195', '#f67280', '#c06c84', '#355c7d', ['Orange', 'Red', 'Blue', 'Wedding', 'Autumn', 'Warm']), + '118279': ('#090089', '#0060ca', '#91ceff', '#fcdc74', ['Blue', 'Yellow', 'Cold']), + '118126': ('#294a66', '#0b3846', '#ffbbbb', '#fcd2c2', ['Blue', 'Pink', 'Wedding']), + '118028': ('#240041', '#900048', '#ff4057', '#ff8260', ['Purple', 'Red', 'Orange', 'Halloween']), + '117924': ('#eff0f4', '#74dbef', '#0074e4', '#264e86', ['Grey', 'Blue', 'Cold']), + '117701': ('#f8d5f0', '#58d5d3', '#41a4c3', '#3f4b83', ['Pink', 'Turquoise', 'Blue']), + '117699': ('#fff1bc', '#7dc383', '#6a9c78', '#446e5c', ['Yellow', 'Green']), + '117613': ('#002bdc', '#2f4bff', '#00a6e7', '#ffe37f', ['Blue', 'Yellow']), + '117601': ('#232931', '#393e46', '#4ecca3', '#eeeeee', ['Black', 'Grey', 'Turquoise', 'Dark']), + '117579': ('#f6ec66', '#fadc6d', '#f97272', '#f65454', ['Yellow', 'Red']), + '117514': ('#702283', '#962071', '#76b39d', '#fdb44b', ['Purple', 'Green', 'Yellow', 'Retro']), + '117565': ('#faffb8', '#c5f0a4', '#35b0ab', '#226b80', ['Yellow', 'Green', 'Turquoise', 'Bright']), + '117448': ('#f8b595', '#f67280', '#c06c84', '#6c5b7c', ['Orange', 'Red', 'Purple', 'Pastel', 'Halloween', 'Skin']), + '117192': ('#448ef6', '#75c2f6', '#65daf7', '#ffe981', ['Blue', 'Yellow', 'Bright']), + '116909': ('#e4eddb', '#307672', '#144d53', '#1a3c40', ['Green', 'Turquoise', 'Winter']), + '116708': ('#ff4d4d', '#ff8364', '#fdb87d', '#ffe8d5', ['Red', 'Orange', 'Warm']), + '117534': ('#fafaf6', '#00fff0', '#00d1ff', '#3d6cb9', ['Grey', 'Turquoise', 'Blue', 'Bright', 'Cold', 'White', 'Neon']), + '116691': ('#1c1124', '#684656', '#de774e', '#b7e1b5', ['Black', 'Orange', 'Green', 'Vintage', 'Halloween', 'Autumn']), + '116690': ('#1c1124', '#693e52', '#74b49b', '#a7d7c5', ['Black', 'Green', 'Vintage', 'Wedding']), + '116678': ('#8ea6b4', '#e7eff3', '#ff8f56', '#984a59', ['Grey', 'Orange', 'Autumn', 'Winter']), + '116554': ('#45eba5', '#21aba5', '#1d566e', '#163a5f', ['Green', 'Turquoise', 'Blue']), + '116599': ('#011f3f', '#0960bd', '#429ffd', '#fef2bf', ['Blue', 'Yellow', 'Cold']), + '116542': ('#ff6107', '#e9290f', '#c40018', '#292725', ['Orange', 'Red', 'Black', 'Warm']), + '118369': ('#f7f7f7', '#ff570c', '#606470', '#323643', ['Grey', 'Orange', 'White']), + '116523': ('#84b9ef', '#fbe4c9', '#ff5d5d', '#952e4b', ['Blue', 'Red', 'Spring']), + '116408': ('#78fee0', '#4bc2c5', '#3b9a9c', '#fef4a9', ['Turquoise', 'Yellow', 'Neon']), + '116289': ('#ecf0f1', '#33cccc', '#2980b9', '#2c3e50', ['Grey', 'Turquoise', 'Blue', 'Cold']), + '114376': ('#edfead', '#d9f489', '#bdcf88', '#d95858', ['Yellow', 'Green', 'Red', 'Christmas']), + '114273': ('#ff6138', '#ffff9d', '#beeb9f', '#79bd8f', ['Red', 'Yellow', 'Green', 'Summer', 'Spring', 'Bright']), + '114244': ('#394a51', '#7fa99b', '#fbf2d5', '#fdc57b', ['Turquoise', 'Orange']), + '114174': ('#283149', '#404b69', '#f73859', '#dbedf3', ['Red', 'Blue']), + '114093': ('#fbfae1', '#cef0b9', '#64a36f', '#ffe121', ['Yellow', 'Green', 'Bright']), + '112989': ('#f56a47', '#b32c50', '#681a1e', '#0a0944', ['Orange', 'Red', 'Brown', 'Warm', 'Halloween']), + '112572': ('#f8f9fc', '#c00000', '#de3c3c', '#f7b32d', ['Grey', 'Red', 'Orange', 'Warm', 'White']), + '112238': ('#ffe6eb', '#ffcdcd', '#6a65d8', '#1d2786', ['Pink', 'Purple', 'Wedding', 'Skin']), + '112038': ('#28544b', '#acbd86', '#ffd6a0', '#ffa06f', ['Green', 'Orange', 'Autumn']), + '112036': ('#6c567b', '#c06c84', '#f67280', '#f8b195', ['Purple', 'Red', 'Warm']), + '111625': ('#fffb97', '#97ffcf', '#2fe1d6', '#38c6bd', ['Yellow', 'Turquoise', 'Summer', 'Spring', 'Bright', 'Neon']), + '111393': ('#e7f5f2', '#f9c7cf', '#12776f', '#0f4137', ['Pink', 'Turquoise', 'Wedding']), + '111218': ('#375a7f', '#4d7cae', '#6a99cb', '#fcfa70', ['Blue', 'Yellow', 'Winter', 'Cold']), + '111185': ('#360982', '#b72a67', '#ff9797', '#fde8cb', ['Blue', 'Purple', 'Pink', 'Sunset', 'Wedding']), + '111086': ('#323232', '#8559a5', '#6db193', '#f4e5c2', ['Black', 'Purple', 'Green', 'Retro']), + '111027': ('#e95280', '#23b1a5', '#ffdd7e', '#f3f3f3', ['Pink', 'Turquoise', 'Yellow', 'Grey', 'Summer']), + '110992': ('#22559c', '#f27370', '#fa9856', '#ede862', ['Blue', 'Red', 'Orange', 'Yellow', 'Sunset']), + '110977': ('#abedd8', '#46cdcf', '#0081c6', '#48466d', ['Blue', 'Turquoise']), + '110878': ('#fae3e3', '#b7b7b7', '#137083', '#3d0240', ['Pink', 'Grey', 'Turquoise', 'Purple', 'Wedding', 'Vintage', 'Skin']), + '110868': ('#11cbd7', '#c6f1e7', '#f0fff3', '#fa4659', ['Turquoise', 'Red', 'Bright', 'Cold']), + '115428': ('#fda403', '#e8751a', '#c51350', '#8a1253', ['Orange', 'Purple', 'Halloween', 'Autumn', 'Warm', 'Gold']), + '110859': ('#a7efe9', '#7fdfd4', '#fbe1b6', '#fbac91', ['Turquoise', 'Orange', 'Summer']), + '110982': ('#032a33', '#255965', '#4c6f7b', '#f1d18a', ['Black', 'Turquoise', 'Yellow']), + '110660': ('#faa9e0', '#f8b3eb', '#eaa3fc', '#fce4b0', ['Pink', 'Purple', 'Yellow', 'Pastel', 'Spring']), + '110659': ('#fbf0f0', '#dfd3d3', '#b8b0b0', '#7c7575', ['Pink', 'Grey', 'Skin']), + '110922': ('#ff6d24', '#4e413b', '#857671', '#e2ded3', ['Orange', 'Brown', 'Grey', 'Autumn', 'Skin']), + '110354': ('#f4eec0', '#aed09e', '#61b292', '#7e6752', ['Yellow', 'Green', 'Turquoise', 'Brown']), + '110223': ('#c7f3ff', '#fdc7ff', '#ffdcf5', '#f2f4c3', ['Blue', 'Pink', 'Yellow', 'Bright', 'Spring']), + '109426': ('#f6efb4', '#35c2bd', '#2796cb', '#3379e4', ['Yellow', 'Turquoise', 'Blue']), + '109414': ('#00204a', '#005792', '#00bbf0', '#fdb44b', ['Blue', 'Orange', 'Cold']), + '109517': ('#f12b6b', '#ff467e', '#fd94b4', '#f6c7c7', ['Red', 'Pink', 'Spring']), + '109389': ('#f6ffcd', '#bcffa8', '#6ba083', '#4f323b', ['Yellow', 'Green']), + '108974': ('#00204a', '#005792', '#00bbf0', '#d9faff', ['Blue', 'Winter', 'Cold']), + '108807': ('#fcfcfc', '#83ffe6', '#ff5f5f', '#2c2c2c', ['Grey', 'Turquoise', 'Red', 'Black', 'Neon']), + '108676': ('#ececeb', '#f9a828', '#07617d', '#2e383f', ['Grey', 'Orange', 'Blue']), + '108574': ('#ff6464', '#ff8264', '#ffaa64', '#fff5a5', ['Red', 'Orange', 'Yellow', 'Summer', 'Warm']), + '108559': ('#f9f8eb', '#76b39d', '#155263', '#f0b917', ['Yellow', 'Turquoise']), + '108539': ('#fffcef', '#d2ebcd', '#ff7f5b', '#393939', ['Yellow', 'Green', 'Orange', 'Vintage']), + '109078': ('#6b0848', '#a40a3c', '#ec610a', '#ffc300', ['Purple', 'Red', 'Orange', 'Yellow', 'Warm', 'Halloween']), + '108347': ('#0278ae', '#51adcf', '#a5ecd7', '#e8ffc1', ['Blue', 'Turquoise', 'Yellow', 'Winter', 'Cold']), + '108305': ('#70d4b4', '#ffebb7', '#bbbbbb', '#aaaaaa', ['Turquoise', 'Yellow', 'Grey']), + '108180': ('#ec7700', '#d65f00', '#c04d00', '#efefef', ['Orange', 'Grey', 'Gold', 'Skin']), + '108152': ('#3a0088', '#930077', '#e61c5d', '#ffbd39', ['Blue', 'Purple', 'Red', 'Yellow']), + '108141': ('#194769', '#f6f6e9', '#d7eef2', '#f2855e', ['Blue', 'Orange']), + '108068': ('#0e9577', '#04dead', '#f1efb9', '#fbfae1', ['Green', 'Yellow', 'Spring']), + '107892': ('#970747', '#fef4e8', '#1989ac', '#283e56', ['Red', 'Blue', 'Retro']), + '108560': ('#fdfdeb', '#f9ce00', '#00818a', '#09194f', ['Green', 'Blue']), + '107677': ('#0f3057', '#00587a', '#008891', '#e7e7de', ['Blue', 'Turquoise', 'Grey', 'Cold', 'Winter']), + '107673': ('#9f609c', '#ea8f79', '#e4d183', '#f8f1e5', ['Purple', 'Orange', 'Yellow', 'Pastel', 'Wedding']), + '107618': ('#283149', '#404b69', '#da0463', '#dbedf3', ['Grey', 'Red']), + '107483': ('#f4e8c1', '#a0c1b8', '#726a95', '#351f39', ['Yellow', 'Grey', 'Purple', 'Black', 'Retro']), + '107482': ('#ffb6b9', '#fae3d9', '#bbded6', '#61c0bf', ['Red', 'Turquoise', 'Pastel', 'Wedding']), + '107279': ('#ecfafb', '#81cbc8', '#4aa6b5', '#d6c481', ['Turquoise', 'Wedding']), + '107218': ('#5628b4', '#d80e70', '#e7455f', '#f7b236', ['Purple', 'Red', 'Yellow', 'Neon']), + '107208': ('#f4f4f4', '#65eeb7', '#ff5722', '#474744', ['Grey', 'Turquoise', 'Orange', 'Neon']), + '107172': ('#232855', '#215b63', '#5fcc9c', '#aaffc7', ['Blue', 'Turquoise', 'Green']), + '107141': ('#4a772f', '#ffdd00', '#fa9e05', '#a7095c', ['Green', 'Yellow', 'Orange', 'Purple']), + '107139': ('#ffa3ac', '#00043c', '#005d6c', '#00c9b1', ['Pink', 'Blue', 'Turquoise', 'Wedding']), + '107050': ('#265961', '#227066', '#76a665', '#ffdd5c', ['Green', 'Yellow']), + '106985': ('#17139c', '#dd3e3e', '#ffe5e1', '#f2f2f2', ['Blue', 'Red', 'Grey', 'Retro']), + '106972': ('#ff7777', '#fff195', '#fcffbf', '#f5e9ff', ['Red', 'Yellow', 'Pink', 'Bright', 'Summer', 'Spring']), + '106827': ('#ebebeb', '#fec100', '#528078', '#3e615b', ['Grey', 'Yellow', 'Turquoise']), + '106929': ('#333644', '#84577c', '#c65f63', '#f6e1b8', ['Black', 'Purple', 'Red', 'Yellow', 'Vintage']), + '106789': ('#fdfdfd', '#e1eb71', '#ecab69', '#e36161', ['Grey', 'Yellow', 'Orange', 'Red', 'Summer', 'White']), + '106748': ('#f2d1a8', '#ebebeb', '#669b7c', '#557669', ['Orange', 'Grey', 'Green']), + '106736': ('#8e1d41', '#dbbf0d', '#ffcd19', '#ffefb4', ['Purple', 'Yellow']), + '106735': ('#111f4d', '#f2f4f7', '#e43a19', '#020205', ['Black', 'Grey', 'Orange', 'Blue', 'Retro', 'White']), + '106734': ('#fcf9f4', '#ffc97c', '#ea7659', '#c1c1c1', ['Orange', 'Grey', 'Autumn', 'White', 'Skin']), + '106733': ('#5f4444', '#af3264', '#ff63b5', '#ffbbbb', ['Brown', 'Purple', 'Pink']), + '106719': ('#bc5148', '#fef8e6', '#7bcecc', '#3090a1', ['Red', 'Yellow', 'Blue']), + '106550': ('#e7e6e1', '#f7f6e7', '#c1c0b9', '#537791', ['Grey', 'Blue', 'Retro']), + '106475': ('#faf4d0', '#c14545', '#ea4c4c', '#703b3b', ['Yellow', 'Red', 'Brown', 'Warm']), + '106516': ('#ecfeff', '#00b7c2', '#128494', '#4ef037', ['Blue', 'Turquoise', 'Green', 'Bright', 'Neon']), + '106499': ('#d0ef84', '#f4d143', '#fda831', '#de561c', ['Green', 'Yellow', 'Orange', 'Autumn', 'Gold']), + '106460': ('#fffbcc', '#fd2e2e', '#cf1b1b', '#900d0d', ['Yellow', 'Red', 'Warm']), + '106353': ('#248888', '#e6e6e6', '#e7475e', '#f0d879', ['Turquoise', 'Grey', 'Red', 'Yellow']), + '106339': ('#e1ffcf', '#cfcbf1', '#bab5f6', '#4d3664', ['Green', 'Purple', 'Retro', 'Wedding', 'Bright']), + '106302': ('#08085e', '#a2ef44', '#fff07a', '#e8fcf6', ['Blue', 'Green', 'Yellow']), + '106083': ('#f6c667', '#b30753', '#280f34', '#bff4ed', ['Yellow', 'Purple', 'Turquoise', 'Retro']), + '105887': ('#ffdd93', '#58dada', '#1ca2bb', '#005e7c', ['Orange', 'Blue', 'Summer']), + '105848': ('#fffde1', '#fef778', '#fba746', '#7f7f7f', ['Yellow', 'Orange', 'Grey', 'Gold']), + '105677': ('#393232', '#4d4545', '#8d6262', '#ed8d8d', ['Grey', 'Pink', 'Dark', 'Skin']), + '105661': ('#a9eca2', '#f5ffcb', '#ffe3b0', '#f5c8bd', ['Green', 'Yellow', 'Orange', 'Pastel', 'Summer', 'Bright']), + '105495': ('#36626a', '#588d9c', '#73b1c1', '#f1d18a', ['Blue', 'Yellow', 'Winter', 'Wedding']), + '105407': ('#211572', '#24bddf', '#f4f4f4', '#fffdbb', ['Blue', 'Grey', 'Yellow', 'Wedding']), + '105558': ('#f7f2c1', '#f0ca6d', '#48ba95', '#403321', ['Yellow', 'Turquoise']), + '105358': ('#282d4f', '#23103a', '#a0204c', '#ff6c00', ['Blue', 'Dark', 'Purple', 'Orange', 'Halloween']), + '105443': ('#ffc7c7', '#ffe2e2', '#f6f6f6', '#8785a2', ['Pink', 'Purple', 'Retro', 'Wedding', 'Skin']), + '105240': ('#f2e8c6', '#f5841a', '#bb0029', '#03002c', ['Yellow', 'Orange', 'Red', 'Black', 'Halloween', 'Autumn']), + '105342': ('#096c47', '#0b8457', '#eac100', '#f8f1d0', ['Green', 'Yellow']), + '105206': ('#211572', '#48c0d3', '#dedede', '#ffe578', ['Blue', 'Grey', 'Yellow', 'Retro', 'Wedding']), + '105115': ('#3e333f', '#fc4442', '#f0e19e', '#f2f2f2', ['Black', 'Red', 'Yellow', 'Grey']), + '104108': ('#c6de41', '#2d6e7e', '#153b44', '#071c21', ['Green', 'Turquoise']), + '104487': ('#f6490d', '#000249', '#1dced8', '#faf9f0', ['Orange', 'Blue', 'Grey']), + '103966': ('#071a52', '#086972', '#17b978', '#a7ff83', ['Blue', 'Turquoise', 'Green', 'Neon']), + '103371': ('#363636', '#dc2f2f', '#ff894c', '#f8f8f8', ['Grey', 'Red', 'Orange']), + '103635': ('#fcf9f9', '#f1f864', '#bceb3c', '#7cbd1e', ['Grey', 'Yellow', 'Green', 'Summer', 'Bright', 'Spring', 'White', 'Neon']), + '102684': ('#000000', '#86003c', '#e41f7b', '#ff8ba0', ['Black', 'Pink', 'Dark']), + '103350': ('#e0fcff', '#bde4f4', '#404969', '#ff7f50', ['Blue', 'Orange', 'Winter']), + '102454': ('#a1d9ff', '#ca82f8', '#ed93cb', '#f2bbbb', ['Blue', 'Purple', 'Pink', 'Wedding']), + '101919': ('#734488', '#492645', '#9febeb', '#fafcdb', ['Purple', 'Blue', 'Yellow', 'Wedding', 'Retro', 'Wedding']), + '101494': ('#ff895d', '#d5eeff', '#78bbe6', '#1b435d', ['Orange', 'Blue']), + '100840': ('#302939', '#50595c', '#e99b9b', '#ffd8d8', ['Black', 'Grey', 'Pink']), + '101875': ('#1fffff', '#fffde1', '#ff9d76', '#ff4273', ['Turquoise', 'Yellow', 'Orange', 'Red', 'Summer', 'Spring', 'Bright', 'Neon']), + '101433': ('#212125', '#239d60', '#a3de83', '#f7f39a', ['Black', 'Green', 'Yellow']), + '101294': ('#fafafa', '#ffe9e3', '#c4c1e0', '#7c73e6', ['Grey', 'Pink', 'Purple', 'Vintage', 'Wedding', 'White']), + '100741': ('#624464', '#d02e77', '#fed6be', '#fffee6', ['Purple', 'Wedding']), + '101436': ('#fbfbfb', '#b9e1dc', '#f38181', '#756c83', ['Grey', 'Turquoise', 'Red', 'Vintage', 'Retro', 'White']), + '101251': ('#3f52e3', '#f6f6f6', '#efe891', '#f12d2d', ['Blue', 'Grey', 'Yellow', 'Red', 'Summer']), + '98686': ('#323232', '#295f4e', '#6db193', '#f4e5c2', ['Black', 'Green', 'Yellow']), + '101477': ('#fbfbfb', '#fff1c1', '#78b7bb', '#808b97', ['White', 'Yellow', 'Turquoise', 'Grey', 'Pastel']), + '100883': ('#dffcb5', '#b7f5de', '#add1fc', '#9870fc', ['Green', 'Turquoise', 'Purple']), + '99599': ('#161d6e', '#1160aa', '#9bb4da', '#e9d2b3', ['Blue']), + '98521': ('#33425b', '#87dfd6', '#38817a', '#f9f8eb', ['Turquoise', 'Wedding']), + '101730': ('#feff89', '#ff9f68', '#f85959', '#ac005d', ['Yellow', 'Orange', 'Red', 'Purple', 'Sunset']), + '100864': ('#0881a3', '#fffdfb', '#fde9df', '#ffd6a4', ['Blue', 'Pink', 'Yellow', 'White']), + '100885': ('#f67280', '#c06c84', '#6c5b7b', '#355c7d', ['Red', 'Purple', 'Sunset']), + '100984': ('#fff5db', '#e1addc', '#c238b5', '#810075', ['Yellow', 'Pink', 'Purple', 'Wedding']), + '98202': ('#1b3c68', '#0074e4', '#00b8c0', '#e9ffb2', ['Blue', 'Turquoise']), + '98138': ('#393e46', '#5c636e', '#f96d00', '#f2f2f2', ['Grey', 'Orange']), + '98780': ('#d1f386', '#eda045', '#df654a', '#cc376d', ['Green', 'Orange', 'Purple', 'Autumn']), + '98625': ('#34374c', '#2c2e3e', '#ee2b47', '#f6f6f6', ['Black', 'Red', 'Grey']), + '98666': ('#f5e1da', '#f1f1f1', '#40a798', '#476269', ['Grey', 'Turquoise', 'Wedding', 'Skin']), + '97923': ('#37474f', '#607d8b', '#90a4ae', '#f7b633', ['Blue', 'Grey', 'Orange']), + '100564': ('#ffbdd4', '#ffe5b9', '#ffc77f', '#ff5c5c', ['Pink', 'Orange', 'Red']), + '97912': ('#f75940', '#334252', '#364857', '#3dc7be', ['Orange', 'Turquoise', 'Retro']), + '97771': ('#dddddd', '#113c4a', '#265a5c', '#3f7b70', ['Grey', 'Turquoise', 'Green', 'Cold']), + '97718': ('#ececec', '#3e3e3e', '#ee046c', '#fcac0c', ['Grey', 'Black', 'Pink', 'Orange']), + '97657': ('#f54d42', '#ff8356', '#ffcd00', '#f5f5f5', ['Orange', 'Yellow', 'Grey']), + '97656': ('#b0dedb', '#e3f3f7', '#fc6e5e', '#583131', ['Turquoise', 'Red', 'Brown']), + '97590': ('#fbf7f7', '#f1e9e3', '#ee712b', '#dc4712', ['Pink', 'Grey', 'Orange', 'Autumn', 'Gold', 'White']), + '97426': ('#f3ecc8', '#78c2c3', '#3f6699', '#0d1b4c', ['Yellow', 'Turquoise', 'Blue', 'Winter']), + '97212': ('#cbf078', '#f8f398', '#f1b963', '#e46161', ['Green', 'Yellow', 'Orange', 'Red', 'Spring']), + '97209': ('#f9f9f9', '#ded5c4', '#ef7e56', '#305973', ['Grey', 'Orange', 'Blue', 'White']), + '97068': ('#8e3343', '#ec9454', '#f1f08a', '#c6cd78', ['Red', 'Orange', 'Yellow', 'Green', 'Autumn', 'Halloween']), + '96781': ('#fcfcfc', '#0fc9e7', '#3186b2', '#4756ca', ['Grey', 'Blue', 'White']), + '96726': ('#e9007f', '#7cdfff', '#d5fffb', '#fcffc8', ['Purple', 'Blue', 'Yellow', 'Bright', 'Neon']), + '96297': ('#fafcd6', '#259f6c', '#1e6b7f', '#140303', ['Yellow', 'Green', 'Blue', 'Black']), + '97007': ('#3e4377', '#fd367e', '#f1f2f3', '#ff9900', ['Pink', 'Grey', 'Orange', 'Wedding']), + '96253': ('#f9fbfc', '#a0dbdb', '#56a7a7', '#fcea90', ['Grey', 'Turquoise', 'Yellow', 'Spring', 'White']), + '95689': ('#003459', '#028090', '#02c39a', '#fce38a', ['Turquoise', 'Green', 'Yellow']), + '95996': ('#d5f7ff', '#494b67', '#ff006c', '#ecebff', ['Blue', 'Red', 'Grey']), + '95353': ('#00649f', '#01aac1', '#00dbe7', '#97ecc5', ['Blue', 'Turquoise', 'Cold']), + '95351': ('#453246', '#f86254', '#b04d5d', '#ffd05b', ['Red', 'Yellow']), + '95568': ('#f0f0f0', '#43dde6', '#364f6b', '#fc5185', ['Grey', 'Blue', 'Pink']), + '95181': ('#085f63', '#49beb7', '#fccf4d', '#ef255f', ['Turquoise', 'Yellow', 'Red', 'Spring']), + '95097': ('#4a2c2c', '#d3504a', '#ffdc76', '#fefea4', ['Brown', 'Red', 'Yellow']), + '94589': ('#a13939', '#e75151', '#fcc88a', '#c2c57f', ['Red', 'Orange', 'Green', 'Christmas', 'Autumn']), + '94531': ('#f1f4f6', '#5ac8d8', '#597fca', '#2552ac', ['Blue', 'Turquoise']), + '94235': ('#f5fac8', '#aee8e6', '#8bcfcc', '#539092', ['Yellow', 'Turquoise', 'Blue', 'Turquoise']), + '94200': ('#9b5d73', '#b0757c', '#c38b8b', '#fff1c5', ['Brown', 'Yellow', 'Skin']), + '94114': ('#66bfbf', '#eaf6f6', '#fcfefe', '#f76b8a', ['Turquoise', 'Grey', 'Pink', 'White']), + '93578': ('#f8eeb4', '#cfee91', '#658525', '#092a35', ['Yellow', 'Green', 'Green', 'Black']), + '93536': ('#f5f5f5', '#01ecd5', '#4586ff', '#32424a', ['Grey', 'Turquoise', 'Blue', 'Black', 'Cold']), + '93497': ('#283e56', '#1989ac', '#e8f1f5', '#ffde25', ['Blue', 'Yellow']), + '93465': ('#f7f7f8', '#4eeaf6', '#c82586', '#291f71', ['Grey', 'Blue', 'Purple', 'Neon']), + '93362': ('#155263', '#ff6f3c', '#ff9a3c', '#ffc93c', ['Turquoise', 'Orange', 'Yellow']), + '93463': ('#f5eeee', '#ea21a2', '#af05aa', '#171313', ['Grey', 'Pink', 'Purple', 'Black']), + '93272': ('#f60c86', '#f9f6d8', '#a5bfdd', '#2e89ba', ['Pink', 'Yellow', 'Blue', 'Wedding', 'Spring']), + '93126': ('#657dc4', '#838ed9', '#ece8e5', '#f59292', ['Blue', 'Blue', 'Pink']), + '92811': ('#682666', '#cf0a2c', '#e73e51', '#ffce00', ['Purple', 'Red', 'Red', 'Yellow']), + '92806': ('#393939', '#849561', '#eed690', '#ecefd8', ['Grey', 'Brown', 'Yellow', 'Grey']), + '93125': ('#d4a5a5', '#ffecda', '#f9ffea', '#a6d0e4', ['Red', 'Orange', 'Yellow', 'Blue', 'Pastel', 'Vintage', 'Summer', 'Skin']), + '92530': ('#97124b', '#dc4444', '#f5a855', '#f4e557', ['Red', 'Orange', 'Yellow', 'Halloween']), + '92752': ('#143a52', '#6e828a', '#cde3eb', '#e3eff3', ['Grey', 'Wedding', 'Winter', 'Cold']), + '92339': ('#432160', '#ff7a5a', '#50e3c2', '#fcf4d9', ['Purple', 'Orange', 'Turquoise', 'Yellow']), + '92337': ('#faf8d7', '#acc6aa', '#71a0a5', '#77628c', ['Yellow', 'Green', 'Purple']), + '92306': ('#a1eafb', '#fdfdfd', '#ffcef3', '#cabbe9', ['Blue', 'Grey', 'Pink', 'Purple', 'Bright', 'Wedding', 'Spring']), + '92208': ('#fff4c9', '#c7e78b', '#81ae64', '#709053', ['Yellow', 'Green', 'Green', 'Green']), + '91572': ('#ffe037', '#1dcd9f', '#088c6f', '#23033c', ['Yellow', 'Turquoise']), + '90182': ('#ff395e', '#8fecc8', '#6f6f6f', '#4a4a4a', ['Red', 'Turquoise', 'Grey', 'Grey']), + '89959': ('#000249', '#0f4392', '#ff5151', '#ff8b8b', ['Blue', 'Red', 'Wedding', 'Halloween']), + '89958': ('#f6f6f6', '#d6e4f0', '#1e56a0', '#163172', ['Grey', 'Blue', 'Cold', 'White']), + '91891': ('#ff007b', '#ff5757', '#ff8585', '#ffebeb', ['Pink', 'Red', 'Orange', 'Spring']), + '92753': ('#f5f5f5', '#ececec', '#facc2e', '#27b1be', ['Grey', 'Yellow', 'Turquoise']), + '89012': ('#d5def5', '#8594e4', '#6643b5', '#430f58', ['Blue', 'Purple', 'Cold', 'Winter']), + '88466': ('#bff4ed', '#280f34', '#b30753', '#f6c667', ['Blue', 'Black', 'Red', 'Yellow']), + '88465': ('#1fad9f', '#cd3131', '#ab1212', '#f6c667', ['Turquoise', 'Red', 'Orange']), + '88422': ('#fc00a3', '#b30c7b', '#780662', '#e3f6f5', ['Pink', 'Purple', 'Purple']), + '88310': ('#461b93', '#6a3cbc', '#8253d7', '#f78f1e', ['Purple', 'Orange', 'Halloween']), + '88241': ('#ff008e', '#124e96', '#0d8abc', '#daeaf6', ['Pink', 'Blue', 'Blue']), + '87834': ('#ffdaa9', '#6fa3a9', '#5f72b2', '#60366f', ['Orange', 'Blue', 'Blue', 'Purple', 'Retro']), + '87607': ('#71397c', '#91519d', '#c582d5', '#ffdf5a', ['Purple', 'Yellow']), + '89856': ('#ffffc1', '#ffd2a5', '#ffa8b8', '#d988bc', ['Yellow', 'Orange', 'Pink', 'Purple', 'Bright', 'Warm']), + '88510': ('#626eef', '#09a8fa', '#41c5d3', '#fffa9d', ['Blue', 'Turquoise', 'Yellow', 'Bright']), + '87245': ('#581845', '#900c3f', '#c70039', '#ff5733', ['Red', 'Orange', 'Warm', 'Dark', 'Halloween']), + '100322': ('#4a3333', '#98d083', '#bcfcc9', '#f2feca', ['Brown', 'Green', 'Yellow']), + '87037': ('#e3d9ca', '#95a792', '#596c68', '#403f48', ['Grey', 'Green']), + '88143': ('#c84361', '#e78775', '#abcdcb', '#ebe59b', ['Red', 'Blue', 'Yellow', 'Summer']), + '88187': ('#6a0000', '#935656', '#c4f0c5', '#f1fff1', ['Brown', 'Green', 'Skin']), + '87687': ('#7d156d', '#b94e8a', '#d87ca1', '#ffd7f1', ['Purple', 'Pink', 'Wedding']), + '87026': ('#363333', '#272121', '#e16428', '#f6e9e9', ['Black', 'Orange', 'Pink', 'Dark', 'Halloween']), + '88300': ('#feffea', '#a3de83', '#2eb872', '#ff5d6e', ['Yellow', 'Green', 'Green', 'Red', 'Spring']), + '88012': ('#f5feff', '#bde4f4', '#404969', '#dc552c', ['Blue', 'Orange', 'Winter', 'White']), + '87640': ('#f03861', '#fef2f2', '#f5d97e', '#e8b844', ['Red', 'Pink', 'Yellow', 'Spring']), + '86615': ('#39065a', '#6a0572', '#9a0f98', '#ea0599', ['Purple', 'Pink', 'Dark']), + '86614': ('#626060', '#928b8b', '#dadbc0', '#e7e9de', ['Grey']), + '87244': ('#27296d', '#5e63b6', '#a393eb', '#f5c7f7', ['Blue', 'Blue', 'Purple', 'Purple', 'Cold']), + '86611': ('#ffbc2c', '#86b86b', '#4d4d4d', '#ececec', ['Yellow', 'Green', 'Grey', 'Grey']), + '86606': ('#f7f7f7', '#f5b553', '#854836', '#000000', ['Grey', 'Orange', 'Brown', 'Black', 'Autumn', 'White', 'Skin']), + '85473': ('#dff4f3', '#dde7f2', '#b9bbdf', '#878ecd', ['Blue', 'Purple', 'Winter', 'Cold']), + '85472': ('#dce8ba', '#f3d179', '#f09872', '#f46060', ['Yellow', 'Orange', 'Red', 'Pastel', 'Autumn']), + '85014': ('#f1e290', '#f677c1', '#9b3284', '#690074', ['Yellow', 'Pink', 'Purple']), + '84735': ('#f2f9f1', '#388e3c', '#8bc34a', '#ddeedf', ['Grey', 'Green']), + '84551': ('#6c5070', '#df6a6a', '#f6f6e3', '#c2dbc1', ['Purple', 'Red', 'Green', 'Vintage', 'Pastel']), + '86342': ('#0e2431', '#fc3a52', '#f9b248', '#e8d5b7', ['Black', 'Red', 'Orange', 'Brown', 'Warm', 'Halloween']), + '84458': ('#f8ed86', '#a5e9db', '#2ca4bf', '#415b90', ['Yellow', 'Turquoise', 'Blue']), + '84126': ('#a6e4e7', '#f9f9f9', '#ebcbae', '#8f8787', ['Turquoise', 'Grey', 'Orange', 'Brown']), + '83572': ('#e9e2d0', '#ea9085', '#d45d79', '#6e5773', ['Brown', 'Pink', 'Red', 'Purple', 'Autumn', 'Skin']), + '86343': ('#ffed8f', '#a7d46f', '#359768', '#3c3352', ['Yellow', 'Green']), + '82296': ('#c4aff0', '#fffeec', '#64d7d6', '#5782bb', ['Purple', 'Yellow', 'Turquoise', 'Blue', 'Wedding']), + '81897': ('#ffe495', '#ffc97b', '#44558f', '#e6f7f7', ['Yellow', 'Orange', 'Blue', 'Gold']), + '82054': ('#dd105e', '#46466e', '#8787a3', '#bdbdd7', ['Red', 'Grey']), + '81699': ('#feff9a', '#6fe8c8', '#85fede', '#b7abfb', ['Yellow', 'Turquoise', 'Purple', 'Bright']), + '81608': ('#ca498c', '#8b2f8a', '#b08fbb', '#f6d5d5', ['Purple', 'Purple', 'Purple', 'Pink']), + '81561': ('#ffe3b7', '#840404', '#cb0101', '#ffaf00', ['Orange', 'Red', 'Yellow', 'Warm']), + '80765': ('#ffdd83', '#e3f8ff', '#28cc9e', '#a6ed8e', ['Yellow', 'Green', 'Summer', 'Spring']), + '81674': ('#fcefee', '#fccde2', '#fc5c9c', '#c5e3f6', ['Pink', 'Pink', 'Pink', 'Blue', 'Retro', 'Wedding']), + '83571': ('#588c73', '#f2e394', '#f2ae72', '#d96459', ['Green', 'Yellow', 'Orange', 'Red', 'Christmas']), + '95352': ('#3b0944', '#5f1854', '#a12559', '#f1bbd5', ['Purple', 'Pink', 'Dark']), + '80660': ('#ffed78', '#feffea', '#addce4', '#586b8f', ['Yellow', 'Blue', 'Summer']), + '80619': ('#f2fcfc', '#bdf1f6', '#8fbaf3', '#0245a3', ['Turquoise', 'Blue', 'Cold', 'Winter']), + '80367': ('#f7f09b', '#ff5200', '#971549', '#470031', ['Yellow', 'Orange', 'Purple', 'Sunset', 'Warm']), + '80280': ('#e2eff1', '#65799b', '#555273', '#e23e57', ['Blue', 'Grey', 'Red', 'Retro', 'Cold']), + '82938': ('#222831', '#393e46', '#f96d00', '#f2f2f2', ['Black', 'Grey', 'Orange', 'Grey', 'Autumn']), + '82114': ('#22eaaa', '#b31e6f', '#ee5a5a', '#ffb174', ['Green', 'Purple', 'Orange', 'Vintage', 'Spring']), + '80168': ('#f1f6f5', '#9ef4e6', '#12cc94', '#6088bb', ['Grey', 'Turquoise', 'Green', 'Blue']), + '80113': ('#c02727', '#f4806d', '#ffffd3', '#f3f2b4', ['Red', 'Orange', 'Yellow']), + '80102': ('#e9e9e5', '#d4d6c8', '#9a9b94', '#52524e', ['Grey', 'Pastel', 'Winter']), + '79894': ('#324e7b', '#86a6df', '#5068a9', '#f8f8f8', ['Blue', 'Grey', 'Cold', 'Winter']), + '79877': ('#434343', '#a64452', '#f7c873', '#f8f8f8', ['Grey', 'Red', 'Orange', 'Autumn']), + '79851': ('#ef6c35', '#161c2e', '#2bb3c0', '#faf7f2', ['Orange', 'Black', 'Turquoise', 'Grey']), + '79812': ('#9ffbfb', '#a100ff', '#db97ff', '#ffb6ff', ['Blue', 'Purple', 'Pink', 'Bright', 'Cold']), + '79725': ('#000000', '#1a8b9d', '#b2d430', '#fff5f5', ['Black', 'Turquoise', 'Green', 'Grey']), + '79143': ('#4e1e1e', '#e63870', '#fbe6a2', '#58e481', ['Brown', 'Pink', 'Yellow', 'Green']), + '79336': ('#ffeed0', '#f79f24', '#e20049', '#7c064d', ['Orange', 'Red', 'Purple']), + '79270': ('#f0bebe', '#5ea3a6', '#3a718c', '#ffffdf', ['Pink', 'Turquoise', 'Yellow']), + '78936': ('#19215e', '#f7e6b5', '#fa67ab', '#80185f', ['Blue', 'Yellow', 'Pink', 'Purple', 'Retro', 'Wedding']), + '78974': ('#303481', '#d6e6f2', '#f5f5f5', '#fff200', ['Blue', 'Blue', 'Grey', 'Yellow', 'Bright']), + '79457': ('#e5f9bd', '#a0e418', '#7fb414', '#525050', ['Green', 'Bright']), + '78984': ('#f9c4ac', '#626f92', '#474168', '#272637', ['Orange', 'Blue', 'Black']), + '78945': ('#070739', '#521477', '#c327ab', '#e1e099', ['Black', 'Purple', 'Yellow', 'Dark']), + '79451': ('#a9eee6', '#fefaec', '#f38181', '#625772', ['Blue', 'Red', 'Vintage']), + '79325': ('#e3e8f8', '#c0c5cd', '#3e588f', '#203562', ['Blue', 'Grey', 'Wedding', 'Cold']), + '78942': ('#464545', '#fb5660', '#f98e90', '#f0f3b0', ['Grey', 'Red', 'Pink', 'Yellow']), + '78705': ('#0b5269', '#03051e', '#978d58', '#eae1e1', ['Blue', 'Black', 'Brown', 'Grey', 'Dark']), + '79837': ('#8e9fe6', '#6acafc', '#6ce6dd', '#dbf094', ['Blue', 'Purple', 'Turquoise', 'Green']), + '78747': ('#2d5c7f', '#fff1a8', '#ff8f56', '#984a59', ['Blue', 'Yellow', 'Orange', 'Sunset']), + '78711': ('#feceab', '#ff847c', '#eb4a5f', '#2a363b', ['Orange', 'Red', 'Black', 'Autumn', 'Warm']), + '87062': ('#fffbe0', '#fce38a', '#2994b2', '#444f5a', ['Yellow', 'Blue']), + '78761': ('#fdfce0', '#f0eeb1', '#dad773', '#b1ad25', ['Yellow', 'Green']), + '78675': ('#3c1b1f', '#b21e4b', '#e2bf81', '#f6e1b5', ['Brown', 'Red', 'Yellow', 'Warm']), + '78631': ('#314a52', '#52686a', '#acbdc5', '#ffded5', ['Grey', 'Pink', 'Winter']), + '78674': ('#f8f8f8', '#c246c6', '#91157e', '#65195e', ['Grey', 'Purple', 'Purple', 'Purple']), + '78630': ('#062121', '#181810', '#e4dcad', '#eeeeee', ['Black', 'Black', 'Brown', 'Grey']), + '78589': ('#e1f5f2', '#6bc5d2', '#5a5d9d', '#390050', ['Turquoise', 'Blue', 'Purple', 'Blue', 'Winter', 'Cold']), + '78489': ('#18587a', '#fc624d', '#fca7a7', '#ffd6d6', ['Blue', 'Pink', 'Orange']), + '78408': ('#343434', '#8e8b82', '#e9dcbe', '#f3f3f3', ['Grey', 'Brown']), + '78378': ('#f7f39a', '#a3de83', '#38817a', '#346473', ['Yellow', 'Green', 'Turquoise']), + '77930': ('#970747', '#fef4e8', '#13445a', '#446878', ['Red', 'Grey', 'Blue', 'Wedding', 'Retro']), + '77071': ('#331621', '#cc085e', '#de7d48', '#eeca98', ['Purple', 'Pink', 'Orange', 'Halloween', 'Warm']), + '93416': ('#f8fcfb', '#c9fdd7', '#79d1c3', '#6892d5', ['Grey', 'Blue', 'Green', 'Vintage', 'Bright', 'Cold']), + '77996': ('#f2f7ff', '#0b409c', '#10316b', '#fdbe34', ['Blue', 'Blue', 'Blue', 'Yellow']), + '77134': ('#ac0c0c', '#a7d82e', '#f5f883', '#fbfadf', ['Red', 'Green', 'Yellow', 'Christmas', 'Spring']), + '77067': ('#f8f5e4', '#f97300', '#0e3047', '#10828c', ['Orange', 'Black', 'Turquoise']), + '76029': ('#dbdbeb', '#7577cd', '#080957', '#ff6d02', ['Purple', 'Blue', 'Orange', 'Cold']), + '76768': ('#1684a7', '#09a599', '#f6ec72', '#f6f6f6', ['Blue', 'Green', 'Yellow', 'Grey']), + '75979': ('#6a759b', '#21273d', '#b9d4f1', '#f1f6f8', ['Blue', 'Black', 'Grey', 'Cold', 'Winter']), + '74943': ('#2e3b3e', '#50666b', '#f9b8be', '#fd6378', ['Grey', 'Pink', 'Vintage']), + '78712': ('#dcedc2', '#ffd3b5', '#ffaaa6', '#ff8c94', ['Green', 'Orange', 'Pink', 'Vintage', 'Pastel']), + '76728': ('#f1e58a', '#4c5374', '#71647c', '#d0f0f7', ['Yellow', 'Blue', 'Grey']), + '74172': ('#222222', '#045757', '#044343', '#e4e4e4', ['Black', 'Turquoise', 'Grey', 'Dark']), + '78331': ('#3f3038', '#fdf6fa', '#fdaed8', '#f361af', ['Grey', 'Pink', 'Wedding']), + '73365': ('#466551', '#368c72', '#7ecba1', '#e7eed2', ['Green']), + '75751': ('#f1684e', '#85c8dd', '#d3e0e2', '#e9f6f5', ['Orange', 'Blue', 'Grey', 'Turquoise']), + '76698': ('#e8f79a', '#49d292', '#3b445b', '#383746', ['Yellow', 'Green', 'Black']), + '76530': ('#f9f9f9', '#efe94b', '#9f1861', '#631357', ['Grey', 'Yellow', 'Purple']), + '76335': ('#f48fb1', '#f06292', '#ad1457', '#880e4f', ['Pink', 'Pink', 'Purple', 'Red']), + '76161': ('#fcf4d9', '#8ed2c9', '#00aaa0', '#d55b3e', ['Yellow', 'Turquoise', 'Orange']), + '77723': ('#560764', '#bb8fa9', '#d8cbbb', '#eeeeee', ['Purple', 'Grey', 'Wedding']), + '75278': ('#fc345c', '#49beb7', '#afffdf', '#eafff7', ['Red', 'Turquoise', 'Green', 'Spring', 'Bright']), + '73354': ('#1b4b36', '#538f6a', '#aebd77', '#e0e7f1', ['Green', 'Grey']), + '73684': ('#2a363b', '#cf4647', '#f5d061', '#f8f6f6', ['Black', 'Red', 'Yellow', 'Grey']), + '74985': ('#33425b', '#3498db', '#fcc29a', '#ecf0f1', ['Blue', 'Orange', 'Grey']), + '73271': ('#1d3e53', '#254b62', '#476d7c', '#77abb7', ['Blue', 'Dark', 'Winter', 'Cold']), + '76308': ('#fbfbfb', '#b1d056', '#e0ff59', '#ffa33e', ['Green', 'Grey', 'Orange', 'Bright']), + '74079': ('#22213d', '#4e3188', '#24babc', '#eaef9b', ['Black', 'Purple', 'Turquoise', 'Yellow']), + '76066': ('#f4e1e1', '#f98903', '#c62727', '#4c3232', ['Pink', 'Orange', 'Red', 'Brown', 'Autumn']), + '74864': ('#1c1124', '#693e52', '#badf96', '#f7ffcd', ['Black', 'Brown', 'Green', 'Yellow']), + '74744': ('#7eb19f', '#0c8282', '#ef9037', '#edddbd', ['Turquoise', 'Turquoise', 'Orange']), + '73149': ('#303841', '#2e4750', '#f6c90e', '#f7f7f7', ['Black', 'Yellow']), + '76222': ('#fffdef', '#f1f1f1', '#e70000', '#c50000', ['Grey', 'Red']), + '73228': ('#8aacff', '#626fe6', '#6d42c7', '#e85b48', ['Blue', 'Blue', 'Purple', 'Orange']), + '73246': ('#eeeeee', '#ea9215', '#3a4750', '#303841', ['Grey', 'Orange']), + '74392': ('#45171d', '#f03861', '#ff847c', '#fecea8', ['Brown', 'Red', 'Orange', 'Yellow', 'Warm']), + '74886': ('#fffcea', '#a5f2e7', '#8983f3', '#3a0077', ['Yellow', 'Blue', 'Purple', 'Retro']), + '75752': ('#d8dfe2', '#71adb5', '#176d81', '#0d3446', ['Grey', 'Turquoise', 'Winter', 'Cold']), + '73012': ('#432c51', '#535474', '#54a4af', '#ecbc55', ['Purple', 'Turquoise', 'Orange']), + '73808': ('#f9f3e6', '#e2dcd5', '#e8aa8c', '#5e616a', ['Orange', 'Grey']), + '77461': ('#ffecba', '#ff8d68', '#a10054', '#001f52', ['Yellow', 'Orange', 'Sunset', 'Autumn']), + '72699': ('#073059', '#2866ab', '#5fbdc5', '#d8d95c', ['Blue']), + '74424': ('#ffdede', '#f7f3ce', '#c5ecbe', '#4797b1', ['Pink', 'Yellow', 'Green', 'Blue', 'Bright', 'Spring']), + '72427': ('#3e3e3e', '#405559', '#68868c', '#ededed', ['Grey', 'Turquoise', 'Winter']), + '72814': ('#fc8a15', '#f6f6f6', '#1ee494', '#009378', ['Orange', 'Grey', 'Green', 'Bright']), + '73938': ('#febfb3', '#e1396c', '#96d38c', '#d0f9b1', ['Pink', 'Red', 'Green']), + '72112': ('#d3d6db', '#3a4750', '#303841', '#be3144', ['Grey', 'Black', 'Red', 'Wedding', 'Winter']), + '72512': ('#c2faf1', '#f6f6f6', '#dfeff0', '#295e6a', ['Turquoise', 'Grey', 'Blue', 'Cold', 'Bright']), + '72277': ('#eae7ed', '#b793e6', '#646ecb', '#3532a7', ['Grey', 'Purple', 'Blue', 'Blue', 'Cold']), + '71918': ('#ff6a38', '#9ed0e0', '#5c868e', '#19483f', ['Orange', 'Blue', 'Turquoise']), + '73328': ('#fffb85', '#ffd464', '#fa5b75', '#5a3662', ['Yellow', 'Yellow', 'Pink', 'Purple']), + '72484': ('#205d67', '#639a67', '#d8ebb5', '#d9bf77', ['Blue', 'Green', 'Brown', 'Vintage']), + '73289': ('#f5f7fa', '#5be7c4', '#4fc1e9', '#7a57d1', ['Blue', 'Turquoise', 'Blue', 'Purple', 'Retro']), + '71715': ('#ff5200', '#003355', '#04536c', '#adaca7', ['Orange', 'Blue', 'Grey']), + '72652': ('#defcf9', '#cadefc', '#c3bef0', '#cca8e9', ['Blue', 'Purple', 'Pastel']), + '71572': ('#31588a', '#638ccc', '#90b2e4', '#eacf79', ['Blue', 'Yellow']), + '72200': ('#2f1b41', '#9f1e49', '#fecd51', '#f2f2f2', ['Purple', 'Red', 'Yellow', 'Grey', 'Retro']), + '72875': ('#11cbd7', '#9feed1', '#fff6a2', '#f60c86', ['Blue', 'Turquoise', 'Yellow', 'Pink', 'Spring', 'Bright']), + '75964': ('#99f0ca', '#c9fdd7', '#fdffe7', '#8c7676', ['Green', 'Green', 'Yellow', 'Brown']), + '71827': ('#151680', '#1c44ac', '#375fc0', '#f1fea4', ['Blue', 'Yellow', 'Cold']), + '71453': ('#d2d4d6', '#7d8df6', '#5a4db2', '#ff771b', ['Grey', 'Blue', 'Orange']), + '71826': ('#b9f9ff', '#dafdff', '#f7e590', '#f5cd6d', ['Blue', 'Yellow', 'Summer', 'Bright']), + '71378': ('#222831', '#393e46', '#0092ca', '#eeeeee', ['Black', 'Grey', 'Blue', 'Winter']), + '73138': ('#f6fea1', '#ffb270', '#f08e6b', '#ff7575', ['Yellow', 'Orange', 'Red', 'Gold']), + '71387': ('#dafaf8', '#d6e1a5', '#027b7e', '#2a014b', ['Turquoise']), + '71609': ('#f49393', '#f21368', '#aa236d', '#261d1d', ['Pink', 'Red', 'Purple', 'Black']), + '72664': ('#22c7a9', '#2db6a3', '#fccf4d', '#fef3cc', ['Turquoise', 'Turquoise', 'Yellow', 'Yellow']), + '71318': ('#691a40', '#9e3668', '#f6a9ce', '#fde3f0', ['Purple', 'Pink', 'Pink']), + '71250': ('#4b4a5a', '#a55540', '#e79a58', '#e1d5d2', ['Grey', 'Brown', 'Orange', 'Autumn']), + '69667': ('#fafafa', '#e8f1f5', '#005691', '#004a7c', ['Grey', 'Blue', 'Cold', 'Winter']), + '70782': ('#f4f4ec', '#76e2f4', '#615dec', '#301781', ['Grey', 'Turquoise', 'Blue', 'Cold']), + '71302': ('#a8e6cf', '#dcedc1', '#ffd3b6', '#ffaaa5', ['Turquoise', 'Green', 'Orange', 'Pink', 'Pastel']), + '71050': ('#f3f6f6', '#30e3ca', '#11999e', '#40514e', ['Grey', 'Turquoise']), + '71246': ('#3d262a', '#127c56', '#eab64d', '#ecf3f6', ['Brown', 'Green', 'Orange', 'Grey']), + '70717': ('#2a2b5f', '#393c83', '#3dc4d0', '#44d9e6', ['Blue', 'Cold']), + '71366': ('#ff4545', '#ff9867', '#ffbf87', '#ffedb2', ['Red', 'Orange', 'Yellow', 'Warm']), + '70596': ('#e7f0d2', '#d2ea9b', '#abcb89', '#83b271', ['Green']), + '70716': ('#921224', '#bce0da', '#ebf5ee', '#bdc6b8', ['Red', 'Blue', 'Grey', 'Vintage', 'Wedding']), + '70746': ('#f8fdc3', '#facbf8', '#efa7f3', '#f677f7', ['Yellow', 'Pink', 'Bright']), + '68865': ('#ddf5f7', '#c0d9e5', '#44679f', '#3b577d', ['Blue', 'Cold']), + '69534': ('#eceff4', '#00ad7c', '#fbd490', '#475762', ['Grey', 'Green', 'Orange']), + '70050': ('#141829', '#21294c', '#f2dea8', '#f9f2d7', ['Black', 'Blue', 'Yellow']), + '71012': ('#fff6fb', '#ffbee3', '#fc5bb6', '#ff0592', ['Pink', 'Bright', 'Wedding']), + '69740': ('#f2eee3', '#baaf92', '#785e4d', '#ff8426', ['Grey', 'Brown', 'Orange', 'Autumn']), + '69056': ('#428b46', '#b7b56e', '#d6d88b', '#e9eab4', ['Green', 'Brown', 'Yellow']), + '70734': ('#7386d5', '#a0b6f5', '#ffefef', '#ff2c2c', ['Blue', 'Blue', 'Grey', 'Red']), + '70588': ('#0962ea', '#0e7cf4', '#0aa0f6', '#faf15d', ['Blue', 'Yellow']), + '68768': ('#f9f8eb', '#ffe1b6', '#7a9eb1', '#415865', ['Yellow', 'Blue']), + '70274': ('#f70776', '#c3195d', '#680747', '#141010', ['Red', 'Pink', 'Purple', 'Black']), + '69955': ('#2e2b2b', '#388186', '#a5e9e1', '#fdf6f6', ['Black', 'Turquoise', 'Grey']), + '68755': ('#fffe9f', '#ffd480', '#fca180', '#f56262', ['Yellow', 'Yellow', 'Orange', 'Red']), + '68238': ('#f2f9f1', '#ddeedf', '#b6cdbd', '#5c715e', ['Grey', 'Green', 'Vintage']), + '68089': ('#c7f5fe', '#fcc8f8', '#eab4f8', '#f3f798', ['Blue', 'Pink', 'Purple', 'Yellow', 'Bright']), + '69360': ('#525252', '#414141', '#313131', '#ec625f', ['Grey', 'Black', 'Red', 'Dark']), + '67181': ('#f0eec9', '#9ee6cf', '#50c9ba', '#4ba2ac', ['Yellow', 'Turquoise']), + '70476': ('#fafafa', '#ff6699', '#c54c82', '#512e67', ['Grey', 'Pink', 'Purple']), + '67166': ('#7effdb', '#b693fe', '#8c82fc', '#ff9de2', ['Turquoise', 'Purple', 'Pink']), + '68212': ('#1d7d81', '#213458', '#887575', '#f6e8e8', ['Turquoise', 'Blue', 'Brown', 'Pink']), + '68660': ('#57d1c9', '#ed5485', '#fffbcb', '#ffe869', ['Turquoise', 'Pink', 'Yellow', 'Yellow']), + '66766': ('#dff5f2', '#87dfd6', '#46b7b9', '#2f9296', ['Turquoise']), + '67816': ('#f3f3f3', '#ffdd67', '#ffcd38', '#4a4a4a', ['Grey', 'Yellow', 'Gold']), + '68797': ('#280b45', '#61105e', '#c84771', '#ffe98a', ['Purple', 'Yellow']), + '67815': ('#8ef6e4', '#9896f1', '#d59bf6', '#edb1f1', ['Turquoise', 'Purple', 'Pink']), + '68019': ('#a44a4a', '#dd8968', '#e4c478', '#e8e46d', ['Red', 'Orange', 'Yellow', 'Warm', 'Gold']), + '67703': ('#eeeeee', '#59569d', '#f25292', '#fea096', ['Grey', 'Purple', 'Pink', 'Pink']), + '67082': ('#d3f6d1', '#a7d7c5', '#74b49b', '#5c8d89', ['Green', 'Turquoise']), + '67020': ('#ff6f6f', '#fff46e', '#f6f6f6', '#a58bff', ['Red', 'Yellow', 'Grey', 'Purple', 'Bright']), + '68678': ('#2f1b41', '#872341', '#be3144', '#f05941', ['Red', 'Orange']), + '68013': ('#dddddd', '#574e6d', '#43405d', '#4b586e', ['Grey', 'Winter', 'Cold']), + '67450': ('#1fad9f', '#cd3131', '#ab1212', '#f6e4b5', ['Turquoise', 'Red', 'Yellow']), + '67080': ('#fc993c', '#ffe775', '#bd4682', '#8c2057', ['Orange', 'Yellow', 'Purple', 'Purple']), + '67593': ('#fafbd4', '#b2ebf9', '#aea1ea', '#8c54a1', ['Yellow', 'Blue', 'Purple', 'Wedding', 'Retro']), + '66373': ('#dde8b9', '#e8d2ae', '#cb8589', '#796465', ['Brown', 'Pastel', 'Vintage']), + '66528': ('#070f4e', '#2772db', '#3ab1c8', '#f5ebeb', ['Blue', 'Grey', 'Cold']), + '66334': ('#c8f4de', '#a4e5d9', '#66c6ba', '#649dad', ['Turquoise']), + '67660': ('#bc4f4f', '#e98b50', '#f3cd97', '#fef2a0', ['Orange', 'Yellow', 'Gold']), + '66246': ('#f9f8ed', '#f4e7d3', '#0881a3', '#1f4e5f', ['Blue', 'Wedding']), + '65976': ('#d7aef3', '#94f6f2', '#f7f680', '#fbd0f5', ['Purple', 'Turquoise', 'Yellow', 'Pink', 'Spring', 'Bright']), + '66663': ('#ebe9f6', '#453c38', '#6a5c55', '#f66e00', ['Brown', 'Grey', 'Orange']), + '65978': ('#ddfee4', '#28cc9e', '#196b69', '#132f2b', ['Green', 'Turquoise']), + '66989': ('#ca3e6b', '#fa8383', '#9dd3cc', '#ffe4b3', ['Red', 'Pink', 'Turquoise', 'Yellow']), + '65929': ('#f6f5f5', '#e3e3e3', '#3bb4c1', '#048998', ['Grey', 'Turquoise', 'Cold']), + '67169': ('#ff006c', '#d62b70', '#973961', '#623448', ['Red', 'Purple', 'Purple', 'Brown']), + '66816': ('#233142', '#455d7a', '#f95959', '#e3e3e3', ['Black', 'Blue', 'Red', 'Grey']), + '66979': ('#f5fac8', '#a5f0e4', '#82c7eb', '#8ea1f0', ['Yellow', 'Blue']), + '66822': ('#4b2c34', '#447878', '#779977', '#ddddbb', ['Brown', 'Turquoise', 'Green']), + '66724': ('#f7f09b', '#ff5200', '#c31207', '#77024d', ['Yellow', 'Orange', 'Red', 'Purple']), + '66380': ('#146c78', '#0e91a1', '#7dce94', '#efede7', ['Blue', 'Green', 'Grey']), + '66554': ('#faee1c', '#f3558e', '#9c1de7', '#581b98', ['Yellow', 'Pink', 'Purple', 'Purple']), + '66116': ('#a9eee6', '#fefaec', '#f9a1bc', '#625772', ['Turquoise', 'Yellow', 'Pink', 'Purple']), + '65520': ('#1b8057', '#55a44e', '#d7c37a', '#ede9a3', ['Green', 'Yellow', 'Brown']), + '67108': ('#3d1860', '#643579', '#bb99cd', '#f5edf7', ['Purple', 'Cold']), + '65211': ('#e67676', '#f2f062', '#a9e6e6', '#7692e4', ['Red', 'Yellow', 'Blue']), + '66214': ('#1b3c59', '#456173', '#11bfae', '#f2f2f0', ['Blue', 'Turquoise', 'Grey', 'Cold']), + '66130': ('#bff4ed', '#280f34', '#e41655', '#b30753', ['Blue', 'Black', 'Red']), + '65423': ('#f3f169', '#46c3db', '#2d6cdf', '#482ff7', ['Yellow', 'Blue']), + '65168': ('#f5e1da', '#f1f1f1', '#40a798', '#476268', ['Grey', 'Turquoise', 'Vintage']), + '65474': ('#511e78', '#8b2f97', '#cf56a1', '#fcb2bf', ['Purple', 'Pink']), + '65846': ('#90f6d7', '#35bcbf', '#41506b', '#263849', ['Turquoise', 'Turquoise', 'Black']), + '63974': ('#ecfffb', '#b4f1f1', '#2d767f', '#1e6262', ['Blue', 'Turquoise', 'Cold']), + '76788': ('#eeeeee', '#fcc314', '#94ac3c', '#295ba7', ['Grey', 'Yellow', 'Green', 'Blue', 'Spring']), + '65180': ('#f2e9d0', '#eaceb4', '#e79e85', '#bb5a5a', ['Brown', 'Orange', 'Red', 'Pastel', 'Vintage', 'Warm']), + '65473': ('#402785', '#5f4e9e', '#fafb97', '#fcc97b', ['Purple', 'Yellow']), + '64711': ('#ebfffa', '#c6fce5', '#6ef3d6', '#0dceda', ['Blue', 'Green', 'Turquoise', 'Bright', 'Cold']), + '64753': ('#f4f4f4', '#fb9935', '#b90b0b', '#8c0909', ['Grey', 'Orange', 'Red', 'Autumn']), + '63788': ('#ffabe5', '#c7f5ff', '#d89fff', '#f6fcae', ['Pink', 'Blue', 'Purple', 'Yellow', 'Spring', 'Bright']), + '63283': ('#1c226b', '#3e31ae', '#4aa9af', '#d1fffa', ['Purple', 'Turquoise', 'Blue', 'Cold']), + '63326': ('#dc3737', '#f7af1d', '#f5e180', '#aeaf7a', ['Red', 'Orange', 'Yellow', 'Autumn']), + '65068': ('#36d1c4', '#a0eecc', '#fff2be', '#f6318c', ['Turquoise', 'Green', 'Yellow', 'Pink', 'Spring', 'Bright']), + '65119': ('#4c6983', '#38556a', '#273952', '#b6fff9', ['Black', 'Winter', 'Cold']), + '65360': ('#be0eaa', '#ea2ba2', '#fb9696', '#f6ca97', ['Purple', 'Pink', 'Yellow', 'Spring']), + '62610': ('#e0fcff', '#90f2ff', '#6eb6ff', '#7098da', ['Blue', 'Bright', 'Cold']), + '65139': ('#fbf7f7', '#f9d00f', '#f0ae2c', '#f92727', ['Grey', 'Yellow', 'Red', 'Bright', 'Gold']), + '64640': ('#1b5a7a', '#1aa59a', '#a6ed8e', '#f3ffb9', ['Blue', 'Turquoise', 'Green', 'Yellow']), + '64641': ('#ff9898', '#cf455c', '#971549', '#470031', ['Pink', 'Red', 'Red', 'Purple', 'Warm']), + '63093': ('#586e72', '#fbf27c', '#5c835a', '#305c5c', ['Grey', 'Yellow', 'Green']), + '64291': ('#eb89b5', '#ffd7e9', '#fffbf3', '#fff8d2', ['Pink', 'Yellow', 'Bright']), + '63246': ('#f4f7f7', '#aacfd0', '#5da0a2', '#34495e', ['Grey', 'Turquoise', 'Cold']), + '62822': ('#7b77ff', '#92cce1', '#f68686', '#ffe3b9', ['Purple', 'Orange', 'Red', 'Yellow']), + '64412': ('#fff6f6', '#eea1eb', '#cb22d7', '#891180', ['Pink', 'Purple']), + '65088': ('#f6eb9a', '#5853bc', '#362391', '#1c0c59', ['Yellow', 'Blue']), + '63973': ('#f03861', '#fef2f2', '#f5d97e', '#7d5e3f', ['Red', 'Yellow', 'Brown']), + '62766': ('#d9f9f4', '#9cd9de', '#86c1d4', '#5a92af', ['Turquoise', 'Blue', 'Cold']), + '63915': ('#2aaf74', '#4ed99c', '#d1ebfe', '#f7be7f', ['Green', 'Blue', 'Orange']), + '62940': ('#f69d9d', '#ffeab6', '#fdffba', '#c0ffc2', ['Pink', 'Orange', 'Yellow', 'Green', 'Bright']), + '62803': ('#253b6e', '#1f5f8b', '#1891ac', '#d2ecf9', ['Blue', 'Cold']), + '63955': ('#f6faf7', '#e7eaa8', '#b4bb72', '#303e27', ['Grey', 'Green', 'Yellow']), + '63931': ('#b80257', '#dd356e', '#fc7fb6', '#ffbbe1', ['Red', 'Red', 'Pink', 'Pink']), + '62923': ('#76d3ff', '#d78bff', '#fffa9d', '#ffbd74', ['Blue', 'Purple', 'Yellow', 'Orange']), + '64857': ('#f2f7ff', '#0b409c', '#10316b', '#ffce63', ['Blue', 'Orange', 'Cold']), + '66129': ('#1fab89', '#62d2a2', '#9df3c4', '#d7fbe8', ['Green']), + '65249': ('#fee856', '#ffce3e', '#e65c7b', '#834496', ['Yellow', 'Yellow', 'Purple']), + '66990': ('#07689f', '#a2d5f2', '#fafafa', '#ff7e67', ['Blue', 'Orange']), + '63366': ('#560764', '#913175', '#dd5b82', '#fe9797', ['Purple', 'Pink']), + '62678': ('#266f89', '#3d93a3', '#3ec483', '#d2e48e', ['Blue', 'Green']), + '64671': ('#29c6cd', '#f6e4c4', '#fea386', '#f19584', ['Blue', 'Orange']), + '62767': ('#ffd9e8', '#de95ba', '#7f4a88', '#4a266a', ['Pink', 'Purple']), + '62193': ('#212121', '#323232', '#0d7377', '#14ffec', ['Black', 'Turquoise', 'Cold', 'Dark']), + '62655': ('#fd9191', '#fddd8a', '#f5fc9e', '#9efcb4', ['Pink', 'Orange', 'Yellow', 'Green']), + '62928': ('#eff7d3', '#cedcc3', '#a7b99e', '#535a3b', ['Yellow', 'Brown', 'Grey', 'Green']), + '62935': ('#3c3b5c', '#d53939', '#ffb563', '#7b3c59', ['Blue', 'Red', 'Orange', 'Purple', 'Halloween']), + '62535': ('#616eef', '#09a8fa', '#41c5d3', '#d0f1cf', ['Blue', 'Turquoise', 'Cold']), + '63012': ('#658361', '#d0dd97', '#f8fae4', '#f9de79', ['Green', 'Green', 'Grey', 'Yellow']), + '62386': ('#2c3e50', '#34495e', '#ecf0f1', '#bdc3c7', ['Grey']), + '62180': ('#f3f6f6', '#90eee1', '#55b3f3', '#6356e5', ['Grey', 'Turquoise', 'Blue']), + '62955': ('#f6378f', '#ffdd00', '#f5efe8', '#8ea5eb', ['Pink', 'Yellow', 'Grey', 'Blue', 'Spring']), + '62456': ('#388e3c', '#8bc34a', '#dce775', '#fff59d', ['Green', 'Green', 'Yellow', 'Yellow']), + '62241': ('#eff0f4', '#d3d6db', '#415f9d', '#233b6e', ['Grey', 'Blue', 'Winter', 'Cold']), + '45072': ('#f4f56e', '#72e8e1', '#58b3d3', '#418c9f', ['Yellow', 'Turquoise', 'Blue', 'Turquoise']), + '70512': ('#14103b', '#f02a71', '#7ec0e4', '#6789ba', ['Black', 'Pink', 'Blue', 'Blue']), + '45047': ('#eeeeee', '#234c63', '#379956', '#ffc85b', ['Grey', 'Blue', 'Green', 'Orange', 'Retro']), + '62199': ('#e38ed2', '#c75696', '#9d3978', '#512e67', ['Pink', 'Purple', 'Purple', 'Purple']), + '44798': ('#006c9a', '#00bebe', '#00f3e4', '#9ff9c1', ['Blue', 'Turquoise']), + '44662': ('#333c4a', '#495664', '#f6f7d3', '#f8fceb', ['Black', 'Yellow']), + '62624': ('#ff8fe5', '#fbff64', '#76e3ff', '#7bc7fa', ['Pink', 'Yellow', 'Blue', 'Bright']), + '45023': ('#2a528a', '#5d6ec7', '#9f71db', '#e9d498', ['Blue', 'Purple', 'Yellow']), + '44995': ('#ffdd83', '#e3f8ff', '#31bccc', '#405983', ['Yellow', 'Blue', 'Turquoise', 'Blue', 'Summer']), + '44992': ('#3a3a62', '#604fdd', '#26c6d0', '#e6e993', ['Purple', 'Turquoise', 'Yellow']), + '44707': ('#499491', '#a3dec9', '#f7fed8', '#fbd400', ['Turquoise', 'Yellow']), + '44958': ('#f70c9b', '#cb007b', '#d6e3ed', '#99b0c2', ['Pink', 'Purple', 'Grey']), + '44675': ('#f0fff3', '#c6f1e7', '#70acb1', '#59606d', ['Turquoise', 'Grey']), + '44906': ('#b31313', '#ff9000', '#fdda16', '#ffee82', ['Red', 'Orange', 'Yellow', 'Warm', 'Gold']), + '44586': ('#4d12ee', '#2f24c1', '#3fd1cb', '#f8f6f6', ['Blue', 'Turquoise', 'Grey']), + '44559': ('#34495d', '#2c3d4f', '#ee7738', '#f59d2a', ['Black', 'Orange']), + '44658': ('#8c7676', '#99f0ca', '#c9fdd7', '#fdffe7', ['Brown', 'Green', 'Yellow', 'Bright']), + '44430': ('#f9f5f0', '#f2ead3', '#f4991a', '#321313', ['Grey', 'Orange', 'Brown', 'Retro', 'Warm', 'Wedding']), + '44400': ('#4e4e6a', '#1f6cb0', '#70a3c4', '#e7e8f5', ['Grey', 'Blue', 'Cold']), + '62847': ('#f73f52', '#ffea85', '#f6f6f6', '#7986c7', ['Red', 'Yellow', 'Grey', 'Blue']), + '44259': ('#defbc2', '#90d26d', '#459d72', '#342b2b', ['Green']), + '44258': ('#f4f4f4', '#6decb9', '#11999e', '#3c3c3c', ['Grey', 'Green', 'Turquoise', 'Black']), + '43937': ('#282f44', '#e6af2e', '#f5d061', '#ececec', ['Black', 'Yellow', 'Grey', 'Gold']), + '44626': ('#104455', '#0a3442', '#3ad3cd', '#7fffd6', ['Turquoise', 'Cold']), + '44243': ('#d2f6fc', '#a9d2ff', '#7984ee', '#6730ec', ['Blue', 'Purple', 'Cold']), + '43846': ('#f1ed63', '#d97d97', '#9862ae', '#815a8f', ['Yellow', 'Pink', 'Purple']), + '43879': ('#ffd6b6', '#ea7362', '#b74242', '#5c2626', ['Orange', 'Brown', 'Warm']), + '43813': ('#364f6b', '#3fc1c9', '#fce38a', '#fc5185', ['Blue', 'Yellow', 'Pink']), + '43750': ('#1b435d', '#78bbe6', '#d5eeff', '#ff895d', ['Blue', 'Orange', 'Cold']), + '43765': ('#ffa0c2', '#f9f5ce', '#e3ce8b', '#9e7e44', ['Pink', 'Yellow', 'Brown']), + '44109': ('#fff2b2', '#9ed763', '#2c9e4b', '#0a4650', ['Yellow', 'Green']), + '44226': ('#f54ea2', '#a94caf', '#7b3b8c', '#41228e', ['Pink', 'Purple']), + '43974': ('#20decb', '#41eecb', '#f9f296', '#fcd78e', ['Turquoise', 'Yellow', 'Spring']), + '44449': ('#2e94b9', '#fffdc1', '#f0b775', '#fd5959', ['Blue', 'Yellow', 'Orange', 'Red']), + '43379': ('#e1eacd', '#bad8b6', '#61b390', '#01352c', ['Green', 'Black']), + '43753': ('#005689', '#007cb9', '#d5eeff', '#ff895d', ['Blue', 'Orange']), + '43636': ('#1b1f3a', '#53354a', '#a64942', '#ff7844', ['Black', 'Brown', 'Orange', 'Dark', 'Warm']), + '43601': ('#113f67', '#34699a', '#408ab4', '#65c6c4', ['Blue', 'Turquoise', 'Cold']), + '44038': ('#f2ffdf', '#b1f1b2', '#1e757b', '#424d69', ['Green', 'Turquoise']), + '43120': ('#ffbc65', '#ac4c5e', '#5c476f', '#eeeeee', ['Orange', 'Red', 'Purple', 'Grey']), + '43560': ('#272932', '#1c7293', '#b9e3c6', '#f1f2eb', ['Black', 'Blue', 'Green', 'Grey', 'Cold']), + '43744': ('#c54c82', '#ec729c', '#f4aeba', '#fdfdcb', ['Purple', 'Pink', 'Yellow', 'Warm']), + '43327': ('#ff5656', '#edf2f6', '#6a7efc', '#494953', ['Red', 'Blue', 'Blue', 'Grey']), + '42678': ('#f7f0e9', '#ffaf9b', '#df5333', '#424242', ['Grey', 'Orange', 'Black']), + '43162': ('#58828b', '#5e9387', '#c8e29d', '#f2f299', ['Turquoise', 'Green', 'Yellow']), + '42664': ('#233142', '#36506c', '#a5def1', '#ebf7fd', ['Black', 'Blue', 'Winter']), + '65175': ('#f23557', '#f0d43a', '#22b2da', '#3b4a6b', ['Red', 'Yellow', 'Blue', 'Blue']), + '43278': ('#f7f7f7', '#fcd59b', '#1fa8cf', '#2657c1', ['Grey', 'Yellow', 'Blue']), + '42568': ('#354649', '#6c7a89', '#a3c6c4', '#e0e7e9', ['Black', 'Grey', 'Winter', 'Cold']), + '42970': ('#faf4e1', '#fabc41', '#ec9454', '#c72767', ['Yellow', 'Orange', 'Purple', 'Warm', 'Vintage', 'Gold']), + '42656': ('#f2f2f2', '#cdcdcd', '#005691', '#004a7c', ['Grey', 'Blue', 'Cold']), + '42755': ('#fdf196', '#f08edb', '#bb47be', '#a31c88', ['Yellow', 'Pink', 'Purple', 'Spring']), + '42452': ('#303841', '#3a4750', '#ea9215', '#eeeeee', ['Black', 'Grey', 'Orange']), + '42726': ('#cbf9da', '#3dd2cc', '#3e6b89', '#122d42', ['Turquoise', 'Blue', 'Cold']), + '42617': ('#f47c7c', '#f7f48b', '#a1de93', '#70a1d7', ['Red', 'Yellow', 'Green', 'Blue']), + '42214': ('#283739', '#2c5d63', '#a9c52f', '#f5f5f5', ['Black', 'Turquoise', 'Green', 'Grey']), + '42563': ('#ed9153', '#fbd157', '#fbede1', '#53435b', ['Orange', 'Yellow', 'Autumn', 'Gold']), + '42191': ('#e3fdfd', '#cbf1f5', '#a6e3e9', '#71c9ce', ['Turquoise', 'Cold']), + '42676': ('#303a52', '#574b90', '#9e579d', '#fc85ae', ['Purple', 'Pink']), + '42560': ('#798a65', '#faf3df', '#d15385', '#8e415b', ['Green', 'Yellow', 'Purple', 'Purple']), + '42254': ('#f4f7ed', '#86ee60', '#2e6e65', '#2b3752', ['Grey', 'Green', 'Turquoise', 'Blue']), + '42012': ('#2e94b9', '#475053', '#acdcee', '#f0fbff', ['Blue', 'Grey', 'Cold']), + '42272': ('#f38181', '#fce38a', '#d6f7ad', '#95e1d3', ['Red', 'Yellow', 'Green', 'Blue']), + '62260': ('#2a363b', '#e84a5f', '#ff847b', '#fecea8', ['Black', 'Red', 'Orange', 'Warm']), + '41858': ('#1333a6', '#317ae1', '#1fdedb', '#fffcbf', ['Blue', 'Turquoise', 'Yellow']), + '41890': ('#ffca61', '#ffec85', '#f2ffdf', '#c9f0d6', ['Orange', 'Yellow', 'Turquoise', 'Spring', 'Summer', 'Gold']), + '42237': ('#283739', '#228896', '#a9c52f', '#f5f5f5', ['Turquoise', 'Blue', 'Green', 'Grey']), + '42657': ('#7a08fa', '#a82ffc', '#c264fe', '#f8ecfd', ['Purple', 'Cold']), + '41810': ('#adf7d1', '#95e8d7', '#7dace4', '#8971d0', ['Turquoise', 'Turquoise', 'Blue', 'Purple']), + '42533': ('#384259', '#f73859', '#7ac7c4', '#c4edde', ['Red', 'Turquoise']), + '41825': ('#f9a828', '#ececeb', '#07617d', '#2e383f', ['Orange', 'Grey', 'Blue', 'Black']), + '42088': ('#c2fcd9', '#a0e4b0', '#f8fba2', '#fa7f7f', ['Green', 'Yellow', 'Red', 'Summer', 'Bright', 'Spring']), + '41796': ('#425e92', '#0c81f6', '#5fe1d9', '#f7fad1', ['Blue', 'Blue', 'Turquoise', 'Yellow']), + '41771': ('#247291', '#f8da5b', '#eef2e2', '#f5f9ee', ['Blue', 'Yellow', 'Grey']), + '41748': ('#fff200', '#f5f5f5', '#d6e6f2', '#303841', ['Yellow', 'Grey', 'Black', 'Bright']), + '41747': ('#015668', '#06648c', '#0f81c7', '#0de2ea', ['Blue', 'Blue', 'Blue', 'Turquoise', 'Cold']), + '41721': ('#70198a', '#bb8fa9', '#c1ea9f', '#f6f1f8', ['Purple', 'Green', 'Grey', 'Wedding', 'Retro']), + '41625': ('#2f2b2b', '#f3368d', '#ffc468', '#fff7ca', ['Black', 'Pink', 'Orange', 'Yellow']), + '41622': ('#afffff', '#74dbef', '#5e88fc', '#264e86', ['Blue', 'Cold']), + '41314': ('#2a3356', '#f35b25', '#fdfcfc', '#e8e2e2', ['Blue', 'Orange', 'Grey', 'Retro']), + '41115': ('#45171d', '#e84a5f', '#ff847c', '#fecea8', ['Brown', 'Red', 'Orange']), + '41029': ('#c190f0', '#9876de', '#fdfe9a', '#9adeb9', ['Purple', 'Purple', 'Yellow', 'Green']), + '41025': ('#f4f7f7', '#79a8a9', '#4d727e', '#1f4e5f', ['Grey', 'Turquoise', 'Cold']), + '41482': ('#00ad7c', '#52d681', '#b5ff7d', '#fff8b5', ['Green', 'Yellow']), + '41089': ('#f85f73', '#fbe8d3', '#928a97', '#283c63', ['Red', 'Grey', 'Blue']), + '39932': ('#295e62', '#1c4648', '#d5d46f', '#dff09d', ['Turquoise', 'Yellow']), + '40871': ('#baf5f0', '#d17ae5', '#e889e5', '#f9fcc9', ['Blue', 'Purple', 'Pink', 'Yellow', 'Spring', 'Bright']), + '40803': ('#fcf0c8', '#f7d098', '#911f27', '#630a10', ['Yellow', 'Red', 'Warm']), + '40848': ('#95efce', '#2ea1d9', '#395ea6', '#3e467f', ['Turquoise', 'Blue']), + '40787': ('#f9fcfd', '#c9eff9', '#07a4b5', '#fed8a7', ['Blue', 'Orange']), + '39481': ('#392f2f', '#3a7563', '#59a985', '#e6d3a7', ['Brown', 'Green']), + '40181': ('#fafafa', '#ff347f', '#c9356c', '#f48db4', ['Grey', 'Pink']), + '39112': ('#ffffe7', '#c6e5f3', '#539ddb', '#084a83', ['Yellow', 'Blue', 'Cold']), + '40128': ('#fa4659', '#feffe4', '#a3de83', '#2eb872', ['Red', 'Yellow', 'Green', 'Spring']), + '40377': ('#f5f5f5', '#c5d200', '#51710a', '#424242', ['Grey', 'Green', 'Green', 'Grey']), + '40297': ('#c7ffff', '#fbeeff', '#ebc6ff', '#7e80ff', ['Blue', 'Pink', 'Bright']), + '42666': ('#900c27', '#c70039', '#f6c667', '#f1f8fd', ['Red', 'Yellow', 'Orange', 'Warm']), + '41743': ('#003744', '#1a554f', '#fda856', '#f6fe91', ['Green', 'Orange', 'Yellow']), + '39602': ('#ffcfdf', '#fefdca', '#e0f9b5', '#a5dee5', ['Pink', 'Yellow', 'Green', 'Blue', 'Pastel', 'Spring', 'Bright']), + '40156': ('#0f1021', '#d01257', '#fb90b7', '#ffcee4', ['Black', 'Pink', 'Pink']), + '39902': ('#d7ffdf', '#ace6c0', '#77b5a6', '#9d4545', ['Green', 'Green', 'Turquoise', 'Brown']), + '38962': ('#fafafa', '#c7eeff', '#0077c0', '#1d242b', ['Grey', 'Blue', 'Black', 'Cold']), + '41475': ('#241e92', '#5432d3', '#7b6cf6', '#e5a5ff', ['Purple', 'Blue', 'Pink', 'Cold']), + '39857': ('#ffeee7', '#fbb448', '#e3670c', '#cc3d0b', ['Pink', 'Orange', 'Orange', 'Autumn', 'Warm']), + '39609': ('#15b7b9', '#10ddc2', '#f5f5f5', '#f57170', ['Blue', 'Turquoise', 'Grey', 'Red']), + '39601': ('#2f3c4f', '#506e86', '#fcb040', '#de703b', ['Blue', 'Orange']), + '38861': ('#e4fffe', '#a4f6f9', '#ff99fe', '#ba52ed', ['Blue', 'Pink', 'Purple', 'Bright']), + '39305': ('#083836', '#66d37e', '#c6e872', '#fbffa3', ['Green', 'Yellow']), + '39666': ('#f95959', '#ffe1a1', '#fcffcc', '#d3e785', ['Red', 'Orange', 'Yellow', 'Green']), + '39614': ('#718ca1', '#59748c', '#354d62', '#d7f2f7', ['Blue', 'Turquoise', 'Cold', 'Winter']), + '39495': ('#f7e74a', '#09c6ab', '#068888', '#02556d', ['Yellow', 'Turquoise', 'Blue']), + '39065': ('#6251da', '#828bff', '#7ab7ff', '#f0fc93', ['Blue', 'Purple', 'Yellow']), + '38961': ('#eaefc4', '#9bdf46', '#25a55f', '#346473', ['Green']), + '38863': ('#f1ffd9', '#8bdbf5', '#b292ea', '#eb55bf', ['Yellow', 'Blue', 'Purple', 'Pink', 'Spring']), + '39317': ('#2b4450', '#497285', '#dfebed', '#f78536', ['Turquoise', 'Blue', 'Orange']), + '38824': ('#f1fafb', '#a0e4f1', '#9dc6ff', '#4993fa', ['Turquoise', 'Blue', 'Cold']), + '39056': ('#513c3c', '#2a769a', '#41c3be', '#f7f36b', ['Brown', 'Blue', 'Turquoise', 'Yellow']), + '38857': ('#ecffc9', '#64fed6', '#82a6ee', '#7871bf', ['Yellow', 'Turquoise', 'Blue', 'Purple']), + '39176': ('#fffc3a', '#ea648d', '#884ea2', '#3d3551', ['Yellow', 'Pink', 'Purple']), + '38817': ('#e6f8f6', '#a0f6d2', '#72dfd0', '#03414d', ['Turquoise']), + '39631': ('#683531', '#bf382a', '#ef7079', '#f7e8c3', ['Brown', 'Red', 'Yellow', 'Warm']), + '38641': ('#d1ffa2', '#00cf95', '#0098ef', '#6d0ad3', ['Green', 'Blue', 'Purple']), + '38340': ('#2f3032', '#383a56', '#b0a565', '#ede68a', ['Black', 'Blue', 'Yellow', 'Dark']), + '38642': ('#d5fdff', '#9de5ff', '#aca8ff', '#ac73ff', ['Blue', 'Purple', 'Cold']), + '38618': ('#01005e', '#22267b', '#28518a', '#17b794', ['Blue', 'Green', 'Cold', 'Dark', 'Winter']), + '38654': ('#b062ea', '#f392f2', '#fed08f', '#f6f39f', ['Purple', 'Pink', 'Orange', 'Yellow', 'Bright']), + '38301': ('#d2fafb', '#5acfd6', '#189bfa', '#0c4b8e', ['Turquoise', 'Blue', 'Cold']), + '38724': ('#feffa0', '#acdb86', '#547c66', '#3b5b5d', ['Yellow', 'Green']), + '38497': ('#c9182b', '#f23a3a', '#e3f3ac', '#44c662', ['Red', 'Green', 'Christmas']), + '38290': ('#3f1263', '#986ead', '#d8cbbb', '#f2f2f2', ['Purple', 'Purple', 'Brown', 'Grey']), + '38288': ('#f1fdf3', '#e5f4e7', '#d1e9d2', '#99cda9', ['Green', 'Green', 'Green', 'Green']), + '37482': ('#5f2f14', '#1297bd', '#1ad7db', '#f3f1f1', ['Brown', 'Blue', 'Grey', 'Vintage', 'Wedding']), + '37362': ('#00334e', '#145374', '#5588a3', '#e8e8e8', ['Blue', 'Grey', 'Cold', 'Winter']), + '37243': ('#f5ff8d', '#50cb86', '#4c74c9', '#312f44', ['Yellow', 'Green', 'Blue', 'Black']), + '37155': ('#283739', '#2c5d63', '#a2c11c', '#e0e0e0', ['Black', 'Turquoise', 'Green', 'Grey']), + '38859': ('#fbffe0', '#ffd6a6', '#ff8ab4', '#d86eff', ['Yellow', 'Orange', 'Pink', 'Purple', 'Spring']), + '37340': ('#0c4762', '#51dacf', '#9ef5cf', '#f4eeee', ['Turquoise', 'Grey']), + '42937': ('#700961', '#b80d57', '#e03e36', '#ff7c38', ['Purple', 'Orange', 'Warm']), + '37026': ('#0eb29a', '#f5fdff', '#ddf0c2', '#8c999a', ['Turquoise', 'Green', 'Grey']), + '37211': ('#39627f', '#4b788f', '#e4de66', '#beb000', ['Blue', 'Green']), + '38164': ('#d65f5f', '#faf99f', '#a1f6b6', '#78d8d0', ['Red', 'Yellow', 'Turquoise', 'Green']), + '36953': ('#3c2f3d', '#2eac6d', '#9dda52', '#f0f0f0', ['Black', 'Green', 'Green', 'Grey']), + '36842': ('#f2f299', '#c8e29d', '#5e9387', '#58828b', ['Yellow', 'Green']), + '36777': ('#fff9c1', '#ffa1d0', '#c244fb', '#84e9ff', ['Yellow', 'Pink', 'Purple', 'Blue']), + '36668': ('#005689', '#007cb9', '#f6c667', '#f1f8fd', ['Blue', 'Orange']), + '36477': ('#00e0ff', '#74f9ff', '#a6fff2', '#e8ffe8', ['Blue', 'Bright', 'Summer']), + '36237': ('#b23256', '#fcd47d', '#31aa75', '#a2ef44', ['Red', 'Yellow', 'Green', 'Christmas']), + '36487': ('#fffaa2', '#d600b1', '#a500a3', '#680097', ['Yellow', 'Purple']), + '36394': ('#64868e', '#98b4a6', '#d1e4d1', '#f3fbf1', ['Turquoise', 'Green', 'Grey', 'Green']), + '38862': ('#f4f1ae', '#ff8d52', '#f85a16', '#ca005e', ['Yellow', 'Orange', 'Purple', 'Warm']), + '36181': ('#007ab5', '#005a85', '#004262', '#d8e6ec', ['Blue', 'Cold']), + '38613': ('#fffbaf', '#ff5656', '#cd0a0a', '#42cfc4', ['Yellow', 'Red', 'Red', 'Turquoise']), + '36185': ('#442a9d', '#f14e95', '#b13cd5', '#faf3fc', ['Purple', 'Pink']), + '36113': ('#191ba9', '#5cc2f2', '#c1eaf2', '#f7f3f3', ['Blue', 'Grey', 'Cold']), + '36041': ('#fd5959', '#ff9c6d', '#fcff82', '#afc5ff', ['Red', 'Orange', 'Yellow', 'Blue']), + '36105': ('#43496e', '#544d7e', '#65589c', '#ffc12d', ['Purple', 'Orange']), + '35990': ('#fcf798', '#e0fff9', '#74d2ff', '#5ca4ca', ['Yellow', 'Blue', 'Bright']), + '35881': ('#fcfaef', '#e2e0a5', '#d3504a', '#a63636', ['Brown', 'Red', 'Vintage']), + '35742': ('#fe7187', '#ca4b7c', '#7a2e7a', '#a8d7f7', ['Pink', 'Purple', 'Blue']), + '35642': ('#daebee', '#b6d7de', '#fcedda', '#ff5126', ['Blue', 'Orange', 'Wedding']), + '35780': ('#07588a', '#6ac1b8', '#bfe9db', '#e1f6f4', ['Blue', 'Turquoise', 'Green', 'Cold']), + '35644': ('#f8ecd9', '#eebee3', '#c576ac', '#662753', ['Yellow', 'Pink', 'Purple']), + '35619': ('#f8ffae', '#f36363', '#ef4a4a', '#d32d2d', ['Yellow', 'Orange', 'Red', 'Warm']), + '35489': ('#e8ecf1', '#b5cfd8', '#7393a7', '#6c737e', ['Grey', 'Blue', 'Winter', 'Pastel', 'Cold']), + '36435': ('#f2ff9b', '#6af79a', '#57acc5', '#444b6c', ['Yellow', 'Green', 'Blue']), + '35271': ('#65ead1', '#f469a9', '#ff917b', '#fcffc1', ['Turquoise', 'Pink', 'Orange', 'Yellow', 'Retro', 'Spring']), + '35497': ('#303841', '#3a4750', '#d72323', '#eeeeee', ['Red', 'Grey']), + '35469': ('#e4fcf9', '#ace6f6', '#4b89ac', '#446491', ['Blue', 'Cold']), + '35159': ('#ee9494', '#ebffaf', '#b4e8c0', '#c3b9ea', ['Red', 'Yellow', 'Green', 'Purple', 'Bright']), + '34110': ('#6f4f8b', '#6d739d', '#7dbcc8', '#b9eaf5', ['Purple', 'Blue']), + '34098': ('#2794eb', '#bff8d4', '#47d6b6', '#17b3c1', ['Blue', 'Turquoise', 'Green']), + '41371': ('#f5f5f5', '#b9e937', '#57d131', '#406661', ['Grey', 'Green']), + '37188': ('#2e94b9', '#fffdc1', '#f0b775', '#d25565', ['Blue', 'Yellow', 'Orange', 'Red']), + '34781': ('#3c9099', '#5fbdb0', '#e3e2c3', '#f0efe2', ['Turquoise', 'Grey', 'Pastel']), + '34104': ('#c4317b', '#ac7c7c', '#d0baa8', '#efe4e4', ['Purple', 'Brown']), + '34002': ('#48f3db', '#51c4e9', '#6150c1', '#4a3764', ['Turquoise', 'Blue', 'Purple', 'Cold']), + '34608': ('#7a4579', '#d56073', '#ec9e69', '#ffff8f', ['Purple', 'Red', 'Orange', 'Yellow', 'Sunset', 'Wedding', 'Warm']), + '33990': ('#f7fbfc', '#d6e6f2', '#b9d7ea', '#769fcd', ['Grey', 'Blue', 'Bright', 'Cold']), + '33743': ('#343434', '#2d4059', '#ea5455', '#fde9c9', ['Black', 'Blue', 'Red', 'Yellow']), + '33592': ('#ebe8be', '#b3c87a', '#347a2a', '#202e24', ['Green']), + '33357': ('#415f77', '#d1e9ea', '#fc5050', '#ffd00c', ['Blue', 'Red', 'Yellow']), + '35508': ('#f7b679', '#e77c7c', '#b55c6c', '#61305d', ['Orange', 'Purple']), + '33208': ('#062d92', '#046fdb', '#03d6d2', '#fffcbf', ['Blue', 'Blue', 'Turquoise', 'Yellow']), + '33261': ('#4b2b30', '#5e3b4d', '#aa96b7', '#d9e2a8', ['Brown', 'Purple', 'Purple', 'Green']), + '33148': ('#f4fab3', '#a4eae8', '#53aca8', '#498eb9', ['Yellow', 'Blue', 'Turquoise', 'Summer']), + '32736': ('#dddddd', '#516c8d', '#28385e', '#304163', ['Grey', 'Blue', 'Cold']), + '32822': ('#b8eef1', '#bf68f6', '#fd89dd', '#f0e48e', ['Blue', 'Purple', 'Pink', 'Yellow', 'Bright', 'Retro']), + '32734': ('#cabfab', '#dfd8c8', '#41444b', '#52575d', ['Brown', 'Brown', 'Grey', 'Grey']), + '32512': ('#041122', '#259073', '#7fda89', '#e6f99d', ['Black', 'Turquoise', 'Green', 'Yellow']), + '32089': ('#ff9090', '#ffcf7f', '#fffa62', '#89c4ff', ['Pink', 'Orange', 'Yellow', 'Blue']), + '32030': ('#2daf94', '#3ec8ac', '#4be4c5', '#c8f6ed', ['Turquoise']), + '32519': ('#ffdbc5', '#ef4339', '#b01c33', '#2e112d', ['Orange', 'Red', 'Black', 'Warm']), + '31443': ('#9ddcdc', '#fff4e1', '#ffebb7', '#e67a7a', ['Blue', 'Yellow', 'Red']), + '32487': ('#414a50', '#85a6b1', '#8bd7d1', '#caedde', ['Grey', 'Turquoise', 'Blue', 'Cold']), + '33469': ('#f72464', '#ff858a', '#fff3a7', '#568564', ['Red', 'Pink', 'Yellow', 'Green', 'Spring']), + '31016': ('#54777d', '#eadb9d', '#feffe4', '#e7e3c5', ['Turquoise', 'Brown', 'Yellow']), + '30601': ('#384137', '#406661', '#3bb873', '#94ed88', ['Green']), + '32018': ('#83580b', '#d9b650', '#f5dd7b', '#fde994', ['Brown', 'Yellow', 'Gold']), + '32571': ('#4f1c4c', '#a91d1d', '#da4949', '#fde9c9', ['Purple', 'Red']), + '31046': ('#ffa5a5', '#ffffc2', '#c8e7ed', '#bfcfff', ['Pink', 'Yellow', 'Blue', 'Pastel', 'Summer', 'Bright']), + '31006': ('#f0f2ac', '#a7cbd9', '#7e94bf', '#5357a6', ['Yellow', 'Blue']), + '29213': ('#93e4c1', '#3baea0', '#118a7e', '#1f6f78', ['Green', 'Turquoise']), + '30356': ('#121435', '#faf9f0', '#edebca', '#ff5722', ['Black', 'Yellow', 'Orange']), + '30546': ('#1d2b53', '#7e2553', '#ff004d', '#fff024', ['Blue', 'Red', 'Yellow']), + '29954': ('#f5f5f5', '#b9e937', '#00b906', '#424242', ['Grey', 'Green', 'Green', 'Grey']), + '30296': ('#353e55', '#b36458', '#bcd3c2', '#e0e7b8', ['Vintage']), + '29746': ('#591fce', '#0c9cee', '#3dbdc2', '#a1f480', ['Purple', 'Blue', 'Turquoise', 'Green']), + '30670': ('#da1212', '#f08c00', '#c6da20', '#f3f5d5', ['Red', 'Orange', 'Green', 'Yellow', 'Autumn', 'Christmas']), + '30163': ('#fafafa', '#e1eeff', '#c2cfd8', '#543a3a', ['Grey', 'Blue', 'Brown', 'Vintage', 'Wedding', 'Cold']), + '29652': ('#b8f7d4', '#6fe7db', '#7fa6ee', '#835af1', ['Green', 'Turquoise', 'Blue', 'Purple']), + '32264': ('#fdffa3', '#f59af0', '#a980e4', '#a2e4a2', ['Yellow', 'Pink', 'Purple', 'Green']), + '29637': ('#61b292', '#aed09e', '#f1e8a7', '#a8896c', ['Green', 'Yellow', 'Brown']), + '30252': ('#1f024c', '#45056e', '#8f1383', '#e47676', ['Purple', 'Orange', 'Dark']), + '29275': ('#f87d09', '#f6f6f6', '#a7cdcc', '#004a55', ['Orange', 'Grey', 'Turquoise']), + '28905': ('#1a1a1b', '#333f44', '#37aa9c', '#94f3e4', ['Black', 'Turquoise']), + '29979': ('#e0c97e', '#fcf8b3', '#fb9378', '#ab6088', ['Brown', 'Yellow', 'Orange', 'Purple']), + '30285': ('#efecea', '#334854', '#e04462', '#f9c535', ['Grey', 'Black', 'Red', 'Yellow']), + '29318': ('#504d4d', '#646363', '#f5b316', '#e7e5e5', ['Grey', 'Grey', 'Yellow', 'Grey']), + '28937': ('#17e7a4', '#f6f1f1', '#e0d909', '#7d7474', ['Green', 'Grey', 'Yellow']), + '29636': ('#89aa97', '#f4e3b7', '#fff798', '#fd7e89', ['Green', 'Yellow', 'Red', 'Spring']), + '28684': ('#0e1555', '#4e1184', '#932b77', '#fd367e', ['Purple', 'Pink']), + '28636': ('#015051', '#04837b', '#01a7a3', '#04f2d5', ['Turquoise']), + '28621': ('#303841', '#3a4750', '#f6c90e', '#f64e8b', ['Black', 'Yellow', 'Pink']), + '28624': ('#c8b273', '#834655', '#9f5069', '#f6cac9', ['Brown', 'Pink']), + '28505': ('#fff5b5', '#ff9071', '#e85395', '#a73ccb', ['Yellow', 'Orange', 'Pink', 'Purple', 'Spring']), + '28465': ('#9bf4d5', '#29cdb5', '#fff3e1', '#373331', ['Turquoise', 'Turquoise', 'Yellow', 'Black']), + '28797': ('#083c5a', '#4cb648', '#fcc72c', '#e4f4fd', ['Blue', 'Green', 'Yellow']), + '28270': ('#fdea2e', '#f40968', '#512e5e', '#20194a', ['Yellow', 'Pink', 'Purple', 'Black']), + '27893': ('#9a47cb', '#ff80f3', '#ffd48b', '#fff079', ['Purple', 'Pink', 'Orange', 'Yellow']), + '26451': ('#15eda3', '#0ea47a', '#068b80', '#127780', ['Green']), + '28174': ('#f5d7a1', '#f0a28e', '#ba6476', '#812d58', ['Yellow', 'Orange', 'Purple', 'Autumn', 'Warm']), + '27119': ('#bbe9db', '#aeccc6', '#9ba6a5', '#757a79', ['Grey', 'Turquoise']), + '27158': ('#020438', '#284184', '#1f8ea3', '#00eaff', ['Blue', 'Turquoise', 'Cold']), + '26949': ('#4ae3b5', '#eeeeee', '#2a5d67', '#171332', ['Turquoise', 'Grey', 'Black']), + '27422': ('#f2ef99', '#de8ae8', '#972ea9', '#6a0e97', ['Yellow', 'Purple']), + '26375': ('#f36b6b', '#ece58a', '#1fb57b', '#84d270', ['Red', 'Yellow', 'Green']), + '25912': ('#003e21', '#067242', '#098b54', '#f8d098', ['Green', 'Green', 'Green', 'Orange']), + '25843': ('#ffe700', '#fe4e6e', '#613864', '#d8d7d7', ['Yellow', 'Pink', 'Purple', 'Grey']), + '25796': ('#f1fcfd', '#c7eeff', '#4d6de3', '#393737', ['Blue', 'Black', 'Cold']), + '24652': ('#000000', '#3e3636', '#d72323', '#f5eded', ['Black', 'Grey', 'Red', 'Dark']), + '25644': ('#feff9f', '#78dec9', '#2a6f7f', '#0e2033', ['Yellow', 'Turquoise', 'Turquoise', 'Black']), + '25451': ('#fff29c', '#ffb26b', '#ff639f', '#ff2865', ['Yellow', 'Orange', 'Pink', 'Red']), + '25729': ('#222831', '#393e46', '#00adb5', '#00fff5', ['Black', 'Blue', 'Cold', 'Dark']), + '24114': ('#cff800', '#feff92', '#0fefbd', '#7899dc', ['Green', 'Yellow', 'Turquoise', 'Blue']), + '24625': ('#240747', '#eb2632', '#f0ab8d', '#f6e4ad', ['Black', 'Red', 'Pink', 'Yellow']), + '24484': ('#76508e', '#482d57', '#03c1eb', '#86f3b8', ['Purple', 'Blue', 'Green']), + '24360': ('#fefea4', '#ffdc76', '#773838', '#4a2c2c', ['Yellow', 'Brown', 'Warm']), + '23782': ('#f79486', '#faf885', '#fcffc9', '#8ff5d2', ['Red', 'Yellow', 'Turquoise']), + '21781': ('#222831', '#2d4059', '#ff5722', '#eeeeee', ['Black', 'Orange', 'Grey', 'Dark']), + '23588': ('#a20a0a', '#bb9518', '#ccd51a', '#f7ffa8', ['Red', 'Brown', 'Yellow']), + '23083': ('#28615b', '#e4f6f6', '#ccccea', '#c089f8', ['Turquoise', 'Turquoise', 'Purple', 'Purple']), + '22672': ('#0c056d', '#590d82', '#b61aae', '#f25d9c', ['Blue', 'Purple', 'Purple', 'Pink']), + '22660': ('#fdf196', '#c5fcda', '#98e5ec', '#67bac6', ['Yellow', 'Blue', 'Bright']), + '22272': ('#f9f7f7', '#dbe2ef', '#3f72af', '#112d4e', ['Grey', 'Blue', 'Black', 'Cold']), + '20916': ('#222831', '#393e46', '#fd7014', '#eeeeee', ['Black', 'Grey', 'Orange', 'Dark']), + '21046': ('#83e4b5', '#3ec8ac', '#4e90a4', '#6e60a0', ['Green', 'Turquoise', 'Blue', 'Purple']), + '20752': ('#27e1ce', '#efffb7', '#d6ec78', '#ff98da', ['Turquoise', 'Yellow', 'Green', 'Pink', 'Spring', 'Bright']), + '20933': ('#f7f6de', '#fa7e0a', '#8f0e0e', '#530c0c', ['Orange', 'Red', 'Brown', 'Autumn', 'Halloween', 'Warm']), + '20614': ('#f8ff95', '#7be77e', '#7a8cf0', '#a45fe6', ['Yellow', 'Green', 'Blue', 'Purple']), + '20605': ('#300532', '#aa3763', '#f6dec4', '#fef8dd', ['Purple', 'Purple', 'Yellow', 'Yellow']), + '20660': ('#faf8f8', '#17ead9', '#6078ea', '#4b4848', ['Grey', 'Turquoise', 'Blue', 'Grey']), + '20333': ('#3e3e3e', '#f4722b', '#f6e7c1', '#b3a78c', ['Grey', 'Orange', 'Autumn']), + '19659': ('#fa5555', '#f7fb76', '#8ded8e', '#2d7d8f', ['Red', 'Yellow', 'Green', 'Turquoise']), + '20198': ('#055049', '#069a8e', '#a1e3d8', '#f5f093', ['Turquoise', 'Yellow']), + '20288': ('#fffbe0', '#fcda05', '#393e46', '#222831', ['Yellow', 'Black']), + '19949': ('#ffdd00', '#f64e8b', '#a01ba7', '#452b45', ['Yellow', 'Pink', 'Purple']), + '19832': ('#001f3f', '#083358', '#0da574', '#ffd717', ['Blue', 'Green', 'Yellow']), + '26363': ('#ea5959', '#f98b60', '#ffc057', '#ffe084', ['Red', 'Orange', 'Yellow', 'Warm']), + '19897': ('#fbffa3', '#c6e872', '#66d37e', '#0d625e', ['Yellow', 'Green']), + '19148': ('#468966', '#fff0a5', '#ffb03b', '#b64926', ['Green', 'Yellow', 'Orange', 'Gold']), + '19775': ('#7bc74d', '#222831', '#393e46', '#eeeeee', ['Green', 'Black', 'Grey']), + '19337': ('#faa9df', '#fae98f', '#f04f4f', '#810749', ['Pink', 'Yellow', 'Red', 'Purple']), + '19020': ('#743c08', '#df760b', '#f6b61e', '#ffebaf', ['Brown', 'Orange', 'Yellow', 'Warm', 'Gold']), + '19113': ('#303841', '#00adb5', '#eeeeee', '#ff5722', ['Black', 'Turquoise', 'Grey', 'Orange', 'Retro']), + '18933': ('#f9ebc4', '#a7cf5d', '#a97555', '#483d3c', ['Green', 'Brown']), + '18919': ('#e6ee75', '#da4949', '#4f1c4c', '#0d132a', ['Yellow', 'Orange', 'Purple', 'Black']), + '18915': ('#6163d3', '#6db7ca', '#fcf769', '#ffd23e', ['Blue', 'Yellow']), + '18612': ('#6fe7dd', '#3490de', '#6639a6', '#521262', ['Turquoise', 'Blue', 'Purple']), + '18378': ('#303841', '#3a4750', '#f6c90e', '#eeeeee', ['Black', 'Yellow', 'Grey', 'Dark']), + '18562': ('#fcffc1', '#9bf4d5', '#1dad9b', '#346357', ['Yellow', 'Turquoise']), + '18221': ('#2b1f31', '#413d65', '#5fb9b0', '#bef992', ['Black', 'Purple', 'Turquoise', 'Green', 'Dark']), + '18914': ('#fbff7c', '#ffe35e', '#e4663a', '#92253f', ['Yellow', 'Orange', 'Red', 'Warm']), + '18473': ('#eb76ff', '#ffa8ec', '#ffccfc', '#fbffb1', ['Purple', 'Pink', 'Pink', 'Yellow', 'Bright']), + '18160': ('#283739', '#2c5d63', '#a9c52f', '#f7eebb', ['Black', 'Turquoise', 'Green', 'Yellow']), + '18085': ('#29d2e4', '#13829b', '#fcc29a', '#fde9c9', ['Blue', 'Turquoise', 'Orange']), + '16545': ('#26252c', '#e54861', '#f2a379', '#efd5b7', ['Black', 'Red', 'Orange', 'Orange']), + '18916': ('#e9f679', '#9bdf46', '#25a55f', '#346473', ['Yellow', 'Green', 'Blue']), + '17722': ('#a42127', '#c83b3b', '#ef9b59', '#fee785', ['Red', 'Orange', 'Yellow', 'Warm']), + '17117': ('#08d9d6', '#252a34', '#ff2e63', '#eaeaea', ['Turquoise', 'Black', 'Red', 'Grey']), + '17726': ('#e3dfc8', '#f5f1da', '#808c6c', '#fdac61', ['Brown', 'Green', 'Orange', 'Wedding', 'Autumn']), + '16615': ('#432f44', '#ea5455', '#a7425c', '#ffd460', ['Black', 'Red', 'Yellow']), + '19373': ('#fefea4', '#fed96b', '#fc92e3', '#ee7cff', ['Yellow', 'Pink']), + '16256': ('#27323a', '#435055', '#29a19c', '#a3f7bf', ['Black', 'Grey', 'Turquoise', 'Green', 'Dark']), + '17143': ('#e4f1fe', '#8dc6ff', '#22313f', '#34495e', ['Blue', 'Black', 'Cold']), + '17190': ('#902424', '#d9af5d', '#cede48', '#e9efba', ['Red', 'Orange', 'Yellow', 'Green', 'Christmas']), + '17001': ('#e4f68f', '#50c19a', '#686354', '#444036', ['Green', 'Brown']), + '16467': ('#2c2d34', '#e94822', '#f2910a', '#efd510', ['Black', 'Orange', 'Yellow', 'Warm']), + '15881': ('#3e1e68', '#583c87', '#e45a84', '#ffacac', ['Purple', 'Purple', 'Pink']), + '17826': ('#b2e672', '#fffd88', '#ffd478', '#f96b85', ['Green', 'Yellow', 'Red', 'Summer', 'Bright']), + '16765': ('#ff7676', '#f6f49d', '#5dae8b', '#466c95', ['Red', 'Yellow', 'Green', 'Blue']), + '15662': ('#260980', '#283996', '#3aa3c1', '#f6ffd2', ['Blue', 'Yellow', 'Cold']), + '17140': ('#fffcca', '#55e9bc', '#11d3bc', '#537780', ['Yellow', 'Green', 'Turquoise', 'Summer']), + '14886': ('#403121', '#a65e09', '#ed9728', '#faf494', ['Brown', 'Orange', 'Yellow', 'Warm', 'Gold']), + '16579': ('#88bef5', '#ba53de', '#f469a9', '#f4fa9c', ['Blue', 'Purple', 'Pink', 'Yellow']), + '15830': ('#364f6b', '#3fc1c9', '#f5f5f5', '#fc5185', ['Blue', 'Turquoise', 'Grey', 'Pink']), + '16617': ('#e6e6e6', '#fad662', '#e57b5c', '#be4747', ['Grey', 'Yellow', 'Orange', 'Red', 'Gold']), + '16255': ('#423737', '#5d5d5d', '#00adb5', '#a3f7bf', ['Grey', 'Blue', 'Green']), + '15697': ('#e23e57', '#88304e', '#522546', '#311d3f', ['Red', 'Purple']), + '15541': ('#f8f8f8', '#faebcd', '#f7c873', '#434343', ['Grey', 'Yellow', 'Black', 'Gold']), + '14881': ('#303841', '#47555e', '#7aa5d2', '#eeeeee', ['Black', 'Grey', 'Blue', 'Cold']), + '14832': ('#e4f9f5', '#30e3ca', '#11999e', '#40514e', ['Turquoise', 'Grey', 'Cold']), + '15473': ('#57385c', '#a75265', '#ec7263', '#febe7e', ['Purple', 'Orange', 'Vintage', 'Warm']), + '15211': ('#ffee7d', '#534c98', '#b767ff', '#44fadd', ['Yellow', 'Purple', 'Purple', 'Turquoise']), + '15458': ('#222831', '#393e46', '#ff5722', '#eeeeee', ['Black', 'Grey', 'Orange']), + '14587': ('#bb2253', '#ec185d', '#ff9171', '#ffb383', ['Red', 'Orange']), + '13930': ('#2bcdc1', '#38817a', '#393e46', '#f66095', ['Turquoise', 'Grey', 'Pink']), + '13136': ('#f7fdb6', '#a4d792', '#21825c', '#424141', ['Yellow', 'Green']), + '12715': ('#fef0ff', '#d6c8ff', '#c79ecf', '#7e6bc4', ['Pink', 'Pink', 'Purple', 'Purple']), + '12370': ('#f78536', '#dfebed', '#497285', '#2b4450', ['Orange', 'Blue', 'Turquoise']), + '14114': ('#3ec1d3', '#f6f7d7', '#ff9a00', '#ff165d', ['Blue', 'Yellow', 'Orange', 'Red']), + '13933': ('#4a304d', '#b17179', '#ffb37b', '#fff199', ['Purple', 'Orange', 'Yellow', 'Sunset', 'Warm']), + '14339': ('#fce38a', '#0e5f76', '#083d56', '#0c2233', ['Yellow', 'Blue', 'Black']), + '13712': ('#4d606e', '#3fbac2', '#d3d4d8', '#f5f5f5', ['Blue', 'Grey', 'Grey', 'Cold']), + '14963': ('#ffef6f', '#ff9757', '#d84545', '#7b3030', ['Yellow', 'Orange', 'Red', 'Brown', 'Warm']), + '10150': ('#e5fcc2', '#9de0ad', '#45ada8', '#547980', ['Green', 'Turquoise']), + '14818': ('#ff5a5a', '#ffb072', '#f9ffa5', '#aabbff', ['Red', 'Orange', 'Yellow', 'Blue']), + '13607': ('#9bb899', '#fcceaa', '#f5827d', '#ea4961', ['Green', 'Orange', 'Red']), + '14684': ('#23425f', '#a64942', '#ff7844', '#ffab5e', ['Blue', 'Brown', 'Orange', 'Warm']), + '12509': ('#106ee8', '#0fc1a1', '#90e0ab', '#cbffce', ['Blue', 'Turquoise', 'Green']), + '14490': ('#eff2dd', '#fcda05', '#ee4848', '#5c3551', ['Grey', 'Yellow', 'Red', 'Purple']), + '12508': ('#5d414d', '#7e858b', '#abd4c1', '#e5f6c6', ['Brown', 'Grey', 'Green', 'Yellow']), + '13096': ('#222832', '#2f3847', '#e7a117', '#c57f1e', ['Black', 'Grey', 'Orange', 'Brown']), + '11346': ('#2be5a6', '#b5ffc7', '#f37ef9', '#904ca7', ['Green', 'Pink', 'Purple']), + '13941': ('#fbef7c', '#f1ac59', '#c93737', '#ff6898', ['Yellow', 'Orange', 'Red', 'Pink']), + '13837': ('#331940', '#5e366a', '#0cca98', '#00ffcc', ['Black', 'Purple', 'Turquoise', 'Retro']), + '14207': ('#fffd75', '#60e550', '#3b6ac0', '#6e3274', ['Yellow', 'Green', 'Blue', 'Purple']), + '12457': ('#cefff1', '#ace7ef', '#a6acec', '#a56cc1', ['Turquoise', 'Blue', 'Purple', 'Cold']), + '13313': ('#2a363b', '#e84a5f', '#ff847c', '#fecea8', ['Black', 'Red', 'Red', 'Orange']), + '13305': ('#e3e7b3', '#f6ffe2', '#e4ce8e', '#d77948', ['Yellow', 'Brown', 'Orange']), + '12461': ('#38486f', '#584f84', '#876a96', '#d7c1e0', ['Purple']), + '11752': ('#0278ae', '#51dacf', '#9ef5cf', '#e8ffc1', ['Blue', 'Turquoise', 'Yellow']), + '13139': ('#e14242', '#8d3434', '#eacd65', '#ebebcd', ['Red', 'Red', 'Orange', 'Yellow']), + '11685': ('#fff395', '#7459dc', '#41b3ff', '#63f5ef', ['Yellow', 'Purple', 'Blue', 'Turquoise']), + '12081': ('#ffc8c8', '#ff9999', '#444f5a', '#3e4149', ['Pink', 'Black']), + '9409': ('#ffde74', '#ffa974', '#ff715a', '#ff3757', ['Yellow', 'Orange', 'Orange', 'Red']), + '10701': ('#1a2f4b', '#28475c', '#2f8886', '#84c69b', ['Turquoise', 'Green']), + '11196': ('#faee5a', '#e4fcf9', '#ace6f6', '#4b89ac', ['Yellow', 'Blue']), + '12280': ('#f8e796', '#c98b70', '#635270', '#363863', ['Yellow', 'Orange', 'Purple']), + '9385': ('#d8fff1', '#78e4d4', '#b485d8', '#5b73a7', ['Turquoise', 'Purple', 'Blue']), + '11000': ('#f1f1f1', '#ff41ed', '#8109b7', '#0c1845', ['Grey', 'Pink', 'Purple', 'Black']), + '10468': ('#f1fafb', '#a0e4f1', '#7ea6f4', '#4a4de7', ['Blue', 'Cold', 'Wedding']), + '11994': ('#fe7847', '#ca2c3f', '#a21738', '#4c0b2f', ['Orange', 'Red']), + '9375': ('#d4ffa3', '#00d8b1', '#1f9ec7', '#3f7a9c', ['Green', 'Turquoise', 'Blue']), + '9353': ('#ff5ab0', '#f7fed4', '#4df4ff', '#1bb5ec', ['Pink', 'Yellow', 'Blue', 'Blue']), + '8656': ('#152a38', '#29435c', '#556e53', '#d1d4c9', ['Black', 'Blue', 'Green', 'Grey', 'Dark']), + '9544': ('#dd4747', '#ed6d54', '#ffbe5b', '#ffe559', ['Orange', 'Yellow']), + '11237': ('#a3f7bf', '#29a19c', '#4b6289', '#60316e', ['Turquoise', 'Green', 'Blue', 'Purple']), + '11343': ('#feffcb', '#ffb576', '#ff6b83', '#c6394d', ['Yellow', 'Orange', 'Red']), + '9416': ('#3b5f41', '#66a96b', '#98e19a', '#c5f5c2', ['Green', 'Green', 'Green', 'Green']), + '10697': ('#f8c957', '#ecf0f1', '#3498db', '#34495e', ['Yellow', 'Grey', 'Blue', 'Blue']), + '10953': ('#a561ff', '#fd72ad', '#fcce9e', '#cfe3ff', ['Purple', 'Pink', 'Orange', 'Blue']), + '10792': ('#303841', '#3a4750', '#00adb5', '#eeeeee', ['Black', 'Turquoise', 'Grey', 'Dark']), + '10119': ('#37b7b5', '#a0e4e0', '#c7f6f5', '#f6b132', ['Turquoise', 'Orange']), + '9970': ('#ffee7d', '#b767ff', '#534c98', '#44fadd', ['Yellow', 'Purple', 'Purple', 'Turquoise']), + '9501': ('#ee0e51', '#e4dcef', '#505458', '#363540', ['Red', 'Pink', 'Grey', 'Black']), + '8169': ('#004182', '#118df0', '#fbffa3', '#ff4b68', ['Blue', 'Blue', 'Yellow', 'Red']), + '8863': ('#faf6ed', '#f6bf4f', '#a2453d', '#aaaaaa', ['Yellow', 'Orange', 'Brown', 'Grey', 'Autumn', 'Gold']), + '10225': ('#3d6271', '#3d899c', '#45a298', '#d8f8b7', ['Blue', 'Turquoise', 'Green']), + '9214': ('#9bcb3c', '#eff669', '#f29f3d', '#cf3333', ['Green', 'Yellow', 'Orange', 'Red', 'Summer']), + '8025': ('#73f7dd', '#2cc4cb', '#1972a4', '#2e3a87', ['Turquoise', 'Blue']), + '8765': ('#fcf5b8', '#b4cd93', '#427a5b', '#403f3f', ['Yellow', 'Green', 'Grey']), + '9834': ('#fcff89', '#fe7187', '#ca4b7c', '#6e386e', ['Yellow', 'Pink', 'Purple', 'Purple']), + '9148': ('#f33535', '#d8e9f0', '#33425b', '#29252c', ['Red', 'Blue', 'Black']), + '9506': ('#00b8a9', '#f8f3d4', '#f6416c', '#ffde7d', ['Turquoise', 'Yellow', 'Red']), + '9522': ('#433751', '#2f576e', '#748b9c', '#f0e3e3', ['Purple', 'Turquoise', 'Grey', 'Pink']), + '9585': ('#990000', '#ff6600', '#c1d343', '#f7f7cf', ['Red', 'Orange', 'Green', 'Yellow', 'Autumn', 'Retro', 'Christmas']), + '8306': ('#feff94', '#ad64c5', '#83d9ef', '#bcfff2', ['Yellow', 'Purple', 'Blue']), + '9140': ('#ffb400', '#fffbe0', '#2994b2', '#474744', ['Orange', 'Yellow', 'Blue', 'Grey']), + '8168': ('#0278ae', '#51dacf', '#9ef5cf', '#e8ffb1', ['Blue', 'Turquoise', 'Yellow']), + '9474': ('#f64662', '#c61951', '#741938', '#56132a', ['Red']), + '9084': ('#2185d5', '#3a4750', '#303841', '#f3f3f3', ['Blue', 'Grey', 'Black', 'Grey']), + '8283': ('#f4f7f7', '#aacfd0', '#79a8a9', '#1f4e5f', ['Grey', 'Turquoise', 'Blue']), + '8529': ('#83ffe1', '#7045ff', '#c768ff', '#ffaded', ['Turquoise', 'Purple', 'Pink']), + '9264': ('#ffe165', '#de4242', '#84243b', '#412135', ['Yellow', 'Red', 'Black']), + '8016': ('#d4ed9d', '#64a97b', '#3a5465', '#3d3931', ['Green', 'Green', 'Blue', 'Black']), + '8941': ('#2fc5cc', '#6df1cc', '#e3ffc3', '#ff89c0', ['Turquoise', 'Pink', 'Bright']), + '8860': ('#fcefed', '#6173f4', '#3b2e40', '#f35e3e', ['Pink', 'Blue', 'Black', 'Orange', 'Retro']), + '8011': ('#bef2eb', '#6dc995', '#3a91aa', '#6b4897', ['Blue', 'Green', 'Turquoise', 'Purple']), + '8835': ('#913131', '#e5ab39', '#c2ff6b', '#a7da46', ['Red', 'Orange', 'Green', 'Green']), + '8182': ('#7b99fa', '#53cdd8', '#96eab7', '#f1f3b8', ['Blue', 'Turquoise', 'Green', 'Yellow']), + '8634': ('#152a38', '#2f5241', '#d6cfb9', '#e4e5db', ['Green', 'Grey', 'Wedding']), + '8328': ('#a8d8ea', '#aa96da', '#fcbad3', '#ffffd2', ['Blue', 'Purple', 'Pink', 'Yellow']), + '8321': ('#f06161', '#eb786b', '#f3a871', '#e9ec82', ['Red', 'Orange', 'Yellow', 'Warm']), + '8015': ('#081f37', '#5fc9f3', '#2e79ba', '#1e549f', ['Black', 'Blue']), + '8303': ('#b2085d', '#f9c11c', '#0d8549', '#3a3d44', ['Yellow', 'Green']), + '8350': ('#dbd8e3', '#5c5470', '#352f44', '#2a2438', ['Grey', 'Purple', 'Black', 'Dark']), + '7642': ('#f38181', '#fce38a', '#eaffd0', '#95e1d3', ['Red', 'Yellow', 'Blue']), + '8171': ('#35013f', '#561050', '#951556', '#e9b5d2', ['Purple', 'Pink', 'Wedding']), + '7635': ('#c8f0f0', '#86d8dc', '#7047a3', '#3a276a', ['Blue', 'Purple']), + '8043': ('#fbe0d8', '#4d727e', '#283644', '#7a6552', ['Pink', 'Turquoise', 'Brown', 'Vintage', 'Wedding']), + '8123': ('#f6ea8c', '#f26d5b', '#c03546', '#492540', ['Yellow', 'Orange', 'Red', 'Purple', 'Warm']), + '7956': ('#155674', '#60beb3', '#79f8bb', '#f5ffae', ['Blue', 'Turquoise', 'Green', 'Yellow']), + '8029': ('#eeeeee', '#ff9966', '#e52b50', '#9c2542', ['Grey', 'Orange', 'Red']), + '8012': ('#b9bc6d', '#ffe894', '#ef765f', '#95415a', ['Green', 'Yellow', 'Orange']), + '8013': ('#353b6e', '#252243', '#74deed', '#9365db', ['Blue', 'Blue', 'Turquoise', 'Purple']), + '7938': ('#eeccb4', '#d83c65', '#4f1567', '#604cc3', ['Orange', 'Red', 'Purple']), + '8001': ('#f0d394', '#98651e', '#6e4b1f', '#533710', ['Brown']), + '7817': ('#3498db', '#ecf0f1', '#34495e', '#f1c40f', ['Blue', 'Grey', 'Orange']), + '7968': ('#ff004d', '#9d0b28', '#5a082d', '#33030d', ['Red', 'Purple', 'Black', 'Dark']), + '7908': ('#a03232', '#c86f5e', '#e6c073', '#fffeb8', ['Red', 'Red', 'Brown', 'Yellow']), + '7919': ('#f7f373', '#65d269', '#2d8b7d', '#2f64a3', ['Yellow', 'Green', 'Turquoise', 'Blue']), + '7639': ('#db5ca6', '#942e88', '#f9cc6a', '#fcff88', ['Pink', 'Purple', 'Yellow', 'Yellow']), + '7638': ('#43bfc7', '#69e9f5', '#645fce', '#40356f', ['Turquoise', 'Blue', 'Purple']), + '7636': ('#ffe0a3', '#e18237', '#943939', '#6a2634', ['Yellow', 'Orange', 'Red', 'Autumn', 'Halloween']), + '7637': ('#59b791', '#83f084', '#f3ffa1', '#f1d665', ['Green', 'Green', 'Yellow', 'Yellow']), + '7640': ('#6ea7c1', '#6b55ae', '#e67fa2', '#ffefa1', ['Turquoise', 'Purple', 'Pink', 'Yellow']), + '7641': ('#e4f5e5', '#a6dfde', '#88a6e5', '#8d6ec8', ['Green', 'Turquoise', 'Blue', 'Purple']), + '7659': ('#feff94', '#ad64c5', '#88d8ec', '#bcfff2', ['Yellow', 'Purple', 'Blue']), + '7634': ('#f0f08e', '#91ca62', '#478077', '#3a4874', ['Yellow', 'Green', 'Turquoise', 'Blue']), + '7403': ('#0b88a8', '#a6dc8c', '#dfeb95', '#095062', ['Blue', 'Green', 'Yellow']), + '7223': ('#5c4b77', '#6990e4', '#b145ad', '#f6a2d4', ['Purple', 'Blue', 'Pink']), + '6843': ('#894949', '#b2704e', '#cd9d77', '#fcc0c0', ['Brown', 'Orange', 'Pink', 'Autumn']), + '7555': ('#f2676a', '#fbe087', '#ad2959', '#62013c', ['Red', 'Yellow', 'Purple', 'Purple']), + '7429': ('#bef2ff', '#4f7097', '#93a7d1', '#1bf5af', ['Blue', 'Green', 'Retro']), + '7422': ('#241023', '#883c82', '#b7569a', '#ffbf00', ['Black', 'Purple', 'Orange']), + '7187': ('#217756', '#63b75d', '#b0d553', '#fced25', ['Green', 'Yellow']), + '7469': ('#b074e9', '#e09ee8', '#f6e97f', '#f3f74d', ['Purple', 'Purple', 'Yellow', 'Yellow']), + '6941': ('#2e3837', '#166678', '#7db9b3', '#e1f6f4', ['Turquoise', 'Cold']), + '7431': ('#cc0500', '#ef2f2a', '#ef832a', '#efac2a', ['Red', 'Orange']), + '7355': ('#422b72', '#266d98', '#3cb29a', '#c4f080', ['Purple', 'Blue', 'Turquoise', 'Green']), + '7277': ('#2c5460', '#bbdc2f', '#61b136', '#cbe0e0', ['Green', 'Grey']), + '7247': ('#2d4059', '#ea5455', '#f07b3f', '#ffd460', ['Red', 'Orange', 'Yellow', 'Warm']), + '6577': ('#430d27', '#582233', '#713045', '#c94e4e', ['Purple', 'Brown']), + '6496': ('#5585b5', '#53a8b6', '#79c2d0', '#bbe4e9', ['Blue', 'Turquoise']), + '7195': ('#118df0', '#0e2f56', '#ff304f', '#ececda', ['Blue', 'Blue', 'Red', 'Grey']), + '6679': ('#b7b9f4', '#5254d8', '#192294', '#000278', ['Purple', 'Blue']), + '7129': ('#552e5a', '#cf7979', '#f6e198', '#ecffa3', ['Purple', 'Orange', 'Yellow', 'Yellow']), + '7128': ('#853e3e', '#c15757', '#ead27a', '#f7f79b', ['Brown', 'Red', 'Yellow']), + '6482': ('#b9dbe6', '#5f818a', '#36595f', '#304852', ['Blue', 'Grey']), + '6917': ('#00c3ff', '#b463a6', '#5c4978', '#3b475e', ['Blue', 'Purple']), + '6362': ('#4cb3cd', '#52d6d3', '#5968b1', '#302579', ['Blue', 'Turquoise', 'Purple']), + '6749': ('#41646e', '#4e7376', '#c2be53', '#e4e1b0', ['Turquoise', 'Green', 'Brown']), + '6998': ('#f06868', '#fab57a', '#edf798', '#80d6ff', ['Red', 'Orange', 'Yellow', 'Blue', 'Summer']), + '6850': ('#ebedc8', '#9ab5c1', '#74698c', '#c1867b', ['Pastel']), + '6837': ('#ef5353', '#b84040', '#dbee7b', '#e2c85b', ['Red', 'Yellow']), + '5986': ('#66e1b4', '#006159', '#00796f', '#009589', ['Turquoise', 'Green', 'Green', 'Green']), + '6158': ('#352f44', '#2a2438', '#411e8f', '#310a5d', ['Black', 'Purple', 'Dark']), + '5271': ('#2f3c4f', '#506f86', '#fbb040', '#de703c', ['Blue', 'Orange']), + '6770': ('#aa1111', '#b15858', '#f2c280', '#fcf8a6', ['Red', 'Red', 'Orange', 'Yellow']), + '6644': ('#068b78', '#9ed79a', '#f2ff97', '#ffcf5e', ['Green', 'Turquoise', 'Yellow', 'Orange']), + '6713': ('#002c6a', '#e45171', '#f8a79b', '#f8d99b', ['Blue', 'Red', 'Pink', 'Yellow']), + '6379': ('#793b89', '#be2490', '#e5a0dc', '#e9bbe5', ['Purple', 'Purple', 'Pink', 'Pink']), + '6186': ('#f3cba5', '#975a5e', '#453953', '#25161b', ['Brown', 'Black', 'Vintage']), + '6588': ('#00a388', '#79bd8f', '#beeb9f', '#ffff9d', ['Green', 'Yellow']), + '6494': ('#333644', '#84577c', '#c65f63', '#e1bf7f', ['Black', 'Purple', 'Red', 'Yellow']), + '5334': ('#397298', '#8ac4ff', '#9179ef', '#7b417d', ['Blue', 'Blue', 'Purple', 'Purple']), + '6156': ('#54447b', '#49b47e', '#94dd4d', '#ffd944', ['Purple', 'Green', 'Yellow', 'Retro']), + '5895': ('#f3ff92', '#f6ce59', '#2e8fc6', '#56cfd2', ['Yellow', 'Orange', 'Blue', 'Turquoise']), + '6324': ('#827055', '#a79e8b', '#d4ceb0', '#ede7cf', ['Brown', 'Grey']), + '6303': ('#dcdada', '#d869c0', '#fffd8c', '#ffbd59', ['Grey', 'Purple', 'Yellow', 'Orange']), + '6178': ('#f0f0ef', '#edd690', '#b1bd5d', '#955a47', ['Grey', 'Orange', 'Green', 'Brown']), + '4175': ('#6b62ce', '#372e96', '#2f99ad', '#84efe2', ['Blue', 'Turquoise']), + '6131': ('#001f3f', '#083358', '#0d63a5', '#ffd717', ['Blue', 'Yellow']), + '6116': ('#d15260', '#e95c63', '#ff9d7b', '#f2f089', ['Red', 'Orange', 'Yellow']), + '6053': ('#152744', '#367591', '#61d2b4', '#9dfdc7', ['Blue', 'Turquoise', 'Green']), + '6054': ('#61bbb6', '#a1dfff', '#ad56cd', '#4a3b85', ['Turquoise', 'Blue', 'Purple']), + '5582': ('#fffac0', '#ffd79a', '#73b9d7', '#9de6e8', ['Yellow', 'Orange', 'Blue', 'Blue']), + '5979': ('#761a1a', '#c13131', '#a7cd78', '#fff279', ['Red', 'Green', 'Yellow', 'Christmas']), + '5594': ('#1b0044', '#5727a3', '#9153f4', '#d6c5f0', ['Purple', 'Purple', 'Purple', 'Purple']), + '5896': ('#f4f787', '#85eb4e', '#32c38c', '#3f84ac', ['Yellow', 'Green', 'Blue']), + '5712': ('#da5c53', '#a8e4b1', '#4aa3ba', '#306d75', ['Red', 'Green', 'Blue']), + '5831': ('#3d065a', '#b51a62', '#70d4b4', '#ddddc7', ['Purple', 'Turquoise']), + '5656': ('#80a3a2', '#abcecf', '#c4dce0', '#daf4f5', ['Grey', 'Blue']), + '5512': ('#fff07a', '#d69830', '#ab3124', '#5f233f', ['Yellow', 'Orange', 'Red', 'Purple', 'Gold']), + '5563': ('#a21232', '#1a1831', '#20615b', '#dece9c', ['Red', 'Black', 'Turquoise', 'Retro']), + '5335': ('#449187', '#91e4a6', '#5f64c0', '#453064', ['Green', 'Blue']), + '5485': ('#f35f5f', '#cc435f', '#f1ea65', '#36a3eb', ['Red', 'Yellow', 'Blue']), + '5389': ('#442d7c', '#6341b4', '#f85aca', '#dafa8b', ['Purple', 'Pink', 'Green']), + '5429': ('#51af5b', '#b3e55e', '#feed30', '#ffcb3c', ['Green', 'Yellow', 'Orange']), + '5240': ('#7696db', '#562d7d', '#ae427b', '#ff8a98', ['Blue', 'Purple', 'Pink']), + '5242': ('#80c0ce', '#467292', '#9adea2', '#c2f69b', ['Blue', 'Blue', 'Green', 'Green']), + '5308': ('#83afa6', '#58727f', '#e5e5e5', '#d3a284', ['Turquoise', 'Grey', 'Brown']), + '2763': ('#222831', '#393e46', '#00adb5', '#eeeeee', ['Black', 'Grey', 'Turquoise', 'Dark']), + '5337': ('#f3f2c9', '#f0d587', '#93af56', '#336371', ['Yellow', 'Green', 'Turquoise']), + '5272': ('#363b4e', '#4f3b78', '#927fbf', '#c4bbf0', ['Black', 'Purple', 'Dark']), + '5336': ('#e25d4e', '#a93545', '#d9528b', '#ff92e8', ['Red', 'Pink']), + '5239': ('#523f79', '#807be4', '#73cff0', '#afffea', ['Purple', 'Turquoise', 'Blue', 'Green']), + '5241': ('#eaf887', '#79dc96', '#3bbbb3', '#377aaf', ['Yellow', 'Green', 'Turquoise', 'Blue']), + '5243': ('#ff8a69', '#f06161', '#bb4272', '#7a3476', ['Orange', 'Red', 'Purple']), + '5246': ('#f6f982', '#d9d46f', '#fa5862', '#c64272', ['Yellow', 'Yellow', 'Red']), + '4994': ('#f6f6d9', '#47e4e0', '#5f81e4', '#f67ff5', ['Yellow', 'Turquoise', 'Blue', 'Pink']), + '5044': ('#51af5b', '#b3e55e', '#f7ffa3', '#dddb6a', ['Green', 'Yellow']), + '5091': ('#f8aa27', '#fac55b', '#fff8b6', '#20655f', ['Orange', 'Yellow', 'Turquoise', 'Summer', 'Gold']), + '5163': ('#f9f3cf', '#ede7cf', '#ddbc89', '#aa512f', ['Yellow', 'Brown']), + '5125': ('#89fad0', '#4ec9e1', '#6796e5', '#228291', ['Turquoise', 'Blue']), + '5124': ('#288fb4', '#1d556f', '#efddb2', '#fa360a', ['Blue', 'Yellow', 'Red']), + '5132': ('#ff6464', '#ffbd67', '#f8fe85', '#5be7a9', ['Red', 'Orange', 'Yellow', 'Green']), + '4343': ('#d9dad7', '#c24d2c', '#3e4a61', '#1a2639', ['Grey', 'Orange', 'Blue', 'Winter']), + '4900': ('#c6f1a2', '#a8d966', '#43a367', '#385380', ['Green', 'Blue']), + '4973': ('#f7f5b2', '#bad4f9', '#5e89ef', '#352771', ['Yellow', 'Purple', 'Blue', 'Blue']), + '4899': ('#6a2e2e', '#cd5a5a', '#ffcf68', '#eff6a5', ['Brown', 'Red', 'Yellow', 'Warm']), + '4901': ('#f46188', '#491d7f', '#642ab6', '#7779ff', ['Pink', 'Purple', 'Purple', 'Blue']), + '4902': ('#489cc1', '#74f6a7', '#43a680', '#236969', ['Blue', 'Green']), + '4910': ('#062925', '#044a42', '#3a9188', '#b8e1dd', ['Green', 'Turquoise', 'Cold']), + '4733': ('#a099ff', '#5a67a6', '#fcb241', '#d68d08', ['Purple', 'Orange']), + '4802': ('#96cd39', '#f5ff65', '#ffba47', '#ff5b44', ['Green', 'Yellow', 'Orange', 'Red', 'Summer', 'Bright']), + '4803': ('#293462', '#211a4c', '#f33535', '#a51c2d', ['Blue', 'Red']), + '4804': ('#243d44', '#167a8b', '#2dea8f', '#24b273', ['Turquoise', 'Green']), + '4281': ('#9a60c1', '#ac92fa', '#96ebf0', '#48c3be', ['Purple', 'Turquoise']), + '4698': ('#563761', '#a7425c', '#f3825f', '#ffe26f', ['Purple', 'Orange', 'Yellow']), + '4464': ('#f2eb80', '#a2bf39', '#2685bf', '#144673', ['Yellow', 'Green', 'Blue']), + '4622': ('#1c0c2a', '#343b99', '#61bdf6', '#9affdc', ['Black', 'Blue', 'Turquoise']), + '4282': ('#8e334c', '#ec9454', '#f1f08a', '#c6cd78', ['Purple', 'Orange', 'Yellow']), + '4461': ('#0c2233', '#065471', '#0a91ab', '#ffc045', ['Black', 'Blue', 'Orange', 'Dark']), + '4581': ('#f7dead', '#cd4439', '#72b896', '#6f7777', ['Yellow', 'Red', 'Green', 'Grey', 'Retro']), + '4515': ('#f7f4ea', '#9ce3cf', '#6a7ff5', '#574b9b', ['Grey', 'Turquoise', 'Blue', 'Wedding', 'Retro']), + '4260': ('#b7569a', '#883c82', '#e4f091', '#f9cd76', ['Purple', 'Purple', 'Yellow', 'Orange']), + '3881': ('#f1efe9', '#beceb0', '#34857f', '#b0a48a', ['Grey', 'Green', 'Brown', 'Turquoise', 'Winter']), + '4535': ('#e0fffb', '#29cdb5', '#008698', '#f39c9c', ['Blue', 'Turquoise', 'Pink']), + '4390': ('#ffb19b', '#f66060', '#9a2c80', '#551863', ['Pink', 'Orange', 'Purple', 'Purple']), + '4337': ('#620808', '#a53f3f', '#f4ce74', '#ffe9c1', ['Brown', 'Brown', 'Yellow', 'Yellow']), + '4285': ('#80ef91', '#4ba54d', '#f3ef82', '#f0c15a', ['Green', 'Green', 'Yellow', 'Orange']), + '4371': ('#f0e9ff', '#cea9ff', '#b346ff', '#545454', ['Purple', 'Purple', 'Grey']), + '4125': ('#302a77', '#5457a6', '#eebb55', '#f1e6d1', ['Blue', 'Blue', 'Orange', 'Yellow']), + '4319': ('#3b939b', '#2f8189', '#91f3fc', '#c9fbff', ['Turquoise', 'Blue']), + '4259': ('#80e5e9', '#7d77f6', '#793e71', '#e471a7', ['Turquoise', 'Blue', 'Purple', 'Pink']), + '4174': ('#ffe180', '#eba059', '#8b3c76', '#41245c', ['Yellow', 'Orange', 'Purple', 'Purple']), + '4176': ('#f0f87f', '#4bc87f', '#29668b', '#6eaff7', ['Yellow', 'Green', 'Blue']), + '4177': ('#85203b', '#cb3b3b', '#e0c45c', '#fff98c', ['Red', 'Yellow']), + '4071': ('#ff5335', '#dfe0d4', '#3e92a3', '#353940', ['Orange', 'Grey', 'Turquoise', 'Black']), + '3287': ('#055049', '#faf35e', '#069a8e', '#a1e3d8', ['Green', 'Yellow', 'Turquoise']), + '4111': ('#000033', '#0066cc', '#0099ff', '#ededed', ['Black', 'Blue', 'Grey']), + '3807': ('#fffbe3', '#ffa9a9', '#6a425c', '#26271a', ['Yellow', 'Pink', 'Purple', 'Brown']), + '3661': ('#1b515e', '#338275', '#88b990', '#abcd9e', ['Green']), + '4038': ('#04879c', '#0c3c78', '#090030', '#f30a49', ['Turquoise', 'Blue', 'Black', 'Red', 'Dark']), + '3907': ('#d14848', '#ec952e', '#f0e449', '#d6f7f8', ['Red', 'Orange', 'Yellow']), + '4057': ('#272e6e', '#ffffc3', '#ffc55c', '#e95d35', ['Blue', 'Yellow', 'Orange', 'Orange']), + '3942': ('#f2f1a7', '#ef5959', '#b43144', '#88a9f7', ['Yellow', 'Red', 'Blue', 'Summer']), + '3890': ('#f1f5bc', '#fecb92', '#f99a9a', '#d1f6a4', ['Yellow', 'Orange', 'Pink', 'Green']), + '3454': ('#335c49', '#678c40', '#bdbe36', '#e5dd90', ['Green', 'Yellow']), + '3943': ('#8aacff', '#6151bb', '#d7f096', '#67ba6d', ['Blue', 'Green']), + '3792': ('#5d697a', '#383838', '#f66b34', '#f2d639', ['Grey', 'Black', 'Orange', 'Yellow']), + '3780': ('#06cdff', '#8200ff', '#470c85', '#18134c', ['Blue', 'Purple', 'Purple', 'Black']), + '3167': ('#824c96', '#433466', '#ffaf4f', '#ed733f', ['Purple', 'Orange']), + '3740': ('#2b3964', '#3482aa', '#6db3b5', '#f9cc7b', ['Blue', 'Turquoise', 'Orange']), + '3781': ('#f4e022', '#5a37c3', '#18224b', '#de1b4a', ['Yellow', 'Purple', 'Black', 'Red']), + '3574': ('#47d0bd', '#daec8b', '#fffdd6', '#ff5da2', ['Turquoise', 'Green', 'Yellow', 'Pink']), + '3459': ('#ccf62c', '#98c74e', '#60a261', '#357a5b', ['Green']), + '3642': ('#f0dca2', '#e0b58c', '#cd7856', '#b5421e', ['Orange', 'Yellow', 'Brown']), + '3604': ('#ff304f', '#002651', '#775ada', '#28c7fa', ['Red', 'Blue', 'Purple']), + '3656': ('#ff6d3f', '#b14b4b', '#594057', '#36162e', ['Orange', 'Red', 'Purple', 'Brown', 'Halloween']), + '3452': ('#4ac3be', '#a3dec9', '#e6efbf', '#faac64', ['Turquoise', 'Orange']), + '3460': ('#eb586f', '#d8e9f0', '#4aa0d5', '#454553', ['Red', 'Blue', 'Blue', 'Grey']), + '3666': ('#ffea66', '#f59159', '#c75080', '#6b206a', ['Yellow', 'Orange', 'Purple']), + '3667': ('#776ae3', '#88e570', '#fbff67', '#ffb44a', ['Purple', 'Green', 'Yellow', 'Orange']), + '3267': ('#d1dbbd', '#91aa9d', '#3e606f', '#193441', ['Turquoise', 'Grey']), + '3590': ('#3d5a59', '#9aebdd', '#367db5', '#313e86', ['Turquoise', 'Blue', 'Blue', 'Blue']), + '3589': ('#ffe390', '#ff926b', '#ff4a4a', '#a83c54', ['Yellow', 'Orange', 'Red']), + '3538': ('#d5441c', '#013c4d', '#9dd5cb', '#f3e5b1', ['Orange', 'Blue', 'Yellow']), + '3530': ('#f7fa86', '#76e7c7', '#9e7eff', '#9c4b9e', ['Yellow', 'Turquoise', 'Purple']), + '3528': ('#0d7685', '#084d68', '#69c181', '#ccf186', ['Turquoise', 'Green']), + '3527': ('#fdf3f3', '#f8e7e7', '#a070a1', '#724060', ['Pink', 'Purple']), + '3328': ('#957541', '#be9639', '#fccf5b', '#dde9eb', ['Brown', 'Yellow', 'Grey', 'Autumn', 'Gold']), + '3435': ('#7c6fff', '#5ca9ff', '#fcff90', '#ffde68', ['Purple', 'Blue', 'Yellow', 'Summer']), + '3449': ('#3b5441', '#83e85a', '#2cb978', '#107a8b', ['Green', 'Green', 'Green', 'Turquoise']), + '3063': ('#c2ffff', '#8bdeff', '#a888ff', '#26466f', ['Blue', 'Purple']), + '3269': ('#fadb3f', '#ecf7c5', '#ea5656', '#27332d', ['Yellow', 'Red', 'Black']), + '2978': ('#bdd8f1', '#82a6cb', '#3667a6', '#214177', ['Blue']), + '3373': ('#d8b5de', '#f9f1bf', '#f3b75b', '#cc7f2a', ['Purple', 'Yellow', 'Orange', 'Gold']), + '3382': ('#ffc7c7', '#dc7646', '#a45c5c', '#6c476e', ['Pink', 'Orange', 'Brown', 'Purple']), + '3383': ('#515661', '#2e9f82', '#68c170', '#d6ec8c', ['Grey', 'Turquoise', 'Green']), + '3177': ('#fdfbda', '#d3d0a8', '#819f7f', '#2d4659', ['Yellow', 'Green']), + '3173': ('#e9e6c9', '#ca6144', '#566683', '#393e51', ['Orange', 'Blue']), + '3324': ('#c24242', '#e08932', '#e5c955', '#f2f5b1', ['Red', 'Orange', 'Yellow', 'Yellow']), + '3059': ('#80ffdb', '#55e0a3', '#5b70f3', '#4850b9', ['Turquoise', 'Green', 'Blue', 'Blue']), + '3060': ('#442b72', '#993d9a', '#8a6bf0', '#fedf96', ['Purple', 'Purple', 'Purple', 'Yellow']), + '3186': ('#d0f66a', '#36c186', '#158a8c', '#1e5287', ['Green', 'Green', 'Turquoise', 'Blue']), + '3213': ('#f7ebc9', '#f2cc96', '#814906', '#d35823', ['Yellow', 'Orange', 'Brown', 'Orange']), + '3062': ('#fba834', '#fce850', '#387adf', '#50c4ed', ['Orange', 'Yellow', 'Blue']), + '3168': ('#a8e0e1', '#5a96bb', '#75448c', '#c46caa', ['Blue', 'Purple']), + '2870': ('#5dacbd', '#24527a', '#a7bcb9', '#e0ebeb', ['Blue', 'Grey']), + '3043': ('#feed30', '#ff6868', '#924992', '#504077', ['Yellow', 'Red', 'Purple', 'Blue']), + '3065': ('#f5eb82', '#dfb361', '#d3775d', '#a75377', ['Yellow', 'Orange', 'Purple']), + '2937': ('#e4e4e4', '#41b3d3', '#61d2dc', '#444444', ['Grey', 'Blue']), + '2982': ('#a62671', '#db466b', '#f96c48', '#f5d773', ['Purple', 'Red', 'Orange', 'Yellow', 'Sunset']), + '3061': ('#1f3a52', '#41a186', '#8cca6e', '#d3f689', ['Turquoise', 'Green']), + '2562': ('#343434', '#055e68', '#62a388', '#b9d2d2', ['Black', 'Turquoise', 'Green', 'Grey', 'Dark']), + '2881': ('#062c80', '#0e6ac7', '#4fb9fc', '#f6f5da', ['Blue', 'Yellow']), + '2655': ('#ff9234', '#ffcd3c', '#fafcb4', '#b0db72', ['Orange', 'Yellow', 'Green', 'Gold']), + '2829': ('#eb2a5d', '#ff6f41', '#ffb44b', '#ffeb7d', ['Red', 'Orange', 'Orange', 'Yellow']), + '2707': ('#fffbb7', '#ffa849', '#68848b', '#4a2b13', ['Yellow', 'Orange', 'Blue', 'Brown']), + '2613': ('#5639a6', '#20236d', '#fa4848', '#ffe087', ['Blue', 'Red', 'Yellow']), + '2715': ('#1a2634', '#203e5f', '#ffcc00', '#fee5b1', ['Black', 'Blue', 'Yellow']), + '2814': ('#740021', '#8d0033', '#bd3246', '#fdc8aa', ['Red', 'Orange']), + '2314': ('#1d0251', '#019081', '#74cc7e', '#d2eba7', ['Purple', 'Turquoise', 'Green']), + '2661': ('#2f2342', '#e42f45', '#b42b3f', '#7ca0e5', ['Black', 'Red', 'Red', 'Blue']), + '2779': ('#4a2377', '#61529f', '#ba69de', '#f3e96d', ['Purple', 'Yellow', 'Wedding']), + '2738': ('#4ac6b7', '#4f5e7f', '#965f8a', '#ff7070', ['Turquoise', 'Blue', 'Purple', 'Orange']), + '2705': ('#ffedc6', '#ffc478', '#fff87d', '#724330', ['Orange', 'Orange', 'Yellow', 'Brown']), + '2485': ('#492b7b', '#301551', '#ed8a0a', '#f7d914', ['Purple', 'Orange', 'Yellow']), + '2555': ('#eadada', '#d59dc5', '#bf5caa', '#4d3a4d', ['Pink', 'Purple', 'Grey', 'Wedding']), + '2759': ('#114b5f', '#1a936f', '#88d498', '#f3e9d2', ['Turquoise', 'Green', 'Yellow']), + '2499': ('#303242', '#394359', '#f2be8d', '#ba6c65', ['Black', 'Red', 'Vintage']), + '2193': ('#483243', '#684184', '#cb73bb', '#f3c2cb', ['Purple', 'Pink']), + '2640': ('#e35454', '#f6fa7b', '#d2d868', '#ac9742', ['Red', 'Yellow', 'Brown']), + '2358': ('#d93153', '#eb5033', '#ff9d00', '#ffd82c', ['Red', 'Orange', 'Orange', 'Yellow']), + '2641': ('#e0f6aa', '#69aeff', '#9d4dff', '#6b3278', ['Green', 'Blue', 'Purple']), + '2487': ('#0e2e3b', '#166678', '#7db9b3', '#d8d7c3', ['Black', 'Blue', 'Turquoise', 'Brown']), + '2512': ('#e8e3c7', '#d4ceb0', '#b85b3f', '#a65238', ['Brown', 'Orange']), + '2389': ('#d2e4f1', '#8facc0', '#818d97', '#484d51', ['Blue', 'Grey']), + '2520': ('#2f1b44', '#892c41', '#c89034', '#fbff5f', ['Purple', 'Red', 'Orange', 'Yellow']), + '2171': ('#f83e4b', '#f7e185', '#cb9bba', '#9d53c3', ['Red', 'Yellow', 'Purple']), + '2130': ('#d2f079', '#c8d35b', '#ad8c45', '#a2663e', ['Green', 'Brown']), + '1895': ('#fadb3f', '#ecf7c5', '#515748', '#27332d', ['Yellow', 'Grey', 'Black']), + '1910': ('#2c2955', '#4c5fb1', '#f9f194', '#cdd582', ['Black', 'Blue', 'Yellow', 'Green']), + '2128': ('#231a31', '#e42f45', '#b42b3f', '#8ab2ff', ['Black', 'Red', 'Red', 'Blue']), + '1907': ('#d6ecfa', '#6f3826', '#b84a39', '#f15c5c', ['Blue', 'Brown', 'Red', 'Wedding']), + '2053': ('#0e153a', '#3d5af1', '#22d1ee', '#e2f3f5', ['Blue', 'Blue', 'Blue']), + '2127': ('#e4ba6f', '#fae88e', '#eb5e60', '#a52f57', ['Orange', 'Yellow', 'Red']), + '1894': ('#83cbfb', '#377fd9', '#edf68d', '#f1d851', ['Blue', 'Yellow']), + '1464': ('#d7df71', '#0e5f76', '#083d56', '#081e3f', ['Yellow', 'Blue', 'Black']), + '1908': ('#4b4c7a', '#eb92fb', '#c855bc', '#a03271', ['Pink', 'Purple']), + '1909': ('#362999', '#4262c5', '#44aec2', '#93efed', ['Purple', 'Blue', 'Turquoise']), + '1914': ('#efbfc6', '#c22828', '#8a0f0f', '#3c0303', ['Pink', 'Red', 'Brown']), + '1805': ('#f7b449', '#dde9f8', '#8293e3', '#5847ad', ['Orange', 'Blue', 'Purple']), + '1652': ('#f5f0e8', '#d3bd9a', '#a28f70', '#674f04', ['Grey', 'Brown']), + '1806': ('#fff56c', '#f1b149', '#4366a9', '#679ceb', ['Yellow', 'Orange', 'Blue']), + '1770': ('#aee1fc', '#60abfb', '#5170fd', '#4636fc', ['Blue']), + '1813': ('#438a70', '#52ceba', '#8affb4', '#eaff81', ['Green', 'Turquoise', 'Turquoise', 'Yellow']), + '1418': ('#e5edc4', '#e1a6e1', '#934662', '#463832', ['Yellow', 'Pink', 'Purple', 'Brown']), + '1649': ('#f0f5f9', '#c9d6df', '#52616b', '#1e2022', ['Grey', 'Black']), + '1660': ('#f6538f', '#b83f87', '#f3e94c', '#e8d124', ['Pink', 'Purple', 'Yellow', 'Yellow']), + '1608': ('#1a2634', '#203e5f', '#eec550', '#f9e3a3', ['Black', 'Blue', 'Yellow']), + '1181': ('#eca106', '#d34f1e', '#91300a', '#5f1b00', ['Orange', 'Brown', 'Gold']), + '1298': ('#3f3f3f', '#95956e', '#d2d86e', '#efefef', ['Grey', 'Green', 'Wedding', 'Retro']), + '1504': ('#48466d', '#3d84a8', '#46cdcf', '#abedd8', ['Turquoise', 'Blue']), + '1319': ('#70560d', '#c3a655', '#efd99b', '#f8edcd', ['Brown', 'Yellow']), + '1303': ('#e7272d', '#ae2a2f', '#fec24a', '#f6e5e4', ['Red', 'Yellow', 'Pink']), + '1037': ('#ffea54', '#ffcb3c', '#feaa2b', '#ff5757', ['Yellow', 'Orange', 'Red', 'Gold']), + '1043': ('#4ec9df', '#63a1d0', '#3576a7', '#344986', ['Blue']), + '643': ('#353941', '#26282b', '#5f85db', '#90b8f8', ['Black', 'Blue', 'Dark']), + '1223': ('#49260a', '#623b1c', '#caad8c', '#f6eddd', ['Brown']), + '839': ('#fbf8ca', '#a13f80', '#5e1043', '#360827', ['Yellow', 'Purple', 'Black', 'Wedding']), + '717': ('#266352', '#128061', '#53c0a2', '#b5f7e6', ['Green']), + '658': ('#611919', '#8e2735', '#deae4f', '#faf189', ['Brown', 'Red', 'Orange', 'Yellow']), + '361': ('#f9ed69', '#f08a5d', '#b83b5e', '#6a2c70', ['Yellow', 'Orange', 'Red', 'Purple']), + '362': ('#225763', '#41d8bf', '#2f89b3', '#3b50b2', ['Blue', 'Turquoise']), + '471': ('#c1f880', '#55c59d', '#4f5aa8', '#7481cf', ['Green', 'Turquoise', 'Blue']), + '470': ('#f75b5b', '#c83b4c', '#46265c', '#794d9a', ['Red', 'Purple']), + '469': ('#1b4b4d', '#f3f66f', '#f1d15f', '#e8984a', ['Yellow', 'Orange']), + '823': ('#561f55', '#df3554', '#902424', '#541f1f', ['Purple', 'Red', 'Red', 'Brown']), + '820': ('#65e892', '#3994d6', '#354abf', '#3d289b', ['Green', 'Blue']), + '255': ('#ef8f6b', '#d36239', '#e2dd66', '#a8b94e', ['Orange', 'Orange', 'Yellow', 'Green']), + '277': ('#e6a157', '#c9753d', '#973a3a', '#5b252d', ['Orange', 'Red', 'Brown', 'Warm']), + '278': ('#33425b', '#5baaec', '#526ed0', '#484cb0', ['Blue', 'Cold', 'Winter']), + '276': ('#fda4cf', '#f46d6d', '#b3533d', '#f0d4a2', ['Pink', 'Orange']), + '274': ('#56bfb5', '#38817a', '#f5f093', '#fbd66f', ['Turquoise', 'Yellow']), + '273': ('#884939', '#967248', '#caa653', '#e9e995', ['Brown', 'Yellow', 'Autumn']), + '272': ('#ff94c7', '#e760bf', '#7e49ac', '#343a69', ['Pink', 'Purple']), + '271': ('#7a81eb', '#504aa7', '#253361', '#599597', ['Purple', 'Blue', 'Blue', 'Turquoise']), + '280': ('#96c99c', '#55829c', '#485791', '#3a316e', ['Green', 'Blue', 'Purple']), + '282': ('#eefca9', '#b7e576', '#83cc61', '#5a9e7c', ['Green', 'Summer']), + '307': ('#693f27', '#e4c144', '#df7943', '#c24b39', ['Brown', 'Yellow', 'Orange']), + '221': ('#b0e6ff', '#7687db', '#8f45a9', '#582e48', ['Blue', 'Blue', 'Purple', 'Purple']), + '222': ('#304d4e', '#4b7551', '#8a9e52', '#f0d699', ['Green', 'Yellow']), + '223': ('#dffcad', '#6ec189', '#595cae', '#424478', ['Green', 'Blue']), + '224': ('#ffd7be', '#95977a', '#3f4c48', '#373640', ['Green']), + '225': ('#b3f7f6', '#7dd076', '#f1f592', '#f4cb81', ['Blue', 'Green', 'Yellow', 'Orange']), + '226': ('#352d4d', '#6d6192', '#69b0c1', '#92e0a9', ['Blue', 'Purple', 'Turquoise', 'Green']), + '227': ('#7a9eaf', '#655989', '#de88a5', '#ffcebb', ['Blue', 'Purple', 'Pink', 'Orange']), + '231': ('#314357', '#456672', '#e3b587', '#c98c70', ['Turquoise', 'Orange', 'Brown', 'Vintage']), + '228': ('#764f51', '#7fc5ca', '#9fe6dc', '#cfffff', ['Brown', 'Turquoise']), + '229': ('#477d7f', '#1f5357', '#64bd97', '#c2ffbb', ['Turquoise', 'Green']), + '230': ('#d19feb', '#fffd9d', '#f7d08c', '#ed8282', ['Purple', 'Yellow', 'Red', 'Bright']), + '232': ('#f6aad0', '#e9767c', '#8f5b4a', '#ddd49f', ['Pink', 'Red', 'Brown']), + '233': ('#a6f2db', '#7bcace', '#678eb4', '#4f4e79', ['Turquoise', 'Blue', 'Blue']), + '234': ('#8cdadb', '#815e94', '#f4f49e', '#f1d089', ['Turquoise', 'Purple', 'Yellow', 'Yellow']), + '236': ('#3b503d', '#4a746e', '#f1edb3', '#c8cf94', ['Green', 'Turquoise', 'Yellow']), + '237': ('#ee8374', '#54567a', '#dab784', '#f8f3b6', ['Orange', 'Blue', 'Yellow', 'Yellow']), + '238': ('#2b2e4a', '#e84545', '#903749', '#53354a', ['Red']), + '240': ('#49493c', '#9fa180', '#f2f77f', '#6ebaa7', ['Brown', 'Brown', 'Yellow', 'Turquoise']), + '241': ('#efd8f4', '#d4abdc', '#ea5656', '#f1e38a', ['Purple', 'Red', 'Yellow']), + '242': ('#ee7c4b', '#c45d3e', '#c6c5b3', '#f5f0c4', ['Orange', 'Orange', 'Brown', 'Yellow', 'Gold']), + '243': ('#b2b7ff', '#d5e8ff', '#d9a2f1', '#d86f9b', ['Blue', 'Purple', 'Pink']), + '244': ('#edf3b7', '#e5c890', '#9268a5', '#644a7f', ['Yellow', 'Orange', 'Purple', 'Purple']), + '248': ('#3d322c', '#654534', '#9c563d', '#d9b26e', ['Brown']), + '246': ('#5f5dbd', '#5e87b8', '#83cee0', '#a4fbe3', ['Blue', 'Blue', 'Turquoise', 'Turquoise']), + '247': ('#804d3b', '#522e24', '#75beda', '#9aedf4', ['Brown', 'Brown', 'Blue']), + '249': ('#dbef98', '#605cb8', '#60c2a4', '#9df0ac', ['Green']), + '250': ('#9a69e1', '#47429d', '#f7b7f3', '#e27393', ['Purple', 'Blue', 'Pink', 'Pink']), + '253': ('#6c95ec', '#3d61ad', '#81e1af', '#41a06f', ['Blue', 'Green']), + '254': ('#d19178', '#a1583e', '#d4c07a', '#f8f7a5', ['Brown', 'Yellow']), + '208': ('#bdf9f7', '#93c4ff', '#b67ccf', '#765a60', ['Blue', 'Purple']), + '187': ('#1d1716', '#402a23', '#a55233', '#f3bc77', ['Black', 'Brown', 'Brown', 'Orange']), + '188': ('#fa8572', '#b24968', '#6c3779', '#6c5fa7', ['Orange', 'Purple', 'Purple']), + '189': ('#f7ec77', '#da5151', '#ed9f66', '#876464', ['Yellow', 'Red', 'Orange', 'Brown']), + '190': ('#48829e', '#51dacf', '#9ef5cf', '#e8ffb1', ['Blue', 'Turquoise', 'Yellow']), + '191': ('#d5ab9c', '#e6e696', '#7bc0a3', '#54878f', ['Brown', 'Yellow', 'Green', 'Turquoise', 'Pastel']), + '192': ('#e2eff1', '#b6d5e1', '#65799b', '#555273', ['Blue']), + '193': ('#ffe76a', '#e0ab5b', '#94784c', '#6e4c41', ['Yellow', 'Orange', 'Brown', 'Gold']), + '194': ('#333a7b', '#4b6982', '#70c6c7', '#b4ffd8', ['Blue', 'Blue', 'Turquoise', 'Green']), + '195': ('#e5f1e3', '#a3cd9e', '#529471', '#35635b', ['Green']), + '196': ('#3e3245', '#524a79', '#97d8ec', '#74bbca', ['Black', 'Turquoise', 'Blue']), + '198': ('#8fc9ae', '#548e87', '#385b66', '#bddaa5', ['Green']), + '202': ('#98d8ff', '#796dce', '#694b7c', '#402a30', ['Blue', 'Blue', 'Purple', 'Purple']), + '203': ('#9effa9', '#36485e', '#333146', '#29252c', ['Green', 'Blue', 'Black']), + '204': ('#f7ffba', '#f7e39c', '#ebaf81', '#da8067', ['Yellow', 'Orange']), + '205': ('#36413d', '#4c657e', '#f29696', '#ffe2ad', ['Black', 'Blue', 'Pink', 'Yellow']), + '206': ('#c1e8da', '#c96868', '#5e4949', '#866770', ['Turquoise', 'Red', 'Grey', 'Brown']), + '209': ('#d4a2be', '#75597d', '#b0b8b4', '#f8e4dd', ['Pink', 'Purple', 'Grey']), + '211': ('#364968', '#fddf97', '#e09664', '#6c4343', ['Blue', 'Yellow', 'Orange', 'Brown']), + '212': ('#ffebbc', '#5da7ae', '#543d46', '#292830', ['Yellow', 'Blue', 'Brown', 'Black']), + '213': ('#ebbf58', '#769353', '#3d655d', '#33484d', ['Orange', 'Green', 'Turquoise', 'Blue']), + '215': ('#4531b1', '#a836ad', '#f16896', '#fff0a4', ['Blue', 'Purple', 'Pink', 'Yellow']), + '216': ('#d15555', '#eda489', '#e8fd96', '#a1d76f', ['Red', 'Pink', 'Yellow', 'Green']), + '217': ('#a45fbe', '#382f60', '#485188', '#4b81ab', ['Purple', 'Blue']), + '218': ('#567582', '#464d5c', '#f7dda4', '#b89068', ['Turquoise', 'Yellow', 'Brown']), + '219': ('#3e6545', '#9973e2', '#82ceda', '#ecffb1', ['Green', 'Purple', 'Blue', 'Yellow']), + '220': ('#bbe06c', '#7cb855', '#469b4c', '#3c6e57', ['Green', 'Green', 'Green', 'Green']), + '185': ('#2a221e', '#46322b', '#c73f65', '#d580bc', ['Brown', 'Pink']), + '180': ('#686ee2', '#5c3e84', '#f35c6e', '#ffa87b', ['Blue', 'Purple', 'Red', 'Orange']), + '181': ('#abf2fb', '#b589ef', '#a964cd', '#f1a3c5', ['Blue', 'Purple', 'Pink']), + '182': ('#ffff8f', '#ec9e69', '#d56073', '#7a4579', ['Yellow', 'Orange', 'Red', 'Purple', 'Sunset', 'Wedding']), + '129': ('#f39de5', '#9b77da', '#4e6b9f', '#6fa5b1', ['Pink', 'Purple', 'Blue', 'Blue']), + '130': ('#516091', '#74bec1', '#adebbe', '#eef3ad', ['Blue', 'Turquoise', 'Green', 'Yellow', 'Pastel']), + '133': ('#ebd9dd', '#d8aed3', '#9182c4', '#486989', ['Pink', 'Purple', 'Blue']), + '134': ('#8be3e1', '#d3f7ad', '#95bb76', '#97935c', ['Blue', 'Green', 'Brown']), + '136': ('#734444', '#c37857', '#eeedbe', '#99b27f', ['Brown', 'Green']), + '137': ('#4c5f7a', '#393e6f', '#3d2e4f', '#321d2f', ['Blue', 'Black', 'Purple', 'Dark']), + '139': ('#e1dfba', '#7f7e90', '#4d424d', '#36292c', ['Grey']), + '140': ('#b1e9a3', '#7ac38f', '#88e0d0', '#c7eeff', ['Green', 'Green', 'Turquoise', 'Blue']), + '141': ('#e97a7a', '#8b4f80', '#8b76a5', '#b9c0d5', ['Red', 'Purple', 'Grey', 'Pastel']), + '146': ('#e04b5a', '#e49756', '#5b305a', '#9a4c68', ['Red', 'Orange', 'Purple', 'Purple']), + '152': ('#f2fc9f', '#edbb91', '#da6969', '#b05977', ['Yellow', 'Orange', 'Red']), + '155': ('#8ecccc', '#50717b', '#3a4042', '#212121', ['Blue', 'Grey', 'Black']), + '156': ('#e6f18c', '#72b37e', '#437975', '#555c78', ['Yellow', 'Green']), + '157': ('#7fcbd7', '#857ebb', '#ca9dd7', '#facbd3', ['Blue', 'Purple', 'Pink']), + '158': ('#d789d7', '#9d65c9', '#5d54a4', '#2a3d66', ['Pink', 'Purple']), + '159': ('#f7c469', '#c46352', '#714433', '#412525', ['Orange', 'Brown', 'Autumn']), + '160': ('#9ae17b', '#6bba62', '#307470', '#42476d', ['Green', 'Green', 'Purple']), + '161': ('#634258', '#6d6087', '#60a0b0', '#9ad1aa', ['Purple', 'Blue', 'Green']), + '162': ('#f1f4c6', '#d6d0b8', '#aaa6a4', '#837d7d', ['Yellow', 'Brown', 'Grey']), + '165': ('#f96d6d', '#b84d69', '#a9d7f6', '#8fb1e9', ['Red', 'Blue']), + '171': ('#d68438', '#f1b24b', '#36846b', '#4bb39a', ['Orange', 'Turquoise', 'Gold']), + '174': ('#639cd9', '#5454c5', '#342056', '#220e24', ['Blue', 'Purple', 'Black', 'Dark']), + '177': ('#7dd87d', '#4c9173', '#5b446a', '#906387', ['Green', 'Green', 'Purple']), +} \ No newline at end of file diff --git a/ThemeMaker/readme.md b/ThemeMaker/readme.md new file mode 100644 index 000000000..46a7e0742 --- /dev/null +++ b/ThemeMaker/readme.md @@ -0,0 +1,172 @@ +# Theme Maker + +## A Tool To Make PySimpleGUI "Look and Feel" Entries + +The Look and Feel themes are defined using a dictionary. Each theme has a dictionary of colors and other settings such as the color for the text, background, input fields, buttons, etc. Generating these themes has been a tedious and long process in the past. This tool was created to make that process easier, more enjoyable, and perhaps something users could participate in. + +This program uses over 1,700 color palettes that were downloaded from https://colorhunt.co/palettes and put into a python file as a dictionary. You'll find the dictionary in `color_themes.py`. + +Here is how the dictionary looks when shortened to 3 entires: + +```python +themes = { + '163372': ('#f4efd3', '#cccccc', '#c2b0c9', '#9656a1', ['Yellow', 'Grey', 'Purple', 'Pastel']), + '163318': ('#594a4e', '#e78fb3', '#ffc0ad', '#6fc1a5', ['Brown', 'Pink', 'Green', 'Vintage']), + '163537': ('#ff8ba7', '#ffc6c7', '#faeee7', '#c3f0ca', ['Pink', 'Green', 'Bright', 'Summer']) } +``` + +## What It Does + +Each palette, a group of 4 colors, is used to present a small "candidate theme layout". A single "candidate" looks like this: + +![SNAG-0587](https://user-images.githubusercontent.com/46163555/69909821-c820b980-13ce-11ea-95fb-03460e7d3873.jpg) + +For each palette you will be presented with 4 of those layouts. Two are "Dark" and two are "Light". You can choose options in each of these layouts and choose to save it. + +The program generates text in a debug window and also appends the text to an output file. This text can be used directly in a look and feel table. + + +## Installing + +There is no installation if you already have PySimpleGUI installed. Simply download the 2 .py files in this folder and run the one named Theme_Maker.py + +## Running - Initial Window + +The first window you're presented with collects information from you regarding how you would like the theme generation window to be laid out and where to start in the palette dictionary. + +![SNAG-0584](https://user-images.githubusercontent.com/46163555/69909830-0322ed00-13cf-11ea-88da-999d6e901002.jpg) + + + + +![SNAG-0586](https://user-images.githubusercontent.com/46163555/69909820-c820b980-13ce-11ea-94db-0e36af813e25.jpg) + + + + +Program that is used to create new themes for use with PySimpleGUI's "Look and Feel" settings. +You are presented with a grid of mini-windows that is created for color palettes downloaded from https://colorhunt.co/palettes +The file color_themes.py contains a large dictionary of approx 1780 palettes. + +For each palette you are shown 4 candidate themes, 2 "light" and 2 "dark". The window shows 5 palettes so you'll have a +total of 20 candidate themes displayed in total. +Each candidate theme has a 3 options - The button color (text and background), the text color for Input/Multiline elements, +and the name of the theme when you save it. These you choose using the radio buttons and one input field. +To "save" one of these candidate themes, check the checkbox to the left of the layout, choose the radio buttons for button +& text settings and optionally change the theme name that is shown above the grid of OK buttons. By default the name starts +with either "Dark" or "Light" and is followed by the first 2 "tags" that were posted with the palette on the colorhunt site. + +After you've selected the themes you want to save from the window of 20 click any "OK" button in the window or close the +window with the "X". You will see the dictionary text in the Debug Window and the values will also be written to a file. +You'll then be shown the next group of 20 candidate themes. + +If you want to exit the program entirely, click any "Cancel" button the page. Note - cliicking "Cancel" will not save any +theme you have checked with the checkbox. You should only exit from a window you have not selected any themes for saving + +If a Theme is selected for saving, then the values for the LOOK_AND_FEEL dictionary are displayed in a debug window and are +also appended to the file new_theme_dict.py. You will need to edit the new_theme_dict.py file to get the syntax correct. +A "," or "}" may need to be added in order to make the table be correct. + +If you're using this program it's assumed you know what you're doing and understand the LOOK_AND_FEEL dictionary and can +figure out how to get the syntax correct for adding it to the main dictionary of themes. + +## Choosing and Saving New Themes + +Let's say you were working with these candidate themes: + +![SNAG-0556](https://user-images.githubusercontent.com/46163555/70284016-94f47680-1790-11ea-9e08-1fe7804eaf1a.jpg) + + +You like the first 2 themes on the second row, so you + +* Mark the checkbox next to each of those 2 themes +* Click the 2 radio buttons indicating choice for input text choice and button color +* Enter a name to be used for the theme +* Click OK anywhere on the screen + +Here is how my choices appear for those 2 entries: + +![SNAG-0577](https://user-images.githubusercontent.com/46163555/70284014-94f47680-1790-11ea-9373-28f80c8a4d31.jpg) + +The result will be that a debug window will open and display the text for the 2 new theme entries for the look and feel theme dictionary. + +![SNAG-0578](https://user-images.githubusercontent.com/46163555/70284013-94f47680-1790-11ea-8be8-507ed929c867.jpg) + +Similar text will be appended to the end of the file "new_theme_dict.py". + + +## Integrating the New Themes + +Now that you've got the text for the themes it's time to integrate it into your PySimpleGUI environment. The way you do this is that you add your themes direcvtly to the look and feel dictionary. + +Begin by copying the text from either the .py file or the debug window: + +```python +'DarkGreenArmy' : {'BACKGROUND': '#3b503d', 'TEXT': '#f1edb3', 'INPUT': '#c8cf94', 'TEXT_INPUT': '#000000', 'SCROLL': '#c8cf94', 'BUTTON': ('#f1edb3', '#3b503d'), 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#3b503d', '#4a746e', '#c8cf94', '#f1edb3'], 'DESCRIPTION': ['Green', 'Turquoise', 'Yellow']} + +'LightGreenArmy' : {'BACKGROUND': '#f1edb3', 'TEXT': '#3b503d', 'INPUT': '#4a746e', 'TEXT_INPUT': '#f1edb3', 'SCROLL': '#3b503d', 'BUTTON': ('#f1edb3', '#3b503d'), 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#3b503d', '#4a746e', '#c8cf94', '#f1edb3'], 'DESCRIPTION': ['Green', 'Turquoise', 'Yellow']} +``` + +This code is written as if you were going to directly add the code inside the PySimpleGUI.py file itself. Instead you'll be adding them directly from your user code rather than modifying the PySimpleGUI.py file. + +Adding the entries to the table can be accomplished using simple assignment to a new dictionary entry. The look and feel dictionary in PySimpleGUI is named `sg.LOOK_AND_FEEL_TABLE`. Here is a sample user program that adds these 2 new themes to the table and then uses one of them to display a window and another to display a popup. + + +```python +import PySimpleGUI as sg + +sg.LOOK_AND_FEEL_TABLE['DarkGreenArmy'] = {'BACKGROUND': '#3b503d', 'TEXT': '#f1edb3', 'INPUT': '#c8cf94', 'TEXT_INPUT': '#000000', 'SCROLL': '#c8cf94', + 'BUTTON': ('#f1edb3', '#3b503d'), 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#3b503d', '#4a746e', '#c8cf94', '#f1edb3'], 'DESCRIPTION': ['Green', 'Turquoise', 'Yellow']} + +sg.LOOK_AND_FEEL_TABLE['LightGreenArmy'] = {'BACKGROUND': '#f1edb3', 'TEXT': '#3b503d', 'INPUT': '#4a746e', 'TEXT_INPUT': '#f1edb3', 'SCROLL': '#3b503d', + 'BUTTON': ('#f1edb3', '#3b503d'), 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#3b503d', '#4a746e', '#c8cf94', '#f1edb3'], 'DESCRIPTION': ['Green', 'Turquoise', 'Yellow']} + +sg.change_look_and_feel('Dark Green Army') + + +layout = [ [sg.Text('My Window')], + [sg.Input(key='-IN-')], + [sg.Button('Popup'), sg.Button('Exit')] ] + +window = sg.Window('Window Title', layout) + +while True: # Event Loop + event, values = window.read() + print(event, values) + if event in (None, 'Exit'): + break + if event == 'Popup': + sg.ChangeLookAndFeel('Light Green Army') + sg.popup('This popup is using a new "Light Green Army" look and feel theme') +window.close() +``` + +## Displaying the New Themes + +When the above program is executed, you are first prsented with a window that's created using the new "DarkGreenArmy" theme. Notice that you can use the "fuzzy theme matching" to make your code more readable by referencing to the theme as "Dark Green Army" when calling `change_look_and_feel` + +![image](https://user-images.githubusercontent.com/46163555/70284546-59f34280-1792-11ea-9a4a-d3aeeb121381.png) + +Clicking the popup causes the light look and feel theme to be loaded prior to calling `popup` to display a window. This will cause the popup to use the light theme and creates this window: + +![image](https://user-images.githubusercontent.com/46163555/70284679-da19a800-1792-11ea-9701-88989cc93ae2.png) + +## Go Make The World More Colorful!! + +Now that you've created some of your very own Look and Feel themes, go use them to create some nice looking windows! **Anything** is better than a default gray window. + + + +# Author + +The PySimpleGUI Organization + + + +# License + +Copyright 2019 PySimpleGUI.org + + GNU Lesser General Public License (LGPL 3) + diff --git a/UserCreatedPrograms/Code Counter.py b/UserCreatedPrograms/Code Counter.py new file mode 100644 index 000000000..e9ace52b8 --- /dev/null +++ b/UserCreatedPrograms/Code Counter.py @@ -0,0 +1,250 @@ +""" + Code Counter + A program that counts the lines of code and code characters in a code-base + Author : Israel Dryer + Modified : 2019-11-01 + You can find the original repository with the latest updates here: + https://github.com/israel-dryer/Code-Counter + +""" +import PySimpleGUI as sg +import statistics as stats +import matplotlib.pyplot as plt +from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg + +WINDOW_SIZE = (1280, 720) + +def clean_data(window): + """ clean and parse the raw data """ + raw = window.AllKeysDict['INPUT'].DefaultText.split('\n') + # remove whitespace + data = [row.strip() for row in raw if row.strip()] + + # remove hash comments + stage1 = [] + for row in data: + if row.find('#') != -1: + stage1.append(row[:row.find('#')]) + else: + stage1.append(row) + + # remove " multiline comments + stage2 = [] + ml_flag = False # multiline comment flag + for row in stage1: + if row.count(r'"""') == 0 and not ml_flag: # not a comment line + stage2.append(row) + elif row.count(r'"""') == 1 and not ml_flag: # starting comment line + ml_flag = True + stage2.append(row[:row.find('"""')]) + elif row.count(r'"""') == 1 and ml_flag: # ending comment line + ml_flag = False + stage2.append(row[row.find('"""') + 1:]) + else: + continue + + # remove ' multiline comments + stage3 = [] + ml_flag = False # multiline comment flag + for row in stage2: + if row.count(r"'''") == 0 and not ml_flag: # not a comment line + stage3.append(row) + elif row.count(r"'''") == 1 and not ml_flag: # starting comment line + ml_flag = True + stage3.append(row[:row.find("'''")]) + elif row.count(r"'''") == 1 and ml_flag: # ending comment line + ml_flag = False + stage3.append(row[row.find("'''") + 1:]) + else: + continue + + clean_code = [row for row in stage3 if row not in ('', "''", '""')] + + # row and character rounds / for calc stats, histogram, charts + char_cnt = [len(row) for row in clean_code] + + # statistics + if len(clean_code) == 0: + char_per_line = 1 + else: + char_per_line = sum(char_cnt) // len(clean_code) + code_stats = { + 'lines': len(clean_code), 'char_per_line': char_per_line, + 'count': sum(char_cnt), 'mean': stats.mean(char_cnt), 'median': stats.median(char_cnt), + 'pstdev': stats.pstdev(char_cnt), 'min': min(char_cnt), 'max': max(char_cnt)} + + return clean_code, char_cnt, code_stats + + +def process_data(window): + """ clean and save data ... previous executed manually with submit button """ + # try: + clean_code, char_cnt, code_stats = clean_data(window) + save_data(clean_code, code_stats, window) + display_charts(char_cnt, window) + display_stats(code_stats, window) + window['T2'].select() + + +def save_data(clean_code, code_stats, window): + window['OUTPUT'].update('\n'.join([row for row in clean_code])) + return + """ save clean code and stats to file """ + with open('output.txt', 'w') as f: + for row in clean_code: + f.write(row + '\n') + + # update display + with open('output.txt', 'r') as f: + window['OUTPUT'].update(f.read()) + + +def display_charts(char_cnt, window): + """ create charts to display in window """ + + def draw_figure(canvas, figure, loc=(0, 0)): + """ matplotlib helper function """ + figure_canvas_agg = FigureCanvasTkAgg(figure, canvas) + figure_canvas_agg.draw() + figure_canvas_agg.get_tk_widget().pack() + return figure_canvas_agg + + figure = plt.figure(num=1, figsize=(4, 5)) + + # histogram + plt.subplot(211) + plt.hist(char_cnt) + plt.title('character count per line') + plt.ylabel('frequency') + plt.tight_layout() + + # line plot + plt.subplot(212) + x = range(0, len(char_cnt)) + y = char_cnt + plt.plot(y) + plt.fill_between(x, y) + plt.title('compressed code line counts') + plt.xlabel('code line number') + plt.ylabel('number of characters') + plt.tight_layout() + draw_figure(window['IMG'].TKCanvas, figure) + + +def display_stats(code_stats, window): + """ display code stats in the window """ + window['LINES'].update('{:,d}'.format(code_stats['lines'])) + window['CHARS'].update('{:,d}'.format(code_stats['count'])) + window['CPL'].update('{:,d}'.format(code_stats['char_per_line'])) + window['MEAN'].update('{:,.0f}'.format(code_stats['mean'])) + window['MEDIAN'].update('{:,.0f}'.format(code_stats['median'])) + window['PSTDEV'].update('{:,.0f}'.format(code_stats['pstdev'])) + window['MAX'].update('{:,d}'.format(code_stats['max'])) + window['MIN'].update('{:,d}'.format(code_stats['min'])) + + +def click_file(window): + """ file button click event; open file and load to screen """ + filename = sg.popup_get_file('Select a file containing Python code:', title='Code Counter') + if filename is None: + return + with open(filename) as f: + raw = f.read() + window['INPUT'].update(raw) + + +def click_clipboard(window): + """ get data from clipboard and paste to input """ + try: + clip = window['INPUT'].Widget.clipboard_get() + window['INPUT'].update(clip) + except: + sg.popup_error('Clipboard is empty', no_titlebar=True) + + +def click_reset(window): + """ reset the windows and data fields """ + window['INPUT'].update('') + window['OUTPUT'].update('') + reset_stats(window) + window['T1'].select() + + +def reset_stats(window): + """ clear the stats fields """ + window['LINES'].update('{:,d}'.format(0)) + window['CHARS'].update('{:,d}'.format(0)) + window['CPL'].update('{:,d}'.format(0)) + window['MEAN'].update('{:,.0f}'.format(0)) + window['MEDIAN'].update('{:,.0f}'.format(0)) + window['PSTDEV'].update('{:,.0f}'.format(0)) + window['MAX'].update('{:,d}'.format(0)) + window['MIN'].update('{:,d}'.format(0)) + +def btn(name, **kwargs): + """ create button with default settings """ + return sg.Button(name, size=(16, 1), font=(sg.DEFAULT_FONT, 12), **kwargs) + +def stat(text, width=10, relief=None, justification='left', key=None): + elem = sg.Text(text, size=(width, 1), relief=relief, justification=justification, key=key) + return elem + + +def main(): + """ main program and GUI loop """ + sg.ChangeLookAndFeel('BrownBlue') + + tab1 = sg.Tab('Raw Code', + [[sg.Multiline(key='INPUT', pad=(0, 0), font=(sg.DEFAULT_FONT, 12))]], + background_color='gray', key='T1') + tab2 = sg.Tab('Clean Code', + [[sg.Multiline(key='OUTPUT', pad=(0, 0), font=(sg.DEFAULT_FONT, 12))]], + background_color='gray25', key='T2') + + stat_col = sg.Column([ + [stat('Lines of code'), stat(0, 8, 'sunken', 'right', 'LINES'), + stat('Total chars'), stat(0, 8, 'sunken', 'right', 'CHARS')], + [stat('Chars per line'), stat(0, 8, 'sunken', 'right', 'CPL'), + stat('Mean'), stat(0, 8, 'sunken', 'right', 'MEAN')], + [stat('Median'), stat(0, 8, 'sunken', 'right', 'MEDIAN'), + stat('PStDev'), stat(0, 8, 'sunken', 'right', 'PSTDEV')], + [stat('Max'), stat(0, 8, 'sunken', 'right', 'MAX'), + stat('Min'), stat(0, 8, 'sunken', 'right', 'MIN')]], pad=(5, 10), key='STATS') + + lf_col = [ + [btn('Load FILE'), btn('Clipboard'), btn('RESET')], + [sg.TabGroup([[tab1, tab2]], title_color='black', key='TABGROUP')]] + + rt_col = [ + [sg.Text('LOAD a file or PASTE code from Clipboard', pad=(5, 15))], + [sg.Text('Statistics', size=(20, 1), pad=((5, 5), (15, 5)), + font=(sg.DEFAULT_FONT, 14, 'bold'), justification='center')], + [stat_col], + [sg.Text('Visualization', size=(20, 1), + font=(sg.DEFAULT_FONT, 14, 'bold'), justification='center')], + [sg.Canvas(key='IMG')]] + + layout = [[sg.Column(lf_col, element_justification='left', pad=(0, 10), key='LCOL'), + sg.Column(rt_col, element_justification='center', key='RCOL')]] + + window = sg.Window('Code Counter', layout, resizable=True, size=WINDOW_SIZE, finalize=True) + + for elem in ['INPUT', 'OUTPUT', 'LCOL', 'TABGROUP']: + window[elem].expand(expand_x=True, expand_y=True) + + # main event loop + while True: + event, values = window.read() + if event is None: + break + if event == 'Load FILE': + click_file(window) + process_data(window) + if event == 'Clipboard': + click_clipboard(window) + process_data(window) + if event == 'RESET': + click_reset(window) + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/UserCreatedPrograms/Klondike_Solitaire.py b/UserCreatedPrograms/Klondike_Solitaire.py new file mode 100644 index 000000000..18e4688de --- /dev/null +++ b/UserCreatedPrograms/Klondike_Solitaire.py @@ -0,0 +1,601 @@ +import PySimpleGUI as sg +import random +from time import sleep +# import ctypes + +cn = b'iVBORw0KGgoAAAANSUhEUgAAAJkAAADICAYAAAD7jkPoAAANY0lEQVR4nO3aT2wc53nH8ed5Z3ZmdpZckqL+REz1x2gsw5LQFlCuMRAgKAq4aAukZJEc6kOARWxYYm1VjihKHA5XhBTRtEorcFECNpBcClAt0BgwUBRGDTQ59BAbqBPZPriR4Ro2ZJFaccmd3dmdeZ8euKvQtiz30Ee05N8HmMuSMzvD/fKdnXeG6QuMjo46S0tLwsx2ZmbmSKFQ+FWapiQiQkT8RevDvU9Ecs/znE6n00mSZHhubm5tdHTUOXjwIBORjePY3mn9O0YyNzdXOnHiROPUqVNP7ty58/u1Ws0zxhyx9o7bhPuPMDPLhv8cHByUlZWVaHZ29lUioiiKvDiO25+38mcii6LI1Ot1f//+/XZ8fDw9ffr0RH9//3Hf94dbrRYlSULMv1tNRDIiyjSODLYWMxeIyCEiEhFiZiqVSlQsFunjjz9+c3Bw8J2bN2/+ulqtnl1YWPBv3LjRud2odseRbGpq6nHP8571PC+s1+sNY4zPzG73TTNrrS0Wi14QBLd2Au59vc+y0WhQu91uO47T+2ALItIREev7vj80NES1Wq2Rpukz1Wr1hSiKzKFDh3hsbCzfvL1bVURRZKanp+XChQu7ieiP1tfXHd/3X3Ych5IkSR3H8bvDpSUiCoLAKRaLVKvV3iei3xCRISKcR+8DvVMjET0yODjY1263SUSo2Wzm3Z8bEcmtta1SqdRnraU8z/98amrqZSKiKIrcOI5vnd3cTdsOmDmZnJz8g5GRkVdEhJIkyUTEOI7jW2vFGMOe5zlERGma/nexWCRmnonj+Gd3848Ad8eZM2cuiMh3kyRpEVHZ9/3fIyLqdDokIo7run1JkuSe50mxWPz57OzsdyYnJ1+bnp7Oicj0Tp2mt8EbN27kIsKe5xXW1tak0WhYZnaNMUZEyBjDdkOWZVlGRN956qmnvvHRRx/9o4gwlvtvqVarz9Tr9QdnZmYOMfO3sizLrLWZtdYaY7jbhZNlmVuv122hUHg1iqI/ZWbatm1bodcWExEdP368ND8/35icnPzB8PDws/V6PRSRAm2MnJRlWTI0NBSurq6+7fv+t4mIJicnr929/yn4Mpidnd1FRJSm6WsDAwMP12q1xHXdUESIuleg5XK5vrKy8vTs7OyLva54aWnJGRsby8+cOfNMuVx+utPp7Go2m9YYY5iZ8jxf2759e//a2tp/NBqNx8+dO/dW702jKDJxHAsRyRYdNygSEZ6enmYios1XjRMTEwdLpdLf9/f3P7K8vLzmOE6/iJC1NisWi26hULhWr9efq1arF5aWlhyen58vrq6uPhmG4Y+MMcP1er3lum4gIpTnebJjx46w1Wq9UqvVovPnz7++sLDgX7lyxS4uLmaEuL5KuFKpuIcOHTLj4+PpyZMnjwwNDcVBEDx6/fr1xHGcsHvWa5XL5cBau5IkyY8HBgZ+wkREURS9tX379oevXbu27rpuX+9Lfl9fHxHRv77//vsnnn/++d/0Jme39lhhq/U6OHbs2OG9e/fOEdGfrK+vU6+bLMvWd+3a1be8vPx2HMcH+cyZM99i5r8rlUp/mCSJJSKXmUlEbBAEr1+9evUvFhcXP0JgsFmvh0qlsvuBBx74l1ardaQ7tUFElIVhaBqNxn+JyN/wuXPnpN1uU57n1I0r933f6XQ69OGHH5YWFxeTxx57LPjpT3/a2uoDgy+XXheVSiUcGRlpFAoFStM0Z2ZHRMhxHPI8j0yapmSt/fStIhIR2rdvXz8Rke/7+ee+E3xl9brYt29ff6+ZHmYmay2laUocRZGl3838d4IgcFqt1lUi+mMiep827rLjChJuh6MoYtqYb91LRP8WBMEDrVYrJ6LePJkY2nRryVprgyAwIvK1OI5/u+nWAAKD2xEiojiOsziOfysiXwuCwNhPPqbDHEXRxkyaSBYEAVtr32232wvM/GIcx53NGwO4jd4MRUFEfuB53rgx5hutVkt6D1PcioyImoODg8WVlZV/Pnv27F+KbDxCtGW7DveUXi+nT5/+p+Hh4e/evHmzSURFok33LkWErbVkjClFUeRt2d7CPSuKIs8YU7LWkojc+hpmbvO79k5POQJ8nm43n3nc63aRAfy/QmSgDpGBOkQG6hAZqENkoA6RgTpEBuoQGahDZKAOkYE6RAbqEBmoQ2SgDpGBOkQG6hAZqENkoA6RgTpEBuoQGahDZKAOkYE6RAbqEBmoQ2SgDpGBOkQG6hAZqENkoA6RgTpEBuoQGahDZKAOkYE6RAbqEBmoQ2SgDpGBOkQG6hAZqENkoA6RgTpEBuoQGahDZKAOkYE6RAbqEBmoQ2SgDpGBOkQG6hAZqENkoA6RgTpEBuoQGahDZKAOkYE6RAbqEBmoQ2SgDpGBOkQG6hAZqENkoA6RgTpEBuoQGahDZKAOkYE6RAbqEBmoQ2SgDpGBOkQG6hAZqENkoA6RgTpEBuoQGahDZKAOkYE6RAbqEBmoQ2SgDpGBOkQG6hAZqENkoA6RgTpEBuoQGahDZKAOkYE6RAbqEBmoQ2SgDpGBOkQG6hAZqENkoA6RgTpEBuoQGahDZKAOkYE6RAbqEBmoQ2SgDpGBOkQG6hAZqENkoA6RgTpEBuoQGahDZKAOkYE6RAbqEBmoQ2SgDpGBOkQG6hAZqENkoA6RgTpEBuoQGahDZKAOkYE6RAbqEBmoQ2SgDpGBOkQG6hAZqENkoA6RgTpEBuoQGahDZKAOkYE6RAbqEBmoQ2SgDpGBOkQG6hAZqENkoA6RgTpEBuoQGahDZKAOkYE6RAbqEBmoQ2SgDpGBOkQG6hAZqLtdZCaKIu+u7wnc87rdfKapWy8wsxhjyFrbiOO4fVf3Du4LcRy3rbUNYwwxs/RevxWZiBSazWYeBMHhKIp+uGldvqt7CveaW31EUfTDIAgON5vNXEQKvdc3j2Rus9nMwjB8SEQujo2Nme6KiAw+V6+PsbExIyIXwzB8qNlsZszs9n7HENGtYY2ZudPpWCK6evny5fzu7zLcq7q9XO10OpaZNw9MYj71AtFGeEEURS4B/B91ewnoU1/8mZmN7/tkjCERIWb2kiTJC4XCXhF57+jRo34cx/bo0aP+1uw6fJlt7kNE3isUCnuTJMmZ2RMRMsaQ7/tkkiR5JM/zN0qlUk5EHRExIuKEYfj1kZGRX1Yqld2XLl1K5+bmSlt9UPDlMTc3V7p06VJaqVR2j4yM/DIMw6+LiCMihog6pVIpz/P8jSRJHjHVavUXzFwMw9Cx1raMMZxlmSRJkhUKhW8eOHDgpWPHjh0+ceJEA6EB0UZgJ06caBw7duzwgQMHXioUCt9MkiTLskyMMWytbYVh6DBzsVqt/oLn5+eLq6urT4Zh+CPHcYZXV1czx3FcIqI8z5MdO3aErVbrlVqtFp0/f/71hYUF/8qVK3ZxcTGjTRcNcN/jSqXiHjp0yIyPj6cnT548MjQ0FAdB8Oj169cTx3FCZqYsy1rlcjmw1q4kSfLjgYGBn5g9e/a0Z2Zm5tbX1+eMMVc9z+uIiBARua4bLi8vrwVB8GhfX99zExMTB8fHx9PFxcUOEUkURYYwj3a/4+7nLIuLi53x8fF0YmLiYF9f33NBEDy6vLy85rpuSESU57kNwzBg5muNRuPCzMzM3J49e9pMRPTEE0/0vfDCC+uTk5NP79q1a355eTllZp+IqFtnMjQ0FK6urr7t+/63iYgmJyevbdlhw5aYnZ3dRUSUpulrAwMDD9dqtcR13bA7Jgkzd8rlcrKysvK3s7OzLx4/frw0Pz/fMEREjuN0iIiMMZ61loiIeqOZiJDjOOHa2hoR0UPW2g+yLPsgiqL9RESVSqUgIozl/lwqlUqBiCiKov1Zln1grf2AiB5aW1sjx3F6gZG1VoIgKKytrf312bNnXzp69Kg/Pz/fIOrOaVy6dKkdRVHQ6XT+YX19/fEdO3b4YRiyiGTWWsvMZK0Vs8F1XdclolcvXrz47u7du7/HzILl/lx27979vYsXL75LRK+6rusaY1xjjLHWSrcLKyJZqVQy/f393G63O8ws27Ztc3ojYG/CVd56663O5cuXW5VK5WcPPvjg/zQaDeP7/suO41CSJKnjOL6ISJqmlogoCILf74501ampqb/qBmsVRmnYGoaIrIgcJqK9vu9Tq9XKiYiY2RBRnmVZq1Qq9eV5bhqNxp8xc14ul98UEZ6enm71NvSJL+2jo6PO5ttJU1NTj3ue96zneWG9Xm8YY3zu3pPqjXLFYtELgqA3mXtXjh709T7PVqtFzWazbYwxzOzyxnf0ThAEhaGhIarVao1Op/NMHMcvfN62PlNFFEWmXq/7+/fvt+Pj4+np06cn+vv7j/u+P9xqtShJkk/EJCIZEWU6hwpfAi5vutltrbXDw8Pmxo0bbw4MDLxz8+bNX1er1bMLCwv+e++9Z8rlchrH8SfOaHccenqTbqdOnXpy586d36/Vap4x5kjv4gC+epg56+/vf6der4/HcfzvRBsPK97pGcQvPL+Njo46S0tLwsx2ZmbmSKFQ+FWapr2rT5wfvzqEmTkIAmo2m0fiOH5jbm6utL6+3vz0yPVp/wuxtdSMN2ZiygAAAABJRU5ErkJggg==' +c0 = b'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' +c1 = b'iVBORw0KGgoAAAANSUhEUgAAAJkAAADICAYAAAD7jkPoAAAv0UlEQVR4nO19eXgVRdb+23375l7IQgiEJayyi4RtQLYfhk1cAJEMH4iIfiiC84GA34zOPDoM4Dg6zOiAyiKgwijjCATnJxAW2QSEoIiQkLCEfYkQNknIcpPb3ef7IzmV7rvk3gAJgfT7PPe5ye2q6uqqt0+dOnVOlQQDVqxYYRsxYoTG/69ataZDtVBnT8kmdbIrSgwRhRORxNclSSIQJAA6QHnwAdIBHQTZ18WyQJZyoRMFn0GCDiqqwK3f/bZAkogIkkSkF0hAgQRJ0u90pTxQ3FKhBMmr0bj+0EklSJlud+ERl9v1/Yhhww5wGk8OAYDkeXH69OnKgz16jQmtXn1cRER4l/r16oWEh4chxB4CSYIXCIAEyec1ANB1ApWFG34gSZKhtsGh6N6VrRsZZXyYCkWA/iLArarIyclF5qVMd1Z29v6cnNxP825kLRkxYkShJ9EkoIRgCV8n9qpVI+KDFi2bd65ftw5sNhsA6GAu3VncOlMt3G5IAGRdJ1zMvIT0Y8dTsn65/vKTTw7eYSSaxP98vXbd+Pp1686PbfeAzel0qABkIqoc44yFSg2paNTXCwoKlOSDafrFzMzfDB38+CLmlgQA69ZtHN64SeOVbVq31G02GxGRrTjzHa28hbsHRdqapGmaJh1JPy6fOn36hSGPP/rpihUrbNKmTZtqQLanxvXu2cBut+tEZLPIZeFmUEw0XVVV7Pnhx8KsX3IeGDz44VNyTn5+35iYeg3tdjtZBLNwK5AkCUQkK4qi39+mjVOXtQkASJYlW6uIsHCCpVhbuH2QIiLCyOkI6Q0UmUUUSHd85mjhHkHxSCgpNpuk2Gy1pk+fLis3U5Cul9ieJEmyJggWvFDMCwIABZKkBcrgCVm2LBsWSgcRgW3wCumUE2wmSZKQlZWF559/Hrm5udB1HS+99BLi4+OhaRobby1UYbDVnojEKmDQw6Wu67DZbEhLS8NXX30lfg8PD0d8fPztrquFewhBj3u8/rh3717YbDY4HA7YbDYkJyejsLAQNpvttqxRWrj3IANmRd4fWLn/4YcfoGkaHA4HiAinTp1Ceno6AFgks+ATxSQrnRxEBJvNBk3TkJycDACYOXMmYmNjoes69u7di6JyKqvHg4U7iaCGS5ZQ586dw7Fjx2C32zFu3DgMGDAAkiRh9+7d5VpJC3c3ykSylJQUFBYWon379ggLC0NcXByICHv27IGmaVAUxRoyLRghAWUkGQ+LPXr0ABGhU6dOCA0NxZEjR3D69GlTWgtVHRJkwD1jxozg/MXY+Mok69y5MyRJQkxMDGJjY6GqKn788UcAll5moQhFnsxSviRJgUlGRJBlGTk5OThw4AAAoE2bNoJMnTp1AgDs2rWr/Gps4e5EcTyILAVYHGcyHT16FJmZmYiMjET79u0hyzJkWcZjjz0GAEhKShKzUAsWjFA0TS8oLQHrWPv27QMA1KtXD+np6cJudvHiRciyjNTUVJw/fx6NGjWCruvW+qYFAYWAPCpyJfMp0ZhMSUlJAIAjR46gc+fOXulcLhd+/PFHi2RVHURAkfNiydqlFMBPR5ZlEBH2798PAOjduzcaNGgATdOg6zrcbjcOHTqE48ePY/fu3Rg2bFj5P4iFSg+ddBQLr9IXyFkiZWRkID09HbIsY+nSpWjWrJkp3dKlSzF27Fh8//33AGDpZRZMKHVM03UdRISUlBTk5+ejSZMmqF+/PjRNg6qqcLvd0DQNHTt2BAAcOHAAmZmZACx7mYUSyACgqb79FtmHjE0XcXFxqFatGogIiqJAURTIsozY2Fi0bNkSN27cQFpaGiRJgqqqFfYQFio3SpVkdrsdly9fxpYtW6AoCpxOJ1RVNS0fSZKEnJwc1KtXD4qiIDExEYWFhbDb7RXyABYqP7xIxuQpKChAv379UKdOHWzZsgWqquKjjz5C06ZNxRISUOT6U7duXezcuROqquIf//gH6tati//85z8AAE0rs3e3hXsMfhV/u92OZs2aITQ0VMwkJUkSbtY8KXU4HOjTpw/H3MFmsyEvLw+KclMxKhbuQXgxgckjyzI+/vhjvxk1TYMsy+jQoQM2bNjgN50107RQqrjhoc5oSmNpxeThGainuc0KlbPAKFXxZzLxOqUkSZBlGZqmYcKECTh9+rTpd+PHIpgFRpkCSTRNgyRJePHFF7Fo0SKMGjUKeXlFGyxaLj4W/CFokrHp4vXXX8eSJUvgdDqxZ88ePP3002LpyTLAWvBAkauPrusBxzW32w273Y558+bhnXfegaIocLlcsNvt+PrrrzFx4kQRaGLBAlC8xSuhACiSZHnFQ51PsqmqCrvdjjVr1uDll182kcntdkNRFMyfPx/vvvsuFEWxLP0WAIAkSYIOKiKZoutuf8OcrutQFAU//vgjnnrqKfGbMT0HkLz66qtYvXo1FEWx9DMLACC2q5Z1P9NANr6eOXMGQ4cORV5enjC4GkFEIu2YMWNw5MgRSJJkEc2CgF/Fn4nzl7/8BT///DPsdrtf4vA+GdnZ2Zg2bZpPMlqouvBLMja2Hjx4ELIsC4IZjazG5SU2yJ48ebKoYMsz1kIxSpVkABAZGQld12G324X3BREhJCQEmqaZ3H4AoFq1agDuTX8yVg0slA0yApgeXnnlFdhsNrhcLqiqiujoaMyfPx8xMTF49dVXERUVBVVVUVBQACLC888/D+DeJBmvbFhEKxv8rl3yVlADBw5EUlISli9fjtDQULz44otwu92YNGkSnnzySYwfPx4LFiyArusYMmQI+vXrd8+FxvEL43K5cPbsWbRu3doKlikLvvp67dC0Q0eIiHRd18kTvn577733CAC99tprQaW/2+F2u4mIaPz48RQZGUknT54kIiJN0+5ktSolivtfVVWNNm7e8i0QxE6LbI5g+5jNZkPfvn2xZMkSEUnOa5qSJN1TEgwoWU5bsGABFi1aBAAYPnw4du3aBbvd7tMDxUJxtFJZtvNkzwpGp06dxPYEfP1eBBuad+7cKVY7ZFnGTz/9hP/5n//Bp59+KkhowT9uih26rkNV1XtaAWbb388//4yRI0eKmTQvpS1ZsgTz58+3ltKCwE2RTJZlEal0L4KKzTSqqmLkyJG4cOECbDabeKnYBX3y5MnYvn07FEWxnANKwb3JkluEkUTfffedF4mYhJqmYeTIkTh37pyJhBbMsEjmAdaxFi5ciAULFvgdDnk4zczMxPDhw+FyuSyfOj+wSGYAK/rbt2/HpEmTAvrIcfoffvgBL7zwgkhvEc0Mi2TF4CHy9OnTGDFihCCLkTC+TDQs+b744gvMnDnT0s98wCIZzLtJDh06FJcuXfJaPmLPEg4FNIKJNmPGDPzrX/+yZpweqPIkI4M/3KhRo5CSkuIljTiGoUmTJnj88ceFPmYES8Lnn38eO3futIhmQJUnGZNj0qRJWLt2Lex2u4kcvJLBQ2JiYiK6d+/udWAZD62FhYWIj4/H8ePHraGzGFWaZDzMzZo1C/PmzYPdbofb7TalYWV+9uzZ6NmzJ3Rdx4oVKxAdHe21SM4S7sqVKxgyZAiuXr1qmTYAyHIVnQoxwZYtW4Y//OEPPoc3/m3s2LGYNGkSVFUFEaFRo0b497//DcA7Up5nnEeOHEF8fDwKCwsB3JuuT8FCdhPlqpoK+IlWuhfBBNuyZQvGjh3r0/Rgs9mgqiq6deuGBQsWiOGRf+/fvz/mzJnj85xPLn/Hjh0YM2aMiLqvqkSTSa9aT86SJjk5Gb/+9a99miqYFPXq1UNCQgIcDodpdskSbvLkyZgwYYLPRXIOJVyxYgWmTJlSpfWzKqWTGW1hgwYNQlZWlk9ThSRJsNvtSEhIQMOGDYUrkyzLQsdi6Tdv3jz069fPJ9E4KPqDDz7A22+/DUVRvHS+qoAqQzKjUj5o0CBkZGR4WfTZ2KppGhYvXoxevXpBVVVBvOTkZHz55ZeCmOwCtWLFCrRs2RKqqvodOt944w0sWrTIa/ZaJbBi1df9kg+mGr0a7zlomka6rlNubi716NGDAJCiKISiI7PFx263EwCaNm0aERV5xOq6TqqqUm5uLrVp04YA0LZt24iISFVVUlWViIgOHz5MNWvWJEmSSJZlU7mSJJHNZiMAlJCQIMq+F8GesYVuN23YtPnbKkEyXddJ0zRSVZUeffRRvwTj38aMGUNEJQRjMowbN44AkM1mo5iYGLp06RLpum5Ks3nzZlIUhWw2G0mS5EU0WZYpJCSEtmzZIu5xr6HKkYylEBHRU0895ZdgLGX69OlDbrebVFU1keezzz4TeTntY489RkQlROHvf/7znyKtJ9FYwoWHh9PevXtN+e4VVCmSGUkyfvz4gARr27YtXb16lYiKhlcOEklNTaXQ0FCSZVmQhMuZOXMmEZUQpbCwkIiI3nnnHdPw64toderUoUOHDhERiRfhXkCVIZmRYL/73e8Cdnj9+vVNEUg8xObk5FC7du1MZOShj4mWmJhIRCVE4ftOnjzZ7325rCZNmtDp06dN+e92VBmScUfPmDHDrwSTZZkkSTINXZ5EGTFiRKlDnyRJVKtWLTpx4gQRlRCU8wczRLdp04YuXLhguv/djCpBMu7gd999128HsxKuKApt3LjRlM9zyFMURZQxbdo02rhxI8myTDabTfzeuXNnysvLEyRjSVhYWEgPP/xwwMlGp06dTEP13QwjydZ/s2n7PUcyJsiCBQv8SiCjOeGLL74gIm/lffXq1ULaMBG6dOkiyp85c6YXAUeNGmUqgwmXnZ1NXbp0CUi0Hj160I0bN0TeuxVMMreq0vpvNq8XJDuQctCY4K4EE4Bnd/7MCNyp8+bNM+XjoSo1NZUiIiKEtLLZbFStWjVKS0sT6XVdp4ceesiLiH/+85+JyEw0IqLMzExhYzPqdp5E69evH+Xn5wtJeDfCGEG+/pvNawAAq1Z93e+n/cnGBHcdmCjLly8XksqTYMbOfOutt4jIW+pcvXqVWrZs6UWeRYsWEVERETnt6dOnKSoqSsw6Oe3KlStNZTN5T506RY0aNQpItMcff1wQ+W4kmpFkGzZtXntPkIw78+uvvyabzSYUcs9O5Fke79/B+diWpqoq9e/fX5CAifD000+b0hOVEOerr74SBGGyVatWzWsiwd8HDx6k2rVrm2a2vog2bNgwYUa52/rkniMZd/yGDRvI4XD4XNIxEuyll14S+fhZuYwXXnjBRBie+d24ccNnZ3O+3/72t175GjZsSOfPnyeikiGT03///fcUHh4ekGhPPfWUyH839cs9RTLutG3btlG1atUCdtozzzxDRCSs+cYy3nrrLUFG1sWqV69OyclF7cJEMQ5hLAE1TaO+fft6ScAuXbpQbm6uiSR8v61bt5LT6fT7UnCdn332Wa86V3bcMyTjztq1a1dQUsHX8ONrycg4Mfj8889N6YxgonF5P//8M8XExIh6cBlPPvkkEfkm9po1a4Ia3l944QWvMioz7gmScSft3buXIiMjAxLs0UcfpcLCQtNSkb8Fbc4zdepUUzq2feXl5VFGRgYRlRCN9a3t27cLSWYsa9KkSaayiMwTFX8zYSPRfvOb34h7VfY+uutJxh114MABoUCXNlPr06cP5eXlmYY5oxIeGRkphiwup3///sJrw1P6DBs2jOrWrSuWoDxXCObNm2eSikySv//970RUQi7j30uWLAmKaJMnTxb3qsz9dFeTjDsyLS2N6tWrF5BgPXr0oOzsbCIyD29EROfPn6emTZsKKciS8L777qPLly+bSMn3ffPNN8U9WrduTZmZmaYyOd1LL73kc/hdtmyZKR1RCdHmz59vyuPvmX7729+KMiprX921JGOJkZ6eTg0bNgxIsM6dO9O1a9eIyFt/ys7Ops6dO5ukhyzLFBoaSgcOHDDdjwmxatUqL9tZt27dKCcnRxDSaAoxTgTYbqcoik8/Mv6bt0j1tSpg/P2NN97wKqMy4a4kmdGYydLHF8H4t3bt2gkpw3mZAG63mwYOHOhT0qxatYqIvI2o+/bto+rVq5sUdKO+ZzTQ8vfly5epefPmJkkpSRLVqFFDzFiNi+F8zz//+c9BSTTPlYXKBCaZq6CANmy8C0jGHXH+/HmTJd4fwVq0aCHsU0aCcWeMGTPG1Fn8/de//pWIvJeDzp49KySn5+SC844ePdp0P/5OTk6m8PBwkiTJZKpo3LgxnT171nQfYx1ff/11vxLN+FL84x//ICKznlcZcFeRjDvg0qVLPn26PAnWoEEDOn78OBH5lhKefmXcWWwi8LWw3bFjR7/3NZZhVMqN37zQzum4nA4dOtD169dNz2kk2tSpU0slGpezePFi0/0qA+4aknHDZ2VlUdeuXf02OEuHWrVqUUpKChH5Jtjf//53nxKsf//+Qo8yuuh4Dqu+CMYfJi17ybJk4e85c+b4vTebVrjdje7iEyZMCIpoK1asMD3rncZdQTLuaJfLRf369SuVYJIkUVhYGCUlJRGRb4X6888/N0kRo7Pg1atXvRR3IqKnn346KIJ5DmHz588nohKC+fOS9eUe5ItozzzzTKlEk2WZ7HY7bdq0yev57xQqPcmMDTx8+PCgGvibb74hIt8E27hxo8nYapR8R48eJSLvmeTEiRNNhAjmY5Qsy5cvF+UZh8AhQ4aYnofL/9///V+v+hsjrB5//PGAL1pERATt27fP9Dx3CpWeZJ4dHWio4A41Kr/GWSEr3twZbEowxk0a71ua0h0M0Zj4mzdvFuUyYW7cuEGdOnUySVO+z7vvvuv1HCxdc3JyqFu3bkHppBwvcCddhCo1ybij//a3v5UqSfwNTUQlpDl9+rRpLdGYb+nSpab78bfR3bqsBDNKFgAUERFBP/30k6gTd/qZM2f81suXbsX5Lly4QPfdd19AonXo0IGys7NNS2gVDSPJ1m+sRE6LnkbPQHai6dOnm/IRlYSx3bhxgzp06OBTYnjmY4J+8MEHpd73ZogWExMjAkyMkeY//PCDye7GEtDpdNKePXtEegb/nZKSQuHh4aYVCl9tM3jwYJHvTvRn8T3dBYVuWr9x85eVgmTGRgwLCwvYiEafMIZR9xk6dKgpPX+PHDlS5DOmX7x4sSDkrRLMU7K0adOGLl++TEQkZq1ERAkJCaa6GUPzPG1oxmc1mkRKW+f0pedVFCodyVhfycrKolatWgUcDp544gki8n5LuTHfeOMNn53Xrl07ysnJEXoOS7Bly5bddoJ5vhQ9evSg3Nxck3mEyGzdNz5j165dKT8/38tZkevM6kSg5SdPtaCiwCTLdxVUDpJxA/zXf/2X34ZjonTu3Fl0lrGeLAn/85//mMpgRT80NFQEgfDSElHR0GycFNxOgnl2+KBBg8Rs0Ui0+Ph4E8E8HSw9CcL/P/vss37bi5/b6XQKvbAi9TMmWV5+Pq3b+M2dJRmTw+ge44tgkiRR7dq16dSpU6Z8RCWNd+LECYqMjPS5lYDxjeZOSkxMFF6w5UUwzyFs7Nixoh6sP16/ft20xmlMz+5BnmqBqqrkcrlEmJ0vyc9ltWrVSkwEKqpvKw3JjOFnTqfTb/gaN+DatWuJyHeDu91u6t69u6nB+Zvdl40E27ZtW6muz+VJtN///veiPtwGSUlJJlseG3dlWRZeG/5erKioKJHHnxQ17lJUEagUJDO6xJRm/+FGmjJlChH5Hzpee+01U3omTvPmzcVbbHR2jIiIMKWrqA/X78MPPxT194wxMD6DJElUr149+vnnn73C44wu3Nx+pRGNw/QqwlBrJtmm5XeEZP7WEz3FvSRJ1KJFC8rNzfVS9LmxNm/eLMrgN5r95nfu3ElEJQpzRkZGqXGP5f0xSubVq1eLtmA9zZ80fvjhh8WL6Wuy8/vf/97vM7H6UL9+fbpy5UqF2M9KSOaixA3fLKlwkrFucPLkSbEdk683kBtszZo1RGR+A/mtvnbtGjVu3Ng07HG+P/3pT0RURDBVVamgoIB69uzpl9QV9eFODw8Pp4MHD4o6EhW5gzscDp9+a7Nnz/bZDvxsbdu2NZHYlzQzxgmUJ4wkW/fNpo8qnGT8gDybLM1c0b9/f1MezzL++7//29SInK9jx45CQnAHvvjii3ecYJ7P16pVK/rll19MJhWO4eQ0/AKFhYXRmTNnvIZNbovExERBYn8SVFEUOnjwoGl9uDzAJMvNy6fEDd8srVCS8YPt3r3bL8GMDbV9+3ZTPuPf27dv9yqD861fv56IiFwuFxGV7I1RlgXv8v4w2YcOHUpEJFx+Ll++7KXMc9px48Z5tQdRyUSA98It7cUdPny4zzJuJ4x2snUbKlgn48YYNGiQX6nCjdGtWzdTHs8y4uLiTOmZYB06dBCKvq7rlJ6eLlYRyttUcbNEe++994iIqKCggIhK3IKM9j5JksjpdPpcAGfdzGhY9nU/nrXy7o7lpZv5svhXyBbrevF25Glpadi4caM4jMEfnn/+eZGPwUcA7tu3D9u3bzeVwecbjRw5UpzoBgAvvfQScnJyxEEPlQn8PH/84x9x6tQpKIoCIsLo0aMhSZJ4NiKCzWaDy+XCsmXLAJjbhbd0HzRoEGrXri3OHPAEn6SyaNEirzLKGxVGMgD47LPPoKqqiQgMbtjq1atj8ODBRZUzHI7F6ZcvX+51jTukX79+AAC73Y6NGzdi69atAU/fvVOg4jM28/PzMWfOHNEmHTt2RNOmTcV1TitJEr766itBOga3W2RkJHr37g0AXmcJACV9kJCQgLy8PEHqikCFkIzfotWrVwPw/RZxg3bu3BkxMTFeJ7Bxw23btg1ACelYStWsWRMtW7YU6RctWuR1uFZlg158zuaqVauQl5cHSZIQEhKC9u3bA4Cou67rICKkpqbizJkzkCTJ1IZUfGxPXFxcqfeSZRnnz5/Hd999J36rCJQ7ybgh09LScPToUa8GYnCDduvWTeTzLOPq1as4fvy46Trni4mJQWRkJAAgOzsbu3btEmch3SyMJDUS3ngEzq2QmJ8hIyMDqampoqwmTZqI+wAlQ2ZhYSFSU1PFb571jI2NNZXrCVmWIUkSvvnmG68ybjMkIh0gqg5UEMkAYM+ePV6i3hfatGnj99rFixeRlZUFwCzJACA0NFQQ4dy5c7hy5cot150MB3t5Sg5d18XhX7dCNG6PEydOiN+qVavmlY7vcerUKVEHz2sNGzaEoijipfT3PN9//z0AeB1zXQ6wARV4ttL+/ftLvc6NVq9ePb/XsrKy/HaqsdHz8vJEQ9/M28qSqlatWlizZg2Sk5Px0EMPASjqGIfDgc8//xxffPGFqO+tdti1a9fE3+5SDvm6fv26z/oCQI0aNXwSlMEvyvHjx5GTk+NTN76dKJ7RQwmU8FbBje/rDTSCf3c6nVzBoMrnfL/88os4lS0yMlIcF3gzROOZ65/+9CcxCXn11VexY8cO6LqOZ599Fs888wwAoHHjxoiLi7vlzoqIiBB/nz9/3m+60u7jcDhgt9sD3uvy5cvIyMhA69atb1kSB4Nyl2RMsszMTAD+G4kfNDs72ysdX4uIiPAiDf999uxZnDt3DgDQqFEjNGzY8KYUfz4Brm7dunjuueegqip0XRf6HgA8+OCD0DQNeXl56NWrFwYNGgRd172OIgwGrDM+8MADAIpOlUtJSQHgW7cKCwvzW5bL5SpVCvKMVdM0XL58WfxW3qiw4TI/P7/U60yGs2fP+k1Tp04dhIeHm9ITERRFQWFhIbZs2QKgSBo+/vjjJjNAsLDZbCAizJw5EzVq1BCzMr4v35tP8SUivP7666IuZb0XAMTGxqJ9+/YgIqSlpeHYsWM+Z5BAkeT0BF+7du0acnNzg7o3v8wVgQojWbAShXU3Y3rWHaKjo9GiRQuv69wZc+fOhaZp0HUdr7zyCpxOp5cppDQoxYeePvLII5gwYYLp6GfjGZV5eXkAIA5Y7datG5577jlomoaQkJCg7sV6HxFhxowZYqbKz+A5QWLjLUs8TxsiEeHIkSPiXM9AI0ZpEu92o8JIFqijmSg7duxAQUGBl1LKluz+/ft7lccNm5KSIgybLVq0wIIFC6DruhjKSiM62/KaNWuGzz77zEsKGhVz48yVh9f3338f7du3R2FhYanDpiRJUBQFsizD7XZj0qRJiI+PhyRJSEpKwtKlS71WRJiAbdu2RatWrbzqxnrVt99+K+7hD9ympQ27tx3lvXbJZfbq1avUtTUY1iA3bNjg5S3Aa20pKSmm7Zg4r9HbgBfJiYg++eQT4ahoTGfcRJg/xpPbjJvb6bpOCxcuFOl423WunzE+sk+fPl7rqkrxySWeXhJ/+MMfTDsINWnSxNQO/OF1zL/97W+iTsb21Yu3GmV/udIcMrnN9u/fb6r7be7vig3u5QYZPXq0qcF8fbhjBg4cSET+3Xz8HYxlXEz+97//LfIdOXKEJkyYQPXr1/e6Z0hICDmdTqpbt67PvcM8XYuAop0WjVtTEZk32/v1r39NACg0NNTrfmFhYTR06FDhZUJUFO3O0VqeBOGXqUGDBnT9+nWvQBpu348//jjgS8wEq1mzpjjL6Xb3+R0l2fvvvx+QZMZG8uXXz56dGRkZVKdOHZ+NapRuL774Ih0+fNhUnyNHjtCmTZsoMTGR1q1bR4sXL6auXbv6POTUKCWM+5RJkkT79u3zKW11Xaf8/Hzq2LEj9e/fn7744gtauXIlJSQkUFJSEuXk5Ij0GRkZNGPGDL9bxBs3c2FvWs/7sQNngwYNAsYtcFv16tVL5L/duCMk4wdJS0sLKr6RO7FRo0YiMNaXZNmxYwdVr16dgCJfMc+hk/+vVq0aDRo0iGbNmkXr16+nvXv30q5du2jp0qX03HPPUf369enbb78lIv9xBEY3Gk//Ls88XL+MjAyKiYmhnj170vvvv0/bt2+nffv20datW2nu3Lk0YsQIqlWrlpeq4EkIADRr1iyvdjAGKPORiYHcyrnub775ps+63w7csb0wmGi9evXy6ybsSTQAFBcXR/n5+UTk+9iZXbt2iS0+uRGNUT/B+PJzkIXnjoUsxVwuF91///1kt9spJCREfHvGcxph3JIg0P2N9WX9jZ/f4XCIg8Z8STAi70Ca0oZKqXhH7vT0dFO/3E7cMZJ5hucH0/mcZsCAAUJ/4JhFopJGv3TpEk2cOFFINWOjsuRxOBwizlKWZXI4HASA5syZQ0S+t8Tk8n/zm9/4rWPz5s3p+vXrpR6Lw4eKsf8+7/zDdfI1IQBAjzzyiGnTFiKz9CIimjJlStDt6bldQ3l5x/oiWbkvKwEQi7bDhg1D9+7dsWfPnoB+Xmwr2rx5M3r27ImPPvoIffr0EdeAIttVdHQ05s6diylTpmDlypVYt24d0tLScP36dVM6AMJzoqCgAOPHj8eUKVOgqqrPpRi2NXXr1k14RVCxPcrhcMDpdEKSJLhcLtSoUcPLLsU2txEjRuDYsWP44x//CLvdDrfb7dOSb7PZ0KxZM/Tt2xejR48Wa6Vut1uYNGw2GxRFwbFjxzBx4kRs2rRJLJ+VBl4lcTgcePPNNytkKcmEivbx379/P9nt9qD3nzC+pePGjRNDlBGekujChQv0448/0saNG2nNmjWUkJBA06ZNo6ioKCEdjdt4lheMkmfcuHHiebp3706LFy+mf/3rX7R8+XLasGEDHTp0SKgGRL736j9//jxNmzZNmGSCDe3j+AbegLkCfPzv3P5k/HAffvihT4Xd38c4nNjtdnriiSfon//8Jx0/frxU5fXKlSu0evVqGjt2rDhg4v7776dr1655Rf74ArdHdnY23bhxg27cuEHZ2dmUl5cnAlUCtZkxZpJ3W6xZsyYNGzaMli9fThcvXvSbV9M0OnPmDCUkJNCYMWOoZs2aPl++YAg2ZMgQUx+UF3yRTFq16ut+9zVruqVTx/YVIkZVVYWiKHj11Vfx7rvvQlEU4ZcVCJ5DbEhICJo2bYrGjRsjOjoaDocDBQUFyMzMxJkzZ3DmzBnTUNKkSRNs3boVzZo1C7jcxMPTO++8g/nz58Nut4t6OhwOyLKMTp064csvvwxYFj9bfn4+HnvsMezYscN0vWnTpmjatCnq1q2LatWqwe1248qVKzh37hxOnz4tlrG4DdhTNhB4eO7WrRs2b96M6tWrl7u3cDGHtILCQtu33+5MfPSRAYOxatXX/fYfSDGysNyZzm8Tz4xQhjfTaLEPJj0r+a1bt6Zjx44RUeC3mSVcampqwFA646m+wZSZlZUlNlzmMzoDPQM/b7ARV7LhrKi4uDgxcaqI3X18Dpd34qB7I9EWLlwoLOO8xUAwDcmE4wblpRv+hISEiHRDhgzxOqWktLpxZ/Tt21dsw2S3200fh8NBISEhVLt2bTHkBepEvu5yucQW6gCEacRYf26LsoTysQmE/x83bpwY1itq+6hKQzKGcZfFAQMGmMjDU/tgG9losuDfateuTR988IG4XzANzXX6y1/+EnTnxsXFkcvlCkrfMbbxypUrxdZRRolVlheNXzKjZG/evLnYg9bznuWNO2bC8AfWsWJjY7Fp0yYkJCRg9uzZ2L17t0mXChSwwZ4WrK9FRUXhueeewyuvvIJGjRoJV+xgXH7Y+0NRFIwfPx7Z2dnIzc31MjvIsozQ0FDUqFEDNWvWRG5uLqKiogLqtWxO0HUdw4cPxyOPPIIFCxZg4cKFOHnypFf7+CuLioNkjPVq0aIFxo8fjwkTJiAiIkK4B93xiK07KckYnsbMHTt20Msvv0z3339/0G91jRo1aMCAATR37lxx8CnRnd/XvjQY65aTk0MrV66kp59+mho3bhy0JGvSpAmNHj2aEhISKC8vz2fZFYlKJ8kYLGF4Rte7d2/07t0bmqbh6NGjSE1NRXp6Os6fPy88Om02G6Kjo9GkSRO0bdsWsbGxpiAUfosDRUf5A8+CgwHHFpQVbPDVdR2hoaEYPnw4hg8fjry8PBw9ehRHjhzByZMnkZmZCZfLBaAokqlu3bpo3rw5WrdujdatW5uCR271ucsDlYJkDG4YNhUoioK2bduibdu2QeXnYZNdo28WfO99+/bhzJkzXp6m1atXF86KNWvWRNeuXW/a/MOu3Ew2Lr9Tp07o1KlTUGUYt2uoTORiVCqSMbihqHgZJ1CkM+tb/LkV8L2uXLmCAQMG+AxB87x3UlISunXr5tNtOlgw2YDgn5v1rcpILCMqJckYbDisgCBUAXbV/utf/4rr168jJCTEa42VpZrNZoPb7cb48eOxd+9eIZFuVdG+E89dnrg3nuI2gYfaEydOYMGCBcIPX9M004eHZbfbDUVRkJKSgrfffrvSbu5yp2GRzAA2dUydOhX5+flBBQbzEPn222/jwIEDwuPEQgkskhWDZ5NLlizB2rVrg5ZKTEIeNnnSEoicVQkWyVCih6Wnp+OVV15BSEiIKYA30Aco2iJg7969mDNnjljEtlCEKk8yVtQvXLiAAQMGICsrC4WFhVBV1UsXK+1TUFAAAPjd736HpKQki2gGVOrZZUWAigNlU1NT0bNnT7jdbmRnZ0PTNLhcrlKXdZxOJ2RZhtPphNPpREREBMLCwkyBwBYskgkzwcMPP4yHH364XMqu6qjyJGMYjZ8svQLZu1i5Nyr5LBktgpVA0YlkCZV3X9WKws1Yzu+4d8NdAjnEroQWN64157ZQLrBkuoVyh0UyC+UOi2QWyh0WySyUOyySWSh3WCSzUO6wSGah3GGRzEK5wyKZhXKHRTILARHsBi/+YJHMghc8PXs9o9DLSjiLZBZMMB4vrWkadu/ejYEDBwrXco6D4GCaYGCRzIIAFZ9Hqus6CgsLYbPZULduXWzatAkXL16EzWaDLMsoLCwU7kzBSDWLZBYAlERqffjhh2jXrh3atWuHl19+GTExMWjWrBkGDhyIrVu3Ii4uDu3atcMTTzxR6knMRlhOixZMm0BPnjxZ/D537lycPHkSUVFRWLhwIQ4fPiwiuI4dO4azZ89i7969AfcMsUhmQQx5GzZsgCzLYkdtWZaxbt06U1pjlPyhQ4eQkZGBpk2blrqlqUUyCyawGzp/WO/iQGeeGLCbeTDexJZOZkHMJocNGybMF/wb28iMtjKWZn369EGDBg0CbswsA5rlq17FwdHyvXr1wltvvQVN0/zqWbIsQ1VV1K9fH5988on/IdKmCBEmQ7NCtyyUEO2NN97A6NGjxWYyRvBuQyEhIUhISECjRo3EpnulwWKXBQHe2O/TTz9FXFycabdJjubSNA1Lly5Fz549oaqqpZNZKBtYbQoJCcFXX32FBx54QBCJj8+eNWsWRo0aVabtTi2SWTCBpVlUVBTWrl2LBg0aQNM0qKqKqVOn4rXXXisTwQCLZBZ8gE+la9q0KRITE+F0OhEfH4/Zs2cHPUQaoZC1kZYFH2D9q0OHDti5cydatmwpfi+rNUKBzRZSnIkAa7+Cqgpfh6jxumSXLl0AwK/nRaC9PxRZlqpZJgwLpQ2BxhNdboYrCpG1B0ZVBlv3ly1bhrNnzwIoOpBCURQ0aNAA8fHxYglp9+7dWL16tRhK+RjJRx55BH369BFk9IS1dlnFwSSbPXs2fvrpJ9O1Ll26ID4+XnhpnD59GrNmzfIq49q1a4JkxrMIGNY4WcXBJov169djzpw5cDgcsNvtmDp1KhITE6HrOux2O4gIo0aNwpo1a9C4cWPY7XZMnDgRycnJmDNnDgCYzBqargHF6ptFMguQZRl16tTBlClT0Lt3b7jdbsTGxqJOnTqmIVCSJAwePBiapsHtdmPChAlo3749nE5n6eVXxENYqPwoLCyErusYMGAAACAxMVFszqyqqtis+bvvvkNGRgaio6PFMY+BrGCWTmYBAIT/Ppsr9u/fD0VRxBDI3wcPHgQAdOjQAZGRkQHdfACLZBaKwUSJjY1FeHg4Tp8+jUmTJqFWrVpwOp3CCJuQkAAA4gQ7i2QWggZ7u9apUwft2rVDUlIS5s2b5zc9S7xgYJHMggDbvnr27ImkpCRERUUhPj4eiqJAkiT88ssvWLFiBWRZFpIsGOOsRTILAjyL7NWrF9577z1IkoR58+YhJCQEALBnzx58+eWXaNGiBe677z5TntIgA4BssyaZFkoI06VLFzidTly9ehWpqalQVRWqqmLTpk0AgI4dOwprf9Aks3z8LQAQkUkNGzZEu3btAADp6elilnngwAEAwIMPPgggqD0xJMCyk1nwAEunnj17AigaIokIeXl52L9/PwDgV7/6FYBShRNJkgQC8gGLZBb8oFevXgCAb7/9FpIk4ezZszhz5gzCwsLQtm1bAIGUfgkgcgOAbDktWjCCidO1a1c4HA4cPHgQFy9exIkTJ6DrOtq1a4c6deoEd9Z6cQJZlqWw4rOVLLJZEHpZkyZNcP/990PXdaxevRqHDx8GUGIfK8tZ64osSfZyqa2FuxZsL3vwwQeRnJyMDz/8EGFhYQDKZoRlyJbTogV/eOihh0BESE1NxZ49eyBJEjp06ACgbAHhluJvwQtMoN69e4vz2CVJQv369dGqVSsAZTN7WSSz4AXWyxo3bozu3buLTVhiY2NRvXp1v27W/mAtK1koFQkJCbh48SLcbjfq1KkDoAxSjEgGiqKVLJ3MgheYSNHR0YiOjvZ5rTSoqgoCXACgaDpdLSwsBKyYSws+YNxunXWzYJCfn0+q6j4BAIpK6uFrv/yiAlCsNUwLnigLsQyQL2ZekjS3th0A5NoREYeys28ccrtVAqBbCwAWbhbFqwC6q6BQyvg5I71Ro/q7iEiS+/btq7oLXAsvXrokQQQxWbBw09DOnjsvuV2FM7p06eJeuXKlLE+fPl2W5RafHD50ODknN1eRJEm1pJmFsoAgpFjh5SvX7MeOHV8+ePBj/16xYoVtxIgRmkREsiRJ+urVG9pERkXs7NK5U+1q1ZwqEVk6moWAKCYXAVCvXL1m37d//9baNSOH/OpXv3KhyOWHJABgxq1evb5zZFSN/9+xQ/tG4WGhKoq8NCyDrQWfkCRJB6CrqqacPX8e6enHv3CG2F7o27evi4ikYvKVmC2YaCtWr25cMyz849YtWz3cIKY+iu1olq5mwQgJxatF17OycejwkSu/XL32x8GDH1sIAEaCcWIBJhoArF23cXxkjYjJUVE1H4iOjobD4SjXWsuSBEkux+G5MqiZN/F4RRHat35r3ov/NpQEl6sAV65cRXb2jWM3cm4kuPJy5j755JM/T58+XZ4xYwYZCQb4eGxjwunTp4e07/zg/3PYbZ0lCTFE5bnWKaG8tkkjAkmQFUmm6ndMJOvIBSRNkvQyUU3Xy8IwCQBpRHpe2SoXbPEyJEkqAOGSW3ennszL2//bESPyAWDbtm1K3759VV/Z/g9G9eEGgHqcJwAAAABJRU5ErkJggg==' +c2 = b'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' +c3 = b'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' +c4 = b'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' +c5 = b'iVBORw0KGgoAAAANSUhEUgAAAJkAAADICAYAAAD7jkPoAAAnCUlEQVR4nO2de3QURdr/v9XdMwkJ94RAwh0h3CKCQRBvu6ABDcEAkaiLu+KNFeHnWQ9yVEQDKHhwl1UREdwXXF0PSEAgLCJ5ASOu+yIQjCgECEECCCThEgkkzExfnt8fmarMJJPMJMwkE9Kfc+aI6a7uqupvVT311I3BhfT0dDk1NVXn///FF/++pUV46B1MZkMsihJDRK2IiPHrjDECgQEwACqHB8gADBAkTxfrgsTKYBD5HoDBAFVE4Prf7hcYIyIwRmTYGWBnYMxo7Eh5JpwxJjEwcv/eFfGHQRqBFamq44hNte1JnTDhR35PVQ0BAKt6MS0tTRk24s4/hoeFPd26dauh0Z06WVu1agmrxQrGUA0CwMA8XgMAwyBQXbRRA4wxl9j6RsW7g/Qz1jUxDYqX70WAqmm4erUMRcVF6uXS0pyrV8tWlV+5/HFqaqqjqtAYUCmw9Rlf3hnRpvWS3n1uujW6YxRkWQYAA1xLjcv1K9XE3zAAkmEQCouKkXcs/6fLJb/9v/Hjk751FRrj/5OxZevU6I4dl90cN1AODQ3RAEhEFBztjElQwypafcNutysHfj5kFBYVTUtOSvyIa4sBwNatmQ91695tXb++fQxZlomIZGfgRo28SdOhwlpjuq7r7EhevnSioOCpcYn3r0pPT5fZ9vTtbRAhH/zd3Xd3tlgUg4hkU1wm9cEpNEPTNHy/N9txueTqwKSkhBPS1dBrI2NiYrpYLAqZAjO5HhhjICJJURSjf79+oYak/xkAKRKTY1u3bEWoxbD2pXdoitPEBda6dUsKDbHeDQAKAAWs9p6jKSATX3FqhSmyzBRZjkhLS5MUb4E0TYPNZoMkSZCkys6mJEncxQEigizLphhNBIyxCmc9AAmM6Z5u0jQNALBx40bcdNNN6NmzJyIjIxEZGYn27dsjIiICHTt2RHR0NCIjI7F48WK3cCbNGyICt7IUMuhqbTfn5eWhuLgYERERGDBgAIgILVq0EA8KCQmBLMuIiIgAYDatzR3utSciMQrotbk8c+YMGGOYOnUqFi5c6PUlvAk1MeHUKDJuf508eRJEhM6dO4OIoGmam5B4z1OSJLMWM/GIAgCG4T6ITESQJAlEhF9//RUA0LVrV27MuXUATEy84RSZZz9YaWkpzp49CwCIiYmBruvQdfd+AhedWYuZ1ITH5tI5PIDi4mJcunQJISEhiImJgSzLNdpcuq6b9piJR2oUGQCcO3cOhmGgU6dOsFgs2LdvHw4ePIhTp05B0zR06dIFQ4YMwbBhwyDLsik0k6owwIvITp06BQAoKSnBkCFDcObMGY9PGjZsGNLS0pCYmGgKzcQJgwSoc+fOpVpdGHl5eZAkCaWlpSgtLUV8fDwmTpyIW265BbIs4/Dhw1i3bh12796NsWPHYtmyZZg2bRoMwzA7B82cipnM7BpjjLBp85fTTxScIiLSDMMgIiJVVYmI6KWXXiIAFBERQStWrKCaePvttwkAMcZo//79RESkaVqN9/sLwzCIx9kkOHB+Dd0wiL7O2pUNABLzMDiuKBUV3Ny5c7Fr1y7k5ORg6tSpACqGjXgvk/971qxZmDx5MogI77zzToOUFHJ2Tm70Xq1hGM4hmqY7+1zSdcNe08XQ0FDcc8896Nq1q3BdKIoiepmKolQMHxgGnnzySQDAnj17oKoqZFkOWMZwgWmaBofD0eQ/Qk1ws4MXpqaaRomAcqqYSlatSiAiOByOal5+twc4Z2f06NEDkiShpKQE5eUeV8f5BcMwwBhDaWkpRowYgalTp4IxVs1/19TRNA2SJGHRokUYO3YsysrKwBir5jgPOpwFgVzHLlkt7Q1jDFar1adn85IWHh4uBtD9Da/B7HY7xo8fj+zsbGRnZ+Pmm2/GzJkzoWmaaOqbMqqqwmKxYOXKlXj55ZcBAMnJydi6datoPYLdTDDIgLPyqn3Va3l5OTIzM5GdnS2axWoPMwwYhoG8vDwQEfr06QOr1SpqHH/h+v5HH30UWVlZsFgskGUZL774Ij799FMoitLkpxppmgaLxYKNGzfimWeegSzLsFqt2LlzJx577DFIkiTstCbDhowtj/1ScNLZI6joG/Ce4X/+8x8CQIMGDSIiIofDQbqui16drutkt9uJiOjhhx8mAPTWW28RUWUP1S89FsMQz3viiScIAFksFtGjlSSJJEmiL7/80u/vbkh4vLOysigkJESkCwApikIAaNq0aeLeYOxZO+Okq5pG27/OyhYiO5b/C5GLyLiIrly5Qj169CDGGC1fvrzGB69bt44URaGQkBA6ceIEERHpuu63iPPMf+GFF9wExn+SJBFjjMLDw2n37t1uYZoKvGDn5ORQmzZtRLpc08nTnZaWRkTBmUafRUZUmehPPvlEJHjhwoX066+/kq7r5HA46Pjx4zR37lySZZkA0IIFC9zC+gOekfPnz3cr0VV//IN06NCBDh8+7Pd4BBIez+PHj1NMTIxHgfFam6d/6dKlRFTRugQTdRIZUWXi33jjDbdEd+vWTWQGL2Hz5s1zC+MPuMCWLl0qBOacN+7xx8Xes2dPOnPmDBH5t0YNBDx+RUVF1LdvX7d0ePoxxsT1zz//nIiCq0ars8iIKjMhJyeHZs6cScOHD6eYmBjq3Lkz3XnnnfTqq6/SoUOH3O71B7yErl69WmR8bQKrKrQhQ4bQ5cuX/R4vf8Lt2ytXrtBtt91Wa01dtdaWJIksFgvt3LmTiIJHaPUSGVH12klV1WrVdCBqsK+++opkWRY2l7fM5z/+oUaNGuXWWQkmeMdJVVUaM2aMzwKrah60bt2acnJyiCg4zANPIvNpFFuWZRiGAV3XYRgGFEWBxWIBUOHTMQzDbzMvdF2HoijYs2cPHnroIeG2oDp02bm/7Ouvvw7Kbj853TGSJOHxxx9HZmZmnd0vPHxpaSmSkpJQUFAgplsFGz5PleDDG5Ik4eLFi5gyZQouXbokxOYP+DSho0eP4sEHH7wuLzcXWnp6OqZPny4+QGMLjYhEOv/yl79g9erV9fbv8cJ95swZjB07FhcvXhQVQlDhS3NJVGE/6LpONpuNRo0aJZoju90url0PPHxhYSH17t3bqwHs6493++fOnUtEjW+7cDNjwYIFdW4ia/rxZ9xxxx1UXl4umuLGoN42mWEYor2fOHEiAaDQ0FACQCkpKURUYQ/U1+7hfrmrV6/SsGHD/CYwVOn2L1u2jIgaT2j8vStXrvSpt1wfoY0bN058r8awQ6uIbD8AYP3GzX+sTWSu3vapU6e61Q78v9fjheYZous6JSUl+a10VxUaF+2mTZuIqOGNZP6+LVu2kCRJPveW61NrP/XUU42SRqJKkWmaTjt2Zv0fF1nK0bx85/XqAuECe/31190SUjVh8+fPd7vfV3hGzJgxw+Pz/fXjPdRWrVpRfn5+gzYpPI0HDhyg8PBwMRQWiHTy/OPO2oYWmlNDmq4b9L87v84CAGz6YtODR44ec1737IxdsWJFjdW7a3P02Wef1Slh/L6tW7cGpAar+uPPf+CBB4io4fxn3FXBfWH+MgU8/biAw8PD6dSpUw1un7mKbPvOrG8AABs2ZCR7EhkXwI4dO7xW7zxhISEhlJ2dLTLWG9x/dccdd7g1aYH88XfwMc5Al3T+/M2bNwdcYFUL0yuvvEJEDWuDehJZjS4MSZKgaRpeeOEFr74qcq44t9vtWLRoUa33crif59ixY9izZ4/4W6Dh04/WrVsHwHs8rxf+/A0bNjTYdHE+zSojIyMoVo95FBk5J8X99ttv+OWXX9x8VVUziv+bC+3EiRMVD/ayWolnfm5uLnRdF9siBBr+jgMHDgDwHs/rhX/gI0eONNg0cf6egoICFBYWNvqM2hpzmIjQpk0bdOnSBUQEq9UqZmXy/+f3KYoCRVHcvOreMpNfLy8vr1fp5mHqWjvw95aUlAAIvMh43Gw2m9v76xK2vtjtdly+fPm6nuEPJHgYiuDKt1gsWLBgARRFgd1uh6ZpiImJweLFixEREYFPPvkEUVFR0DQNdrsdiqJg5syZALxnJs/AiIiIOpdw10UV9QkLAO3atQMQ+Caaxy0kJMTt/d7wtHCkrqKTZTlgU+HrQo0T4vlqo5SUFGRnZyMzMxNhYWFITU3F8ePHce7cOcTFxWHPnj1YvXo1JElCYmIiBg0aJLb3rA2eYXFxcQgNDYXNZvNpRQ6/p127digpKUFYWBg0TYOqqgB8EzdjDIMGDQKAgC9E5mOxN910E/bu3euTUFzzwXXIiZsxvhbgqKgoREdHu/2tUdiQsSX5UO4RZ8eg5qk+rvBFv3ySorf7a4Lfm5CQ4NYrqunHr6ekpNCXX35JACgpKYm2bNkirntzcPJnfPfdd0TUcL3LtWvXEuDdD8h72WFhYbRt2zbq1asXAaA33niDhg4d6lMPtTGdsrx3qWk6Ze7Y+Y1PIiOq9PM4HA4yDIMOHjxImZmZdOTIETFLVlXVOvtjqq4lqM1VwjMuOjqaSktL6d///jcBoBEjRhAR0axZs8R9Nc0qtVqtBIDGjx8v0hVouJ/K4XAIP5nVavWYRj5HDAC9//77RETUsWNHAkA//vgj5ebmirA1CY0XovDw8AZ3OvP0EpHmUFXatn2H7yILJDwDlixZUs2fpSiKW2Z26tSJ9u3bR0RECxcuJADUo0cPunr1KhER/elPf3L7YIqikKIobqK7/fbb6eLFiw06x4yn8cSJE9SvX79qceRz5vjfZ86cSUQV07HDwsIIAKWnpxMR0eeffy7yxDWNrvkUGhpKGRkZbu9uKPwmMl3XxXijP+A12vbt2+n3v/+9x6Gr8ePH0/Hjx0UYvjrKarVSbm6u+PvixYupS5cu1Up4t27dKC0tjcrLy10zo8HgeXXhwgWaMWMGRUZGVotj7969adWqVSJ+mZmZ4torr7winrFr1y4xkaBqLTZmzJgG3Y+kKp5ExjZkbEnu26f3pgH9+xIR1bbWN6C4Og2PHj2Kw4cP48KFC2jVqhVuueUW9OvXT9zncDjQp08fsZXVqlWrMGXKFLFm8fLly9izZw/y8/NhsVjQt29fxMfHIzw8HEClAd3QuHYyLly4gJycHJw+fRqMMfTs2RO33347QkND4XA4YLVaMXv2bLz11lsAgPj4eOzbt090JADg+++/x88//wybzYbIyEgMHjwY/fv3B9B4mxI681ZXNU3++ptdu+5PuO/3jd5culLb9BRu17iWcF7jJScni/C1ld7Gmv7iiuu0KU/wOGqaRnFxcW626sGDB4mo9hVKjTmXjL+fqtRkQbWJGD/VhE/11jQNmqaJGoDPzv3ss8/Exi+KoiArKwuFhYUiPDlnn/LwfEZsMJyawhgT7iFPceT3/PDDDzh8+DAsFouYfZyRkSGuA3ALz/MpGDeODq7YOOFH6vCRBD5HX5Zl5Ofn41//+pc4jkfTNJSWluLdd98FUDlu5xo+GMRVFW9xXLx4MXRdh6qqsNvt0HUdK1asgN1uFyJ1Dc/zKRhpcruTnDhxAo888gisVitsNhtUVQURoby8PCgGg68HLhy73Q7GGO677z434em6jlOnTqFPnz5+32skkDQZkfFSmpCQgISEhEaOTWDgogkJCcGaNWtqvTdYay1PNBmRcaiG3YWC0Ra5HmoaU22KaWxyIuO2zI1OUxRTTdw4KTEJWiSJ6jBPxsSkHkgqUZmma4CHPWNNTPyBRIZZk5kEFtMmMwk4pshMAo4pMpOAY4rMJOCYIjMJOKbITAKOKTKTgGOKzCTgmCIzCRhExABTZCYBomJuHCsHuMjMgSUTP+M8EFoDAEkGgnLvd5OmDz963GwuTQKOKTKTgGOKzCTgmCIzCTimyEwCjikyk4Bjiswk4JgiMwk4psjqiLmC0Dc0XQOci+BNkdUBcm6eF3SHlgY5psh8hO+iU1RUJLayMvENU2Q+oKoqJEnCm2++if79+yMrK0ucPWXiHVNkXlBVFRaLBcuXL8drr72GkpISjB8/Hj/88AMURTEnF/iAKbJa4Bsdr127FtOmTYMsy5BlGaWlpRg7dizy8/Mhezg2yMQdU2Q1oGkaFEVBZmYmHnvsMWGH8d0cCwsLkZiYKPaqNW20mjFF5gEusD179iAlJUXUVNx9wbc5P3bsGMaNG4crV66YvU4PkHM6rCmyKnAB5ebmIikpCWVlZR4FxIWYnZ2NlJQUt0O2TECMSQBQBpgic4M3hadPn0ZiYiIuXLhQa1PIhbZ9+3b88Y9/FE2qKTR3TJE54Vu4X7p0CYmJiTh58qRPRj0X2tq1azFjxgyzI+DEtWCaIkOlJ//atWtITk7GwYMH6+Se4EL74IMPMG/ePLczKpsrRAbIOa7U7EXmupv2I488gu+++65eIuFCmzt3LpYtWwZFUcRBr82dZi0yfvSMLMt45plnsHnzZlgslnrXQvxZ06dPx/r166/rWTcSzVpkvPaZM2cOVq5cCYvFcl21D68VJUnC5MmTsWvXrmbedLLmvSSOe/OXLVuGBQsW+K154z1Lh8OBCRMm1Nm+u3FgICKXFeTNDO4Ly8jIwPTp0/3eI+Q91ZKSEowbNw7nzp1rljM3mMTsQDMUGbebDhw4gD/84Q/C0epv3xYXckFBASZPntzsfGdEBDIoFGiGImOMQdM0PPXUUygvL4ckSQETAG+Ss7Ky8M9//rNZTQ+SJAkMrAXQzESm6zokScJXX32F/fv3N4jjVNd1MMbw97//HZqmNYtzoQDwA3Cb39glr7E2bdoExliDnBfJ7bDc3Fzk5uY2y4H0ZiUyfvLaL7/8UmEzNJCdxJvkY8eOAaj5mMEblWYlMtezu+sKP/+c/7s+73Y4HHUOdyPQrETGa5AOHTrUqbms2gOta03Ea83IyEjxvBscRmSAMRYGNDORcZGMGDHC56aSN3UxMTHo1KkTACA2NhaSJPlUozHGQEQIDw/HoEGDxDObBUQS0MxExj/uxIkToSiKmH1RE7y2k2UZX375JYYNGwYAWL58OV566SUYhgGLxVLrO/l7xowZg44dO4reZnOi2YlM13X06tULM2fOFA5TWZbdPjwXFr//vffew+DBg1FUVAQAKCoqwptvvon4+Hixmsm1duLi5GOhLVq0wJtvvulV1DcqzUpkQKXQFixYgClTpkBVVei6LppP3rzpui7umz59Oq5evYri4mIAwOHDhyFJEjZv3oxhw4ZBVVVhp/HwRARVVdGuXTts2LAB/fv3BxE1n6bShWaXYsaYsKc+/vhjpKen47777kO7du0AQNhPI0eORGZmJmbPng3DMFBQUIDTp08DAHJycgAAMTEx+Oabb/Daa6+hZ8+ewn6TJAldu3bFs88+i3379uH+++8XszOaI0pjR6Ax4E0WEWHSpEmYNGkSiouLcebMGTgcDkRHR6Nbt24AALvdDqvViqysLGiaBsYYvv/+e5SWlqJly5Zo0aIF5s+fj9mzZ+P48eMoLS1FmzZt0L17d4SHhwOoHC9trjRLkXEYY8IQj4qKQlRUlLjG54ZZLBYwxrB+/XoAgMViwfnz5/H1118jOTlZCC80NBQDBw50ez5/dnMWGNAMm8uqcAOfi0rXdbG5Cm9ajx49ir179woDX1EUrF69WlyXZblaeCISz27umDngxFUwXBjcmP/rX/8Km80GVVVhs9mgaRrWrVuH3NxcMU+savjm2IusiWbdXHqD+7j69euHWbNmCfHpuo6ysjIUFxdjwIABjRzL4McUmRcYY3jxxRdrvcdsEmvHFJkPuPrRXKnqxDXxjCkyH2juvcPrxaznTQKOKTKTgGOKzCTgmCIzCTgS0Cxmapo0IpIOQJLNCs0kcJjqMgk4pshMAo4pMpOAY4rMJOCYIjMJOKbITAKOKTKTgGOKzCTgmCIzCTimyEwCjikyk4Bjiswk4JgiMwk4pshMAo4pMpOAIxlEEoM5adEkcEhWixLuXPLVvI7MMGkwzObSJOA0ucW9VXdF5PANT24EXA96rUpTXGjc5ETWFDO5rtxoe5o1GZHxTX0zMzNx8eJFWCwWhISEiNosKioKw4cPb9Kb//K4X7p0CdnZ2WjZsiWICOXl5SgrK8OVK1eQkpKCsLCwJpXOJiMyvlN1VlYWFi1aVO36kiVLMHz4cHFfU4QLx2azYezYsdVOlBs0aBAeffTRJrf/bNDGlNsl3P7imTpz5ky0bdsWiqLAYrFAlmV06dIFTz/9NIDK5rRq+GCE75LtmkZd1xETE4Pk5GRIkgSLxSK2FH3llVegKIqbvVb1GcFIUInMMAxRerkhz/d1BSpqsw4dOmD06NHiWD9d1zFx4kS0aNECmqaJLTVdwxMRNE0Lmg/Bt2/nW4a6buvOBTN+/HghJlVVERERgfvvvx8AxLmZrtuO8nwKxsPBgkZk/CxK3tRdunQJZ8+ehc1mczu4gYgwYcIEEQYAUlJSRM0lyzJkWUZZWRnOnj2Ly5cvgzEGRVEa/RhALiAeR4fDgaKiIhFH161EExIS0LJlS1HoxowZg7Zt20JVVZFPkiShrKwMv/32m0g7z6dgIihExrcgP3nyJObMmYOhQ4ciNjYW/fr1Q//+/fHYY49h7969sFqtICIMHToUVqsVqqoiOjoa8fHxAACr1YqdO3di4sSJ6NevH/r164fY2FiMGDEC8+fPb9SzwLm9xRhDRkYGUlNT0b9/f/Tt2xexsbEYNWoUPv30U1H7duzYEXfeeaeofceOHSt24y4vL8fSpUtx7733ivA333wznn76aezduxeyLAdXjbYhY0vyodwjRESGYRjU0Oi6TkREa9asoXbt2hEqRh6q/WRZprfffpuIiK5cuULdu3cnADR69Gji8Z4zZ06N4QFQp06daOvWrW7vbQh4/C5evEjjxo2rNY7jxo2j0tJSMgyDFi1aRADIarXSoUOHiIho//79NHDgwBrDM8Zo3rx5RESkaZpf4q5pms/55UyrZrPbaVvmji2NLjKeCdu2bROZZLFYSJIkYowRY4wkSSJFUUiSJAJAS5cuJSKivn37EgB67rnniIho9uzZQoyKoojw/BkWi4UAUEhICP34448i8wKNYRik6zrZbDa66667CAApikKyLLulU5ZlEcfRo0cTEdGuXbsIAEVFRZHNZqOjR49S+/btRT7JslxjPi1evNgtjxuKoBKZYRhkGAbZ7XYhGEVRaiyhkiSJD7Njxw4aPHgwAaAVK1bQ7t27RcY7z732+OMf8b777iOihqnNVFUlIqIlS5aIWqm2mozHccGCBSJdcXFxZLPZaNCgQT7nU2hoKBUUFNQ5nZqmiYKhaRr997//pQkTJtBzzz1HDodDXOf/rUpQiYyXsB07dojMqS3zeVMAgNq3b09t2rQhADRmzBiKjY0VpdlbeF5rHDlyhIgCLzT+wQYPHiwE4C2dvObt06cPAaDo6GhKSEjwOZ+4COfOnUtElUL3Ja5V/71v3z4CQPfff39dnuEmskYz/Mlp0O7atcvncUdy8YhfvnwZAJCZmYm8vLxax/tcw/Pe1+7duwEE9jxw7mIoLCxEXl4eDMPw6X2GYUBVVXFm+blz57B9+3afOy08n7KysgD4tgU8D7N69Wrcc889GDRoEObMmYOBAwciMjISkyZNwt69ezFu3DjceuutmDp1KoqLi33y0TW6a7ygoKBO/iueGfzf/MgaX5/Bw/IT3xqC8+fPo7y8HADqFE/ucuGF0FfXBM+PwsJC0XN3zbeq8Hu2bt2KyZMni78fPHgQ2dnZ6Ny5MzZs2IBnn30WqqoCqDgp7+TJk9i2bZvXIa5GF1ldBOYpTH1qooaesVGfd7kWHHI6auuK1WoV765NBPw969atE6MMqqqKsWIAOHDgAIDKERXGGHbu3ImTJ0+iR48etQ51NbqfrFevXg060Ms/Xq9evQL+Lp6u6OhotGnTxu1vgYT72m666Sa3ERNv8eQFlo8ccAd51dEX/jMMAw6Hw3t8rj9J9YMnLCEhwSd7yl/vNAwDYWFh+N3vfgcgsEfW8PdFRkZiyJAhDVaD8oKUlJQk/t/b/QAwevRo0Txz+Piv6zgwb34HDBiAnj17em0uJaBxDl7nXuk77rgDI0aMEMMigX4nEeHhhx9GTEyMKKmBhBeeP//5zw0yPYfbqB07dsRDDz0khrFqg3+Lhx9+GAkJCVBVtcaZLHyc1WKx4MMPP4TFYvGYLkVWKquwDRsyko8cPebsfTaOM3bv3r0ky7JwLsJLF70+P+74bNu2LZ06dUq4FhoCXddJVVUaMWKEVz/X9f64n+2jjz5yy2Nf4mgYBpWUlNAtt9xCAKq5WxhjIu5r1qzx+HzuwtA0nbZt536yRhSZaySXLVsmPoC/hcZ9YwBo06ZNRNSww0r8XXl5eWLozBd/V11/XACTJk1yy9u6xvP06dNi2I7nm6vA3n33XSLy7H8LSpERVUaWDw3x0ujvzP/ggw/ImQMNnkb+zqysLLJarSRJkl+FxtN41113UXl5uaiZ6hvPn3/+2a1A8OfPnj2biGp28AatyAzDEJGeMmWKX4XGn5OWlkZEvnu/AwF/9/r160Ut4Y9am9c2cXFxdPHiRSK6vpqax3PXrl0UGhoqnv/MM8+I6zVpJWhFxiPHR/sfeOABt9J5vQKbNm0aETWuwDgOh4OIiJYvXy7SeD1C4wLo1q0bnTx5koj8YwrwvNq6dStJkkQPPvhgrWOWHI8i++KLTQ8Gg8iIKo3Pq1ev0rBhw65LaFxgqamp5Ex1vZqPQMCF9sYbb1xXGnlz2759e/rpp5+IyL+mABfat99+S+fPnydVVb0WVM8i2/Tvh47m5RMR6cHwEXgpLCoqotjYWLfSWlf7JCEhgRwOB+m63qCGvi/wj/X888/XS2i8txwaGkrffvut2zP9gTex1nTdk8gUSWItgmnlCx+ji4qKwtatW3H33XfXaUarLMvQNA233XYbvvjiC3FYfTClEYBYn/Dee+/h/PnzWLNmDRRFqbZCyRN8XBMA1q5di7vvvhuapvltlRb3Weq6jh9++AE//fQTysvL0bJlSwwYMADx8fFiQYtP+bohY8tjx/J/IQqSmozDS0p2dja1bt3arXmo6cdrvNjYWCosLCSihnVV1BXuq1NVlUaPHu1TjebqSvj444+JyL81GM+vTz75hOLi4jzGYeDAgbR69Wq3+13TRNUM/yAVGVFl5u3cudNrt58LLCYmhvLz84mocVwVdYXboaWlpTR06FCvQuPX/va3vxFRpX3nD3h+TZs2TbwvOTmZ3n//fUpPT6cPPvjAbfr4kiVL3MIRVYpMVbWmITIi37r9XHht27alnJwct3BNAV4bnDt3jnr37l2jHcoF9vLLLxNRYGywpUuXirzcsmWLx3tXrVpFsixTWFhYtdm3Nc2MDWqREVWW1o8++qhat5/PiA0JCaFvvvmGiJqWwDj8Ix89epQ6duxYzTzgvWVffFV1hT/n0qVLFBUVRQBo1apVRFSR96qqkqZppKqq+BaPP/44AaBXX31VxMflWU1PZESViXjrrbeE0FynM2/cuNHtvqaI61huq1atqi2CSUlJEff581vxPEtPTycANGDAADHHv+p7eE/96NGjlJiYSJ9++qn4O1ETFxlRZWbMmjWLgMpFGStXrnS73pThadi2bZuYNACARo0aRXa7PSDuGNdhPcYYPf/8825/rwtBNce/PnD3xNtvv42nnnoKDocDS5YswZNPPlnr9JSmBHdjjBkzBqtXr4au6xg+fDg2btwIq9UKIHBz4K5cuQIiQmRkpE9z0HzdFqFJfRW+lJ+I8NFHH+HRRx/FvffeK1ZW3ygoigJd15GamoqIiAjExcWhdevWAd/Np23btmCMoaioyOu8N1dfmjealMiAyhm1jDEhsGBztPoDPpHw3nvvBYCAOpR5nsbHx4OIsH37djFD1nUKNjlnyLoWdl8mmjbZr8Or6xtRYBzXTWYCOaOWz6YdNWoUunXrhry8PCxcuFBsDMMF5ropzD/+8Q/ExcXh6aefRllZWa0rxiQAkOSm96FutC0va4J/5EDC1yK0atUK77zzDgDgtddew3PPPYdDhw6Jba4cDgf279+PKVOmYOrUqcjNzcXGjRu9xlHhLzFp3rju9bZq1Sq88MIL+PDDD/Hhhx+ie/fuaN26Nc6fP4/CwkIRRpIkDBgwAKGhoaKmq1KbMaAJN5cm/ocL7YknnsCPP/6I119/HSNGjEB5eTkKCgoQGhqKxMRELFy4EBMmTIBhGOjSpQuAautfiTEGAq4BTdDwNwksXGg9evTAvHnzMG/ePNjtdmiahvDwcHHfjBkzAAA9evQAAA/2GAOIVABQyJtDxKTZwXu23E0REhKCkJAQABAry/Py8gAA3bt3r/lBTjtMkSTW0nm2kik2E4EkSaLn7loP8XWW3Dbr2rUrgNrtekVi7MbxYpr4DU9OVm7cl5aWori4GADQuXNnAF5ERmTWYCbVqc09pOs6Lly4gBYtWiAqKgqAF5H5PXYmTR673Y6ff/5Z7JOmqioMw0BZWRlkWUZubi4AoFOnToiMjPT6PFNkJgI+RHf27FncdtttXu9v2bKl2JHcrMlMfIIb+tHR0Vi7di00TXM7iOLatWviPrvdjp49e9b+QCIJqOhdmjaZiRuhoaFITU31+X5PtZimaSDABgCKbtBF50Zm5tiSicDXpXk1dRCuXbtGmqYeBwBFI+3wpZISDYBijmGacK5zAqhUWFTMdFXfBQBSZOvWuaWlV3JVVSMAhjkAYFJfnB0Aw2Z3sDNnz+R17Rr9XyJi0siRIzXVbltRWFzMAATRgTwmTRT91OlfmWpzzB06dKi6bt06SUpLS5MkqffKw7mHD1wtK1MYY5pZm5nUBYKoxRznL1y0HDuWvzYp6YE16enpcmpqqs6ISGKMGZs3b+vXtn3r/wy9dUhkixahGhGZNpqJV5ziIgDa+YuXLD/k5Hwd2a7tuPj4eBuc62IZAHDFbd781a1t27fZNPiWQV1btQzXAEjk9HWYmFSFMWYAMDRNV079+ivy8vJXh1rlp0aOHGkjIuYUX6XbggstffPmbu1atvqfvn1iEzrHRMPpRzNtNRNXGJwTXn+7XIrcw0culFy8NCcp6YEVAOAqMH6zgAsNALZszZzatk3r59u3bzewQ4cOYj5RoJAYA5MC2DwHg5lZj+RV7J9//a/mK4388CTYbHZcuHARpaVXjl25emW9rfzq0vHjx59NS0uT5s6dS64CAzwk2/XGtLQ066Bbh90VYpFvZQwxRIGcrs0QqIVHRCAGSWEShTValWygDGA6Y0adpGYYdVEYA0A6kVFet8j5+ngJjDE7CMWqoR78pbw8Z2Zq6jUAyMrKUkaOHOnRg/v/AVUvz9RtmXqZAAAAAElFTkSuQmCC' +c6 = b'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' +c7 = b'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' +c8 = b'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n4JcVVXxzO+++47uu+++e+poMBjoH//4B509e1bc16tXLwJAOp2ODh48SERERqORJkyYQNWrV7+njMDAQBo3bhylp6c7TE5VVclqtZa4LHtZfSqUZEywadOm2TSWTqcjvV5vQ7g6derQH3/8QUREEydOFNfx6RtvvfWWuFaWZdLr9aTX60mWZfF9w4YN6dixY0TkWqKxnG+//fY9MhaUs169erRnzx4iInrnnXfES3L9+nXKycmhnj17FltGixYt6MKFCzbkdhXcimTc8KtWrRINVlCLASBJkshgMAiipaen04IFC8Tbn5mZSd988434W0sqbRl86ELLli0pOzu7RAc3OFLOJUuWFFlH/g0A1a1blzIzM2nhwoVCbovFQiNGjBAHSOSdwFaonN27dy+VBmKoqkoWi4XMZjMpikKXL1+mrVu30l9//UUWi4WsVqv4t7D7yV1Ipqoqmc1matmyJUmSZJdgBbUbNx5rBF9fX/r8889Fx9lreHuduGDBAiIislgsTpdRVVUyGo3UpEkTkmW5WDn1ej0BoEGDBtG8efMEyd577z2bdihJGXFxcURU8gR89vo/ISGBAFBYWNg95di73m1Ixm/X/v37xRtYXMPZu66k92mJKkkS9enTx6YezgJ3yu7du8UwXho5fXx8bP4uqbx6vZ4kSaKxY8cSUcleJu77mzdv0s8//0wLFiygU6dOERGRt7c3jR8/noiIoqOjafr06bR582ab+wqUU/EHePHMh48U5EXn4kB5Lg7KS3pCGu8+lWDazvecOHECZrNZ5Hx11pog1+nIkSOlygbEdTIajTZ/l0RGvp6IcPLkSQDFL8VxuVeuXEGPHj2QlJQEIPdQjE8//RQNGzZE586d8eabb+K7774T933wwQf46quvip3JVqgL49atW6W+p2AnlbThtdfeunUL2dnZ4oQRZyM7O7tMmYS0xCrt/QBw9+5dAMUvrPMm52XLliEpKQne3t5QFAVGoxGTJk2CJEn4+OOPcenSJRt/3Ndff40XX3wRrVq1KpJoFepICQgIcOnzuLGrV68OX19flz2X11hLi7IQSwt/f/9SlXP58mURIWy1WoVPjohw6dIl4dS2WCwi9ImPISrqGRV6BjkfxO6q3F0cfNi8eXOXZPbhstu3bw/A9XJy+5Z0ualJkyY2daS85S8uk4nE/ycihIWFie8Kgwwo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' +c9 = b'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' +c10 = b'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' +c11 = b'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' +c12 = b'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' +c13 = b'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' +c14 = b'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' +c15 = b'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' +c16 = b'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' +c17 = b'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' +c18 = b'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' +c19 = b'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' +c20 = b'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' +c21 = b'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' +c22 = b'iVBORw0KGgoAAAANSUhEUgAAAJkAAADICAYAAAD7jkPoAAA/DUlEQVR4nO2dd3wcxfnGvzO7d+pdsuXejQkdTG+hhBYbTDO9g4FgQkIglB9gEkIJJZQQeu+YbgglYDqEkEAgodrGvan3cre7M78/Zvck27J0J1t3p6DnEwXrdFtm9tmZd9553+cVdMLs2bOt6dOne8Hvzz338lZZOZm7CEtsE7LtoVrrPK21CP4uhNBoBKBAt9IFtAKFRnb1x0QgRQtK6/gPEP7XFWz41TcKhNBaI4TWKiIgIhBCpfqm1oLfUzkasU6nBfeP0q5GVDhO9Lt2p/0f0w899IvgO2tzCECs/cdZs2bZO+y86wk52dmn5+fnTR5SXh7Oy8slHAojBOtAAwLR5d8AlNLoRLixHgghOt1tfFBKbZRr9w0SbExS0UOfaXBcl+bmFioqK5yGxsZ/Nze3PNDa1PDg9OnTo2sTTUAHwZ596a+7lhTk3zZ+wrhthwwehGVZYIYCTep7JV3Z8mOGAKRSmtUVlcybv+A/DXX1506bNuX9zkQTwS8vvfLqjCGDB9+xxeabWZmZGS4gtdbpMc8MIK0hzKyvIpGI/eV/v1arKyrOPmTKQfcE3BIAr776xhEjR418ZtImE5RlWVprbfkHp/TmB9B/YKw14XmeJ76bt0AuWrz4tKkHHfDA7NmzLfHmm28WIENf7bn7LsNCoZDSWlsD5BpAb+ATTbmuyyef/ivaUNe82ZQpP1skm9va9ho6tHx4KBTSAwQbwIZACIHWWtq2rTadNClTSe9MQEsprIn5uXmaAcN6ABsPIj8/V2dmhHcHsAEbkeDKUWvQisA7IIQAObBGGEDMjhe2ZQnbskpmzZol7YTOoDVaKYRlgbDWZKbWaK0Q0tqItzyA/gohhHHWAzZCeD0dAJjRSwiEZaEj7bR9/zXO6uWIUJiMUePIGDsRISxQamBUGwBa69hMZ2ulm+M4AoRAey5V995M9aN30/71D3gtICRYJZC70+4Mnvlb8veeglbewIj2I0Xgtddax3YBe54utQat8VqaWHzmYdQ9PxcrDwoO/ClZW2yHam2h6cO5NLz+AU0ffMDwWVcxaOZlA0QbQAzxkUxKll98KrXPziVn6+GMuOkh8nbbJ/YVFYlQeecfWX39LJZfcTmhEWMpOuRYtOcZ+20AP2pIMBvJXUF7HkhJ03uvU/Pkc2SMzGX0Pc+Rt9s+aM9Dey7ac5HhMOW/uoJBZ5+HdmDVdb/Fa2pESAlpu0E9gGTBJ1n3RKh7/hG8RkHRYUeSvdUOaCeKsCyEZSMs2xBJKQafdyWZmwym7esVNLzxvLHjVHzrigH876KbZaA2U51StH3/FSJDk7f7/iZAbO3Vo/+7lV9I9tbbo6OCxjdfMn8b2EH40WP9JPMHN608VFsLwgKZm+eTZl3iaH+BIDKyEGFN21efo9pajfE/MGX+WCGgO5IJYUhjhwiVDUFHBNFF881xel0bzgQVCqJL5iGzwalYSXTFEvPHAZL9CCGQ4Fx55ZXdx4sF9lTuzj8Fral76XHzBynRruvHVit0NAJS0vzJO7R+/h+sXBuvxcWtrjTnGSDZjw7+oNMmhOieZMIP8y4++gwyxuXR9N4/WfXHixHSQti28cRKiQhn4KxaxrKLzjYjoBDggtfckJQGDSBN4eeDSNHd5riUaOURHjaK4dfeCTasuu6PLD7zMJo/fJPoiiVEfviemsfuYv60XWj9/HsQCq0VCJCZWUlrzwDSF7bnqUh3XxDSQiuPokOOQ0jJ8it+Q9UDL1D92AvYxaCj4NaAzIaSYw8hb6+fs/yisxGZAru4zJxjYIH5o4atoVWbpeR6qSCkBcqjcOox5O6yD3VzZtPyybs4q5cgs/LInLQl+XsdSN6e+9P893fwGj0yxg0iPHx0cILE7mptG643LO18jgGWJw/BPnfnvUsRdyisQHsedskgyk6ZSdkpM7u8QNOHb+I1C7I23xYrvzChqAzteV3Hpmnt74XK7gmrzFQtfFtxzXO7gEifbS4/bCoW3eI/mFiSoZQ9vxxa+eegY4jQmPPFc3wfQmmFP3jFsXcZQErTDv9BxjrCJ0DQWY1/ewER0hTsfyiAiT/riWSdwogAVFsbXlM9aJBZ2Vj5BWZnAdazH6rRnolzE75XRnseur0VrBAyMzN2PEp1LE5SBeWBtNZpx9p3tN69305xfcLqxtWZJnvHcZMssmQhGSPHmBHC02sSR2lEOEz1I7fT/Ol3ZG1aRuGBRwD03EifYAB1c56i7vknaP/+S7yGatAgsnLJGDmevD33p/jIE80UrLX/RMQaBI0u+YG6l5+h5ZO3iS5fhNfWgrBD2AWlZG22DUXTjiV3173XuW4yYV46Cx2N0PThXFo++zvRJfPwmhsRoTDh4WPJ3fGn5O+1HyIja92XtBNBnZXLaP7H+7TP/wa3thJhWdhlQ8n6ydbk7rwnVl5BytrZGTaA53a9vxi8CRW3/Z7ll19F6QmHM/LWx9ckjhCIcJjmj95i5TWXoj0oO/18rMLint8kvwO8+lqWzDyO+r++jrBBZACWH5fU3IqzopKm9z6m8q6bKP/VpQw6+yLjo/MjRLTrsPqmK6i698+4NS3mHCGMq1lDxFtK8yefU/3w/ZQcezzDr7sHmZGZ9AcQhD81vv0yK2b9lvbvv0M7/n3694qCCusWsiZNZMiFV1J48DEdRPMJ5qxaxqqbfkfDK7NxqppM+nXn6dKGjJHDGHTmrymb8RvfeZ660bv7kcy/p6yfbI2Vp6h++GncuhoG//JysrfYFpGRiVtVQf3LT7PqhsuJLmul6LC9KTv9/A4bar0w21DadVh81mHUv/oeofKQmY5VR16LsECEJUIKdHsjyy66mMii7xlx/QNo5aKamll8xqHUv/o2djHYpbYfCq59499IKIg8CRoq73sM1d7M6DufTyrJAoI1vP4cC086wgR75lv+zgqx9gY7LZEf5rHw5GMZcuHnDLnkBnQ0gghn0PTBGyw550Siyyqx8sEu6nwOgohBnMoVLD3/Atrn/ZcRNzwYpKslpa1ro1uSmVWlIn/fgxn76EssPf9Map95i/pX3iJjbDFWbh7RFUuJLtNY+VB6ynRGXn8vIhTu8QGaUc6m5tF7qH/1PcJDwqhodH1fNi+jJQiV21Te+SDhEWMYfO7lLD77cOpfe5vQkDDaccxOxJoHm//54UzhoWFqnnyRgv0fp+jQ49Ge22Gv9RW0RgiJV1fNsovPRNggs+0u7rUDIktiZ0tWXnsjIjuX8vNm0fzx2/xwzFTQDnaZjXY9E47V1fFhSWioTeXdD5O9zU6UHHdWymy0nnvXH6bz95rCpDc/o/bZx2h6/w0iC7/Da2wkY9QmFB28A0WHHkvenvubY3ocIbSxSzyXmsfvROZI1Hqm7DUP02jXxS6WVP7lGlq//CeNb71FqMxCr4+ga0N5yExJ9aN3UHTo8bFdjb6E9jyEbVP34hNEl9QYgjjrJ5i5T4UWGrtEsvrGK7HyC6l+6Da062DlWfEdj4uVL6m653qKjzzFvPwpkDWJ7xWWFtp1sEvLGXTWBQw66wK066CjUWR2Tuxr2ol2WiV20xBlbKno4gW0L/gOmamMXREPtAZLo9rbqZ/zMjJPrvdt7vJwTyEyNe3ffYlTuYrQoCF9Pm0GZkPju6+CLUz747pZDUIjbMGy3/4KmQkyR6DjeSEBlEJkCNp/WET79/8la4vJMbsumYjvNVYKYYfW+EjYIUMwrWKdJkJh8z0hjatgPQg2zCPLFqFaVOKN1oAUWHlWt9dZ38HCEniNrTgrl/r304cqYcHiJNJO+/xvkGEdm7rjO978n11gIUIJENSHkBIVgcii+f7tJD9YIY4Yf+NMbfvqMxrffgMVaSN7q+0p+NkUQyYh0V6UprffJLJ0AVZuAbk770F4xNhuRgjTUNXShHb99PZE71xrtN6AqFst4p9iNwhmenIb6vAa6qCXg0gio/WaEKBAtTb18vgNR7ckC5bOVQ/8ieWXXoCOdlAh/6e7M+ahOUQWz2fpL0+l9auvYlOeVZDDqNvuo3Dq0evJWjLEs3LzEXYfjyRdQWuwQObk+nfT9zZKSj3wAkQ4MzXXpjuS+QRrn/8NK674DSIMVn7IdwtoGt/7gPmH7oRbtZroygazlNZmS8hraGHFVb8mf9+pyKzsdUa0YCkdHjkWmWOB5yXPFhUC7WjsshLCI8bEPuvDCwJgFRRjlwzCrW1C2IJkSY9o7SFCEBo2yr+dpBLdhPoopbq8ajC6NH/0FqpVIDNCMReBdj3sIkn7t9/j1jdgF0p/Oe2iHQeZI3BrKokuX0LMK98Z0nwWHjmWzHETUZHkaWkIaaHaBNlb7dCxt9qXHS/Mnq8IhcjabBt0VPS8zbYxr+1oQmUFZE7c3P8oSf2MQGgiYAz/Vj8lruueDvixFlG0pxBZEmELtLfWdBc4QdfrkzFZTMKyKTjwCHS7Tl7H+07g4sNP9G81GVO16bvCAw+PzQTJgJAWqlWQs+Oe2EUlZsGRnJFMCyFQaEMyWymnqxVHwPicHXZHZq9nRRREEXSGFOioIFw+rNshOiBVyTEzCJXnoKJJ6AAp8VoU2VtPpGC/Q42TNAnOySCZJn/fg8nadBSqLVl6IRohNaXHn+3/mtyVZSBXLdX69hqkcUNkbbYNBfsdhNegEHbPD0RYEq9ZU3zsDGRGpgmx6eoSwvi3QkOGU3bGr835+/iBCyHQUc2QC65BhDP8FycJb7affyqzshl0zqWo1r4fuYVl4TZ45P10N/L22N/Y2CmKyIirpUMuvRGrIMNs5nYz2gjbwqt3yd1lS8pOO99fPKy/YUJKtFIMOvticraZiNfk9tkbLmwLt86jaNpBFBx4eNK3WIIc1uLpp5K727Z4DW7fXV8ItAcyy2bYrNv8Z5a6ZJ7un6g0o03m+E0Z9rsbceu99e/zSYmOaOO+uPWJjvj+7qZAv/EyK4cRNz5gYqN0Hyz1pUS1a0LlhQy/6k5/LzHZ7gSBRiMsm+FX34UIW2iPPjERhGVeqCEXXGYWG17yvfyd0eOwISyzx1h6wkwGnX06TqWDCIXW+pIAJVARxajbHyFz4mYxHY0ez+/vYeZstytDLrkSt3bjv+ECiWpTjLzhbkJDR5ppMgUaakFbs7fcniEXzcKt3fijqRmxXQr2253BMy83I3aK9eIkloXXgzc5SCYZcfXdFB95MG6l07HNJARg4TV6jLjpLxTsfxjaTYwoQecPnnk5RYceiFvjmpS7jQBhh3BqXMrP/w0FB01P+N42NjraehlF0/Y3L9XGaqs0L1N4WBmjbn0cpIglXacS8VFcCLPaFILRdz5D4cEH4FY5iIwwIPEaXEZcdwOlx//CPMREO010hHKPuvlRsjYdg9fkdhtaHNdpbRu32qHosJ8z9JIb0iMcWXT4yUbe/BiZm4zGa97wtprFhZlRRt/5JKEhI4xrKQ1UL+O/g5hsQZgx975A4cEHEF0eRTV5jLj+JsrOuMDEZvX2rRQSrRVWYQmj73seKy8XFaXXnSRsC7feJWenbRj15yf9S6Q2uSIGv612cSlj7nseKycHFdEbRAghLbwGM5vk7rKPHyeXuhfKZCsZt1dirZIStEJkZDLm/hcZfNZpjLr9XspOO3+jBP8FU0nWplsz+q7H0Y4ClfhwL2wLr8kjc8IYxj70MlZOXlrEundGrK0/2YbR9zwJHr1qK/gmQbXL0EsvpeSYs3yToI8DMXuA0h3F0xJ/dfxpTYQyGHHjfRQfdbrvg9lIdoVlIkbz9zmYkX+6C6/RM4LHcXa+sCy8Zo/QkHLGPf4aocHD4l6EJBuxtu49lRF/uguvKbG2gk+wSofBv5hB+QVXb9hs0kfo5Vxkpk7teSYdbiM/QGHbaNeh5JgzGX7V1cY4lnaPflNhWahWD7ukhHFPvEbGmE3Sww7rBrG2Hj2D4b//g9/W+O5X2CHcKofSk45h+DV3+yvJ9GvrBhgBZm+yrxplOt9l0C8uZcilF+NUO4Zo6/u+TzCroJDxT75G1qZbp9wuiRcdbf0/yi/8DU51z6ORCNk4VQ7FRx3GqFse68hoSiOTIED6zSExiJiPbsiF1zLkwvNxq31bY61+jBGssJhxT71O1hbbJydBZKMhaKvH0EtvZPDZM3Cq3HWikWPftkO4lS7FR05j1B1PE2SgpyPBIK1Jhr/c9zv//27qeMulTZAGJmwLr8XDLill/Ow3yN5qx35GMB+Ba0N5DL/2bspOOQGnyuky7N2pciiefiij73qmYyZJU4JBupMMYp1viHYjQy+5CLfGBSER4RBeo0eofAjjn3mLrM0n90+CBRDCuDeUYuTNjxiiVToIK2T6wbZxKh1KjjmyE8HSa9XcFfrH0+hEtCEXXYfMzGLFVVeC55ExcRTjn3ydjLGT+jfBAviCcQHRZEYmFXfdS6jUjGBlp53EyJse9L+sSVgxKQXoP0+kE9EGnzcLmZtP/ZyXGHXHg4SHjYklC/9PIFAmVIrh192DVVjMyqv/SPkF5zFs1i3ENHv7AcGgP5EMYitalKLstF9TdtqvzecpjJXqMwRToNYMufg68veeQs4Ou8WijtN9iuyM/kWyAH5AZSxOKg0drRsFMaKpDoL1I3IF6L9PJ/AJ9ZMpY4MgjHZvfyQY9GeS/ciQjp78eCGjjtvix5P1z9dkAGkPKYVQOoXx3wP438fAdDmAPscAyQbQ50gvF8bGkAwP1Lk7WwBCIGQarkR9ydFYcrUgFuae6DlinZaGG+XpQbKEJMMlXa1RYlk5UsZk1tf5jvISf4h9AW10cYVldXj3O0MZDfz1ryh9Sfmg5sHa7YnVPUgsALKvkHqSdZJId1Yto/nTj2if9xVuTQWgsYvLyd5yMrm7/NQIpHQ6JvbvTnID7Qu+pe3LfxFZvggdjWBl55IxdhOyt9mRUPkw/xiVulHNT8cTFuhIO5GlC3EqVqAdDys3n4zR47DLBse2ldYZmWLHm/a6tTU4lSvRkTZkVg522RDsouKOLbY0cOCmlmR+B6i2FlZeczG1sx/BrWk08e5dSIaXnTaTQWf9NhYCDsQeQuNbL1N5z820/PNDvEZnTXlQG0Kl+RQcdDhDL7kGu7Q8JZ0fjC7R5YuovPMmGt99DWflIlSrBgUiBFZRATmTd6fs1JnravDGpDg1dS88Se0zD9P29Wd4DTVoD4QFVmEpmeM3o+DnR1B6/Iy4RKL7GmL2cy/tvcnEcXO33Hyz5Mpw+yOQam9j4YkH0PDGh9glJj6sK8lwFfHwGqHwwH0Yfc+zWHkFxvbyFMsvPYuqBx8wlRFziE1Dna+lXQ+3DrI3H8f4Z94mNGQEyYxiCCJXmz54g8UzjiG6ug4rG0QYMzIJgVYK7WpUm7n9kuNOYvjVf0Fm58QiTNq//w/Lfns2TR9+bIQuswy5YiHxLugoqDbI32tnxtz/AnbJoKS11eeQ57iu9fa77713wM/2/WnKLOEgi3v1TZfR8PqHhIdmGEUgzzMaaJ7/47q+vpcgNDhM/WtzWXTawWaKlBZLzjmKyrsewC6yjS4+nc7hdhyPFITKw7R9/QNLf3vqmkTuayhjP0UWL2DRaYfjNdQRKgshMnz7Uilzj9qIENsFFla+TdV9D7PojEOMhr9l0/rFJ8w7eA+aP/oYu9jGKrB8QT065LpCAivXIjQkTOM7f2fJL4/x1ZeS1NYukBqS+TaUU7mKmifuwS6VKCfavbSR1mgnSmhwiIY3PmDldRex6sb/o+bJFwgNCXWQaX29qTU6GsUutWh8ay4t//wwpvXR19D+dFVx2+9xq1qQuUZQ0ITs6LW/bF4SzyU0NEz9nLmsvvV3uNUVLDzlELyGBqxiu6O9a/SZjhn9OholVB6i4fV3aPjbC35be5Bl38jQQVHVpF41uLhfdrrp/ddxKlsRtuyeYJ2PdRzsUknlX26k4k/XYJdJ88DihTD6afV/nR2cMcG7TxD+C+U11NH49ivIPNFtkYg1Do062CWSqntuZP7hu+JUVGLlyp41/AMoDZag9pmHzO9JXOwYs0u0QkCyFA2lbf/9zOjMJgqtEBkSkSk7AvjihdIIW9P29edA3288B0qObd/9F6eizsikxy1Gp0EqtOMQWfADMqsLVcvujlYeMkPT+t9/oVqaY1IQyYDvmHHBX6v0JLjSF7cA4NbXgOhlo7VKnGBgajBa4NZWdVp19WHH+w/VWbEY7ZC4Zqtfs0BkyoQ1/AGEDV59LU51xRr3kwwELsDUujDinDb6AskOndFOpPdcjnn1N+D4JNtjnZGi1aXpMKuguHfT5QZAIMDFuDCE8CuaJEHHPzPHv0xybROtQGRmdTiyU+AvS+lmXtaWk0m6QSgF2oXsbXYCSKwETS8QTI+Z4yYhs/r+emtdHB2FjFHjsEvKUuaUTQnJAn2u/D32xy7LRDvJCy3WnofMFRT87BD/Xvr4ur7NlzlxczLHjUO3k8SaBRIdwQgTi+S4a7pCakYyP2Y9NHQkBfsfgteUJKlzy0I1Q+7Ou5K1+bb+PmAfXzcoFhEOU3TYSai2ZNUsEGhXYRXaFB1+kvkkRQk3KZsu/RRWBp9zGVaejXaTVYdRM3jmZeZfyVrO+zr+JcefTXhUCaq97zfohW3hNSgKD5pG5vhN+0R9KV6kziaTEu0pMjfZnLIZv8St8+KqE9BbBBLrhYdMJW+P/f2KKElaYfr7knZxKYN/cRGqSW24fGdP13M0VmGY8vOvMg7hFKZwpNTwF37+ZPmvf0/21hPwml3oi86XEhXRhAYXMOzKP6ek04OaBaUn/5KcnbbAa+w7WSthWbj1HoPPvYiMcZOMQziFuampDRUNdPyzcxh544NmK0Jt/KBCISSqRTHij3cSHjYqNRLrvmdShDMYcd29iFDf6PgHBTvydp/M4JmXGXswBbFzrufGwq1SH48c6PhP3pWhl/0Br3bjiqaIkI1T7TL43JkUTj0mtcJ4/iZ19tY7MvTyq42JsDH1O/yiGHZpAaNue9xUUk6DcOzUkwxiYneDfnEpxdOn4VY7iNCGd76wbdwal8KD9mbo5bekhdxlrK1nXkTpcUcaBcmNofEqBGiJjpqCHRljJqaNVm7q7wAA4a/AFCP+9DDZ2/4Er97doIWAsC28RpeszSYw6o7ZCCn9ZJJUx7z7bVWKETc8SO6OW21wWwGEZePWugy76o/k73NwWkmZpgnJiEV2Wrn5jLn/RUKDS1GtXq9WYcKSqFaP0KBSxj70MnZhiTF+0yVbySe6zM5hzH0vEBo2qNdtBWLqi4NnnsWgGb9NC4n1zkiTXvfh22cZoycw5sEXEOFMVDRB1R5/JSkysxnz8EtkjN0kvmlSa+OcDX5640MLNrLj2dD2AybDw8cw5oGgrZiqxglAhIwCdslRhzL8D3empdp3epEMM+ybhcBujLnvabSLSSyJp/OlBFcDFmMffI6cbXfpvpaS1iZaNMgK8lPqgjSzmIR8d1DKnCPYF+z0o5XX7VZOYJ/lbLsLo+9+HB1VCa2uRciU9Sk4YC9TdUWrNDEJ1kTakQxYo2DE6DseNpVuleyeaFKaJApXMOb+p8nb44Du6zzFUvFsM/q1NBNdupD2+d8QXboI1d7WISHf1cjmh0mb9DQjlOw1N+FWVeBWV6Ij7QhpdRB8PSNb0NaC/Q5j1K334DV7QM9ECxY1ebvvzJj7X0KEM/z83vR5pNqPfkifiXstBEUUiqadgIq0s3TmDGSuBaKrktT+CObA6HufpGC/w+IiGMql5umHqH/5GdoXfIVXX412oohQBnZJOTnb7UrJsaeTu8teax7XKVc08sN31D73OM0fv010+Q+o9lYQEiuviKxJW1F4yNEUHXL0Gsetr63FR52B19zEst/+BqvQBtaO4fe/HzIEy91pMmMf/SsyJy+Wj5km0L5vrgXSmGRgDFrtupQcdQZ4HkvPO9sQTapYlKiQEu1otCcYc9+THeUGuyMY4FZXsvjMI2mY+z4ybFLThA0I0NEI0WVLaJ+3hNpnnqDk+JNNalpmNngeWBbadVh1/WVU3XcbXl27OT5EbG7wahton7eYuhdfona/+xj158ewy9af7xm0tey089GRdpZf9n/YRTZ6LaLFCLbz9ox77DWs/KJO+ZjpibSh/voQVOsoOfYsRt5yJ6rF6yh0JSUqqtDYjHnw2Z4JBrFsniUzj6ThzfcJDQ5h5VuIsPCnY/NfEZYmzS7Poureh1h44kGo1hYzLTY1svCEA1l13fWg27FLbWSuOYew/Z8MiV1oYZeGqH9tLgtPnYJqayXIKFpvW31/4bDfX4Vb5wIdOaSmtKJL3h67MO6JN7AKS9KWYEopApd/2pMMOhHtuLMY9ed7UK0KtEBHFCKczbhHX6Jgv0N7JJj2TI3z+jlP0vD6+4TKQ+io05FaFgiXaA1a+bmfHqEhYRreeI9lF56M1pplF51K/StzCQ0JGwPfdc3DXmN1aXIpteMQLg/T9N5nVD94SyzMab1t9Rc+g2dexvCrr8VrcAGJCIdxq10K9tuHcY+97o9gSQhV6iW0VrFw1H5BMljTbhl9x0OoNoVVUMT4p18nb88D4yrmGuzh1Tx5LyLsixvHAR2NYpdI6uY8y/yDJ1P/ynPYgyQ62kOuqA/lushcSe2zD6Ndp6PIw/ru018MDDr7YkbeeAuq2cNZEaXo8EMY+8gr6WiDdYu0tsnWhrBDaM+j6PCTyBi/KVZhERmjJhjfUE9bM9r425zKVbR99TkyS5lKt/FCK0RI0PLZF8hsETdBAVAaGdZEly7EWbGU8KhxPknWf/1g6iw95TysohLavvmKoZdc25GX0E8IBv2MZEBMxz97qx3MB3Fq+GutEMIiumgeXn0LIjOR/MfYSZA58Y+AnQ4EKVDtLk51BeFR44w0VA9HCcsGpSiadjxF0zruof8QTKRBSlxv4Re6MkZ6nB3u80m1NKM9v6pab7z6G5IIojGr00QQk1LQaaM3Fh8EWutW6K8kg8QNXv/ZyLx8hK27M4n6BtokFcucXP92EqjOm2bbRPFCSBGBfmT4bygCoz9j9ASsghzwkpgeJgTaA7uokNCwUbHP/reh0Upnwo+IZIHBbJcZ5UbVJpKWvSOkRLcJsjbbBruwuFPJnv9dSGkhhMiCHxPJ6BA/KTriZJMdlaznLEB7mqKDj13jPv6XIYRA+EInPyqSBalphVOOImuLsXgtSXAFSIlqVWROGkHh1KMJxPt+TOifJIuF6CS4UvNT02RmFkMuvAYd0X2eZCGkRLVphlzwB2ROrkliSXSqDGLc+in6H8nWCNGxEu58YVlo5VE45SiKph2EW7fhoc/rvZZt4da5FE75GUWHndi7gMLA8Sp7459LD/QvkumOUWD1n35P49yXeyVTKTA+smG/v5PQ4AJURCcckdojpDC5noMKGH7NvWaaTHAEC+LVokt/oH3+10mTH90IEKZgh86G/kQyZWL0dTTC4hmHs/zyWSw86RDq5jwe2+uLG36ibXjYSIZfdweqxewGbEwILJPrecPdhIcnnusZRPS2/udT5k3Zke/33YbGd181I3EKdd0ShAX9hWT+A1JtLSw8eQo1zzxPeEQYYQsWzzie2mcfikVqxIsg9Lno4GMZ9IuzcKp73mCP+9y2yfUsv+A3FP78qIQzh4LN/uZ/vMuCI/fDrakBXBaeOI3GN19MuK2pghD9ZHUZjABecwMLjz+AhtfeIlRmoyNRsDQyS7LknFOofeaBxIkmjX027IrbyN97541in5m4e5fiI6Yw9JIbDcESWE0GBGt6/3V+OOYgVEsDMkuCLQCXhaccQcMbz/cbokG6k8wvsOA11bPwuANofOdD7FK7Q/1ZaZAamS1ZMvM0ap99MLHON74cRCjE6LueJWPsCLzm3mf7CNvGq3XJ3WU7k9ihVEL7jQHBGue+zMITDkE7bchMI0yDMlEgwlIsOm06DX97od8QLX1JtsYIdiBNH3xiCLZ2pwZEy7JYMvNUY6Ml0vnS10obNJSxD72ElZeHiiSuuhMkE2duMo4xD85BZuf6f0iUYHNYePJhoB1khlxT7VopsDuI1vj2y/2CaOlJMt1hgy06aWoHwdanX680WAqZKVly1gk0vvVSQp0v/HzPrJ9sw9gHngUslEPcK05hW3jNHuHhQxn7xGuEBg31w6Lj694Ywd75KwtPOQKEB6H1yKn7RAOPRaceSfMn78Riz9IV6UcybSIktBNl0emH0vjOB90TLIDSYGmEDYtOP4rmf7zrd358S/5ghZq7236MuftxdESBJ3okmrAsVIuHXVLKuCdeiwVRxhsloj3fyP/7XBadcjjgGq3/7nxiSiEzBNqNsPDEQ2j76l9+2HZ6ujfSi2R+3UukZMl5x9Hw1zexS0IJVeAQYdP5i045jPb5X/tBjnESzQ/xLjhoOqP/8mCP+Z7CsvBaPayiYsY/9TqZm2yZ0ErSOGdt2r76FwtPOhTtRpDh+KJutaeQmRaqqYmFJ04lunxRLKAz3ZBWJAs84ssv/wU1TzyLXRZCuwmUtKGj893aOhadNBW3pjKhnQGTmuZQdPjJjLrtHj87at1kW2FbeC0edkkZ45/+G1mbbxer5BYXfKXH6LKF/HDCVFRzEzLTSqziiOchcy2iy1ez8OSpeI31fn5nehEtbUgW2CWVd11H5Z/vJFSaOMFi5/I8rDybtu8XsfisI9GuY/Rh44yEDXIgi486g5G33d2RhidNZTlhW3hNHqHyoUx45q3ECeaLv3hNDSw8+WCiK1Yjc6xeTXfa9bAKbVo//5olM4/2T7+BxSU2MtKCZEEiSMPfXmDFFZeYKmhqwwxZ7brYJTYNb77PiivPje1ZxotYGt7RMxh1+31m6vQEIjOM1+CRMWoUE56bS+akLRNT0QlMAiFY8stjaP3319gFNtrtvT2lHRe7NETdS2+w8urzfUdz+thnqSeZnwgSWTSPJeeeZGpAdiVF0AtoxyVUalN5x93UPvdQwsZxQLTi6acx+s6HUVGNsyJK5sTxjH/2bTLGTooZ7nHfkzJ22Ko/XkTd869hl2wcF4R2HEJlNqtvvoW6lx5LaNHT10gtybRGo9GOw5LzjsOra0JmJJhu1tMllIeVZ7H84plEfvguYeM4IFrRYScy9oFnKD7qaMY/9w7hEWNjhnsi9yIs4wtbdeP1Xfv9NgBae1g5kmUXnEVk4fdpsxBIKcm07xGv+PPvaXr/X1gFffD2aY0IgVvfwrKLTzdST/iZ4nFC2CY1reCAwxlz35OEBg83eZiJ7AxoU73Xrali2YUzzMvERiaAv7r26ltYeuEpJoO9G1mEZCF1JPNXV+3zvqbi1j9iF/WdHaE9D7vQpvGtj8zWk0xsFQfE0vCMpEHiqo1amRrgK68+n8jiCrMf2QejjPbMQqBp7t+peeIuf382taNZ6mqQ+wH2q675DV6LY4q19+Ebpz2FzBasvnkWqqWpdwVGA72xRAnmu2aa//4ONU88hlVkbZCh3/P1FDJPsvpPV+LWVSe1mGpXSFl5aCElLf/6kPo33sAqSEIwnlbIbEn7dyuofe6RmBJiMiCk8V2tvvFSSEaikjZbbNHF1dQ8ekdS29oVJJBwxOYGw3+rap95CB1JXmqaViAyBLWz7++IkOhrKA+EpOWzj2n6+BNkXnKiW7UyI3fN0/eh2lrNAiVFo5n0ANmXdX7WgY7JI7X88wNEpk6ezaA8ZJam7ev/EFk8v0O8pA+hfbG+xrdeRrcn74VCKUSmILJgGS2ffWzuJUU7AcmfLgOlw6oKnFXLjTphMutiW2Y7qH3Bt/7t9HFRVZ9Ubd9+AXZyV3pCSnRU0PrFP8wHvahhvjGQApKZ/6jWZqPPmvREagEeeHXVybmcTzK3thphkbTyh4Dpa6FxVi83v6coaT11LowNZZfsbaEvkzkus3I27PoJXzaFvqofnZ/M54WVX4jIyupdwICflW1EUxI71CT3QnjkWHM7fT2U+g20cvPNyrI3w4mUvZNOF4AWhMqH+/eS+Ck2BlJAMuOzsYvLyBg1Hh1NrANNkKAie8vNsAoKwJPEzTQh0VEIDysnc+JmHffThwgWNeHRE9BuLwo5CPNC6UgvJBWUQoQ12VtM9s+VmvkyZX4yhKDo0BNQbSruDCERCuE2eGSMHsn45/5O0eEn4dYoRDgU5/EWXpOmaNoJyOxc40ro844358/f5+cgEht5hR3CrVUMv+omSk89G7dKIULxtdUog0N45CByJu9qzvdjKg8dVPkoOe4s8nbbGrciigiHu7az/KIMRl7cIWP0KMY+/DJWbh6Dz72M3F02x1kdRdi2743v4ikKgQiHcGscsrcax6BfXGL2EpPQ6cbbrsjf6+fk7T4Zt8Y1be2G3EF7ndUOpcceSdnp5zPssj+Rt9s2uFUOItT98QhhMqfqFGWnnY/MzUvSC9U1UkPtoEpaZhZj7p1D7i6TcVZHUS1+EYhOhUC1o3EbPNw6l4L9fsaEF981Yc6ui11cxrgn36Lo8ENw61y8Bg88bcoOWnaspI12NM5qh6xNJjD2wZexCorWuI8+b6s2o9LIW54gc+JonIqo2cz2yRT78TfcvSYPt9Zl0JmnMPK2x004UUYmYx9+lbw9dsapiKLdTsf7bY2dQ2miK6IUT/85ZaefH0stTBVSWugerQkNHcGEFz9k5A03kb31tohwFjqq0RGTUBIqG0ThAQcy5v4nGPfU3wgPG206zbZBK+ySwYx94EXGPf4i+fvth8jKxmtSuHUubp2LalHYZUMoP/98Jr76dzLGbRqTPEhuWxUZoycwYc5HlJ54PCKUjVvn4Va7ONUubrWLW2dCvXN33pVxjz3HiBsfQNghQxxtBPzGP/suw664AruwLHZ80NbgHDKrkGH/91tG3/08wgqt8dKmAmL2cy/tvcnEcXO33HwzdC9EQTYYa0U0RJcvxa1ejXajWPlFhMqHYeUX+t/1Q3Q6EyRYnvv37axcRtv3X+FWV4CUhIeMJGvzrTvOkUp58k7Xji5bTMvnnxBdMh/V3o7MzCA8fAxZm21D5iabd3y/M0E69ZVbW0XT+3Np++qfOJUrEdIiNHgYmZO2JneXPQkNHuofk0TZUgg45EWiUevddz/46wH77zsl9cLE/mozCOgLDx9JePjINb+jlLl5y2IdyzmYVj0PIQShoSMIDR2xzmVMzUuZWnnyIBpCa8IjRhMeMbrr7/kh2uvEq8X6SmEXl1E07WiKph3d9SmC9qaBbGjqSQYdemPg7yWasEJBRw2lnjXvg5J/yt8vDJxCwrfR0kTdMBiZlDJbWp19VwIjytfd/foLoeDFNB0VjHRm9bpGCcQ0QHqQrDP8kabX75+QbGQVqL6BlIgNMYk7v5hpjtQnkgzgfx4DJBtAn0MqrWWv9tMGMIA4IcMhO8cyRmL6pBwP4H8KA9PlAPoc/ZNkWscqp/0okEa6Fr1B/yNZTMffd8z28wfQIwKvfz9uZ/8imd/hOtpOw5t/NZ/18wfQLXy1Ru1GO9rZD9vab0im/Q73mhtYeNIU5k+dwtLzju/INkozTa4NhXZdkBbNn7zD1ztsyopZ55oXrB8SrV+4jIMMbLe2koUnTqH5438SHh2m6uHHUZF2Rv/lqQ6hu35TOnn9iMmsv/caC085HNXWRsWtt6OjUYZfe7fZ5yU99iXjQdo/kYBgTuUKFkzfl+ZP/mnUcCJRQmUhap96jkVnHhmLtu3vI1pAsIa/Pc/CE6ahnTasXAu7zKbyzntYdvEZfrW7jSOvlQykNcliBFu1jAVH7kPrl//FLuoQKdaug10Wou7ZF1l85hF+Kn7/tdECgtW//CSLTjkScJBhiXY9E6RZZlN5130su+h0M3L3E6KlL8lUJ4IdtS/t33yPXbiunlcH0V5iydnTOzq+H3R+ZwQEq3v+ERbNONbUSQ+JNbLrtesSKgtReff9LLt4BgSKPWne1vQkmTIS5U7lSn44Zj/av52H1QXBAhii2dTMfoEl5x0fK9CV7p0fQLuOIdgLj7D47JOQGX6Zmy4kFLTrECoLUXXXvSy//JwOmdI0bmv6kUwpkBZefS0Ljz+Q1q+/65ZgAYK3vPrRp1h2yYx+0fkQjGAh6l95isW/OMnollm6W42O4KWq+PMdrLz2wr7T8A9mhA3UC0kvkvn1LFV7KwtPmUrLZ/8xNlickpfBW155x72svuHStC6gAB1TZOM7r7D4zOPNCGbpuDQrtGv0cFddfyOVd1678cvfdA793sCCrulDMq1jCjhLZh5N07sfG9HeeAtFBKfxjEDvymuvpebxO9K29lCg+N3y+UcsOnU6WMpUh0xAFEUrD7vYZvnll1L33EMbrfxNUMzVq69hweH7UvfCo75TuHfnThuSad/QX37FOdQ++zJ2aQKVSNY4kTmXVWCx7MKZNH34t7RSggY6FL8Xz2fRSYeio21xVyJZA1qD9rByLZacdwbNn767waN38BycihUsOHJvGubOZcnMk6l74ZFev7BpQbJAB7/6oVuovH3DCkWYE5rKcUhYfNYxRJctTBsl6MBG9JoaWHTaNJyKKmR2LzRsO5/P0qBdFs84Cmflst631RcGdCqWs2D6vrT8+z+EBocQIVh81kmdpNsTI1rKSaaV5xewepvll56PVWhtcKEIwBS5ypI4FbUsOfcYtJNYVZI+QZD8ISXLfnMSrZ9/YxS/N1Q/VilktkV0eSWLzz0a7bmJtzUo/VhXzQ/H7k/b198ZezjigIUpXnv2iTTOnZPwaJlakimFEBKnciVLzjnOZI/IjUcE7fqq1+9+yqobL/FXnKkbzYK0v8q7rqNm9ksbVcdfu8Y+a5z7Matvujyxtgb1FKJRFp1xKK1ffNOx4BIYAlqABYvPPIa2b75IaLRMrY6/H7az/OLTiSxejcze+LLj2vUIldhU3HYTzZ+8m3D5m412Hz7BWr/4Byv/cJl5iBvZTtSOIdrqW/5Iy78+jLutQT2F5Vf8goY3PzSV+dYpXquQGRKvuZXFv5iOam7yD+55QJDgJT9rnI4to7oXHqXuxaD8S188fI32izIsv/QsI9Kb7K0nbbJIdTTCsotOQ7sewuqLqdu3RZVm+f+dhY5G6WmbLXgO9a88TdW995v67k7X9rD2PKx8m9Yv5rPyugs7nN5dwLKs2BAm8UAmO3JBG1EU1dLEqusvRWaJvp3GlMLKtWn5/HuqH7qt287pC2hf8KTqwVtp/sfXWHl9uNr1K+S1fPo11Y/ebnRj1zea+c/Ba6xnxe9/jcwUPWromtHSovrBe2j94tP11hPtnJyUUn2y2tkP0v7dcmR236/8THlCQdV9f8JrqItlYfc5fHkFt7aayjuuw0qCxLqpgymo+PM1RqtWdt3W4DnUz3mCyPxVcT4HjbAEql1Teff1/ifdI2X6ZNp1qXnqbkRmH49iAbRGZkoii6qof+0581ESbLPgGvUvPU50aR0yMwnVQbRGZlpEF9dQ+/R9JtixS2Kb0ab5H+/HanmuA7mu5pspXAttX31m3E/rIXHsFBvQlN7Bf3vav/2Stm++QWaRPP+VNoVRG998CUhOkYxAF6z+1WcRIRHb1ehraKURmYL6l5+KOX/X/+UulH/8PArV7JldiLVLZAvpC7r0fC9JJ1nQyS1ffopqofvGb/RrK2SGpv37/6KjET8mqw8fujYyV25tFe3f/QeRqZMXVKkUMlPTPv9boiuXrqcwhml73p4HmKKxgg7xQKVxaz3ydt8VEQ6j2rTRSrNtZNjGrVPk7PTTDp9ZNy+s1EkVlu+As2KJ+UdSr67BAre+Fq+xruOzPrucObezchluQ2OfFylb6+IgBao5SnT5Yv+TNa9tSuEoig45jrKTjzRCevVGUA+RweBf/Yrxz7zPiOsfwMrOx612cGtcoquj5O81mSEXXB1bPHQHG8sK+9OGWWf3NQKVo3TaS+wjaL8WnmptAU+YjIpkvtPCrKJVe2twQ119CREOM+ovsyk9+SMiC+chQmGyt92BjNETQCmKph1HzuRdaHjzr7jVVWRO3JTCgw5FhDK6nmrXgi2lyEqqC8NvaKh8KGZ87sU5OjcqoYcmwNPYhcVY+cUdn/URgmW8yMo2+4u9PY/VywhYrRAhjV1Yas7TVVM7aZvlbL8rOdvv2nG470MDCA8fQ9kpM9c6f3wqjlKvPYb2NXwDMnuLyb0r3iWl0ZRt9+OuEpEslxIVEWRuuqVRoFbd2xIbDP/c4aEjsPLz0C6JX08II7icYFsRAu1q7NJCMkaP9z/rZjARwhSNdaIxMgvLwq2rxalcjVdXu8bXE1HTTrrhHxT4zN5qBzInjEG3EXcamwiF8OoUOdttz9hH5yDCGWgvAYlOAShN4RQjgdnn5qgw7hm7ZBDZW22PakugSpwQICx0RDPonHOR2dmmMEacD1ZYFqpVkDN5d6zC4o5sru6PQoTCqJYmKu+6kXlTd+KbHYfx9XZD+GbX0cyftisVt1+LV1/T495l575NgZ/MdLwIZzB45uV4zX7dye46X0pTKKLGIXOTMYy6/Wny95nK0Ev+iFevQIseV6kiHMKtc8nZcUsKDzzcd5ImIe3U7+xBMy70/x0HUaRESAu3yqNsxi8ZduVtDD73ctw6FZON7xZCmBI7UpvrQs/rGz8Ko+2bL5g3ZSeWnnchzR/9g/Cw4eRM3gErL5fGuR+z7IJL+f7AHWj98tNuI2Y95cVKrKfGGetvRRQfeQrlvz4Hp8Lxl9B+YYjOmvRCoNsUToVD7i47Mf7ZtwmPGIN2opSech4jrrsW1ebhNnixc6+jjS8EbpVDeOggRt36OCKckTQDPLCn8vY8gPJf/Yroasdo+Af3Jq1Y2engM9WmcGtdyi88j2GzbkVHoww6+2LKL/glTqWDdlSn42WnH8uXnodohUv5+ReSs8PuXYscd4Yfah1dupCFx+1Pyz+/JX+/7Zn42ntMeus7JrzwDya9u4Dxz75A7m4/ofU/C1kwfW/av/9qPa6RNZG6DHL/LRj2u9vJnLQVlXfdTOSHb/HafLFd/6WXmZAxYRIlx55O2Wm/RNgh41wMGZtq0NkXk73tzlTc/AeaP3nH18LvfB2wci0Kpx7IsN/dRMboiUnPNBf+XunQy27GKiyj4tZrcaqbERYxfVutAA+EDVk/2ZTy86+g8OCjfePdtHnYFbeSMWYTVl1/Jc7yKrDM9wNTS3ugo2Dlhxl+1cWU//p3finu7kd5o20sWD7rHNq+ryR/z60Z9/jf1pC2l1nZFOw/jdwd92DxWUfQ+sXXuLVVvnSC6tZcFM+/9MrxW2z2k0fHjxujtNYyVTr+2nVo+/oLIgvn4dZWmE3twjIyx08ia4ttDbk6fb/j8I5ObJ/3Na1f/ovoikXo9jZkdg6hIaPI3nIymZv4BbtSKWXgr8aiyxZS/8pztP77E5zKFaAVVlEpmWM3JXeXvcnbc19EKCO2sR6Df+9u1SrqX3mOpo/fJrpsAaq1GaRFqHQoOdvtQtERx5M5YbO4Vn/BCrLl0w+Yd/AeyMwMJr7yEVmbb4d2TKpe7Lt+uJJ2HXSkDZmT30UT01TH3yRVhMjeanuyt9q+y6916NLLtQ63YnW+Mydu1lH9bW0EQ3oqtTL8PcTwiLEMOvvCbr/a2X0QgzR9ZZcNofSUmZT6LgXtRM02TydCBLmr8aJ29v24NYJB5xxG1ubboSIRpG13cnEo/z+e7/kPxe3CSD3JoCMiQis/bDj4g7+/KHrQ4Q86swdt/HRAsCrTvh0UG6m09sNsuq87sIaGvxBGsz8U7jiH8vz2xkEwP0JEtTbT9NFbWLmaoqnHAiAzMta6sET4teoTLUSRFiQDYkv2DZqsN1QbP1mQcl1XhhDx3/vaGv6dSv8ktGL2R6LIwnlElqwgNCSb3F32RrW1UP/KczTOfYX2BV+hHZfQ4GHk7rIPJUefbIq0Kq/DoOwB6UOyAfQevbSjjcEuiS5diG4DWZ5F9SO3U/vk/TR9NA+ZBeFR+QgBrV/Op+6Fd6m6/zZG3nAHBQccEfeULAGk1Q/e/gH0GZy6arPj1ljPissvouXf8yg9cSqT3v07m32ynJ/8fTmT/vY+JcccQHR5FYtOm07zR3ON4Esce9ASkhNXNYA0RkAUyxj6pScfx5j755Cz7U7InDxkTh45O+zO2Edeo+Sow/AaNCuunImOtvvT/np9jgJSnRI3gLSAlZsPFuiIQ2hYGcP/8BeziHBdAtGVINl6+O9vJ2NMES2ffUfTh3P9FfM6zlgthEBDGwyQ7EcOM4OFyociw+A1Kwp+NgUrryCWdB2Irgg7ZNwng4aQs/PueE2C5k/e9c/T1UgmQGsHUhi0OIDUIzCTwiPHYRVko13IGDvJ+MS6ZIWRkQoPGw1a49VUBGfq9gJSSpHrxz0NkO3HBj8iJjx0BBmjJ6AjAremwji8u+SNkZFyayrN6JaR5X/ePXWkFCK0se99AP0HRibKIn/fqYCm6Z2/GuVH1tr4ViYJXDU30vLJe8hME65lTtL9NZIftDiAtILx4mtKjjmTjLH5tPzrOypuvxr8CA/teTEiIiWr/nQ5bd+tInPTwRTsf2hs16A7DBj+P3YIifYUoSHDGXrZDWgFq6//HatvuRLV0uSHXll4DXWsvPYiKv9yGyIEwy672Q+GVD3H+CepKQNIYwjLOFVLjpmBW1PByj9cwfLf/o7aJ+4he/Ku4Lk0//ND2r6qJlRmMfy6Gyk8+JiYYF5PGCDZAICO4MrBMy8nZ/s9qLrnVpo+epPap54FAaHyQspOnc6gs84ne+sd44pTQ2sJJltpwCYbAODnXyiP3B33JHfHPXHranGrV4MQhMqGYBUUmi/GQTDXddHQDmB7StdEo1FIRs7lANIfQXweAruoGLuoOPYnU9NJxLUp3tbWpl3X+QHAdrX7bW1dnQvYA3uYAwA6SNRZEtSPXYv3DKsrKoXneO8ByNL8/G8aG5u+cRxXA2pgA2AAMQQa/nEGKPqh16o9EhUrVq6YN2LEkI+01kLutdderhNpv3t1ZaVgzRSMAQygN/CWLlsunPbolZMnT3aeeeYZKWfNmiWlHH//t998+2VzS4sthHAHRrMBJAJNbBSLVlXXhubPX/D0lCkHPjl79mxr+vTpnvAzlNScOa9PKizO/2DyttuUZmVlulrrARttAD3CJ5cG3Oqa2tBn//7326VFhVO32267dkzIjxYAAePmzHlt28Lighe33mrLEXm5OS4mSmNgV2AAXUIIoQDlup69dPly5s1b8ERm2Dptr732atdaC598HW6LgGiz58wZWZSbd98mEyb+bNjQIfh+tAFbbQCdIfC3JOsbGvnm2++q62pqL5sy5cC7AToTLPhyDAHRAF559Y0ZhQX5vywuLtqsrKyMjLVTpDYypBCItSUjNybSwczsRfOUUhtFUUFrjdoosqma9vYI1dU1NDY3zW9qbHq2trr59mOPnbZy1qxZ8sorr9SdCQZdNLvzF2fNmhXectsddssIWdsKwVCt+3JDXfRZaqTWaIG0hdTZKRuSFS0gPCFUQlRTCWnMCkB7WqvWxG4u3tNLhBARNJWOcr5a2Nr6799Mn94G8M4779h77bVXl+VV/h/lVEX2rdaM+QAAAABJRU5ErkJggg==' +c23 = b'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' +c24 = b'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' +c25 = b'iVBORw0KGgoAAAANSUhEUgAAAJkAAADICAYAAAD7jkPoAADEHklEQVR4nOyddXxdVdb3v/ucc/3G3Zs2ldTdhQrUaaHFWtw7wODOIDPIAIPP4BQY3NtSo1Spu6WWNkkbd725euT949yk+MA8lEfe+X0+bZJ7j+699trLl+Bb+Pjjj+Vzzz1Xa/v7s8++7ONw2YcLWfSzKEqqYRgRhmGItu+FEAYGAtDB8PIjMHTQMZB+7MtfA0m0ohvGLz9BoGOYD/Bfv/tvAiEMw0AIw9ADAgICIfT/7of6HsIj5TIQPxi0tudHN1QDURUKBQ/7Q/6t55511p62Y75PQwDi+18+8MADyuBhIy5yOZ1XRkZGDExJTrZGRLixWqwIwQ9gAALxo98B6LqB8Wto4ycghPjW0/4ymPf+nzaNbfiVL/O74l/MlwEhVcXjaaWquirU1Ny82+Npne9taXrz3HPPDX6f0AScJLBPFy4ZERcV+XxO5079U5ISkWUZQKeNlv578V+n1P/gt4YAJF03qKyqJv/osX1NDY03zJw57ZtvE5po+2Ph4qVXpyQlvdirZw/ZbrepgGQYxv+MfeY/+B8NYe76eiAQUPbuP6BXVlXNmzFtyqtttCUAli79anZmVuYn3bp21mVZNgzDkMMn/7c+/H/wvwemtCY0TdPE4fxjUtHx41dMnzJp/scffyyLrz/+Ooo4OW/MqFFpFouiG4Yh/4e4/oN/B2FC01VVZcu2HcGmBk+PadNOL5I8dt/Y1NTUdItFMf5DYP/BfwVCCAzDkBRF0XO7dbPrknYNYEiSkLtEuiMM/iNY/we/HURkpNuw26yjwDSLKIj/ds3xP/g/gvBOKBRZFoosxz3wwAOS8m9fzTDMfyevzk8ay/6D/+8ghDCN9YCCENq/OuHbMDTNpFZJ+gFRGZqG+JHP/4P//2AYRjsPUgzd8PzyM3WEaaBFa25Ea2xA97WCrGCJT0COjjOP03WTCP+D/+/QZrU3DKPdC/jLt8sw4TQt+4Taf76O7+BOQlV1GCEQFrAkJxA16WxSbrkfJTHV3Er/w9H+A34hkRmahpBlGr54h6IrLkb3gzXDTsSoEchRMQRLj+Pdl0fVc6/Q/PUiOv5zCY4e/f7D0f4DIExkuv4zTmTDQMgSWnMD5Y/cCgKSbriS5JsewJKS3n5M667NlN13Hc3r91By15V0Wbg9zMn+J7g9/4P/TkhgRiv8FAxdBwSt2zcQOFqDIzeLjMdeMQlM10xuZei4Bgwn7aHnkN2CQFE+am2VSWTf0kDbFNIf/OPkT/iPwe7/Gn7BdmlOebC8GD0gUOISzS1Q10EylQB0HXQNJSEFyQV6aytqSyNKYsp3GNnPimjiR381n6Cd6gy+9et3iNH47n//Ftq8He2X+YnoIvGDX37sGPH9D372mv+X8SvsZCZXkqw24EeEekkGTTUHUjdMwvsWdN2gvjWIrhtoho5NkRGYE2tVTLlNlgQWWcII/95+52/N6r+e4P+JUxh2qLS/yPdMP99aHN9fJ99fMsbJE74LYY7Oydi9Nqr+KYjvELwkfjom8L8AAb+GyNqNHgo/+QJhGUwoMsJqBUAzDGRge0ENp9+3mJgYJxEOC7Ik0HUDWRLIskRI07HIEpKAkKZjtyjohoGmGzit5u9CgNOmoGo6iixht8iENJNgFVlC03UcVgVZEhiGeawkmY/usiltvrX2x3XaFKTwyEY4LHRKicRpUahq8iEEKLKE06rgtCmEVA2LLGNRBHaLjG6AzSJjt8jYreaC0Q0D3QBNN8iId5mf6SDbLSjhRWNtG/lvsfiwkfzkrPzLyf6FW8J/64ITSBB68MEHjX9NZOE50b0eDB0kuzP8+Q+5maFroIFw2dqPa5vTI+VN+DWd1Q9NISnKgT+ko+k6khAEQhqqpoMQBEMaalhGDKoammZukf6QiqqZn/uDGmqYU/qDGiFNRwC+oIZumMd7A6pppzGgNaBiYBoHWwMmt9UNg8bWYPizEBsOV1FwqBJ0g6iMGJrKGiHSbj68L0ROTgJxEXa8ARWLImGzSGi6eY388iYwDJx2C956LzGJETT7gkQ5rThtCpaybVjVFlRLBNbIBIjJJmh14bCYhmubLGFVBLphIMsKdpuFEAKrpmNoBoosochSO1ErsoQ1/AwAgZCOL6ThD2okRjlJijA4VtGIw6ZgGGAJn+u0KtgsEnargsMqY1XMRRTnsjKoSyKJUY7fzPJkRjILnxDiFxBZGIammidbrD/2LQC632/azRQL4nseq0BQIynORaekSADc9n/z6U8RXl1xiHsqmnn6j6ehSIKv9pRy6/ReXPqPdTwyZyCT+2X86HmBkMbWozVc+vd1zBnVicLKZiKdVnpmxvDIR7soPVYD69+GUEP7OTlRCdyTEomkqbzutZGiwFlWL15DYrdqZa9wcpoi+CzByV+uz0QL6u1MyfjOVmr+IWRQbRYkWXCgys1DH/Zg0mld6ZcQgarp+IMaQVWjyRtEEgJVNz+TJXOBf776COdP7M4HN41F0w0U+TfigOF8EEX8Que47m01xQq7PXy+8cMTdR1DB2G1IWw287PwsnDYFCyyFN72xLd2W8O0wynKD66n6zqGriPaFIz2M8L/azoGBkJWILwdGZoOmhZ2e0n8nFzSptUKAS98dZD41Ci2Ha5EFYJXrx3Jq18f5q8XDuaMPmnhbfak3NJ2ns0iM7p7Mmsemsp5T6/iwXMH4A9p7Cys5ZG5A6n1S7wdWEn+xi+RbHZ0VaWypYZUdw2DrZAOPN8Aw2IhSYITHrjPBa0VEBqRyexREdAQBOVHFInvvAjgUNl9MIY87VwW3jn+J9/7+5gtiW/JwL+9yUnRND3wSw40/D5zu7S1saDvmiYEoPu9GCrfmmDal15rQEWRJVMGOul7ACEQigK6TrCsGK2pHjC1WEtK2klj7rf5uGGaVbCc5Ja63weAbHeAHD5H105qwD8CTTeQZMGW/Gry9tRw5viOzBrekWZfkEv/vo5H5gyiY1IEqm60y1Rt+PaWomo6WQlu3rxuDHOeXc1FozszuHMC85cdID42kglnzeHg7i3IgQYEBh5D5vZGiX8m6XS2G3QOytzdLBhmNwgpggw9xNVOF+9e2AFag+ZYByRCqoxqmFxBEt9a5AI0XWDD4NntuVw1cwC6YRBS9e8oUN+FQNV0LIqEVZaIcvzYDvXbQDHAG2a7P0u+bZMobHYMTTW3TyEQ38qcMgIBDA2T83zP0h9SzReCMI2FicYIBah++WkavniPYOkxDH/A1C6dbuxdehF7weXEXXDlSZubYbRfu3nVEhqXfILv4B605nowBEpsIq7Bo0m4dB7WrJwwJ/xpr4MAXliax+3jdnOYZP655hiBUIjbz+pjElhYyfjZQZQldN0gNz2arX+dwU1vbGbtvjLOH92ZJm+ATcckep7/J468+Uc0IWORIK9V49UmiTuiNK5x65xXpbDVL1iaGOKGJitPvNgZV1QsX+yMxaLodI5roktsMxZHEAwBQQVVlTEwCc5iNSivttBoGcjkPtEIDGyWn15gAEJIyJKg2Rdq1/D/y2ib12/7LsW/CoUVAnQdPehHALI7AiEr5hbVdl1NRciy6SxXze3SNHXQvuQDqtbODcytx8AI+Ci6fDqNi1YjR4KwAnKYK/o8eLZtpvmbzTR++TEdXvoQyR2FkGWCpUWU3HoVTatXgW6e10brgaJiPJt2UPfOa2T9/U2iJs36UfeWbhhIQrC9qJWa8q28f2ERqU+X8fRV/Th/RFb7cbJkCvg/zRHCWiWgqjqyJPHiNSPZcKiSp77YS6s/RK/sWM6cMJynN41HP7wKXVZQJIPXGwxGOmRGWjX+Gq9zS63EjArBC8924ZAxlnkvpdA/q5k4R4gPDmThDSmkR3oZmlbLqMwqMuObwYCg34rsDLL6eBI5mV2QBajaL5etBAZZCe5fdOwvhW7o7TLjLzPGSjJ6cyOSG5q+WoA1oyOSKwpbZkccvfqZBGXoaE0NJiHb7eYW+C34glr7ajF0DUlRqHz2IRoXrcaaZkNXQ9+NUZMFkksgR8o0Lv6aotBZ5HyyjmDpcY7OGE3geClKrAyGMHMrw6cJASJSRve2cPzaC+i6Yhf2zj1+QGhtDPFvi/Yzr/demjwao3tlcf6ILEKqRp0ngF2RiXbbkIX4Sa2rjVglcw9r/3xkbjIjc5PZdrSGBVuK2JZfhW3YNfhbWpHLtoCioKo6D9YKPkiRyLXonGcXPKvIHPAO5J0Dmey+fRWyy8OLX+Vyce9qIp1+dpYksqUsnnf3Z6NgcEn/Y5zVrRiAreXJDB6TFB6HXy5XBVUdf+hXRXz9Kvw8kek6Qlbw5e2ged0alDiB78hRCi6ch5BBjgBnn27EX34D8Rf/wZSVQmEzx/deUtNPygdCUVDraqh99yXkOAk9FPyhgTFMcIauY0lSaF77DcW3XYr/4B4CJ0pR4iwYodAPn9kwXWGS04JaG6LqH4+S9dz75rbZ/lomYew+0Urp8fWcPbGCDUeSWZfnYdqjy9l/ooH61iDCMEiPcXLTjN5cfXq3doL61q2QhOBgaSMrdpdwrKoFwzBIjLTTIyOGYd2SGNw5gcGdEwAoqmnlrCjB/leuQ/hrsMgSx/wGzzdJPBCtMzfGYGdZiHv+vpP8N+o57/qNDOsTS3HKCJ7c0pWiez4kzRlkYFodmYkNTJ4/hVVFKczuewyCCiWtiVycGmGO8a+Q3X1BjbhTqO4rAJr6QypuC0BsWrGAggvOQnKCsMhYYl2k3HEzurcVz8ZVNK/djWfbdXj3bMIIqQgLSBZL+CInCafFF8JpM2laAK07NhCqakGJkk2N8GdgqCpypETtW28jWUGJFj9OYN87R3IKPJtXo7d6kFzuk/ICJtN5+NM9XN9nFzg0lhRkUl0bIve0KB44byBpsU48AZW1+8p49IMdHCxt5NnLhpoEKoWNukJwxYvf8OHqfAblJjOyezJZCREEQhq7CmtZuqOYrORI5k3MJcplJTvBxR3nj2DumunY8uYTRKBIBu82GIyyy0x0aNwQDT7bMaxSAn1zk1m8/DA33VPAazuyufL903hnV2f6ptey9YZFOG1BpuWUgS4RDAia1EhSY2zhMf7lVGZTJBKjHOZ5p8Ds/9OcLBxOLUdEETnudHwHNhOq8SC7rURPno29a08AmlYspPjWK6h9+z0kBwgHWFJMm1Kbcx3M+W3nZEDg+FFQf0XItq6jRMtmxOW/IMq2GwoLqDXVBCuKsed0B8NACz/HmkNNNFes5vxJlbTWRPHS1lSG90vkyUuGcbCkgQVbj9PcGmRC33QOvnQ+Zz2xko2HqxjRLamd0ADG90rjz+cNIC3ORYMnQN6JegKqzum9U+mUEkV5fSs2i9xuvukUK0P2YHyHPodgA4psatYP1Ql6pEh0dsGkKh997pDJnXQPvs6fc/ea3vh8Mm+s68n0AYW8f946WhpdVHnsDEiuB1UmoMlYLC5c1p8X9n8MIc04paF/P0lkbRqZe9hYcj4Zi//wfk7cfDEt6/Zw5IzeRJ95Hu7hY5HdkcguO3q0Dckmo5V5cXTvg7lvnRRkWnxBXDZL+/V1byu/1pltaL9SbhACI2Sg+0zN2PiWDejhj7dw39A9CEeI97dlEdJd5B0vo9sfPyG/rJGxPVMZ3yuVw6UNdE+P5oFz+7Ghjcgww1cMA+aM6sTXe8uY+9Qq1h+qJDneTXNrgAirwpDcZOaOzmHqgMz2RZYe6yQ6Npqzb72XRS/cQ4NPQ5EFZQGDJxslnozVmB4DKw+uZ5neC3LOg1oP2YlN+HxWDtVEUe1xEPBbiXcGSY72YKgmYUmS9KuIpe3YFl+QBo9pyWqzB/6W+Nd6q6FjaBr2br3I+WQtSddfCUKh+qUPKZh7DflnXoDvUBlaQwCtyYvkkPBs+wYQ3zEdGHyXFcuR0ac2clYI0Awkpw1LnCkTabo50W9+U0GyupKxvepoqXXz+eE0XpmxiyavzpHj9QhJYkt+NR+sL+BIWSPVTT5a/Cpa2K1F+w/zl9ve2cq6bSfAIlPR6DOt6bJEdqKbRm8QX1BFCqv1KbEuUlywM9Qdb7dZaJqGjsAiwYImnUVeCaswuD/GR+djr4Gvnov7lTA0uYEHx+9jbFY1r27ryvEmF93imsCioukSVklDU/2EtF+3cAFkWXzL3PF7bpdtEBJCBnQd2R1FxhOvkXjNbbRsWotaX40lIREhyQQrS2lesYjWnbtpXPIV9R+9Qex5V0AoBLKEx6/itpuczACcvQYgbEZ4Sz0FEAI9CM5uOShJpsVekiSafDovfbmaDycfBFnjrb2dmZhdxbROxRjaQLCaNpSAppN3tBq7TeH11Ufx1Xl4+OqR4Ysb7QT7j+UH2X+4GqLsyEB8lANvUKWy2c/HGwrpllxLjMvK2UOyUXUDiyzRJT2G2vpW5v/9SR6fd5R9u3cgLBYkVePROuhnk8my6DwX2cqsmnxkWwwlDRauWzoQ790fY7X7uXbBCKbllIMuTGe9TccuWqjzhIh3W/l1lntBXIStbdh+c/xCC5xZ/slQQxihILZOXYm/6BqSb/wTcXOuIfb8K0m+6UE6L9hM8i13oTVA47JP218Awhpd+G6aruPoOwR7104YPuOUhGgLScLwG0RPOQchy2ihEJIkuP/jg5ydvoqOGR5qqqPYWBrPH4YdpNJjw+1SzAiLgIoWUEGRUQTMHJxFfGIEmQku89phk4VhwGk9UrhhRm+SIu2Emv1Ikml4tlplGlv8JMc6SYh0fDsSjin9MtiWV8HXuwqRRv4BzZWGHta+60IGDzcIgkBPq8YNe1/AevhtVs/bxKZLlmF1eVial8HeykjGdiwl2GoxtzirQZy1joJqs0zcz8ShnhyjMEX5Q1q7UnYq8AuvLMJZSt8SKnUDQwuZ/sxwWI+w2ki58zEiTpuMJSnVPC5MQN6ASnykuVoMVUOy2oi/+HpKbrkZxSX/thxNCPSAjiU1ktgLrkY3DBSLhR1Frezdt5QnLywGFV7a2YULexzHGulnz954rps6gEtHZ/DZ5iJ8ARW3w8Ko7ikM7ZLIoGM19O8Yb76SODlBPTJieO6q4Txw/gDWH6pg85Fq8koaWPLNMfr2TOXdW00foimTmY93eu80QpJEqy/AzXPOYK2zitcfvxuLxYrFUFndrPOhQ+YSl8oFiRqXvVfARWoMueMm89T2/tQH7Hw4ZxuuWECzoreo6EC3mGp2FdQyuXf0r5KtFEngtFr+9YH/Jn6eyL4luDcseJ+W9StB13ENHEHMrDlIdnNlq7WVNK9aTqiqBCU2mZizz0dyRnzn/JCmt9uYhCSBoRN3wdXUvv13/PmFSE7pB4GO/y6ELKPWq6TccTuWxBRUVUUoCne9s54/j9iMNSLItiNpeIIWpuUeh6CFRUdT6T7AQbe0KLqlR7OnsBanVaFrWhQbDlcS5bCQHuv6oa0sHEMWG2FjxuAO9O+UwEtL8hh15XCumtQdwzBj6hRJtAcVZidFkNsxjpAhaKyvx5c8jNjuY6g/uA5FsSAZGk/VGQy2SeQqBn9Lhgmf1DDWUs1p3WvonlTKgg/rKCgMEtvByY1zMoiJsjA0pZa/HTmBIOc7z/iT4xT+GVD1UyGKteNfEplh6JTcchE1b3yACAfF1sx/m5o3nqPjPxfjO7Cb4luuIVReQ1thz/JH7qLjO4twDRwBqgqSQlDV22UyhMDQDSSHk/SHX+TYrImYXPK/TmRCltGaVdzDepN49e2oqoaiKDyzrJhu8hJG92zA32zjjX2d+NOIfSDpFJYn8sGujtyd2wQIZg3NZtbQ7PZrrs2rYHhX05Kuh53q7fcTAjm8deqGQWqMk0cvHnJyCDFDXdrQFkpz4egcXlmwjyn90nlk7kAeOftdRg/pS1l1PYos41F1HqwTzE806GiFP8cU85d3XmFgIlSFJERQZ5YNtq6GaSsqeebJ3pzWX+bP2/ZSWD2Sjom2HyyIn4I/qOIN/Lzd8d+EAJB0Xf/RpzDC4TKeLWupffsDLMkWlBgFJUbGkqjgyzvA0TMHcXzebNSGGpR4BSVWQUmyEaqsp/zR20xbVdieFAhp33E0C1nG0FQiRp1B4rw/oNWpP3BF/WpIAiMEkstB1jPvgNWGJEFRbZBPVy3m4fFHwNB5cVsuYzKqSI9vQgtZeGpbVx6fuIeW1hbADJbUdTOKAeBASQOn90kL3+LkcOm60Z6EI4SpCMiSQNMNVE1vj075ziOGx+O84R1pVHUsFpnPNhfwwtoq5KFXo+kymmFgkQXbWw3me0wRZbZLMMBhYU2Thf1CpjnKwWLFSrdEhaebmnj0mp18+U01aRENvLW+tP35fgk03SD0S2yPvwICgTAIgCn4e8Mpcd8Lcw1Hoe7fSVsMs6GqGJrWboEP1dSCoSM5RPg7FSMURIoUBAoOozY1tGec64bxA+FSSDKGrpFy999wDe2N1qS2H//r30ogkNFaNTKfeQ17t95oIRVJkrnt7S3c0W8N0Yk+th1LpaDRzZw+BQD8c08OubEtXDPgKCV1ptCsyBJCCCyKRE2zn0ZvkEE5CeHbmCEyWtggK/2I41yWRPgaP3xMSZhh552SIxnRM4VXFu6je0YsU/sls+SVB7joiqvQw94WWYJ/1BvsCMk40HkoVuOgCqOcEvOcIS526TxdC5+rgoeFl6+u3c27f/uQ1xaspCVgOut/qlxv28daeDH9xm4lQwiBjmESmaLroR8tHBweIMkVwY9tY4amIyxhi/33V0xb4KLF0k65vqCG5fshM+FZkOwOOvzjI+SYSIzAv6dtCllBrVNJve9PxMyYixoMoVgU3l5fSVTLImYMrKG1wcEz23K5Y9hBkHSqGyNYU5zEtSP2sao4k7yyEGDKjlpYPlyxt5QYlw2Xzdzy22L/ZUnw6eYith2rMcfjV5in2g695vRuHKhswWFTWLm3nPlfbudE5iyMtGFooRBCkghqBvfVCuoMiZF2ncucIZ4+EWB5mcriKhVD13nCF8EtrkysA3ozpLOLbo56ajyqGR2F0R6S/mNQdR27VSbGbf32lPwmaAvxVPSfcFa1xYm5hoxBdks/7sr5kZEVsozWpOIaOALZFWGuyjB3crS5PL51SyHJGJqGrVM3Orz4DgVzZiBZFBDGL545oVgI1YRIvPoykm/6M7qqIikyVc0ary9ewqfT94Ok88i6PkzpVE5WQgO6JvPYxp6c2+04iivEmztSKW0R+IIaDuvJojHZCRFsOFRJUXUL2YkRlNV7+fibY+R2iMUiC2b/bSV7n5pFjMv6i+Pj2xJdpg3IJDXBzQsL9nLttJ4Iw2DmSBsbU2/mnj/sxjA0FBnyfTo310pMtOocjk0j4/SRlAzsT3ZuT57IyqBTUiLC5cbqdBLx/eBKfsIfGVY+/QEtnBTz32HCkCQMXcPeuTvR02dR9/4nKHEKhqr+zOUEhmYgOSSS/nBP+BMT3oCK9SeC6IQsY6gqkePPJP2xpym59RbzXtrP3St8rmJBrQkRe+4MMh5/A3QNXUgoksSd725lXu7XJKW3smR7DlVeO48O3AYhmeKGSJLsPqYNKmP9KpWvXn4JudNhKhvGkJ0UhSTMLX54tyTum92P6Q8t5Zaz+zKyezKr9pXx2Y4TOARcPq4rkQ7Lr07AaFMAbp3eiyseW4HdZSPGZaWiroU9lU60Xucj7XoLQ7FgtcD6lhDapCks+vgj4iJ+OvYrpOkQFvgNTK5b0hggya2Et09zm293oAvw+EO0+IK//OF/JX6WfEU41zLl7r/RvHoFmqcFYflpU4OwKISqQqT96W4cvQaYykOYiwlxkpP92FwIxSTghMtvJlRZRsUTT2FJsGCoP631CIuCWhMievpEOvzjY8BAM0x5aMHOOkKVC5hzYQU1FVG8vDuHlyZvIxhUCAat/HN/R+4dsxdPncTVjxxC9bYQ2r+InWuXkH3eBeiaqZXqhsG8iblM7pfOwu0n6JISxeL7J/+y0f0ZyOFIjjmjOvHE54kcLqxlzviujMpN4jK7Dc/MLK64eBfekn3oiplCWHX4AIbfh+qwm+FMstxWB6z9ut8XSUprWhhyzXxmTRvCC5cPbR99TdeRhURQ1fEGVNSwknMKXJf/woQR5mbWtEwyHn+JwkvnoMQoGD8iowmLglobInrKaSTd/Jd27bTdFhPSSIz8eeGyTeNMvedvaA11VL/21k8SmrCYHCxqyul0eP0LhMWCoZvabGsAXlz4FS+ftgeEwa0rBjC1UwU1PgefHe7AymPJnJ5dihwnuOf2Ig4XNmO32/AHQrzwVT7TzxFYJKk9XgygQ2IEN07t+UvG9BdBCNOXarfIPHLhYGbfuQDNInP2kA7IMpTUB4iaeBf+j2/FaK5EslgpOH6CK6+6igULFqCqalufBeCkSfL1zeVs3XoQt01Cjk4gduELLNn6PgtrRnKNeJT+XZMYl5tI5xjTnOQPaUQ6LKTEmjbPnwkA/rchIctoPxPdYMpMKtHTLyDljjsI1agI5bvWYaEoaA0qzj7dyHrxE4QkIaTvrrC2xNefhRBmfoCukfHEfOLmnEOoJoSwfP9+FtTqENFnTqbj/EVINgcYBjoCSQge//IYExK+pmP3Or7YmcPyo6kcb3Hw8s6uPLWxK1uL4pjap45tKxt44cMiLIpEKKQhYfDNisXklzcjhLm11HsCvLfuGFf+4xsmPLiUyX9Zxm1vbmH9oUoaW4MUVrWg/UJTwfchS2au5ayhHejeL52gL4giCzokRHL+0HQW3DWJGWedjRaWTS0WCwsXLuStt95CURTUsOjSdv8Fu8p58493MPuJGfR64gKeemc9yVsXktrQSmL1Ud74cDW1l03lmjl38N72CgBa/SGsikyMqy2R5Lensl+kxrURWsqdj5Nw6RzU6vDEGyYH05pU7J070fHd5Sgx8eFldVJ9VjWdoKr/IOPnx28m2gP2s154n9hZZ6LWhNptaG1Cfuz5s8l+YyHCZjdT8TCzz4/XBtmycwnzBlfwty+HcMnCISRFeHHZgjT7JUqqIxnUsZZFh6KZfd8JhKFjYIZwy7IEZTt5cf574WT4kzawtDgXydEOPEGN5XtKufaVDUy4fzEXPLMaX9Cc7F+jYcJJL0hRtYfy2lYOlTVxvMZDVaOX9Yeq+XDdYeSeZ9N50DgIBjAQyLLMzTffzPHjx5FlGV3X0TRT6921r4BHT7xHdpTg7d5XE2PxMaJXBgmP34M+cCwRTicXG3t5aPuzvP3FRvOZdYOAejJZ+lTgl6kUYQ5j6DoZT7+N1tJMwxeLsSTbCdX4cXTvQqcPvsKalmXmPH7P1tWWiOG0/lJXqQDDzLfs8MonGNrZNCxcgiVeCWuRV5DxxGvhfEMzdr+t5MFDnx7AoZbRgJ07v+pLrCPIVQMLCKkyS4+k0juzgotGlfDUE3spKa3DosjtnEA3TE748T8e485r5pKVGEGs28ac0TmU13tJjXV+5zFrmvzYrXK7J+OXCv4GpqHUIkt4gypn3L+YhEg7MRE2PlmTz5wJ3RiVm0yU04KQZJa67+X5XYdQtGokRaGxsZGrr76aFStWoGkaVotCQIM3DwV4r/+faJHs1EiZ4G3h9pGPc8PM8bxXvYzG3RVcmnMzE46vJibSia4b+MOGZ+U3DlIw3W0m4f7yK4cLcghJpsPLnxA99Qz8x/y4Bg8g59M1WNM6fEfQ/zZCmm6WEvhVEXWmAVgoVrJf/YyYmVMJ1aik/ek+Mp54/aRtTpgRp5IkKK718sn63TgcNqa8PQaLMBiRWUtFq5MP8rIwUOneQeWLlUEKdm1rT2VrHxgMZFmmvrqcec8tQghhlkrQDbYeq2bonQt5fukBmsOaWEKUnQjHL3csG5hcXRCOa1uTz8XPr6Op2c9lp3fD7bTiV3XmrzjE6rxy8subyTteTUJyGrc+/BAWQ0PXVKxWK19//TVPP/MsiqLw5pp8xtz0PqdvfJXLStfx+DAn557RlZ5ZDZyZ/Q6bP5nHlr0n6BCnIVmsPJF2AV0z4pAkgaoZuB2Wk+al3wi6obfXHfl1xhFhapbCaqfD6wuInPg+MTNnIUdEt1dj/DGEVB2BwGE7qWn+IoQd6cJqI/vVz0m+eR/O3gNPSrniZBiRIgueWXKIRKmKsTmNbDiRRIwjyPDMOjxBiRN1TjrEB5mTtZnH3/+GBo9AUU7G6oMAXTVtRorE8rV5fLa9nFmDUlE1nbMGd6CoqoUN+8sZ3T2ZPllxbR04ftH7tHFzRZZo9as88tlunlucR25mDGeO7sSxiiYm9knDG1ApKKpjw8EKEiLs5KZHE+e2ckgehq/TRDi2wvSXKgr33HM3M6dNQlec7DhQyMv1S0nLbyWh1wysnXsz1/0IZ55WDz4/Da4+3DLsNJRZV6N64e43LuQ6SwQX9Ihqr69hTs4vnJtfgV9vgQu7mCS7g/iLrjA/M4yfdQdpuml1/rncxZ9EG0ezWE0C+5HUNkWWaPIGeX1VPrNyvHx9NJmy6ijGdC+jVZdZciSN2iYHs/vW8PbWbDbuX4MiGeZOC+hhxUfYI9BS+iE6j0V2pnPXW+uZ1m82VlnC4w8xMjeZ3ORIDpY0kJ0YQaTD+qOTYhjmO7clyythn6aqGby0JI/1x2qoavAye1g2dpuCJKCi2Y8/qHHpmE68a+g0eQLEOBSiXVZqWwL4ghp3/eVxPrmvgOOFx5CtNgJ+P+fNuZjt27exZe4ZjPzEyfDkInK3OvhyzWq6KZ0ZnvMNKw5msfJINGcqW7ETRSjKxqZAHKn5lZyZ48YRFmNOgfUC+HeIDGjL5m7nXj+5lM3HDqg6uv6vM5r/1f2+nT3ehjaj5mdbivDU1vO2pxMYOnKEj3VFCawrSAJFQ3YFeHlrB/BHYndAyG+gCQl0AyUqFanTGIz0QTgiU0iNcxBtM9h3sJL31xdw2dguOK0Kg8P+y5Nv9kOc5Fgnv1U1g4/WH+PJhfvYu6+MoQMyiYy0s3p3KeeN7YzTKrNsXT5njMxhU4mX1MxU1u87wW2fHmLukDQm9U2hX4cYFEVm8/CzKSh4Ekk3sFqt7Nixnecef5izz72DvNdeIsmt8nxBCjQWMmPuLKqz5vLyWi95hw8yrkinZ8/bOR5yMXZsPxbdOoYlO0t+Xa/afwP/vi+hrYbFL4BumNqP9V+k+/+r+/0YMbfR3Lvrj4GugKwjCw0tFNZGLSqGJqEFLEguCaU8D7+vFWQriSJERFQ8BRP+AlIM47q7SXYbpLrtREU5qalr5ZHP9nDpaV0wMJNg26DI33qesHlGCkdiNHmDvLv2KF/tKcVhUyip97J5axFXnN2XtEQ3+49WM6ZnMqgqFgk2HWtETk/j463lZNQeYULJaq5Ry9gY2YUXqk7nRGUnZg3vCIbOzLlXE+GvYPkn74DVisVi5Y67/sS9ncaRI7fy+v5PGJGdz5+Tz2XaV3+lo3o6dzklDlo1Jnj2cv+Jj7kpegpXT78cVTfwBtV2eaxt+/+tceocVpxc7YGQTkg1/mVNiV+Ltnip4toW1u+r5dzBlRyqi2D/8Xim9S6hS0Izr2zrRFykl4v7FfH3vP40lsczI0rm0kiNXIugTm/i3ePvcyimDwe2JdPQvy8VhsKu7UVoAY3WsgYe+mAbD84Z/NPbfTimDOCjDQU8+tlu9uVVcPrITlTWexjVPYU+GZHER9jokhrF4SovS461cLg0wI7S4yglxxgXOMLkuu309uSTibmPj2ks4LMYlQ2lfyB6Xymn9UzFpvlw95qCuvArbEY9gZDKkCFDuXBYR1YE5nH+UwZdfGXUBAUte1YT+mwh7/eYxFSrjQcKFnI8BIOm92dsl0gUTCN5SP2fysl+BXTdXPl2S5tb6bdZLW0BhEt3V+IQ9XRL8LP0aDI5yY2MzKrFE7QiYVDdYuH9fdmMLt7CwSNfkqgo1Ogab9cLtno10ipW8UXyKoosLjYf78QWVze6JnbnoD0ZIzKGhz45wq46nYtGZRNjl/F7/XRPiyQzzoUQUN3oY+3+cl75+hDrdpRw+Yze2O02LprQnS/3VHC0VeBXrXy8vwpryAvlxXQKlDHJc4zcpiP0CpaQqQa5pR6eNWxkWqGzrFNrKNxct4ajRVG85p9O55QouqdHM3bUMNIe/RtP3XYxc+deyOtvvI7dZuOaucmkDx6Ix6dy2Z5i3pifx9HEYyzuch7dk5zcOXgaw3omce+V09maV8u+kkYSI05hSGwYvwuReQMhNP1XmjB+Adqut+5AGcGQzOKjSXiCVkJula8KkjhRJxE0JCxWO0U1QZ6uWEaKKOYOP9RqCmMcgqsjdG6ut/G8T+c+SytdW/cxvHEfm4stpEfG4HGnsc+Zyc4P4rl7YQJ+Rwxluh05IpK0xCiQZIrrvVDvNbWI+BgW7S7H1+zhjueKiW2pJTFYR5ynnBtC5XT3lpCq1lLU4qeTAp2sYJPh+YCF/YbEiwk6BwIGW7wqihZifKSDomArhqbz1up8+nRKIN6pcKLCwhsfL+byc6ai6gYhVUMSMK2zWabg/N4xRG6YyuKaABv+NJ4R4cje+hDc8+oXTE76iJLCTuxzzcRpbdv2+R+iXf4b0AwDR7iU5G+Fb8uqecV1BA07u0psoHo5USg4EZFGn5xYMp1e+mTH8OmaY8zMvpMzk/byh7r1DG06gCOko0nwTFyI2VUWioIWanSJUNgYXFNfzWeJ1UwTu7EpUGjAetVJ/0gnDYaNamHHL6zYFCuGRSFaqBilQYK+VmINP8mah+3eINmojLCCRwdFhlnVErtDVtKsEn2sBp1lnVdaBO/GB+imQbYVeseksDRhOFMjh+Ho0gN7aQUNjX7Wbj2O4rTyxT0TmTbAzNRXJPGDOmyarjM02aCYarqkxAAGBdU6i5f+jXt7LiIhCVpDCbxwxEeU82Sq4qnAqZXJwivDF2yr9/pfXyZ6uO6VJEyzwMHSRg6faAiHBekM7p7C6G5JXDK+C8W1rUy95XOmDcxk/MAMSut9LKodyaLIwXQOlDCpfjtjGnYxOFDKY+4An3vgzGgY75RIUATPNFn5o0fi+ViVdX7Buy0CVD/Lm3w8HWMwVIBdgk898JoHulvghkjIsJhv+mizYG1AIc1i4y0fXB6ps9QjUQmsTtcwtBDbfAZrWuAuNyRHRPOKsztfxw1hU2R3QpodRJCUmiqSoh106pbEul0lJMY66ZkRDcDRiibeWHGYIzUhImyQkxLHiNx0xveIYFyveI6xgiW7y5kzsgMr1n/M7Kzl7KzOZVJ0PutK00mNcdDQ9Mvba/07+F04maqZ5gtrm3T8K2mtzQ0DpvZmRkbofLW7lOtf24TQdUb1zeDB8wcwrldq+3lznl3HPVeN4LLxXXn08z1ccloXLn5oMbGZsRw10jma3pFX0mbQpaWQSd7D3NiUR05rMfagD28I7nRq3OSHqWUK3WwGD8To5FoF73kULmqQuCvGYItPsDEAV8dDsQoXN0lMdahUaYI6XfBJUgjVUFnggb/UQMAw+DgWklWokSV6xSdjdOrGCncP7rV0IuhOICLaQYIe4JrxObyx9hgT+6bz2pd5vDZvFJpu0C8rjrOeWMldM3rRITWWZxZu5p8zt2JTgng8Fr5aksqn66dzrMqK1uhiQmAfa46kUVy4lkNSFl3iGimvFShR/RmQ5Gbh1srfZqJ/Ar8LkfmDprFT/pXapW4YYWu+1K7Z5Vd4ee+bE7y34RgFB04waWw2e56ZhcumUN7g5bkleVw3qQdvr803iwPPHcRp9y/hhSuHcfe725l7Zh9S491sPFSBPxBi14EGDiT0IK+1G6TOJJtGMuoK6BUoIbuhkAtcNUzxNTHQaMGpg9cPf7RpZGrwlwrobYVPYsEuwGKFaRHwdBM4Jfh7NBghCEpwTqTCwNhoCpU4Frgy2O3uyEF7BhURaXglJ92zYujW6iEl1sYV47ty7sNfcfWknpQ2Bpg2MIM4t5231xzl71cM594PdrDknon0vfETemREk5yQjsO+izMHlbLlUCZ2ZyPNrW+w8MhgVDmHBP8ybn/T4MSJ/nRKzGNCr4Nc9cF4br5iFMt3HMFpO3U5lwCK9KMB/r8t2mLjf4nc38a1BGZmjyQLAhp8vqWcN1ccp7VpO3cNW4c7N5Enavuy4VArj3y2E0OHl748wF3nD0AIM/7r/ZvGsmp/OVdN6Eqkw8qxymYOPncOpz+0lMcuHMykvyznijN7Ee2wsGBTAbqi0BCMoygUxTdaf+J6RVJfWUNqqJlIrZnEUCOJoWZitBbigy1MCXpJt8ECNYgKaEJCki30xUKL7OAByU2FHEmlEkW9I45qEYE9Po5mrwGqBj4fgzvEceGIDtz89Gpe/9MUVuwtIzMpkvMn5fLF1uM8fMFAznt6FWsemsrlL35D9/RoMuJcfL2vlAMvnseoOxZQ3+Tnks9HsTwiwNDsUpYfzOKQN5mMBI0dBXE0eoPE6rvY3dwFX2sTN35+OqPHXkf3VDvzG/1Yf0NZ+ceghAyjVTXDnE+ZLhtUzSqL7cm9P3KMybVMU0cb1zpWp/Lh6v18vnYfXeILifb7kG0R5CTKTB+6lwv7lnLVgsE89mojWAxQgozunoQsCcb3SuVIRRPvrT/GG/NG89aafOZfN5ovthbRKyuG7hkxnNYjhVfnjWL6Yyt46upRzHzsK6YOzKSosploq0y918vg/hmszKumTI3nEBJomBZgi0x6SgSlRXVm/Yy2taoDmgFRDhRZoPqCJMU6qCqqZnjfVJbcNZ4jpQ2MvP0Lpg7vhDekMXtEDqsOVLFibxmXjevC3xbt5+WrR7DuYCWJUXbmjOrEZ1uKePWakfiCGg+c259hdy+ic3IkB188h5vmb+OFdw4x8o3JPD9lK9cMyGdCl1L2lChsq4nk1R3p3DfmOOuOdWSD/0puO2cgg7Kd7Y/cxslOFbuRjFPoU2i7sBmv9MPbtPn42iofKrLAH9RYtP0EMx9ZSt+JF/GnuVPY+8Y8LotfwMe37GL+WTt5ZVs2t386CsOAxfOW89WNm+jXJQB6BFe/vI3le4r5bEsBp9+9iP7Z8eiGwdzROQzvmsTfFu7nlum9aPaGWHrfJFbsKaNLShSZ8W4yEiK486y+JMa4uHvOYI7VtHLjlB4Mz4nhjB5xWDUvMwfGM6lnJKM72NAqKrl/VhfS3BrC10y8XWVC90gm9IoiU/GRKfu4aFACT83KZUj3eGJdCtFuO0O6pXDZtN7Iisz95/Zn0fYTvHrtKPYU1TGuZyoV9V5qmv2cPaQDumFwRp90nlmchyRLuOwKCZF2OiQ6GHHT58Rdtoh3Vh3gvrPyWHvFMp7Z0hX5TxeT/uRMYjJO48UHh+GxD6GyoZW7ZsXw0S2jGZTtJBDSEAJa/eq/51P+FfhdZLKQqrcbYttoWjfCjuMwd8sva+LddUf5ZGM+h4s1KPkK9n6IVYAmSUz6437OW5bOM7dm8eyFu1i9I4k7VvSjW0ILt484wK4/FvL2tlweXNmFybfVgGyA5kWRjPak20e/2ENqrJPMeDe1zX4AjlU2c+dZfXht5WEePG8AxyqamdQvnebWILOHd6TFF+K0nqlUN/lQLArnjsqhtN6LoRs8UtLE3HHd2F3SRG5GHE3eENdP7c3WY9UM7prMir1ljO+bSUmDl+um9mL+6iPtmeYPnNOP+z7YSeeUKG57eyvXnJHL5P4ZHChp4KIxnXlmcR6vXDMSf1AjK8GN265w8VMrue/8/mw80siqvS24I2Vmd9rCoxP2k5DUyM5jaeTEeBme3sDOsgiq6t10PS2ZwTUGn+QlMnucGcZuhN18BqBp+rfyYU+NoezUElmYebUGzPpcZmsbUCQzitUb1FiwpZD5q/JZs78cPRgC3UJ6Yoi1d3lZsrALNz1XgSXYgpAlPlpWwoqN1dx5RUfuvFxlXK9a3t6YyQWfjmREZi03DjnEJUOOsHBPJ57b2o01BfHMe2UvB8taibAbPPnBTt69exIA8ZF2DpQ2svVoNddP7k7nlCjOG96Rc55axeMXDWLhthPceVYflu0qZULvNOavPsJ5IzpS3eSjZ0Y0Hp/K6X3SiXRY6Z4eQ1aCm42Hq+ibHceuojom9U1jd1E9PTJiWHuggjmjcli6u6St/RRpsS7uP6cfSVEOshIiWLarhNtn9GZ/cT0XjOzI4wv2cqS8ia6pUYBBbZOfr74+zntrK4hz13HX8GJuHXmE+KQGduWnc9vXA7ErOvPP2kxybAtnvDKJw/kbePDVr9hwogOZ8bns+7waJeo4Zw7KwKaYi74loBLlPHU1/OF3cyuZQYVtvsu84jpeW3WCBRsOEzQgPtJC/84JFJQ0oWkhFlywlk4JdeyImIt8Rhx64VL0Q8uxCWhoVrnrmUP8c1EZf7q2I5ecFeSSQWX8Y0MWsz8axdCMeuYNzGdG/yPsK0rhhS2deenLatQmN8hWXv86n9G5iQghuPSplZw9OgeA80d0JL+imbL6VjomRnLeiE6kxTr528L9XDepOxF2C0M6J/LckjzOGtKB/cUNjOiaSCCkEeW0kpMSSb0nQHyknUBIo1dWLJnxLjLjXVQ3+UiJcTC+Z+p3+gJ0SHCjGwbjeqbyzJI8VvxpMsnRZjmECIfE2HsXMmdcTzYdaWLn4VrGDvJwWZ/dXNS3EJw+th1N4/41fUAI7hp1iNyMCj7blsodL43neHMM1Xd8Rpw7QMQjSZw4rtCjVxJ3v7uVO17fSL9uSbx/01gsssB1CstGwSknMpP9BjWdiuoWnluaxyeby9m4o4oxXfOZP30vz+VdxKWTx/P4J2toqDN4YfYeBnQt5dZPRvHO9i5g1VH6zEVJH0BgzyKUmr0I4GBBCxfcvofn34vjniuzuG6yl+tGFjN/azpXLhxCdkwrF/cp5LXz1/PaWQ4+P5DJm3uyWbonSMpVDUgK6NV15GREo+squiG46bUNdEuLMmP6Y52UN3ipbfHjdiiM7ZlKcrSDhtYgKTFO6loCZMS5qGjwIkmQnRiBP6ghAU3eIG67hXkTc4l12zCABk+Ac4dno+kGhVVNrDpQwbzTuyGALqmRrNp0jKe/3MPMwZ1YsKOCffl+0FReX7ya83qWMf/mYrplVoHfyuLDGSzJTyfWGeTW4UfolFjO1wcSueHLKXToPIELp8exYcsHxCU28Ma6znRM7Yg93YfbaaW4NkR1a4DLxnZm5d4yvAHt/4ZMZlUkGmpbuOn5jeSm17PoisNM71IBthCa+h5rdvmprXfTLaua60cepLw4jqfXZmOxe5mZW8qfxuymWY3mzA9upKHwAMqxL1Gq8pFl2LynjunX1zGifzy3XJjO5ZM9XD7qBKv2J/Hyti74NnVnXMdKzsot5uz+h2ltiuSTvDQ+PpjJNksSH64oZsWBxTisBmX5ZUyfkEPb4nh64R68gRCSEMwcnEVFg5fKRi8WWSI3LRq7VeapL/fT4AmSleAm1m2jNaByqLwJ3TDo0yEOMCNtN+dXM2NQFgAVDR5uen41OYkuspOiuPeDveiqk1uf381tUXtJddZx3bBq5vQpYXjHCrCoFJTG8vSqfhxriKR3Qj2PTthDjKuFL/Yl8eT2udhihnH/1TmM7hbFYwuPMi37GAidVSU5LLl/CunRsGJPKRMfWMIL80YxfWAWzy89gEWR/rdzMhMen2qmyTltRLvsjM6swTA0hCoYke3lnrUlFJVmc+2oeur8Gm/s78HEAZn8Zfj7DOpYBD47GI0U31jKg+uH8/T6P2Gt2Yh/x0LwVaAoEht31bJxVy09X4rmylmpXH2mh/EXl1FdEcXn+5K4aelAoh0hxnSo4oJexVw64jBqi4P1JUl8fjCR9ScS8CTH8eX6cjqULUORoeBIObZIK59vK6ZLsps/fbCDDTuOs3BbITMGd8TQNf656hA5qVFYZIlYt42F2wrZsa+E8voW0uMi0XSNQyUN3PPuduIiXWi6zM3/PECw1cYZ96xGcRnEWBs5e0gLZ3SsYmxWGV1SG0HoFFdHM39LF/ZVReG2qUzMqeSWEXlomoVXtnTg7QO9mDluEn++pjOJpl+coGawJW8fr40uo7osisNNWXy64QBf7yqmZ4dYljwwhSn9M8grbuAfyw6ihjQGhov7nSr8bg5yQwgyE61sPhDDpPfHsvbi5aw4EkeEI5YDdR14el4PXlkWZPCzaXz4wCUMaKzjppd68OzZMDCtDKHAogOZvLM9EYEXf8wZDLwoma4nXuSDVY045CCaJJF3tImb/trIw686OGtcIlfOSODaUbVgdXCsJJoV+XHc9lU/nBaNPsmNDM+s4YUzy0DRCLQ4yKuJZnVhFDvKY0jKjaOwzs7sx5diaFbwGSC7mfnQBgb2OU5Vk4+S/Fb2HQ1wemgDcRF2Plp/DJoUBt+7jtN6pLKjoJKjhS1g1Zjy0EekR/jIjmrmrLNb6Z9UR5+ketLjWkFW8Xsc7K6M5Zl16ZxodOG0qAzPbODxAfnY3I0Ul7h4YNVAXtmaRV0wgXWPTWR452jAIKiahfZ2nfARa+wlMa2VN9f3YfdhFYflCDOGdeKOmX0A2Ha0hi1Hq0mJsrNuUyGJcwaaE3WKCkX/LkTmC6oQ1Ih02DltuIu1O4I8vnUsHxzsyLhcJ09e3JH7FxTS5HczsU8XQkEPS3aWs6OuI5Pegpr7q/nr2lzuWTYAdAEWjasGbuXV2Tt4YNWlGEYavuKNcPgzQMdhFdQ1hnjt02Je+7SUnl0iOWtsPOdNiOYPIyrA7qCmxs3G49H8c09HGn0WouxBOse30COhiVuGH0eOPGDeK2DF77NR2mKj1ueiuMlKc9BBUe0WWiIsKB1saLqBx7cDo87grqES0S5wSX4kw8MFQzW6TA+R4vYT6fSDogIC1WvheLObXZWxvLu/A2VNTmQBmdGtDElv4Ibhx1Fi/KgVPj5Y3MybC8ro1q8X11xWzjdFEVw3ZxbDO0cTVDUsiowkTOXqiy0FnJFxBLDwwYF0hF3mz3MHUdUY4NJn1qADfXLiuey0LozrmUrvjYWnJGv82/idHOQ6QhYcKG0kOSYGWiW+qR/DoRdG8eLKQv706momlK0mM1TPxqpenLa7H+/PG0pilA23ow+zFnRnwdeNWBJUTs+u4IGx+xjcuYz7lwzmL8t6gFNh3qVduLZbX+55x82Sz3YCnvALauTlN5CX38DDr0j06BzJhCExnDk6mqm9ncwcaAPNQVmtk30Vkaw+kcJTm7tzvCWazjF19E5qJMnpJyvKT4zdR8fMZiJsKg5rCOyhcO8bA1QL6GYRvqAmoepWfKqEagiO1jnZWR7NsXoX9T47fs2ssJ3gCtEp1ssZXRromViCNcoLRgi1VmXjDh8frqjji1VVVNWaddPe+pOfZFs5XbPPZPagFNRQCKuiYITLhXqDsP/IHu6bUkNleQwbSxIwCHDZC+vp1zGOy8d15czBHdoZ1vWvb8SAdpnst6Y1o62p6m983e/BfOxgSMPQZewSJEv53HHRcQypgNmPaTQIncuOvMUdDRtpAa6pXcHZvj+yIr8rfxiTw+78PNLFRj68qoGx2ZUkxjdyuDSBSa9M5at9mcTGenh95mbOGnaENXs7UpQylbtevIvuzgo+XbySRet2I3yVGP4WDFUn72gjeUcbefZdiI920Ld7JGP6RTK6j4uhOXYmd7WA5mbuW2nE2qK56YPRzBpxiPP7FLO7MhLVsFDvlzlW52ZfVQwpkUHqvRYmdKohyhbCG9DwqzIhZPJrI1l6MIO+GdU4rDJdkwI8csZOkiwhZIsP1ACB5iCFZUG+2BVk5xEvOw56OFDQQnWYsEAgy4LeXWPI7BrBJ1ti6TVgHAiQLSfjwASw6kA9CeIAEUl+Plqbi7da4pwpGXxw8+nIksAbUNlZWMvOYzV8uaOYJduPg9N6SuL6zWsKL7QR2Sl2kTf6BKmJzeTdtIGYKA9FVQ4u+ygGn7WF4kCIC7VKNKBJlkgL6MzR83h9byWvvb+BVVev5rKzmiiqimFFQRLvLhjC14Up6C12umXU8vmF68jNqOaGd/qzPziT928dTJ8OUQBcdMllnPnCdo6+/wq3l/yT1T6ZHX6JIhWCqkFto4+Vm3ys3FQFgMNuJTXJQWqcjLepmb+/OYY39nZhaGods3scg5AEhgBFY1NRBves6cUzE7Yz/aNR3DZ4H3FuP+1ddK0hahujSDycxt/OOMCuApWyIwW8Nb+Y/GIoKg9QWhOkuj6IxxPCdIq2QUZRFLNxqjBbaw/qEYXh0NhS34mRtUsof+E9lCkziZtxAaqqYotPZOnuE5zR4TjoCguOpCJsMiv3lTPi3kU0e0NEOixkJbjpnRnLI3MHEh/t4O1Pd//yzP5fgXCIvQpmoObPFlz5LaDpGgFV5u87u7L2SDT7ajvyxo3jmNA7jqH3r+C+hHPQQx+RKby8Hd+HBR3O5Ys/DkMy+nLjS3bOX6CiItNQFwPOAAR1+nesZtnlXxNj9zLtlfF063Uuay/MBQGqqqFqGlaLzNBuCaT4T3C2JcRou0SrblCgSuz0C3YGFA6HoEIzic7nD1FwIkjBCQCJwuONTOhSx+2LBrChNJG0SB+aLmgKSuw6kUjXpDq6J9fhU2XO/XQUcW4vQVXGZVVpCljZXR6Lwxqgd7KHp55cy7KNtT8yOhKyZJhl2wFDAx0NXQVdkpDDMXij+0YiVDsHC2xM/Oxa6gMBgmtWUvPCn9HqgyTfcS9Vwd6c0buKpppINpfGYUghnrn0NCb0SSPWbWvPr2xDYUUTfDux9zeGCFPaKd0u2zPGtBB1jW7uX9wPdI35tw/gk/WFrNpXyCuXDmCeJPG6NJIjxdU0Bqw8Ors3/bNjeWpJEcIaRU2Vn4tHFdAruZAHV/YjLaGapZetxG3xMfqlCVx67pVcc1py+30Vxby5JEnUtwRwal4aDWjQwIpBD0WjXwRcHiGo1wUlKhSogveaZfb5DRxWgS+gsiuvlmHdmjhWIbHgkq8hoJiczBZk1cFMntvWhRavnZEZtXw0awOGbo6qkHR0GXr9YyqdEnzInnLW7mxCUWRkM9WTkI75i6GDZEW3OkFICHcCIqErRksVongbqiaQZYURPZ2cKJaJTe9H114dqTuQj+IQBGuqiQjB4hffQTr/EhJS/SzcnU19ixPZ5mfp7lI2HqmmqtFLl9Ro4iJsVDZ6WbW/nLyCWnBa/o8I/rqBUDQMReWlGbs407WQTa396dz9AhbvKmHj/ePYWdjEmNuX8M0TY/hqfx1Pf3mIhasW8szELXwa14W/ru7JtO7FyKKZzy/6hqRID8NemcQFF13PNcPs1K9eTujAHrSWWpKuvw8iosyEYkWg+1uQwUxbM8BrQKsBGAZ2YdDdAoOsMNIhMaNMUKcaGAas3uXhtgkV3L24I+e9O5bOsS3oOng0hS1FycRHeHBZVHZUxHDVl0NIj/ISZTcIaYLCRjtl1RHcPOowa7bW4POHsFpkgiFTSO9jE2RYBDuyplCVORYhW8y6HhYnhiMGpWQLnNiKYeikpbrpkG3jve0O+g4eSkLzIKq2Hkaxy2C1YNVCHIjszIDkMpB1vilN5fxxuXy4dAsRDguDOyewePsJzhyU2V779pozcjn9z8soK2/C8X/BGOsPBjH8Vv542hGuHbUDrdHCaxdsou/fDIYPmMDyvfV8svwd7h5ZyPPLOtM7PcSWTR/zzR+Ogl9nQIet7KqMYvGOznxy1Qp6ZFdwwRujiZY6c/3hf7D/tjdQjx7DCAEGxJx9CZauUUiSoKHJQ7bhM7sehp+nfXMQpiSkGtCiQ6Js0McusbLFbKG49aCXFEsNsg0GptRyXp9iWr02NDlIp8hWVh1PwBOy0T+lhasGHkVTJXQDLDaVozu60eS3cXqHCu56uwEwQ5uskuDvyTDGpuEUMCNrEFqHLvjq6/D4VFCDEPBAfWFbE0d6dHJDlMT+mgTGj0/EPmoi4qV/mpUtS/y4Lzubii43MTvub+gtVqq1jpw7JoPlG/eyLb+axAg7103pwcBO8VgVmWZfiJeWH6S61gMW+VT2iQB+N2OsAKtKflUUH+/oyrm9i8DfwpX9q3h+RxkvfX6AbddvISkCsu4/wole9Wy75hihVgPDUHhzd2fKaqKYO/ogs4cf5tVl2VREn8unjX9h57ULsCSCFCkjDAE2GyIiCkUIPt1axfwvD/CBLUAgKMzwn+8hXGoFWYCEQScrrDTAIgmKK4N4Gurpn+bhaE0UG0sSEaqB0xGgssXZXvelJajQErDSIdJLlF0lKDQy3D46pLUQoVWxaqcHgSCkGYxwSUywa9SpBqoEfr+H7iku8prq8OiqmYYuSdBc3j75/bpFgC4oD2bRLQakEROxpbgJFHlIvewcrE++S8PjHzNgWBMHKyKQHVlM75/EwZfnUN7gZU9RHV9sLmLOU6tRFIkGb5BAow+cVpA42ez2FFHb7yKTtfhCoBgsz0vjaJOdLgnN3PtVP5YXJqM3tXDN2EIGda1lyHPT6dTFYFbXYuYtGsILMzZyyccj+WBjV1xxHtZO3kFleQSP7hjN2id7o94ZxJBBspr1OFSPjrt7V+xpmTz95QG+2fARqdHxaAhshoEHGYmfVnIMoFM43F2WBaGQRlFxM0Mzmvjbou7YbToZUS24VYXChghUHRTJoMJjZ21REnFOP7FOlaLGCB5a0ZM/jC2moLCOmvoANkUQUGGkg/aS52alA4kOiRHkHQYQplymBqClAiO8vQ/o6iLUJKFaM0h1AXIciZffBPYIkq+7g+0nfESEjmGNC7F5Txo56RkokiAlxklKjJMBHePp0yGON1ceNvMtFAk5wvZvV4j8tfhdOJkBoAvSsyRKGx0Mefl0gkErGILuHZt4eeYmnl7Zj237Y3nqloFUV7p4eX0dR+snsaowHuwh7h99gPiUBi58dSiXTR5LhxgF38Nv0GXKOkr/dC1qQyNaM3S8/A/c8kURsQVPsODGPK79YBo37L6CZf6/EqP6aJQkFONHat4CIQOyFLOoRdsRecdayB3Wgjvew0Nj9mOXQwirSqxF4739GdR5rYzMqOfhKdsgpJhva9NYcCiFwemNbNhUj8DAEBJCgn52g5BBe/9LWZKIj7S31/JCyIigB7x1aAYIodC7o52iWivR0anIsqmtJ9/6F3NcDYN9RQ10jqnBsBjsqIjHYQlS2+ynNaBSWNXM+98U8MbXhzEESDYFo62TimGgKPIp7RAHp5yTmaysLVtJ0wxSYiLJTHSy7aiHaKmBNVcu55vCZG5b2pfYVIO3Vx9hXN9uJCceYNUhB5JNkBDbyh+GHOHQkVj2eYfx+pk5aLqBIzEZx8zz8BceoPTxZ+l+0wzu9g5FLnmS+y44yqHD2WTZmpg1x80539zPvYfmM85/lJofITSBKZslywbRikRzuLzl3mM+5k1rwNNsZ/IHo+mW0IhmCLYWptAlqZ5Im8oHB9Lxh8bSPbGV5oDCl4cT2VcRw9Dkndy2y4MBhHSDZItEtqITNMLyoQEWCaKc1nDKnwGSjPA3QqAFHYiJstAhzcLSQifJ4eawhmEmH6shDYvVQn55LX3jaxEBmcLmRFZ+upO3V+0gpEGrJwBBDVxmmav2Nj0/Mk+nCr9P0GK4x1JueiT1HpVtR/zkxlSy7PKV1HntzHh3LEg69a0K9QdbafQe4twxnXjpyz2EAi4uGVGEO6GZvy4aylWThmC3SGbOgKGDbpBw859JvuQ6/nlU4ejCZ1lw9R5W7+3A6a+dxoyex/n8mhVs6pXD7Pdu5pod73JFyyaqvkdoAtNyGC0MEmVoDLcQOHzCT7ylBeHQeGrCPkZ0LgZJ48u9XXlpRzaNfoXpncuZf/Z6UGWwB6lsGUlBcyRRRi3bD3nN7nA6dLZCjDDwhJmWbIBDD6Io8kl7uCRDay0i3L89PcmBEi1TUB9Beo/o8MOaqV9yePYqa2vokdOC4XGQXx8BskZjqwqGQFgVZLuCphnfTRQxU1exKRI2RWr/6FTglBFZm6vDMAyCqoahG6w+4MEt+7hhYB5PTN/JzpIkTnv1NDwBGcUKZ+cWEWHXeGN7Gu+uO0bXDkkcOl7HNf2KqCtzku8bwD/GZIS3GVNk1yUDgUGJJYmn33+V9Zeu55tDmZz54STW/HUqhyvqGfjXGL6+fBW7r1vMoNcvIrRJ5pqm9VTL3yU0zYBIGVIVyPebVusTlUFEsJmEiCDnfjKM07t0xKqEWHM4nQGZ1YDGwkMpzFs0nPTIFur9dpYcSGd0x0aqqxqoqg9hlc32NV2tYPlWJ/S2Eu4Oq3KSAISEHGwO/22QkWQDu6DUE0X3uHAZdAg3hDCf2dtaQ6dYHyWNMVS02EHRkYRZIt4wDNSfsbVL7cnSvy1UTW3vlvS7cLKgqmNRBJf1yeMv4/eQmNjCi2t7ceOCPnTpGE9lkw9Fq+ejuWvAprKl7FwOlFnwewWDMhvomFnDCyuyGN23H26bCLcXlADR3kD+zje3cOeAlYQMN+PfOB2rVef5Zdto9tnYeSKFni9MY92Vy9lz9QL6aBeQsKmZma17qf0eR5MNg0yLmWUhS4LaJhXV20q00+D8LgU8ePpudE3io/RavipIwhtSmNi5iicmbiPoVwjJEl8dSaF7UitHi5oAHVmSQYfOlh+2oRICLEpbHQtzwYhgM4os0AzomO4CBLX+KJKjwn0QdA1DURAIapsNhFqLyx1kc2UEoYAFyRpCN/4V4ZhbrlWWvmXx/18b6qNT06pwTp/jvDJnE8v3ZHH/u6PZnp/AuOHJxERY8KsahSUW7lk2CH9I5miNC8Wm4/VonN21DAixqrQL904yix/L4Ulpq3i987iXqtK1XDC5gkmvT+HWIfncPW4vjS0aa08kUpzRn5KWdEa9eSbrL/uCtVd8xciWy+i282GyQnX4hEDCaB/jdCVcUFcW+EMaVbWt5MR5eW9XR1QBiRE+luR1ICWqBUUy2FEaw6s7uhJr0/Fo0Oy10DepkX27zUgQM1VTkGUxMAN9TkIIs0aYYRjIwkATMoEGj8migIx4AarARzQJ0WbnY0lR0IIBZFmmxicTITWAQ+dYnRs0Kdyy519Mi5k2hSLLWJT/rTJZeE8IqmCTAnx1LI3cJ87mcEUsqckRuBPq2Z5fidVuRdd1+ndL5rGvHSAJhCMEOkgOjTM7V1BX4SBg7Ub/DDtCllDrq5FdkRgWc9Bf/OoQt/bfzr4TaVR7bfz1grVs3NORDSUp3DljC5pmUJ0wlR7p0Qx5spXSOxfyj7kHua/6Yj4ofLq9Li2Yk5OumM/eNk91DX4S3SpavJdp3UpwKQZVjW7KPTY8QYWsGC/DMmoJabC6IJWS2ihyYxr4pMBMu1MNcEuQJJuaZdtWaQAICTOBW0cLOoBW+qfWcuV5aZTI/TDL7xxGt8XTeM/lePK2YevZE8+u7cSlx1N550Lc1laQDE40u35ZsIOhIRQ7hiYR71Zw2X5difhfi1Obn44ZFSvQqWt1UOZNJifNwrjuUVw7uReeJj+6qtEpOYoWX5BuOXZkixdDVRG6QmaMh66p9awqjKNDSiayItG4ZikHh/WlYdmn5nbWHOL4iV1M6VXFyztyuGP4Qd7b0J3Rr0/CqgRAFSwrSON4rcH0/slcPWMSU94aw9k99tN7ShTvOIcSq+toQmoX/pNlk0O2zVdpZSuxdh/1rQ7KmtzU+ezUe21m+UsMDN3c2hyKSrwjgC0qgFs0c7TED5j9LZMUQbQ4ycl0IZABuwixeGcNLS0WRuVUkzdvITtfdTJuen82+MbijIpGD0kEmoOom5bRuvcAdR9+hL+wEP/WbZRt3UpSrAAdTjTaf37HM8LKki0SKdAIW/5OxJ5X2/s8nSqc8u1S0wy8AZUIuyAnyUq0y46iKGw4VElGVizFFc0cKKmnS2o0B4vrURSFMwdlsHZvE/2TisDlZ/2JBPpN7klo+fscu3QuUgCqX3+G2JlzWXmwkT5ReWBR2FIey6GqSFpCCvtuXEiP7Ar+smgY6050JL1lKafdewCHM4a1hZ35aFMpz0zcwtTt45ixZScKZrP4kAFxkkGEJGgOj3t1g05qrwB51WkUN0bg1wKUN7vIjm9BkhRONLrYcCIJvwYf7c0m1qViUT2U1qhh5cdUJpwCPAboQiJK1/EImS3+NDKOrWPdVbsY3amctcdSmfvxMERUfyoCBlHSXnxBC/boeNwpqTRV1KK4JVMutRs0hgQOuweQaQo6QPxEb0tDA9mOkCSkwjVI+z8BbyNN0V2BU2vG+N0E/7hYF3XNAewWhbzieppag4zpnsyhSDs7DlZy8EQ9SbFOnFaZVn8If8hgSFo9BDWOqF2YsOVzSp++GNkqkCMkPDt2QcFeNp9wMjWriLr6aHYXRpIe18L+G1dQ3OTg+g/H0j+thuq7PqXFZ6Gi1eDPq3pBoCe3rOzDeX0LmHZGkOX7ejPHt4s6SUboGtEyJCiCxqCpEJRVtpBpCRHnDjAuu5zYiFZO1LpoDNrxqgqDMuq5cdhBFFmn1WdlZWkWrS3NNLeqWGRBUIMMi8AiDEJIJOs6u5Q0Hu1yIfefV8xNI3azcn8Cw1+Zyua9yWT1TueJqT2o9h7CJodo9Rs445NJmH4Odd/sQomyodVpuAb0R+vcC2fJx6Ap1LQqZpTut6nM0E1xwBaJ1FSMtO8jjNLd6JIASTH/nWKcwjuYQllrQEWSBCfKGpFsFnwhjVZ/iB6ZsZTWtrLrSDX2CBuKEMiGRu+sZHQEQq9nQEo9ht9FaZmO/N7NBJCQ7GZxEymo07BhExXe7ozq08CHhzpy+qhenNW9lb6PB5nav5U7xuyiusXBpDdPJ8rl56NrV5Czx8Mf5/TjQGkTz63dxbVj8pnTZTjn7NyJw6LhkwRuAWkWwdGAuborPXasUpDKRhdv7u5CVlwLH+/PYkKXShyKxrIjKdyyfChCwDvbMpnWt47mltB3emB2UHRChkSSrvOeexDzB13Am5fuoG9EKWe9NoxjgdHklTVx47TdTO66hIUr41m1tRf39VFoCshoHi8RV92A851XCRwsQnJZifnLy3iLLEQZITAELQEZ+BYnMzSwOBFaCOngAjj0JXrQB4qCxWJB8/lIjo8BQNd1pN+69U2Y3H8ft5JhICxmXHtDaxDDMCip9VBZ78XmsIBh4LIK0hLTCASaGBm7mo2OrnSNbaWiyYUWtJKgNuBv1tCEhhwBVgGFRZVIsVE4YoJsKI1lRJrGvDPH8fgyHyHfOv6xpQd7S2I5v08RF/QrYMe+ZN44OJSS1/qw6WgjVzzZlRvPWErUkIHcXTGXO2sXYA+2EiMZJEugCANkgUsO4JBVeneo4bnZ60BR6RrdyqaSRCo8Di4dUMgL560BDGxiDB6iqKpuBsIly2WFeLuNBL2FxyNH88moc9l61WIsaoiBr87lpnOm8nBuNHMffZFnT9/No5t68uLZ+0mKcuAJWTFsBlZ0sLtIe/Qliq+8lPQXXoRug/Du3IchS4CMqsthrUIHZJN7VR9E7P0Ao7bAjLGzWNFUFb/qg6QB+PpdfvI5f8MpD3d+boXfwRjrD2oEVb3dz6aGfWaVda0kxLhwKJCVFEdpI6Roa5nb8SjPbOpPEIn0GC9fHXbRvV8/egx/iPJ167GnJtK8YSUuSy3lPccSV7IJLAohr5Pu90zGE7iBhX++j75zqnn5/B3cOOwABTVRPLCqL2/u7kBNq8St/9zPleM74LfkcLw0kku7HmNi2nQKu3Unp6UMd8DH1t2rURurAR/ba9OZJVk5VhXJ3HfOINEd5PM9GVw95AiRthDv7OhESDOwKhofbu/I3VOO01Ag2scBSaGX5OFtR38+HX0ue65eSF5VFBe+NwK/M5XG5ipmPLobzQc4VD47kMGH+7KIdKhM7FiJZghsNnMxRoyaSI8dBxCRsWDoeDXCAr2Mhgy6iqE4EFoQae/7cHgphq6DrKDIEsFgEEWWeOm5p3i9tAsVLUHgl7Xu+XdxyjmZbhjhJgRg6AboYLcrZiN5Q6W82UKqu5L7B2zAZYVbVozkeHkkA7tWgSNEucdFeowL96X3knOtqQ77y4qxBDxsacok/viHIJzIdR6ylRaO3PMIA/qN5KI5vfnbV5UUNkUyPruMa/sd47ZhB6nx2nh96xYm3d+fmgYXWyuSOC2rlhm5+Xx+4Qb8up1W3UJrdVcW5Q2l6vAeNvsGcvfyXvRJqeWPgw/ROamBaIufJFcr/hCc0aWMe0/biwJsKEwg2uanocls8qUZApek8lzsOZQMHMK2qxZxuMLNsOcmkZEU4O0z3iXFUc/UmVZuWj6KJ9f0ZuctnzPiuRlsPJRO4owdNLTI2CwWEAJD11AiY1FDKpJF+VYDMrMUFPYo5KYjsP1N9LoikCQkxSxiGwwG6d6lI8+++Br5egeOrF5JTqc2f+hva8LQdZ02k/8pt5MFQhqqZmCEdCIi7CiywOPx0zUrCU2zkGY/yO2D9rMkP4v523PAGkKyq0RazRzF8hY7adlu0MxubUISWNIykYGKJQWkRfogZKE56EC2yughjaqn7+fCB5fz9WobNw09SHGjnbf3Z7P6SBrXDT/M01fuZPdfEyk+3oXd1Qmc16+QkhYnF38wnNHZVcRbGkmPsnH1iGrsM9LAKKa0dCErCtP47EAWx7d2Ye3hdM7uVUSj38uR2gh2VCSTVx5JaX0Eye4Qh+t95gBL4NUM8jvFsPraDXhaNOYsmMKA7tmMTlrM+H4lvLuhD4PSK1l19RKG/ONM4l0+Nl67jNTHZyMMlZAmEdLbKEB8p/2P6XyXQNaIUxooPLoH6dB7qAE/KBYUSRAMmgR/9aVzmXT5nfx5RTkbVn8FDhmLcmqsWIaht8uGp96EoRvouk5CrJOAqhPtsmIIJ4ankl4JZai6lcsXjqSpxYbkDCBLBqGgQrI7BEKn3m+jW4QDZDOBVUgCQ1VBkqhp8ZNu8xPUFURzEzZVJRghUb1tBwODBSixOZzxZojM+BAuWWVyt1KGd6zmjcVdIWIQz9zeg69WHQKrRqQ1wHubO7O1cSD9c+JJCBh4jlagBIvoElnEGZ0quLzfQbDo1DRGsaFbKV8VpjB/VydqfTZKG9wkuULUNLg5Wu/E59dRZIGOwCbrfHnONlIiYxj55hhe+eNZtAY1XvjnVyDD8oIELvpgOIuvXM7WeYsZ8tI0MGSyYz0ENAkhvte2ua3+FKBqAk9QApuFmANvwJ4T6Iope+m6RjCokdspk5vueYhSd1/O/tsu8Pj546xSjpQKGjDrcxgYv1kTj+/jlBOZquug6kQ7LfTplMKGg+V0iyjl7O4FLD2WztrDKWAPIbsCaLpAMgBDEOvQQBiohoNo1/fqZwkJJIkmjx+3I0BzyEqSrwGLAQFJJtASwll8iMzULuR6VjNvTBVaUKIuIHPbkr58ciiH6jfHUdKg89EyJxgSSa4A82bn0CEe3t5wgi/vnsTjC6Dek8Ti6v48tqWcHolehmeUMy6jiMmdKzhrYD5oEpU10Wwtj6Oo0cXw7tV8vNXKgRVNZll5TWXC8GRyhsbz9yVZHPL05WhFKy8tz2PPkS48tijIuxeu5OxuxZz/7jj+OnUbn527iYyHJ4NTJ9YRpMFjBlC2eSWMNuezAIssTIu6AAXV9CBYFHy+ILKAm6+/hn7Tr+aFNVVs/2YrXbr5eO/6zaRGtXL2/KFI3+0Te0pwSgV/CDe90nWKGwxiSqqYlbOb9Igg96zoj6qD5AqYFvPwdiAJA0kYWKUAGAZ+3UJkW+PScPhLm+wQDAWJjVNpDrqx+8xkEYSEoYFRX02kqxdlZXY2FCdhI4AQBvFOLz3SVKLdDipbfCAsgEASBoMGdqdHks6d7+5mxL2LqKz1QCCEZJPJyYznswcu5eIXtvDk3w8hxQQZmdXCqMxaTutQycSO5djdPm4atwdarGwa1IONe5p4+gsft12Qir/ZysMb+qDoFWz5ZhX/GF1C4jR4akMu41+czmMTd3Lino85673xPPBlZyYMT+VIeROSEUQzrHh1M/pXGCBkpb03hNNpI9RkAUngcFjA0PH5gnQfOJL77rqdXf50Ln5hL3hD3HlOIfeM2c17uzty22sT8dZrTO8Qnq82Te03hfg9MsjDAqBm4fyuB5ne+QQPrRvA/vJosIWQFAM9TFwCkCSDYMACAQuKZMan+EOS2ZFN15HaohXCeaK6HiLaruENKSh+fzvxSQJUBJWNQYbFeemd3IARlLBJKjO6luENHeCqZ+043T1wyj4wdJqDVl6/5X7KFZm03KFkRypYFYnP7zid617ewPFaDy8t30tqZJDnbhvCl9ur2VlQwNUDCvjiSCZ3reyPw6KRG99Ej8RmRnZsYUiylZ72bCaevpwXv8miqi6JqX3ymH/NNr74pgeNvhAvnbeOnQUpPLSyLz3SmjH8DUyZPJc3L+1E7vUfohlgSDYa6xqp++MsqvLyiRg4iNbCQpLTYpAH3I8hm5xe10K4bAoX3nAvHcddyKMr8sjbup1O3YK8c+4mYhw+znx7POuOpCG5g0i2IG393n97CAzD+FYG+SlEi19FVkI0Bu1csWQETS02ZEcQTRft4SiyZKBpElqTg6n9C3HJOpphvnyTX5htpyWJ6jeeQa+rJuWOxwAIhII4lRBVIbNiuanB6lhtUONMoq6hkvgUnW8KEtldEU1ZfRRjc8p4Ys5aBh7+muvnh7hiWgCQaGoSPFnwPB9G9ifrgZsYGGvw7oYiBnSMRxXQJzOWh97dznu3n86cUZ3Izazm2qf3MXfAMeYOPkR1TTT7quJpCFho9MKrWyL5ZF8uc/ufAF3j1b1dWP74aTz8sZ1lmw5jtYd4dGVvHt3Qi1k9j/P0tF10+dtIxowewz+nSxyYOBTNMQNhsSC5Iqhd/gUNRz7Hp4B/Tx4aEBELlrRL0KJcoPoJdJ7O+WPH40hP587nV0FI5tZZx7l91D7e2tmJe1b0Q1cllAgvCBlVF/+19pD/AkISAfg9jLGGqcYvzEsHWUWyhdq3RlOgNdBabbhdAZ44dxNDM2q5+rNhdI5rxMxZU1Gio1HXf0nJHbcgAY6BI4geNw2LEcQqa/hCMppuXk8NacQlu9impFF+vAgl08ZpHSq5YeBhYmO8EJJ5f2UnXtvXh4g0B51iWtC9MifURG6e+hr7Kzy8IgV46NND3DStJ1/tKSUl2smXd5/B2AeWcPGTX/P4gr0cLW9E9ccz892xvHPWRhKjPUxIrINWK3/ePJ60tM5Ih73M7XmCXQXRuGK6MbF3AuX1PZjyyDhenbuXVVcsp6zJxZriZC76qD9xyRl8dnYkR6aNQi2sJH7kZAwh0eLVSM3NxVpnQQR0FLcEQQMpIZLo9FSqawBdw56QzfztIYwV+8jqoDJ/1gbc1gBT3hzPruOJ4PIjW1RUXTJLB2C0F4z+7f3jBoZu2OF3iMJo9YdAN7DYQwjJaOdeiqRjqBKax87svkVsumY5QV1myCuns+NoPE6LBrqBsNkJVpRTdc+1SA4JySFR/uAfIRTC6ZSxyRpeVSYgFCRFoLfoRI0axxOHXFzdew8TcsvYcCKRa5YOYcA/ZpD++Jn8/eBFvHbLJQzul0CfuAqO1riJcMTz2gOzcSfGcfFjyzGE4MxBWTz9ZR59O8RRUNnMxoMVaJJg374y/jC5B4VvzGJfXTZaCD7dl82cD8+h27OTWd94OleffwGREVb6Jdew5Fgy3TKSeH31cR56ZyMDuzTyyYEsHlzTn+3l8cRG+LDh4ZppA7H9/S7qj1bijJOI1rwYsoy/yUO3KVOJHjYCrUkDWUJtUnEPGU1s1+4Q9JsrTAtgeFSum3SC1Zd/zcpjSQz5x1R2lcea3Au+I/uaP0+NRilJMkIIB/wOnKxtgeiGwMBofznV4yAtvoUXLlhPVnQr1305jPW7YrCnGjhSbAQ0Uw7D4eLE8w+TU1iOcMhIgG9/ES2LP0ZxZ+GUVfyqgs8RTbDUID7JwfIh8yhavZekxEQ+3+tgaucybhx+kJ3lccz85zBevX4EPdMjqa4pYczEOt7d14mKRoW739zE2O5JDDmzO6t2FnP+M6tYseMEq/eX8fLXh+iREUtJfSsNCO6b1QdkO52iqomOa2HB1zn8Ye6NrNx9kGff+ppxefuJiWnB5g5xtCmVz9YeIT8rn49n76JvsherBCHNoEm18NQ3uayrGcSrcRWULFqINU5GBDUcRgiEoMUPjiQnkbc9hlgyDN2nIUdaiLj5YWwNZgQvBtT57Tw4bTdjO1Uy+e1x5JfHItw+M4RJN/lJ2/gHAzbQgkQ4Tk15dSEEpppyKrXLMHW1BlSTI2FyLzVgAV3mhjEHuGXkQT7a34mz3x0FTX7Gj09jfJ8Unnp/D0ILgCxD0E9g2zqEw2IK9pKEZJFoXLMMBl2BRdbx63aqg604XHainn+Tu7+2kibX8PrsLaw7msQDa/qQXx3NC2dt5bPz1/DIp30Y2jWDTNshXHEBFhxJo0NEPcnuSDpm5rA238PSleVgM8jtk8jEPsmsyatg91NnEwhpdLj6A2Y++hWSHM3QpGKamxRSk3MY2Ulm3TEng0u/4dK9m1ly4VUgwfFGO95qH5fNLGFw33KueGMi6wuTiXW3kB4TpLk+RP/ecSSV7OdYvYoUZ8FQNRyKjk2BoGHBGfJC96Ek33oXlff/lQ7vzIesHiiVVSiKDLrAKut8sj+TB9f1BM2UvVRdal/osqSjBS2gSUzuWc7mo1YC2infzH4fY2xblKnW4qRXZg0vzdyKVTaY/f5Ydu6LICpDcPsV47B4ynjuT3+k7sAOPO5MmJ2MjoRXsqFXhVCtZkKsWg9SdDw2K0iyQGv14O87EvfNNzHs3SCP9/o7Jf5YZv3zNO4ft5dvbvqCwwWp2BSD7JhWZn+2lw9XFrFtXgHVVXEMyQrw4Bnv09IkcawKspIS6DIrnVWHY3HZrfTPyWHNgRbOeHA5ueluYqIseIIqO3cf4PZ5HsqbEnlpvcqB2hXsOFZD9KAZPBE4m8HuQxA00OQoHrl1CI+ulHEqfl45czMNLVYCqkxAgX9uTGR3RCzWquPoOsiYIdshxYYi6fg1C5FuJxgGyTc+SOSgEUSMnWauZFlp506GAQdK41Ai/eiy9h3u1Tb+3dLquXHYEYqboli1J5UYp/xTU/eb4ZSH+gRCGmhgEYK/TN/OFQOP8vetPfjLslzwBzl7agbTh3bk43++xbI3n0BgBvpV1XhBSLiVAMbcW4iX9xDdazBq8TG8O3eQcNXNaCvzQJJxCZX9WhpTPywivm4vz+/qwwfnruP8XgVct2gIr+7owvm9Csivllh0dBDNnhjGdjnBoF4NvDS/kS8X7MBV5CYpxkVO7+6MyWphWue9PDpWI7/mG7YcXcTw5Fze2CDzzYEEXvjDafTMcDP+rk+Y+dFQYh2teBrrKay00NjiI/+dS/jqkJdvlu8FZIKahVtm5nLBqAxy5sHLO0sZnV1LQLVQ1mpj92GFgRMltCav6TESZvCkLhnYZQ0NO5FOq2kns9qIHDsNTTVzHYIhDbtibqtCgGRVzSZo35J91YAVhMEd4/cxpkM1r+7MYUtpLEHdOOXl1eH3sPhrGmgSS+asJ8rZypjXJnP4kJ2Mrgo3TO/H8Vofd8y7lJrDm8zap4qNQCCIqgOSjBxsJeqMyUSNvOgHUoMS3AKSjtVqwVNTzj6Pl8q7t/POngwyHzmPxybvYMHlK3hoyWDOfX0it13Wh7uGxXLxcyt54ow9hOp9PDX/EAUlHnbthVGD03C2zmFTQQR3jj7C6MwKsmJ8nNm1kisjjvDiRDu7yuJYnb+Xt/Z0IypCoSVgJyGxE7NOS+CRC3rx7OJ93PDSOrYfbWV4ihWEioKXoAqN3hDRDh8X9DrOxM5VqKpEflMUR4oyafSq7XU5BAYhIGSVsUh+/Lodtz08VbpuRoyFfZe+oIpMEAwzn0LHDOuWhIGOQPU46JdZw7zBx8iriWJlURKR9hAJkXaqqv3YradkuxRmax3hhN+ByAKqAYrGfev6sPmQA1S44oKuZGVl8NXbT7Lq0/eAZhSLxTRDBAJggMPtBkNHkmQcegBUFa0939IASUE1DJB1ipsc3Dz+KCOyKhg7fzxb/vAlmTFeJr80hbIWBy9M38ob+7K5e0Y2d7x/hCu6b2Rg93pmP96RgpINOB0WgkGV0f2i0FNb2JgfQb+UOqo8LmZ+OIahaU1IskqcNcj4nArO6nKYDpGbeWqEi11VSRyoTaQumMCdL25DsqWQXxXk8FE/2REusBhEWAM8+MFePtm4lwXnrUAVdi75eARlPjspkX4MyUtFXT3eqAQkCYShE5Bs2CIdIIVoDFiIsIeTPSSBEJIZ0QJ4fEFcliBogma/hCQZyEIn6LchyTo3jD5IojvAW7s70TW+kfwGN9urUsiIcwHe9vY3pwSGaew85UTmC5qp2Jv32xnSJ4GrpvXh4M4tPHLNHwmUH8AiVHTZiq6GzIjXpC7Q8Tyc/TTQ1oazpSVQFEQ4CgMMNMxCdSBQhMZn+zJ5dMpmWgMWxr46hTVXL6Hx4fdo9VnAqpPq9pF15QpGZe5j6eW7uW3RZFZtqsImTEOuqhlESo0UBZ30T2pECzsEE9w+Fl6wmnvX9Gb7iXg2VUTzdUEqhY2RnNGhkFmdDnNtz3yajBisik5rIICnl4ODfRN5ZmdXUBW6xjbyzCu7GDyglFH9KliyuTOnd6pkSrdS+iTXc7AikuEfdaV49iBcUaBr0IANi1uApNIUdOG2SWZggAhX/dE1kBRafD4yXSHQZAK6jK5KBINORuVUcsOww+ysjGPx4VQaAgbVWgr1IhMjWEFBZTBcKPD/wHYJQEjltsuH069TPC/+6To2rvwSCVAUGQ0LqEGExQE9ZqB2PR38LjyhQ2ZVQ0AKuz4MTQMkkMykXq3NYaxr5BckMvyFM9l0/SIKaiMY/MIMrui/C6uks3tjLlsLkhmUcZill3/Fa0eGsvXTZv5e+yoXCQVrOLk3wm2nvFnB7fQRZffiVc1cyCafgqZL3DDsCGO6nWD9kUxmfnQG3S376HvnFqJcBmp0Z/r3SGTk4N64nSHUaBdH6iNpbXYwIKmauJz++JWuTH0mwNz+ZXRNqmdDcQIfHuhAc8hCb+sh3vOex5/Pns2xVz/Fn+QmOiIEhk5T0EVktB2hfKvGmqKAYVDb1EJcpBdUC5UeFx1iW3hq+g5SHCFuXN6f4elVZMQHOHq8E/mHQ8iikpBuoFhlVGhPhzuVOOVE1twaAKeTHetX8Le7FkGpKXtpQkZXgwhDQ6T3Q+99HnpUJoraAqFw5edw1RuXXQFdR7aEH9fQ0YwwJ5PgaEMU983czvKCJKa9MZnFVy3j+e1dWFZ3I1lJNl745hgTcg/z9RUr2FKSzraXq/l78UJ2fSvtDSAhPoLmehl/q421hSm0eO2UtziQBNT5Hby+I4dDzU6+PpRGhMvHtcOq+PQfrdQ1CGjYi61C4vQ9W6nTrWyK6UVZRlfWlKcwNrOU5ASJrY+fzasrBzD36a1kpputa87teYKmkML9nt4889FeLv3LY3Q4coDt26pITZTAp1MrUpCO7KVu1zpcEyaiRMegBQPYUjJobG4gK9NPaYObZLeXd2Zs4ctjKSxqiGJAejPLC3pQE3KiSH501YvVZsXmtiAJQbNunNKI2Db8DqkqVmiuZO3i+5EBYbGaUbFqEOGIgt7noHUYbYYIB5pBlkDIWGWTuwgIbw0SjasWY0/NwJHbh1DAIKCarQ1r/U66xtSz6pKvOVgbw44j8aQnxvPM5b258fUt3DhmI8+etYNHtg7lxY8SWJZ3B3FWOOE3iZdw8V+7Q6HW5+C+EXs5b0AB+O1sK4/Br8okOgM8PnYHiem13DM4n+6vTmdrXTZeayIWfw2qZEG2qmTbmonWYXTLGqJPNPPGvrP44sIjOIMH2V9yOldNyOa1Lxex6Ypl7KmK5dqFQylvcXDTmANEyi0MeyKJkhcXsveBj+juOI5Pjab6aDUNH4ymoaQZOdWK5HCjN/pJfPJVvESQ5m5lU1Uyhqpw84r+dIttprDORnGgE7HRDuqPlBER5WRE9zR8wRCaBpqhk1fr+VZfpf/FKXGekICCr7ELQdBixwiaFmg6DMfodQ66KxGCHswCcGa2DQa4LQEz8cSjYYmNR139GUdnzMbdvyPdl+8mKEUQCgUBCVUNctfSgeypiaNzbC0vbOlKY4vg7Ade44GRa5g5ooInFg3kw4+tvFzzLJIs8AtBXXg71jQDRRY4I6OobhH/r723DpCjzNq+f2Wt09PjbrGJu3sCJBCBBAgkuGQJsLgsyyILLLq4W4AFFndCEiDu7p6ZzETGXbqnrez7o3omYRcJ+zD7vs/7cf2TTHf1XXVXnTr3uY9ch4dW9mbRsXTqfS62VcaT4IxwqCGGWZ+OYWzXSjYeSaS42oHNJhDjlmloMjENA78uEDIhYsJhSeR8/1YWbx5D+Zlp3DZ4D7f/czMxisyNA3fhSW3hn98NZVKXMq4YVMi2qngqM71cacxn5HNDqYsZwKr0zWyp8JIdn0yiolKXLGOGI2hqPUozHNq4AzmnJ1KMyq5dXpyyRp+UehYc6kJCYgYlJeUcLaknI93LE5cOZW9JAwXlTdhtEppmsGdn2f8bLgxT06Cx1Mr2jgQRPCmYfWdhZA0BPQIRX1S4ToAAya4QaDp+JQFh/xbK774cJUkmuKuYupceInLb48hGAESJimaR128di9dzJte/vp4Ys4BHzlrBtcP3UNyUzC2vDmHMJ5/xpVqOLoBPEHCZBsdU0YrBG5DoEcDmpiWs8N7MDfTNK4egg7HvnkpDUMEtq9x26h76ZFVT2iWeAUfOINPdTFdvHevKAUxMRcEUVUTdwBRMFBHGHV7HI6sn8uLkZTy8fjOrilII9MpCloJcO2gPvoiTCz8dQ8cEH49PW8vmQ7m8+EwLKckVdMtt4d0F6YyZdCqeih5ULd+KPV5BD+nEZtrYO/xcko99g+mU2FXtpbjWw/baGECmJlRFvNvGmCG5nNonk7R4Jy8u2EPHdC9uu0xhfTO4bNijAfL/1YUkIR1wuBFaTISuEzF6TMe0x0KkhePa6zgsfgjIiwuCIaGaTuoevJ5wvR/BISN6BBo/nkvozFtxuwUQIWy4efrzHfRILue10zZwdr8iKmu9/PGrkbyyqy+nlCznT+FyKhQJ0TSQTZMwAiVq6zlNMpJtRBQvLc0SVy8czMCsWkrr3eyt8eJUNEqabby9oxMj/S62Hk0m2GJDFVw4HFE/kwB+3USNhtBE06BREDg3sIVLl53GoWFpvDN9C4PmTqVHr7P5rjHMnG8PIxp+Vl2xjKHdj/LowiG8vzuPe04vpDYsgRRiQ3keL1+ThVRwBuLS7ZgGaH6D9NffYB859HYfQtCcbC5PoDGkgBLCadOZOqgDheXN/HXmQDYfquHl7/ZzWr8sDNPkux3HSI11QFhrXxdGFO0oZNarEQqFoOsUcExCT+0PatASsJ9IljNMQNbJ9vhBtdNSF8BbXYTpUsAwEBwyZmMzlTt2YbdrYOoETBd3j1zAxcP2U13p4YYvR/L61k5EAjJ4TPraqghHM9gFTGQBGgxLyAQRTN2kQ7qN8mAcLleYL2esIcYRpsbv4LJvRhLRJVyKzoweJeQnN5DnCTJvfxYVLS5y0lxAEESBuohG2LB4w6wscoFYU+eygq+ZM+8yll31BTcN3kK92oePbx7OzQke1JJXGdrnKDe9P5a3t3Wm8LbPWXggh7NTfBw47MEe35duMRCccgniww9jhqDz2x8gn3EBOx/5hksHN1JT42V/bSxIEbpkxjGoUxrbimrolRfH0l1ldM300i8vgQPljbhtEjuLAmh6CBSl3Rl94L+RGatGIL4TWqwTwr7jfq8fgVWXKqLYNHK9AcIBiYA9lfjUREJ76jFiQA/rSG5o0CVi5WYQZeKMamr2buXyD47yZeQKmp39QWggLUWiXrKjawaCYPHomIAiQLkmUKebKKJFI9Ap20VFMJZAo52XtnQjM66JmmYXLapMjN2kNuBgS0Uise4AjSGFUESiWbWT6G1lKTRpESSCgkisqaFhabMGUeTs0B4WL93NfZ3G8fR5yxjxtJcHv4whGA6TYLPy8m8aWsQzZ2whooscbvBw+ah9XPP+QM4f2w8Ae6euZD7wKI7ufYkdO4niyiD+5iI6ZrXw3pY8Ii12MtIEwqrEip0F1NSG6JQWhyIJ1PnCyBIs3FRBg19nfMdjXDHwCDct6AFC+/Yfh3YUstY1PqDqlu2l8oupvoIApi6Q4oqQHhuiqErGm5RBv2deJ7hhNa6+/Wg5uI9Yt4I/uzuJ9R+DXUHf9Ca3bqwAQBmjIidH0H0G8W4nitOFEQ617Z1ahaxIFTB1o62tTLe8GBaUJzBr0CHO6n2YlhYHdgRcshplPRdRRJ3qFjtVfie6LlIXcpKRbFViyIJAo2pQr5kkyLRRRImmSZMg8lj1B1zw8Z/oltSfddctZ8jLbjYfzSU9oSfNbyuMzS7jcGMyb+/sxp9G7KW0zMH+0EieHZ4eZQ+ClGvuxMDyF36zs4ZecYfAZfLFwSyMcITaBpkeKcUsvmYpjQEPfV82KW1oIcZmsPlAgA7eGj66bAsT+x6h6Ggauiqj/Bc8pf8dZ2yr9vqF9EsBE3SRDE8Q2RWmuCmRHI8b74jReEeMA8Bz6pkIQPX8Q6S5/BCB6toAkiSiYKIJVlq3aRh4nAoOjx1HsOkHO3QRKIjaY1H+YbJzEti3J4ZcZxDdgARnC4YXEp0hwqrlWRmdU01efAAtvYkX1udzqM5F3xR725hhE6oNka5t3NnWnDTAicZrRS9y5dzbcF6nsem6hUx44wyWHOiAd/J17JM0HnjtAJcO3UGfbqVcMnck10wdg0OxNiaSGE1DN00EWWbBpv081u8YzVVeVh1NZeLoTBZtqiDGDoluFX9Qx2VXqGsOcCykcGaXg3x+2VpqfDYuevsUPtida1WROf8Xp/q0arKWkPqzWxcrBVtAEARk0cQIinSO94ND5UBtDD1y0zANA03VkGUJTdeRJZHq+kaGJgTQmgzqmjV03UAQBQzZFS3bB7tNxuNSiDXDbU5XwQQVgUNWdT4R3SQ+RsQZn0KNT2JwYoR1hzOxSxoHqr2EdQlRMCisc/DE+u7kJfgJahLNLTbqAjpJuTHWwKZVHV+iCcj2H75PIiYBQSDR8PHWvqe4+bk/Uj2nH4uv+ZbZH4ykrCqdXtkZjO1+hHcuXsP361LwuydxwbBk9BMyJSyadoGNRX6C9dsZ0KOB5xb3xOVM5e3rRnONbR3zlkXo+vw51AQkmoI2TJ/G1UN28OqFa/lwXRdumDcCzZFAdkqE0vJGzHbvR/LfcGH8jPKSRAFdN9BDKugGmmSCIdMzuQnQOexL5NTcRItTS1EQRAEpGiBubK6lY26Ymnqd+sZIdDZ2RGcchqGDCTZFwmMTcBnh1ggVsgCNxnEhMw2Dnh2cNIqpBAPw0PjdZHkDGKZAYZ2H13Z0I6RJZHjCvHXmZrzOFnDo3OcYwCs7e5DQ340kCm0a8Yj6425NyTRpEQQSTB9vHniKu5+4mH0XjeXNC9eR91Ac368TOfiXZWwpsvFJ6Tm8cofV01I44QaaWGlAzy3cxyXd9oIp8er2jpiizquL9lHvCzN8YAbrt1dCjARhmUsHFfLqhWt49NsB3L1kOIO7uLHboKgyhOiw4Wx1YfxPH/TPoP00WfSygxH9xzWZALo/jNPrZHS/bLpnxeEPRfhoRQm9UhogJFIVTqNnVqx1eLQwUBQsQz3UUk1GnMaG7RFUVbec9nYPhuK2KJNMcCqylb0QlQATsAuwTxWo1ExskkDEgMHdPRQ0p6Bo8NL2rnTwhilvkVl2II1Eb4RYu8bhBidnfDiGnDgfTSEbm0uTCJsCoiuO1HiZ8joreH1YtTSlYJr/9uQk0ySIgCJqPF36Nt/N7c/InWfjjnFT+KeFmHqAu1ZcwC2XnkPMp3Opd8eRMOU8TF3DFEREQWR/eZA9BzfyzjUlLNmZS0FVCgY1/O3tRoQYE9M0cHoFwiGJvjl1vHPBSl5Y2pe7FgzCk6CyqdgPZggwwBTancMf/lsV5FG00nmLAhgRnfNP68pfZw6ia6a37ZjKhoXke2sJNtnRlCxyEyUr5UcSo8QtAmWNBopWgRRrcPCYdcNEwHQlYtpciLql2eyKaKV/R10Khmk1Z9gRETB0o20ZGtgznncOp3L50EKenLYaQnawR2ge6uWRdf1ojsh0TfSz5rLFSIoKis7S/blMeGsCQTHWcn/UWWbBUQ38poD0E4yHIiaaCY02iQsbtvPh9iHkTHNyqFbl0RWTeezWa+n51YPsuP4+lBiQPvoK74RpaIa1YfnLhzu4qe8mFIfJX9f0wAjKJKUGue2M7dy7rB9/OnsQFQ0+3v7mAJ9fsJq1RZnctGAoglMkEAxxUe9DfFOQiS+ooNgEHLaon+x/szNW0634oiAI6IEIhm5AUKVv/yzeumFcm8cZoNqnE/aXkp/WwuajHuJi01GifBLqkUKUvC4IwKFKP8m2CrAL7C1qASxby4xNwxQV0K2cNIdNJnScNiLKCSuw1eILRtVNFEkgIzedXavc7FeziV0wGrdkUBdSWH0omfy0ZuIdKkUNbi74YiQdE5tpjiisPpKGGZCoCMXRPc/J2j0tSKJAlWpSYwhkCRBdkf8N1q4TGhEZ7TjKU3uGM7vuch68ejoDhDK2PvIgjkwZDJOS266gcsAYuj73Ep8Wuag7sojZNx/mw/XdWb8vm+zURuZO38Dp/Q6RExPgn4cy2HLQzwOTd5MT10Kf50/BDAiM6FbN4xM2M7JHKee+dTpfbM1FdqjtVq10ImRoH77Q1iFbl0stqNKrczKDuyQT61Coagxy/hNLiPc46JHpJS/Ng90RR4JUghSnsnZVHJ07dwY1yOGbriSwagH5q4qxJySx92gN+XE1oAnsK7aEzATwZP7gGhTRpFEzCYg29GhacxCB/VY9L5ph0r+zjWZ7Lg1+kcPXLSYjsRktZMOvi2zpkMR3h3PwRyQyPEFuGXoAty2Cakic2/MYN0SGsLUykf5d3TC/FkWAoGYZ/x1s1m7z5+6shAGaSnxiAt88cAqJXjc1H32C6NMQEhQwIexrRPnwa7YNncjtRdksmraexiYPN347mCtHHOSZqeuJtWngc9I5oRGpsJzaBpl+KX7OeW8QuanduXrqMq7ttRLZqRCqdzN32jqCEfj+cAdctuMV/O0FWQfEdqoiNomWawUi/OWKYTxy0eAffH+42kdxZTOn3TufLtmxnDOqHwNTy8HU2dzYmZn2ANUXn0/9ovVIIjTO/5jUS6/j4NFj/CG7EbPB4OCR1uC6CTHJoEcsV4gpEB8XR0WziCzZSBLBLgu84xMoixjYZYGIaXDKoDj2NGUSqXby0NpejM6tQDDAlEz2VyThC0sokklYk9hTE09mbAsJTo1Yu4opmmyv8HJaJ+8JkzYpVAUmOqBBs5a41rTqf4UoWhX2Z4/uSKLXjW6YmHVVGBqIERW1GVwOKB85gPMWqDx74Vd07djMeW+dQW2VjbVOL81BJ058NBlurp4/lOmnjuKi02DaXfX84cIhfH3tSKgrgvIkKupM0r2N1Pvi2V4ej10xENqNpuA42mW5bCVUi6i6lfNlk6hqCvGX9zdbfZYQ2FhYzc4jdUwfkofdqRDRRVbsLGDu6Fq05hhKKmNI+NMkqkuKsac60OrCBBZ9Qfji66itPUzvoWEOHYlQUhm0bDxRxIzNAlsMpi4jCrUc2r6G8qDMp6qbikbYZ0is9GsIQrQzswnjh2fwQEE6l47cz/jO5SiGTE1IwpR0SpodhFFQRIOgJrK/No6AJuCxaTREbCQ5VPZVe0gZlIjLIREKW/lZXzSbTHOJZEoG4WhWRuSE+9IqcAIQNgRi7XKUckywCkJEASkjF+8Zg8mYeTGTvnZwbcf5XDx6H499M5TPduQxeKCT/UedXPDxUMZ305i7PpM3bhpFRZPJqoImyEhlVN8cmgNhYhOv5t7ve/Hm/K1sv2UTV3/Tlcq6GJLTrMTR41fTPmh/Z2z02lftLef+WQPpku7F67Jx5Sn5APhCKoUVjazZVIm7Yxm9cxpZU9EBx4EismqK8SU4EFQVbCbikX1s21uNRyzBlmSw/js/mqahKBK6bkLBIiR3IkJtITQU88339dbJRZHtSCDo2CQBSbAa23fOtJHasSObl8Vy5mmHGJheh80wsYkmKDpOQWLRkQzCmkSqO8Rtw/YQ54gQ0iQkm0qOJ8D5H49GdyXRI8/OloNBbLJEYdjg/HKB6R6JfnborJikSSZ2rGYRIRM0THTAj0KoMWgVgBsG8efPxjX+LGLyO2FKDma8tpcLMl/iwenbeX9Vb+6a35NTBsWRkRxPYVUVa7amU2fPY++ro3hjyX6W7Klh/Yr1XKYX8MS9O7ir8xAuH5PDqJ4dGN0rnzGv51JwoAkcGiYySjtyYbSiXYUsohmEVIvuacn9U8hNjsE0YffRelbvr6CoshmnXaG83o8g2ji9cw2mK8iCw1l0bN6H3AJqSwjFCdhk7JEAKzceoE9KKUgiq7Y1Aie8gwWL2v4WJZBsMppmWn6z1mvSW48wmTM9lT2+HFymytqSJBqCLhKcYQxToCYksbogjQG5jcTYI5T7nVzz7RASnCEiuoiBSWFdHAQkDjanMaxnDFsOBDB0DVkUKTXgRevyiJdEuigmgxww2AHdFJN4USDBBEN2EOtxo+s6qmbgSEpBSUph67Egt772DWemfcLtMw/xweqeXPnFMExJZNnOZpJiyzktp5SzJlWxeH8h170q4PbY2bV0OYsqXybT34BuE5nhu5wdXS9n6gCRO99ZyuikrbxxeykrChJ5atsYlPZPwmhfITNMi2VRkEWum7uW9Dgngglh3cCmSGQnxaDpBkdqA5h2iamdyhDCNtYdTuFvD0zG8ZVGalIGgc2r8C3fjy/FydpjVTw+qhKjzmTd9gbrRILVB8mQFDTVQMeq9UTXQFTISHXQOctOjzwHPTo4yc8VeHFTbyZOhhuWpNItu5HvLl0KhlWJrekSpk3ln8mdeG17VxYeyqZXSjPfXLzUGlcxQLLqDbo/cTbzC9L44+kJvLLMjkKEYEMNnNAhuEEX2KSLbIrualNlkb42k97xKaxQ0rk6XIEkdUGSJBpaNB7+7ADLNi7h6dNXMK5fDS98P4AbvxkMusTQjpXcOnw/53Q/hmyDHcdc7I2JZX84zOJDjZxiHKGbv4ECm0JuSOV8qZBH9tcwYsE+Hpy6lbtOL2Z1cSpbyxJxKgLSb0yr/mNoVyHTDdMyZjUdVdW5akJ3hnSxiHDr/WFe/34/3TPjkDWJ5IQWRnesYs+ROGyODoydPAImzwMgUlOF/4sPOJjSm6b1e+mWG6Rgf4SiUj+iKBKJtD5Qg4R4BwO7xjCqr5thPd306OQmNcmFaHPRpLkpb3Gyq8rLPlcf7lhZy4FaDw5J5+wPJ5AREyArNkS8w/K9Fde76JHYwBcHc3HJBtd9MwyP3UQ0dWJsOkFD5GB9LCV+N85eMxh1ZSzvTFtGsLKaHQU+Vu3ws3ZXC/uKg2ia2nZfqhBZpAksCjRA2Vu8fOOnHF54Ogl9z2DJIZXze+9h2037MSM6V7w9jrfXdyfWG+SVaWu4cEAhJTVeHlzdl/e2ZlOl5fHM7IFMTID8vVU8dWwwg+P2MDZQyH5vAk9G+vDyHwbTK8XB5L8aPLm5P03+GAirdOkSpWtsZ7STkFneeU03aQxE6JibwPf3TQZgc2EN8zcf5fP1h1F1Hb+qEvHD5IFVKHF+Pl7Si4mDemMaBrpuIIkgJqeScPUtHN3hZ0blewixGg//o4RIREcQZXp18TBtbDxnjvTSt1sMDo+H+qCHgtpYltS4KS2y0RIRsEsqSa4wKa4Wvpj2HYkulSxvEGy6FcA3NBANq9upAEhRBmdTtCz2sAwRmeaQTFPIQZnPydD0WorqPWwuT8AtR3hqfX9y4lV69/Fz96mNJCkNNNY1smF3E1+vamTpZh/HKgLWuOgokkhjYwPvf/gRfPgRrhgX/Tpn89miOO7dczEHytLJTq1g2ezvcdt1zn33NOYVZKC1OEBs4Zs77Tz63S4qqxv58u4zyEuN5ckv0nm6opw6XeaKqYNZs7uG+IGZjBncl4++2YkzOUJEiKDIsRbBIPzvdcaapomIQEAz2FRYw/I95RSWNDA4P4Ulf5tCWryLG99YwwtH9nFJ72PgF9lc14PXhmUhiCICArppIltMDjzx/iq62HORPmwmEjnI63d3ZcLQGPLyvPj0eHaUe3lzTwwVPgW3EqFTnJ8hqWVc3MOP7AxZwhORqW5SqGrxsKcunm8K0zhYLdKiOdAFJyFdprLJIKyaKLJIskfCJmrYhDBxjjB5CQY5sWESnS1keloYkNaArecRcKhgSAQa3Oyp9rCjMp6lB7IIaB1J96oMyW/mibF1eKhl94F6Pl3SwGfLGikqsdoVipKMQxEItwQ5+86DgAAdYvHkD2f5lfto1mPp/8RY/CE7CCZx3gDvzljH1MRCvrSNZF1Jb/aU1nHdafm8OK8QJa8jH84ZytaCcjzhdTz/fgl3n+rjc09/QhHRotGQxP+CHmsvFwbWixFUdUwBKo/Vc/7TS5l350T+fHZfAJ7+ehfvryxgW2ETnTqEGNmpnNUHE0hI7U9OooSqGVH6b4GSeo0b3thMRclBJg8Lct6QENed04va2nhWFCfyxjI3smHQLaWJs7ocITu5GSQdPeBgZ1UcL2zKZl99CnuqYiludOF0JXG0OgJ+HXdqLJef2o0Eu8wz3+xCrWpm/LgunNU3k+92lPLZqiKIdzGqZzrVVWEKlldYk7MJeOIkgoFmcuI1Mtx+OnrrGJ3bzIicRuYMLAZ3GMIyByrjWHs0mQV7OiJI+QzK9nHjtdU8cmM1m3fVMvfrOj5dWk+zzzLaHHarplI7vJhwyWLm1MSw3TYVf048ir2RU/Kq+Me560n3+okEPbx57lrG907D44hl4t/mMy1rAZtrO/HavAQW7d7GjqsWMucKFYwI758X4oqvRhIwBRyKhCAIvzFp1L+jfQ1/wyTGLjP+lK6M6Z1Bn9wEVu6v5O9f7GDmsA68c/MpXP+PPXSXPkf0Bnh7d2+mTuyGgIAiC6w+0MSHq4o4emQj0zus56t7y9BVgfkF2axZm4xd0hieXcvdI4txelsg5GD14QRe2tybzRWZbC/30KDGkJOWyLFj9WDqfHzXqUzun87eknpOv+srXvxDby4ea3VKy4lTeWPxAZbdOxaAO87sQNbsY7x1wwhO758LmJz/5GJW7y5nwX2T6JDq5fGv9/DYW5upyexCJGYYHy6tQ21uJjFOpVNsHad1qmVKfhWzo0Lna3Dx/aF0/r40D1PsxLjOjTx/fznP3V7F+9/W8PzHNew91GQ9HEXGMGHZNj/wETZNROs4lTpdZcGhPGZ1KyQmJsSusjS+3xPmvblLeGHaMq4/cy+Tnk/no28KGNw/QHaSSiQoYbPbOG9QMfev6sm+Whe2/0LqNbSzkDUHI8TH2JkwIJtkj4Oa5hBT719In05JuF02HHYFX0sDV487SmOZgwoGcsHwFL7dUc+rC3eg1a/n6gHbOOuCGo42JvLIij6U+1wMzqjh7jG7iUv2YfrcLCjI5KN9OXx7IB5NScPpcFJVWgc2g4V/HcekAdm8tmgfj3+9i/OHZwMwtEsKU0bnE1StzYkgQE6yl1G9stoC8SHVpG/nVEb3zKShJUK828bonpl4Y5wM6JgCwOVjO/GPRXvZ/vQk0hNiOFLdRO+bP6fOJ+Px9uaRDUEeWRogOTHMoNRKLu5bxrRupcwYXEh9XSyf7c3mui970jGpMxdMKmfOrAoWr6zmwbcqWb2tHjCx263OI9qWD5AqdrMlcwJb9nflzPsreXVVGncvGUCk0cHoPiVcf2oRu/bmsrI4g5hcgbiUodyy0Mcz09ewsziOPy3oSWVLCtk5x3n7W+fbXmjf3WW0xXGHZA9Xv76GYFDFX+On+7guXPniCnx1BpP6VdGvRw2vLc6nNpTHxc+uJFC+hL+M2sGwbk3sOJLBTd+OwsBgVo+jjMwvA0NkRUEWr84bwFcHUgg3x4BuMmZkFl/+eRwJMQ7ueHcD/1hxiEkDcgC4cHQ+/1heRFjV2XSohj65CYzumkpzQKUlrLH7WD1JHjt2SUQQBBbtLGNYfjLpcU5cNpnnFuzkzul9UTWDEV1T2XyohohmUO8PM3FgLukJMfhDKgkxLuwOGx/dNpopA3MpLG9g0J++pKZOZL3Um28/6IDDHWRS1zpm9y9izvBDzBm1n7WFGTy7KhedPC4bVM6qD0pYs7aGe14pZ+WWWgAURcYo241UthuXU+aSJ8ay2HYRRBqJS/Yx98yN6BGRaxYMJhhWsEkqB8urWHw0j+2lMs1CPmP79uat6Z1YsK2E1xfvb8/H34Z2FTJNN4ioOqf2yeDF2SPYXVzL4YYAy3eVWVUyskJuTC31DS5e3N6PLNsK/thxIyPPrGdTYQ6XfjSAeEeY6wbvJz+3Cl+dlwcW9OL9vV0orIwjLT2eV2/sgyxo/PHZZVw0JpeEGAcN/jB/Obc/n64/QmVjAI9DweNU6JbppaSuBX9I5dP1hxnSJZnPNhyhsiHAlxuPcOUp+bSENSKawXML9tA9ayROm0wgrLFsdzl/Obsvtc0hRvdI44sNRzitTyYHyxqZ0CcD3TAJqzrfbi/ltF4ZTBmYSyii0yUjnpSEGJ68og+XjevEkl3lnPf35Xy5MY0v16XgTe7NdcPKuH7IQV6cuZriY8m8sqULr23I5MrB5az4IJlFi6v503Ol7CpoAERsNgl/UGXxl+uxjcrHldmfj2ZtpGteFbd8Oo71h9NBaSHSqHEsqHPG0CxmjD6d80dk4nFY3temlggum8WD0T4c/sfRbrFLBMvwR7BssykDs5ky0Fqq3l5ewOFqH28sLWRj/RB6P5OPP6Kx5MaN6AJc8cF4TBPuHbOLLh2qOXoshT9+NI5/7sgmOTmHRt0PWjVf/WkSQ/PTAKjzq8zbfIw5E7pzz4dbeOmqkQzLT2FrcR2BsEZmgosz+mexal8lp/RK56Xv9jF1YA7VTUFCqs6qfZVcMT6fqqYgZfUt7DpaT2F5M2FVp6Y5xMFyq8NIaX0Ar9PG8r0VXDquC++ubGDakDy+3HSEs4fk8e32Em6Y0pMvNh4hLzkGf0hjSOdkrjqtGwCTB+SSkx6DOwuundyTr7dU8si3cTy3qQdndz3G3WP28MS56ygpS+TZ9d14e0s6N485ys55Cbz6zyrueekodY1BJElCFoJE1rxCSrdMRtzUgdeW9eXZxZ1AaSIjycvMKZ249JR8+uUltj2bUETDpkg0ByPH3RftjHZ19xqGReEtS2Lbm67pBpePz+eycflkJjhZcN90Fj50MfHxHUl75EwyHzqfgemNvH3FIlQNJj8/mrzHJvLK4o5cfnp/il+azMFnz6RLh2QKKnyousGGgmpumtyT0voAlY1B6vxhPlxbxHVn9ODjtUUkxNh5at5uRnRNZdmecuJj7KzdX0VlY4CIpnOkxse2g1XsL22ktjnElxuPUFbr55stx/CFVLYU1VBa2cy2w7X4QxEKK5rZerCKTYdqqPeF8YdU7vznZsrqWyivD5Cf7uX+j7fRIyueVfsrufKUrjQHIlQ3BTla4yes6nx3/1Rmn9qdeX8ez6kjk2ip9PHe+ly6PzGBc18/HX/ExlPnreH2Eft4YXU2f5o/hAtnduPown5cOzMPXYeIIWGz2yk4UEbciDXc8nkWo4Zk8MYtp7D7+fN4+srh9MtLxDCjTnETZElEFAQME5y2/04dUbuepSWstRnVArQlKL6zvJDvd5XSPdPLiOu+YNY4gadOWcO8ffGsPpLGi5s6801BCqtLspk1pg9XdPLz7sJdjOyWjGlCstfFs3NG8vBnO7hkbBc+WVdMfIydOad15cVv93LR6M5c9dIqSt64kOveWEdLRGP1/krK6wM0+sMs2VlKU1OAp77aQXMgwpOfb4eIyqOfb6O6KcS9728C4I0l+0nxOtlXUo9gGtz5zgZMTF5auBtZ17nl5ZVMHJzLk1/twDANFu8sIycpho/WFSMIUOcPUVbn59Te/Xht8QFmjezIcwv3cuvU3iR5HNT5wiTE2ClvCDNnRn8uP60LWw/Xc8Or25hfmM2VA47w6IStvH7hCr7b3pk/fNyHSd2rePlZD5dN8nLKVTsJhDVyc3O4+prruOCyP5CXntB2/7VoobF4YupH67MJqcj/heA4gGyYpthe3cEgGoo2rYl+v6ual75cxbc7qonxeLjilM4cqWnkmW915k4L887Z60EweXljd677eiCxXokLhyVyav8BjO6exqvfH2DWyE6sO1jN5P7ZvLBwLyv3VnDxmM784eVVLLjrdE55YCHnDutAVbWPhz/fwcCOifx57hrC4QhXvbwCU5CYPXcj7pQk3ttcA7oJqg6eBLYdbonqdhlkE3/ExF9ltRTEEcPyvfUgiTjiXCR0zKb8UC2f72tC8wVJjbPx4sJ9xLkVPl15kOvP6svjX+4kJymGTzcc4Z3lBcwYlseqvRWsfuhM7v9kG385uy9vLD1I96w4XrtuDADDu6az/mAlH3y+i1cX5zB3UzJPTCrglrG7OKPPUR78dhAjHxrGxF4+Tp99KlMGdmfGeefh9Vo5ba28bZIgIP8MmYqmmzht7dUo4oeQbYrslqRoe4rf2PxrCWtR+kn4bHM1hzY9ziunbeasuulsOyDzz5WFpOYkoPrqKfXF8dT6PgzJqOGP47aT4g4y89NxXPDMCnTDpP69y1l7oIovNx5BkUXuen8zL84ewYwnl7L9ybM5VNnMi9/vp1dWHP9cfpAO2bE88P4msrOSKKmIgNPJnpIQGCFStWYyjCZSI3WkhetI1H1k6j5saoAkwuiGDoaKgECcBJWCnYgpYSIQMUyqTIUtmkJfdyItvmx24qCqOZkq2QsxTvp1yGRzUSMRLcJLs7vQ//pPePb6cdz70Vaum9STZxfsYUNBNYIAry7az5qHplLVFIzajm5W76/hgml9OGNgJgu3V3LrPC/v7MjhqkG7aGiBGn0InswefHRNB1rrv3Vdt6q6BAH5JNwRgYj2X0nzgf/C7tKliDQG4aNvP+Wj6WtYd6wrxZUOeveIo0N6PKW1PvbUOfhqr5c7R+2mc4LFgTFjRAHT92Zz6rgrKa2o4JT7F3LXOX254uXVrHv4TM57cin9OybROT2Wp+bt4qyBWdz92mp69shkb1UQBBlsLhqOlTBMr6R3QzE9AkfpGSrHCDXSQW8h3oRmHRJF+C4E//TBeDec6wK3YKVrLwjCxz5wiPBIPMQLEDThTxLsbYRqA7IV2GYo7BDj2I2T8mMD2OEcAN4U7vpqP33yM1m44TCaAAM6JHDLS6vY9/qF3PDGeu46py/F1X7eXHKApy8fxtvLC3ho1kBO6ZOJ2y6RkRDDx9/u5EhLNqt9Y7lwQkeeHpiIpQ8MNM1AkiSiiuKkoWpGmyZrB/3yA7RbWAksvliPU+HjdSVMyVyDZsaxpTyJ83rsI6Hbtdw7vQt//3oXMS4bV4ybwNd7jvJ5wVqy3KUkeIJU1Ee4+c01RD68iHdXFnLliyspLWnkhYV7OX9kR85/YAHD+mXy0O4KEhLiweFi74EjdDPrGe8/wIjAQbq3HCUz3ExIA68E7wdhdURGFBVGOGCyy+SjoMjXqsQNKRprwyI3+QX6KwYbQlZNwKMpOpvDcGmjyEPxOpmKwBt+gU0RkcIw3JegM82uMk6vwQbUHj3GYdsClkZiKT7SneaeM9h10EZ8VhJHvtxP9w7xLNlVim6aDM9PpcPs91j26DQW7y7ncLWfGyb3oNu1H9Os6giGwYOzR3PD1B543Y62e2wV/YrIv7rzriVMYU0n1tX+VJ7QzposrOqohsjOQ4XckNeAXRS4uMc+puw5jZeHZOGyK9Q0BdlbUM2kWxK4fHw2BZVD2Xa4gSPVfmblGDzVyYM/GObSsV0wTLjq8cXMXXKQlBgbPbtlsbNaJ1jbiLb7O65q2cagUAljRD8NIbihHhJtImfEyIx2CXwVFFmuCTyeqFKkwod+gYV+UMwIT8ZDIjDcDntFeM0P3W0yt3stYuWuboiXZP5UK+Awdfo4JZ6Nj1BuCNxVJ9E9SSRFNtkSEVmmSvhCBnd56xBr1nBg5XrelbNYsdtL/nlXsDzYiVve3cbtU7sx48kl5OcmkJfiZsaji+jZMZlu139CXUsYQhrnT+jGPTMHANHGG1h1E/8xeV30ZxHNwPX/wu5SwOKWr6pvIK6bwd4agz9/P5rbZ13A4I5W0W5agoe6siBbixuY0MdJfppMfloKkPKDsRbtreXutzegRXQaK5tolO3E2OqJP7yG2Y1buUivoIMMpmT1/b45aGeQx2CKy2RxUOTrWmiOhHkjETwq9BVgQDysithwOhPZKcVSJntQFSduWeI0rRFfZQFv+RQcukq6Ap1FjfsToF72MEX0ERZFBgkG13tFLqmSGGA3sYsCw+06u0y4v1nhmUSdnprOaxylWoSNH9yKkjqG+d4hfLg+hrMGpPLF6sP0uOU7mivr2LC/0mLasdsRBI1pg3OjLbbN36RfeKtoqpqBTfnfbJNFvbHNQRWbZNCiuznvkzPo3aMn98wZRWamm1WlIYL1jXy/bh8DjUMIuvqDm6jpVqN0RRL5+NPPeOybAzx82UwieoRdpQHWLfuG4AcPsjATrvcrXKcq9HQIDLCZ7FEFHILBfbEqhgZj3HDQLVLtTGWTPY1dSjqH7akUK8kIiemUizHEJiXQqFoUCC67QvWhUkiopEvHNBI8TspKK6kuLUUJNuH2JvLqgS9IqjvGoLRY0tRmbBpMiBOY5TFpMQTOcgtcUi3wdrPAMLvIGyGJ1S0w3m3wuX8lfy1ayXPaZbztn0zE38iIDvWUOeIprvGQFe9HFlsoJpah+clRaobf9hGFVf3/DU1mmuCyy7x/0zgaWsaREGdn9vOLiV/0IbLqY27cFB4tep5Lmndw1fMpPNdrBCkJbk7tncFlQ9MBk4ceeoh7772XjMQYCkf3pywSR5pXof/AQXx0YA4316/gaKCAR9MUGgyDtUGT5ojO/V44KseyPi6f5c7uFMR1oVhKwpGWgsflpE9eAnmqSl6Cg4G5XgrKGvC3hFiyswy3GuSWK4dy9qiudE2zqKFaNCiqDtIUiCDLIop6C/e8+R2PbPVBpJLskgW82XCMBc0aU2PCDFJMHvJGuLNBZlNYoJdiMMsrcnu1wE7iKUjOJSjGQEuYJLdAxwSN+qCKHhHomeIjElJRYjrQKdXT5gL6LaHqxg8Kq9sT7e6MBUj0OEj0wJxXVzPy6Yu4wF7Lc1lTyFVqmSwfJOKHtEMbOXZoP0Or1vNs7FAKH7ifMxNKuPfee7HbHZTX+XnhwTuYt3AJEU2jsMpL/cUpfLWiP7cID3OqVkqTCKMTFNZ4+nCPdwgr3N1ocSbRp0cGarOf7qLOmf0zuXVqT77ceISjNS18uK6Ytbsk9h6pw22Tuf3cftx8Zm/iXK3OARPTNHHLIn0ynIAz+rmHLx+aQ58bP+VwWQJnX34Ofl89jUGTqxYuI+3oCsaEj/J4so9kQaPKEHjfD7KuMT/vfOhyGqgtCHqIWr+Dt9Z2BkUDm0ZzWGHXUTvXnJMFCOiG8Zs5TltlNaTqxykK2jl1sX1dGIbR1hm2Kajy9cYjXNRxMOOTR1Joy6dLUgtdXtqBvKeQfa9u56CYxTipio8Pv8+MhadxxT0TycnKpLS8ApvNTqh0H88+/iBp46/CCDVj18Ig2pmbMxtvyyrKlDgWegdRkdwJUZY4s0ciphohwS2wtTlCWlwMfzq7H6GIxg1vb8YjiVwyoSsdUzxU1rVw9oiO9O9gxfk03UQUj9NatSKi6VbGrmG5AJ66YgjT7vqayvog3bMz0auaOOP0qXy3pS+fOFys3P02sQcXUmwqFuMjYFObUfUIaEFMQUaUDER3GNMQsCs6JuAnhlkjc4H2qfDXTtRk7RzCbFchC4QtF0ZNU5DZL61BqTjGHk8+HtUPZj1lTRIPL1xJQag7G8088Ldwb+bFfBHTn7KQQKfsDJ5//nmmn3MuYGKIEl//81U+mjWTYUMGUe8LctXEHnywvoS/re5OZmoseqCFU9OcJHvsjOqRigF8vuEwWcmxJMXYGXvXPPJSPPzzxrGc1jcLr/OH23jdMC2H5r8Ejw3D/MESo2DFY88anMvo4Z34Zs0hSromc6hOJRjSkCM1SEXrqSpaT5UmIgg6imgiKnb0lG6YhgpIVmGyYZXYIUAgZGddgcmgXin0y0vENNunk1tI1dtoo9ob7S5kaXFOHvhsO98s2MUa//N0O1SN59zh/GniLPqH/855A0rYetBNcdYF3DXjFPwP/ZE1TbGUywm8v/YwF519DjNnXcDHH32I3W4HM8w9N17JsGueQ7B7SfXa6J7qYnCazKY9h+jWJZUaX4Sa5jB9O6ZwoLyRUFhn28FqQhGNG8/qw/0XDGwzejXdbIt9iT/hGjBMK7j88Oc7iLHLDOmcjCyLDO+aCsCd0/swZctRNh7zY5TtRjiyGrFqF2o4YDXIEEVMQcDQddSMCRDbAyHSQLJHZXr3EnwhG5/uzSbeHWFil3I+3hjHFad0s3qqR3sMtMG0egYggCD+eiE5cXatzNc/KcLRcwmthaz/Idp5D2vlj/9t5kDGT+zJo3FnsTIth51GAvuONRFri+COMeiZHmFAp1jOGdWF6ep+Xtr/BafVrOfiJ1ZzpLKJV156gdS0NFRVRbE5OFRUjG/Lp9w1oz+n9UojI9HN5CEd6N8ri8Ij9STH2slMctMUjLD3aD2NgQjZ8U5W/306j182FJdNPiErwYrxtWYn/BhaU5dunNKT1xcfYPzl/+RQpc8i8TNMJvbNpHvPXIyDq7GvfgLh2AbMSAAkGVOULCZs00THzv1XupjRowAzotA/vZFYp05JswtNFzm7Wzl6JIInMZkLR3UE+GFdpGFYNAaSZAnYCbRcJ/1EonOMaL9g+JvHz8V/eK5WtJMmayXA04h1KSTE2Ln1zF6cuaWUJYOHIvpDBNce5HDeOSyvL+G7fXYO1zdxpHkRbu+F+Pv5qewxitfPHkhcjJ24GC8vvfgSM2aci2EYyLLCd5/9k2BsRzqNOAuXEMLrctC3QyLbD9eyeG0xV5/bn+W7y9m0tYRbLxnCoxcPxiaJaLplRP+aJaj12FinjfNGdqQ4N4HnF+5hWH4yndKssrIXrxzGWe/fSdgUQLFZhcXRxmAIIoKhMWFsHtWOnuzY56JDmo+uic2oukSlz0lSTJgMj8qKA7Fce0YPvC5b27UCmLqGIMloNRWU3ns7nnHjSJx1Vdvnvwat/Hx2248LmanrCJKE3lRHyZ9vwDN2HIkXzPmPzgX/BS4MpyJhmrCpSuWcqoWcr+1jVud7SHT4WHbPGei4WHzXR+i6zNK1u3mqejUPJE3jH9dOYHrvZExA0zTOPfccLrroIt5//33sdjvhCGz6/EUeuG4WEVs6/kCEDqkeTMPkyw2HWbGzlIOljbx19+lcMd7i3dAN81fv0oIRjcLyJuI9DrIT3TwaZSYKq3qbJjAMnVO6JzJt8hg+eHMPNsFEO5EUzdTRTRfDzxiDXwxyqKwjZw8qZkBmPSUNbsoaY/h01hp6JNby2rbzuXlKd6ucsJUrNvpww4cPUnzJmQR2FVL/+QeYoSBJl9+IqWkI8i8/ytYIpW4Ylib7kUYRrQKmVpRQdMkUWjbupuGLDxFEgYSZV530uU5EuwhZ66rjD2k47TKCAAkOkQI9lt6Nh8lRKxjUfADbRc8gCTr5jsnY5XTeOPocmY3VvJE6gV7ZccfzoUQRwzB49tlnWb58OZWVlSiKjcb6WqaedzETb3wej6TidduJi7Hjcioc3FfJ83dM4Irx+UQ0A+VXaq9WQuB5W47x2AdbcMQ6qKhrQZZFvC4bmYlu8hJjGN4tlSkDs4lxitx963V89eHbhEIhq9QsarSrqsGc89JITE3gbx92Z2L/YwzOq+ODnR1YtD+TW0ftZ0x+Oc8uzeLaMweTHGtrO3+rgAX3bafooimo5RUo6TZMVefY7TeBKJJ06fW/6uHrppXj1+rCaH1erQIWKT1M0ayJhA4eQsm0YYZ1jt44B8HpIv6si361oLV7ca8t6sW/ekQmO66aw4RlQ6gISzhIQt1fSLkAi3pmEBeJ8Df3BHYkZXH2zGl09lrlYFbCnYCu6yQlJfHyyy8zffp0JNNaNusKtzDetovhp8+gqMqHL2gxYb/bGMTrUtp6ev9aL0CrQJ49JI/zhncgGNFZurOMDQXV1PnD2BSRrhlx5KV4sCsShm7Qo0cPLrroIubOnYvNZsM0LHqG3p29vHZ3Hmd/GkdSQpDs2AC1PoWi6lienLKF2yZv5kBBPF9XnM7K6/IxDEuLtQpYYMcGii6aglZfjxQrYYYjIApIHomS225AtDtImPkHTE1FkH8m6B1VZapmEFb1tmcDWN1eJAm1qpSiWRMIFRQhxcmYoQhIAqJT5Oi1lyJ7E/CMndQmkCeDdhWyoGq5MADsiszb14ygdOYACssbeeirfVzVdJRIUho3XDGVMd2SqQwJ3BinMKGrld15ouKRJAlV05g2bRoXXnQxH7z/HjabHVGAOTfcSZ8b0xmTn4TbIeNyKMguG3e8s5EZwzrgsElt3GC/Fq0Pwm2XOWtILmcNyf3R43RdxzRNrrzySt54440oA7dVzvbhY92oj3ipaFb49vLlvLSlK+OzG9hRkcScAQXQ4uC2RQO449yxuG3WZkKICljLtrUUXTAZw9+M5JYwNf14JqhgIMZIHL3pKsQYD3FTZp6UlrH2D0KbDxPDjBJFN1N86VRCB6MCpmnRjCLTateomxyeM5P8+RtwdOlhDXQShC3turtUteM7Et20grxZ8Q7G90xj/u1jqJ00mxl33coTM3tzZt80rhqayoSuCWhRohZNN9F0ixPDNE2U6M17/82X6dypA5oaQVFsCGoz6ce+Zmj3dJJjHeQkurlxai+MoMoL3+6N5rT/5+mfYc3AHzxOmLJg6zEe/2pn298mtOVzDRw4kC5duqDpBppu8PhNXek5KJav9ybx9rQtDEqv5skzNvHWzg5c0P0onhQ/H29Kw5ZyOucPTbH8dKZ+XINFBUx0StHOxSfANEE0EO0iR665GP/axQiyjKlrPzufiKZHNVlUyExLWEpuvwz/pp1I8VEBOxGGdR69wcfR62dhhILHr+EX0L5Cpp/YmcNiEjRNy95x2mW2PDiBP47JaWP/aYUc9VfJkuVakKK1kM1BlXUHqrh1fgVqzwstyhLdQJJEvv/kLR574R80RUyKKxspqWsBm8zfv9iBL6i2nftk0SqUW4pqmPrgt4y8ax49rvmIt5YVMLBTEiv2VDDjiSXU+y0SZNO0tJmiKJw+8VQE0+TcCdncOCed4iInNlmkW3ItyAZbjiaT5/Xzh+H7aap28szOUTx56ZCocrIELHhgJ0UXTokKmPjvAnb8QhFkAJ3iK2cQOrATQZIxjZ84Huv+K7IY1dImoixT+97L1H30FUqSgqn+uJCauo7klfFv3E3Vcw+AKFo+u1+ADPpvHrZoHS6sGm21fa2fCQJIQusDN4/zygIVjUEa/SHqAhpFAYmWxiYaahs5VuOnuqSCDTU6ldVN/PnAa7xBOU94JBY1G9hkEVGSYOvbdLnyLMS0dNK8NvrkxHPf2xt5Z0Uh10/qgfYrYoCGYbmHlu2uoENaLC9cPYrN+yvp1SGRtDgXC+85g2tfX8vsl1fx5R0TrJckOsk+k2ZjblZ46o4i1ECYN3bmc/eoPZgIVDbG8PauTrw8eQMoJvcvyefcU6fQKcVudV1RZCIlxRRfNBmtoR4pJrpE/gzMVi3T3EzxFdPJ/2YDclJq1Nd1fL4mVtV4IKJhGCaWJSAQqa6g8u93IcWKv6gFTV1HjhOpnvssibOuwpbb6UeXTVmS21SYiG7t3toDrZwWP/qdYNkFoiC0abHb/rGOHnM+4/yb5rL5Dxfy4ANvcM8b6xj/yBTueHMmr6y4hVwaGW2rpmegmrsTIMUmoOo6kiCwt6iEq667hcKaEIt3lFDjD6O4FJ75ZjdGtJ/5yUKK9ie/emI3MhPdSAJccmpX+ndIRNNNDNPk4jGdf6gdow9UcKczbHgauZ2beXNjFzrGteB2BhFEkyfX9eSGQQeJT/Szdk88e/Wp3DY5D03TkWQJvamB4svPJFJSflIC1gpTN5BiZEKFRzhy7XmYmobZSoz7L9ANa0PWmk7W8OV7REqbEO2/3P8K00RQRPS6MA1fv2999AvarF2kq7X6KRBRaes38zMwoxOb2C8HhxzEnhaPipuNR//OjcFlrO94CjXJecTIAj7JyZ9zZuMTIEM0uDtRwEQE00CSZWxlGxjjLubCcd0Z3DGJBy4YRCAQYeXeiigv68mtma1VZF6XjfvOH0CXdK+VPBi9VkGwyJVP6Z3RNofWmTptCtf0PUBjrZt15clcMaAARJOv9nYgLSbIiC6lRHx27l07gscuGYsomAiYCKbJketnEti+D8krn7SAtd1HTUOOl2lavJryh25GkKQfXTYD4VZNZj3+0IFdlmH/r7em1eP/bycCJIFw0cHjN+tn0K42mSCAfBLMMVJ0CZs+tCN5uV7mzVqM66renJd3M5eULGJ48wFWJPVjcXwf/nr4Q8psSbybOR4xbDDJZXCO16pqE00Tf9jg1DPO5i+vL+S7baUkex3EuWy8s6IQ+Pf7CNbLq+mGFWr6ke9OTHtu7agiAPtKG5nYNxNNtwhLjKhtmeyRmHcwl+vnD+X6gQVIikptUwzfFafzx0EHQBR5bEUewwdPY0CeC03VkGSZ8kduo3HeYuRE5d8N75OEqWkoSTJVL7xE4/yPLPvsX+w5wzRRZKlt5ywoNksZnLCdF0RLq2lN0bZFJ64CVjATTtKF8ZsLmclxwY5oBjH2X/aStHqh41wS/fJ7sO6om2cmfculs1Um93uUBWI/EivLyA1Vo2Z4cdpMXsw8j6Mx8eiqyZ/jIdsuohkWF62AirLtLW6e2h2Py87gzkks2V1ORDOQo8vgv15va6hJ4LjAEf3uRCeuibWBqWoMYpom3TLjkCVro6LI1hiZXoMvtnYlxR1kSMdyMARe29qVmd2O4Y4LsrsohqV1k/nrOV3RNQ1ZUWj67nMqn30WJVnGPIH68z96BqaO6BIpueNaIqVHLYExjLaVMBjWfpCjFjf5PDAMjKBqCZMgoPutJTB++lmYqokRtPxogiSDoWMEdWJGnHLCXflptDtNwclv6KyHP2VgDsuPZaD73VzXZweL/7ianDn5OO8dTfcn+1E8eRSKW6YplMJ9mZcgYRKHyX1JJggiuqYjyQpff7uE0y+7jVUFjXTPi6esvIktRTVt1wWWhjINk4aWMM9+vYvZzy3ns/WH2wTuRC124pwA1hdUk5/hJRjRefqrXVz/+loueWYZ320vwRvjITXdx10j9mKasPVYGkFNYnx+CWZI5s4Vg7nvwlOxyyaCIKI31FF693WIDgHT/M8D0ccv0kR0CKhVjZQ9cD0IAic+Cd0wsSkSNrsCpkHsuDPIfvIpJHc8RtDAVE0cnfPJfekTOsz9mpxn38aWlonWpKM1ahghk9TrryR++sWWjfYLGk02zf+BA+lnYPm4TNz2kyu7EgVLi4zoksBbkQyEsIBqOOibXE3frFKIKFzy+Wi6J9byxczdVPrs/HHZaD5sGM5FNesZ6xS5xCvwbgPYRANRkgls/4JE/RKCcjJJboVvt5cyomsqpmlimkKbcT/kz19zaGcprux4DlT52FJYw7RheQzPT0H6F3uj9W6tO1jFmYNzqW0O8cL8PXTM9LLzUA12u0hmSiojsytJ8rZgqDLv7c3jhkEHwW7w6tJsMjufxSk9vG27ydJn/kq4uAo56Uf8U/8hTE1Hjpdo/Ho+/suWEDPqNMs1IcoEInpb3lxrMkPy7FtJvOhaAts2IrpjcPbojaDYMXWdhHMvwztxGi2b1mEEfDi69sSR3+ukr0VEkmxRF8ZvI2zRUVpJPk6WOab1WeYkKijONCqaZBRFJxixYegKt3w3jGHZ9dx17jpMXSBkiLw7eS2PpV9CpSuWSMTklnjId4pENANJgKr6Zu648y502UXHrARW7in7wck2FFZz/QsrqW0O0WNgDhHNoGdOPJ9uOMyImz9j9F3zeHPpQUIRvbVPa9vSuXJfBdc+v4Lb3t1Ii26wbGsJdUGLkurUv3xD9yQ/uEN8tqcDed4WOmbWUl7u5p1Dp/LoBX3QdR1JkQkfLqDuvblIceKvNvRPCqZA9Wt/j07bunbjhIxlACPgp+z+W2jZsoaYEeNw9R2EINswIxHAxFQjSJ44Yk+dTNyZMy0B+xWpP6IoCs72cGG0GsG/phS+1XcTF5tIpV8B0cQh6zQ0uSnxubik12Gaa+I40uxhxnuncs+i7gRjvDyccwGKaeLA5IFEEyXqJJQlCXvlVnyL/s4lo3I5WBWhsSVkCYoA5fUBahtamDQwG8kEECitC2C3SSguG2t2lfPeqkNEooazGQ0s1zSHqPOFaWiJsHZvObX+MKJdRrFJBCM6NdU+0mIiELAz/1Aml/UtAkTuXtqDq6aeTmKMhKlbqdj1n/4DvUFFiDpGf0uYuoEYA761KwgXH0SIevhbwtoPcuciJUeoePRZii6YRN2HczGCAWtnabMhSLK1MWgdMxIBQz+pcFIrRPPXmE2/AqpuoBoGbodl+J+Mv7fVPRDvcdMctiYmKDpbKxLpmdRMyBDp//w06gIKT521GbdTQNb8fJswmvlpg5AiBoPtJnMSBDTD6i3ZEjF54sW5VO94GMWoZU+JLxr6Mxmen8Kgvlk4JJHdh2pw2ES+31HK/qP1qCEVNJ2/ntefWKftB2GpozV+pg/J5eDrF3DdpJ4MzEvApoiovjBqSxgQaFHhuTW9GZ9bRVxKM0t3JVGmnMHssemWho92mPevW4pgEyyf1m8OE0GW0Bs1/OuWtRngmn5Cy2nDwJHfk7w3XgBT4NhNcyiY1IcjV5/Nsdsv59itl3L0ullUPH4PwX07EGy2KB39yWuydg2Qi/xnjDGCIKLqlr1gSga7a+LIim0hJaOWv47bxeUfj0aJCaKGFGJcYfxhlT8nz2ZQcyEJwWauiTVYExDZGTCwyWAiU7p7NzHxI9haVMeoblZv74QYO6f3zaKs1k9ehpcqX4h+eQkcrfLRKyuOa87owege6dZcxON+JI9TIcnjQBYEEmLsnD+iI2eqOo3+MEVVzWwurOHxZT0Z0KGeby9eiuqz8+D6Qfz9j8OtAaxuXRjBIGplOYJiHk9w/K0RvebQoX1tH4U1iycuOjFMXSfpkuvRG+op+9sDhIuKCOwpwoyAGQFEMMNQ9cJjpMy5kYx7n/5FrXGiqd9uQmaYJjZZ+sHaf7IQBQOnYrV4FgyB3TVxXN3vELX1saw9mgKCiRq00S+rjq7JPqp8NjTZza2B2Xx4+GlUU+BvSSazyiwWHjD5xxdHYVAtReNUDMMKr0giRHSDhy8azJNXDGfPkTqagyq9cxOIj7GjGSavLtjLGYNy6Jwei4F18zqnxbKpsIZV+yo4d0RH1uyrwOO0cVpfq9/mJ+uLmHnXMu68sAA5NsSr33egY5eJDO0U84PG9eiatfT8WgjCr357jVCoLWlRbet51TqcgBkJ49+0CkEyEN0OTAwSLptFypzb0ZsaaPjmI2rffY2KJ58hfKyY9Dv/jqNjlx+ErU6ExYxk/b8de5C3ho5O/jetdoKvxUdcZhhEkyafi8awwvBO5aw9lMnGI2m8PnMNX+7Ko3daPeV+J0cqkpl32SIuYSwvNZ3GDbVL6GETuSlB5LEaqzuvTdEJ7X4F8VgHRLE3hq5jmAKHq3w88sk2RAE6ZHhJ9Tr5dkcpW4tq2bi/krQ4J6cNyGqLtWJaxv89M/ox9cHvmDY4h4tO6UpOkpvth+tYf7CSp788QNcuTYzrWIavxsnbB4fzyd19oulGAq3qRXA4EZyu6J/HP//5GxtdqsSTFDQBMAWU9Ky2iERI1fFGyVZa88LCxQfxLVuK6BbQ/SHMMDQv+Y7YsZOIO2sW7iFjUCvLaZw/n6aFX9O08BvcgwfR+bM1x1Oyf+Jht5uQqbqBLB3PWToZWRNFUA0IBWrJ8Ggg6qwuSWHDkRSWFWQxMruanX/5CNxBTFXkL8v7sezi5SRIJh67hhQK82z6TM4KbSelpZ7LPAargiLr/IblkAw38e2bj3D9hZPIy87EJoucN6ID543owIaDVWwpquVYbQthTee03hncO6Nf23JpzcHaMBimyYCOSax69CzufncTFzy5BAMrcpGd6KTOb3Bhr2qkhBae+6w7YwaNJydRQTPMKDGdgGnoCLKMo3MPgnuPIDtFTP0XlkxRwgzpiE4ZI6IhKIKV6/VzMA0Em0nMwJFtmqwlrBHjiAqZYYIEakUJRkRASfSQO/c9at58hoavl3No5gU4e96IICtojQ2IDgNEBTQB78Tplo8suvz/FNpByKyp+ENWaz3pZLMeTMtvU1StoqhHSYxV0YIKQzNreXHyZr7cn8Nb27uQ6/UzLLuGMbk1PDJ+N50TfDw5fR23zh9GT28DwZ5u/hi+hvmHHiZoCjyQaDAjLOCLOmkLio8y6KyryJl8Myk2lXG9Mrl4XBeGdU1lWLTE7d9m9C8Jj635aZ3TYvn4jtMAaA5EMEyTOLedv35RSFLlN0Qa7cwrHc782V2sAP2Jg0S1UMJ5V1D/+XwQZauH048Z1KKIIEpEKlRSr59N0iV/pPDcMei+FiTXT/vWBFlG9+s4u3fCPWS05eWPCkN1c6h1aOtyNA10E9FmwzP6dGJPPZP6T/5B/SfvENi5ETMSwtRBsEnozSq5z71C4oXXWC/LL5TLtUtYCaChJUT4B/REP6/LjGiJ2qp91XTzHgE7GIZAsivIjH6FvDB9La9M2cCkzuWUNbn5eG8eVS1O5iwYxqQ3z6B3ag2Xj64gZe9BnIrJm+mn4o4Y5MpwZyIYCAiGjiLL+PYt5ZJOzVx6ancKyxqYdN9CZj2+mCM1PsBaTk6MZf7YKtAqaK3HxLpsxLntVDQEWLLpKH0zgry7IYsxA0eREiu3VrO1wcr5MvCecQ7Jsy9FLYtgRqyUmdbwTasn3QgYaLUqKVddQtZDr+LsOYC8Vz9BVBzoTZp1vCxHfxf9rSxjBDVM1STj7qcQbPY2P5w/pOKJarLWXbNaXYmpgWB3YoQCACScfwWdP1tBj7WH6b72MLkv/BMzoiN7JTxjzgBD52SoYH9zTWZEc+oPlDURCGs/zCP/GbTab0u27ePP3cpBtaqrdUPECNgB8CgqozqWMapLCWgygaCNprCNdK+Pg8FUZj7ejS+2PcArnSbzRM4lnNKwg4xAHee6RVZ5RL5tNrCJgK7x3CP3cNptb9ElK5EZozqz8UAVY+74igcvHcpl4/PRdOMXC09aBc3KUDZ55LPtrDtQSWl1gO3l8Swq681rt3eymmX9yFhC1IDPefId7B26Uvv2K0TKSq0dHYAAklvA1ac/KXNuIv7cSwFL68SOm0yXr1dQeteNtGzehKlyXGVE33RbdiqZ9z9O7IRpbTn8YBn+8TGWi6h1U2tGQlaCrM2O6HABppXKLcnIKRaNvSDLCPbog9L1k67HbDebLBTRsMsSSrTWsdUe+FcI0Xwymyyy9WgQf+1m+uW0EAkpiIIV/mlNu9EMESNki6bemdhlnXTFT53u5uM3JZ7a8AwLcoYxunEn3f1HeTD3El4++AJh3eTuBJOtYYnqiIFNlik7Usjyfz5Kx9sf5pVvdjK0VyYf/XkiN8xdy7HaFu49rz+abiBGMy9+DK0FH0eqfVz16hrGd0/jtun9uPv9zdzyeU9uu2wY2fHyCbbYv02+7b+p199F8uXXE9y3k0j5MUw1gujy4OjYFUf33tZBrWlGshWkdvUdSv6CDfhWLMK3bjmRkiIwDZTULJy9BuI9bTJSfNLxpMKozecPqf9GGyXY7NZu3m6P1ggIbf+iW5kYuq8JNBPBZbOO/5c5/BR+cyFrPWV6vAubIp4UcVvrW/7gxxu4Y+g2JI+G1CKAYFopKJYX4t9hiOAK8/mOvgir1uKIk1gZ25MnKzbgNMo46kzh+dyzubf4M9w2eDRe5/pKUE0ZRVGo3rSQgg1jGTP+fPxN1RRX+3jx6lE8+fUuHv1iB385px9gPVuLqqC1ltJK67HJIsVVzcx4cimvXT2KbYfreOzz7ewva4RYF7NP6YymGxgmaPycwWCCbiDExOIeMhr3v07TBHTteCDaNEGwcv4FUcIz7nQ8407/8ZF/pKpIN0zc0eyYttsajZuJdscJRvwJ6cyiiBmJYGqAIsOvLYkT24EFWdNNqg7VMuvpZeRnetF1s03oDdPK449xKsS5bATCGu+tPsy2g/uZmuSmYX0WTjmCU9aJsRnIEjhl/Qdt8wRBQMCARoF3t6Ux2OHhCe8UUv3VVOGkRTYZV7WBab0expXWwMVVq8lITidTcXGoZD8YAirw/tznGB4Kk5wxkD4dkrn5rfVMHpDNxsIaLnhiCX+9YBDds+KiRvsPrH/8IZULnl3OTVN6sbe0kQ4pHu44ux/n3beAqcPy6J4Vf5J3S/jZ3Zko8KMP9bjwGD98CVsDrVH7DqLvaatjNqLjD6mtZ44OZr3MgsN5fIw2LWX90FQjmDqIig3xhFDTL0G2xv/tcvzFqCAMzU9m7l2nU1jVDCa4HTLBsEZYM2gKRKj3hWkKRtB1ExOTBLfMxEF9mVs0AEUyMU0DXVdxyCCJJrquoRkGYrTRaiiiIwoGhiFQ5RcpHfYHIoKMjMHKHmchqiqqKOOU3LyddjXftUznsOogrJnEmM8hNx9DM0wcSguaLjFvwzHmbS8n3m3n/rfWk54dT0VxLR+tOkTf/BR65iQQ77YRjGho0WtesLWE+lo/tU0hissauXpyT16bvweagmw9VMPfPt2Gx2lDwCqktclWM1O3Q44mPwptBbayJLZVdNsVsc2WdShyG9OiTZaiNaTHXUOSKGBTJKuaSxJRJBETAUX6IeWVAG2rSk1z6N8XBkGwbDKHRfp3opC10hqYagQ0EGTFCi/9MgRoj+UyOq8kj4M/TOz2Ww8PWO9Va8KCZa8ZbbFKE4GQYfnbRExkQ0cQwKeL+HwBQhGdONcs7LofzbDe+BYxDknQiWg6TYEILrtMgz+MboKm6wTDOhHdIBTRaWwJU90cwi6LDJmZgk0WCUQ0MOFwtY+bzumLzSYjAQ0tEZoClsbQDYOwau1YQ6qOYRgEI1Z76GD0b0m0xhKj1efBiI4ii4RVvS3ZIKTqUc604zHIE+OqbU5jQBZFtGhlkhwlh9ENk407Srl11kCOHwlmOGz952eKg81IBEO3MmmFn9dkZnTVCUI7Gv5Wwt/P7Tx+nAdVOOE/J35tHSu0HfPDaJXIiSv+D6dvHRgDpMfEnvC552eu7f9etLpMVE1vYyYKRxulqZphUWFhfWZi5fSFVB0ByzWjGyby5UPpkhkHHLeHjXAQDJCcliY7sWahFUY4ZGkyh+O4b+wnF0EBTFOFdkxabE1pbi/87EX/xJdmNCzUKsAnGvL/+tufGv9ETfEfQzj+svzEV9HvhX/7rFUo5BN2hx7nf87H32Z1hUPHP/w3kbD+Nlp8lt0mKSeX6hNdr2VRFGKik2kXYWsv/KwV+RNfCv+iHn/UFj0p8/S3s2H/U/y0rJv85FfRL0xoW3JboTc30ua2aPODRUNguo4giBjBgOVX+5X5h7IoCP+dthS/4zfFCdbDj33zs6vYj/1thEMIkklw306MUBCxdZeJ5aAFaF75HZgS9pxO0Y3CL4eUoB2TFn/H/w4IglX6lnT5jTi6J+PfuI/iyybRvGwBkdIjqNUVBHZupvSuq2n88lMERSf+vMutH5+k5Px3ugX8jv97IVqF0Y7O3en86XKOXHUeDZ+vpHH+SpQkEGQJrVFHawR7tkL2Y/fjPe2sk6pSasXvQvY72nLUHF160uXrNdS+N5fA1nVESgoxIhGc/dKIHTuF2FMm4uw18N/TUn4BvwvZ77AQLQCWvAmkXvfn45//i0D9GvI7TFO0hhaF322y32EhSk1gnpgWHs3kNTXtB5kcvwRN0zAhBCDrhlkXiUTg/4Z9+e/4Pw9BOIHhutWvKPxqMuJgMGhqmloEIGqmtr++oUEDxPZor/I7/jfjVxZpHIdYWVUt6Kq+EkBMio3d19zs26eqmgkY7RQA+B3/P4BV/CwYoXBEKCsvK8jOTl9rmqYgjh8/XlPDodcqq6sF2oqYfsfv+I+hHyspFdRQ5P5Bgwapn376qSjed999oih2fnP/vv07/S0tsiAI2u/a7Hf8Gli5aiaCIERqauuUwsJDH0+dOunDTz75RDr//PN1wTRNURAEY96877rFJcSuHjSgf5LT6dBM05R/t9F+xy8hKlwmoNXU1Svbtm9flhQfd+bAgQNDWCk/Ftdmq8TNm/ftgLgE71f9+vbJ9sS4NUA0o76O3/E7/hWCIBiAoWm6fKy0lIKCQx84bNLs8ePHh0zTFKLCd9xt0Spon8yblxMf43mja5f8CZkZ6UT9aL/bar/jRAhEa6Mam5rZt/9AbUNd/T1Tp056DeBEAWs9uA2tggYwf+H3c+K8sTcmJMT3TE5OtnpNtiNEQUBoh+ahbfi/wcz8D6ZnnEDD+T+BaZoY/4N2gieMRCgUpra2juZmX6HP7/ssFPC/OH369PL77rtPvP/++80TBQx+ZNonHnjffffZ+gwYMsquSAMEgQzTbE/6T+HXpimdNEwTU0CUBdF0/R9TyQYtIOiCYPwqUTN+FaWUAJi6aRqBX3dxJzu8iCAIYUyqVUPdUxwIbL/t/PODAMuXL5fHjx//o6Xs/x+1UYuoA4jLPQAAAABJRU5ErkJggg==' +c26 = b'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' +c27 = b'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' +c28 = b'iVBORw0KGgoAAAANSUhEUgAAAJkAAADICAYAAAD7jkPoAAAfXUlEQVR4nO2de3BURdr/v31uMyEkIREhgGCIAYKA8BJui7BLdo2XFGi4mPKCitx+hdaLBWztUsoS1C0VVyhlERd80XWBHy4EkIhcBAFlXYSVUvhJAiQ/QEQDkgRzn5lzed4/Mn2YgVwmwIFJpj9VpyqZ6XOmu+d7up9+nqfPMASwbt06OTs72+T/b9jwcf+oaPdwJrP/UhWlMxHFEBHj7zPGCAQGwAKoBvVAFmCBINX3ZnOQWDUsotBPYLBAdRW49k+/LjBGRGCMyPIywMvAmHWzK1U/0YwxiYFR8PddV39YZBDYeV33HfPongPZY8d+y8tcriEAYJe/mZOTowz51d1PRLdpMzU2NmZQp8RELSamLTRVA2O4AgLAwOp9DwAsi0DN0UYDMMYCahsadZ8dpl9jcxtzQ2ni+yJANwxUVVXj/M/n9fKKim+qqqrfq6ksfz87O9t3udAYcElguZs/ufuWuNglKT3uGNipYwfIsgwAFriWbi7XrlTB9YYBkCyLcO78zzhRWHSk/OIv/52VNfqLQKEx/s/mLVund+rYcVm/vn1kt9tlAJCIKDzmGUFYw+pmfcvr9SqH/99R69z58zMeGp25gmuLAcDWrTsmdLu92/rUXj0sWZaJiGT/yTe18oKWQ521xkzTNNmxE0XSqdOnp4zJvP+9devWyWznzp1xkNTvfjNyeBdVVS0ikoW4BFeDX2iWYRj46uDXvvKLVX1Gj844JVXV1qZ37px4m6qqJAQmuBYYYyAiSVEUq3dqqtuSzP8DgCSJyT1j28YQhGEtuH6w2Ni25HZpIwFAAaCANW/laFkWLCvYNcAYgyRJwo6LcPzfP1NkmSmyfEtOTo6kNOcClmXZYpKk+heepmly14cggmGM1TnrAShgzGzqBCBYPPn5+fjPf/6DkydPQtd1xMXFYeTIkRg6dChkWYZlWQ2KUBAZEBG4D14hi6qaOoEL7MCBA8jJycGOHTvqLTd06FD88Y9/xNixY4XQIhTutSciOwrY5HRpWRZkWcamTZvw6KOPwuv1YvDgwXjsscfQv39/SJKEwsJC/POf/8SuXbswbtw4vP/++5g0aZKYOgV1fJT3ybM/nP2RiMiwLIsCMU2TLMuioqIiiompW4EuWLCALi/HWbx4MTHGKD4+noqLi8myLDJNs96ygtaJXxmmaZq0a8/nx3Jycurms8tXihxu6C9btgzV1dUYP348cnJyQEQwDAOmacI0TfvvWbNmISMjAxcvXsTq1avBGGvw2oLIwS+yK11kRARFUeDz+fDhhx/CsixMmzatbq61LCiKAlmWIcsyFEWx3RojRowAYwzHjx+/4Y0RhCcN2mTc38UYw7Rp01BcXIxhw4YBQL12FndtXLhwAQBw5513OlFfQQukScNfVVUsWLCg0TJ8WjUMAzt27AARITU1FYAIskc4DAgxZZTbXXRZ8iG3zSRJgizLeP3113HixAl06NABaWlpICLhxohYGCRAX7BgAYXk8b98euR2GbfHampqsGjRIsyfPx8AsHDhQnTo0EG4MCKYukxmVssYC01kgXDhyLKMH3/8EWvWrMG7776LoqIiREdH480338SkSZNsEbZ0+A11+SjOkWVZmAQN4d8foLBmBMe5wCorK7Fo0SL89a9/RVlZGQAgKysLOTk5GDBgQKvx9gfeUI3B3TStoc1OoJim5Q2lIO/wvXv34plnnkFBQQEkScL8+fPx6KOP2oZ+a5ki+UhsGAa2bduGQ4cOobq6GpZlobq6Gqqqom/fvnjooYeQmJgIoPW0/bqz4aOPHz95+nsiIrMhT75hGEREtHLlSpJlmQDQgw8+SF9//bVdxjRNO0LQ0HVaAoH1X7NmDfXt25fn2tV7JCQk0OjRo+nIkSNEdKmvIhV/35mmadGu3Xu/BgBs3LxlYmMi4522Zs0aAkCMMVqyZIn9vq7r9YaOWqLQLMsiwzDINE2aNm2aLSRVVUnTtHoPXiY2Npby8vKIiCI6lMZFphsG7dy9p2mR8ZHp2LFj1LZtWwJAy5cvJ6KGxeXxeKiystLxxjgBb8+zzz5LAMjlcpGiKCRJUoOHLMu22FRVpYMHD0Z0zLY+kTVqqVLdxgC89NJLqKqqwqOPPorp06fD5/NBlmXb0CUi+xg3bhx69eqFr776CkCdndISME0TkiRh3759ePvtt6FpGgzDaDL2Sn5focvlgq7r+NOf/iRWm5chAYBpXCkEbvieO3cOeXl5iIqKwvz584NcE1xY/G8AKC0txU8//YRTp04FvR7u8Hq+9957tkiaU3fDMMAYw759+3D27FlIkiSSA/w0OJLxDj569Ciqq6vRpUsXJCUl2d59f3qtffD8fiKCLMuIjY0F0HLCSryeZWVlQTdPqPB219TU4OTJk/ZrghBil6WlpSAiFBUVITk5GfHx8XbnKYqCqKgoAHVfktfrxbfffgsA8HpD8oyEHbGxsfaNc7UIcQXTZBZGv379cNddd6GyshI+nw+lpaVB5Twejz0tKIqClJQUEBHi4uIcrPb1hwtjyJAhWL16dbPP57lzUVFRSElJASCcs5wGRcY7qHfv3jh8+DC8Xq89JQZuidN13S7Pp9JAL3lLcU7yeo4bNw7PP/88amtr7ek/1PN9Ph8efPBBdOnSRThmA2jyVuOd7HK5oKoqFEWBpmlwu91wu92IiYlBTEwMoqOjERUVBU3TWlznkj8+6fV60aVLF7zwwgswTROKElpolwvslltuwSuvvALTNK/KrmutNNmLgXcz+VN3fvjhB2zevBlnz57FLbfcgoyMDDtmGZjsGO6YpmkvWgJH37lz5+Kbb77BunXr7KzfhmCMQdd1qKqKjRs3Ijk5Oeh9HlxvaTfe9SSkW5UxZg//27Ztw8SJE+3AOFA3Vb766qv4wx/+0GKC44GumHPnzuHkyZMoKytDVFQUunXrhrVr1yIxMRHLli1r0B3Bb6SOHTti48aNGD58OE6dOoWamhqoqooOHTqgXbt2AC7NCC3h5rvubNy8ZWJh0UmiRmKXPJ5XW1tLSUlJBIDcbjdpmkYul8sOrZw6dYqIwj+swuu3bds2yszMpHbt2gXFIzVNo0GDBtHSpUspKSmJGGMky/IV3n5FUQgAjRs3jqZPn05JSUl2ZERRFEpMTKQHHniA1q1bZ392Swy3NYfLPP6HAAC5m/KeCFVkv/zyC3Xo0CGo02VZJsYYaZpGhYWFYR9S4bHY3//+90HCkmWZVFUlRVHIv73ejtU2FlaSJOmKoLkkSUHXAEDZ2dlUXV1th+paK1xkhmHSrs/2/BuoM/xr/FNBg+M4t7Xi4uLw8MMPB9kYkiSBiDBixAikpKQ0a0V2o+FT/uLFi/HGG29A0zSoqgpZlkFEME3Tnu4VRYGqqiFNb7IsQ9M0ewcXANvOU1UVLpcL69atw1NPPWX3VyuHGGOwQF4AkBTL0htrNBdUcXEx9u/fjyFDhsDlcsEwDLsMYwxDhw7FwYMHUVxcbH9p4QS3wY4fP44XXngBiqLY+0Yvryv5V5uhxl3JH78MzKAl/+rSNE3oug6Xy4Xc3Fxs2rQJkiS1mJjutcAfVy1ZjdyqfARbuHAh+vTpg+HDh+Opp54KEhhfoS1cuBBDhw5F37598eqrr4bdxl5ely1btsDj8dzwEYX8yQbLly8HEFkLgAaXgTwr4V//+hfmzp2LixcvQlGUS18OkxD4XHXybwYuKyvD888/j9zc3LC6Y/mX+uWXX96UKZ2PmEeOHEFVVVWkTJsAQgiQf/HFF5BlGW63OyiXXTINkGmCMcmO9VmWBZfLBUVRsGzZMgDhc8dyW+nMmTNX5Sjl/rTL/24ulZWVKC8vBxA5Mc4meyo5Odkejeq2wKkwDANG7B1QbrkdpmnY3nEeWjIMA/379wcQPh3Jb5CYmJirCoDzvaeX/91ceMQkkpAgy/VOafxhdg899BBGjRoFj8cDXdfh83nRIyUFK/7+P4iOcmHhq6+gffv28Pl8MAwDtbW1uPPOOzF//vyw2tzLRTZs2DDbPgoFLsiEhAQMGDAARIQ+ffqgR48eAEIPgvPrdO3aFQkJCWHVN07TYCt5p0RFRWHr1q1YvHgxxowZgyeeeAKff/EFblN+QeXZExg89Fc4cOAApkyZglGjRmHmzJnYvXs34uPj7euEA/wLnTRpElRVDQqBNQZfhb722muYO3cuiAgZGRl45513mrW3lK+4x44dC7mBG7vVsnHzloeO5h/z+9GudBI25Djs1+8uAkBpaWmNOeXCCu6Iffnll0PK4Xe73XYbLcui559/ngBQeno6WZZF99xzjx39aMxZy6Mi3bp1o9LS0ha/o6sx/O0yDMOkHbs+2ws0I0DO7zzGGC5cuIDevVORknIHoqKiUF5ejrZt29rGf7juquYjyLx583Du3Dm8/fbbAFCv09WyLHg8HvTq1QsbN24EAOzduxcA8NNPP8EwDOTm5iIzMxP//ve/g1be5J+OeczX6/WiU6dO2LRpExISElpMfPdasChg131TI1lrIzDstXLlSkpOTm5wT2V2djadO3eOiIgKCgrI5XKRLMukKIq957SiooImT57c4DVkWabs7Gw6ffo0EYV/XPda4SOZT9dp+85de4EQszDqI9CmaElpLIHulsmTJyM7Oxu7du3C/v378f3330OWZaSmpuL+++/H4MGD7fM+/PBDeL1etGnTBjU1NVi1ahXS0tIQHR2NlStXYurUqVi/fj0OHz6MyspKtG/fHoMHD8bYsWMxYMAAAIiIEaxeIm0kC6Sp3d58o291dTXdfvvtxBgjVVWJMUbt27enkpISMk2TdF1v9Dp8d30kUN9IFoG31SUCA+OXPwOXxyElScLatWvx/fff2ytNVVVRUlKCDz74wB6ZLMsKOi/w/8Z+XCMSiNyW+2GM2c9ZC3wGLn/d5/Nh8eLFQc5moM61sWLFCui6bi90eBkeEeD/RzqiBxqAB/5ff/115OfnwzAMeL1eGIZhO56PHz+OFStW2KtIQf1cteHf2uEj0JAhQ/Duu++ic+fOUFXVdlFUVFSguLgYbdq0AdCyFj83GiGyBuAiu/fee0MqH45+wXBBiKwJ+B7Ty0VEARtDxCjWOEJkTRDpK8Prgeg9geNIEoVJwpeg1SLpRNWGaQCN7FYSCK4FiSwxkgmcRdhkAscRIhM4jhCZwHGEyASOI0QmcBwhMoHjCJEJHEeITOA4QmQCxyD/j6oKkQkcoS41itUAfpGJGLngeuP/QWgDACQZgGWGz8PqBK0H/tPjYroUOI4QmcBxhMgEjiNEJnAcITKB4wiRCRxHiEzgOEJkAscRIhM4gmEagN/HL0QmcBwhMoHjCJEJHEeITOA4QmQCxxEiEziOEJnAMajuBzOEyASOQIxJAFANCJEJbgBCZAJHCPz9eSEygSMQWSB/XEmITOA4QmQCxxEiEzgIE1viBE7CQESXdpALBE7AJOYFhMgEDkFEIIvcgBCZwCEkSQIDiwKEyAQO4f9xWRG7FNwYhMgEjiNEJnAcITKBEzAiCyBqAwiRCZxFBoTIBA4iVpeCG4YQmcBxhMgEjiNEJnAcITKB4wiRCRxHiEzgOEJkAscRIhM4jhCZwHGEyASOI0QmcBwhMoHjCJEJHEeITOA4EsB/L1ogcAbJBCDJYkATOIdQl8BxhMgEjiNEJnAcITKB4wiRCRxHiEzgOEJkAscRIhM4jhCZwHGEyASOI0QmcBwhMoHjCJEJHEeITOA4QmQCx5EsIolBJC0KnEPSVCValmXA/3vRAsH1RkyXAscRIhM4jhCZwHGEyASOo9zsCrQEiAiWZYGobm0ky7LYRtgMhMgawbIs/mtn8K/AgzBNs97XBcEIkdUDF9ecOXOwc+dOREdHIzk5GXFxcfB6vThz5gyKi4sxZcoUzJkzB4ZhQFFEVzaE6Jl64CLr2LEjjh49CgA4ePDgFeVGjBgBoO63HQUNE/G9w+0tfhARJEkCESErKwvJyclQVRUulwuapqFNmzZgjGHGjBkYOnQoTNO0ywcegktErMgsy4JpmmCMQZIk+2CMgYig6zpSU1PxyiuvQNd1u7zH44GmaZg9e7YtKH6dwMM0TZimKQSHCJ0uAw32srIylJSUwOPxQFEUJCQkIDExEbIswzAM/OY3v0FcXBwqKiqgaRq8Xi+ysrKQkpICn88HTdMAAD6fD6WlpVAUBe3btw9aEPDpt6UROCpfS/1bXsuvES6wo0eP4qmnnkLv3r3Rp08fDBgwAP369cOdd96JyZMno7CwEIqiIDExEVOnTg0akZ555hlYlgVN03D48GFMmTIFffv2RWpqKlJTU3HXXXdh2rRp+PTTT22BWZZ1E1sdOoHtDBzlr4mNm7c8dDT/GBGRZVkWtWYMwyAioqVLl1JUVBShLimAGGMkSRJJkmS/1qFDB/ryyy+JiOjAgQMkyzIBoN69e5PX6yUiojfffJM0TbPPqe8YPHgwnThxgoiITNO8OQ0PAcuy7P6xLIu8Xi9NmzaN7r33XrrnnnvoyJEjZBgGmaZpHw1dh4gMj9dL23fs2hJRIuMd+NZbbxEAkiSJNE0jWZZJlmVbZLIsk8vlIgAUHx9P+fn55PV6qUuXLgSApk+fTkREixYtIgAkyzJpmkaKotjXUhSFNE2zBZiSkkIlJSVkmiaFYx83VKdZs2YRAOrWrVu9oqrvvPpEFhHTpWVZkGUZ3377LWbPng1FUSBJEgzDuGI1SH6jX9M0XLx4ERMmTIDP50NiYiIA4Le//S1Onz6NOXPmQFEUMMZgGIa9MiX/atUwDBiGAZfLhaKiIjz99NP2KjScICIwxlBeXo7Zs2ejX79+GDp0KDZs2IB58+bB7Xbjueeew3fffYeJEyciLS0N48ePx5EjR+xFUpNEwkjGR7Hx48cTANI0zR65GjtUVSUA9Nhjj1GvXr0IAK1atYrGjh1LAEhV1ZCuw0e47777jojCZ9q0LItM0ySv10sjR468YqqfPXs2JSUlUb9+/ezRnR/x8fFUUFBgXyPwmhRp0yVv04ULF6hdu3bEGAuaHkMRCALsNt7ZoZ7Pp2UA9OKLLxIRka7rN7NLbPjNt3nzZgJAbrebFEUhVVXtdnM7lTFmmwXcnp0xYwYRBbcnIqdLvqo7deoUfvnll2ZPWURkT4sA4PV6mx2v5J936NAhAOHzjF5er9LSUgCwpz8+9auqCqAuIUCSJNvvR0SQZRlVVVUhfY4CmGHTaCcxTfOqzw10P8iyfNV2la7rAMJHZPyGy8jIQFxcHMrLy4Pe433G22tZFhhj8Hg8AIBHHnkEQP3tUWTFHsIkmK079sbblpSUhLZt29oddbVcjcB4FKBnz54AEDY+My6y2267DZ9++imysrJw2223ISoq6oqyjDFER0fD7XYjKSkJb775JjIzM+1FVaOf41QDwgUe4klMTMSoUaPsof5GwqeYCRMm2HUKF7jQhgwZgk2bNqGgoAB/+9vf7BguL2NZFl588UUUFBTg6NGjeO6554LKNPoZTjcinHjxxRchy3JIeWChCqGpcpqmQdd1ZGRk4O677w7pzr/RMMZgWRZ8Ph/atm2LPXv2XCEgIsI//vEPdO3aFW3atIFhGCH3UUSITJZlWJaFgQMH4t1334VpmtB1HYqiQFEUyLJsHzwvLBQbjgfNA68hSZJ9HUVR4PF40LlzZyxfvtzpZl4TjDFomgafz4fPPvssKBRmWRYURcGRI0fslKfmjMYRITLgkiH79NNPY9u2bejTpw98Ph98Ph90XbcPn88Hy7Jw6623Nno9IkK7du3Qpk2boGsYhmFfx+fzYfjw4fjss8/QvXv3kKeXmwU3JWJjY+0RV5ZlqKoKwzCQkJCAO+64o9ntUOhql0otED5V3n///UhPT8cnn3yC3bt3o7CwEIZhoEOHDhg0aBAGDx6MuXPnoqSkxB4FA+GGfHx8PF577TX8/PPP+Pzzz/HDDz+gqqoKsbGx6NmzJ8aMGYOxY8fao0I4C4xPmbIsY/ny5Zg0aRKKiors9xMTE7FixQrceuutzW/Lho8+nnD8RBERkdkanbH1wZ2QDTFhwgQCQIqiNOhgVRSFAFDPnj2ppKSk0euFi4e/MbjnnvdNRUUF5eXl0TvvvEO5ubl0/vx5IqKgIHljsUvDMGn7zjpnrCJJLCqc7zAn4L4u7nTkTkhJkjBx4kTk5uZC0zQYhtHgNSzLgqqqOHHiBAYOHIj9+/cjMTHRtlX46HddUmVuAHx05sTExGDMmDFXlLuaRYtCFJnPwAjcgcSN91WrVmHt2rVwuVy247QxTNOEy+XCmTNnMHPmTOTm5tor13BbQTYEBQTIjx07BsYYFEWBy+UKugkZY3YKuq7rqK2tRVJSEmJiYuwyDRGRmbGB8BHM6/Xi5Zdftv1qocJXqRs2bMChQ4eQlpbWorbK8Rvsz3/+M954441mnTty5Ejs3bu3XoFRgKkf8SLjxu6hQ4dQWFhYr6HfFHw63Lp1K9LS0sIunScUampqwBhDcnIyfve730GWZdTW1gaZDLxdRUVFOHDgAE6ePAnDMKBp2hWjmWmZgL8bI15kvONOnz5tT6GN2WKNUVxcfD2rdkNxu92QZRnPPvssZs2a1WjZL774AqNGjULHjh3tILqYLkPA5XJd03Y2xhhiYmKuc61uHJWVlbaPjydcBm5YZoxB13W43W58+OGHICIMGjTINi8aMw8iXmR8qktLS4Omafb2tuaIjYuTb/YNp9hkU/D233PPPQCAzMxMO3M4cFVsGAbcbjfy8/OxevVqAMDTTz8d2mdc5zq3OHgkICkpCY8//jhM07SngFBQFAW6rqN3797IyMgIe6/+5fC6ZmdnY8WKFejbt2/Q6+RPR1cUBWVlZXjyySdRWVmJqVOnYtiwYSEtclpObzgI98gvWrQIAwYMsPdgNvT0Hm67KYpi771csWIF3G73NacS3Sz4vgS+6KGATcuqquLYsWO47777cOjQIfz617/GW2+9FbLnX4gMwWGinTt3Yvz48XY8knd0YACcB9h9Ph969OiBbdu2YcSIEWGZYREqkiQFbYzhbfZ4PFiyZAmGDRuGr7/+GpmZmcjLy7Mf1xDSDbVx85aJhUUniSIorNQQge3fvn07Pfzww9SpU6crNljExMTQ3XffTUuWLKGKigoiajpU1RIIbH9tbS29//771KdPHzvHf/78+XaIrDn7LhUAkGQxoAEIMvjvu+8+3HfffSgvL0dhYSGKi4thmibat2+P7t27o0uXLvZ5LXkE41CA53/16tVYunQpjh07BgDIysrCvHnzbB8gNTcLA2hZqyGn4X3Bvf5xcXEYNGjQFeXIb7PwKbQlw22rsrIyjBw5Evn5+QCAqVOnYvLkyfjVr34F4Koe+scA4cJoEN6Z5A+kB8KfEdEaHnzHR25d1/H4448jPz8f/fv3x9///ncMGDAAwKVgfzMERowxEFALCJE1SUOP8mwt8NjlmjVrsH37dnTu3Bkff/wxunbtCl3X6x2pKSBzpeFZkAFEOhBhSYuCK+Ei+eijjyBJEmbMmIGuXbsGPRaroXOaNLP8BSRJYm39v60kxBZhkD/d2ufzoaCgAJZlIT09vcEdXXxz7/r169G/f3+sXLnSfr0xJImx0N3bglaJruuorKwEgKA8ssvhjuYPPvgAR44cQUlJCYCm96JKkZq0KLi0JzU6OhqjRo2CJEnYvHmzPYrxQDkPnKuqiq+++gp79uxBVFQUsrOzATS9Obxlr70F143JkyfbobVVq1bZW/r4oaoq9u3bh0ceeQQ1NTWYNWsWunfvbj+YuTHE6jLC4Uma6enpmDlzJpYsWYInn3wS77zzDjIzM3H77bejtLQUu3fvxscffwygLvvipZdeCklggBCZAJcSBN566y2MHj0af/nLX7Bz507s378/qFz//v0xe/ZsPPnkk7Yd1ugKk0gC6nYrCZtMYAstIyMDGRkZOHXqFPLz83HhwgV7HylPA2rcP1aHYRggwAMAimlRqc/nAyB+IzrS4RkmkiShe/fu6N69+xVlQg0t1dbWkmHo/x8AFIOMgrKLFw0AiohhCriAAp+BC6DRHzKrB+nc+Z+ZqZufA4DUPjY2v6KiMl/XDQJgiQCAAMAVD47hImsM/zRqebw+9uNPP57o2rXTl0TEpPT0dEP3epaf+/lnBnsTk0Bw1ZhnfjjLdI9vwaBBg/T169dLUk5OjiRJKSsL8gsOV1VXK4wxQ4xmguZAsEcx34WSMrWwsOifo0c/sHbdunVydna2yYhIYoxZeXnbU9slxO4bNPC/2kdFuQ0iEjaaoEn84iIARklpmXrom292t49vNyYtLc0Df0YtAwCuuLy8bQPbJcR9NKD/XV1j2kYbACTy+zoEgsthjFkALMMwlTNnz+LEiaL/69bkKenp6R4iYn7xXXJbcKGty8vrFt825n969eiZ0aVzJ/j9aMJWEwTC4A9J/lJegfyCYyUXS8vmjR79wHIACBQYL2zDhQYAW7bumN4uLnZmQkJ8n1tvvRUul8vRWkuMgUkOTs/hYGZeRfPqXAnX/tH1Zfhe5ZXg8XhRUlKKiorKwsqqylxPTdXSrKysn3JycqQFCxZQoMCAepodWDAnJ0e7a+CQES5VHsgYOhM5GVBncCpVngjEIClMojY3bUi2UA0wkzGrWVKzrOYojAEgk8iqaV7lQr28BMaYF4SfdUv/7mRNzTdzsrNrAWDPnj1Kenp6vQ8R+V+PRrOy7szCIQAAAABJRU5ErkJggg==' +c29 = b'iVBORw0KGgoAAAANSUhEUgAAAJkAAADICAYAAAD7jkPoAAAmAUlEQVR4nO2deXRUVdb2n3OnqowQIkiAgAEZIqNi5P1UWiLQREShUaKiRpc2vCJLRBEiKgvEKCrIUhrt9QqIoqKQaGsIEGWSwRa0hWaQQUKQMSFAGJKQVN1hf3+kzqVCKkkFKUhR57dWLUjVrZN7b557zj5773M2gxeLFy+WU1NTTf7zV18t6R4W4byVyexGVVFaEFEUETH+OWOMQGAALIDOwQdkARYIkq8P/YYBjM6BYNXnOxao8gT+5G+/VDBGRGCMyHIxwMXAWD0u6LLguVMRBFbtpvHzh0UGgR3TdffuCr1iU+rf/vZffsyFGgIAduGHkydPVm75f7c9GhEe/vfo6Kib45o316KiIqGpGhhDNQgAA/P5GQBYFoGILuZ6L7hA5nW2/lH5uxvan5FTz4u5rNTx9yJANwyUlpbhWNEx/czZs1tKS8s+OldyZn5qaqr7QqEx4LzAsr5deltso+hZ17dvd1Pctc0gyzIAWOBaurL8eaUKLjUMgGRZhMJjRfh9b962M6dOPzNkyKB13kJj/Idvc5aNjLv22g+6duksO50OA4BERA1jnBE0aFjlqG+5XC5l6/bfrMJjx0YNHjTwQ64tBgDLln13f+s2rTM7dWxvybJMRCR7vnxFT14QPFRaa8w0TZPt/j1P2v/HH0/eMzDlo8WLF8tsxYoVjSCpO+7ofWtLVVUtIpKFuAQXg0dolmEY2Pjzf9xnTpV2HjSo/36ptLw8uUWL5q1UVSUhMMGfgTEGIpIURbESO3VyWpL5vwBIkpjcIToyiiAMa8Glg0VHR5LTofUGAAWAAlb7zLG+LgjRG4Yunr89U2SZKbIcO3nyZEmp60uecbZev8iyLDDGhNhCGM/fnwBAAWNmXQeXlpbWKjYigq7rICIoioJGjRoF4LQFwQQRgQ+ACllU6usg0zQhyzJmz56NN954A7Isw+12Vxs6GWMwTRMulwuapkFRFPTu3RszZsxAmzZt7GMEoQH32hMRLI9WahwuuZi2bt2KgoICAIDT6YSiKNWERkTQNA3FxcWQZRlfffUVYmJiMGfOHBiGAUWpc1QWXMXU+dePjIyEqqpISkpCVlYWFEWp0jPpuo5GjRrhH//4B15++WWYpolu3brhlVdegWVZPDQlCGEUoNJQr4mysjLouo6IiAjExcX5POabb77B66+/bgssOzsbbdq0sScAgtDGI7LqLgpJqgxbDh06FMXFxRg8eDAsywIRQZIk6LoOTdOwcOFCpKWlwTRNJCcnIysrC02aNLFtOoGgxuGSiywlJQUpKSlVPjMMA5qm4bPPPkNaWhqICHfffTcyMzMRFhYmBCaoQp1ZFpZlwTRNe0jVdR2KouDjjz/Go48+CiJCSkoKFi9eDE3ThMAE3jDAD8Of92hApeBUVcXcuXMxYsQISJKENm3aYM6cOQgPDwfA/SP1d+AKrjYYJECfMmWK//lilmVBkiTMmTMHI0aMgMPhgGVZOHz4MG677TY89NBDyM3NtT39lyIbVhC8VGYys3LGmH8iM00TkiRhy5YtGDlyJADA5XIhMjISUVFROHjwIL788kvcddddSE1NxdmzZ68aoRERTNOEYRjVXrXNygUAPOtBJFZHcBwAZFkGEaFDhw546aWXMHDgQGRmZmL37t3Yu3cvtm3bhkmTJiEsLAyZmZkYMmQIXC6XPXQGI9wWZYxBlmUoilLtJUmSLUJBzSimabn8OZAxhoiICLz++uvVPmvSpAm6du2KXr16ITU1FWvWrMF7772HCRMmBKXH33vycvLkSfz888/Yvn07CgoKoOs6YmNjcf311+OWW25Bx44dIcuybU4IfPDVN0sezv/jABGRaVkWeWNZFum6ToZh2O8ZhkGmadr/WpZFpmmSy+UiIqLHHnuMJEmijh07UkVFhd1OsMCv9cCBAzRq1Ci69tprea5dtZfD4aC+fftSbm4uERGZpnklT71B4Plbm6Zp0crVP/wHACRWyzSQMQZFUaq4JGRZhiRJ9r+MMUiSBEmSYFkW+vbtC8uyUFpaioqKioA+IJcaHgbLyclBz5498c9//hPHjh2DoijQNK3KS1VVuN1urFq1CikpKRg/fjwkSYJpmkFrIlxKLLJAqCVATh4XxKlTp7BgwQK0aNECw4YNq9M1we2XYIQPdxs3bsTQoUOh6zocDodt4Psy8vnDxRjDjBkzEBYWhqlTpwpf4QX4NCL4Dd2wYQPGjh2L1NRUHDp0qDJ9o5YZFWMM27dvB2MM4eHh0DQtMGcdIAzDwOjRo+2QGc+RqwnyGP2maUJVVWRkZGDbtm22jSaoRAIA06g6O+K9VefOnREZGQlJkrBixQo7ZnnhjecujnPnzmHRokUgItx00012iKmhO2b5+f/666/YvHkzFEWBYRh+f5/38ESEhQsXAqg96SDU8NmTcfuqbdu2uPPOO2FZFl577TUcOHAADocDjLEq4SZun40dOxb79++HqqoYN24cgOBIWOQPzY4dO2wb82Lb2L59OwCImaYXtd4JIsL06dPRuHFj/PHHH+jbty8WLlyIs2fPVjH+8/Pz8fjjj2POnDkAgIyMDCQlJdk9RLDA/YF/Bv5QCeP/PLVmYViWhQ4dOmD58uV49NFHkZeXh4cffhhxcXHo0aMHYmJicPToUWzatAnl5eUAgIkTJ2LChAlBZfzyB6Fbt24AcFHOVS6u7t27AxAiq8LX3+Y8sjcvn8iHn8zj8CAiouLiYpo6dSp17969mr/I6XTSX//6V1q+fHmV7wQT3PeXlJREAEhVVZIkya+XLMukKApJkkTbt2+32wtFuJ9MNwxasXrNfwA/szAsy0JMTAwmTZqEF198EQcPHkRhYSHOnDkDp9OJdu3a2YtGgtHzTZ5ZoqIoePPNN9G3b18A8Dv+qqoqKioqMHbsWHTp0gW6rttDbzDYpIHGr3gPF5okSVBVFe3atUNCQkIVMZHHvREsQ6S3sBhjUFUVAHDnnXfirbfeQnp6ul/XIkkSKioq0L9/f7zzzjsAYLcFwJ5dB9uDdynx68rJk3J96NAhPPHEE2jbti3i4uLQpUsXTJ06FS5XZfgzWG4kX3vAY6rHjh1DXl4e9u3bh6KiIkyYMAEzZ860na01wQPkTzzxBL7//ntUVFQgLy8PO3bsQF5eHsrLy+3JUSgH0f1aQQ4AZ86cQf/+/bFnzx77s6KiIkyePBlFRUWYPXt2UBj7vEc+d+4c3n//fWRmZmLv3r0oKyuDJEmIjIxEmzZtkJqaigEDBiAnJweKolTze/H1pvHx8ejTpw/uu+8+/PLLLygqKrLXoLZs2RL9+/fHuHHj0KFDh6C4P5eYSlsh61/Zj9Zm+POA8b///W8CQJqmkaIoJMsyaZpGsixTQkKCbeg25GA4P8ddu3ZR165dq0xePEvqq7xkWfbL8L+wHUmSqrQXFRVFn332GRFRlWSDqxFu+BuGSStXrfk3UNmTnfM8pTVaqIZhoHnz5nA6nXC5XPYwQR67plWrVrAsC4ZhVLFHGhK8JyooKEBKSortWPYV0ObZvf4Ocfya+T0hj3kBVPreSktL8cgjj0BRFDzwwAOh0KMRYwwWyAUAkmJZ+oU32T6SyE7YS0hIwNChQ6vcQM7o0aPtTIWGmhHLz/uFF16wBabrur3Mz/vFoxn+wuOXvC3++4jIzqeTJAlPPfUUjh49ak+krnb4dtWSVcMcmzzT77179+LFF1/EyJEjcfjw4Soi4h79zz77DE899RRmzJiB0tLSBic0PuvNz89HVlYWZFmuV2zyz8ID6KdPn8b8+fPtsFyo4NPw57Ov7du3o0+fPiguLrY/8/UU5uTk2P9funQpcnNz7SGkIfiJuLG/YcMGuN1uaJp2WUXGz4Exhg0bNgAInpn4pcDnlfJe7O2330ZxcbGdtnNhGjUXkKqq0DQNYWFh+OGHH7BgwYIGOW0vKCi4aNF777d2sQIhIpSW+txE6arGZ0/Gb+aRI0fstBf+5HNPtmEYtq+Ji4kn8P3xxx+X5+zrSWRk5EV9z3sSIEkSDMO4qGA6Yywk926TIMvVehw+HA4aNAiGYdizIcYYdF2HYRiIiIiAqqrQdd3OiK2oqIAsy0hNTa1svIEMCfyhufHGG+u9uogLLC4uDtHR0WCMITExsd69NLdT/+d//gdAaOWb+VQB34NszJgxGD16tC0m0zTxyiuv4LnnngNjDEuWLEHv3r1hmiZ0XUd4eDgyMjLQvXv3BpXmw3udpKQkdO3a1e/wFxdnVFQU1q1bhzZt2sA0TSxZsgRDhgyxd5b0px2++v6BBx4A0HAewMvC19/mDP5t526PH823IzUvL4+++OILWrlyJRERjR8/ngBQZmYmERH9/PPPtGrVKjp48CARNcwMBO4EzcnJqeJUri2zwuFwEACaPXs2ERHFxsYSAFqzZg3t3LnTztaoqx2n00kAaOzYsVXO5WrEoyHDMEz6buWqH/wS2YWC2bx5s+3JTkxMrHbDGqLAOPxcMzIy7GvQNI1UVbXFoqoqaZpme+yffPJJIiLauHEjybJMAOipp54iIqLJkydXa4e3cWE7AwYMoPLycjIMo0FHRf4sXGRuXafcFSv9ExlRpXD4+sszZ87Q999/T8uXL6cdO3ZUW4fZ0OFCmzdvHsXFxdW4pjI6OpqmTZtGRJU3zluYf/nLX+z2PvjgA2rSpEmN7URGRtKECROCcg3qxeBLZOzrb3MGd2x//Tc3JHYkIqptGeZVA/ebnThxAllZWVi7di0OHDgA0zTRsmVL3Hbbbbj//vvt3SLJszCGr0RSVRU7duyw050OHz6MzMxMrF+/3p6Rx8fH49Zbb8U999yDhIQEABe3XX2w4blGUzcMefUPa9em9O/Xx6+e7EKlGoYRND1XTfhjF7lcLrIsi7777jsCQIqikKZpBIAmTJhARGT3UHX9rqu9B+P46snqPcXh7gqeJxWsePv7eJCcvHbwsSzLTmicMWMGgPPuDEmSMHfuXBw/ftze+K+2drj7J1QJXpVcAry3YeAefZ4QQJ6A+qZNm/DDDz/YSwElSYLD4cDp06fxzjvv2OKpqZ1gfhAvFeIO1ADvtcaNGwdd1+FyueB2u6HrOsrLy2FZFt566y3k5eWJFeN1EFx7Ol0meC92+vRp9OnTB4MHD0ZMTAzCw8PBGIPL5cK5c+dQUFCAkpKSK326DR4hMh/wIbBx48bIyMjw6ztiWKwZIbI6qCslKNSNen8QIquDYNslsiEi+nhBwBEiEwQcya0bZZ7cKGFYCAKCJDFm8b09BYJAIIZLQcARIhMEHCEyQcARIhMEHCEyQcARIhMEHCEyQcARIhMEHCEyQcARIhMEBMYkEKEc4CITUSXBJYYBkCRmAIAk4+IqcAgEdUG8BvmVPhHB1Y8QmSDgCJEJAo4QmSDgCJEJAo4QmSDgCJEJAo4QmSDgCJEJAoJhGoBnDxqxPNoPyKvuEnC+cITYnsA/hMhqgYfbatrvwrIsscmdHwiR+YD3Wnyv/4qKCuzfvx9FRUUwTRONGjVC69at0bRpU3s3n2CsvX65ECK7APJsHswYw48//oj58+djzZo19sbFnCZNmqBHjx4YNmwY0tLSEB4eHgp1LC8K8eh5wQV24sQJPPTQQ7j99tsxb9485Ofn23vI8m07i4uLsXr1aowaNQo9e/bEmjVrIPsoISQQIrPhQ+SpU6fQr18/fPnll3ahWL73K7fB+FDKq+Pt3r0bAwYMQG5urtja0wdCZB64TfXSSy9h69atCAsLs0tee1fk5XjvcK1pGnRdR1paGo4fP97gispeKciTDitEhvNlsIuKivD5559DkiS43W6/v28YBhwOB44fP44FCxbUq375VQoxJgFAGSBEBuB8WcBt27ahpKQEkiTVuyfilXnXr18PoGFULG4oCJF5UVJS8qecrORVmTfUReZtlwqRedGsWTMQ0UUZ7lycrVu3BhBaRVN9QWSBPHElITLAHh579OiB+Ph4ex//+kJEuPfeewGInswbITKcrz4SERGB9PR0vyv7chRFgdvtRlJSEu6++27h/b+AkL4T3i4KWZZhGAZGjhyJQYMGweVy+SU0PhONiYnBvHnz7LpMQGXskxf1Ck1YaC+J49XeuKOVF/NSVRVLlizBsGHDoOt6rT2SJEkwDAMJCQnYvHkzunbtahfv8q6mx2uQhxYMRHQOCNHYJfeL/fbbb1i0aBF+/fVXnDp1CpqmoVWrVujVqxdeffVVFBUVYd26dVAUpZrfiwsnMjISs2bNwubNmzF16lTk5eWhpKQEYWFhSExMxODBg3HvvffaEYNQGkaZxFwAgK+++vbOzVu2ehfEvGqxLMsuBDtp0iS7QKqvl6Zp1LhxY7tYva8i9owxcjgc1Lhx4xrbAUDJycmUn59PRA27RvulwKMhvexcOS3N/f5jIMR6Mm57Pffcc3j33XchyzI0TatiM/FZodvthtvtrtUxyxiD2+2Gy+WCqqp2OIm8MjkAYM2aNUhOTsaaNWuQkJAQEj2aJElgYGFACNlkPA1n2bLlePfdd6FpGgDYFXf5yzAMGIZh21N1wW0v7+q9lmVVacvpdOLAgQMYPnw4dF0P9KU2CDx2bijFLj0F5i0Dr746uUqPU+M36vj8wmNrw+12Q9M0bNy4EZmZmfaEIVQICZGZVqVzdd2Ow/hlyx5IIJhXYLbHGENmZqb9/1AhJERGVmVPs/e3LSCzArKiAJfZd8XThQ4dOgQAIZVBGxIi47v8sbLjYOQGWP0vm/vSvH++GFRVrTyjq9tBy4gIDAgdw5+Lo0WrNiCqf/CaMWYb9cD5SEF94CK94YYbAITCxoMEIlKAEBEZd0PcfvttaNmyJUzLgiSr8Kf6Ip85vvHGG7jxxhtBRPjwww9x8803gzHmd4/GJxLDhg0DEBo2WUjNLr298xkZGSDLgmy4ADJRm9BUVYWu6xgyZAgmTpwIXddBROjWrRsyMjJgmqZf5aN5O7feeiv69+9f7wB8sBMSIgN4j2Th8ccfR9qzk+BqOQBa4+aQGYFJnsW5HgeqJElQVRUulwvt2rXDRx99hCNHjiA/Px8A8MUXX6Bv37647777UFFRAUmSqi3w5f4z3k6TJk0wd+7ckBIXJ2REBgBMYrAswsw3p2LQ0y+gQo2DblowDb3SC2+asDxOVJfLhc6dO2Pp0qWIiYnB+vXrce7cOQDAzp07oSgKsrKyMGHCBBiGAV3XYZqm7ek3TRO6rsPlcqFLly5YsWIFEhMTQ8LbX41Qil0SEVVeokVEJs39YT8Nfvp1at2qJcmqRghvSY6wSErs1IkmTZpEp0+ftr+XmppKAEiSJGrSpAkVFRXZ92vlypU0cODAKjHM6Oho6t27N73//vtUVlZGRFd/3JLI1pBR4XJR7ncrc4AQi10ClRlOlTt/Mzx5x3V48o6XUPrWGBw+chQHyiOQEG2iXZsWkOXKW2OaJgoKCrBs2TIwxqCqKoqLi/HFF19gzJgxcLvd6Nu3L/r27YvCwkIUFBSAMYZmzZqhRYsW9u8NyR7MQ8iJDOCpdJWRABAhMjISnTp2QCevY3iyoaIomDNnDkpLS6Fpmj0kvvfeexgxYgScTicMw4AkSWjevDmaN29ut0GetZmyLIeswIAQs8kuRJYYZFmyF4+YXivEuTF/5swZzJkzB4qi2PaWw+FAfn4+Fi5caBv73E3ivcqcJ0KGgruiNkJaZBw+o5QlyXaa8h5r1qxZKCgosCcDuq6joqICADBlyhSUlpZClmVbVJJXG4JKQnK4rAvyZM6ePXsWOTk56NGjB6655ho7PciyLFRUVKCwsBC5ubm4//77xY4+tSBE5gPeCzkcDqxcuRJRUVE1Hst7NSGwmhEiqwWHwwGHwwEA1TZd4UOj0+m8UqcXNAiR1YG3rVXTZ4LaEYZ/HdQmIiEw/xAiEwQcITJBwJEA0e0LAotkApBk0aEJAodQlyDgCJEJAo4QmSDgCJEJAo4QmSDgCJEJAo4QmSDgCJEJAo4QmSDgCJEJAo4QmSDgCJEJAo4QmSDgCJEJAo4QmSDgSJIsS8yPzeAEgotFkhgiPGsGr+pNTAVXDjFcCgKOEJkg4AiRCQKOEJkg4IhtCuqA74FBPoo78C2ixJLC2hEiq4NQ3iHxUiFE5gO+kYqu60hLS4NlWQgPD0fz5s3BGMOxY8cgyzL27NmDZ599FkOHDhX7k9WCEJkPeHEJRVFw/PhxrFq1yudxERER6Nq1q/0dgW/EWIDzJWm89yDjvdns2bMRGRkJTdPgcDigaRrCw8MhyzJeffVVtG/f3t6YGKjdhgtVQlpkRATDMGzjnRvyvMCXaZro1KkTHnvsMbjdbvt4XoXkvvvus8XEC3p5TwZ4Bd9gxnuz5foWPuOErMj4xsOKooCIcPr0aRw5cgTFxcX2ztf8Bj///PMICwuDYRhQFAWWZWHo0KG47rrroOs6FEWxaywdPXoUx44dw7lz56q1E4x4b7Z8sZOgkBQZ33j46NGjeOutt9CzZ0907NgRiYmJSExMxODBg5GdnQ1FUSBJEtq2bYsBAwbYQpFlGenp6bAsC5qmYe/evXjhhRfQo0cPu42OHTvi/vvvx8qVK+0/VLAIjZdaJCIcPnwY27Ztw7Zt27B//367NgGvc+AXX3+bM/i3nbs9FUuu7rI3lmXZpWemT59OsbGxdpkaX6+//e1vdPz4cSIimj9/vv3+LbfcYrfz4YcfUmRkZK3t3HXXXbRr1y4iatilb7zvD+frr7+2r2PUqFHVvnPh8b7K3oSUyPgN+fvf/27fOE3TSFEUkmXZfqmqSpqm2YJyu920Z88ecjgcBICeeeYZIiKaNWsWASDGWI3tqKpKACg2NpZ27Njh8w/Z0Ni3bx+tW7eOCgsLiYjohhtuIAC0c+dO0nWdVq9eTZs2bbKP99ZNSIvMMAwiIsrOziYA5HA4SJZlkiSpxpfT6SQA9PzzzxMRUatWrQgAffLJJ/Tbb78RY4wURSFFUfxq55577qlyLg0Fy7LIsiwqKyujxx9/3D7f2NhYWrZsGY0fP566d+9OeXl51L179yo9+o4dO4jo/AMc0iLjN6F3797EGCNVVWsVBn/xnuhf//oX9enThwBQeno63XjjjQSgToHxF+8ZFy5cSEQNS2j8XJ599lkCQLIsk6Io9sMYFxdH7dq1o/j4eAJQpYdOTEyksrIyW6ghKzIusD179vgtLv6SZZkYYxQdHU3NmjUjxhhJkmSXJfT3pWkaMcZo4MCBRNRwRMb/5oZhUEJCgj3Me1+7t33p/VDxB2fDhg12GyFbipCXAfzpp5+g6zo0TfO7UD15inmdPXsWZ8+etafx3DVRn3MgIhQWFtrfbwgwxuxrjIqKgmmadnkf/r73sby0tSRJthvommuusT/3hQTTDJkg8P79+y8q/EMel4e3MOojsAvbamhYlgXGGNLT0wEA5eXl0HXddmOQV0TEsiy7IrFhGHj66afRsWPHavU8ZUm2HWQKcPXH3fj1JSUlXbRj9M+Kg0cCWrduDQANKqDOe+Xhw4ejRYsW+PTTT1FSUoI9e/Zg+/btVUJmMTExuPXWW9G4cWP0798fjz32mM/KLN4/h8RwyW/SHXfcgdjYWJw6deqKOEeJCA8//LD9/4YEHzb79OmDPn36AABuv/12W0D8X8YY3n//fbRp06bKd2sjJMZJXr8yMjISI0aMsDMsLlcPrqoq3G43unTpgnvvvde2axoajDG43W6YpomFCxfixx9/hKqqtj2pKAqKi4vx4osvwjRNuFwuv9oNCZEBsHuujIwMPProo3YJQR464i9Zlu33/Olt+DGKotgGsXdbqqrC5XIhLCwMc+fOtavONVQThZ/3sWPHAKBKxWL+WWFhoX1tfrUZyBNuSHjfqAULFmDixIkAALfbDcMw7Jeu6/Z7dfU2RARN02BZFtxut20se7flcrnQoUMH5ObmolevXg2+4D1/uO6++26EhYWhvLzcjlVWVFTANE088sgjAPwf8hVqaMZBAOG2BRHhjTfewNChQ/HRRx9h48aNOHHiBFRVRYsWLdC1a1cMGTIEb7/9NlatWgVVVaul7PCeyOl04oMPPkBhYSFWrlyJo0ePQtd1hIWFoX379hg4cCCGDx+OiIiIBmXs1wTv8Tt06IDvvvsOU6ZMwbZt22AYBq677jo8/fTTePLJJ+0Zt198882S+/f8nkdEZF6tzlhfXOgMLSsrI5fLZf+ckZFhxyNrcrByr3hSUhKdOHGCiIh0XSdd1+nCe9nQ45XemKZJbrfb/lnXdSorK6vyc01a4c5YwzApd4XHGUsSC2vI3XegkGXZ9vsoioLw8HC7+3/ppZcwbdq0Oh2u/Lu//PILunfvjp9++gnx8fH25zwdhttqwQDvbSVJQllZGQ4cOIDS0lI4nU40a9YMzZs3t3Pn/B36JaLQ3QNDkiT7hvEM2WXLlmHatGm217suLMuCw+HAkSNH8MQTT9jZsFxcl3MW+2fhAtu3bx/GjBmD66+/Hp07d0avXr3QvXt3tGzZEn/5y18wb9486LrutxsoJPxk/iDLMgzDwMsvv1zFdvMHHqpauXIlli5dinvuuSco7C9v+PlmZWVhxIgROH36NJo2bYrhw4ejVatWOHnyJLZu3Yr169dj/fr1mDdvHj7//HMkJCT47NGq3Luvv815ZG9ePlGI2WTecHtpy5YtxBirMwWotgB4WloaEVXaLcECt09zc3PtgHh6ejqdPn262rG//vor9evXjwBQp06d6OTJk2Sapm2j+QqQB4ehEGDI89Tt27cPwMUt6CVPz3fkyJGLbuNKQJ4geElJCZ5++mkQEdLT0/Hmm2+iUaNGtjvGNE1YloWbbroJOTk5uP3227F7925MmzatzmEzOO7EZcLpdP6pcA9jDI0aNQLQ8MJGNcEzKbKzs5Gfn4/ExES89tprtqj4Ihk+GXC73XA4HJg6dSpkWcaiRYtQUlJS6yRJiAznfV7dunWD0+m0sxLq2wYRoVevXgCCR2SctWvXgjGGBx98EKqqVkvz4fDPevXqhaioKBw6dMgeAWrqzYTIADs3Kj4+Hg888ABM0/Q7ZOL9/YiICDz00EP2e8EAP8/Dhw+DiNChQ4daHxD+8IWHhyMzMxNffvklOnbsWKWtCxGzSw88nPL222/jp59+wu+//w5N06qtLPeGMQZZlu2wy8yZMxEfHx90M0vgvHh4Dpk/x/br16/a+76+GxyP22WA37hmzZph1apVSE5OtuORpiexk9snPIBumibcbjckScKsWbMwcuTIoBMYH+LatWsHxhjWrl1rG/J8MkOetZZ8AsDh79WFEJkXPL24VatWWL16NT755BMkJycjKioKhmHA7XbbL8MwEBsbiwcffBAbN27EM88802BTeGqDP1xDhw4FEWHRokVYt24dNE2zkwp4j80nABz+Xl0oACDJQmscPmwyxpCWloa0tDQcPnwYe/bswaFDh+ByuaAoCtq0aYNu3bqhWbNmABpWpmt94OG1Pn36YMSIEZgzZw4GDRpkJxA0bdoULpcL27dvx8cff4z27dtjzJgxUFXV/8nR19/mPJL/xwGiEHbG1oTX6ptajwmm4Lcv+IJjwzDohRdeIFmW7UXLbdu2pZYtW1ZZsXTw4EEi8h30v8AZuxQQw2WtyLJcZXce71yxYAx+14T3pirTp0/Hf//7X7zyyitISkpCUVERjhw5AkmSEBkZieXLlyM+Pr6u4DgxxkBAOSBE5hfeGbPezslgCXz7C09T79KlC1577TVs2rQJKSkpAACHw4HMzEykpKT4mX3BACIdACSiIPMaCgKKJEnQdR0AkJ6ejqysLEREROCbb75BSkqKveEf3/mn1iwMz1OoSBKL9NRWEmILccjjE1RVFRMmTMD06dNtgfXr18/enw1AvfYrkyTG/HdtC65auMBkWca4ceMwffp0REdHIzs7G/369bM3++P+s3Xr1mHcuHHYtWsXgJpDSkCIJy0KKiGPw1WWZYwdOxYzZ85EbGwssrOzceedd8IwDDvMxuO6H330EWbOnIlPP/3Ufr8mhOEvsENB48ePx3vvvQeHw4H58+fjjjvugGmaVRyuPNuipKQETqfTTm2qbRIkYpchDp8p5uXlYcaMGQAAl8uFsWPHYvTo0T7tLl3XcfToUQBAWVkZgNqzToTIQhwe1G7ZsiVGjRplp/yUlZX5DBkxxhAREYEWLVqgdevWmDhxYo1pQSCSgMrZpbDJQhg+zIWFheGDDz4AcL6GwcW0wzEMAwRUAIBkWnTS7XYDEDWiQx1uvNclMPLKzKjJ4C8vLyfD0PcBgGKQsav41CkDgHK1ebAF9cPf/T+4TmpJCJAKjxUxUzfXAoB0TXT0zrNnS3bqukEALBEACG2803tqetWEZ5i1KlxuduTokd/j4+N+JCImJScnG7qr4v8Ki4oYgOCoZiBoyJgHDx1meoV7ys0336xnZmZK0uTJkyVJun7erp27tpaWlSmMMUP0ZoL6QLB7MffxEyfVvXvzFg0adNcXixcvllNTU01GRBJjzMrOzu3UuEn0+ptvuvGasDCnQUTCRhPUiUdcBMA4frJY3bxly+prYhrf07Nnzwp4ctIYAHDFZWcvv6lxk0bf9OjeLT4qMsJAZZaGiAoIfMIYswBYhmEqBw8fxu+/5y10avKTycnJFUTEPOI777bgQlucnd06JjJqbsf2Hfq3bBEHjx9N2GoCbxg8IcnTZ85i567dJ06dLH5l0KC7/g8AvAXGD7bhQgOAnGXfjWzcKHpMkyYxnZs2bWpvQxkoJMbApAAOz1fazLzIS6vMevjzv55nWVyCllBR4cKJEydxtrRkb8nZkqziE6Wzhw8fcnTy5MnSlClTyFtggI9L9z5w8uTJWrebbrndoco3MYYWRIEMqDMEKouZSCIGS2ESC78SXbJEjAhURoxZjKx6yc2y6qMwBoBMIutc/c7Q3+YlMMZcIBTplr4j/9y5LeNSU8sBYM2aNUpycrLP9XH/Hwf4JSx83aj+AAAAAElFTkSuQmCC' +c30 = b'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' +c31 = b'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' +c32 = b'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' +c33 = b'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' +c34 = b'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' +c35 = b'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' +c36 = b'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' +c37 = b'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' +c38 = b'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' +c39 = b'iVBORw0KGgoAAAANSUhEUgAAAJkAAADICAYAAAD7jkPoAACxe0lEQVR4nOz9d3gcVdL+D386TJ5RzsmSHCTnnDM44UDOOcMuS16WZQlLXhZYlgxLMhljMAYcABvnnLMsy5Zl5RxG0sRO7x89km0yz7M2z/v9UVy6sDTdPd3nVNepc9ddVQLHyNy5c6Xzzz9f6/h93rwF/R0u+yhBEgZaZDnNMAyPYRhCx+eCIBgYCIAOhp8fEEMHHQPxhz78NSIKPnTD+OUnCOgY5g3877/9vyKCYBgGgmAYekiAkIAg6L/1Tf2wuARBEAUE4/j5Nu8f3VANhFpFCRcGleCm8886a2fHMd/VIQDhux/+/e9/l4eNHH2Zy+m8NirKMyQ1JcXq8bixWqwIAt8TAxAQfvAzAF03MH6NbvyICIJwzN3+MjG/+//oNP7ahzmp8jPzZYCiqrS3+6itq1W8ra072tt9b/nbvLPPP//88HcVTYCjCvbpF4tGx0dHPd+te9dBqclJSJIEoNOhS7+t/O819Xf5b4sAiLpuUFNbR9HBQ7u9zS03n3nmzNXHKprQ8csXCxdfn5qc/HLfPr0lu92mAqJhGP831pnf5f+0COaqr4dCIXnXnn16TW3tH86YOf21Dt0SABYv/ubcrC5Zn+TnddclSTIMw5AiJ/+mN/+7/P+PmN6aoGmaJhQWHRJLjhy5Ztb0aW/NnTtXEpYuXRqNaNk7fuyodIvFohuGIf2uXL/L/0QiiqarqsrGzVvD3ub23jNnTi4R2wOBiWlpKRkWi8X4XcF+l/+NCIKAYRiiLMt6z/x8uy5qNwCGKApSjyi3x+B3x/p3+e+JEBXlNuw261gwASQZ4TffOf4u/49IZCUUZEkSZEmK//vf/y7+vnv8XU6ICIJggvWAjCBoP3WwYRho2vcPkWW589+6rqPrx4OegiB04Gy/y/8HxTAMOjB42dCN9p86WBCE4xTqh0QURcTfjeLvwlHU3jCMzijgj2pPZDtKdXU1ixcv7rRmhmEQFRXFWWedhc1mQxAE1q9fz9KlS3E4HNjtdgKBABkZGVx00UUdZvNkPN/v8n9UflTJNE1DlmW+/fZbrr322u99vm/fPnr16gXAO++8w2uvvXbc53a7nTPPPBOXy9WpsL/L/zdFBL7nT8FRn+uMM85gyZIlDB48GFmWmTBhAsuWLaNr165omoau61xzzTVYLBYEQWDq1KksXLiQtWvX/q5gvwsQsWS6/uMQmcfjYfLkyXz11Vds27aN6dOnc8opp6BpGoZhIEkSCxYsQFEU8vLymDdvHi6Xq/P83xXsd/lpjx5QVRVRFAmHw4Dp5Guahqqq2Gw21qxZw5NPPokkSbzxxhu4XC7C4TCyLHduBvRjdhq/y/8dEYUfp2j9N+VnlawDiuiwSFarFUmSMAwDr9fL1VdfTTgc5sEHH2TMmDGoqorVaj3uGuL/gAv2u/w/IQL8AiX7rjidTgzDQJZlbr75Zg4dOsSUKVO4//770TTtOGzMMEAQ4FBNKzsO1hPQ9V8fvPqVytlxuM0i43FaCGtWFE0iggsevbefvPD3b/KnjrZZRGRJNJ/3193uT4qBQVDRvr8KGGCTNVw2HX9QJaT8JNR5nAiCgChAtMPC4G6JuO2WE0QWFBBBefDBB41frWS6riMIAq+++irvvfceNpuNZ599tnMZ7bB4hvk9aLrBtEe+xorBwB5J6Dq/2ETrhoE/pP6q++uYkK3FddQc8TKmTyODUhvxWMKIAp3641ckdON4CytgoBkyqiFhGAK6AaIAomAQ0kTCmoTwAwrYFpZQdREB89lE4effJMMAzRAQBcO8rx8RVdOP+0bDAESDfXXxHC51kZ4bQ356zC9WFFU3CIU1Nu6s4NFrRnLvuQPRNB1Z+u/inCaTWQgIgvDLlayDQt29e3dKS0u54447sNlsaJqG3+//PsU6YsVUTSeoaCx8cDr5adH/1Qf5KWkPhul162LuHbOeaaOKodkJogEdCvBjiqCLpiLaVbCooEgQskTOgeOtnAC6AKIGVsX8XRPN48UfoX0bgvkja+AIQdAKqvTj9/PdN1IVITrEhytzePXg1Sz7+zgs8q+PrMx4/BtK6n8Sh//fSyQ/QBZ+YXC8A+Z444032LJlC4FAoPOz119/nVdfffUHz9MiO9ewoqHqJgos/pQpi4SxRFH8wcELK6Zl+6mQlabruO1WnrtuGDe8WMRX8SF6JTaCboAiEVZlVF1AEo1Oy2QgYBhgtylgU3hjVV+WHUzj1jF7GZFZa353yIpugCQaaLqAJBhYXEFaWl3cvHgohxujeG7GFoZkV6P67Ki6iBRRNj2Sj2GzKmBVqWmI5sWNPbl2SBHZiS0E2u3I0ncU0zh6XzoCAgZ2m4K3xsVTW4bw4d+GY5ElFE3/6TE9RlRNxyKLxLltJy29RtY0PfRLDuywVB988AEAMTEx3HrrrTz22GPMmTOHRx55hMTExO/hYqpuEAxriIKALHYsQT88IIZhIIhip+n2er00NDQQCoWw2WwkJyfjdrsBU+l/LJQliRKabnDWkDRe6TaEIc84mdbfy9ScCsZl1ZGf6MVqD2P4bXSgN5Kog0VjcWEWB70eesS00Te1kVe35PHR3mxO61bFtG6VgIEasmC3K4TCMm9t6sWiA2mMz67ltNxK7l3aj2k9Erl+8EFc7gBawIphCKZyiQZby5NYW57E1uo4RB0u+XwU/5y8nTFdq1Da7UiieUOaLiCLBoKkgqSDrIMiU9YWxWUf9eHcU6fTM9WJqhlYfsVSZxgComAq7sna8MsG+I1OD+rnxeFwAPDZZ58xceJEVq5cyapVq5g7dy433XRTZ6TgWPklL1mHcuq6zuzZs5kzZw579+6lsbERVVWRZZnk5GRGjRrFn/70J8aOHfuTimbGz+CVawfRbVsZSY4qRJvBF4VZ/HOthz4pXu4cuQ/RAA1o1WRu/GI0cXaF6wYX0T+lkdP6HAZFZl9NLHP25fDOrlzuHr2XARn1FNTEc8+yQczoXs6NE4pZW5pKSLfzz3P2sL04ivM+Gc9ZvUq5un8xsqRRUBfLI6v64ZB0pnWv4JXTDuKJa2PXkRSu/2IUt4zYzyWDilB9dgTBwOIMoQRslDXGcKTVyebKBPY2xPHFjlgG9uvJvWd2Q9UNZOnHB1fTjZMGU3RKZLd3bOxSFH4lWhoIBHjqqaeYOHEimqZxww03AOaSqarq/4h5YUbsDZqbm5kyZQrXXnst3377LTU1NSiKAoCiKFRUVDB37lzGjRvHE088gSiKPxitABBFAd0w6JoSw13n9GHejnjWHk7BEaVy66kHqG63MuXDUwkZArJN5davhjIivZEXz1pD/+Rm0ERCXheoIjnRfh45dQd/Gb2Xx1b3oyHg4IYFI7h31B66Z/j556sJBJ/diu+prTz+cBQNipO3zlnDsxt6srwkjao2J39eOpi7x+3hrYuXcf6wQjxWhUCTh/5ZNWy4fjHv7OzKF3tzke1hJIvGC+v6cNn8Mby3pws7q+Ppk9rMKVnlSJ5Y5t4+MmKRfmQ8I2MqiaaC/RYYpW7oRIzXL1+WO5RnxIgR3HTTTZ0KNWvWLDIzM9m1axerVq1CEIRIMN38gkBYJaxpP/k2GYaBKIpcf/31LFu2DJvN1gnmiqJobrsj/7ZYLEiSxD333MPnn3/euav9IREFAV03eOCcvqiJ3dE+2Yr1obXcMzuXW085xFndy3h8TX9K62JoCNi5Zfwu+j97Fr2fO4NdtXHYottYVJTOgBdn0f/FmQzMqiXBEeSaOWMZlVpLj9QgLzxs4fX1z3BX+zJubFvNy7tfZ/kzDayvyuSDWev4YHcX7l82kL+O3EdIEej58MXc8+VI/KqEwx7mix09WFCYwZzzVvPRnhw0Q+LVrfmsK0/ktfPWMat/HUmeMJtrknlwWXf+84expMa6ftS37YBRBEFg7b5q/GEVQeDX5UX/l+UXK1mHwZs2bVrn31RVxe12c9lllwGmNfuuGMZPv0kdTv6uXbv49NNPkWUZRVE6w1bf/VFVtZPZ8cADD3RGJH4ogVgQTFV3O2z8+6qhFMWkc422k78ufYHTnhjC1YOPYEFl0luT2VsbxZoDXXjhnE30y2zlwQ0DCNgtPLR5IEPyWvjHubv5YE9f3izM48v9ebhiRC5aOp4Wzcq+lO4sjOnOt55stkenk+ts4dYVQykJxvDOvq68taMHzYqDkGFhWq8qZu/uhtOusO5IMjcuGMojK/oRZ1VIcfn495o+bKmM54NzN/D3xX354I4GXPcvYfbrCr0Hj+fCUV1QNR3pB8yYrhsIAvhDKuc8uZSxf5rL9Ee+xusPd75wx83NL5n4/4LIAJr642BeB2nx2EnssBwd/tDll1/Ok08+yYIFCygtLSUjIwNV1bBYfh4h6bjut99+C3QmI/zkOR3fv2/fPoqLi8nLy+vE774rkiig6QZXDkvlzSnncf3nZVyoHqDY5yH3nfMYGl/PIW8cSEGmvDOWMWlVlNfLGCGN8x8Ygq+ugYOCwuzdHqqbrYzWdyDLOivnCQTVcuRoF/+Omg6GQViQEQydBtGFtbCcW4u6kG2tJoyFy9/ty+BsLz7dRltI4uZvRzLvQBcCditXjD3I0zv68druPEJBka1XfcVbu7qhvrmdfwRXcMAqkt47jTeuHWRasB9QMAPTRWgPKjy7cC8Ds+NpHNeNVasPMePRr1l0/zSiHVY01Rxbf1glwWP72fn5b8jPaoEsywiC0BkqSkhIQJKkTgui6zp5eXmce+65zJkzh/fff597772XX+uatbS0/Opguq7rx0EpPyYdV331ysH02XsZnymNXNK8Hs+6JqKC7ZxtacSt+InWAyibFeItIdyCihLS8MgGFkDTwCHBsX62GPF3OrJw9Ijl1A0z7V4TQBUlwoKEzxBp2O1AsdgIW2RKtsbwJ7ebGkssiwpSKbcnEetqpN4Sy5/WjmR3TQxv2xZQITi4NulybvjTZWR4LGi68T0rZt6DQWmDj9nLDjBzSBZDuyVS/fo61jitrNtVyYxHvmbRfdNw2U3MT9UNLPLJATF+lrTo9/spKChgw4YNWCwW1qxZw6RJk+jatWvncW1tbaSlpWGxWHjllVcYOnQo+T17kpWZ+YtvpHfv3p1L4s9Jx/IYFxdHdnY28NNsD1EUUDWD3pmxXDO9J5tefZ3na+bgN0zsNaBByDAxUdUKbQpU6qBaZFoUgzZVR5Et+BWR1rBCQDfQENBkSyQ8Zd6zAEiqgmToOCWBGKuMU1dxEybBIhJFkGgVnCqMEyuQWkwM1hDAL0C9IFNljWPXgS70ienCM7mXUBSIYuSMMdw4IsXcTf6QFYtYt7ve3cT1k/MZ2i0RXTeVTjcMHDFO1m0p5cb/rOWj20/pvNeT5ab9LGnx+eef529/+1vn3z/++GM+/vhjCgoK6NmzJ5Ikcffdd/PKK68AUFlZydSpUwGor63G6k740R0g0GkNp02bRlpaGlVVVciy/KPOPJibkHA4zBVXXEFMTEwnxPFTIonmhuTp83pz4bpUxhW4iZY0Aoj4VQ2/qqOJIqoo4lc0grqOKoiENd0sDIQOhhaZmY6f70KMgukIClLk/4AhgSEhiQIOQSdWEkiQReJEnRSLSJKok2kRyJZ0ukgq/YN1DKaOhNYt/MM3nN0j7+PdayLL5I+8R6IooGg63VKimNQ3Dd0w8IVUthXXg1UmpGiIUXbmby6lvNFHZrzrv1IE55fKj85Mh781ZcoU6uvrUVW109K43W7S0tI6rd25557bufu0Wq1YrVbcbjeeqGi8YTOe+d1H0nW9k48GJrj72muvMXPmzJ905jtoR3379uWRRx4xH0KWO5NZjmWMHCsdf4pxWnniulMZ+PoDv3qwIFJh5JgYaOfzYC5Znfp37D0Dug7tQLsC5cddzbwxURJJt1gZZIdTPDKJaHxj78L8O8YQE+X6wWXyWAmrOjEuG2BCG8W1rdQ0+UEWMSJggqYbtAXCgOukwho/q2SDBw9m8ODB3/v82CymU045hVNOOeUHr6P4fYiieJyZPxZE1TQNr9eLYRjMmDGDpUuXcu6559LW1va9TUCH1Rs2bBhLlixBFEWqqqpwuVxER0d3XvPH2LgdFKX+Q0fRfeYtVG5eRI8UF7Fx8cTGxREbG0tMTDTR0THExsYQFeXB7fbgdDqxOxzYbHbsNhuiJKHrBqJowiSiIBBWVALBIH6fj/b2Npqam2mor+fD5bs5UN6GIohYa7cjBL2osd3BV4vaVA6R2m2aplOuQXkQvvCGwYB7bhzMpO4xKKqK5WcstSwK1HkDKJqOVRYJhDXQDYTvgLW/NPz035Sfdfy/m+6m6zpWq/V7WUzhcPg49F03DKwWi/mwBtgtpsXSNR1Zlti7dy8vvPACq1evpqGhAUEQSExMZMKECWRlZbFnz55OpeiQjn8nJydzySWXsGvXLlpaWnC5XOTn53PBBRdw3XXXIcvyDypaB7ZUXNPKIdsQFi+5m2n90/6HQ/fLZMTZbYy/cx5ZWfFcOvxuEp0GD3xeiq+lhatHelixq5TSyiYkpQWjpRzZW44RaiMxuxd/u+UGdMNA/gW7KFEUqGzyEQirWGUr2YluXC4rvoCCKImdwOhvIT+rZMemu3XwyAoKCjoR+fT0dKZOnUq3bt2Om9gfA/9kWWLu3LlceeWV39sZ1tfXU1BQANAZYjpWOpRswYIFx/29vb2d2trazvDWZ599RnR0dOd1OkTXDURJ4JMNJRhtLXy89iDPLthNmy9ETpKbET2SyEuPob7Fz+DuieQmR0W+F656aTW90mOYNiiTw7WtLNlRwc4jjTS2h5AkkTinlZ7p0ZwxLJupAzM644ljc510z7QTVloR5HRUq53zR6Qy+4tGxMTunHZaT16cs43o9FgMQ8Dv96ErYdqcLuqDMtke4Zfx1AxobguhauYYpcY6GdotkZVbyxDdVn7CLT7h8oupPh1L3PPPP8+f//znznAPmETGl19+mSuuuOJH44kdCrOvoIDLLruMcDiM1Wo9DoPrQPa/i8t9Vzr8rmN3o6IoIkkSK1eu5IYbbmDu3LkRv4/I56b/E1Z15qw7DJJEZZOfU/umEQxphDSN3WUtvLH8ILvWH2bGzL4svHcqqqYjigIpsS6e+3IPzy4uICnaTnaih0FdExmQk8Cg3ARiXFa2Hqxj4eYymvwK15yaR1jVEUSRM4bl8vQ7G3FMEigsa2BkXgpfxBazu7iai8bkkpHpJNZlcOXE7ry1/CDZySks+novj8/bzus3jjVf2J9Z5gQBFE1H1Y5qU78ucazcdOS3rEJhUn10Xf/ZO+hQnJKSEu644w40TcNqtXaGg/x+P7fddhtnnnkm0dHRP6ggHWjzk08+2algxyoqRBJCf8Er90PHaJrWuSP+5JNP2LZtK4MGD+kcXkU1KS6H633s2l9DTLybu87ox8erDxH2h7nxjH50TYmixRfmwAWD+eNLq7jznU3864rh6LrBv64YzlOXD0MUBIqqvby6aB81rUEOVnk5VOklI8HFFaf04JLx3VEiE93h/wzploCgaLQGFFr8Cq0BhVNG5GCTBAJhne5pMVhlidyUGHpnxTKyRxKr91Ty4Yoi/n7eIDLifzyM1DkmBjhsMtYIPcqA/zoR8deIgIBgmNtvGfBHJu1Hn6DDYlRVVXWGgToUpCPEo2laZ7LJD1wBi9WCriqsXrX6mPjmf1867mfhoq8YPHgIGw/UcN8HW2kPqmQle1CDKl2zYvEGVabctwDCGj16JNH86U66JLq5elIepw/rwrg+FzH4rvn8/fxBRDksKJFQzktfF/DX2Rtpb/KR0y2RAV3iGNQ1AYsk8NbyA1wwKpfMBHfEdTDvKSvejWGRqG4J4LLJ1HoDeGwykijQ4g8T47ThsstsP9xAcowT3YDx/dJZuLSQTzaUcPvMPp1L/Y9JJ+MholcCcKi6FcQf4vKecDEEQUDHMJVM1nXl5zCTDl9r+PDh9OrVi4KCAiRJ6rRwqqoyadKkTj6ZrpvLxLHnS5JMMOCnta3tV4GucNSS/tLzAJob6mgO6pz79Lc8eP4QzhyRzaJtZVz52BIe/+NYlu+p5NvaVqyxTorKmikqbgBZZP7GEq6e0hOnJBLjsuKwShgGWCSRoKJx30fbaA+EsSd6KKnyUlLlZcG2MkbnJXPtlJ5YZPN4BAEhcq9uhwWsMnXeAPnpMUgR+o3bbsHrDxPrtiKJIi2+MB6HhfrWIH0yYynIT2b5nipun9nnB0NJ5tiaS2UwrCEgdFqypvYQ6w7Ugk3uXEVOdoy8g2Qk6r8gliPLMl6vl7q6Om677bbjd5G6js1m44YbbqCyspJAIPC9XSGCgK5p2OwOnE7HLypd0GHtOixeRyLxL5We3brw5fZazhyWzbWT8zlS184VE3rgSvFwSp9UE1aRRFRVN0ffKoGqU1XdyktfFfC3l1Zz1rAuWCQRJXIPBeXNBPxhBItMsC2IKAjcff4gXA4rq1Ye5LKHF3PFsyvYeLDOZLV2DoHpubcHFRxWCc0wUDWDGJcVX0gl3m1HFCCsacS6bdR5g8R77HRLicIfVqlo9HUSDX9KzDCXedCKvVU01rYiWST0iJGwWsTfZI/5k4t2x6Q+8sgj9OrVix49enD33Xcf95mu62iaxqWXXkp+fj59+vThueeeQzpGEQUEwkoYyWJlwoQJx4GwPyQdVnLSpEmcf/75ANx9991YLJZO6s8PybGbgWmnTUdTQ3j95hJ+wTPLyLziXf4wuSeJ0Q7W7q5EDatIkkDv3AS6p8Vw9tiufPbgdMpfu4ieAzI4a3i2eT8RK5qV4CY13oVdFhnUMxmPx8aCzaX0SIninhvHsOGlC/nk7skM65ZoAv5Cx/N3jKeB3SqhaQaabiqZqhlEu6ydjOF4t40WX4h4tw2rLBHlsLDzSKN5/k9omWYY2K1yZzxyR0kjQoS0iGFgs8rEuWxo2slXs58MK0mSxEcffcQDDxxFx30+X6cl6lhGVVWloaEBMOGE2267jf79BzBhwvijjI3IiN97773M/+wzfD4fVqu1M5LQeUMRqo/dbmf27Nk89dRTGIbBnXfeiSzLPPbYY9hsNlRVPc6yiaKILMuEQiEuu+xyunTvxaykAA9/tJF/fraTr++bRptfwWGXmf7wV/jbQ1x2Wm8SY51M6J3K9IGZSBGfp7LJR3K0nbxI4oskmjSZhCg7H995Kq99W8iVE7uTEuPEY7eQHOP4wTHseKpAWANBwGGVwQBfSEUA7LIZbopyWDqXwxiXFX9YJc5jQzMMUqOc7K9oYebgrMg4/fgKcGx6a0NbkGMNqe0Y5P9ky89CGJ9++imSJHUyLzqkY4I7rE6HdbFYLKiqyrx585gwYXynP9CxxObn5TF37lwuuugiWltbOz/rwMU6FGzu3LlkZGSwbNkywKQCPfzww2zZsoUlS5Z877yOpXXy5Mm8/PJL6LpOYrSDZQ9O5553NrF0ZwXeoMrWojrio+z06JbIu7dNBEz/RZIEwoqOKMLSXZWkxjrN5VQzKc5ihDI0rHsiw7onUlDeTG6yp3MZ0yJjIIrfBwxafGFEh4WkaAeqZqBHGlgYRCIGopn/4AupxLlthFUdt82CAKTGOiht+PmsorCidQbKAeLctqNabhhYOxgXvwF5UUSSfnCn12FdPB5P544SjiqVzWbrxLmOBWw7fCmPx2P+/p3rqqrG9OnT2bRpE5dccgnx8fGdSmK1Wpk0aRIrV65k1qxZ7Nixg6KiIgDee+89RFFk0aJFPProo2RmZnaeB5CXl8c///lPvvrqK9xut3kfukHX5Cjm/mUy8++Zyu0z+5Ce6Obpq0bQLSUK3TDQdYM4ty2y5ReQJZG3lhcxdUAGYCqPpptlFjpih4YBvTJjOxVMEEy4QPqOgnVMZ1N7yFyuItbJbpFwRJY2p03qtPKqphPrtiGJIlaLGYrLSnDT0Br82YnsoO50XGtwbgJIR3eWkiRiEX8bn+xnY5fXXXcd77zzDsGg+aC6rmOxWJg7dy4PPvggffr04b333us8LxgM4na7ueKKK8zrSOJxMWNRMsHW/Px83n//fRoaGigqKsLn85GdnU337t07r/X++++jKAqSJLFixQpKSkrIycnh3nvv5ZZbbmHfvn20traSmppKfn4+FovJlepYxjt2/PXeAInRDvrmxDOku5k1HeOymr6ipmMROp5ZYHdpE2FV57yROaiagc1y1Hdcs78Gp01mcG7C0YC1EMEAhR+IC0aWt/rWIA6rRHK0A19IwWmT8YWChBQdm8XMrBIEAV9QxWGVsUWsjs0ikRTjIBjJEP+pzdJ3P5nYJ434ZA+N3qMK+gOx+5MiP6lkuq4zevRovvzySx577DGampro3bs399xzDy0tLezZs4f333+fM888k6eeeorq6mry8vJ4+OGHycvrAYAgiFhlsdNcCxAJMJssjISEBBISEjq/t8Myeb3eTutlsVgIBoO8/fbbPPTQQ4RCITweDyNGjDjunjVNM530yPeU1rdz03/WElY0dFGgYH8NV5/Rj2ZfiBiXDUEwSwxAJD9UgH3lzdhkEafNHJq3VxQhiwIzhmTR3B7ij6+tY8+/z+mkdguAIB4NpX1X0QzDoLEtiN0ikRbrZH9lM0nRLhpagwgYOKwygbCKKEBI1bDIAk6bjKoZWC2SaWU7XI6fwQGO3WDEuW30z45n+ZZSsEg4LBKxbltnuOtEx8nNbCXTLfhJn6xD0WbNmsWsWbMIBoPY7XZUVaVPnz6oqsrLL7/Miy++yNlnn43P5+ssG6XqOnJkVyaLApbvhJqOjYd2+HcdmwlZlpk9ezb19fUAnVb0P//5D3fddRdut7tTSTvOO65GrWHu3i56djmn9k7jxmm9cNhkcq95nyFdE9l8sI7EKDu+kMqSLaWcMiiTKIcVRdW5aExXVu+vZehtnzIgL5labwBvW5Alu6to8Qa4fVafiA9mYJHMPNJNB2qJcdvomRFz3DN23JcvpGK3SiTHONhd2khytIPCihYUTTfHRhKxW0x8LRTWiffYaA8q2C0SbrtZ9+3HEX9T1QNhDUk6+sIIgkCix26GAgyDWLeNOLftpAWYdOPo/Pxs3OHYWKLdbkfXdfbt24fP5yMtLY01a9bQ2tqKYRi4XK5O1saxA/JTZrpDOTrikZIkEQgEmD17NjExMaSlpZGamkp6ejpNTU2dySod3DFJko6DNYzIZBypM6lCj1w8hEueXcHsbwpIS41m6oAMFu+sQFF17v1wK09+soNRf1sAAlhkkS2H6pGDCt27xKFoOq9cP4ZvHpxBbqKbBI+dHqnRCIIJzta1Bhh613zufX8zVzy3gkc+3QGYk9yhFFVNfpbvqSLeYyfBYyq2226hPaSiaKb1dNllbBYJm0WksT1IUpQDrz+Mppu1QCyy2AnF/Ng4Hk+JMmHQWm8AJBE0g+QYB7EuK8pvECn/RQHyDgvREavs378/R44cIRQKoaoqLper0wodW5Ps10qHooiiyOeff05UVBQOh6Pz2s3NzZ1W7ceYsELEGU+KdiBgOt3/uHQoc5YW8tXfprJoWxm7tpUzNj+FeLeNqAQ36Q4Lum7wp9fW8urc7aDqfP6vszljqJkZ9PzifTz07xXgtDD7k+2cPasvb986AREzjhnjtPKvq0fyxGc7+etZ/bFIoplYK8JVL69mX3kz43unEuu20hZQiPfYEAVwWCTaRAGXzYIkCiRGOSiuaSU72UN1sx+nVeJwTSsCUNXkJ9Zl+1Gu3HHzJQo0tAXZWdKIYJMxfGGSoux47Basv0E881dV9Tn24SRJwul0/ujn/xux2Wx069bte3/v2LH+nOiGgcdh4YbJPZn090XcfVZ/Lp7WkzeXFLKsoApHtJ0oh4ULx+Ty0LubOHt8N3r88WOaWoMsevpsRuYlE+syE2dkSeTaU/M4bWAGFY1+Pt1wmNcW7GXFnioevXQo7982kc82lPD0J9sZ1Ss1Anvonf/fXFSHx2nBbpFw2S20BRQcVhlREHDaZXx1KskxDrYU19MjLZrNh+q5aExX1hXW0D0lmr3lzZ0bkp4ZMR17ie+JYRz/Yn+5pYyW+nZsMQ5Cuk6Cx44sib8JI+NXl47qkGPN84ko2flDKW7H0np+SqRI9vhl47sR57Zy33tb2FlQDUGF6Ox4Av4we8ubyU+PYevz57Fmfw2Xje9Oe1jjw+UH+HDNIWq9AWqaAzS2h9BVjVMHZDC8exLdkjwsfeIMFmw6wouL9mG1SqRE2Zk8KIv7zx8UqWZkgrd3vruJlvp2UtJjkCXT9/KHVVw2GUXTiXPbOVLfTka8iwNVXmYOzuLtFUXcPrMvBeUtnD6kC88t3se4niks3FrGRWO6ElY1DEM8mkIggIS5aQiFj0JRy3ZXdpK7rdEOXA4LkhDpZnyS5X+sZCe6FuwPKdKv+U4xgpPNGJzFjMFZ7CxpZH1hDfsqWvh2WzkVjT4MAwZ3TWBwV3N329gWpLSmFZfDQqzb1glN+IIKJXXtrC+s5WBZE5JF4rlrRwEQUrTjYA5VM9kX2w438Py8nQhOC/6wgm6A0yoRUjRiXFbqvAESPDaKqr2kxjqpbvaTGutA1w12lzbhC6rYLRKqplPvDfDtnirW7q9hTM+U457z2FKpx3ooFU1+DNGMV6qigD+okhxj/8FspxMt/2Ml+78ux4KnAANy4hmQEw/AnqnNXPPy6s5lR9XNxLZ4j517zxv4s9cOqyY5UJJEbJFdYWdjhAg4V93sN3dVkog/pNLiC2OPMDokUaA9qHKg0gsGPPPFboJhjae/3ENClJ0bXlyFKgrc+e4mworGqr1VWGSJKQ99xXljchnRPYmUGAdZCS4Gdk3sbM5gtRx9Md12GXQDmyzhsAp8uqGE6YMz8Tis33+gEyz/TypZBwrv9Ye5/4Mt7C1vxipL5CS6uf+CwbgcJuDZsTGIddnAjCOjaGaZq5e+LuDtb/aTkuzhtRvGkBrrxAAkQejE/AyOWo+OMpmN7SH+83UB7688iGGVEQxQVZ3i2lassoQkipQ3+RmYE8+Vj3xFercEHvpkO/gVCosbIhcDVJ2m2jYQQHLbUAJhFN3g3S/38K4eYY1YJYZ3T+Lze6dF6EhHLeqovGQWrzpoWlCLhN0qUdXk+8mMpxMl/88pmWGYqWmBkMbUR75iVLdEPrz9FKwWiWc+38X4BxYyICWKwV0T+XpHBUVVXm6Z0ZuwqmORRCRJRBIEpg/K5OG52yn3Bmnxh8lMcH8Pq+rwiTp8n5X7qrny38spLW8GuwWsEcqTAOW1bTS1hxjSNYG731xPm6pz56VDufWMfkQ5LLy9vIi73t5IXlYsTqvMqX3T2FLcgD+kYpVF0uKcRDutfLu7igm9U/lwzSGCisamLaX868vdXDGxB8ox5SYuGtOVR+duj/xNJjnaYdbD+A1il//PKZkWAX/fX30It93CM9eMYvaKInaWNPLc1SPZX93Kpx9tpXDhH3hgzjbOHNaFxrYQ8R11IXQTSE6OcVL1xiUIArQF1M6KkSbmZ0R8Pr2TbGiRRK56cRWlVV6skao7mm662bIsobb4+XpnBTdN60X+RW8Rn5vApifOoLLJz5/eWM97t0zgSEM7LpuM1x+me1o0bUGVU/qm8uo3+7l8fHeKa1oZ0SOJ1oDC7tJYtuyvwRrlYH9FC4qqdwbHVc0gN9nDgG4JbC9uwCqJhCL07x8jP55IOSmgyUmNmUX4ZAXlTYzOS0JRVe58eyMT+6RR3exnZ0kDj903Dd0wA8qVTX5W7qvmH/N3UdloLieyJBLlsGCzSFgkiXiPDUkUOut9iYKAourUeoO8t+ogy/dU8cWWUkbnp4CmgwBqewhDMUto6boOVpl/fraLvPRobrtmFI0ljdz74VbeXlbIpxtKCIQ1JvROpcUfRpZENh2s53BtK42tIURBYPvhBrYfbuBApZd1+2uobw2iKzphb4DR+cnIktjJeNEim4GUaIcZ3BcEwqqGoum/SUrJCbdkBmbi6Ync1XQQFXVdRzdAlmROHZjDU1/u4yFZ5v7zh/D1hmJW7qlk9q2T6ZUexWkPf8npQ7vw2cbDzBjUhfveXs+zX+xmUF4qiQnRSDYbb13eD0GAZr/C/govsmiQl+KmqtHHrtJmZFlkxZ5KhnRN4N1VB3nl+jEs3lhMc0Mb44Znc6QxSEV9ABEVyS6yu7Cau97ewL+vHMmwnDhe+7oAt8PKusdm4bBKLNpWSosvRHWzn+a2EKIo8OayQkob2iiua6esIYSmBjFUFUkU6ZoZw3ljunHXGf1ZsbeKDixfihAmG9tCWGWJsKIREAXcdn6TCLksnuCiCEaEy9TJZ/ovvUvHxjw7QlLH5gRkWlrYvGYZ/57dwu2XzyIo9MIugre+itMemMPWCgtbSw6B5mfzoXqQ7dS1Bli2Zhcpvhp6BKp42nYL9oxs3vlsDfsPVOKXbPTr15Wq1hCjuyew42ANWlijzbDRLTudN1eXcWD2New8WM/kvom8uGAzNz/yEXpmPliiwaPw9Kf72Fsb5PFLh7L88e4IgKZrvLB4D68vPgSCDVQVwhrIEjjaIShgczeQ5vFT5otGM5zkd09k84OTOgP5YU3vXJZkSaSyycfOkgZcdpmwqhNWQ0S7rJ0wUEeA/2SIrBiGT9VUOBH9Av7L8l3F6gh3hUIh9u7dy4YNG9i0aRPbtm3j8OFilFCYO5bBMw9kkNKtL6qqU7JrLV4/TL/yPHoNSGLO1nQqWlxkxPmoaIrm0cq3ubJ5A27gzb9vosiazj3+QpItCl7Rzp7iZA5E5bJrbxaqNR7R0NlWvJ78hAAfVEXRLbyLIX278/zzHzH/xWf4U30pidpQNsYPo0KOIWh1sXVZFZPWbCY/NQqbw8qmJjf+mjbyctqY0rWKIemtpMZLbDps46lvEjlzhMI/pmzCG/Qw7qXRnNv4LSVb45n4QJgbzxnGVcNScNsk1GOK3H287jBtde1E58TjC6lIggkGd3Bjg2HtpGFmsvFb1nn8hdJRd0OW5U7Fqq6uZsWKFXz99desX7+e4uLi750niOZOsaKigoqKCsCkywgGjLd9y18uyOOWPvt4Z28+d44uZEVJPJ9uGsPNO3ozoGw3M31buMJXjFcCrwqxQC+qkVp3EpbAJ5owSDCsU+6DyxxQcyvstEK0Af9wQ3K8AA1buLR+CwERwpKMQzawqBrlW508kXo6XUcN556puzm3TyWWRBXadZatamDV7EO8cl4+F5+bAKEwV88fw6O7X+EsfyEtImwq+ZwP1kzi1Qnn4rHIpMYexcAWby/H6raZvmfEXwurWufuOKzqeByWEz538H98d3mUui108vcXL17Mhx9+yLJly2hubu489tjaHB00oI4KzJIkHSVQGWbrnUfeqWf6qbn06adxllLGw1+l8Y9z9zN9eC1FlfHM2T6WezdNJHH/YSbWbWWgUoJTgnYRgpKMaBhYdA0DcFgE+sSJCIaGJdMsxmIIAgFdp1kzMCQJXRBwGipxikpZwM6ypNFUT+3LVROCXNBrEcQY+KrgzTcaePXjcnYVNnPzxblcfF4a+Nu47ptT6btoCacFCzlikRENjRFqJeMr32Hp/HXcGH85511o0slbfCaDY+LgTNYX1uK2W3DaZBPe6cT1Tto0nngl+588S8ey2GG1DpY18tE7b/D+e29x8GBR53EdVSA76EXH5iAcK99NpZMkgXZfiD//az+L/zOInpmthD/aR6/TKrj6rHQumuTlgWlVMMXDwgOpfLH5Qj7d1kbfkj2M9+6kq+HFiCicioRomDRwA0DXOp/bQABBxIWGQ4Fi3cO7KSOpH9WTSRP9PNDrMKIzTMMRg7ffqeHVj8soLjf5/JOGJ/D83/Ig2MoruwbS8EkRD7etosUi4TJ0bIJBmy7QIkmcEThEddNcdoqTAZMyHlLM++lghGiaTqtfOa6MwcmSE6dkEbZASIlsnX/Bq/PdZbHwcDUPflaIv+hj9n75H0pqv3uCiUMZ+q9b8TXNQJZEvllfz/xvajnnzFQevCaJd+YXc9e/9vPASxbGD43nihlJnD+xiZnXOKg9M445uwbw6uZR2PdUMKpyG8NDhSSIGkER/IKAgYBoGJHSngIudGyKwX7iWJI2irYx3ZgxoY2z8grBrlBVpPHqZ9W8Oa+cqjqz+IzVIuJ2yrz29z4gB9hWksJTn2XxedObVIoi/24S2BUUmOGCyz066BoNokj3tiOUqH4Aop1WWgMK+/ZWk5kaZfankkUUXe9kq55MOeGWTNGNn2za2iEdwKYsyzQ2NnL3w4/z5hcrefDukdx9azn2u06lraKdb7e1M3+1l6Ubm6ipNwfVJDsK6NovT/mKJHnz1+cPMXV0PJ4UB/+6owdXPrCHUFjl6zU1fL2mhjsSnZx5SjLXnt7CrSNquHWCi41Hkvhs2wy+3TqVrAMHGFu/nT56DTbJICSaHTgExWC3kMTS7DGoY7M5Y2wT03sUgKxSvFfh5U+qeOeLChpbzGqNFtlkVoQVnaduyyenh422BpUzv5pOpbeGy5rtVLaGaFR0QGdfSGKsQyRXNhAMg5BsRxdNyy9LIkO7JbBvfw02q0STL4zLIaDpIFnsZhTiJLriv/lyqUeC05Io0tLSwlNPPsnsd9+jpwK3pKVTvcjL5Zt7EptrZ3hPP6dNruWs8+qh3sf81e28Nr+Ob9bXmZnggoAsCb8ogVXXDSRJ5FBZO//5pJI7/5DNxTNTeGFOOdv3t2CLJOFW1/t55eMSXvn4CEP7xnL5zBQun+plxLllqNOj+Lwwk2+29uGT7S30K9lFz/YSWiQPG7oOxjIhg/PG1DMhdzcIOnt3hHhhTiUfLqqk3W/WErHI5nJmAIqiM2t8MlddkA4BH/csG8mQzesJFH/N7sYmEERkweisdC0IoAkC0bpGtT2ONvFo/uclY7vx7rcHaG4P4/OHyEiKJbz6Bf5yyze8/dab+NST55T9Zo6/Aeia0ZlQ+9mKHfztDxdx4MABAN7NkenbUkFz/SbakDhgyWRTVC8+ysjD3SuP6UObuOy0Ms46O46CbVn8870aPlxUiaoe5br/nAU1IhnWT75dwuUzU0jMtPOPm7sx5Q/bzPxI3cxj7CjTvmVPE1v2NHH/yzZmjU/m2jOSOHdkM+cOtlFSE8f8XSP4vOgUkuLDXDWkhpE5u8Aw2LYlyHMfljP366pOzleHcqmaEcmlMIiNtvLCPb0QpHbe29eXls8P8WHNPP6oCLyNiE0w0Ayz65qmaqwPygx1Key1xPHP+IuZapiKaxgwpmcKackeKqpbESwCByrbEBoDlMx+i9LiQ+xxTuPC0V1P0OweL7+JknWkk0mSwOp9Vdw7Zw81h3Zy6MABsxMJBmFVp14WCFsF7GgMN44wruUIvubF7N6fyZLlw3m3e18GjVC5c0wx77zg4q+Xp/K3l8v5fFkVYE6k+hNWzYwOCNQ1hXhhTgUP39mNyePiOWNCEl+srMVmFdH1SCaTYeYuCgK0eEO892UZ731ZxsBesVw2M5Urp/m5Y3IdTJZA0CEssGlDgH+/X8q8JdURh1voVC5NM6v06AYYmoYOPPvnnnTpJlNaF827c108Wf0FBy0Sf46DTWGB/X4VEDBL8Yt4FYVdpPH0hGsYGYcJ4GLSjuwWCZdVBsMw2bCyCNHpSKLIytWroYsT2XbxCZ5pU066knW0wlM0nVteX8eSLaU8dMUoRl2RS/68+1EUBbckYsNEsEXDQAd8CLRJAiIGA41yRjWUU9loZ8GeEVyyfCR9xnfnkVMLmP+mnUULU7nj6YMUHWlFkjqqAf3w/XRk9rz8cTk3XZBBUrqNR//UjeU7ArR5WzuPkyWxM8dSFM2sb1032FHQzI6CZh5+1casCcnMGJuAbsC8b2uYv7QG3dAj8IqIHqmBIYkCimqgq5GUsdgMzp0Yx+XnJEMgxMPLR3D+tg+JllWaDIFYweA0twUZmalugcqwQYao0s+dzJOnXMvrf9iLv9rLy9VTAJOvVtXsp7LRB7J09Pkju3C7JBEU1ZPml500JetgMVhkkfUHarnxpdX0z4ln6/PnEeuyUVJSgiRJKIrygwF1AQMpMih+BLySRIIe5K62lVywazXzDo1ixsaJzDrNz32n7WX6KBe3PV3B8x8eNh80spX/rhgRa9boDfH6Z1Xcd1suvXIcDLj8Ts6P/4ZtO0tZsr6Zqjp/5zkWWezINDtq3VqPWrfOe44olxZZeiXJDKzrkWzvKaNTuOuyRP556CJuGnMQpH3MPziQ8MJCpinF1MkiFkOnTYernApXuQWcgF0wqNE83Df+al65dh/Znhq+PpJN1DE5EJ9vPkJ7kw8pyoEWgXYsajsqkdxW9fgChCdCjEhT1ZPGwoh2mmj0ve9v5tJnlvPgxUN47/ZTiHXZ0HQDp9OJNZIBHgZU48c3DZogkKKqLIodyHVZl+IRda7yr+WlzU9S/OIRRj07gfWtXXjuiW58+u8hJMbaI8kdP3zFjp5Er35STnOtiuAKMTgrQFqfgcx+PZeCz0bw0ZODmDkhBYdNRlF1NE2PVL8+at0sslmOSpbNHyFybVkyrZ6i6kS5LdxwfjYbPhzFwnfzye2ZT6LDz6jMg3h98by+II4bKhfRKgudL5UAqJgM3hZDoD4k8rc+V/Dw1WV0c9Whh6J45uUtpOhmnqphGHy4ptisiNdhrXQNve0YDEg/sUpmQlaCHyJKdiJj5B3DtOlgHeP+9iXrC2vZ+NRZnD0iB1Uz32pJFDpra5hH/7hogkiMprPY1YvH+17L9qHjeTZmCoIBkqTwWOM8/rzgeR592M2SFVGcc4GbTR8NZVifWBT1hxXN7MYrUlkX4JNvahHsdq7tc4Dr5vdk9sI8RJuVCy+KZsFbvdnxyUju/0MeeTkeNM3otEwddTH0iL/VYbk6lCshxsZdV3djxyejePWpbgweaGFHYQyT3h7BJb1KkV0hXtrem0HrV5Il+vEjHFeDR4g8e4Km83zaGVx2tcGQ2BKQPfzxoUKWLjtIF5upZA2tAfZXehEiBfAEQcAq6jgIfueKJ04iWVEqmHF+9BOIAttkicYWPyP//Bn3XjiYRy8eCpjLpywdbQghyzI22/ENpQwEdOFoEpeOgFPXKbHG8UC/G/jo/I2MzahgmHAG8d+2cZV3A0csdnDbuaBhPbd8cg7Da3TemraWte8P4KI/H2Det1U/uiEQgNfnlXP1OWn0zmyif3Ibf/l6KOsrknHLCjN6VDCpVx0PD8rg4evTWLiujblLalm6vp6aBjMftKOyjxZ5gRJibFx3XhZ/vCCdjB4yBDS+2pLEN8UZvL25B70zG5nS+zBH6jPZuDjIY60baLIIxKGjC+AzOhRMIE7X+dKSj/O8XlzSfRVYY3ju9RL+8+kRszCz3Vwu61oD2C0icdEOGlv8CJKAy27B47bTzsljQnRM3YnHyQTQFY33/jyJS8d1i3ST5Qe55h1vrkUUEEUJ0dBwaEYnvdkQwCXAo4nnc9OUak7peggUK+9PX0efyj/QY18N2aFGdrm702Zxck7zFj75ajBdS89n5cUL+PTlPG570MZzH5Z8T9E03UAQBbYWeFm3zcu4U+2cmVfOJX2PcPnQQpbs78K8ghweWD6Q8/scZmZeDTNnCMw8PYrm0m4sXNvC7PnlrNjSiKbpxMfYuPz0DO66IoPUHjL4dL7dkshzm3sytWstfx5bwJLDqfxtZAHYVF7a1J1Ju74g2WJQK4gsCQjYgOF2HcUAC9CgWVkybgZvTdyFIdrYs9vL3c8XIVskVEXrpP3EOKxm9nlQiRTQEEiJcSLYj5nukxi8POFKFghrpKdGH6NgQmd7mO8/Z6SWgycdl60Zv66wNHU4NVI0boJImkqZI4mt9oHMUveBbsFQJGI8GjNCWxEQmJdxKk5CuNUgVgGGy4c4VKhzwVvj+ei6rTz7iAW3U+KxNw59T9HMYnc6H31VzfhT8piaU8UTG/tyzch9zOhRzr66GF7dkMeGing+O1BHhsfH6d0rOLtPFZddFsNlZ8WxbXuA+haVwXl2ErtbCNRb+Xh1Eq9vzWfFkWSS3EEu7VfGigPppLiDTO91mKKaLCq+beL60H6+RebVZp01PvOenkoWmeUCq6LzRtJELj4rQIK1GV2L4uZ/7CQU1rBKAlhciFFm44uUOBeJUXZqa1rBbsEqCzgdDuo83YAt5oXDIU4Wo+yk7C4l0Sww11GzVPxRgx3h0Qea2SbF4XJ5cATbGKZV0mBEscWaS5y/hf/4/8Er26/h2sFuoh1ePt+dRWL5EbJaGqnUjqCIApk2PwHRRmZrCZPq3+fVfT24tDad9U9JPHpPHpqq88Tbh49TtA7wdtHaetqqupOX5qXOZ+W82VNIjfUzIKOBjy9ezdzCDOZeuJK1xWl8sq8Lcwu60j+pgXP7lDJ4mAEWg0Cdna+2xHGwMYZoe4irBhSjirDo4hV8sLMrN8wbxReXL0NwKry9LJuBBV9wXROsCpjbVpsIYR1Wh2QucqvsNKJpmjiA87tuAauHT7+oYvX2RhNaES0w+A9UKNGR8RaZOTiLvftrAHBYzB4HXvWYdDjlxyqV//flhCuZKEAwrBJWNSTJDIXc/vYmThuYwaR+6WYVn05n3JzkUKCNLeEk8mNSqZQc3Bd9CrkZYSb3bqDZb+WJ7WPYW5rOqsPJnD6glfc3pbExuR+J5+WSn9nOlwXp/LUgm6eqXqWHr5EyezyXaKU8sqiIa+UkXn+4D/+4ryfNrQr/+ay8U9H0SE5kRY2fNTtamX66kxFp9czZ15VPrl4CskptdQJNISeiJjA6o45x3ctpaPHw9aF0Hlvdn4ZvJBJcATI8CoPSm7h+cBF2R4gWr5OFh7Nw2RSsksrQbtWcln+E8sZ0qlZ5GeYv4u6gjIgaySoyXYRyVUBQDBakj+fSSY2IgkLIJ/PQayXmDk7TEXpNhaR+1NU3AGbxvtOHduGJT3aApuOw2s1+S5E6Igac1OXyhEMYgiAQUnT8YQ1JNJtdXTy2K/26xHUmbQBYLRYcDrO2hiiKNMXnUetKpEpOJiZZZNnVq3hq0lreOGMl7924kxiPysKDqYTbXWwsj+e5M7fy5DmbubpfIZ9f+i2XDT7Mx44xFMXkUJM+hsqEQWiyyJtb+nHJS/GEm5p46bF+TB2ZiKLqneGtjmyeb9bXAzIj0hs4NbeG97bkMX9TLxIdIeKdIWra3EyfcwotLW7i7SEu7XuYDy/71oyd6laePHMdFw4rYF1pCg9+O5iKVhd+RQKryq1LBnFWj0os0T4+2t2FngWbGO0wOD1KQDfM6oiKYXaeKw+pbNejCI/JY1JaCdhcfPJVDQXFrUgi6JKMkD0KFD++8NENXPfUKGJjHKDoOKySSbc2fhvy80nByXTDIMph4eVv9vP55lKGdUskNdbJta+sYX+FSTw0OFp2XcRgsWcgL6SeyxdRkzk9r5p4jxctFIXqdzOgRx1PzdzGjpoYNlUkMjG7llsm74d2Fxgu0CXuGFrA1sS+GO1VDC/9grjKjYiihH3kGXxUNJb7ZqtIUpB3nuhHdroTNZJS1oHXrtnehNEiMCStmao2OzEWjYFd6thUlcDzG3KJdwZYdOEKYuLa+OJABufNG4cua4zr0sCMHjU8s2IARSWpnNq9jPsm7OLlbd3ZVBHLnspEZnSv5eJeJQR9cexcrzOhfS+NgsCd0RoxsogoQL5DJN1u5UanzvrEoUwd04YkhAj7DJ56t7Sz3kZMUga3XzARiz3SGS4y3i6bhWiHxQwrRTZaMidviTxWTriSGYaBzWKi4vnp0WQlumnxhQmGNaYOyDAL6MJx+2odgYeLXmDZnrvo07yFxBgFwy6xfX8reRdt4Nb7SpmUVUWUU2RfnZMZvZpZsKiGrPM2MfXWHfjaIckRxCKFKIwbzCE5iQpdRpUkVH8rli5pPLWqP6+8UUZyvou3H+oTAU+PNqPYf9jH4dIQsQlBVB10XWBZcSpnzBnH2sPJnPb+JF7e3p3CykTOzK/gwzPXIGoCii5jGAKju9SSHOVnxeE0lhzIpMbnpDUoMfmNKYQ16JJZy9eHs0nZtZ9USaXdEEgRdf6TbPBOKsxL1fkiTeUSj0Rp/96cllUGVidfrapnd5HXxFkFCWXQVby6/DCqP0RUBPAWBQFfUMEbUDrrrlllEfXYXvP/L1F9DMPEynQDTulj7n5W7qsmLy2a80bmdB53rCEXDIOX08/ggy7DORx2Mj7lWwhJXPb3XeSUtfL1QS+LN1mwjxzM3th41h72ELuwiD+GDT4tbuGDrxO4/opoxjuLSW2rQ0NHNnSiJQutkhXd34LcdwIPbBIZt3Ib46enc9flOfzjrWLkSHHfYFhl+wEfuf2jGJLSyHlzxvH8GZt44bStPLUpn9fPWM+hhije2NEdw4ARaQ2My6ugsNGJoun0SIX7VwwgzhnithEFDE5p5N/xvZFFg27RzSCJLNsZzYT67QRFkA0DH9DPauZG+nSBOENjoT2fPiMkomytGKqHF+aUmXCOZhCVmMID159BQDX454dbjuulVFDRQnOzH2STDt7iC6Mdi4fKJ4ffDycp71KSIm9SpOPa7tIm4tw2kqJN/tN3MTNRlmhMH0pNWTVn5G5hwigr/3i4nJpDLYxPEDFUieWFh8gKvMqOmjx2b6khrUHj4hwHfcMh/v1hORecn0Ef9TPe31HErZkWkiWDZk1AkCxohoCuBGhQcrjuic9Z0SOa+27qyucr6ygsacNmkVA12L6/lfOEGPITvCTF+7hxzB4OVyYzOKWZNLefmjYXT0/dzOGGaL45nMYVcybyzcEkLLJBs9/GraP3Em9VWF+axMTsOkq8LgTD4I6hu6lvTqFlezO9tHr8ktkiRwACHQZGENBVg125/flDXh2GbGHXTi8rtzaaKKcg0NrrYu78YBeSHkJrD5MYZe8cw8XbyyGsRiAMySzzrisYQqToh9Xs8nuiRNVUOhJBT1rZPcMwnWpRENhT2kRZQzuSKPxgSMvQNGivR3Q7KNxTyqzL9vPIf0q5JiMKh83NkbDMzZdkc3Bhf9Y9bXDo3VjiukWxskUhxSkSKmnnrBlr+ebLYtpsVja26RSGDDozADSDvFQ346cNZkPbZN79pBpnmoV//Kn7cRV69hxsg5BIz/hWRASCLW5kwcAi6TT47Ly4JZ9QWMYta1zQ6wjzL1/KuJx6bh1xgH/P3Ei32DZKmz0EDdOSz93aBUWDuORmvj6cRpfDhTgl0z3oEBFz6m3oVBh26JdG/9haBNHGB4tr0DQDSTCQ3XGcNW0Ct03rxqyh2cg2qTP7SDcM9pQ1mbFLQSCoaLT4QxhKu1nPQzRzD06WnHBLpusGTpuEJB1VqD1lTeQke5gxKOsH4UBDN6C1Bj1/Fgdcd3KguhDrCJXnZCtaWzVUzicjVqK2IYS3TiE2DnR0PmxWOSvZySUJOs5WPwkuEcUD+8Myq9oUQhrm4AYULp+Yx7SB6QzZNpWnyrpy0ZE1nD4tiQkfJrByq1ld53CFH71NJy0qRPfYNlQBvjqUzOLCdP44pIgPLvwWbGGeX9Wf1rCF585fwUV9yxmU0szDKwZx25D9DOheSVxNHBd/NgZBF7mgVxkIEpv3u5jQcoCgaLoHkZQI8/kFEaeus8PVnd79dGRriPZGgU++rQUEDN0g1ON0vtzTirqlAatVQG0VaWwLQ6ROR22LD0ECUTLwBsK0qyJ6/CDs1dsJBvxg+eEuKidCTgoYK0aCWEKkJsP+Si8eRzV/O3vAD5cNFwT0uiKE+CIsoo4tzkHo8Hq0ohWAwKjxA3m1YgR3P5UHRgB7sJypPbzUqRrzjxxglwAz4gTirFaiBIN+okFjyOBASEDRDXDbuPejrdw3ZxuSReeQtxsfbd3Pdac3cfdV2Z1KVl0for5RJzk1hF8RGf/WZDRBoDlo4cl1vYmyKYztUstNQw+QGm1GBQ82uemX1MTD0zew83Aaj63vg1+RuLhvGZtq4hiVWo+/PZb6/QG6HbNU2gQIG8fUDdGgMC2Pq3MaMSwW1u1oobTKZ2bL6xrnTx3B0mqJ24Zu4uJhFSzamcCCLelcN6kHH62vZtuBNhDsaEGRBk0lK6aGr56oJdY5mr8+tJN3tmqdsM2JlpPGJ9MjDM3thxtpbQmwrqCG0vp2shLc37dmoohxeBUcWYcuiQST8lHSRvDxvFt57+v9nDmmmMLaeCzvfUGW6OW9gefywZ29mfLeFO7Pj+PFl//De7tXY2n2Y7FaUTSNFtVAscsgynRGFgzQAMMf5LmNmVw9qpZJYxMY0juGbftaaPWFqagPkZxrxW0Jc26/CqZ1reaelf15+5JlNNbG8k1JKi9ty0M0YEiXOtaWxXOo3kO/klQa222cmV/OlPxSmlqi6Z+YS0ZCMytquuEpq8IjGIQEM6u7VBNJl3QEw7TK9YZEoFsafWKKEAwLC1abDAtR11BiuzN3m8TArqU8MG0vWw6nMjbHx5/fqmbwXUtJlzaz8NJCkqMUXtrcjbc3d6eq3cGGkhgm9RV4/vYM3r0t2cyLOAly8hbmSKzyvdWHQNMJtAd5/LOdPw48ixLoKkZCHtrQ6yBrLKeeNoukQVOo9okEC2u5tmo5F9duI7W2mNJmkBQ/V19xNqln3kPL6PtpSOpNVTBMvSagGCDJFoRI1rckiggRmvLV5/fDV6/x8YIK5GQbV56eZuYg6AY1jRrIBinuEBVtTjQd0txBNhRm8ffV/bh4SCGPnrKNywcUs/pgGtvKEzjU4uLi3iW8fN4q0l0Bbvx8LFur48iJacNwh9hcFkdWUxlRMuxRRK6ulTizEu5qkNAFEYcBBy0ppPaw4rQHCLYYLNvUCIhoBgwb2JNLZ/ajwWcjGLRQ3u7kui9GMq1rHY8Nf50vr1/MxKwKUiz1zL5oJUW3f8HdIw6yoy4eh+Hl04pBGCmjkDT/jwz+f1dOiiXrIPVtO9zAy5/vQnSYDRBem7eTqQMyOHt4thlG6dQ4AXQVqcck9EFXoGsKBFppaWmhoinAKek+sia6uK74ZixhlazRceRHFSFIMr52Dc3XjOBOQppwN2x+Hf3wGnTMdDBkC1pYRVN1EAVi45zcf2YvDhUO5sWvPuPiS4KcOSGR+1+y0twaprLWB7KTZKefJFcQzZDYV+fhwQnNzAxaQBdYVZzGvAOZPH/BKrbUxPLA2L2sK0+kxW9lZNcqbhQErp4/khsGH0RAoqDMzvnBcpaE4Zpag6CmIwrwTZtBjs3C4+4whe5senXxgxUKin0UlbabCSeijZb4gRiGn/J6B+fPmcAz07ex6JKvwFCpC7p4YP4wdraPwGrzwLJtXDf4IDeP2AOixLNr8plXOp6E5GZCysmxZCclJa6jtr6i6tx93iD+OX8XiAKv//nUzi4ehn60vbShqUhZwzCGXA1hP7JoYEgygijisgmAzuXDD/D87rMpbvDw2tgFiIaGzSpjtYqohoBohBENCWPkjViUdsLlOxBEGUODuGgHOUkedpU2UdXgJ+fGD8EShcsYR/Gu/XQdlMaYgbEsWFVLe1AAXaBrbBvPbuzLO7tz2VYex91LBnF2z3LqWjwMSG0yC2yEZMZmNZLgDNErrYmmNgdvbunJ0kOpHG6MYnhaI3rATVulBkozNzcIBCO9nXTMkk8ftBpcZ4XGpHRmJXpBlFm3q8EkQaLhjEkiodtgDld56Z4bxYJdAgv2TmfSIBfxUR52Vxrs39PAA9flIwgGD71Tx7ytGbgTBdrbVGhQefruHJbusdEaOLHs2IiLeeKVrKPSjCDAiB5JjOiRhGQRsVlkrp3S07yZSOZ4OGw+tGRzoPQ+GwIBCIXQNZOZYJEk2oMKHpvOA4uHMi6+gjmnFfLilp48MLoVEQWnVSDObUVrDaGFNRBCkHMWlO9BkiVCIY2zT83mmStH0Pf2eZTVtGJoBug+fI4+LN9bQO4Yg8kj4lmwqpbahgCGLmC3COTEtXHd4EPctmQgM7pX0hCw8dS6PkTZFEam11Pf7mJ/o4uP9nQhKdrPlvIkJnWt4v1z13L1F2NJcgSo8kVBXTtOI4xXlwEVQ+joTmPQFtZYq8iQGkeOpxIUiXU7j9b8CEtuuiS5SY6ys3pPFXEx8MZtk5kxJBtrpGTsOysKufJfy5k8LJvoKI37LxrC1af24usdZdz11jreXXWIA4W1TB+YeaKm3RBMiMQHJ1DJOpz5kKoRPCamphvwWIQd2yGCIKCpCqGIJVPkaGwxyaREWeiSGE96tINTBmSQmeChLahj6AZfFaextSCZZzf3wFAt3DJ0P8V1IZbu8fLB7dPYMmMAzf4gFQ1t1LaFmHP4VSpb/UhuJ++tKmLB1jLqvAEMDAb0SCYp2saSNTqri6O4zh9kVP8YAFp9KoJVI8nl54YhxZw1+CDv7+3KxOxaFhen8dTkrRTUx7C+IpFn5vTmq8IUkqKCPDl1Ox+dsxrsYe78ciTbKqNJS2hleVVX5BYvPSWDN5MN7q8XKQ+bicnRFokeVo0EiwMh1UmiM4DiFdh5oA0idOycvD6UNGms2VdMRXETbz9wGmcNz6a5PcTmimbG5Kdw+tAcumUnMO8vk9lxuJH89Gj8oTA2WaSyJURzyKyVcbKIGCeB6iPgD6udRX07AGdBgOK6EFXNCskxDjyGgqFrgMB5Z0zjmRcvQxIkmgM6Tb4wdc1tPDxnO6J/H2NzWnk+ajMPyP1pCNq5cXAhKXHtnNeznAde+4ChPVNJjk8nIdpDfnoiqSGJuWPuQqttRNBVQopObdCHbJVQgyqXjOvK8G7xLNlYy47aGNT6BvrlxxDllGhtaqamoS9vbOtKrd/O4SYHO6ujqPU5SHSGQNRJdwXoFtfKRxesYMrsqbwwYysOW5D1ZUkMza1mR20MUXYV7GHKWt3E+0sIGjDarvN6isH9DQLXRkMvO6RhsMWIwZUkgE3lSLHOkaoAQqSZWm5ONmePy2bdHoGlusB5I3LQdINF28uZs7aYL/+ajMMmE1Q0Ei55m9NH5uJ2WAirGpWNPsb1TmX7kUYQI52EgROB/JtFbn5Bl7gTIWbFHoNr/rOFQ4UbyE+qRZXiOFLrwettQxKhPG447y76ElWpQfCXYRdbKGu0suRwCm+etZO4GB99bTC6Sx1V9XZGd21GtgW5ZVgxmS4Vi7SesXE11AQdFBYkEAwZDOjajSNKPpLuQ5dE0wFCR46y8Nf3NiJiIHjcFJfGU1N1hJg4HXeUkw+rp7Lkicl0i2+ma5qP9bUJCLrBuNmT+Ou4fXSJayPOGqa0OYoJPUv54/AiUlxBqv0WYhwKskUjL8ZHczgEkkZFi5XYkBdRgGYd0kWDt5MNZCCIgaBBmSOB1HgVZDhQGiAUUpFEMESJbcEs1r27GV95PedM791JuX5i/i48kTbTmmKQEuPg9RvG0D0tmq4pUZ3jf7C6lTP/8Q0FNa3Yj2ly8d+f56O9T06qknVYs1eWHSFQ9j4rr9uHRdJAEzhUZ2XygkRiomx8cNECvtyXwv6DsfTqFuDywaWUNUQxtbeXRYe6EDAs7CqNRn9mNRfo5fx91zlkntqD4moLs/Jr8IaT8AkGaYqX+V9LuPKdjEhv4ot9KaiaFeTI8h06yhTV0MBtoDpSmP5IkEB8HlV9ziUzJ5aPz/qGkenVUNgCWU4C7ihmzp7ATR+O5e4EL2f3quaGwUW0Bxx8U5zMlspY/nrqDr49kMXpH46n+EgSD565BRDwhW0kqO3ogjn4KoABIcxKQCIG9c44+npCaIjsLzF52AIgOKO55JS+RMfG8sI8P/npMYAZQYmyW9hf0cLusib6ZcURCGt8sOYQS3dV8eQVw0iMcrCzpIH7PtiKHlTAKh9XmfFEyklVMrNmF+wrOcxTkw8gCxJBnxXdgG5dQky//lre35rC2Z/qDNyylqsPL2RjdAZxWbdyxeiDdIlpY3tFLDuaEnggaRWadzs9bAaxdXU8t24CibYGWhQrfRNa+fM3s3hl/6PcW7eI5ZsyuLDXIwgWjXE51eyrj8bQdS4bcQCnBE1BiRqfnW+PpBCIy2aP5w6wOxBCIo+OXM7IfjUcfqiM2g+PYM20M/jVgbxy+jaGViWBxcm7m7J5d0cOGTF+7BaV3kkN3P/VQOp8DvKTGmlqtxLv8AMioZCALWQqGcfllgpoggi6jtcZTW6sD8kSprTCzGIXdNCSevP88hpQDoJfJSfJzE7KTvKw/h+nk3HDR4y750vOHJlDUXkzsU4r10/Jp7S+nbaAgiSK3HPuABZvL2fHjgqkk+SUnRQl68g20iKJrhp2SrxOumQ1YwtbEWQd/CJ+ReCG4aU8tXY4F6hV9BbqiA81sL1rAaW+RJYfzqKm3cqH565jVK8gj15xOYsaBMZPsvDikDc58/2JyIKILIpcNeQwBf5e5Pja2ByTh9WmIaCx4tLlvLw9n6XluTx76TYIyiBDdYWHga8k4NMcJmc8HMLQJVI9CkrAtHh2K7hSrPg1B90SW+iV1ER21wl8sekAgfYQFTXR/GnCHl64cj0EHWCo4AxzxZvTsFsADLSwjkdQIrigucnXBBGLrpMYUglYYKWzD1FFAihhvtxRg2BxoKpB+qS5Of3cPrz51S5q/K2d7BWP3cK+8mZq6tqw2i0cqjH7j951Vn/2lzfzp+m9cdlkfCGVS55dQYM3CMfUjz2BM3/yUuIUzSCgaDgjjub+Sh9XrxvBu4495Mc209oGL23qwye7U/FYmyFUx8PpFzI/agxGtMSyS9ajGCrfHEzBp1qIopl5u6PJHK5TH3RgtXiZtz2GM7vuoz0kMSC5nvS4EKtSMnj30CUkJoqomyQEQ6chYGdWzmHuer2NC/Y4yXWG2OEVWC/0p02Pw+1poUt0AA2RQ1Vx7G2IZrJYTO4N2TSMzyCqmwNrjAq6wrC0Bhbt2M2o1Aaa/VDcEs2LG/thr99BotaAz8inXtWYX+zjmhtbQJMJhgwcgmqW1hTAEARiVJ16i41P0k5hXvJEiqQ4nv6sgaf9XRBjo7A46lF1kYOxw3liwQH0kAYCVDebhfP0iJ/rkURmjsolM97Fui1lnPH4N4iiwOzlB+ieFo3NItPYFqS+LdjZ5ucEzjyGYfjhJFmykKLitMpsPFjHn19bR217kKpwBmP/k0SC20dCbByFRxRG9k3g2inTWLarhDlrD7PF1oPEWBu3bMgj3u3G6XTi9nioFTy43DYcFpEkq0SbISFggKriNFTWtARpLfOhhBpxJ9WzqriNJF89mt2ChoxsaWPkkU+49ZCfGBtEN8HS+EYe//sULu+7h7RoBTWoU1Qfjd0eZkVBFk+s7M+RUAzWtSqTulRx/8QdPDJxFw+O20NsogK6QFWTg38vS+aZ+9YyN9pPkn07InDYC8olI0FyYkPBqqtoAgiGgEfT+TRpFM/nXk5lIAiFS5CrtkOgEV0xcUMFs8hyaP9CxKyhyAMuRBEkCsqbALPIcN8ucdxz+XA+WFHEc1eN4L0l+xnWO5U5d5xKIKR0smZbfGH63vYpFY2+n+1p/r8VQRRCcBKUTNMNol1WvtxSynmPf4MhiTS9fyXjH/iSnUU+GhqtnDIonTdvymPyg18xY0ASV0/I5vYZfbji6aX88fR+9M5JpT0YJhQK0xoI4QuGaQ+009ASRtHBr4DD6cQmGURJClnJ8cR1SyXamktxbZDX16zgmwN/5l89LiYgSMiWaJLTe5LQuB2HS6SqFW6d4eWeGVtQC3wEqg1sOR56Z9WypzyZKW9NRg1LEPIDEnsL89hYE8uqK5ZgtSo0LGhEsoukjY/nqVmFFC2MI7kySJxVJ0aCMapMayQVvC0sm/kMBjhEg4e7X867ydMQ9n6CY+98VIOjTR9kCXTNrD3riEKIy0WMSgE1gOyMZ+Oh+s6eUIYBw3ITuPuFlfxz/i7m3juV297ayDmPf81pw3NIjbFTXNvGCwv3UtnoQ7BInFi/38DQDTucBCWTRLMJ+x3vbEIJaySkOJm94gDbC+tMhqdDYOG2EgbmxOL3K7y6pJD7zh3IkG6JLHr0dPre+intvqBJlxAcoIYiiak6SBazcEigCeoOQEsJ9D4HWsqgfC0MuwYcsTxU8RYD2htJDLfg02z0ja5AUYqoDxskixp6spubL8lCLTfYd9s2wmVhUm/pSdr1abyypStq2ILF3s6t5w+ke2o0ry3Zy8bd8axvyGTYhlUcfPQwVg90fWE4UaMTGX1qPxpeqyLOAkEdZEUlFIq0w9FFdATcwLWpF/O1YyoUb8NoqCPQ/1ooWQlWF2QORYtJByVg5lU6EsAWA4imsgf9HNrlZeW+Kqb0z0DVDDxOC9gsfLKhhPdXH6K60YcRVFiw6hDRadHohkGbNwBWGcInFowVRQlBEBxwEpTMIok0tgZpCygYmk5qjJN1hbVMG5bN3rImKipa+M/tp7LjcAM0tFPfGkQUBAJhlewENzOHZjFnSRFWp45xaCGk9EZIzEas3YtUsxejvQ69tQbR5sZweqDsc4TK7QT7XoAem8TdJbO5qHYNXkkgOeSlXY0HWQC7DUP2EVZ10jIkuiRZMNo1PAMTaAs1IUVb0XU6lxRDN5g5pAvje6Vy/eQ8Ei7/FJQQYroHe1cHzkwHUrwdUdfIMI5gQ0cTwBAFRN0gEAhHmghAhtbE8wmjKZt8A4/3cVLdmk1D4FwaWv20+c4grEFQBXS1s8WhQzZwWwRiXFbS4j2kxDppbQlz/5zd9OuSSEqMjUE5CSQnurltZh9inBJXPfEt7gQXoeYA39w/jQ/XFPP8m+vJH9KFVneAkKL95Nz9b0QQhIi9PkmJJFaLRJTDwhPXTeLqU/KO+/ybHRXc/cZ6lj1xBsXVXvaUNUdSuMwl4LyROcxZWoSGCC3lCAeXontSMByxEG6FQCOEfSiSHUL1KPE9YOq/yLYK3F3wOFMbd9MoyyRoKpLfR1BJNI2BYdAa0MlywPJdPnJXBLhwipXc+3uA14AoCdQAVw0s4ZWt+agBB9Mf/JrXbj6FojqDcZkFTMipgLw4Bg4YYvafdBgEGsO88Gktj4vgUMBpGLSpYGkPgwCibPB4xuUsjOnJ2S4veWkp9M6JJ85jx2WTscgilkjbAU038yJ0Qzc3T2EdVVPw+hUaW4PEOupp2lzM9L83cPXUYZwxLIMHLxrMbW9s4IzRfdCtbtq8ImDh1W8KWLytgrGjuzLvvmlc8eIqfMEfLkn/35YTT7+OtAZ02WUMHd5YdoCSmlaqmv1IksjmQ/Xs2VPJWU8u5f7zBjLlr1+wbE8Vp/Y1M5sGZCdgcVtQNBBG3Qr+RuTCLxF99SjROWhpk8w6EB4Hekw2KQS5vHIB51Z9Q5waplkWEdExBLAZikkBFwUaBCtP2Fz0T7VRpoa46LVcPqrpw7V9dtA71U9ZoYP9DbFcOuAgiy9byqOrB3HA6+KeNz7jvN5H+PDcPby0vjdqSGNQVisWUWRPnZNXtvVnhy/Mv4QNDI6NJahrvKl4uUuxoRrgssG7UdN46uy1JLp2sGZTNCMS69kbdKLgIaA5qPPbccgC0faw2Z9AF9B0lRhLGyFVI8vTTrrNy9a6VIZmZHCoJcjf31vE3e/F4bJZQFNI9r/H4quaqfU5eXpdb97+rJDH/jiMv507CIC6lsD/O8xYM+9SQlENrn3kK26+YjiT+qahG/C3D7cwJj+FxrYgReXNvPFtIYKisa6wlol9UhEEgcQoO/EeO3WN7Yh6CEMPoxevQtPCIBcy6txkbLn5rDgUxcDWAl4peo7kkI9WGbyyiGToaIKIYEBYsCBJQMgge8pVvDRzE3GxJlPjqrnpvL0yHU0JM7S+nvp2Gy9t6kHfpCam9i1jclIVdZUy8bkSFlcIdIG3tmdT0tYbaWsrDU1+CFuJjg1w+N1o4h1DEC12LFaFMwvtvFkwGFlcSY84H5IYomZpNf0ObmV5wkhaL40jL6WFtzalkR7j5+nTV0DIzjs7u1PbZuemYcVExzbx4ILRfL0/jWFdaslPT2HNSpHLd3xITWwMD3e9Gn9Yx98W4u3zt3PFmH3gs4JNZVJmFVPmnsWfZg7onJOT2ffyxEMYkW6xDpvE038+lT9O7Yk/pOH1h3n84qHIksDCTSXEuWws3V2FYcDonsmdReUskT7fui+MrlnBW4WkhkGS0JUgz07ZxtBxpQz613Tu3P4+yYqPequMRdeQjmmMYAC6w4nLqqEFJXY2JbP4UHdSXK00qVYON7vBGWJjRRQHa12c3beM+8YVsLE6gVHZley6bQf6Pi/KFVkk3dwX0R9Etto5bbCbb7fXIls0BClMitvH4bYYSttiaY8AzSsrUvmkKJth37aw8FAymqzSc/MmhrcepkvdQfLfeBl7hg0xZDAgo4knV4xF8rYTfnkDqZqf68ZMoy0nk6+3p2CJga0709C+dTGy9WsmthWxJpxC7qBWGlQHNW02JmdXEWpxoGsSut9GRmIbeTGV7K0IMKqb6xc17vjfzrph1sp1wkms498eUPjLGxtYsKWUATkJ+EMqH6w5RFjRkBSNt26dSEqMg1kPLaaotIlQWGP6oEx8IYXWgMLwARlkpyew+s23qcFMbo2LsdM1J45Am50EfwO5wWpaZQGLrqJHvrsjxUw3oNnmwiMHCGpWjjTZueyt8SRnNnPv2L3cOryQ4mY3rUEbRe0yT6zszZl9Kqlss3Pn8AKyh9lpsEF8Xw82Tytri9LZUxnN5qpyCEQq64g6B+qjmPTGZJAiCQQQcUxVbvhkNKCRnNjK1jNPp35bIYVRqczo5SXR7efm4QcorvewoSERvd7CBF8pvYQW3q+ahJgr4IkN8ujlU1i87SDdjMVkJjl4es/NeO12ll+4kvM+HkdFbQI1gSjSMpvBZwe7SmOdncLmRLLiLMdlRZ1wMQwRToKShRSt0xrNGNGF+XdP6QyHDO+eSJTTypx1xdR5A/TNjOW+S4Zx45NLWfv8eQBUNflpbvYTiHcRDisI7R11T3V657qJS5Qoa7Uht4ZwoqAbAhbAJpoWtF0HUTAIC9DkiiPeXkmj145dhvvP3sjNIwtp8tnokujl04Js/jqqkPf2ZPH0V4NYUJSMFrQy7cNTuffMVLpe5udQyMLOlR7+sGg4gXYVoWYNd0xt5qxT7Fz+8VBKmqIxRB8EVASPzVyWDDO3UnIGMQyZtqCTkYMaiT01ltGSn7EZC9lYks7XBVnM6l3GeUMOsKM8jX9pN5IotHPfhBYm9PiC7cVpfFN0mIlRjYztUmFy/PMSEFUb//g6k51zX0NoFrlVS+TSi/PIdjRR2e7kxU39uW7WJDLirCiaiaudTDnhSuYLqXgcFiRRZGBOAu+sPIgoQEjR2VPayMfrDtPQ6OOOWX1Jj3chCdAtL5nR+cnohsGW4gYS3VYSY1zsOVBMVVU1FklA0QwG9YoCp0FFlRO3t5kUAapEEa9u8FKzSLIMd0apNGoGrYJMIDqKOFsxxe1R2AWNqwcV47aGuWL+KF6dvgWLZJDm8XHj0IMEwxYuHVrI8oOZPLy8H7vf8yCIApkeH5sPJfPArIO0H1jLM1+tYsb1/RjdL4ZzdqXz1FceTpuYxWUT8rnu5TX4ggqSbCatqIYMYR+0NTG//FJSm9tRFR/PblYQ1HrstOMsjiUvroWByXWcMiCBIy2xZDrLQZVYWpLEgkPp5GYNobA8lbjoKLrkOhmQEocYbOSVx9/F8AewJZ/PVuUi1jc3khgTywu3ZzE6L6azNNbJlpOA+OvEum1EOSw8/Po6Rg7P5uIxXYlyWcnPjOXTv0zigY+2UecNoGhmmaPbZ/SOVKsW+XxLKXFRdqYOzOKAcojDoVawSKBpDO8bDWiUt7nI8pbxng9e84nUazotioYoCtgFmatcKmVSNEKcA9ESoF1NoqYuhs8LM7hxwi4+PW81b27vzoe7sihudPHH4UU8OWUrjsQWkiwGE7JrKW12seRwCm/M2MysuRN46LT1HE4P8swLIit3K4ybYWVQShNIoBlmhUk9QrPQ/GHQDQSPE2H9C8jBKoZcs5L8rN7Ee+y4HVYssoVab5grX1zPmMzX+biwG09/1Q+0IP9e34UN13zFmzu788ItVzKhp5uN+6uoafFzsLqJ95YWsbe8Gc0eC4EQF45M5dpr+vzAbETq+Z9kPTsJGeSm8z6uVyp2DC47NY+LxnYH4Ownl2CTReqa/Ww7VM9Zw7K5ZGy3znP3lTexbk8VyTF2nl5QQN3uw0iYtfCtFomBPTygGlQ1OnB5q3iwCXyG2VxeFsxd1D/qDMo9cEpqIjHxBlhCbKuO5c1LVnHVsP28s74P68qSsIoGHofC7SMOUOO38ZelQ4hzhBmZUceUXkeo8PYg0aVQ1urGQEQNykg2Bxg6KzbX81Agg5HpDTjidZZsqmDJuiPIUXYIKjxx7Wi6p8VwzuNfIYRaaG33cd+T70FqfxBDuBxWuqdGs+OZs5jSL5pAKIggWHn/7xPZsH8/L31cxqHGGNJiLUzo6eb6l1fw7rxdYLeYraQdHvAWYm1rAEOnvsVnVo80zI57Tb4Qi7eVc+m4br9Jf+aTgpM5rBKn9k3joTe28tW+dl5dUUtlo4/iXUfYX9nCqB4JvLumlANVGvFxbuLdNqqbA3y8cjeZ8TaunpyPJtp4a987HMSkL3TPcpGbaQNFpaxKZFq4gppYeL3JJL3qmMC+ZkCrDiWOdHKSghjoHG5x8/meLuysjaVPUjP/mrIFT1SQivbJjMuqJTHBS6DNxYHGKFaUpDBv/hiWHkqhVZFZUpSC06EiiwYYKrIksq2ghaojCl0y2xmS0sg6fyq60Y7qN3fBu8uaqGz2I0gSFocHtb0erXQxYtdBGJoVX1hj594a9le0YpMlNF3gthE7OXvhWnxKAndO28uUnGr+usqC16dwuLYNyWNHdlnQkBC0MMbqdzC0SCKOaDYyq2kO4Qv5ufPtjXyxpJDAvVM5Z3g20U7rydhhdsoJVzKbReJIdStNbQGG9/TRJ/4wqe5VCNES64RU0roNZFh+OjsOfYVau4EcezPxWgA54CLd1ZsDJVE8On8PlpCXxi3LkSP+2PC+0VijRPw+O/5SP8lKEzfFCHzRLlAbNlvNhHUYHyXxRLTGg+50zk1uRgjL7G+MYlR2HY9O2o7d4+Ornd0YnN5IRpQPl1VjX1ky7+zO5ckZGxiQ2kB1wIFV7E+1z8Fzk7dyzaIREJaxSAIuh4S3XWHplhYu7xXHWXnlrNmfwhM3jOJgTTtvLt7Hh0sKQdORo50omsFoB8wwDvHo1jfxD7sBQQmCTcQiC9itEqouYLUL+I/sJ1Cqk36lgt0axtBCBBXz2TRNwzBsGKKMuPll9NY6ZKsNwqHOgjELt5Zy/YtrzOaqCW6uf/pbvhzXnfl/mWTueE9SibITvs3w2EVKSsP8e+5cNl6zkOsGlzIp18etw8pYdtM3nJ/wNM1772f7tR8x/4o9DEiFGl8G+UkiW/7wLQPTazh/dB8u6ydhhH0IkW6+E4bGgahxuD0aW1k9TsHALghcFwMIIk5R4M8JIq8mKEgC1CQkMzK5nvq6OAalNHNunzKuXzgCFIlpPSrYVpXAxztzeHJ9L2KdQZ48dTsIBruqEnhvRzcu6VdG30Qv8Q6VyjY7wZBOfLSV+BizXNNny2oRgjLn5ZdjjwqQGOUiyiGDpmPx2JA8NgxBBNlGmgiTY+2MrlyDvuE1JNmGITsxkJBQcdlUHlrYm3vX/octlQ+z7dVqFpZlk+EJY7NY8AfDYHUiGhrihhfRy7aYGfcRXFASzWm9ZlJPzh7bDTSzJ4DVaePecwYgSyKqbnCyqnueeMRfsiHU7uVv522jxXDw+rYc3tzRAwGDM3uW8fTUXcwadISXV3bhnxuGUlYRy8heZcRVxzA2s5rrhpfyxw8OQ+1SRMymo067zJgBMaAp7K2NIblmB1YJmnS42KXR2yoSJUK+rBPUDQ4L0dgy3GTENvH1nizyE9rpm1bHbZLC7uoEPtqTy5ayRHTRYG99LFd+Noaeia3M7FHOiIwG/tK9nNUF3REFDWdSE5nRIep9DjLj24n2mEq/fFMDJQdC5OSFubBvJdc8vBI8CqLbbnYp0Q0kySxVukkReKpFxO20klO1mpLVXsidjKDMoDkkkhQlkOgJUueOp7G9kbPTDtI1vg/VwRiONAZRsCK2FCPufhe1ufwYBTOVKxQKdY7/81ePZNmuClrq25l1ah4jeiSZEy8KnSTSE+2nnXgwVrZiHFrCwkUVTJk6ljeuW4P4lsDrG/OZf6ArXxzMJMXWRnp6Pp/dP5wnPt9HVngd/7pwF/XVsbyzM59Zww6x7YO11AAYOsP6xpKT5QAlwO5iBwNaSwmLZke5EDDIoqMBTbpIvGGwz55Dt1wVw+ZjXUUiAVWm2Oumut1JSYubC3uW8o/TtnDa26cx+/QN2Cwhtlcm8tWhdD4tyCHB7aesxcWeumjqg3bWlMTTEpTIdIp0SXWyY38L7X6FdxdX8/c+XbhtcCEf7clFF2SUQBhCGritGGYbMoZaDWY6VJpCCsPjJERjD96Du7lp1mI2tjvpcSbo3QZxS/ZdiO3tXDK4nouO7GR/YRljLr0d9dAKqC8hbKggiAjfafkcCJiM2VBYIS3OyQVju/Kf97dwwaicznREAKt8cvCyEw9haDpE23nliyZKmrdgFRVW24bQq3cCaS6Fb7dVUSfEsvWvo0mNdXPX6T0YfscAvizOoaJZJNgeT6+oTbTU1iHKErqqceaEZLAbtLa6KC9QOUerIyiZdb7gaKsYUQBJh52x+Zye24AQltlUHcfSvRloOlw/+CAzBhxi7uaeFDd78FiCtIcEvEEX7+/L4cWpm0E02NcQzW2Lh3Ck2cXNowsIhWUKG6Pp29tLboZZ50sUBN78rILbLsmif24Dl/Qv4a3l2cw4NYvLJ+Rz8b+WoRtgEWVEQSBBAtluQRMloqwyZf4wUlEBSgD+9oyT2x4dxYPTd9CqWAgpVs64Yy9R9Z+TKkKCDXBJNGsyXkOgJqRyrJp1OPUd5SHOGpbNfxbsZWB2wnEcspNVNvbkZCuJAoYOC1dWATJ9L7XQJ9NFTWMbAiBLKm1BjWTDoFdGDElJdnzEcPEpqcRH23nlvhfwKyCIBg67zMxxCRhqkC0NuXgOlpMg6jQiIkWGuuP9lNFpNERqu3RhcmYBrY3RrCpO5vpRB/j3aZvZVxNL2GfHIumkuv2Uex04LDo2WcEuabSoEjsrEqgM2Hh95hY+2teFayZvY+/bU9ldG815ok7PXDcAVqtIeY2f1+dV8Oebs3hw9C4+3Z5KTZPC3rIms+6YATGyQLJVYqNmY48vTKOi0h4K0xrWOC3ZRu8o+MAb4L7Bq4nv6wQNmgqCzG47RKsBgiRRGzSQDR3JJtKsmt18f2izKArm33tnxpKTFUd8lO37B50EOQn20gAt0m9RBDkpl8T0FGJsOuFIY3pBEHFYzDfcZbOQ6LETaveyvriB5avXY1RtN4vu6jqnDIuna64LQdVYsT+egTV7UCUziV/n6IZJFwRcOuywdCG5p524mAa+PpxOuMXFad1qOVAfw8cF2VgdISZmV/N5YRYbjyRz2ocTeX9fNg+M3U1MbBuGIOD1O2gNSVhEDfw20qP87G+MAcWgd1cz4KyoR1tN1xxWyUxr5aGp+9m2q4lH3tlgxlLNisIIuoZdD7PKG6YyxcG/PhpJ3JAECtrDaGgIYZj4VCxXvz+Tma+fRdc73TjDAmNirOiagRhr5bM5I/nnLT0YYRHIdQjHxSSPt2QGCR47g3PjsVukk1n0ulNOvJIZBmhmjQtVFxB89cQLjdjtTtNZDShM7pdOZoIL3TAwMOtlNLUGKSxvZ9vaNfjCOoZgtsy55sw0DFmjORjDwa0hhgRLaBfMpdIVSZg1qxUKWA1YnTCI0/o2gG4wvygDEYM99R7yulXyl5H7uP/r4dy3cgC6LuJxhrlpqFnd8fZvhvLnz8Zi6PDH0XsJaxJ762Pxtjs50uRmR00MtEv07GInMdaGpunIskB9U4i//LsIRCc3Dd3HxP51CNZoRNGs9VoXVljvN3ACV0SLyI1hRuU6efMvPVjabvDvWoMq3WBvSzbv7shk6aFk3DHRdNEMboiViNN0Hr2pG2MnJjDhYAPvxGq8kirhkES0iAYd6/gLggmLDMqJxyZLJ7MRSaecnOUyUgTXEGRsoWZyLYexeaKwSLWg68wamtV5qKLpBBUNVAGUViwVq9EFAV3T6NHFzbQxiQiKn6/Lu9Jj3z6SrTp1oozd0NgeEkiXDGJEA9EwqDVkKrr34PSc3TTUxvNpQSa6VWXevizio3308AQZktLIxJwaoqwqRS1Ozs4rxxnbzpWDDrK1LIkFRZm8sDWP0mYXRU1ukl1DGJ5TQ0mrk6LqKHpktdGnu4flm4KRnuYi7y2s4LTRCVx0URKvn7aOYdUzaPbLGJJOtk1kiF3Aa4gEBAG/V2HN1hYmnpLAlbMyeHtBBaeP8DD9SoM1NQexSQanzkhhTWoSl81rZPywBK46O43ALi9Ne5oQJfPlsosCwYhj1uH4A1Q1+4lz2RjTMwVF06lp8ZOZ4D4p094hJ2d7EQ6aptwwsFnBbreTGOXAZpFAEslONB9aiPynKhpnT+lHfstK1NZapEgf7ZvOz8QRI6FpVtZtchFftZVZ9SKXVgtcUiNzUZXA6pCERxJw6gYrnL3pNVgkKqaet/fmcsfwIi4ZfpDd1TH0jvIxKf8IZwwq4v4VA/msMIfsmCCKJrB8bzYXzZ3AkC61PHTaJj65cAWn5NTQM9HLo6duZ1bPCuySxrryeHDrjBoQG7l/OqtL3/jYPnZvCdC1q4/Zs9Zh6BLo0K6G8BmQS4h0m0CbplPTGEZTdV69L481s4cz/7V+lGnZRFnDJDoD7KxP4pV/5lP46SiWPt8fu1VAaw5DSEcyL3scrtqxXIZVnRmPfc3mQ/WM7ZlCYaWXi55dYU68KJwsLPbEK1lI0fj/tXfe4VGW2d//PG1mMsmkd0IIECT03qQjoCCCYsWKDQV7X3dVXOu6rrq7dnAtWJBiAZQOIsWC9BZKaCGk90x/2vvHMzMEBMTdJbvv/vxeV64Q5qn3febc5z7le1DDZGsGmiBRq8eSnRSFwyaBYRKMcJdaPGSCbCM/fxdVWxYiiAKarpOZEsV1YzMxAx7WlGfj+q6AGl89mzwCO70qm7wagqkzo86kyBCRTViV3Y8buh4Gv8Kr68+hf/NKbup8gCn99jKgRRnPLO+J7o7ib6N+YFSrIywrSKdBtTGkVTH39NqNqovM3dCWFfuacUevPZzbvAbFrnHrZ4OQJdhekQCqydCeCYCAbpghF4FAvVtl3D0bKcg3GNv3CC+e/xN6QKJWVdkbNNmkSuwJgG6arPyhCilKwm4TGDA4CdHmYOWSLdzcaR9Dk3aw9KM5uP122nZzITtEiFbw7qrG8JkIIqFyjWMIC5lNFlk+dTT989Lw+DW6tkxk0WMXWDNhmE0WxhQbP9TZQJibzLqDSXaajWinSFZiDKmxDghobD5YFfrUYoOR7E7y1yyjotaNKFkdNR68PoeEVBuCKTJ7bTLDD68mJ8aKTyqCgCyCTRTY6zf5sMYg39YMe680emQd4vt92Xh9NjIS3FT5bLRL9mBKOjd2KQAEvtqTzc0L+lHvUbh3aU+WHmhG72ZVKI4gvZpV0TzBQ2GtE6eigWky57ol3N1rNwv3Z2LWSfTpEEOztKhIm2gj1JX4ULGXkbeuZ+8ugwfHHuCxjjNJqzzK+CSFFrJJrmQwKMHGOwuO8uLrh9hTrbF+Wz1X3reb8vUL6NGqji6Zbo5s38uaqbuoW1WGrzRIzYIjlM06gOQ8wQ0R+rfXa3HBmiYkuRwUVroZ8NgCKur9uBxN14kkDFkHxLOYxBaWXzFEMNIt10ZirImqi5appkjM+f4gD1/c2UqmkxWk2kMIBxchyxKaptOqeTSTrsiCgIe15a1g+T46Uc1hRDTTQBZAMyyGHKcs0lvRmJMxhBv6lYAYZOraDuQm19OrTSG7SjtSUO3Ea4p8W5jGd0XJtEmo46mhm8ga52NjcQLz8lswbX1buqTXML5dIZ1yi1i9ozVlHgc6AjN+aMesnS0oqnOyuSiB7u1rGdY7iY8WeBFFMPQQ74cscvCol9G3bWTVh7156lo4siWNRxaWMDhWZohTZIDdZFiigWfabr797BByUCWrMEj02GxMWSEpTWRE7zTMhUcp/v4oAYeI6TEQFI7tck7QEWpo5QhzwTVLjObLR0aQEutAN01EhCbdAJxFwz/09qZhVUGbAAI7CjwkVugW8YpugkNm24FKthysolduCpqmov34DqbqQbDJmJrJn+5qQ3SchBFUmLE0iUsPf06tInCOCM3tIkcCJsmKwLVxAuOdBh4pmco+uVyUu4r8A80RBYEruxVw80fDWbw3g9qgQklDFH0yy3ly0DaSm/vBK0FAoH/navp3LqfyaBRf5mfx9LedCKzqwr6qGHaXx1LS4ODKDoeYc81KZqzPY+7uLLp3ruTioal8uOBIJDgNoOsmiiyyv8jD5XdvYeWM3rz/165kNXPywXuHiBGgs6IjW60FcPmDDLWreBIl+g1NAU1HUQQuvCST1zZX8apTxx80EJ2W9IRvZbXMOSZtjVcmQbCWzRYhu9dqgw0NAe1/h2nRErJwzr3J7lKR4q0ZTLpRRws5j8yAxtZDlpC5a2qoPVpgZVEENS44N4XLLsyAYD1z93cmcclG8oR6KhBJEgzeTxPYpUl0kHWyFQGnanB3xvncPLgUUfYxY0dLnh2ylTbNK7jsgxxaxPj528D1jDqnhOh0FaokPphRzacLi6msDdKvczwTxmTSr5uNW84v4JaGAjYcSOTrgiwW0II9FbG0S64nxoTbuxdw9bxz0SplRvSNIzMliuIKn9VmOiQAWkjQfthew4R7tzD31S488/u2uJJsPPPnPQxMlZFkAZuq0VLS8JkCX6kSj2U5EUQwAwYDOsXyjCzjUXWrx+UJ/AKioSEaAqZw6uk0TRPNMK1ia3eAgoNVRNubxrnQBHcRIi4MAZOAkkypN4n4KJAlCTnaTtuseMrrrW232+slqOkIgonTofD3R/MwjSBlwRS++Fzmoco11NkEFNMgAKSJJi3sGl4EgprBejETfVAbxuZ+Q0lJGm/+mEuV20Hszhwe6Lud8/OKwSVi1EjM+KiGv844yOb8usjTbthZy2ufHmZwzySuGZPJ2MHJ9OxQT89OW5k6ZDtrD6Uwa1sOH2xrRb3Pztwd2TzWbxud2rkZPzyd12YetPpmNuptHha0ed+WMeG+bXz0YicemdKSnq1iGP/YTroVe5maI2MzdbymyR2OID99sJ9Oj7UnPlnhD4/nc5XhJ1rGKhQOX/cUIy6Kx5s/JqCHkkcrGvxc8MdFBGu82OSzx7TYGGdRyMLGmGRxVmBttW12J/a4KBb8VMgPu8uIipKpcwdIirFSZkzDwDQNDANevO8c2rRxgV7Hu2s6MGjtIuIVnVpTQArdQQUCpkXBFG2YfHTORfxu2CEExc/vVw2kZ3otk3rtomdWDcRKBCpszF5Qzt8+PMTGXbXWIIRsUhPLdtR0k1U/VbLqp0oeT3Zw0ZA0rrwgnSHdYxnQrYoBHUupKXew/HAa6w8n8fHOlvwpbwPXX5jJm7MOo5+EySQsaHNXlFJzu8Z7z3XkvDFpbM1x8tKfdrNrfRkXJINPFOgSa1K0uphOV3nIyXBw/q4yrkuFWg3cBmxQZVRBpIeskiE1WjZD7xAdHR25r26YkSTGud8d4OEPfuT8blkcLKvHG/gfqSA/EVrAh2QazPvpMDsPVZGY4KSotJ6+bawUFFd0FLpqcveEbCZfmwNaNR/t7obzg9WMUPdRrYgojbIOBABBJNkwmBPVmawL0hiYs4xNe5pT75dYPmUJOCTqjkrMmlvGG58eZusei71QlsTQt9zybVnUANbWXpJEEKC00s/0uYeZPvcwXfPiuGxkBpcMS6V9HlzeopDzWlVz+1e9aCi30au7g0E9E/lmfSWyLFo2Z+N3DwnaivWV9L/2R/7+u3ZcPC6dV9/qzgv/OMyLH+7nEn+ANvEwMk1kW0kd7qN1TGguUK2biECMCOfadQwMbFhxS5HjfVHhwLimGzhkmaBmcPubq1mzo4RpdwxieOdm/Li/0nJ6NwGa1OMvCAKir5LsKD+IMlHRCm6/Ste8NDq2SATAIyYy+vbb+Nutu0CvZ3VpWxqm72Vc5XZEh0icYaXzGOax8JECVJg2vug2lpn9t4Mh8sWhPH43pJCjJT6mz67lowVH2H/E4l89UbgkUUBr1HA0rNmMRp/rhsmW3XVs2V3HM2/vY0S/ZK4clcXYIQF6ZVSxrjCd83sVc9dV2XyzvvKkLRbBEjRZFjlS6uOSezdxzbJMnrkzl0ceaM3OYSlMf30/69YUc75s8FwG+ASR0oBBeGETgKjQm1vVDNYk2huR2nk8HgQBHHYba3aVMvnN1fRtm8a2164gSpHQDRNfUD/r/GRhNAHTogB2O0Io9hglBLllQAZzClQSo+2UNwS4dmBupFSrqFbDlZ4KrnUs3NWV26bnct6mL9miGmToNjZ7NKpMkddTdDAMdEEgRTd4MPVirh7rJjuhkuoShQWzVrDVXsrq749Q57GWBVm2SFxOJlytmseQk+1iW34tldXhsIyAIguhRg6WdhMF8AcMFqwqY8GqMtKS7AhKPuOHp3NBlxZcODiJLm3j2La3DkkUT7p06roZed+Pvy7m69UVPHhDSx69uQV/fasri5c1Y9aMQyRtLmeAYJATC7ok4DMswT9lwVFIymqqq/CpBg++s5avNhzhLzf34/JzWwFE6i7/R1wYIQgi2OJRTQNJkjEcsWwuF3B7/cQ6bdT5NHq0To4c7vX52H3U4JWfBrPoI4l7N/6JByvqABFqrUC7JEGhJpArW0yF8+x5NIzsyuQOi0GK4Ym3drF1zWG2hq6pyCKGcWxyRVGItErukBvHPde04KYxCUhJInp5gDnf1PPOvHJW/VSFGurbLYUmxhLQkHFtQllVAAjw8ZcNPHptGlnnOPndxBwmPLqV0yEse7IsUtug8thre5mxoJjf39KSG67M4oKhySxeWcmSz4uQN1bQ1RMkLwrioiAoCgSMY177sA4WQx19l676noG/m8c5GS5+euVSUmMdaLqBJIr/m3WXhhpAaD+WVLGUsiP78cjJfFdkYjeDREfZCGr6ceQfDinIT4XpxL9WzF+OvEeNHMApywR1zYpsCqDrOg9XyHycBm4hije6XMNnIzcgxigsW1bJ67MLkWUJsLhUNd1EkgQEg4jm6tkxgTsnZHPD6ARIkSkoSmTt+hQSog0uuayCq65K4+C2et79qoaZS8rYX9gQeUZFFjHMY8upLInUuXWmfX6Upx5qw/iRqfT4MJ6Nu2qRpZNrszB03bqGKArsPexm4uPbee3TIzx6cw7jL8rggpEpbNtSz4plZWxcV07y4XraBnWa2yDGYTXnVUQRSRYxQr2SLr7oQh65eyAdW1hfXj0UgYAm7W8fwVkXsgavj27d27Pwk5946bkneWPZQWRJxFBN4pw2NN1kza5SBrVLB8AtRdHdvZ0PC9+iTIAkWaStHbZ6QBZBNS07bHdAwKeb/LHFRKZcUkHbtHKqSx3c9sxOq0FMiKxXCjl9w70dB/VM5u6rs7l0RBzES2wrTOHTj5KpXllJUvle/KLM4hap5AxM5YJ+bp5+ooqn78pgyeo6ps+rZNG6SrxeS6OGl1zDMBEEgbfmHuHOq7JIzXbw9OTWjL5r4xmNkWmGtaylLTfsrOXS+7fQ+73D3DWhOdeOTqfzo+dgVrfih+31bPm+ii1bqok+7CZX1yioD3LYZ9C1Sxf++NRTjB07FrCyksXTaK+mkrcmaHQv4JQN0pIT+PPLf2Pn88vYsK8ch03CoUg47TLvfbOXh8Z1wiZLaIJIK18xPlPAL4gkCgZ2ScQAgoZVANHFKTPJGWRW4gW4RmUzpeNXIMRx17NbOHjUiyKLkUxUTbNKyC4cnM4912QzYmA0REtsOJTKJ/NTKVtdx+g98+kbPIwcGg1PCezckMknszszrXtLup0rMm5IFXPHVlFbUM8HC2t5/+tytuTXhtq7gMMmUVEd4G8fH+HZR9pwwdBkxgxK46vVZSfdaZ4MRqhMTQppnfXba7huew1/fOsAl45IZfzQFPp1jKVf/ySLCLmohstv30RNbEf+8eIdXHvNtdhsNnTdQBCFyHUaIyxukigQFepIcrYX0CZh9VH1cLsbwyqKxVoioh0y8dE29hdWs6Owhu6tkjFNcIpWfEAULG10lVOjLiDSwgbXx4sMk4N8Yz+HJf1G88OwBRATw7szjvDJomIcdgl/wLKjbIrEJSMyuHdCFn37OkGRWL0/nTmrk9G/LWLIgTl0N45iylBnPzYhomzSxSymZ1ExJYU2flrejkdbdSK6V0dG9vNxz+Qy7rk1nc0/1TNtXhWfraygosraLPz148PcckkmLdvF8MI9uSz/sRJVNSJxxDNB2KMvSVYD2IJCNy/8w80L7xaS0yyK7BSBrGSRKy4dwVv/mE9ep0EoIYHRdR1J+mUnqygITUa80jTNIgRrlylJEk6bgiBaPclVzaBHq2SykqLZHhIyhyJRJzuJMgxMWcZrGFwQZTA8CmRBwGbo7BViuS/vVr68+DsSkjR2bNG4/+XdCAL4AzrRUTJXjsrk7qub06WHA0yJRXubMe/bBOTVBxheuITOZjmaDA2SCKaV5Bh5XhO8CBiKQCxBLgpsZdT2rezemcyaBV35JK8trfq2Znzvat58sZQ3ymuYvbyWdxZUsfyHKiY8uoN1M7rSvnMcD1yXw7Pv7D9jbdYYpmlRq9tsEmpQxTQ1DhU14DdbMWz8HfS9dDJpyVYhi67r1tJ4BgIWuf6vepp/Hk3GTxaGQ5GsdBjTxDBNYqNsVtp16I1dZoC1cV1Z4VrLQO9haiWRhpDD0W8IxJs69zS/lccvK6JP9hG8DbFMeOQ76hpUYpw2rh3bjPuuyeKcznYImCzYmsXna5JwrSvgoqL55FFFwAbVyJHAsigI2DEs2yjsfxMIsTOK+EQRwQ5tzEo6Vy+nds1yNqw/h1czuuPu3IkB/VSuuKiUK68sp2x/La9+qfLIgjb85ap9PHBjK2Z8XcaREg+SdMx+A37mSxMEAVEUI7n5mqZFluOEhARGjBjOhAkTuHD0aBSbVRRiGDqCKP0q4WpqNElT1cZj6bRbeeZ2WcKhyKzbU8bRCjd/vLIHAJKuUheTwkP9/8S5mz7l0eJ5JNis8FG8CQ8lX0Kfi11M6b0Q9ETuemIjBwvreOj65tx7bRaZ7ZzgEVi4PpOXfmhHyg87mFz0Pu3MatySdZ0oFexYQXsZ8Jtw2JCxySIum4hiatgMDVk3UUwTwbSYrIMi1EgipgyDjL2MOryXokIHS1Z159acbiT0aMXVvct45sFC3l2j8Po3bbljbD5vPZzN2Pt2hciWzYjgSJIU0iZWtophGJHPwBKsc889l/HjxzNq1CgyMjIin4U1lyj+9wpXGLJhmqHF69+LsGB5A9px6S92RUISRARRwCaL1LgDNEuJoWO2lcKsmnBR9wymTxnCO+v78+6nPejy7fsk200+cg2hckB7vj3/K1bmt+axpT05Uu9i1tt1DOqewJEqgbkLE/hgSzab9iSCIpEQ14m1jhag6yRFSaTqDbT1FJLnKyJObaBGiGFF1gCErgM4VF5H/v4y0mNEXGYAl+omLVhDi0AFuYESWnqKyA5WEG/oaAJssccTVDUmeb9j8tbv2LwrlSnf34mY2wk7QXaUJ2GIAv4oB0qqjr98DwBxcfEE1SA+rzcSbwRISkwkr107evfuzaBBg+jbty/p6emRsdN1y9b8tcvifxqyTZGjQw/cJMxVcdE2YhxyRPAM0+SaAa0jRqgkCMRF20mKsfHIsOYw7HH+9NWlTHpnHdhjaVNdxMB3LmDtgTSr2KTZGK5aoRP8OkhQk8AvE5cSxSv3t+e8ThnExsWy7Ug9by/N5+vV+8EmszzhXDB1MDSQFX58aTy9Mx3sq/Dy1YYjPPD+j1bVf7QEkmyNTCCAXQqS5i4hp6qABkNG7jeMLm0ymTpvIf3q8imyJ1ASE4+3JMbizMLP3fP6Wt7jTllc1C2Kv08aTHpGM3QtyPLVPzD+mfmM7JHD1OuH0ap1LmmpKceNV1i7SdJ/95J4OjR5gFwWBVxRCqW1PhAgIcbOBd2yjjsmqFpLRnGNl5nf7GHZlqMWD5dZxVElg31lKihBbNECHbMS2VRQBYbI8B6Z1Lp9/GPKYDrnJLOnuI6l3xfQKt3FV/cPZHavDK59aTmCZLX9M00Tmxpk6479fLnSw3vztvGXuwbz7m19uPGFpWCXOScrnop6P1Mn9sAUJVRRYcOhOjIxeWp8e9qkxfB4dgbTluwlJTkaV2kFgttLfIyDDs0zWbGpED2ocsXobsy6fygz1hxm/apdiKLEM9dfxLSErkxbtpt+/foBx/qxh+2z8M//z2hyIZNEEYdNwq/q+AIayS4HGYnOyOcev4pdkfAFdQY8Op+De8pAEhg5uA1un8rkC9rx4rytpMWlEB9tp1lSNC3TYimu9nL1gFyWbz9K55xkK6V7xo9c0CWLO6d/R8/Wyaz788UcqfXx4BurkVwWEYrfNJn0yreEStm54a+rWPzkaHp1y6ZrThJHqzy8NaUzA9ulRbzmjRFUdZ4el8fTF7UBUaKgpI7P1x/GLoscrnCz4tsCOnbKZNb9Qxn37CIqGvw8d20fJr+xmpLqOuY8NIJpX21gf2kdrdKsDruy3OTTclbR5G8TZZOQRIHyCjdqmxRUzYhoLgDVMEmNi+LbnSVU1/vp2jMbmyhw3eA27DxSQ+u0WPq0SaNFios6bxBvUOO8Ts34amMh1e4AhRVWpoUvqNEuK543bx/AkM6ZXDVlFpNaJTPt9gG8unAnh4vrEG2ylbEbY7P8RrKIv6SeQ+Vu/nRtL7q0SMLEqsCOVKaHdsL+oIZdkbCF/FOGYLlCcjPiuPfCjviDGos2FzF0QGseuqQLry7cyfyZG9mz9C58QZ0ESeLOCy3KTc0Ap12JpOj8r6HJ9bAJVteMgEZQM6j1BFibXxr5POw/S4yx49MNNM1AkiV2HakhqOocqfKwo7CG0lov89YfZv2+Ct5amg/Anz7fwsaCcu555zvG98lh1v3n4Q/qLNxQSPfBuXy8poCKej8TBrQGvxpipraaWQiCgL/Kw8D+rbioZzbDOmaS5LKT7HJEcswg1DNIsHp4PvrJBi554msmT1sXCU4bpolNFol12riyfyt6tEmhfVY8by/bzeBRHbhz+jpiHDIrXh5Pm/Q4xj63hG6tkslIcFr3+Q9UeJ9tNLkmC6gGKbEOUHXio21E2WXeXLqbW0bkWcmCokBQN+jdJoVL+uQwa/EuME2+31IEkoASZUMQBb7fVRoKZuogCmw7XG2lNgQ0/v75Ft75Zi/926axp7iOwn3lHPz0Jm55YzVr8kvp0So5kgYhAFGSiCqYPDF5IA+M64IYzrawyCsisT9Nt6IVhglxThtbD1ax7Ju92DLjeHBcJ3JSrHbNYXK5oKpz9+gObDlYRecWiXxy71D+umA7U95eC0CDN8jQzs14akJPDJPQ/ZoGTSnLTS5khmmiGQZE27hhSBt2FNawuaCc4moPzRKj8QW1yKR+ev8w7hrVnnW7yygoa2BXUQ3r95YT9ASJdjnwBDQS4p3U1PuIi1Ko86lcMrgNX284zKiuWczfWMgtw9qyFCiscNMuK56KOj8pcQ6k2CjssohXN6it9zP7dyO5rF/LkJPYelY94rMykSQRWRIIT09A1bn9/HZ8fO9Q9hbX0eBVI89txU2t0FlmgpNVO4rJDNmd917UiXsv6kRpjZeEGLtVRd+ECDuC/aGYblOgyYXM41et1JNoGx2zE8lMdFLnCVJYaQmZqpmR8IuqmfRvl07/dsd8RXuK6xj37GLO69qc3UdrGd83h+nLdvPwxV3469c7uG5wLjZF5Kr+rchOiSE3I5ZWGbHkF9WSFu+MuE4km2Qtl94gQ/vkcFm/lqiaResuRGTp2CT4ghoPf/gTWQlR5GUlkJHopO85qeiGSdtmcVS7A6zZVUKCy0HH5gnW7jDk4W+dHsuD7/9IenwUuemx5DWLJ69ZvPWOuoEsNm0SYfi+TXXLJheyoKrjDWqIQI07gKYb2G1SpLJZECDaIYf+baIbofBLKMLcNjOOV28bwIvztnFe50z2FddxzaBcDlU0cN+YjizcdITrBuXyxfrDjOqWxZItRQxol05FXah6OuT9NA1LY5mqzqiuWRF+e0GAep/KjJV72F1chy+o071lEud3b06MQ2bl5iJeW5JPUXkDqDpClILTLhNtV4hXJAZ1zeLt2/qz43A1pgldWiaRmx5Hab2Ph95eB3YZGvw0b5HIY1f0YNLIvCaLITbG/9xy2fiFDKDOo5IQbefTdQf4dnsxOelxnJMZB4A3qB3XIs9agsLLkKUZBrdL58lZm8hIcLJqZwlDOmTw4eoCJo9sx/vf7CMn1UW9N0hmQjR+1SA2SuFIpZuUqCiiHTK13iCSJOJr8DN66DncO6YjhmnZXg0+laFTvyYjxk6vUCOxJ2Zu5M7XVzNlXGeeu7Ev2ckx1HmDFFd7cNoVUuMcNE+Koc4X5JNvC2h16yc4nTaibTKJLjvTpwwixeVg7NC2eIIayVEKLTPjeG/5blbtKuHDu4cgCGdmk5mmGYl5hn+H453/bjS+lxDa2PwzOOu7S8MwcTYqInX7VFTdQBQFCkrqMDSDy/u1jPCX6oZ5XBiqMcIhGJsikRBjx6FYOWkOm0ytJxiycUTqfSom4LTLoXIwEb9qoOoGkiBSXO0BzcAA7h7dIZK9KgoCmw9W0SYjlksH5fLJF9vITo7hyDtXc8P57Xnj45/oOWkmne77jImvfUu3lsn0bJ1MdnIMk6etpfmNH3HHn5Yyvn9r/nxDH1olRXOgtJ53v9lLaryT1btK+MeUgUwc2Y7ctFi+//PFCMD05bsRBeG0GbSRMWjkpA1HAQRBQNP+/eVtje/1rwhxE6X6HHvAGk+QqgY/AH5VR7bLjOl5jJ9MFCDGfmpSEDO0riW77DT4VDITo/EEVBRJxK/qJLscHK32oIQMdTOkoSRRwBvQyEgQOVjegL/KTULzBHq2TrEqfiTLR5XXLA5FEtl9uBq3TWLRpiPcMKQN7989mKsHt+ZPc7fwzfcHGNYpE1eUwuzvDpAYbeNojZfOzRN48P5hXNInh1vfXMPsz7eQ0iEDl0PB7Q9y75hOrN5VymMzN2AXBIprfUy9sjtPz9nM7SPbndZHFtYod911FwUFBSiKgt1uZWKUl5fTv39/nn/++TPOJzsVwgF6URSpqKigvr4eRVGIi4sjNjb2OO15pmh6m0zTqaz3Y5Mtr35CjJ3s5GPFqJ6AdkYNP9PjnVTU+4lzKlS7g8REKZTX+YmPtlHVECDaoWCYZsTBqRsmFfV+WqfFcrTaYr2598KOJLnskQJY04TUuCj+cFk3Pli2myeu6cWNQ8/BMK3NyMguWcz9/hDfGFDrCfKHj37i9aX5JNlluuem8OHDw2mV6kLVDF6e2Je2zeKo9wS5ZXhbpi/fzZjuzbnqlZVc3DuHP1zalYPlDdwx/TuGd84MvdXx4ePGqUC6brWwOeecc3j99dd/Nh6PPPLISc87Uw0UXhrDwmOaJtOnT+exxx7DZrPx7LPP8sADD0SuZxjGGS+hTe6MNUzLsAZrE+BTdVStkcdfM3/G9XAcQi/VLNFJtTuAQ5Go9waJc9qoqPchiSL+oG7lY+lGhKs+qBlUNQQibIPEOri4d4ufXdo0IS8zjudv6MNtI/KwhcroFFlk1roDzP7uAFvfv45hnTLZsq+c567pxfbXr6R9dgLjX1iOFiracEUpPDi2M09N6IkiiWQlRaObJgWl9fxjxR6mTFvHpNdWkxht485RHSyNGwpb6boeiV+Gf8IpQtdccw0JCQlIkoTD4UCWZbp168aoUaMiWRqNzwtf63QwQ19GURQpKipi//79CILANddcgyRJBAKBSN3A3r17KS4u/lVLaJNrMtM0LWI8rO+tu97PlkPVtE634naSKOC0Ny5lPR7h/8lIcLL1cDUpsQ78mk5CjI3SWl/EgI9z2vAFdXTDCJHsmbj9KpphUlTlJdppI9llUSM0VpyCYPnyDMPa0UqhynIT6NoyiZapLmQRHhzbiQfHdoqcN6xLM1buLA1pRBNMq6ZTEKCkxkuSy8Geo3V0aJ7Alw+PYE9xHWkhl0bjsTEhstwFAgG8Xi8xMTEoimVCJCYm0r17d1auXAmApmlMnjzZGrvQeaqq4na7cTqdkSXVMIxTLnGiIFBRUcGdd97JwoUL0TSNgQMHMn36dHr16oXL5SI+Pp7+/fuzYcMG7HY7I0eO5LXXXiM9Pf2014b/gCYTEHDaZXTDwBfUQNP5cv2hY58LltY45fkhgchMdNLgs4LphmFl2FY3+C26ASDeaSOgGgR1g4Cq4w/qeAMaqmZQ3WA5ZFPiHMdfNARRsDYLcuhaYkiTtM2MY/XTY0iLc6IZlqYMa+FHPlzP5ee2tOogQ+Ehy98mcLjCjd0mcai8gZQYO8mxDvrnpZGbHhsp0QtrE0EQ+OKLLxg/fjzt2rUjLy+Pjh07MnnyZAoKLLajK6+8EtM0CQaDpKSkcOmllyKKIlu3buXGG2+kffv25OXl0a5dOy6//HKWLFmCKFoa+aSGnwATJ05k9uzZeDwe/H4/y5Yto2/fvhw6dIiamhoGDhzId999FxHgzz77jOuvv/64JMtToelTfSSBuCgFVTfxBDRQJDbsr7SWmZBKOe1qSXi5jMYTsKID/qBORoKTWm+QaJuVq2ZgRoQqECrQNUyTgKZh+lXS4pwoknhch44wwkHwsG1T71NJjLE0givq2KbENC0td7jCTVmdn+sG51qUnnBch9wD5Q0cKm3gQEk96zYW0rPaQ4fMeO4c05FeuSkR+8btdnPDDTfw+eefH/c85eXl7N27lzlz5vDll18yceJEXnjhBfbv3895551HYmIiH3zwAbfffjt+v/+4cw8ePMjcuXOZNGkSr7/+urVbDNtVIU6R/fsPsHTp0ogmDNtmpaVWTLmkpMSaO1mOLOOSJLF8+XL2799PmzZtTq8pTz2dZweyLCJLIgFNp96rgiBQ5wviDtlpAVU/vb8o9FF6fBSaZuALaAQ1nUSXnVp3ELsigmAJXkDTEbDy08K8tKYJBHVS46wCjLC7JMyNAZbmCrs+ZElkX0k9T3y6kaVbi447J/x79a4S2mbGkRBtRxJDVUAm3P7WGj5dXcCSrUWsWbufxBg7O965mtcnDaBf2zQuf2EZs787YAXWDZOrr76azz//HJvNhizLSJIUcVXYbDaqqqoYO3Ysbrebu+66C4Bx48axa9cuJk6cSCAQwGazHXeeoigoisK0adO4++67Q5Xvx3+Lw0Z/Y0P+WHr3MXdJ4/8Ln3dGc35GR/0boYgiPtViXvQFNTAt3qywnyyoGcRHW1rjZLImYE2uXZGIiZLxBLWIBnMHVDITnNR5AwQ0I0LXbnKsj5BhAppBTCiqYDa6bjj2WFBSx7bD1Rwoa+BotQe/arDtcDVPv/cDf717MHdf2DFEQmztBtfml9E+Kx6AFduOsnpXCQWlDXy7q4S3v9wGokCnbll8ev8w7nznOzbsKObNe4by9dRRTPz7N1xxbis++2wOCxYswGazReg4wwgb/YqiUFNTw6233sq5554LWDbZpEmTAEvTND43fJ4gCCiKwptvvsktN99M9x49MHQdMUSEk9u6FcOHD2fJkiWnnLewIDbeRIwYMYLWrVv/ok0mg96kDTY1w6CyxktsjJ1aTwBUnZyUmIjD9ky83oZhIkoCzZNj8Po1Smq82GSRgGoQ67RRVufDG1Dx+FUCmmWT2WSROKfNEqRG30Br8ARqvUHeXLSTd5bmU1rvR5BEvJVua1dgAnYZ0anw7GdbuPm8tsQ4lMiyvnZ3GYdK6liytYhdBZVWdohmgCRiT3QSrPTw+8u68uTsTdT7VN64awg17gD989JwRdnQgU9nfhyym06tHTRNQxRFPvvsMxYsWIAgCNx+++0hFp9TO2SPee1h1uzZlpA1vo8g8NFHHzF16lSWL19OdXU1Xq830g8gvLuNi4sjKSmJuLg4BgwYwGOPPXbKZ5YlObJOyui/zrH2r8I0gYCG3yFbwq0bXNA16xfPOw4hQeyUncBXG49Q51UxMPEHNWKjFAzDYt0OagaabtlkdkUiyiZhl0UIUUcBEX4NWRTomZuCIol8uu4Amw9UQpQNxSFjGiaKLOGr9nDr5XlEOxSCmoFNFvl+bzl1ngCX9m/F6vxSCGqkpiTg13Qa3AEM3USIUshJcfHU7M10yIpnQHsr4P/y/O0oiowI7N13IKJ1Tj9+lr0UDAYRBAGPx/OLwhk+zzRh9+7dwPFfZsOE5ORkXn/9dTRNo7i4mCFDhnDw4MGInWYYBqmpqfzwww8kJiaeMB2nf+azTkzsCWiNUmbC/YVMjBArjRhtY0yP7FNe5WQIuxyGdsjkuc+2UtPgt3aSmoHDJltLnGbgC1oEyL6gpa3timRpH6eN+hCfRTij2hWlMLJrFrIsUlLtoV1mHFsLq9lxuBpkEa3Wi6hIJMc60HUj4sv7dO1+LuyZzdu3DSCg6Uxbupv3l+/mcJUHSZFQ3QEwDH7cX4koClTW+hj02AIcskhQM3h7yiAEwGY/85bNYUFr/PuXELa3wq6Q4xRZ6JrBYBC73c6qVas4ePBgxNAHaynet28fX331Fddff33E/juTZ26SHuQngyCAqRmkJkfTMs110l3eqRAuDm6Z5qJ1hovlByrZc7SWaIdMg0+lqMrDzgOVdMtJJCHaToMviCSKKJJIrSeALUphX2m91T3khJvmNYtnkShapXyhQlyHIDBqcBteubkf2aGWMbJkTdTl57bkyhdXMLNdOhMG5XLX6A5kJDh56Yut7DhczXkDW6MaJi98uJ4BPZoz+4HzKK31EQhqtEh1EbYK+/Xty+ZNm5Ak6YzcAicGyc8EpmnSt2/f8F/HvXt4x2iaJl9//XVk83BiGd7XX3/N9ddfjyzL/73O2ONgmthD/qgwREGIGOWnP9WSyknD27F05V4+Xr2Py89tzZYDFbRIdlJZE0VpjZeMBCc17gCyJJIc62DLoSpaprnYX1xHSbWXZknRmCbsPFLD3pI62qS5eP6GPlTU+dh1pIY6n8rMbwvQdIPff7yByjofnZoncM/YTmQkOBmQl84rN/fjykfm8YcOGVzUqwVtm8Vx+YDW3DuuMwkxdh7/ZAMlR2vpfZVlC6XHR4VfH90wkCWJO+64g2nTpkVijyd66cMa63RCdapjwhuCxMRErrvuOgDsiozzJOMsCALt2rWLPEe4qCVs9Ofl5R0b/zPEf07ITEASqXQHqPYEyUywHsXpkE5aFXQiJNHiCBvXK5u+/dvww+ZSEuLK8OsSI7pksWx7JduO1DGuVwuqGvxUu/20bxbLx9+WWj24a718v7eM8X1yUDWD1mkxHCir4/cfrmdPaT26adlhVQ1+VFUnOzmG3uek0irDxRsLtqHYJJ6Z0IOgqjOuVzYTLu1MfJQNVddYtOkwRRVu3H4VT1Cn1hOEeAfDOmYiCgKaYSKF+EHkkEC1b9+ev//970yZMgU4plmA40JDp9MejbVOWOAMw0BVVWRZ5oMPPiAtLQ3TNBBOYoeHNdmDDz7I9u3bf+avu+qqq3j44YdDIbAzD8LL5q8RyX8DwkNkApIs4q3xsTa/lCtCdJPyr9iEWEWvIs+Oy+X8D/7Eti0V6Kkd8O9uhWC6yPek0rtFNO6AQbnboCKg0Do7kyU/HgJnNJ/+UMRl/Vpht1n3HNsrh7G9cqjxahwqd9PgDxIbZSMnNYb4qGPfx9dvHYCOtXmyhZ73k3vP+9nz1QYh3gbDnvuW6tpaurVMsjrJnZAAENZckydPJjMzk6effprNmzcft1ts2bIlNpuNPXv2/MwOC+/+evToQVlZGUVFRZElV5Zl+vTpw3PPPcegQYNO624IXycmJobPPvuMtWvXsn79ekRRpG/fvpGlNuxTO1PISJItdEKTVJAfy5kKPahh8OPeikZCdmYtWUzTIksRMHjp2YfRjqyhHuDobnZsto4RbC7eXOREtEcTjEpjX7PmJDpAqo1FSMjg6+WlfN1ZonWzJGw2O4pNQRIlXDFRtE8VEQWrX1Iw6KbSq+Pz+a3MDkNDVVV8fiu26PV6aXB7aGhooL6+noaGevweNx53PWUV1axeX8Wid58HQjHEk2jqsC02btw4xo0bx/bt2ykqKkLXdbKzsyPhpMYB8zDCtlNubi6LFi2ioKCA6upqZFmmRYsWkSXuVAJmGEbEYWg5hg1M02TAgAEMGDAgcpymacfd/0w1miyKQlRTujB8Qc3qQtLY0A/9NoEYp40zkXUj9IKPz/wR3+p1XBGvUKAJlGkm1Tr4NB0z2IA7GKbhPEDhwe8pDF1dBILAmIUhSiqbDUVREEURWZFDYaUQ7RXW72BQtXZhqmq159GNM06d/vTdDEb0nWZ1aDlFoCUsLJIk0alTJzp1sgLwfr+f3r17k5+ff9KNQdgTP2vWLHRdZ86cOcd9fmIaz4lQTtE0orHzVZblf7roWA4F/psMqm5GemOHZ7Fj8wTAmswad4DMBOdpr2Hlf4l8tqWM6W9/yY74SkwD6gSoRqTSECnRZYo0KNKgWINSDSp1k3pDoF7V0cHiqxAENNNECwSgUcfbX0ZYVCGUO40oiSimSYwi4TANYmUJRZbRg0FmfLyErpcXcNeI3Ej+2skQtovC1FGKonDzzTezffv2k0YDwjAMA5vNxty5c3nppZe4//77I7bYqdJywgL0zj/e5asF87FaDQURRZGMjAxeffXVyBdvxowZzJw5E1mWI8LXtm1bXnnlldAQnFoxNAHF+vF/D+/cjCWr9iG7BCsdOtpmZaeaYGKyYttR/naTxQtxMu+/ZQ9YGbaT316LHpPIixmjaVezlxa+MjKNBrJMg76y9XZBQBfBC9QbAg1I1OjQIMhUBTQCsoLXFGgIqvgNLG58UcSQ5PANkTRrYkXAJoBNEohWFBRMFExkTSVGggQFonSNWNkg2tRxCmCXICYI6+xubvvoOyb0ySLRZT+p++TYmFnLkc1mY+/evcyaNQtJkn4xxTqs0f7yl79w6623HpfJejKEP9u6dSvz588/7tikpCReeOEF4uPjAdi4cSOLFy8+7vyjR49GNO+Jdlrja511IfMF9UjmhKobPDC2E/vL6nlr7hZEl53YGDs5qTEIAtz21joGtEuPVFOf7NseZnK+/cMtXLnmZS6jiBuzb6E09ypaacXYqhrI8pWSVFNFdrCEdlIJDo+PJLOBFMlPrKrRVgLJ0JHsIAq65bNrNBJWX7FghL5cFkMkPRyLMmGqEWpzU7GEUzUhKIEu6tQjUylFccSMR02M49uUHlRWGzw6cyPTb+tv2aansQrC9tP69esjWbG/5D8LRwxKS0vZt28fPXr0iDACnQzh5e/ll1/i6af+yCuvvMIzzzxDRkYGGzduJCEhIWKfvfTSS1x66aWMHj0aTdOYN28eQ4YMObWWNPQI9/tZF7JwU1WwQjimafLmrf0xDZO352yGGDveoMb9H/xASqyDu0d3+EUBm7m5jOD7f+Zp93d4A9Amo5SVU7bxyre5/H1lDw6eU8e1XQ+w392Vp9e3YEx2IRVVJlWlEs1tleDRiVYbSMRNlK4j+PzEKgEEDOwYOAUdAwEdEbseoNjnwGVT0WWZet2BJjvwCnZ0SaBBsBOU7GC3U2va8Uk2agQXmk1Bi7LRPFVjQ2kLbq2cw9MVHzJ14WVcPyyPgW2STrtshhEIBH7VTq5xluuZQhRE4uPjeeSRR3jrrbcoKytj//79pKamRmw5WZYZNGgQaWlpHD16lH79+mG328/IX9Yky6VpHvu3EGqj/NZtAzAMk+mfbWHkU4u458IO3DSs7SkH3ggtk5UNfqb8dSUP1xxguXAOH2T25sqbTWIMDx6/TGp8JYvGfYMh6szc2IZ+WeXMn7yCV9d2YWFBFpMH1lNVF80DywdRU+Pi0u4FxMfqvLnIxcvlHxAwBQxRQjNECqLSeT1zPJd2Pcrifel4amPIa1HB7wbvwhNQuHt+T+7st4eRrYsZ90kfXhi+hZbJVczY4OLLzZmg6qwau4DPD5VS8ZcKHmtYhbPhKA+8l8X3z14EnHpLHxasvLy8M3Z8hl0bCQkJtGrVKvJ/ZzJJqqridDq57LLLeOONN3jjjTcimR6Nd5OKoqDrOh6PB5fLdUbP1STO2LAfyiRkI2PtLqdNHki7ZnF0bpnMeZ0yT/vNDvuXJr39I/FaIQXXjcUb4+GRzqXEUcrwGSNYfMMyVATK/VFkxtdT44vmlRGbMIIwqkUhH29qzpPz27NpygK+2RXLsH7V/FQcx+vDf2T/hoG03biDTopKlQCJJuwNwr4OXfhg+E9M8vZCaQ739t1NQXU0r67oSofYUh7qtJlmzSr4Qw8Xbyxqy33nbeP5czex+2g0r47awB2Le7DiplW8fnsbnn+jgc6+I+z4fiuvrWjHPcNPvQkI7yL79u3LwIEDWbNmDXa7HVVVTyp0YW0TCAS48cYbiYuL+1WVS2FhnDhxIm+99Rbz58+nqKiIrKwsNE1DkiTKy8spLCzEbref1JVyKpz9ZhE+lSjb8S8a1v6mCfeN7QxwWgHTQ1mz760uxF+2mC0PbaGkKpq9VS4WbExnwe5snjhvC+lxDTw+cBt3LuzN+5es493bFkCVi6DXQW6im1U3LMfhCLLqQBYV/mgm9luDsrEt//iuLc9dd4DfeR5g/KbFdNEPsM5MZk6PC3hxwm6e/rY9/VtUkhXrZWVhOnf23UEgaKNbViXpsT6CdbH8YcAuLm5bTNcWZdz6xQAm9ypgeM+97KyM4/z3BzPjiu/4Iq0PXxWMIG2/i2dm/MA1vZuR6HKEyFZOPn7hnd2YMWPYuXMnQCSuaI2hGYkI6LrO6NGjefLJJ38xx+tEhI33Xr160a9fP9atW8cnn3zCww8/jKZpyLLM7Nmz8fl8JCYm/qqw0ll3kOnm8cTEjSEIVhsa47QazHJ5VNT7uOW1HzlQm8TU5V34eHsOJQ1RDMyu4odJC7mqy37UBie5KbU8PWwLt87rz/c7c8AZwObygWiwpTyB+xb24W8/tuXvF6xHDyhc03UfMVEauwpjeOehPciP9+f5oQ+w/76LeH5qGSv3JDN/fxZXdDjEiNwiqv0yb/2Ux7C2R2ifXYbkULFJBoojQEqchwmfDiXOEeTufjvxlyZwT/8d3NZzH/fO70mgQeD8DmU8MWI3AU8Zj8/eEqkfOBnCQpKTk8PatWt5+OGHycrKQtd1VFVFVVU0TcM0TTp27Mjf/vY3FixYQHR09D9V8R12adxyyy0AvPfee/h8Pmw2G6WlpTz33HORCqhfA+HzeV9d26lD+w9zW7c0TNMU/10JjJpukZfcPm0txdVe5v9u5HF5/GeKcK78xS9+S5rnC+4fWkRzZwPO6AAIhsXTFFRQdRFJMNENASUqyKHqWB5a2pNYe4A2yQ0EVRnNEOiVXs1FeUdAMNBV2SrsjQqwsiCLBflZdG9WTWq8SnGNnT3lLnISPVzX6QDRsoZhCIiKzooDzZi3uznVXjvDckoZ3a6QTcUpzNyWw9i8I1ze+QC6XwkVlQjIUUHMoMLawlTyq1ysO5rCor2ZVNQ62fXmWNo2i8c0OfUXrZFWqq+vZ9u2bRw4cICGhgYSExPJy8ujc+fOx+Xo/9I8trtnLq/dcu5xZkpY2N1uNx06dODIkSMsXryY888/n+HDh7NixQoEQcDlcrF7924yMjJO6roQBEEPBIPSqlVrvr7g/OFjzr4LI2A16DJM06IC4MybFBiG1YT0nVVHSfd/wVvXbAa3gmqI+DwOMC1SFmtDYaKFiMF8Hgc5Lg8fXbqaGz8fwJ6yeJ4YtoWWCfWAQNCvYJgSomA9ic8dxbCcYjql1XD3V71YtDubKf3yeeDcfFJi3Wh+OwFNtvKu/BLntTrKea2KWX0onZfWduCjXS2ZPvonPrx4HSgaAY/durYACOD32pFEk4EtSxiYW8QkYy8l3hge+6oNd7/fgmWPDUEzjBD/2YnCYf2frukYhkFsbOzPwj1gmRSBoBoStLDz5YRrhf4UhZP7IMPZtS6XizvvvJNHHnmEd955h8WLF7NixQrraf6JULcMnDSW9u+CX9Wp8wSthgzyr9NikiiwrbCeN79cyMabtgECOHQUQbP6cAscn6TfGKaAXTT45OZl1mdBEVQZBLC5gj+/mSmQ4nQz88YVGHUxiEn14FdAl5CjVWTBPMZuF7rnoA6FDOp0GOqjwRGwvL6miD2m8fWFSM9w6zwZJMiIr+cft/7I6NdjeWNpDlNG5pxiFMIvJoV+Tj1Wkq0xvcMvuEZO0bU3rA1vuukmXnjhBebOnQuAoii8/PLLTJ06FZ/P9ysD5Jx5Kfs/g5yUGGYvyWfEU4uIdsjouomqGxEVLYlCZBtvGCZB3YhUC7n9KuvyK1Bo4Nb53bEJemjZMEO2gZWFYRm/luYQrB5xCJg4FR3dCKXNiJa2AwFBMJAJ7dIisUkB0xRQJB2XTcOnZSEJJlYcwjom1m6AcCxpUsBK446xBSPyLloDCoCIgSyqJ7VJbaKBoUCDT+OO5xbzwco0clLjIm6eU02JVTpp2bkCRFoI/RJCNS8EVJ3Sai/7D1cR57T97LhwgDw5OZkePXqwYsUKDMPgD3/4A3feeSePPvror5EXAc7i7jJccv/45d0Y3S0Ln2ZYRb26QZ1XtfLuZYuVxxIKgaBmUOe1ytpkUSSoG0y93IYpyJTUWwPkChVwSKKAx6/iilLQDZOqUGGv0y7jD+r4gjpRNplqt5/4aHuErgAssfEGdBr8FlGLXRFxKBYDkBAaGiEkXN6AFmqnrFEZ1NB0g0SXw6KmSrRqN0tqvMiSQEDViXYoRNmkkBBY0uUJaBGBBmvCo20gSwo3XmJyx5U6dR4VzbBa70TZrJy6k2ULG6Fn8QSsjIgkl93aPPBLuqvR3Ajw/LW96Jpj5eqfaAuGl8S6ujoMw+Dcc8/l8ccfp7Ky8kwFzBSsZ/LBWRSy8KPEOBQGd8w87bG/4b8HYd/awoUL2bhxI3Fxcbz//vsRR++ZazEBTFOFJkhaNM1jef6NExb/qWtx/Le18d+NTTOz8YchdXAyczqyhgjHzj3ZPYkcG0boLqHr/mwIT5yIkw1xZGk/OU43lY2f/V+xdE7UYOE4Z35+PjfddBO6rvPqq6/Spk2b06YKnRIhiZRFUYgJTcFZETZBsFrZ/Odwunv/muc68VjhNJ/9K/c5U/z7rhlOKwr7wK677jrKysqYOHEi1113Haqq/qzuIOz8PRPBk0VBODXj3G/4P4HGpXJPPPEEGzdupHv37rz66qsRH50oiiQkWHl/4ULfcJTgl9DkSYu/4b8HYRvr4MGDLFu2jO3bt/P222+jKApJSUlERUVFlsmNGzcyc+ZM/H4/hmHw8MMPM2HCBAYMGPDLttqX87++4+ChQtM0Tc0wDPM3/N+BqqqmaZrmCy+8YPlqTvjJz8+PHHvFFVf87PM+ffqYpmmamqZFjgvJkBoIquaiJcs/hf903eVv+I8i7Hi98cYb6dChA4Zh0NDQgGmaZGVlkZubG9FSL774IjfddNNxWR05OTnAL6cT/SZk/4cRXuJSUlK48MILT3tsdnY22dknp5M45VJpmiJYu8vfbLL/4zDNYy2rzbC7qVFxMRBJw26M02XgapqGCX4AWTfMqmAwCE1Qc/kb/jtxokCdDL/WR+bz+UxNU/cDiJqp5VfX1GjAvy3N5zf8n4dYWlYu6Kr+LYCYHBu7q76+YZeqaiZgnKgSf8NvOFOENgmGPxAUjhYf3du8ecY60zQFcejQoZoa8L9dWl4eTkL6Db/hX4FeeKRIUP3BJ3v27KnOmTNHFKdOnSqKYu4/8nflb3V7PLIgCNpv2uw3/BqE048EQQhWVFYr+/YVzBozZtTM2bNnS1dccYUumFbKtTF//uK8+MTYNT27d0uOinJopmnKv9lov+GXEBIuE9Aqq6qVjZs3r0xOiL+oR48efqyUHyvVMyxx8+cv6h6fGPdl1y6dm7tiojVANEO+jt/wG06EIAgGYGiaLhcWFbF3b8EnDpt089ChQ/2maQoh4TvmtggL2uz587MTYlzvtG1zzohmmRmE/Gi/2Wq/oTEEQknAtXX17MrfXVlTVf3YmDGj3gZoLGDhgyMICxrAVwuXTIqPi707MTGhQ0pKSqRHz9mCKAgIv7KS6Vfhv8HM/Cdezwhly/6raOxw/RevhN8foLKyivr6hn0N7oa5fq/7tYsvvrh46tSp4pNPPmk2FjA4yWs3PnDq1Km2zt17D7ArUndBINM0z2adpsDZokkzTUwBURZE0/kfU8kGHhB0QTB+laidtmPezyAApm6ahvfXPdyZXl5EEIQAJuWqoe444PVufuCKK3wA33zzjTx06NCT0g79P9MuxLqscC2GAAAAAElFTkSuQmCC' +c40 = b'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' +c41 = b'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' +c42 = b'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' +c43 = b'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' +c44 = b'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' +c45 = b'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' +c46 = b'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' +c47 = b'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' +c48 = b'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' +c49 = b'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' +c50 = b'iVBORw0KGgoAAAANSUhEUgAAAJkAAADICAYAAAD7jkPoAAC+d0lEQVR4nOz9dXxVx/b/jz9ny7GcuCcQJLi7FCsUirRAkbq7Ub/VW791p05bKlSgtIWixYoVd3dIgJCEuB3fe8/vj3MSaEvt3sL787vf+3o8omefM7Nn1l6zZq3XWiM4CVOnTlUvuugis/bv776b1d4Z5ThLqKKjrmkZUspoKaWofV0IIZEIwALp5RSQFlhIlFO9+FegCA+WlH/+DQILGe7Af9763wIhpJQIIaUVEBAQCGH9X3fq1IgSQigCIX8+3+H+Y0lDIo6HQsE9/pB/7UWjRm2pveaXMgQgfvniE088oXXr2evKKJfrhpiY6C7paWm26Gg3Nt2GEPwKEhCIU74GYFkS+Vdk4zcghDipt38O4bb/H53Gv3ozZxR/MF8SQoZBTY2H40XHQ5VVVZtrajwfe6srP7nooouCvxQ0AScE7NsZc3olxsa82aRpdqf01BRUVQWwqJWl/1v855L6P/zdEIBiWZLC40Xs239gW2V5xR0XXHD+8pMFTdT+MWP23JvSU1Pfbdumtepw2A1AkVL+v7HO/A//T0OEV30rEAhoW7fvtAqPH7915PnDPqiVLQEwd+78sVkNsr5p0byppaqqlFKqkTf/n3b+f/j/H4StNWGapin27Dug5OTmXj982JCPp06dqoqFUxfGkqju6NenT6aua5aUUv2fcP0P/w4igmYZhsGadRuCleU1rc8/f1COUuPw9c/IyKin65r8n4D9D/8JhBBIKRVN06yWLVo4LMW8GZCKItRmMe5oyf8M6//h74OIiXFLh93WB8IOJA3xf75z/B/+SxBZCYWmqkJT1cQnnnhC+d/u8X84LRBChJ31gIIQ5h+94U/jb3C6/g//HZBS1omDIi1Z8x9+2onfhYiEcf6H/6+iVhqklHVRwP98uTx5NyotEP9bgf+Hn0P7t98pLRCCvIdvpmbdehQHmNV+ojp0JGv8lxHh+38hGvU//F9DA7Csf2eJEyAhcPgANWu2oCWAWQF6ahLSshCK8j/5+h+AyHJpWf+ewS6lpPHnC0m6YhRmpUrsub3InrwkLGDA/6Tsf4D/xCaLGPlCVbE3aYFVbeJo0QahaUjL5De5P//D/+fw79tktZASGQyAApbPE9ltipNfBmQ45BD+9e9BhF524jNlnQV4SvGuE3r52334vWv+1Pvrvv3BZ/Db1/zetSca+VusXRmZq9OoDwT8HUImxIkBEcqvBkecNPA/m4O/CeKkb3/uo0WtOfnzz/ida8QpXoM/9xm11526b3+FiPmrXvzHOL1xaoECoSeffFL+50L2G7CkRBGCHUfKueXtZXgsSYLb/vc9NQLsmkrIsKjyBfEFTOKinZihIIrfW7e7FYCJQsgZTcjvRxNgt4K4hIFCWAB8UiWg6gQtBU3TUC0DmxHAqZiYCPyWSsjuImRYKJaBTZHYrRD2CHnakAI/KiFVJ2QJhK6jmUE0M4QTEwF40fDrTrz+EIaiYbdrOM0gmmWgSePntyYlXqni0d0oikSXEp2wz9wnNAyhEWX4qPIbxEfZUJQ/P6iWJYmyq1T4TOzAR3f0pXX9+Lr5+rsQZjILnxDiNAqZJVFUwYo9hazeV8TyF0YS77ZH6CB/8kMiKkBaFlgSoaon1kghsGkKQcPiWKmHDxfv55uZ6/nsyGskh6oIIVCQCFUhWCFxXXs90dfcy9FRXXGFvDiFUacN/IoNb7VK1Lh7SL/iFg4Pb49WVYlTl5gIfAGBbNCY9E/mk3/zSOTuXbhiNWyWAQJMKQgoOp4KSfJrE9BjXBTceBXOKBO7DCGQ+KRGtT2O6I/mk/PDLJRJH5IW5UUPeE4ImRBIC1RNI/nbtexbuIjS8a8SEwcuw4dE4BFONsQ04b2kUTx2TTcuPKsRqqLwW+z0Wi0qJYRMi6RonfcWHeGZT5eCDLD2QKuwkFmgqP/JjJ+q8XB+gCZOc3DcsiStmyTRq0XqaWujVb04BrXP5OkEBf0pg/aql3IBdWMWA+rMCTR9/BFKLhhE4cSv0NJ1rJCBQKCoJqZp0GrsYDDycJQUImLAsgABapTA3LuD7L3z6fray+wd3h+jCGREFQoBwgA9AZpfNoKSB64j0axA1QSWGbYVVS2IVeShuXcbyg1D2D/hYXCCpYCMPDhCExhlkqSrLyO1cwsy7xuCl8MQCPfFEJApYbHZnFuv6s3Tl7T9y2M1c3M5s35aycGHFnD99x3wBG1/2zz8FjTTtAKnuxHDsMJJHfyVTacA00DRNLz7duBZt4qkK25CmmbE9jvx5FoyLMyPX92X6/0zWP/GXdzn30C+UNGlhbCphEoC5Dx8G/Vf+oRjM2bgP+JB2AEkZrVF3Ige0KY7eU/diccQ6IqGtIywKpAC6Rbs+ed9tF53hOztBZRPm0Ko4AiK3QbSIni8nKQrr6Vm106OTP4aJU49IaUAloLpstj98pO0XLwXeW5fKucux5aun2T8KZhagLi7/0XRZ2+Rt/EwtjQdaRhYikKstJiuZ7BxwC1suqgNhmlFAtG/M4yRvYUqJLd/soud26ex4rrFzM1rxdK9GVw74rRPP5oEb3j6f0OjWVZ4iVN+bdT/FSiKQMo//xHSNBGahv/ALnIuORffrgKMo/tJf/hlpGEgNLWuy6oARQhMS/LatWfRY/9jZMx5iIt9uzmuqOiGgS1RpXzqNJKvGkeLRZsp/uBtrGAVQig4WrQn+bo78G5dR9lXn6DHAKaBqJ19S6LYFMzScg5d3I/ES2/ElpqMPSMdYXeg2B1gmfg2ruL4O8+jqBKB9fO4rmWiR6kENu+jesF0mkyczf6x/fFu3IgVCo+LUQHJ15+PLSOLolefxBYnEJF+KFISRPBSk2v44I4BODWBaYH6B/aYFTFPhr64BlvpNyy9dQuPL+7K6ilB0tVCgor+l+fy9ycuPMknxy418UdbDEX5j9fTvyqb0jQQqkYgdx8HLxlMML8AWwM7BS++gtDtpP3jmV8JWm0UK9Ym+e6+AfQouJ+0TU/R23eYUkVBlxaKU3D4jkvJfOINovv2IVhYAEp4zTv84A2Uz/wa0+NB2ERYPZ4M00K4BNUbN1H5060/99Sc5LVQY0CxUZcGeLJLRVoSJUrh2BN3k/XGJBpN/Bbf9i2EivKx/F6EYif5unEcf+tpAkfK0JM1pGFgCIV0aXFX3DCG33I1fRpGY1gS7Q8EzLAsNEXh3YU5pHom8+mNu7nsiz40nLqY77wrGVTvWnzi9CyXlrQiTqXfc2FEJDJwcA++3buIOXsQijuav6SOCF8aDP35sJU0TYSqEczL4eDF5xLMy0ONVpHBAFqSRv6zzyIcDlLHPRoRtBO3oCphbdYq3c2Uh89jzCNVTNv3HE39RVQKBdVm4T9+nH1XXoqQYU+0CqgSNB2io0FxhHd3qCcxCup+SoRbgWjlhNcmMla1+xFphU0DS4AJmDLyM/IaNvAdPcK+C85GT4zBlpWNo1FT7E1a4GjegMLxT3L8zefQ4hWkYWIIhSTLYqq9CTnn38GU4U0wLfmHGgxAjXRy7rodTBu2hRdW9cL7/X7u8a2kSBMI0zojac9/KGRHH76R0m9W0PTbT0kYc3XdMvZnIYTAHzQjv//+tWEBUwkVHuXgJecSyD2MGqMijfD7pWWiJWgce+IxFIeT5BvuQxohhHZC5auKwDAthrVJ4a0HR3Pp0zXMzXmJ1FAVQQR2OyhOJeyaQFBjQYUlKJeC0oBBhR8qUagKhPAKDZ+iEpISf9DAkrUpqCZ2XUNTFOwCHGYIF5IYu040ECsksbpCnDSJ1QTRQuISYKt1qTgEhoRAVRU1GzdTuXozmJEkRg20GECAhcApJUc1Ny+1uZ15t/VBVQSWJf9wdZGRsTcsOF5eTRCdA/k2RnjXUaoq2JAYmr1O25xOaACmcQreYq1ESFAdKpbXEzFkfwErYnvU7pNPgT+l+KywgBklhRy8dDD+vQdQ404IWLgvEomJGqtx9KF/oDhdJF5+668ETVMVQqbkhl71Kbv/ci57tpKPjryLxwhw0CfZG4LcoOSYISk2oNKCQG2WQ10IQY38rHUvKPwsCictwnnPcGJRtE7csJCoQhCtCOJUQYoK9TRoqIe/sjRI1ySxNrArAokgKCXBiKuhNoLhEpIrUi7l7ttG0S496k8tkydDyvCXKQSJwkOs5UfHQleh2JGAJv8+zupv4TdVkrTCcUlb/UZIcxXeTavgytvANJFGrfNQgqoQyN0PQqAlp574f2RC/tRwWCYoKmZFCQcvH4J3+260BA0ZMn59rZQgTNQYlSP33IZwOEkYc82vBE1XBSFT8sDAhgg5jnPv3Id+aAZBxRZur9axJCQqFvov6nX8TOb49fNzsq31y1CWIUGRYfGssAQVhiAXwbqT4mqqKkhWBQ11aGGD1jZJM5ukviaJVSRSKMRLydPOHrgvuIoHzmmAYUo09U/HNYDw9VEOHSEtqoSDkKJS44dxDa7jiKMRUaffufDHYaW4YWMp+eRzKmZOI3bo98See8HPXq9e9gPVSxajxUliB46I/PfEQBjWHyjkiBfQrK7k4BXD8Gzcihb/GwJWCylBsVBcKofHXYvicBJ33sW/stF0VRAyLO4flIXn4bt56pZN2H1HMQkLQm3HwjaTDkoUON1gd0NULGhOsDtxOByg2iLaLGzxS8vADAUw/H4I+MDwga8Ggh403SBUHQSqwAo7Y2t1oyoidR8kFBoKhQas8YT7oSpQX1doZRd0t1u4hMK33a5k+bWdkFLy72ZkhB95iaHq/CP2Mi44x8FFV9/K5jdnEzDO0HJ5Kgg17OeJOWc4iVddQvGEKeRcN4r4Cy4mqnNPEALv1vWUz5hM6JhJ6p1XE9W1D0Q0IGbYR+QNGL9djMeyQFGwvDUcuvo8alavR0v8AwGre68E1UKxKeTefDmNP3MSc86IXwmapioYpsVjV53N8ZLxvP/6a+hOG6nxcaRlNaJ+/SxS0zPITEshOSGepPgYYtxO3E47LoeOTVNx6OqvlnzLAn/IJGRaePwhvP4QwVCIpduP8ub3mxnZNJeVBx3Us5WQU+BH8ZYQqK7Ae2gXhCoiK2tYiwhAE2AKhdwg5IZgbhXQ8nw2vXAJ2ckuQqaFrv51KROA06aCUDA8HtpedBEvPdiVRWsO4in1YtNPv+n/+5osMrJZr0zCltGQkkkTKP7wa46/+3VYV6lgq+8g/Z93kPHwS3Vs2T+FyLUy4CfnupFUL1355wWsFpYMz460yLnuIrK/moW716CfCVptd1QkZ3Vtz/wR9zHl/oE0TnOT4Ph3uE4nh81rh89Z9+rITmkcLApxT5P5DGmVRVp0kA2FqWRGx3Gkxs2Rwx0prhFkaHls23qEGNXLji0HKC23gVkOhJdau4D3n7+TVvXiKfcEiI+yY1phn9dfjTFqqhLmDAqF/i0TuH/CMt6dswc05Yxk2/4pIRO6TvqDz5N8/d14N68nkLsPK+jHltGQqC49sdVv9NdajSSbSNMg5+bRVM5fjJb8FwWsFpaFoitYwQCHrh5F9tfziOrc+1caTUrBoi1HGNsjjW4N3b/6GMO0sGSta+DEJAoRWZ1FLWvht3zWEr9hYtdU7j6/DeM/b8VnIzfy4qqWXN56JzP21ePi7IPMojGXpFZyoCKTW86LIsPt48XFA1idk4S7eCmHChSC5Uco09tx/oCerNt3nBteXczrtw9gWMe0SF8lqvLnWRQOzUIVFg6byoPvLAdZDZr2u0yjvxN/zhchJdKy0JJSiRl0/q9ftswIG/aPb1pKGYn3CQ6Pu5SKGT+gJf2bAlbXvoViV7B8Hg5dPpwm3y3C2bpznVO3NoC8/mAJl/XOxpKSzQdLOFhUjSUlzdJi6ZSdBHBqNkLkz805pSzakseW3FIqfCHcNo2m6TH0b5tB/7aZuGzh4ezXPIbn9I4EQqtx2sLRDo9ho3G8j7IdCk1jS/l0cz3Ob3CQLzc14KxGXqKiqjirQTOyYr18t7sbu4/qPP/NMs7r0Zl9R4q4bfxkerTrzlOXdqR5elhzGmbYTvs9zWZJCIaCaGqY04ffoG2nNO4b3o67PlpD0Dj92WV/TsiEQKgqMhRC6DpVi2cRPJJD0jV3IkNBhP4nvcYRpyWKwpG7r6B0ynd1Xu3/FNK0UJwqZlUFBy8dSpPvluBo2hrLNFFUlWpfiOMVPt6cs4OJi/aiawqN02IoqvRxuLCK7GQ342/pQ89mKXWCJiO+woIyLz0fmcmRI2U0z06mW7Nk2mYlEDItcoprmP3JGizT4rKzm3L70NZEO3XaN23BkpwEemSWsqc0loZxHo7VuGgS7yFkqTg1i6qQA0OqNIiuYubedAbUz2dvgU7XpKPUd2oUeP0crehCSr1oll41i+/3bOHSf/Wkd5ezuGd4cxol2yPDKjHD5u2vBE4CIVOiCoVKr8EVF7Rl4h1d+XBVPtUVfmx/crf6n+BPe1WlYSB0Hc/mVeTecilGiQfFHU3C2Gt/5T741XtP8gNI0+DYY7dT/OmX6Mk60gj9p/dwoh3TRIlSCRUVc+jyoWRPXoCtUXMAjpV5qPKGMKr99B/YnDvPa8O2nFJ2HatAVxW2HShm8BNz2PT6GLJTY8IxvwgR0u3QuX5AM/q2Tkdakq25peQUVaMoglaZcdw6pBWhkMms9YcpqfIT7dTp2zqdhfPq83jfA0za3oiu6SXsKIqjSXw1hyujaJVcyc7iWNLdPoKWiks30VTYXpzIte0OsqUom6YxOSiE6NysGe+vS+WFy3ZyZbvjvLt2A5c/04XWLbpy9YBm9G4ejVZHOZEYVngHrIRjFCgiHHkImTrNGqZx8asLOfb9NBzRTbA5woJ6mviLYZ1iWdYffnytfePdvp6Dl52H5fWgxmscHncd5TO+QGj6b2ojKWV4dwOgKHi3rKPwrY/QU2x/q4DVtRcy0eJteHccpfCNJxERx+WREi9W0I873saRUg+DnprLba/9yEcL99CyXhwXnt2U6pIaXv5+G0KEbSwhwstnjEvn0Qs7Mn7mdgY8NIN73v2JN79Yz4Ktx6iXGEV5TYD+bTN47bqeNEqNBqBr41gO1TQiWvdR5HGQGuUnp9JNVqyHA+XRdEgtZ2tRHI3jayiscVI/xoMnpBE0FVw2A4mgUWwVuflHeO3qznywtQ3FR+JIjArx2LCDrLphMn2dr/DixDcZ+uRsnp12gI25XiwEmqKgKQJFUdAiSWPSsrBsDt585UtGfnQjPxR+SAt/Lobu/J3R/PchEAgZ3j4rgDeSEndKYZNmWMB8uzZz8JKhWJUVKA4FpIniUDh861VU/vBNOIHkFEIjZXh3Q+RGnW06kXTlaEJFwd/Vfv/2zWkKZmUQR5NkUm59CDMS6N53PEi3+kV0yShnzcYifMEQOHX8QYPVOwponRnHmMEtWbjtGFJKNFX5WU7C2Fd+5PsFu9Gi7aArkBjFniPlTPxxL267RpkniGnJiIddkh6rENLrUe4L+78EEm9II0o3KPI4aBRXw7FqF+luHwU1TprE15Bf4yTeEaDEayfR6cdlVyko2E2LdBdXntuPB+Zng8ukuszJB+tbM6yFl1k3zeWDvm9gz3uWp94fz7mPfsd1723gzflHWL63kmMVBgFDweEwcWsGHxW9zwgjj4AADfnXaj3/eUghBBYyAKBplhX6rcLBtYazf+82Dl4yBLO8FMWlhjldAKpA6IKcGy+h0ac2YgeOPMWuTmKL6HIJKE4XDd6eghUYRcX3c/79XeUpIFQFy2+hRMfQ+PPZOFt1IBQyUBWNI6UBemYWY6oGK/em43IE6dEhA2/QYPOhEp6YuolAtZ/GDRIIGBYOXY04QAUlVX6mr8lFJERBwGBs36a0bZDAazO20blJMgOemINqWozp15SJt/XBadNQBcTFpnCozEGiM0i5345TM/CENEwLonQDw1JwqCaVAZ3O6aXMP5ROq6RK9pfF0CiumpqQixhyOVBs8soVbej0wADmb8lncMciZs3I4ObvenBxlxxGdTnOHYPy+Ic2l+qi+SzJSWDppnRmL0ynNJTG3iKV0VPPZcHh+tjtbXEHDKocDo7ZU7HJv2fsTzkfkUVYs35jHyytMBsicGAXBy8eTKi4CNX9i1iiZUV8LZKc6y8ie9L3RPcbGhHC2sAGOPSIVqhLo9NoNOE7DoVGUDlnQXh3+Z8a/4qCFZAIu4vsL2bhat8NIxhEirAztrwmQNfEao4HYwhVBvDYTey6wordJSRH2Rh5VmM278jniC9UFxsUhDlwUQ6dK89uypSl+wjVBNlfUMmqPccJmmFhbJ0Zx/ldsrhhcEui7BqGJVER1EuKZ39ZNFmxXvKqnaS7fRyvceK2GXhDGrH2EH5DxZKCOHuIUq+DzOhC1ucnMjQ7n/3lsaTa8tmcW0WT5Hg+GdefS57PY3m9Wcy6ehG9PxlB3swC8qZv5/ImnYlp24Gerao5u+lxRnQ7CGIHeKGkOootBQmc36SAfV3bsLSmNYcCsRzbmoRD/v0myy9xasPfshCKSiB3PwcuGUywsPDXAnbStYquYIVCHLpmNNmT5+Lu0T+snVQFVRGU1ARO5CuFDR6EzU6jj77n0NXnUbVwyX/mxlAUZEgiFJ3Gn00nqmtfwESzndj1Vnn9ZKZ6OZhvMnxoS9o3srHraAWjuzWgdVY8Nw9uxeFzmnH928vDS+VJjCanTWXSHf345+gOLN9VwIZDJUhL0iDZTePUGB4e04EY54mlv/Z92Wkx7NsSwwVp1aw5Fk+b5EoKPE5SogIc9zjIivFQ7HPgtoUwLIEpwamZVPhtJDoDrM53ku46zu6jxcgu8XRpFMOTV4/m/ElVLLvpRxZeNZ+rja5oc2p4b81bLNpSn1UxbZmTmEkwI4v4ejqN6wVpkVZDs5RqhmYXc5X9KJojCKZFZu5gfOZpS/Oow69biIxu2BXQn2DesTCf61QCVvsWy0LoCjIU4OBlQ2ixcCta4/Cuzq5r5B0rp7zGT2yUPezYVJSwcDqcNP54BgevGEL18lXhoPhf1WiKCEeiLYVGn04luve5YBkcLDF474eNuDQPHiueBRsP8vy1knk5klvPb8PQtjG/+qgpK4/TICXsqDWtnwejLSlpnhlL88xYbjxFN0wr7PY4OaGjcWoUG7zxpEQdp8yXRprbx9aiOJolVFNQ4yQ7vppj1U7S3H5KfXbiHCGqAzo2zSLs0lJIjAmyPy8fIZoRCJlc0SudCs9l9P1AMPeqRXxx4zoujLuEVbNa8WLRFIaUH6W4DCr2qxQoCRzRU9juTGFJVDzV7hhEbDquBEGJO4mC8lic6ulbLmvxG2IsETYbjiat8O87xp9xsgpFYAUs7I0aoLhj6oRVUwVGfog35+3nibFtCRoWNk2EnTqWhRIVTeNJczl46SBq1qwPB8f/rKApAkwFK2jS6MPJxAwciWWEKPMr3P72N9zQ9Fu6NKjg/VUtqCjtSao7SNCwOFRYhdHKHaYvqwLDsLDrKlsPl9GpUVLdGJy85FuWRIoTjNe6+xYCRYifkQhrNVnDJBclgVji7X48IY0YW5DqoI3UKD97S1PoWa+Yn46k0DWjlKNVUdSP9nCkKrwZKPfr6IqJy6ZQXp5H0AS7rhIyLcad2wDElTyxTPB434XMuHwuT9U7izHfPcLt+75jQGgvsYpJFMW0MYrRKndCBYQs8AFBU+FATBY/ZN+DeQYy/RVUFdM8SUtFQieKw0XDj2YSM6AfRqnxu0RFoamYVSb2xg1pMnkhemoGijSRwA1tVvL9PUv4aM5K5m0rwaYpEb4UdYKmRsfS+Iu5RHVqj1n++239rJ+WguU1afjOp8SdfwlGMIii6czeXEJb93rG9qkkK8aO2xXNgJaFRCVWsrPYSX5ZFaqqoCqgKQJbJAC+43A5ZzVPiXy8qNstCsI7ZFURaKrysy9V+XUiR20CWFqcjmJLQFdCqIrAqVt4ggoJzgBlfjv1or0c9zhJi/JRWOOgSUI1B8qjyY6rpqDGRYIjQFA6cFpH2VsYBGpJmZJxgzK584rbGTrlKj5aksUT5yxl4oM5TB55Nf9Iu4oDVjJuM5zhVKqpFOk6lXYV06Zgd1q0sw7jMqowxOlfLk8dH47YTYrdQaNPZuDu1Q2j7NSTLzQVs9rEVi+D7Mnz0TMahA1/RUUAB8ti6FK/lHU3z+DOd77hs5/y0VUlPIEQtqcsEy0uieyv5uFs2xKzopa//xsQAgi3m/X6u8SPvhppGCgRl0jjFCe7S+MgFEQRgiYJ1fx4wwJW7M5i5a4s9uYVhTlgEa++IqCo0ocnEKJ9w8Q6enOtAB0r8/DMt5up8YeN5D/a9IeFThLvEgg9jqBhYtdMTAt0FWyqScBUiLWH8IRU3DaDyoCNrBgv+TUu6sd6KfI4SHN7KfJG0TT6GBtzKsJtR+KoIdOiTT03y1+4jHmVtzDmvb5kqoUsvH0uFz4cxVvDx/FIxuWspyG2oEmKESLWMtGxMBGEUM9YJerfJiHUahl3LNmfz8XdvTPGL7SMUFXMGhM9JYXsKfOxN2wWcXuo1CqraQfa0+C5izlQk8LK66bxxEdfMe6T7aiR7CUJCCXsFtGS0siePB9H82zMKvPUgiYECBWzwqD+i6+exIzVIhlRkr7NY7hu5GXc//1ZPLswkxpfDVd/1YHRX/fmyyvWUFV+kEpfWJBq80XKagJU+UIkuO2oiqCoys/Mtbn4giaZCVF8umQfz0/fCoBp/nG8r5YiHRudSKVfJckVxGvouPQQQVPFqZkETYUo3cQb0lCFJNYRxGcouDSDmpBOisvPvrIYuqQfZ8uh4+G2rbBbRVcVDpdalNUIptzbh8vH3s/YWTfwxLQWjM7Ywbx7FnPt0w6WX3s5j3W9i9cTh7FMNOW4EYUzICl2JOC1xaFbp8cmC2crhcfp93WlooBlosYlkv3VPA5cci7ejZtR4zSwLCyfiRYfT/ZXc3E0bVPnVwsjvGSkJ6jYfNXcMr4pL9xmI/fhmZz/YRFjXruA7+7tGWZ0KyLCQTPR0+qTPXkBB8b0J3DkyM83HUIgFBWj1CDzX/8i+fp7I365k3d24WVu9FktyEz/F/M35ZOHRUFhBRnuJVzW7wDvbWnM0l3FjOiUEra3pKRJWgw9m6Uw8NHZXD2oOUdLPLwzbQvOWCcD2qQT7bLRv3V6XRt/BCuSqJIUl8jRyhNLYlqUn/waJ+lRPvKqXTSMreFQhZskV4DqoE6iI8ixaie6YuG2GeRWuBjR2Mu0XblYsi02TeHHncW8NHUtKfpuHJqPA6WZ9OrUnWmPXcSEBV0Z8t0aOsat46aOe/jgkr34RsWy9EgGK/e2ZuFBhaq8AGuCWZiWA43TEyC3pFVnv/4xnUpRI4KWRPbnc7E3a4xZZSANieKKJvvLOTjbdP6FgJ2AqdiwKx4+3f0Cr7wWxYfb2zH7zpVUH53OXZ9tR4kkRgCghjWarX5jsqfMR09Pw6wJc/8BhKJhlBhkPPJwOFvJ/PUSLmXYbtlyuIqvftxCVVkOXRq6uKZ/Jl3TCiGksbvIzsQf99btBBURtrU+v/NsrhjQlHfn7WJUj4bkTLqK927uTYv0WD6/ox8D22WeRAf6c6iXHM+Okngax4XDSVkxHvaUxNI8sZLtRXF0SCtjXX4iLSJ/96pfxLIjqSQ4A5T6HETbglQEo0kwN1JUA9uPVnL5S1N4tOv7PNRzJUPq5/LxiO+oPvg6V4xfziOjmjL9ySto0+Nhntz+IIMnnMfEFfXJVMp55pyNTLljPZP/dZC5d27G7aohYP3dtQl+jT/H2atdzpLTaPLVfOzZjZCWQuMvZ+Hq2DOsTU4hYBAOpwTQceNlwr63eOXtOKZtac3Ui7bz2aKN5Jf7I0tnJE9RVZGmgb1xC5pMnoeWmIjlM1HsdkIlIdLuvYu0+5+rW5ZPhhWx0ncfq+Hyl7+mi/oqtzT7Fz/Me5HLn/6JGzsfY39ePF4rluVbd7D9SDlKJI2uFtcMaM7q50fSMjMOm6owqH0m945qT5ushPBQ/MndWK22a5Yezer8dBrHVbKvLIasGA9bjsfRMqmKbUVxtE8pZ2NBAtnx1azPT2Rgw0JW5SWTFuVj2ZFkRjTNY+qeJlzWbCMPTFrH/Z9v5qWzV9M+A+5f2J0317Rm5KQhjB91DHfVLF7/IZcYh+CaszP46h8DuX7sNdwxuwc3z+tBk7dHMvDDc3hmTjO+35+FYaoo4vRbZn+aGCpUFWmZ2Bo0oem05TSb+RPubv3+VIqcgsQndBzC4p95X/D+ysbEJfjJjilk+9Ewwf3kXFqhht0Yjhbtyf5yDmpMLIHcACm33UTG42+EBUw5kdhbi1o76NU5+7mp1U9c2b+YKHssdj2a3i1z6Nb8GLf+0JlJF2ykYUwp1763KZJkFd6EFFb4mPLTQV6ctoU35+5kwsI9TFq6n2lrcli6s4AtOaX4Iul9fzQ1tcLYpZGbzaWNsSsBKvw23LZw7NKth6gJaWFCoSIp89uxIueXprp8lPnt7C+LpmVSJfnVOikxOgnVk5k/v5DuDQx0GWDmxT8y7bKlbN+Xwburm3FXj8PM23wUKSEQMrEsyciuaQzqYLD6utk0TAjSataPnPvuZOTEtfhDTvQzcKzrX9q/CkUFaaGn1UNPq3eCz/8noEoLr4CsUBFaRTXS0klwBE4q/fmLtjQNaRq42ncne8oCPOtXk3zDXWFOmqL+jJsiqeVUScDC7dDYlRsDwuR4hZOzMgt47fxV3DutF53Tyzkv+wh3L+hI4NBmxv+Qzl1DWyElvDxjG5/N34Xi0OsYsroW/hkyLKpKa7hpZDtev6YHpmnVBf5P2f/IDjA1RqNB/bYsy1lAs8QadpbE0TG1nA2FiXTPKGVlXjIXtjjC59sbMrLZMb7a2ZA7u+3llTUtubjlEZ5d0Zq3zt3I9bO7M+uKpRTUJHDZNz14a/g6bIrF1zsa0qlpAenRPqqDKg5dQ4iwyaAogrJKE9O0kFIjzeZlTGg9XahmhqvDaeP3/BJ/3UkilDB9Wsq/XGtIAbzY0F06Qpjomk5StCP8sae4X6GGNxiu9t1wte9G7YXhTG0ZqfNQ62oQ2PVwf565uCXNx/Xm9s9djGmfh9BgxGcDaZ1exvNDN3DBZ4P4cvRPbDyWwN0vbuPslkm0b5jC85d35cUru50yrzFoWJRU+fBHsuF/T8Bql9/axI+EKI3nV7Xks9F7eGFVM+7vsYfx65rzr35beW5VG547ezPPrWrFgz138fn2htzQ4SB21aJ5UhWzDmSwKi+Zu87azcfrm/P6iNWsz0lldU4GqTEexrY+zJAmxzmnWT5jPu/A6GENgROa1rAsAoaFEBIvOh9Fn8PTsfEc6nYh7DuMKU+/oP17njjxb1a2FiCkRZQSAiFx2hSctj/ogqIgLQtpWliKckKoFEFtlQ7TtMgpqmLb4Qq25JSw51glCiG+31+fd1e2p1X9Ej4cs4rGcdUMmTiE6zvvo0u947yxujWPDl3DRa9obHxlJFF2HSGgpNrP4m35YFq43XaGdKiHTVPISIj6zW5aUob5AuoJ7//+gkrem7ebzxdtBaMx728MsKsoDr+hEOcIcazaRcvEKioDNq5rf5BHl7bj7m57uXdRJyZevIQHZvbiyja5vLymOVd1OMTlnfdy56zumKZKvNPH/opk9pe7+eeA7Xy8Kp4q12Cu7J0eMRtE3dHcMhIz9gUMlnW/makP9sRt+ukx7uBfKqD37+L0u3sjkAhMFGyWgUsL2zUBQzlROecUqJ04RREoulZnQAZCJjuPlrNy93F+2l3IugMVHCmuRAZ8kYRvgc2tsOX2ZZiY3De3G3dM74mimbx/wWpaJVdw47Q+vHzuWjYUpLP/xyIe/HIN71zfB8uSuB061767HO+OfG68tS/DOtUnZFh1scxaoz7sC6Iug0hRwwp+wZY8Plq0h29/OgABg7SsBKo8AV5e3gKBypPL2/D5yLU8sqQ9b5y7gUnbGjOuyz7OnTyARGeQrhklPDWvK2Nb5zB7bwM+GrmWp5a0Y2N+Ik+evYVj5W7KamykxvhpnFzFy4sbsqR8FFPu61eX41nb11inDbsW9nnaVIWvxnVF91Zx/Ydrwi6h0zTfJ+OMCZmGSaZpMSWhE8fsCWCF8Jrar/MZpcSyJKqi1E0cwOESLyt25jN30xHWHSjmYGEFskxhaJccpozczZBJQ6g0o3FEBzEtQSioMPjT/nx3+TLmX7uA26adxYLcNN5b2YooR4hPL1nCVxubsCk/jtfG7uaeSVFc1KMRfVvV4+uVh6gX6yRtWBtq/CEKK3ykxp5gkJqRDYaiCGpj6AcLq/hm5SG+XH6AHQeKwZL06pBJRmIUReU+9hdYGIYPC4NpmxvRNL6afWUxvLmuGa2TKnluRSuW3TqDp+f2YEzLo/xwMIPv99Tngd7beGpRB/o3OM6i3Ewaj7+Q3i2LyIz1U5HjZPGOGPp17sSiJ7rU9U1VBFtzSinzBIhzR0cKF0mcdpUbxy/jaGFBOLtZU08XafEXc3+aISPfK5Ro3ortwIf1r2a0OEq4nEgYlpQYpoVNUyOCFX5lx+FS5mwtYsGmw2zbf4SSQj+jBrdi4u196f/EHNQkhU0FDQlZOey6eyaDPhrMrvw4tKgAQrc4Wumk27tDebjvTt4ds5K9x+O4cvLZ6I4g10/tQ3XIxvgh63l8aSfOaprHbRPWsfPNevRolsK6V0YR67IRNCxCplWX86gqoq5azqHjVcxad5gFW/NYf6CEKn8Im6IQH+vk0Us6U1oTYP/RMvLKqgELhyOKqkqIi6tgdX4Ky/cn88P2+lzSM5+pO7IIaS46p5XS5r2h3NNjL1N31uPjHc2pQeeNlZ1JiC0j2V9EzdICfJ5C4ggy2BVNic3LszOcXNcni/SEaD5avJdx7/5ErzbpLNtRQnaiB3QNf9Dk6P5iHBl2BrTJZO66I2fkzLXTLmR2aeJTYrm4/TNcfuk53FgeJG/PQWpz7mszg2rZs2v2FfHd6hwWbTnKviIfZsl+Aiu+4LyzW9Lw8ifo1jie7k1TwtUVMTnu1ej73lA+vngFO+6ezhVf9+WrjU3AEUS3GximwvM/tuPbnVm8PmwD6+7/jh93ZvHg/M7YNYusl8cw+cKlXN45gSs+8XHLu0t4/7b+df23aQo27YSRX+kNMnNtLlOWH6DaH+Kc9vW4e3g7mqbHUljp5dVpW6mo9JISY8NhE+RXuDhWqeIvD9Iqq4Lreu7hjj47+HpTE3QVuicf4bnJGrrjIM9/FQuuLLKyPLy+rhkIJ02q93NxxQbahg6TdKCMBqEi4o0QWiQkZwioPKxxw/7reOrbwfRo4GDFlqMM79OIGQ+eywsz9vDO9DmgCgKGRYcOmUx/pDcVwsHclR+fkQ3maRcyIS0sofPJE2OwWUEufmE7/bNrHx8Fl10j53gVn68/zrz1uQhPFef3zKZj40TsMSZ9k1fz2oIc6if3IMrlJCnaRkG5F0Imqk1Bmgqj2uey8VgSB8qi+fKaxZzbvIBxM7pR47GjuYIIt5/9pdGc/8lABjQt4PlzN7Hh7u9ZeyCdDzc14/FFbalWmzLp8b68MX0jXe/+hqHds6ifFI3DplHtM8gv87Avv5KjxTUkue1c3Ceby/o1QTvJhdMwJYrbzmvNvR9v4MYJW4iOcpLs9DI4ax83jznI0OZHMC2Vx+d1Yuq++uy8dSE3PLAcbXM1mhKm4twwugHj72lPl/cHcO766dxeMhebIQkRFqiggLLIAyoJVwNKwcByJnBnl3WMaryHQbv6IRQdS0qu6teEGcvdyGDYI/DPa3ux8EAVi995CcVI4d8usPEXoCm/RfD/m2BaEsWl88I3G1iy4TD4HcS0BqSKz1C56IX57CkqZ9iK93j6tgtp8PBdPDx+Pt1bpKE6ghQfLMMUCkkZ9Sn0hGhVL478ci+YFqqiEAyptEgu55lRa2jyzOUs2h3P99csJeeBfK79piezd2SBbqDbQ0hbiMUHU+n+3jD6ZRfycO+dfDRyJZ6gnS/Wb2fzuh3c0KcLY98KsWHDNrBJ3PWi6Z6dSJfsRC7t24xezVNJiQ2nkVX5oaAoQF6Zn13Hqtl5tJyth/IoKj7EiOxSRrXIY2DjfJISAhwoiOfBBV34cE0z/Kag8NF5PPTyZj5fVI3druMLGAzrncyHzzfism+7MGr5d4yr/InjqqBKU1GQdXmraiTwbAiFdNPkscThdBji4pURc9h+sBGm30ZmfLiPIcPCaVMQqonbqXHrc7MYcehLXihawPrmD+Lh70/m+SW0kJQew4xsyU4DFEVgBQyWrDiElugkISmOgGGBIgiETDZtyqVx+1S++PIpSv5xBaWZKZzfty979x8l0QGrDuwDaRGf0Yj9viANUqJZtKMQTCu8/RaSKr+OZap0Ti9FSRjF+VOzuaTRD8y6biFzdjbirtmdOFgYB/YQNlcQ04JlB1NZtj+dBslVXNEuhyvbH6Z50jyM4AzW39iAHw7UZ+2xREoDJn6fyZq91Ww4cIw35wgCwQCGEcSp+lGsKhL1crKiS+meXMa4vpW0TgthWoKdxbF8sLkV03ZnsjE/Abw2bE4vOf9cwpdTNvP65HycDhWfP0SnlnHMea85t84bgGPKOm6r+ol8TUWT5ilriBlCIdmymOJsT/7Q3sw9bw75+Ymc+9UAgiFJ1+zEcExWE+RXmBSU2dlT6eT8fVN4pWIBG6MSKFOi0c9EfTJ5mrcXSpj8xMWDW/DYRR2547Od1PiNCGtWQagKV3dLR+1+FtqLk+G687h6yg/0KdAYmV7Jtp27cdl1ZGwWTg8gFNbtL/5ZXCfOaaFIQbFH59UbGpMV14xb3sui2/ifeGnwGg7cN4N31rTg2WWtKShxg81AdwYRwOEKF88u6sCzS9uSnVJN/0bFDGp0jEtaH+LOrruwKRbeoEXQsJAoSBQ0YaIoEGULuzMMqVPsdbKvLIbp+zK4Z2EimwrjKKtygaGAbqBoJprDx5q7VrNt5RZueykHh03B5zdpmBnN6o+b8+TGfuR9tod3q2ZzXFV/s0CdhSBaWuwUiXzb+0Kmj16OCEnGTB9IKK+KhHg7A9rVZ19+JdeNX8reI5Iek8ai6NEsajeKntV98cckUF4isZ/GbKVanHabzDAtNKdO/54tuG/abpasPMK4c3RA4guEsGdkcMflZwGQeNbZ1HTrxeJu/Wj85CyUqqNU1vg5u2dn8s142tePRgAr9x4HXa2rYO62hZcSXVOoqgmRmOXmmwd7sWB7Kx75siNpq5bywuDN3NptLxM3NOP11c3YnR8PSLCHsEd7MS3BwZIoDhbE8tHKpqCbuF1+6kUHSHT5SIkycdsMVEUSMFXKfSqlXhslPjuF1XZ8fhuEIoVmVRN0E9UeRHGEHaNBj8b0W9aiFW7mvPv2o+uCQMgiIdbB+k+a8Wl+XxZMKOWL0q8oUxSU39EwihCYBrzY9ipeuXQvaTFFjJs9lNytAW4pns5PvZ8hK9FF9u1fc27rDHLLPHz5j0H0bp7MukNlDHpuEeufHUaHO78m+Ce4cf8pTruQqYCBxjtPvc2VxxbQyNUA1dEesKixVEZmWThmfknets14NqzCrassOWsUl/TJ5u1n3wCge59z2F5icsfQeuQUVbPncBnCrtX5eMJZ+eH4YtDmIrR7E4Xz53DuLXdy7guD+XRJa66fs47mrpXc12cnN965i+W59XhvXRPm7k+nqsoZNhZ0A9UZQFXCtOuaoMaeIhtYsZHKdSdZFIokXN04XCdNswVRHeH+GJaCGVIxDRWhm4SqbHxwxSY62zfR/PI9IE2kBTabjdUTm7NK9uTtt2BKwQd4I2zd37JdDKGQalo8mTycUZcq9Gq4m2kb2/PO0ob8VPAA/3QO4vIh7dmeU8yhXYWsdOgcK6nhmakb6NAoieU786nKK2LchOWEguZfoi39uzjtQhZSdFy+Ij4/+hbZXj+fSJODsj2g04Xj3DH5acq8w4jqO5SUy27Cyspm1otrqJ9/iB9/XEK824mraS8oDdEwNZZHJ2/E8gTR4pwgT2JESAvL7uTws/dzbPm7FJebJI26HEdWDNf0r8c1/esxZf05PLxgHQ7/ai5vtYVJIxdjCCfLc9OZvqcei3OT2V/qxvRpYAlQrHBpbMUKn3iAPGG5SsJCJwUENQxLwbBEnbDWT6zBpZnszU3giRE7uarJRpqP2UVldQCbrhA0BEvfbkpFelfu+1ciXx5+GYFZd1zPqWAKQYK0+EFvQmBkJ+7qsphj+Slc8UMvXsl9B6evgo2t+zO7fSJfLt1L21bpXNijEdf0b4bbrnG80sfZbTJo2zCR/DIPRtD8W89T+i2cdiELCpUMsxyHGaBAU/BqrrqiX1Wqiyq/n8ynX+G8r8to9FMVme5tNNIDLPrqbYKGxWUjzmdNWSzX9K6HYVp8smQvOLTw2U2R8akNTSlIqmd9RdBjEjfybBxpmQghCBQV4lm6mEvO7sEl/xzEqn09+HbFQT6atomm0TsYnH2IlwbkEOMQFHuj2VEUz+bjCewsjuFguYtir4MSr4ZhaRgyTBvXVYmKSYIzREpUgMZxXlokVdEhpYLmSRU0Si/j7u+70zGtmif7raXLRTs5nO/BYVPwByXTX2pKRueOnPOvxkzY9yrx0ks14neY9wIdQamp823P0Uwcsg1Mk6sWDeDs3cu4sXwjn7mbk1E/jWi7SkGFjxG9G9M8M5Z35u5i2TPhkl8HCqu455PVvHhlN+asyvl/qD7Zf4jaWJ8qLZTaaox+L3rTNqRcdzd5N13MPc/NYcLUFXx1wMudzY/z3JwFxLsdZPW+mF3HfFzUK5v3Fuwm/0g5aqwD0zwhZLUB4JBhEP/PN8lI86ING4uw2zHLS8m5rD9VP+4h6Y5LaTT+S85q5uKsZh0I0oElu7ws2XyIj5ftx2bsp0lUDm2TixjasJBr2wRx2yxURcWSIEVYY0kp0BSrrgK2lBZVAYWiGp29pVHMPpDC9993x+4wmHvVMobcsJONuysiO0mTdx/Mpv957ejyfHte2P4mTcxSyhQFTf62fWQIQYph8WTaMK4e66FewlEmrO7J9lUGi0u+okQRqEaA1GgbUkK0U+f+lxZBvAsUQdNxU2mRGceyXQVUl3uZvf4IGBZnYLU8c7HLkyEILzMNbAFaP/o0Bf3rkT3rTQ4a/XhkgJOPHr2HkGlx9XXX80N+DE+NboYnYPDE5A0Ih87P5qI201sKKqpMdrVrjvvSzgCYpok/7zCe9XtQnOBu1Z5wIRAV3/5d1HwzmcG33cLgVm2ANhwqCrG7DHYeOMaPRwupqikl4C/FYVUizBoUJYQaIfn5TRWhOPGbDvzEotvjcThiadMojU+3FhMoX0XOI8u5+r4dzF9dgsuh4vWbPH5DA266vhUdX+3Ovesm0iN0lKLIiSm/BUsIYqXFEi0L67w2XNZqGfmFqTywqC1vFryMwwgRUCDW8FBWWY0Q8NOuQkaf14Ybh7aipNpP2/oJ+EMmd3pbc7TUgyUlN776439HWOlUcGjhkxGMQBCHQyf+8be5/97xPDn9Dj69dxR7Dx2lT9d2FNQ7n8aaztBODbj1w5UUF1Shxjp/ni0UpraCopJpq+DlK/uy96tePPrkM3Tt1o2oth1Jve8utJQMkq67GwDjaA65lw2kZkMBwWAV6Y+9jiokjVN0Gldv5bzzWwANAQiZUC3AY4GnxIhMikAIicOmEh0jiAZqGUuLd5by+dy57HtwOQ8+t51JcwrqBOym0Zk89c/29H63L2OWTWVEYDcFfyBgkdYwDMm0jufzwsD9IEPcsbw3vXevYGD1fo6pGimGQWlKFrtyQhSWVeMLmjgUwfS1uazcXcjq50fi0FXu/mQ1W3LLmHxPf1CV/44A+algU03QVA6X+Vi7t4j7NsSTfM0jzH3xVqb/sJgom6Dl+bexy6cz7/6e/Lj9KO/P2IYa7ThlOpppSrCp1C+YisDLzB8WMmfBYi6++GLuvuceuj7+Rt21hmHgy9mPd1sBehw4GzcNF+4N+Ml/5UHyX3yVuLHn0ej9aSiqgq5quLesxLZ3B/UvvvkXLRtYOfugUSsAVuwt55IXvmbbXct4Z+IuXpp0tE7ALjg7hQmvtubq95JoM3M2twTWcVRR/9AZagqFRMtikrsr3UZE0SJ1A4t2tWTRuigWeaZTblexm+DRVCamnUfbhAJunrCar+/tT5+HvmfW0r0Q5aDV3d+SHOPgcHEN0U6d1nd/B4ZVF+w/nTjjQiaJ5DpqCvllHka+tIYPbuvMty/fyYSvp5Ec4+TqB15kXnkG8x/uTplXMuipFaBqSHHqSrq6GhY8jyeEFAKHTSMQNPjqq6+YPHkygweew4033sSQ84bhckUR2/dcsp55BJFRn/hLbsSyLAK5Bzj+6qtoUeBbsRDh86DExuPbvZV9YwcSPOYnq6KKlJv+gTRNZCjI4VvHUjJzPp2nfcfGpoMZ9cx0Vty8nKULd3HPa4dw2sMC1rdjPNMndOW+jxKY9NJULo2uoSpFRTXNk4ohnBo6kkLTxoYeZ/NZ511Yfid3z2vPnUnraDOsPlVEE6/7uH1lL1xx0ay48XuumlxK/yc1DIcbLdnCrKnh1sEteWBkO2ZuOML2w2WM7tGQdrdMOU0JcWHI2kNVT2MbJxpDYIlwMFe3jEgZqTB1uoPzIF8+/Q5TZy4gNc5Ji4FXMq+6GV+O60y0y87gJ79hXKf1fLW3OaVVNoRm/cqOiNLD2kCRoTq/jxACNVKCYd7CRcxbuIjs7GxGjhzJqNFj6HH/sz+7eWd2C6KHDqDyxxXUe3YCREVjWRbenZsxSvyoLvCsXIS4+f5wUcC92ymZ+QOxTlj84AMMbRJk0WVLKdy1i0sf2Y/dJvAFTFpnR7P4k458uiSK115djk2pYXKNhluXPBIHZdZJh7/+AqZQiDctPk3sw/AhAeJiivh4VRf8+X5uTVpEyV4ndoefzaUxTPa0Z9Ol81E1lesarmbgwz+Cw46W1BAlvQPj5+xi4dZ8tuSWUOULMWfTUU4UVPj7EakU7oWIkJ3OGLlEYJdBYkwLO7AiqgVNpQBVJX7/ZOYv3ABAXJSdzHNuYXdSX6Ze3poWmbE0+8cyurq38eZ1q+jzYzUXfd0HRTMjp3qffEeAKfFk9MM0v6lbUlVVRYlQtqWUHDx4kNdee43XXnuN7IYN6NO3HwMGDqRLl85kN2lK0y8XgrcaXLF1H504bCwlHZ7B9JtkPjcBywrvKm1Zjcns15HKdZu5wX4xH49eRapnG+1u342uQSBoUS/VzZrPWvHh9vbcOqUeDnMqQRkOS31YJkjVVG5wm5SY4eMIfgkbksOWk9weXXim1RYClW6eWN2WO5MXE5sVS7miY68o58GywVzRNY9maUUQjOOtz9YjCouwC/DnLmfMsFU8fFlPur7VBRm0gSLZX1AJmjhthn9EfA0gXM/WOo2hBVWalKrRbLdn8GlUR6ZljuBf5noQCtW52wAY0Ls7+xMHUlO/Bz/e3YO4+BhaPTgH95bVrMxuxP49mVzYdQ/X56QxcXUz1KgA5kmlblVFAU+AmvQBvPvpJcyd+hHzFi4iFArXrhAReq2qhksZmKbJwdzDHMydxKeTJqGqKg2ysmjZpi3tOnakSf16NG7SlPT0NBKSksj8fBHO6GjUuMRIiwpEx1L5xNdccMfH/OP2IOe6V9F87B4sK6xVY6MdrP6sJcvL2nLr5FaoaS6MNhcjN3+NJTRUYfJsMSSrKiOcJqXWz5cVUygkmBafJJ7FoH5+nM4yPtjSHeVwOdc0WI8nKoG4QIBFSjtWq02Y2nM6luZk86ZyZv9UEi4VoSoQDJFg99O5STFZCSFUNYO3bu1Gq/oJNLr289NEiwijlt192pfLKEIUKmlc1uV5nrq+D4d/zKXaF5786MwmdG/YliZjxtE/NZFHL2jOin3FDLjpc65f9y73ejdxd+Fw7so4i7mXz+bFgZtZcDCNvHIXSmSJrHNhCJWjxV6GPTiaW68ezc6dO5n0+RdM/fprjuTmALVnuIWJ+JqqIhQFKSWGYXAoJ4dDOTnMmTWzru+qqhLtdhOXlExUVBRRdhsOlwuHzUZNwGS9pzETHolmTPIqWl24i6qaQDiFTmgs/6glRfYWjHyvO4pDYIVqkM2Ho3hKkfsWgaohTJMHiwRJ6SrdbSYVJwmajqTQ0tndrguPtdiJ6Yni+eXNeKTjKhx2QUWhB5dd8uiOrjw2Yg8pcZUgY3n+452YpoWuqRAKgbM+enQ8lgHBYIBPHzqbs5rEcvlriyFgnJGw0mlnrBmWRLcJlj87nOwoi01b8nA7dTANfO2v41jDy+nXKpVHL2jJ41N20+euxVwVmMtjbfdQ1j2J5zqvYleBi2k7WpKYXMarg7YgTfVnD6CMlLrxhyx63z2V2etzaN26NS++8Dz79+7i+n++htKwF9IRW1cmyzBNQiEjnBmvKKiqiqZp6LqOrut19lxFZSW5Bw+wc9tW1q1fz/Jly1iwcCGrli/m4xFLuLb5ZnpcvZtjxz3YbQohQ+GHt1pgr9eSzq+cjYGKoplIqUDIh9XpatSGPeoy4P2mxR2Fkn0hhWgRPkzMEgoxlmSeuwPtewriYoqYviubkgqVgWIn/qg4EuspvB06i7KG9biv41akFsW6DWVMX1yIGjlPSrhiofXl4cpFWMQ4VZ6avJHGt01h5tL9YNdPlIg4jTjtmsy0JKpT5/YPV7J802EwXOF8RL8gLjqO758cSJzbwcB/LSYtMIuLOiSy3eqGv10u8YUWdj3Ac1tn8fCcIQxtepix7Q4ydFtDfthZH3uUnzqiSqRGRd929Zi0ZD8vfruFET0a0q5xKl/lZWB0uZlEZ4h6levZOnMCbj0cYPcated1yrBgRQrwCUXFZvv5IRiWJdFU8AcM3nioNVdc1YizRq5kd04VDruKP2Ax+fnmdOjRir7vdmV420KWHE6kpsaOYg+FWSOhAGbXm1ECNVgFO9BUlTLD4rYihS/TBPGKxIskYMHqxt15pc1hCGi8sb0V15srSa2upJxo7IkmU4pa8ECP7Tij/CBjeHZiTriPuho+Q73NBRCVDoYfCFPcV63KAZdJ0+ap7M8pPSNhpdOuyTRVwV8dZPm6XLCpuGKcKDIEIYnDZmfJ3ioaX/cF3dRP+eKGTXx1yVLW5sfz4YwMbFWVVBYoDK+3nxTFw4sr2iGcAV7ovw27w8CyavM/Bcjw0YMvXduDqQ+cy+s39qaoKshDn63GV1mBFqwmNS2NMUOH8U4qzM6EGZnwdrpCXzdoUmIa4UPlhRBYpkEwGPzZF2YIfyDEA9c24q7bGzLy6nWs3laGy6HiD5i88Y9sxo5qRv0nu1JUFeSz0fPYevtszmpYjBXUw5lXkWo3Vs87UBIbYZommqqQG7C4vVjBj0KclGxU0kjqHEer1KNsPVqfXXs07mq5i0BGLPH1NNaWNaDScnJTx71IxcXaDWXMXl4UflBCBkpcJlaj/iANNJsLpCRomDRolMDqV0bx9d39IGT86fOZ/iMZON0NCAGYFp3bpvOvSztw96S9hAwvaBo/7a9mxndPwc6p+MfoMKYLqlLJ24M28NC687nvKpMYCxSbwcs79zDwi37c2H4f7RoWcF3nA7y3skWYbhMxzEKG5IVvNvPERW3o0iSZLk2SueFtPzuPVhCqMdi1p4C3Nh9ljUvikwZSEbRwSFq447ih86O0tOez4LANqUfRVM1jWMsoDMOgprqagrwcFqzcweUD3bz4bCuuv20LM5cfr3O2PnxdQ+66sRlNn+/Oxef0pllGNC9vbcwDHd5n9lWLafXmcI5XO8IuGCuEVO3IXnehLH4Os6YITVHZ4rW4p1Tj63iLNaldGdW1GNQAE7Y3oWdiIQlmORXlbqJ8Xp7ffS5XDTyGy+kBEcurXxzGsiS6Hj4zllYjsDR72PpWNSCcavjuPQMptCxufuWnM5Z3eQbOORcIBUaf3YIP1xayb28JbpsGmgN70RbUbe+hW6W88U0xmzaVIhUXV3TcR2zIw8tzmqIEq/AehR4NjtI3s5hHfmwHqsXDPXeTEOsFszaPPBwwn7bqECOe/YEnp2zkw4V7mDhnJyHD5MYRbclunMyN5UswTQgIBT+CQAgmpQ7kuKsJuQn9MOObocZnkdbzIt547VXefnM8n37yMe9PWUDjix7gsxc68cQTO/n4+7w6AbtuZCbPPdqSXm9354rhY/lkXDceHt2Km8eMZdiXI4hxeLm6Yy6qoaIrVjgD3wxgORKQve9GOKIxrbBtuKzKYFRJNMfbZzGsYS7+iljm7U/jWt9SQqbA7g2wq9TNwdgsbmqxB6k62be3mplLixCKghEyURIaYGV2gaC3NrALUmLpdh54fjJFlw/i7K1TwKafVvdVLU67kIVCIaRu5/mPFtHt3dsZU7GQKsUBloVUdEwp6ioGPTh+f92JQOMHb+GFtS2pCsTizFDB5WL8RTuYfqQRBw6nUj+jhJs6HQK/jlPzg6Uihcasx4fy9f2DiHbqvD9vF/ZoOzoWB0pNrjw2i2uPLadGVVCkxGlJ8lwxfJvYD19pEbsP5JESoxJls6gfLXliynremr2VBz5dx/lPfsfGO9cxYdJ2nv4wp86bf37fVCa+2opzxrcjFN2HGLWGHg/PpMYXIivOZJ+nMXvyEmgYU4NR4yRoqKiKDAua4cWKawBnjUOoOoaU2HXBao+XDGUl9rggS45kYuRX0yu1FDM2muiWKtOMdnROKyczqRyh2fjyhwICQfNEfY6mg5Cq46TzRwVIi5Bmp++uGVxatIUHK+aiml5Mcfr1zGlsIfyEeEKgBT1MOvom91ZtpUHNEUxFBenF1aAdJLfDDJmomsaitSXMXVKE0F0MbJpLm0wPD3zYkJqPd3P000Iypq6kf85q/rWhA1iScV32ocX6MEwBQsEiXB06IyGKwR3r4/eHCHiDhITGkvWHyd6xAGmL1M8QghhL8l78QNp1aUvrBrEQlAzqlMW8x8/j/K4NSY5x8sz0nbz88RreGTafxYt2cvuL+3HYVXwBk57tEpg1oRWXfdKaqMxRxDm83PvcIq46uxlup44hVYY0yqNRYiVjWuUz7txtNIj1YfpsEVNShUA1VmpbRPebULEIWeB22Rnetx6EQkzd35CzHEeIFj6CIQvfHj+zyppxQ5ccJAq+ihCTfygEwDIMlKgEZEYnCPkipU81UDRAIcGoZqBnJwU2Ba+w15U0ON047WLsV2zUCxylQ/UhjmoKLhVUGa51qatAq1EItfZsb3hywiHMoESi8EK/LXxxpDmlRhx2m8RMiOYfgw/z7bZ08gqTyEwvYUSbIxR43FiKhWkanPf4HD5YuJtXZm5n19ZjDOvZiG5Nk7mpYCo9AkeoidxxlGmxJSqV7zLOZfueXA4er8EV4yAYMuneNJlLe2dzUa9sqj2CeQ/uIur4RsY8uBe7ruAPmDRvFMPKSW24d2ZL/PGX8srlTflpQx6Z7TK5sm82AG/M2sbLvWfgssPuYxaP9l5N7n3TeXbwZjAVFCKO4kAVZoNeqF2uwDIt+nWw0b9rkFC5ndUH4xhYtAFvCGI0i42yPv4YNwMy8xCagzVbK9l/pAZV1cIx4fpdsRxxIA1qPa0CCYpG/VApKcEyLKzfzSH4O2CYRq1j8szELhWhEBQKdmmdRC0WmAEvJDdHyepCKGcdqqaxfkc5Pywt5vzBqfSpd5gunTry1d4sxiVvpjwumvYVe+hUtpc3trXmlXqLubXjAb7c2QhFhHBoJuf3aMJL328l91gVttQoVh7y0LdsLf889gOldgUFCwuBArySfRU2dxze6go0XcMEymsC3DlxFQnRNl787iCvD1tJI/862t68G02TBEKS9OQo1n/Rhrc3tmba4aFMuq0eo55fhL/Kz4Wj2hPttHH1+1tpHnqXqhjBhZ+MpE2zHuTvLaOVYy4vjFlHmd/Gq0tbo7qCmJYKgRqspudCKJ4G7Xcg1RA7ipIo8dkZcpMbl1RQLC/L1iTSp3cpDpcPRAwzlhZFxthCCgGZXcA6IWDU/iZU4owaXGYAUwebZUTiyP8FzthanFy9RxVASFATUEEaWM3OQ6gqIsKrennSYWRIIhXB/e22M0nrjfPSxqSPyCDmhkY8du1xJm/KxFsRS/8m+dQENdbuyyQtRmNwlywqvcGwY1+34Skr4ZK93+DRw2dAGUIh0bD4MLEPeS0HMKhlLLImSKO0GBY+OYxbh7RiX345T724lkf7b2R0+np6XLcLwwgnf7ij7Kz9rCXzjrXkzm+6YJrVnP3EXHYdKYcYB/ee15JbP9lFVMkHXN3+ICOmjuX9B27n/Vu7M+OfQ1lScTHfrmzAA2ftQ3cYdecEIAQEfdCgDw06dkUoHhblptMkroZ63QX2Dgm4+qaytmMfhjQ8BkIhWG2wcHUZAJZhIWIzsOIbgRE4qeCbQFfNSHzXhEhpeyWS4PdfsVz+Ej/z1AsBhh8rIRuR2QnTtFBUlZ82lbF6YzloToY2PYyWYOP7Y82wxYQIWk7ObXWMeEeQb3c0RI32MiS7gN4Th7L+qIOnp6ym3BMk2mXDHh3DM4c/ondNLj5FIoUg2rTY5ErjjQaXkZObz4zlB3HGOrn7/Db0a5XO6O4NqfC7uHVsPve2W03Xq3dQXhVAVQBF46eJrThAc55ceT7XnNeEvIPFKKoCFT5uPa8lU9ZVUrr/E14avJv39l3Ju3eOYeHqbXywcA9IyaW96rMmL55El0HI0LACOqoS1icmAmQVXZLywFJZfiSZ3k3KQFiohkFxnoPCYoU+9YpBsbHnkIe9udUIRcUCRGprpO6K0MJFHWPYkmHDP6g7sTT15MNWzgjOmJDV3pdPKr/gMAmkZSKbDgrTc0S4cNuE7/IQioqih7ip3QHeXpsNEkxTgGZwdbscPtneCIIaFzQ7SnSUD19IY+O+AqRpURG0c9WuT7mkZAPFmoIiQZdQIzSebXsniclJKMEg/bo0oG/7TOZuOMLYV+aTds10EkNLGT9oFT2u2cqRQu+JcNH4Zjjqt2XA87149ZpuPDSqLWlpsaghk1su6cDInu1Zt3YSE87bRPeJw+l/1ihenLyUez9dz5AO9RBCsOFAER1SKlGja3j9/I00TPBgeOwIIZGmQmx0iHYpVeBxsK0ojlZVhwnu80CNjxW5SSS5g6TGVoOqs2Zb5c/OgJLJLeAULFsTQLEI2B3UYEMRYUr3mcIZ1WRSKHgt9aSiUYQdgoYfmdgckdwMw7AQQuH7JUUUHPWCdHBFmxxyK93sL0jCaQ8i/TpXtDnMgbJojhQkkphQxdAmheC1A3YsPYqxRfO5L282ZaqCGqk2GGVZPNTwag4ktyLDLZE+gyvPbsq8x4by1MUd+G5hPg3cu5lz+VoG3byVbfurcdpVAkGLz//VhFbd2zDmsw4M7lDCC9O30Twznu3vXcLedy9kSI92bFo7gW8umc7rW/ry5l03sn7PPhbO3cs/L+tCVrKbdxbmkX/oB67oncf2/dH0SD7Culvn8ML5G7AMFWGoZMfVkBTr4WhpDJZQaF+5n9IfyqiZeZRZc3U61a8CxQBLsHpbZXgMLRNFd0BcAzCD/FJNhRNtTEJOF5VaNE4ZjnAEFP030+/+TpwRIQsvBoI4aVHqiP+5kEWukIoGjfoCoEYywWcsLQabjYTYKnpkljJpe0OwG/iDGumJFTRLqOK7vfWRjgB96hczusNBbu11iJjy47x0+DNqhAJCYgmFBMPihaxRLEw7B8/x42zeUkCDxok0TImm0hfg/YVHaZFZxuqb1zD23o0s21SOyxF2VbxydzYXjmlBx5f60T69gnkPzyZb/ECXR5aQ5LbjsZxc9dJXXNNkAU8vPpsbL32IOJuHJ77cjFIvjjuHNGfxrkpe//ob5l65nAdmtuTWpTfw6OY7GfDJUMa0PMTnY9YgfTZaJVeDw8/WikQcJeU0qC4ipCtYNkGBSKBzWhkIBdNrsnV/NQCWKSE6DcsZH3b3n0pLSYtKxUlI1TEshfHOXhhnqhbG6W5AItAwiJIWb0V34JuEQbxo7fjFQChh2yy9PYorFvzhJ3TqwuPccml9pFS4ok0uT/3Uhn8ZOqomQIdRbfKZvjOTewbo9KlfzI7iWN6+cBkJsjtPHr+Af1V+T6lUSDJM3qo3mA8zx6L4KklJjeGhG3qz52g5j3+1lr2HfQhZwsH7V3Ln0xv4bvGJ7KL7r8rivltb0un1PhR7nUzbnsX7P3Ri4rUbuOQDO81uCTGywzEO3jmNWftbsbxyNHs/XcHXq3IwPUHO7d2IIo/CzW9OZvX1C7l7dktk+i2suK81AB8vbc2oKX623zuL51e0JM3tA5vB1vwYujXx4GwTjSiHinIXu/xJtE/KBaFRXB4kJ89L2IS3UGIzkZodAjVhR+/P5iAMgeDR2NG4m9Wn4Vm9Yd6WUzzwf+fcR47POm0tRGAnRJGSyJBGD7L+hjdJya5PMBD8+UAIwDKQznhERodIjQuV1VsryMn1IoSNAQ0KqA5q7M6LRfd7CR2TnOs6yKESJ+UlcbTOLGZjYQLfrGnOM6M3snPIAJ6LG0aKtBhffyivZF2JbnmxhCDaaWPc0Fa8fVMvujWvR2V5ETvvX8vr723gnW9PZBdddX4GLz3aigHvn8Xmw0loriAB4NYZ3fl6dXOm3LCKdH0tszeU8OSiNqwL3UTzFIuvpm9F0RTQBAKdsS/M5vtRs3h+WUOOOa9hRKcozn9+PoUVXq47OxVXVBJmDQxvVkhWjBcQ7C2OoW2bIFEj0km8pAHyorYoSS7quapA0Tha4KeiJoSihBc8GZMeGchTLX8RKlQgSIMLL2fGB/dwUYckOH0Z5FKE59cDZ0CTaZZBpSORya/eytCWCTQdNxcjUijlV7AsZEZnOLAMTQtTan5cX8YNTbOIclXRtl4NX3wA9ycfpDTkwC39JAV78lNBKiNSS+jf4DgXfTqQdfE1rL1iGh2rL6Dvgb4cik9BmH5CQRNdV0mNcfDWnO3kl/oZP30LOx7ZwvSpq3nyo6M4IwI2tFcyn73Siosm9WDJ7gxat3CwK89AKBZSlVw2pTexjiDL7lxEt/HDeWd1H+Tc1lz99gpw2QgFDZo2Tmb+pgLW3DgLb9Bim3kZl3WL4vxx33Lnjb1IjXWybE8lAX85itsi0WVQP8YLhsLRaiftNuzEqxQhDY28giBpdi9xjiAoNo4eD4CUKGq4eLOITqvbVZ6Y6vB2Syi2cGFiXWVom3ge/HApXy4+AJFz1k83Trsm8wUtElNcRJk+ejw4jQN7i4h26j8/ggQiQeMgMqExwhUX9ukAC9eUgRUuOdE/s4BN9dpjG5BEdM8kkvrG08JVypLcFFAkndPL6dGohNtnd2V/SRxLr52LJzMB/CCMIK0bJbH9zQv559gO/GPSel74aD3Lb1vPvlWrueXFnHC4yG/SrU08c99vze3Tu/HN5mx0d4C2WSm4HRoyaJEUZyM2xsboSf1YeyiVn275gRb1DjNxaQGfjevLijfGsv7lUQStKKZcuJTymhomH7+D7//Rk/snrsZdP4F/ju6AEIJ/fbuJOzpvRjgEa/LiyIrxgN9OdcBGS3sJ0ggfopa7upoUVwChhW2uwwXe8LBF6nOYtphT7iwRImzvSlCF4J7xy/lywe7weYancYdpWSf6ctqFzGFTKSuqod8js1m74UiE+vUbT49lYDniEElNw0smgrXbKvFUBBFo9KpfTG6JA3+eiWpZWB6LrmnF7CiJh4BO84QqkhOqSIxx0vGdc7CAldfOJs4RxKE6eezC9jTPiCXBbQ+Xcrp3D+SuYtRDB7DbwuGiJlnRrPikNc/81JV3F2TTo20UibFuohwasS4bBAzaNUgiI9GOzy8577NBHC6LYcn1C/nnx9P4ek0BvVqm8cyMI1yVPZsRLQ+xsOxmxl0wkJvfWUzZsSr6d6pHSqyTu77Yxw2Nv+LSjofp80J/5uxPpWFsDYbPRoVPIdZhYtSYUFnD+pSWaC5AGIDC8dLIAfXSQtFsaK7fMfoj4y2EANMiLTOOYd0bgmGeNj6ZlBYy4qw67UKmCJAhE4dT5/ZLOtO7e8Mwx/+3uOVCQSY3j/yqcLTQy77DXlB1msVUQKKLjeXpaEerqcoL0r4yl9xSJ8HqKFqnVLIyN5pHrr6SN28dTue3ziEtpoa51y5GYnLF68tpdfdUutyzkNdHbaFZ4CcG3LEXXYNg0CI10cXaz1rxye5OPDa7DcLlJyMhmni3DV1VcGoCYVpkxLsABaGblHo1+n84EKFoLL1uPvdOmE2Lm2eTFfyMh/rupct7F2A4GnDxC9P5avEBcGpc2SebedurCOW+y7Dsvby/bSwXnHcLLVMt3LYQlSEnmgUp0UGkrqFE2/HZXMTbAuEZsySVNSc0hSk0QkLjd1OPFEFNIMSAng3JeesiejdPAX/ov4Pjb1oSYdfY8+YY3r6xD9Xe4O/vZ0wD4huBEKhK+GibrftqQNVwOf3E6QFWlKehpYGa7qZRdBWOiir2V8UhnH46Z1Tx9owd9G7m5rJhw+n/wQB6NirkuyuWggW7d1bx9JAtXJS+grNu3IVpmlhS4nLZWP1JS5aVd+TmL9sTFWtij3bgCRi4bBrHiqvID6hI3UZecTWGaSEtQZRbUhqIY8CEQTRMDDLrsvkcKsyna2qQy2eO4Jye5/Dmd6vZcKAMbBrRCU6OlJlsX/0izw7YTbePR9O33w3EOWqo8vqw2UzKfBqBkESrrsGf58U4HMCsMkhwR/ZrlqS0PLxcSgsUmwtFs8PvpepKiV1V6NK2Hld+vp1HvtyCiLJhnIEieKddyKSUoClM21ZCywdnsnVLAdFO269tMgireiuEjEpGOKIRkXV9677qCG3FpG29GgK7SzD3VlJzPEhMQRH1fMXsrowDLUTLZB9TZ++mw33Tef7iZhxXe9Jz/ECGts9l6iXLsMU4sAXKOfum7VRWh1AVkFJl+YSW5DvaM/rjLjTIcqKogqzkaA4X1+DxB5m1vpBmhdtIsnlYeqCKo8VVIATxUS4u6JnCrhw3Qz4+l05ZJfx4y09c9Wknencbxv3nZYHfAl+IOJeKZk9k8Ypvub/nEvpO6s8VQ0fw1owV3PDofJy6CapJdVAlFJJoQoAmUBwCw+7ErYciZbegxhepzSZBtTlQNFudof8bE4HQdV764EfUCU/zQd7baDKAcVr5ZOLMpMTpikD64Y0XJvJk/nfMi+5KjUg9tZGKAMtE2qJRopKRvioAdh/yQDC8DW8eV8l6dwO0DkdxhFzoDcFa7eJQcbhoXcM4HwD9W6cwcdlxmtnX4gs4uPDDAXxz43y+dkQx6q4COOZH0xRChmDu+Ga4GrWlx8vdQZO4ozRKvUHinDa2HCgk6IjjyvL5PJ37NTmORG5peif7XI0RhGOabruDuAyFZXn1GTupP99ev4gvb4In5qVw8zmNmfrUeRzJr0A445i5eBbTLl7ApK1deOK661m0eReTpu+kVY+mJGnhIsyWJZBCoMfqqEIJEwcUBfWksylD5kkPqaKFN07S+LVNJiDaFc47NVF49fgn3Fi5mf1uFzL575zpX8+llNILZ0CTBYSGO1TCzII3uahmHw1rDmP97tMjkaqOcCfVbQ8OF/gI+SxAITumitX2Jvh2+wjsLcXYUUmsp4ojHjcIQaxeRafO6Yzp3Z6J079i6ugfsekBpu9qx7ivenJBp+3MfcJHVHoTJArfPtuALn3a0Wt8T5xRLmx2CBnhZf54eQ1BJZZzi5byeO7XlCsKGf5SPt73Gg2Dx5CaC2ka7C+swmF3kBYb5LuNjbhtSj8u63OIm1rMYOzrK7mwZyNuHN6R75b9xPcXzWLcrNbEtHycFmmCCd9uw54azT0j2oYPM7MsQsKOYpgYBR5CZQZGcQDF68HiBO/ur1hSYbNLIVb6yfYXkK8qeBTnH73tP4ZQRADOSKVFjVSjDFfQQ6GqIFXtdw/tivQO03kiW7uoLEBZVYDUKJX60V6w6Xiio3FFm6iajU5VRWypSgVLId3tI79EsmfXXOZdOZvbZvfnsuE3sLBfMu3vj+Yfn/t45ZrdjGcgN0xtjNpsPx3Ht6KsQmNovwTW7i8NH8NjGByu0Di/bDEvHPoYrxAIJDWqQnKgkvf2vs7lLR6h0JtI6YHjJMa4qPELRJSP91a1INYR5PmxK6n5bjJZN1WS4Kpm2vCveW1lNsWua6isLuO89zcgNJV2DROw6wpHSzygqyjSwNB0tPounPF2bBL08gg1CkCAw/bX9YMqLQQSRVp1ZwGcLkgpkZZ0wBnQZGG2iYIlFFRp4cL840YlqK64yAcIqjwmVZ4wLz7B7sNSwKtoKCGBWSVJs3so8WpgCJLcKsI8wj1tZ3L37C78VNKDwpI8bn5zORNvbs+PFRfw5swmXH/2Vu4YUM2oV/qSndWCps1isOs2nLYwry2kOhlSvorxBz7ExMIUYZ+UJi2qVYWmnuO8u/91HL4qPB4DXRUYliQt3o0zOsgLP7bl5bldeGrsFgbXW051TQFvr23GpuAVtKsnuOaZeRwp94JdxReUPPzF1kitMIEmDAKGwAgIZMBE+i2kCRU+pW5Qo6P+vUMezhT3QlEUBMIJZ7B0VK32Ovn7b0OCLRoARUgME8qrQoCNWD2IX7VzoNhNsutYuIR7jYdQjA4oGKZkeOtj7C6vz9R9PfB4c3jss0NQ4mVQl0weG9OWMXfn0ShZ8uboJeiBElzZ17FoawBPIHQSiVBleOkqkIKgUH4WSNakRZmu0rsil1sKvuflzKvDZUqB9IQoyjwBVGeAB37oTFqUlw+vWsENnw/k9cU98MzuQu/H5kLQBMMA1cbuIyW8NHAb0/ZlQVDBoVnoiiTkk1j2INK0iBEB8gJ6eOgUQXJCeLkLpxwa4SLNv+vzkoSESkCEj3Q83WepRgrdnJnY5algyLBs//Z9SkKKIzyeSphwV1bpB0XBbbOIsll4hI7q0lBcGlqcA29IB0Mjw+3lg9XprAiOo2NjO4pB+IThJCffbyjn3e9/4I3Lt3DBpz1ZvD2LV6/aQKrnG9ZsqaK0ykOlNxj2HUmLmfE9IgzSX/YONEsSUGCvKwtZWw6L8AYvrJAkSIurpvflpz3N+OiSJQzvuI17vtzHh7f04pYLO9G/Y2Ok32LzuB9pEl/GnpJoUBRi7AZOl0pQsaHbFQxdo9vRzSg+C6QOAmJc4faEADPowwwFT6S//eaoijp7+EzQrmtxZvlkkZ+m1EAqhKzfuGEpUXT7z/4bDIXfrSoWNtVEsathFqIwsdkiZTaFQoU3wNDu2ZzTJoUV245hAVcPbMr0J0ayfsdmJp77LRWhAGmxiVz0XX/W7KjHTd3X0bd5Ppv2+fCHgkhFxWb5mJ/ch48yziYpZGKIk6uIKcSaFk81uogZyeegSF+dEVBS5UNTJGaVgyfO3c3sUbO45J1UiqtTmXHdKjau/45PfzrOY1d2o02GwuJbFrA1X+G7witIjnVS7VFJdATD9p/uQHFrqLEO0jvHUuB1hE/xwqJeWljKpAAZ8iLMIH9mOk2hYAoFmzT44xXl78EZEzJDKKhAyJJhVqYl8JtKJAP8F5ASTQ8zOGsDuIalAgIFA4mkulJiVQYxfRZmiReBBQr4AgZnNU9m0fZ8RIWfJlmxTLitP/PW72LlNd+xsySRuOYPcezz0Xz/zzGM/vpcjpRFsfCGBXSvfxzTa0NTJS67TucGUTybfhWT088iJWRiCoWg0HBbFu/WG8yk1AuI0/ykJ8cQMsOlMY9X1OCttDGmSw5PDtvKzG+XkD/7de54cg81AZ1Vt65k2erZZI6ZQSd9EjIY4F8bbqJ1dhNKyoNUBmy47CFS9Rr8awrw7irHt68acbyKUp8NTyjsD8tKCx/QJREII4AIVIU19u85/ZHEGh7STYttjiwMxf27Fbf/LpwRIRNIUgwTUxXMj+tat7P5Kwq7NmIiRHg9UuPsOJrH4GwWiy07LsxjNyVxUTamrDzEhPm7kbrgX5f15KnJq7k4eTw7ilNYZTxEi3QHj36ymuRoeOH68+n30TnUBHRmX7OIZqlV5B03UFVJjENDV00ezr6FT9L7EGtYZAYNNrvr82rmZYhQNUJRSI4JL+12XRKs1OjfLI9vr1vL3Y/t4YOZpTh0g69n7aLdsz0pDrpZectSWjYsYc72RpTG3cEHN7fniU+WUuJXqQy6wB4kyg3HmzTG3TQKW0MXmU1sVFVBsc8JlkGDDCeaqmJa4TPaqTlOpNjGr8cu8tMnNH6M6cSz8T15qMnt4eoOp0ebCSktkNIFZ2J3KSVB1c4HMT0Y0uRBNqf1wmV4kX/gabYs82e3LyI1LyQahtTCy4QnRDC3mqqcEA6bBExsNgc7D5RSWlrDW/84hy9WHGV4zEsI1cngKcNZvusIQ/75Pc9+vp5BT8/nqj71UNzZ9H5vIHEug3nXLsImy6jyKmw7UkarrHgapUTxRMpFbI5vzMcpvXm7053ERanhyUWgCEEoFKKkWqNd/RIW37aK58fvZ/xXR8LFWEJw3XkJXNPXw4B3zwUh+fHmeUzbkwTR7akfp+D3hsALedVO0ALEx1usLMnAOuKhusAi2lNKps3DgcoYsAwyk22kJdlOOLUrDv+KrPjrQZW8lnElPD2RCfefBz4f4vSed6nCGRAytwhy1Erlq/Oe5K0376NBqh1vyPr96L8QGMFA5BD58HW1xYdNS4STuUp8BI76sPwSTAu7GgLNoqRGoU12Cgc+vIQluwxiqqeTFOXhnf1XMqpbBj+tOYge7QKbimmGGPz8Sj4Z9B1Z8T66vn4OjZKqmHPNMqJUP6WFPlxODTMQYFjPJtx71nM8lno1VvOONEl1QUhiWpJKr4+i4yHqO4tZfc9qPvpiP4+8daCulEG/TnF89GwX1uXFsC83iiEfDyIpysvm+xZy/0ezKPWqbJlwMa2zU9lb4gANWsZVUJmaAikaUpO4XRATrGFHaRxIk5g4G80bRkFkYyLKDiGsEL+5PiiC8ho/j13VgRcuaMmKbUcB5bSa/2dsd+kPWbiSotj+9EAOHy4gd08Rbof++4wBIVBMP3DisrDzUeIzFLyGQlS8ghKlo0cp+FNicekhUC3yKyWN05N5/vtc1OLPGD9kF9cvvIK3bhmOYfhQVI1Q0OC64a0w1GTUstm0SSyiKBCP39aVO6d1pEubw3x70TIcTpW9R6vJr/ByUa9skBKb9JOsGTh0LXJ/QQ4dC5AS42ft3StYvGg/Nz69H7tNwRcwadskmh8ndOCCKT1Yc6wNLdrprDqSycjPBtKufiUfnzeHoU9/TzAoSExNZt1RN0iFjukV/HQwBqsEFNPENEwaiBK2FMaHB8Um6NwyJjxcCsjyIwhfeaQkwantXJddY/HWfNrf9y1vfLMZnBrmf0MRPEUITNOi9xNzWbUjD+xRSCkxpfidbbRAMzwYENFmCglxTpAWVSEHZnWAZHsVMl5HsfyszE8ipZMFiklIiWXmTwd4b+xSxo4s5PJZY/nsH5cRpQX4cVshFrD06aF4rShExau8NWQz3ScO5uVbr2Bw2zhueV/lhW8qeGjkPr4I2Bg7uU/4YC3DQBGQ2TgZb0hiSolQJaGQSpTqZ+WdKzi0/SAj79lTV5i4fpqLdZPac8+PPThq9aX0iwH4QxaPT17Ly1NMLp90Nl9eu4jPQvPpdmeQtvXLaFzfhVVto11yOW5nFtUlIfT6UVghO+f6t/FyYUuskB1Ft+jVIQ4AS1GRAQ+iPBcyOofLeP5ypZDgsmssXZsLio+EzATKSj3/Hcm9qiIIeAKs2nQUDAtdDxunptSw5G80LwQhTzkQfmh1TRDnVsEyKTWjyfCV0SxwBMNtQzg0jhFHsqMGFJP9ZdE8e95ObjnnACMmD+S2sRfTKEnj23VHqT5QzC2jWlMacPPGpDf4aMxyzv28F727DkSzqvluTQ6vXHs2s0qv5J2FzRnTczcfj16P9Crsza/CpikoEV6WYZpIK3zYw+LbVmEVH2DgLbsQwsS0JHExdjZMasOb27vw1rQGZMYGWLWniIPHq3hvwX40p4evtrbmym+Gcl7XQ3x62TqEZmNPSTRVNVE0TqjAFaNxyJWO0wFWnIteDSqRe4o55E0EI0DXVjHEuPXwYRmAKNoZMf5PNabho6LtMQ4+eGAQ3z9wDgSN/46D7hVFgGHRJDuJ8dd2462F+VR6V4UrVv8WpETzlYWTUqUkLsZGjFsFYZJfbqPGGUVUy3gCIQsE6HaNRnHVIBWOVLoY3jSf1ZtSUeO7MbJjHEWVfu6esIKevRowrEtLHvrgMzbcsIqLv+jNzur25K7awnvf1YAnyNoPLuLWQY258sGzaJCgcG2/zeRXqry8KA5F+GiUEsOh41UIKUCqzL5+NQ3V/bS5bhceXwBVFaiqxtpPWvNDcSfe3TKA799qy6Hj1Vz6+mKqPUFCoRCG6qaHbz1HZnh50H42L45eRlGNnQdm9mBvWQzdk3Np3NDgx6XxtFfz8Ljjibb7SUqxWJqbQnb7AtIzounaOo4f1xaH3T0F21GCnlMTEISg2h/inTv7cWnfBox8aXH4iO0zIGWnvz6ZYaJF21n41Hnkm3bmrSsg1qlh/aZ/RiCsELKmKLKYWqQm2kmICZcQPFQZTbPYKmS5h8CxAFV7AxRWaGQnVIOhcKA8mvKAnVKfSpO0cD3+n3YXcEP/bB6/dhBPfT6bDTfN4KFFrdkVOAe3VkVekQ90DeyCp7/bz+fzF/PxtesZPqkTCzc14p8jNnJd6zWUlwoQFoWlXvILAnx1zXr6pO2l11W7KCr1omsKhqGw7L0W5No7cc0XXZj7SB9GdmvI8K4NKC/3UlHjIyDt1AsW8Na+d/jm6LtYE9fw/Nye3D98Ddf32s3MffVAszg7s5DtmS0QMQqaW0fE2eh7dANz96aF3Ys2wbDeSeFR01RkdSGi/CBo9l9TqSxJnFNn6rpCul73DvsWLwGn/YwUJj799GvC+5/zX/iRqfc+TLvSzfgUR6T2xymeIkVFBD1IT3GdKm+Y7kR1hAum7CqLpY33MDZF4IwWlMVFUxyXSMvYCgjayalwsbskhr5Nytmw5xD7CgOM6dGI60f05cPv5zJ55BReWp5Nsftqpt7ZgfxiLxgm7RrFMXxgR5Zt3s5nQ78l3y8Y0qk1N/4wiPW7UnntwrWM7ZjDln3VyKDO22M2cmmbPfS9ejf7j1ThsKkEQ5LvX2mG3qA9503sSasmcfzjk1XcMmEFb87Zic8wkDYXqaFSPtj7Bu6QjyM2jTuqlvLlFJ33l/fko/NXk1ftwqpyMaRxPrsr4zleGYcW8GIGdUYM8rKjMIbiylgwgpzXOwmbrmKYkU1S3oZTG/9SElRtbJk5h/dWPMK0/DfRTN9pJi1GpvS0N6AqmN4AVy5+hhlHP2dM2VIqDQcBo/akW8nPAn+KhvAWI32Vkbpl0KpxFOgCTIVdhdGkpZiQ6EKP1di3WyVOBMiI9VJT7aTMZ2PixoZoNo1Hu03ngqcmM/DR6Tz3/tO8M+hjfjyQyoKyy/lqXEdmbszDLPYwvFdDtrx2IXazki23zmPS5hTWh27khyf68eEdwxn21UD25cXy2Yi1WIbgicHbuL3fTgbfsJf1O8tw2lX8QZMP/5lNxz4dGPbFOfz04gVsHz+KgR3qM2H2Dt6athlLt5McquDjPS/SxFOAVw0TEk0gRavh1uk9eXllaw6URXOgKIGMhGLSWjr4uqApzpIAVT5Jvfw8mpbkMu1wI6Tpp3kTN706hJNIVAU4thHFX/EzQTtBmJU8V/IVzUJVeGTkrKozgNMuZB5hp17wCJdUbyRfVTB+t/5CWMioPIq0rDqHbccW0YCJ1+ekoNpBFyMXX4mJKKhisb01qfUEisPD/vIYagIax6uc9Hl/CPXiJLMv/o5PznmPLy5byL7CON7ZfQnzH+lDyLR4f95utDgH/7qiN/dP/IF3z36NZYeiWVJzAxNvasOizUcZ0DqeZ685j4ETBzHgs4GM67ObJ0ds44q7DrBg9fG6UgbP3NKAiy7qSIPH2tO6YT0y43UUobBsVyGKZeGIdoAUvHToXVrWFFKlqQgkLlOy25XC+rg2KHh5YEEnVh1IYXleCtJuMKZhDnNEG4wEUDUNmeSkpyuPiZsaISwFbHDV8PRIqraG5SlHFGwBzVmXhxkXE27bJk2EaeKNFLY5Y7SfM9GIHYk/wif7Y8IiULIfCB8xqGkKbZtGgxViT2U8otxLk2A+fq+FdMD2qEZ0TSkB3WRPSQyGX0dzhNiUH0/vCedyzifDmJPbDMtSeG5lR965qS9uh8r4OTvJ3ZXPG+P68vjUXZz1/2vvvcOkqLa279+uqo6TMzMMMMMAQ845SUZQFFAxoJhzRo961KOe4/GYA2YxICrmgAkwkiTnnCbAMDmn7unuCvv7o3oIivE54/u+z+d9XcAwXdWVVu299lr3upf7ZbYVxTA390LOG5pKz2vfZfxtCzntoW+5YmwG5VYGsa5anpm5hZvvymPBl0eFiW84uzWzr+5J7znDOHfCcLJbObnsuR8YcsenHCxvQNEgICK4uPQzRlfvo9qhokkTRYJTSP6ReSmNaiSWaaA4mkDCWzvaIZrcnN3lEDnBeLbkxeMUOoblZFrnAvLKXGwtTkHqAU4blURKgt2mUQDkLT0uMOsON+N0CYsIxfyTVMmO4k8SXPkxn+xnIBREyAeVB2xfzjLp2CaCrDYesEKsKEyhgywjOt5EjXRgRMZwIJDI8NblSEuwtzra1kmStiy7wxXiYEUkL23KhKDAJ2Polh5ByDBpbAqx8qVz+OGAQQ/xKl1SDG5cfh5zLh7ADS+toLjGXgxsySvjpPuWMyJpC0tuXs+Djx7kqQX5Rwzs7PEpzLmvN4OfH8bt503n7VuG8fwVIxGqYO32IrYfKMPwJNC/djM3H/6UWs1+2SQCr5Q83+40xIBRKLqP+GgPyXHxpCbUsK8qmi2HUkhMrGJ09zrmBQfgrmykzmfSLv8gIwo38/j2HggrRHwrN+dPTkNKC1VTsSoOoJTvsrXKsI6rEv+J1M2fYG9/OtXHbelhQdyf0ntQnSj1hdBQiqIpCAHD+sTiitZAhxWFKYzMqEZ1O3CaAVYUJuL3eBjcqgKhO8mtjgSHE4SKZWErazt1fLqG4hZ0iDjMK8vKcGoq953dj7fX1pLUMJebhhYy8d0pfHrXaXy0eh+15T7QVIb1SaW8wUlFwQq+uX4Dr75ymDuf3n8kXTRmQDzvPtGLoc8OYHt+MrV15Xy3vZgNuRV8s70I1aNx09mDOMXYyVN7nwVpIZGYQhBlSp5IGMcTKeexY08BVtBi5oj2XHFyf07NOsCrp25i7tYOoMCNPXfzRUM2+pgsUscl4zoni7tvqOOz7SmU1sZhGSGuOKM1bqdqR/AlsPdL2y35GSMS2IFyt/PnGiH+9/CnG5kmzZ+ZMiWoDijdiWVJLBSkhEnDEkEY1Pqj2H3IzeimnfiFhlMx+KEpg06JDSTENdJQ42T1m3Nh4xw7ca1otkaEw+JAaQxfbs/g5TPWsXrVPM56ZCnj//EpsTVzePjk/Qx8dQKv3HgGaTGCF7/ZD4rg7ZtP4tIJ/WjnLWLrHRv57IsiLvvn3iPpoj6dY/jmpV5MXTCAlLYT+eifI6kPSO5csJ4J9y1CFQLTgpe/2s31e+aSbPgJKjap0G1ZNKqC4tEzifPay0KhKRRV+Vi9sxADJ5N75HKwLoLiokSGZh2mQ9sQn4Z64OmkYiVG069bJT0Sa3h0bVcUGaBT5yhmTEzFsiw0TcUq3Y1SuAFckTZr9kfQpf0UXNr/OiOzS72kFHg00056N4cxhIIwmqBoky1taZgkxroY2TcOaQb5/nAqEb4GMpMaMXQNacLnpRlMyixGRgqWb6ojP68UtXgdrH7ODn8oClJaCNXknI+GMH9zZ+afvpJ7ezzCsyNf5D+n7eW0t0Zwy9lnMqFHPAtW5tOQW8kpJ7UnMS6eG5//mJXX/cDmDcWcMXvXkXRRRloE6+f35LrFAwhEn8Intw1m+uAsrprYhZraJuoaAkQ6BI7IWIYdXk5GYwUNDluMT0iFgDOCKzrejLtNFnFeQaiskf9cPJiBHZP5bsMhNM2BdNkkxLlbO4A3xC399vLMqvYQCJfImfDvMTuZu60D1bVRWJbObRdm4HSE+4oLgdz6DgTqbEmp8LxoCgUFBVOCjoMf6162BP40ETwTBW+YZ66joh23urFAdaFU5yFrClA1O7o2aXgiialuhG7w4YEMxiQdxh3QsUIhCksV6l1RnJpViLAcLFxRiyIEitOBVbwNde1zCEWzGRuKRaOuctmHQ2j/1DTm7+1JdmaAN1e2JjlzEteOT0c3LR74cAsZHRM5c2g2Zz/8KSuu/gF/WQkTr9qBlCaGKUmIdbPxjR48sL4/L3yZRShQwd8XbODV7/ax7kA5lqqgmiY9s1LoEKlzw+GPQEgUKdGFIMm0eClyCOsjB/L+N9vJO1zHBdN7c9Mp3bl9Wh/umDWIWl8IoShEOAxe2NiBQFU0Z/bOxUQwb20HnJYPf5WTUWn5DIgq4aHV3VGkn27dYzj/lNaYpj2ayfoK2PAiwmwuCrZJi7GWxRexA0HztnjVEvwZFeQIVEwSMMkRXt6PGESdX2JyjBMqJagaHFxlN7cKn9b5k1ORwqC6MYYVe2M5PbSVBsVBNAZfi57EpGr0S63ErIblm+1SNmmaoGiYhzehbJ4P4eZVQkhUT4iaoMpj3/SgqCSW/VVeemcmA5IlWwoZ0D6B1/8+iTve3MDbZ35HW0cJIy/aSX1jECHA7dJY91oX3ivozeeHJvLlnAlcd3I34rwacz7fzln3L6aw2ocpYPmOSk7d9BrdQjU0hlNoXinZrkQRc8ZFjOkVi0MotEqKpLI+wJwvdlLrC+FxqnbzeQmRToPy4jgWbMtC8QT41+jd3LqwMzkP51P66n5Kny/gjuDnvJHbkfLqGCwzyD+uaE+k12GvNF0OqNuJrC0A1YlfOHgkcRpTMy7h9W4XgRH88yTWW7JTmEvqlGsJTE25kr9NeY7KXuMRTceSFsMOf2MpFK5HUQSWYdK9QzSjBiUgTD8L9rSnTyif7m2qMRQXSoTg3fLOTOlYBBGNrChJpyH5bCIVgWFhN0JQVKycpah7PwdXNNIyMS2Bppmoqsneqmimdy/lo9X7aAwKpvRvy5uzxzDr6TXcP2Ix4zIKGXr+DkoqfDgddrpo2Qtd2aGN5NqvxrH20YlM7p/B9CFZ3DatD5VBDRERiW5KOnZqS3dRzMyKZVQr9mrSFOCxJPdmzWKp0ZpgoAk9ZOHxOLh7Rl8cmsI1c1dwz9xVxETYMg5SCoRm8tCazjRUxzK16wG6dLH4oPMkUrq5sTrHMyKrmmH71vCfjb1RLD8ZWRHcMisDy7JwmnrzHQZFYASDbO9+Glc9/R8mdUuCoC2i19LQTOyofEvBiUm9iKHHlVfz0gW9uODZDTQUm7hUA1WYIFXQ3Ij8FVhBP6pDQ1oG18xogzNKwWrQ+PBABtd5P0P4VDQ1yL5KL3tiM3m583cIy8HcjW15pPp9HCmSi8sVQqZEIG0KzNb3UL0JmG2HQaAeKRRMIbl/RReWXbOIK0rfZPw9fi4alc0ji/K4oONiLh9WwNAzd7PvoJ0uCoQsFj3RAVdmX6bd4SKqeg5nT3sDb1QsMTExiKhWGAeKUKw4lJhWWP5a+u95i9bColIRhKQg1pAsje3I+ti+sH4XoJCcGs1Np3RjaOcUhnZOoc7fieLaNfgC220miiWQToOcklie39CJ2yds4KFRW5n4/CDO6bkBb0SIoOnirtEHGLdlEDf3SqRNYiN3X9KG91cG2VOXjUjrijtig93/UgiuGdeOlWv38O7yHHA7MK2Wny5bnIXRFDKJbRXJrWPacv3LK3h78UEuG+rCssLxG8WB0lQJuUsRisA0TNJTPJx3SipS9/NtYSZleToTO5fSIJzEWD6+oS8dEv30aFvM7tI2lGxsZIBvD26v4KlkyfVlAsuyu8ZJQKybi+qKwkzugRlsQHHpLM9pxZmvjeelM1bTI3E+Ax+exGXjDvDvaTmcOmsPa7ZX4XHboniv35VBdP9TGXFtLsqOeTQCH+//6bUqgOWJJteASqMeNV5jhFuSoUnqpcIrnWZx9dTBzF+0Dn+TTlVDgPdW5JJTVMf5ozoysGMy54zqyPdf286ETw+L1zl1HlndhVk98xmedZBRA7pzc/UU5vtfo8Kv0dGs5eSGLVy87CS+n7mQvIpYSnrcwkWjRnDT+AzyFp0HgQAIJw99sAWzoRZczj9t2dfiRubUVOqrfXSZ/QlmeR0QhRACoUhcqkGj5kHZ9RFGUx2qQ8PQDW6dlUFMohNCIR5ZmsUl8VtQUlWcTS6aqiVPHejNf2blgDPEKzs60O/gKiJVKDEFkzwW/05SuKNcoEm7MsoydJQfnkY56VashGyssKF9tKMt3x5KIt2jc/ZJpbx8/nYuvnEfX64sPRJsffy6dAZMnkjvexMw9ryKqipYQkX7kYdhmJYt/NZUjwLUCYVXq0xeFYJoFUwp8W/5mhzVi2568Tq99OiYzCtXDeKd5fu5+tkVJCW4Ka3R6Bt7jBKlFGgOi+oaL/cs78HLM5bz4NDN9HthLKWTs2mb4MN0unjJt42B77ShZ9FkhDueeTefwtSBrXlw7hd4DxeCszWNQYlZ10Rmp0RGdUtj3pI9Lf34gT8jQa6AFbIwfUFmnNqd0yd2pTFga69qTifUFSAPfIuiKJiGSfv0CC49Ix1p+Pg+py2mLrgsbg01BRbO8noWHkrHzEzg3M77qa9LZNVGF6c1rqdegBNJpQXnRFjcnCAwJChSgqJghfyw4gmUyn3gisSyJK6IAHU1XiJcAd69cC13/OsAr392NF30t/Nacc75Ixn4UAf07x9FGnUYpoVl6DYnTNePjMiaqqBpGqrmQKgaigBNscvQ6g2Jz5SIvJWUv38rcslddCxcwD/HRdMlPY5/zRzE+jlnct7w9hSV1/Pj0JVpCRRviNc2duCHPe3o2b6AS0eUcNEH/ai/fwP592yi7q61tKvcT2S7k1jxyCV0TnUx7ckf+GpnHZrLC0LSGNQ5Y3wnNjx6BlGxMRAwfpnX99+ygZY+gJSgqoJ3/z6B924ZT0brGIK6iaEIvC4VdnyCDAUQqoKUkrsuzSQy3oHQLf65oTfj9e04Y12gaViKyTOhk7is6wE88bUs2JdN5u6dZFk+gkKxtSqAaguujzY5O1bBkHZjBBQVGWxErHwcpToXzeUk2OBiQEYp62Yv56kXcnl43tF00YWTk7nzhgH0eGEskTX7yUzzkN42g+TkZGJiYnC77P7kpmliGAa6HjY8Q8c0DVszVVFRNQ1NtRm1UlHtim9fNdtWf83Uk0cxZsxYnnv+BRrq6pg1pit3XDIaldBxSpQSu1rLMgU3fN2XoC+CB0esoaBdFs/LkUSUhng6YSJn338Xq/8xhHdX7uWiuVs4s6sTx87XCPjqQNHQsHDGxjHjkcV88toH4HX+7/DJArpJVEoUXdvEcfGzS3n98wKeOEOixUo8DblQvBHFoaEbFt2yopl5WmsINfB5fify1/m5vOsGGurcuGpqWFLTkVyZwOwBazD9UXy8LpFrKxbgU8IjVhgCqLfgvniLEkNlRaOJAwtDUTGDPlybXyE4+AF6p5ex6qYfePO9fG5+7MCRdNGkIfG8cF8/Or86gStHdOXOxyajRD0Lho4eNqggCrWV5VRXVlFcVMjhw4Xk5hxg//795ObmUlhUiGEYx90Lh8OBlALLsqu1AkGdpUu/Z+nS73nooYeYOeMM8swMemcEfpIOMi2B6tbZkp/EYyt7ctepa3hl0noml13Mi6mTeOfh8xnTM50rnl/B4UbBVZ2reeCaS9mTd5hpQ3qBoYM3kpVvf8ScwpdJ8uiM8v7rSLioJdHiRuZ2qNSW1tPzkgU2Jwwnz62JpTbUh8MVBgo6QgcHcM+V7XFGKhiNGrd83Yu7+y3H44AaKYiOcnJf8TguH1VIUnI5H+/uR+yGvfQ1KqgMJ52bYRfyg2FJnkyyuNBS2ek3bT9KFQQryxgQv4sVtxzg2+8KmHXXPlwOQVPQpH+XKBY+1ZcBb45meqdsbvv0Uko+cdHhveWIiKgjx6ib9xTK6mV0e3nhT645aJjk5eaweeNGfvjhB1avWsXOHTvQdf3INg6Hw+7TEg4fFR4u4OHHnwRg1N09QU3+STrIsgSqO8S/l3djbGYZk7rl0rNNL645eyZjeqZz2fMriI2LZYJ/MZddcAemhJgIN5ZpgtBINur4R/EL9DSqyJNxOAi1aLOIZrS4kZmWRPM4uW1GX+Z8uZMRXVvRNqk3r2wpo8FdinPwJYRythGXIDlzXBJC1PLvNcOIrqrmjOBKioMqCfhZ4OxLUUJr7ur/AZYewRsrU7io6COaVHHcKNYMBdABDxYvJsFFZQo5QRMs6No+khV37GT7pnKm3bQLh2YR1CVZ6V5WvNKXyW/3Z+DQGTxa8Bibl+1GWFD+1oskX/k3kJKKlx+n4Na/IU0wWt9A6t1PgmmgV5RSePPFuFOT6PL0e3TJzmbmzJkA7DlUwKKPPuSzTz9l1apVRwzO4XBgmiaqquJ0qAR1w9a1OEHsUgKWAgFDYcLbo+iXcJhnrzqZET3a8OBHm5k2rAu7Pn2K2ff+B4cCd/3jbr7eY6AH3gPNQ/vGQlr5q6hyizCn789hlP0JbW8kiiIY3CmZaE8fRndPI8arEQg0sqDQxGh9EldecQ11DXDdl29w2aBS/r08m3UXf0t8UjbeRhWHMPnHMxP428idJKVV8v72AcSu3Elfq4IKTflZPQcFaJKQoFjMS1M5szQO0xvi63k9KDhUz8Qrt6Mb9miREONi3bxeXP3dQJSESbx8Tjsq3usNIXBmRBMx6CQ78S6EPaIpth2oHi+apoKqcPCWWTR8u4LaJvCOOoXY02eCqiIrSulQnMcts2dzy+zZbNu2jbfeeIM35s+nvKoKsI3NME0sU+KJ8IQlBE5gaBI0l6Sh0iCmzyRG9OjMs4t2UuJTcX75HLff+x/io7w8/tI8djp6E9m0G0/MGgiGqLcisFQFx5/ghx2LFjcyVVEINencNG8NecV1OFwavdrFc6ii0a5Gaqxnx+5DvHnrOM59chwvPFLOnafso19GCU2NEXha+3nk+74Q5eK24dvw++JZ8FUsNxe/QYMm7FbTvwAFgS4lkahEj72BD2/chFNrZMhFm6htCOLQFBRVYf28bjy5awCrKsew54mhWJZJ0tmXEuFx4cnIRPQceOQ7k2ZeictXieXwEHvxbCw9hFQ0lKQ0QrUQPawDkb0GoqoqjWuWcvDa8/HvKab9W/NJmH4BvXr1otfjj3PHfx7kxccf45mnn6asrAy7pWY8hWpnsIrtfqA/vh5FYPoNOnRI4MObBzJ/6V7qTRcjlJXMuOufuB0qY6dfwPObnJzaq5i7LhvPui8XglWCdDiOLCgkf5amz5/i+BvEp0SR+9zZzHj8O26e0oMhnZIBmP7wN9x0Wk+ufmEFry/dz8OzBjJh1zv8bcherIADpyNEeUUUf/+2O+9NW4MntoHHVoyg28oVtBeNVKKg/hqLIMzduibtXO69tJouifX0mb6Vw2V2H8tgCNa/lM3a0CDeyxnHgWcmAAqGBfVN0DDpfBobwX+wyU6FSXCogsiZdxHjhYABboe90mz/xPOk9xuEc9o5ENsKw7SoX7cc/9Zi1BhQHQ6EEFhA074dOHP2c9edd3LZZZfx9Jw5vPD8c9TUVtPDvR9EPOIEL5CQYCF56eqRKELhs60VTGjt44prrgfgjjv+zseeUxn+/RzuSY7iU9coakNewBaqkdgjfEgqGFIJa4y0LFrcyDwOjeriOi56djkju6Wy7WAVm3IrifJoXDCmEzsPVVFR5WNU11S6ZiYSY4ZoXFNE9IRkVHxc/M4YRrer4Mx+ezlQlsHyhUEerltFjUP5VQaBKVSSTZPbE6Yz9MpWzMxezcjz9rArrx6PS6EpaPHOA505FDOWmU8P4IxpqVzy4hYKyyvRQ/UoZi0u2YhHa8KlBnFrpq0CL1UMy0WISAw1Gs2VSEx0Iu1SW9F95E30kNAe0FSFtCuvJ7hxHa5Bw4g59WwAgnu2kXfWKJr21ZL18TukTDmHBx54gCuvvY6L73uVAraBrPjJSKaqCmZ9E+dM7MqY7qlMf/RbTh/Qjrfvm0Vtg5/zzzmTz/w9uXBILLNvm0vhxN74ohbS4EgAuR/F0FEsC0uzqdgOYSFbWnKRP8HILEvi8DrYkl/F/Hc20rFvWyb2bs3yXaXs2FSAkhwF/iBVjUGinCqeuBj09AQUVyOvr+jC4txUDt24EFD51+JOnLNtPk5NEpS/HOQzhEor0+SxyNHEzurO3SetZNqlOazccrTN4JM3t+ecaZ0Z/mIqN0zaTdfIb8mMriWjfZBYj4nHAYZUkFLDkDb9qNlP0oSBIuz8qy8EpY1ODlRFsOnjRN5pzCLk7ERW2w6M65vB6LcWY491EsuS1H77Bf5dtbhagSsxBSklhhC0jdQYndmF9Q1+kCUc65gLwDJMnJEuHjl/AFtyyyluFJRt+JSvl68lu30buk6dja+gCX91FV/sSWDi3Q+jnnUBqbddjFQcqJaB+BPqLH+MFjcy3bSIiPaw9bHp3Pzaap66dOiRzybfv4TnrhzGhU8vo7Dah88fok4TJGW7KMkXXPpRP148YyNtWpfy8oahRH65mZHWYcrVn3f2IWxglsk8d3+KzhrF+9N+4IrZOSxcerTN4K3np3PBzL6c8novFs/8AQuT3eXx7KhI57O8GPZVRVLS6KXM56BJ1whZKs3S+aoAp2oS6TRIjQiSEeune1I9fVOruXhAOamROdQHlrC6IJaFH2fx5Fs96dqhB+ec1J6BHaJIPXUKwX0HiZkymcgho8GyqH71SfxP/puY2gjMqy4D63gSjqoKjLogZ53SjTaJkdz4+nqmdPHy1n3PAzD1vMt4f6ePD/42mrs/3En7oIHo3J90L9Q0lGAptsiNKRQ0IdBR0PlfMl26nSq1xXV0vvEDurSOZdw/F9k0bMWm/57y7yUcrmjk7ZtGs2hXJVHFeUSWlTHys3OZ0LWKK4ZtZU9JJh+8K3i84itqfmE1CbaiY7Jl8omjK8tOmcq3F6/mH/fn8PLHh48Wf0xI4dE7u9NzzhB2lMTR79Xx5NdEYPid0FwLqlqgWKBKm3QojullJMFnKviCLspqPWwtiGehZftrOE1ax/kY3a6SaV0KeWDCLjS5iS/3JfLgK72wooZwwaS+nPnsywBYUmL5Gil+8HYiigystKQjsavm2VJgzwg4NW6b0pPCygbKfeAqWc+Offn0zM6kLv0k0kvqaL91CS8WfY1/zUFqpM7yfjMpdXlQrT2gqERikRCExZ5ULC36T+nc2/LNInSTmOQozhrUjk+/3s2Y7mncc2YfWsd72J5fRcfUGDSXRnpiJHNXHuT2gg+Yd1eQvKZY3pq+nJDu5rZPunH5tvfxqCbmL6wmDaGQYFks0zKZP2omi6/dyPMvHODfr+Yf6WM5fnAi7z7ZnXPeGcyOwwloLoMDZVEYFjgjArii/WgRAXCEo/W6CkEHlt8V/uPG8rsg4LA/Q4JLxxHRZO/rDFFU5+atjRmcMX8kaY9PY9Zno4mL8vL+OUu5q9fjfPTBg4z42+e8u7IIRQi0qGi8Y08j5farKb/kfjQZBAQNQdvghRBYAYMu7RPomRHPvKUH6N0mghVLFgIwYdq57D5Uz/kvnc2+c0+lNmARefXfSZj7KXMyziVoAdKg0pPAYm8XXmgzhp2n3GyrZv8J0CwplRPFY/5bkNg0/n7d20FyDl3aJdImMQpV8+JSoLY+wHnD2lNYr1OwZhVpDp3LEy7k/SnLSUiq4eZFJ9P5q6UMsYopU35+FDOFQqxlsUNtxYMDL2PFzdv59KN9XPtwDm6nQlPAZFCPOL5+qTtXfTaY9zZk4ooJYFoCNAt0lVCT7TnhNIn2hkiN8pEa0URqVJAEr4lTsZuP6dJBTZNKSYOLokYPhXVuGvxuCKn2KOgwUL0hNMUiaKh8uqMNn25rR0ZyHTcOOcDLZ20jp3wH93zal7lfj+LfF/Rj6NyPAFA+LyRm2wpAwR8SIOyqInSTyX3aALBifzXj24R444c1RLgdRLUfgF7oYsTFF1A6/2Wy7nwIZ0QEH63aT/nGfcSc7gALdpuJ5I3+D8/OHk2/UIA3Zr9vMxhaGJrToUWoqgq0TAjYranUV/iYfedcRspGzr2vAqJcdIyqpKg2nTmX92TqoAzmfL2fhoYgs9rcxu2nH2ZC9528vnkoOz8o4+X6ZVT8gh9mIYiQFkVqDLO7X8Nns/exZ/UuzrpjP06HIBCy6JwZzap53fjnygG8tKIDIjJEsNEFUsEREaRX22pGtqvgpHaV9EqpoW1UI0ILgSkJhhRqAwoBXSFkaUhAxSDKDREuBQuV4kY3m0tjWXmoFUsPJrO3PBozqIHDQPMEURTJwVovNy/sz/3LunL7yD28d8F6lh3YxTWPj6Bfr1G8eFk39MY6Ypx2ga/f0Ox2U1KCIhjXszV1vgBBS0VWHKDBH2TU4L4U6nFM7hVL2vS5NAUt9o3tRqdFm3nqq32o4cJeTEm0W+WtW0awv6CI619ZC07tT6m7bPk4meIgUq9gVf4/CQRhVPod9OofyxvjlnLeshuYOigDKWHD7gJqzTRmjizmntErWJufzSMLknj98IP4FHHCmBHY6z0H0GQ5uarDtcydXYJyaDsTrtuPplgYJiTFe1g/vwuv7enNfR/3Ao9JhGpxcu9DnNO9gLEZxcRG+PD5YUdpBEv2JbC3uh1F/iTqjThMJZoQHhTFRYTbhaZCMBQi0NSIz19Fkqua/mm1DG9Tzt3DNvL0RJ3DDdF8vLsNb2zPZHtxPJgKuEO4ov1UBzRu/6wfT6/uxJOnbmb9dV/w9y/2MOTuU6msc3F9L4FlaARNJyAxLIniddIvK5HV+8pom+ilaPtOBNCxa09qdAepwSD/encD9zz+CuatM/jszFP4IeEqsCzbnxM2Re3U+5dQXVwFLu1Paw/d8j3IpUnAEc3rzt7k9x1FdPrJpKpLiItqomtiEwFT4lRgW2GIvtmlvHXBVxSXJTDz7UHcs3sOCbKJOuVoTOxIWV34Z1VKvJbFNZkX8s+b6+kWWEXXy3MJ6iaqomJJwcq52XxX2Ycr5g9kaLdirhqYw/QuBbhEE9tK4nh1ayc2lrYh6MggPTWDNqkJjO4fQ9tEL62iHbSKOTqlVNQFWLWvjA05FWzMVdlQoOMrVllkJIPamT59YugQVcTotD3M7HmQW8ZsZ8vBFB5d1ZX3d7Uh2OhG8YTQopsoanAz4/WTmNA1i/kzVnNGxWtMfX0iBxtaoSgHaDIUUECaFjFRHpKi3Ww5WENWgovNuTlIoZDargP5foOs1AS2H6ph68Eq5nW6nsVbv+Kswa0JmREE9Z2gKBimRfXhWnr2TaNv+yReX7SrRes7jthASx/AgYVhuVh28TN8Mns476wsZvOqz5GaRklNE5oiUAR4HLCvQvDw4kzm7RnEyF3LONOfxx6HgkK4XlBKHFLitCSaZWulagr8PXEaaae1pbd3I30v8VFd48MpQBrw2UPt8SX04aEPM1g7+wsGZZWyK9/Lw8u6sKGyO+V6K5Jjo+nWIYabT+lEjEexNW2PQUFFA+//kMt324vxBw26ZcTTuXUss0a157pJ2UhpkV9Wz4Jv9hEXG0Hv7pO45vkYnlxfT/uYRu4atYO3L/yGh4oSufO7PizYlkEoJHG4daTD4Ou9abR/ZCovTF1H4T0fsfZgKy54ZxQldW5Uh4kZhGiPA8OU5Jf7GNw+ik8LDqJJixrDxer8MlpHGPiCFlc9u4Lh3VN5/4076Z3m5fnvCtm3NgCqQmNA56oZ/fnXrAFc/+o60M0/RQSvxY0sqFu44t18cu0A3v5mJ9c9v407xkiEW2V9Tjm3zN/ClWMzyCmqYPrIEewyx1NWk8cqTwavebIZZeUSbRgIIKBAiRrNYXcyhyNT2axksju6LbsjO+JcE+Sr7eOp6TMGmVpMsCaX5KgA2yM7c/u7rdl85WLy6ryc8eoYQhFDcXqiuHJ6W3YdKmXe17tJj0tnwn2fkldcz/ybx9CtTRwbD1Swem8peSX1dGsbx9+m9WJEt1QcP1N4c+OpvTj9oSXc9cJSvrhqHQW1bt7f0Y4rPh+E9skQnpu2hrcu+prr9rbhqk8Hs+1wAoo3iBYRpMlQuejtEXx7IJV5Z61gS1k0b23IQnHrICVup4amCmr9OiXlNRyuDWFEZfPMJkF2e4FDVbl4TEcm9k23S+qwGTANfh1VFciAJC4qkujUZCbe/h45+wvAm/S/g7SoqgK9Saf7LQs5eKAUQl48Tnu1lJ4YyTdbCli9I5dpgzJ59drhAFTN6sqiXUN4c9nJPLR0HdmBYhymQb47BSMlhiotivqaBDpklVJZ46K7p5JeyfXsr41i7ZU/cPNXg1lbfAr90yq5+8N03Cl19Hv5ZHaXxYBP8Oi1reicFsXW/FLKa5qY0KcdjbrJwdJGAnUBzv7PV3TPSuSkbqlMH9Ke0T3ScGpHDcswbdJheV0TUkJ8tJu9h2toFeflnZvH0Sn3fd7elsb9Y/cypXMBsz4exvQuBcxaOJSURf35YOZSts7+mNs/H8wjy7tjaQaKaiEiA7y1sQNbiuNZffVi2kSFmPXhcJo0i9JaP08v2sVXmw/xsS9Av/Me44r+nZnctw1DOsajqcefnx1WU8K9qewwSHVQsPOBf/BUxRIOJrflQu9NLdUs4ji0vJEJgRUyObivjD59WpMWl0LI2AMhk36ZCTx+1ekcu7ANGRYJ0V5O7+3hjSX7UNOjsFpnIjSdiFoPRlDl0m67SXI1saE4gdtO38X9K3rSJ7WW83oeZPaiXnx49iJOfXMsDw7bSrLWlQiXCdJi9+EEHJFNvLV0HxFOBwmxHtLjI1iXW8nmXSW4Il2cNb4zF4zqyLhere0mp2EYYX1VoQgURSAQNAZ0LpizjKqKRtq2ieXlq0fSKtbDf84fwoWPVnH78AP8cCCDeWeuJKcqhi6JdfRNqqPjnKlcM2A/T562lpPal3H+e8Op1zUUTeKIDrKrNJb2j53Co+M34HGW46uJwxOj8NHqPP45oy/jeqfTvW3ccaGAZsNXFIGm2t3ymmGXBzrpGCji4cr3iAHqm6pAhk7Qnuy/j5ZvRSjsriS3zxrIgxcO4InFhRRsE6AI6pt0m8WgcURP3qkprM2t59YX3+X6Xt8wbnIThyojKK530SauiShvkOfWd0a3BDcN3cdja7rx4pR1XPX5IIanVzCkdTUPLOvDS1M2ctWXA/n4zJXcuaw3j07YyObSOH7IT2Hb/lpS0zysyalAVjYSmx7HHTP7c9GYbLLTYo6cumGFGzGEHxzY4QQBGJZFx9QYMlOiWff1Hgb2TKN9ShQhw2LWSZl8sq4TvZ5RaPznEj7fn8zqg6m8d+4yFmzuRM9WNRyqiWTCaxN5dspaXjh9A+e8NQjTDKALBbwmijuRl3Mu4obT4xjeNYU+mYnERjiP3ldpYRgWQlWPGNbPQRWSRlPD669DWoJ6DRxGEEzd7nPVwvhTfDJnrIdZk3px4aubeeOdndx+qi0AYlpH5diEsEl6ueUBrnn2Az4+/QPSElS+29+Kar8LoUje2dUKn6Fy37jNvLutPfO3ZfK3wXu4/Zt+vDF1Ned/MozXTl3HhZ/bLQTHZJSzcF86E9uX8NbWDtw/agfPR4aIcevMXZZJelsX9105nLOGZxHtsZ19K3xOiiLQlJ8+gGZH2aEKpIRrJ3Xl+pO7oB/zkgA8c9lItuUVc+m7A4iOMZh7zre8srI3NUGVlZcvYc6qbtzxVR+yHzkLj8tHdvtoJvbuRq+MeHplJNC5dTQRbudxx7YsiWWaaA6757jmUCDceueXYL8UgibT7j4sLYhQTJzCPLFu748hLaRlIRT1V3pqnhgtPla6NEGwUWfMVS/Ras4NPFU4B83QkVJBFUdvj2VJhIB/vLed67t/i8sVxercZHQJKw4mszw/mZOzD3PZgH1c8fFwTs0uIt6ts7UsjrEZpby9wza4J9Z35l8n7eDBVd25edBuluS1ZmxGKVvLYumTUoNLM7h7+G7Skmp45OJRXDq+85GVmyVtFq/6CzmQAyV15JbWU1kfoClkMLxzCkO7tGJk11RqfSGq6gM0BgzS4z28fM0E3tuQyeV99vOvRYPRhMXfR21n9KsT2Vkay7orF7Hhus+Z0eUgquZizqVDuGRsNv2yEolwO+021aZlv4wShGUbWP2yL9k3cTi+Tats5aJfSQ8JICQFiaYfR9gLE/zGyLu0l/FC1Y6ItvxetLiRGULFEarni1138p+atQyq244IBhCaRVyEhqLIcN2irWNRWpbH6Z0r+HRPa9aWJLCzNJY7Rm/n5E6FnPXOKBbuyuC1qWu49JOhXN3vAMsLUhjZtpxNpQl0SmigqMFLhMPAoVoU1XsZlGa3ihnWpoKtZfEMSqtic2kcd47czoFyHdOy0E0LTRW/uJxvliL/x7ubGH37Qobd/TltrnwHz7nzcJ79GuqMV8i4+l16XvseH6zJw5KSsT1bc981nRnz3HBWFaZwYd/9nP7GOO4YsYM3z13OqkOtUaXg9QvXYPl28+6aYgxLohuWrdEs7GlQVYQtM6BpNCxbRP6F0/GtX0XuuZPxb12DUDWkcWJDay6nU6RiE5WE/TL7LYWgVFB+gYUhTROEQjB/HwU3XYleVmRLUpm/L6ne4tOlkBa68PJQm/PpXbGXTVZrisracUlZLvvKLJyK/U5ZloVpgSIsYl06qwri+Wxfa+ruW8COQ8lM61pAY8jNrKfH0Da6jrtH7OL+H7pxee8cvsxpzbROh1m4P52zuhziwz1tOaPzYT7c246zux7iw71tOa9bPvO2d+DUrELmbs3mzkFruXzVLhSl/c9mE467jvDU+do1IwmEDAKGxe7DNRSFW8fER7pIifGQEOWmXXIkQghMS/KPM/ry3JIKxrVdyMe7sjipXTkTskrp9uTpvDplC11T6sHSQJpo4Sna5PhZSRq2gTWu/o68i6YjrRBasgOroZ7cmVPo8OG3eLr0RpqGPeIcA1UI/KaT+Mg6ilP7U7A/mg5mPU2q21Ya/7lMimkiVJVQYT65503Ctymfpp2ryXrvO7SEZKRl2tPnb0CLj2TVjRYvnbWexx6tZdjDmZzy9wQGpVZy9eIRLN7i44qXtpBXYavLuDRBXHwGb25rxaOTtxGpWnR79EyuWjQIVJV1Bx3cdkN33sqbQqfYMoKmw5ZX8rnpGF/P3soYeqfUsL86muz4enJqokiJaMKnO4hx6eimQqI3SG1AI9arkMAuDlbaAclfS680P3OvSyM+yk1anJdxPVtz4ehOXDS6E6cNaMegTsl0SI3GoR7tvqYoKi9c2ZOn1nbi2Y0duXHIbu79rhe7C9L4bK+btUUWV77VgZTWA5nSN/nIlN0MGR7BfJt+IHfW6UgziOJSkEEdxatiVleRe+4kgnl77REtPMo0G2l6vIecai9adDUXjS7jltTLcVhgOZyguk8sgmfZBqaXFZF77kSCufm4O7jxbd1J7vmTMOuqbQP7jTG2lh/JMJm/OYtadz09EmqZ0LGES/vXg6VTU+1lwdY13DqnNz61K3+bMZinLxnEyL9PRnMsYv3Vn7OnNJHe6eU8uzyevebJfHt+V15ZFs9rWxdzTrcCtpfH0iGuntzaKNKimqjwuWkT7aMxpBHvDlHU4CU9yk+5z01aZBMNIQdJ3gCHG6LpGpPPtoJ6MhPjsKRNRvw1WFKiCMHizYdZu7uUHu0TGderNYcqGrn+lVVcN6krM4ZlIcPGYknJGQNbc3N0N0LGZpAWm6o7UvbuVL7dOZxFOUV06B/DExM74HKotu8VPlbzyOTfvp68maciAz4Ut4I07XY/0jRRIlX00lJyzp1Ix4+W4UzPDGv623nJ0/omEfCdw98XNPLgKZsIiYGcPe9GuurFnLAeyrJlt4zqcnLPm0jT3gNosRqWP4AWp+Fbv5m8i6aQteArFG+kbWi/wuRo+dylBqv3JtBz3SYKhcm8+FRkeiZts1WGdavlitFFXKd8yOpd0WxZ35UVW09j5phhPLYyljd2HybeU0nJqr4kpvXlg1sHI6XklD5JXPZtDy7us4Sc6jb0T61k2aEUeqfUsLMylt4pNeTWRtElsY4d5bFkxjaQVxtFm2gfRQ1esuIa2V8TS+f4CrYXVUPfuPBI9stWZloSVRG88NUePl1/iD4Z8dzwyirMgM7H90zmiYsGc9Mrq1mXU8njFw6yV4NSIlSFayZmsfDrteiGh01FXq55bRu92rjpkZnGuF6tiHCpWPKoOkGzgQX2bSf3vFMw6+tQvGEDOwbSMFGjVEL5BeSeO5EOHy3FkdwaTBNUFY8TLhzbj1n7HYyd+x7fXbmCjrGdOWvBFGjwHV9HEJZWMOtryD1/Ev5tu9Diwv6esKdtLV6jYflq8i89nfavf4lwun7V0FqehSEcJFHIPfWfo+ugV0DVXpXcZa1ZE5vNu1mdSR8UwUXDCrm29w/szdnCTV+PpXvHCdw+dQKKouLSICvZXs5bUpIao2K5syhvEDg1iHOHKGn0MDmriE2l8UzKKmJ5QSsGpFay9FAKZ2QfZsXhFPq1qmJHRRwZMY3k1MQwvFUxi8uqgazftNRqNsRVe8twOhQevGAgd53Vhx35VXRvF0+Ux8GCW8cy/K7PeXDmAJyaYi/OgGn9W/PSZ8ncvKQ3SUo1wz3P0Fut4VCel6kf9GHa+Oncflq2vcqWFkLVCObtI/fckzGrKlEi1J91uKVhosaoBPYeIHfmJDq8/z1aXCLCspCKgmVZvHF1T+5410WXxyLZddMSvjs3xOjnRx71l6QEVcHyNZA3azK+dZvR4n+6oJCGgZagUbfke/KvOpPMVxbafmBYp/ZEaPn20IAlFcoUB+UOjTqHittp0k8UcF3NN9yz7hl6vfgBD9ypct5rEwlFprLkyi/oGHqB8x9bRHWDj6xkJ7ppr7iaV3kd2qSzt9KL12ErKLpU+wEEDZVop0GFz0WriAAVPg+x7hDlPjcRDp2iBjeto5qoDbhJjDCorqsN34hft7JmBZwnLhrE1IEZBHSTSLeDIV1aEeVxYElJUZWP1FgvmmqHCppXrJ1SvaiedD7dm8jmGxdxYd8amqxkLhxUw+dnL2XekmWU1On26k9VCRUdJPfciYSKSlAif97AmiENEzVWw79lB3kXTMZsrANFQVgWapiB8dA52Vx+xrn0eGYKKw/Fg9PkmMQAZkM9eZdMoWHF2hMa2NFjGWiJDmo++ZJD15+LDAVtI/sZv/ZPkUFTFEmypRNvGkRKEw072V2pqYRcKoPJ5T/58znl7Te47d5YblwyhntOO8hrE1/jqide4b6PcnCoSriznP3Q+mWlsLc6gVhXkBKfh/RoPxV+NzHuEEFTwZICVbGOLOF1SyCEwKc7iXGFqA0oeB0mTU114eDrr19H84uaHOPhkjGdcId9KMuSR9JOa/aV0yE12m4ma1m2io9l5w7bpSQwe8guVKD9M6fhdZig6iQl6qRG+Gn0GwihECotJPec8QQPHkKN1pDGbwsZSMNAi9NoXL2B/ItPwwr47ZO2rHCqyWL2pAzuv+w87lnaDyzjCNVHVRVKHr6d2s+W40h2IfVfjr1JQ8fZykXlqx9S/tKj4Xjdic+z5YOxlk6FbMd98dP5Ru3CVqsVxaFI/AEVV9AkJmTiMgEVRsqDPLf/Obwv/MDQx8bijotk542fUbjzae56Z0t4JLHfln6ZcRz2pxLr8nOwNpKO8Q0cqosgNbKJCr+baJdOXcBJnDtEY8iBS7UImbb8uFO1UISCS1NwUYc/dOJzt4OhNmnQtOx/m4OjRtg3EoLjVoM7D1czuFNy2PDs/Zq3T43zkuINsLMoidpSF5/sjOCjbbFc9nY27TP60THVQ6iqnLzzJ9G0NydsYL+Ph2+PMhr1367g4OXT7UCtECBtQwsZFtMHpPHlP0aAcbQiSkpJzPjTcaS4sPwh+DWJV1XBbAzi6hBP1MiJdhL+Z95UDcwWJa6ZpuCq0XsZ1COVsvK25NcK6msE9dUWoZoQak0TMXVVZDYU0jl4mCxZwd0Nyxn71XZmlVzDPy6P5pWL1/L6tzVc//psnrmoD5a06JjiIKi1xSXWU9wYwZDWFWwpjWdoegUljV7SovwUNnhpHeWntNEdDl04iXYamFIAJoalEqnWUO2TRDjFEbeimUmqCHGCRrjhMv8fpWOaDa20pol+YxNRFIE7vLMa/iwu0o1lKeTWaPTvk05c9iC+rqinY98YZk/JxqyvJX/WZPxbdx51uP8ApG4bWu0XX3HomhlkvPRReNUqcWoKpiWZ3Lcdbdsn4Asa4edkEnXSyWS+/C55F5+JMCRo4qji47F3QFGwghaKy0v7+Z/i7TXgqPMfnjI1VTsyhGmYtIgCcrPdKgqMbV/KpOwG1A7gdgbCcsgqRsjN4cYotlemsqmgC2/lOGna30CbojzG1GxjzuanueX5awhd3puLxuxg/RuvcPcH1/Pvszrj1iA2rh3+kIXf0PA6DJoMlRhXiO3lcXROqCO3NorMmEaKGiJIjfRT6nOT5A3QEHIQ7dKp190kOSsprQvRJs4VbsYjjhjM/uI6PlqTz4GSeg5X+4jxOBiancKYHmn0zkw47noVIdBNi/L6JlonRLAhp4JFmwpYtrMEv24yODuJxetr6dTHS2Gdwdh+bbn3jI5H9pdNPnIuOhXf2k2/6A/9VjSPaFXvL0TxzKLtnLfs/GP4XKWEhAjXEWKCUFSkYRA9fioZL75J/uXn2XahcLyhKQJLlwjhJHP+J0T0H37CIPCxaLHV5VEfUHLWWyMZ92EemgZlSa2IiTTJiGqgT0oN2bHl9E/O5fRhTTBepcEfx3eH0li8oxeHd+rklMUzY14PlmmNPD9zG1NeWsC7ba7nnMHJtElJp6TRQ4TDpD7kwKPZPoFfV4l3h1jjczGsdTk7K2IZ1a6UHw4nkxXXSKXfTYo3QEljJOkRFeSXNzIgI9zFVoGvthbyyDubqGjSuWFKD/714Ra6p8cS0E1ueXY5eJ1MG9aet24YhcepHYmJ1ftD5Jc1MvyWj+ndpRXfbi2kZ0Y8IHj6nY0go6nsEkN9UyOtIpz21Csliq5z6NLTaVi2Ci3hf25gR+68YeBIclA5fwGKN4L0B18KKxPZumjWjxx1oWlIQyf21HNp92yAQ1dfghKhgrDCvUgFmAIMScb894gaPuFINuKX0PL6ZIqKU6/m8ZyncIRMNmhteWjEdVw1oILzP+xP57btSIwIYPiKSXcXMjStgJM75DJ16g7ktCi+ykllzncGZ70/kl3Xf84r09Yy5f0MTu55EQM6tmLXykTSohvJr40kJbKJ2oATTZGoisSna0S7dGoCThLcQSr9boa0rmBPVSxton3k1EbRIbacdUXVQAJCCPxBgzeX57CrsAbF42T9gXI8Lo1bp/Xi5a/34Ix2Y1p2cwkj7Ng3v+gB3cTjVPH5Q/ywuwRVU+jRLoHlu4pxxXowgyp7KyPxqNA31o2mKohgkILrz6J+yXdoCQ6kof/i/fy9kIaOluSg7IW5CI+b1vfMQVomiBOnhITmQBoG8WdcjGxq4tBN16JGq6BIMAVWwCRz7gJixk9FGjpCc5zwe45Fy2thCIUIqwm3MInToMnppkNqiLP77+LN7Z155fZxtIpWKK412F7QyKo9Zdyy8RCBb/cwMGkPM3sfZPHVORSVJ+AwIDbe5Pru33Dv+7156Px+LFycQb/ULeyoTKJ3SjWHGyKIdYeoDTpwKhLDsleaigJNhkq0S6fM56ZLQh0bSpMZ2CmP9/YXAx0BSaTbwds3jSZkWmzMqeCBD7agBw3Oeew7MCxUt4ZZ5eO2q0cQ7XFiWvJImCLS7QAB95zbnwZ/iBcX7eK1xbvAodpshkATe6ujcAons+LsWy/1EIG92xEOoKX6HIVdl2DuCXThT7R5eERLOP8arEATh++4FTVKw/IbtHv2ZWJPO+83Gxj8GaRFKRGqgyJnCv9x9GB+m/M4iTpMn2Lrpup2WCItViMtNpaTe8YC2eSUjeKLTSXMXrMHvt7MBd23c1bPBpBwwaBS3p6/hH0lPZDerihyDeV+D8neAKsOJ9EvtZqCugiSvAGKGz3EuYNUNTmJdBropoJhCjwOg0qfk4QISX1tHv7QSXidyhHn36EqbM2rYurADEwp+WrpAXCqWALuvHwY983oa88gYVqQaUlivE76ZCYw++llnDWpG6nJUZSUNYBhkt4mnk5pMSzfdhinO4qMRDu4rEVG0f6Nbzhwxij00hLUXwi6/hEITcOo1oka2pd2cxaE842/7oM3j2hJl92CFWii8M5/0O7Zp4mfcdnvMjAATbZw4Z0bnWotiSnd7+eas4fwiNvL59++jxrmbWmKgs3CsFUZm/2bDilObprcjpsmt+OHfUN59at9PDd/LWd03MyNYw/xt4HrWbBsJ0nJncipctly5kJSF3QQ4wqxuTSOXsm17K6MITO2kX1VMbSLaaSgPoLkiABVfhcRzhD1eiQJ4gCbD/kZ3tHL4apGnlm0myEdEumVmcC2/EoGdUiiV0YCbeO9DO2aipSSRxZu56ZTux8hKQpst+XRWYP4YVsRHy4/wGlDMxlzbj+yW0XTIzOB15fu5/tVIeKSokmKdgNgmSau9p3IemcxOWeOxaypQvH8NH30RyA0FbPOwNujC+3fXIQaG39ELfI37a+qSEMn5bq7ieg/jMjBo5F66Bed/BNBQ1Wd4RBGi1SQCwQEdd6743QGZMYy8Z9L8YTN2qnZsSoIx5vEUSqdlPJILm94djTDswewp7gbj3w0lJEvLmN6h+0sP7Sd88ZPZGd+Ov3SayhrdJIZU09AF5Q1uGiV6WfpoWTO736QhfvTmZRVzKrCZIanl7O5NJ6eSbVsLE1icMpBvttRwvCOWaTGejmlXxue+2In+eUNpCREkBzjweNUWba3jKcW7SInv4rxQzK5fnK3Iwuc5mR4l9axLH94Kre9toZ1e8rYc7gWh6ZQVR8gLtJFdGIkKTFuojwOeyRUVaRp4Onci6wFX5IzYwKWr/5oIvyP3ndNxaw3cWVlkrVgCVpCyhH6zm8aVprJiuERK3LwaPt7w4J/v4fqoymK8LRkEyfTkuB18sayfcx47BD+4hBjBmpHlp8/d71CiCOsCEvazNAuaV7mXd+PdTkdueOtTWzYuI1zR9dSqgzn1R92cPXYKjq18pNb24q4aBWf5UUTFpowKG90EucKkFfj5YLuDbyxoz2X9c7hte0duarnYd5duw+mZ6GpglHdUhnVLZW8snqW7SxhZ0ENZXVNRLo0Lh/XmYl90umVkfCTc1bCK7Ze7eL56p+nkFtSz4HSehRFkJEcSafUGKY/8i2qerRkTVPFEdKht9cgst76nJxzJmEF/Qin8pvpNMfdO1XFbDRxtk4j650lONLaQtjAfhOktItagYaV3+LbtAazuhIlMhJ3dk+iho9GS0j+TQwMsPsotOh0KcLzyPvf7QfToFVGKxyq73fReBW7AMCWWZIwqEM0S+8bzadrM2nXKoqS2ibe+LgS3/6viVHrCEoP/fu15ftqjUZ3BKsrMnF6vFRb8cR6BUHpIsoZRGDhC9qiwErjFrYWjKZ7axeGZaEIaJ8STfuU6BOeU3N1EIRflKN/YUgLgSArNZqs1OP39wVDjOqaGv7f0cnDdrYNIgaMpP38T8ibOQWp6wjH7zM0oapYTSZafDxZby/CldHpyAj2mxA2nNDhfApuvoi6b1ZgNoQXo2EtUHd2Eml3/ZuEc674TSNay/PJhABTEpfg5fGLBhIdFcOT7+T9sYIEYVebN1cMnT44A4AXvtqL49A8VhWuPbLtd19txKUJjNYDiGrbBVUvxxhQxF4ZQ0eXg2ivgx9K2nBat1qWFnXg3B65zFtZyJyZHX/SduZEOHF10E+vyQLqg1DRaLD9UDVrdtdy5rBs5Ane7mZDixo+gcxX3yfvojPgFyLvPzm6qmAFTJSIKLLeXoS7c69fDZQeh/Cqx6yvJe/Ck2lcvZ/IIZ1IOO9yXO2zMRsbqP/6E6o/+JCDV10JliThvCtPaGjHuvp/AmkR0E2+vGs8sYlxnHTPCrKc2Fxx/pgCsxKmNqtC8vHGEl5/8j70wrWgaBDusaEgMQzg0HpqD60H4PG1AGtYEQF6XGdSI30MyDTZkCcY1CueJfJrUiJ1kmMj8bg0PE4HHqeKpio4NQWHphyTerJFlw1T0hQy8AcN6v0han0Bqur9VNQ0UFZZQ1l5ORUlRVQVHyRQkg9aJKt6Obh8TJZdOcTxptlsaNHjTidj7tvkX3o2ilBA5ZcNTVGwQhKhuWn/xqd4ew36TYHSYyEtE6FqVL39km1gw7vQ4b1l9tQYRtzp5+HOvp+if95D8b9uIeqkk3G2bveTqdO0zCMRmZaPk0kJbo3Zn+TQsOY7epYU4BjTGbAF8oJGODv+O79TEXCoys/5j3/NzYG9+OMVdhuCA0FBkS4xLAFhkSc7wo3dklqGaPSB8G0nH8jfa39n/r580HZy16I0cMfY84PmtFmXLpd9AzXX0ZOQhOktgBmCYMD+YwYg1AghH+iNIP0Q7o/rxDaotx7YRkR8Gs9dMQwjTIT8qaHpxE6eQcZzAQ5efSGK95jI+4+hCDAASyVz/gf2KvB3GhiAOOKHfY20BAkzLkZLSMYKBuwFgLTL4pKv/Ts1H8+ncUMutV+8R/KVt4VL5n42Qd6ysMcrjdQvX2RuyYcoIZ0HG28FNCK0EL+RxXIcLGnLgV7+xjau2DmXW5VC6uIUpNSptwSHTcH+kGBXSLAvBId0KDckugl2jEjaldPCTiMpYeq1NINovnzw2cc5dqQ90agrjvn3RCVmVjgLYwoFKQUhGd66sYTn536EJzGZx6Z3xDCtn0y/dpxKJ276LKxgE4duuAo16gSGJgRYClbIpP2r7xA9+tQ/ZGDNpEWkxKiqQHFKHKlt7DinpoV9OvXIaOfq2I2GVXkE9u86/macAC1uZCE0VLOO/1R/BJZOpeYlqAuktBuoBnXLPvljlKV/CaYl0RTBMyuLCL73ArMb1nBIKGDa06RDUeisQQ+nxVlAUEKdBaWm4LAhOGTAIV1QqNu/qzKh0ZToFiAVjOPHFI4zrZ/zI39uERPO93kVSFShjQOyHNDVCa0CX/DwkybJUTdx2/hMdNP6iZBLs6ElnHslMhig4JabUGNVwDqGiapg+UzavfAaMZNn/DED+7nrUZSfXnN4gaPFJYAp8WR3P+b3J0bLT5eKSlSonpBhoaoCTdfxKy6EKpHi9/lkzdPk/qoQzz/9Dq+XvU+DEKjN7dqFQG8wCZognIADFFXgVRWyNejmMGleJOkI/BIaLEGtBVWmoFoKqgxJrQV1qNQHdfxCoUnRCJoWgTCRL9Qc5wtPw26HhkcReE2daIdKvAIJKqRoCskqJKmSeE0QiYXDMjARqA0H6OvP57SHI0iJvYELB7TCMO2QxrFoNrTEi27ECgYo/PsdqHFaeERTMOsN2j31nJ1r/J2R+D8CEQ6ep/79URJmXounW8/wef4fYGE0w0SQIANECAMRgscjxzOoXwjMIBWhZNJi7VP4LaNY8zR53dwfuHbLs6QQolqEBfKEQIYk0aNHosbEEdy/m1BZEWadn6DfJKiCEhMufZM2W1YF4oUkSYPOmu0ZKooA1R4tpLT7nZhY4eCwQFoWRtjImrv3KsJAEaBKiSIMBAKpSwzddtd0EwwD6p0gIhSQFpaqEiUNXj/0HDMeiCft4UsZnx2HER6pj0Vziif5ytuRgQBF992HGmdH89s89CgJ518THsFa1sDsk7HPTYtLsEez34AWNzJFSqocXoJ+wbqU7nS5Npu/jVzHpW/0YGS/ocR6xJEqoF9C881/YnkhkR/OYZpxiNKwULFQVcx6i+jxY8la8C1YJnp5KVagCauhnlDJIWo+fYfahR+gOIXti9E8oh0dmaQAGZSYDcaREJYQdlxSCBAaKJ7m2N/R/QgHi6VNQEXqEkdyPI7kViiaE09sPM7WbQns24Fv/SYUr4IqTRqFQhu9nmd2P8G598ex7NGz6Z4aecL7ITQNaRqk3Hgv0tApfuAh0u9/gKTLb/0fTZF/mK/azOn/LcHYP3iI3wwPIWqNVF4ccxmXX1BJjzYbmDp3CLGZZ3PPGZ3Rw9x46xeW580Fr/uqdV5+9h3eqF5MlaKiYPcYFwhMU5Jyx8PUfvcFh667DMULWnwCjlbtiBw2lnbPvY+Wfjuljz6ClqBx7IpDgM1R1yVaXAzJl16A4nJi1tVhBfxYfh9WwI9eWU7Tzq0gBEIVx/tiikBI2/3PfGkB0WNOIVSQh1FThVBAiYzD060nhffdRPkzT6MlaKiGSZWiMkgv4a5NjzHxgTg2PTSFVpEOu2bgxy+eUJGmRcot/ybm9Jm4O3TBMu0ytt+TgpbhVYwlZdgn/gOhJCF+s4VqAMqv8bn/B9BNhd5ZNdz/tzICjSFGv3oWl049h/OHNcdefv1EmyuJbpm7jBu2Pkc7qVMtwn0cFDBrDRLOOJnIHv3I7xuHq7IWxQtWSRnG9t1ULliM6+B20h96FX3Bs+i1fnAetRHbNEwsP2QveAP6D8fYuBEtMQ5cbvBEgMsD8fGYiz8k75LzwB0OpopmH1xCHSSecxrxU2ZQddelVM57DamER7d6SLrgNNq+sBDx1bs0FZQj3eCVJo0CZjXtpWbpvznzUQ/L7p104mCvOHq/PB262L/6I88ufMuFIqj1BX///r8TGtCiHH9fSHLTkHUcOKww+rnxTJ8wlJ6tBd9sK0JVbU9MCFvs5NgpQgKmaR2JIy3cUsr3Xy7nMtHEd2oSUkqEAiHVjeG0aDXuBoKvfUBtkYOI+FaIQBNCk0i3hhXlZN2HS2k1JZe6Pmcgv/8Gp2Ki6kEURaAjMC0HenoCBRHdKZt5Mdp3i8Fp2A3sI6IIqdGERkwg7fYHKeg8AtfBA2gihDB0VFVBOjxUqArxXaaR8N16SuZ9jMMRiyM81YY8Gr7PV9Pq7O00TLgB39zniXVaWE0+kLDH5aaPVcYTS1cx1IR7pnajXXIUAklANwERltcK359fiEv9EprL9CrrA+zMqUSc/F94yD8P+7X4+NMvzu/dq8ebme3aWlJK5b9lcJZlT3Gr9pXz5IdryKs2aQgKkqJBVRxEeRx28SsQCBn4ggbVjcFwnSY4NIWkaDcRLs3mztc2YUib55UQYe8f0E2McHdT0wIjGMTtcaJaFsIyaXaspKqiS4VgMESpzyJCtYh2KTQFQjT4dVITIrBQKGowiLBbEOHXDToleqlpDNDYFMLlclDZEMKUEBkdhTBCpEU7sUyT8romhKaRnBiNP2hRVFqN2+OmbZyTylo/piVplRBJZZOkrt5Hh3bJVNY00NjgJznKhRBQ6dMxNRcaJpV1TUS4HKTFe3FodimbQBA0THTD+uN+FM3pR0FAN4kQ8Oy1I+nXPhEzXJ+JlOw7uSeNq3aS9d57xJ4y43elpqQtHWqEdF37fumKjyZNHHdmi/lkzf7EsOxkht11evMp0AJsot+J48/BlEc1MMI3CADdlDhU8ZM9jt2mGc3p6+ZxxQr7O82rxJ+76mOPcZxEgfwfOOR/EL+28Pr9ECClDn8CabE5mS1+xBVrzsgAR1QWf3xjmyk+onkbcXR/+3uP2eFHcdMT4ghnLWws2NJKzbdAiKMCcQ7VXowozccNP/ljDax5v+bvPK6ULvy9QogwofGocTaP8rZa4/Hf0Xw/jh6DE/7+v4Fm2YXjvtcyjx7U+pk01m9F+II1RRGR4YfVIsZ27M1rfoBC/NSgfnbfE2xnc81O9MFvP69jaTrH/XzMuR63ujvBNsdRfY7ZXv7o8x//fOx2P3fso8f47df0e3FC10jV7HCIBMUb8V85AUUR4k+I4Nn4Pz1Rngg/TiKd6Oef2/7Y3/14399yrb/32C2K8Jvh27QKvawMJUKjcdX3WMHA0cDgH0SLkxb/wv8DaCYqFuSyb+JwpA6KFwrvfQqzyUebB+f+Pl7aj9Dy1Up/4f9+hKdEJSqWxIsuxKypRjgcWH6TyMGjjtvmj+AvI/sLx+Uj2z72+ok3+Y1FIyfCX0b2F45CyiMyBvb/w4uDP1poJKUC9uryL5/sL9gQ4rcXnPwKDMNAQgBAMS1ZFQqF4P/Oxd9f+H8UTU1N0jD0XADFkMae6poaA/ivpZT+wv/voZSWlQtTN5cDKInR0bvr6xt267ohAevPaBf8F/53IpzVsALBkCgqLtrfpk3qKimlUEaPHm3owcBLpeXlghaTlfkL/z+CWXC4UOiB0H39+/fXP/jgA0W59957FUXp8Oqe3Xu2Nfp8mhDC+Gs0+wu/B3Z1oEQIEaqorHYcOJDz3qmnTnrn/fffV2fMmGGKML3H+uyzJZ1j46NX9u/bJ9HjcRtSSu0vH+0v/BrCxiUBo7Kq2rFpy5bvE+Nip/Tr1y8ASCFsvjDNFvfZZ4v7xsbHLOzdq2ebqMgIA1BkONbxF/7CjyGEsADLMEytoLCQ/ftz3nY71UtHjx4dkFKKsPEdDVs0G9r7n33WNi4y6pXsjp3Gt05LJRxH+8tX+wvHQhCmz9XW1bN7z97Kmqrqu089ddJLAMcaWPPGR9BsaABfLPrqitiY6Bvi4+O6JSUl4XK5aEk09/duMfzf4Gb+gcuzLOt/ROlqhpQS6w/IUJ3gmwgEglRWVlFf33CgobHhw4C/8dmpU6cW33vvvcp9990njzUwOMFlH7vhvffe6+zZd+Bwl0PtKwRpskW7oos/nL34NUiJFCiaUKT3/9iQbOEDYQph/S5T+6Uqrp9CANKU0vL/vpP7rV+vIIQIIinXLX1nnt+/5ZYZM5oAli5dqo0ePfqEst3/H9W01tRwFOEbAAAAAElFTkSuQmCC' +c51 = b'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' +c52 = b'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' + +cards = 52 # Total 52 cards +rows = 2 # Two rows +columns = 7 # 7 colums +cells = rows * columns # Cells - total positions for cards +all = cells + cards # Total cards and blan cards +card_width = 153 # Width of card in pixels +card_height = 200 # height of card in pixels +pad_x = 36 # Gap between cells on horizontal +pad_y = 36 # Gap between celss on vertical +card_pad = 25 # The distance between cards in stack +font = 'simsun 16 bold' # font used in buttons +width = (card_width + pad_x) * columns + pad_x # Graphic width +height = (card_height + pad_y) * rows + pad_y + 9*card_pad # Graphic Height +# Coordinates for each cell +ref_x = [(pad_x + card_width) * int(i%7) + pad_x for i in range(cells)] +ref_y = [height - card_height * int(i/7) - pad_y * int(i/7 + 1) + for i in range(cells)] +# Rack position for each cards +stack = [i for i in range(cells)] + [0 for i in range(24)]+[ + 6+i for i in range(8) for j in range(i)] +show_card = [38, 40, 43, 47, 52, 58, 65] # Cards shown when beginning +start_x = int((width-card_width)/2) # Position for flash card show +start_y = card_height+pad_y +# Image BASE64 data of cards with top-side and bottom-side +byte = [['']+[c0 for __ in range(52)],[cn,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10, + c11,c12,c13,c14,c15,c16,c17,c18,c19,c20,c21,c22,c23,c24,c25,c26, + c27,c28,c29,c30,c31,c32,c33,c34,c35,c36,c37,c38,c39,c40,c41,c42, + c43,c44,c45,c46,c47,c48,c49,c50,c51,c52]] +# Area of rack in cells, 0 ~ 13 for all cells +top = [3, 4, 5, 6] +bottom = [7, 8, 9, 10, 11, 12, 13] + +button_down = False # Flag for mouse left button down +drag = False # Flag for mouse in drag mode +start = True # Flag for initial position of mouse +New_Start = True # Flag for new game + +# ctypes.windll.user32.SetProcessDPIAware() # Set unit of GUI to pixels + +class poker(): + ''' + Definition of eack poker card: + Parameter: + card - Sequence number of cards, 0 ~ 65. + kind - Kind of cards, 'Blank Card' or 'Card' + Attributes: + card - Sequence number of cards, 0 ~ 65 + ids - Id of graphic element + up - Card value of upper card, None for no upper card + down - Card value of lower card, None for no lower card + x,y - Variable coordinate of card used when drag mode + x0, y0 - Coordinate of card whne in cell/rack + kind - Suit of cards, spades♠/hearts♥/clubs♣/diamonds♦ (1~4) + no - Number of card (1~13) + rack - Which card located (0~13, not in 2) + fix - Blank card if defined as fixed position + side - State of cards, back side of front side (0/1) + ''' + def __init__(self, card=None, kind='Card'): + + # Initialize values for each card + + self.card = card + self.ids = None + + if kind=='Blank Card': + + self.x0 = self.x = ref_x[card] + self.y0 = self.y = ref_y[card] + self.up = None + self.down = None + self.kind = 0 + self.no = 0 + self.rack = card + self.fix = True + self.side = 0 if card==2 else 1 + + else: + self.up = None + self.kind = int(card_list[card-cells]/13)+1 + self.no = card_list[card-cells] % 13 + 1 + self.side = 0 + self.fix = False + self.rack = stack[card] + self.new_card(self.rack) + + def cards(self): + # Return numbers of cards in rack of caller + return p[self.rack].up_cards() + + def click_rack0(self): + # Event handler for click on Rack 0 (foundation) + if self.fix and (p[1].cards()>0): + while True: + pp = p[p[1].find_top()] + if not pp.move_rack(0): return + # 0 card/Rack 0 + elif not self.fix: + # If three cards in Rack 0 + if p[1].cards()==3: p[1].move_rack_bottom() + self.move_rack(1) + + def click_rack1(self): + # Click on Rack 1 to move card to Rack 3 ~ 6 (top) + if self.fix or (self.up_cards()>1): + return + else: + self.move_to_any_rack2() + + def click_rack3(self): + # Click on Rack 7 ~ 13 (Bottom) to move card to Rack 3 ~ 6 (top) + # If No card or number of cards moret than 1 + if self.fix or (not self.side) or (self.up_cards()>1): + return + else: + self.move_to_any_rack2() + + def find_top(self): + # Find top card in caller's Rack + card = self.rack + while True: + if p[card].up == None: + return card + card = p[card].up + + def flash(self): + # Show cards from bottom-center to cells when game start + for i in range(all): + index = (p[i].kind-1)*13+p[i].no if p[i].kind!=0 else 0 + d = byte[p[i].side][index] + # Load image BASE64 data and show on bottom-center + if d != '': + p[i].ids = draw.DrawImage(data=d, location=(start_x,start_y)) + # Calculation step and steps to move image + x, y, x0, y0 = p[i].x0, p[i].y0, start_x, start_y + dx, dy, step = start_x-x, start_y-y, 5 + if abs(dx) > abs(dy): + step_x = step if dx<0 else -step + count = int(abs(dx)/abs(step_x)) + step_y = -dy/count + else: + step_y = step + count = int(abs(dy)/step_y) + step_x = -dx/count + num = 0 + # Loop to show trace of card + while True: + num += 1 + x0 += step_x + y0 += step_y + draw.RelocateFigure(p[i].ids, x0, y0) + draw.ParentForm.refresh() + if num == count: + break + # Move image to final position on cells + draw.RelocateFigure(p[i].ids, x, y) + draw.ParentForm.refresh() + + + def move_back(self): + # Move card back to original position after drag + pp = self + while True: + pp.x, pp.y = pp.x0, pp.y0 + draw.RelocateFigure(pp.ids, pp.x, pp.y) + if pp.up==None: + break + pp = p[pp.up] + draw.ParentForm.refresh() + + def move_from_rack1_to_rack2(self, rack): + # Drag card from Rack 1 to Top (Rack 3 ~ 6) + # If no card or not only one card + if (self.up_cards()!=1) or self.fix or (not self.side): + return + pp = p[p[rack].find_top()] + # Move card with no 1 to Top when no card in Top + if pp.fix and (self.no==1): + self.move_rack(rack) + # Move card with same suit and one higher no. to Top + elif not pp.fix: + if (self.kind == pp.kind) and (self.no==pp.no+1): + self.move_rack(rack) + + def move_from_rack1_to_rack3(self, rack): + # Drag card from Rack 1 to Bottom (Rack 7 ~ 13) + # If not only one card + if (self.up_cards()!=1) or self.fix or (not self.side): + return + pp = p[p[rack].find_top()] + # Move card 'King' on Rack 1 to blank rank in Bottom + if pp.fix and (self.no==13): + self.move_rack(rack) + # Move card from Rack 1 to Bottom if different suit and less one + elif ((not pp.fix) and + (self.kind%2 != pp.kind%2) and (self.no==pp.no-1)): + self.move_rack(rack) + else: + self.move_back() + + def move_from_rack2_to_rack3(self, rack): + # Move card from Top to Bottom + # If blank card + if (self.up_cards()!=1) or self.fix or (not self.side): + return + pp = p[p[rack].find_top()] + # If 'King' card to blank rack + if pp.fix and (self.no==13): + self.move_rack(rack) + # if card with different suit and less one + elif ((not pp.fix) and + (self.kind%2 != pp.kind%2) and (self.no==pp.no-1)): + self.move_rack(rack) + else: + self.move_back() + + def move_from_rack3_to_rack2(self, rack): + # Move card from Bottom to Top + # If no card + if self.fix or (not self.side): + return + pp = p[p[rack].find_top()] + # If card 'Ace' moved to blank rack on Top + if (pp.fix and (self.up_cards()==1) and (self.no==1)): + self.move_rack(rack) + # If one front-side card moved to non-blank rack on TOP + elif ((not pp.fix) and (self.up_cards()==1) and + (self.kind==p[card2].kind) and (self.no==p[card2].no+1)): + self.move_rack(rack) + # If lower card not shown, then turn over + else: + self.move_back() + + def move_from_rack3_to_rack3(self, rack): + # Move cards from Bottom to Bottom + # If no card + if self.fix or (not self.side): + return + # If bottom card is 'King' and moved to blank rank + pp = p[p[rack].find_top()] + if (pp.fix and (self.no==13)): + self.move_rack(rack) + # If cards with differet suit and <1, moved to non-blank rack on Bottom + elif ((not pp.fix) and (self.kind%2!=pp.kind%2) and (self.no==pp.no-1)): + self.move_rack(rack) + else: + self.move_back() + + def move_offset(self, dx, dy): + # move Image with offset + if self.fix or (not self.side): + return + pp = self + while True: # Bring cards to front + draw.BringFigureToFront(pp.ids) + if pp.up == None: break + pp = p[pp.up] + pp = self + while True: # Move cards + pp.x, pp.y = pp.x + dx, pp.y + dy + draw.RelocateFigure(pp.ids, pp.x, pp.y) + if pp.up == None: break + pp = p[pp.up] + draw.ParentForm.refresh() + + def move_rack(self, rack): + # move top cards of caller to up side of card2 + if self.fix: return False + if rack in [0,1]: self.turn_over() + card_d = self.down # keep down card and cut the link + p[card_d].up = None + + card_now = self.card # start from caller card + if card_now == None: return False + ok = False + while True: + if card_now == None: break # Not card left for moving + pp = p[card_now] + top_card = p[rack].find_top() + + pp.rack = rack # Update new info for card + pp.x0, pp.y0 = pp.x, pp.y = p[top_card].offset(rack) + + p[top_card].up = card_now # build link + pp.down = top_card + pp.update(same=True, front=True) + + card_now = pp.up # next card + pp.up = None + ok = True + + if (ok and (p[card_d].rack in bottom) and (not p[card_d].fix) and + (not p[card_d].side)): + p[card_d].turn_over() # down card to turn over + + return True + + def move_rack_bottom(self): + # Move lowest card of Rack 1 to Bottom of Rack 0 which with 3 cards + card1 = p[1].up # Remove card1 from Rack 0 + if card1 == None: return + p[card1].turn_over() + p[1].up = p[card1].up + if p[1].up!= None: p[p[1].up].down = 1 + + card0 = p[0].up # Insert card1 to Rack bottom + p[0].up = card1 + p[card1].up = card0 + p[card1].down = 0 + p[card0].down = card1 + + p[card1].x0 = p[card1].x = p[0].x0 # new position, rack on Rack 0 + p[card1].y0 = p[card1].y = p[0].y0 + p[card1].rack = 0 + p[card1].update() + draw.SendFigureToBack(p[card1].ids) + draw.SendFigureToBack(p[0].ids) + + card = p[1].up # new position for cards on Rack 1 + p[card].x0 = p[card].x = p[1].x0 + card_up = p[card].up + p[card_up].x0 = p[card_up].x = p[1].x0 + card_pad + p[card].update() + p[card_up].update() + + def move_to_any_rack2(self): + # Move one card to rack on Top + for rack in top: + top_card = p[rack].find_top() + pp = p[top_card] + if pp.fix and (self.no==1): # If 'ACE' card to blank rack + self.move_rack(rack) + return True + elif ((self.kind==pp.kind) and (self.no==pp.no+1)): + self.move_rack(rack) # If card with same suit and >1 + return True + return False + + def new_card(self, card): + # Initialize a new card for (x, y), (x0, y0) and up + dy = 0 if card ==0 else card_pad + count = p[card].cards() + self.x = self.x0 = p[card].x0 + self.y = self.y0 = p[card].y0 - dy*count + card = p[card].find_top() + p[card].up = self.card + self.down = card + + def offset(self, rack): + # Calculation coordinate for offset on different rack + # Rack 1: (card_pad, 0), Bottom: (0, card_pad) + # If blank rack, (0, 0) + dx = dy = 0 + if rack == 1: + dx, dy = card_pad, 0 + elif rack in bottom: + dx, dy = 0, card_pad + pp = p[p[rack].find_top()] + if pp.fix: + dx = dy = 0 + return pp.x0 + dx, pp.y0 - dy + + def turn_over(self): + # Turn over card and update image + self.side = 1 - self.side + self.update(same=False) + + def up_cards(self): + # count cards up and include caller card + count = 0 if self.fix else 1 + card = self.up + while True: + if card == None: + return count + count += 1 + card = p[card].up + + def update(self, same=True, front=False): + # Update image position, or image if not same + if front: + draw.BringFigureToFront(self.ids) + if same: + draw.RelocateFigure(self.ids, self.x, self.y) + draw.ParentForm.refresh() + else: + index = (self.kind-1)*13+self.no if self.kind!=0 else 0 + d = byte[self.side][index] + draw.DeleteFigure(self.ids) + self.ids = draw.DrawImage(data=d, location=(self.x, self.y)) + +def id_to_card(ids): + # find card for image id + for card in range(all): + if p[card].ids == ids: + return card + return None + +def get_card(x, y, down=True): + # get card by position (x,y), button down for 1st one, button up for 2nd one + ids = draw.get_figures_at_location((x,y)) + if down+len(ids)<2: return None + return id_to_card(ids[down-2]) + +def condition(): + # Check all the conditions of cards selected when button down and up + result = set() + if drag: result.add('D' ) + if card1!=None: result.add('C1' ) + if card2!=None: result.add('C2' ) + if card1!=None and p[card1].rack==0: result.add('R10') + if card1!=None and p[card1].rack==1: result.add('R11') + if card1!=None and p[card1].rack in top: result.add('R12') + if card1!=None and p[card1].rack in bottom: result.add('R13') + if card2!=None and p[card2].rack==0: result.add('R20') + if card2!=None and p[card2].rack==1: result.add('R21') + if card2!=None and p[card2].rack in top: result.add('R22') + if card2!=None and p[card2].rack in bottom: result.add('R23') + if card1!=None and p[card1].fix==False: result.add('F1' ) + if card2!=None and p[card2].fix==False: result.add('F2' ) + if card1!=None and p[card1].side==1: result.add('S1' ) + if card2!=None and p[card2].side==1: result.add('S2' ) + return result + +sg.change_look_and_feel('Green') +# Three buttons on top side - 'New Game', 'Game Over' and 'Flush All' +# One Graphic area on bottom side +layout= [[sg.Button('New Game', pad=(pad_x, (pad_y,0)), font=font), + sg.Button('Game Over', pad=(pad_x, (pad_y,0)), font=font), + sg.Button('Flush All', pad=(pad_x, (pad_y,0)), font=font)], + [sg.Graph(background_color='green', canvas_size=(width, height), + graph_bottom_left=(0,0), key='Graph', pad=(0,0), enable_events=True, + graph_top_right=(width, height), drag_submits=True)]] + +# Create window +window = sg.Window('Klondike Solitaire', layout=layout, + background_color='green', finalize=True) +# Easy name for graphic element +draw = window['Graph'] # type: sg.Graph + +# Loop Start for event detect +while True: + + # Initial poker cards, flash only when game start + if New_Start: + card_list = random.sample(range(cards), cards) + p = [0 for i in range(all)] + for i in range(cells+cards): # Initial cards + kind = 'Blank Card' if i < cells else 'Card' + p[i] = poker(card=i, kind=kind) + p[0].flash() # Flash cards + for card in show_card: p[card].turn_over() + New_Start = False + + event, values = window.read() # read window event + + if event==None or event=='Game Over': # Window close of Game over clicked + break + + # No event + elif event == sg.TIMEOUT_KEY: + continue + + elif event == 'New Game': # New Game button event + for i in range(all): + if p[i].ids != None: draw.DeleteFigure(p[i].ids) + New_Start = True + + elif event == 'Flush All': # Auto move cards to top + while True: + result = False + for i in [1]+bottom: # Check all cards + card = p[i].find_top() + if p[card].fix: continue + ok = p[card].move_to_any_rack2() + result = result or ok + if not result: break + + if event == 'Graph': # Button DOWN event + + x1, y1 = values['Graph'] + if not start: # Keep position + x0, y0 = old_position + dx, dy = x1-x0, y1-y0 + old_position = (x1, y1) + + if button_down: # Check first mouse button down + if (x1,y1)!=(x0,y0): + drag = True + if (card1 != None) and (p1.side==1): # Check if movable + if (((p1.rack in [1]+top) and p1.up_cards()==1) or + (p1.rack in bottom)): + p1.move_offset(dx, dy) + else: + if start: # save initial position + old_position = values['Graph'] + start = False + button_down = True # 1st mouse down event + card1 = get_card(x1, y1) # Mouse down generate two time events + if card1 != None: + p1 = p[card1] + + elif event == 'Graph+UP': # Button UP event + + x2, y2 = values['Graph'] + card2 = get_card(x2, y2, down=False) + if card2!= None: + p2=p[card2] + rack2=p2.rack + result = condition() + ''' + Check condition for what to do + D for Drag, C for card, S for card shown, F for card not fixed + R1m for button down/area m, R2n for button up/area + ''' + if {'D','C1','R10','S1','F1'}.issubset(result) and 'C2' not in result: + p1.move_back() + elif {'D','C1','R11','S1','F1','C2','R22'}.issubset(result): + p1.move_from_rack1_to_rack2(rack2) + elif {'D','C1','R11','S1','F1','C2','R23'}.issubset(result): + p1.move_from_rack1_to_rack3(rack2) + elif {'D','C1','R12','S1','F1','C2','R23'}.issubset(result): + p1.move_from_rack2_to_rack3(rack2) + elif {'D','C1','R13','S1','F1','C2','R22'}.issubset(result): + p1.move_from_rack3_to_rack2(rack2) + elif {'D','C1','R13','S1','F1','C2','R23'}.issubset(result): + p1.move_from_rack3_to_rack3(rack2) + elif {'D','C1','S1','F1'}.issubset(result) and ( + ('R11' in result) or ('R12' in result) or ('R13' in result)): + p1.move_back() + elif {'C1','R10'}.issubset(result): + p1.click_rack0() + elif {'C1','R11'}.issubset(result): + p1.click_rack1() + elif {'C1','R13'}.issubset(result): + p1.click_rack3() + + button_down = False + drag = False + start = True + +window.close() \ No newline at end of file diff --git a/UserCreatedPrograms/Minesweeper.py b/UserCreatedPrograms/Minesweeper.py new file mode 100644 index 000000000..557f4f052 --- /dev/null +++ b/UserCreatedPrograms/Minesweeper.py @@ -0,0 +1,229 @@ +import PySimpleGUI as sg +import random + +''' +Source code of MineSweeper Game +''' + +blank = b'iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAEnQAABJ0Ad5mH3gAAAA5SURBVEhL7c0xAQAgDMTABynVU7MohAUN6ZJbMmbV6ZsB+xfnGOMY4xjjGOMY4xjjGOMY4xgzNE4euGMCWklhg+IAAAAASUVORK5CYII=' +bomb = b'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' +flag = b'iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAE9ElEQVR4nL2WTWxUVRTHf+fe+147pbQKFChUipREKUYEEhAT2SgGNP0IpkkXsDCwIWHVdMWGuDEkRIwJC+OCEQkbiCB2ISQkiiHRlCIsnBqirZCWr1JqKRPBmXn3uJg37bR0qNHqP3nJzP363XPOPedeUVURESUvAbRlTf0zodWGocePrl3ovZeO+0KgAngAFMY7wDMhib9cUVsIZIr+o6pipkBpe7UuIWQuOOu/r51T/jbwprX2hDHmJ2NMyhhzVUQ+rK2tXeacyznnvHPOG2M8EMVQsda+IyKfAXOL1wcQERWKtB8MQOqVpTseRdH+c6mhPg9bmCJjDLlcbgT4CPgauAsEZWVlz2cymc0i0gysBUa89yuAsYKxxa4plgD6+Y6X5yS7b9258OtIZexKLbhRRDSKIr9x40bX3NxMTU0Nt2/f/iOZTAbXr18PrLWoKrH1t733rcCP8XxPCQnAx1tXlm1bvbi/PHQRIpExRo0xGgSBioju2bNH0+m0T6fT2YGBAe3v79f79+/rhg0bIhHJOuciY0wuntcRr21LQSfBW9bU/lBdESpIzsZg55wCOjw8rMlkUltbW3Xnzp26adMmr6r+0KFDCmgYhj6GPmCaGE+rtrb8zt5du+TUouqEgmRtkcXOOd27d6+mUim9ePGinjlzRs+fP68DAwPa0NCggDrn1BgTxd858id7EthMBQ8N5QeEVgYTgQF0fIr3nlwux+HDh+nu7iaRSBAEAXV1dTQ2NmKtpby8nCiKIB9PA3xDPp0mudqVstwZO5AIJsbGJ5nOzk6uXLlCT08Ply5dIp1OM2/ePFpaWjh27Bi7du3iyJEjOOckiiJUdR1P5vuTFhcUWBkod/luEYP3nvnz53Pw4EHOnj1LfX09XV1dnD59mqqqKjo7Ozl+/DgLFixAZMKrItJDnNtPtXjhwnyuOSe3yvJggyree6IoYvv27aRSKXbv3k1vby9jY2OMjo7S3NxMX18fxhhEhCiKBEBVXwc+AR7GcJ3W4saT+Y4glDuBNR7EeFUNgoDR0VGGh4e1o6NDV61axYEDB2hqauLo0aMkk0my2Szt7e1473HOeSASkc1ANUXFo5QEYP9bjfPeeHHhiLVGjTG5IAiyIuLb29u1r69P169fr7ELFdDq6mrdt2+fr6+vz4lIZK3VOKV6gFXxuiVDOw4+0dZmt7206JdEvogUFlFghHyJ1DAM1TmXC8MwS75SKaDGGBWRq8aY95g4zU/P41gGoHXNku+enVOmIL9ZkQ+cc69VVlYuAKorKirWicipwoastRqG4Ygx5gtrbQuTz8/fgo4XkdY1tV+9sHjup0BVqZnW2iZjzC5r7RZg4dTuUtBp87hQRECG1j9X/e21Ow/HltVTfuMGGSYOiQAaRVHXNDDI521UyrinBhv0VjqTWw3I8uXkmLiptOi3jQ0oWBcxEe+SmgHMoMUsmmGRwuU/I2xGcKGIqJhBRWuK22ZL08a4UEQM3CSf/Jw8WfoS/yea1uL3Y5f9mcncVaFs68qVZUy8Qv47cEF3E/fui6KJxKOa2QLOBFZALl8mq8LjyEWLAfb/Hxa3teX7BPndqCwF6G2bPXDJh8B4EVEdEqRuUtssaKY8BpFbQN1sAWcEj+etMojo1Br8r1XS1Zwk5upNYMWkzcyCjKpOG7cT8eNMA/kZ+BJmr4ioqvwF0Vn06LBZVccAAAAASUVORK5CYII=' + +font = 'Courier 16 bold' +width = 25 +height = 14 +all = 80 +new_start = True +size = (30,30) +# 0: 0, 1: hidden card, 2: bomb card, 3: flag card, 4: shown card +im = ['', blank, bomb,flag, ''] +color = [('grey', 'grey'), ('black', '#22B14C'), + ('black', '#22B14C'), ('black', '#22B14C'), ('black', 'grey')] + +def binding_all(): # Bind right button of mouse to cell object + + for x in range(width): + for y in range(height): + window[b[x][y].key].bind( + '', '+RIGHT') + +# Setting for top buttons +def button1(text, key=None, disabled=False, button_color=('white', 'green')): + + return sg.Button(text, pad=(10, 10), font=font, focus=False, key=key, + disabled=disabled, button_color=button_color) + +def button2(x, y): # define cell as instance of button and + + b[x][y] = button(x,y) # bulid Button + return b[x][y].button + +def check_blank(x, y): # Check if cell near 0-bomb cel + + if b[x][y].num==0: return False + for i in [-1, 0, 1]: + for j in [-1, 0, 1]: + if i==0 and j==0: continue + if ((0<=x+i