forked from EDCD/EDMarketConnector
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathttkHyperlinkLabel.py
97 lines (77 loc) · 4.14 KB
/
ttkHyperlinkLabel.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
from sys import platform
import webbrowser
import Tkinter as tk
import ttk
import tkFont
# A clickable ttk Label
#
# In addition to standard ttk.Label arguments, takes the following arguments:
# url: The URL as a string that the user will be sent to on clicking on non-empty label text. If url is a function it will be called on click with the current label text and should return the URL as a string.
# underline: If True/False the text is always/never underlined. If None (the default) the text is underlined only on hover.
# popup_copy: Whether right-click on non-empty label text pops up a context menu with a 'Copy' option. Defaults to no context menu. If popup_copy is a function it will be called with the current label text and should a boolean.
#
class HyperlinkLabel(ttk.Label, object):
def __init__(self, master=None, **kw):
self.url = kw.pop('url')
self.popup_copy = kw.pop('popup_copy', False)
self.underline = kw.pop('underline', None) # override ttk.Label's underline
self.foreground = kw.get('foreground') or 'blue'
self.disabledforeground = kw.pop('disabledforeground', None) or 'SystemWindowText'
ttk.Label.__init__(self, master, **kw)
if self.url:
self.bind('<Button-1>', self._click)
if self.popup_copy:
self.menu = tk.Menu(None, tearoff=tk.FALSE)
self.menu.add_command(label=_('Copy'), command = self.copy) # As in Copy and Paste
self.bind(platform == 'darwin' and '<Button-2>' or '<Button-3>', self._contextmenu)
if self.underline is not False:
self.font_n = kw.get('font', ttk.Style().lookup('TLabel', 'font'))
self.font_u = tkFont.Font(self, self.font_n)
self.font_u.configure(underline = True)
if self.underline is True:
self.configure(font = self.font_u)
else:
self.bind('<Enter>', self._enter)
self.bind('<Leave>', self._leave)
self.configure(state = kw.get('state'), text = kw.get('text')) # set up initial appearance
# Change cursor and appearance depending on state and text
def configure(self, cnf=None, **kw):
if kw.get('state') == tk.DISABLED:
if 'foreground' not in kw:
kw['foreground'] = self.disabledforeground
if self.underline is not False and 'font' not in kw:
kw['font'] = self.font_n
if 'cursor' not in kw:
kw['cursor'] = 'arrow' # System default
elif 'state' in kw:
if 'foreground' not in kw:
kw['foreground'] = self.foreground
if self.underline is True and 'font' not in kw:
kw['font'] = self.font_u
# Hover cursor only if widget is enabled and text is non-empty
if ('text' in kw or 'state' in kw) and 'cursor' not in kw:
if self.url and (kw['text'] if 'text' in kw else self['text']) and (kw['state'] if 'state' in kw else str(self['state']))!=tk.DISABLED:
kw['cursor'] = platform=='darwin' and 'pointinghand' or 'hand2'
else:
kw['cursor'] = 'arrow' # System default
super(HyperlinkLabel, self).configure(cnf, **kw)
def __setitem__(self, key, value):
self.configure(None, **{key: value})
def _enter(self, event):
if str(self['state']) != tk.DISABLED:
self.configure(font = self.font_u)
def _leave(self, event):
if self.underline is None:
self.configure(font = self.font_n)
def _click(self, event):
if self['text'] and str(self['state']) != tk.DISABLED:
url = self.url(self['text']) if callable(self.url) else self.url
if url:
self._leave(event) # Remove underline before we change window to browser
webbrowser.open(url)
def _contextmenu(self, event):
if self['text'] and (self.popup_copy(self['text']) if callable(self.popup_copy) else self.popup_copy):
self.menu.post(platform == 'darwin' and event.x_root + 1 or event.x_root, event.y_root)
def copy(self):
self.clipboard_clear()
self.clipboard_append(self['text'])