/[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 898 by jonathan, Mon May 12 12:19:58 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 *
# Line 16  from Thuban.Model.table import Table, FI Line 18  from Thuban.Model.table import Table, FI
18       FIELDTYPE_STRING       FIELDTYPE_STRING
19    
20  from Thuban.Model.color import Color  from Thuban.Model.color import Color
21    from Thuban.Model.range import Range
22    
23  import classifier  import classifier, resource
   
 from Thuban.common import Str2Num  
24    
25  ID_CLASSGEN_GEN = 4001  from Thuban.Model.classgen import ClassGenerator, \
26  ID_CLASSGEN_CLOSE = 4002      CustomRamp, GreyRamp, RedRamp, GreenRamp, BlueRamp, GreenToRedRamp, \
27  ID_CLASSGEN_COMBO = 4007      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.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.genButton.SetDefault()
80            self.genChoice = wxChoice(self, ID_CLASSGEN_GENCOMBO)
81    
82          buttonSizer.Add(self.genButton, 0, wxALL, 4)          self.genpanels.append((GENCOMBOSTR_UNIQUE, GenUniquePanel))
83          buttonSizer.Add(60, 20, 0, wxALL, 4)          if self.type in (FIELDTYPE_INT, FIELDTYPE_DOUBLE):
84          buttonSizer.Add(wxButton(self, ID_CLASSGEN_CLOSE, _("Close")),              self.genpanels.append((GENCOMBOSTR_UNIFORM, GenUniformPanel))
85                          0, wxALL, 4)              self.genpanels.append((GENCOMBOSTR_QUANTILES, GenQuantilesPanel))
86    
87            for name, clazz in self.genpanels:
88                self.genChoice.Append(name, [clazz, None])
89    
90            self.genChoice.SetSelection(0)
91    
92            self.propPanel = None
93            custom_ramp_panel = CustomRampPanel(self, layer.ShapeType())
94    
95            self.propCombo = wxChoice(self, ID_CLASSGEN_PROPCOMBO)
96            self.propCombo.Append(PROPCOMBOSTR_GREY,  GreyRamp())
97            self.propCombo.Append(PROPCOMBOSTR_RED,   RedRamp())
98            self.propCombo.Append(PROPCOMBOSTR_GREEN, GreenRamp())
99            self.propCombo.Append(PROPCOMBOSTR_BLUE,  BlueRamp())
100            self.propCombo.Append(PROPCOMBOSTR_GREEN2RED, GreenToRedRamp())
101            self.propCombo.Append(PROPCOMBOSTR_HOT2COLD,  HotToColdRamp())
102            self.propCombo.Append(PROPCOMBOSTR_CUSTOM, custom_ramp_panel)
103    
104            self.propCombo.SetSelection(0)
105    
106          #############          #############
107    
# Line 64  class ClassGenDialog(wxDialog): Line 111  class ClassGenDialog(wxDialog):
111                    0, wxALL, 4)                    0, wxALL, 4)
112          sizer.Add(wxStaticText(          sizer.Add(wxStaticText(
113              self, -1,              self, -1,
114              _("Field Type: %s") % classifier.Classifier.type2string[self.type]),              _("Data Type: %s") % classifier.Classifier.type2string[self.type]),
115              0, wxALL, 4)              0, wxALL, 4)
116    
117          psizer = wxBoxSizer(wxHORIZONTAL)          psizer = wxBoxSizer(wxHORIZONTAL)
118          psizer.Add(wxStaticText(          psizer.Add(wxStaticText(self, -1, _("Generate:")),
             self, -1,  
             _("Generate:")),  
119              0, wxALIGN_CENTER_VERTICAL, 0)              0, wxALIGN_CENTER_VERTICAL, 0)
120            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)  
121    
122          sizer.Add(psizer, 0, wxALL | wxGROW, 4)          sizer.Add(psizer, 0, wxALL | wxGROW, 4)
123    
124          #############          self.sizer_genPanel = wxBoxSizer(wxVERTICAL)
125            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  
126    
127          if self.type in (FIELDTYPE_INT, FIELDTYPE_DOUBLE):          psizer = wxBoxSizer(wxHORIZONTAL)
128              panel = GenUniformPanel(self, layer, fieldName, self.type)          psizer.Add(wxStaticText(self, -1, _("Color Scheme:")),
129              self.genCombo.Append(COMBOSTR_UNIFORM)              0, wxALIGN_CENTER_VERTICAL, 0)
130              self.genCombo.SetClientData(self.genCombo.GetCount() - 1, panel)          psizer.Add(self.propCombo, 1, wxALL | wxGROW, 4)
131              sizer.Add(panel, 0, wxGROW | wxALL, 4)          sizer.Add(psizer, 0, wxALL | wxGROW, 4)
             sizer.Show(panel, False)  
   
         #############  
   
         self.propPanel = None  
   
         panel = CustomRampPanel(self, layer.ShapeType())  
   
         self.propPanel = panel  
   
         sizer.Add(panel, 1, wxALL | wxGROW, 4)  
132    
133          #############          sizer.Add(custom_ramp_panel, 1, wxGROW | wxALL, 4)
134            sizer.Show(custom_ramp_panel, False)
135    
136            buttonSizer = wxBoxSizer(wxHORIZONTAL)
137            buttonSizer.Add(self.genButton, 0, wxALL, 4)
138            buttonSizer.Add(60, 20, 0, wxALL, 4)
139            buttonSizer.Add(wxButton(self, wxID_CANCEL, _("Close")),
140                            0, wxALL, 4)
141          sizer.Add(buttonSizer, 0,          sizer.Add(buttonSizer, 0,
142                    wxALL | wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL, 4)                    wxALL | wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL, 4)
143    
   
144          self.SetSizer(sizer)          self.SetSizer(sizer)
145          self.SetAutoLayout(True)          self.SetAutoLayout(True)
146          sizer.SetSizeHints(self)          sizer.SetSizeHints(self)
147    
148          self.sizer = sizer          self.topBox = sizer
149    
150            self.__DoOnGenTypeSelect()
151    
152            EVT_CHOICE(self, ID_CLASSGEN_GENCOMBO, self._OnGenTypeSelect)
153            EVT_CHOICE(self, ID_CLASSGEN_PROPCOMBO, self._OnPropTypeSelect)
154            EVT_BUTTON(self, wxID_OK, self.OnOK)
155            EVT_BUTTON(self, wxID_CANCEL, self.OnCancel)
156    
157          EVT_BUTTON(self, ID_CLASSGEN_GEN, self._OnGenerate)          self.__DoOnGenTypeSelect()
158          EVT_BUTTON(self, ID_CLASSGEN_CLOSE, self._OnCloseBtn)  
159            self.genChoice.SetFocus()
160    
161      def GetClassification(self):      def GetClassification(self):
162          return self.clazz          return self.clazz
# Line 130  class ClassGenDialog(wxDialog): Line 164  class ClassGenDialog(wxDialog):
164      def AllowGenerate(self, on):      def AllowGenerate(self, on):
165          pass #self.genButton.Enable(on)          pass #self.genButton.Enable(on)
166    
167      def _OnGenerate(self, event):      def OnOK(self, event):
168            """This is really the generate button, but we want to override
169            the wxDialog class.
170            """
171    
172            index = self.genChoice.GetSelection()
173    
174          selIndex = self.genCombo.GetSelection()          assert index != -1, "button should be disabled!"
175    
176            genSel = self.genChoice.GetString(index)
177            clazz, genPanel = self.genChoice.GetClientData(index)
178    
         sel = self.genCombo.GetString(selIndex)  
         genPanel = self.genCombo.GetClientData(selIndex)  
179          propPanel = self.propPanel          propPanel = self.propPanel
180    
181          if sel == COMBOSTR_UNIFORM:          if genSel in (GENCOMBOSTR_UNIFORM,          \
182                          GENCOMBOSTR_UNIQUE,           \
183                          GENCOMBOSTR_QUANTILES):
184    
             min = genPanel.GetMin()  
             max = genPanel.GetMax()  
185              numGroups = genPanel.GetNumGroups()              numGroups = genPanel.GetNumGroups()
             sp = propPanel.GetStartProperties()  
             ep = propPanel.GetEndProperties()  
186    
187              if min is not None \              index = self.propCombo.GetSelection()
                 and max is not None \  
                 and numGroups is not None:  
188    
189                  self.clazz = ClassGenerator().GenUnifromDistribution(              propSel = self.propCombo.GetString(index)
190                               min, max, numGroups, sp, ep,              propPanel = self.propCombo.GetClientData(index)
                              self.type == FIELDTYPE_INT)  
191    
192                  self.parent._SetClassification(self.clazz)              ramp = propPanel.GetRamp()
193    
194          elif sel == COMBOSTR_UNIQUE:              if genSel == GENCOMBOSTR_UNIFORM:
195    
196              list = genPanel.GetValueList()                  min = genPanel.GetMin()
197              numGroups = genPanel.GetNumGroups()                  max = genPanel.GetMax()
             sp = propPanel.GetStartProperties()  
             ep = propPanel.GetEndProperties()  
198    
199              if len(list) > 0 \                  if min is not None \
200                  and numGroups is not None:                      and max is not None \
201                        and numGroups is not None:
202    
203                  self.clazz = ClassGenerator().GenSingletonsFromList(                      self.clazz = ClassGenerator().GenUnifromDistribution(
204                                  list, numGroups, sp, ep)                                  min, max, numGroups, ramp,
205                                    self.type == FIELDTYPE_INT)
206    
207                  self.parent._SetClassification(self.clazz)                      self.parent._SetClassification(self.clazz)
208    
209          else:              elif genSel == GENCOMBOSTR_UNIQUE:
210              pass  
211                    list = genPanel.GetValueList()
212    
213                    if len(list) > 0 \
214                        and numGroups is not None:
215    
216                        self.clazz = ClassGenerator().GenSingletonsFromList(
217                                        list, numGroups, ramp)
218    
219                        self.parent._SetClassification(self.clazz)
220    
221                elif genSel == GENCOMBOSTR_QUANTILES:
222    
223                    _range = genPanel.GetRange()
224                    _list = genPanel.GetList()
225                    _list.sort()
226    
227      def _OnCloseBtn(self, event):                  delta = 1 / float(numGroups)
228                    percents = [delta * i for i in range(1, numGroups + 1)]
229                    adjusted, self.clazz = \
230                        ClassGenerator().GenQuantiles(_list, percents, ramp, _range)
231    
232                    if adjusted:
233                        dlg = wxMessageDialog(self,
234                            _("Based on the data from the table and the input\n" +
235                              "values, the exact quantiles could not be generated.\n\n" +
236                              "Accept a close estimate?"),
237                            _("Problem with Quantiles"),
238    
239                            wxYES_NO|wxYES_DEFAULT|wxICON_QUESTION)
240                        if dlg.ShowModal() == wxID_YES:
241                            self.parent._SetClassification(self.clazz)
242                    else:
243                        self.parent._SetClassification(self.clazz)
244    
245        def OnCancel(self, event):
246          self.Close()          self.Close()
247    
248      def _OnGenTypeSelect(self, event):      def _OnGenTypeSelect(self, event):
249            self.__DoOnGenTypeSelect()
250            return
251    
252          combo = event.GetEventObject()          combo = event.GetEventObject()
253    
254          selIndex = combo.GetSelection()          selIndex = combo.GetSelection()
255    
256          if self.genPanel is not None:          if self.genPanel is not None:
257              self.sizer.Show(self.genPanel, False)              self.topBox.Show(self.genPanel, False)
258    
259          self.genPanel = combo.GetClientData(selIndex)          self.genPanel = combo.GetClientData(selIndex)
260          if self.genPanel is not None:          if self.genPanel is not None:
261              self.sizer.Show(self.genPanel, True)              self.topBox.Show(self.genPanel, True)
262    
263            self.topBox.SetSizeHints(self)
264            self.topBox.Layout()
265    
266        def _OnPropTypeSelect(self, event):
267            combo = event.GetEventObject()
268    
269          self.sizer.SetSizeHints(self)          selIndex = combo.GetSelection()
270          self.sizer.Layout()          sel = combo.GetString(selIndex)
271    
272            if isinstance(self.propPanel, wxPanel):
273                self.topBox.Show(self.propPanel, False)
274    
275            self.propPanel = combo.GetClientData(selIndex)
276    
277            if isinstance(self.propPanel, wxPanel):
278                self.topBox.Show(self.propPanel, True)
279    
280            self.topBox.SetSizeHints(self)
281            self.topBox.Layout()
282    
283        def __DoOnGenTypeSelect(self):
284            choice = self.genChoice
285    
286            sel = choice.GetSelection()
287            if sel == -1: return
288    
289            clazz, obj = choice.GetClientData(sel)
290    
291            if obj is None:
292                obj = clazz(self, self.layer, self.fieldName, self.fieldType)
293                choice.SetClientData(sel, [clazz, obj])
294    
295            if self.curGenPanel is not None:
296                self.curGenPanel.Hide()
297                self.sizer_genPanel.Remove(self.curGenPanel)
298    
299            self.curGenPanel = obj
300            self.curGenPanel.Show()
301    
302            self.sizer_genPanel.Add(self.curGenPanel, 1,
303                wxALL|wxEXPAND|wxADJUST_MINSIZE, 3)
304            self.sizer_genPanel.Layout()
305            self.Layout()
306            self.topBox.SetSizeHints(self)
307    
308  ID_UNIFORM_MIN = 4001  ID_UNIFORM_MIN = 4001
309  ID_UNIFORM_MAX = 4002  ID_UNIFORM_MAX = 4002
# Line 238  class GenUniformPanel(wxPanel): Line 349  class GenUniformPanel(wxPanel):
349          sizer = wxBoxSizer(wxHORIZONTAL)          sizer = wxBoxSizer(wxHORIZONTAL)
350    
351          sizer.Add(wxStaticText(self, -1, _("Number of Groups:")), 0, wxALL, 4)          sizer.Add(wxStaticText(self, -1, _("Number of Groups:")), 0, wxALL, 4)
352          self.numGroupsCtrl = wxSpinCtrl(self, ID_UNIFORM_NGROUPS, style=wxTE_RIGHT)          self.numGroupsCtrl = wxSpinCtrl(self, ID_UNIFORM_NGROUPS,
353                                            style=wxTE_RIGHT)
354          EVT_TEXT(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)          EVT_TEXT(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)
355          EVT_SPINCTRL(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)          EVT_SPINCTRL(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)
356          sizer.Add(self.numGroupsCtrl, 1, wxALL, 4)          sizer.Add(self.numGroupsCtrl, 1, wxALL, 4)
# Line 259  class GenUniformPanel(wxPanel): Line 371  class GenUniformPanel(wxPanel):
371          self.numGroupsChanging = False          self.numGroupsChanging = False
372          self.steppingChanging = False          self.steppingChanging = False
373    
374          self.numGroupsCtrl.SetRange(1, 100)          self.numGroupsCtrl.SetRange(1, sys.maxint)
375    
376          self.numGroupsCtrl.SetValue(1)          self.numGroupsCtrl.SetValue(1)
377          self.stepCtrl.SetValue("1")          self.stepCtrl.SetValue("1")
# Line 309  class GenUniformPanel(wxPanel): Line 421  class GenUniformPanel(wxPanel):
421          self.numGroupsCtrl.Enable(on)          self.numGroupsCtrl.Enable(on)
422          self.stepCtrl.Enable(on)          self.stepCtrl.Enable(on)
423    
         if on:  
             self.numGroupsCtrl.SetRange(1, abs(max - min) / 0.001)  
   
424          ngroups = self.GetNumGroups()          ngroups = self.GetNumGroups()
425    
426          if ngroups is not None  \          if ngroups is not None  \
# Line 342  class GenUniformPanel(wxPanel): Line 451  class GenUniformPanel(wxPanel):
451          min = self.GetMin()          min = self.GetMin()
452          max = self.GetMax()          max = self.GetMax()
453    
         if ngroups >= self.numGroupsCtrl.GetMax():  
             self.numGroupsCtrl.SetRange(1, ngroups + 1)  
   
454          if ngroups is not None  \          if ngroups is not None  \
455              and min is not None \              and min is not None \
456              and max is not None \              and max is not None \
# Line 393  class GenUniformPanel(wxPanel): Line 499  class GenUniformPanel(wxPanel):
499      def _OnRetrieve(self, event):      def _OnRetrieve(self, event):
500    
501          if self.layer.table is not None:          if self.layer.table is not None:
502              range = self.layer.table.field_range(self.fieldName)              wxBeginBusyCursor()
503              self.minCtrl.SetValue(str(range[0][0]))              min, max = self.layer.table.ValueRange(self.fieldName)
504              self.maxCtrl.SetValue(str(range[1][0]))              self.minCtrl.SetValue(str(min))
505                self.maxCtrl.SetValue(str(max))
506                wxEndBusyCursor()
507    
508      def __GetValidatedTypeEntry(self, win, value, type, badValue = None):      def __GetValidatedTypeEntry(self, win, value, type, badValue = None):
509    
# Line 437  class GenUniformPanel(wxPanel): Line 545  class GenUniformPanel(wxPanel):
545          return valid          return valid
546    
547      def __CalcStepping(self, min, max, ngroups):      def __CalcStepping(self, min, max, ngroups):
548          step = Str2Num(str((max - min) / float(ngroups)))          step = (max - min) / float(ngroups)
549          if self.fieldType == FIELDTYPE_INT:          if self.fieldType == FIELDTYPE_INT:
550              step = int(step)              step = int(step)
551    
# Line 461  ID_UNIQUE_DONTUSE = 4004 Line 569  ID_UNIQUE_DONTUSE = 4004
569  ID_UNIQUE_USENONE = 4005  ID_UNIQUE_USENONE = 4005
570  ID_UNIQUE_SORTAVAIL = 4006  ID_UNIQUE_SORTAVAIL = 4006
571  ID_UNIQUE_SORTUSE = 4007  ID_UNIQUE_SORTUSE = 4007
572    ID_UNIQUE_REVAVAIL = 4008
573    ID_UNIQUE_REVUSE = 4009
574    
575  class GenUniquePanel(wxPanel):  class GenUniquePanel(wxPanel):
576    
# Line 476  class GenUniquePanel(wxPanel): Line 586  class GenUniquePanel(wxPanel):
586                                      wxVERTICAL)                                      wxVERTICAL)
587    
588    
589            #bsizer = wxBoxSizer(wxVERTICAL)
590            topSizer.Add(wxButton(self, ID_UNIQUE_RETRIEVE,
591                                _("Retrieve From Table")),
592                       0, wxALL | wxALIGN_RIGHT, 4)
593    
594            EVT_BUTTON(self, ID_UNIQUE_RETRIEVE, self._OnRetrieve)
595    
596            #topSizer.Add(bsizer, 0, wxALL, 4)
597    
598          sizer = wxBoxSizer(wxHORIZONTAL)          sizer = wxBoxSizer(wxHORIZONTAL)
599    
600          self.dataList = []          self.dataList = []
# Line 487  class GenUniquePanel(wxPanel): Line 606  class GenUniquePanel(wxPanel):
606          self.list_avail_data = []          self.list_avail_data = []
607          psizer.Add(self.list_avail, 1, wxGROW, 0)          psizer.Add(self.list_avail, 1, wxGROW, 0)
608    
609          psizer.Add(wxButton(self, ID_UNIQUE_SORTAVAIL, _("Sort")))          bsizer = wxBoxSizer(wxHORIZONTAL)
610            bsizer.Add(wxButton(self, ID_UNIQUE_SORTAVAIL, _("Sort")))
611            EVT_BUTTON(self, ID_UNIQUE_SORTAVAIL, self._OnSortList)
612    
613          EVT_BUTTON(self, ID_UNIQUE_SORTAVAIL, self._OnSortAvailList)          bsizer.Add(wxButton(self, ID_UNIQUE_REVAVAIL, _("Reverse")))
614            EVT_BUTTON(self, ID_UNIQUE_REVAVAIL, self._OnReverseList)
615    
616            psizer.Add(bsizer, 0, wxGROW, 0)
617          sizer.Add(psizer, 1, wxGROW, 0)          sizer.Add(psizer, 1, wxGROW, 0)
618    
619                    
620          bsizer = wxBoxSizer(wxVERTICAL)          bsizer = wxBoxSizer(wxVERTICAL)
621          bsizer.Add(wxButton(self, ID_UNIQUE_USEALL, _("Use All")),  
622            bmp = resource.GetBitmapResource(USEALL_BMP, wxBITMAP_TYPE_XPM)
623            bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USEALL, bmp),
624                     0, wxGROW | wxALL, 4)                     0, wxGROW | wxALL, 4)
625          bsizer.Add(wxButton(self, ID_UNIQUE_USE, _("Use >>")),          bmp = resource.GetBitmapResource(USE_BMP, wxBITMAP_TYPE_XPM)
626            bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USE, bmp),
627                     0, wxGROW | wxALL, 4)                     0, wxGROW | wxALL, 4)
628          bsizer.Add(wxButton(self, ID_UNIQUE_DONTUSE, _("<< Don't Use")),          bmp = resource.GetBitmapResource(USENOT_BMP, wxBITMAP_TYPE_XPM)
629            bsizer.Add(wxBitmapButton(self, ID_UNIQUE_DONTUSE, bmp),
630                     0, wxGROW | wxALL, 4)                     0, wxGROW | wxALL, 4)
631          bsizer.Add(wxButton(self, ID_UNIQUE_USENONE, _("Use None")),          bmp = resource.GetBitmapResource(USENONE_BMP, wxBITMAP_TYPE_XPM)
632            bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USENONE, bmp),
633                     0, wxGROW | wxALL, 4)                     0, wxGROW | wxALL, 4)
634    
635          EVT_BUTTON(self, ID_UNIQUE_USEALL, self._OnUseAll)          EVT_BUTTON(self, ID_UNIQUE_USEALL, self._OnUseAll)
# Line 518  class GenUniquePanel(wxPanel): Line 646  class GenUniquePanel(wxPanel):
646          self.list_use_data = []          self.list_use_data = []
647          psizer.Add(self.list_use, 1, wxGROW, 0)          psizer.Add(self.list_use, 1, wxGROW, 0)
648    
649          psizer.Add(wxButton(self, ID_UNIQUE_SORTUSE, _("Sort")))          bsizer = wxBoxSizer(wxHORIZONTAL)
650            bsizer.Add(wxButton(self, ID_UNIQUE_SORTUSE, _("Sort")))
651            EVT_BUTTON(self, ID_UNIQUE_SORTUSE, self._OnSortList)
652    
653          EVT_BUTTON(self, ID_UNIQUE_SORTUSE, self._OnSortUseList)          bsizer.Add(wxButton(self, ID_UNIQUE_REVUSE, _("Reverse")))
654            EVT_BUTTON(self, ID_UNIQUE_REVUSE, self._OnReverseList)
655    
656          sizer.Add(psizer, 1, wxGROW, 0)          psizer.Add(bsizer, 0, wxGROW, 0)
657    
658          bsizer = wxBoxSizer(wxVERTICAL)          sizer.Add(psizer, 1, wxGROW, 0)
         bsizer.Add(wxButton(self, ID_UNIQUE_RETRIEVE,  
                             _("Retrieve From Table")),  
                    0, wxGROW | wxALL, 4)  
   
         EVT_BUTTON(self, ID_UNIQUE_RETRIEVE, self._OnRetrieve)  
659    
         sizer.Add(bsizer, 0, wxALL, 4)  
660    
661          topSizer.Add(sizer, 1, wxGROW, 0)          topSizer.Add(sizer, 1, wxGROW, 0)
662    
# Line 541  class GenUniquePanel(wxPanel): Line 666  class GenUniquePanel(wxPanel):
666    
667          self.parent.AllowGenerate(False)          self.parent.AllowGenerate(False)
668    
         self.mylist = ["Hallo", "Welt!", "Wie", "geht", "es", "dir", "?"]  
   
669      def GetNumGroups(self):      def GetNumGroups(self):
670          return self.list_use.GetItemCount()          return self.list_use.GetItemCount()
671    
# Line 552  class GenUniquePanel(wxPanel): Line 675  class GenUniquePanel(wxPanel):
675              list.append(self.dataList[self.list_use.GetItemData(i)])              list.append(self.dataList[self.list_use.GetItemData(i)])
676          return list          return list
677    
678      def _OnSortAvailList(self, event):      def _OnSortList(self, event):
679          self.list_avail.SortItems(lambda i1, i2:          id = event.GetId()
680                                      cmp(self.dataList[i1],  
681                                          self.dataList[i2]))          if id == ID_UNIQUE_SORTUSE:
682                list = self.list_use
683      def _OnSortUseList(self, event):          else:
684          self.list_use.SortItems(lambda i1, i2:              list = self.list_avail
685                                      cmp(self.dataList[i1],  
686                                          self.dataList[i2]))          list.SortItems(lambda i1, i2: cmp(self.dataList[i1],
687                                              self.dataList[i2]))
688    
689        def _OnReverseList(self, event):
690            id = event.GetId()
691    
692            if id == ID_UNIQUE_REVUSE:
693                list = self.list_use
694            else:
695                list = self.list_avail
696    
697            #
698            # always returning 1 reverses the list
699            #
700            list.SortItems(lambda i1, i2: 1)
701    
702      def _OnRetrieve(self, event):      def _OnRetrieve(self, event):
703          self.list_use.DeleteAllItems()          self.list_use.DeleteAllItems()
# Line 568  class GenUniquePanel(wxPanel): Line 705  class GenUniquePanel(wxPanel):
705          self.list_avail.DeleteAllItems()          self.list_avail.DeleteAllItems()
706          self.list_avail_data = []          self.list_avail_data = []
707    
708          list = self.layer.table.GetUniqueValues(self.fieldName)          list = self.layer.table.UniqueValues(self.fieldName)
709          index = 0          index = 0
710          for v in list:          for v in list:
711              self.dataList.append(v)              self.dataList.append(v)
# Line 583  class GenUniquePanel(wxPanel): Line 720  class GenUniquePanel(wxPanel):
720              self.__MoveListItem(0, self.list_avail, self.list_use)              self.__MoveListItem(0, self.list_avail, self.list_use)
721    
722      def _OnUse(self, event):      def _OnUse(self, event):
         print "_OnUse"  
723          self.__MoveSelectedItems(self.list_avail, self.list_use)          self.__MoveSelectedItems(self.list_avail, self.list_use)
724    
725      def _OnDontUse(self, event):      def _OnDontUse(self, event):
         print "_OnDontUse"  
726          self.__MoveSelectedItems(self.list_use, self.list_avail)          self.__MoveSelectedItems(self.list_use, self.list_avail)
727    
728      def _OnUseNone(self, event):      def _OnUseNone(self, event):
         print "_OnUseNone"  
729    
730          for i in range(self.list_use.GetItemCount()):          for i in range(self.list_use.GetItemCount()):
731              self.__MoveListItem(0, self.list_use, self.list_avail)              self.__MoveListItem(0, self.list_use, self.list_avail)
# Line 626  class GenUniquePanel(wxPanel): Line 760  class GenUniquePanel(wxPanel):
760  #       list.SetColumnWidth(0, event.GetSize().GetWidth())  #       list.SetColumnWidth(0, event.GetSize().GetWidth())
761  #        #      
762    
763    ID_QUANTILES_RANGE = 4001
764    ID_QUANTILES_RETRIEVE = 4002
765    
766    class GenQuantilesPanel(wxPanel):
767    
768        def __init__(self, parent, layer, fieldName, fieldType):
769            wxPanel.__init__(self, parent, -1)
770    
771            self.parent = parent
772            self.layer = layer
773            self.fieldName = fieldName
774            self.fieldType = fieldType
775    
776            topBox = wxStaticBoxSizer(wxStaticBox(self, -1, ""),
777                                        wxVERTICAL)
778    
779            self.text_range = wxTextCtrl(self, ID_QUANTILES_RANGE, "")
780            self.button_retrieve = wxButton(self, ID_QUANTILES_RETRIEVE,
781                                            _("Retrieve from Table"))
782    
783            self.spin_numClasses = wxSpinCtrl(self, -1, style=wxTE_RIGHT)
784            self.spin_numClasses.SetRange(1, sys.maxint)
785            self.spin_numClasses.SetValue(1)
786    
787    
788            sizer = wxBoxSizer(wxHORIZONTAL)
789            sizer.Add(wxStaticText(self, -1, _("Apply to Range")), 0, wxALL, 4)
790            sizer.Add(self.text_range, 1, wxALL, 4)
791            sizer.Add(self.button_retrieve, 0, wxALL, 4)
792    
793            topBox.Add(sizer, 0, wxEXPAND, 0)
794    
795            sizer = wxBoxSizer(wxHORIZONTAL)
796            sizer.Add(wxStaticText(self, -1, _("Number of Classes:")), 0, wxALL, 4)
797            sizer.Add(self.spin_numClasses, 1, wxALL, 4)
798    
799            topBox.Add(sizer, 0, wxEXPAND, 0)
800    
801            self.SetSizer(topBox)
802            self.SetAutoLayout(True)
803            topBox.Fit(self)
804            topBox.SetSizeHints(self)
805    
806            EVT_TEXT(self, ID_QUANTILES_RANGE, self.OnRangeText)
807            EVT_BUTTON(self, ID_QUANTILES_RETRIEVE, self.OnRetrieve)
808    
809            self.__range = None
810    
811        def GetNumGroups(self):
812            return self.spin_numClasses.GetValue()
813    
814        def GetRange(self):
815            assert self.__range is not None
816    
817            return self.__range
818    
819        def GetList(self):
820    
821            _list = []
822    
823            if self.layer.table is not None:
824                wxBeginBusyCursor()
825    
826                #
827                # FIXME: Replace with a call to table when the method
828                # has been written to get all the values
829                #
830                table = self.layer.table
831                for i in range(table.NumRows()):
832                    _list.append(table.ReadValue(i, self.fieldName))
833    
834                wxEndBusyCursor()
835    
836            return _list
837    
838        def OnRangeText(self, event):
839    
840            try:
841                self.__range = Range(self.text_range.GetValue())
842            except ValueError:
843                self.__range = None
844    
845            if self.__range is not None:
846                self.text_range.SetForegroundColour(wxBLACK)
847            else:
848                self.text_range.SetForegroundColour(wxRED)
849    
850        def OnRetrieve(self, event):
851    
852            if self.layer.table is not None:
853                wxBeginBusyCursor()
854                min, max = self.layer.table.ValueRange(self.fieldName)
855                self.text_range.SetValue("[" + str(min) + ";" + str(max) + "]")
856                wxEndBusyCursor()
857    
858  ID_CUSTOMRAMP_COPYSTART = 4001  ID_CUSTOMRAMP_COPYSTART = 4001
859  ID_CUSTOMRAMP_COPYEND = 4002  ID_CUSTOMRAMP_COPYEND = 4002
860  ID_CUSTOMRAMP_EDITSTART = 4003  ID_CUSTOMRAMP_EDITSTART = 4003
# Line 657  class CustomRampPanel(wxPanel): Line 886  class CustomRampPanel(wxPanel):
886                        | wxALIGN_CENTER_VERTICAL, \                        | wxALIGN_CENTER_VERTICAL, \
887                     4)                     4)
888    
889            bmp = resource.GetBitmapResource(USE_BMP, wxBITMAP_TYPE_XPM)
890          bsizer = wxBoxSizer(wxVERTICAL)          bsizer = wxBoxSizer(wxVERTICAL)
891          bsizer.Add(wxButton(self, ID_CUSTOMRAMP_COPYSTART, _("Copy >>")),          bsizer.Add(wxBitmapButton(self, ID_CUSTOMRAMP_COPYSTART, bmp),
892                     0, wxGROW | wxALL, 4)                     0, wxGROW | wxALL, 4)
893          bsizer.Add(wxButton(self, ID_CUSTOMRAMP_COPYEND, _("<< Copy")),          bmp = resource.GetBitmapResource(USENOT_BMP, wxBITMAP_TYPE_XPM)
894            bsizer.Add(wxBitmapButton(self, ID_CUSTOMRAMP_COPYEND, bmp),
895                     0, wxGROW | wxALL, 4)                     0, wxGROW | wxALL, 4)
896    
897          topSizer.Add(bsizer,          topSizer.Add(bsizer,
# Line 696  class CustomRampPanel(wxPanel): Line 927  class CustomRampPanel(wxPanel):
927          self.SetAutoLayout(True)          self.SetAutoLayout(True)
928          topSizer.SetSizeHints(self)          topSizer.SetSizeHints(self)
929    
930      def GetStartProperties(self):      def GetRamp(self):
931          return self.startPropCtrl.GetProperties()          return CustomRamp(self.startPropCtrl.GetProperties(),
932                              self.endPropCtrl.GetProperties())
     def GetEndProperties(self):  
         return self.endPropCtrl.GetProperties()  
933    
934      def _OnCopyStart(self, event):      def _OnCopyStart(self, event):
935          self.endPropCtrl.SetProperties(self.startPropCtrl.GetProperties())          self.endPropCtrl.SetProperties(self.startPropCtrl.GetProperties())
# Line 714  class CustomRampPanel(wxPanel): Line 943  class CustomRampPanel(wxPanel):
943      def _OnEditEnd(self, event):      def _OnEditEnd(self, event):
944          self.endPropCtrl.DoEdit()          self.endPropCtrl.DoEdit()
945    
946  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.898

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26