/[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 1391 by jonathan, Thu Jul 10 14:54:02 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.layer import SHAPETYPE_ARC
20    from Thuban.Model.range import Range
21  import classifier  from Thuban.UI.common import ThubanBeginBusyCursor, ThubanEndBusyCursor
22    
23  import resource  import classifier, resource
24    
25    from Thuban.Model.classgen import \
26        generate_uniform_distribution, generate_singletons, generate_quantiles, \
27        CustomRamp, GreyRamp, RedRamp, GreenRamp, BlueRamp, GreenToRedRamp, \
28        HotToColdRamp
29    
 from Thuban.common import Str2Num  
   
 ID_CLASSGEN_GEN = 4001  
 ID_CLASSGEN_CLOSE = 4002  
 ID_CLASSGEN_GENCOMBO = 4007  
 ID_CLASSGEN_PROPCOMBO = 4008  
30    
31  USEALL_BMP  = "group_use_all"  USEALL_BMP  = "group_use_all"
32  USE_BMP     = "group_use"  USE_BMP     = "group_use"
# Line 35  USENONE_BMP = "group_use_none" Line 35  USENONE_BMP = "group_use_none"
35    
36  GENCOMBOSTR_UNIFORM = _("Uniform Distribution")  GENCOMBOSTR_UNIFORM = _("Uniform Distribution")
37  GENCOMBOSTR_UNIQUE = _("Unique Values")  GENCOMBOSTR_UNIQUE = _("Unique Values")
38    GENCOMBOSTR_QUANTILES = _("Quantiles from Table")
39    
40  PROPCOMBOSTR_CUSTOM     = _("Custom Ramp")  PROPCOMBOSTR_CUSTOM     = _("Custom Ramp")
41  PROPCOMBOSTR_GREY       = _("Grey Ramp")  PROPCOMBOSTR_GREY       = _("Grey Ramp")
42  PROPCOMBOSTR_RED        = _("Red Ramp")  PROPCOMBOSTR_RED        = _("Red Ramp")
43  PROPCOMBOSTR_GREEN      = _("Green Ramp")  PROPCOMBOSTR_GREEN      = _("Green Ramp")
44  PROPCOMBOSTR_BLUE       = _("Blue Ramp")  PROPCOMBOSTR_BLUE       = _("Blue Ramp")
45    PROPCOMBOSTR_GREEN2RED  = _("Green-to-Red Ramp")
46  PROPCOMBOSTR_HOT2COLD   = _("Hot-to-Cold Ramp")  PROPCOMBOSTR_HOT2COLD   = _("Hot-to-Cold Ramp")
47    
48    ID_CLASSGEN_GENCOMBO = 4007
49    ID_CLASSGEN_PROPCOMBO = 4008
50    
51    ID_BORDER_COLOR = 4009
52    ID_BORDER_COLOR_CHANGE = 4010
53    
54  class ClassGenDialog(wxDialog):  class ClassGenDialog(wxDialog):
55                                                                                    
56      def __init__(self, parent, layer, fieldName):      def __init__(self, parent, layer, fieldName):
57          """Inialize the class generating dialog.          """Inialize the class generating dialog.
58    
# Line 53  class ClassGenDialog(wxDialog): Line 61  class ClassGenDialog(wxDialog):
61    
62          wxDialog.__init__(self, parent, -1, _("Generate Classification"),          wxDialog.__init__(self, parent, -1, _("Generate Classification"),
63                            style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)                            style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
64                                                                                    
65          self.parent = parent          self.parent = parent
66            self.layer = layer
67          self.clazz = None          self.clazz = None
68    
69          self.type, name, width, prec = layer.table.field_info_by_name(fieldName)          col = layer.ShapeStore().Table().Column(fieldName)
70            self.type = col.type
71    
72            self.fieldName = fieldName
73            self.fieldType = self.type
74    
75            self.curGenPanel = None
76    
77            self.genpanels = []
78    
79          #############          #############
80          # we need to create genButton first because when we create the          # we need to create genButton first because when we create the
81          # panels they will call AllowGenerate() which uses genButton.          # panels they will call AllowGenerate() which uses genButton.
82          #          #
83          buttonSizer = wxBoxSizer(wxHORIZONTAL)          self.genButton = wxButton(self, wxID_OK, _("Generate"))
84          self.genButton = wxButton(self, ID_CLASSGEN_GEN, _("Generate"))          self.cancelButton = wxButton(self, wxID_CANCEL, _("Close"))
85            self.genButton.SetDefault()
86    
87            self.genChoice = wxChoice(self, ID_CLASSGEN_GENCOMBO)
88    
89            self.genpanels.append((GENCOMBOSTR_UNIQUE, GenUniquePanel))
90            if self.type in (FIELDTYPE_INT, FIELDTYPE_DOUBLE):
91                self.genpanels.append((GENCOMBOSTR_UNIFORM, GenUniformPanel))
92                self.genpanels.append((GENCOMBOSTR_QUANTILES, GenQuantilesPanel))
93    
94            for name, clazz in self.genpanels:
95                self.genChoice.Append(name, [clazz, None])
96    
97            self.genChoice.SetSelection(0)
98    
99            for i in range(self.genChoice.GetCount()):
100                clazz, obj = self.genChoice.GetClientData(i)
101    
102                if obj is None:
103                    obj = clazz(self, self.layer, self.fieldName, self.fieldType)
104                    obj.Hide()
105                    self.genChoice.SetClientData(i, [clazz, obj])
106    
         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)  
107    
108          #############          #############
109    
# Line 85  class ClassGenDialog(wxDialog): Line 119  class ClassGenDialog(wxDialog):
119          psizer = wxBoxSizer(wxHORIZONTAL)          psizer = wxBoxSizer(wxHORIZONTAL)
120          psizer.Add(wxStaticText(self, -1, _("Generate:")),          psizer.Add(wxStaticText(self, -1, _("Generate:")),
121              0, wxALIGN_CENTER_VERTICAL, 0)              0, wxALIGN_CENTER_VERTICAL, 0)
122            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)  
123    
124          sizer.Add(psizer, 0, wxALL | wxGROW, 4)          sizer.Add(psizer, 0, wxALL | wxGROW, 4)
125    
126          #############          self.sizer_genPanel = wxBoxSizer(wxVERTICAL)
127            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)  
   
         #############  
128    
129          psizer = wxBoxSizer(wxHORIZONTAL)          psizer = wxBoxSizer(wxHORIZONTAL)
130          psizer.Add(wxStaticText(self, -1, _("Color Schemes:")),          psizer.Add(wxStaticText(self, -1, _("Color Scheme:")),
131              0, wxALIGN_CENTER_VERTICAL, 0)              0, wxALIGN_CENTER_VERTICAL, 0)
132    
133          self.propCombo = wxComboBox(self,          # Properties (Ramp) ComboBox
134                                     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)  
   
         #############  
135    
136          self.propPanel = None          self.propPanel = None
137          panel = CustomRampPanel(self, layer.ShapeType())          custom_ramp_panel = CustomRampPanel(self, layer.ShapeType())
138          sizer.Add(panel, 1, wxALL | wxGROW, 4)  
139          sizer.Show(panel, False)          self.propCombo.Append(PROPCOMBOSTR_GREY,  GreyRamp)
140            self.propCombo.Append(PROPCOMBOSTR_RED,   RedRamp)
141          self.propCombo.Append(PROPCOMBOSTR_GREY,  GreyRamp())          self.propCombo.Append(PROPCOMBOSTR_GREEN, GreenRamp)
142          self.propCombo.Append(PROPCOMBOSTR_RED,   RedRamp())          self.propCombo.Append(PROPCOMBOSTR_BLUE,  BlueRamp)
143          self.propCombo.Append(PROPCOMBOSTR_GREEN, GreenRamp())          self.propCombo.Append(PROPCOMBOSTR_GREEN2RED, GreenToRedRamp)
         self.propCombo.Append(PROPCOMBOSTR_BLUE,  BlueRamp())  
144          self.propCombo.Append(PROPCOMBOSTR_HOT2COLD,  HotToColdRamp())          self.propCombo.Append(PROPCOMBOSTR_HOT2COLD,  HotToColdRamp())
145          self.propCombo.Append(PROPCOMBOSTR_CUSTOM, panel)          self.propCombo.Append(PROPCOMBOSTR_CUSTOM, custom_ramp_panel)
146    
147            self.propCombo.SetSelection(0)
148    
149            psizer.Add(self.propCombo, 1, wxALL | wxGROW, 4)
150            sizer.Add(psizer, 0, wxALL | wxGROW, 4)
151    
152          #############          if layer.ShapeType() != SHAPETYPE_ARC:
153                psizer = wxBoxSizer(wxHORIZONTAL)
154                self.fix_border_check = wxCheckBox(self, -1, _("Fix Border Color"))
155                psizer.Add(self.fix_border_check, 0, wxALL | wxGROW, 4)
156                self.border_color = classifier.ClassGroupPropertiesCtrl(
157                    self, ID_BORDER_COLOR,
158                    ClassGroupProperties(), SHAPETYPE_ARC,
159                    style=wxSIMPLE_BORDER, size=(40, 20))
160                psizer.Add(self.border_color, 0, wxALL | wxGROW, 4)
161                psizer.Add(wxButton(self, ID_BORDER_COLOR_CHANGE, _("Change")),
162                        0, wxALL, 4)
163                sizer.Add(psizer, 0, wxALL | wxGROW, 4)
164                EVT_BUTTON(self, ID_BORDER_COLOR_CHANGE, self.OnBorderColorChange)
165            else:
166                self.border_color = None
167    
168          sizer.Add(buttonSizer, 0,          sizer.Add(custom_ramp_panel, 1, wxGROW | wxALL, 4)
169                    wxALL | wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL, 4)          sizer.Show(custom_ramp_panel, False)
170    
171            # Finally place the main buttons
172            buttonSizer = wxBoxSizer(wxHORIZONTAL)
173            buttonSizer.Add(self.genButton, 0, wxRIGHT|wxEXPAND, 10)
174            buttonSizer.Add(self.cancelButton, 0, wxRIGHT|wxEXPAND, 10)
175            sizer.Add(buttonSizer, 0, wxALIGN_RIGHT|wxBOTTOM|wxTOP, 10)
176    
177          self.SetSizer(sizer)          self.SetSizer(sizer)
178          self.SetAutoLayout(True)          self.SetAutoLayout(True)
179          sizer.SetSizeHints(self)          sizer.SetSizeHints(self)
180    
181          self.sizer = sizer          self.topBox = sizer
182    
183            self.__DoOnGenTypeSelect()
184    
185            EVT_CHOICE(self, ID_CLASSGEN_GENCOMBO, self._OnGenTypeSelect)
186            EVT_CHOICE(self, ID_CLASSGEN_PROPCOMBO, self._OnPropTypeSelect)
187            EVT_BUTTON(self, wxID_OK, self.OnOK)
188            EVT_BUTTON(self, wxID_CANCEL, self.OnCancel)
189    
190            self.__DoOnGenTypeSelect()
191    
192          EVT_BUTTON(self, ID_CLASSGEN_GEN, self._OnGenerate)          self.genChoice.SetFocus()
         EVT_BUTTON(self, ID_CLASSGEN_CLOSE, self._OnCloseBtn)  
193    
194      def GetClassification(self):      def GetClassification(self):
195          return self.clazz          return self.clazz
# Line 160  class ClassGenDialog(wxDialog): Line 197  class ClassGenDialog(wxDialog):
197      def AllowGenerate(self, on):      def AllowGenerate(self, on):
198          pass #self.genButton.Enable(on)          pass #self.genButton.Enable(on)
199    
200      def _OnGenerate(self, event):      def OnOK(self, event):
201            """This is really the generate button, but we want to override
202            the wxDialog class.
203            """
204    
205            index = self.genChoice.GetSelection()
206    
207          index = self.genCombo.GetSelection()          assert index != -1, "button should be disabled!"
208    
209          genSel = self.genCombo.GetString(index)          genSel = self.genChoice.GetString(index)
210          genPanel = self.genCombo.GetClientData(index)          clazz, genPanel = self.genChoice.GetClientData(index)
211    
212          propPanel = self.propPanel          propPanel = self.propPanel
213    
214          if genSel in (GENCOMBOSTR_UNIFORM, GENCOMBOSTR_UNIQUE):          if genSel in (GENCOMBOSTR_UNIFORM,          \
215                          GENCOMBOSTR_UNIQUE,           \
216                          GENCOMBOSTR_QUANTILES):
217    
218              numGroups = genPanel.GetNumGroups()              numGroups = genPanel.GetNumGroups()
219    
220              index = self.propCombo.GetSelection()              index = self.propCombo.GetSelection()
# Line 178  class ClassGenDialog(wxDialog): Line 223  class ClassGenDialog(wxDialog):
223              propPanel = self.propCombo.GetClientData(index)              propPanel = self.propCombo.GetClientData(index)
224    
225              ramp = propPanel.GetRamp()              ramp = propPanel.GetRamp()
226                if self.border_color and self.fix_border_check.IsChecked():
227                    props = self.border_color.GetProperties()
228                    lineColor = props.GetLineColor()
229                    lineWidth = props.GetLineWidth()
230                else:
231                    lineColor = None
232                    lineWidth = None
233    
234              if genSel == GENCOMBOSTR_UNIFORM:              if genSel == GENCOMBOSTR_UNIFORM:
235    
# Line 188  class ClassGenDialog(wxDialog): Line 240  class ClassGenDialog(wxDialog):
240                      and max is not None \                      and max is not None \
241                      and numGroups is not None:                      and numGroups is not None:
242    
243                      self.clazz = ClassGenerator().GenUnifromDistribution(                      self.clazz = generate_uniform_distribution(
244                                  min, max, numGroups, ramp,                                  min, max, numGroups, ramp,
245                                  self.type == FIELDTYPE_INT)                                  self.type == FIELDTYPE_INT,
246                                    fixes = (lineColor, lineWidth, None))
247    
248                      self.parent._SetClassification(self.clazz)                      self.parent._SetClassification(self.clazz)
249    
# Line 198  class ClassGenDialog(wxDialog): Line 251  class ClassGenDialog(wxDialog):
251    
252                  list = genPanel.GetValueList()                  list = genPanel.GetValueList()
253    
254                  if len(list) > 0 \                  if len(list) > 0:
255                      and numGroups is not None:                      self.clazz = generate_singletons(list, ramp,
256                                         (lineColor, lineWidth, None))
257                        self.parent._SetClassification(self.clazz)
258    
259                      self.clazz = ClassGenerator().GenSingletonsFromList(              elif genSel == GENCOMBOSTR_QUANTILES:
                                     list, numGroups, ramp)  
260    
261                    _range = genPanel.GetRange()
262                    _list = genPanel.GetList()
263                    _list.sort()
264    
265                    delta = 1 / float(numGroups)
266                    percents = [delta * i for i in range(1, numGroups + 1)]
267                    adjusted, self.clazz = \
268                        generate_quantiles(_list, percents, ramp, _range,
269                                           (lineColor, lineWidth, None))
270    
271                    if adjusted:
272                        dlg = wxMessageDialog(self,
273                            _("Based on the data from the table and the input\n" +
274                              "values, the exact quantiles could not be generated.\n\n" +
275                              "Accept a close estimate?"),
276                            _("Problem with Quantiles"),
277    
278                            wxYES_NO|wxYES_DEFAULT|wxICON_QUESTION)
279                        if dlg.ShowModal() == wxID_YES:
280                            self.parent._SetClassification(self.clazz)
281                    else:
282                      self.parent._SetClassification(self.clazz)                      self.parent._SetClassification(self.clazz)
283    
284      def _OnCloseBtn(self, event):      def OnCancel(self, event):
285          self.Close()          self.Close()
286    
287        def OnBorderColorChange(self, event):
288            self.border_color.DoEdit()
289    
290      def _OnGenTypeSelect(self, event):      def _OnGenTypeSelect(self, event):
291            self.__DoOnGenTypeSelect()
292            return
293    
294          combo = event.GetEventObject()          combo = event.GetEventObject()
295    
296          selIndex = combo.GetSelection()          selIndex = combo.GetSelection()
297    
298          if self.genPanel is not None:          if self.genPanel is not None:
299              self.sizer.Show(self.genPanel, False)              self.topBox.Show(self.genPanel, False)
300    
301          self.genPanel = combo.GetClientData(selIndex)          self.genPanel = combo.GetClientData(selIndex)
302          if self.genPanel is not None:          if self.genPanel is not None:
303              self.sizer.Show(self.genPanel, True)              self.topBox.Show(self.genPanel, True)
304    
305          self.sizer.SetSizeHints(self)          self.topBox.SetSizeHints(self)
306          self.sizer.Layout()          self.topBox.Layout()
307    
308      def _OnPropTypeSelect(self, event):      def _OnPropTypeSelect(self, event):
309          combo = event.GetEventObject()          combo = event.GetEventObject()
# Line 232  class ClassGenDialog(wxDialog): Line 312  class ClassGenDialog(wxDialog):
312          sel = combo.GetString(selIndex)          sel = combo.GetString(selIndex)
313    
314          if isinstance(self.propPanel, wxPanel):          if isinstance(self.propPanel, wxPanel):
315              self.sizer.Show(self.propPanel, False)              self.topBox.Show(self.propPanel, False)
316    
317          self.propPanel = combo.GetClientData(selIndex)          self.propPanel = combo.GetClientData(selIndex)
318    
319          if isinstance(self.propPanel, wxPanel):          if isinstance(self.propPanel, wxPanel):
320              self.sizer.Show(self.propPanel, True)              self.topBox.Show(self.propPanel, True)
321    
322          self.sizer.SetSizeHints(self)          self.topBox.SetSizeHints(self)
323          self.sizer.Layout()          self.topBox.Layout()
324    
325        def __DoOnGenTypeSelect(self):
326            choice = self.genChoice
327    
328            sel = choice.GetSelection()
329            if sel == -1: return
330    
331            clazz, obj = choice.GetClientData(sel)
332    
333            if self.curGenPanel is not None:
334                self.curGenPanel.Hide()
335                self.sizer_genPanel.Remove(self.curGenPanel)
336    
337            self.curGenPanel = obj
338            self.curGenPanel.Show()
339    
340            self.sizer_genPanel.Add(self.curGenPanel, 1,
341                wxALL|wxEXPAND|wxADJUST_MINSIZE, 3)
342            self.sizer_genPanel.Layout()
343            self.Layout()
344            self.topBox.SetSizeHints(self)
345    
346  ID_UNIFORM_MIN = 4001  ID_UNIFORM_MIN = 4001
347  ID_UNIFORM_MAX = 4002  ID_UNIFORM_MAX = 4002
# Line 287  class GenUniformPanel(wxPanel): Line 387  class GenUniformPanel(wxPanel):
387          sizer = wxBoxSizer(wxHORIZONTAL)          sizer = wxBoxSizer(wxHORIZONTAL)
388    
389          sizer.Add(wxStaticText(self, -1, _("Number of Groups:")), 0, wxALL, 4)          sizer.Add(wxStaticText(self, -1, _("Number of Groups:")), 0, wxALL, 4)
390          self.numGroupsCtrl = wxSpinCtrl(self, ID_UNIFORM_NGROUPS, style=wxTE_RIGHT)          self.numGroupsCtrl = wxSpinCtrl(self, ID_UNIFORM_NGROUPS,
391                                            style=wxTE_RIGHT)
392          EVT_TEXT(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)          EVT_TEXT(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)
393          EVT_SPINCTRL(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)          EVT_SPINCTRL(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)
394          sizer.Add(self.numGroupsCtrl, 1, wxALL, 4)          sizer.Add(self.numGroupsCtrl, 1, wxALL, 4)
# Line 308  class GenUniformPanel(wxPanel): Line 409  class GenUniformPanel(wxPanel):
409          self.numGroupsChanging = False          self.numGroupsChanging = False
410          self.steppingChanging = False          self.steppingChanging = False
411    
412          self.numGroupsCtrl.SetRange(1, 100)          self.numGroupsCtrl.SetRange(1, sys.maxint)
413    
414          self.numGroupsCtrl.SetValue(1)          self.numGroupsCtrl.SetValue(1)
415          self.stepCtrl.SetValue("1")          self.stepCtrl.SetValue("1")
# Line 358  class GenUniformPanel(wxPanel): Line 459  class GenUniformPanel(wxPanel):
459          self.numGroupsCtrl.Enable(on)          self.numGroupsCtrl.Enable(on)
460          self.stepCtrl.Enable(on)          self.stepCtrl.Enable(on)
461    
         if on:  
             self.numGroupsCtrl.SetRange(1, abs(max - min) / 0.001)  
   
462          ngroups = self.GetNumGroups()          ngroups = self.GetNumGroups()
463    
464          if ngroups is not None  \          if ngroups is not None  \
# Line 391  class GenUniformPanel(wxPanel): Line 489  class GenUniformPanel(wxPanel):
489          min = self.GetMin()          min = self.GetMin()
490          max = self.GetMax()          max = self.GetMax()
491    
         if ngroups >= self.numGroupsCtrl.GetMax():  
             self.numGroupsCtrl.SetRange(1, ngroups + 1)  
   
492          if ngroups is not None  \          if ngroups is not None  \
493              and min is not None \              and min is not None \
494              and max is not None \              and max is not None \
# Line 440  class GenUniformPanel(wxPanel): Line 535  class GenUniformPanel(wxPanel):
535              self.parent.AllowGenerate(False)              self.parent.AllowGenerate(False)
536    
537      def _OnRetrieve(self, event):      def _OnRetrieve(self, event):
538            table = self.layer.ShapeStore().Table()
539          if self.layer.table is not None:          if table is not None:
540              range = self.layer.table.field_range(self.fieldName)              ThubanBeginBusyCursor()
541              self.minCtrl.SetValue(str(range[0][0]))              try:
542              self.maxCtrl.SetValue(str(range[1][0]))                  min, max = table.ValueRange(self.fieldName)
543                    self.minCtrl.SetValue(str(min))
544                    self.maxCtrl.SetValue(str(max))
545                finally:
546                    ThubanEndBusyCursor()
547    
548      def __GetValidatedTypeEntry(self, win, value, type, badValue = None):      def __GetValidatedTypeEntry(self, win, value, type, badValue = None):
549    
# Line 486  class GenUniformPanel(wxPanel): Line 585  class GenUniformPanel(wxPanel):
585          return valid          return valid
586    
587      def __CalcStepping(self, min, max, ngroups):      def __CalcStepping(self, min, max, ngroups):
         step = Str2Num(str((max - min) / float(ngroups)))  
588          if self.fieldType == FIELDTYPE_INT:          if self.fieldType == FIELDTYPE_INT:
589              step = int(step)              step = int((max - min + 1) / float(ngroups))
590            else:
591                step = (max - min) / float(ngroups)
592    
593          return step          return step
594    
# Line 605  class GenUniquePanel(wxPanel): Line 705  class GenUniquePanel(wxPanel):
705          self.SetAutoLayout(True)          self.SetAutoLayout(True)
706          topSizer.SetSizeHints(self)          topSizer.SetSizeHints(self)
707    
708          self.parent.AllowGenerate(False)          width, height = self.list_avail.GetSizeTuple()
709            self.list_avail.SetColumnWidth(0,width)
710            width, height = self.list_use.GetSizeTuple()
711            self.list_use.SetColumnWidth(0,width)
712    
713          self.mylist = ["Hallo", "Welt!", "Wie", "geht", "es", "dir", "?"]          self.parent.AllowGenerate(False)
714    
715      def GetNumGroups(self):      def GetNumGroups(self):
716          return self.list_use.GetItemCount()          return self.list_use.GetItemCount()
# Line 648  class GenUniquePanel(wxPanel): Line 751  class GenUniquePanel(wxPanel):
751          self.list_avail.DeleteAllItems()          self.list_avail.DeleteAllItems()
752          self.list_avail_data = []          self.list_avail_data = []
753    
754          list = self.layer.table.GetUniqueValues(self.fieldName)          ThubanBeginBusyCursor()
755          index = 0          try:
756          for v in list:              list = self.layer.ShapeStore().Table().UniqueValues(self.fieldName)
757              self.dataList.append(v)              index = 0
758              i = self.list_avail.InsertStringItem(index, str(v))              for v in list:
759              self.list_avail.SetItemData(index, i)                  self.dataList.append(v)
760                    i = self.list_avail.InsertStringItem(index, str(v))
761              self.list_avail_data.append(v)                  self.list_avail.SetItemData(index, i)
762              index += 1      
763                    self.list_avail_data.append(v)
764                    index += 1
765            finally:
766                ThubanEndBusyCursor()
767    
768      def _OnUseAll(self, event):      def _OnUseAll(self, event):
769          for i in range(self.list_avail.GetItemCount()):          for i in range(self.list_avail.GetItemCount()):
# Line 703  class GenUniquePanel(wxPanel): Line 810  class GenUniquePanel(wxPanel):
810  #       list.SetColumnWidth(0, event.GetSize().GetWidth())  #       list.SetColumnWidth(0, event.GetSize().GetWidth())
811  #        #      
812    
813    ID_QUANTILES_RANGE = 4001
814    ID_QUANTILES_RETRIEVE = 4002
815    
816    class GenQuantilesPanel(wxPanel):
817    
818        def __init__(self, parent, layer, fieldName, fieldType):
819            wxPanel.__init__(self, parent, -1)
820    
821            self.parent = parent
822            self.layer = layer
823            self.fieldName = fieldName
824            self.fieldType = fieldType
825    
826            topBox = wxStaticBoxSizer(wxStaticBox(self, -1, ""),
827                                        wxVERTICAL)
828    
829            self.text_range = wxTextCtrl(self, ID_QUANTILES_RANGE, "")
830            self.button_retrieve = wxButton(self, ID_QUANTILES_RETRIEVE,
831                                            _("Retrieve from Table"))
832    
833            self.spin_numClasses = wxSpinCtrl(self, -1, style=wxTE_RIGHT)
834            self.spin_numClasses.SetRange(1, sys.maxint)
835            self.spin_numClasses.SetValue(1)
836    
837    
838            sizer = wxBoxSizer(wxHORIZONTAL)
839            sizer.Add(wxStaticText(self, -1, _("Apply to Range")), 0, wxALL, 4)
840            sizer.Add(self.text_range, 1, wxALL, 4)
841            sizer.Add(self.button_retrieve, 0, wxALL, 4)
842    
843            topBox.Add(sizer, 0, wxEXPAND, 0)
844    
845            sizer = wxBoxSizer(wxHORIZONTAL)
846            sizer.Add(wxStaticText(self, -1, _("Number of Classes:")), 0, wxALL, 4)
847            sizer.Add(self.spin_numClasses, 1, wxALL, 4)
848    
849            topBox.Add(sizer, 0, wxEXPAND, 0)
850    
851            self.SetSizer(topBox)
852            self.SetAutoLayout(True)
853            topBox.Fit(self)
854            topBox.SetSizeHints(self)
855    
856            EVT_TEXT(self, ID_QUANTILES_RANGE, self.OnRangeText)
857            EVT_BUTTON(self, ID_QUANTILES_RETRIEVE, self.OnRetrieve)
858    
859            self.__range = None
860    
861        def GetNumGroups(self):
862            return self.spin_numClasses.GetValue()
863    
864        def GetRange(self):
865            assert self.__range is not None
866    
867            return self.__range
868    
869        def GetList(self):
870            _list = []
871            table = self.layer.ShapeStore().Table()
872            if table is not None:
873                ThubanBeginBusyCursor()
874                try:
875                    #
876                    # FIXME: Replace with a call to table when the method
877                    # has been written to get all the values
878                    #
879                    for i in range(table.NumRows()):
880                        _list.append(table.ReadValue(i, self.fieldName))
881                finally:
882                    ThubanEndBusyCursor()
883    
884            return _list
885    
886        def OnRangeText(self, event):
887    
888            try:
889                self.__range = Range(self.text_range.GetValue())
890            except ValueError:
891                self.__range = None
892    
893            if self.__range is not None:
894                self.text_range.SetForegroundColour(wxBLACK)
895            else:
896                self.text_range.SetForegroundColour(wxRED)
897    
898        def OnRetrieve(self, event):
899            table = self.layer.ShapeStore().Table()
900            if table is not None:
901                ThubanBeginBusyCursor()
902                try:
903                    min, max = table.ValueRange(self.fieldName)
904                    self.text_range.SetValue("[" + str(min) + ";" + str(max) + "]")
905                finally:
906                    ThubanEndBusyCursor()
907    
908  ID_CUSTOMRAMP_COPYSTART = 4001  ID_CUSTOMRAMP_COPYSTART = 4001
909  ID_CUSTOMRAMP_COPYEND = 4002  ID_CUSTOMRAMP_COPYEND = 4002
910  ID_CUSTOMRAMP_EDITSTART = 4003  ID_CUSTOMRAMP_EDITSTART = 4003
# Line 791  class CustomRampPanel(wxPanel): Line 993  class CustomRampPanel(wxPanel):
993      def _OnEditEnd(self, event):      def _OnEditEnd(self, event):
994          self.endPropCtrl.DoEdit()          self.endPropCtrl.DoEdit()
995    
996  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.1391

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26