/[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 614 by jonathan, Mon Apr 7 08:56:38 2003 UTC revision 677 by jonathan, Tue Apr 15 19:21:01 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 *
# Line 17  from Thuban.Model.table import Table, FI Line 19  from Thuban.Model.table import Table, FI
19    
20  from Thuban.Model.color import Color  from Thuban.Model.color import Color
21    
22    import classifier
23    
24    import resource
25    
26    from Thuban.common import Str2Num
27    
28  ID_CLASSGEN_GEN = 4001  ID_CLASSGEN_GEN = 4001
29  ID_CLASSGEN_CANCEL = 4002  ID_CLASSGEN_CLOSE = 4002
30    ID_CLASSGEN_GENCOMBO = 4007
31    ID_CLASSGEN_PROPCOMBO = 4008
32    
33    USEALL_BMP  = "group_use_all"
34    USE_BMP     = "group_use"
35    USENOT_BMP  = "group_use_not"
36    USENONE_BMP = "group_use_none"
37    
38    GENCOMBOSTR_UNIFORM = _("Uniform Distribution")
39    GENCOMBOSTR_UNIQUE = _("Unique Values")
40    
41    PROPCOMBOSTR_CUSTOM     = _("Custom Ramp")
42    PROPCOMBOSTR_GREY       = _("Grey Ramp")
43    PROPCOMBOSTR_RED        = _("Red Ramp")
44    PROPCOMBOSTR_GREEN      = _("Green Ramp")
45    PROPCOMBOSTR_BLUE       = _("Blue Ramp")
46    PROPCOMBOSTR_HOT2COLD   = _("Hot-to-Cold Ramp")
47    
48  class ClassGenDialog(wxDialog):  class ClassGenDialog(wxDialog):
49                                                                                                                                                                    
50      def __init__(self, parent, table, fieldName):      def __init__(self, parent, layer, fieldName):
51            """Inialize the class generating dialog.
52    
53            parent -- this must be an instance of the Classifier class
54            """
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
60          self.clazz = None          self.clazz = None
61    
62          type, name, width, prec = table.field_info_by_name(fieldName)          self.type, name, width, prec = layer.table.field_info_by_name(fieldName)
   
         sizer = wxBoxSizer(wxVERTICAL)  
63    
64            #############
65            # we need to create genButton first because when we create the
66            # panels they will call AllowGenerate() which uses genButton.
67            #
68          buttonSizer = wxBoxSizer(wxHORIZONTAL)          buttonSizer = wxBoxSizer(wxHORIZONTAL)
69          self.genButton = wxButton(self, ID_CLASSGEN_GEN, _("Generate"))          self.genButton = wxButton(self, ID_CLASSGEN_GEN, _("Generate"))
70    
71          buttonSizer.Add(self.genButton, 0, wxALL, 4)          buttonSizer.Add(self.genButton, 0, wxALL, 4)
72          buttonSizer.Add(60, 20, 0, wxALL, 4)          buttonSizer.Add(60, 20, 0, wxALL, 4)
73          buttonSizer.Add(wxButton(self, ID_CLASSGEN_CANCEL, _("Cancel")),          buttonSizer.Add(wxButton(self, ID_CLASSGEN_CLOSE, _("Close")),
74                          0, wxALL, 4)                          0, wxALL, 4)
75    
76          if type in (FIELDTYPE_INT, FIELDTYPE_DOUBLE):          #############
77              self.panel = GenRangePanel(self, table, fieldName, type)  
78          elif type == FIELDTYPE_STRING:          sizer = wxBoxSizer(wxVERTICAL)
79              print "Select a field that is an int/decimal"  
80              #panel = GenSingletonPanel(self, table, fieldName)          sizer.Add(wxStaticText(self, -1, _("Field: %s") % fieldName),
81          else:                    0, wxALL, 4)
82              assert False, "Shouldn't be here."          sizer.Add(wxStaticText(
83              pass              self, -1,
84                _("Data Type: %s") % classifier.Classifier.type2string[self.type]),
85                0, wxALL, 4)
86    
87            psizer = wxBoxSizer(wxHORIZONTAL)
88            psizer.Add(wxStaticText(self, -1, _("Generate:")),
89                0, wxALIGN_CENTER_VERTICAL, 0)
90    
91            self.genCombo = wxComboBox(self,
92                                       ID_CLASSGEN_GENCOMBO,
93                                       "", style = wxCB_READONLY)
94            psizer.Add(self.genCombo, 1, wxALL | wxGROW, 4)
95            EVT_COMBOBOX(self, ID_CLASSGEN_GENCOMBO, self._OnGenTypeSelect)
96    
97            sizer.Add(psizer, 0, wxALL | wxGROW, 4)
98    
99            #############
100    
101            self.genPanel = None
102    
103            panel = GenUniquePanel(self, layer, fieldName, self.type)
104            self.genCombo.Append(GENCOMBOSTR_UNIQUE, panel)
105            sizer.Add(panel, 1, wxGROW | wxALL, 4)
106    
107            self.genPanel = panel
108    
109            if self.type in (FIELDTYPE_INT, FIELDTYPE_DOUBLE):
110                panel = GenUniformPanel(self, layer, fieldName, self.type)
111                self.genCombo.Append(GENCOMBOSTR_UNIFORM, panel)
112                sizer.Add(panel, 1, wxGROW | wxALL, 4)
113                sizer.Show(panel, False)
114    
115            self.genCombo.SetSelection(0)
116    
117            #############
118    
119            psizer = wxBoxSizer(wxHORIZONTAL)
120            psizer.Add(wxStaticText(self, -1, _("Color Scheme:")),
121                0, wxALIGN_CENTER_VERTICAL, 0)
122    
123            self.propCombo = wxComboBox(self,
124                                       ID_CLASSGEN_PROPCOMBO,
125                                       "", style = wxCB_READONLY)
126            psizer.Add(self.propCombo, 1, wxALL | wxGROW, 4)
127            EVT_COMBOBOX(self, ID_CLASSGEN_PROPCOMBO, self._OnPropTypeSelect)
128            sizer.Add(psizer, 0, wxALL | wxGROW, 4)
129    
130            #############
131    
132            self.propPanel = None
133            panel = CustomRampPanel(self, layer.ShapeType())
134            sizer.Add(panel, 1, wxALL | wxGROW, 4)
135            sizer.Show(panel, False)
136    
137            self.propCombo.Append(PROPCOMBOSTR_GREY,  GreyRamp())
138            self.propCombo.Append(PROPCOMBOSTR_RED,   RedRamp())
139            self.propCombo.Append(PROPCOMBOSTR_GREEN, GreenRamp())
140            self.propCombo.Append(PROPCOMBOSTR_BLUE,  BlueRamp())
141            self.propCombo.Append(PROPCOMBOSTR_HOT2COLD,  HotToColdRamp())
142            self.propCombo.Append(PROPCOMBOSTR_CUSTOM, panel)
143    
144            self.propCombo.SetSelection(0)
145    
146    
147            #############
148    
         sizer.Add(self.panel, 1, wxGROW | wxALL, 4)  
149          sizer.Add(buttonSizer, 0,          sizer.Add(buttonSizer, 0,
150                    wxALL | wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL, 4)                    wxALL | wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL, 4)
151    
152    
153          self.SetSizer(sizer)          self.SetSizer(sizer)
154          self.SetAutoLayout(True)          self.SetAutoLayout(True)
155          sizer.SetSizeHints(self)          sizer.SetSizeHints(self)
156    
157            self.sizer = sizer
158    
159          EVT_BUTTON(self, ID_CLASSGEN_GEN, self._OnGenerate)          EVT_BUTTON(self, ID_CLASSGEN_GEN, self._OnGenerate)
160          EVT_BUTTON(self, ID_CLASSGEN_CANCEL, self._OnCancel)          EVT_BUTTON(self, ID_CLASSGEN_CLOSE, self._OnCloseBtn)
161    
162      def GetClassification(self):      def GetClassification(self):
163          return self.clazz          return self.clazz
164    
165      def AllowGenerate(self, on):      def AllowGenerate(self, on):
166          self.genButton.Enable(on)          pass #self.genButton.Enable(on)
167    
168      def _OnGenerate(self, event):      def _OnGenerate(self, event):
         min = self.panel.GetMin()  
         max = self.panel.GetMax()  
         numGroups = self.panel.GetNumGroups()  
         cgp = ClassGroupProperties()  
         cgp2 = ClassGroupProperties()  
                                                                                   
         cgp.SetLineColor(Color(.5, 0, 0))  
         cgp2.SetLineColor(Color(1, 0, 1))  
         cgp2.SetLineWidth(10)  
169    
170          if min is not None \          index = self.genCombo.GetSelection()
             and max is not None \  
             and numGroups is not None:  
             self.clazz = ClassGenerator().GenerateRanges(min, max,  
                                                          numGroups, cgp, cgp2)  
         else:    
             self.clazz = None # for now  
171    
172          self.EndModal(wxID_OK)          genSel = self.genCombo.GetString(index)
173                                                                                            genPanel = self.genCombo.GetClientData(index)
174      def _OnCancel(self, event):  
175          self.EndModal(wxID_CANCEL)          propPanel = self.propPanel
176    
177            if genSel in (GENCOMBOSTR_UNIFORM, GENCOMBOSTR_UNIQUE):
178                numGroups = genPanel.GetNumGroups()
179    
180                index = self.propCombo.GetSelection()
181    
182                propSel = self.propCombo.GetString(index)
183                propPanel = self.propCombo.GetClientData(index)
184    
185                ramp = propPanel.GetRamp()
186    
187                if genSel == GENCOMBOSTR_UNIFORM:
188    
189                    min = genPanel.GetMin()
190                    max = genPanel.GetMax()
191    
192                    if min is not None \
193                        and max is not None \
194                        and numGroups is not None:
195    
196                        self.clazz = ClassGenerator().GenUnifromDistribution(
197                                    min, max, numGroups, ramp,
198                                    self.type == FIELDTYPE_INT)
199    
200                        self.parent._SetClassification(self.clazz)
201    
202                elif genSel == GENCOMBOSTR_UNIQUE:
203    
204                    list = genPanel.GetValueList()
205    
206                    if len(list) > 0 \
207                        and numGroups is not None:
208    
209                        self.clazz = ClassGenerator().GenSingletonsFromList(
210                                        list, numGroups, ramp)
211    
212                        self.parent._SetClassification(self.clazz)
213    
214        def _OnCloseBtn(self, event):
215            self.Close()
216    
217        def _OnGenTypeSelect(self, event):
218    
219            combo = event.GetEventObject()
220    
221            selIndex = combo.GetSelection()
222    
223            if self.genPanel is not None:
224                self.sizer.Show(self.genPanel, False)
225    
226  ID_RANGE_MIN = 4001          self.genPanel = combo.GetClientData(selIndex)
227  ID_RANGE_MAX = 4002          if self.genPanel is not None:
228  ID_RANGE_NGROUPS = 4003              self.sizer.Show(self.genPanel, True)
 ID_RANGE_STEP = 4004  
229    
230  class GenRangePanel(wxPanel):          self.sizer.SetSizeHints(self)
231            self.sizer.Layout()
232    
233      def __init__(self, parent, table, fieldName, fieldType):      def _OnPropTypeSelect(self, event):
234            combo = event.GetEventObject()
235    
236            selIndex = combo.GetSelection()
237            sel = combo.GetString(selIndex)
238    
239            if isinstance(self.propPanel, wxPanel):
240                self.sizer.Show(self.propPanel, False)
241    
242            self.propPanel = combo.GetClientData(selIndex)
243    
244            if isinstance(self.propPanel, wxPanel):
245                self.sizer.Show(self.propPanel, True)
246    
247            self.sizer.SetSizeHints(self)
248            self.sizer.Layout()
249    
250    
251    ID_UNIFORM_MIN = 4001
252    ID_UNIFORM_MAX = 4002
253    ID_UNIFORM_NGROUPS = 4003
254    ID_UNIFORM_STEP = 4004
255    ID_UNIFORM_RETRIEVE = 4005
256    
257    class GenUniformPanel(wxPanel):
258    
259        def __init__(self, parent, layer, fieldName, fieldType):
260          wxPanel.__init__(self, parent, -1)          wxPanel.__init__(self, parent, -1)
261    
262          self.parent = parent          self.parent = parent
263            self.layer = layer
264            self.fieldName = fieldName
265          self.fieldType = fieldType          self.fieldType = fieldType
266    
267          topSizer = wxStaticBoxSizer(wxStaticBox(self, -1, "Ranges"),          topSizer = wxStaticBoxSizer(wxStaticBox(self, -1, ""),
268                                      wxVERTICAL)                                      wxVERTICAL)
269    
270            #############
271    
272          sizer = wxBoxSizer(wxHORIZONTAL)          sizer = wxBoxSizer(wxHORIZONTAL)
273    
274          sizer.Add(wxStaticText(self, -1, _("Min:")), 0, wxALL, 4)          sizer.Add(wxStaticText(self, -1, _("Min:")), 0, wxALL, 4)
275          self.minCtrl = wxTextCtrl(self, ID_RANGE_MIN, style=wxTE_RIGHT)          self.minCtrl = wxTextCtrl(self, ID_UNIFORM_MIN, style=wxTE_RIGHT)
276          sizer.Add(self.minCtrl, 0, wxALL, 4)          sizer.Add(self.minCtrl, 1, wxALL, 4)
277          EVT_TEXT(self, ID_RANGE_MIN, self._OnRangeChanged)          EVT_TEXT(self, ID_UNIFORM_MIN, self._OnRangeChanged)
         self.goodTextColour = self.minCtrl.GetForegroundColour()  
         self.badTextColour = wxRED  
278    
279          sizer.Add(wxStaticText(self, -1, _("Max:")), 0, wxALL, 4)          sizer.Add(wxStaticText(self, -1, _("Max:")), 0, wxALL, 4)
280          self.maxCtrl = wxTextCtrl(self, ID_RANGE_MAX, style=wxTE_RIGHT)          self.maxCtrl = wxTextCtrl(self, ID_UNIFORM_MAX, style=wxTE_RIGHT)
281          sizer.Add(self.maxCtrl, 0, wxALL, 4)          sizer.Add(self.maxCtrl, 1, wxALL, 4)
282          EVT_TEXT(self, ID_RANGE_MAX, self._OnRangeChanged)          EVT_TEXT(self, ID_UNIFORM_MAX, self._OnRangeChanged)
283          topSizer.Add(sizer, 0, wxALL, 4)  
284            sizer.Add(wxButton(self, ID_UNIFORM_RETRIEVE, _("Retrieve From Table")),
285                0, wxALL, 4)
286            EVT_BUTTON(self, ID_UNIFORM_RETRIEVE, self._OnRetrieve)
287    
288            topSizer.Add(sizer, 1, wxGROW, 0)
289    
290            #############
291    
292          sizer = wxBoxSizer(wxHORIZONTAL)          sizer = wxBoxSizer(wxHORIZONTAL)
293    
294          sizer.Add(wxStaticText(self, -1, _("Number of Groups:")), 0, wxALL, 4)          sizer.Add(wxStaticText(self, -1, _("Number of Groups:")), 0, wxALL, 4)
295          self.numGroupsCtrl = wxSpinCtrl(self, ID_RANGE_NGROUPS, style=wxTE_RIGHT)          self.numGroupsCtrl = wxSpinCtrl(self, ID_UNIFORM_NGROUPS,
296          EVT_TEXT(self, ID_RANGE_NGROUPS, self._OnNumGroupsChanged)                                          style=wxTE_RIGHT)
297          EVT_SPINCTRL(self, ID_RANGE_NGROUPS, self._OnNumGroupsChanged)          EVT_TEXT(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)
298          sizer.Add(self.numGroupsCtrl, 0, wxALL, 4)          EVT_SPINCTRL(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)
299            sizer.Add(self.numGroupsCtrl, 1, wxALL, 4)
300    
301          sizer.Add(wxStaticText(self, -1, _("Stepping:")), 0, wxALL, 4)          sizer.Add(wxStaticText(self, -1, _("Stepping:")), 0, wxALL, 4)
302          self.stepCtrl = wxTextCtrl(self, ID_RANGE_STEP, style=wxTE_RIGHT)          self.stepCtrl = wxTextCtrl(self, ID_UNIFORM_STEP, style=wxTE_RIGHT)
303          EVT_TEXT(self, ID_RANGE_STEP, self._OnSteppingChanged)          EVT_TEXT(self, ID_UNIFORM_STEP, self._OnSteppingChanged)
304          sizer.Add(self.stepCtrl , 0, wxALL, 4)          sizer.Add(self.stepCtrl , 1, wxALL, 4)
305          topSizer.Add(sizer, 0, wxALL, 4)  
306            topSizer.Add(sizer, 1, wxGROW, 0)
307    
308            #############
309    
310          self.SetSizer(topSizer)          self.SetSizer(topSizer)
311          self.SetAutoLayout(True)          self.SetAutoLayout(True)
# Line 141  class GenRangePanel(wxPanel): Line 314  class GenRangePanel(wxPanel):
314          self.numGroupsChanging = False          self.numGroupsChanging = False
315          self.steppingChanging = False          self.steppingChanging = False
316    
317          self.numGroupsCtrl.SetRange(1, 100)          self.numGroupsCtrl.SetRange(1, sys.maxint)
318    
319          self.numGroupsCtrl.SetValue(1)          self.numGroupsCtrl.SetValue(1)
320          self.stepCtrl.SetValue("1")          self.stepCtrl.SetValue("1")
# Line 156  class GenRangePanel(wxPanel): Line 329  class GenRangePanel(wxPanel):
329                                              FIELDTYPE_INT,                                              FIELDTYPE_INT,
330                                              None)                                              None)
331    
         ##if self.__ValidateEntry(self.numGroupsCtrl, value, int):  
             #return value  
   
         #return None  
   
332      def GetStepping(self):      def GetStepping(self):
333          step = self.stepCtrl.GetValue()          step = self.stepCtrl.GetValue()
334          return self.__GetValidatedTypeEntry(self.stepCtrl,          return self.__GetValidatedTypeEntry(self.stepCtrl,
# Line 196  class GenRangePanel(wxPanel): Line 364  class GenRangePanel(wxPanel):
364          self.numGroupsCtrl.Enable(on)          self.numGroupsCtrl.Enable(on)
365          self.stepCtrl.Enable(on)          self.stepCtrl.Enable(on)
366    
         if on:  
             self.numGroupsCtrl.SetRange(1, abs(max - min) / 0.001)  
   
367          ngroups = self.GetNumGroups()          ngroups = self.GetNumGroups()
368    
369          if ngroups is not None  \          if ngroups is not None  \
# Line 206  class GenRangePanel(wxPanel): Line 371  class GenRangePanel(wxPanel):
371              and max is not None \              and max is not None \
372              and ngroups != 0:              and ngroups != 0:
373    
374              self.stepCtrl.SetValue(str((max - min) / ngroups))              #self.stepCtrl.SetValue(str((max - min) / ngroups))
375                self.stepCtrl.SetValue(str(self.__CalcStepping(min, max, ngroups)))
376                #self.numGroupsCtrl.SetValue(ngroups)
377    
378              self.parent.AllowGenerate(self.GetStepping() is not None)              self.parent.AllowGenerate(self.GetStepping() is not None)
379          else:          else:
# Line 227  class GenRangePanel(wxPanel): Line 394  class GenRangePanel(wxPanel):
394          min = self.GetMin()          min = self.GetMin()
395          max = self.GetMax()          max = self.GetMax()
396    
         if ngroups >= self.numGroupsCtrl.GetMax():  
             self.numGroupsCtrl.SetRange(1, ngroups + 1)  
   
397          if ngroups is not None  \          if ngroups is not None  \
398              and min is not None \              and min is not None \
399              and max is not None \              and max is not None \
# Line 243  class GenRangePanel(wxPanel): Line 407  class GenRangePanel(wxPanel):
407              # called steppingChanging tries to prevent the recursion.              # called steppingChanging tries to prevent the recursion.
408              #              #
409              self.numGroupsChanging = True              self.numGroupsChanging = True
410              self.stepCtrl.SetValue(str((max - min) / ngroups))  
411                self.stepCtrl.SetValue(str(self.__CalcStepping(min, max, ngroups)))
412    
413              self.parent.AllowGenerate(self.GetStepping() is not None)              self.parent.AllowGenerate(self.GetStepping() is not None)
414          else:          else:
# Line 268  class GenRangePanel(wxPanel): Line 433  class GenRangePanel(wxPanel):
433              # see note in _OnNumGroupsChanged              # see note in _OnNumGroupsChanged
434              #              #
435              self.steppingChanging = True              self.steppingChanging = True
436              n = int((max - min) / step)              self.numGroupsCtrl.SetValue(self.__CalcNumGroups(min, max, step))
             if n == 0:  
                 n = 1  
   
             self.numGroupsCtrl.SetValue(n)  
437    
438              self.parent.AllowGenerate(self.GetNumGroups() is not None)              self.parent.AllowGenerate(self.GetNumGroups() is not None)
439          else:          else:
440              self.parent.AllowGenerate(False)              self.parent.AllowGenerate(False)
441    
442        def _OnRetrieve(self, event):
443    
444            if self.layer.table is not None:
445                range = self.layer.table.field_range(self.fieldName)
446                self.minCtrl.SetValue(str(range[0][0]))
447                self.maxCtrl.SetValue(str(range[1][0]))
448    
449      def __GetValidatedTypeEntry(self, win, value, type, badValue = None):      def __GetValidatedTypeEntry(self, win, value, type, badValue = None):
450    
451          if type == FIELDTYPE_INT:          if type == FIELDTYPE_INT:
# Line 313  class GenRangePanel(wxPanel): Line 481  class GenRangePanel(wxPanel):
481          else:          else:
482              win.SetForegroundColour(wxRED)              win.SetForegroundColour(wxRED)
483    
484            win.Refresh()
485    
486          return valid          return valid
487    
488        def __CalcStepping(self, min, max, ngroups):
489            step = Str2Num(str((max - min) / float(ngroups)))
490            if self.fieldType == FIELDTYPE_INT:
491                step = int(step)
492    
493            return step
494    
495        def __CalcNumGroups(self, min, max, step):
496            n = int((max - min) / step)
497            if n == 0:
498                n = 1
499    
500            if self.fieldType == FIELDTYPE_INT and step == 1:
501                n += 1
502    
503            return n
504    
505    
506    ID_UNIQUE_RETRIEVE = 4001
507    ID_UNIQUE_USEALL = 4002
508    ID_UNIQUE_USE = 4003
509    ID_UNIQUE_DONTUSE = 4004
510    ID_UNIQUE_USENONE = 4005
511    ID_UNIQUE_SORTAVAIL = 4006
512    ID_UNIQUE_SORTUSE = 4007
513    ID_UNIQUE_REVAVAIL = 4008
514    ID_UNIQUE_REVUSE = 4009
515    
516    class GenUniquePanel(wxPanel):
517    
518        def __init__(self, parent, layer, fieldName, fieldType):
519            wxPanel.__init__(self, parent, -1)
520    
521            self.parent = parent
522            self.layer = layer
523            self.fieldName = fieldName
524            self.fieldType = fieldType
525    
526            topSizer = wxStaticBoxSizer(wxStaticBox(self, -1, ""),
527                                        wxVERTICAL)
528    
529    
530            #bsizer = wxBoxSizer(wxVERTICAL)
531            topSizer.Add(wxButton(self, ID_UNIQUE_RETRIEVE,
532                                _("Retrieve From Table")),
533                       0, wxALL | wxALIGN_RIGHT, 4)
534    
535            EVT_BUTTON(self, ID_UNIQUE_RETRIEVE, self._OnRetrieve)
536    
537            #topSizer.Add(bsizer, 0, wxALL, 4)
538    
539            sizer = wxBoxSizer(wxHORIZONTAL)
540    
541            self.dataList = []
542    
543            psizer = wxBoxSizer(wxVERTICAL)
544            self.list_avail = wxListCtrl(self, -1,
545                            style=wxLC_REPORT | wxLC_SINGLE_SEL)
546            self.list_avail.InsertColumn(0, "Available")
547            self.list_avail_data = []
548            psizer.Add(self.list_avail, 1, wxGROW, 0)
549    
550            bsizer = wxBoxSizer(wxHORIZONTAL)
551            bsizer.Add(wxButton(self, ID_UNIQUE_SORTAVAIL, _("Sort")))
552            EVT_BUTTON(self, ID_UNIQUE_SORTAVAIL, self._OnSortList)
553    
554            bsizer.Add(wxButton(self, ID_UNIQUE_REVAVAIL, _("Reverse")))
555            EVT_BUTTON(self, ID_UNIQUE_REVAVAIL, self._OnReverseList)
556    
557            psizer.Add(bsizer, 0, wxGROW, 0)
558            sizer.Add(psizer, 1, wxGROW, 0)
559    
560                    
561            bsizer = wxBoxSizer(wxVERTICAL)
562    
563            bmp = resource.GetBitmapResource(USEALL_BMP, wxBITMAP_TYPE_XPM)
564            bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USEALL, bmp),
565                       0, wxGROW | wxALL, 4)
566            bmp = resource.GetBitmapResource(USE_BMP, wxBITMAP_TYPE_XPM)
567            bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USE, bmp),
568                       0, wxGROW | wxALL, 4)
569            bmp = resource.GetBitmapResource(USENOT_BMP, wxBITMAP_TYPE_XPM)
570            bsizer.Add(wxBitmapButton(self, ID_UNIQUE_DONTUSE, bmp),
571                       0, wxGROW | wxALL, 4)
572            bmp = resource.GetBitmapResource(USENONE_BMP, wxBITMAP_TYPE_XPM)
573            bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USENONE, bmp),
574                       0, wxGROW | wxALL, 4)
575    
576            EVT_BUTTON(self, ID_UNIQUE_USEALL, self._OnUseAll)
577            EVT_BUTTON(self, ID_UNIQUE_USE, self._OnUse)
578            EVT_BUTTON(self, ID_UNIQUE_DONTUSE, self._OnDontUse)
579            EVT_BUTTON(self, ID_UNIQUE_USENONE, self._OnUseNone)
580    
581            sizer.Add(bsizer, 0, wxALL | wxALIGN_CENTER_VERTICAL, 4)
582    
583            psizer = wxBoxSizer(wxVERTICAL)
584            self.list_use = wxListCtrl(self, -1,
585                            style=wxLC_REPORT | wxLC_SINGLE_SEL)
586            self.list_use.InsertColumn(0, "Use")
587            self.list_use_data = []
588            psizer.Add(self.list_use, 1, wxGROW, 0)
589    
590            bsizer = wxBoxSizer(wxHORIZONTAL)
591            bsizer.Add(wxButton(self, ID_UNIQUE_SORTUSE, _("Sort")))
592            EVT_BUTTON(self, ID_UNIQUE_SORTUSE, self._OnSortList)
593    
594            bsizer.Add(wxButton(self, ID_UNIQUE_REVUSE, _("Reverse")))
595            EVT_BUTTON(self, ID_UNIQUE_REVUSE, self._OnReverseList)
596    
597            psizer.Add(bsizer, 0, wxGROW, 0)
598    
599            sizer.Add(psizer, 1, wxGROW, 0)
600    
 class GenSingletonPanel(wxPanel):  
601    
602      def __init__(self, parent, table, fieldName, fieldType):          topSizer.Add(sizer, 1, wxGROW, 0)
603    
604            self.SetSizer(topSizer)
605            self.SetAutoLayout(True)
606            topSizer.SetSizeHints(self)
607    
608            self.parent.AllowGenerate(False)
609    
610            self.mylist = ["Hallo", "Welt!", "Wie", "geht", "es", "dir", "?"]
611    
612        def GetNumGroups(self):
613            return self.list_use.GetItemCount()
614    
615        def GetValueList(self):
616            list = []
617            for i in range(self.list_use.GetItemCount()):
618                list.append(self.dataList[self.list_use.GetItemData(i)])
619            return list
620    
621        def _OnSortList(self, event):
622            id = event.GetId()
623    
624            if id == ID_UNIQUE_SORTUSE:
625                list = self.list_use
626            else:
627                list = self.list_avail
628    
629            list.SortItems(lambda i1, i2: cmp(self.dataList[i1],
630                                              self.dataList[i2]))
631    
632        def _OnReverseList(self, event):
633            id = event.GetId()
634    
635            if id == ID_UNIQUE_REVUSE:
636                list = self.list_use
637            else:
638                list = self.list_avail
639    
640            #
641            # always returning 1 reverses the list
642            #
643            list.SortItems(lambda i1, i2: 1)
644    
645        def _OnRetrieve(self, event):
646            self.list_use.DeleteAllItems()
647            self.list_use_data = []
648            self.list_avail.DeleteAllItems()
649            self.list_avail_data = []
650    
651            list = self.layer.table.GetUniqueValues(self.fieldName)
652            index = 0
653            for v in list:
654                self.dataList.append(v)
655                i = self.list_avail.InsertStringItem(index, str(v))
656                self.list_avail.SetItemData(index, i)
657    
658                self.list_avail_data.append(v)
659                index += 1
660    
661        def _OnUseAll(self, event):
662            for i in range(self.list_avail.GetItemCount()):
663                self.__MoveListItem(0, self.list_avail, self.list_use)
664    
665        def _OnUse(self, event):
666            self.__MoveSelectedItems(self.list_avail, self.list_use)
667    
668        def _OnDontUse(self, event):
669            self.__MoveSelectedItems(self.list_use, self.list_avail)
670    
671        def _OnUseNone(self, event):
672    
673            for i in range(self.list_use.GetItemCount()):
674                self.__MoveListItem(0, self.list_use, self.list_avail)
675    
676        def __MoveSelectedItems(self, list_src, list_dest):
677            while True:
678                index = list_src.GetNextItem(-1,
679                                             wxLIST_NEXT_ALL,
680                                             wxLIST_STATE_SELECTED)
681    
682                if index == -1:
683                    break
684    
685                self.__MoveListItem(index, list_src, list_dest)
686    
687    
688        def __MoveListItem(self, index, list_src, list_dest):
689    
690            item = list_src.GetItem(index)
691    
692            x = list_dest.InsertStringItem(
693                    list_dest.GetItemCount(),
694                    str(self.dataList[item.GetData()]))
695    
696            list_dest.SetItemData(x, item.GetData())
697    
698            list_src.DeleteItem(index)
699    
700    #   def _OnListSize(self, event):
701    #       list = event.GetEventObject()
702    
703    #       list.SetColumnWidth(0, event.GetSize().GetWidth())
704    #      
705    
706    ID_CUSTOMRAMP_COPYSTART = 4001
707    ID_CUSTOMRAMP_COPYEND = 4002
708    ID_CUSTOMRAMP_EDITSTART = 4003
709    ID_CUSTOMRAMP_EDITEND = 4004
710    ID_CUSTOMRAMP_SPROP = 4005
711    ID_CUSTOMRAMP_EPROP = 4006
712    
713    class CustomRampPanel(wxPanel):
714    
715        def __init__(self, parent, shapeType):
716          wxPanel.__init__(self, parent, -1)          wxPanel.__init__(self, parent, -1)
717    
718            topSizer = wxStaticBoxSizer(wxStaticBox(self, -1, ""), wxHORIZONTAL)
719    
720            bsizer = wxBoxSizer(wxVERTICAL)
721            bsizer.Add(wxStaticText(self, -1, _("Start:")), 0, wxALL | wxCENTER, 4)
722            self.startPropCtrl = classifier.ClassGroupPropertiesCtrl(
723                self, ID_CUSTOMRAMP_SPROP,
724                ClassGroupProperties(), shapeType,
725                style=wxSIMPLE_BORDER, size=(40, 20))
726            bsizer.Add(self.startPropCtrl, 1, wxGROW | wxALL | wxCENTER, 4)
727            bsizer.Add(wxButton(self, ID_CUSTOMRAMP_EDITSTART, _("Change")),
728                       0, wxGROW | wxALL | wxCENTER, 4)
729    
730            topSizer.Add(bsizer,
731                       1, wxALL \
732                          | wxSHAPED \
733                          | wxALIGN_CENTER_HORIZONTAL \
734                          | wxALIGN_CENTER_VERTICAL, \
735                       4)
736    
737            bmp = resource.GetBitmapResource(USE_BMP, wxBITMAP_TYPE_XPM)
738            bsizer = wxBoxSizer(wxVERTICAL)
739            bsizer.Add(wxBitmapButton(self, ID_CUSTOMRAMP_COPYSTART, bmp),
740                       0, wxGROW | wxALL, 4)
741            bmp = resource.GetBitmapResource(USENOT_BMP, wxBITMAP_TYPE_XPM)
742            bsizer.Add(wxBitmapButton(self, ID_CUSTOMRAMP_COPYEND, bmp),
743                       0, wxGROW | wxALL, 4)
744    
745            topSizer.Add(bsizer,
746                       0, wxALL \
747                          | wxALIGN_CENTER_HORIZONTAL \
748                          | wxALIGN_CENTER_VERTICAL,
749                       4)
750    
751            bsizer = wxBoxSizer(wxVERTICAL)
752            bsizer.Add(wxStaticText(self, -1, _("End:")), 0, wxALL | wxCENTER, 4)
753            self.endPropCtrl = classifier.ClassGroupPropertiesCtrl(
754                self, ID_CUSTOMRAMP_EPROP,
755                ClassGroupProperties(), shapeType,
756                style=wxSIMPLE_BORDER, size=(40, 20))
757            bsizer.Add(self.endPropCtrl, 1, wxGROW | wxALL | wxCENTER, 4)
758            bsizer.Add(wxButton(self, ID_CUSTOMRAMP_EDITEND, _("Change")),
759                       0, wxGROW | wxALL | wxCENTER, 4)
760    
761            topSizer.Add(bsizer,
762                       1, wxALL \
763                          | wxSHAPED \
764                          | wxALIGN_RIGHT \
765                          | wxALIGN_CENTER_HORIZONTAL \
766                          | wxALIGN_CENTER_VERTICAL,
767                       4)
768    
769            EVT_BUTTON(self, ID_CUSTOMRAMP_COPYSTART, self._OnCopyStart)
770            EVT_BUTTON(self, ID_CUSTOMRAMP_COPYEND, self._OnCopyEnd)
771            EVT_BUTTON(self, ID_CUSTOMRAMP_EDITSTART, self._OnEditStart)
772            EVT_BUTTON(self, ID_CUSTOMRAMP_EDITEND, self._OnEditEnd)
773    
774            self.SetSizer(topSizer)
775            self.SetAutoLayout(True)
776            topSizer.SetSizeHints(self)
777    
778        def GetRamp(self):
779            return CustomRamp(self.startPropCtrl.GetProperties(),
780                              self.endPropCtrl.GetProperties())
781    
782        def _OnCopyStart(self, event):
783            self.endPropCtrl.SetProperties(self.startPropCtrl.GetProperties())
784    
785        def _OnCopyEnd(self, event):
786            self.startPropCtrl.SetProperties(self.endPropCtrl.GetProperties())
787    
788        def _OnEditStart(self, event):
789            self.startPropCtrl.DoEdit()
790    
791        def _OnEditEnd(self, event):
792            self.endPropCtrl.DoEdit()
793    
794  class ClassGenerator:  class ClassGenerator:
795    
796      def GenerateSingletons(self, list, numGroups, prop1, prop2):      def GenSingletonsFromList(self, list, numGroups, ramp):
797          """Generate a new classification consisting solely of singletons.          """Generate a new classification consisting solely of singletons.
798    
799          The resulting classification will consist of at most 'numGroups'          The resulting classification will consist of at most 'numGroups'
# Line 346  class ClassGenerator: Line 815  class ClassGenerator:
815          clazz = Classification()          clazz = Classification()
816          if numGroups == 0: return clazz          if numGroups == 0: return clazz
817    
818          for value, prop in zip(list, PropertyRamp(numGroups, prop1, prop2)):          ramp.SetNumGroups(numGroups)
819    
820            for value, prop in zip(list, ramp):
821              clazz.AppendGroup(ClassGroupSingleton(value, prop))              clazz.AppendGroup(ClassGroupSingleton(value, prop))
822    
823          return clazz          return clazz
824    
825      def GenerateRanges(self, min, max, numGroups, prop1, prop2):      def GenSingletons(self, min, max, numGroups, ramp):
826    
827            clazz = Classification()
828    
829            #step = int((max - min) / float(numGroups))
830            step = int(Str2Num(str((max - min + 1) / float(numGroups))))
831    
832            if numGroups > 0:
833                cur_value = min
834    
835                ramp.SetNumGroups(numGroups)
836    
837                for prop in ramp:
838                    clazz.AppendGroup(
839                        ClassGroupSingleton(
840                            Str2Num(str(cur_value)),
841                            prop))
842                    cur_value += step
843    
844            return clazz
845    
846        def GenUnifromDistribution(self, min, max, numGroups,
847                                   ramp, intStep = False):
848            """Generate a classification with numGroups range groups
849            each with the same interval.
850    
851            intStep -- force the calculated stepping to an integer.
852                       Useful if the values are integers but the
853                       number of groups specified doesn't evenly
854                       divide (max - min).
855            """
856    
857          clazz = Classification()          clazz = Classification()
858          if numGroups == 0: return clazz          if numGroups == 0: return clazz
859    
860          step = (max - min) / float(numGroups)          ramp.SetNumGroups(numGroups)
861    
862            step = Str2Num(str((max - min) / float(numGroups)))
863    
864            if intStep:
865                step = int(step)
866    
867          cur_min = min          cur_min = min
868          cur_max = cur_min + step          cur_max = cur_min + step
869    
870          i = 0          i = 0
871          for prop in PropertyRamp(numGroups, prop1, prop2):          for prop in ramp:
872    
873              if i == (numGroups - 1):              if i == (numGroups - 1):
874                  cur_max = max                  cur_max = max
875    
876              # this check guards against rounding issues              # this check guards against rounding issues
877              if cur_min != cur_max:              if cur_min != cur_max:
878                  clazz.AppendGroup(ClassGroupRange(cur_min, cur_max, prop))                  clazz.AppendGroup(
879                        ClassGroupRange(
880                            Str2Num(str(cur_min)),
881                            Str2Num(str(cur_max)),
882                            prop))
883    
884              cur_min = cur_max              cur_min = cur_max
885              cur_max += step              cur_max += step
# Line 377  class ClassGenerator: Line 887  class ClassGenerator:
887    
888          return clazz          return clazz
889    
890  class PropertyRamp:  CLR  = 0
891    STEP = 1
892    class CustomRamp:
893    
894        def __init__(self, prop1, prop2):
895            self.prop1 = prop1
896            self.prop2 = prop2
897    
898            self.count = 0
899    
900        def __iter__(self):
901            return self
902    
903        def GetRamp(self):
904            return self
905    
906        def SetNumGroups(self, num):
907    
908      def __init__(self, num, prop1, prop2):          if num <= 0:
909                return False
910    
911          self.count = int(num)          self.count = int(num)
912          num = float(num)          num = float(num)
913    
914            prop1 = self.prop1
915            prop2 = self.prop2
916    
917          self.lineColor = prop1.GetLineColor()          clr = prop1.GetLineColor()
         self.fillColor = prop1.GetFill()  
         self.lineWidth = prop1.GetLineWidth()  
   
918          lineColor2 = prop2.GetLineColor()          lineColor2 = prop2.GetLineColor()
919          fillColor2 = prop2.GetFill()          
920          lineWidth2 = prop2.GetLineWidth()          self.noLine = clr is not Color.Transparent \
921                            and lineColor2 is not Color.Transparent
922    
         self.line_redStep   = (lineColor2.red   - self.lineColor.red)   / num  
         self.line_greenStep = (lineColor2.green - self.lineColor.green) / num  
         self.line_blueStep  = (lineColor2.blue  - self.lineColor.blue)  / num  
   
         self.line_widthStep = (lineWidth2 - self.lineWidth) / num  
   
         self.fill_redStep   = (fillColor2.red   - self.fillColor.red)   / num  
         self.fill_greenStep = (fillColor2.green - self.fillColor.green) / num  
         self.fill_blueStep  = (fillColor2.blue  - self.fillColor.blue)  / num  
923    
924      def __iter__(self):          self.lineInfo = self.__GetColorInfo(prop1.GetLineColor(),
925          return self                                              prop2.GetLineColor(),
926                                                num)
927    
928            self.fillInfo = self.__GetColorInfo(prop1.GetFill(),
929                                                prop2.GetFill(),
930                                                num)
931    
932            self.lineWidth = prop1.GetLineWidth()
933            self.lineWidthStep = (prop2.GetLineWidth() - self.lineWidth) / num
934    
935            return True
936    
937      def next(self):      def next(self):
938          if self.count == 0:          if self.count == 0:
939              raise StopIteration              raise StopIteration
940    
941          prop = ClassGroupProperties()          prop = ClassGroupProperties()
942          prop.SetFill(self.fillColor)  
943          prop.SetLineColor(self.lineColor)          if self.lineInfo is None:
944                prop.SetLineColor(Color.Transparent)
945            else:
946                prop.SetLineColor(Color(self.lineInfo[CLR][0] / 255,
947                                        self.lineInfo[CLR][1] / 255,
948                                        self.lineInfo[CLR][2] / 255))
949    
950                self.lineInfo[CLR][0] += self.lineInfo[STEP][0]
951                self.lineInfo[CLR][1] += self.lineInfo[STEP][1]
952                self.lineInfo[CLR][2] += self.lineInfo[STEP][2]
953    
954            if self.fillInfo is None:
955                prop.SetFill(Color.Transparent)
956            else:
957                prop.SetFill(Color(self.fillInfo[CLR][0] / 255,
958                                self.fillInfo[CLR][1] / 255,
959                                self.fillInfo[CLR][2] / 255))
960    
961                self.fillInfo[CLR][0] += self.fillInfo[STEP][0]
962                self.fillInfo[CLR][1] += self.fillInfo[STEP][1]
963                self.fillInfo[CLR][2] += self.fillInfo[STEP][2]
964    
965    
966          prop.SetLineWidth(int(self.lineWidth))          prop.SetLineWidth(int(self.lineWidth))
967            self.lineWidth        += self.lineWidthStep
968    
969            self.count -= 1
970    
971            return prop
972    
973        def __GetColorInfo(self, color1, color2, numGroups):
974    
975            if color1 is Color.Transparent and color2 is Color.Transparent:
976                #
977                # returning early
978                #
979                return None
980            elif color1 is not Color.Transparent and color2 is Color.Transparent:
981                color = [color1.red   * 255,
982                         color1.green * 255,
983                         color1.blue  * 255]
984                step = (0, 0, 0)
985            elif color1 is Color.Transparent and color2 is not Color.Transparent:
986                color = [color2.red   * 255,
987                         color2.green * 255,
988                         color2.blue  * 255]
989                step = (0, 0, 0)
990            else:
991                color = [color1.red   * 255,
992                         color1.green * 255,
993                         color1.blue  * 255]
994                step = ((color2.red   * 255 - color1.red   * 255)   / numGroups,
995                        (color2.green * 255 - color1.green * 255) / numGroups,
996                        (color2.blue  * 255 - color1.blue  * 255)  / numGroups)
997    
998    
999            return (color, step)
1000    
1001    class MonochromaticRamp(CustomRamp):
1002        def __init__(self, start, end):
1003            sp = ClassGroupProperties()
1004            sp.SetLineColor(start)
1005            sp.SetFill(start)
1006    
1007            ep = ClassGroupProperties()
1008            ep.SetLineColor(end)
1009            ep.SetFill(end)
1010    
1011            CustomRamp.__init__(self, sp, ep)
1012    
1013    class GreyRamp(MonochromaticRamp):
1014        def __init__(self):
1015            MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(0, 0, 0))
1016    
1017    class RedRamp(MonochromaticRamp):
1018        def __init__(self):
1019            MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(.8, 0, 0))
1020    
1021    class GreenRamp(MonochromaticRamp):
1022        def __init__(self):
1023            MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(0, .8, 0))
1024    
1025    class BlueRamp(MonochromaticRamp):
1026        def __init__(self):
1027            MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(0, 0, .8))
1028    
1029    class HotToColdRamp:
1030    
1031        def __iter__(self):
1032            return self
1033                    
1034          self.lineColor.red   += self.line_redStep      def GetRamp(self):
1035          self.lineColor.green += self.line_greenStep          return self
         self.lineColor.blue  += self.line_blueStep  
   
         self.fillColor.red   += self.fill_redStep  
         self.fillColor.green += self.fill_greenStep  
         self.fillColor.blue  += self.fill_blueStep  
1036    
1037          self.lineWidth       += self.line_widthStep      def SetNumGroups(self, num):
1038            if num < 0:
1039                return False
1040    
1041          self.count -= 1          self.num = float(num)
1042            self.index = 0
1043    
1044            return True
1045    
1046        def next(self):
1047            if self.index == self.num:
1048                raise StopIteration
1049    
1050            clr = [1.0, 1.0, 1.0]
1051    
1052            if self.index < (.25 * self.num):
1053                clr[0] = 0
1054                clr[1] = 4 * self.index / self.num
1055            elif self.index < (.5 * self.num):
1056                clr[0] = 0
1057                clr[2] = 1 + 4 * (.25 * self.num - self.index) / self.num
1058            elif self.index < (.75 * self.num):
1059                clr[0] = 4 * (self.index - .5 * self.num) / self.num
1060                clr[2] = 0
1061            else:
1062                clr[1] = 1 + 4 * (.75 * self.num - self.index) / self.num
1063                clr[2] = 0
1064    
1065            self.index += 1
1066    
1067            prop = ClassGroupProperties()
1068            prop.SetLineColor(Color(clr[0], clr[1], clr[2]))
1069            prop.SetFill(Color(clr[0], clr[1], clr[2]))
1070    
1071          return prop          return prop
1072    
1073    #class Colors16Ramp:
1074    #
1075        #def __iter__(self):
1076            #return self
1077    #
1078        #def GetRamp(self):
1079            #return self
1080    #
1081        #def SetNumGroups(self, num):
1082            #if num < 0:
1083                #return False
1084    #
1085            #self.index = 0
1086    #
1087            #return True
1088    
1089        

Legend:
Removed from v.614  
changed lines
  Added in v.677

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26