76 lines
3.0 KiB
Python
76 lines
3.0 KiB
Python
|
# -*- coding: utf-8 -*-
|
||
|
"""This module implements a pop up menu widget"""
|
||
|
from __future__ import division
|
||
|
from __future__ import absolute_import
|
||
|
from __future__ import print_function
|
||
|
from __future__ import unicode_literals
|
||
|
from collections import defaultdict
|
||
|
from functools import partial
|
||
|
from asciimatics.event import KeyboardEvent, MouseEvent
|
||
|
from asciimatics.screen import Screen
|
||
|
from asciimatics.widgets.button import Button
|
||
|
from asciimatics.widgets.frame import Frame
|
||
|
from asciimatics.widgets.layout import Layout
|
||
|
|
||
|
|
||
|
class PopupMenu(Frame):
|
||
|
"""
|
||
|
A widget for displaying a menu.
|
||
|
"""
|
||
|
|
||
|
palette = defaultdict(lambda: (Screen.COLOUR_WHITE, Screen.A_NORMAL, Screen.COLOUR_CYAN))
|
||
|
palette["focus_button"] = (Screen.COLOUR_CYAN, Screen.A_NORMAL, Screen.COLOUR_WHITE)
|
||
|
|
||
|
def __init__(self, screen, menu_items, x, y):
|
||
|
"""
|
||
|
:param screen: The Screen being used for this pop-up.
|
||
|
:param menu_items: a list of items to be displayed in the menu.
|
||
|
:param x: The X coordinate for the desired pop-up.
|
||
|
:param y: The Y coordinate for the desired pop-up.
|
||
|
|
||
|
The menu_items parameter is a list of 2-tuples, which define the text to be displayed in
|
||
|
the menu and the function to call when that menu item is clicked. For example:
|
||
|
|
||
|
menu_items = [("Open", file_open), ("Save", file_save), ("Close", file_close)]
|
||
|
"""
|
||
|
# Sort out location based on width of menu text.
|
||
|
w = max(len(i[0]) for i in menu_items)
|
||
|
h = len(menu_items)
|
||
|
if x + w >= screen.width:
|
||
|
x -= w - 1
|
||
|
if y + h >= screen.height:
|
||
|
y -= h - 1
|
||
|
|
||
|
# Construct the Frame
|
||
|
super(PopupMenu, self).__init__(
|
||
|
screen, h, w, x=x, y=y, has_border=False, can_scroll=False, is_modal=True, hover_focus=True)
|
||
|
|
||
|
# Build the widget to display the time selection.
|
||
|
layout = Layout([1], fill_frame=True)
|
||
|
self.add_layout(layout)
|
||
|
for item in menu_items:
|
||
|
func = partial(self._destroy, item[1])
|
||
|
layout.add_widget(Button(item[0], func, add_box=False), 0)
|
||
|
self.fix()
|
||
|
|
||
|
def _destroy(self, callback=None):
|
||
|
self._scene.remove_effect(self)
|
||
|
if callback is not None:
|
||
|
callback()
|
||
|
|
||
|
def process_event(self, event):
|
||
|
# Look for events that will close the pop-up - e.g. clicking outside the Frame or ESC key.
|
||
|
if event is not None:
|
||
|
if isinstance(event, KeyboardEvent):
|
||
|
if event.key_code == Screen.KEY_ESCAPE:
|
||
|
event = None
|
||
|
elif isinstance(event, MouseEvent) and event.buttons != 0:
|
||
|
origin = self._canvas.origin
|
||
|
if event.y < origin[1] or event.y >= origin[1] + self._canvas.height:
|
||
|
event = None
|
||
|
elif event.x < origin[0] or event.x >= origin[0] + self._canvas.width:
|
||
|
event = None
|
||
|
if event is None:
|
||
|
self._destroy()
|
||
|
return super(PopupMenu, self).process_event(event)
|