/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/UI/classgen.py
ViewVC logotype

Annotation of /branches/WIP-pyshapelib-bramz/Thuban/UI/classgen.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 711 - (hide annotations)
Wed Apr 23 08:46:23 2003 UTC (21 years, 10 months ago) by jonathan
Original Path: trunk/thuban/Thuban/UI/classgen.py
File MIME type: text/x-python
File size: 33488 byte(s)
(ClassGenDialog.__init__): Use a wxChoice control instead of a wxComboBox.
        wxChoice controls do not generate events as the uses highlights
        possible choices which fixes problems with resizing the dialog when
        the use selects an option.

1 jonathan 607 # Copyright (c) 2003 by Intevation GmbH
2     # Authors:
3     # Jonathan Coles <[email protected]>
4     #
5     # This program is free software under the GPL (>=v2)
6     # Read the file COPYING coming with Thuban for details.
7    
8 jonathan 677 import sys
9    
10 jonathan 607 from Thuban import _
11    
12     from wxPython.wx import *
13    
14     from Thuban.Model.classification import Classification, ClassGroupRange, \
15     ClassGroupSingleton, ClassGroupProperties
16    
17     from Thuban.Model.table import Table, FIELDTYPE_INT, FIELDTYPE_DOUBLE, \
18     FIELDTYPE_STRING
19    
20     from Thuban.Model.color import Color
21    
22 jonathan 629 import classifier
23    
24 jonathan 649 import resource
25    
26 jonathan 629 from Thuban.common import Str2Num
27    
28 jonathan 607 ID_CLASSGEN_GEN = 4001
29 jonathan 629 ID_CLASSGEN_CLOSE = 4002
30 jonathan 635 ID_CLASSGEN_GENCOMBO = 4007
31     ID_CLASSGEN_PROPCOMBO = 4008
32 jonathan 607
33 jonathan 649 USEALL_BMP = "group_use_all"
34     USE_BMP = "group_use"
35     USENOT_BMP = "group_use_not"
36     USENONE_BMP = "group_use_none"
37    
38 jonathan 635 GENCOMBOSTR_UNIFORM = _("Uniform Distribution")
39     GENCOMBOSTR_UNIQUE = _("Unique Values")
40 jonathan 629
41 jonathan 649 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 jonathan 635
48 jonathan 607 class ClassGenDialog(wxDialog):
49    
50 jonathan 629 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 jonathan 607 wxDialog.__init__(self, parent, -1, _("Generate Classification"),
57     style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
58    
59 jonathan 629 self.parent = parent
60 jonathan 607 self.clazz = None
61    
62 jonathan 629 self.type, name, width, prec = layer.table.field_info_by_name(fieldName)
63 jonathan 607
64 jonathan 629 #############
65     # we need to create genButton first because when we create the
66     # panels they will call AllowGenerate() which uses genButton.
67     #
68 jonathan 607 buttonSizer = wxBoxSizer(wxHORIZONTAL)
69     self.genButton = wxButton(self, ID_CLASSGEN_GEN, _("Generate"))
70 jonathan 629
71 jonathan 607 buttonSizer.Add(self.genButton, 0, wxALL, 4)
72     buttonSizer.Add(60, 20, 0, wxALL, 4)
73 jonathan 629 buttonSizer.Add(wxButton(self, ID_CLASSGEN_CLOSE, _("Close")),
74 jonathan 607 0, wxALL, 4)
75    
76 jonathan 629 #############
77 jonathan 607
78 jonathan 629 sizer = wxBoxSizer(wxVERTICAL)
79    
80     sizer.Add(wxStaticText(self, -1, _("Field: %s") % fieldName),
81     0, wxALL, 4)
82     sizer.Add(wxStaticText(
83     self, -1,
84 jonathan 649 _("Data Type: %s") % classifier.Classifier.type2string[self.type]),
85 jonathan 629 0, wxALL, 4)
86    
87     psizer = wxBoxSizer(wxHORIZONTAL)
88 jonathan 635 psizer.Add(wxStaticText(self, -1, _("Generate:")),
89 jonathan 629 0, wxALIGN_CENTER_VERTICAL, 0)
90    
91 jonathan 711 self.genCombo = wxChoice(self, ID_CLASSGEN_GENCOMBO)
92 jonathan 629 psizer.Add(self.genCombo, 1, wxALL | wxGROW, 4)
93 jonathan 711 EVT_CHOICE(self, ID_CLASSGEN_GENCOMBO, self._OnGenTypeSelect)
94 jonathan 629
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 jonathan 635 self.genCombo.Append(GENCOMBOSTR_UNIQUE, panel)
103 jonathan 629 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 jonathan 635 self.genCombo.Append(GENCOMBOSTR_UNIFORM, panel)
110 jonathan 660 sizer.Add(panel, 1, wxGROW | wxALL, 4)
111 jonathan 629 sizer.Show(panel, False)
112    
113 jonathan 660 self.genCombo.SetSelection(0)
114    
115 jonathan 629 #############
116    
117 jonathan 635 psizer = wxBoxSizer(wxHORIZONTAL)
118 jonathan 660 psizer.Add(wxStaticText(self, -1, _("Color Scheme:")),
119 jonathan 635 0, wxALIGN_CENTER_VERTICAL, 0)
120 jonathan 629
121 jonathan 711 self.propCombo = wxChoice(self, ID_CLASSGEN_PROPCOMBO)
122 jonathan 635 psizer.Add(self.propCombo, 1, wxALL | wxGROW, 4)
123 jonathan 711 EVT_CHOICE(self, ID_CLASSGEN_PROPCOMBO, self._OnPropTypeSelect)
124 jonathan 635 sizer.Add(psizer, 0, wxALL | wxGROW, 4)
125 jonathan 629
126 jonathan 635 #############
127 jonathan 629
128 jonathan 635 self.propPanel = None
129     panel = CustomRampPanel(self, layer.ShapeType())
130 jonathan 629 sizer.Add(panel, 1, wxALL | wxGROW, 4)
131 jonathan 635 sizer.Show(panel, False)
132 jonathan 629
133 jonathan 649 self.propCombo.Append(PROPCOMBOSTR_GREY, GreyRamp())
134 jonathan 635 self.propCombo.Append(PROPCOMBOSTR_RED, RedRamp())
135     self.propCombo.Append(PROPCOMBOSTR_GREEN, GreenRamp())
136     self.propCombo.Append(PROPCOMBOSTR_BLUE, BlueRamp())
137 jonathan 649 self.propCombo.Append(PROPCOMBOSTR_HOT2COLD, HotToColdRamp())
138 jonathan 635 self.propCombo.Append(PROPCOMBOSTR_CUSTOM, panel)
139    
140 jonathan 660 self.propCombo.SetSelection(0)
141 jonathan 635
142    
143 jonathan 629 #############
144    
145 jonathan 607 sizer.Add(buttonSizer, 0,
146     wxALL | wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL, 4)
147    
148 jonathan 629
149 jonathan 607 self.SetSizer(sizer)
150     self.SetAutoLayout(True)
151     sizer.SetSizeHints(self)
152    
153 jonathan 629 self.sizer = sizer
154    
155 jonathan 607 EVT_BUTTON(self, ID_CLASSGEN_GEN, self._OnGenerate)
156 jonathan 629 EVT_BUTTON(self, ID_CLASSGEN_CLOSE, self._OnCloseBtn)
157 jonathan 607
158     def GetClassification(self):
159     return self.clazz
160    
161     def AllowGenerate(self, on):
162 jonathan 629 pass #self.genButton.Enable(on)
163 jonathan 607
164     def _OnGenerate(self, event):
165    
166 jonathan 635 index = self.genCombo.GetSelection()
167 jonathan 607
168 jonathan 635 genSel = self.genCombo.GetString(index)
169     genPanel = self.genCombo.GetClientData(index)
170    
171 jonathan 629 propPanel = self.propPanel
172 jonathan 607
173 jonathan 635 if genSel in (GENCOMBOSTR_UNIFORM, GENCOMBOSTR_UNIQUE):
174 jonathan 629 numGroups = genPanel.GetNumGroups()
175 jonathan 607
176 jonathan 635 index = self.propCombo.GetSelection()
177 jonathan 629
178 jonathan 635 propSel = self.propCombo.GetString(index)
179     propPanel = self.propCombo.GetClientData(index)
180 jonathan 629
181 jonathan 635 ramp = propPanel.GetRamp()
182 jonathan 629
183 jonathan 635 if genSel == GENCOMBOSTR_UNIFORM:
184 jonathan 629
185 jonathan 635 min = genPanel.GetMin()
186     max = genPanel.GetMax()
187 jonathan 629
188 jonathan 635 if min is not None \
189     and max is not None \
190     and numGroups is not None:
191 jonathan 629
192 jonathan 635 self.clazz = ClassGenerator().GenUnifromDistribution(
193     min, max, numGroups, ramp,
194     self.type == FIELDTYPE_INT)
195 jonathan 629
196 jonathan 635 self.parent._SetClassification(self.clazz)
197 jonathan 629
198 jonathan 635 elif genSel == GENCOMBOSTR_UNIQUE:
199 jonathan 629
200 jonathan 635 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 jonathan 629 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     if self.genPanel is not None:
220     self.sizer.Show(self.genPanel, False)
221    
222     self.genPanel = combo.GetClientData(selIndex)
223     if self.genPanel is not None:
224     self.sizer.Show(self.genPanel, True)
225    
226     self.sizer.SetSizeHints(self)
227     self.sizer.Layout()
228    
229 jonathan 635 def _OnPropTypeSelect(self, event):
230     combo = event.GetEventObject()
231 jonathan 629
232 jonathan 635 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 jonathan 629 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 jonathan 607 wxPanel.__init__(self, parent, -1)
257    
258     self.parent = parent
259 jonathan 629 self.layer = layer
260     self.fieldName = fieldName
261 jonathan 607 self.fieldType = fieldType
262    
263 jonathan 629 topSizer = wxStaticBoxSizer(wxStaticBox(self, -1, ""),
264 jonathan 607 wxVERTICAL)
265    
266 jonathan 629 #############
267    
268 jonathan 607 sizer = wxBoxSizer(wxHORIZONTAL)
269    
270     sizer.Add(wxStaticText(self, -1, _("Min:")), 0, wxALL, 4)
271 jonathan 629 self.minCtrl = wxTextCtrl(self, ID_UNIFORM_MIN, style=wxTE_RIGHT)
272     sizer.Add(self.minCtrl, 1, wxALL, 4)
273     EVT_TEXT(self, ID_UNIFORM_MIN, self._OnRangeChanged)
274 jonathan 607
275     sizer.Add(wxStaticText(self, -1, _("Max:")), 0, wxALL, 4)
276 jonathan 629 self.maxCtrl = wxTextCtrl(self, ID_UNIFORM_MAX, style=wxTE_RIGHT)
277     sizer.Add(self.maxCtrl, 1, wxALL, 4)
278     EVT_TEXT(self, ID_UNIFORM_MAX, self._OnRangeChanged)
279 jonathan 607
280 jonathan 629 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 jonathan 607 sizer = wxBoxSizer(wxHORIZONTAL)
289 jonathan 629
290 jonathan 607 sizer.Add(wxStaticText(self, -1, _("Number of Groups:")), 0, wxALL, 4)
291 jonathan 660 self.numGroupsCtrl = wxSpinCtrl(self, ID_UNIFORM_NGROUPS,
292     style=wxTE_RIGHT)
293 jonathan 629 EVT_TEXT(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)
294     EVT_SPINCTRL(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)
295     sizer.Add(self.numGroupsCtrl, 1, wxALL, 4)
296 jonathan 607
297     sizer.Add(wxStaticText(self, -1, _("Stepping:")), 0, wxALL, 4)
298 jonathan 629 self.stepCtrl = wxTextCtrl(self, ID_UNIFORM_STEP, style=wxTE_RIGHT)
299     EVT_TEXT(self, ID_UNIFORM_STEP, self._OnSteppingChanged)
300     sizer.Add(self.stepCtrl , 1, wxALL, 4)
301 jonathan 607
302 jonathan 629 topSizer.Add(sizer, 1, wxGROW, 0)
303    
304     #############
305    
306 jonathan 607 self.SetSizer(topSizer)
307     self.SetAutoLayout(True)
308     topSizer.SetSizeHints(self)
309    
310     self.numGroupsChanging = False
311     self.steppingChanging = False
312    
313 jonathan 677 self.numGroupsCtrl.SetRange(1, sys.maxint)
314 jonathan 607
315     self.numGroupsCtrl.SetValue(1)
316     self.stepCtrl.SetValue("1")
317     self.maxCtrl.SetValue("0")
318     self.minCtrl.SetValue("0")
319     self.minCtrl.SetFocus()
320    
321     def GetNumGroups(self):
322     value = self.numGroupsCtrl.GetValue()
323     return self.__GetValidatedTypeEntry(self.numGroupsCtrl,
324     value,
325     FIELDTYPE_INT,
326     None)
327    
328     def GetStepping(self):
329     step = self.stepCtrl.GetValue()
330     return self.__GetValidatedTypeEntry(self.stepCtrl,
331     step,
332     self.fieldType,
333     0)
334    
335     def GetMin(self):
336     min = self.minCtrl.GetValue()
337     max = self.maxCtrl.GetValue()
338     return self.__GetValidatedTypeEntry(self.minCtrl,
339     min,
340     self.fieldType,
341     max)
342    
343     def GetMax(self):
344     min = self.minCtrl.GetValue()
345     max = self.maxCtrl.GetValue()
346     return self.__GetValidatedTypeEntry(self.maxCtrl,
347     max,
348     self.fieldType,
349     min)
350    
351     def _OnRangeChanged(self, event):
352    
353     hasFocus = wxWindow_FindFocus() == event.GetEventObject()
354     min = self.GetMin()
355     max = self.GetMax()
356    
357     on = min is not None \
358     and max is not None
359    
360     self.numGroupsCtrl.Enable(on)
361     self.stepCtrl.Enable(on)
362    
363     ngroups = self.GetNumGroups()
364    
365     if ngroups is not None \
366     and min is not None \
367     and max is not None \
368     and ngroups != 0:
369    
370 jonathan 629 #self.stepCtrl.SetValue(str((max - min) / ngroups))
371     self.stepCtrl.SetValue(str(self.__CalcStepping(min, max, ngroups)))
372     #self.numGroupsCtrl.SetValue(ngroups)
373 jonathan 607
374     self.parent.AllowGenerate(self.GetStepping() is not None)
375     else:
376     self.parent.AllowGenerate(False)
377    
378    
379     if hasFocus:
380     event.GetEventObject().SetFocus()
381    
382     def _OnNumGroupsChanged(self, event):
383     if self.steppingChanging:
384     self.steppingChanging = False
385     return
386    
387    
388     obj = event.GetEventObject()
389     ngroups = self.GetNumGroups()
390     min = self.GetMin()
391     max = self.GetMax()
392    
393     if ngroups is not None \
394     and min is not None \
395     and max is not None \
396     and ngroups != 0:
397    
398     #
399     # changing the value in the stepCtrl sends an event
400     # that the control is changing, at which point
401     # we try to update the numGroupsCtrl. This causes
402     # an infinite recursion. This flag and the one
403     # called steppingChanging tries to prevent the recursion.
404     #
405     self.numGroupsChanging = True
406    
407 jonathan 629 self.stepCtrl.SetValue(str(self.__CalcStepping(min, max, ngroups)))
408    
409 jonathan 607 self.parent.AllowGenerate(self.GetStepping() is not None)
410     else:
411     self.parent.AllowGenerate(False)
412    
413    
414     def _OnSteppingChanged(self, event):
415     if self.numGroupsChanging:
416     self.numGroupsChanging = False
417     return
418    
419     step = self.GetStepping()
420     min = self.GetMin()
421     max = self.GetMax()
422    
423     if step is not None \
424     and min is not None \
425     and max is not None \
426     and step != 0:
427    
428     #
429     # see note in _OnNumGroupsChanged
430     #
431     self.steppingChanging = True
432 jonathan 629 self.numGroupsCtrl.SetValue(self.__CalcNumGroups(min, max, step))
433 jonathan 607
434     self.parent.AllowGenerate(self.GetNumGroups() is not None)
435     else:
436     self.parent.AllowGenerate(False)
437    
438 jonathan 629 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 jonathan 607 def __GetValidatedTypeEntry(self, win, value, type, badValue = None):
446    
447     if type == FIELDTYPE_INT:
448     func = int
449     elif type == FIELDTYPE_DOUBLE:
450     func = float
451     elif type == FIELDTYPE_STRING:
452     func = str
453     else:
454     assert False, "Unsupported FIELDTYPE"
455     pass
456    
457     if self.__ValidateEntry(win, value, func, badValue):
458     return func(value)
459    
460     return None
461    
462     def __ValidateEntry(self, win, value, test, badValue = None):
463    
464     valid = value != ""
465    
466     try:
467     if valid:
468     value = test(value)
469    
470     if badValue is not None:
471     valid = value != test(badValue)
472     except ValueError:
473     valid = False
474    
475     if valid:
476     win.SetForegroundColour(wxBLACK)
477     else:
478     win.SetForegroundColour(wxRED)
479    
480 jonathan 620 win.Refresh()
481    
482 jonathan 607 return valid
483 jonathan 629
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 jonathan 649 ID_UNIQUE_REVAVAIL = 4008
510     ID_UNIQUE_REVUSE = 4009
511 jonathan 629
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 jonathan 649 #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 jonathan 629 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 jonathan 649 bsizer = wxBoxSizer(wxHORIZONTAL)
547     bsizer.Add(wxButton(self, ID_UNIQUE_SORTAVAIL, _("Sort")))
548     EVT_BUTTON(self, ID_UNIQUE_SORTAVAIL, self._OnSortList)
549 jonathan 629
550 jonathan 649 bsizer.Add(wxButton(self, ID_UNIQUE_REVAVAIL, _("Reverse")))
551     EVT_BUTTON(self, ID_UNIQUE_REVAVAIL, self._OnReverseList)
552 jonathan 629
553 jonathan 649 psizer.Add(bsizer, 0, wxGROW, 0)
554 jonathan 629 sizer.Add(psizer, 1, wxGROW, 0)
555    
556 jonathan 607
557 jonathan 629 bsizer = wxBoxSizer(wxVERTICAL)
558 jonathan 649
559     bmp = resource.GetBitmapResource(USEALL_BMP, wxBITMAP_TYPE_XPM)
560     bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USEALL, bmp),
561 jonathan 629 0, wxGROW | wxALL, 4)
562 jonathan 649 bmp = resource.GetBitmapResource(USE_BMP, wxBITMAP_TYPE_XPM)
563     bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USE, bmp),
564 jonathan 629 0, wxGROW | wxALL, 4)
565 jonathan 649 bmp = resource.GetBitmapResource(USENOT_BMP, wxBITMAP_TYPE_XPM)
566     bsizer.Add(wxBitmapButton(self, ID_UNIQUE_DONTUSE, bmp),
567 jonathan 629 0, wxGROW | wxALL, 4)
568 jonathan 649 bmp = resource.GetBitmapResource(USENONE_BMP, wxBITMAP_TYPE_XPM)
569     bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USENONE, bmp),
570 jonathan 629 0, wxGROW | wxALL, 4)
571 jonathan 607
572 jonathan 629 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 jonathan 607
577 jonathan 629 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 jonathan 649 bsizer = wxBoxSizer(wxHORIZONTAL)
587     bsizer.Add(wxButton(self, ID_UNIQUE_SORTUSE, _("Sort")))
588     EVT_BUTTON(self, ID_UNIQUE_SORTUSE, self._OnSortList)
589 jonathan 629
590 jonathan 649 bsizer.Add(wxButton(self, ID_UNIQUE_REVUSE, _("Reverse")))
591     EVT_BUTTON(self, ID_UNIQUE_REVUSE, self._OnReverseList)
592 jonathan 629
593 jonathan 649 psizer.Add(bsizer, 0, wxGROW, 0)
594    
595 jonathan 629 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 jonathan 649 def _OnSortList(self, event):
618     id = event.GetId()
619 jonathan 629
620 jonathan 649 if id == ID_UNIQUE_SORTUSE:
621     list = self.list_use
622     else:
623     list = self.list_avail
624 jonathan 629
625 jonathan 649 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 jonathan 629 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     item = list_src.GetItem(index)
687    
688     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 jonathan 607 wxPanel.__init__(self, parent, -1)
713    
714 jonathan 629 topSizer = wxStaticBoxSizer(wxStaticBox(self, -1, ""), wxHORIZONTAL)
715 jonathan 607
716 jonathan 629 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 jonathan 649 bmp = resource.GetBitmapResource(USE_BMP, wxBITMAP_TYPE_XPM)
734 jonathan 629 bsizer = wxBoxSizer(wxVERTICAL)
735 jonathan 649 bsizer.Add(wxBitmapButton(self, ID_CUSTOMRAMP_COPYSTART, bmp),
736 jonathan 629 0, wxGROW | wxALL, 4)
737 jonathan 649 bmp = resource.GetBitmapResource(USENOT_BMP, wxBITMAP_TYPE_XPM)
738     bsizer.Add(wxBitmapButton(self, ID_CUSTOMRAMP_COPYEND, bmp),
739 jonathan 629 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 jonathan 635 def GetRamp(self):
775     return CustomRamp(self.startPropCtrl.GetProperties(),
776     self.endPropCtrl.GetProperties())
777 jonathan 629
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 jonathan 607 class ClassGenerator:
791    
792 jonathan 635 def GenSingletonsFromList(self, list, numGroups, ramp):
793 jonathan 607 """Generate a new classification consisting solely of singletons.
794    
795     The resulting classification will consist of at most 'numGroups'
796     groups whose group properties ramp between 'prop1' and 'prop2'. There
797     could be fewer groups if 'list' contains fewer that 'numGroups' items.
798    
799     list -- any object that implements the iterator interface
800    
801     numGroups -- how many groups to generate. This can not be
802     determined while the classification is being
803     generated because the stepping values must
804     be precalculated to ramp between prop1 and prop2.
805    
806     prop1 -- initial group property values
807    
808     prop2 -- final group property values
809     """
810    
811     clazz = Classification()
812     if numGroups == 0: return clazz
813    
814 jonathan 635 ramp.SetNumGroups(numGroups)
815    
816     for value, prop in zip(list, ramp):
817 jonathan 614 clazz.AppendGroup(ClassGroupSingleton(value, prop))
818 jonathan 607
819     return clazz
820    
821 jonathan 635 def GenSingletons(self, min, max, numGroups, ramp):
822 jonathan 607
823     clazz = Classification()
824 jonathan 629
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 jonathan 635 ramp.SetNumGroups(numGroups)
832    
833     for prop in ramp:
834 jonathan 629 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 jonathan 635 ramp, intStep = False):
844 jonathan 629 """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()
854 jonathan 607 if numGroups == 0: return clazz
855    
856 jonathan 635 ramp.SetNumGroups(numGroups)
857    
858 jonathan 629 step = Str2Num(str((max - min) / float(numGroups)))
859 jonathan 607
860 jonathan 629 if intStep:
861     step = int(step)
862    
863 jonathan 607 cur_min = min
864     cur_max = cur_min + step
865    
866     i = 0
867 jonathan 635 for prop in ramp:
868 jonathan 607
869     if i == (numGroups - 1):
870     cur_max = max
871    
872     # this check guards against rounding issues
873     if cur_min != cur_max:
874 jonathan 629 clazz.AppendGroup(
875     ClassGroupRange(
876     Str2Num(str(cur_min)),
877     Str2Num(str(cur_max)),
878     prop))
879 jonathan 607
880     cur_min = cur_max
881     cur_max += step
882     i += 1
883    
884     return clazz
885    
886 jonathan 629 CLR = 0
887     STEP = 1
888     class CustomRamp:
889 jonathan 607
890 jonathan 635 def __init__(self, prop1, prop2):
891     self.prop1 = prop1
892     self.prop2 = prop2
893 jonathan 607
894 jonathan 635 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     if num <= 0:
905     return False
906    
907 jonathan 607 self.count = int(num)
908     num = float(num)
909    
910 jonathan 635 prop1 = self.prop1
911     prop2 = self.prop2
912    
913 jonathan 629 clr = prop1.GetLineColor()
914     lineColor2 = prop2.GetLineColor()
915    
916     self.noLine = clr is not Color.Transparent \
917     and lineColor2 is not Color.Transparent
918 jonathan 607
919    
920 jonathan 629 self.lineInfo = self.__GetColorInfo(prop1.GetLineColor(),
921     prop2.GetLineColor(),
922     num)
923 jonathan 607
924 jonathan 629 self.fillInfo = self.__GetColorInfo(prop1.GetFill(),
925     prop2.GetFill(),
926     num)
927 jonathan 607
928 jonathan 629 self.lineWidth = prop1.GetLineWidth()
929     self.lineWidthStep = (prop2.GetLineWidth() - self.lineWidth) / num
930 jonathan 607
931 jonathan 635 return True
932 jonathan 607
933     def next(self):
934     if self.count == 0:
935     raise StopIteration
936    
937     prop = ClassGroupProperties()
938    
939 jonathan 629 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 jonathan 607
946 jonathan 629 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 jonathan 607
950 jonathan 629 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))
963     self.lineWidth += self.lineWidthStep
964    
965 jonathan 607 self.count -= 1
966    
967     return prop
968    
969 jonathan 629 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 jonathan 635
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 jonathan 649 class GreyRamp(MonochromaticRamp):
1010     def __init__(self):
1011 jonathan 654 MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(0, 0, 0))
1012 jonathan 649
1013 jonathan 635 class RedRamp(MonochromaticRamp):
1014     def __init__(self):
1015 jonathan 654 MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(.8, 0, 0))
1016 jonathan 635
1017     class GreenRamp(MonochromaticRamp):
1018     def __init__(self):
1019 jonathan 654 MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(0, .8, 0))
1020 jonathan 635
1021     class BlueRamp(MonochromaticRamp):
1022     def __init__(self):
1023 jonathan 654 MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(0, 0, .8))
1024 jonathan 635
1025 jonathan 649 class HotToColdRamp:
1026    
1027     def __iter__(self):
1028     return self
1029    
1030     def GetRamp(self):
1031     return self
1032    
1033     def SetNumGroups(self, num):
1034     if num < 0:
1035     return False
1036    
1037     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
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    

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26