comparison urwid_satext/sat_widgets.py @ 84:9f683df69a4c

shortcut keys are now managed in separate module, with a class checking for conflicts
author Goffi <goffi@goffi.org>
date Thu, 04 Sep 2014 16:50:12 +0200
parents c456beff1779
children c95462c21966
comparison
equal deleted inserted replaced
83:12b5b1435e17 84:9f683df69a4c
21 from logging import debug, info, warning, error 21 from logging import debug, info, warning, error
22 import encodings 22 import encodings
23 utf8decode = lambda s: encodings.codecs.utf_8_decode(s)[0] 23 utf8decode = lambda s: encodings.codecs.utf_8_decode(s)[0]
24 24
25 from urwid.util import is_mouse_press #XXX: is_mouse_press is not included in urwid in 1.0.0 25 from urwid.util import is_mouse_press #XXX: is_mouse_press is not included in urwid in 1.0.0
26 from .keys import action_key_map as a_key
26 27
27 28
28 class AdvancedEdit(urwid.Edit): 29 class AdvancedEdit(urwid.Edit):
29 """Edit box with some custom improvments 30 """Edit box with some custom improvments
30 new chars: 31 new chars:
48 self.completion_cb = callback 49 self.completion_cb = callback
49 self.completion_data = {} 50 self.completion_data = {}
50 51
51 def keypress(self, size, key): 52 def keypress(self, size, key):
52 #TODO: insert mode is not managed yet 53 #TODO: insert mode is not managed yet
53 if key == 'ctrl a': 54 if key == a_key['EDIT_HOME']:
54 key = 'home' 55 key = 'home'
55 elif key == 'ctrl e': 56 elif key == a_key['EDIT_END']:
56 key = 'end' 57 key = 'end'
57 elif key == 'ctrl k': 58 elif key == a_key['EDIT_DELETE_TO_END']:
58 self._delete_highlighted() 59 self._delete_highlighted()
59 self.set_edit_text(self.edit_text[:self.edit_pos]) 60 self.set_edit_text(self.edit_text[:self.edit_pos])
60 elif key == 'ctrl w': 61 elif key == a_key['EDIT_DELETE_LAST_WORD']:
61 before = self.edit_text[:self.edit_pos] 62 before = self.edit_text[:self.edit_pos]
62 pos = before.rstrip().rfind(" ")+1 63 pos = before.rstrip().rfind(" ")+1
63 self.set_edit_text(before[:pos] + self.edit_text[self.edit_pos:]) 64 self.set_edit_text(before[:pos] + self.edit_text[self.edit_pos:])
64 self.set_edit_pos(pos) 65 self.set_edit_pos(pos)
65 elif key == 'enter': 66 elif key == a_key['EDIT_ENTER']:
66 self._emit('click') 67 self._emit('click')
67 elif key == 'shift tab': 68 elif key == a_key['EDIT_COMPLETE']:
68 try: 69 try:
69 before = self.edit_text[:self.edit_pos] 70 before = self.edit_text[:self.edit_pos]
70 if self.completion_data: 71 if self.completion_data:
71 if (not self.completion_data['completed'] 72 if (not self.completion_data['completed']
72 or self.completion_data['position'] != self.edit_pos 73 or self.completion_data['position'] != self.edit_pos
152 def setCompletionMethod(self, callback): 153 def setCompletionMethod(self, callback):
153 """ Same as AdvancedEdit.setCompletionMethod, but with a third argument: current mode""" 154 """ Same as AdvancedEdit.setCompletionMethod, but with a third argument: current mode"""
154 super(ModalEdit, self).setCompletionMethod(lambda text,data: callback(text, data, self._mode)) 155 super(ModalEdit, self).setCompletionMethod(lambda text,data: callback(text, data, self._mode))
155 156
156 def keypress(self, size, key): 157 def keypress(self, size, key):
157 if key == 'esc': 158 if key == a_key['MODAL_ESCAPE']:
158 self.mode = "NORMAL" 159 self.mode = "NORMAL"
159 return 160 return
160 if self._mode == 'NORMAL' and key in self._modes: 161 if self._mode == 'NORMAL' and key in self._modes:
161 self.mode = self._modes[key][0] 162 self.mode = self._modes[key][0]
162 return 163 return
260 261
261 def selectable(self): 262 def selectable(self):
262 return True 263 return True
263 264
264 def keypress(self, size, key): 265 def keypress(self, size, key):
265 if key==' ' or key=='enter': 266 if key in (a_key['TEXT_SELECT'], a_key['TEXT_SELECT2']):
266 self.setState(not self.__selected) 267 self.setState(not self.__selected)
267 else: 268 else:
268 return key 269 return key
269 270
270 def mouse_event(self, size, event, button, x, y, focus): 271 def mouse_event(self, size, event, button, x, y, focus):
693 694
694 def getValue(self): 695 def getValue(self):
695 return self.selected 696 return self.selected
696 697
697 def keypress(self, size, key): 698 def keypress(self, size, key):
698 if key=='up': 699 if key==a_key['MENU_BOX_UP']:
699 if self.listBox.get_focus()[1] == 0: 700 if self.listBox.get_focus()[1] == 0:
700 self.parent.keypress(size, key) 701 self.parent.keypress(size, key)
701 elif key=='left' or key=='right': 702 elif key in (a_key['MENU_BOX_LEFT'], a_key['MENU_BOX_RIGHT']):
702 self.parent.keypress(size,'up') 703 self.parent.keypress(size,'up')
703 self.parent.keypress(size,key) 704 self.parent.keypress(size,key)
704 return super(MenuBox,self).keypress(size,key) 705 return super(MenuBox,self).keypress(size,key)
705 706
706 def mouse_event(self, size, event, button, x, y, focus): 707 def mouse_event(self, size, event, button, x, y, focus):
754 urwid.connect_signal(menu_box, 'click', self.onItemClick) 755 urwid.connect_signal(menu_box, 'click', self.onItemClick)
755 756
756 self.loop.widget = urwid.Overlay(urwid.AttrMap(menu_box,'menubar'),self.save_bottom,('fixed left', columns),max_len+2,('fixed top',1),None) 757 self.loop.widget = urwid.Overlay(urwid.AttrMap(menu_box,'menubar'),self.save_bottom,('fixed left', columns),max_len+2,('fixed top',1),None)
757 758
758 def keypress(self, size, key): 759 def keypress(self, size, key):
759 if key == 'down': 760 if key == a_key['MENU_DOWN']:
760 key = 'enter' 761 key = 'enter'
761 elif key == 'up': 762 elif key == a_key['MENU_UP']:
762 if self.save_bottom: 763 if self.save_bottom:
763 self.loop.widget = self.save_bottom 764 self.loop.widget = self.save_bottom
764 self.save_bottom = None 765 self.save_bottom = None
765 766
766 return self._w.base_widget.keypress(size, key) 767 return self._w.base_widget.keypress(size, key)
799 for menu_item in self.menu[category]: 800 for menu_item in self.menu[category]:
800 if item == menu_item[0]: 801 if item == menu_item[0]:
801 callback = menu_item[1] 802 callback = menu_item[1]
802 break 803 break
803 if callback: 804 if callback:
804 self.keypress(None,'up') 805 self.keypress(None, a_key['MENU_UP'])
805 callback((category, item)) 806 callback((category, item))
806 807
807 def onCategoryClick(self, button): 808 def onCategoryClick(self, button):
808 self.__buildOverlay(button.get_label(), 809 self.__buildOverlay(button.get_label(),
809 self.x_orig + self._w.base_widget.getStartCol(button)) 810 self.x_orig + self._w.base_widget.getStartCol(button))
836 current_menu.setOrigX(name_len) 837 current_menu.setOrigX(name_len)
837 self.columns.contents[0] = (current_name, ('given', name_len, False)) 838 self.columns.contents[0] = (current_name, ('given', name_len, False))
838 self.columns.contents[1] = (current_menu, ('weight', 1, False)) 839 self.columns.contents[1] = (current_menu, ('weight', 1, False))
839 840
840 def keypress(self, size, key): 841 def keypress(self, size, key):
841 if key=='up': 842 if key==a_key['MENU_ROLLER_UP']:
842 if self.columns.get_focus_column()==0 and self.selected > 0: 843 if self.columns.get_focus_column()==0 and self.selected > 0:
843 self.selected -= 1 844 self.selected -= 1
844 self._showSelected() 845 self._showSelected()
845 return 846 return
846 elif key=='down': 847 elif key==a_key['MENU_ROLLER_DOWN']:
847 if self.columns.get_focus_column()==0 and self.selected < len(self.name_list)-1: 848 if self.columns.get_focus_column()==0 and self.selected < len(self.name_list)-1:
848 self.selected += 1 849 self.selected += 1
849 self._showSelected() 850 self._showSelected()
850 return 851 return
851 elif key=='right': 852 elif key==a_key['MENU_ROLLER_RIGHT']:
852 if self.columns.get_focus_column()==0 and \ 853 if self.columns.get_focus_column()==0 and \
853 (isinstance(self.columns.contents[1][0], urwid.Text) or \ 854 (isinstance(self.columns.contents[1][0], urwid.Text) or \
854 self.menus[self.name_list[self.selected]].getMenuSize()==0): 855 self.menus[self.name_list[self.selected]].getMenuSize()==0):
855 return #if we have no menu or the menu is empty, we don't go the right column 856 return #if we have no menu or the menu is empty, we don't go the right column
856 857
973 return self.widget_list[self.focus_column][1].selectable() 974 return self.widget_list[self.focus_column][1].selectable()
974 except IndexError: 975 except IndexError:
975 return False 976 return False
976 977
977 def keypress(self, size, key): 978 def keypress(self, size, key):
978 if key=='left': 979 if key==a_key['COLUMNS_ROLLER_LEFT']:
979 if self.focus_column>0: 980 if self.focus_column>0:
980 self.focus_column-=1 981 self.focus_column-=1
981 self._invalidate() 982 self._invalidate()
982 return 983 return
983 if key=='right': 984 if key==a_key['COLUMNS_ROLLER_RIGHT']:
984 if self.focus_column<len(self.widget_list)-1: 985 if self.focus_column<len(self.widget_list)-1:
985 self.focus_column+=1 986 self.focus_column+=1
986 self._invalidate() 987 self._invalidate()
987 return 988 return
988 if self.focus_column<len(self.widget_list): 989 if self.focus_column<len(self.widget_list):
1036 (maxcol,)=size 1037 (maxcol,)=size
1037 1038
1038 if is_mouse_press(event) and button == 1: 1039 if is_mouse_press(event) and button == 1:
1039 _prev,_next,start_wid,end_wid,cols_left = self.__calculate_limits(size) 1040 _prev,_next,start_wid,end_wid,cols_left = self.__calculate_limits(size)
1040 if x==0 and _prev: 1041 if x==0 and _prev:
1041 self.keypress(size,'left') 1042 self.keypress(size, a_key['COLUMNS_ROLLER_LEFT'])
1042 return True 1043 return True
1043 if x==maxcol-1 and _next: 1044 if x==maxcol-1 and _next:
1044 self.keypress(size,'right') 1045 self.keypress(size, a_key['COLUMNS_ROLLER_RIGHT'])
1045 return True 1046 return True
1046 1047
1047 current_pos = 1 if _prev else 0 1048 current_pos = 1 if _prev else 0
1048 idx = 0 1049 idx = 0
1049 while current_pos<x and idx<len(self.widget_list): 1050 while current_pos<x and idx<len(self.widget_list):
1061 1062
1062 return False 1063 return False
1063 1064
1064 def render(self, size, focus=False): 1065 def render(self, size, focus=False):
1065 if not self.widget_list: 1066 if not self.widget_list:
1066 return SolidCanvas(" ", size[0], 1) 1067 return urwid.SolidCanvas(" ", size[0], 1)
1067 1068
1068 _prev,_next,start_wid,end_wid,cols_left = self.__calculate_limits(size) 1069 _prev,_next,start_wid,end_wid,cols_left = self.__calculate_limits(size)
1069 1070
1070 idx=start_wid 1071 idx=start_wid
1071 render = [] 1072 render = []
1169 def keypress(self, size, key): 1170 def keypress(self, size, key):
1170 ret = super(FocusFrame, self).keypress(size, key) 1171 ret = super(FocusFrame, self).keypress(size, key)
1171 if not ret: 1172 if not ret:
1172 return 1173 return
1173 1174
1174 if key == 'tab': 1175 if key == a_key['FOCUS_SWITCH']:
1175 try: 1176 try:
1176 self.focus_position -= 1 1177 self.focus_position -= 1
1177 except IndexError: 1178 except IndexError:
1178 self.focus_position = 2 1179 self.focus_position = 2
1179 1180
1190 self.tabs = [] 1191 self.tabs = []
1191 self.__frame = FocusFrame(urwid.Filler(urwid.Text('')),urwid.Pile([self._buttons_cont,urwid.Divider(u"─")])) 1192 self.__frame = FocusFrame(urwid.Filler(urwid.Text('')),urwid.Pile([self._buttons_cont,urwid.Divider(u"─")]))
1192 urwid.WidgetWrap.__init__(self, self.__frame) 1193 urwid.WidgetWrap.__init__(self, self.__frame)
1193 1194
1194 def keypress(self, size, key): 1195 def keypress(self, size, key):
1195 if key=='tab':
1196 self._w.keypress(size,key)
1197 return
1198 return self._w.keypress(size,key) 1196 return self._w.keypress(size,key)
1199 1197
1200 def _buttonClicked(self, button, invisible=False): 1198 def _buttonClicked(self, button, invisible=False):
1201 """Called when a button on the tab is changed, 1199 """Called when a button on the tab is changed,
1202 change the page 1200 change the page