From 551a19c83b88e269a852f5d93b2a1e3aca531582 Mon Sep 17 00:00:00 2001 From: rdbende Date: Mon, 1 Mar 2021 22:54:21 +0100 Subject: [PATCH 01/20] Create NumberEntry widget An entry that takes only numbers or calculations and calculates the result of the calculation --- ttkwidgets/numberentry.py | 91 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 ttkwidgets/numberentry.py diff --git a/ttkwidgets/numberentry.py b/ttkwidgets/numberentry.py new file mode 100644 index 00000000..ec69b6f3 --- /dev/null +++ b/ttkwidgets/numberentry.py @@ -0,0 +1,91 @@ +""" +Author: rdbende +License: GNU GPLv3 +Copyright (c) 2021 rdbende +""" + +import tkinter as tk +from tkinter import ttk + + +class NumberEntry(ttk.Entry): + """ + An entry that takes only numbers or calculations and calculates the result of the calculation + + :param expressions: Allow the use of expressions (default is True) + :type expressions: bool + + :param roundto: The number of decimals in the result (default is 0) + :type roundto: int + """ + + + def __init__(self, master, **kwargs): + + + self._expr = kwargs.pop("expressions", True) + self._round = kwargs.pop("roundto", 0) + ttk.Entry.__init__(self, master, **kwargs) + self.bind("", self._eval) + self.bind("", self._eval) + self.bind("", self._check) + + + def _eval(self, *args): + current = self.get() + try: + if len(current) > 0: + if int(self._round) == 0: + result = int(round(eval(current), 0)) + self.delete(0, "end") + self.insert(0, result) + else: + result = round(float(eval(current)), self._round) + self.delete(0, "end") + self.insert(0, result) + except SyntaxError: + self.delete(0, "end") + self.insert(0, "SyntaxError") + self.select_range(0, "end") + except ZeroDivisionError: + self.delete(0, "end") + self.insert(0, "ZeroDivisionError") + self.select_range(0, "end") + + + def _check(self, *args): + typed = self.get() + if not typed == "SyntaxError" and not typed == "ZeroDivisionError": + checked = self._replace(typed) + self.delete(0, "end") + self.insert(0, checked) + + + def _replace(self, typed) -> str: + if self._expr: + allowed = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+", "-", "*", "/", "%", "."] + else: + allowed = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "."] + for current in typed: + if not current in allowed: + typed = typed.replace(current, "") + return typed + + + def cget(self, key): + """Return the resource value for a KEY given as string""" + if key == "expressions": + return self._expr + elif key == "roundto": + return self._round + else: + return ttk.Entry.cget(self, key) + + + def keys(self): + """Return a list of all resource names of this widget""" + keys = ttk.Entry.keys(self) + keys.extend(["expressions", "roundto"]) + keys = sorted(keys) + return keys + From a6db0b37d142b00b5c39b74d86daf05411a3bdce Mon Sep 17 00:00:00 2001 From: rdbende Date: Mon, 1 Mar 2021 22:55:48 +0100 Subject: [PATCH 02/20] Change the default hover-cursor to hand2 Change the default hover-cursor from hand1 to hand2 --- ttkwidgets/linklabel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ttkwidgets/linklabel.py b/ttkwidgets/linklabel.py index f1f4f730..7af88e78 100644 --- a/ttkwidgets/linklabel.py +++ b/ttkwidgets/linklabel.py @@ -29,7 +29,7 @@ def __init__(self, master=None, **kwargs): :type clicked_color: str :param kwargs: options to be passed on to the :class:`ttk.Label` initializer """ - self._cursor = kwargs.pop("cursor", "hand1") + self._cursor = kwargs.pop("cursor", "hand2") self._link = kwargs.pop("link", "") self._normal_color = kwargs.pop("normal_color", "#0563c1") self._hover_color = kwargs.pop("hover_color", "#057bc1") From 7611f2a1ffbe6639825e7ab81e3ece98b9209d27 Mon Sep 17 00:00:00 2001 From: rdbende Date: Mon, 1 Mar 2021 22:57:11 +0100 Subject: [PATCH 03/20] Change the movement cursor to fleur Change the movement cursor from exchange to fleur --- ttkwidgets/itemscanvas.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ttkwidgets/itemscanvas.py b/ttkwidgets/itemscanvas.py index ea7bb128..06f210e9 100644 --- a/ttkwidgets/itemscanvas.py +++ b/ttkwidgets/itemscanvas.py @@ -113,7 +113,7 @@ def left_motion(self, event): return item = results[0] rectangle = self.items[item] - self.config(cursor="exchange") + self.config(cursor="fleur") self.canvas.itemconfigure(item, fill="blue") xc, yc = self.canvas.canvasx(event.x), self.canvas.canvasy(event.y) dx, dy = xc - self.current_coords[0], yc - self.current_coords[1] From 61a46c5f7d20764776a084e8dacdb3c4bc7e39f1 Mon Sep 17 00:00:00 2001 From: rdbende Date: Mon, 1 Mar 2021 22:58:07 +0100 Subject: [PATCH 04/20] Add NumberEntry to __init__.py --- ttkwidgets/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ttkwidgets/__init__.py b/ttkwidgets/__init__.py index 2360b89c..f8d9f0f7 100644 --- a/ttkwidgets/__init__.py +++ b/ttkwidgets/__init__.py @@ -11,6 +11,7 @@ from ttkwidgets.timeline import TimeLine from ttkwidgets.tickscale import TickScale from ttkwidgets.table import Table +from ttkwidgets.numberentry import NumberEntry from ttkwidgets.validated_entries.numbers import ( PercentEntry, IntEntry, FloatEntry, From 8941ab3e8bbb4e7be37413d464041636bb51008b Mon Sep 17 00:00:00 2001 From: rdbende Date: Tue, 2 Mar 2021 18:33:27 +0100 Subject: [PATCH 05/20] Fixed portability issues Change the default cursor to use the native link pointer on Mac and Windows --- ttkwidgets/linklabel.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ttkwidgets/linklabel.py b/ttkwidgets/linklabel.py index 7af88e78..10cb31fd 100644 --- a/ttkwidgets/linklabel.py +++ b/ttkwidgets/linklabel.py @@ -29,7 +29,12 @@ def __init__(self, master=None, **kwargs): :type clicked_color: str :param kwargs: options to be passed on to the :class:`ttk.Label` initializer """ - self._cursor = kwargs.pop("cursor", "hand2") + if root.tk.call('tk', 'windowingsystem') == 'win32': + self._cursor = kwargs.pop("cursor", "hand2") # Native Windows hand pointer + elif root.tk.call('tk', 'windowingsystem') == 'aqua': + self._cursor = kwargs.pop("cursor", "pointinghand") # Native Mac hand pointer + else: + self._cursor = kwargs.pop("cursor", "hand1") self._link = kwargs.pop("link", "") self._normal_color = kwargs.pop("normal_color", "#0563c1") self._hover_color = kwargs.pop("hover_color", "#057bc1") From 8488995fd0d8ef26616a16c8a2cafc8462cd3dd3 Mon Sep 17 00:00:00 2001 From: rdbende Date: Tue, 9 Mar 2021 09:31:12 +0100 Subject: [PATCH 06/20] Restore cursor --- ttkwidgets/itemscanvas.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ttkwidgets/itemscanvas.py b/ttkwidgets/itemscanvas.py index 06f210e9..ea7bb128 100644 --- a/ttkwidgets/itemscanvas.py +++ b/ttkwidgets/itemscanvas.py @@ -113,7 +113,7 @@ def left_motion(self, event): return item = results[0] rectangle = self.items[item] - self.config(cursor="fleur") + self.config(cursor="exchange") self.canvas.itemconfigure(item, fill="blue") xc, yc = self.canvas.canvasx(event.x), self.canvas.canvasy(event.y) dx, dy = xc - self.current_coords[0], yc - self.current_coords[1] From 8b614d2ce7da363483c3aacc19ba7e621082c5c9 Mon Sep 17 00:00:00 2001 From: rdbende Date: Tue, 9 Mar 2021 09:32:19 +0100 Subject: [PATCH 07/20] Restore linklabel --- ttkwidgets/linklabel.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/ttkwidgets/linklabel.py b/ttkwidgets/linklabel.py index 10cb31fd..f1f4f730 100644 --- a/ttkwidgets/linklabel.py +++ b/ttkwidgets/linklabel.py @@ -29,12 +29,7 @@ def __init__(self, master=None, **kwargs): :type clicked_color: str :param kwargs: options to be passed on to the :class:`ttk.Label` initializer """ - if root.tk.call('tk', 'windowingsystem') == 'win32': - self._cursor = kwargs.pop("cursor", "hand2") # Native Windows hand pointer - elif root.tk.call('tk', 'windowingsystem') == 'aqua': - self._cursor = kwargs.pop("cursor", "pointinghand") # Native Mac hand pointer - else: - self._cursor = kwargs.pop("cursor", "hand1") + self._cursor = kwargs.pop("cursor", "hand1") self._link = kwargs.pop("link", "") self._normal_color = kwargs.pop("normal_color", "#0563c1") self._hover_color = kwargs.pop("hover_color", "#057bc1") From 9584d3f36941a6aa89ac3dbe70d36f6032bdb6ee Mon Sep 17 00:00:00 2001 From: rdbende Date: Tue, 9 Mar 2021 10:03:30 +0100 Subject: [PATCH 08/20] Add __getitem__, __setitem__ and configure Add __getitem__, __setitem__, config and configure, docstring formatting --- ttkwidgets/numberentry.py | 40 +++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/ttkwidgets/numberentry.py b/ttkwidgets/numberentry.py index ec69b6f3..dfef7310 100644 --- a/ttkwidgets/numberentry.py +++ b/ttkwidgets/numberentry.py @@ -11,27 +11,31 @@ class NumberEntry(ttk.Entry): """ An entry that takes only numbers or calculations and calculates the result of the calculation - - :param expressions: Allow the use of expressions (default is True) - :type expressions: bool - - :param roundto: The number of decimals in the result (default is 0) - :type roundto: int """ - - - def __init__(self, master, **kwargs): - + def __init__(self, master=None, **kwargs): + """ + Create a NumberEntry + :param expressions: Allow the use of expressions (default is True) + :type expressions: bool + :param roundto: The number of decimals in the result (default is 0) + :type roundto: int + """ self._expr = kwargs.pop("expressions", True) self._round = kwargs.pop("roundto", 0) ttk.Entry.__init__(self, master, **kwargs) self.bind("", self._eval) self.bind("", self._eval) self.bind("", self._check) - + + def __getitem__(self, key): + return self.cget(key) + + def __setitem__(self, key, value): + self.configure(**{key: value}) def _eval(self, *args): + """Calculate the result of the entered calculation""" current = self.get() try: if len(current) > 0: @@ -52,7 +56,6 @@ def _eval(self, *args): self.insert(0, "ZeroDivisionError") self.select_range(0, "end") - def _check(self, *args): typed = self.get() if not typed == "SyntaxError" and not typed == "ZeroDivisionError": @@ -60,8 +63,8 @@ def _check(self, *args): self.delete(0, "end") self.insert(0, checked) - def _replace(self, typed) -> str: + """Delete the not allowed characters""" if self._expr: allowed = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+", "-", "*", "/", "%", "."] else: @@ -70,7 +73,14 @@ def _replace(self, typed) -> str: if not current in allowed: typed = typed.replace(current, "") return typed - + + def configure(self, **kwargs): + """Configure resources of the widget.""" + self._expr = kwargs.pop("expressions", True) + self._round = kwargs.pop("roundto", 0) + ttk.Entry.configure(self, **kwargs) + + config = configure def cget(self, key): """Return the resource value for a KEY given as string""" @@ -81,11 +91,9 @@ def cget(self, key): else: return ttk.Entry.cget(self, key) - def keys(self): """Return a list of all resource names of this widget""" keys = ttk.Entry.keys(self) keys.extend(["expressions", "roundto"]) keys = sorted(keys) return keys - From af423609e1248373b11443eb6cd1c73e66ef71a9 Mon Sep 17 00:00:00 2001 From: rdbende Date: Tue, 9 Mar 2021 10:20:29 +0100 Subject: [PATCH 09/20] Update AUTHORS.md --- AUTHORS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/AUTHORS.md b/AUTHORS.md index 1b80c6ff..2d96264b 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -27,5 +27,7 @@ This file contains a list of all the authors of widgets in this repository. Plea * `AutocompleteEntryListbox` - [Dogeek](https://github.com/Dogeek) * `validated_entries` submodule +- [rdbende](https://github.com/Dogeek) + * `NumberEntry` - Multiple authors: * `ScaleEntry` (RedFantom and Juliette Monsel) From a4af5668769e0c1e3a491d036e9f429a4b97b4bd Mon Sep 17 00:00:00 2001 From: rdbende Date: Tue, 9 Mar 2021 10:24:43 +0100 Subject: [PATCH 10/20] Create example for NumberEntry --- examples/example_numberentry.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 examples/example_numberentry.py diff --git a/examples/example_numberentry.py b/examples/example_numberentry.py new file mode 100644 index 00000000..d46d9e8b --- /dev/null +++ b/examples/example_numberentry.py @@ -0,0 +1,14 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) rdbende 2021 +# For license see LICENSE + +from ttkwidgets import NumberEntry +import tkinter as tk + +root = tk.Tk() +root.title('NumberEntry') + +NumberEntry(root, expressions=True, roundto=4).pack(pady=30) + +root.mainloop() From 439323ee87e87e5d8ea7a5c4dda99ec5236a8474 Mon Sep 17 00:00:00 2001 From: rdbende Date: Tue, 9 Mar 2021 10:50:14 +0100 Subject: [PATCH 11/20] Create unittest for NumberEntry --- tests/test_numberentry.py | 41 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 tests/test_numberentry.py diff --git a/tests/test_numberentry.py b/tests/test_numberentry.py new file mode 100644 index 00000000..6e421775 --- /dev/null +++ b/tests/test_numberentry.py @@ -0,0 +1,41 @@ +# Copyright (c) rdbende 2021 +# For license see LICENSE + +from ttkwidgets import NumberEntry +from tests import BaseWidgetTest +import tkinter as tk + + +class TestNumberEntry(BaseWidgetTest): + def test_numberentry_init(self): + entry = NumberEntry(self.window, expressions=True, roundto=4) + entry.pack() + self.window.update() + + def test_numberentry_events(self): + entry = NumberEntry(self.window, expressions=True, roundto=4) + entry.pack() + self.window.update() + entry.insert(0, "1+2-3*4/5**6") + self.window.update() + entry._check() + self.window.update() + entry._replace("1+2-3*4/5**6") + self.window.update() + entry._eval() + self.window.update() + + def test_numberentry_config(self): + entry = NumberEntry(self.window, expressions=True, roundto=4) + entry.pack() + self.window.update() + entry.keys() + self.window.update() + entry.configure(expressions=False, roundto=0) + self.window.update() + entry.cget("expressions") + self.window.update() + value = entry["roundto"] + self.window.update() + entry["roundto"] = 4 + self.window.update() From 19f361e044aacdfc5ab0e2f87936d6ccc370502c Mon Sep 17 00:00:00 2001 From: rdbende Date: Tue, 9 Mar 2021 10:59:21 +0100 Subject: [PATCH 12/20] Add NumberEntry to sphinx documentation --- docs/source/ttkwidgets/ttkwidgets.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/ttkwidgets/ttkwidgets.rst b/docs/source/ttkwidgets/ttkwidgets.rst index 21543502..65bef4a9 100644 --- a/docs/source/ttkwidgets/ttkwidgets.rst +++ b/docs/source/ttkwidgets/ttkwidgets.rst @@ -17,6 +17,7 @@ ttkwidgets DebugWindow ItemsCanvas LinkLabel + NumberEntry ScaleEntry ScrolledListbox Table From acdbec576364ceb875536d2eabcf4f5144ac88b6 Mon Sep 17 00:00:00 2001 From: rdbende Date: Tue, 9 Mar 2021 14:59:21 +0100 Subject: [PATCH 13/20] Update AUTHORS.md --- AUTHORS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AUTHORS.md b/AUTHORS.md index 2d96264b..5aa5cfb0 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -27,7 +27,7 @@ This file contains a list of all the authors of widgets in this repository. Plea * `AutocompleteEntryListbox` - [Dogeek](https://github.com/Dogeek) * `validated_entries` submodule -- [rdbende](https://github.com/Dogeek) +- [rdbende](https://github.com/rdbende) * `NumberEntry` - Multiple authors: * `ScaleEntry` (RedFantom and Juliette Monsel) From fb2dd121122afc866508164b756007ce96c6bdb9 Mon Sep 17 00:00:00 2001 From: rdbende Date: Thu, 11 Mar 2021 11:41:05 +0100 Subject: [PATCH 14/20] Fixed fatal config bug --- ttkwidgets/numberentry.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ttkwidgets/numberentry.py b/ttkwidgets/numberentry.py index dfef7310..0d329420 100644 --- a/ttkwidgets/numberentry.py +++ b/ttkwidgets/numberentry.py @@ -76,8 +76,8 @@ def _replace(self, typed) -> str: def configure(self, **kwargs): """Configure resources of the widget.""" - self._expr = kwargs.pop("expressions", True) - self._round = kwargs.pop("roundto", 0) + self._expr = kwargs.pop("expressions", self._expr) + self._round = kwargs.pop("roundto", self._round) ttk.Entry.configure(self, **kwargs) config = configure From e5d60f33b188b36b0cbc7f8b4ac04877dcf44104 Mon Sep 17 00:00:00 2001 From: rdbende Date: Mon, 22 Mar 2021 17:27:48 +0100 Subject: [PATCH 15/20] Update __init__.py --- ttkwidgets/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/ttkwidgets/__init__.py b/ttkwidgets/__init__.py index f8d9f0f7..2360b89c 100644 --- a/ttkwidgets/__init__.py +++ b/ttkwidgets/__init__.py @@ -11,7 +11,6 @@ from ttkwidgets.timeline import TimeLine from ttkwidgets.tickscale import TickScale from ttkwidgets.table import Table -from ttkwidgets.numberentry import NumberEntry from ttkwidgets.validated_entries.numbers import ( PercentEntry, IntEntry, FloatEntry, From de2d5c23ff025895ced00f9c9c9b73179edd240e Mon Sep 17 00:00:00 2001 From: rdbende Date: Mon, 22 Mar 2021 17:28:52 +0100 Subject: [PATCH 16/20] Update __init__.py --- ttkwidgets/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ttkwidgets/__init__.py b/ttkwidgets/__init__.py index 2360b89c..f8d9f0f7 100644 --- a/ttkwidgets/__init__.py +++ b/ttkwidgets/__init__.py @@ -11,6 +11,7 @@ from ttkwidgets.timeline import TimeLine from ttkwidgets.tickscale import TickScale from ttkwidgets.table import Table +from ttkwidgets.numberentry import NumberEntry from ttkwidgets.validated_entries.numbers import ( PercentEntry, IntEntry, FloatEntry, From c2f68cab6a1995048cd411b5596fd129740fb06b Mon Sep 17 00:00:00 2001 From: rdbende Date: Thu, 25 Mar 2021 15:39:58 +0100 Subject: [PATCH 17/20] Update numberentry.py --- ttkwidgets/numberentry.py | 83 +++++++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 34 deletions(-) diff --git a/ttkwidgets/numberentry.py b/ttkwidgets/numberentry.py index 0d329420..32783e51 100644 --- a/ttkwidgets/numberentry.py +++ b/ttkwidgets/numberentry.py @@ -10,19 +10,28 @@ class NumberEntry(ttk.Entry): """ - An entry that takes only numbers or calculations and calculates the result of the calculation + An entry that takes only numbers, calculations or variables, + and calculates the result of the calculation """ - def __init__(self, master=None, **kwargs): + def __init__(self, master=None, allowed_chars={}, **kwargs): """ Create a NumberEntry + :param allowed_chars: Set the accepted variables, the name must be one single character + e.g.: allowed_chars={'p': 3.14} + :type allowed_chars: dict :param expressions: Allow the use of expressions (default is True) :type expressions: bool :param roundto: The number of decimals in the result (default is 0) :type roundto: int + :param variables: Allow the use of the user specified variables + specified in allowed_chars (default is True) + :type variables: bool """ + self._allowed = allowed_chars self._expr = kwargs.pop("expressions", True) self._round = kwargs.pop("roundto", 0) + self._vars = kwargs.pop("variables", True) ttk.Entry.__init__(self, master, **kwargs) self.bind("", self._eval) self.bind("", self._eval) @@ -37,63 +46,69 @@ def __setitem__(self, key, value): def _eval(self, *args): """Calculate the result of the entered calculation""" current = self.get() - try: - if len(current) > 0: + for i in current: + if i in self._allowed.keys(): + current = current.replace(i, str(self._allowed[i])) + if current: + try: if int(self._round) == 0: result = int(round(eval(current), 0)) - self.delete(0, "end") + self.delete(0, tk.END) self.insert(0, result) else: result = round(float(eval(current)), self._round) - self.delete(0, "end") + self.delete(0, tk.END) self.insert(0, result) - except SyntaxError: - self.delete(0, "end") - self.insert(0, "SyntaxError") - self.select_range(0, "end") - except ZeroDivisionError: - self.delete(0, "end") - self.insert(0, "ZeroDivisionError") - self.select_range(0, "end") - + except SyntaxError: + self.delete(0, tk.END) + self.insert(0, "SyntaxError") + self.select_range(0, tk.END) + except ZeroDivisionError: + self.delete(0, tk.END) + self.insert(0, "ZeroDivisionError") + self.select_range(0, tk.END) + def _check(self, *args): typed = self.get() if not typed == "SyntaxError" and not typed == "ZeroDivisionError": - checked = self._replace(typed) - self.delete(0, "end") - self.insert(0, checked) - - def _replace(self, typed) -> str: - """Delete the not allowed characters""" - if self._expr: - allowed = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+", "-", "*", "/", "%", "."] - else: - allowed = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "."] - for current in typed: - if not current in allowed: - typed = typed.replace(current, "") - return typed + if self._expr: + allowed = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+", "-", "*", "/", "%", "."] + else: + allowed = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "."] + if self._vars: + allowed.extend(self._allowed.keys()) + for current in typed: + if not current in allowed: + typed = typed.replace(current, "") + self.delete(0, tk.END) + self.insert(0, typed) - def configure(self, **kwargs): - """Configure resources of the widget.""" + def configure(self, allowed_chars={}, **kwargs): + """Configure resources of the widget""" + self._allowed = allowed_chars self._expr = kwargs.pop("expressions", self._expr) self._round = kwargs.pop("roundto", self._round) + self._vars = kwargs.pop("variables", self._vars) ttk.Entry.configure(self, **kwargs) config = configure def cget(self, key): """Return the resource value for a KEY given as string""" - if key == "expressions": + if key == "allowed_chars": + return self._allowed + elif key == "expressions": return self._expr elif key == "roundto": return self._round + elif key == "variables": + return self._vars else: return ttk.Entry.cget(self, key) def keys(self): """Return a list of all resource names of this widget""" keys = ttk.Entry.keys(self) - keys.extend(["expressions", "roundto"]) - keys = sorted(keys) + keys.extend(["allowed_chars", "expressions", "roundto", "variables"]) + keys.sort() return keys From c1887dd767316bddd977374019b2fd4be243921e Mon Sep 17 00:00:00 2001 From: rdbende Date: Thu, 25 Mar 2021 15:44:12 +0100 Subject: [PATCH 18/20] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 0e4047c8..01b0e3b2 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ A collection of widgets for Tkinter's ttk extensions by various authors. Copyright (C) Mitja Martini 2008 Copyright (C) Russell Adams 2011 Copyright (C) Juliette Monsel 2017 + Copyright (C) rdbende 2021 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 From 213bd08a78b662bb86bb033caf54fd737605e6d1 Mon Sep 17 00:00:00 2001 From: rdbende Date: Thu, 25 Mar 2021 15:50:01 +0100 Subject: [PATCH 19/20] Update example for NumberEntry --- examples/example_numberentry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/example_numberentry.py b/examples/example_numberentry.py index d46d9e8b..5df92370 100644 --- a/examples/example_numberentry.py +++ b/examples/example_numberentry.py @@ -9,6 +9,6 @@ root = tk.Tk() root.title('NumberEntry') -NumberEntry(root, expressions=True, roundto=4).pack(pady=30) +NumberEntry(root, expressions=True, roundto=4, allowed_chars={'p': 3.14159, 'x': 5}).pack(pady=30) root.mainloop() From 3bad128adf27058e68eb690873839578e913d206 Mon Sep 17 00:00:00 2001 From: rdbende Date: Thu, 25 Mar 2021 15:56:48 +0100 Subject: [PATCH 20/20] Update test for NumberEntry --- tests/test_numberentry.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/tests/test_numberentry.py b/tests/test_numberentry.py index 6e421775..07195643 100644 --- a/tests/test_numberentry.py +++ b/tests/test_numberentry.py @@ -8,25 +8,23 @@ class TestNumberEntry(BaseWidgetTest): def test_numberentry_init(self): - entry = NumberEntry(self.window, expressions=True, roundto=4) + entry = NumberEntry(self.window, roundto=4, allowed_chars={'p': 3.14}) entry.pack() self.window.update() def test_numberentry_events(self): - entry = NumberEntry(self.window, expressions=True, roundto=4) + entry = NumberEntry(self.window, roundto=4, allowed_chars={'p': 3.14}) entry.pack() self.window.update() - entry.insert(0, "1+2-3*4/5**6") + entry.insert(0, "1+2-3*4/5**p") self.window.update() entry._check() self.window.update() - entry._replace("1+2-3*4/5**6") - self.window.update() entry._eval() self.window.update() def test_numberentry_config(self): - entry = NumberEntry(self.window, expressions=True, roundto=4) + entry = NumberEntry(self.window, roundto=4, allowed_chars={'p': 3.14}) entry.pack() self.window.update() entry.keys() @@ -37,5 +35,5 @@ def test_numberentry_config(self): self.window.update() value = entry["roundto"] self.window.update() - entry["roundto"] = 4 + entry["allowed_chars"] = {'p': 3.14159} self.window.update()