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类SimpleFocusListWalker()的实例源码
def reply_box(self, button, thr_id):
subject = ur.Edit(("blue", "Subject: "), wrap="clip")
name = ur.Edit(("blue", "Name: "), "Anonymous", wrap="clip")
if thr_id == -1:
text = ur.Edit(multiline=True)
else:
text = ur.Edit(edit_text=">>" + thr_id, multiline=True)
post_btn = ur.AttrMap(ur.Button(
"Post", self.add_post, (subject, name, text, thr_id)),
"green", "b_green")
box = ur.LineBox(ur.ListBox(ur.SimpleFocusListWalker(
[name, subject, ur.LineBox(text, "Post text"),
self.parent.div, post_btn])))
self.loop.Widget = MyOverlay(
box, self.loop.baseWidget,
"center", ("relative", 100), "top", ("relative", 100),
None, None,
self.parent.margin, self.parent.margin,
int(self.loop.dimensions[1] * 0.3),
int(self.loop.dimensions[1] * 0.3),
self.parent)
def test_evaluated_key_does_not_replace_original_key(self):
# Create a list of widgets that translate 'j' to 'down' in their
# keypress() methods.
lst_contents = [self.mk_widget(urwid.Text, str(i), context='item')
for i in range(1, 10)]
self.keymap.bind('j', context='item', action=Key('down'))
# Create ListBox with separate key context. If the ListBox gets to
# handle 'j', it just checks a mark we can look for.
lst_widget = self.mk_widget(urwid.ListBox, urwid.SimpleFocusListWalker(lst_contents), context='list')
lst_got_j = FakeAction()
self.keymap.bind('j', context='list', action=lst_got_j)
# Make sure everything works regularly
size = (3, 3)
self.assert_lines(lst_widget, size, exp_lines=('1 ', '2 ', '3 '), exp_focus_pos=0)
lst_widget.keypress(size, 'down')
self.assert_lines(lst_widget, size, exp_lines=('1 ', '2 ', '3 '), exp_focus_pos=1)
# Do the actual test: Pressing 'j' should pass 'j' to the focused item,
# which evaluates it to 'down'. But the list widget must get 'j'.
lst_widget.keypress(size, 'j')
self.assert_lines(lst_widget, size, exp_lines=('1 ', '2 ', '3 '), exp_focus_pos=1)
self.assertEqual(lst_got_j.callnum, 1)
def __init__(self):
self.prefs = bbjrc("load")
self.mode = None
self.thread = None
self.usermap = {}
self.window_split = False
self.last_pos = None
# these can be changed and manipulated by other methods
self.walker = urwid.SimpleFocusListWalker([])
self.box = ActionBox(self.walker)
self.body = urwid.AttrMap(
urwid.LineBox(
self.box,
title=self.prefs["frame_title"],
**frame_theme()),
"default"
)
self.loop = urwid.MainLoop(
urwid.Frame(self.body),
palette=colormap,
handle_mouse=self.prefs["mouse_integration"])
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 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 set_escape_key(self, button, args):
mode = args[0]
widget = OptionsMenu(
urwid.ListBox(urwid.SimpleFocusListWalker([
urwid.Text("Press Enter when done"),
urwid.AttrMap(KeyPrompt(
self.prefs["edit_escapes"][mode],
self.save_escape_key,
[mode]
), "opt_prompt")])),
title="Set key for " + mode,
**frame_theme()
)
app.loop.widget = urwid.Overlay(
urwid.AttrMap(widget, "30"),
app.loop.widget,
align=("relative", 50),
valign=("relative", 50),
width=25, height=5
)
def toggle_detail(self, item):
if not self.detail_view:
self.before_detail = self.body
detail_text = json.dumps(
item.detail, indent=4, sort_keys=True, cls=DateTimeEncoder)
lines = detail_text.split('\n')
text_lines = [urwid.Text(l) for l in lines]
list_box = DetailListBox(
urwid.SimpleFocusListWalker(text_lines), self)
self.body = list_box
LAYOUT.contents['body'] = (self.body, None)
self.detail_view = True
else:
self.body = self.before_detail
LAYOUT.contents['body'] = (self.body, None)
del self.before_detail
self.detail_view = False
def __init__(self):
self.walker = urwid.SimpleFocusListWalker(contents=self.log_messages)
self.list_box = urwid.ListBox(self.walker)
self.graph = urwid.BarGraph(
attlist=['graph bg background', 'graph bg 1', 'graph bg 2'],
satt={
(1, 0): 'graph bg 1 smooth',
(2, 0): 'graph bg 2 smooth'
}
)
self.graph_widget = urwid.LineBox(self.graph, title=self.graph_title)
self.default_widget = urwid.Columns([
urwid.LineBox(
self.list_box,
title="Logger"
),
self.graph_widget
])
self.logger_widget = urwid.LineBox(
self.list_box,
title="Logger"
)
def MOTD_screen(self):
"""MOTD display method - first screen shown."""
self.motd_flag = True
self.header = self.make_header()
mid = ur.Padding(ur.ListBox(
ur.SimpleFocusListWalker([
self.div, ur.Text([("red", "Welcome to "),
("yellow", "sshchan!\n==========="),
("red", "========\n"),
("green", "SERVER: "),
self.config.server_name,
("green", "\nMOTD:\n")], "center"),
self.div])), "center", ("relative", 60), self.width,
self.margin, self.margin)
# TODO: add currently online users to the footer.
self.footer = ur.AttrMap(ur.Text(
" " + self.config.server_name + " " + self.config.version +
" | Press H for help", align="center"), "reverse", None)
try:
with open(self.config.motd, 'r') as m:
buf = m.read()
except FileNotFoundError:
buf = "---sshchan! woo!---"
motd = ur.Text(buf, "center")
mid.original_widget.body.append(motd)
mid.original_widget.body.append(self.div)
return ur.Frame(mid, self.header, self.footer, focus_part="body")
def print_thread(self, button, thread):
thr_no = self.board.thread_exists(int(thread))
thr_body = self.board.get_index()[thr_no]
replies = ur.SimpleFocusListWalker([])
subject = ("reverse_red", thr_body[1])
if subject[1] == "":
subject = (None, "")
op = self.parse_post(thr_body[2])
op_info = ur.Text([("reverse_green", op["name"]),
" " + op["stamp"] + " ", subject])
op_btn = CleanButton(
"No. " + op["id"], self.reply_box, op["id"])
op_widget = ur.AttrMap(ur.Columns(
[("pack", op_info), ("pack", op_btn)], 1), "reverse")
replies.extend([op_widget, op["text"], self.parent.div])
if len(thr_body) > 3:
for postno in range(3, len(thr_body)):
reply = self.parse_post(thr_body[postno])
reply_info = ur.Text(
[("green", reply["name"]), " " + reply["stamp"]])
reply_btn = CleanButton(
"No. " + reply["id"], self.reply_box, reply["id"])
reply_widget = ur.Columns(
[("pack", reply_info), ("pack", reply_btn)],
1)
replies.extend([reply_widget, reply["text"], self.parent.div])
contents = ur.ListBox(replies)
contents.set_focus(0)
self.loop.Widget = ur.Frame(
contents, self.parent.header, self.parent.footer, "body")
def __init__(self, test_id, text, escape_method):
self.escape_method = escape_method
lines = text.split('\n')
list_items = [
urwid.AttrMap(urwid.Text(line), None, focus_map='reversed') for line in lines
]
super(TestResultWindow, self).__init__(
urwid.ListBox(
urwid.SimpleFocusListWalker(list_items)
),
title=test_id
)
def test_listbox(self, test_list):
list_items = []
for position, test_id in enumerate(test_list):
test_line_attr = self.get_list_item(test_id, position)
list_items.append(test_line_attr)
return urwid.ListBox(urwid.SimpleFocusListWalker(list_items))
def __init__(self, pubpen):
self.pubpen = pubpen
self.keypress_map = IndexedMenuEnumerator()
self._ship_moved_sub_id = None
self.listwalker = urwid.SimpleFocusListWalker([])
box = urwid.ListBox(self.listwalker)
outer_layout = LineBox(box, lline=None, blcorner='?',
tlcorner='?', trcorner='\u252c',
brcorner='\u2524')
super().__init__(outer_layout)
self.pubpen.subscribe('ship.destinations', self.handle_new_destinations)
# pubpen event handlers
def __init__(self, pubpen):
self.pubpen = pubpen
self.save_button = urwid.Button('(S)ave')
self.load_button = urwid.Button('(L)oad')
self.quit_button = urwid.Button('(Q)uit')
self.continue_button = urwid.Button('(ESC) Continue Game')
self.buttons = urwid.SimpleFocusListWalker((
urwid.AttrMap(self.save_button, None, focus_map='reversed'),
urwid.AttrMap(self.load_button, None, focus_map='reversed'),
urwid.AttrMap(self.quit_button, None, focus_map='reversed'),
urwid.AttrMap(self.continue_button, None, focus_map='reversed'),
))
self.entrybox = urwid.ListBox(self.buttons)
# Draw a box around the widget and constrain the widget's size
linebox = urwid.LineBox(self.entrybox, tlcorner='\u2554',
tline='\u2550', trcorner='\u2557',
blcorner='\u255A', bline='\u2550',
brcorner='\u255D', lline='\u2551',
rline='\u2551')
padding = urwid.Padding(linebox, align='center',
width=len(self.continue_button.get_label()) + 6)
filler = urwid.Filler(padding, valign='middle',
height=len(self.buttons) + 2)
outer_layout = LineBox(filler, lline=None, blcorner='?',
tlcorner='?', trcorner='\u252c',
brcorner='\u2524')
super().__init__(outer_layout)
urwid.connect_signal(self.save_button, 'click', self.save_game)
urwid.connect_signal(self.load_button, 'click', self.load_game)
urwid.connect_signal(self.quit_button, 'click', self.quit_client)
urwid.connect_signal(self.continue_button, 'click', self.continue_game)
def __init__(self, pubpen):
self.pubpen = pubpen
self.loop = self.pubpen.loop
self.message_list = urwid.SimpleFocusListWalker([])
list_box = urwid.ListBox(self.message_list)
message_win = LineBox(list_box, tline=None, lline=None, bline=None,
trcorner='?', brcorner='?')
super().__init__(message_win)
self.pubpen.subscribe('user.login_failure', partial(self.add_message, severity=MsgType.error))
self.pubpen.subscribe('user.order_failure', partial(self.add_message, severity=MsgType.error))
self.pubpen.subscribe('ship.movement_failure', partial(self.add_message, severity=MsgType.error))
self.pubpen.subscribe('market.event', self.handle_market_event)
self.pubpen.subscribe('ui.urwid.message', self.add_message)
def get_history(self):
while self.updateLocked:
time.sleep(0.5)
self.updateLocked = True
self.separator_pos = -1
current_cmd = self.Telegram_ui.current_chan['id']
if current_cmd not in self.prev_date:
self.prev_date[current_cmd] = 1
# deletion of previous messages
self.msg_list = [] # urwid.SimpleFocusListWalker([urwid.Text(('top', " "), align='left')])
super().__init__(self.msg_list)
self.pos = 0
if current_cmd not in self.Telegram_ui.msg_buffer:
current_print_name = self.Telegram_ui.current_chan['print_name']
try:
msgList = self.Telegram_ui.sender.history(current_print_name, 100)
except:
msgList = []
self.Telegram_ui.msg_buffer[current_cmd] = msgList
if current_cmd not in self.Telegram_ui.msg_archive:
self.Telegram_ui.msg_archive[current_cmd] = []
else:
self.print_msg_archive()
for msg in self.Telegram_ui.msg_buffer[current_cmd]:
self.print_msg(msg)
# messages have been printed, deletion form buffer (they are in archive now)
self.Telegram_ui.msg_buffer[current_cmd] = []
self.draw_separator()
self.updateLocked = False
def __init__(self, content):
"""
:param content: text string to be displayed
"""
lines = [UnicodeText(line) for line in content]
body = urwid.SimpleFocusListWalker(lines)
urwid.ListBox.__init__(self, body)
def test_hardcoded_keys_keep_working(self):
list_contents = [urwid.Text(str(i)) for i in range(1, 10)]
widget = self.mk_widget(urwid.ListBox, urwid.SimpleFocusListWalker(list_contents),
context='list')
size = (3, 3)
self.assert_lines(widget, size, exp_lines=('1 ', '2 ', '3 '))
widget.keypress(size, 'down')
self.assert_lines(widget, size, exp_lines=('2 ', '3 ', '4 '))
widget.keypress(size, 'page down')
self.assert_lines(widget, size, exp_lines=('5 ', '6 ', '7 '))
widget.keypress(size, 'up')
self.assert_lines(widget, size, exp_lines=('4 ', '5 ', '6 '))
widget.keypress(size, 'page up')
self.assert_lines(widget, size, exp_lines=('1 ', '2 ', '3 '))
def test_non_hardcoded_keys_are_evaluated(self):
list_contents = [urwid.Text(str(i)) for i in range(1, 10)]
widget = self.mk_widget(urwid.ListBox, urwid.SimpleFocusListWalker(list_contents),
context='list')
action = FakeAction()
self.keymap.bind('a', context='list', action=action)
size = (3, 3)
self.assert_lines(widget, size, exp_lines=('1 ', '2 ', '3 '))
widget.keypress(size, 'a')
self.assert_lines(widget, size, exp_lines=('1 ', '2 ', '3 '))
self.assertEqual(action.callnum, 1)
self.assertEqual(action.args, (widget,))
def test_evaluated_keys_are_offered_to_parent_again(self):
list_contents = [urwid.Text(str(i)) for i in range(1, 10)]
action = FakeAction()
widget = self.mk_widget(urwid.ListBox, urwid.SimpleFocusListWalker(list_contents),
context='list', callback=action)
self.keymap.bind('j', context='list', action=Key('down'))
size = (3, 3)
self.assert_lines(widget, size, exp_lines=('1 ', '2 ', '3 '))
widget.keypress(size, 'j')
self.assertEqual(action.callnum, 0)
self.assert_lines(widget, size, exp_lines=('2 ', '3 ', '4 '))
def test_key_translation_to_builtin_key(self):
class SelectableText(urwid.Text):
def selectable(self): return True
def keypress(self, size, key): return key
list_contents = [SelectableText(str(i)) for i in range(1, 10)]
listw = self.km.wrap(urwid.ListBox, context='list')(urwid.SimpleFocusListWalker(list_contents))
self.km.bind(key='j', action=Key('down'))
self.assertEqual(listw.focus_position, 0)
listw.keypress((3, 3), 'j')
self.assertEqual(listw.focus_position, 1)
def __init__(self, srvapi, keymap, columns=None, sort=None, title=None):
self._srvapi = srvapi
self._keymap = keymap
if self.focusable_items:
self._ListItemClass = keymap.wrap(self.ListItemClass, context=self.keymap_context)
else:
self._ListItemClass = self.ListItemClass
self._items = ()
self._marked = set()
self._columns = columns or []
self._sort = sort
self._sort_orig = sort
self._title_name = title
self.title_updater = None
self._table = Table(**self.tuicolumns)
self._table.columns = self._columns
if self.focusable_items:
walker = urwid.SimpleFocusListWalker([])
else:
walker = urwid.SimpleListWalker([])
self._listbox = keymap.wrap(urwid.ListBox, context=self.keymap_context + 'list')(walker)
listbox_sb = urwid.AttrMap(
ScrollBar(urwid.AttrMap(self._listbox, self.palette_name)),
'scrollbar'
)
pile = urwid.Pile([
('pack', urwid.AttrMap(self._table.headers, self.palette_name + '.header')),
listbox_sb
])
super().__init__(pile)
def __init__(self, column_meta):
self.qrlist = urwid.SimpleFocusListWalker([])
self.widgets = {}
self.column_meta = column_meta
self.sort_column = column_meta.default_sort_key
self.sort_keys_map = {c.sort_key: name
for name, c in column_meta.columns.items()}
super(QueryListBox, self).__init__(self.qrlist)
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 __init__(self, choices: Sequence[Mod]):
"""Create menu for choices.
Keyword arguments:
choices: The :class:`Mod`s to choose from.
"""
items = [self.Item(m, self.choose, self.end_loop) for m in choices]
super().__init__(urwid.SimpleFocusListWalker(items))
self.chosen = None