/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/UI/classgen.py
ViewVC logotype

Diff of /branches/WIP-pyshapelib-bramz/Thuban/UI/classgen.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 629 by jonathan, Wed Apr 9 10:09:44 2003 UTC revision 1341 by jonathan, Tue Jul 1 16:10:42 2003 UTC
# Line 5  Line 5 
5  # This program is free software under the GPL (>=v2)  # This program is free software under the GPL (>=v2)
6  # Read the file COPYING coming with Thuban for details.  # Read the file COPYING coming with Thuban for details.
7    
8    import sys
9    
10  from Thuban import _  from Thuban import _
11    
12  from wxPython.wx import *  from wxPython.wx import *
13    
14  from Thuban.Model.classification import Classification, ClassGroupRange, \  from Thuban.Model.classification import ClassGroupProperties
     ClassGroupSingleton, ClassGroupProperties  
15    
16  from Thuban.Model.table import Table, FIELDTYPE_INT, FIELDTYPE_DOUBLE, \  from Thuban.Model.table import FIELDTYPE_INT, FIELDTYPE_DOUBLE, \
17       FIELDTYPE_STRING       FIELDTYPE_STRING
18    
19  from Thuban.Model.color import Color  from Thuban.Model.range import Range
20    from Thuban.UI.common import ThubanBeginBusyCursor, ThubanEndBusyCursor
 import classifier  
21    
22  from Thuban.common import Str2Num  import classifier, resource
23    
24  ID_CLASSGEN_GEN = 4001  from Thuban.Model.classgen import \
25  ID_CLASSGEN_CLOSE = 4002      generate_uniform_distribution, generate_singletons, generate_quantiles, \
26  ID_CLASSGEN_COMBO = 4007      CustomRamp, GreyRamp, RedRamp, GreenRamp, BlueRamp, GreenToRedRamp, \
27        HotToColdRamp
28    
29    USEALL_BMP  = "group_use_all"
30    USE_BMP     = "group_use"
31    USENOT_BMP  = "group_use_not"
32    USENONE_BMP = "group_use_none"
33    
34    GENCOMBOSTR_UNIFORM = _("Uniform Distribution")
35    GENCOMBOSTR_UNIQUE = _("Unique Values")
36    GENCOMBOSTR_QUANTILES = _("Quantiles from Table")
37    
38    PROPCOMBOSTR_CUSTOM     = _("Custom Ramp")
39    PROPCOMBOSTR_GREY       = _("Grey Ramp")
40    PROPCOMBOSTR_RED        = _("Red Ramp")
41    PROPCOMBOSTR_GREEN      = _("Green Ramp")
42    PROPCOMBOSTR_BLUE       = _("Blue Ramp")
43    PROPCOMBOSTR_GREEN2RED  = _("Green-to-Red Ramp")
44    PROPCOMBOSTR_HOT2COLD   = _("Hot-to-Cold Ramp")
45    
46  COMBOSTR_UNIFORM = _("Uniform Distribution")  ID_CLASSGEN_GENCOMBO = 4007
47  COMBOSTR_UNIQUE = _("Unique Values")  ID_CLASSGEN_PROPCOMBO = 4008
48    
49  class ClassGenDialog(wxDialog):  class ClassGenDialog(wxDialog):
50                                                                                    
51      def __init__(self, parent, layer, fieldName):      def __init__(self, parent, layer, fieldName):
52          """Inialize the class generating dialog.          """Inialize the class generating dialog.
53    
# Line 38  class ClassGenDialog(wxDialog): Line 56  class ClassGenDialog(wxDialog):
56    
57          wxDialog.__init__(self, parent, -1, _("Generate Classification"),          wxDialog.__init__(self, parent, -1, _("Generate Classification"),
58                            style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)                            style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
59                                                                                    
60          self.parent = parent          self.parent = parent
61            self.layer = layer
62          self.clazz = None          self.clazz = None
63    
64          self.type, name, width, prec = layer.table.field_info_by_name(fieldName)          col = layer.ShapeStore().Table().Column(fieldName)
65            self.type = col.type
66    
67            self.fieldName = fieldName
68            self.fieldType = self.type
69    
70            self.curGenPanel = None
71    
72            self.genpanels = []
73    
74          #############          #############
75          # we need to create genButton first because when we create the          # we need to create genButton first because when we create the
76          # panels they will call AllowGenerate() which uses genButton.          # panels they will call AllowGenerate() which uses genButton.
77          #          #
78          buttonSizer = wxBoxSizer(wxHORIZONTAL)          self.genButton = wxButton(self, wxID_OK, _("Generate"))
79          self.genButton = wxButton(self, ID_CLASSGEN_GEN, _("Generate"))          self.cancelButton = wxButton(self, wxID_CANCEL, _("Close"))
80            self.genButton.SetDefault()
81    
82            self.genChoice = wxChoice(self, ID_CLASSGEN_GENCOMBO)
83    
84            self.genpanels.append((GENCOMBOSTR_UNIQUE, GenUniquePanel))
85            if self.type in (FIELDTYPE_INT, FIELDTYPE_DOUBLE):
86                self.genpanels.append((GENCOMBOSTR_UNIFORM, GenUniformPanel))
87                self.genpanels.append((GENCOMBOSTR_QUANTILES, GenQuantilesPanel))
88    
89            for name, clazz in self.genpanels:
90                self.genChoice.Append(name, [clazz, None])
91    
92            self.genChoice.SetSelection(0)
93    
94            for i in range(self.genChoice.GetCount()):
95                clazz, obj = self.genChoice.GetClientData(i)
96    
97                if obj is None:
98                    obj = clazz(self, self.layer, self.fieldName, self.fieldType)
99                    obj.Hide()
100                    self.genChoice.SetClientData(i, [clazz, obj])
101    
         buttonSizer.Add(self.genButton, 0, wxALL, 4)  
         buttonSizer.Add(60, 20, 0, wxALL, 4)  
         buttonSizer.Add(wxButton(self, ID_CLASSGEN_CLOSE, _("Close")),  
                         0, wxALL, 4)  
102    
103          #############          #############
104    
# Line 64  class ClassGenDialog(wxDialog): Line 108  class ClassGenDialog(wxDialog):
108                    0, wxALL, 4)                    0, wxALL, 4)
109          sizer.Add(wxStaticText(          sizer.Add(wxStaticText(
110              self, -1,              self, -1,
111              _("Field Type: %s") % classifier.Classifier.type2string[self.type]),              _("Data Type: %s") % classifier.Classifier.type2string[self.type]),
112              0, wxALL, 4)              0, wxALL, 4)
113    
114          psizer = wxBoxSizer(wxHORIZONTAL)          psizer = wxBoxSizer(wxHORIZONTAL)
115          psizer.Add(wxStaticText(          psizer.Add(wxStaticText(self, -1, _("Generate:")),
             self, -1,  
             _("Generate:")),  
116              0, wxALIGN_CENTER_VERTICAL, 0)              0, wxALIGN_CENTER_VERTICAL, 0)
117            psizer.Add(self.genChoice, 1, wxALL | wxGROW, 4)
         self.genCombo = wxComboBox(self,  
                                 ID_CLASSGEN_COMBO,  
                                 "", style = wxCB_READONLY)  
         psizer.Add(self.genCombo, 1, wxALL | wxGROW, 4)  
         EVT_COMBOBOX(self, ID_CLASSGEN_COMBO, self._OnGenTypeSelect)  
118    
119          sizer.Add(psizer, 0, wxALL | wxGROW, 4)          sizer.Add(psizer, 0, wxALL | wxGROW, 4)
120    
121          #############          self.sizer_genPanel = wxBoxSizer(wxVERTICAL)
122            sizer.Add(self.sizer_genPanel, 1, wxGROW | wxALL, 4)
         self.genPanel = None  
   
         panel = GenUniquePanel(self, layer, fieldName, self.type)  
         self.genCombo.Append(COMBOSTR_UNIQUE)  
         self.genCombo.SetClientData(self.genCombo.GetCount() - 1, panel)  
         sizer.Add(panel, 1, wxGROW | wxALL, 4)  
   
         self.genPanel = panel  
123    
124          if self.type in (FIELDTYPE_INT, FIELDTYPE_DOUBLE):          psizer = wxBoxSizer(wxHORIZONTAL)
125              panel = GenUniformPanel(self, layer, fieldName, self.type)          psizer.Add(wxStaticText(self, -1, _("Color Scheme:")),
126              self.genCombo.Append(COMBOSTR_UNIFORM)              0, wxALIGN_CENTER_VERTICAL, 0)
             self.genCombo.SetClientData(self.genCombo.GetCount() - 1, panel)  
             sizer.Add(panel, 0, wxGROW | wxALL, 4)  
             sizer.Show(panel, False)  
127    
128          #############          # Properties (Ramp) ComboBox
129            self.propCombo = wxChoice(self, ID_CLASSGEN_PROPCOMBO)
130    
131          self.propPanel = None          self.propPanel = None
132            custom_ramp_panel = CustomRampPanel(self, layer.ShapeType())
133    
134          panel = CustomRampPanel(self, layer.ShapeType())          self.propCombo.Append(PROPCOMBOSTR_GREY,  GreyRamp)
135            self.propCombo.Append(PROPCOMBOSTR_RED,   RedRamp)
136          self.propPanel = panel          self.propCombo.Append(PROPCOMBOSTR_GREEN, GreenRamp)
137            self.propCombo.Append(PROPCOMBOSTR_BLUE,  BlueRamp)
138            self.propCombo.Append(PROPCOMBOSTR_GREEN2RED, GreenToRedRamp)
139            self.propCombo.Append(PROPCOMBOSTR_HOT2COLD,  HotToColdRamp())
140            self.propCombo.Append(PROPCOMBOSTR_CUSTOM, custom_ramp_panel)
141    
142          sizer.Add(panel, 1, wxALL | wxGROW, 4)          self.propCombo.SetSelection(0)
143    
144          #############          psizer.Add(self.propCombo, 1, wxALL | wxGROW, 4)
145            sizer.Add(psizer, 0, wxALL | wxGROW, 4)
146    
147          sizer.Add(buttonSizer, 0,          sizer.Add(custom_ramp_panel, 1, wxGROW | wxALL, 4)
148                    wxALL | wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL, 4)          sizer.Show(custom_ramp_panel, False)
149    
150            # Finally place the main buttons
151            buttonSizer = wxBoxSizer(wxHORIZONTAL)
152            buttonSizer.Add(self.genButton, 0, wxRIGHT|wxEXPAND, 10)
153            buttonSizer.Add(self.cancelButton, 0, wxRIGHT|wxEXPAND, 10)
154            sizer.Add(buttonSizer, 0, wxALIGN_RIGHT|wxBOTTOM|wxTOP, 10)
155    
156          self.SetSizer(sizer)          self.SetSizer(sizer)
157          self.SetAutoLayout(True)          self.SetAutoLayout(True)
158          sizer.SetSizeHints(self)          sizer.SetSizeHints(self)
159    
160          self.sizer = sizer          self.topBox = sizer
161    
162            self.__DoOnGenTypeSelect()
163    
164          EVT_BUTTON(self, ID_CLASSGEN_GEN, self._OnGenerate)          EVT_CHOICE(self, ID_CLASSGEN_GENCOMBO, self._OnGenTypeSelect)
165          EVT_BUTTON(self, ID_CLASSGEN_CLOSE, self._OnCloseBtn)          EVT_CHOICE(self, ID_CLASSGEN_PROPCOMBO, self._OnPropTypeSelect)
166            EVT_BUTTON(self, wxID_OK, self.OnOK)
167            EVT_BUTTON(self, wxID_CANCEL, self.OnCancel)
168    
169            self.__DoOnGenTypeSelect()
170    
171            self.genChoice.SetFocus()
172    
173      def GetClassification(self):      def GetClassification(self):
174          return self.clazz          return self.clazz
# Line 130  class ClassGenDialog(wxDialog): Line 176  class ClassGenDialog(wxDialog):
176      def AllowGenerate(self, on):      def AllowGenerate(self, on):
177          pass #self.genButton.Enable(on)          pass #self.genButton.Enable(on)
178    
179      def _OnGenerate(self, event):      def OnOK(self, event):
180            """This is really the generate button, but we want to override
181            the wxDialog class.
182            """
183    
184          selIndex = self.genCombo.GetSelection()          index = self.genChoice.GetSelection()
185    
186            assert index != -1, "button should be disabled!"
187    
188            genSel = self.genChoice.GetString(index)
189            clazz, genPanel = self.genChoice.GetClientData(index)
190    
         sel = self.genCombo.GetString(selIndex)  
         genPanel = self.genCombo.GetClientData(selIndex)  
191          propPanel = self.propPanel          propPanel = self.propPanel
192    
193          if sel == COMBOSTR_UNIFORM:          if genSel in (GENCOMBOSTR_UNIFORM,          \
194                          GENCOMBOSTR_UNIQUE,           \
195                          GENCOMBOSTR_QUANTILES):
196    
             min = genPanel.GetMin()  
             max = genPanel.GetMax()  
197              numGroups = genPanel.GetNumGroups()              numGroups = genPanel.GetNumGroups()
             sp = propPanel.GetStartProperties()  
             ep = propPanel.GetEndProperties()  
198    
199              if min is not None \              index = self.propCombo.GetSelection()
                 and max is not None \  
                 and numGroups is not None:  
200    
201                  self.clazz = ClassGenerator().GenUnifromDistribution(              propSel = self.propCombo.GetString(index)
202                               min, max, numGroups, sp, ep,              propPanel = self.propCombo.GetClientData(index)
                              self.type == FIELDTYPE_INT)  
203    
204                  self.parent._SetClassification(self.clazz)              ramp = propPanel.GetRamp()
205    
206          elif sel == COMBOSTR_UNIQUE:              if genSel == GENCOMBOSTR_UNIFORM:
207    
208              list = genPanel.GetValueList()                  min = genPanel.GetMin()
209              numGroups = genPanel.GetNumGroups()                  max = genPanel.GetMax()
             sp = propPanel.GetStartProperties()  
             ep = propPanel.GetEndProperties()  
210    
211              if len(list) > 0 \                  if min is not None \
212                  and numGroups is not None:                      and max is not None \
213                        and numGroups is not None:
214    
215                  self.clazz = ClassGenerator().GenSingletonsFromList(                      self.clazz = generate_uniform_distribution(
216                                  list, numGroups, sp, ep)                                  min, max, numGroups, ramp,
217                                    self.type == FIELDTYPE_INT)
218    
219                  self.parent._SetClassification(self.clazz)                      self.parent._SetClassification(self.clazz)
220    
221          else:              elif genSel == GENCOMBOSTR_UNIQUE:
222              pass  
223                    list = genPanel.GetValueList()
224    
225                    if len(list) > 0:
226                        self.clazz = generate_singletons(list, ramp)
227                        self.parent._SetClassification(self.clazz)
228    
229                elif genSel == GENCOMBOSTR_QUANTILES:
230    
231                    _range = genPanel.GetRange()
232                    _list = genPanel.GetList()
233                    _list.sort()
234    
235                    delta = 1 / float(numGroups)
236                    percents = [delta * i for i in range(1, numGroups + 1)]
237                    adjusted, self.clazz = \
238                        generate_quantiles(_list, percents, ramp, _range)
239    
240                    if adjusted:
241                        dlg = wxMessageDialog(self,
242                            _("Based on the data from the table and the input\n" +
243                              "values, the exact quantiles could not be generated.\n\n" +
244                              "Accept a close estimate?"),
245                            _("Problem with Quantiles"),
246    
247      def _OnCloseBtn(self, event):                          wxYES_NO|wxYES_DEFAULT|wxICON_QUESTION)
248                        if dlg.ShowModal() == wxID_YES:
249                            self.parent._SetClassification(self.clazz)
250                    else:
251                        self.parent._SetClassification(self.clazz)
252    
253        def OnCancel(self, event):
254          self.Close()          self.Close()
255    
256      def _OnGenTypeSelect(self, event):      def _OnGenTypeSelect(self, event):
257            self.__DoOnGenTypeSelect()
258            return
259    
260          combo = event.GetEventObject()          combo = event.GetEventObject()
261    
262          selIndex = combo.GetSelection()          selIndex = combo.GetSelection()
263    
264          if self.genPanel is not None:          if self.genPanel is not None:
265              self.sizer.Show(self.genPanel, False)              self.topBox.Show(self.genPanel, False)
266    
267          self.genPanel = combo.GetClientData(selIndex)          self.genPanel = combo.GetClientData(selIndex)
268          if self.genPanel is not None:          if self.genPanel is not None:
269              self.sizer.Show(self.genPanel, True)              self.topBox.Show(self.genPanel, True)
270    
271            self.topBox.SetSizeHints(self)
272            self.topBox.Layout()
273    
274        def _OnPropTypeSelect(self, event):
275            combo = event.GetEventObject()
276    
277            selIndex = combo.GetSelection()
278            sel = combo.GetString(selIndex)
279    
280            if isinstance(self.propPanel, wxPanel):
281                self.topBox.Show(self.propPanel, False)
282    
283            self.propPanel = combo.GetClientData(selIndex)
284    
285            if isinstance(self.propPanel, wxPanel):
286                self.topBox.Show(self.propPanel, True)
287    
288            self.topBox.SetSizeHints(self)
289            self.topBox.Layout()
290    
291        def __DoOnGenTypeSelect(self):
292            choice = self.genChoice
293    
294            sel = choice.GetSelection()
295            if sel == -1: return
296    
297          self.sizer.SetSizeHints(self)          clazz, obj = choice.GetClientData(sel)
         self.sizer.Layout()  
298    
299            if self.curGenPanel is not None:
300                self.curGenPanel.Hide()
301                self.sizer_genPanel.Remove(self.curGenPanel)
302    
303            self.curGenPanel = obj
304            self.curGenPanel.Show()
305    
306            self.sizer_genPanel.Add(self.curGenPanel, 1,
307                wxALL|wxEXPAND|wxADJUST_MINSIZE, 3)
308            self.sizer_genPanel.Layout()
309            self.Layout()
310            self.topBox.SetSizeHints(self)
311    
312  ID_UNIFORM_MIN = 4001  ID_UNIFORM_MIN = 4001
313  ID_UNIFORM_MAX = 4002  ID_UNIFORM_MAX = 4002
# Line 238  class GenUniformPanel(wxPanel): Line 353  class GenUniformPanel(wxPanel):
353          sizer = wxBoxSizer(wxHORIZONTAL)          sizer = wxBoxSizer(wxHORIZONTAL)
354    
355          sizer.Add(wxStaticText(self, -1, _("Number of Groups:")), 0, wxALL, 4)          sizer.Add(wxStaticText(self, -1, _("Number of Groups:")), 0, wxALL, 4)
356          self.numGroupsCtrl = wxSpinCtrl(self, ID_UNIFORM_NGROUPS, style=wxTE_RIGHT)          self.numGroupsCtrl = wxSpinCtrl(self, ID_UNIFORM_NGROUPS,
357                                            style=wxTE_RIGHT)
358          EVT_TEXT(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)          EVT_TEXT(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)
359          EVT_SPINCTRL(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)          EVT_SPINCTRL(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)
360          sizer.Add(self.numGroupsCtrl, 1, wxALL, 4)          sizer.Add(self.numGroupsCtrl, 1, wxALL, 4)
# Line 259  class GenUniformPanel(wxPanel): Line 375  class GenUniformPanel(wxPanel):
375          self.numGroupsChanging = False          self.numGroupsChanging = False
376          self.steppingChanging = False          self.steppingChanging = False
377    
378          self.numGroupsCtrl.SetRange(1, 100)          self.numGroupsCtrl.SetRange(1, sys.maxint)
379    
380          self.numGroupsCtrl.SetValue(1)          self.numGroupsCtrl.SetValue(1)
381          self.stepCtrl.SetValue("1")          self.stepCtrl.SetValue("1")
# Line 309  class GenUniformPanel(wxPanel): Line 425  class GenUniformPanel(wxPanel):
425          self.numGroupsCtrl.Enable(on)          self.numGroupsCtrl.Enable(on)
426          self.stepCtrl.Enable(on)          self.stepCtrl.Enable(on)
427    
         if on:  
             self.numGroupsCtrl.SetRange(1, abs(max - min) / 0.001)  
   
428          ngroups = self.GetNumGroups()          ngroups = self.GetNumGroups()
429    
430          if ngroups is not None  \          if ngroups is not None  \
# Line 342  class GenUniformPanel(wxPanel): Line 455  class GenUniformPanel(wxPanel):
455          min = self.GetMin()          min = self.GetMin()
456          max = self.GetMax()          max = self.GetMax()
457    
         if ngroups >= self.numGroupsCtrl.GetMax():  
             self.numGroupsCtrl.SetRange(1, ngroups + 1)  
   
458          if ngroups is not None  \          if ngroups is not None  \
459              and min is not None \              and min is not None \
460              and max is not None \              and max is not None \
# Line 391  class GenUniformPanel(wxPanel): Line 501  class GenUniformPanel(wxPanel):
501              self.parent.AllowGenerate(False)              self.parent.AllowGenerate(False)
502    
503      def _OnRetrieve(self, event):      def _OnRetrieve(self, event):
504            table = self.layer.ShapeStore().Table()
505          if self.layer.table is not None:          if table is not None:
506              range = self.layer.table.field_range(self.fieldName)              ThubanBeginBusyCursor()
507              self.minCtrl.SetValue(str(range[0][0]))              try:
508              self.maxCtrl.SetValue(str(range[1][0]))                  min, max = table.ValueRange(self.fieldName)
509                    self.minCtrl.SetValue(str(min))
510                    self.maxCtrl.SetValue(str(max))
511                finally:
512                    ThubanEndBusyCursor()
513    
514      def __GetValidatedTypeEntry(self, win, value, type, badValue = None):      def __GetValidatedTypeEntry(self, win, value, type, badValue = None):
515    
# Line 437  class GenUniformPanel(wxPanel): Line 551  class GenUniformPanel(wxPanel):
551          return valid          return valid
552    
553      def __CalcStepping(self, min, max, ngroups):      def __CalcStepping(self, min, max, ngroups):
         step = Str2Num(str((max - min) / float(ngroups)))  
554          if self.fieldType == FIELDTYPE_INT:          if self.fieldType == FIELDTYPE_INT:
555              step = int(step)              step = int((max - min + 1) / float(ngroups))
556            else:
557                step = (max - min) / float(ngroups)
558    
559          return step          return step
560    
# Line 461  ID_UNIQUE_DONTUSE = 4004 Line 576  ID_UNIQUE_DONTUSE = 4004
576  ID_UNIQUE_USENONE = 4005  ID_UNIQUE_USENONE = 4005
577  ID_UNIQUE_SORTAVAIL = 4006  ID_UNIQUE_SORTAVAIL = 4006
578  ID_UNIQUE_SORTUSE = 4007  ID_UNIQUE_SORTUSE = 4007
579    ID_UNIQUE_REVAVAIL = 4008
580    ID_UNIQUE_REVUSE = 4009
581    
582  class GenUniquePanel(wxPanel):  class GenUniquePanel(wxPanel):
583    
# Line 476  class GenUniquePanel(wxPanel): Line 593  class GenUniquePanel(wxPanel):
593                                      wxVERTICAL)                                      wxVERTICAL)
594    
595    
596            #bsizer = wxBoxSizer(wxVERTICAL)
597            topSizer.Add(wxButton(self, ID_UNIQUE_RETRIEVE,
598                                _("Retrieve From Table")),
599                       0, wxALL | wxALIGN_RIGHT, 4)
600    
601            EVT_BUTTON(self, ID_UNIQUE_RETRIEVE, self._OnRetrieve)
602    
603            #topSizer.Add(bsizer, 0, wxALL, 4)
604    
605          sizer = wxBoxSizer(wxHORIZONTAL)          sizer = wxBoxSizer(wxHORIZONTAL)
606    
607          self.dataList = []          self.dataList = []
# Line 487  class GenUniquePanel(wxPanel): Line 613  class GenUniquePanel(wxPanel):
613          self.list_avail_data = []          self.list_avail_data = []
614          psizer.Add(self.list_avail, 1, wxGROW, 0)          psizer.Add(self.list_avail, 1, wxGROW, 0)
615    
616          psizer.Add(wxButton(self, ID_UNIQUE_SORTAVAIL, _("Sort")))          bsizer = wxBoxSizer(wxHORIZONTAL)
617            bsizer.Add(wxButton(self, ID_UNIQUE_SORTAVAIL, _("Sort")))
618            EVT_BUTTON(self, ID_UNIQUE_SORTAVAIL, self._OnSortList)
619    
620          EVT_BUTTON(self, ID_UNIQUE_SORTAVAIL, self._OnSortAvailList)          bsizer.Add(wxButton(self, ID_UNIQUE_REVAVAIL, _("Reverse")))
621            EVT_BUTTON(self, ID_UNIQUE_REVAVAIL, self._OnReverseList)
622    
623            psizer.Add(bsizer, 0, wxGROW, 0)
624          sizer.Add(psizer, 1, wxGROW, 0)          sizer.Add(psizer, 1, wxGROW, 0)
625    
626                    
627          bsizer = wxBoxSizer(wxVERTICAL)          bsizer = wxBoxSizer(wxVERTICAL)
628          bsizer.Add(wxButton(self, ID_UNIQUE_USEALL, _("Use All")),  
629            bmp = resource.GetBitmapResource(USEALL_BMP, wxBITMAP_TYPE_XPM)
630            bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USEALL, bmp),
631                     0, wxGROW | wxALL, 4)                     0, wxGROW | wxALL, 4)
632          bsizer.Add(wxButton(self, ID_UNIQUE_USE, _("Use >>")),          bmp = resource.GetBitmapResource(USE_BMP, wxBITMAP_TYPE_XPM)
633            bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USE, bmp),
634                     0, wxGROW | wxALL, 4)                     0, wxGROW | wxALL, 4)
635          bsizer.Add(wxButton(self, ID_UNIQUE_DONTUSE, _("<< Don't Use")),          bmp = resource.GetBitmapResource(USENOT_BMP, wxBITMAP_TYPE_XPM)
636            bsizer.Add(wxBitmapButton(self, ID_UNIQUE_DONTUSE, bmp),
637                     0, wxGROW | wxALL, 4)                     0, wxGROW | wxALL, 4)
638          bsizer.Add(wxButton(self, ID_UNIQUE_USENONE, _("Use None")),          bmp = resource.GetBitmapResource(USENONE_BMP, wxBITMAP_TYPE_XPM)
639            bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USENONE, bmp),
640                     0, wxGROW | wxALL, 4)                     0, wxGROW | wxALL, 4)
641    
642          EVT_BUTTON(self, ID_UNIQUE_USEALL, self._OnUseAll)          EVT_BUTTON(self, ID_UNIQUE_USEALL, self._OnUseAll)
# Line 518  class GenUniquePanel(wxPanel): Line 653  class GenUniquePanel(wxPanel):
653          self.list_use_data = []          self.list_use_data = []
654          psizer.Add(self.list_use, 1, wxGROW, 0)          psizer.Add(self.list_use, 1, wxGROW, 0)
655    
656          psizer.Add(wxButton(self, ID_UNIQUE_SORTUSE, _("Sort")))          bsizer = wxBoxSizer(wxHORIZONTAL)
657            bsizer.Add(wxButton(self, ID_UNIQUE_SORTUSE, _("Sort")))
658          EVT_BUTTON(self, ID_UNIQUE_SORTUSE, self._OnSortUseList)          EVT_BUTTON(self, ID_UNIQUE_SORTUSE, self._OnSortList)
659    
660          sizer.Add(psizer, 1, wxGROW, 0)          bsizer.Add(wxButton(self, ID_UNIQUE_REVUSE, _("Reverse")))
661            EVT_BUTTON(self, ID_UNIQUE_REVUSE, self._OnReverseList)
662    
663          bsizer = wxBoxSizer(wxVERTICAL)          psizer.Add(bsizer, 0, wxGROW, 0)
         bsizer.Add(wxButton(self, ID_UNIQUE_RETRIEVE,  
                             _("Retrieve From Table")),  
                    0, wxGROW | wxALL, 4)  
664    
665          EVT_BUTTON(self, ID_UNIQUE_RETRIEVE, self._OnRetrieve)          sizer.Add(psizer, 1, wxGROW, 0)
666    
         sizer.Add(bsizer, 0, wxALL, 4)  
667    
668          topSizer.Add(sizer, 1, wxGROW, 0)          topSizer.Add(sizer, 1, wxGROW, 0)
669    
# Line 539  class GenUniquePanel(wxPanel): Line 671  class GenUniquePanel(wxPanel):
671          self.SetAutoLayout(True)          self.SetAutoLayout(True)
672          topSizer.SetSizeHints(self)          topSizer.SetSizeHints(self)
673    
674          self.parent.AllowGenerate(False)          width, height = self.list_avail.GetSizeTuple()
675            self.list_avail.SetColumnWidth(0,width)
676            width, height = self.list_use.GetSizeTuple()
677            self.list_use.SetColumnWidth(0,width)
678    
679          self.mylist = ["Hallo", "Welt!", "Wie", "geht", "es", "dir", "?"]          self.parent.AllowGenerate(False)
680    
681      def GetNumGroups(self):      def GetNumGroups(self):
682          return self.list_use.GetItemCount()          return self.list_use.GetItemCount()
# Line 552  class GenUniquePanel(wxPanel): Line 687  class GenUniquePanel(wxPanel):
687              list.append(self.dataList[self.list_use.GetItemData(i)])              list.append(self.dataList[self.list_use.GetItemData(i)])
688          return list          return list
689    
690      def _OnSortAvailList(self, event):      def _OnSortList(self, event):
691          self.list_avail.SortItems(lambda i1, i2:          id = event.GetId()
692                                      cmp(self.dataList[i1],  
693                                          self.dataList[i2]))          if id == ID_UNIQUE_SORTUSE:
694                list = self.list_use
695      def _OnSortUseList(self, event):          else:
696          self.list_use.SortItems(lambda i1, i2:              list = self.list_avail
697                                      cmp(self.dataList[i1],  
698                                          self.dataList[i2]))          list.SortItems(lambda i1, i2: cmp(self.dataList[i1],
699                                              self.dataList[i2]))
700    
701        def _OnReverseList(self, event):
702            id = event.GetId()
703    
704            if id == ID_UNIQUE_REVUSE:
705                list = self.list_use
706            else:
707                list = self.list_avail
708    
709            #
710            # always returning 1 reverses the list
711            #
712            list.SortItems(lambda i1, i2: 1)
713    
714      def _OnRetrieve(self, event):      def _OnRetrieve(self, event):
715          self.list_use.DeleteAllItems()          self.list_use.DeleteAllItems()
# Line 568  class GenUniquePanel(wxPanel): Line 717  class GenUniquePanel(wxPanel):
717          self.list_avail.DeleteAllItems()          self.list_avail.DeleteAllItems()
718          self.list_avail_data = []          self.list_avail_data = []
719    
720          list = self.layer.table.GetUniqueValues(self.fieldName)          ThubanBeginBusyCursor()
721          index = 0          try:
722          for v in list:              list = self.layer.ShapeStore().Table().UniqueValues(self.fieldName)
723              self.dataList.append(v)              index = 0
724              i = self.list_avail.InsertStringItem(index, str(v))              for v in list:
725              self.list_avail.SetItemData(index, i)                  self.dataList.append(v)
726                    i = self.list_avail.InsertStringItem(index, str(v))
727              self.list_avail_data.append(v)                  self.list_avail.SetItemData(index, i)
728              index += 1      
729                    self.list_avail_data.append(v)
730                    index += 1
731            finally:
732                ThubanEndBusyCursor()
733    
734      def _OnUseAll(self, event):      def _OnUseAll(self, event):
735          for i in range(self.list_avail.GetItemCount()):          for i in range(self.list_avail.GetItemCount()):
736              self.__MoveListItem(0, self.list_avail, self.list_use)              self.__MoveListItem(0, self.list_avail, self.list_use)
737    
738      def _OnUse(self, event):      def _OnUse(self, event):
         print "_OnUse"  
739          self.__MoveSelectedItems(self.list_avail, self.list_use)          self.__MoveSelectedItems(self.list_avail, self.list_use)
740    
741      def _OnDontUse(self, event):      def _OnDontUse(self, event):
         print "_OnDontUse"  
742          self.__MoveSelectedItems(self.list_use, self.list_avail)          self.__MoveSelectedItems(self.list_use, self.list_avail)
743    
744      def _OnUseNone(self, event):      def _OnUseNone(self, event):
         print "_OnUseNone"  
745    
746          for i in range(self.list_use.GetItemCount()):          for i in range(self.list_use.GetItemCount()):
747              self.__MoveListItem(0, self.list_use, self.list_avail)              self.__MoveListItem(0, self.list_use, self.list_avail)
# Line 626  class GenUniquePanel(wxPanel): Line 776  class GenUniquePanel(wxPanel):
776  #       list.SetColumnWidth(0, event.GetSize().GetWidth())  #       list.SetColumnWidth(0, event.GetSize().GetWidth())
777  #        #      
778    
779    ID_QUANTILES_RANGE = 4001
780    ID_QUANTILES_RETRIEVE = 4002
781    
782    class GenQuantilesPanel(wxPanel):
783    
784        def __init__(self, parent, layer, fieldName, fieldType):
785            wxPanel.__init__(self, parent, -1)
786    
787            self.parent = parent
788            self.layer = layer
789            self.fieldName = fieldName
790            self.fieldType = fieldType
791    
792            topBox = wxStaticBoxSizer(wxStaticBox(self, -1, ""),
793                                        wxVERTICAL)
794    
795            self.text_range = wxTextCtrl(self, ID_QUANTILES_RANGE, "")
796            self.button_retrieve = wxButton(self, ID_QUANTILES_RETRIEVE,
797                                            _("Retrieve from Table"))
798    
799            self.spin_numClasses = wxSpinCtrl(self, -1, style=wxTE_RIGHT)
800            self.spin_numClasses.SetRange(1, sys.maxint)
801            self.spin_numClasses.SetValue(1)
802    
803    
804            sizer = wxBoxSizer(wxHORIZONTAL)
805            sizer.Add(wxStaticText(self, -1, _("Apply to Range")), 0, wxALL, 4)
806            sizer.Add(self.text_range, 1, wxALL, 4)
807            sizer.Add(self.button_retrieve, 0, wxALL, 4)
808    
809            topBox.Add(sizer, 0, wxEXPAND, 0)
810    
811            sizer = wxBoxSizer(wxHORIZONTAL)
812            sizer.Add(wxStaticText(self, -1, _("Number of Classes:")), 0, wxALL, 4)
813            sizer.Add(self.spin_numClasses, 1, wxALL, 4)
814    
815            topBox.Add(sizer, 0, wxEXPAND, 0)
816    
817            self.SetSizer(topBox)
818            self.SetAutoLayout(True)
819            topBox.Fit(self)
820            topBox.SetSizeHints(self)
821    
822            EVT_TEXT(self, ID_QUANTILES_RANGE, self.OnRangeText)
823            EVT_BUTTON(self, ID_QUANTILES_RETRIEVE, self.OnRetrieve)
824    
825            self.__range = None
826    
827        def GetNumGroups(self):
828            return self.spin_numClasses.GetValue()
829    
830        def GetRange(self):
831            assert self.__range is not None
832    
833            return self.__range
834    
835        def GetList(self):
836            _list = []
837            table = self.layer.ShapeStore().Table()
838            if table is not None:
839                ThubanBeginBusyCursor()
840                try:
841                    #
842                    # FIXME: Replace with a call to table when the method
843                    # has been written to get all the values
844                    #
845                    for i in range(table.NumRows()):
846                        _list.append(table.ReadValue(i, self.fieldName))
847                finally:
848                    ThubanEndBusyCursor()
849    
850            return _list
851    
852        def OnRangeText(self, event):
853    
854            try:
855                self.__range = Range(self.text_range.GetValue())
856            except ValueError:
857                self.__range = None
858    
859            if self.__range is not None:
860                self.text_range.SetForegroundColour(wxBLACK)
861            else:
862                self.text_range.SetForegroundColour(wxRED)
863    
864        def OnRetrieve(self, event):
865            table = self.layer.ShapeStore().Table()
866            if table is not None:
867                ThubanBeginBusyCursor()
868                try:
869                    min, max = table.ValueRange(self.fieldName)
870                    self.text_range.SetValue("[" + str(min) + ";" + str(max) + "]")
871                finally:
872                    ThubanEndBusyCursor()
873    
874  ID_CUSTOMRAMP_COPYSTART = 4001  ID_CUSTOMRAMP_COPYSTART = 4001
875  ID_CUSTOMRAMP_COPYEND = 4002  ID_CUSTOMRAMP_COPYEND = 4002
876  ID_CUSTOMRAMP_EDITSTART = 4003  ID_CUSTOMRAMP_EDITSTART = 4003
# Line 657  class CustomRampPanel(wxPanel): Line 902  class CustomRampPanel(wxPanel):
902                        | wxALIGN_CENTER_VERTICAL, \                        | wxALIGN_CENTER_VERTICAL, \
903                     4)                     4)
904    
905            bmp = resource.GetBitmapResource(USE_BMP, wxBITMAP_TYPE_XPM)
906          bsizer = wxBoxSizer(wxVERTICAL)          bsizer = wxBoxSizer(wxVERTICAL)
907          bsizer.Add(wxButton(self, ID_CUSTOMRAMP_COPYSTART, _("Copy >>")),          bsizer.Add(wxBitmapButton(self, ID_CUSTOMRAMP_COPYSTART, bmp),
908                     0, wxGROW | wxALL, 4)                     0, wxGROW | wxALL, 4)
909          bsizer.Add(wxButton(self, ID_CUSTOMRAMP_COPYEND, _("<< Copy")),          bmp = resource.GetBitmapResource(USENOT_BMP, wxBITMAP_TYPE_XPM)
910            bsizer.Add(wxBitmapButton(self, ID_CUSTOMRAMP_COPYEND, bmp),
911                     0, wxGROW | wxALL, 4)                     0, wxGROW | wxALL, 4)
912    
913          topSizer.Add(bsizer,          topSizer.Add(bsizer,
# Line 696  class CustomRampPanel(wxPanel): Line 943  class CustomRampPanel(wxPanel):
943          self.SetAutoLayout(True)          self.SetAutoLayout(True)
944          topSizer.SetSizeHints(self)          topSizer.SetSizeHints(self)
945    
946      def GetStartProperties(self):      def GetRamp(self):
947          return self.startPropCtrl.GetProperties()          return CustomRamp(self.startPropCtrl.GetProperties(),
948                              self.endPropCtrl.GetProperties())
     def GetEndProperties(self):  
         return self.endPropCtrl.GetProperties()  
949    
950      def _OnCopyStart(self, event):      def _OnCopyStart(self, event):
951          self.endPropCtrl.SetProperties(self.startPropCtrl.GetProperties())          self.endPropCtrl.SetProperties(self.startPropCtrl.GetProperties())
# Line 714  class CustomRampPanel(wxPanel): Line 959  class CustomRampPanel(wxPanel):
959      def _OnEditEnd(self, event):      def _OnEditEnd(self, event):
960          self.endPropCtrl.DoEdit()          self.endPropCtrl.DoEdit()
961    
962  class ClassGenerator:    
   
     def GenSingletonsFromList(self, list, numGroups, prop1, prop2):  
         """Generate a new classification consisting solely of singletons.  
   
         The resulting classification will consist of at most 'numGroups'  
         groups whose group properties ramp between 'prop1' and 'prop2'. There  
         could be fewer groups if 'list' contains fewer that 'numGroups' items.  
   
         list -- any object that implements the iterator interface  
   
         numGroups -- how many groups to generate. This can not be  
                      determined while the classification is being  
                      generated because the stepping values must  
                      be precalculated to ramp between prop1 and prop2.  
   
         prop1 -- initial group property values  
   
         prop2 -- final group property values  
         """  
   
         clazz = Classification()  
         if numGroups == 0: return clazz  
   
         for value, prop in zip(list, CustomRamp(numGroups, prop1, prop2)):  
             clazz.AppendGroup(ClassGroupSingleton(value, prop))  
   
         return clazz  
   
     def GenSingletons(self, min, max, numGroups, prop1, prop2):  
   
         clazz = Classification()  
   
         #step = int((max - min) / float(numGroups))  
         step = int(Str2Num(str((max - min + 1) / float(numGroups))))  
   
         if numGroups > 0:  
             cur_value = min  
   
             for prop in CustomRamp(numGroups, prop1, prop2):  
                 clazz.AppendGroup(  
                     ClassGroupSingleton(  
                         Str2Num(str(cur_value)),  
                         prop))  
                 cur_value += step  
   
         return clazz  
   
     def GenUnifromDistribution(self, min, max, numGroups,  
                                prop1, prop2, intStep = False):  
         """Generate a classification with numGroups range groups  
         each with the same interval.  
   
         intStep -- force the calculated stepping to an integer.  
                    Useful if the values are integers but the  
                    number of groups specified doesn't evenly  
                    divide (max - min).  
         """  
   
         clazz = Classification()  
         if numGroups == 0: return clazz  
   
         step = Str2Num(str((max - min) / float(numGroups)))  
   
         if intStep:  
             step = int(step)  
   
         cur_min = min  
         cur_max = cur_min + step  
   
         i = 0  
         for prop in CustomRamp(numGroups, prop1, prop2):  
   
             if i == (numGroups - 1):  
                 cur_max = max  
   
             # this check guards against rounding issues  
             if cur_min != cur_max:  
                 clazz.AppendGroup(  
                     ClassGroupRange(  
                         Str2Num(str(cur_min)),  
                         Str2Num(str(cur_max)),  
                         prop))  
   
             cur_min = cur_max  
             cur_max += step  
             i += 1  
   
         return clazz  
   
 CLR  = 0  
 STEP = 1  
 class CustomRamp:  
   
     def __init__(self, num, prop1, prop2):  
   
         self.count = int(num)  
         num = float(num)  
   
         clr = prop1.GetLineColor()  
         lineColor2 = prop2.GetLineColor()  
           
         self.noLine = clr is not Color.Transparent \  
                         and lineColor2 is not Color.Transparent  
   
   
         self.lineInfo = self.__GetColorInfo(prop1.GetLineColor(),  
                                             prop2.GetLineColor(),  
                                             num)  
   
         self.fillInfo = self.__GetColorInfo(prop1.GetFill(),  
                                             prop2.GetFill(),  
                                             num)  
   
         self.lineWidth = prop1.GetLineWidth()  
         self.lineWidthStep = (prop2.GetLineWidth() - self.lineWidth) / num  
   
     def __iter__(self):  
         return self  
   
     def next(self):  
         if self.count == 0:  
             raise StopIteration  
   
         prop = ClassGroupProperties()  
   
         if self.lineInfo is None:  
             prop.SetLineColor(Color.Transparent)  
         else:  
             prop.SetLineColor(Color(self.lineInfo[CLR][0] / 255,  
                                     self.lineInfo[CLR][1] / 255,  
                                     self.lineInfo[CLR][2] / 255))  
   
             self.lineInfo[CLR][0] += self.lineInfo[STEP][0]  
             self.lineInfo[CLR][1] += self.lineInfo[STEP][1]  
             self.lineInfo[CLR][2] += self.lineInfo[STEP][2]  
   
         if self.fillInfo is None:  
             prop.SetFill(Color.Transparent)  
         else:  
             prop.SetFill(Color(self.fillInfo[CLR][0] / 255,  
                             self.fillInfo[CLR][1] / 255,  
                             self.fillInfo[CLR][2] / 255))  
   
             self.fillInfo[CLR][0] += self.fillInfo[STEP][0]  
             self.fillInfo[CLR][1] += self.fillInfo[STEP][1]  
             self.fillInfo[CLR][2] += self.fillInfo[STEP][2]  
   
   
         prop.SetLineWidth(int(self.lineWidth))  
         self.lineWidth        += self.lineWidthStep  
   
         self.count -= 1  
   
         return prop  
   
     def __GetColorInfo(self, color1, color2, numGroups):  
   
         if color1 is Color.Transparent and color2 is Color.Transparent:  
             #  
             # returning early  
             #  
             return None  
         elif color1 is not Color.Transparent and color2 is Color.Transparent:  
             color = [color1.red   * 255,  
                      color1.green * 255,  
                      color1.blue  * 255]  
             step = (0, 0, 0)  
         elif color1 is Color.Transparent and color2 is not Color.Transparent:  
             color = [color2.red   * 255,  
                      color2.green * 255,  
                      color2.blue  * 255]  
             step = (0, 0, 0)  
         else:  
             color = [color1.red   * 255,  
                      color1.green * 255,  
                      color1.blue  * 255]  
             step = ((color2.red   * 255 - color1.red   * 255)   / numGroups,  
                     (color2.green * 255 - color1.green * 255) / numGroups,  
                     (color2.blue  * 255 - color1.blue  * 255)  / numGroups)  
   
   
         return (color, step)  

Legend:
Removed from v.629  
changed lines
  Added in v.1341

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26