/[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 728 by jonathan, Thu Apr 24 16:06:28 2003 UTC revision 1526 by jonathan, Wed Jul 30 15:43:06 2003 UTC
# Line 11  from Thuban import _ Line 11  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    
 import classifier  
   
 import resource  
   
 from Thuban.common import Str2Num  
   
 ID_CLASSGEN_GEN = 4001  
 ID_CLASSGEN_CLOSE = 4002  
 ID_CLASSGEN_GENCOMBO = 4007  
 ID_CLASSGEN_PROPCOMBO = 4008  
30    
31  USEALL_BMP  = "group_use_all"  USEALL_BMP  = "group_use_all"
32  USE_BMP     = "group_use"  USE_BMP     = "group_use"
# Line 37  USENONE_BMP = "group_use_none" Line 35  USENONE_BMP = "group_use_none"
35    
36  GENCOMBOSTR_UNIFORM = _("Uniform Distribution")  GENCOMBOSTR_UNIFORM = _("Uniform Distribution")
37  GENCOMBOSTR_UNIQUE = _("Unique Values")  GENCOMBOSTR_UNIQUE = _("Unique Values")
38    GENCOMBOSTR_QUANTILES = _("Quantiles from Table")
39    
40  PROPCOMBOSTR_CUSTOM     = _("Custom Ramp")  PROPCOMBOSTR_CUSTOM     = _("Custom Ramp")
41  PROPCOMBOSTR_GREY       = _("Grey Ramp")  PROPCOMBOSTR_GREY       = _("Grey Ramp")
42  PROPCOMBOSTR_RED        = _("Red Ramp")  PROPCOMBOSTR_RED        = _("Red Ramp")
43  PROPCOMBOSTR_GREEN      = _("Green Ramp")  PROPCOMBOSTR_GREEN      = _("Green Ramp")
44  PROPCOMBOSTR_BLUE       = _("Blue Ramp")  PROPCOMBOSTR_BLUE       = _("Blue Ramp")
45    PROPCOMBOSTR_GREEN2RED  = _("Green-to-Red Ramp")
46  PROPCOMBOSTR_HOT2COLD   = _("Hot-to-Cold Ramp")  PROPCOMBOSTR_HOT2COLD   = _("Hot-to-Cold Ramp")
47    
48    ID_CLASSGEN_GENCOMBO = 4007
49    ID_CLASSGEN_PROPCOMBO = 4008
50    
51    ID_BORDER_COLOR = 4009
52    ID_BORDER_COLOR_CHANGE = 4010
53    
54  class ClassGenDialog(wxDialog):  class ClassGenDialog(wxDialog):
55                                                                                    
56      def __init__(self, parent, layer, fieldName):      def __init__(self, parent, layer, fieldName):
57          """Inialize the class generating dialog.          """Inialize the class generating dialog.
58    
# Line 55  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 87  class ClassGenDialog(wxDialog): Line 119  class ClassGenDialog(wxDialog):
119          psizer = wxBoxSizer(wxHORIZONTAL)          psizer = wxBoxSizer(wxHORIZONTAL)
120          psizer.Add(wxStaticText(self, -1, _("Generate:")),          psizer.Add(wxStaticText(self, -1, _("Generate:")),
121              0, wxALIGN_CENTER_VERTICAL, 0)              0, wxALIGN_CENTER_VERTICAL, 0)
   
         self.genChoice = wxChoice(self, ID_CLASSGEN_GENCOMBO)  
122          psizer.Add(self.genChoice, 1, wxALL | wxGROW, 4)          psizer.Add(self.genChoice, 1, wxALL | wxGROW, 4)
         EVT_CHOICE(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.genChoice.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.genChoice.Append(GENCOMBOSTR_UNIFORM, panel)  
             sizer.Add(panel, 1, wxGROW | wxALL, 4)  
             sizer.Show(panel, False)  
   
         self.genChoice.SetSelection(0)  
   
         #############  
128    
129          psizer = wxBoxSizer(wxHORIZONTAL)          psizer = wxBoxSizer(wxHORIZONTAL)
130          psizer.Add(wxStaticText(self, -1, _("Color Scheme:")),          psizer.Add(wxStaticText(self, -1, _("Color Scheme:")),
131              0, wxALIGN_CENTER_VERTICAL, 0)              0, wxALIGN_CENTER_VERTICAL, 0)
132    
133            # Properties (Ramp) ComboBox
134          self.propCombo = wxChoice(self, ID_CLASSGEN_PROPCOMBO)          self.propCombo = wxChoice(self, ID_CLASSGEN_PROPCOMBO)
         psizer.Add(self.propCombo, 1, wxALL | wxGROW, 4)  
         EVT_CHOICE(self, ID_CLASSGEN_PROPCOMBO, self._OnPropTypeSelect)  
         sizer.Add(psizer, 0, wxALL | wxGROW, 4)  
   
         #############  
135    
136          self.propPanel = None          self.propPanel = None
137          panel = CustomRampPanel(self, layer.ShapeType())          custom_ramp_panel = CustomRampPanel(self, layer.ShapeType())
138          sizer.Add(panel, 1, wxALL | wxGROW, 4)  
139          sizer.Show(panel, False)          self.propCombo.Append(PROPCOMBOSTR_GREY,  grey_ramp)
140            self.propCombo.Append(PROPCOMBOSTR_RED,   red_ramp)
141          self.propCombo.Append(PROPCOMBOSTR_GREY,  GreyRamp())          self.propCombo.Append(PROPCOMBOSTR_GREEN, green_ramp)
142          self.propCombo.Append(PROPCOMBOSTR_RED,   RedRamp())          self.propCombo.Append(PROPCOMBOSTR_BLUE,  blue_ramp)
143          self.propCombo.Append(PROPCOMBOSTR_GREEN, GreenRamp())          self.propCombo.Append(PROPCOMBOSTR_GREEN2RED, green_to_red_ramp)
         self.propCombo.Append(PROPCOMBOSTR_BLUE,  BlueRamp())  
144          self.propCombo.Append(PROPCOMBOSTR_HOT2COLD,  HotToColdRamp())          self.propCombo.Append(PROPCOMBOSTR_HOT2COLD,  HotToColdRamp())
145          self.propCombo.Append(PROPCOMBOSTR_CUSTOM, panel)          self.propCombo.Append(PROPCOMBOSTR_CUSTOM, custom_ramp_panel)
146    
147          self.propCombo.SetSelection(0)          self.propCombo.SetSelection(0)
148    
149            psizer.Add(self.propCombo, 1, wxALL | wxGROW, 4)
150            sizer.Add(psizer, 0, wxALL | wxGROW, 4)
151    
152          #############          if layer.ShapeType() != SHAPETYPE_ARC:
153                psizer = wxBoxSizer(wxHORIZONTAL)
154                self.fix_border_check = wxCheckBox(self, -1, _("Fix Border Color"))
155                psizer.Add(self.fix_border_check, 0, wxALL | wxGROW, 4)
156                self.border_color = classifier.ClassGroupPropertiesCtrl(
157                    self, ID_BORDER_COLOR,
158                    ClassGroupProperties(), SHAPETYPE_ARC,
159                    style=wxSIMPLE_BORDER, size=(40, 20))
160                psizer.Add(self.border_color, 0, wxALL | wxGROW, 4)
161                psizer.Add(wxButton(self, ID_BORDER_COLOR_CHANGE, _("Change")),
162                        0, wxALL, 4)
163                sizer.Add(psizer, 0, wxALL | wxGROW, 4)
164                EVT_BUTTON(self, ID_BORDER_COLOR_CHANGE, self.OnBorderColorChange)
165            else:
166                self.border_color = None
167    
168          sizer.Add(buttonSizer, 0,          sizer.Add(custom_ramp_panel, 1, wxGROW | wxALL, 4)
169                    wxALL | wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL, 4)          sizer.Show(custom_ramp_panel, False)
170    
171            # Finally place the main buttons
172            buttonSizer = wxBoxSizer(wxHORIZONTAL)
173            buttonSizer.Add(self.genButton, 0, wxRIGHT|wxEXPAND, 10)
174            buttonSizer.Add(self.cancelButton, 0, wxRIGHT|wxEXPAND, 10)
175            sizer.Add(buttonSizer, 0, wxALIGN_RIGHT|wxBOTTOM|wxTOP, 10)
176    
177          self.SetSizer(sizer)          self.SetSizer(sizer)
178          self.SetAutoLayout(True)          self.SetAutoLayout(True)
179          sizer.SetSizeHints(self)          sizer.SetSizeHints(self)
180    
181          self.sizer = sizer          self.topBox = sizer
182    
183            self.__DoOnGenTypeSelect()
184    
185            EVT_CHOICE(self, ID_CLASSGEN_GENCOMBO, self._OnGenTypeSelect)
186            EVT_CHOICE(self, ID_CLASSGEN_PROPCOMBO, self._OnPropTypeSelect)
187            EVT_BUTTON(self, wxID_OK, self.OnOK)
188            EVT_BUTTON(self, wxID_CANCEL, self.OnCancel)
189    
190            self.__DoOnGenTypeSelect()
191    
192          EVT_BUTTON(self, ID_CLASSGEN_GEN, self._OnGenerate)          self.genChoice.SetFocus()
         EVT_BUTTON(self, ID_CLASSGEN_CLOSE, self._OnCloseBtn)  
193    
194      def GetClassification(self):      def GetClassification(self):
195          return self.clazz          return self.clazz
# Line 161  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()          index = self.genChoice.GetSelection()
206    
207            assert index != -1, "button should be disabled!"
208    
209          genSel = self.genChoice.GetString(index)          genSel = self.genChoice.GetString(index)
210          genPanel = self.genChoice.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 179  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 189  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 199  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 233  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.sizer.SetSizeHints(self)          self.topBox.SetSizeHints(self)
317          self.sizer.Layout()          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            if self.curGenPanel is not None:
328                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 436  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 482  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 601  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 644  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()):
# Line 699  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 787  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 GreyRamp(MonochromaticRamp):  
     def __init__(self):  
         MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(0, 0, 0))  
   
 class RedRamp(MonochromaticRamp):  
     def __init__(self):  
         MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(.8, 0, 0))  
   
 class GreenRamp(MonochromaticRamp):  
     def __init__(self):  
         MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(0, .8, 0))  
   
 class BlueRamp(MonochromaticRamp):  
     def __init__(self):  
         MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(0, 0, .8))  
   
 class HotToColdRamp:  
   
     def __iter__(self):  
         return self  
           
     def GetRamp(self):  
         return self  
   
     def SetNumGroups(self, num):  
         if num < 0:  
             return False  
   
         self.num = float(num)  
         self.index = 0  
   
         return True  
   
     def next(self):  
         if self.index == self.num:  
             raise StopIteration  
   
         clr = [1.0, 1.0, 1.0]  
   
         if self.index < (.25 * self.num):  
             clr[0] = 0  
             clr[1] = 4 * self.index / self.num  
         elif self.index < (.5 * self.num):  
             clr[0] = 0  
             clr[2] = 1 + 4 * (.25 * self.num - self.index) / self.num  
         elif self.index < (.75 * self.num):  
             clr[0] = 4 * (self.index - .5 * self.num) / self.num  
             clr[2] = 0  
         else:  
             clr[1] = 1 + 4 * (.75 * self.num - self.index) / self.num  
             clr[2] = 0  
   
         self.index += 1  
   
         prop = ClassGroupProperties()  
         prop.SetLineColor(Color(clr[0], clr[1], clr[2]))  
         prop.SetFill(Color(clr[0], clr[1], clr[2]))  
   
         return prop  
   
 #class Colors16Ramp:  
 #  
     #def __iter__(self):  
         #return self  
 #  
     #def GetRamp(self):  
         #return self  
 #  
     #def SetNumGroups(self, num):  
         #if num < 0:  
             #return False  
 #  
         #self.index = 0  
 #  
         #return True  
   
       

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26