mirror of
https://github.com/Sneed-Group/Poodletooth-iLand
synced 2024-12-27 05:32:41 -06:00
255 lines
8.4 KiB
Python
255 lines
8.4 KiB
Python
#----------------------------------------------------------------------------
|
|
# Name: itemspicker.py
|
|
# Purpose:
|
|
#
|
|
# Author: Daphna Rosenbom, Gitty Zinger, Moshe Cohavi and Yoav Glazner
|
|
#
|
|
# Created: Oct 3, 2010
|
|
# Version:
|
|
# Date:
|
|
# Licence: wxPython license
|
|
# Tags: phoenix-port
|
|
#----------------------------------------------------------------------------
|
|
'''
|
|
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
|
|
__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 ItemsPicker(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)
|
|
'''
|
|
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'''
|
|
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._dest.GetItems()
|
|
|
|
|
|
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 = list(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 = list(map(self._source.GetString, self._source.GetSelections()))
|
|
items = self._dest.GetItems()
|
|
oldItems = set(items)
|
|
for newItem in newItems:
|
|
if newItem not in oldItems:
|
|
items.append(newItem)
|
|
self.SetSelections(items)
|
|
|
|
|
|
def _FireIpSelectionChanged(self):
|
|
self.GetEventHandler().ProcessEvent(
|
|
IpSelectionChanged(self.GetId(),
|
|
self._dest.GetItems(),
|
|
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.GetSelections()
|
|
if selections:
|
|
allItems = self._dest.GetItems()
|
|
items = [item for i, item in enumerate(allItems)\
|
|
if i not in selections]
|
|
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.ListBox(self, -1, style = style)
|
|
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.Bind(wx.EVT_LISTBOX_DCLICK, self._OnDClick)
|
|
sizer.Add(self._dest, 1, wx.EXPAND|wx.ALL, 5)
|
|
return sizer
|
|
|
|
|
|
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__':
|
|
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()
|
|
|
|
|