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

Legend:
Removed from v.620  
changed lines
  Added in v.711

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26