/[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 1526 by jonathan, Wed Jul 30 15:43:06 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    from Thuban.UI.common import ThubanBeginBusyCursor, ThubanEndBusyCursor
22    
23    import classifier, resource
24    
25    from Thuban.Model.classgen import \
26        generate_uniform_distribution, generate_singletons, generate_quantiles, \
27        CustomRamp, grey_ramp, red_ramp, green_ramp, blue_ramp, green_to_red_ramp, \
28        HotToColdRamp, FixedRamp
29    
30    
31    USEALL_BMP  = "group_use_all"
32    USE_BMP     = "group_use"
33    USENOT_BMP  = "group_use_not"
34    USENONE_BMP = "group_use_none"
35    
36  import classifier  GENCOMBOSTR_UNIFORM = _("Uniform Distribution")
37    GENCOMBOSTR_UNIQUE = _("Unique Values")
38    GENCOMBOSTR_QUANTILES = _("Quantiles from Table")
39    
40  from Thuban.common import Str2Num  PROPCOMBOSTR_CUSTOM     = _("Custom Ramp")
41    PROPCOMBOSTR_GREY       = _("Grey Ramp")
42    PROPCOMBOSTR_RED        = _("Red Ramp")
43    PROPCOMBOSTR_GREEN      = _("Green Ramp")
44    PROPCOMBOSTR_BLUE       = _("Blue Ramp")
45    PROPCOMBOSTR_GREEN2RED  = _("Green-to-Red Ramp")
46    PROPCOMBOSTR_HOT2COLD   = _("Hot-to-Cold Ramp")
47    
 ID_CLASSGEN_GEN = 4001  
 ID_CLASSGEN_CLOSE = 4002  
48  ID_CLASSGEN_GENCOMBO = 4007  ID_CLASSGEN_GENCOMBO = 4007
49  ID_CLASSGEN_PROPCOMBO = 4008  ID_CLASSGEN_PROPCOMBO = 4008
50    
51  GENCOMBOSTR_UNIFORM = _("Uniform Distribution")  ID_BORDER_COLOR = 4009
52  GENCOMBOSTR_UNIQUE = _("Unique Values")  ID_BORDER_COLOR_CHANGE = 4010
   
 PROPCOMBOSTR_CUSTOM = _("Custom Ramp")  
 PROPCOMBOSTR_RED    = _("Red Ramp")  
 PROPCOMBOSTR_GREEN  = _("Green Ramp")  
 PROPCOMBOSTR_BLUE   = _("Blue Ramp")  
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 44  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 70  class ClassGenDialog(wxDialog): Line 113  class ClassGenDialog(wxDialog):
113                    0, wxALL, 4)                    0, wxALL, 4)
114          sizer.Add(wxStaticText(          sizer.Add(wxStaticText(
115              self, -1,              self, -1,
116              _("Field Type: %s") % classifier.Classifier.type2string[self.type]),              _("Data Type: %s") % classifier.Classifier.type2string[self.type]),
117              0, wxALL, 4)              0, wxALL, 4)
118    
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())
         sizer.Add(panel, 1, wxALL | wxGROW, 4)  
         sizer.Show(panel, False)  
   
         self.propCombo.Append(PROPCOMBOSTR_RED,   RedRamp())  
         self.propCombo.Append(PROPCOMBOSTR_GREEN, GreenRamp())  
         self.propCombo.Append(PROPCOMBOSTR_BLUE,  BlueRamp())  
         self.propCombo.Append(PROPCOMBOSTR_CUSTOM, panel)  
138    
139            self.propCombo.Append(PROPCOMBOSTR_GREY,  grey_ramp)
140            self.propCombo.Append(PROPCOMBOSTR_RED,   red_ramp)
141            self.propCombo.Append(PROPCOMBOSTR_GREEN, green_ramp)
142            self.propCombo.Append(PROPCOMBOSTR_BLUE,  blue_ramp)
143            self.propCombo.Append(PROPCOMBOSTR_GREEN2RED, green_to_red_ramp)
144            self.propCombo.Append(PROPCOMBOSTR_HOT2COLD,  HotToColdRamp())
145            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          EVT_BUTTON(self, ID_CLASSGEN_GEN, self._OnGenerate)          self.__DoOnGenTypeSelect()
191          EVT_BUTTON(self, ID_CLASSGEN_CLOSE, self._OnCloseBtn)  
192            self.genChoice.SetFocus()
193    
194      def GetClassification(self):      def GetClassification(self):
195          return self.clazz          return self.clazz
# Line 149  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 167  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                    ramp = FixedRamp(ramp,
229                        (props.GetLineColor(), props.GetLineWidth(), None))
230    
231              if genSel == GENCOMBOSTR_UNIFORM:              if genSel == GENCOMBOSTR_UNIFORM:
232    
# Line 177  class ClassGenDialog(wxDialog): Line 237  class ClassGenDialog(wxDialog):
237                      and max is not None \                      and max is not None \
238                      and numGroups is not None:                      and numGroups is not None:
239    
240                      self.clazz = ClassGenerator().GenUnifromDistribution(                      self.clazz = generate_uniform_distribution(
241                                  min, max, numGroups, ramp,                                  min, max, numGroups, ramp,
242                                  self.type == FIELDTYPE_INT)                                  self.type == FIELDTYPE_INT)
243    
# Line 187  class ClassGenDialog(wxDialog): Line 247  class ClassGenDialog(wxDialog):
247    
248                  list = genPanel.GetValueList()                  list = genPanel.GetValueList()
249    
250                  if len(list) > 0 \                  if len(list) > 0:
251                      and numGroups is not None:                      self.clazz = generate_singletons(list, ramp)
252                        self.parent._SetClassification(self.clazz)
253    
254                      self.clazz = ClassGenerator().GenSingletonsFromList(              elif genSel == GENCOMBOSTR_QUANTILES:
                                     list, numGroups, ramp)  
255    
256                    _range = genPanel.GetRange()
257                    _list = genPanel.GetList()
258                    _list.sort()
259    
260                    delta = 1 / float(numGroups)
261                    percents = [delta * i for i in range(1, numGroups + 1)]
262                    adjusted, self.clazz = \
263                        generate_quantiles(_list, percents, ramp, _range)
264    
265                    if adjusted:
266                        dlg = wxMessageDialog(self,
267                            _("Based on the data from the table and the input\n" +
268                              "values, the exact quantiles could not be generated.\n\n" +
269                              "Accept a close estimate?"),
270                            _("Problem with Quantiles"),
271    
272                            wxYES_NO|wxYES_DEFAULT|wxICON_QUESTION)
273                        if dlg.ShowModal() == wxID_YES:
274                            self.parent._SetClassification(self.clazz)
275                    else:
276                      self.parent._SetClassification(self.clazz)                      self.parent._SetClassification(self.clazz)
277    
278      def _OnCloseBtn(self, event):      def OnCancel(self, event):
279          self.Close()          self.Close()
280    
281        def OnBorderColorChange(self, event):
282            self.border_color.DoEdit()
283    
284      def _OnGenTypeSelect(self, event):      def _OnGenTypeSelect(self, event):
285            self.__DoOnGenTypeSelect()
286            return
287    
288          combo = event.GetEventObject()          combo = event.GetEventObject()
289    
290          selIndex = combo.GetSelection()          selIndex = combo.GetSelection()
291    
292          if self.genPanel is not None:          if self.genPanel is not None:
293              self.sizer.Show(self.genPanel, False)              self.topBox.Show(self.genPanel, False)
294    
295          self.genPanel = combo.GetClientData(selIndex)          self.genPanel = combo.GetClientData(selIndex)
296          if self.genPanel is not None:          if self.genPanel is not None:
297              self.sizer.Show(self.genPanel, True)              self.topBox.Show(self.genPanel, True)
298    
299          self.sizer.SetSizeHints(self)          self.topBox.SetSizeHints(self)
300          self.sizer.Layout()          self.topBox.Layout()
301    
302      def _OnPropTypeSelect(self, event):      def _OnPropTypeSelect(self, event):
303          combo = event.GetEventObject()          combo = event.GetEventObject()
# Line 221  class ClassGenDialog(wxDialog): Line 306  class ClassGenDialog(wxDialog):
306          sel = combo.GetString(selIndex)          sel = combo.GetString(selIndex)
307    
308          if isinstance(self.propPanel, wxPanel):          if isinstance(self.propPanel, wxPanel):
309              self.sizer.Show(self.propPanel, False)              self.topBox.Show(self.propPanel, False)
310    
311          self.propPanel = combo.GetClientData(selIndex)          self.propPanel = combo.GetClientData(selIndex)
312    
313          if isinstance(self.propPanel, wxPanel):          if isinstance(self.propPanel, wxPanel):
314              self.sizer.Show(self.propPanel, True)              self.topBox.Show(self.propPanel, True)
315    
316            self.topBox.SetSizeHints(self)
317            self.topBox.Layout()
318    
319        def __DoOnGenTypeSelect(self):
320            choice = self.genChoice
321    
322            sel = choice.GetSelection()
323            if sel == -1: return
324    
325            clazz, obj = choice.GetClientData(sel)
326    
327          self.sizer.SetSizeHints(self)          if self.curGenPanel is not None:
328          self.sizer.Layout()              self.curGenPanel.Hide()
329                self.sizer_genPanel.Remove(self.curGenPanel)
330    
331            self.curGenPanel = obj
332            self.curGenPanel.Show()
333    
334            self.sizer_genPanel.Add(self.curGenPanel, 1,
335                wxALL|wxEXPAND|wxADJUST_MINSIZE, 3)
336            self.sizer_genPanel.Layout()
337            self.Layout()
338            self.topBox.SetSizeHints(self)
339    
340  ID_UNIFORM_MIN = 4001  ID_UNIFORM_MIN = 4001
341  ID_UNIFORM_MAX = 4002  ID_UNIFORM_MAX = 4002
# Line 276  class GenUniformPanel(wxPanel): Line 381  class GenUniformPanel(wxPanel):
381          sizer = wxBoxSizer(wxHORIZONTAL)          sizer = wxBoxSizer(wxHORIZONTAL)
382    
383          sizer.Add(wxStaticText(self, -1, _("Number of Groups:")), 0, wxALL, 4)          sizer.Add(wxStaticText(self, -1, _("Number of Groups:")), 0, wxALL, 4)
384          self.numGroupsCtrl = wxSpinCtrl(self, ID_UNIFORM_NGROUPS, style=wxTE_RIGHT)          self.numGroupsCtrl = wxSpinCtrl(self, ID_UNIFORM_NGROUPS,
385                                            style=wxTE_RIGHT)
386          EVT_TEXT(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)          EVT_TEXT(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)
387          EVT_SPINCTRL(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)          EVT_SPINCTRL(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)
388          sizer.Add(self.numGroupsCtrl, 1, wxALL, 4)          sizer.Add(self.numGroupsCtrl, 1, wxALL, 4)
# Line 297  class GenUniformPanel(wxPanel): Line 403  class GenUniformPanel(wxPanel):
403          self.numGroupsChanging = False          self.numGroupsChanging = False
404          self.steppingChanging = False          self.steppingChanging = False
405    
406          self.numGroupsCtrl.SetRange(1, 100)          self.numGroupsCtrl.SetRange(1, sys.maxint)
407    
408          self.numGroupsCtrl.SetValue(1)          self.numGroupsCtrl.SetValue(1)
409          self.stepCtrl.SetValue("1")          self.stepCtrl.SetValue("1")
# Line 347  class GenUniformPanel(wxPanel): Line 453  class GenUniformPanel(wxPanel):
453          self.numGroupsCtrl.Enable(on)          self.numGroupsCtrl.Enable(on)
454          self.stepCtrl.Enable(on)          self.stepCtrl.Enable(on)
455    
         if on:  
             self.numGroupsCtrl.SetRange(1, abs(max - min) / 0.001)  
   
456          ngroups = self.GetNumGroups()          ngroups = self.GetNumGroups()
457    
458          if ngroups is not None  \          if ngroups is not None  \
# Line 380  class GenUniformPanel(wxPanel): Line 483  class GenUniformPanel(wxPanel):
483          min = self.GetMin()          min = self.GetMin()
484          max = self.GetMax()          max = self.GetMax()
485    
         if ngroups >= self.numGroupsCtrl.GetMax():  
             self.numGroupsCtrl.SetRange(1, ngroups + 1)  
   
486          if ngroups is not None  \          if ngroups is not None  \
487              and min is not None \              and min is not None \
488              and max is not None \              and max is not None \
# Line 429  class GenUniformPanel(wxPanel): Line 529  class GenUniformPanel(wxPanel):
529              self.parent.AllowGenerate(False)              self.parent.AllowGenerate(False)
530    
531      def _OnRetrieve(self, event):      def _OnRetrieve(self, event):
532            table = self.layer.ShapeStore().Table()
533          if self.layer.table is not None:          if table is not None:
534              range = self.layer.table.field_range(self.fieldName)              ThubanBeginBusyCursor()
535              self.minCtrl.SetValue(str(range[0][0]))              try:
536              self.maxCtrl.SetValue(str(range[1][0]))                  min, max = table.ValueRange(self.fieldName)
537                    self.minCtrl.SetValue(str(min))
538                    self.maxCtrl.SetValue(str(max))
539                finally:
540                    ThubanEndBusyCursor()
541    
542      def __GetValidatedTypeEntry(self, win, value, type, badValue = None):      def __GetValidatedTypeEntry(self, win, value, type, badValue = None):
543    
# Line 475  class GenUniformPanel(wxPanel): Line 579  class GenUniformPanel(wxPanel):
579          return valid          return valid
580    
581      def __CalcStepping(self, min, max, ngroups):      def __CalcStepping(self, min, max, ngroups):
         step = Str2Num(str((max - min) / float(ngroups)))  
582          if self.fieldType == FIELDTYPE_INT:          if self.fieldType == FIELDTYPE_INT:
583              step = int(step)              step = int((max - min + 1) / float(ngroups))
584            else:
585                step = (max - min) / float(ngroups)
586    
587          return step          return step
588    
# Line 499  ID_UNIQUE_DONTUSE = 4004 Line 604  ID_UNIQUE_DONTUSE = 4004
604  ID_UNIQUE_USENONE = 4005  ID_UNIQUE_USENONE = 4005
605  ID_UNIQUE_SORTAVAIL = 4006  ID_UNIQUE_SORTAVAIL = 4006
606  ID_UNIQUE_SORTUSE = 4007  ID_UNIQUE_SORTUSE = 4007
607    ID_UNIQUE_REVAVAIL = 4008
608    ID_UNIQUE_REVUSE = 4009
609    
610  class GenUniquePanel(wxPanel):  class GenUniquePanel(wxPanel):
611    
# Line 514  class GenUniquePanel(wxPanel): Line 621  class GenUniquePanel(wxPanel):
621                                      wxVERTICAL)                                      wxVERTICAL)
622    
623    
624            #bsizer = wxBoxSizer(wxVERTICAL)
625            topSizer.Add(wxButton(self, ID_UNIQUE_RETRIEVE,
626                                _("Retrieve From Table")),
627                       0, wxALL | wxALIGN_RIGHT, 4)
628    
629            EVT_BUTTON(self, ID_UNIQUE_RETRIEVE, self._OnRetrieve)
630    
631            #topSizer.Add(bsizer, 0, wxALL, 4)
632    
633          sizer = wxBoxSizer(wxHORIZONTAL)          sizer = wxBoxSizer(wxHORIZONTAL)
634    
635          self.dataList = []          self.dataList = []
# Line 525  class GenUniquePanel(wxPanel): Line 641  class GenUniquePanel(wxPanel):
641          self.list_avail_data = []          self.list_avail_data = []
642          psizer.Add(self.list_avail, 1, wxGROW, 0)          psizer.Add(self.list_avail, 1, wxGROW, 0)
643    
644          psizer.Add(wxButton(self, ID_UNIQUE_SORTAVAIL, _("Sort")))          bsizer = wxBoxSizer(wxHORIZONTAL)
645            bsizer.Add(wxButton(self, ID_UNIQUE_SORTAVAIL, _("Sort")))
646            EVT_BUTTON(self, ID_UNIQUE_SORTAVAIL, self._OnSortList)
647    
648          EVT_BUTTON(self, ID_UNIQUE_SORTAVAIL, self._OnSortAvailList)          bsizer.Add(wxButton(self, ID_UNIQUE_REVAVAIL, _("Reverse")))
649            EVT_BUTTON(self, ID_UNIQUE_REVAVAIL, self._OnReverseList)
650    
651            psizer.Add(bsizer, 0, wxGROW, 0)
652          sizer.Add(psizer, 1, wxGROW, 0)          sizer.Add(psizer, 1, wxGROW, 0)
653    
654                    
655          bsizer = wxBoxSizer(wxVERTICAL)          bsizer = wxBoxSizer(wxVERTICAL)
656          bsizer.Add(wxButton(self, ID_UNIQUE_USEALL, _("Use All")),  
657            bmp = resource.GetBitmapResource(USEALL_BMP, wxBITMAP_TYPE_XPM)
658            bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USEALL, bmp),
659                     0, wxGROW | wxALL, 4)                     0, wxGROW | wxALL, 4)
660          bsizer.Add(wxButton(self, ID_UNIQUE_USE, _("Use >>")),          bmp = resource.GetBitmapResource(USE_BMP, wxBITMAP_TYPE_XPM)
661            bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USE, bmp),
662                     0, wxGROW | wxALL, 4)                     0, wxGROW | wxALL, 4)
663          bsizer.Add(wxButton(self, ID_UNIQUE_DONTUSE, _("<< Don't Use")),          bmp = resource.GetBitmapResource(USENOT_BMP, wxBITMAP_TYPE_XPM)
664            bsizer.Add(wxBitmapButton(self, ID_UNIQUE_DONTUSE, bmp),
665                     0, wxGROW | wxALL, 4)                     0, wxGROW | wxALL, 4)
666          bsizer.Add(wxButton(self, ID_UNIQUE_USENONE, _("Use None")),          bmp = resource.GetBitmapResource(USENONE_BMP, wxBITMAP_TYPE_XPM)
667            bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USENONE, bmp),
668                     0, wxGROW | wxALL, 4)                     0, wxGROW | wxALL, 4)
669    
670          EVT_BUTTON(self, ID_UNIQUE_USEALL, self._OnUseAll)          EVT_BUTTON(self, ID_UNIQUE_USEALL, self._OnUseAll)
# Line 556  class GenUniquePanel(wxPanel): Line 681  class GenUniquePanel(wxPanel):
681          self.list_use_data = []          self.list_use_data = []
682          psizer.Add(self.list_use, 1, wxGROW, 0)          psizer.Add(self.list_use, 1, wxGROW, 0)
683    
684          psizer.Add(wxButton(self, ID_UNIQUE_SORTUSE, _("Sort")))          bsizer = wxBoxSizer(wxHORIZONTAL)
685            bsizer.Add(wxButton(self, ID_UNIQUE_SORTUSE, _("Sort")))
686            EVT_BUTTON(self, ID_UNIQUE_SORTUSE, self._OnSortList)
687    
688          EVT_BUTTON(self, ID_UNIQUE_SORTUSE, self._OnSortUseList)          bsizer.Add(wxButton(self, ID_UNIQUE_REVUSE, _("Reverse")))
689            EVT_BUTTON(self, ID_UNIQUE_REVUSE, self._OnReverseList)
690    
691          sizer.Add(psizer, 1, wxGROW, 0)          psizer.Add(bsizer, 0, wxGROW, 0)
692    
693          bsizer = wxBoxSizer(wxVERTICAL)          sizer.Add(psizer, 1, wxGROW, 0)
         bsizer.Add(wxButton(self, ID_UNIQUE_RETRIEVE,  
                             _("Retrieve From Table")),  
                    0, wxGROW | wxALL, 4)  
   
         EVT_BUTTON(self, ID_UNIQUE_RETRIEVE, self._OnRetrieve)  
694    
         sizer.Add(bsizer, 0, wxALL, 4)  
695    
696          topSizer.Add(sizer, 1, wxGROW, 0)          topSizer.Add(sizer, 1, wxGROW, 0)
697    
# Line 577  class GenUniquePanel(wxPanel): Line 699  class GenUniquePanel(wxPanel):
699          self.SetAutoLayout(True)          self.SetAutoLayout(True)
700          topSizer.SetSizeHints(self)          topSizer.SetSizeHints(self)
701    
702          self.parent.AllowGenerate(False)          width, height = self.list_avail.GetSizeTuple()
703            self.list_avail.SetColumnWidth(0,width)
704            width, height = self.list_use.GetSizeTuple()
705            self.list_use.SetColumnWidth(0,width)
706    
707          self.mylist = ["Hallo", "Welt!", "Wie", "geht", "es", "dir", "?"]          self.parent.AllowGenerate(False)
708    
709      def GetNumGroups(self):      def GetNumGroups(self):
710          return self.list_use.GetItemCount()          return self.list_use.GetItemCount()
# Line 590  class GenUniquePanel(wxPanel): Line 715  class GenUniquePanel(wxPanel):
715              list.append(self.dataList[self.list_use.GetItemData(i)])              list.append(self.dataList[self.list_use.GetItemData(i)])
716          return list          return list
717    
718      def _OnSortAvailList(self, event):      def _OnSortList(self, event):
719          self.list_avail.SortItems(lambda i1, i2:          id = event.GetId()
720                                      cmp(self.dataList[i1],  
721                                          self.dataList[i2]))          if id == ID_UNIQUE_SORTUSE:
722                list = self.list_use
723      def _OnSortUseList(self, event):          else:
724          self.list_use.SortItems(lambda i1, i2:              list = self.list_avail
725                                      cmp(self.dataList[i1],  
726                                          self.dataList[i2]))          list.SortItems(lambda i1, i2: cmp(self.dataList[i1],
727                                              self.dataList[i2]))
728    
729        def _OnReverseList(self, event):
730            id = event.GetId()
731    
732            if id == ID_UNIQUE_REVUSE:
733                list = self.list_use
734            else:
735                list = self.list_avail
736    
737            #
738            # always returning 1 reverses the list
739            #
740            list.SortItems(lambda i1, i2: 1)
741    
742      def _OnRetrieve(self, event):      def _OnRetrieve(self, event):
743          self.list_use.DeleteAllItems()          self.list_use.DeleteAllItems()
# Line 606  class GenUniquePanel(wxPanel): Line 745  class GenUniquePanel(wxPanel):
745          self.list_avail.DeleteAllItems()          self.list_avail.DeleteAllItems()
746          self.list_avail_data = []          self.list_avail_data = []
747    
748          list = self.layer.table.GetUniqueValues(self.fieldName)          ThubanBeginBusyCursor()
749          index = 0          try:
750          for v in list:              list = self.layer.ShapeStore().Table().UniqueValues(self.fieldName)
751              self.dataList.append(v)              index = 0
752              i = self.list_avail.InsertStringItem(index, str(v))              for v in list:
753              self.list_avail.SetItemData(index, i)                  self.dataList.append(v)
754                    i = self.list_avail.InsertStringItem(index, str(v))
755              self.list_avail_data.append(v)                  self.list_avail.SetItemData(index, i)
756              index += 1      
757                    self.list_avail_data.append(v)
758                    index += 1
759            finally:
760                ThubanEndBusyCursor()
761    
762      def _OnUseAll(self, event):      def _OnUseAll(self, event):
763          for i in range(self.list_avail.GetItemCount()):          for i in range(self.list_avail.GetItemCount()):
764              self.__MoveListItem(0, self.list_avail, self.list_use)              self.__MoveListItem(0, self.list_avail, self.list_use)
765    
766      def _OnUse(self, event):      def _OnUse(self, event):
         print "_OnUse"  
767          self.__MoveSelectedItems(self.list_avail, self.list_use)          self.__MoveSelectedItems(self.list_avail, self.list_use)
768    
769      def _OnDontUse(self, event):      def _OnDontUse(self, event):
         print "_OnDontUse"  
770          self.__MoveSelectedItems(self.list_use, self.list_avail)          self.__MoveSelectedItems(self.list_use, self.list_avail)
771    
772      def _OnUseNone(self, event):      def _OnUseNone(self, event):
         print "_OnUseNone"  
773    
774          for i in range(self.list_use.GetItemCount()):          for i in range(self.list_use.GetItemCount()):
775              self.__MoveListItem(0, self.list_use, self.list_avail)              self.__MoveListItem(0, self.list_use, self.list_avail)
# Line 664  class GenUniquePanel(wxPanel): Line 804  class GenUniquePanel(wxPanel):
804  #       list.SetColumnWidth(0, event.GetSize().GetWidth())  #       list.SetColumnWidth(0, event.GetSize().GetWidth())
805  #        #      
806    
807    ID_QUANTILES_RANGE = 4001
808    ID_QUANTILES_RETRIEVE = 4002
809    
810    class GenQuantilesPanel(wxPanel):
811    
812        def __init__(self, parent, layer, fieldName, fieldType):
813            wxPanel.__init__(self, parent, -1)
814    
815            self.parent = parent
816            self.layer = layer
817            self.fieldName = fieldName
818            self.fieldType = fieldType
819    
820            topBox = wxStaticBoxSizer(wxStaticBox(self, -1, ""),
821                                        wxVERTICAL)
822    
823            self.text_range = wxTextCtrl(self, ID_QUANTILES_RANGE, "")
824            self.button_retrieve = wxButton(self, ID_QUANTILES_RETRIEVE,
825                                            _("Retrieve from Table"))
826    
827            self.spin_numClasses = wxSpinCtrl(self, -1, style=wxTE_RIGHT)
828            self.spin_numClasses.SetRange(1, sys.maxint)
829            self.spin_numClasses.SetValue(1)
830    
831    
832            sizer = wxBoxSizer(wxHORIZONTAL)
833            sizer.Add(wxStaticText(self, -1, _("Apply to Range")), 0, wxALL, 4)
834            sizer.Add(self.text_range, 1, wxALL, 4)
835            sizer.Add(self.button_retrieve, 0, wxALL, 4)
836    
837            topBox.Add(sizer, 0, wxEXPAND, 0)
838    
839            sizer = wxBoxSizer(wxHORIZONTAL)
840            sizer.Add(wxStaticText(self, -1, _("Number of Classes:")), 0, wxALL, 4)
841            sizer.Add(self.spin_numClasses, 1, wxALL, 4)
842    
843            topBox.Add(sizer, 0, wxEXPAND, 0)
844    
845            self.SetSizer(topBox)
846            self.SetAutoLayout(True)
847            topBox.Fit(self)
848            topBox.SetSizeHints(self)
849    
850            EVT_TEXT(self, ID_QUANTILES_RANGE, self.OnRangeText)
851            EVT_BUTTON(self, ID_QUANTILES_RETRIEVE, self.OnRetrieve)
852    
853            self.__range = None
854    
855        def GetNumGroups(self):
856            return self.spin_numClasses.GetValue()
857    
858        def GetRange(self):
859            assert self.__range is not None
860    
861            return self.__range
862    
863        def GetList(self):
864            _list = []
865            table = self.layer.ShapeStore().Table()
866            if table is not None:
867                ThubanBeginBusyCursor()
868                try:
869                    #
870                    # FIXME: Replace with a call to table when the method
871                    # has been written to get all the values
872                    #
873                    for i in range(table.NumRows()):
874                        _list.append(table.ReadValue(i, self.fieldName))
875                finally:
876                    ThubanEndBusyCursor()
877    
878            return _list
879    
880        def OnRangeText(self, event):
881    
882            try:
883                self.__range = Range(self.text_range.GetValue())
884            except ValueError:
885                self.__range = None
886    
887            if self.__range is not None:
888                self.text_range.SetForegroundColour(wxBLACK)
889            else:
890                self.text_range.SetForegroundColour(wxRED)
891    
892        def OnRetrieve(self, event):
893            table = self.layer.ShapeStore().Table()
894            if table is not None:
895                ThubanBeginBusyCursor()
896                try:
897                    min, max = table.ValueRange(self.fieldName)
898                    self.text_range.SetValue("[" + str(min) + ";" + str(max) + "]")
899                finally:
900                    ThubanEndBusyCursor()
901    
902  ID_CUSTOMRAMP_COPYSTART = 4001  ID_CUSTOMRAMP_COPYSTART = 4001
903  ID_CUSTOMRAMP_COPYEND = 4002  ID_CUSTOMRAMP_COPYEND = 4002
904  ID_CUSTOMRAMP_EDITSTART = 4003  ID_CUSTOMRAMP_EDITSTART = 4003
# Line 695  class CustomRampPanel(wxPanel): Line 930  class CustomRampPanel(wxPanel):
930                        | wxALIGN_CENTER_VERTICAL, \                        | wxALIGN_CENTER_VERTICAL, \
931                     4)                     4)
932    
933            bmp = resource.GetBitmapResource(USE_BMP, wxBITMAP_TYPE_XPM)
934          bsizer = wxBoxSizer(wxVERTICAL)          bsizer = wxBoxSizer(wxVERTICAL)
935          bsizer.Add(wxButton(self, ID_CUSTOMRAMP_COPYSTART, _("Copy >>")),          bsizer.Add(wxBitmapButton(self, ID_CUSTOMRAMP_COPYSTART, bmp),
936                     0, wxGROW | wxALL, 4)                     0, wxGROW | wxALL, 4)
937          bsizer.Add(wxButton(self, ID_CUSTOMRAMP_COPYEND, _("<< Copy")),          bmp = resource.GetBitmapResource(USENOT_BMP, wxBITMAP_TYPE_XPM)
938            bsizer.Add(wxBitmapButton(self, ID_CUSTOMRAMP_COPYEND, bmp),
939                     0, wxGROW | wxALL, 4)                     0, wxGROW | wxALL, 4)
940    
941          topSizer.Add(bsizer,          topSizer.Add(bsizer,
# Line 750  class CustomRampPanel(wxPanel): Line 987  class CustomRampPanel(wxPanel):
987      def _OnEditEnd(self, event):      def _OnEditEnd(self, event):
988          self.endPropCtrl.DoEdit()          self.endPropCtrl.DoEdit()
989    
990  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))  
   

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26