diff --git a/main.py b/main.py index 23fc70e..8201d37 100644 --- a/main.py +++ b/main.py @@ -3,6 +3,7 @@ import tkinter as tk from tkinter import filedialog as fd from tkinter.messagebox import showinfo, askyesno, askokcancel from tkinter import ttk +from tooltip import Hovertip from pathlib import Path from deploy import download_ffmpeg, download_git, deploy, get_ffmpeg_version, update import logging @@ -66,7 +67,7 @@ def create_options_frame(container): # Use ITA checkbox use_ita = tk.StringVar() - use_ita.set("1") + use_ita.set("0") use_ita_check = ttk.Checkbutton( frame, variable=use_ita, @@ -91,6 +92,18 @@ def create_options_frame(container): text='Override Workshop', command=lambda: print(override_workshop.get())) + Hovertip(use_ita_check, + 'Check this box if you use Into The Abyss mod.' + '\nITA and Sunken Tapes override the same style file.') + + Hovertip(buffs_check, + 'Check this box to enable some songs causing strange effects' + '\nThis is the intended default behaviour.') + + Hovertip(override_workshop_check, + 'Keep this unchecked to prevent Steam Workshop' + '\noverriding your custom installation.') + for widget in frame.winfo_children(): widget.pack(side="top", padx=3, pady=3, fill="x") diff --git a/tooltip.py b/tooltip.py new file mode 100644 index 0000000..d714318 --- /dev/null +++ b/tooltip.py @@ -0,0 +1,186 @@ +"""Tools for displaying tool-tips. + +This includes: + * an abstract base-class for different kinds of tooltips + * a simple text-only Tooltip class +""" +from tkinter import * + + +class TooltipBase: + """abstract base class for tooltips""" + + def __init__(self, anchor_widget): + """Create a tooltip. + + anchor_widget: the widget next to which the tooltip will be shown + + Note that a widget will only be shown when showtip() is called. + """ + self.anchor_widget = anchor_widget + self.tipwindow = None + + def __del__(self): + self.hidetip() + + def showtip(self): + """display the tooltip""" + if self.tipwindow: + return + self.tipwindow = tw = Toplevel(self.anchor_widget) + # show no border on the top level window + tw.wm_overrideredirect(1) + try: + # This command is only needed and available on Tk >= 8.4.0 for OSX. + # Without it, call tips intrude on the typing process by grabbing + # the focus. + tw.tk.call("::tk::unsupported::MacWindowStyle", "style", tw._w, + "help", "noActivates") + except TclError: + pass + + self.position_window() + self.showcontents() + self.tipwindow.update_idletasks() # Needed on MacOS -- see #34275. + self.tipwindow.lift() # work around bug in Tk 8.5.18+ (issue #24570) + + def position_window(self): + """(re)-set the tooltip's screen position""" + x, y = self.get_position() + root_x = self.anchor_widget.winfo_rootx() + x + root_y = self.anchor_widget.winfo_rooty() + y + self.tipwindow.wm_geometry("+%d+%d" % (root_x, root_y)) + + def get_position(self): + """choose a screen position for the tooltip""" + # The tip window must be completely outside the anchor widget; + # otherwise when the mouse enters the tip window we get + # a leave event and it disappears, and then we get an enter + # event and it reappears, and so on forever :-( + # + # Note: This is a simplistic implementation; sub-classes will likely + # want to override this. + return 20, self.anchor_widget.winfo_height() + 1 + + def showcontents(self): + """content display hook for sub-classes""" + # See ToolTip for an example + raise NotImplementedError + + def hidetip(self): + """hide the tooltip""" + # Note: This is called by __del__, so careful when overriding/extending + tw = self.tipwindow + self.tipwindow = None + if tw: + try: + tw.destroy() + except TclError: # pragma: no cover + pass + + +class OnHoverTooltipBase(TooltipBase): + """abstract base class for tooltips, with delayed on-hover display""" + + def __init__(self, anchor_widget, hover_delay=1000): + """Create a tooltip with a mouse hover delay. + + anchor_widget: the widget next to which the tooltip will be shown + hover_delay: time to delay before showing the tooltip, in milliseconds + + Note that a widget will only be shown when showtip() is called, + e.g. after hovering over the anchor widget with the mouse for enough + time. + """ + super(OnHoverTooltipBase, self).__init__(anchor_widget) + self.hover_delay = hover_delay + + self._after_id = None + self._id1 = self.anchor_widget.bind("", self._show_event) + self._id2 = self.anchor_widget.bind("", self._hide_event) + self._id3 = self.anchor_widget.bind("