/[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 1341 by jonathan, Tue Jul 1 16:10:42 2003 UTC
# Line 5  Line 5 
5  # This program is free software under the GPL (>=v2)  # This program is free software under the GPL (>=v2)
6  # Read the file COPYING coming with Thuban for details.  # Read the file COPYING coming with Thuban for details.
7    
8    import sys
9    
10  from Thuban import _  from Thuban import _
11    
12  from wxPython.wx import *  from wxPython.wx import *
13    
14  from Thuban.Model.classification import Classification, ClassGroupRange, \  from Thuban.Model.classification import ClassGroupProperties
     ClassGroupSingleton, ClassGroupProperties  
15    
16  from Thuban.Model.table import Table, FIELDTYPE_INT, FIELDTYPE_DOUBLE, \  from Thuban.Model.table import FIELDTYPE_INT, FIELDTYPE_DOUBLE, \
17       FIELDTYPE_STRING       FIELDTYPE_STRING
18    
19  from Thuban.Model.color import Color  from Thuban.Model.range import Range
20    from Thuban.UI.common import ThubanBeginBusyCursor, ThubanEndBusyCursor
 import classifier  
21    
22  from Thuban.common import Str2Num  import classifier, resource
23    
24  ID_CLASSGEN_GEN = 4001  from Thuban.Model.classgen import \
25  ID_CLASSGEN_CLOSE = 4002      generate_uniform_distribution, generate_singletons, generate_quantiles, \
26  ID_CLASSGEN_GENCOMBO = 4007      CustomRamp, GreyRamp, RedRamp, GreenRamp, BlueRamp, GreenToRedRamp, \
27  ID_CLASSGEN_PROPCOMBO = 4008      HotToColdRamp
28    
29    USEALL_BMP  = "group_use_all"
30    USE_BMP     = "group_use"
31    USENOT_BMP  = "group_use_not"
32    USENONE_BMP = "group_use_none"
33    
34  GENCOMBOSTR_UNIFORM = _("Uniform Distribution")  GENCOMBOSTR_UNIFORM = _("Uniform Distribution")
35  GENCOMBOSTR_UNIQUE = _("Unique Values")  GENCOMBOSTR_UNIQUE = _("Unique Values")
36    GENCOMBOSTR_QUANTILES = _("Quantiles from Table")
37    
38    PROPCOMBOSTR_CUSTOM     = _("Custom Ramp")
39    PROPCOMBOSTR_GREY       = _("Grey Ramp")
40    PROPCOMBOSTR_RED        = _("Red Ramp")
41    PROPCOMBOSTR_GREEN      = _("Green Ramp")
42    PROPCOMBOSTR_BLUE       = _("Blue Ramp")
43    PROPCOMBOSTR_GREEN2RED  = _("Green-to-Red Ramp")
44    PROPCOMBOSTR_HOT2COLD   = _("Hot-to-Cold Ramp")
45    
46  PROPCOMBOSTR_CUSTOM = _("Custom Ramp")  ID_CLASSGEN_GENCOMBO = 4007
47  PROPCOMBOSTR_RED    = _("Red Ramp")  ID_CLASSGEN_PROPCOMBO = 4008
 PROPCOMBOSTR_GREEN  = _("Green Ramp")  
 PROPCOMBOSTR_BLUE   = _("Blue Ramp")  
48    
49  class ClassGenDialog(wxDialog):  class ClassGenDialog(wxDialog):
50                                                                                    
51      def __init__(self, parent, layer, fieldName):      def __init__(self, parent, layer, fieldName):
52          """Inialize the class generating dialog.          """Inialize the class generating dialog.
53    
# Line 44  class ClassGenDialog(wxDialog): Line 56  class ClassGenDialog(wxDialog):
56    
57          wxDialog.__init__(self, parent, -1, _("Generate Classification"),          wxDialog.__init__(self, parent, -1, _("Generate Classification"),
58                            style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)                            style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
59                                                                                    
60          self.parent = parent          self.parent = parent
61            self.layer = layer
62          self.clazz = None          self.clazz = None
63    
64          self.type, name, width, prec = layer.table.field_info_by_name(fieldName)          col = layer.ShapeStore().Table().Column(fieldName)
65            self.type = col.type
66    
67            self.fieldName = fieldName
68            self.fieldType = self.type
69    
70            self.curGenPanel = None
71    
72            self.genpanels = []
73    
74          #############          #############
75          # we need to create genButton first because when we create the          # we need to create genButton first because when we create the
76          # panels they will call AllowGenerate() which uses genButton.          # panels they will call AllowGenerate() which uses genButton.
77          #          #
78          buttonSizer = wxBoxSizer(wxHORIZONTAL)          self.genButton = wxButton(self, wxID_OK, _("Generate"))
79          self.genButton = wxButton(self, ID_CLASSGEN_GEN, _("Generate"))          self.cancelButton = wxButton(self, wxID_CANCEL, _("Close"))
80            self.genButton.SetDefault()
81    
82            self.genChoice = wxChoice(self, ID_CLASSGEN_GENCOMBO)
83    
84            self.genpanels.append((GENCOMBOSTR_UNIQUE, GenUniquePanel))
85            if self.type in (FIELDTYPE_INT, FIELDTYPE_DOUBLE):
86                self.genpanels.append((GENCOMBOSTR_UNIFORM, GenUniformPanel))
87                self.genpanels.append((GENCOMBOSTR_QUANTILES, GenQuantilesPanel))
88    
89            for name, clazz in self.genpanels:
90                self.genChoice.Append(name, [clazz, None])
91    
92            self.genChoice.SetSelection(0)
93    
94            for i in range(self.genChoice.GetCount()):
95                clazz, obj = self.genChoice.GetClientData(i)
96    
97                if obj is None:
98                    obj = clazz(self, self.layer, self.fieldName, self.fieldType)
99                    obj.Hide()
100                    self.genChoice.SetClientData(i, [clazz, obj])
101    
         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)  
102    
103          #############          #############
104    
# Line 70  class ClassGenDialog(wxDialog): Line 108  class ClassGenDialog(wxDialog):
108                    0, wxALL, 4)                    0, wxALL, 4)
109          sizer.Add(wxStaticText(          sizer.Add(wxStaticText(
110              self, -1,              self, -1,
111              _("Field Type: %s") % classifier.Classifier.type2string[self.type]),              _("Data Type: %s") % classifier.Classifier.type2string[self.type]),
112              0, wxALL, 4)              0, wxALL, 4)
113    
114          psizer = wxBoxSizer(wxHORIZONTAL)          psizer = wxBoxSizer(wxHORIZONTAL)
115          psizer.Add(wxStaticText(self, -1, _("Generate:")),          psizer.Add(wxStaticText(self, -1, _("Generate:")),
116              0, wxALIGN_CENTER_VERTICAL, 0)              0, wxALIGN_CENTER_VERTICAL, 0)
117            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)  
118    
119          sizer.Add(psizer, 0, wxALL | wxGROW, 4)          sizer.Add(psizer, 0, wxALL | wxGROW, 4)
120    
121          #############          self.sizer_genPanel = wxBoxSizer(wxVERTICAL)
122            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)  
   
         #############  
123    
124          psizer = wxBoxSizer(wxHORIZONTAL)          psizer = wxBoxSizer(wxHORIZONTAL)
125          psizer.Add(wxStaticText(self, -1, _("Color Schemes:")),          psizer.Add(wxStaticText(self, -1, _("Color Scheme:")),
126              0, wxALIGN_CENTER_VERTICAL, 0)              0, wxALIGN_CENTER_VERTICAL, 0)
127    
128          self.propCombo = wxComboBox(self,          # Properties (Ramp) ComboBox
129                                     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)  
   
         #############  
130    
131          self.propPanel = None          self.propPanel = None
132          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)  
133    
134            self.propCombo.Append(PROPCOMBOSTR_GREY,  GreyRamp)
135            self.propCombo.Append(PROPCOMBOSTR_RED,   RedRamp)
136            self.propCombo.Append(PROPCOMBOSTR_GREEN, GreenRamp)
137            self.propCombo.Append(PROPCOMBOSTR_BLUE,  BlueRamp)
138            self.propCombo.Append(PROPCOMBOSTR_GREEN2RED, GreenToRedRamp)
139            self.propCombo.Append(PROPCOMBOSTR_HOT2COLD,  HotToColdRamp())
140            self.propCombo.Append(PROPCOMBOSTR_CUSTOM, custom_ramp_panel)
141    
142            self.propCombo.SetSelection(0)
143    
144          #############          psizer.Add(self.propCombo, 1, wxALL | wxGROW, 4)
145            sizer.Add(psizer, 0, wxALL | wxGROW, 4)
146    
147          sizer.Add(buttonSizer, 0,          sizer.Add(custom_ramp_panel, 1, wxGROW | wxALL, 4)
148                    wxALL | wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL, 4)          sizer.Show(custom_ramp_panel, False)
149    
150            # Finally place the main buttons
151            buttonSizer = wxBoxSizer(wxHORIZONTAL)
152            buttonSizer.Add(self.genButton, 0, wxRIGHT|wxEXPAND, 10)
153            buttonSizer.Add(self.cancelButton, 0, wxRIGHT|wxEXPAND, 10)
154            sizer.Add(buttonSizer, 0, wxALIGN_RIGHT|wxBOTTOM|wxTOP, 10)
155    
156          self.SetSizer(sizer)          self.SetSizer(sizer)
157          self.SetAutoLayout(True)          self.SetAutoLayout(True)
158          sizer.SetSizeHints(self)          sizer.SetSizeHints(self)
159    
160          self.sizer = sizer          self.topBox = sizer
161    
162            self.__DoOnGenTypeSelect()
163    
164            EVT_CHOICE(self, ID_CLASSGEN_GENCOMBO, self._OnGenTypeSelect)
165            EVT_CHOICE(self, ID_CLASSGEN_PROPCOMBO, self._OnPropTypeSelect)
166            EVT_BUTTON(self, wxID_OK, self.OnOK)
167            EVT_BUTTON(self, wxID_CANCEL, self.OnCancel)
168    
169          EVT_BUTTON(self, ID_CLASSGEN_GEN, self._OnGenerate)          self.__DoOnGenTypeSelect()
170          EVT_BUTTON(self, ID_CLASSGEN_CLOSE, self._OnCloseBtn)  
171            self.genChoice.SetFocus()
172    
173      def GetClassification(self):      def GetClassification(self):
174          return self.clazz          return self.clazz
# Line 149  class ClassGenDialog(wxDialog): Line 176  class ClassGenDialog(wxDialog):
176      def AllowGenerate(self, on):      def AllowGenerate(self, on):
177          pass #self.genButton.Enable(on)          pass #self.genButton.Enable(on)
178    
179      def _OnGenerate(self, event):      def OnOK(self, event):
180            """This is really the generate button, but we want to override
181            the wxDialog class.
182            """
183    
184            index = self.genChoice.GetSelection()
185    
186          index = self.genCombo.GetSelection()          assert index != -1, "button should be disabled!"
187    
188          genSel = self.genCombo.GetString(index)          genSel = self.genChoice.GetString(index)
189          genPanel = self.genCombo.GetClientData(index)          clazz, genPanel = self.genChoice.GetClientData(index)
190    
191          propPanel = self.propPanel          propPanel = self.propPanel
192    
193          if genSel in (GENCOMBOSTR_UNIFORM, GENCOMBOSTR_UNIQUE):          if genSel in (GENCOMBOSTR_UNIFORM,          \
194                          GENCOMBOSTR_UNIQUE,           \
195                          GENCOMBOSTR_QUANTILES):
196    
197              numGroups = genPanel.GetNumGroups()              numGroups = genPanel.GetNumGroups()
198    
199              index = self.propCombo.GetSelection()              index = self.propCombo.GetSelection()
# Line 177  class ClassGenDialog(wxDialog): Line 212  class ClassGenDialog(wxDialog):
212                      and max is not None \                      and max is not None \
213                      and numGroups is not None:                      and numGroups is not None:
214    
215                      self.clazz = ClassGenerator().GenUnifromDistribution(                      self.clazz = generate_uniform_distribution(
216                                  min, max, numGroups, ramp,                                  min, max, numGroups, ramp,
217                                  self.type == FIELDTYPE_INT)                                  self.type == FIELDTYPE_INT)
218    
# Line 187  class ClassGenDialog(wxDialog): Line 222  class ClassGenDialog(wxDialog):
222    
223                  list = genPanel.GetValueList()                  list = genPanel.GetValueList()
224    
225                  if len(list) > 0 \                  if len(list) > 0:
226                      and numGroups is not None:                      self.clazz = generate_singletons(list, ramp)
227                        self.parent._SetClassification(self.clazz)
228    
229                      self.clazz = ClassGenerator().GenSingletonsFromList(              elif genSel == GENCOMBOSTR_QUANTILES:
                                     list, numGroups, ramp)  
230    
231                    _range = genPanel.GetRange()
232                    _list = genPanel.GetList()
233                    _list.sort()
234    
235                    delta = 1 / float(numGroups)
236                    percents = [delta * i for i in range(1, numGroups + 1)]
237                    adjusted, self.clazz = \
238                        generate_quantiles(_list, percents, ramp, _range)
239    
240                    if adjusted:
241                        dlg = wxMessageDialog(self,
242                            _("Based on the data from the table and the input\n" +
243                              "values, the exact quantiles could not be generated.\n\n" +
244                              "Accept a close estimate?"),
245                            _("Problem with Quantiles"),
246    
247                            wxYES_NO|wxYES_DEFAULT|wxICON_QUESTION)
248                        if dlg.ShowModal() == wxID_YES:
249                            self.parent._SetClassification(self.clazz)
250                    else:
251                      self.parent._SetClassification(self.clazz)                      self.parent._SetClassification(self.clazz)
252    
253      def _OnCloseBtn(self, event):      def OnCancel(self, event):
254          self.Close()          self.Close()
255    
256      def _OnGenTypeSelect(self, event):      def _OnGenTypeSelect(self, event):
257            self.__DoOnGenTypeSelect()
258            return
259    
260          combo = event.GetEventObject()          combo = event.GetEventObject()
261    
262          selIndex = combo.GetSelection()          selIndex = combo.GetSelection()
263    
264          if self.genPanel is not None:          if self.genPanel is not None:
265              self.sizer.Show(self.genPanel, False)              self.topBox.Show(self.genPanel, False)
266    
267          self.genPanel = combo.GetClientData(selIndex)          self.genPanel = combo.GetClientData(selIndex)
268          if self.genPanel is not None:          if self.genPanel is not None:
269              self.sizer.Show(self.genPanel, True)              self.topBox.Show(self.genPanel, True)
270    
271          self.sizer.SetSizeHints(self)          self.topBox.SetSizeHints(self)
272          self.sizer.Layout()          self.topBox.Layout()
273    
274      def _OnPropTypeSelect(self, event):      def _OnPropTypeSelect(self, event):
275          combo = event.GetEventObject()          combo = event.GetEventObject()
# Line 221  class ClassGenDialog(wxDialog): Line 278  class ClassGenDialog(wxDialog):
278          sel = combo.GetString(selIndex)          sel = combo.GetString(selIndex)
279    
280          if isinstance(self.propPanel, wxPanel):          if isinstance(self.propPanel, wxPanel):
281              self.sizer.Show(self.propPanel, False)              self.topBox.Show(self.propPanel, False)
282    
283          self.propPanel = combo.GetClientData(selIndex)          self.propPanel = combo.GetClientData(selIndex)
284    
285          if isinstance(self.propPanel, wxPanel):          if isinstance(self.propPanel, wxPanel):
286              self.sizer.Show(self.propPanel, True)              self.topBox.Show(self.propPanel, True)
287    
288            self.topBox.SetSizeHints(self)
289            self.topBox.Layout()
290    
291        def __DoOnGenTypeSelect(self):
292            choice = self.genChoice
293    
294            sel = choice.GetSelection()
295            if sel == -1: return
296    
297            clazz, obj = choice.GetClientData(sel)
298    
299            if self.curGenPanel is not None:
300                self.curGenPanel.Hide()
301                self.sizer_genPanel.Remove(self.curGenPanel)
302    
303          self.sizer.SetSizeHints(self)          self.curGenPanel = obj
304          self.sizer.Layout()          self.curGenPanel.Show()
305    
306            self.sizer_genPanel.Add(self.curGenPanel, 1,
307                wxALL|wxEXPAND|wxADJUST_MINSIZE, 3)
308            self.sizer_genPanel.Layout()
309            self.Layout()
310            self.topBox.SetSizeHints(self)
311    
312  ID_UNIFORM_MIN = 4001  ID_UNIFORM_MIN = 4001
313  ID_UNIFORM_MAX = 4002  ID_UNIFORM_MAX = 4002
# Line 276  class GenUniformPanel(wxPanel): Line 353  class GenUniformPanel(wxPanel):
353          sizer = wxBoxSizer(wxHORIZONTAL)          sizer = wxBoxSizer(wxHORIZONTAL)
354    
355          sizer.Add(wxStaticText(self, -1, _("Number of Groups:")), 0, wxALL, 4)          sizer.Add(wxStaticText(self, -1, _("Number of Groups:")), 0, wxALL, 4)
356          self.numGroupsCtrl = wxSpinCtrl(self, ID_UNIFORM_NGROUPS, style=wxTE_RIGHT)          self.numGroupsCtrl = wxSpinCtrl(self, ID_UNIFORM_NGROUPS,
357                                            style=wxTE_RIGHT)
358          EVT_TEXT(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)          EVT_TEXT(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)
359          EVT_SPINCTRL(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)          EVT_SPINCTRL(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)
360          sizer.Add(self.numGroupsCtrl, 1, wxALL, 4)          sizer.Add(self.numGroupsCtrl, 1, wxALL, 4)
# Line 297  class GenUniformPanel(wxPanel): Line 375  class GenUniformPanel(wxPanel):
375          self.numGroupsChanging = False          self.numGroupsChanging = False
376          self.steppingChanging = False          self.steppingChanging = False
377    
378          self.numGroupsCtrl.SetRange(1, 100)          self.numGroupsCtrl.SetRange(1, sys.maxint)
379    
380          self.numGroupsCtrl.SetValue(1)          self.numGroupsCtrl.SetValue(1)
381          self.stepCtrl.SetValue("1")          self.stepCtrl.SetValue("1")
# Line 347  class GenUniformPanel(wxPanel): Line 425  class GenUniformPanel(wxPanel):
425          self.numGroupsCtrl.Enable(on)          self.numGroupsCtrl.Enable(on)
426          self.stepCtrl.Enable(on)          self.stepCtrl.Enable(on)
427    
         if on:  
             self.numGroupsCtrl.SetRange(1, abs(max - min) / 0.001)  
   
428          ngroups = self.GetNumGroups()          ngroups = self.GetNumGroups()
429    
430          if ngroups is not None  \          if ngroups is not None  \
# Line 380  class GenUniformPanel(wxPanel): Line 455  class GenUniformPanel(wxPanel):
455          min = self.GetMin()          min = self.GetMin()
456          max = self.GetMax()          max = self.GetMax()
457    
         if ngroups >= self.numGroupsCtrl.GetMax():  
             self.numGroupsCtrl.SetRange(1, ngroups + 1)  
   
458          if ngroups is not None  \          if ngroups is not None  \
459              and min is not None \              and min is not None \
460              and max is not None \              and max is not None \
# Line 429  class GenUniformPanel(wxPanel): Line 501  class GenUniformPanel(wxPanel):
501              self.parent.AllowGenerate(False)              self.parent.AllowGenerate(False)
502    
503      def _OnRetrieve(self, event):      def _OnRetrieve(self, event):
504            table = self.layer.ShapeStore().Table()
505          if self.layer.table is not None:          if table is not None:
506              range = self.layer.table.field_range(self.fieldName)              ThubanBeginBusyCursor()
507              self.minCtrl.SetValue(str(range[0][0]))              try:
508              self.maxCtrl.SetValue(str(range[1][0]))                  min, max = table.ValueRange(self.fieldName)
509                    self.minCtrl.SetValue(str(min))
510                    self.maxCtrl.SetValue(str(max))
511                finally:
512                    ThubanEndBusyCursor()
513    
514      def __GetValidatedTypeEntry(self, win, value, type, badValue = None):      def __GetValidatedTypeEntry(self, win, value, type, badValue = None):
515    
# Line 475  class GenUniformPanel(wxPanel): Line 551  class GenUniformPanel(wxPanel):
551          return valid          return valid
552    
553      def __CalcStepping(self, min, max, ngroups):      def __CalcStepping(self, min, max, ngroups):
         step = Str2Num(str((max - min) / float(ngroups)))  
554          if self.fieldType == FIELDTYPE_INT:          if self.fieldType == FIELDTYPE_INT:
555              step = int(step)              step = int((max - min + 1) / float(ngroups))
556            else:
557                step = (max - min) / float(ngroups)
558    
559          return step          return step
560    
# Line 499  ID_UNIQUE_DONTUSE = 4004 Line 576  ID_UNIQUE_DONTUSE = 4004
576  ID_UNIQUE_USENONE = 4005  ID_UNIQUE_USENONE = 4005
577  ID_UNIQUE_SORTAVAIL = 4006  ID_UNIQUE_SORTAVAIL = 4006
578  ID_UNIQUE_SORTUSE = 4007  ID_UNIQUE_SORTUSE = 4007
579    ID_UNIQUE_REVAVAIL = 4008
580    ID_UNIQUE_REVUSE = 4009
581    
582  class GenUniquePanel(wxPanel):  class GenUniquePanel(wxPanel):
583    
# Line 514  class GenUniquePanel(wxPanel): Line 593  class GenUniquePanel(wxPanel):
593                                      wxVERTICAL)                                      wxVERTICAL)
594    
595    
596            #bsizer = wxBoxSizer(wxVERTICAL)
597            topSizer.Add(wxButton(self, ID_UNIQUE_RETRIEVE,
598                                _("Retrieve From Table")),
599                       0, wxALL | wxALIGN_RIGHT, 4)
600    
601            EVT_BUTTON(self, ID_UNIQUE_RETRIEVE, self._OnRetrieve)
602    
603            #topSizer.Add(bsizer, 0, wxALL, 4)
604    
605          sizer = wxBoxSizer(wxHORIZONTAL)          sizer = wxBoxSizer(wxHORIZONTAL)
606    
607          self.dataList = []          self.dataList = []
# Line 525  class GenUniquePanel(wxPanel): Line 613  class GenUniquePanel(wxPanel):
613          self.list_avail_data = []          self.list_avail_data = []
614          psizer.Add(self.list_avail, 1, wxGROW, 0)          psizer.Add(self.list_avail, 1, wxGROW, 0)
615    
616          psizer.Add(wxButton(self, ID_UNIQUE_SORTAVAIL, _("Sort")))          bsizer = wxBoxSizer(wxHORIZONTAL)
617            bsizer.Add(wxButton(self, ID_UNIQUE_SORTAVAIL, _("Sort")))
618            EVT_BUTTON(self, ID_UNIQUE_SORTAVAIL, self._OnSortList)
619    
620          EVT_BUTTON(self, ID_UNIQUE_SORTAVAIL, self._OnSortAvailList)          bsizer.Add(wxButton(self, ID_UNIQUE_REVAVAIL, _("Reverse")))
621            EVT_BUTTON(self, ID_UNIQUE_REVAVAIL, self._OnReverseList)
622    
623            psizer.Add(bsizer, 0, wxGROW, 0)
624          sizer.Add(psizer, 1, wxGROW, 0)          sizer.Add(psizer, 1, wxGROW, 0)
625    
626                    
627          bsizer = wxBoxSizer(wxVERTICAL)          bsizer = wxBoxSizer(wxVERTICAL)
628          bsizer.Add(wxButton(self, ID_UNIQUE_USEALL, _("Use All")),  
629            bmp = resource.GetBitmapResource(USEALL_BMP, wxBITMAP_TYPE_XPM)
630            bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USEALL, bmp),
631                     0, wxGROW | wxALL, 4)                     0, wxGROW | wxALL, 4)
632          bsizer.Add(wxButton(self, ID_UNIQUE_USE, _("Use >>")),          bmp = resource.GetBitmapResource(USE_BMP, wxBITMAP_TYPE_XPM)
633            bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USE, bmp),
634                     0, wxGROW | wxALL, 4)                     0, wxGROW | wxALL, 4)
635          bsizer.Add(wxButton(self, ID_UNIQUE_DONTUSE, _("<< Don't Use")),          bmp = resource.GetBitmapResource(USENOT_BMP, wxBITMAP_TYPE_XPM)
636            bsizer.Add(wxBitmapButton(self, ID_UNIQUE_DONTUSE, bmp),
637                     0, wxGROW | wxALL, 4)                     0, wxGROW | wxALL, 4)
638          bsizer.Add(wxButton(self, ID_UNIQUE_USENONE, _("Use None")),          bmp = resource.GetBitmapResource(USENONE_BMP, wxBITMAP_TYPE_XPM)
639            bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USENONE, bmp),
640                     0, wxGROW | wxALL, 4)                     0, wxGROW | wxALL, 4)
641    
642          EVT_BUTTON(self, ID_UNIQUE_USEALL, self._OnUseAll)          EVT_BUTTON(self, ID_UNIQUE_USEALL, self._OnUseAll)
# Line 556  class GenUniquePanel(wxPanel): Line 653  class GenUniquePanel(wxPanel):
653          self.list_use_data = []          self.list_use_data = []
654          psizer.Add(self.list_use, 1, wxGROW, 0)          psizer.Add(self.list_use, 1, wxGROW, 0)
655    
656          psizer.Add(wxButton(self, ID_UNIQUE_SORTUSE, _("Sort")))          bsizer = wxBoxSizer(wxHORIZONTAL)
657            bsizer.Add(wxButton(self, ID_UNIQUE_SORTUSE, _("Sort")))
658            EVT_BUTTON(self, ID_UNIQUE_SORTUSE, self._OnSortList)
659    
660          EVT_BUTTON(self, ID_UNIQUE_SORTUSE, self._OnSortUseList)          bsizer.Add(wxButton(self, ID_UNIQUE_REVUSE, _("Reverse")))
661            EVT_BUTTON(self, ID_UNIQUE_REVUSE, self._OnReverseList)
662    
663          sizer.Add(psizer, 1, wxGROW, 0)          psizer.Add(bsizer, 0, wxGROW, 0)
664    
665          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)  
666    
         sizer.Add(bsizer, 0, wxALL, 4)  
667    
668          topSizer.Add(sizer, 1, wxGROW, 0)          topSizer.Add(sizer, 1, wxGROW, 0)
669    
# Line 577  class GenUniquePanel(wxPanel): Line 671  class GenUniquePanel(wxPanel):
671          self.SetAutoLayout(True)          self.SetAutoLayout(True)
672          topSizer.SetSizeHints(self)          topSizer.SetSizeHints(self)
673    
674          self.parent.AllowGenerate(False)          width, height = self.list_avail.GetSizeTuple()
675            self.list_avail.SetColumnWidth(0,width)
676            width, height = self.list_use.GetSizeTuple()
677            self.list_use.SetColumnWidth(0,width)
678    
679          self.mylist = ["Hallo", "Welt!", "Wie", "geht", "es", "dir", "?"]          self.parent.AllowGenerate(False)
680    
681      def GetNumGroups(self):      def GetNumGroups(self):
682          return self.list_use.GetItemCount()          return self.list_use.GetItemCount()
# Line 590  class GenUniquePanel(wxPanel): Line 687  class GenUniquePanel(wxPanel):
687              list.append(self.dataList[self.list_use.GetItemData(i)])              list.append(self.dataList[self.list_use.GetItemData(i)])
688          return list          return list
689    
690      def _OnSortAvailList(self, event):      def _OnSortList(self, event):
691          self.list_avail.SortItems(lambda i1, i2:          id = event.GetId()
692                                      cmp(self.dataList[i1],  
693                                          self.dataList[i2]))          if id == ID_UNIQUE_SORTUSE:
694                list = self.list_use
695      def _OnSortUseList(self, event):          else:
696          self.list_use.SortItems(lambda i1, i2:              list = self.list_avail
697                                      cmp(self.dataList[i1],  
698                                          self.dataList[i2]))          list.SortItems(lambda i1, i2: cmp(self.dataList[i1],
699                                              self.dataList[i2]))
700    
701        def _OnReverseList(self, event):
702            id = event.GetId()
703    
704            if id == ID_UNIQUE_REVUSE:
705                list = self.list_use
706            else:
707                list = self.list_avail
708    
709            #
710            # always returning 1 reverses the list
711            #
712            list.SortItems(lambda i1, i2: 1)
713    
714      def _OnRetrieve(self, event):      def _OnRetrieve(self, event):
715          self.list_use.DeleteAllItems()          self.list_use.DeleteAllItems()
# Line 606  class GenUniquePanel(wxPanel): Line 717  class GenUniquePanel(wxPanel):
717          self.list_avail.DeleteAllItems()          self.list_avail.DeleteAllItems()
718          self.list_avail_data = []          self.list_avail_data = []
719    
720          list = self.layer.table.GetUniqueValues(self.fieldName)          ThubanBeginBusyCursor()
721          index = 0          try:
722          for v in list:              list = self.layer.ShapeStore().Table().UniqueValues(self.fieldName)
723              self.dataList.append(v)              index = 0
724              i = self.list_avail.InsertStringItem(index, str(v))              for v in list:
725              self.list_avail.SetItemData(index, i)                  self.dataList.append(v)
726                    i = self.list_avail.InsertStringItem(index, str(v))
727              self.list_avail_data.append(v)                  self.list_avail.SetItemData(index, i)
728              index += 1      
729                    self.list_avail_data.append(v)
730                    index += 1
731            finally:
732                ThubanEndBusyCursor()
733    
734      def _OnUseAll(self, event):      def _OnUseAll(self, event):
735          for i in range(self.list_avail.GetItemCount()):          for i in range(self.list_avail.GetItemCount()):
736              self.__MoveListItem(0, self.list_avail, self.list_use)              self.__MoveListItem(0, self.list_avail, self.list_use)
737    
738      def _OnUse(self, event):      def _OnUse(self, event):
         print "_OnUse"  
739          self.__MoveSelectedItems(self.list_avail, self.list_use)          self.__MoveSelectedItems(self.list_avail, self.list_use)
740    
741      def _OnDontUse(self, event):      def _OnDontUse(self, event):
         print "_OnDontUse"  
742          self.__MoveSelectedItems(self.list_use, self.list_avail)          self.__MoveSelectedItems(self.list_use, self.list_avail)
743    
744      def _OnUseNone(self, event):      def _OnUseNone(self, event):
         print "_OnUseNone"  
745    
746          for i in range(self.list_use.GetItemCount()):          for i in range(self.list_use.GetItemCount()):
747              self.__MoveListItem(0, self.list_use, self.list_avail)              self.__MoveListItem(0, self.list_use, self.list_avail)
# Line 664  class GenUniquePanel(wxPanel): Line 776  class GenUniquePanel(wxPanel):
776  #       list.SetColumnWidth(0, event.GetSize().GetWidth())  #       list.SetColumnWidth(0, event.GetSize().GetWidth())
777  #        #      
778    
779    ID_QUANTILES_RANGE = 4001
780    ID_QUANTILES_RETRIEVE = 4002
781    
782    class GenQuantilesPanel(wxPanel):
783    
784        def __init__(self, parent, layer, fieldName, fieldType):
785            wxPanel.__init__(self, parent, -1)
786    
787            self.parent = parent
788            self.layer = layer
789            self.fieldName = fieldName
790            self.fieldType = fieldType
791    
792            topBox = wxStaticBoxSizer(wxStaticBox(self, -1, ""),
793                                        wxVERTICAL)
794    
795            self.text_range = wxTextCtrl(self, ID_QUANTILES_RANGE, "")
796            self.button_retrieve = wxButton(self, ID_QUANTILES_RETRIEVE,
797                                            _("Retrieve from Table"))
798    
799            self.spin_numClasses = wxSpinCtrl(self, -1, style=wxTE_RIGHT)
800            self.spin_numClasses.SetRange(1, sys.maxint)
801            self.spin_numClasses.SetValue(1)
802    
803    
804            sizer = wxBoxSizer(wxHORIZONTAL)
805            sizer.Add(wxStaticText(self, -1, _("Apply to Range")), 0, wxALL, 4)
806            sizer.Add(self.text_range, 1, wxALL, 4)
807            sizer.Add(self.button_retrieve, 0, wxALL, 4)
808    
809            topBox.Add(sizer, 0, wxEXPAND, 0)
810    
811            sizer = wxBoxSizer(wxHORIZONTAL)
812            sizer.Add(wxStaticText(self, -1, _("Number of Classes:")), 0, wxALL, 4)
813            sizer.Add(self.spin_numClasses, 1, wxALL, 4)
814    
815            topBox.Add(sizer, 0, wxEXPAND, 0)
816    
817            self.SetSizer(topBox)
818            self.SetAutoLayout(True)
819            topBox.Fit(self)
820            topBox.SetSizeHints(self)
821    
822            EVT_TEXT(self, ID_QUANTILES_RANGE, self.OnRangeText)
823            EVT_BUTTON(self, ID_QUANTILES_RETRIEVE, self.OnRetrieve)
824    
825            self.__range = None
826    
827        def GetNumGroups(self):
828            return self.spin_numClasses.GetValue()
829    
830        def GetRange(self):
831            assert self.__range is not None
832    
833            return self.__range
834    
835        def GetList(self):
836            _list = []
837            table = self.layer.ShapeStore().Table()
838            if table is not None:
839                ThubanBeginBusyCursor()
840                try:
841                    #
842                    # FIXME: Replace with a call to table when the method
843                    # has been written to get all the values
844                    #
845                    for i in range(table.NumRows()):
846                        _list.append(table.ReadValue(i, self.fieldName))
847                finally:
848                    ThubanEndBusyCursor()
849    
850            return _list
851    
852        def OnRangeText(self, event):
853    
854            try:
855                self.__range = Range(self.text_range.GetValue())
856            except ValueError:
857                self.__range = None
858    
859            if self.__range is not None:
860                self.text_range.SetForegroundColour(wxBLACK)
861            else:
862                self.text_range.SetForegroundColour(wxRED)
863    
864        def OnRetrieve(self, event):
865            table = self.layer.ShapeStore().Table()
866            if table is not None:
867                ThubanBeginBusyCursor()
868                try:
869                    min, max = table.ValueRange(self.fieldName)
870                    self.text_range.SetValue("[" + str(min) + ";" + str(max) + "]")
871                finally:
872                    ThubanEndBusyCursor()
873    
874  ID_CUSTOMRAMP_COPYSTART = 4001  ID_CUSTOMRAMP_COPYSTART = 4001
875  ID_CUSTOMRAMP_COPYEND = 4002  ID_CUSTOMRAMP_COPYEND = 4002
876  ID_CUSTOMRAMP_EDITSTART = 4003  ID_CUSTOMRAMP_EDITSTART = 4003
# Line 695  class CustomRampPanel(wxPanel): Line 902  class CustomRampPanel(wxPanel):
902                        | wxALIGN_CENTER_VERTICAL, \                        | wxALIGN_CENTER_VERTICAL, \
903                     4)                     4)
904    
905            bmp = resource.GetBitmapResource(USE_BMP, wxBITMAP_TYPE_XPM)
906          bsizer = wxBoxSizer(wxVERTICAL)          bsizer = wxBoxSizer(wxVERTICAL)
907          bsizer.Add(wxButton(self, ID_CUSTOMRAMP_COPYSTART, _("Copy >>")),          bsizer.Add(wxBitmapButton(self, ID_CUSTOMRAMP_COPYSTART, bmp),
908                     0, wxGROW | wxALL, 4)                     0, wxGROW | wxALL, 4)
909          bsizer.Add(wxButton(self, ID_CUSTOMRAMP_COPYEND, _("<< Copy")),          bmp = resource.GetBitmapResource(USENOT_BMP, wxBITMAP_TYPE_XPM)
910            bsizer.Add(wxBitmapButton(self, ID_CUSTOMRAMP_COPYEND, bmp),
911                     0, wxGROW | wxALL, 4)                     0, wxGROW | wxALL, 4)
912    
913          topSizer.Add(bsizer,          topSizer.Add(bsizer,
# Line 750  class CustomRampPanel(wxPanel): Line 959  class CustomRampPanel(wxPanel):
959      def _OnEditEnd(self, event):      def _OnEditEnd(self, event):
960          self.endPropCtrl.DoEdit()          self.endPropCtrl.DoEdit()
961    
962  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.1341

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26