Source code for lookatme.widgets.clickable_text

"""
This module contains code for ClickableText
"""


import platform
import subprocess

import urwid
from urwid.util import is_mouse_press

import lookatme.config
from lookatme.widgets.smart_attr_spec import SmartAttrSpec


[docs]class LinkIndicatorSpec(SmartAttrSpec): """Used to track a link within an urwid.Text instance""" def __init__(self, link_target, orig_spec, link_type: str = "link"): """Create a new LinkIndicator spec from an existing urwid.AttrSpec :param str link_target: The target url for the link """ self.link_target = link_target self.link_type = link_type super().__init__(orig_spec.foreground, orig_spec.background)
[docs] def new_for_spec(self, new_spec): """Create a new LinkIndicatorSpec with the same link information but new AttrSpec """ return LinkIndicatorSpec(self.link_target, new_spec, self.link_type)
[docs]class ClickableText(urwid.Text): """Allows clickable/changing text to be part of the Text() contents""" signals = ["click", "change"] def __init__(self, markup, *args, **kwargs): self._log = lookatme.config.get_log().getChild("ClickableText") super(ClickableText, self).__init__(markup, *args, **kwargs)
[docs] def mouse_event(self, size, event, button, x, y, focus): """Handle mouse events!""" if button != 1 or not is_mouse_press(event): return False total_offset = (y * size[0]) + x raw_text, chunk_stylings = self.get_text() rendered = self.render(size).text # TODO: this won't work too well with wrapped text! curr_offset = rendered[0].decode().find(raw_text) found_style = None for info in chunk_stylings: style, length = info if curr_offset < total_offset <= curr_offset + length: found_style = style break curr_offset += length if found_style is None or not isinstance(found_style, LinkIndicatorSpec): self._emit("click") return True this_sys = platform.system() link_cmd = { "Linux": ["xdg-open"], "Darwin": ["open"], "Windows": ["start"], }.get(this_sys, None) if link_cmd is None: self._log.debug( "No link-opening command defined yet for {!r}".format(this_sys) ) return True found_link = found_style.link_target subprocess.Popen( link_cmd + [found_link], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT ) return True