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

Legend:
Removed from v.629  
changed lines
  Added in v.1219

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26