Tooltip Module

"""
Each of the following changes will result in reduced performance:
1) The instance attributes are wrapped in getters and setters.
2) The instance attributes are injected as parameters.
"""

import tkinter

from raconverter.constants import *


class CreateToolTip:
    """
    Create a tooltip for a given widget.
    This class has been adapted without further changes.
    Credits go to "vegaseat @ DaniWeb" on www.daniweb.com.

    :param widget: The widget (i.e., button, entry, canvas etc.)
    :param tooltip_text: The tooltip text
    """

    def __init__(self, widget, tooltip_text=DEFAULT_TOOLTIP_TEXT):
        self.widget = widget
        self.tooltip_text = tooltip_text
        self._top_level = None
        self._scheduled_function = None

        # Binding
        self.widget.bind(ENTER_EVENT, lambda event: self.enter())
        self.widget.bind(LEAVE_EVENT, lambda event: self.leave())
        self.widget.bind(BUTTON_PRESS_EVENT, lambda event: self.leave())

    def enter(self):
        """
        Event handler when the mouse pointer enteres the widget.
        """
        self.schedule()

    def schedule(self):
        """
        Schedule function call after wait time.
        """
        self.unschedule()
        self._scheduled_function = self.widget.after(WAIT_TIME, self.show_tip)

    def unschedule(self):
        """
        Cancel scheduling of function (reset scheduling).
        """
        scheduled_function = self._scheduled_function
        self._scheduled_function = None
        if scheduled_function:
            self.widget.after_cancel(scheduled_function)

    def show_tip(self):
        """
        Show tooltip on top of the widget (with a small offset).
        """
        # Note: 'insert' is a named index corresponding to the insertion cursor
        x, y, cx, cy = self.widget.bbox(INSERT)
        x += self.widget.winfo_rootx() + OFFSET_X
        y += self.widget.winfo_rooty() + OFFSET_Y

        # Create a top level window
        self._top_level = tkinter.Toplevel(self.widget)
        # Leave only the label and remove/ignore the top level window
        self._top_level.wm_overrideredirect(True)
        self._top_level.wm_geometry(OFFSET % (x, y))

        # Create label (tooltip)
        label = tkinter.Label(self._top_level, font=FONT, justify=SIDE_LEFT, text=self.tooltip_text)
        label.config(borderwidth=TOOLTIP_BORDERWIDTH, wraplength=WRAP_LENGTH, relief=RELIEF_SOLID, background=WHITE)
        label.pack(ipadx=LABEL_IPADX1)

    def leave(self):
        """
        Event handler when the mouse pointer leaves the widget.
        """
        self.unschedule()
        self.hide_tip()

    def hide_tip(self):
        """
        Reset and destroy the top level window.
        """
        top_level = self._top_level
        self._top_level = None
        if top_level:
            top_level.destroy()

Leave a Reply

Your email address will not be published.