Commit c9c0f49c authored by Lysander Trischler's avatar Lysander Trischler

Refactor PushButton and SelectableProxyAttrMap

Now this is probably more urwid-like with separation of functionality
and presentation. Although it is much uglier, I reckon. :-/
parent d7d06135
......@@ -457,8 +457,9 @@ class TwtForm(urwid.ListBox, TwtFormatter):
microsecond=0)
.astimezone()
.isoformat())
self._publish = widgets.PushButton("publish-normal", "publish-focus", "publish-disabled", "Publish Twt", on_press=self.publish_twt, selectable=False)
cancel = widgets.PushButton("cancel-normal", "cancel-focus", None, "Cancel", on_press=lambda *_: frame.body.pop_widget())
publish = widgets.PushButton("Publish Twt", on_press=self.publish_twt)
self._publish = widgets.SelectableProxyAttrMap(publish, "publish-normal", "publish-focus", "publish-disabled", selectable=False)
cancel = widgets.PushButton("Cancel", on_press=lambda *_: frame.body.pop_widget())
preview_widgets, rows_calculating_delegate_widget = self._render_new_twt()
preview_list_walker = urwid.SimpleFocusListWalker(preview_widgets)
preview_box_adapter = widgets.DelegatingBoxAdapter(widgets.VimListBox(preview_list_walker),
......@@ -470,8 +471,8 @@ class TwtForm(urwid.ListBox, TwtFormatter):
title="Reply Preview" if original_twt else "New Twt Preview",
title_align="left"),
urwid.Columns([urwid.Text(""),
(len(self._publish.label) + 4, self._publish),
(len(cancel.label) + 4, cancel)],
(len(publish.label) + 4, self._publish),
(len(cancel.label) + 4, urwid.AttrMap(cancel, "cancel-normal", "cancel-focus"))],
dividechars=2)])
# Focus the text edit, which follows directly the conversation. This
......
......@@ -507,59 +507,63 @@ class DelegatingBoxAdapter(urwid.BoxAdapter):
return canv
class PushButton(urwid.AttrMap):
class PushButton(urwid.Button):
"""
A button widget like `urwid.Button` but with its label in square brackets
rather than angled ones. Also emits the "click" signal when releasing the
button and not when pressing. Can be disabled using
`set_selectable(False)`.
button and not when pressing.
"""
def __init__(self, attr_map, focus_map, disabled_map, label, on_press=None, user_data=None, selectable=True):
attr_map = self
class Btn(urwid.Button):
"""
A button widget like `urwid.Button` but with its label in square brackets
rather than angled ones. Also emits the "click" signal when releasing the
button and not when pressing.
"""
button_left = urwid.Text("[")
button_right = urwid.Text("]")
button_left = urwid.Text("[")
button_right = urwid.Text("]")
def __init__(self, label, on_press=None, user_data=None, selectable=True):
# If we'd use super() instead, the overridden button_left/right
# class fields would not be used.
urwid.Button.__init__(self, label, on_press, user_data)
# hide the cursor
self._label._cursor_position = len(label)
self._last_mouse_event = None
self._last_mouse_button = None
self._selectable = selectable
def mouse_event(self, size, event, button, x, y, focus):
last_event = self._last_mouse_event
self._last_mouse_event = event
last_button = self._last_mouse_button
self._last_mouse_button = button
# We want the "click" signal to fire when the user released the left
# mouse button. This way, it is still possible to abort on press by
# draging the mouse away.
# http://urwid.org/manual/userinput.html#mouse-release-events says,
# that often there is no information on which mouse button is released.
# It will then be set to 0. But when we know some real button, it must
# be the left one.
if self.selectable() and last_button == 1 and button in (0, 1) and last_event == "mouse press" and event == "mouse release":
self._emit("click")
return True
return False
def __init__(self, label, on_press=None, user_data=None):
# If we'd use super() instead, the overridden button_left/right
# class fields would not be used.
urwid.Button.__init__(self, label, on_press, user_data)
def set_selectable(self, selectable):
self._selectable = selectable
# hide the cursor
self._label._cursor_position = len(label)
self._last_mouse_event = None
self._last_mouse_button = None
def selectable(self):
return self._selectable
def mouse_event(self, size, event, button, x, y, focus):
last_event = self._last_mouse_event
self._last_mouse_event = event
last_button = self._last_mouse_button
self._last_mouse_button = button
# We want the "click" signal to fire when the user released the left
# mouse button. This way, it is still possible to abort on press by
# draging the mouse away.
# http://urwid.org/manual/userinput.html#mouse-release-events says,
# that often there is no information on which mouse button is released.
# It will then be set to 0. But when we know some real button, it must
# be the left one.
if attr_map.selectable() and last_button == 1 and button in (0, 1) and last_event == "mouse press" and event == "mouse release":
self._emit("click")
return True
return False
class SelectableProxyAttrMap(urwid.AttrMap):
"""
An attribute map which delegates selectable queries and requests to the underlaying widget.
"""
super().__init__(Btn(label, on_press, user_data), attr_map, focus_map)
def __init__(self, w, attr_map, focus_map, disabled_map, selectable=True):
super().__init__(w, attr_map, focus_map)
self._normal_map = self.get_attr_map()
self._disabled_map = disabled_map if isinstance(disabled_map, dict) else {None: disabled_map}
self._selectable = True
......@@ -567,16 +571,11 @@ class PushButton(urwid.AttrMap):
def selectable(self):
return self._selectable
return self._original_widget.selectable()
def set_selectable(self, selectable):
if self._selectable != selectable:
self._selectable = selectable
if self._original_widget.selectable() != selectable:
self._original_widget.set_selectable(selectable)
self.set_attr_map(self._normal_map if selectable else self._disabled_map)
@property
def label(self):
return self._original_widget.label
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment