...
authorPierre Ratinaud <ratinaud@univ-tlse2.fr>
Fri, 18 Jul 2014 23:31:41 +0000 (01:31 +0200)
committerPierre Ratinaud <ratinaud@univ-tlse2.fr>
Fri, 18 Jul 2014 23:31:41 +0000 (01:31 +0200)
TODO [deleted file]
images/chi2.png [new file with mode: 0644]
images/frequences.png [new file with mode: 0644]
images/icone_chd.png [new file with mode: 0644]
images/matrix.png [new file with mode: 0644]
images/matroot.png [new file with mode: 0644]
images/reinertmatrix.png [new file with mode: 0644]
images/simimatrix.png [new file with mode: 0644]
textchdalc.py [deleted file]
vitemspicker.py [new file with mode: 0644]

diff --git a/TODO b/TODO
deleted file mode 100644 (file)
index 261804c..0000000
--- a/TODO
+++ /dev/null
@@ -1,13 +0,0 @@
-- système de template pour la présentation des résultats
-- traitement texte :
-    - méthode alceste (intégrer le temps et les personnes)
-- AFCM (mja et mjca)
-- système de configuration
-- anova
-- correlation
-- U de Mann Whitney
-- autres tests non paramétriques
-- regression linéaire ?
-- intégration avec openoffice
-
-
diff --git a/images/chi2.png b/images/chi2.png
new file mode 100644 (file)
index 0000000..cafcdd4
Binary files /dev/null and b/images/chi2.png differ
diff --git a/images/frequences.png b/images/frequences.png
new file mode 100644 (file)
index 0000000..802ab7a
Binary files /dev/null and b/images/frequences.png differ
diff --git a/images/icone_chd.png b/images/icone_chd.png
new file mode 100644 (file)
index 0000000..ea79d7e
Binary files /dev/null and b/images/icone_chd.png differ
diff --git a/images/matrix.png b/images/matrix.png
new file mode 100644 (file)
index 0000000..ddff27e
Binary files /dev/null and b/images/matrix.png differ
diff --git a/images/matroot.png b/images/matroot.png
new file mode 100644 (file)
index 0000000..45da44a
Binary files /dev/null and b/images/matroot.png differ
diff --git a/images/reinertmatrix.png b/images/reinertmatrix.png
new file mode 100644 (file)
index 0000000..af18db8
Binary files /dev/null and b/images/reinertmatrix.png differ
diff --git a/images/simimatrix.png b/images/simimatrix.png
new file mode 100644 (file)
index 0000000..3a2e3d6
Binary files /dev/null and b/images/simimatrix.png differ
diff --git a/textchdalc.py b/textchdalc.py
deleted file mode 100644 (file)
index 9e8b4ad..0000000
+++ /dev/null
@@ -1,299 +0,0 @@
-#!/bin/env python
-# -*- coding: utf-8 -*-
-#Author: Pierre Ratinaud
-#Copyright (c) 2008-2009 Pierre Ratinaud
-#Lisense: GNU/GPL
-
-from chemins import ConstructPathOut, ChdTxtPathOut
-from OptionAlceste import OptionAlc
-import wx
-import os
-from ConfigParser import RawConfigParser
-import sys
-from functions import sortedby, print_liste, CreateIraFile, exec_rcode, ReadDicoAsDico, check_Rresult
-from dialog import PrefGraph
-from layout import OpenCHDS, PrintRapport
-from PrintRScript import RchdTxt, AlcesteTxtProf
-from openanalyse import OpenAnalyse
-from corpus import Corpus
-from guifunct import getPage, getCorpus
-from time import time, sleep
-
-class AnalyseAlceste :
-    def __init__(self,parent, cmd = False, big = False):
-        self.conf = None
-        self.parent = parent
-        self.type = 'alceste'
-        self.cmd = cmd
-        self.big = big
-        #page = getPage(self.parent)
-        #if page is not None :
-        #    self.corpus = getCorpus(page)
-        #    print self.corpus.parametre
-        #else :
-        try :
-            self.corpus = Corpus(parent)
-            self.corpus.parametre['encodage'] = parent.corpus_encodage
-            self.corpus.parametre['lang'] = parent.corpus_lang
-            self.corpus.parametre['filename'] = parent.filename
-            self.ConfigPath = parent.ConfigPath
-            self.DictPath = parent.DictPath
-            self.AlcesteConf = RawConfigParser()
-            self.AlcesteConf.read(self.ConfigPath['alceste'])
-            self.KeyConf = RawConfigParser()
-            self.KeyConf.read(self.ConfigPath['key'])
-            if not cmd :
-                self.dial = OptionAlc(self, parent)
-                self.dial.CenterOnParent()
-                self.val = self.dial.ShowModal()
-                self.print_alceste_parametre()
-                self.dial.Destroy()
-            else :
-                self.val = wx.ID_OK
-            if self.val == wx.ID_OK :
-                pathout = ConstructPathOut(self.corpus.parametre['filename'], 'alceste')
-                self.dictpathout = ChdTxtPathOut(pathout)
-                self.read_alceste_parametre()
-                self.KeyConf.read(self.ConfigPath['key'])
-                self.corpus.supplementaires = [option for option in self.KeyConf.options('KEYS') if self.KeyConf.get('KEYS', option) == "2"]
-                self.corpus.typeactive = [option for option in self.KeyConf.options('KEYS') if self.KeyConf.get('KEYS', option) == "1"]
-                self.make_analyse()
-        except AttributeError :
-            wx.MessageBox(u'Vous devez charger un corpus\nFichier -> Ouvrir un texte', u'Pas de corpus', wx.OK|wx.ICON_INFORMATION)
-            self.val = False
-
-    def load_corpus(self):
-        self.corpus.read_formes()
-        self.corpus.read_lems()
-        self.corpus.read_ucis_paras_uces()
-        self.corpus.read_parametre()
-
-    def print_alceste_parametre(self): 
-        self.conf = RawConfigParser()
-        self.conf.read(self.parent.ConfigPath['alceste'])
-        lem = self.dial.radio_1.GetSelection()
-        expressions = self.dial.radio_exp.GetSelection()
-        if lem == 0 : lem = 'True'
-        else : lem = 'False'
-        if expressions == 0 : expressions = 'True'
-        else : expressions = 'False'
-        self.AlcesteConf.set('ALCESTE','lem',lem)
-        self.AlcesteConf.set('ALCESTE', 'expressions', expressions)
-        self.AlcesteConf.set('ALCESTE', 'classif_mode', str(self.dial.radio_box_2.GetSelection()))
-        self.AlcesteConf.set('ALCESTE', 'tailleuc1', str(self.dial.spin_ctrl_1.GetValue()))
-        self.AlcesteConf.set('ALCESTE', 'tailleuc2', str(self.dial.spin_ctrl_2.GetValue()))
-        self.AlcesteConf.set('ALCESTE', 'nbforme_uce', str(self.dial.spin_ctrl_3.GetValue()))
-        self.AlcesteConf.set('ALCESTE', 'mincl', str(self.dial.spin_ctrl_4.GetValue()))
-        self.AlcesteConf.set('ALCESTE', 'minforme', str(self.dial.spin_ctrl_5.GetValue()))
-        self.AlcesteConf.set('ALCESTE', 'nbcl_p1', str(self.dial.spin_nbcl.GetValue()))
-        self.AlcesteConf.set('ALCESTE', 'max_actives', str(self.dial.spin_max_actives.GetValue()))
-        with open(self.parent.ConfigPath['alceste'], 'w') as f:
-            self.AlcesteConf.write(f)
-        with open(self.parent.ConfigPath['key'], 'w') as f:
-            self.KeyConf.write(f)
-    
-    def read_alceste_parametre(self) :
-        self.conf = RawConfigParser()
-        self.conf.read(self.parent.ConfigPath['alceste'])
-        for option in self.conf.options('ALCESTE') :
-            if self.conf.get('ALCESTE', option).isdigit() :
-                self.corpus.parametre[option] = int(self.conf.get('ALCESTE', option))
-            else :
-                self.corpus.parametre[option] = self.conf.get('ALCESTE', option)
-            
-        list_bool = ['lem', 'expressions']
-        for var in list_bool :
-            if self.corpus.parametre[var] == 'True' :
-                self.corpus.parametre[var] = True
-            else : 
-                self.corpus.parametre[var] = False
-
-    def make_analyse(self) :
-        t1 = time()
-        if not self.big :
-            self.corpus.content = self.parent.content
-            if not self.cmd :
-                self.dlg = wx.ProgressDialog("Traitements",
-                                             "Veuillez patienter...",
-                                             maximum=9,
-                                             parent=self.parent,
-                                             style=wx.PD_APP_MODAL | wx.PD_AUTO_HIDE | wx.PD_ELAPSED_TIME | wx.PD_CAN_ABORT
-                                             )
-                self.dlg.Center()
-            else :
-                self.dlg = None
-            ucis_txt, ucis_paras_txt = self.corpus.start_analyse(self.parent, dlg = self.dlg, cmd = self.cmd) 
-    #        #print('ATTENTION PHRASE')
-    #        #ucis_paras_txt = self.corpus.make_ucis_paras_txt_phrases(para_coords, ucis_lines, ucis_txt)
-    #        del ucis_lines
-    
-            #FIXME
-            self.corpus.make_len_uce(self.corpus.get_tot_occ_from_ucis_txt(ucis_txt))
-            del ucis_txt
-            
-            if not self.cmd :
-                self.dlg.Update(5, '%i ucis - Construction des uces' % len(self.corpus.ucis))
-    
-            if self.corpus.parametre['classif_mode'] in [0,1] :
-                self.corpus.make_ucis_paras_uces(ucis_paras_txt, make_uce = True)
-                #self.corpus.make_ucis_paras_uces_sentences(ucis_paras_txt, make_uce = True)
-            else :
-                self.corpus.make_ucis_paras_uces(ucis_paras_txt, make_uce = False)
-            del ucis_paras_txt
-    
-            print 'len(ucis_paras_uces', len(self.corpus.ucis_paras_uces)
-            
-            if not self.cmd :
-                self.dlg.Update(6, u'Dictionnaires')
-            uces, orderuces = self.corpus.make_forms_and_uces()
-    
-            print len(uces)
-            print len(orderuces)
-            self.corpus.ucenb = len(uces)
-            print 'len(uces)',len(uces)
-            #ucis_paras_uces_lems = self.corpus.make_ucis_paras_uces_lems(lexique)
-            self.corpus.make_lems(self.parent.lexique)
-            
-            #----------------------------------------------
-            #self.corpus.make_eff_min_forme()
-            #self.corpus.parametre['max_actives'] = 1500
-            self.corpus.min_eff_formes()
-            #----------------------------------------------
-    
-            self.corpus.make_var_actives() 
-    
-            self.corpus.make_var_supp()
-            
-            if not self.cmd :
-                self.dlg.Update(7, u'Creation des tableaux')
-            if self.corpus.parametre['classif_mode'] == 1 :
-                #tabuc1 = self.corpus.make_sparse_matrix_with_uce(orderuces)
-                #self.corpus.write_sparse_matrix(self.dictpathout['TableUc1'], tabuc1, len(orderuces), len(self.corpus.actives))
-                #print time() - tps1
-                #tps2 = time()
-                self.corpus.make_and_write_sparse_matrix_from_uce(orderuces, self.dictpathout['TableUc1'])
-                #print time() - tps2
-    
-                #tabuc1 = self.corpus.make_table_with_uce(orderuces)
-                uc1 = None
-                uces1 = [[uce, orderuces[uce]] for uce in orderuces]
-                uces1 = sortedby(uces1, 1)
-                self.corpus.lenuc1 = len(uces1)
-                #uces1.sort()
-                self.corpus.write_tab([[u'uce',u'uc']] + [[i, i] for i in range(0,len(uces))], self.dictpathout['listeuce1'])
-            elif  self.corpus.parametre['classif_mode'] == 0 :
-                self.corpus.lenuc1, uces_uc1 = self.corpus.make_uc(uces, orderuces, self.corpus.parametre['tailleuc1'])
-                print 'len uc1 : ', self.corpus.lenuc1
-                uces1 = [[uce,uces_uc1[uce]] for uce in orderuces]
-                uces1 = sortedby(uces1, 1)
-                self.corpus.write_tab([[u'uce',u'uc']] + [[i, val[1]] for i, val in enumerate(uces1)], self.dictpathout['listeuce1'])
-                #tabuc1 = self.corpus.make_tab_uc(uces_uc1, uc1)
-                self.corpus.make_and_write_sparse_matrix_from_uc(uces_uc1, self.dictpathout['TableUc1'])
-            elif self.corpus.parametre['classif_mode'] == 2 :
-                #tabuc1 = self.corpus.make_table_with_uci()
-                self.corpus.make_and_write_sparse_matrix_from_uci(self.dictpathout['TableUc1'])
-                uc1 = None
-                uces1 = [[uce, orderuces[uce]] for uce in orderuces]
-                uces1 = sortedby(uces1, 1)
-                self.corpus.lenuc1 = len(uces1)
-                self.corpus.write_tab([[u'uce',u'uc']] + [[i, i] for i in range(0,len(orderuces))], self.dictpathout['listeuce1'])
-    
-            #self.corpus.write_sparse_matrix(self.dictpathout['TableUc1'], tabuc1, len(orderuces), len(self.corpus.actives))
-            #self.corpus.write_tab(tabuc1,self.dictpathout['TableUc1'])
-    
-            if self.corpus.parametre['classif_mode'] == 0 : 
-                self.corpus.lenuc2, uces_uc2 = self.corpus.make_uc(uces, orderuces, self.corpus.parametre['tailleuc2'])
-                print 'len uc2 :', self.corpus.lenuc2
-                #tabuc2 = self.corpus.make_tab_uc(uces_uc2, uc2)
-                self.corpus.make_and_write_sparse_matrix_from_uc(uces_uc2, self.dictpathout['TableUc2'])            
-                #self.corpus.write_tab(tabuc2, self.dictpathout['TableUc2'])
-                uces2 = [[uce, uces_uc2[uce]] for uce in orderuces]
-                uces2 = sortedby(uces2, 1)
-                self.corpus.write_tab([[u'uce',u'uc']] + [[i, val[1]] for i, val in enumerate(uces2)], self.dictpathout['listeuce2'])
-            
-            if sys.platform == 'win32' :
-                try :
-                    if self.parent.pref.getboolean('iramuteq', 'R_mem') :
-                        R_max_mem = self.parent.pref.getint('iramuteq','R_max_mem')
-                    else :
-                        R_max_mem = False
-                except :
-                    R_max_mem = False
-            else :
-                R_max_mem = False
-            RchdTxt(self.dictpathout, self.parent.RscriptsPath, self.corpus.parametre['mincl'], self.corpus.parametre['classif_mode'], nbt = self.corpus.parametre['nbcl_p1'] - 1, libsvdc = self.parent.pref.getboolean('iramuteq','libsvdc'), libsvdc_path = self.parent.pref.get('iramuteq','libsvdc_path'), R_max_mem = R_max_mem)
-            
-            pid = exec_rcode(self.parent.RPath,self.dictpathout['Rchdtxt'],wait = False)
-            while pid.poll() == None :
-                if not self.cmd :
-                    self.dlg.Pulse(u'CHD...')
-                    sleep(0.2)
-                else :
-                    sleep(0.2)
-            check_Rresult(self.parent, pid)
-            if not self.cmd : 
-                self.dlg.Update(7, u'Profils')
-            ucecl = self.corpus.read_uce_from_R(self.dictpathout['uce'])
-            ucecl0 = [cl for uce,cl in ucecl if cl != 0]
-            clnb = len(list(set(ucecl0)))
-            classes = [cl for uce, cl in ucecl]
-            uces1 = [val for val, i in uces1]
-            
-            self.corpus.make_lc(uces1, classes, clnb)
-            self.corpus.build_profile(clnb, classes, self.corpus.actives, self.dictpathout['Contout']) 
-            
-            #passives = [lem for lem in self.corpus.lems if lem not in self.corpus.actives]
-            self.corpus.build_profile(clnb, classes, self.corpus.supp, self.dictpathout['ContSupOut'])
-            
-            self.corpus.make_etoiles(self.corpus.para_coords)
-    
-            self.corpus.build_profile_et(clnb, classes, uces1, self.dictpathout['ContEtOut'])
-            
-            AlcesteTxtProf(self.dictpathout, self.parent.RscriptsPath, clnb, '0.9')
-            
-            pid = exec_rcode(self.parent.RPath, self.dictpathout['RTxtProfGraph'],wait = False)
-            while pid.poll() == None :
-                if not self.cmd :
-                    self.dlg.Pulse(u'AFC...')
-                    sleep(0.2)
-                else :
-                    pass
-            check_Rresult(self.parent, pid)
-            
-            self.corpus.dictpathout = self.dictpathout
-            
-            if not self.cmd :
-                self.dlg.Update(8, u'rapport')
-    
-            temps = time() - t1
-            self.corpus.minutes, self.corpus.seconds = divmod(temps, 60)
-            self.corpus.hours, self.corpus.minutes = divmod(self.corpus.minutes, 60)        
-    
-            PrintRapport(self.corpus, 'txt')
-            
-            CreateIraFile(self.dictpathout, clnb, os.path.basename(self.corpus.parametre['filename']))
-            
-            self.corpus.save_corpus(self.dictpathout['db'])
-     
-            afc_graph_list = [[os.path.basename(self.dictpathout['AFC2DL_OUT']), u'Variables actives - coordonnées - facteurs 1 / 2'],
-                          [os.path.basename(self.dictpathout['AFC2DSL_OUT']), u'variables supplémentaires - coordonnées - facteurs 1 / 2'],
-                          [os.path.basename(self.dictpathout['AFC2DEL_OUT']), u'Variables illustratives - Coordonnées - facteur 1 / 2'],
-                          [os.path.basename(self.dictpathout['AFC2DCL_OUT']), u'Classes - Coordonnées - facteur 1 / 2'],
-                          [os.path.basename(self.dictpathout['AFC2DCoul']), u'Variables actives - Corrélation - facteur 1 / 2'],
-                          [os.path.basename(self.dictpathout['AFC2DCoulSup']), u'Variables supplémentaires - Corrélation - facteur 1 / 2'],
-                          [os.path.basename(self.dictpathout['AFC2DCoulEt']), u'Variables illustratives - Corrélations - facteur 1 / 2'],
-                          [os.path.basename(self.dictpathout['AFC2DCoulCl']), u'Classes - Corrélations - facteurs 1 / 2'],]
-            chd_graph_list = [[os.path.basename(self.dictpathout['dendro1']), u'dendrogramme à partir de chd1']]
-            if self.corpus.parametre['classif_mode'] == 0 :
-                chd_graph_list.append([os.path.basename(self.dictpathout['dendro2']), u'dendrogramme à partir de chd2'])
-            chd_graph_list.append([os.path.basename(self.dictpathout['arbre1']), u'chd1'])
-            if self.corpus.parametre['classif_mode'] == 0 :
-                chd_graph_list.append([os.path.basename(self.dictpathout['arbre2']), u'chd2'])
-            print_liste(self.dictpathout['liste_graph_afc'],afc_graph_list)
-            print_liste(self.dictpathout['liste_graph_chd'],chd_graph_list)
-            if not self.cmd :
-                self.dlg.Update(9, u'fin')
-                self.dlg.Destroy()
-                OpenAnalyse(self.parent, self.dictpathout['ira'])  
-        else :
-            self.corpus.make_big()
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