def quit_prompt(self):
"""Pop-up window that appears when you try to quit."""
# Nothing fancy here.
question = ur.Text(("bold", "Really quit?"), "center")
yes_btn = ur.AttrMap(ur.Button(
"Yes", self.button_press, "quit"), "red", None)
no_btn = ur.AttrMap(ur.Button(
"No", self.button_press, "back"), "green", None)
prompt = ur.LineBox(ur.ListBox(ur.SimpleFocusListWalker(
[question, self.div, self.div, no_btn, yes_btn])))
# The only interesting thing in this method is this Overlay widget.
overlay = MyOverlay(
prompt, self.loop.baseWidget,
"center", 20, "middle", 8,
16, 8,
parent=self)
self.loop.Widget = overlay
python类Overlay()的实例源码
def refresh(self, data=None, force=False):
widget = self.frame.body
while isinstance(widget, urwid.Overlay):
widget = widget.contents[0][0]
interested = force
invalidate = False
try:
while True:
event = self.sync.result_queue.get(0)
if widget.interested(event):
interested = True
if hasattr(event, 'held_changed') and event.held_changed:
invalidate = True
except queue.Empty:
pass
if interested:
widget.refresh()
if invalidate:
self.updateStatusQueries()
self.status.refresh()
def popup(self, widget,
relative_width=50, relative_height=25,
min_width=20, min_height=8,
width=None, height=None):
self.clearInputBuffer()
if width is None:
width = ('relative', relative_width)
if height is None:
height = ('relative', relative_height)
overlay = urwid.Overlay(widget, self.frame.body,
'center', width,
'middle', height,
min_width=min_width, min_height=min_height)
if hasattr(widget, 'title'):
overlay.title = widget.title
self.log.debug("Overlaying %s on screen %s" % (widget, self.frame.body))
self.screens.append(self.frame.body)
self.frame.body = overlay
def quote_view_action(self, button, message):
"""
Callback function to view a quote from the message object menu.
"""
widget = OptionsMenu(
ActionBox(urwid.SimpleFocusListWalker(self.make_message_body(message))),
title=">>%d" % message["post_id"],
**frame_theme()
)
self.loop.widget = urwid.Overlay(
widget, self.loop.widget,
align=("relative", 50),
valign=("relative", 50),
width=("relative", 98),
height=("relative", 60)
)
def search_prompt(self):
# XXX: remove if when thread search is supported
if self.mode != "index":
return
popup = OptionsMenu(
urwid.ListBox(
urwid.SimpleFocusListWalker([
urwid.Text(("button", "Enter a query:")),
urwid.AttrMap(StringPrompt(self.search_callback), "opt_prompt"),
urwid.Text("Use a blank query to reset the {}.".format(self.mode))
])),
**frame_theme())
self.loop.widget = urwid.Overlay(
popup, self.loop.widget,
align=("relative", 50),
valign=("relative", 25 if self.window_split else 50),
width=("relative", 40), height=6)
def formatting_help(self, *_):
"""
Pops a help window for formatting directives.
"""
# we can "recycle" the server's formatting abilities to
# use the same syntax for the help text itself
message = network.fake_message(
"\n\n".join(format_help), format="sequential")
widget = OptionsMenu(
urwid.ListBox(urwid.SimpleFocusListWalker(app.make_message_body(message, True))),
title="Formatting Help",
**frame_theme()
)
va = 5 if self.window_split else 50
vh = 45 if self.window_split else 75
app.loop.widget = urwid.Overlay(
widget, app.loop.widget,
align=("relative", 50),
valign=("relative", va),
width=app.prefs["max_text_width"],
height=("relative", vh)
)
def test_overlay(self):
s1 = urwid.SolidFill(u'1')
s2 = urwid.SolidFill(u'2')
o = urwid.Overlay(s1, s2,
'center', ('relative', 50), 'middle', ('relative', 50))
self.assertEqual(o.focus, s1)
self.assertEqual(o.focus_position, 1)
self.assertRaises(IndexError, lambda: setattr(o, 'focus_position',
None))
self.assertRaises(IndexError, lambda: setattr(o, 'focus_position', 2))
self.assertEqual(o.contents[0], (s2,
urwid.Overlay._DEFAULT_BOTTOM_OPTIONS))
self.assertEqual(o.contents[1], (s1, (
'center', None, 'relative', 50, None, 0, 0,
'middle', None, 'relative', 50, None, 0, 0)))
def test_focus_path(self):
# big tree of containers
t = urwid.Text(u'x')
e = urwid.Edit(u'?')
c = urwid.Columns([t, e, t, t])
p = urwid.Pile([t, t, c, t])
a = urwid.AttrMap(p, 'gets ignored')
s = urwid.SolidFill(u'/')
o = urwid.Overlay(e, s, 'center', 'pack', 'middle', 'pack')
lb = urwid.ListBox(urwid.SimpleFocusListWalker([t, a, o, t]))
lb.focus_position = 1
g = urwid.GridFlow([t, t, t, t, e, t], 10, 0, 0, 'left')
g.focus_position = 4
f = urwid.Frame(lb, header=t, footer=g)
self.assertEqual(f.get_focus_path(), ['body', 1, 2, 1])
f.set_focus_path(['footer']) # same as f.focus_position = 'footer'
self.assertEqual(f.get_focus_path(), ['footer', 4])
f.set_focus_path(['body', 1, 2, 2])
self.assertEqual(f.get_focus_path(), ['body', 1, 2, 2])
self.assertRaises(IndexError, lambda: f.set_focus_path([0, 1, 2]))
self.assertRaises(IndexError, lambda: f.set_focus_path(['body', 2, 2]))
f.set_focus_path(['body', 2]) # focus the overlay
self.assertEqual(f.get_focus_path(), ['body', 2, 1])
def render(self, card):
div = urwid.Divider()
rdiv = urwid.AttrMap(div, 'header')
header = urwid.Filler(urwid.Pile(
[rdiv, rdiv, rdiv, rdiv, rdiv]), valign='top')
h1_text = urwid.Text(('h1', self.name))
h2_text = urwid.Text(('h2', 'v' + self.version), align='right')
hg_text = urwid.AttrMap(urwid.Padding(urwid.Columns(
[h1_text, h2_text]), left=2, right=2, align='center'), 'header')
body = urwid.Pile([hg_text, rdiv, card, div])
widget = urwid.Overlay(body, header, 'center', 76, 'top', 'pack', top=1)
self.loop.widget.original_widget = widget
def popup(self, widget):
self._popup_original = self.main_loop.widget
self.main_loop.widget = urwid.Overlay(
widget,
self._popup_original,
'center', ('relative', 90), 'middle', ('relative', 85)
)
def __init__(self, main_widget):
self.main_widget = main_widget
self.pop_up = urwid.Frame(urwid.WidgetPlaceholder(None))
self.w_placeholder = urwid.WidgetPlaceholder(self.main_widget)
self.pop_up_overlay = urwid.Overlay(urwid.LineBox(self.pop_up),
self.main_widget,
'center',
('relative', 60),
'middle',
('relative', 60))
def render(self, card):
div = urwid.Divider()
rdiv = urwid.AttrMap(div, 'header')
header = urwid.Filler(urwid.Pile(
[rdiv, rdiv, rdiv, rdiv, rdiv]), valign='top')
h1_text = urwid.Text(('h1', self.name))
h2_text = urwid.Text(('h2', 'v' + self.version), align='right')
hg_text = urwid.AttrMap(urwid.Padding(urwid.Columns(
[h1_text, h2_text]), left=2, right=2, align='center'), 'header')
body = urwid.Pile([hg_text, rdiv, card, div])
widget = urwid.Overlay(body, header, 'center', 76, 'top', 'pack', top=1)
self.loop.widget.original_widget = widget
def __init__(self, movies):
footer=urwid.AttrWrap(urwid.Text('Press q to exit, use up and down arrow to navigate, press Enter to select'), 'footer')
items = self.make_items(movies)
self.listbox = urwid.ListBox(urwid.SimpleListWalker(items))
top = urwid.Overlay(self.listbox, urwid.SolidFill(' '),
align='center', width=('relative', 60),
valign='middle', height=('relative', 60),
min_width=20, min_height=9)
urwid.Frame.__init__(self, urwid.AttrWrap(top, 'body'), footer=footer)
def show_popup(self, _, text):
popup = PopUpDialog(text)
urwid.connect_signal(popup, "close", self.close_popup)
self._w = urwid.Overlay(popup, self.orig_widget,
align="center", width=("relative", 70),
valign="middle", height=("relative", 70))
def overlay_p(self):
"""
Return True or False if the current widget is an overlay.
"""
return isinstance(self.loop.widget, urwid.Overlay)
def remove_overlays(self, *_):
"""
Remove ALL urwid.Overlay objects which are currently covering the base
widget.
"""
while True:
try:
self.loop.widget = self.loop.widget[0]
except:
break
def quote_view_menu(self, button, post_ids):
"""
Receives a list of quote ids and makes a frilly menu to pick one to view.
It retrieves messages objects from the thread and attaches them to a
callback to `quote_view_action`
"""
buttons = []
for pid in post_ids:
try:
message = self.thread["messages"][pid]
if len(post_ids) == 1:
return self.quote_view_action(button, message)
author = self.usermap[message["author"]]
label = [
("button", ">>%d " % pid),
"(",
(str(author["color"]),
author["user_name"]),
")"
]
buttons.append(cute_button(label, self.quote_view_action, message))
except IndexError:
continue # users can submit >>29384234 garbage references
widget = OptionsMenu(
urwid.ListBox(urwid.SimpleFocusListWalker(buttons)),
title="View a Quote", **frame_theme()
)
self.loop.widget = urwid.Overlay(
widget, self.loop.widget,
align=("relative", 50),
valign=("relative", 50),
height=len(buttons) + 3,
width=30
)
def deletion_dialog(self, button, message):
"""
Prompts the user to confirm deletion of an item.
This can delete either a thread or a post.
"""
op = message["post_id"] == 0
buttons = [
urwid.Text(("bold", "Delete this %s?" % ("whole thread" if op else "post"))),
urwid.Divider(),
cute_button(("10" , ">> Yes"), lambda _: [
network.message_delete(message["thread_id"], message["post_id"]),
self.remove_overlays(),
self.index() if op else self.refresh()
]),
cute_button(("30", "<< No"), self.remove_overlays)
]
# TODO: create a central routine for creating popups. this is getting really ridiculous
popup = OptionsMenu(
urwid.ListBox(urwid.SimpleFocusListWalker(buttons)),
**frame_theme())
self.loop.widget = urwid.Overlay(
popup, self.loop.widget,
align=("relative", 50),
valign=("relative", 50),
width=30, height=6)
def back(self, terminate=False):
if app.mode == "index" and terminate:
frilly_exit()
elif self.overlay_p():
self.loop.widget = self.loop.widget[0]
elif self.window_split:
# display a confirmation dialog before killing off an in-progress post
buttons = [
urwid.Text(("bold", "Discard current post?")),
urwid.Divider(),
cute_button(("10" , ">> Yes"), lambda _: [
self.remove_overlays(),
self.index()
]),
cute_button(("30", "<< No"), self.remove_overlays)
]
# TODO: create a central routine for creating popups. this is getting really ridiculous
popup = OptionsMenu(
urwid.ListBox(urwid.SimpleFocusListWalker(buttons)),
**frame_theme())
self.loop.widget = urwid.Overlay(
popup, self.loop.widget,
align=("relative", 50),
valign=("relative", 25),
width=30, height=6)
else:
mark()
self.index()
def goto_post_prompt(self, init):
if self.mode != "thread":
return
count = self.thread["reply_count"]
live_display = urwid.Text("")
edit = JumpPrompt(count, lambda x: self.goto_post(x))
items = [
urwid.Text(("button", " Jump to post")),
urwid.AttrMap(edit, "opt_prompt"),
urwid.Text(("bold", ("(max %d)" % count).center(18, " "))),
live_display
]
urwid.connect_signal(edit, "change", self.jump_peek, live_display)
if init.isdigit():
edit.keypress((self.loop.screen_size[0],), init)
popup = OptionsMenu(
urwid.ListBox(urwid.SimpleFocusListWalker(items)),
**frame_theme())
self.loop.widget = urwid.Overlay(
popup, self.loop.widget,
align=("relative", 50),
valign=("relative", 25 if self.window_split else 50),
width=20, height=6)
def general_help(self):
"""
Show a general help dialog. In all honestly, its not
very useful and will only help people who have never
really used terminal software before =)
"""
widget = OptionsMenu(
urwid.ListBox(
urwid.SimpleFocusListWalker([
urwid_rainbows(
"This is BBJ, a client/server textboard made for tilde.town!",
True),
urwid.Text(("dim", "...by ~desvox")),
urwid.Divider("-"),
urwid.Button("Post Formatting Help", self.formatting_help),
urwid.Divider("-"),
urwid.Text(general_help)
])),
title="?????",
**frame_theme()
)
app.loop.widget = urwid.Overlay(
widget, app.loop.widget,
align=("relative", 50),
valign=("relative", 50),
width=30,
height=("relative", 60)
)
def open_box(self, box):
self.original_widget = urwid.Overlay(urwid.LineBox(box),
self.original_widget,
align='center', width=('relative', 80),
valign='middle', height=('relative', 80),
min_width=24, min_height=8,
left=self.box_level * 3,
right=(self.max_box_levels - self.box_level - 1) * 3,
top=self.box_level * 2,
bottom=(self.max_box_levels - self.box_level - 1) * 2)
self.box_level += 1
def main_shadow(self, w):
"""Wrap a shadow and background around widget w."""
bg = urwid.AttrWrap(urwid.SolidFill(u"\u2592"), 'screen edge')
shadow = urwid.AttrWrap(urwid.SolidFill(u" "), 'main shadow')
bg = urwid.Overlay( shadow, bg,
('fixed left', 3), ('fixed right', 1),
('fixed top', 2), ('fixed bottom', 1))
w = urwid.Overlay( w, bg,
('fixed left', 2), ('fixed right', 3),
('fixed top', 1), ('fixed bottom', 2))
return w
def main_shadow(self, w):
"""Wrap a shadow and background around widget w."""
bg = urwid.AttrWrap(urwid.SolidFill(u"\u2592"), 'screen edge')
shadow = urwid.AttrWrap(urwid.SolidFill(u" "), 'main shadow')
bg = urwid.Overlay( shadow, bg,
('fixed left', 3), ('fixed right', 1),
('fixed top', 2), ('fixed bottom', 1))
w = urwid.Overlay( w, bg,
('fixed left', 2), ('fixed right', 3),
('fixed top', 1), ('fixed bottom', 2))
return w
def test_get_cursor_coords(self):
self.assertEqual(urwid.Overlay(urwid.Filler(urwid.Edit()),
urwid.SolidFill(u'B'),
'right', 1, 'bottom', 1).get_cursor_coords((2,2)), (1,1))
def test_overlay(self):
self.wstest(urwid.Overlay(
urwid.BigText("hello",urwid.Thin6x6Font()),
urwid.SolidFill(),
'center', None, 'middle', None))
self.wstest(urwid.Overlay(
urwid.Text("hello"), urwid.SolidFill(),
'center', ('relative', 100), 'middle', None))
def make_quit_confirmation(self):
text = urwid.AttrMap(urwid.Text('Do you really want to quit ? (y/n)'), 'body')
self.quit_confirm_view = urwid.Overlay(text, self.current_view, 'left',
('relative', 100), 'bottom', None)
return self.quit_confirm_view
def make_submit_confirmation(self):
text = urwid.AttrMap(urwid.Text('Do you want to submit your code ? (y/n)'), 'body')
self.submit_confirm_view = urwid.Overlay(text, self.current_view, 'left',
('relative', 100), 'bottom', None)
return self.submit_confirm_view
def make_search_view(self):
text = urwid.AttrMap(urwid.Edit('Search by id: ', ''), 'body')
self.search_view = urwid.Overlay(text, self.current_view, 'left',
('relative', 100), 'bottom', None)
return self.search_view
def __init__(self, quiz, host_view, result, loop = None):
self.quiz = quiz
self.host_view = host_view
self.result = result
self.loop = loop
self.logger = logging.getLogger(__name__)
if result:
if 'status_code' not in result:
raise ValueError('Unknow result format: %s' % json.dumps(result))
if result['status_code'] is 20:
self.listbox = self.make_compile_error_view()
elif result['status_code'] is 10:
self.listbox = self.make_success_view()
elif result['status_code'] is 11:
self.listbox = self.make_failed_view()
elif result['status_code'] is 12:# memeory limit exceeded
self.listbox = self.make_unified_error_view("Memory Limit Exceeded")
elif result['status_code'] is 13:# output limit exceeded
self.listbox = self.make_unified_error_view("Output Limit Exceeded")
elif result['status_code'] is 14:# timeout
self.listbox = self.make_unified_error_view("Time Limit Exceeded")
elif result['status_code'] is 15:
self.listbox = self.make_runtime_error_view()
else:
raise ValueError('Unknow status code: %d' % result['status_code'])
else:
raise ValueError('result shouldn\'t be None')
self.overlay = urwid.Overlay(urwid.LineBox(self.listbox), host_view,
align='center', width=('relative', 95),
valign='middle', height=('relative', 95),
min_width=40, min_height=40)
footer = urwid.Pile([urwid.Text('Press Esc to close this view.', align='center'),
urwid.Divider()])
urwid.Frame.__init__(self, self.overlay, footer=footer)