comparison frontends/primitivus/custom_widgets.py @ 151:7fcb4f083686

Primitivus: custom_widgets imrpovments - new container: TabsContainer - menu roller can now remove a menu - new Button: CustomButton (use ClickableText, and we can define the borders) - SelectableText now manage mouse events
author Goffi <goffi@goffi.org>
date Fri, 30 Jul 2010 18:43:09 +0800
parents 80661755ea8d
children 2fa58703f1b7
comparison
equal deleted inserted replaced
150:63d20bda5754 151:7fcb4f083686
93 def display_widget(self, size, focus): 93 def display_widget(self, size, focus):
94 (maxcol,) = size 94 (maxcol,) = size
95 middle = (maxcol-len(self.text))/2 95 middle = (maxcol-len(self.text))/2
96 render_text = middle * self.car + self.text + (maxcol - len(self.text) - middle) * self.car 96 render_text = middle * self.car + self.text + (maxcol - len(self.text) - middle) * self.car
97 return urwid.Text(render_text) 97 return urwid.Text(render_text)
98
99
100 98
101 class SelectableText(urwid.FlowWidget): 99 class SelectableText(urwid.FlowWidget):
102 """Text which can be selected with space""" 100 """Text which can be selected with space"""
103 signals = ['change'] 101 signals = ['change']
104 102
148 if key==' ' or key=='enter': 146 if key==' ' or key=='enter':
149 self.setState(not self.__selected) 147 self.setState(not self.__selected)
150 else: 148 else:
151 return key 149 return key
152 150
151 def mouse_event(self, size, event, button, x, y, focus):
152 if urwid.is_mouse_press(event) and button == 1:
153 self.setState(not self.__selected)
154 return True
155
156 return False
157
153 def rows(self,size,focus=False): 158 def rows(self,size,focus=False):
154 return self.display_widget(size, focus).rows(size, focus) 159 return self.display_widget(size, focus).rows(size, focus)
155 160
156 def render(self, size, focus=False): 161 def render(self, size, focus=False):
157 return self.display_widget(size, focus).render(size, focus) 162 return self.display_widget(size, focus).render(size, focus)
173 class ClickableText(SelectableText): 178 class ClickableText(SelectableText):
174 signals = SelectableText.signals + ['click'] 179 signals = SelectableText.signals + ['click']
175 180
176 def setState(self, selected, invisible=False): 181 def setState(self, selected, invisible=False):
177 self._emit('click') 182 self._emit('click')
183
184 class CustomButton(ClickableText):
185
186 def __init__(self, label, on_press=None, user_data=None, left_border = "[ ", right_border = " ]"):
187 self.label = label
188 render_txt = "%s%s%s" % (left_border, label, right_border)
189 self.size = len(render_txt)
190 super(CustomButton, self).__init__(render_txt)
191 if on_press:
192 urwid.connect_signal(self, 'click', on_press, user_data)
193
194 def getSize(self):
195 """Return representation size of the button"""
196 return self.size
197
198 def get_label(self):
199 return self.label
178 200
179 class GenericList(urwid.WidgetWrap): 201 class GenericList(urwid.WidgetWrap):
180 signals = ['click','change'] 202 signals = ['click','change']
181 203
182 def __init__(self, options, style=[], align='left', option_type = SelectableText, on_click=None, on_change=None, user_data=None): 204 def __init__(self, options, style=[], align='left', option_type = SelectableText, on_click=None, on_change=None, user_data=None):
335 return urwid.BoxAdapter(self.genericList, height) 357 return urwid.BoxAdapter(self.genericList, height)
336 358
337 ## MISC ## 359 ## MISC ##
338 360
339 class MenuBox(urwid.WidgetWrap): 361 class MenuBox(urwid.WidgetWrap):
362 """Show menu items of a category in a box"""
340 signals = ['click'] 363 signals = ['click']
341 364
342 def __init__(self,parent,items): 365 def __init__(self,parent,items):
343 self.parent = parent 366 self.parent = parent
344 self.selected = None 367 self.selected = None
513 if self.columns.get_focus_column()==0 and self.selected < len(self.name_list)-1: 536 if self.columns.get_focus_column()==0 and self.selected < len(self.name_list)-1:
514 self.selected += 1 537 self.selected += 1
515 self.__showSelected() 538 self.__showSelected()
516 elif key=='right': 539 elif key=='right':
517 if self.columns.get_focus_column()==0 and \ 540 if self.columns.get_focus_column()==0 and \
518 (self.columns.widget_list[1].__class__ == urwid.Text or \ 541 (isinstance(self.columns.widget_list[1], urwid.Text) or \
519 self.menus[self.name_list[self.selected]].getMenuSize()==0): 542 self.menus[self.name_list[self.selected]].getMenuSize()==0):
520 return #if we have no menu or the menu is empty, we don't go the right column 543 return #if we have no menu or the menu is empty, we don't go the right column
521 544
522 return super(MenuRoller, self).keypress(size, key) 545 return super(MenuRoller, self).keypress(size, key)
523 546
526 if name not in self.name_list: 549 if name not in self.name_list:
527 self.name_list.append(name) 550 self.name_list.append(name)
528 self.menus[name] = menu 551 self.menus[name] = menu
529 if self.name_list[self.selected] == name: 552 if self.name_list[self.selected] == name:
530 self.__showSelected() #if we are on the menu, we update it 553 self.__showSelected() #if we are on the menu, we update it
554
555 def removeMenu(self, name):
556 if name in self.name_list:
557 self.name_list.remove(name)
558 if name in self.menus.keys():
559 del self.menus[name]
560 self.selected = 0
561 self.__showSelected()
531 562
532 def checkShortcuts(self, key): 563 def checkShortcuts(self, key):
533 for menu in self.name_list: 564 for menu in self.name_list:
534 key = self.menus[menu].checkShortcuts(key) 565 key = self.menus[menu].checkShortcuts(key)
535 return key 566 return key
599 if widget!=None and widget.selectable(): 630 if widget!=None and widget.selectable():
600 self.set_focus(focus_name) 631 self.set_focus(focus_name)
601 632
602 return urwid.Frame.keypress(self, size, key) 633 return urwid.Frame.keypress(self, size, key)
603 634
635 class TabsContainer(urwid.WidgetWrap):
636 signals = ['click']
637
638 def __init__(self):
639 #self._current_tab = 0
640 self._buttons_cont = urwid.GridFlow([],19,1,0,'left')
641 self.tabs = []
642 self.__frame = urwid.Frame(urwid.Text(''),urwid.Pile([self._buttons_cont,urwid.Divider(u"─")]))
643 urwid.WidgetWrap.__init__(self, self.__frame)
644
645 """def selectable(self):
646 return True
647
648 def keypress(self, size, key):
649 return key"""
650
651 def __buttonClicked(self, button, invisible=False):
652 """Called when a button on the tab is changed,
653 change the page
654 @param button: button clicked
655 @param invisible: emit signal only if False"""
656 tab_name = button.get_label()
657 for tab in self.tabs:
658 if tab[0] == tab_name:
659 break
660 if tab[0] != tab_name:
661 error(_("INTERNAL ERROR: Tab not found"))
662 assert(False)
663 self.__frame.body = tab[1]
664 if not invisible:
665 self._emit('click')
666
667 def __appendButton(self, name):
668 """Append a button to the frame header,
669 and link it to the page change method"""
670 button = CustomButton(name, self.__buttonClicked, left_border = '', right_border=' |')
671 self._buttons_cont.cells.append(button)
672 if len(self._buttons_cont.cells):
673 #first button: we set the focus and the body
674 self._buttons_cont.set_focus(0)
675 self.__buttonClicked(button,True)
676
677 def addTab(self,name,content=[]):
678 """Add a page to the container
679 @param name: name of the page (what appear on the tab)
680 @param content: content of the page
681 @return: ListBox (content of the page)"""
682 listbox = urwid.ListBox(urwid.SimpleListWalker(content))
683 self.tabs.append([name,listbox])
684 self.__appendButton(name)
685 return listbox
686
604 ## DECORATORS ## 687 ## DECORATORS ##
605 class LabelLine(urwid.LineBox): 688 class LabelLine(urwid.LineBox):
606 """Like LineBox, but with a Label centered in the top line""" 689 """Like LineBox, but with a Label centered in the top line"""
607 690
608 def __init__(self, original_widget, label_widget): 691 def __init__(self, original_widget, label_widget):
610 top_columns = self._w.widget_list[0] 693 top_columns = self._w.widget_list[0]
611 top_columns.widget_list[1] = label_widget 694 top_columns.widget_list[1] = label_widget
612 695
613 class VerticalSeparator(urwid.WidgetDecoration, urwid.WidgetWrap): 696 class VerticalSeparator(urwid.WidgetDecoration, urwid.WidgetWrap):
614 def __init__(self, original_widget, left_char = utf8decode("│"), right_char = ''): 697 def __init__(self, original_widget, left_char = utf8decode("│"), right_char = ''):
615 """Draw a separator on left and/or of original_widget.""" 698 """Draw a separator on left and/or right of original_widget."""
616 699
617 widgets = [original_widget] 700 widgets = [original_widget]
618 if left_char: 701 if left_char:
619 widgets.insert(0, ('fixed', 1, urwid.SolidFill(left_char))) 702 widgets.insert(0, ('fixed', 1, urwid.SolidFill(left_char)))
620 if right_char: 703 if right_char: