aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorB Stack <bgstack15@gmail.com>2019-06-14 13:47:33 -0400
committerB Stack <bgstack15@gmail.com>2019-06-14 13:47:33 -0400
commit517ec6e9d9c2659a4fe0e39de5f03cf3b72adcff (patch)
tree86e2ca5cfffddb48c865ebe10b4d7d6a2f5e588a
parentimport tkinter, instead of from tkinter import * (diff)
downloadlogout-manager-517ec6e9d9c2659a4fe0e39de5f03cf3b72adcff.tar.gz
logout-manager-517ec6e9d9c2659a4fe0e39de5f03cf3b72adcff.tar.bz2
logout-manager-517ec6e9d9c2659a4fe0e39de5f03cf3b72adcff.zip
add tooltips to tcl
-rwxr-xr-xlogout-manager-tcl.py180
1 files changed, 167 insertions, 13 deletions
diff --git a/logout-manager-tcl.py b/logout-manager-tcl.py
index e8bf095..694a648 100755
--- a/logout-manager-tcl.py
+++ b/logout-manager-tcl.py
@@ -19,15 +19,16 @@
# gtk-3.0 default icon theme https://coderwall.com/p/no3qfa/setting-gtk2-and-gtk3-theme-via-config-file
# homedir https://stackoverflow.com/questions/4028904/how-to-get-the-home-directory-in-python
# natural sort https://stackoverflow.com/questions/46228101/sort-list-of-strings-by-two-substrings-using-lambda-function/46228199#46228199
+# tooltips https://stackoverflow.com/questions/3221956/how-do-i-display-tooltips-in-tkinter/41381685#41381685
# Improve:
-# add tooltips
# add svg support
# Dependencies:
# python36-tkinter | python3-tk
# python36-pillow-tk | python3-pil.imagetk
import os, sys, configparser, glob, re
-import tkinter
+import tkinter as tk
+import tkinter.ttk as ttk
from functools import partial
from pathlib import Path
from PIL import Image, ImageTk
@@ -45,6 +46,158 @@ actions = lmlib.Actions
# graphical classes and functions
print("Loading graphics...")
+class Tooltip:
+
+ '''
+ It creates a tooltip for a given widget as the mouse goes on it.
+
+ see:
+
+ http://stackoverflow.com/questions/3221956/
+ what-is-the-simplest-way-to-make-tooltips-
+ in-tkinter/36221216#36221216
+
+ http://www.daniweb.com/programming/software-development/
+ code/484591/a-tooltip-class-for-tkinter
+
+ - Originally written by vegaseat on 2014.09.09.
+
+ - Modified to include a delay time by Victor Zaccardo on 2016.03.25.
+
+ - Modified
+ - to correct extreme right and extreme bottom behavior,
+ - to stay inside the screen whenever the tooltip might go out on
+ the top but still the screen is higher than the tooltip,
+ - to use the more flexible mouse positioning,
+ - to add customizable background color, padding, waittime and
+ wraplength on creation
+ by Alberto Vassena on 2016.11.05.
+
+ Tested on Ubuntu 16.04/16.10, running Python 3.5.2
+
+ TODO: themes styles support
+ '''
+
+ def __init__(self, widget,
+ *,
+ bg='#FFFFEA',
+ pad=(5, 3, 5, 3),
+ text='widget info',
+ waittime=400,
+ wraplength=250):
+
+ self.waittime = waittime # in miliseconds, originally 500
+ self.wraplength = wraplength # in pixels, originally 180
+ self.widget = widget
+ self.text = text
+ self.widget.bind("<Enter>", self.onEnter)
+ self.widget.bind("<Leave>", self.onLeave)
+ self.widget.bind("<ButtonPress>", self.onLeave)
+ self.bg = bg
+ self.pad = pad
+ self.id = None
+ self.tw = None
+
+ def onEnter(self, event=None):
+ self.schedule()
+
+ def onLeave(self, event=None):
+ self.unschedule()
+ self.hide()
+
+ def schedule(self):
+ self.unschedule()
+ self.id = self.widget.after(self.waittime, self.show)
+
+ def unschedule(self):
+ id_ = self.id
+ self.id = None
+ if id_:
+ self.widget.after_cancel(id_)
+
+ def show(self):
+ def tip_pos_calculator(widget, label,
+ *,
+ tip_delta=(10, 5), pad=(5, 3, 5, 3)):
+
+ w = widget
+
+ s_width, s_height = w.winfo_screenwidth(), w.winfo_screenheight()
+
+ width, height = (pad[0] + label.winfo_reqwidth() + pad[2],
+ pad[1] + label.winfo_reqheight() + pad[3])
+
+ mouse_x, mouse_y = w.winfo_pointerxy()
+
+ x1, y1 = mouse_x + tip_delta[0], mouse_y + tip_delta[1]
+ x2, y2 = x1 + width, y1 + height
+
+ x_delta = x2 - s_width
+ if x_delta < 0:
+ x_delta = 0
+ y_delta = y2 - s_height
+ if y_delta < 0:
+ y_delta = 0
+
+ offscreen = (x_delta, y_delta) != (0, 0)
+
+ if offscreen:
+
+ if x_delta:
+ x1 = mouse_x - tip_delta[0] - width
+
+ if y_delta:
+ y1 = mouse_y - tip_delta[1] - height
+
+ offscreen_again = y1 < 0 # out on the top
+
+ if offscreen_again:
+ # No further checks will be done.
+
+ # TIP:
+ # A further mod might automagically augment the
+ # wraplength when the tooltip is too high to be
+ # kept inside the screen.
+ y1 = 0
+
+ return x1, y1
+
+ bg = self.bg
+ pad = self.pad
+ widget = self.widget
+
+ # creates a toplevel window
+ self.tw = tk.Toplevel(widget)
+
+ # Leaves only the label and removes the app window
+ self.tw.wm_overrideredirect(True)
+
+ win = tk.Frame(self.tw,
+ background=bg,
+ borderwidth=0)
+ label = tk.Label(win,
+ text=self.text,
+ justify=tk.LEFT,
+ background=bg,
+ relief=tk.SOLID,
+ borderwidth=0,
+ wraplength=self.wraplength)
+
+ label.grid(padx=(pad[0], pad[2]),
+ pady=(pad[1], pad[3]),
+ sticky=tk.NSEW)
+ win.grid()
+
+ x, y = tip_pos_calculator(widget, label)
+
+ self.tw.wm_geometry("+%d+%d" % (x, y))
+
+ def hide(self):
+ tw = self.tw
+ if tw:
+ tw.destroy()
+ self.tw = None
+
def get_gtk3_default_theme():
# abstracted so it does not clutter get_scaled_icon
name = "hicolor"
@@ -143,10 +296,10 @@ def get_scaled_icon(icon_name, size = 24, fallback_icon_name = "", icon_theme =
class App:
def __init__(self, master):
- frame = tkinter.Frame(master)
+ frame = tk.Frame(master)
frame.grid(row=0)
- self.buttonLock = tkinter.Button(frame, text="Lock", underline=3, command=partial(actions.lock,config))
+ self.buttonLock = tk.Button(frame, text="Lock", underline=3, command=partial(actions.lock,config))
self.buttonLock.grid(row=0,column=0)
# WORKS master.bind_all("<Alt-k>", something)
# PASSES 2 params when expecting 1 master.bind_all("<Alt-k>", self.buttonLock.invoke)
@@ -154,35 +307,36 @@ class App:
# WORKS, for basic image loading.
#self.photoLogout = get_scaled_icon("/usr/share/icons/Adwaita/48x48/actions/system-log-out.png")
- #self.buttonLogout = tkinter.Button(frame, text="Logout", underline=0, command=lambda: actions.logout(config), image=self.photoLogout, compound=TOP)
+ #self.buttonLogout = tk.Button(frame, text="Logout", underline=0, command=lambda: actions.logout(config), image=self.photoLogout, compound=TOP)
#self.photoLogout1 = Image.open("/usr/share/icons/Adwaita/48x48/actions/system-log-out.png")
#self.photoLogout1.thumbnail(size=[24,24])
#self.photoLogout = ImageTk.PhotoImage(self.photoLogout1,size="24x24")
#self.photoLogout = get_scaled_icon("/usr/share/icons/Adwaita/48x48/actions/system-log-out.png", 24)
#self.photoLogout = get_scaled_icon("system-log-out", 24, icon_theme="default")
self.photoLogout = get_scaled_icon(config.get_logout_icon(), config.get_icon_size(), config.get_icon_theme())
- self.buttonLogout = tkinter.Button(frame, text="Logout", underline=0, command=lambda: actions.logout(config), image=self.photoLogout, compound=tkinter.LEFT)
+ self.buttonLogout = tk.Button(frame, text="Logout", underline=0, command=lambda: actions.logout(config), image=self.photoLogout, compound=tk.LEFT)
master.bind_all("<Alt-l>", partial(actions.logout,config))
+ Tooltip(self.buttonLogout, text="HERE IS SOMETHING!")
self.buttonLogout.grid(row=0,column=1)
self.photoHibernate = get_scaled_icon(config.get_hibernate_icon(), config.get_icon_size(), config.get_icon_theme())
- self.buttonHibernate = tkinter.Button(frame, text="Hibernate", underline=0, command=lambda: actions.hibernate(config), image=self.photoHibernate, compound=tkinter.LEFT)
+ self.buttonHibernate = tk.Button(frame, text="Hibernate", underline=0, command=lambda: actions.hibernate(config), image=self.photoHibernate, compound=tk.LEFT)
self.buttonHibernate.grid(row=0,column=2)
master.bind_all("<Alt-h>", partial(actions.hibernate,config))
self.photoShutdown = get_scaled_icon(config.get_shutdown_icon(), config.get_icon_size(), config.get_icon_theme())
- self.buttonShutdown = tkinter.Button(frame, text="Shutdown", underline=0, command=lambda: actions.shutdown(config), image=self.photoShutdown, compound=tkinter.LEFT)
+ self.buttonShutdown = tk.Button(frame, text="Shutdown", underline=0, command=lambda: actions.shutdown(config), image=self.photoShutdown, compound=tk.LEFT)
self.buttonShutdown.grid(row=0,column=3)
master.bind_all("<Alt-s>", partial(actions.shutdown,config))
self.photoReboot = get_scaled_icon(config.get_reboot_icon(), config.get_icon_size(), config.get_icon_theme())
- self.buttonReboot = tkinter.Button(frame, text="Reboot", underline=0, command=lambda: actions.reboot(config), image=self.photoReboot, compound=tkinter.LEFT)
+ self.buttonReboot = tk.Button(frame, text="Reboot", underline=0, command=lambda: actions.reboot(config), image=self.photoReboot, compound=tk.LEFT)
self.buttonReboot.grid(row=0,column=4)
master.bind_all("<Alt-r>", partial(actions.reboot,config))
- #self.buttonCancel = tkinter.Button(frame, text="Cancel", underline=0, command=frame.quit)
- self.buttonCancel = tkinter.Button(frame, text="Cancel", underline=0, command=self.quitaction)
- self.buttonCancel.grid(row=1,columnspan=8,sticky=tkinter.W+tkinter.E)
+ #self.buttonCancel = tk.Button(frame, text="Cancel", underline=0, command=frame.quit)
+ self.buttonCancel = tk.Button(frame, text="Cancel", underline=0, command=self.quitaction)
+ self.buttonCancel.grid(row=1,columnspan=8,sticky=tk.W+tk.E)
master.bind_all("<Alt-c>", self.quitaction)
# Found this after trial and error.
@@ -194,7 +348,7 @@ class App:
#def something(event=None):
# print("Got here!")
-root = tkinter.Tk()
+root = tk.Tk()
# MAIN LOOP
root.title("Log out options")
bgstack15