/[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 635 by jonathan, Wed Apr 9 15:42:25 2003 UTC revision 2709 by dpinte, Tue Oct 3 09:34:51 2006 UTC
# Line 1  Line 1 
1  # Copyright (c) 2003 by Intevation GmbH  # Copyright (c) 2003, 2004 by Intevation GmbH
2  # Authors:  # Authors:
3  # Jonathan Coles <[email protected]>  # Jonathan Coles <[email protected]>
4  #  #
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  from Thuban import _  """The Classification Generator Dialog"""
9    
10    __version__ = "$Revision$"
11    # $Source$
12    # $Id$
13    
14    
15  from wxPython.wx import *  import sys
16    
17    import wx
18    
19    from Thuban import _
20    
21  from Thuban.Model.classification import Classification, ClassGroupRange, \  from Thuban.Model.classification import ClassGroupProperties
     ClassGroupSingleton, ClassGroupProperties  
22    
23  from Thuban.Model.table import Table, FIELDTYPE_INT, FIELDTYPE_DOUBLE, \  from Thuban.Model.table import FIELDTYPE_INT, FIELDTYPE_DOUBLE, \
24       FIELDTYPE_STRING       FIELDTYPE_STRING
25    
26  from Thuban.Model.color import Color  from Thuban.Model.layer import SHAPETYPE_ARC
27    from Thuban.Model.range import Range
28    from Thuban.UI.common import ThubanBeginBusyCursor, ThubanEndBusyCursor
29    
30    import classifier, resource
31    
32    from Thuban.Model.classgen import \
33        generate_uniform_distribution, generate_singletons, generate_quantiles, \
34        CustomRamp, grey_ramp, red_ramp, green_ramp, blue_ramp, green_to_red_ramp, \
35        HotToColdRamp, FixedRamp
36    
37    
38    USEALL_BMP  = "group_use_all"
39    USE_BMP     = "group_use"
40    USENOT_BMP  = "group_use_not"
41    USENONE_BMP = "group_use_none"
42    
43  import classifier  GENCOMBOSTR_UNIFORM = _("Uniform Distribution")
44    GENCOMBOSTR_UNIQUE = _("Unique Values")
45    GENCOMBOSTR_QUANTILES = _("Quantiles from Table")
46    
47  from Thuban.common import Str2Num  PROPCOMBOSTR_CUSTOM     = _("Custom Ramp")
48    PROPCOMBOSTR_GREY       = _("Grey Ramp")
49    PROPCOMBOSTR_RED        = _("Red Ramp")
50    PROPCOMBOSTR_GREEN      = _("Green Ramp")
51    PROPCOMBOSTR_BLUE       = _("Blue Ramp")
52    PROPCOMBOSTR_GREEN2RED  = _("Green-to-Red Ramp")
53    PROPCOMBOSTR_HOT2COLD   = _("Hot-to-Cold Ramp")
54    
 ID_CLASSGEN_GEN = 4001  
 ID_CLASSGEN_CLOSE = 4002  
55  ID_CLASSGEN_GENCOMBO = 4007  ID_CLASSGEN_GENCOMBO = 4007
56  ID_CLASSGEN_PROPCOMBO = 4008  ID_CLASSGEN_PROPCOMBO = 4008
57    
58  GENCOMBOSTR_UNIFORM = _("Uniform Distribution")  ID_BORDER_COLOR = 4009
59  GENCOMBOSTR_UNIQUE = _("Unique Values")  ID_BORDER_COLOR_CHANGE = 4010
60    
61  PROPCOMBOSTR_CUSTOM = _("Custom Ramp")  class ClassGenDialog(wx.Dialog):
 PROPCOMBOSTR_RED    = _("Red Ramp")  
 PROPCOMBOSTR_GREEN  = _("Green Ramp")  
 PROPCOMBOSTR_BLUE   = _("Blue Ramp")  
62    
 class ClassGenDialog(wxDialog):  
                                                                                   
63      def __init__(self, parent, layer, fieldName):      def __init__(self, parent, layer, fieldName):
64          """Inialize the class generating dialog.          """Inialize the class generating dialog.
65    
66          parent -- this must be an instance of the Classifier class          parent -- this must be an instance of the Classifier class
67          """          """
68    
69          wxDialog.__init__(self, parent, -1, _("Generate Classification"),          wx.Dialog.__init__(self, parent, -1, _("Generate Classification"),
70                            style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)                            style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)
71                                                                                    
72          self.parent = parent          self.parent = parent
73            self.layer = layer
74          self.clazz = None          self.clazz = None
75    
76          self.type, name, width, prec = layer.table.field_info_by_name(fieldName)          col = layer.ShapeStore().Table().Column(fieldName)
77            self.type = col.type
78    
79            self.fieldName = fieldName
80            self.fieldType = self.type
81    
82            self.curGenPanel = None
83    
84            self.genpanels = []
85    
86          #############          #############
87          # we need to create genButton first because when we create the          # we need to create genButton first because when we create the
88          # panels they will call AllowGenerate() which uses genButton.          # panels they will call AllowGenerate() which uses genButton.
89          #          #
90          buttonSizer = wxBoxSizer(wxHORIZONTAL)          self.genButton = wx.Button(self, wx.ID_OK, _("Generate"))
91          self.genButton = wxButton(self, ID_CLASSGEN_GEN, _("Generate"))          self.cancelButton = wx.Button(self, wx.ID_CANCEL, _("Close"))
92            self.genButton.SetDefault()
93    
94          buttonSizer.Add(self.genButton, 0, wxALL, 4)          self.genChoice = wx.Choice(self, ID_CLASSGEN_GENCOMBO)
         buttonSizer.Add(60, 20, 0, wxALL, 4)  
         buttonSizer.Add(wxButton(self, ID_CLASSGEN_CLOSE, _("Close")),  
                         0, wxALL, 4)  
95    
96          #############          self.genpanels.append((GENCOMBOSTR_UNIQUE, GenUniquePanel))
97            if self.type in (FIELDTYPE_INT, FIELDTYPE_DOUBLE):
98          sizer = wxBoxSizer(wxVERTICAL)              self.genpanels.append((GENCOMBOSTR_UNIFORM, GenUniformPanel))
99                self.genpanels.append((GENCOMBOSTR_QUANTILES, GenQuantilesPanel))
         sizer.Add(wxStaticText(self, -1, _("Field: %s") % fieldName),  
                   0, wxALL, 4)  
         sizer.Add(wxStaticText(  
             self, -1,  
             _("Field Type: %s") % classifier.Classifier.type2string[self.type]),  
             0, wxALL, 4)  
   
         psizer = wxBoxSizer(wxHORIZONTAL)  
         psizer.Add(wxStaticText(self, -1, _("Generate:")),  
             0, wxALIGN_CENTER_VERTICAL, 0)  
   
         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)  
100    
101          sizer.Add(psizer, 0, wxALL | wxGROW, 4)          for name, clazz in self.genpanels:
102                self.genChoice.Append(name, [clazz, None])
103    
104          #############          self.genChoice.SetSelection(0)
105    
106          self.genPanel = None          for i in range(self.genChoice.GetCount()):
107                clazz, obj = self.genChoice.GetClientData(i)
108    
109          panel = GenUniquePanel(self, layer, fieldName, self.type)              if obj is None:
110          self.genCombo.Append(GENCOMBOSTR_UNIQUE, panel)                  obj = clazz(self, self.layer, self.fieldName, self.fieldType)
111          sizer.Add(panel, 1, wxGROW | wxALL, 4)                  obj.Hide()
112                    self.genChoice.SetClientData(i, [clazz, obj])
113    
         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)  
114    
115          #############          #############
116    
117          psizer = wxBoxSizer(wxHORIZONTAL)          sizer = wx.BoxSizer(wx.VERTICAL)
         psizer.Add(wxStaticText(self, -1, _("Color Schemes:")),  
             0, wxALIGN_CENTER_VERTICAL, 0)  
   
         self.propCombo = wxComboBox(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)  
118    
119          #############          sizer.Add(wx.StaticText(self, -1, _("Field: %s") % fieldName),
120                      0, wx.ALL, 4)
121          self.propPanel = None          sizer.Add(wx.StaticText(
122          panel = CustomRampPanel(self, layer.ShapeType())              self, -1,
123          sizer.Add(panel, 1, wxALL | wxGROW, 4)              _("Data Type: %s") % classifier.Classifier.type2string[self.type]),
124          sizer.Show(panel, False)              0, wx.ALL, 4)
125    
126          self.propCombo.Append(PROPCOMBOSTR_RED,   RedRamp())          psizer = wx.BoxSizer(wx.HORIZONTAL)
127          self.propCombo.Append(PROPCOMBOSTR_GREEN, GreenRamp())          psizer.Add(wx.StaticText(self, -1, _("Generate:")),
128          self.propCombo.Append(PROPCOMBOSTR_BLUE,  BlueRamp())              0, wx.ALIGN_CENTER_VERTICAL, 0)
129          self.propCombo.Append(PROPCOMBOSTR_CUSTOM, panel)          psizer.Add(self.genChoice, 1, wx.ALL | wx.GROW, 4)
130    
131            sizer.Add(psizer, 0, wx.ALL | wx.GROW, 4)
132    
133            self.sizer_genPanel = wx.BoxSizer(wx.VERTICAL)
134            sizer.Add(self.sizer_genPanel, 1, wx.GROW | wx.ALL, 4)
135    
136            psizer = wx.BoxSizer(wx.HORIZONTAL)
137            psizer.Add(wx.StaticText(self, -1, _("Color Scheme:")),
138                0, wx.ALIGN_CENTER_VERTICAL, 0)
139    
140            # Properties (Ramp) ComboBox
141            self.propCombo = wx.Choice(self, ID_CLASSGEN_PROPCOMBO)
142    
143            self.propPanel = None
144            custom_ramp_panel = CustomRampPanel(self, layer.ShapeType())
145    
146          #############          self.propCombo.Append(PROPCOMBOSTR_GREY,  grey_ramp)
147            self.propCombo.Append(PROPCOMBOSTR_RED,   red_ramp)
148            self.propCombo.Append(PROPCOMBOSTR_GREEN, green_ramp)
149            self.propCombo.Append(PROPCOMBOSTR_BLUE,  blue_ramp)
150            self.propCombo.Append(PROPCOMBOSTR_GREEN2RED, green_to_red_ramp)
151            self.propCombo.Append(PROPCOMBOSTR_HOT2COLD,  HotToColdRamp())
152            self.propCombo.Append(PROPCOMBOSTR_CUSTOM, custom_ramp_panel)
153    
154            self.propCombo.SetSelection(0)
155    
156            psizer.Add(self.propCombo, 1, wx.ALL | wx.GROW, 4)
157            sizer.Add(psizer, 0, wx.ALL | wx.GROW, 4)
158    
159            if layer.ShapeType() != SHAPETYPE_ARC:
160                psizer = wx.BoxSizer(wx.HORIZONTAL)
161                self.fix_border_check = wx.CheckBox(self, -1, _("Fix Border Color"))
162                psizer.Add(self.fix_border_check, 0, wx.ALL | wx.GROW, 4)
163                self.border_color = classifier.ClassGroupPropertiesCtrl(
164                    self, ID_BORDER_COLOR,
165                    ClassGroupProperties(), SHAPETYPE_ARC,
166                    style=wx.SIMPLE_BORDER, size=(40, 20))
167                psizer.Add(self.border_color, 0, wx.ALL | wx.GROW, 4)
168                psizer.Add(wx.Button(self, ID_BORDER_COLOR_CHANGE, _("Change")),
169                        0, wx.ALL, 4)
170                sizer.Add(psizer, 0, wx.ALL | wx.GROW, 4)
171                self.Bind(wx.EVT_BUTTON, self.OnBorderColorChange, id=ID_BORDER_COLOR_CHANGE)
172            else:
173                self.border_color = None
174    
175          sizer.Add(buttonSizer, 0,          sizer.Add(custom_ramp_panel, 1, wx.GROW | wx.ALL, 4)
176                    wxALL | wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL, 4)          sizer.Show(custom_ramp_panel, False)
177    
178            # Finally place the main buttons
179            buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
180            buttonSizer.Add(self.genButton, 0, wx.RIGHT|wx.EXPAND, 10)
181            buttonSizer.Add(self.cancelButton, 0, wx.RIGHT|wx.EXPAND, 10)
182            sizer.Add(buttonSizer, 0, wx.ALIGN_RIGHT|wx.BOTTOM|wx.TOP, 10)
183    
184          self.SetSizer(sizer)          self.SetSizer(sizer)
185          self.SetAutoLayout(True)          self.SetAutoLayout(True)
186          sizer.SetSizeHints(self)          sizer.SetSizeHints(self)
187    
188          self.sizer = sizer          self.topBox = sizer
189    
190            self.__DoOnGenTypeSelect()
191    
192            self.Bind(wx.EVT_CHOICE, self._OnGenTypeSelect, id=ID_CLASSGEN_GENCOMBO)
193            self.Bind(wx.EVT_CHOICE, self._OnPropTypeSelect, id=ID_CLASSGEN_PROPCOMBO)
194            self.Bind(wx.EVT_BUTTON, self.OnOK, self.genButton)
195            self.Bind(wx.EVT_BUTTON, self.OnCancel, self.cancelButton)
196    
197          EVT_BUTTON(self, ID_CLASSGEN_GEN, self._OnGenerate)          self.__DoOnGenTypeSelect()
198          EVT_BUTTON(self, ID_CLASSGEN_CLOSE, self._OnCloseBtn)  
199            self.genChoice.SetFocus()
200    
201      def GetClassification(self):      def GetClassification(self):
202          return self.clazz          return self.clazz
# Line 149  class ClassGenDialog(wxDialog): Line 204  class ClassGenDialog(wxDialog):
204      def AllowGenerate(self, on):      def AllowGenerate(self, on):
205          pass #self.genButton.Enable(on)          pass #self.genButton.Enable(on)
206    
207      def _OnGenerate(self, event):      def OnOK(self, event):
208            """This is really the generate button, but we want to override
209            the wxDialog class.
210            """
211    
212            index = self.genChoice.GetSelection()
213    
214          index = self.genCombo.GetSelection()          assert index != -1, "button should be disabled!"
215    
216          genSel = self.genCombo.GetString(index)          genSel = self.genChoice.GetString(index)
217          genPanel = self.genCombo.GetClientData(index)          clazz, genPanel = self.genChoice.GetClientData(index)
218    
219          propPanel = self.propPanel          propPanel = self.propPanel
220    
221          if genSel in (GENCOMBOSTR_UNIFORM, GENCOMBOSTR_UNIQUE):          if genSel in (GENCOMBOSTR_UNIFORM,          \
222                          GENCOMBOSTR_UNIQUE,           \
223                          GENCOMBOSTR_QUANTILES):
224    
225              numGroups = genPanel.GetNumGroups()              numGroups = genPanel.GetNumGroups()
226    
227              index = self.propCombo.GetSelection()              index = self.propCombo.GetSelection()
# Line 167  class ClassGenDialog(wxDialog): Line 230  class ClassGenDialog(wxDialog):
230              propPanel = self.propCombo.GetClientData(index)              propPanel = self.propCombo.GetClientData(index)
231    
232              ramp = propPanel.GetRamp()              ramp = propPanel.GetRamp()
233                if self.border_color and self.fix_border_check.IsChecked():
234                    props = self.border_color.GetProperties()
235                    ramp = FixedRamp(ramp,
236                        (props.GetLineColor(), props.GetLineWidth(), None))
237    
238              if genSel == GENCOMBOSTR_UNIFORM:              if genSel == GENCOMBOSTR_UNIFORM:
239    
# Line 177  class ClassGenDialog(wxDialog): Line 244  class ClassGenDialog(wxDialog):
244                      and max is not None \                      and max is not None \
245                      and numGroups is not None:                      and numGroups is not None:
246    
247                      self.clazz = ClassGenerator().GenUnifromDistribution(                      self.clazz = generate_uniform_distribution(
248                                  min, max, numGroups, ramp,                                  min, max, numGroups, ramp,
249                                  self.type == FIELDTYPE_INT)                                  self.type == FIELDTYPE_INT)
250    
# Line 187  class ClassGenDialog(wxDialog): Line 254  class ClassGenDialog(wxDialog):
254    
255                  list = genPanel.GetValueList()                  list = genPanel.GetValueList()
256    
257                  if len(list) > 0 \                  if len(list) > 0:
258                      and numGroups is not None:                      self.clazz = generate_singletons(list, ramp)
259                        self.parent._SetClassification(self.clazz)
260    
261                      self.clazz = ClassGenerator().GenSingletonsFromList(              elif genSel == GENCOMBOSTR_QUANTILES:
                                     list, numGroups, ramp)  
262    
263                    _range = genPanel.GetRange()
264                    _list = genPanel.GetList()
265                    _list.sort()
266    
267                    delta = 1 / float(numGroups)
268                    percents = [delta * i for i in range(1, numGroups + 1)]
269                    adjusted, self.clazz = \
270                        generate_quantiles(_list, percents, ramp, _range)
271    
272                    if adjusted:
273                        dlg = wx.MessageDialog(self,
274                            _("Based on the data from the table and the input\n"
275                         "values, the exact quantiles could not be generated.\n\n"
276                              "Accept a close estimate?"),
277                            _("Problem with Quantiles"),
278    
279                            wx.YES_NO|wx.YES_DEFAULT|wx.ICON_QUESTION)
280                        if dlg.ShowModal() == wx.ID_YES:
281                            self.parent._SetClassification(self.clazz)
282                    else:
283                      self.parent._SetClassification(self.clazz)                      self.parent._SetClassification(self.clazz)
284    
285      def _OnCloseBtn(self, event):      def OnCancel(self, event):
286          self.Close()          self.Close()
287    
288        def OnBorderColorChange(self, event):
289            self.border_color.DoEdit()
290    
291      def _OnGenTypeSelect(self, event):      def _OnGenTypeSelect(self, event):
292            self.__DoOnGenTypeSelect()
293            return
294    
295          combo = event.GetEventObject()          combo = event.GetEventObject()
296    
297          selIndex = combo.GetSelection()          selIndex = combo.GetSelection()
298    
299          if self.genPanel is not None:          if self.genPanel is not None:
300              self.sizer.Show(self.genPanel, False)              self.topBox.Show(self.genPanel, False)
301    
302          self.genPanel = combo.GetClientData(selIndex)          self.genPanel = combo.GetClientData(selIndex)
303          if self.genPanel is not None:          if self.genPanel is not None:
304              self.sizer.Show(self.genPanel, True)              self.topBox.Show(self.genPanel, True)
305    
306          self.sizer.SetSizeHints(self)          self.topBox.SetSizeHints(self)
307          self.sizer.Layout()          self.topBox.Layout()
308    
309      def _OnPropTypeSelect(self, event):      def _OnPropTypeSelect(self, event):
310          combo = event.GetEventObject()          combo = event.GetEventObject()
# Line 220  class ClassGenDialog(wxDialog): Line 312  class ClassGenDialog(wxDialog):
312          selIndex = combo.GetSelection()          selIndex = combo.GetSelection()
313          sel = combo.GetString(selIndex)          sel = combo.GetString(selIndex)
314    
315          if isinstance(self.propPanel, wxPanel):          if isinstance(self.propPanel, wx.Panel):
316              self.sizer.Show(self.propPanel, False)              self.topBox.Show(self.propPanel, False)
317    
318          self.propPanel = combo.GetClientData(selIndex)          self.propPanel = combo.GetClientData(selIndex)
319    
320          if isinstance(self.propPanel, wxPanel):          if isinstance(self.propPanel, wx.Panel):
321              self.sizer.Show(self.propPanel, True)              self.topBox.Show(self.propPanel, True)
322    
323            self.topBox.SetSizeHints(self)
324            self.topBox.Layout()
325    
326        def __DoOnGenTypeSelect(self):
327            choice = self.genChoice
328    
329            sel = choice.GetSelection()
330            if sel == -1: return
331    
332          self.sizer.SetSizeHints(self)          clazz, obj = choice.GetClientData(sel)
         self.sizer.Layout()  
333    
334            if self.curGenPanel is not None:
335                self.curGenPanel.Hide()
336                self.sizer_genPanel.Remove(self.curGenPanel)
337    
338            self.curGenPanel = obj
339            self.curGenPanel.Show()
340    
341            self.sizer_genPanel.Add(self.curGenPanel, 1,
342                wx.ALL|wx.EXPAND|wx.ADJUST_MINSIZE, 3)
343            self.sizer_genPanel.Layout()
344            self.Layout()
345            self.topBox.SetSizeHints(self)
346    
347  ID_UNIFORM_MIN = 4001  ID_UNIFORM_MIN = 4001
348  ID_UNIFORM_MAX = 4002  ID_UNIFORM_MAX = 4002
# Line 238  ID_UNIFORM_NGROUPS = 4003 Line 350  ID_UNIFORM_NGROUPS = 4003
350  ID_UNIFORM_STEP = 4004  ID_UNIFORM_STEP = 4004
351  ID_UNIFORM_RETRIEVE = 4005  ID_UNIFORM_RETRIEVE = 4005
352    
353  class GenUniformPanel(wxPanel):  class GenUniformPanel(wx.Panel):
354    
355      def __init__(self, parent, layer, fieldName, fieldType):      def __init__(self, parent, layer, fieldName, fieldType):
356          wxPanel.__init__(self, parent, -1)          wx.Panel.__init__(self, parent, -1)
357    
358          self.parent = parent          self.parent = parent
359          self.layer = layer          self.layer = layer
360          self.fieldName = fieldName          self.fieldName = fieldName
361          self.fieldType = fieldType          self.fieldType = fieldType
362    
363          topSizer = wxStaticBoxSizer(wxStaticBox(self, -1, ""),          topSizer = wx.StaticBoxSizer(wx.StaticBox(self, -1, ""),
364                                      wxVERTICAL)                                      wx.VERTICAL)
365    
366          #############          #############
367    
368          sizer = wxBoxSizer(wxHORIZONTAL)          sizer = wx.BoxSizer(wx.HORIZONTAL)
369    
370          sizer.Add(wxStaticText(self, -1, _("Min:")), 0, wxALL, 4)          sizer.Add(wx.StaticText(self, -1, _("Min:")), 0, wx.ALL, 4)
371          self.minCtrl = wxTextCtrl(self, ID_UNIFORM_MIN, style=wxTE_RIGHT)          self.minCtrl = wx.TextCtrl(self, ID_UNIFORM_MIN, style=wx.TE_RIGHT)
372          sizer.Add(self.minCtrl, 1, wxALL, 4)          sizer.Add(self.minCtrl, 1, wx.ALL, 4)
373          EVT_TEXT(self, ID_UNIFORM_MIN, self._OnRangeChanged)          self.Bind(wx.EVT_TEXT, self._OnRangeChanged, id=ID_UNIFORM_MIN)
374    
375          sizer.Add(wxStaticText(self, -1, _("Max:")), 0, wxALL, 4)          sizer.Add(wx.StaticText(self, -1, _("Max:")), 0, wx.ALL, 4)
376          self.maxCtrl = wxTextCtrl(self, ID_UNIFORM_MAX, style=wxTE_RIGHT)          self.maxCtrl = wx.TextCtrl(self, ID_UNIFORM_MAX, style=wx.TE_RIGHT)
377          sizer.Add(self.maxCtrl, 1, wxALL, 4)          sizer.Add(self.maxCtrl, 1, wx.ALL, 4)
378          EVT_TEXT(self, ID_UNIFORM_MAX, self._OnRangeChanged)          self.Bind(wx.EVT_TEXT, self._OnRangeChanged, id=ID_UNIFORM_MAX)
379    
380          sizer.Add(wxButton(self, ID_UNIFORM_RETRIEVE, _("Retrieve From Table")),          sizer.Add(wx.Button(self, ID_UNIFORM_RETRIEVE, _("Retrieve From Table")),
381              0, wxALL, 4)              0, wx.ALL, 4)
382          EVT_BUTTON(self, ID_UNIFORM_RETRIEVE, self._OnRetrieve)          self.Bind(wx.EVT_BUTTON, self._OnRetrieve, id=ID_UNIFORM_RETRIEVE)
383    
384          topSizer.Add(sizer, 1, wxGROW, 0)          topSizer.Add(sizer, 1, wx.GROW, 0)
385    
386          #############          #############
387    
388          sizer = wxBoxSizer(wxHORIZONTAL)          sizer = wx.BoxSizer(wx.HORIZONTAL)
389    
390          sizer.Add(wxStaticText(self, -1, _("Number of Groups:")), 0, wxALL, 4)          sizer.Add(wx.StaticText(self, -1, _("Number of Groups:")), 0, wx.ALL, 4)
391          self.numGroupsCtrl = wxSpinCtrl(self, ID_UNIFORM_NGROUPS, style=wxTE_RIGHT)          self.numGroupsCtrl = wx.SpinCtrl(self, ID_UNIFORM_NGROUPS,
392          EVT_TEXT(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)                                          style=wx.TE_RIGHT)
393          EVT_SPINCTRL(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)          self.Bind(wx.EVT_TEXT, self._OnNumGroupsChanged, id=ID_UNIFORM_NGROUPS)
394          sizer.Add(self.numGroupsCtrl, 1, wxALL, 4)          self.Bind(wx.EVT_SPINCTRL, self._OnNumGroupsChanged, id=ID_UNIFORM_NGROUPS)
395            sizer.Add(self.numGroupsCtrl, 1, wx.ALL, 4)
396          sizer.Add(wxStaticText(self, -1, _("Stepping:")), 0, wxALL, 4)  
397          self.stepCtrl = wxTextCtrl(self, ID_UNIFORM_STEP, style=wxTE_RIGHT)          sizer.Add(wx.StaticText(self, -1, _("Stepping:")), 0, wx.ALL, 4)
398          EVT_TEXT(self, ID_UNIFORM_STEP, self._OnSteppingChanged)          self.stepCtrl = wx.TextCtrl(self, ID_UNIFORM_STEP, style=wx.TE_RIGHT)
399          sizer.Add(self.stepCtrl , 1, wxALL, 4)          self.Bind(wx.EVT_TEXT, self._OnSteppingChanged, id=ID_UNIFORM_STEP)
400            sizer.Add(self.stepCtrl , 1, wx.ALL, 4)
401    
402          topSizer.Add(sizer, 1, wxGROW, 0)          topSizer.Add(sizer, 1, wx.GROW, 0)
403    
404          #############          #############
405    
# Line 297  class GenUniformPanel(wxPanel): Line 410  class GenUniformPanel(wxPanel):
410          self.numGroupsChanging = False          self.numGroupsChanging = False
411          self.steppingChanging = False          self.steppingChanging = False
412    
413          self.numGroupsCtrl.SetRange(1, 100)          self.numGroupsCtrl.SetRange(1, sys.maxint)
414    
415          self.numGroupsCtrl.SetValue(1)          self.numGroupsCtrl.SetValue(1)
416          self.stepCtrl.SetValue("1")          self.stepCtrl.SetValue("1")
# Line 307  class GenUniformPanel(wxPanel): Line 420  class GenUniformPanel(wxPanel):
420    
421      def GetNumGroups(self):      def GetNumGroups(self):
422          value = self.numGroupsCtrl.GetValue()          value = self.numGroupsCtrl.GetValue()
423          return self.__GetValidatedTypeEntry(self.numGroupsCtrl,          return self.__GetValidatedTypeEntry(self.numGroupsCtrl,
424                                              value,                                              value,
425                                              FIELDTYPE_INT,                                              FIELDTYPE_INT,
426                                              None)                                              None)
427    
428      def GetStepping(self):      def GetStepping(self):
429          step = self.stepCtrl.GetValue()          step = self.stepCtrl.GetValue()
430          return self.__GetValidatedTypeEntry(self.stepCtrl,          return self.__GetValidatedTypeEntry(self.stepCtrl,
431                                              step,                                              step,
432                                              self.fieldType,                                              self.fieldType,
433                                              0)                                              0)
# Line 322  class GenUniformPanel(wxPanel): Line 435  class GenUniformPanel(wxPanel):
435      def GetMin(self):      def GetMin(self):
436          min = self.minCtrl.GetValue()          min = self.minCtrl.GetValue()
437          max = self.maxCtrl.GetValue()          max = self.maxCtrl.GetValue()
438          return self.__GetValidatedTypeEntry(self.minCtrl,          return self.__GetValidatedTypeEntry(self.minCtrl,
439                                              min,                                              min,
440                                              self.fieldType,                                              self.fieldType,
441                                              max)                                              max)
# Line 330  class GenUniformPanel(wxPanel): Line 443  class GenUniformPanel(wxPanel):
443      def GetMax(self):      def GetMax(self):
444          min = self.minCtrl.GetValue()          min = self.minCtrl.GetValue()
445          max = self.maxCtrl.GetValue()          max = self.maxCtrl.GetValue()
446          return self.__GetValidatedTypeEntry(self.maxCtrl,          return self.__GetValidatedTypeEntry(self.maxCtrl,
447                                              max,                                              max,
448                                              self.fieldType,                                              self.fieldType,
449                                              min)                                              min)
450    
451      def _OnRangeChanged(self, event):      def _OnRangeChanged(self, event):
452    
453          hasFocus = wxWindow_FindFocus() == event.GetEventObject()          hasFocus = wx.Window_FindFocus() == event.GetEventObject()
454          min = self.GetMin()          min = self.GetMin()
455          max = self.GetMax()          max = self.GetMax()
456    
# Line 347  class GenUniformPanel(wxPanel): Line 460  class GenUniformPanel(wxPanel):
460          self.numGroupsCtrl.Enable(on)          self.numGroupsCtrl.Enable(on)
461          self.stepCtrl.Enable(on)          self.stepCtrl.Enable(on)
462    
         if on:  
             self.numGroupsCtrl.SetRange(1, abs(max - min) / 0.001)  
   
463          ngroups = self.GetNumGroups()          ngroups = self.GetNumGroups()
464    
465          if ngroups is not None  \          if ngroups is not None  \
# Line 380  class GenUniformPanel(wxPanel): Line 490  class GenUniformPanel(wxPanel):
490          min = self.GetMin()          min = self.GetMin()
491          max = self.GetMax()          max = self.GetMax()
492    
         if ngroups >= self.numGroupsCtrl.GetMax():  
             self.numGroupsCtrl.SetRange(1, ngroups + 1)  
   
493          if ngroups is not None  \          if ngroups is not None  \
494              and min is not None \              and min is not None \
495              and max is not None \              and max is not None \
# Line 429  class GenUniformPanel(wxPanel): Line 536  class GenUniformPanel(wxPanel):
536              self.parent.AllowGenerate(False)              self.parent.AllowGenerate(False)
537    
538      def _OnRetrieve(self, event):      def _OnRetrieve(self, event):
539            table = self.layer.ShapeStore().Table()
540          if self.layer.table is not None:          if table is not None:
541              range = self.layer.table.field_range(self.fieldName)              ThubanBeginBusyCursor()
542              self.minCtrl.SetValue(str(range[0][0]))              try:
543              self.maxCtrl.SetValue(str(range[1][0]))                  min, max = table.ValueRange(self.fieldName)
544                    self.minCtrl.SetValue(str(min))
545                    self.maxCtrl.SetValue(str(max))
546                finally:
547                    ThubanEndBusyCursor()
548    
549      def __GetValidatedTypeEntry(self, win, value, type, badValue = None):      def __GetValidatedTypeEntry(self, win, value, type, badValue = None):
550    
551          if type == FIELDTYPE_INT:          if type == FIELDTYPE_INT:
552              func = int              func = int
553          elif type == FIELDTYPE_DOUBLE:          elif type == FIELDTYPE_DOUBLE:
554              func = float              func = float
# Line 466  class GenUniformPanel(wxPanel): Line 577  class GenUniformPanel(wxPanel):
577              valid = False              valid = False
578    
579          if valid:          if valid:
580              win.SetForegroundColour(wxBLACK)              win.SetForegroundColour(wx.BLACK)
581          else:          else:
582              win.SetForegroundColour(wxRED)              win.SetForegroundColour(wx.RED)
583    
584          win.Refresh()          win.Refresh()
585    
586          return valid          return valid
587    
588      def __CalcStepping(self, min, max, ngroups):      def __CalcStepping(self, min, max, ngroups):
         step = Str2Num(str((max - min) / float(ngroups)))  
589          if self.fieldType == FIELDTYPE_INT:          if self.fieldType == FIELDTYPE_INT:
590              step = int(step)              step = int((max - min + 1) / float(ngroups))
591            else:
592                step = (max - min) / float(ngroups)
593    
594          return step          return step
595    
# Line 499  ID_UNIQUE_DONTUSE = 4004 Line 611  ID_UNIQUE_DONTUSE = 4004
611  ID_UNIQUE_USENONE = 4005  ID_UNIQUE_USENONE = 4005
612  ID_UNIQUE_SORTAVAIL = 4006  ID_UNIQUE_SORTAVAIL = 4006
613  ID_UNIQUE_SORTUSE = 4007  ID_UNIQUE_SORTUSE = 4007
614    ID_UNIQUE_REVAVAIL = 4008
615    ID_UNIQUE_REVUSE = 4009
616    
617  class GenUniquePanel(wxPanel):  class GenUniquePanel(wx.Panel):
618    
619      def __init__(self, parent, layer, fieldName, fieldType):      def __init__(self, parent, layer, fieldName, fieldType):
620          wxPanel.__init__(self, parent, -1)          wx.Panel.__init__(self, parent, -1)
621    
622          self.parent = parent          self.parent = parent
623          self.layer = layer          self.layer = layer
624          self.fieldName = fieldName          self.fieldName = fieldName
625          self.fieldType = fieldType          self.fieldType = fieldType
626    
627          topSizer = wxStaticBoxSizer(wxStaticBox(self, -1, ""),          topSizer = wx.StaticBoxSizer(wx.StaticBox(self, -1, ""),
628                                      wxVERTICAL)                                      wx.VERTICAL)
629    
630    
631          sizer = wxBoxSizer(wxHORIZONTAL)          #bsizer = wxBoxSizer(wxVERTICAL)
632            topSizer.Add(wx.Button(self, ID_UNIQUE_RETRIEVE,
633                                _("Retrieve From Table")),
634                       0, wx.ALL | wx.ALIGN_RIGHT, 4)
635    
636          self.dataList = []          self.Bind(wx.EVT_BUTTON, self._OnRetrieve, id=ID_UNIQUE_RETRIEVE)
637    
638          psizer = wxBoxSizer(wxVERTICAL)          #topSizer.Add(bsizer, 0, wx.ALL, 4)
         self.list_avail = wxListCtrl(self, -1,  
                         style=wxLC_REPORT | wxLC_SINGLE_SEL)  
         self.list_avail.InsertColumn(0, "Available")  
         self.list_avail_data = []  
         psizer.Add(self.list_avail, 1, wxGROW, 0)  
639    
640          psizer.Add(wxButton(self, ID_UNIQUE_SORTAVAIL, _("Sort")))          sizer = wx.BoxSizer(wx.HORIZONTAL)
641    
642          EVT_BUTTON(self, ID_UNIQUE_SORTAVAIL, self._OnSortAvailList)          self.dataList = []
643    
644          sizer.Add(psizer, 1, wxGROW, 0)          psizer = wx.BoxSizer(wx.VERTICAL)
645            self.list_avail = wx.ListCtrl(self, -1,
646                            style=wx.LC_REPORT | wx.LC_SINGLE_SEL)
647            self.list_avail.InsertColumn(0, _("Available"))
648            self.list_avail_data = []
649            psizer.Add(self.list_avail, 1, wx.GROW, 0)
650    
651                    bsizer = wx.BoxSizer(wx.HORIZONTAL)
652          bsizer = wxBoxSizer(wxVERTICAL)          bsizer.Add(wx.Button(self, ID_UNIQUE_SORTAVAIL, _("Sort")))
653          bsizer.Add(wxButton(self, ID_UNIQUE_USEALL, _("Use All")),          self.Bind(wx.EVT_BUTTON, self._OnSortList, id=ID_UNIQUE_SORTAVAIL)
654                     0, wxGROW | wxALL, 4)  
655          bsizer.Add(wxButton(self, ID_UNIQUE_USE, _("Use >>")),          bsizer.Add(wx.Button(self, ID_UNIQUE_REVAVAIL, _("Reverse")))
656                     0, wxGROW | wxALL, 4)          self.Bind(wx.EVT_BUTTON, self._OnReverseList, id=ID_UNIQUE_REVAVAIL)
657          bsizer.Add(wxButton(self, ID_UNIQUE_DONTUSE, _("<< Don't Use")),  
658                     0, wxGROW | wxALL, 4)          psizer.Add(bsizer, 0, wx.GROW, 0)
659          bsizer.Add(wxButton(self, ID_UNIQUE_USENONE, _("Use None")),          sizer.Add(psizer, 1, wx.GROW, 0)
660                     0, wxGROW | wxALL, 4)  
661    
662          EVT_BUTTON(self, ID_UNIQUE_USEALL, self._OnUseAll)          bsizer = wx.BoxSizer(wx.VERTICAL)
663          EVT_BUTTON(self, ID_UNIQUE_USE, self._OnUse)  
664          EVT_BUTTON(self, ID_UNIQUE_DONTUSE, self._OnDontUse)          bmp = resource.GetBitmapResource(USEALL_BMP, wx.BITMAP_TYPE_XPM)
665          EVT_BUTTON(self, ID_UNIQUE_USENONE, self._OnUseNone)          bsizer.Add(wx.BitmapButton(self, ID_UNIQUE_USEALL, bmp),
666                       0, wx.GROW | wx.ALL, 4)
667          sizer.Add(bsizer, 0, wxALL | wxALIGN_CENTER_VERTICAL, 4)          bmp = resource.GetBitmapResource(USE_BMP, wx.BITMAP_TYPE_XPM)
668            bsizer.Add(wx.BitmapButton(self, ID_UNIQUE_USE, bmp),
669          psizer = wxBoxSizer(wxVERTICAL)                     0, wx.GROW | wx.ALL, 4)
670          self.list_use = wxListCtrl(self, -1,          bmp = resource.GetBitmapResource(USENOT_BMP, wx.BITMAP_TYPE_XPM)
671                          style=wxLC_REPORT | wxLC_SINGLE_SEL)          bsizer.Add(wx.BitmapButton(self, ID_UNIQUE_DONTUSE, bmp),
672          self.list_use.InsertColumn(0, "Use")                     0, wx.GROW | wx.ALL, 4)
673            bmp = resource.GetBitmapResource(USENONE_BMP, wx.BITMAP_TYPE_XPM)
674            bsizer.Add(wx.BitmapButton(self, ID_UNIQUE_USENONE, bmp),
675                       0, wx.GROW | wx.ALL, 4)
676    
677            self.Bind(wx.EVT_BUTTON, self._OnUseAll, id=ID_UNIQUE_USEALL)
678            self.Bind(wx.EVT_BUTTON, self._OnUse, id=ID_UNIQUE_USE)
679            self.Bind(wx.EVT_BUTTON, self._OnDontUse, id=ID_UNIQUE_DONTUSE)
680            self.Bind(wx.EVT_BUTTON, self._OnUseNone, id=ID_UNIQUE_USENONE)
681    
682            sizer.Add(bsizer, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 4)
683    
684            psizer = wx.BoxSizer(wx.VERTICAL)
685            self.list_use = wx.ListCtrl(self, -1,
686                            style=wx.LC_REPORT | wx.LC_SINGLE_SEL)
687            self.list_use.InsertColumn(0, _("Use"))
688          self.list_use_data = []          self.list_use_data = []
689          psizer.Add(self.list_use, 1, wxGROW, 0)          psizer.Add(self.list_use, 1, wx.GROW, 0)
690    
691          psizer.Add(wxButton(self, ID_UNIQUE_SORTUSE, _("Sort")))          bsizer = wx.BoxSizer(wx.HORIZONTAL)
692            bsizer.Add(wx.Button(self, ID_UNIQUE_SORTUSE, _("Sort")))
693            self.Bind(wx.EVT_BUTTON, self._OnSortList, id=ID_UNIQUE_SORTUSE)
694    
695          EVT_BUTTON(self, ID_UNIQUE_SORTUSE, self._OnSortUseList)          bsizer.Add(wx.Button(self, ID_UNIQUE_REVUSE, _("Reverse")))
696            self.Bind(wx.EVT_BUTTON, self._OnReverseList, id=ID_UNIQUE_REVUSE)
697    
698          sizer.Add(psizer, 1, wxGROW, 0)          psizer.Add(bsizer, 0, wx.GROW, 0)
699    
700          bsizer = wxBoxSizer(wxVERTICAL)          sizer.Add(psizer, 1, wx.GROW, 0)
         bsizer.Add(wxButton(self, ID_UNIQUE_RETRIEVE,  
                             _("Retrieve From Table")),  
                    0, wxGROW | wxALL, 4)  
701    
         EVT_BUTTON(self, ID_UNIQUE_RETRIEVE, self._OnRetrieve)  
702    
703          sizer.Add(bsizer, 0, wxALL, 4)          topSizer.Add(sizer, 1, wx.GROW, 0)
   
         topSizer.Add(sizer, 1, wxGROW, 0)  
704    
705          self.SetSizer(topSizer)          self.SetSizer(topSizer)
706          self.SetAutoLayout(True)          self.SetAutoLayout(True)
707          topSizer.SetSizeHints(self)          topSizer.SetSizeHints(self)
708    
709          self.parent.AllowGenerate(False)          width, height = self.list_avail.GetSizeTuple()
710            self.list_avail.SetColumnWidth(0,width)
711            width, height = self.list_use.GetSizeTuple()
712            self.list_use.SetColumnWidth(0,width)
713    
714          self.mylist = ["Hallo", "Welt!", "Wie", "geht", "es", "dir", "?"]          self.parent.AllowGenerate(False)
715    
716      def GetNumGroups(self):      def GetNumGroups(self):
717          return self.list_use.GetItemCount()          return self.list_use.GetItemCount()
# Line 590  class GenUniquePanel(wxPanel): Line 722  class GenUniquePanel(wxPanel):
722              list.append(self.dataList[self.list_use.GetItemData(i)])              list.append(self.dataList[self.list_use.GetItemData(i)])
723          return list          return list
724    
725      def _OnSortAvailList(self, event):      def _OnSortList(self, event):
726          self.list_avail.SortItems(lambda i1, i2:          id = event.GetId()
727                                      cmp(self.dataList[i1],  
728                                          self.dataList[i2]))          if id == ID_UNIQUE_SORTUSE:
729                list = self.list_use
730      def _OnSortUseList(self, event):          else:
731          self.list_use.SortItems(lambda i1, i2:              list = self.list_avail
732                                      cmp(self.dataList[i1],  
733                                          self.dataList[i2]))          list.SortItems(lambda i1, i2: cmp(self.dataList[i1],
734                                              self.dataList[i2]))
735    
736        def _OnReverseList(self, event):
737            id = event.GetId()
738    
739            if id == ID_UNIQUE_REVUSE:
740                list = self.list_use
741            else:
742                list = self.list_avail
743    
744            #
745            # always returning 1 reverses the list
746            #
747            list.SortItems(lambda i1, i2: 1)
748    
749      def _OnRetrieve(self, event):      def _OnRetrieve(self, event):
750          self.list_use.DeleteAllItems()          self.list_use.DeleteAllItems()
# Line 606  class GenUniquePanel(wxPanel): Line 752  class GenUniquePanel(wxPanel):
752          self.list_avail.DeleteAllItems()          self.list_avail.DeleteAllItems()
753          self.list_avail_data = []          self.list_avail_data = []
754    
755          list = self.layer.table.GetUniqueValues(self.fieldName)          ThubanBeginBusyCursor()
756          index = 0          try:
757          for v in list:              list = self.layer.ShapeStore().Table().UniqueValues(self.fieldName)
758              self.dataList.append(v)              index = 0
759              i = self.list_avail.InsertStringItem(index, str(v))              for v in list:
760              self.list_avail.SetItemData(index, i)                  self.dataList.append(v)
761                    i = self.list_avail.InsertStringItem(index, str(v))
762              self.list_avail_data.append(v)                  self.list_avail.SetItemData(index, i)
763              index += 1  
764                    self.list_avail_data.append(v)
765                    index += 1
766            finally:
767                ThubanEndBusyCursor()
768    
769      def _OnUseAll(self, event):      def _OnUseAll(self, event):
770          for i in range(self.list_avail.GetItemCount()):          for i in range(self.list_avail.GetItemCount()):
771              self.__MoveListItem(0, self.list_avail, self.list_use)              self.__MoveListItem(0, self.list_avail, self.list_use)
772    
773      def _OnUse(self, event):      def _OnUse(self, event):
         print "_OnUse"  
774          self.__MoveSelectedItems(self.list_avail, self.list_use)          self.__MoveSelectedItems(self.list_avail, self.list_use)
775    
776      def _OnDontUse(self, event):      def _OnDontUse(self, event):
         print "_OnDontUse"  
777          self.__MoveSelectedItems(self.list_use, self.list_avail)          self.__MoveSelectedItems(self.list_use, self.list_avail)
778    
779      def _OnUseNone(self, event):      def _OnUseNone(self, event):
         print "_OnUseNone"  
780    
781          for i in range(self.list_use.GetItemCount()):          for i in range(self.list_use.GetItemCount()):
782              self.__MoveListItem(0, self.list_use, self.list_avail)              self.__MoveListItem(0, self.list_use, self.list_avail)
# Line 637  class GenUniquePanel(wxPanel): Line 784  class GenUniquePanel(wxPanel):
784      def __MoveSelectedItems(self, list_src, list_dest):      def __MoveSelectedItems(self, list_src, list_dest):
785          while True:          while True:
786              index = list_src.GetNextItem(-1,              index = list_src.GetNextItem(-1,
787                                           wxLIST_NEXT_ALL,                                           wx.LIST_NEXT_ALL,
788                                           wxLIST_STATE_SELECTED)                                           wx.LIST_STATE_SELECTED)
789    
790              if index == -1:              if index == -1:
791                  break                  break
# Line 651  class GenUniquePanel(wxPanel): Line 798  class GenUniquePanel(wxPanel):
798          item = list_src.GetItem(index)          item = list_src.GetItem(index)
799    
800          x = list_dest.InsertStringItem(          x = list_dest.InsertStringItem(
801                  list_dest.GetItemCount(),                  list_dest.GetItemCount(),
802                  str(self.dataList[item.GetData()]))                  str(self.dataList[item.GetData()]))
803    
804          list_dest.SetItemData(x, item.GetData())          list_dest.SetItemData(x, item.GetData())
# Line 664  class GenUniquePanel(wxPanel): Line 811  class GenUniquePanel(wxPanel):
811  #       list.SetColumnWidth(0, event.GetSize().GetWidth())  #       list.SetColumnWidth(0, event.GetSize().GetWidth())
812  #        #      
813    
814    ID_QUANTILES_RANGE = 4001
815    ID_QUANTILES_RETRIEVE = 4002
816    
817    class GenQuantilesPanel(wx.Panel):
818    
819        def __init__(self, parent, layer, fieldName, fieldType):
820            wx.Panel.__init__(self, parent, -1)
821    
822            self.parent = parent
823            self.layer = layer
824            self.fieldName = fieldName
825            self.fieldType = fieldType
826    
827            topBox = wx.StaticBoxSizer(wx.StaticBox(self, -1, ""),
828                                        wx.VERTICAL)
829    
830            self.text_range = wx.TextCtrl(self, ID_QUANTILES_RANGE, "")
831            self.button_retrieve = wx.Button(self, ID_QUANTILES_RETRIEVE,
832                                            _("Retrieve from Table"))
833    
834            self.spin_numClasses = wx.SpinCtrl(self, -1, style=wx.TE_RIGHT)
835            self.spin_numClasses.SetRange(2, sys.maxint)
836            self.spin_numClasses.SetValue(2)
837    
838    
839            sizer = wx.BoxSizer(wx.HORIZONTAL)
840            sizer.Add(wx.StaticText(self, -1, _("Apply to Range")), 0, wx.ALL, 4)
841            sizer.Add(self.text_range, 1, wx.ALL, 4)
842            sizer.Add(self.button_retrieve, 0, wx.ALL, 4)
843    
844            topBox.Add(sizer, 0, wx.EXPAND, 0)
845    
846            sizer = wx.BoxSizer(wx.HORIZONTAL)
847            sizer.Add(wx.StaticText(self, -1, _("Number of Classes:")), 0, wx.ALL, 4)
848            sizer.Add(self.spin_numClasses, 1, wx.ALL, 4)
849    
850            topBox.Add(sizer, 0, wx.EXPAND, 0)
851    
852            self.SetSizer(topBox)
853            self.SetAutoLayout(True)
854            topBox.Fit(self)
855            topBox.SetSizeHints(self)
856    
857            self.Bind(wx.EVT_TEXT, self.OnRangeText, id=ID_QUANTILES_RANGE)
858            self.Bind(wx.EVT_BUTTON, self.OnRetrieve, id=ID_QUANTILES_RETRIEVE)
859    
860            self.__range = None
861    
862        def GetNumGroups(self):
863            return self.spin_numClasses.GetValue()
864    
865        def GetRange(self):
866            assert self.__range is not None
867    
868            return self.__range
869    
870        def GetList(self):
871            _list = []
872            table = self.layer.ShapeStore().Table()
873            if table is not None:
874                ThubanBeginBusyCursor()
875                try:
876                    #
877                    # FIXME: Replace with a call to table when the method
878                    # has been written to get all the values
879                    #
880                    for i in range(table.NumRows()):
881                        _list.append(table.ReadValue(i, self.fieldName,
882                                                     row_is_ordinal = True))
883                finally:
884                    ThubanEndBusyCursor()
885    
886            return _list
887    
888        def OnRangeText(self, event):
889    
890            try:
891                self.__range = Range(self.text_range.GetValue())
892            except ValueError:
893                self.__range = None
894    
895            if self.__range is not None:
896                self.text_range.SetForegroundColour(wx.BLACK)
897            else:
898                self.text_range.SetForegroundColour(wx.RED)
899    
900        def OnRetrieve(self, event):
901            table = self.layer.ShapeStore().Table()
902            if table is not None:
903                ThubanBeginBusyCursor()
904                try:
905                    min, max = table.ValueRange(self.fieldName)
906                    self.text_range.SetValue("[" + str(min) + ";" + str(max) + "]")
907                    # This is a workaround, which will result in OnRangeText
908                    # being called twice on some platforms.
909                    # Testing showed this is needed with current wx 2.4. versions
910                    # on MacOSX to guarantee that it is called at all.
911                    self.OnRangeText(None)
912                finally:
913                    ThubanEndBusyCursor()
914    
915  ID_CUSTOMRAMP_COPYSTART = 4001  ID_CUSTOMRAMP_COPYSTART = 4001
916  ID_CUSTOMRAMP_COPYEND = 4002  ID_CUSTOMRAMP_COPYEND = 4002
917  ID_CUSTOMRAMP_EDITSTART = 4003  ID_CUSTOMRAMP_EDITSTART = 4003
# Line 671  ID_CUSTOMRAMP_EDITEND = 4004 Line 919  ID_CUSTOMRAMP_EDITEND = 4004
919  ID_CUSTOMRAMP_SPROP = 4005  ID_CUSTOMRAMP_SPROP = 4005
920  ID_CUSTOMRAMP_EPROP = 4006  ID_CUSTOMRAMP_EPROP = 4006
921    
922  class CustomRampPanel(wxPanel):  class CustomRampPanel(wx.Panel):
923    
924      def __init__(self, parent, shapeType):      def __init__(self, parent, shapeType):
925          wxPanel.__init__(self, parent, -1)          wx.Panel.__init__(self, parent, -1)
926    
927          topSizer = wxStaticBoxSizer(wxStaticBox(self, -1, ""), wxHORIZONTAL)          topSizer = wx.StaticBoxSizer(wx.StaticBox(self, -1, ""), wx.HORIZONTAL)
928    
929          bsizer = wxBoxSizer(wxVERTICAL)          bsizer = wx.BoxSizer(wx.VERTICAL)
930          bsizer.Add(wxStaticText(self, -1, _("Start:")), 0, wxALL | wxCENTER, 4)          bsizer.Add(wx.StaticText(self, -1, _("Start:")), 0, wx.ALL | wx.CENTER, 4)
931          self.startPropCtrl = classifier.ClassGroupPropertiesCtrl(          self.startPropCtrl = classifier.ClassGroupPropertiesCtrl(
932              self, ID_CUSTOMRAMP_SPROP,              self, ID_CUSTOMRAMP_SPROP,
933              ClassGroupProperties(), shapeType,              ClassGroupProperties(), shapeType,
934              style=wxSIMPLE_BORDER, size=(40, 20))              style=wx.SIMPLE_BORDER, size=(40, 20))
935          bsizer.Add(self.startPropCtrl, 1, wxGROW | wxALL | wxCENTER, 4)          bsizer.Add(self.startPropCtrl, 1, wx.GROW | wx.ALL | wx.CENTER, 4)
936          bsizer.Add(wxButton(self, ID_CUSTOMRAMP_EDITSTART, _("Change")),          bsizer.Add(wx.Button(self, ID_CUSTOMRAMP_EDITSTART, _("Change")),
937                     0, wxGROW | wxALL | wxCENTER, 4)                     0, wx.GROW | wx.ALL | wx.CENTER, 4)
938    
939          topSizer.Add(bsizer,          topSizer.Add(bsizer,
940                     1, wxALL \                     1, wx.ALL \
941                        | wxSHAPED \                        | wx.SHAPED \
942                        | wxALIGN_CENTER_HORIZONTAL \                        | wx.ALIGN_CENTER_HORIZONTAL \
943                        | wxALIGN_CENTER_VERTICAL, \                        | wx.ALIGN_CENTER_VERTICAL, \
944                     4)                     4)
945    
946          bsizer = wxBoxSizer(wxVERTICAL)          bmp = resource.GetBitmapResource(USE_BMP, wx.BITMAP_TYPE_XPM)
947          bsizer.Add(wxButton(self, ID_CUSTOMRAMP_COPYSTART, _("Copy >>")),          bsizer = wx.BoxSizer(wx.VERTICAL)
948                     0, wxGROW | wxALL, 4)          bsizer.Add(wx.BitmapButton(self, ID_CUSTOMRAMP_COPYSTART, bmp),
949          bsizer.Add(wxButton(self, ID_CUSTOMRAMP_COPYEND, _("<< Copy")),                     0, wx.GROW | wx.ALL, 4)
950                     0, wxGROW | wxALL, 4)          bmp = resource.GetBitmapResource(USENOT_BMP, wx.BITMAP_TYPE_XPM)
951            bsizer.Add(wx.BitmapButton(self, ID_CUSTOMRAMP_COPYEND, bmp),
952                       0, wx.GROW | wx.ALL, 4)
953    
954          topSizer.Add(bsizer,          topSizer.Add(bsizer,
955                     0, wxALL \                     0, wx.ALL \
956                        | wxALIGN_CENTER_HORIZONTAL \                        | wx.ALIGN_CENTER_HORIZONTAL \
957                        | wxALIGN_CENTER_VERTICAL,                        | wx.ALIGN_CENTER_VERTICAL,
958                     4)                     4)
959    
960          bsizer = wxBoxSizer(wxVERTICAL)          bsizer = wx.BoxSizer(wx.VERTICAL)
961          bsizer.Add(wxStaticText(self, -1, _("End:")), 0, wxALL | wxCENTER, 4)          bsizer.Add(wx.StaticText(self, -1, _("End:")), 0, wx.ALL | wx.CENTER, 4)
962          self.endPropCtrl = classifier.ClassGroupPropertiesCtrl(          self.endPropCtrl = classifier.ClassGroupPropertiesCtrl(
963              self, ID_CUSTOMRAMP_EPROP,              self, ID_CUSTOMRAMP_EPROP,
964              ClassGroupProperties(), shapeType,              ClassGroupProperties(), shapeType,
965              style=wxSIMPLE_BORDER, size=(40, 20))              style=wx.SIMPLE_BORDER, size=(40, 20))
966          bsizer.Add(self.endPropCtrl, 1, wxGROW | wxALL | wxCENTER, 4)          bsizer.Add(self.endPropCtrl, 1, wx.GROW | wx.ALL | wx.CENTER, 4)
967          bsizer.Add(wxButton(self, ID_CUSTOMRAMP_EDITEND, _("Change")),          bsizer.Add(wx.Button(self, ID_CUSTOMRAMP_EDITEND, _("Change")),
968                     0, wxGROW | wxALL | wxCENTER, 4)                     0, wx.GROW | wx.ALL | wx.CENTER, 4)
969    
970          topSizer.Add(bsizer,          topSizer.Add(bsizer,
971                     1, wxALL \                     1, wx.ALL \
972                        | wxSHAPED \                        | wx.SHAPED \
973                        | wxALIGN_RIGHT \                        | wx.ALIGN_RIGHT \
974                        | wxALIGN_CENTER_HORIZONTAL \                        | wx.ALIGN_CENTER_HORIZONTAL \
975                        | wxALIGN_CENTER_VERTICAL,                        | wx.ALIGN_CENTER_VERTICAL,
976                     4)                     4)
977    
978          EVT_BUTTON(self, ID_CUSTOMRAMP_COPYSTART, self._OnCopyStart)          self.Bind(wx.EVT_BUTTON, self._OnCopyStart, id=ID_CUSTOMRAMP_COPYSTART)
979          EVT_BUTTON(self, ID_CUSTOMRAMP_COPYEND, self._OnCopyEnd)          self.Bind(wx.EVT_BUTTON, self._OnCopyEnd, id=ID_CUSTOMRAMP_COPYEND)
980          EVT_BUTTON(self, ID_CUSTOMRAMP_EDITSTART, self._OnEditStart)          self.Bind(wx.EVT_BUTTON, self._OnEditStart, id=ID_CUSTOMRAMP_EDITSTART)
981          EVT_BUTTON(self, ID_CUSTOMRAMP_EDITEND, self._OnEditEnd)          self.Bind(wx.EVT_BUTTON, self._OnEditEnd, id=ID_CUSTOMRAMP_EDITEND)
982    
983          self.SetSizer(topSizer)          self.SetSizer(topSizer)
984          self.SetAutoLayout(True)          self.SetAutoLayout(True)
# Line 750  class CustomRampPanel(wxPanel): Line 1000  class CustomRampPanel(wxPanel):
1000      def _OnEditEnd(self, event):      def _OnEditEnd(self, event):
1001          self.endPropCtrl.DoEdit()          self.endPropCtrl.DoEdit()
1002    
 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 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))  
1003    

Legend:
Removed from v.635  
changed lines
  Added in v.2709

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26