/[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 907 by bh, Fri May 16 15:01:04 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 ClassGenerator, \
24  ID_CLASSGEN_CLOSE = 4002      CustomRamp, GreyRamp, RedRamp, GreenRamp, BlueRamp, GreenToRedRamp, \
25  ID_CLASSGEN_GENCOMBO = 4007      HotToColdRamp
26  ID_CLASSGEN_PROPCOMBO = 4008  
27    USEALL_BMP  = "group_use_all"
28    USE_BMP     = "group_use"
29    USENOT_BMP  = "group_use_not"
30    USENONE_BMP = "group_use_none"
31    
32  GENCOMBOSTR_UNIFORM = _("Uniform Distribution")  GENCOMBOSTR_UNIFORM = _("Uniform Distribution")
33  GENCOMBOSTR_UNIQUE = _("Unique Values")  GENCOMBOSTR_UNIQUE = _("Unique Values")
34    GENCOMBOSTR_QUANTILES = _("Quantiles from Table")
35    
36  PROPCOMBOSTR_CUSTOM = _("Custom Ramp")  PROPCOMBOSTR_CUSTOM     = _("Custom Ramp")
37  PROPCOMBOSTR_RED    = _("Red Ramp")  PROPCOMBOSTR_GREY       = _("Grey Ramp")
38  PROPCOMBOSTR_GREEN  = _("Green Ramp")  PROPCOMBOSTR_RED        = _("Red Ramp")
39  PROPCOMBOSTR_BLUE   = _("Blue Ramp")  PROPCOMBOSTR_GREEN      = _("Green Ramp")
40    PROPCOMBOSTR_BLUE       = _("Blue Ramp")
41    PROPCOMBOSTR_GREEN2RED  = _("Green-to-Red Ramp")
42    PROPCOMBOSTR_HOT2COLD   = _("Hot-to-Cold Ramp")
43    
44    ID_CLASSGEN_GENCOMBO = 4007
45    ID_CLASSGEN_PROPCOMBO = 4008
46    
47  class ClassGenDialog(wxDialog):  class ClassGenDialog(wxDialog):
48                                                                                    
49      def __init__(self, parent, layer, fieldName):      def __init__(self, parent, layer, fieldName):
50          """Inialize the class generating dialog.          """Inialize the class generating dialog.
51    
# Line 44  class ClassGenDialog(wxDialog): Line 54  class ClassGenDialog(wxDialog):
54    
55          wxDialog.__init__(self, parent, -1, _("Generate Classification"),          wxDialog.__init__(self, parent, -1, _("Generate Classification"),
56                            style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)                            style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
57                                                                                    
58          self.parent = parent          self.parent = parent
59            self.layer = layer
60          self.clazz = None          self.clazz = None
61    
62          self.type, name, width, prec = layer.table.field_info_by_name(fieldName)          col = layer.table.Column(fieldName)
63            self.type = col.type
64    
65            self.fieldName = fieldName
66            self.fieldType = self.type
67    
68            self.curGenPanel = None
69    
70            self.genpanels = []
71    
72          #############          #############
73          # we need to create genButton first because when we create the          # we need to create genButton first because when we create the
74          # panels they will call AllowGenerate() which uses genButton.          # panels they will call AllowGenerate() which uses genButton.
75          #          #
76          buttonSizer = wxBoxSizer(wxHORIZONTAL)          self.genButton = wxButton(self, wxID_OK, _("Generate"))
77          self.genButton = wxButton(self, ID_CLASSGEN_GEN, _("Generate"))          self.genButton.SetDefault()
78            self.genChoice = wxChoice(self, ID_CLASSGEN_GENCOMBO)
79    
80          buttonSizer.Add(self.genButton, 0, wxALL, 4)          self.genpanels.append((GENCOMBOSTR_UNIQUE, GenUniquePanel))
81          buttonSizer.Add(60, 20, 0, wxALL, 4)          if self.type in (FIELDTYPE_INT, FIELDTYPE_DOUBLE):
82          buttonSizer.Add(wxButton(self, ID_CLASSGEN_CLOSE, _("Close")),              self.genpanels.append((GENCOMBOSTR_UNIFORM, GenUniformPanel))
83                          0, wxALL, 4)              self.genpanels.append((GENCOMBOSTR_QUANTILES, GenQuantilesPanel))
84    
85            for name, clazz in self.genpanels:
86                self.genChoice.Append(name, [clazz, None])
87    
88            self.genChoice.SetSelection(0)
89    
90            self.propPanel = None
91            custom_ramp_panel = CustomRampPanel(self, layer.ShapeType())
92    
93            self.propCombo = wxChoice(self, ID_CLASSGEN_PROPCOMBO)
94            self.propCombo.Append(PROPCOMBOSTR_GREY,  GreyRamp())
95            self.propCombo.Append(PROPCOMBOSTR_RED,   RedRamp())
96            self.propCombo.Append(PROPCOMBOSTR_GREEN, GreenRamp())
97            self.propCombo.Append(PROPCOMBOSTR_BLUE,  BlueRamp())
98            self.propCombo.Append(PROPCOMBOSTR_GREEN2RED, GreenToRedRamp())
99            self.propCombo.Append(PROPCOMBOSTR_HOT2COLD,  HotToColdRamp())
100            self.propCombo.Append(PROPCOMBOSTR_CUSTOM, custom_ramp_panel)
101    
102            self.propCombo.SetSelection(0)
103    
104          #############          #############
105    
# Line 70  class ClassGenDialog(wxDialog): Line 109  class ClassGenDialog(wxDialog):
109                    0, wxALL, 4)                    0, wxALL, 4)
110          sizer.Add(wxStaticText(          sizer.Add(wxStaticText(
111              self, -1,              self, -1,
112              _("Field Type: %s") % classifier.Classifier.type2string[self.type]),              _("Data Type: %s") % classifier.Classifier.type2string[self.type]),
113              0, wxALL, 4)              0, wxALL, 4)
114    
115          psizer = wxBoxSizer(wxHORIZONTAL)          psizer = wxBoxSizer(wxHORIZONTAL)
116          psizer.Add(wxStaticText(self, -1, _("Generate:")),          psizer.Add(wxStaticText(self, -1, _("Generate:")),
117              0, wxALIGN_CENTER_VERTICAL, 0)              0, wxALIGN_CENTER_VERTICAL, 0)
118            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)  
119    
120          sizer.Add(psizer, 0, wxALL | wxGROW, 4)          sizer.Add(psizer, 0, wxALL | wxGROW, 4)
121    
122          #############          self.sizer_genPanel = wxBoxSizer(wxVERTICAL)
123            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)  
   
         #############  
124    
125          psizer = wxBoxSizer(wxHORIZONTAL)          psizer = wxBoxSizer(wxHORIZONTAL)
126          psizer.Add(wxStaticText(self, -1, _("Color Schemes:")),          psizer.Add(wxStaticText(self, -1, _("Color Scheme:")),
127              0, wxALIGN_CENTER_VERTICAL, 0)              0, wxALIGN_CENTER_VERTICAL, 0)
   
         self.propCombo = wxComboBox(self,  
                                    ID_CLASSGEN_PROPCOMBO,  
                                    "", style = wxCB_READONLY)  
128          psizer.Add(self.propCombo, 1, wxALL | wxGROW, 4)          psizer.Add(self.propCombo, 1, wxALL | wxGROW, 4)
         EVT_COMBOBOX(self, ID_CLASSGEN_PROPCOMBO, self._OnPropTypeSelect)  
129          sizer.Add(psizer, 0, wxALL | wxGROW, 4)          sizer.Add(psizer, 0, wxALL | wxGROW, 4)
130    
131          #############          sizer.Add(custom_ramp_panel, 1, wxGROW | wxALL, 4)
132            sizer.Show(custom_ramp_panel, False)
         self.propPanel = None  
         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            buttonSizer = wxBoxSizer(wxHORIZONTAL)
135            buttonSizer.Add(self.genButton, 0, wxALL, 4)
136            buttonSizer.Add(60, 20, 0, wxALL, 4)
137            buttonSizer.Add(wxButton(self, wxID_CANCEL, _("Close")),
138                            0, wxALL, 4)
139          sizer.Add(buttonSizer, 0,          sizer.Add(buttonSizer, 0,
140                    wxALL | wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL, 4)                    wxALL | wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL, 4)
141    
   
142          self.SetSizer(sizer)          self.SetSizer(sizer)
143          self.SetAutoLayout(True)          self.SetAutoLayout(True)
144          sizer.SetSizeHints(self)          sizer.SetSizeHints(self)
145    
146          self.sizer = sizer          self.topBox = sizer
147    
148            self.__DoOnGenTypeSelect()
149    
150            EVT_CHOICE(self, ID_CLASSGEN_GENCOMBO, self._OnGenTypeSelect)
151            EVT_CHOICE(self, ID_CLASSGEN_PROPCOMBO, self._OnPropTypeSelect)
152            EVT_BUTTON(self, wxID_OK, self.OnOK)
153            EVT_BUTTON(self, wxID_CANCEL, self.OnCancel)
154    
155          EVT_BUTTON(self, ID_CLASSGEN_GEN, self._OnGenerate)          self.__DoOnGenTypeSelect()
156          EVT_BUTTON(self, ID_CLASSGEN_CLOSE, self._OnCloseBtn)  
157            self.genChoice.SetFocus()
158    
159      def GetClassification(self):      def GetClassification(self):
160          return self.clazz          return self.clazz
# Line 149  class ClassGenDialog(wxDialog): Line 162  class ClassGenDialog(wxDialog):
162      def AllowGenerate(self, on):      def AllowGenerate(self, on):
163          pass #self.genButton.Enable(on)          pass #self.genButton.Enable(on)
164    
165      def _OnGenerate(self, event):      def OnOK(self, event):
166            """This is really the generate button, but we want to override
167            the wxDialog class.
168            """
169    
170            index = self.genChoice.GetSelection()
171    
172          index = self.genCombo.GetSelection()          assert index != -1, "button should be disabled!"
173    
174          genSel = self.genCombo.GetString(index)          genSel = self.genChoice.GetString(index)
175          genPanel = self.genCombo.GetClientData(index)          clazz, genPanel = self.genChoice.GetClientData(index)
176    
177          propPanel = self.propPanel          propPanel = self.propPanel
178    
179          if genSel in (GENCOMBOSTR_UNIFORM, GENCOMBOSTR_UNIQUE):          if genSel in (GENCOMBOSTR_UNIFORM,          \
180                          GENCOMBOSTR_UNIQUE,           \
181                          GENCOMBOSTR_QUANTILES):
182    
183              numGroups = genPanel.GetNumGroups()              numGroups = genPanel.GetNumGroups()
184    
185              index = self.propCombo.GetSelection()              index = self.propCombo.GetSelection()
# Line 177  class ClassGenDialog(wxDialog): Line 198  class ClassGenDialog(wxDialog):
198                      and max is not None \                      and max is not None \
199                      and numGroups is not None:                      and numGroups is not None:
200    
201                      self.clazz = ClassGenerator().GenUnifromDistribution(                      self.clazz = ClassGenerator().GenUniformDistribution(
202                                  min, max, numGroups, ramp,                                  min, max, numGroups, ramp,
203                                  self.type == FIELDTYPE_INT)                                  self.type == FIELDTYPE_INT)
204    
# Line 195  class ClassGenDialog(wxDialog): Line 216  class ClassGenDialog(wxDialog):
216    
217                      self.parent._SetClassification(self.clazz)                      self.parent._SetClassification(self.clazz)
218    
219      def _OnCloseBtn(self, event):              elif genSel == GENCOMBOSTR_QUANTILES:
220    
221                    _range = genPanel.GetRange()
222                    _list = genPanel.GetList()
223                    _list.sort()
224    
225                    delta = 1 / float(numGroups)
226                    percents = [delta * i for i in range(1, numGroups + 1)]
227                    adjusted, self.clazz = \
228                        ClassGenerator().GenQuantiles(_list, percents, ramp, _range)
229    
230                    if adjusted:
231                        dlg = wxMessageDialog(self,
232                            _("Based on the data from the table and the input\n" +
233                              "values, the exact quantiles could not be generated.\n\n" +
234                              "Accept a close estimate?"),
235                            _("Problem with Quantiles"),
236    
237                            wxYES_NO|wxYES_DEFAULT|wxICON_QUESTION)
238                        if dlg.ShowModal() == wxID_YES:
239                            self.parent._SetClassification(self.clazz)
240                    else:
241                        self.parent._SetClassification(self.clazz)
242    
243        def OnCancel(self, event):
244          self.Close()          self.Close()
245    
246      def _OnGenTypeSelect(self, event):      def _OnGenTypeSelect(self, event):
247            self.__DoOnGenTypeSelect()
248            return
249    
250          combo = event.GetEventObject()          combo = event.GetEventObject()
251    
252          selIndex = combo.GetSelection()          selIndex = combo.GetSelection()
253    
254          if self.genPanel is not None:          if self.genPanel is not None:
255              self.sizer.Show(self.genPanel, False)              self.topBox.Show(self.genPanel, False)
256    
257          self.genPanel = combo.GetClientData(selIndex)          self.genPanel = combo.GetClientData(selIndex)
258          if self.genPanel is not None:          if self.genPanel is not None:
259              self.sizer.Show(self.genPanel, True)              self.topBox.Show(self.genPanel, True)
260    
261          self.sizer.SetSizeHints(self)          self.topBox.SetSizeHints(self)
262          self.sizer.Layout()          self.topBox.Layout()
263    
264      def _OnPropTypeSelect(self, event):      def _OnPropTypeSelect(self, event):
265          combo = event.GetEventObject()          combo = event.GetEventObject()
# Line 221  class ClassGenDialog(wxDialog): Line 268  class ClassGenDialog(wxDialog):
268          sel = combo.GetString(selIndex)          sel = combo.GetString(selIndex)
269    
270          if isinstance(self.propPanel, wxPanel):          if isinstance(self.propPanel, wxPanel):
271              self.sizer.Show(self.propPanel, False)              self.topBox.Show(self.propPanel, False)
272    
273          self.propPanel = combo.GetClientData(selIndex)          self.propPanel = combo.GetClientData(selIndex)
274    
275          if isinstance(self.propPanel, wxPanel):          if isinstance(self.propPanel, wxPanel):
276              self.sizer.Show(self.propPanel, True)              self.topBox.Show(self.propPanel, True)
277    
278            self.topBox.SetSizeHints(self)
279            self.topBox.Layout()
280    
281        def __DoOnGenTypeSelect(self):
282            choice = self.genChoice
283    
284          self.sizer.SetSizeHints(self)          sel = choice.GetSelection()
285          self.sizer.Layout()          if sel == -1: return
286    
287            clazz, obj = choice.GetClientData(sel)
288    
289            if obj is None:
290                obj = clazz(self, self.layer, self.fieldName, self.fieldType)
291                choice.SetClientData(sel, [clazz, obj])
292    
293            if self.curGenPanel is not None:
294                self.curGenPanel.Hide()
295                self.sizer_genPanel.Remove(self.curGenPanel)
296    
297            self.curGenPanel = obj
298            self.curGenPanel.Show()
299    
300            self.sizer_genPanel.Add(self.curGenPanel, 1,
301                wxALL|wxEXPAND|wxADJUST_MINSIZE, 3)
302            self.sizer_genPanel.Layout()
303            self.Layout()
304            self.topBox.SetSizeHints(self)
305    
306  ID_UNIFORM_MIN = 4001  ID_UNIFORM_MIN = 4001
307  ID_UNIFORM_MAX = 4002  ID_UNIFORM_MAX = 4002
# Line 276  class GenUniformPanel(wxPanel): Line 347  class GenUniformPanel(wxPanel):
347          sizer = wxBoxSizer(wxHORIZONTAL)          sizer = wxBoxSizer(wxHORIZONTAL)
348    
349          sizer.Add(wxStaticText(self, -1, _("Number of Groups:")), 0, wxALL, 4)          sizer.Add(wxStaticText(self, -1, _("Number of Groups:")), 0, wxALL, 4)
350          self.numGroupsCtrl = wxSpinCtrl(self, ID_UNIFORM_NGROUPS, style=wxTE_RIGHT)          self.numGroupsCtrl = wxSpinCtrl(self, ID_UNIFORM_NGROUPS,
351                                            style=wxTE_RIGHT)
352          EVT_TEXT(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)          EVT_TEXT(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)
353          EVT_SPINCTRL(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)          EVT_SPINCTRL(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)
354          sizer.Add(self.numGroupsCtrl, 1, wxALL, 4)          sizer.Add(self.numGroupsCtrl, 1, wxALL, 4)
# Line 297  class GenUniformPanel(wxPanel): Line 369  class GenUniformPanel(wxPanel):
369          self.numGroupsChanging = False          self.numGroupsChanging = False
370          self.steppingChanging = False          self.steppingChanging = False
371    
372          self.numGroupsCtrl.SetRange(1, 100)          self.numGroupsCtrl.SetRange(1, sys.maxint)
373    
374          self.numGroupsCtrl.SetValue(1)          self.numGroupsCtrl.SetValue(1)
375          self.stepCtrl.SetValue("1")          self.stepCtrl.SetValue("1")
# Line 347  class GenUniformPanel(wxPanel): Line 419  class GenUniformPanel(wxPanel):
419          self.numGroupsCtrl.Enable(on)          self.numGroupsCtrl.Enable(on)
420          self.stepCtrl.Enable(on)          self.stepCtrl.Enable(on)
421    
         if on:  
             self.numGroupsCtrl.SetRange(1, abs(max - min) / 0.001)  
   
422          ngroups = self.GetNumGroups()          ngroups = self.GetNumGroups()
423    
424          if ngroups is not None  \          if ngroups is not None  \
# Line 380  class GenUniformPanel(wxPanel): Line 449  class GenUniformPanel(wxPanel):
449          min = self.GetMin()          min = self.GetMin()
450          max = self.GetMax()          max = self.GetMax()
451    
         if ngroups >= self.numGroupsCtrl.GetMax():  
             self.numGroupsCtrl.SetRange(1, ngroups + 1)  
   
452          if ngroups is not None  \          if ngroups is not None  \
453              and min is not None \              and min is not None \
454              and max is not None \              and max is not None \
# Line 431  class GenUniformPanel(wxPanel): Line 497  class GenUniformPanel(wxPanel):
497      def _OnRetrieve(self, event):      def _OnRetrieve(self, event):
498    
499          if self.layer.table is not None:          if self.layer.table is not None:
500              range = self.layer.table.field_range(self.fieldName)              wxBeginBusyCursor()
501              self.minCtrl.SetValue(str(range[0][0]))              min, max = self.layer.table.ValueRange(self.fieldName)
502              self.maxCtrl.SetValue(str(range[1][0]))              self.minCtrl.SetValue(str(min))
503                self.maxCtrl.SetValue(str(max))
504                wxEndBusyCursor()
505    
506      def __GetValidatedTypeEntry(self, win, value, type, badValue = None):      def __GetValidatedTypeEntry(self, win, value, type, badValue = None):
507    
# Line 475  class GenUniformPanel(wxPanel): Line 543  class GenUniformPanel(wxPanel):
543          return valid          return valid
544    
545      def __CalcStepping(self, min, max, ngroups):      def __CalcStepping(self, min, max, ngroups):
546          step = Str2Num(str((max - min) / float(ngroups)))          step = (max - min) / float(ngroups)
547          if self.fieldType == FIELDTYPE_INT:          if self.fieldType == FIELDTYPE_INT:
548              step = int(step)              step = int(step)
549    
# Line 499  ID_UNIQUE_DONTUSE = 4004 Line 567  ID_UNIQUE_DONTUSE = 4004
567  ID_UNIQUE_USENONE = 4005  ID_UNIQUE_USENONE = 4005
568  ID_UNIQUE_SORTAVAIL = 4006  ID_UNIQUE_SORTAVAIL = 4006
569  ID_UNIQUE_SORTUSE = 4007  ID_UNIQUE_SORTUSE = 4007
570    ID_UNIQUE_REVAVAIL = 4008
571    ID_UNIQUE_REVUSE = 4009
572    
573  class GenUniquePanel(wxPanel):  class GenUniquePanel(wxPanel):
574    
# Line 514  class GenUniquePanel(wxPanel): Line 584  class GenUniquePanel(wxPanel):
584                                      wxVERTICAL)                                      wxVERTICAL)
585    
586    
587            #bsizer = wxBoxSizer(wxVERTICAL)
588            topSizer.Add(wxButton(self, ID_UNIQUE_RETRIEVE,
589                                _("Retrieve From Table")),
590                       0, wxALL | wxALIGN_RIGHT, 4)
591    
592            EVT_BUTTON(self, ID_UNIQUE_RETRIEVE, self._OnRetrieve)
593    
594            #topSizer.Add(bsizer, 0, wxALL, 4)
595    
596          sizer = wxBoxSizer(wxHORIZONTAL)          sizer = wxBoxSizer(wxHORIZONTAL)
597    
598          self.dataList = []          self.dataList = []
# Line 525  class GenUniquePanel(wxPanel): Line 604  class GenUniquePanel(wxPanel):
604          self.list_avail_data = []          self.list_avail_data = []
605          psizer.Add(self.list_avail, 1, wxGROW, 0)          psizer.Add(self.list_avail, 1, wxGROW, 0)
606    
607          psizer.Add(wxButton(self, ID_UNIQUE_SORTAVAIL, _("Sort")))          bsizer = wxBoxSizer(wxHORIZONTAL)
608            bsizer.Add(wxButton(self, ID_UNIQUE_SORTAVAIL, _("Sort")))
609            EVT_BUTTON(self, ID_UNIQUE_SORTAVAIL, self._OnSortList)
610    
611          EVT_BUTTON(self, ID_UNIQUE_SORTAVAIL, self._OnSortAvailList)          bsizer.Add(wxButton(self, ID_UNIQUE_REVAVAIL, _("Reverse")))
612            EVT_BUTTON(self, ID_UNIQUE_REVAVAIL, self._OnReverseList)
613    
614            psizer.Add(bsizer, 0, wxGROW, 0)
615          sizer.Add(psizer, 1, wxGROW, 0)          sizer.Add(psizer, 1, wxGROW, 0)
616    
617                    
618          bsizer = wxBoxSizer(wxVERTICAL)          bsizer = wxBoxSizer(wxVERTICAL)
619          bsizer.Add(wxButton(self, ID_UNIQUE_USEALL, _("Use All")),  
620            bmp = resource.GetBitmapResource(USEALL_BMP, wxBITMAP_TYPE_XPM)
621            bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USEALL, bmp),
622                     0, wxGROW | wxALL, 4)                     0, wxGROW | wxALL, 4)
623          bsizer.Add(wxButton(self, ID_UNIQUE_USE, _("Use >>")),          bmp = resource.GetBitmapResource(USE_BMP, wxBITMAP_TYPE_XPM)
624            bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USE, bmp),
625                     0, wxGROW | wxALL, 4)                     0, wxGROW | wxALL, 4)
626          bsizer.Add(wxButton(self, ID_UNIQUE_DONTUSE, _("<< Don't Use")),          bmp = resource.GetBitmapResource(USENOT_BMP, wxBITMAP_TYPE_XPM)
627            bsizer.Add(wxBitmapButton(self, ID_UNIQUE_DONTUSE, bmp),
628                     0, wxGROW | wxALL, 4)                     0, wxGROW | wxALL, 4)
629          bsizer.Add(wxButton(self, ID_UNIQUE_USENONE, _("Use None")),          bmp = resource.GetBitmapResource(USENONE_BMP, wxBITMAP_TYPE_XPM)
630            bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USENONE, bmp),
631                     0, wxGROW | wxALL, 4)                     0, wxGROW | wxALL, 4)
632    
633          EVT_BUTTON(self, ID_UNIQUE_USEALL, self._OnUseAll)          EVT_BUTTON(self, ID_UNIQUE_USEALL, self._OnUseAll)
# Line 556  class GenUniquePanel(wxPanel): Line 644  class GenUniquePanel(wxPanel):
644          self.list_use_data = []          self.list_use_data = []
645          psizer.Add(self.list_use, 1, wxGROW, 0)          psizer.Add(self.list_use, 1, wxGROW, 0)
646    
647          psizer.Add(wxButton(self, ID_UNIQUE_SORTUSE, _("Sort")))          bsizer = wxBoxSizer(wxHORIZONTAL)
648            bsizer.Add(wxButton(self, ID_UNIQUE_SORTUSE, _("Sort")))
649            EVT_BUTTON(self, ID_UNIQUE_SORTUSE, self._OnSortList)
650    
651          EVT_BUTTON(self, ID_UNIQUE_SORTUSE, self._OnSortUseList)          bsizer.Add(wxButton(self, ID_UNIQUE_REVUSE, _("Reverse")))
652            EVT_BUTTON(self, ID_UNIQUE_REVUSE, self._OnReverseList)
653    
654          sizer.Add(psizer, 1, wxGROW, 0)          psizer.Add(bsizer, 0, wxGROW, 0)
655    
656          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)  
657    
         sizer.Add(bsizer, 0, wxALL, 4)  
658    
659          topSizer.Add(sizer, 1, wxGROW, 0)          topSizer.Add(sizer, 1, wxGROW, 0)
660    
# Line 579  class GenUniquePanel(wxPanel): Line 664  class GenUniquePanel(wxPanel):
664    
665          self.parent.AllowGenerate(False)          self.parent.AllowGenerate(False)
666    
         self.mylist = ["Hallo", "Welt!", "Wie", "geht", "es", "dir", "?"]  
   
667      def GetNumGroups(self):      def GetNumGroups(self):
668          return self.list_use.GetItemCount()          return self.list_use.GetItemCount()
669    
# Line 590  class GenUniquePanel(wxPanel): Line 673  class GenUniquePanel(wxPanel):
673              list.append(self.dataList[self.list_use.GetItemData(i)])              list.append(self.dataList[self.list_use.GetItemData(i)])
674          return list          return list
675    
676      def _OnSortAvailList(self, event):      def _OnSortList(self, event):
677          self.list_avail.SortItems(lambda i1, i2:          id = event.GetId()
678                                      cmp(self.dataList[i1],  
679                                          self.dataList[i2]))          if id == ID_UNIQUE_SORTUSE:
680                list = self.list_use
681      def _OnSortUseList(self, event):          else:
682          self.list_use.SortItems(lambda i1, i2:              list = self.list_avail
683                                      cmp(self.dataList[i1],  
684                                          self.dataList[i2]))          list.SortItems(lambda i1, i2: cmp(self.dataList[i1],
685                                              self.dataList[i2]))
686    
687        def _OnReverseList(self, event):
688            id = event.GetId()
689    
690            if id == ID_UNIQUE_REVUSE:
691                list = self.list_use
692            else:
693                list = self.list_avail
694    
695            #
696            # always returning 1 reverses the list
697            #
698            list.SortItems(lambda i1, i2: 1)
699    
700      def _OnRetrieve(self, event):      def _OnRetrieve(self, event):
701          self.list_use.DeleteAllItems()          self.list_use.DeleteAllItems()
# Line 606  class GenUniquePanel(wxPanel): Line 703  class GenUniquePanel(wxPanel):
703          self.list_avail.DeleteAllItems()          self.list_avail.DeleteAllItems()
704          self.list_avail_data = []          self.list_avail_data = []
705    
706          list = self.layer.table.GetUniqueValues(self.fieldName)          list = self.layer.table.UniqueValues(self.fieldName)
707          index = 0          index = 0
708          for v in list:          for v in list:
709              self.dataList.append(v)              self.dataList.append(v)
# Line 621  class GenUniquePanel(wxPanel): Line 718  class GenUniquePanel(wxPanel):
718              self.__MoveListItem(0, self.list_avail, self.list_use)              self.__MoveListItem(0, self.list_avail, self.list_use)
719    
720      def _OnUse(self, event):      def _OnUse(self, event):
         print "_OnUse"  
721          self.__MoveSelectedItems(self.list_avail, self.list_use)          self.__MoveSelectedItems(self.list_avail, self.list_use)
722    
723      def _OnDontUse(self, event):      def _OnDontUse(self, event):
         print "_OnDontUse"  
724          self.__MoveSelectedItems(self.list_use, self.list_avail)          self.__MoveSelectedItems(self.list_use, self.list_avail)
725    
726      def _OnUseNone(self, event):      def _OnUseNone(self, event):
         print "_OnUseNone"  
727    
728          for i in range(self.list_use.GetItemCount()):          for i in range(self.list_use.GetItemCount()):
729              self.__MoveListItem(0, self.list_use, self.list_avail)              self.__MoveListItem(0, self.list_use, self.list_avail)
# Line 664  class GenUniquePanel(wxPanel): Line 758  class GenUniquePanel(wxPanel):
758  #       list.SetColumnWidth(0, event.GetSize().GetWidth())  #       list.SetColumnWidth(0, event.GetSize().GetWidth())
759  #        #      
760    
761    ID_QUANTILES_RANGE = 4001
762    ID_QUANTILES_RETRIEVE = 4002
763    
764    class GenQuantilesPanel(wxPanel):
765    
766        def __init__(self, parent, layer, fieldName, fieldType):
767            wxPanel.__init__(self, parent, -1)
768    
769            self.parent = parent
770            self.layer = layer
771            self.fieldName = fieldName
772            self.fieldType = fieldType
773    
774            topBox = wxStaticBoxSizer(wxStaticBox(self, -1, ""),
775                                        wxVERTICAL)
776    
777            self.text_range = wxTextCtrl(self, ID_QUANTILES_RANGE, "")
778            self.button_retrieve = wxButton(self, ID_QUANTILES_RETRIEVE,
779                                            _("Retrieve from Table"))
780    
781            self.spin_numClasses = wxSpinCtrl(self, -1, style=wxTE_RIGHT)
782            self.spin_numClasses.SetRange(1, sys.maxint)
783            self.spin_numClasses.SetValue(1)
784    
785    
786            sizer = wxBoxSizer(wxHORIZONTAL)
787            sizer.Add(wxStaticText(self, -1, _("Apply to Range")), 0, wxALL, 4)
788            sizer.Add(self.text_range, 1, wxALL, 4)
789            sizer.Add(self.button_retrieve, 0, wxALL, 4)
790    
791            topBox.Add(sizer, 0, wxEXPAND, 0)
792    
793            sizer = wxBoxSizer(wxHORIZONTAL)
794            sizer.Add(wxStaticText(self, -1, _("Number of Classes:")), 0, wxALL, 4)
795            sizer.Add(self.spin_numClasses, 1, wxALL, 4)
796    
797            topBox.Add(sizer, 0, wxEXPAND, 0)
798    
799            self.SetSizer(topBox)
800            self.SetAutoLayout(True)
801            topBox.Fit(self)
802            topBox.SetSizeHints(self)
803    
804            EVT_TEXT(self, ID_QUANTILES_RANGE, self.OnRangeText)
805            EVT_BUTTON(self, ID_QUANTILES_RETRIEVE, self.OnRetrieve)
806    
807            self.__range = None
808    
809        def GetNumGroups(self):
810            return self.spin_numClasses.GetValue()
811    
812        def GetRange(self):
813            assert self.__range is not None
814    
815            return self.__range
816    
817        def GetList(self):
818    
819            _list = []
820    
821            if self.layer.table is not None:
822                wxBeginBusyCursor()
823    
824                #
825                # FIXME: Replace with a call to table when the method
826                # has been written to get all the values
827                #
828                table = self.layer.table
829                for i in range(table.NumRows()):
830                    _list.append(table.ReadValue(i, self.fieldName))
831    
832                wxEndBusyCursor()
833    
834            return _list
835    
836        def OnRangeText(self, event):
837    
838            try:
839                self.__range = Range(self.text_range.GetValue())
840            except ValueError:
841                self.__range = None
842    
843            if self.__range is not None:
844                self.text_range.SetForegroundColour(wxBLACK)
845            else:
846                self.text_range.SetForegroundColour(wxRED)
847    
848        def OnRetrieve(self, event):
849    
850            if self.layer.table is not None:
851                wxBeginBusyCursor()
852                min, max = self.layer.table.ValueRange(self.fieldName)
853                self.text_range.SetValue("[" + str(min) + ";" + str(max) + "]")
854                wxEndBusyCursor()
855    
856  ID_CUSTOMRAMP_COPYSTART = 4001  ID_CUSTOMRAMP_COPYSTART = 4001
857  ID_CUSTOMRAMP_COPYEND = 4002  ID_CUSTOMRAMP_COPYEND = 4002
858  ID_CUSTOMRAMP_EDITSTART = 4003  ID_CUSTOMRAMP_EDITSTART = 4003
# Line 695  class CustomRampPanel(wxPanel): Line 884  class CustomRampPanel(wxPanel):
884                        | wxALIGN_CENTER_VERTICAL, \                        | wxALIGN_CENTER_VERTICAL, \
885                     4)                     4)
886    
887            bmp = resource.GetBitmapResource(USE_BMP, wxBITMAP_TYPE_XPM)
888          bsizer = wxBoxSizer(wxVERTICAL)          bsizer = wxBoxSizer(wxVERTICAL)
889          bsizer.Add(wxButton(self, ID_CUSTOMRAMP_COPYSTART, _("Copy >>")),          bsizer.Add(wxBitmapButton(self, ID_CUSTOMRAMP_COPYSTART, bmp),
890                     0, wxGROW | wxALL, 4)                     0, wxGROW | wxALL, 4)
891          bsizer.Add(wxButton(self, ID_CUSTOMRAMP_COPYEND, _("<< Copy")),          bmp = resource.GetBitmapResource(USENOT_BMP, wxBITMAP_TYPE_XPM)
892            bsizer.Add(wxBitmapButton(self, ID_CUSTOMRAMP_COPYEND, bmp),
893                     0, wxGROW | wxALL, 4)                     0, wxGROW | wxALL, 4)
894    
895          topSizer.Add(bsizer,          topSizer.Add(bsizer,
# Line 750  class CustomRampPanel(wxPanel): Line 941  class CustomRampPanel(wxPanel):
941      def _OnEditEnd(self, event):      def _OnEditEnd(self, event):
942          self.endPropCtrl.DoEdit()          self.endPropCtrl.DoEdit()
943    
944  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.907

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26