/[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 649 by jonathan, Fri Apr 11 14:27:12 2003 UTC revision 907 by bh, Fri May 16 15:01: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
   
 import classifier  
20    
21  import resource  import classifier, resource
22    
23  from Thuban.common import Str2Num  from Thuban.Model.classgen import ClassGenerator, \
24        CustomRamp, GreyRamp, RedRamp, GreenRamp, BlueRamp, GreenToRedRamp, \
25  ID_CLASSGEN_GEN = 4001      HotToColdRamp
 ID_CLASSGEN_CLOSE = 4002  
 ID_CLASSGEN_GENCOMBO = 4007  
 ID_CLASSGEN_PROPCOMBO = 4008  
26    
27  USEALL_BMP  = "group_use_all"  USEALL_BMP  = "group_use_all"
28  USE_BMP     = "group_use"  USE_BMP     = "group_use"
# Line 35  USENONE_BMP = "group_use_none" Line 31  USENONE_BMP = "group_use_none"
31    
32  GENCOMBOSTR_UNIFORM = _("Uniform Distribution")  GENCOMBOSTR_UNIFORM = _("Uniform Distribution")
33  GENCOMBOSTR_UNIQUE = _("Unique Values")  GENCOMBOSTR_UNIQUE = _("Unique Values")
34    GENCOMBOSTR_QUANTILES = _("Quantiles from Table")
35    
36  PROPCOMBOSTR_CUSTOM     = _("Custom Ramp")  PROPCOMBOSTR_CUSTOM     = _("Custom Ramp")
37  PROPCOMBOSTR_GREY       = _("Grey Ramp")  PROPCOMBOSTR_GREY       = _("Grey Ramp")
38  PROPCOMBOSTR_RED        = _("Red Ramp")  PROPCOMBOSTR_RED        = _("Red Ramp")
39  PROPCOMBOSTR_GREEN      = _("Green Ramp")  PROPCOMBOSTR_GREEN      = _("Green Ramp")
40  PROPCOMBOSTR_BLUE       = _("Blue Ramp")  PROPCOMBOSTR_BLUE       = _("Blue Ramp")
41    PROPCOMBOSTR_GREEN2RED  = _("Green-to-Red Ramp")
42  PROPCOMBOSTR_HOT2COLD   = _("Hot-to-Cold Ramp")  PROPCOMBOSTR_HOT2COLD   = _("Hot-to-Cold Ramp")
43    
44    ID_CLASSGEN_GENCOMBO = 4007
45    ID_CLASSGEN_PROPCOMBO = 4008
46    
47  class ClassGenDialog(wxDialog):  class ClassGenDialog(wxDialog):
48                                                                                    
49      def __init__(self, parent, layer, fieldName):      def __init__(self, parent, layer, fieldName):
50          """Inialize the class generating dialog.          """Inialize the class generating dialog.
51    
# Line 53  class ClassGenDialog(wxDialog): Line 54  class ClassGenDialog(wxDialog):
54    
55          wxDialog.__init__(self, parent, -1, _("Generate Classification"),          wxDialog.__init__(self, parent, -1, _("Generate Classification"),
56                            style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)                            style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
57                                                                                    
58          self.parent = parent          self.parent = parent
59            self.layer = layer
60          self.clazz = None          self.clazz = None
61    
62          self.type, name, width, prec = layer.table.field_info_by_name(fieldName)          col = layer.table.Column(fieldName)
63            self.type = col.type
64    
65            self.fieldName = fieldName
66            self.fieldType = self.type
67    
68            self.curGenPanel = None
69    
70            self.genpanels = []
71    
72          #############          #############
73          # we need to create genButton first because when we create the          # we need to create genButton first because when we create the
74          # panels they will call AllowGenerate() which uses genButton.          # panels they will call AllowGenerate() which uses genButton.
75          #          #
76          buttonSizer = wxBoxSizer(wxHORIZONTAL)          self.genButton = wxButton(self, wxID_OK, _("Generate"))
77          self.genButton = wxButton(self, ID_CLASSGEN_GEN, _("Generate"))          self.genButton.SetDefault()
78            self.genChoice = wxChoice(self, ID_CLASSGEN_GENCOMBO)
79    
80          buttonSizer.Add(self.genButton, 0, wxALL, 4)          self.genpanels.append((GENCOMBOSTR_UNIQUE, GenUniquePanel))
81          buttonSizer.Add(60, 20, 0, wxALL, 4)          if self.type in (FIELDTYPE_INT, FIELDTYPE_DOUBLE):
82          buttonSizer.Add(wxButton(self, ID_CLASSGEN_CLOSE, _("Close")),              self.genpanels.append((GENCOMBOSTR_UNIFORM, GenUniformPanel))
83                          0, wxALL, 4)              self.genpanels.append((GENCOMBOSTR_QUANTILES, GenQuantilesPanel))
84    
85            for name, clazz in self.genpanels:
86                self.genChoice.Append(name, [clazz, None])
87    
88            self.genChoice.SetSelection(0)
89    
90            self.propPanel = None
91            custom_ramp_panel = CustomRampPanel(self, layer.ShapeType())
92    
93            self.propCombo = wxChoice(self, ID_CLASSGEN_PROPCOMBO)
94            self.propCombo.Append(PROPCOMBOSTR_GREY,  GreyRamp())
95            self.propCombo.Append(PROPCOMBOSTR_RED,   RedRamp())
96            self.propCombo.Append(PROPCOMBOSTR_GREEN, GreenRamp())
97            self.propCombo.Append(PROPCOMBOSTR_BLUE,  BlueRamp())
98            self.propCombo.Append(PROPCOMBOSTR_GREEN2RED, GreenToRedRamp())
99            self.propCombo.Append(PROPCOMBOSTR_HOT2COLD,  HotToColdRamp())
100            self.propCombo.Append(PROPCOMBOSTR_CUSTOM, custom_ramp_panel)
101    
102            self.propCombo.SetSelection(0)
103    
104          #############          #############
105    
# Line 85  class ClassGenDialog(wxDialog): Line 115  class ClassGenDialog(wxDialog):
115          psizer = wxBoxSizer(wxHORIZONTAL)          psizer = wxBoxSizer(wxHORIZONTAL)
116          psizer.Add(wxStaticText(self, -1, _("Generate:")),          psizer.Add(wxStaticText(self, -1, _("Generate:")),
117              0, wxALIGN_CENTER_VERTICAL, 0)              0, wxALIGN_CENTER_VERTICAL, 0)
118            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)  
119    
120          sizer.Add(psizer, 0, wxALL | wxGROW, 4)          sizer.Add(psizer, 0, wxALL | wxGROW, 4)
121    
122          #############          self.sizer_genPanel = wxBoxSizer(wxVERTICAL)
123            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)  
   
         #############  
124    
125          psizer = wxBoxSizer(wxHORIZONTAL)          psizer = wxBoxSizer(wxHORIZONTAL)
126          psizer.Add(wxStaticText(self, -1, _("Color Schemes:")),          psizer.Add(wxStaticText(self, -1, _("Color Scheme:")),
127              0, wxALIGN_CENTER_VERTICAL, 0)              0, wxALIGN_CENTER_VERTICAL, 0)
   
         self.propCombo = wxComboBox(self,  
                                    ID_CLASSGEN_PROPCOMBO,  
                                    "", style = wxCB_READONLY)  
128          psizer.Add(self.propCombo, 1, wxALL | wxGROW, 4)          psizer.Add(self.propCombo, 1, wxALL | wxGROW, 4)
         EVT_COMBOBOX(self, ID_CLASSGEN_PROPCOMBO, self._OnPropTypeSelect)  
129          sizer.Add(psizer, 0, wxALL | wxGROW, 4)          sizer.Add(psizer, 0, wxALL | wxGROW, 4)
130    
131          #############          sizer.Add(custom_ramp_panel, 1, wxGROW | wxALL, 4)
132            sizer.Show(custom_ramp_panel, False)
         self.propPanel = None  
         panel = CustomRampPanel(self, layer.ShapeType())  
         sizer.Add(panel, 1, wxALL | wxGROW, 4)  
         sizer.Show(panel, False)  
   
         self.propCombo.Append(PROPCOMBOSTR_GREY,  GreyRamp())  
         self.propCombo.Append(PROPCOMBOSTR_RED,   RedRamp())  
         self.propCombo.Append(PROPCOMBOSTR_GREEN, GreenRamp())  
         self.propCombo.Append(PROPCOMBOSTR_BLUE,  BlueRamp())  
         self.propCombo.Append(PROPCOMBOSTR_HOT2COLD,  HotToColdRamp())  
         self.propCombo.Append(PROPCOMBOSTR_CUSTOM, panel)  
   
   
   
         #############  
133    
134            buttonSizer = wxBoxSizer(wxHORIZONTAL)
135            buttonSizer.Add(self.genButton, 0, wxALL, 4)
136            buttonSizer.Add(60, 20, 0, wxALL, 4)
137            buttonSizer.Add(wxButton(self, wxID_CANCEL, _("Close")),
138                            0, wxALL, 4)
139          sizer.Add(buttonSizer, 0,          sizer.Add(buttonSizer, 0,
140                    wxALL | wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL, 4)                    wxALL | wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL, 4)
141    
   
142          self.SetSizer(sizer)          self.SetSizer(sizer)
143          self.SetAutoLayout(True)          self.SetAutoLayout(True)
144          sizer.SetSizeHints(self)          sizer.SetSizeHints(self)
145    
146          self.sizer = sizer          self.topBox = sizer
147    
148          EVT_BUTTON(self, ID_CLASSGEN_GEN, self._OnGenerate)          self.__DoOnGenTypeSelect()
149          EVT_BUTTON(self, ID_CLASSGEN_CLOSE, self._OnCloseBtn)  
150            EVT_CHOICE(self, ID_CLASSGEN_GENCOMBO, self._OnGenTypeSelect)
151            EVT_CHOICE(self, ID_CLASSGEN_PROPCOMBO, self._OnPropTypeSelect)
152            EVT_BUTTON(self, wxID_OK, self.OnOK)
153            EVT_BUTTON(self, wxID_CANCEL, self.OnCancel)
154    
155            self.__DoOnGenTypeSelect()
156    
157            self.genChoice.SetFocus()
158    
159      def GetClassification(self):      def GetClassification(self):
160          return self.clazz          return self.clazz
# Line 160  class ClassGenDialog(wxDialog): Line 162  class ClassGenDialog(wxDialog):
162      def AllowGenerate(self, on):      def AllowGenerate(self, on):
163          pass #self.genButton.Enable(on)          pass #self.genButton.Enable(on)
164    
165      def _OnGenerate(self, event):      def OnOK(self, event):
166            """This is really the generate button, but we want to override
167            the wxDialog class.
168            """
169    
170            index = self.genChoice.GetSelection()
171    
172          index = self.genCombo.GetSelection()          assert index != -1, "button should be disabled!"
173    
174          genSel = self.genCombo.GetString(index)          genSel = self.genChoice.GetString(index)
175          genPanel = self.genCombo.GetClientData(index)          clazz, genPanel = self.genChoice.GetClientData(index)
176    
177          propPanel = self.propPanel          propPanel = self.propPanel
178    
179          if genSel in (GENCOMBOSTR_UNIFORM, GENCOMBOSTR_UNIQUE):          if genSel in (GENCOMBOSTR_UNIFORM,          \
180                          GENCOMBOSTR_UNIQUE,           \
181                          GENCOMBOSTR_QUANTILES):
182    
183              numGroups = genPanel.GetNumGroups()              numGroups = genPanel.GetNumGroups()
184    
185              index = self.propCombo.GetSelection()              index = self.propCombo.GetSelection()
# Line 188  class ClassGenDialog(wxDialog): Line 198  class ClassGenDialog(wxDialog):
198                      and max is not None \                      and max is not None \
199                      and numGroups is not None:                      and numGroups is not None:
200    
201                      self.clazz = ClassGenerator().GenUnifromDistribution(                      self.clazz = ClassGenerator().GenUniformDistribution(
202                                  min, max, numGroups, ramp,                                  min, max, numGroups, ramp,
203                                  self.type == FIELDTYPE_INT)                                  self.type == FIELDTYPE_INT)
204    
# Line 206  class ClassGenDialog(wxDialog): Line 216  class ClassGenDialog(wxDialog):
216    
217                      self.parent._SetClassification(self.clazz)                      self.parent._SetClassification(self.clazz)
218    
219      def _OnCloseBtn(self, event):              elif genSel == GENCOMBOSTR_QUANTILES:
220    
221                    _range = genPanel.GetRange()
222                    _list = genPanel.GetList()
223                    _list.sort()
224    
225                    delta = 1 / float(numGroups)
226                    percents = [delta * i for i in range(1, numGroups + 1)]
227                    adjusted, self.clazz = \
228                        ClassGenerator().GenQuantiles(_list, percents, ramp, _range)
229    
230                    if adjusted:
231                        dlg = wxMessageDialog(self,
232                            _("Based on the data from the table and the input\n" +
233                              "values, the exact quantiles could not be generated.\n\n" +
234                              "Accept a close estimate?"),
235                            _("Problem with Quantiles"),
236    
237                            wxYES_NO|wxYES_DEFAULT|wxICON_QUESTION)
238                        if dlg.ShowModal() == wxID_YES:
239                            self.parent._SetClassification(self.clazz)
240                    else:
241                        self.parent._SetClassification(self.clazz)
242    
243        def OnCancel(self, event):
244          self.Close()          self.Close()
245    
246      def _OnGenTypeSelect(self, event):      def _OnGenTypeSelect(self, event):
247            self.__DoOnGenTypeSelect()
248            return
249    
250          combo = event.GetEventObject()          combo = event.GetEventObject()
251    
252          selIndex = combo.GetSelection()          selIndex = combo.GetSelection()
253    
254          if self.genPanel is not None:          if self.genPanel is not None:
255              self.sizer.Show(self.genPanel, False)              self.topBox.Show(self.genPanel, False)
256    
257          self.genPanel = combo.GetClientData(selIndex)          self.genPanel = combo.GetClientData(selIndex)
258          if self.genPanel is not None:          if self.genPanel is not None:
259              self.sizer.Show(self.genPanel, True)              self.topBox.Show(self.genPanel, True)
260    
261          self.sizer.SetSizeHints(self)          self.topBox.SetSizeHints(self)
262          self.sizer.Layout()          self.topBox.Layout()
263    
264      def _OnPropTypeSelect(self, event):      def _OnPropTypeSelect(self, event):
265          combo = event.GetEventObject()          combo = event.GetEventObject()
# Line 232  class ClassGenDialog(wxDialog): Line 268  class ClassGenDialog(wxDialog):
268          sel = combo.GetString(selIndex)          sel = combo.GetString(selIndex)
269    
270          if isinstance(self.propPanel, wxPanel):          if isinstance(self.propPanel, wxPanel):
271              self.sizer.Show(self.propPanel, False)              self.topBox.Show(self.propPanel, False)
272    
273          self.propPanel = combo.GetClientData(selIndex)          self.propPanel = combo.GetClientData(selIndex)
274    
275          if isinstance(self.propPanel, wxPanel):          if isinstance(self.propPanel, wxPanel):
276              self.sizer.Show(self.propPanel, True)              self.topBox.Show(self.propPanel, True)
277    
278            self.topBox.SetSizeHints(self)
279            self.topBox.Layout()
280    
281        def __DoOnGenTypeSelect(self):
282            choice = self.genChoice
283    
284            sel = choice.GetSelection()
285            if sel == -1: return
286    
287            clazz, obj = choice.GetClientData(sel)
288    
289          self.sizer.SetSizeHints(self)          if obj is None:
290          self.sizer.Layout()              obj = clazz(self, self.layer, self.fieldName, self.fieldType)
291                choice.SetClientData(sel, [clazz, obj])
292    
293            if self.curGenPanel is not None:
294                self.curGenPanel.Hide()
295                self.sizer_genPanel.Remove(self.curGenPanel)
296    
297            self.curGenPanel = obj
298            self.curGenPanel.Show()
299    
300            self.sizer_genPanel.Add(self.curGenPanel, 1,
301                wxALL|wxEXPAND|wxADJUST_MINSIZE, 3)
302            self.sizer_genPanel.Layout()
303            self.Layout()
304            self.topBox.SetSizeHints(self)
305    
306  ID_UNIFORM_MIN = 4001  ID_UNIFORM_MIN = 4001
307  ID_UNIFORM_MAX = 4002  ID_UNIFORM_MAX = 4002
# Line 287  class GenUniformPanel(wxPanel): Line 347  class GenUniformPanel(wxPanel):
347          sizer = wxBoxSizer(wxHORIZONTAL)          sizer = wxBoxSizer(wxHORIZONTAL)
348    
349          sizer.Add(wxStaticText(self, -1, _("Number of Groups:")), 0, wxALL, 4)          sizer.Add(wxStaticText(self, -1, _("Number of Groups:")), 0, wxALL, 4)
350          self.numGroupsCtrl = wxSpinCtrl(self, ID_UNIFORM_NGROUPS, style=wxTE_RIGHT)          self.numGroupsCtrl = wxSpinCtrl(self, ID_UNIFORM_NGROUPS,
351                                            style=wxTE_RIGHT)
352          EVT_TEXT(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)          EVT_TEXT(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)
353          EVT_SPINCTRL(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)          EVT_SPINCTRL(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)
354          sizer.Add(self.numGroupsCtrl, 1, wxALL, 4)          sizer.Add(self.numGroupsCtrl, 1, wxALL, 4)
# Line 308  class GenUniformPanel(wxPanel): Line 369  class GenUniformPanel(wxPanel):
369          self.numGroupsChanging = False          self.numGroupsChanging = False
370          self.steppingChanging = False          self.steppingChanging = False
371    
372          self.numGroupsCtrl.SetRange(1, 100)          self.numGroupsCtrl.SetRange(1, sys.maxint)
373    
374          self.numGroupsCtrl.SetValue(1)          self.numGroupsCtrl.SetValue(1)
375          self.stepCtrl.SetValue("1")          self.stepCtrl.SetValue("1")
# Line 358  class GenUniformPanel(wxPanel): Line 419  class GenUniformPanel(wxPanel):
419          self.numGroupsCtrl.Enable(on)          self.numGroupsCtrl.Enable(on)
420          self.stepCtrl.Enable(on)          self.stepCtrl.Enable(on)
421    
         if on:  
             self.numGroupsCtrl.SetRange(1, abs(max - min) / 0.001)  
   
422          ngroups = self.GetNumGroups()          ngroups = self.GetNumGroups()
423    
424          if ngroups is not None  \          if ngroups is not None  \
# Line 391  class GenUniformPanel(wxPanel): Line 449  class GenUniformPanel(wxPanel):
449          min = self.GetMin()          min = self.GetMin()
450          max = self.GetMax()          max = self.GetMax()
451    
         if ngroups >= self.numGroupsCtrl.GetMax():  
             self.numGroupsCtrl.SetRange(1, ngroups + 1)  
   
452          if ngroups is not None  \          if ngroups is not None  \
453              and min is not None \              and min is not None \
454              and max is not None \              and max is not None \
# Line 442  class GenUniformPanel(wxPanel): Line 497  class GenUniformPanel(wxPanel):
497      def _OnRetrieve(self, event):      def _OnRetrieve(self, event):
498    
499          if self.layer.table is not None:          if self.layer.table is not None:
500              range = self.layer.table.field_range(self.fieldName)              wxBeginBusyCursor()
501              self.minCtrl.SetValue(str(range[0][0]))              min, max = self.layer.table.ValueRange(self.fieldName)
502              self.maxCtrl.SetValue(str(range[1][0]))              self.minCtrl.SetValue(str(min))
503                self.maxCtrl.SetValue(str(max))
504                wxEndBusyCursor()
505    
506      def __GetValidatedTypeEntry(self, win, value, type, badValue = None):      def __GetValidatedTypeEntry(self, win, value, type, badValue = None):
507    
# Line 486  class GenUniformPanel(wxPanel): Line 543  class GenUniformPanel(wxPanel):
543          return valid          return valid
544    
545      def __CalcStepping(self, min, max, ngroups):      def __CalcStepping(self, min, max, ngroups):
546          step = Str2Num(str((max - min) / float(ngroups)))          step = (max - min) / float(ngroups)
547          if self.fieldType == FIELDTYPE_INT:          if self.fieldType == FIELDTYPE_INT:
548              step = int(step)              step = int(step)
549    
# Line 607  class GenUniquePanel(wxPanel): Line 664  class GenUniquePanel(wxPanel):
664    
665          self.parent.AllowGenerate(False)          self.parent.AllowGenerate(False)
666    
         self.mylist = ["Hallo", "Welt!", "Wie", "geht", "es", "dir", "?"]  
   
667      def GetNumGroups(self):      def GetNumGroups(self):
668          return self.list_use.GetItemCount()          return self.list_use.GetItemCount()
669    
# Line 648  class GenUniquePanel(wxPanel): Line 703  class GenUniquePanel(wxPanel):
703          self.list_avail.DeleteAllItems()          self.list_avail.DeleteAllItems()
704          self.list_avail_data = []          self.list_avail_data = []
705    
706          list = self.layer.table.GetUniqueValues(self.fieldName)          list = self.layer.table.UniqueValues(self.fieldName)
707          index = 0          index = 0
708          for v in list:          for v in list:
709              self.dataList.append(v)              self.dataList.append(v)
# Line 703  class GenUniquePanel(wxPanel): Line 758  class GenUniquePanel(wxPanel):
758  #       list.SetColumnWidth(0, event.GetSize().GetWidth())  #       list.SetColumnWidth(0, event.GetSize().GetWidth())
759  #        #      
760    
761    ID_QUANTILES_RANGE = 4001
762    ID_QUANTILES_RETRIEVE = 4002
763    
764    class GenQuantilesPanel(wxPanel):
765    
766        def __init__(self, parent, layer, fieldName, fieldType):
767            wxPanel.__init__(self, parent, -1)
768    
769            self.parent = parent
770            self.layer = layer
771            self.fieldName = fieldName
772            self.fieldType = fieldType
773    
774            topBox = wxStaticBoxSizer(wxStaticBox(self, -1, ""),
775                                        wxVERTICAL)
776    
777            self.text_range = wxTextCtrl(self, ID_QUANTILES_RANGE, "")
778            self.button_retrieve = wxButton(self, ID_QUANTILES_RETRIEVE,
779                                            _("Retrieve from Table"))
780    
781            self.spin_numClasses = wxSpinCtrl(self, -1, style=wxTE_RIGHT)
782            self.spin_numClasses.SetRange(1, sys.maxint)
783            self.spin_numClasses.SetValue(1)
784    
785    
786            sizer = wxBoxSizer(wxHORIZONTAL)
787            sizer.Add(wxStaticText(self, -1, _("Apply to Range")), 0, wxALL, 4)
788            sizer.Add(self.text_range, 1, wxALL, 4)
789            sizer.Add(self.button_retrieve, 0, wxALL, 4)
790    
791            topBox.Add(sizer, 0, wxEXPAND, 0)
792    
793            sizer = wxBoxSizer(wxHORIZONTAL)
794            sizer.Add(wxStaticText(self, -1, _("Number of Classes:")), 0, wxALL, 4)
795            sizer.Add(self.spin_numClasses, 1, wxALL, 4)
796    
797            topBox.Add(sizer, 0, wxEXPAND, 0)
798    
799            self.SetSizer(topBox)
800            self.SetAutoLayout(True)
801            topBox.Fit(self)
802            topBox.SetSizeHints(self)
803    
804            EVT_TEXT(self, ID_QUANTILES_RANGE, self.OnRangeText)
805            EVT_BUTTON(self, ID_QUANTILES_RETRIEVE, self.OnRetrieve)
806    
807            self.__range = None
808    
809        def GetNumGroups(self):
810            return self.spin_numClasses.GetValue()
811    
812        def GetRange(self):
813            assert self.__range is not None
814    
815            return self.__range
816    
817        def GetList(self):
818    
819            _list = []
820    
821            if self.layer.table is not None:
822                wxBeginBusyCursor()
823    
824                #
825                # FIXME: Replace with a call to table when the method
826                # has been written to get all the values
827                #
828                table = self.layer.table
829                for i in range(table.NumRows()):
830                    _list.append(table.ReadValue(i, self.fieldName))
831    
832                wxEndBusyCursor()
833    
834            return _list
835    
836        def OnRangeText(self, event):
837    
838            try:
839                self.__range = Range(self.text_range.GetValue())
840            except ValueError:
841                self.__range = None
842    
843            if self.__range is not None:
844                self.text_range.SetForegroundColour(wxBLACK)
845            else:
846                self.text_range.SetForegroundColour(wxRED)
847    
848        def OnRetrieve(self, event):
849    
850            if self.layer.table is not None:
851                wxBeginBusyCursor()
852                min, max = self.layer.table.ValueRange(self.fieldName)
853                self.text_range.SetValue("[" + str(min) + ";" + str(max) + "]")
854                wxEndBusyCursor()
855    
856  ID_CUSTOMRAMP_COPYSTART = 4001  ID_CUSTOMRAMP_COPYSTART = 4001
857  ID_CUSTOMRAMP_COPYEND = 4002  ID_CUSTOMRAMP_COPYEND = 4002
858  ID_CUSTOMRAMP_EDITSTART = 4003  ID_CUSTOMRAMP_EDITSTART = 4003
# Line 791  class CustomRampPanel(wxPanel): Line 941  class CustomRampPanel(wxPanel):
941      def _OnEditEnd(self, event):      def _OnEditEnd(self, event):
942          self.endPropCtrl.DoEdit()          self.endPropCtrl.DoEdit()
943    
944  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(0, 0, 0), Color(1, 1, 1))  
   
 class RedRamp(MonochromaticRamp):  
     def __init__(self):  
         MonochromaticRamp.__init__(self, Color(.2, 0, 0), Color(1, 0, 0))  
   
 class GreenRamp(MonochromaticRamp):  
     def __init__(self):  
         MonochromaticRamp.__init__(self, Color(0, .2, 0), Color(0, 1, 0))  
   
 class BlueRamp(MonochromaticRamp):  
     def __init__(self):  
         MonochromaticRamp.__init__(self, Color(0, 0, .2), Color(0, 0, 1))  
   
 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.649  
changed lines
  Added in v.907

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26