...
[iramuteq] / vitemspicker.py
1 '''
2 Created on Oct 3, 2010
3
4 @authors: Daphna Rosenbom,Gitty Zinger,Moshe Cohavi and Yoav Glazner
5 The widget is contributed by NDS ltd under the same license as wxPython
6
7 items_picker.ItemsPicker:
8 - Displays available items to choose from,</LI>
9 - Selection is done by the Add button or Double Click,</LI>
10 - De-Selection is done by the Remove button or Double Click,</LI>
11
12 Derived from wxPanel
13 '''
14 import wx
15 from listlex import ListForSpec
16 __version__ = 0.1
17
18 IP_DEFAULT_STYLE = 0
19 IP_SORT_CHOICES = 1
20 IP_SORT_SELECTED = 2
21 IP_REMOVE_FROM_CHOICES = 4
22
23
24 wxEVT_IP_SELECTION_CHANGED = wx.NewEventType()
25 EVT_IP_SELECTION_CHANGED = wx.PyEventBinder(wxEVT_IP_SELECTION_CHANGED, 1)
26 LB_STYLE = wx.LB_EXTENDED|wx.LB_HSCROLL
27
28
29 class IpSelectionChanged(wx.PyCommandEvent):
30     def __init__(self, id, items, object = None):
31         wx.PyCommandEvent.__init__(self, wxEVT_IP_SELECTION_CHANGED, id)
32         self.__items = items
33         self.SetEventObject(object)
34
35     def GetItems(self):
36         return self.__items
37
38
39 class VItemsPicker(wx.Panel):
40     '''
41 ItemsPicker is a widget that allows the user to form a set of picked
42 items out of a given list
43 '''
44     def __init__(self, parent, id=wx.ID_ANY, choices = [],
45                  label = '', selectedLabel = '',
46                  ipStyle = IP_DEFAULT_STYLE,
47                  *args, **kw):
48         '''
49 ItemsPicker(parent, choices = [], label = '', selectedLabel = '',
50 ipStyle = IP_DEFAULT_STYLE)
51 '''
52         self.parent = parent
53         self._destData = {}
54         wx.Panel.__init__(self, parent, id, *args, **kw)
55         self._ipStyle = ipStyle
56         sizer = wx.BoxSizer(wx.HORIZONTAL)
57         sizer.Add(self._CreateSourceList(choices, label), 1,
58                    wx.EXPAND|wx.ALL, 5)
59         sizer.Add(self._CreateButtons(), 0, wx.ALIGN_CENTER|wx.ALL, 5)
60         sizer.Add(self._CreateDestList(selectedLabel), 1,
61                    wx.EXPAND|wx.ALL, 5)
62         self.SetSizer(sizer)
63         
64         
65     def SetItems(self, items):
66         '''SetItems(self, items)=> None
67 items - Sequence of strings that the user can pick from'''
68         pass
69         #return self._source.SetItems(items)
70     
71     
72     def GetItems(self):
73         '''GetItems(self)=> items
74 returns list of strings that the user can pick from'''
75         return self._source.GetItems()
76     
77     
78     Items = property(fget = GetItems,
79                      fset = SetItems,
80                      doc = 'See GetItems/SetItems')
81     
82      
83     def GetSelections(self):
84         '''GetSelections(self)=>items
85 returns list of strings that were selected
86 '''
87         return [self._destData[i][0] for i in self._destData]
88     
89     
90     def SetSelections(self, items):
91         '''SetSelections(self, items)=>None
92 items - Sequence of strings to be selected
93 The items are displayed in the selection part of the widget'''
94         assert len(items)==len(set(items)),"duplicate items are not allowed"
95         if items != self._dest.GetItems():
96             self._dest.SetItems(items)
97             self._FireIpSelectionChanged()
98     
99         
100     Selections = property(fget = GetSelections,
101                      fset = SetSelections,
102                      doc = 'See GetSelections/SetSelections')
103     
104     
105     def _CreateButtons(self):
106         sizer = wx.BoxSizer(wx.VERTICAL)
107         self.bAdd = wx.Button(self, -1, label = 'Add ->')
108         self.bAdd.Bind(wx.EVT_BUTTON, self._OnAdd)
109         self.bRemove = wx.Button(self, -1, label = '<- Remove')
110         self.bRemove.Bind(wx.EVT_BUTTON, self._OnRemove)
111         sizer.Add(self.bAdd, 0, wx.EXPAND|wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5)
112         sizer.Add(self.bRemove, 0, wx.EXPAND|wx.ALL, 5)
113         return sizer
114     
115     
116     def _set_add_button_label(self, label=None):
117         if label is None:
118             return
119         self.bAdd.SetLabel(label)
120     
121     add_button_label = property(fset = _set_add_button_label, fget = lambda x:x)
122     
123     
124     def _set_remove_button_label(self, label=None):
125         if label is None:
126             return
127         self.bRemove.SetLabel(label)
128     
129     remove_button_label = property(fset = _set_remove_button_label, fget = lambda x:x)
130     
131     
132     def _OnAdd(self, e):
133         if self._ipStyle & IP_REMOVE_FROM_CHOICES:
134             self._MoveItems(self._source,self._dest)
135         else:
136             self._AddSelectedItems()
137             
138     def _MoveItems(self,source,dest):
139         selections = source.GetSelections()
140         selectedItems = map(source.GetString, selections)
141         dest.SetItems(dest.GetItems() + selectedItems)
142         selections = set(selections)
143         #source.SetItems([item for i, item in enumerate(source.GetItems())\
144         #              if i not in selections])
145         self._FireIpSelectionChanged()
146             
147     def _AddSelectedItems(self):
148         newItems = self._source.getselectedwords()#map(self._source.GetString, self._source.GetSelections())
149         items = [self._destData[i][0] for i in self._destData]
150         oldItems = set(items)
151         for newItem in newItems:
152             if newItem not in oldItems:
153                 self._destData[len(self._destData)] = [newItem, '']
154                 self._SetDestItems()
155                 self._source.selected[newItem] = 1
156                 self._source.Refresh()
157         #self.SetSelections(items)
158         self._FireIpSelectionChanged()
159     
160     def _FireIpSelectionChanged(self):
161             self.GetEventHandler().ProcessEvent(
162                         IpSelectionChanged(self.GetId(),
163                                             None,
164                                              self ))
165         
166             
167     def _OnRemove(self, e):
168         if self._ipStyle & IP_REMOVE_FROM_CHOICES:
169             self._MoveItems(self._dest, self._source)
170         else:
171             self._RemoveSelected()
172     
173     def _RemoveSelected(self):
174         selections = self._dest.getselectedwords()
175         if selections:
176             #allItems = self._dest.GetItems()
177             #items = [item for i, item in enumerate(allItems)\
178             #          if i not in selections]
179             #notselected = [item for i, item in enumerate(allItems)\
180             #          if i in selections]
181             
182             for item in selections :
183                 del self._source.selected[item]
184             tokeep = [self._destData[i][0] for i in self._destData if self._destData[i][0] not in selections]
185             self._destData = dict([[i, [word, '']] for i, word in enumerate(tokeep)])
186             self._source.Refresh()
187             self._SetDestItems()
188             #self.SetSelections(items)
189             self._FireIpSelectionChanged()
190        
191         
192     def _CreateSourceList(self, items, label):
193         style = LB_STYLE
194         if self._ipStyle & IP_SORT_CHOICES:
195             style |= wx.LB_SORT
196         sizer = wx.BoxSizer(wx.VERTICAL)
197         if label:
198             sizer.Add(wx.StaticText(self, label = label), 0,
199                        wx.ALIGN_LEFT|wx.ALL, 5)
200         #self._source = wx.VListBox(self, -1, style = style)
201         self._source = ListForSpec(self, self.parent, dlist = items, first = ['eff'], menu = True)
202         self._source.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self._OnDClick)
203         #self._source.Bind(wx.EVT_LISTBOX_DCLICK, self._OnDClick)
204         #self._source.SetItems(items)
205         sizer.Add(self._source, 1, wx.EXPAND|wx.ALL, 5)
206         return sizer
207     
208     
209     def _CreateDestList(self, label):
210         style = LB_STYLE
211         if self._ipStyle & IP_SORT_SELECTED:
212             style |= wx.LB_SORT
213         sizer = wx.BoxSizer(wx.VERTICAL)
214         if label:
215             sizer.Add(wx.StaticText(self, label = label), 0,
216                        wx.ALIGN_LEFT|wx.ALL, 5)
217         #self._dest = wx.ListBox(self, -1, style = style)
218         self._dest = ListForSpec(self, self.parent, dlist = {}, first = ['eff'], menu = True)
219         self._dest.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self._OnDClick)
220         #self._dest.Bind(wx.EVT_LISTBOX_DCLICK, self._OnDClick)
221         sizer.Add(self._dest, 1, wx.EXPAND|wx.ALL, 5)
222         return sizer
223     
224     def _SetDestItems(self):
225         self._dest.itemDataMap = self._destData
226         self._dest.itemIndexMap = self._destData.keys()
227         self._dest.SetItemCount(len(self._destData))
228         self._dest.Refresh()
229         
230     def _OnDClick(self, e):
231         lb = e.GetEventObject()
232         selections = lb.GetSelections()
233         if len(selections) != 1:
234             return #DCLICK only works on one item
235         #if e.GetSelection() != selections[0]:
236             #this can happen using ^DCLICK when two items are selected
237         #    return
238         if lb == self._source:
239             self._OnAdd(e)
240         else:
241             self._OnRemove(e)
242
243
244         
245
246 if __name__ == '__main__':
247     print 'ezerzerzer'
248     test = wx.App(0)
249     frame = wx.Frame(None, -1)
250     d = wx.Dialog(frame, style = wx.RESIZE_BORDER|wx.DEFAULT_DIALOG_STYLE)
251     
252     d.sizer = wx.BoxSizer(wx.VERTICAL)
253     d.sizer.Add(wx.StaticText(d, -1, label = 'Example of the ItemsPicker'),
254                  0, wx.ALL, 10)
255     ip = ItemsPicker(d, -1, ['pop', 'cool', 'lame'],
256                       'Stuff:', 'Selected stuff:',IP_SORT_SELECTED|IP_SORT_CHOICES|IP_REMOVE_FROM_CHOICES)
257     ip.add_button_label = u'left -> right'
258     ip.remove_button_label = u'right -> left'
259     d.sizer.Add(ip, 1, wx.EXPAND, 1)
260     d.SetSizer(d.sizer)
261     test.SetTopWindow(frame)
262     def callback(e):
263         print 'selected items', e.GetItems()
264     d.Bind(EVT_IP_SELECTION_CHANGED, callback)
265     d.ShowModal()
266     d.Destroy()
267     frame.Close()