Add mouse-over row highlighting
parent
3ea28f04a4
commit
488bdb34be
|
@ -0,0 +1,60 @@
|
|||
"""Hoverable Behaviour (changing when the mouse is on the widget by O. Poyen.
|
||||
License: LGPL
|
||||
"""
|
||||
__author__ = 'Olivier Poyen'
|
||||
|
||||
|
||||
from kivy.properties import BooleanProperty, ObjectProperty
|
||||
from kivy.factory import Factory
|
||||
from kivy.core.window import Window
|
||||
|
||||
|
||||
class HoverBehavior(object):
|
||||
"""Hover behavior.
|
||||
|
||||
:Events:
|
||||
`on_enter`
|
||||
Fired when mouse enter the bbox of the widget.
|
||||
`on_leave`
|
||||
Fired when the mouse exit the widget.
|
||||
"""
|
||||
hovered = BooleanProperty(False)
|
||||
# Contains the last relevant point received by the Hoverable. This can
|
||||
# be used in `on_enter` or `on_leave` in order to know where was dispatched
|
||||
# the event.
|
||||
border_point = ObjectProperty(None)
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.register_event_type('on_enter')
|
||||
self.register_event_type('on_leave')
|
||||
Window.bind(mouse_pos=self.on_mouse_pos)
|
||||
super(HoverBehavior, self).__init__(**kwargs)
|
||||
|
||||
def on_mouse_pos(self, *args):
|
||||
# do proceed if I'm not displayed <=> If have no parent
|
||||
if not self.get_root_window():
|
||||
return
|
||||
pos = args[1]
|
||||
# Next line to_widget allow to compensate for relative layout
|
||||
inside = self.collide_point(*self.to_widget(*pos))
|
||||
if self.hovered == inside:
|
||||
# We have already done what was needed
|
||||
return
|
||||
self.border_point = pos
|
||||
self.hovered = inside
|
||||
if inside:
|
||||
self.dispatch('on_enter')
|
||||
else:
|
||||
self.dispatch('on_leave')
|
||||
|
||||
# implement these in the widget impl
|
||||
|
||||
def on_enter(self):
|
||||
pass
|
||||
|
||||
def on_leave(self):
|
||||
pass
|
||||
|
||||
|
||||
# register for global use via kivy.factory.Factory
|
||||
Factory.register('HoverBehavior', HoverBehavior)
|
|
@ -19,9 +19,11 @@ from kivy.lang import Builder
|
|||
from kivy import utils
|
||||
from kivy.app import async_runTouchApp
|
||||
from kivy.core.window import Window
|
||||
from kivy.graphics import Color, Rectangle, RoundedRectangle
|
||||
|
||||
from ..log import get_logger
|
||||
from .pager import PagerView
|
||||
from .kivy.hoverable import HoverBehavior
|
||||
|
||||
log = get_logger('monitor')
|
||||
|
||||
|
@ -44,13 +46,16 @@ def colorcode(name):
|
|||
|
||||
|
||||
_bs = 0.75 # border size
|
||||
|
||||
# medium shade of gray that seems to match the
|
||||
# default i3 window borders
|
||||
_i3_rgba = [0.14]*3 + [1]
|
||||
|
||||
# slightly off black like the jellybean bg from
|
||||
# vim colorscheme
|
||||
_cell_rgba = [0.07]*3 + [1]
|
||||
_black_rgba = [0]*4
|
||||
|
||||
_kv = (f'''
|
||||
#:kivy 1.10.0
|
||||
|
||||
|
@ -128,6 +133,50 @@ _kv = (f'''
|
|||
''')
|
||||
|
||||
|
||||
class HighlightRowHoverable(HoverBehavior):
|
||||
def on_enter(self):
|
||||
"""Highlight row on enter.
|
||||
"""
|
||||
log.debug(
|
||||
f"Entered cell {self} through {self.border_point}")
|
||||
row = self
|
||||
if row.mouse_over or row.is_header:
|
||||
return
|
||||
|
||||
# add draw instructions
|
||||
color = row._color = Color(*_i3_rgba)
|
||||
rect = row._rect = RoundedRectangle(
|
||||
size=row.size,
|
||||
pos=row.pos,
|
||||
radius=(10,)
|
||||
)
|
||||
# add to canvas
|
||||
canvas = row.canvas
|
||||
if row._rect not in canvas.before.children:
|
||||
canvas.before.add(color)
|
||||
canvas.before.add(rect)
|
||||
|
||||
# mark row as being "selected"
|
||||
row.mouse_over = True
|
||||
|
||||
def on_leave(self):
|
||||
"""Un-highlight row on exit.
|
||||
"""
|
||||
log.debug(
|
||||
f"Left cell {self} through {self.border_point}")
|
||||
row = self
|
||||
if not row.mouse_over or row.is_header:
|
||||
return
|
||||
canvas = row.canvas
|
||||
# remove instructions from canvas
|
||||
if row._color in canvas.before.children:
|
||||
canvas.before.remove(row._color)
|
||||
canvas.before.remove(row._rect)
|
||||
|
||||
# mark row as being "un-selected"
|
||||
row.mouse_over = False
|
||||
|
||||
|
||||
class HeaderCell(Button):
|
||||
"""Column header cell label.
|
||||
"""
|
||||
|
@ -224,7 +273,7 @@ class BidAskLayout(StackLayout):
|
|||
return [self.last, self.bid, self.ask]
|
||||
|
||||
|
||||
class Row(GridLayout):
|
||||
class Row(GridLayout, HighlightRowHoverable):
|
||||
"""A grid for displaying a row of ticker quote data.
|
||||
|
||||
The row fields can be updated using the ``fields`` property which will in
|
||||
|
@ -232,14 +281,17 @@ class Row(GridLayout):
|
|||
"""
|
||||
def __init__(
|
||||
self, record, headers=(), bidasks=None, table=None,
|
||||
is_header_row=False,
|
||||
is_header=False,
|
||||
**kwargs
|
||||
):
|
||||
super(Row, self).__init__(cols=len(record), **kwargs)
|
||||
self._cell_widgets = {}
|
||||
self._last_record = record
|
||||
self.table = table
|
||||
self.is_header = is_header_row
|
||||
self.is_header = is_header
|
||||
|
||||
# selection state
|
||||
self.mouse_over = False
|
||||
|
||||
# create `BidAskCells` first
|
||||
layouts = {}
|
||||
|
@ -248,7 +300,7 @@ class Row(GridLayout):
|
|||
for key, children in bidasks.items():
|
||||
layout = BidAskLayout(
|
||||
[record[key]] + [record[child] for child in children],
|
||||
header=is_header_row
|
||||
header=is_header
|
||||
)
|
||||
layout.row = self
|
||||
layouts[key] = layout
|
||||
|
@ -518,7 +570,7 @@ async def _async_main(
|
|||
{key: key for key in headers},
|
||||
headers=headers,
|
||||
bidasks=bidasks,
|
||||
is_header_row=True,
|
||||
is_header=True,
|
||||
size_hint=(1, None),
|
||||
)
|
||||
box.add_widget(header)
|
||||
|
|
Loading…
Reference in New Issue