...
[iramuteq] / vitemspicker.py
diff --git a/vitemspicker.py b/vitemspicker.py
new file mode 100644 (file)
index 0000000..d385210
--- /dev/null
@@ -0,0 +1,267 @@
+'''
+Created on Oct 3, 2010
+
+@authors: Daphna Rosenbom,Gitty Zinger,Moshe Cohavi and Yoav Glazner
+The widget is contributed by NDS ltd under the same license as wxPython
+
+items_picker.ItemsPicker:
+- Displays available items to choose from,</LI>
+- Selection is done by the Add button or Double Click,</LI>
+- De-Selection is done by the Remove button or Double Click,</LI>
+
+Derived from wxPanel
+'''
+import wx
+from listlex import ListForSpec
+__version__ = 0.1
+
+IP_DEFAULT_STYLE = 0
+IP_SORT_CHOICES = 1
+IP_SORT_SELECTED = 2
+IP_REMOVE_FROM_CHOICES = 4
+
+
+wxEVT_IP_SELECTION_CHANGED = wx.NewEventType()
+EVT_IP_SELECTION_CHANGED = wx.PyEventBinder(wxEVT_IP_SELECTION_CHANGED, 1)
+LB_STYLE = wx.LB_EXTENDED|wx.LB_HSCROLL
+
+
+class IpSelectionChanged(wx.PyCommandEvent):
+    def __init__(self, id, items, object = None):
+        wx.PyCommandEvent.__init__(self, wxEVT_IP_SELECTION_CHANGED, id)
+        self.__items = items
+        self.SetEventObject(object)
+
+    def GetItems(self):
+        return self.__items
+
+
+class VItemsPicker(wx.Panel):
+    '''
+ItemsPicker is a widget that allows the user to form a set of picked
+items out of a given list
+'''
+    def __init__(self, parent, id=wx.ID_ANY, choices = [],
+                 label = '', selectedLabel = '',
+                 ipStyle = IP_DEFAULT_STYLE,
+                 *args, **kw):
+        '''
+ItemsPicker(parent, choices = [], label = '', selectedLabel = '',
+ipStyle = IP_DEFAULT_STYLE)
+'''
+        self.parent = parent
+        self._destData = {}
+        wx.Panel.__init__(self, parent, id, *args, **kw)
+        self._ipStyle = ipStyle
+        sizer = wx.BoxSizer(wx.HORIZONTAL)
+        sizer.Add(self._CreateSourceList(choices, label), 1,
+                   wx.EXPAND|wx.ALL, 5)
+        sizer.Add(self._CreateButtons(), 0, wx.ALIGN_CENTER|wx.ALL, 5)
+        sizer.Add(self._CreateDestList(selectedLabel), 1,
+                   wx.EXPAND|wx.ALL, 5)
+        self.SetSizer(sizer)
+        
+        
+    def SetItems(self, items):
+        '''SetItems(self, items)=> None
+items - Sequence of strings that the user can pick from'''
+        pass
+        #return self._source.SetItems(items)
+    
+    
+    def GetItems(self):
+        '''GetItems(self)=> items
+returns list of strings that the user can pick from'''
+        return self._source.GetItems()
+    
+    
+    Items = property(fget = GetItems,
+                     fset = SetItems,
+                     doc = 'See GetItems/SetItems')
+    
+     
+    def GetSelections(self):
+        '''GetSelections(self)=>items
+returns list of strings that were selected
+'''
+        return [self._destData[i][0] for i in self._destData]
+    
+    
+    def SetSelections(self, items):
+        '''SetSelections(self, items)=>None
+items - Sequence of strings to be selected
+The items are displayed in the selection part of the widget'''
+        assert len(items)==len(set(items)),"duplicate items are not allowed"
+        if items != self._dest.GetItems():
+            self._dest.SetItems(items)
+            self._FireIpSelectionChanged()
+    
+        
+    Selections = property(fget = GetSelections,
+                     fset = SetSelections,
+                     doc = 'See GetSelections/SetSelections')
+    
+    
+    def _CreateButtons(self):
+        sizer = wx.BoxSizer(wx.VERTICAL)
+        self.bAdd = wx.Button(self, -1, label = 'Add ->')
+        self.bAdd.Bind(wx.EVT_BUTTON, self._OnAdd)
+        self.bRemove = wx.Button(self, -1, label = '<- Remove')
+        self.bRemove.Bind(wx.EVT_BUTTON, self._OnRemove)
+        sizer.Add(self.bAdd, 0, wx.EXPAND|wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5)
+        sizer.Add(self.bRemove, 0, wx.EXPAND|wx.ALL, 5)
+        return sizer
+    
+    
+    def _set_add_button_label(self, label=None):
+        if label is None:
+            return
+        self.bAdd.SetLabel(label)
+    
+    add_button_label = property(fset = _set_add_button_label, fget = lambda x:x)
+    
+    
+    def _set_remove_button_label(self, label=None):
+        if label is None:
+            return
+        self.bRemove.SetLabel(label)
+    
+    remove_button_label = property(fset = _set_remove_button_label, fget = lambda x:x)
+    
+    
+    def _OnAdd(self, e):
+        if self._ipStyle & IP_REMOVE_FROM_CHOICES:
+            self._MoveItems(self._source,self._dest)
+        else:
+            self._AddSelectedItems()
+            
+    def _MoveItems(self,source,dest):
+        selections = source.GetSelections()
+        selectedItems = map(source.GetString, selections)
+        dest.SetItems(dest.GetItems() + selectedItems)
+        selections = set(selections)
+        #source.SetItems([item for i, item in enumerate(source.GetItems())\
+        #              if i not in selections])
+        self._FireIpSelectionChanged()
+            
+    def _AddSelectedItems(self):
+        newItems = self._source.getselectedwords()#map(self._source.GetString, self._source.GetSelections())
+        items = [self._destData[i][0] for i in self._destData]
+        oldItems = set(items)
+        for newItem in newItems:
+            if newItem not in oldItems:
+                self._destData[len(self._destData)] = [newItem, '']
+                self._SetDestItems()
+                self._source.selected[newItem] = 1
+                self._source.Refresh()
+        #self.SetSelections(items)
+        self._FireIpSelectionChanged()
+    
+    def _FireIpSelectionChanged(self):
+            self.GetEventHandler().ProcessEvent(
+                        IpSelectionChanged(self.GetId(),
+                                            None,
+                                             self ))
+        
+            
+    def _OnRemove(self, e):
+        if self._ipStyle & IP_REMOVE_FROM_CHOICES:
+            self._MoveItems(self._dest, self._source)
+        else:
+            self._RemoveSelected()
+    
+    def _RemoveSelected(self):
+        selections = self._dest.getselectedwords()
+        if selections:
+            #allItems = self._dest.GetItems()
+            #items = [item for i, item in enumerate(allItems)\
+            #          if i not in selections]
+            #notselected = [item for i, item in enumerate(allItems)\
+            #          if i in selections]
+            
+            for item in selections :
+                del self._source.selected[item]
+            tokeep = [self._destData[i][0] for i in self._destData if self._destData[i][0] not in selections]
+            self._destData = dict([[i, [word, '']] for i, word in enumerate(tokeep)])
+            self._source.Refresh()
+            self._SetDestItems()
+            #self.SetSelections(items)
+            self._FireIpSelectionChanged()
+       
+        
+    def _CreateSourceList(self, items, label):
+        style = LB_STYLE
+        if self._ipStyle & IP_SORT_CHOICES:
+            style |= wx.LB_SORT
+        sizer = wx.BoxSizer(wx.VERTICAL)
+        if label:
+            sizer.Add(wx.StaticText(self, label = label), 0,
+                       wx.ALIGN_LEFT|wx.ALL, 5)
+        #self._source = wx.VListBox(self, -1, style = style)
+        self._source = ListForSpec(self, self.parent, dlist = items, first = ['eff'], menu = True)
+        self._source.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self._OnDClick)
+        #self._source.Bind(wx.EVT_LISTBOX_DCLICK, self._OnDClick)
+        #self._source.SetItems(items)
+        sizer.Add(self._source, 1, wx.EXPAND|wx.ALL, 5)
+        return sizer
+    
+    
+    def _CreateDestList(self, label):
+        style = LB_STYLE
+        if self._ipStyle & IP_SORT_SELECTED:
+            style |= wx.LB_SORT
+        sizer = wx.BoxSizer(wx.VERTICAL)
+        if label:
+            sizer.Add(wx.StaticText(self, label = label), 0,
+                       wx.ALIGN_LEFT|wx.ALL, 5)
+        #self._dest = wx.ListBox(self, -1, style = style)
+        self._dest = ListForSpec(self, self.parent, dlist = {}, first = ['eff'], menu = True)
+        self._dest.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self._OnDClick)
+        #self._dest.Bind(wx.EVT_LISTBOX_DCLICK, self._OnDClick)
+        sizer.Add(self._dest, 1, wx.EXPAND|wx.ALL, 5)
+        return sizer
+    
+    def _SetDestItems(self):
+        self._dest.itemDataMap = self._destData
+        self._dest.itemIndexMap = self._destData.keys()
+        self._dest.SetItemCount(len(self._destData))
+        self._dest.Refresh()
+        
+    def _OnDClick(self, e):
+        lb = e.GetEventObject()
+        selections = lb.GetSelections()
+        if len(selections) != 1:
+            return #DCLICK only works on one item
+        #if e.GetSelection() != selections[0]:
+            #this can happen using ^DCLICK when two items are selected
+        #    return
+        if lb == self._source:
+            self._OnAdd(e)
+        else:
+            self._OnRemove(e)
+
+
+        
+
+if __name__ == '__main__':
+    print 'ezerzerzer'
+    test = wx.App(0)
+    frame = wx.Frame(None, -1)
+    d = wx.Dialog(frame, style = wx.RESIZE_BORDER|wx.DEFAULT_DIALOG_STYLE)
+    
+    d.sizer = wx.BoxSizer(wx.VERTICAL)
+    d.sizer.Add(wx.StaticText(d, -1, label = 'Example of the ItemsPicker'),
+                 0, wx.ALL, 10)
+    ip = ItemsPicker(d, -1, ['pop', 'cool', 'lame'],
+                      'Stuff:', 'Selected stuff:',IP_SORT_SELECTED|IP_SORT_CHOICES|IP_REMOVE_FROM_CHOICES)
+    ip.add_button_label = u'left -> right'
+    ip.remove_button_label = u'right -> left'
+    d.sizer.Add(ip, 1, wx.EXPAND, 1)
+    d.SetSizer(d.sizer)
+    test.SetTopWindow(frame)
+    def callback(e):
+        print 'selected items', e.GetItems()
+    d.Bind(EVT_IP_SELECTION_CHANGED, callback)
+    d.ShowModal()
+    d.Destroy()
+    frame.Close()
\ No newline at end of file