Mercurial > urwid-satext
comparison frontends/primitivus/custom_widgets.py @ 15:8241b3157699
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 | f7d24eff1272 |
children | 263fe4d067ad |
comparison
equal
deleted
inserted
replaced
14:f7d24eff1272 | 15:8241b3157699 |
---|---|
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: |