/[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 654 by jonathan, Fri Apr 11 15:49:58 2003 UTC revision 1274 by jonathan, Fri Jun 20 17:46:04 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  
   
 import resource  
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_GENCOMBO = 4007      CustomRamp, GreyRamp, RedRamp, GreenRamp, BlueRamp, GreenToRedRamp, \
27  ID_CLASSGEN_PROPCOMBO = 4008      HotToColdRamp
28    
29  USEALL_BMP  = "group_use_all"  USEALL_BMP  = "group_use_all"
30  USE_BMP     = "group_use"  USE_BMP     = "group_use"
# Line 35  USENONE_BMP = "group_use_none" Line 33  USENONE_BMP = "group_use_none"
33    
34  GENCOMBOSTR_UNIFORM = _("Uniform Distribution")  GENCOMBOSTR_UNIFORM = _("Uniform Distribution")
35  GENCOMBOSTR_UNIQUE = _("Unique Values")  GENCOMBOSTR_UNIQUE = _("Unique Values")
36    GENCOMBOSTR_QUANTILES = _("Quantiles from Table")
37    
38  PROPCOMBOSTR_CUSTOM     = _("Custom Ramp")  PROPCOMBOSTR_CUSTOM     = _("Custom Ramp")
39  PROPCOMBOSTR_GREY       = _("Grey Ramp")  PROPCOMBOSTR_GREY       = _("Grey Ramp")
40  PROPCOMBOSTR_RED        = _("Red Ramp")  PROPCOMBOSTR_RED        = _("Red Ramp")
41  PROPCOMBOSTR_GREEN      = _("Green Ramp")  PROPCOMBOSTR_GREEN      = _("Green Ramp")
42  PROPCOMBOSTR_BLUE       = _("Blue Ramp")  PROPCOMBOSTR_BLUE       = _("Blue Ramp")
43    PROPCOMBOSTR_GREEN2RED  = _("Green-to-Red Ramp")
44  PROPCOMBOSTR_HOT2COLD   = _("Hot-to-Cold Ramp")  PROPCOMBOSTR_HOT2COLD   = _("Hot-to-Cold Ramp")
45    
46    ID_CLASSGEN_GENCOMBO = 4007
47    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 53  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.genButton.SetDefault()
80            self.cancelButton = wxButton(self, wxID_CANCEL, _("Close"))
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 85  class ClassGenDialog(wxDialog): Line 114  class ClassGenDialog(wxDialog):
114          psizer = wxBoxSizer(wxHORIZONTAL)          psizer = wxBoxSizer(wxHORIZONTAL)
115          psizer.Add(wxStaticText(self, -1, _("Generate:")),          psizer.Add(wxStaticText(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_GENCOMBO,  
                                    "", style = wxCB_READONLY)  
         psizer.Add(self.genCombo, 1, wxALL | wxGROW, 4)  
         EVT_COMBOBOX(self, ID_CLASSGEN_GENCOMBO, 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(GENCOMBOSTR_UNIQUE, panel)  
         sizer.Add(panel, 1, wxGROW | wxALL, 4)  
   
         self.genPanel = panel  
   
         if self.type in (FIELDTYPE_INT, FIELDTYPE_DOUBLE):  
             panel = GenUniformPanel(self, layer, fieldName, self.type)  
             self.genCombo.Append(GENCOMBOSTR_UNIFORM, panel)  
             sizer.Add(panel, 0, wxGROW | wxALL, 4)  
             sizer.Show(panel, False)  
   
         #############  
123    
124          psizer = wxBoxSizer(wxHORIZONTAL)          psizer = wxBoxSizer(wxHORIZONTAL)
125          psizer.Add(wxStaticText(self, -1, _("Color Schemes:")),          psizer.Add(wxStaticText(self, -1, _("Color Scheme:")),
126              0, wxALIGN_CENTER_VERTICAL, 0)              0, wxALIGN_CENTER_VERTICAL, 0)
127    
128          self.propCombo = wxComboBox(self,          # Properties (Ramp) ComboBox
129                                     ID_CLASSGEN_PROPCOMBO,          self.propCombo = wxChoice(self, ID_CLASSGEN_PROPCOMBO)
                                    "", style = wxCB_READONLY)  
         psizer.Add(self.propCombo, 1, wxALL | wxGROW, 4)  
         EVT_COMBOBOX(self, ID_CLASSGEN_PROPCOMBO, self._OnPropTypeSelect)  
         sizer.Add(psizer, 0, wxALL | wxGROW, 4)  
   
         #############  
130    
131          self.propPanel = None          self.propPanel = None
132          panel = CustomRampPanel(self, layer.ShapeType())          custom_ramp_panel = CustomRampPanel(self, layer.ShapeType())
         sizer.Add(panel, 1, wxALL | wxGROW, 4)  
         sizer.Show(panel, False)  
133    
134          self.propCombo.Append(PROPCOMBOSTR_GREY,  GreyRamp())          self.propCombo.Append(PROPCOMBOSTR_GREY,  GreyRamp())
135          self.propCombo.Append(PROPCOMBOSTR_RED,   RedRamp())          self.propCombo.Append(PROPCOMBOSTR_RED,   RedRamp())
136          self.propCombo.Append(PROPCOMBOSTR_GREEN, GreenRamp())          self.propCombo.Append(PROPCOMBOSTR_GREEN, GreenRamp())
137          self.propCombo.Append(PROPCOMBOSTR_BLUE,  BlueRamp())          self.propCombo.Append(PROPCOMBOSTR_BLUE,  BlueRamp())
138            self.propCombo.Append(PROPCOMBOSTR_GREEN2RED, GreenToRedRamp())
139          self.propCombo.Append(PROPCOMBOSTR_HOT2COLD,  HotToColdRamp())          self.propCombo.Append(PROPCOMBOSTR_HOT2COLD,  HotToColdRamp())
140          self.propCombo.Append(PROPCOMBOSTR_CUSTOM, panel)          self.propCombo.Append(PROPCOMBOSTR_CUSTOM, custom_ramp_panel)
   
141    
142            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          EVT_BUTTON(self, ID_CLASSGEN_GEN, self._OnGenerate)          self.__DoOnGenTypeSelect()
163          EVT_BUTTON(self, ID_CLASSGEN_CLOSE, self._OnCloseBtn)  
164            EVT_CHOICE(self, ID_CLASSGEN_GENCOMBO, self._OnGenTypeSelect)
165            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 160  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            index = self.genChoice.GetSelection()
185    
186          index = self.genCombo.GetSelection()          assert index != -1, "button should be disabled!"
187    
188          genSel = self.genCombo.GetString(index)          genSel = self.genChoice.GetString(index)
189          genPanel = self.genCombo.GetClientData(index)          clazz, genPanel = self.genChoice.GetClientData(index)
190    
191          propPanel = self.propPanel          propPanel = self.propPanel
192    
193          if genSel in (GENCOMBOSTR_UNIFORM, GENCOMBOSTR_UNIQUE):          if genSel in (GENCOMBOSTR_UNIFORM,          \
194                          GENCOMBOSTR_UNIQUE,           \
195                          GENCOMBOSTR_QUANTILES):
196    
197              numGroups = genPanel.GetNumGroups()              numGroups = genPanel.GetNumGroups()
198    
199              index = self.propCombo.GetSelection()              index = self.propCombo.GetSelection()
# Line 188  class ClassGenDialog(wxDialog): Line 212  class ClassGenDialog(wxDialog):
212                      and max is not None \                      and max is not None \
213                      and numGroups is not None:                      and numGroups is not None:
214    
215                      self.clazz = ClassGenerator().GenUnifromDistribution(                      self.clazz = generate_uniform_distribution(
216                                  min, max, numGroups, ramp,                                  min, max, numGroups, ramp,
217                                  self.type == FIELDTYPE_INT)                                  self.type == FIELDTYPE_INT)
218    
# Line 201  class ClassGenDialog(wxDialog): Line 225  class ClassGenDialog(wxDialog):
225                  if len(list) > 0 \                  if len(list) > 0 \
226                      and numGroups is not None:                      and numGroups is not None:
227    
228                      self.clazz = ClassGenerator().GenSingletonsFromList(                      self.clazz = generate_singletons(
229                                      list, numGroups, ramp)                                      list, numGroups, ramp)
230    
231                      self.parent._SetClassification(self.clazz)                      self.parent._SetClassification(self.clazz)
232    
233      def _OnCloseBtn(self, event):              elif genSel == GENCOMBOSTR_QUANTILES:
234    
235                    _range = genPanel.GetRange()
236                    _list = genPanel.GetList()
237                    _list.sort()
238    
239                    delta = 1 / float(numGroups)
240                    percents = [delta * i for i in range(1, numGroups + 1)]
241                    adjusted, self.clazz = \
242                        generate_quantiles(_list, percents, ramp, _range)
243    
244                    if adjusted:
245                        dlg = wxMessageDialog(self,
246                            _("Based on the data from the table and the input\n" +
247                              "values, the exact quantiles could not be generated.\n\n" +
248                              "Accept a close estimate?"),
249                            _("Problem with Quantiles"),
250    
251                            wxYES_NO|wxYES_DEFAULT|wxICON_QUESTION)
252                        if dlg.ShowModal() == wxID_YES:
253                            self.parent._SetClassification(self.clazz)
254                    else:
255                        self.parent._SetClassification(self.clazz)
256    
257        def OnCancel(self, event):
258          self.Close()          self.Close()
259    
260      def _OnGenTypeSelect(self, event):      def _OnGenTypeSelect(self, event):
261            self.__DoOnGenTypeSelect()
262            return
263    
264          combo = event.GetEventObject()          combo = event.GetEventObject()
265    
266          selIndex = combo.GetSelection()          selIndex = combo.GetSelection()
267    
268          if self.genPanel is not None:          if self.genPanel is not None:
269              self.sizer.Show(self.genPanel, False)              self.topBox.Show(self.genPanel, False)
270    
271          self.genPanel = combo.GetClientData(selIndex)          self.genPanel = combo.GetClientData(selIndex)
272          if self.genPanel is not None:          if self.genPanel is not None:
273              self.sizer.Show(self.genPanel, True)              self.topBox.Show(self.genPanel, True)
274    
275          self.sizer.SetSizeHints(self)          self.topBox.SetSizeHints(self)
276          self.sizer.Layout()          self.topBox.Layout()
277    
278      def _OnPropTypeSelect(self, event):      def _OnPropTypeSelect(self, event):
279          combo = event.GetEventObject()          combo = event.GetEventObject()
# Line 232  class ClassGenDialog(wxDialog): Line 282  class ClassGenDialog(wxDialog):
282          sel = combo.GetString(selIndex)          sel = combo.GetString(selIndex)
283    
284          if isinstance(self.propPanel, wxPanel):          if isinstance(self.propPanel, wxPanel):
285              self.sizer.Show(self.propPanel, False)              self.topBox.Show(self.propPanel, False)
286    
287          self.propPanel = combo.GetClientData(selIndex)          self.propPanel = combo.GetClientData(selIndex)
288    
289          if isinstance(self.propPanel, wxPanel):          if isinstance(self.propPanel, wxPanel):
290              self.sizer.Show(self.propPanel, True)              self.topBox.Show(self.propPanel, True)
291    
292            self.topBox.SetSizeHints(self)
293            self.topBox.Layout()
294    
295        def __DoOnGenTypeSelect(self):
296            choice = self.genChoice
297    
298          self.sizer.SetSizeHints(self)          sel = choice.GetSelection()
299          self.sizer.Layout()          if sel == -1: return
300    
301            clazz, obj = choice.GetClientData(sel)
302    
303            if self.curGenPanel is not None:
304                self.curGenPanel.Hide()
305                self.sizer_genPanel.Remove(self.curGenPanel)
306    
307            self.curGenPanel = obj
308            self.curGenPanel.Show()
309    
310            self.sizer_genPanel.Add(self.curGenPanel, 1,
311                wxALL|wxEXPAND|wxADJUST_MINSIZE, 3)
312            self.sizer_genPanel.Layout()
313            self.Layout()
314            self.topBox.SetSizeHints(self)
315    
316  ID_UNIFORM_MIN = 4001  ID_UNIFORM_MIN = 4001
317  ID_UNIFORM_MAX = 4002  ID_UNIFORM_MAX = 4002
# Line 287  class GenUniformPanel(wxPanel): Line 357  class GenUniformPanel(wxPanel):
357          sizer = wxBoxSizer(wxHORIZONTAL)          sizer = wxBoxSizer(wxHORIZONTAL)
358    
359          sizer.Add(wxStaticText(self, -1, _("Number of Groups:")), 0, wxALL, 4)          sizer.Add(wxStaticText(self, -1, _("Number of Groups:")), 0, wxALL, 4)
360          self.numGroupsCtrl = wxSpinCtrl(self, ID_UNIFORM_NGROUPS, style=wxTE_RIGHT)          self.numGroupsCtrl = wxSpinCtrl(self, ID_UNIFORM_NGROUPS,
361                                            style=wxTE_RIGHT)
362          EVT_TEXT(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)          EVT_TEXT(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)
363          EVT_SPINCTRL(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)          EVT_SPINCTRL(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)
364          sizer.Add(self.numGroupsCtrl, 1, wxALL, 4)          sizer.Add(self.numGroupsCtrl, 1, wxALL, 4)
# Line 308  class GenUniformPanel(wxPanel): Line 379  class GenUniformPanel(wxPanel):
379          self.numGroupsChanging = False          self.numGroupsChanging = False
380          self.steppingChanging = False          self.steppingChanging = False
381    
382          self.numGroupsCtrl.SetRange(1, 100)          self.numGroupsCtrl.SetRange(1, sys.maxint)
383    
384          self.numGroupsCtrl.SetValue(1)          self.numGroupsCtrl.SetValue(1)
385          self.stepCtrl.SetValue("1")          self.stepCtrl.SetValue("1")
# Line 358  class GenUniformPanel(wxPanel): Line 429  class GenUniformPanel(wxPanel):
429          self.numGroupsCtrl.Enable(on)          self.numGroupsCtrl.Enable(on)
430          self.stepCtrl.Enable(on)          self.stepCtrl.Enable(on)
431    
         if on:  
             self.numGroupsCtrl.SetRange(1, abs(max - min) / 0.001)  
   
432          ngroups = self.GetNumGroups()          ngroups = self.GetNumGroups()
433    
434          if ngroups is not None  \          if ngroups is not None  \
# Line 391  class GenUniformPanel(wxPanel): Line 459  class GenUniformPanel(wxPanel):
459          min = self.GetMin()          min = self.GetMin()
460          max = self.GetMax()          max = self.GetMax()
461    
         if ngroups >= self.numGroupsCtrl.GetMax():  
             self.numGroupsCtrl.SetRange(1, ngroups + 1)  
   
462          if ngroups is not None  \          if ngroups is not None  \
463              and min is not None \              and min is not None \
464              and max is not None \              and max is not None \
# Line 440  class GenUniformPanel(wxPanel): Line 505  class GenUniformPanel(wxPanel):
505              self.parent.AllowGenerate(False)              self.parent.AllowGenerate(False)
506    
507      def _OnRetrieve(self, event):      def _OnRetrieve(self, event):
508            table = self.layer.ShapeStore().Table()
509          if self.layer.table is not None:          if table is not None:
510              range = self.layer.table.field_range(self.fieldName)              ThubanBeginBusyCursor()
511              self.minCtrl.SetValue(str(range[0][0]))              try:
512              self.maxCtrl.SetValue(str(range[1][0]))                  min, max = table.ValueRange(self.fieldName)
513                    self.minCtrl.SetValue(str(min))
514                    self.maxCtrl.SetValue(str(max))
515                finally:
516                    ThubanEndBusyCursor()
517    
518      def __GetValidatedTypeEntry(self, win, value, type, badValue = None):      def __GetValidatedTypeEntry(self, win, value, type, badValue = None):
519    
# Line 486  class GenUniformPanel(wxPanel): Line 555  class GenUniformPanel(wxPanel):
555          return valid          return valid
556    
557      def __CalcStepping(self, min, max, ngroups):      def __CalcStepping(self, min, max, ngroups):
         step = Str2Num(str((max - min) / float(ngroups)))  
558          if self.fieldType == FIELDTYPE_INT:          if self.fieldType == FIELDTYPE_INT:
559              step = int(step)              step = int((max - min + 1) / float(ngroups))
560            else:
561                step = (max - min) / float(ngroups)
562    
563          return step          return step
564    
# Line 605  class GenUniquePanel(wxPanel): Line 675  class GenUniquePanel(wxPanel):
675          self.SetAutoLayout(True)          self.SetAutoLayout(True)
676          topSizer.SetSizeHints(self)          topSizer.SetSizeHints(self)
677    
678          self.parent.AllowGenerate(False)          width, height = self.list_avail.GetSizeTuple()
679            self.list_avail.SetColumnWidth(0,width)
680            width, height = self.list_use.GetSizeTuple()
681            self.list_use.SetColumnWidth(0,width)
682    
683          self.mylist = ["Hallo", "Welt!", "Wie", "geht", "es", "dir", "?"]          self.parent.AllowGenerate(False)
684    
685      def GetNumGroups(self):      def GetNumGroups(self):
686          return self.list_use.GetItemCount()          return self.list_use.GetItemCount()
# Line 648  class GenUniquePanel(wxPanel): Line 721  class GenUniquePanel(wxPanel):
721          self.list_avail.DeleteAllItems()          self.list_avail.DeleteAllItems()
722          self.list_avail_data = []          self.list_avail_data = []
723    
724          list = self.layer.table.GetUniqueValues(self.fieldName)          ThubanBeginBusyCursor()
725          index = 0          try:
726          for v in list:              list = self.layer.ShapeStore().Table().UniqueValues(self.fieldName)
727              self.dataList.append(v)              index = 0
728              i = self.list_avail.InsertStringItem(index, str(v))              for v in list:
729              self.list_avail.SetItemData(index, i)                  self.dataList.append(v)
730                    i = self.list_avail.InsertStringItem(index, str(v))
731              self.list_avail_data.append(v)                  self.list_avail.SetItemData(index, i)
732              index += 1      
733                    self.list_avail_data.append(v)
734                    index += 1
735            finally:
736                ThubanEndBusyCursor()
737    
738      def _OnUseAll(self, event):      def _OnUseAll(self, event):
739          for i in range(self.list_avail.GetItemCount()):          for i in range(self.list_avail.GetItemCount()):
# Line 703  class GenUniquePanel(wxPanel): Line 780  class GenUniquePanel(wxPanel):
780  #       list.SetColumnWidth(0, event.GetSize().GetWidth())  #       list.SetColumnWidth(0, event.GetSize().GetWidth())
781  #        #      
782    
783    ID_QUANTILES_RANGE = 4001
784    ID_QUANTILES_RETRIEVE = 4002
785    
786    class GenQuantilesPanel(wxPanel):
787    
788        def __init__(self, parent, layer, fieldName, fieldType):
789            wxPanel.__init__(self, parent, -1)
790    
791            self.parent = parent
792            self.layer = layer
793            self.fieldName = fieldName
794            self.fieldType = fieldType
795    
796            topBox = wxStaticBoxSizer(wxStaticBox(self, -1, ""),
797                                        wxVERTICAL)
798    
799            self.text_range = wxTextCtrl(self, ID_QUANTILES_RANGE, "")
800            self.button_retrieve = wxButton(self, ID_QUANTILES_RETRIEVE,
801                                            _("Retrieve from Table"))
802    
803            self.spin_numClasses = wxSpinCtrl(self, -1, style=wxTE_RIGHT)
804            self.spin_numClasses.SetRange(1, sys.maxint)
805            self.spin_numClasses.SetValue(1)
806    
807    
808            sizer = wxBoxSizer(wxHORIZONTAL)
809            sizer.Add(wxStaticText(self, -1, _("Apply to Range")), 0, wxALL, 4)
810            sizer.Add(self.text_range, 1, wxALL, 4)
811            sizer.Add(self.button_retrieve, 0, wxALL, 4)
812    
813            topBox.Add(sizer, 0, wxEXPAND, 0)
814    
815            sizer = wxBoxSizer(wxHORIZONTAL)
816            sizer.Add(wxStaticText(self, -1, _("Number of Classes:")), 0, wxALL, 4)
817            sizer.Add(self.spin_numClasses, 1, wxALL, 4)
818    
819            topBox.Add(sizer, 0, wxEXPAND, 0)
820    
821            self.SetSizer(topBox)
822            self.SetAutoLayout(True)
823            topBox.Fit(self)
824            topBox.SetSizeHints(self)
825    
826            EVT_TEXT(self, ID_QUANTILES_RANGE, self.OnRangeText)
827            EVT_BUTTON(self, ID_QUANTILES_RETRIEVE, self.OnRetrieve)
828    
829            self.__range = None
830    
831        def GetNumGroups(self):
832            return self.spin_numClasses.GetValue()
833    
834        def GetRange(self):
835            assert self.__range is not None
836    
837            return self.__range
838    
839        def GetList(self):
840            _list = []
841            table = self.layer.ShapeStore().Table()
842            if table is not None:
843                ThubanBeginBusyCursor()
844                try:
845                    #
846                    # FIXME: Replace with a call to table when the method
847                    # has been written to get all the values
848                    #
849                    for i in range(table.NumRows()):
850                        _list.append(table.ReadValue(i, self.fieldName))
851                finally:
852                    ThubanEndBusyCursor()
853    
854            return _list
855    
856        def OnRangeText(self, event):
857    
858            try:
859                self.__range = Range(self.text_range.GetValue())
860            except ValueError:
861                self.__range = None
862    
863            if self.__range is not None:
864                self.text_range.SetForegroundColour(wxBLACK)
865            else:
866                self.text_range.SetForegroundColour(wxRED)
867    
868        def OnRetrieve(self, event):
869            table = self.layer.ShapeStore().Table()
870            if table is not None:
871                ThubanBeginBusyCursor()
872                try:
873                    min, max = table.ValueRange(self.fieldName)
874                    self.text_range.SetValue("[" + str(min) + ";" + str(max) + "]")
875                finally:
876                    ThubanEndBusyCursor()
877    
878  ID_CUSTOMRAMP_COPYSTART = 4001  ID_CUSTOMRAMP_COPYSTART = 4001
879  ID_CUSTOMRAMP_COPYEND = 4002  ID_CUSTOMRAMP_COPYEND = 4002
880  ID_CUSTOMRAMP_EDITSTART = 4003  ID_CUSTOMRAMP_EDITSTART = 4003
# Line 791  class CustomRampPanel(wxPanel): Line 963  class CustomRampPanel(wxPanel):
963      def _OnEditEnd(self, event):      def _OnEditEnd(self, event):
964          self.endPropCtrl.DoEdit()          self.endPropCtrl.DoEdit()
965    
966  class ClassGenerator:    
   
     def GenSingletonsFromList(self, list, numGroups, ramp):  
         """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  
   
         ramp.SetNumGroups(numGroups)  
   
         for value, prop in zip(list, ramp):  
             clazz.AppendGroup(ClassGroupSingleton(value, prop))  
   
         return clazz  
   
     def GenSingletons(self, min, max, numGroups, ramp):  
   
         clazz = Classification()  
   
         #step = int((max - min) / float(numGroups))  
         step = int(Str2Num(str((max - min + 1) / float(numGroups))))  
   
         if numGroups > 0:  
             cur_value = min  
   
             ramp.SetNumGroups(numGroups)  
   
             for prop in ramp:  
                 clazz.AppendGroup(  
                     ClassGroupSingleton(  
                         Str2Num(str(cur_value)),  
                         prop))  
                 cur_value += step  
   
         return clazz  
   
     def GenUnifromDistribution(self, min, max, numGroups,  
                                ramp, 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  
   
         ramp.SetNumGroups(numGroups)  
   
         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 ramp:  
   
             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, prop1, prop2):  
         self.prop1 = prop1  
         self.prop2 = prop2  
   
         self.count = 0  
   
     def __iter__(self):  
         return self  
   
     def GetRamp(self):  
         return self  
   
     def SetNumGroups(self, num):  
   
         if num <= 0:  
             return False  
   
         self.count = int(num)  
         num = float(num)  
   
         prop1 = self.prop1  
         prop2 = self.prop2  
   
         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  
   
         return True  
   
     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)  
   
 class MonochromaticRamp(CustomRamp):  
     def __init__(self, start, end):  
         sp = ClassGroupProperties()  
         sp.SetLineColor(start)  
         sp.SetFill(start)  
   
         ep = ClassGroupProperties()  
         ep.SetLineColor(end)  
         ep.SetFill(end)  
   
         CustomRamp.__init__(self, sp, ep)  
   
 class GreyRamp(MonochromaticRamp):  
     def __init__(self):  
         MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(0, 0, 0))  
   
 class RedRamp(MonochromaticRamp):  
     def __init__(self):  
         MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(.8, 0, 0))  
   
 class GreenRamp(MonochromaticRamp):  
     def __init__(self):  
         MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(0, .8, 0))  
   
 class BlueRamp(MonochromaticRamp):  
     def __init__(self):  
         MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(0, 0, .8))  
   
 class HotToColdRamp:  
   
     def __iter__(self):  
         return self  
           
     def GetRamp(self):  
         return self  
   
     def SetNumGroups(self, num):  
         if num < 0:  
             return False  
   
         self.num = float(num)  
         self.index = 0  
   
         return True  
   
     def next(self):  
         if self.index == self.num:  
             raise StopIteration  
   
         clr = [1.0, 1.0, 1.0]  
   
         if self.index < (.25 * self.num):  
             clr[0] = 0  
             clr[1] = 4 * self.index / self.num  
         elif self.index < (.5 * self.num):  
             clr[0] = 0  
             clr[2] = 1 + 4 * (.25 * self.num - self.index) / self.num  
         elif self.index < (.75 * self.num):  
             clr[0] = 4 * (self.index - .5 * self.num) / self.num  
             clr[2] = 0  
         else:  
             clr[1] = 1 + 4 * (.75 * self.num - self.index) / self.num  
             clr[2] = 0  
   
         self.index += 1  
   
         prop = ClassGroupProperties()  
         prop.SetLineColor(Color(clr[0], clr[1], clr[2]))  
         prop.SetFill(Color(clr[0], clr[1], clr[2]))  
   
         return prop  
   
 #class Colors16Ramp:  
 #  
     #def __iter__(self):  
         #return self  
 #  
     #def GetRamp(self):  
         #return self  
 #  
     #def SetNumGroups(self, num):  
         #if num < 0:  
             #return False  
 #  
         #self.index = 0  
 #  
         #return True  
   
       

Legend:
Removed from v.654  
changed lines
  Added in v.1274

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26