mirror of
https://github.com/EDCD/EDMarketConnector.git
synced 2025-06-01 16:11:18 +03:00
Split out ttk HyperlinkLabel widget into a separate file and generalise.
This commit is contained in:
parent
c4991d09ef
commit
a74a928764
@ -8,12 +8,11 @@ from os.path import expanduser, isdir, join
|
||||
import re
|
||||
import requests
|
||||
from time import time, localtime, strftime
|
||||
import urllib
|
||||
import webbrowser
|
||||
|
||||
import Tkinter as tk
|
||||
import ttk
|
||||
import tkFont
|
||||
from ttkHyperlinkLabel import HyperlinkLabel
|
||||
|
||||
if __debug__:
|
||||
from traceback import print_exc
|
||||
@ -39,50 +38,6 @@ SERVER_RETRY = 5 # retry pause for Companion servers [s]
|
||||
EDSM_POLL = 0.1
|
||||
|
||||
|
||||
class HyperlinkLabel(ttk.Label):
|
||||
|
||||
def __init__(self, master=None, **kw):
|
||||
self.urlfn = kw.pop('urlfn', None)
|
||||
ttk.Label.__init__(self, master, **kw)
|
||||
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)
|
||||
self.menu = tk.Menu(None, tearoff=tk.FALSE)
|
||||
self.menu.add_command(label=_('Copy'), command = self.copy) # As in Copy and Paste
|
||||
self.bind('<Enter>', self._enter)
|
||||
self.bind('<Leave>', self._leave)
|
||||
self.bind('<Button-1>', self._click)
|
||||
self.bind(platform == 'darwin' and '<Button-2>' or '<Button-3>', self._contextmenu)
|
||||
|
||||
# Make blue and clickable if setting non-empty text
|
||||
def __setitem__(self, key, value):
|
||||
if key=='text':
|
||||
if self.urlfn and value:
|
||||
self.configure({key: value}, foreground = 'blue', cursor = platform=='darwin' and 'pointinghand' or 'hand2')
|
||||
else:
|
||||
self.configure({key: value}, foreground = '', cursor = 'arrow')
|
||||
else:
|
||||
self.configure({key: value})
|
||||
|
||||
def _enter(self, event):
|
||||
self.configure(font = self.font_u)
|
||||
|
||||
def _leave(self, event):
|
||||
self.configure(font = self.font_n)
|
||||
|
||||
def _click(self, event):
|
||||
if self.urlfn and self['text']:
|
||||
webbrowser.open(self.urlfn(self['text']))
|
||||
|
||||
def _contextmenu(self, event):
|
||||
if self['text'] and self['text'] != AppWindow.STATION_UNDOCKED:
|
||||
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'])
|
||||
|
||||
|
||||
class AppWindow:
|
||||
|
||||
STATION_UNDOCKED = u'×' # "Station" name to display when not docked = U+00D7
|
||||
@ -127,8 +82,8 @@ class AppWindow:
|
||||
ttk.Label(frame, text=_('Station:')).grid(row=2, column=0, sticky=tk.W) # Main window
|
||||
|
||||
self.cmdr = ttk.Label(frame, width=-21)
|
||||
self.system = HyperlinkLabel(frame, compound=tk.RIGHT, urlfn = self.system_url)
|
||||
self.station = HyperlinkLabel(frame, urlfn = self.station_url)
|
||||
self.system = HyperlinkLabel(frame, compound=tk.RIGHT, url = self.system_url, popup_copy = True)
|
||||
self.station = HyperlinkLabel(frame, url = self.station_url, popup_copy = lambda x: x!=self.STATION_UNDOCKED)
|
||||
self.button = ttk.Button(frame, text=_('Update'), command=self.getandsend, default=tk.ACTIVE, state=tk.DISABLED) # Update button in main window
|
||||
self.status = ttk.Label(frame, width=-25)
|
||||
self.w.bind('<Return>', self.getandsend)
|
||||
|
95
ttkHyperlinkLabel.py
Normal file
95
ttkHyperlinkLabel.py
Normal file
@ -0,0 +1,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):
|
||||
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:
|
||||
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'])
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user