Entry Fields Module

import re
import tkinter
import tkinter.messagebox

import raconverter
import raconverter.tooltip
from raconverter.constants import *


class EntryFields:
    """
    A class with general/specific methods to create and handle entry fields.
    """

    def __init__(self):
        self._frame = tkinter.Frame()

    @property
    def frame(self):
        """
        Get frame.

        :return: A frame
        """
        return self._frame

    @staticmethod
    def add_tooltip(parent, tooltip_text):
        """
        Add a tooltip.

        :param  parent: The parent widget
        :param tooltip_text: The tooltip text
        """
        raconverter.tooltip.CreateToolTip(parent, tooltip_text)

    @staticmethod
    def entry_standard(parent, label_width, entry_width, label_text, default_value=None):
        """
        Create entry frame with entry label and field.

        :param parent: The parent widget
        :param label_width: The label width
        :param entry_width: The entry field width
        :param label_text: The label text
        :param default_value = None | Default value
        :return: Entry field
        """
        # Entry frame
        entry_frame = tkinter.Frame(parent)
        entry_frame.pack(side=SIDE_TOP, padx=ENTRY_FRAME_PADX10, pady=ENTRY_FRAME_PADY5, fill=FILL_X)
        # Entry label
        entry_label = tkinter.Label(entry_frame, font=FONT, anchor=ANCHOR_EAST, width=label_width, text=label_text)
        entry_label.pack(side=SIDE_LEFT)
        # Entry field
        textvariable = tkinter.StringVar(entry_frame, value=default_value)
        entry_field = tkinter.Entry(entry_frame, font=FONT, width=entry_width, textvariable=textvariable)
        entry_field.pack(side=SIDE_RIGHT, fill=FILL_X, expand=EXPAND_YES)

        return entry_field

    def entry_data_file_name(self, parent, label_width, entry_width, label_text, default_value=None):
        """
        Create entry frame with a specific entry label and field.
        Validation/invalidation methods are included.

        :param parent: The parent widget
        :param label_width: The label width
        :param entry_width: The entry field width
        :param label_text: The label text
        :param default_value = None | Default value
        :return: Data file name field
        """
        # Register validate/invalidate methods
        validatecommand = (self.frame.register(self.valid_data_file_name), ENTRY_STRING)
        invalidcommand = (self.frame.register(self.invalid_name), ENTRY_NAME)

        # Entry frame
        entry_frame = tkinter.Frame(parent)
        entry_frame.pack(side=SIDE_TOP, padx=ENTRY_FRAME_PADX10, pady=ENTRY_FRAME_PADY5, fill=FILL_X)
        # Entry label
        entry_label = tkinter.Label(entry_frame, font=FONT, anchor=ANCHOR_EAST, width=label_width, text=label_text)
        entry_label.pack(side=SIDE_LEFT)
        # Entry field
        textvariable = tkinter.StringVar(entry_frame, value=default_value)
        entry_field = tkinter.Entry(entry_frame, font=FONT, width=entry_width, textvariable=textvariable)
        entry_field.config(validate=VALIDATE, validatecommand=validatecommand, invalidcommand=invalidcommand)
        entry_field.pack(side=SIDE_RIGHT, fill=FILL_X, expand=EXPAND_YES)

        return entry_field

    def entry_variable_name(self, parent, label_width, entry_width, label_text, default_value=None):
        """
        Create entry frame with a specific entry label and field.
        Validation/invalidation methods are included.

        :param parent: The parent widget
        :param label_width: The label width
        :param entry_width: The entry field width
        :param label_text: The label text
        :param default_value = None | Default value
        :return: Variable name field
        """
        # Register validate/invalidate methods
        validatecommand = (self.frame.register(self.valid_variable_name), ENTRY_STRING)
        invalidcommand = (self.frame.register(self.invalid_name), ENTRY_NAME)

        # Entry frame
        entry_frame = tkinter.Frame(parent)
        entry_frame.pack(side=SIDE_TOP, padx=ENTRY_FRAME_PADX10, pady=ENTRY_FRAME_PADY5, fill=FILL_X)
        # Entry label
        entry_label = tkinter.Label(entry_frame, font=FONT, anchor=ANCHOR_EAST, width=label_width, text=label_text)
        entry_label.pack(side=SIDE_LEFT)
        # Entry field
        textvariable = tkinter.StringVar(entry_frame, value=default_value)
        entry_field = tkinter.Entry(entry_frame, font=FONT, width=entry_width, textvariable=textvariable)
        entry_field.config(validate=VALIDATE, validatecommand=validatecommand, invalidcommand=invalidcommand)
        entry_field.pack(side=SIDE_RIGHT, fill=FILL_X, expand=EXPAND_YES)

        return entry_field

    def validate_data_file_name(self, entry):
        """
        Validate the data file name.

        :param entry: The entry field with the data file name
        :return: True | False
        """
        valid = True
        data_file_name = entry.get()

        # Validate entry string
        if not self.valid_data_file_name(data_file_name):
            # Get the full widget name
            entry_name = str(entry)
            self.invalid_name(entry_name)
            valid = False

        return valid

    def validate_variable_name(self, entry):
        """
        Validate the variable name.

        :param entry: The entry field with the variable name
        :return: True | False
        """
        valid = True
        variable_name = entry.get()

        # Validate entry string
        if not self.valid_variable_name(variable_name):
            # Get the full widget name
            entry_name = str(entry)
            self.invalid_name(entry_name)
            valid = False

        return valid

    @staticmethod
    def valid_data_file_name(entry_text):
        """
        Validation method for data file name.

        :param entry_text: entry text
        :return: True | False
        """
        valid = True

        # Accept empty string
        if not entry_text:
            pass
        else:
            valid &= not len(entry_text) >= 128
            valid &= re.match('^(?!\d)\w+$', entry_text) is not None

        return valid

    @staticmethod
    def valid_variable_name(entry_text):
        """
        Validation method for variable name(s).

        :param entry_text: entry text
        :return: True | False
        """
        valid = True
        names = entry_text.split()

        # Accept empty string
        if not entry_text:
            pass
        else:
            for name in names:
                valid &= not len(name) >= 128
                valid &= re.match('^(?!\d)\w+$', name) is not None

        return valid

    def invalid_name(self, entry_name):
        """
        Action performed if validation of the data file or variable name fails.
        The method is called automatically when the validation method returns False.

        :param entry_name: The name of the entry
        """
        # Get entry
        entry = self.frame.nametowidget(entry_name)
        # Clear entry and show warning
        entry.delete(INDEX_START0, INDEX_END)
        tkinter.messagebox.showwarning(INVALID_NAME, INVALID_NAME_MESSAGE)
        # Return focus to entry
        entry.focus_force()

Leave a Reply

Your email address will not be published.