/[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 677 - (hide annotations)
Tue Apr 15 19:21:01 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: 33694 byte(s)
(GenUniformPanel): Fix spin control weirdness by setting the range to
        (1, maxint).

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     self.genCombo = wxComboBox(self,
92 jonathan 635 ID_CLASSGEN_GENCOMBO,
93     "", style = wxCB_READONLY)
94 jonathan 629 psizer.Add(self.genCombo, 1, wxALL | wxGROW, 4)
95 jonathan 635 EVT_COMBOBOX(self, ID_CLASSGEN_GENCOMBO, self._OnGenTypeSelect)
96 jonathan 629
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 jonathan 635 self.genCombo.Append(GENCOMBOSTR_UNIQUE, panel)
105 jonathan 629 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 jonathan 635 self.genCombo.Append(GENCOMBOSTR_UNIFORM, panel)
112 jonathan 660 sizer.Add(panel, 1, wxGROW | wxALL, 4)
113 jonathan 629 sizer.Show(panel, False)
114    
115 jonathan 660 self.genCombo.SetSelection(0)
116    
117 jonathan 629 #############
118    
119 jonathan 635 psizer = wxBoxSizer(wxHORIZONTAL)
120 jonathan 660 psizer.Add(wxStaticText(self, -1, _("Color Scheme:")),
121 jonathan 635 0, wxALIGN_CENTER_VERTICAL, 0)
122 jonathan 629
123 jonathan 635 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 jonathan 629
130 jonathan 635 #############
131 jonathan 629
132 jonathan 635 self.propPanel = None
133     panel = CustomRampPanel(self, layer.ShapeType())
134 jonathan 629 sizer.Add(panel, 1, wxALL | wxGROW, 4)
135 jonathan 635 sizer.Show(panel, False)
136 jonathan 629
137 jonathan 649 self.propCombo.Append(PROPCOMBOSTR_GREY, GreyRamp())
138 jonathan 635 self.propCombo.Append(PROPCOMBOSTR_RED, RedRamp())
139     self.propCombo.Append(PROPCOMBOSTR_GREEN, GreenRamp())
140     self.propCombo.Append(PROPCOMBOSTR_BLUE, BlueRamp())
141 jonathan 649 self.propCombo.Append(PROPCOMBOSTR_HOT2COLD, HotToColdRamp())
142 jonathan 635 self.propCombo.Append(PROPCOMBOSTR_CUSTOM, panel)
143    
144 jonathan 660 self.propCombo.SetSelection(0)
145 jonathan 635
146    
147 jonathan 629 #############
148    
149 jonathan 607 sizer.Add(buttonSizer, 0,
150     wxALL | wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL, 4)
151    
152 jonathan 629
153 jonathan 607 self.SetSizer(sizer)
154     self.SetAutoLayout(True)
155     sizer.SetSizeHints(self)
156    
157 jonathan 629 self.sizer = sizer
158    
159 jonathan 607 EVT_BUTTON(self, ID_CLASSGEN_GEN, self._OnGenerate)
160 jonathan 629 EVT_BUTTON(self, ID_CLASSGEN_CLOSE, self._OnCloseBtn)
161 jonathan 607
162     def GetClassification(self):
163     return self.clazz
164    
165     def AllowGenerate(self, on):
166 jonathan 629 pass #self.genButton.Enable(on)
167 jonathan 607
168     def _OnGenerate(self, event):
169    
170 jonathan 635 index = self.genCombo.GetSelection()
171 jonathan 607
172 jonathan 635 genSel = self.genCombo.GetString(index)
173     genPanel = self.genCombo.GetClientData(index)
174    
175 jonathan 629 propPanel = self.propPanel
176 jonathan 607
177 jonathan 635 if genSel in (GENCOMBOSTR_UNIFORM, GENCOMBOSTR_UNIQUE):
178 jonathan 629 numGroups = genPanel.GetNumGroups()
179 jonathan 607
180 jonathan 635 index = self.propCombo.GetSelection()
181 jonathan 629
182 jonathan 635 propSel = self.propCombo.GetString(index)
183     propPanel = self.propCombo.GetClientData(index)
184 jonathan 629
185 jonathan 635 ramp = propPanel.GetRamp()
186 jonathan 629
187 jonathan 635 if genSel == GENCOMBOSTR_UNIFORM:
188 jonathan 629
189 jonathan 635 min = genPanel.GetMin()
190     max = genPanel.GetMax()
191 jonathan 629
192 jonathan 635 if min is not None \
193     and max is not None \
194     and numGroups is not None:
195 jonathan 629
196 jonathan 635 self.clazz = ClassGenerator().GenUnifromDistribution(
197     min, max, numGroups, ramp,
198     self.type == FIELDTYPE_INT)
199 jonathan 629
200 jonathan 635 self.parent._SetClassification(self.clazz)
201 jonathan 629
202 jonathan 635 elif genSel == GENCOMBOSTR_UNIQUE:
203 jonathan 629
204 jonathan 635 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 jonathan 629 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     self.genPanel = combo.GetClientData(selIndex)
227     if self.genPanel is not None:
228     self.sizer.Show(self.genPanel, True)
229    
230     self.sizer.SetSizeHints(self)
231     self.sizer.Layout()
232    
233 jonathan 635 def _OnPropTypeSelect(self, event):
234     combo = event.GetEventObject()
235 jonathan 629
236 jonathan 635 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 jonathan 629 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 jonathan 607 wxPanel.__init__(self, parent, -1)
261    
262     self.parent = parent
263 jonathan 629 self.layer = layer
264     self.fieldName = fieldName
265 jonathan 607 self.fieldType = fieldType
266    
267 jonathan 629 topSizer = wxStaticBoxSizer(wxStaticBox(self, -1, ""),
268 jonathan 607 wxVERTICAL)
269    
270 jonathan 629 #############
271    
272 jonathan 607 sizer = wxBoxSizer(wxHORIZONTAL)
273    
274     sizer.Add(wxStaticText(self, -1, _("Min:")), 0, wxALL, 4)
275 jonathan 629 self.minCtrl = wxTextCtrl(self, ID_UNIFORM_MIN, style=wxTE_RIGHT)
276     sizer.Add(self.minCtrl, 1, wxALL, 4)
277     EVT_TEXT(self, ID_UNIFORM_MIN, self._OnRangeChanged)
278 jonathan 607
279     sizer.Add(wxStaticText(self, -1, _("Max:")), 0, wxALL, 4)
280 jonathan 629 self.maxCtrl = wxTextCtrl(self, ID_UNIFORM_MAX, style=wxTE_RIGHT)
281     sizer.Add(self.maxCtrl, 1, wxALL, 4)
282     EVT_TEXT(self, ID_UNIFORM_MAX, self._OnRangeChanged)
283 jonathan 607
284 jonathan 629 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 jonathan 607 sizer = wxBoxSizer(wxHORIZONTAL)
293 jonathan 629
294 jonathan 607 sizer.Add(wxStaticText(self, -1, _("Number of Groups:")), 0, wxALL, 4)
295 jonathan 660 self.numGroupsCtrl = wxSpinCtrl(self, ID_UNIFORM_NGROUPS,
296     style=wxTE_RIGHT)
297 jonathan 629 EVT_TEXT(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)
298     EVT_SPINCTRL(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)
299     sizer.Add(self.numGroupsCtrl, 1, wxALL, 4)
300 jonathan 607
301     sizer.Add(wxStaticText(self, -1, _("Stepping:")), 0, wxALL, 4)
302 jonathan 629 self.stepCtrl = wxTextCtrl(self, ID_UNIFORM_STEP, style=wxTE_RIGHT)
303     EVT_TEXT(self, ID_UNIFORM_STEP, self._OnSteppingChanged)
304     sizer.Add(self.stepCtrl , 1, wxALL, 4)
305 jonathan 607
306 jonathan 629 topSizer.Add(sizer, 1, wxGROW, 0)
307    
308     #############
309    
310 jonathan 607 self.SetSizer(topSizer)
311     self.SetAutoLayout(True)
312     topSizer.SetSizeHints(self)
313    
314     self.numGroupsChanging = False
315     self.steppingChanging = False
316    
317 jonathan 677 self.numGroupsCtrl.SetRange(1, sys.maxint)
318 jonathan 607
319     self.numGroupsCtrl.SetValue(1)
320     self.stepCtrl.SetValue("1")
321     self.maxCtrl.SetValue("0")
322     self.minCtrl.SetValue("0")
323     self.minCtrl.SetFocus()
324    
325     def GetNumGroups(self):
326     value = self.numGroupsCtrl.GetValue()
327     return self.__GetValidatedTypeEntry(self.numGroupsCtrl,
328     value,
329     FIELDTYPE_INT,
330     None)
331    
332     def GetStepping(self):
333     step = self.stepCtrl.GetValue()
334     return self.__GetValidatedTypeEntry(self.stepCtrl,
335     step,
336     self.fieldType,
337     0)
338    
339     def GetMin(self):
340     min = self.minCtrl.GetValue()
341     max = self.maxCtrl.GetValue()
342     return self.__GetValidatedTypeEntry(self.minCtrl,
343     min,
344     self.fieldType,
345     max)
346    
347     def GetMax(self):
348     min = self.minCtrl.GetValue()
349     max = self.maxCtrl.GetValue()
350     return self.__GetValidatedTypeEntry(self.maxCtrl,
351     max,
352     self.fieldType,
353     min)
354    
355     def _OnRangeChanged(self, event):
356    
357     hasFocus = wxWindow_FindFocus() == event.GetEventObject()
358     min = self.GetMin()
359     max = self.GetMax()
360    
361     on = min is not None \
362     and max is not None
363    
364     self.numGroupsCtrl.Enable(on)
365     self.stepCtrl.Enable(on)
366    
367     ngroups = self.GetNumGroups()
368    
369     if ngroups is not None \
370     and min is not None \
371     and max is not None \
372     and ngroups != 0:
373    
374 jonathan 629 #self.stepCtrl.SetValue(str((max - min) / ngroups))
375     self.stepCtrl.SetValue(str(self.__CalcStepping(min, max, ngroups)))
376     #self.numGroupsCtrl.SetValue(ngroups)
377 jonathan 607
378     self.parent.AllowGenerate(self.GetStepping() is not None)
379     else:
380     self.parent.AllowGenerate(False)
381    
382    
383     if hasFocus:
384     event.GetEventObject().SetFocus()
385    
386     def _OnNumGroupsChanged(self, event):
387     if self.steppingChanging:
388     self.steppingChanging = False
389     return
390    
391    
392     obj = event.GetEventObject()
393     ngroups = self.GetNumGroups()
394     min = self.GetMin()
395     max = self.GetMax()
396    
397     if ngroups is not None \
398     and min is not None \
399     and max is not None \
400     and ngroups != 0:
401    
402     #
403     # changing the value in the stepCtrl sends an event
404     # that the control is changing, at which point
405     # we try to update the numGroupsCtrl. This causes
406     # an infinite recursion. This flag and the one
407     # called steppingChanging tries to prevent the recursion.
408     #
409     self.numGroupsChanging = True
410    
411 jonathan 629 self.stepCtrl.SetValue(str(self.__CalcStepping(min, max, ngroups)))
412    
413 jonathan 607 self.parent.AllowGenerate(self.GetStepping() is not None)
414     else:
415     self.parent.AllowGenerate(False)
416    
417    
418     def _OnSteppingChanged(self, event):
419     if self.numGroupsChanging:
420     self.numGroupsChanging = False
421     return
422    
423     step = self.GetStepping()
424     min = self.GetMin()
425     max = self.GetMax()
426    
427     if step is not None \
428     and min is not None \
429     and max is not None \
430     and step != 0:
431    
432     #
433     # see note in _OnNumGroupsChanged
434     #
435     self.steppingChanging = True
436 jonathan 629 self.numGroupsCtrl.SetValue(self.__CalcNumGroups(min, max, step))
437 jonathan 607
438     self.parent.AllowGenerate(self.GetNumGroups() is not None)
439     else:
440     self.parent.AllowGenerate(False)
441    
442 jonathan 629 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 jonathan 607 def __GetValidatedTypeEntry(self, win, value, type, badValue = None):
450    
451     if type == FIELDTYPE_INT:
452     func = int
453     elif type == FIELDTYPE_DOUBLE:
454     func = float
455     elif type == FIELDTYPE_STRING:
456     func = str
457     else:
458     assert False, "Unsupported FIELDTYPE"
459     pass
460    
461     if self.__ValidateEntry(win, value, func, badValue):
462     return func(value)
463    
464     return None
465    
466     def __ValidateEntry(self, win, value, test, badValue = None):
467    
468     valid = value != ""
469    
470     try:
471     if valid:
472     value = test(value)
473    
474     if badValue is not None:
475     valid = value != test(badValue)
476     except ValueError:
477     valid = False
478    
479     if valid:
480     win.SetForegroundColour(wxBLACK)
481     else:
482     win.SetForegroundColour(wxRED)
483    
484 jonathan 620 win.Refresh()
485    
486 jonathan 607 return valid
487 jonathan 629
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 jonathan 649 ID_UNIQUE_REVAVAIL = 4008
514     ID_UNIQUE_REVUSE = 4009
515 jonathan 629
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 jonathan 649 #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 jonathan 629 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 jonathan 649 bsizer = wxBoxSizer(wxHORIZONTAL)
551     bsizer.Add(wxButton(self, ID_UNIQUE_SORTAVAIL, _("Sort")))
552     EVT_BUTTON(self, ID_UNIQUE_SORTAVAIL, self._OnSortList)
553 jonathan 629
554 jonathan 649 bsizer.Add(wxButton(self, ID_UNIQUE_REVAVAIL, _("Reverse")))
555     EVT_BUTTON(self, ID_UNIQUE_REVAVAIL, self._OnReverseList)
556 jonathan 629
557 jonathan 649 psizer.Add(bsizer, 0, wxGROW, 0)
558 jonathan 629 sizer.Add(psizer, 1, wxGROW, 0)
559    
560 jonathan 607
561 jonathan 629 bsizer = wxBoxSizer(wxVERTICAL)
562 jonathan 649
563     bmp = resource.GetBitmapResource(USEALL_BMP, wxBITMAP_TYPE_XPM)
564     bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USEALL, bmp),
565 jonathan 629 0, wxGROW | wxALL, 4)
566 jonathan 649 bmp = resource.GetBitmapResource(USE_BMP, wxBITMAP_TYPE_XPM)
567     bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USE, bmp),
568 jonathan 629 0, wxGROW | wxALL, 4)
569 jonathan 649 bmp = resource.GetBitmapResource(USENOT_BMP, wxBITMAP_TYPE_XPM)
570     bsizer.Add(wxBitmapButton(self, ID_UNIQUE_DONTUSE, bmp),
571 jonathan 629 0, wxGROW | wxALL, 4)
572 jonathan 649 bmp = resource.GetBitmapResource(USENONE_BMP, wxBITMAP_TYPE_XPM)
573     bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USENONE, bmp),
574 jonathan 629 0, wxGROW | wxALL, 4)
575 jonathan 607
576 jonathan 629 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 jonathan 607
581 jonathan 629 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 jonathan 649 bsizer = wxBoxSizer(wxHORIZONTAL)
591     bsizer.Add(wxButton(self, ID_UNIQUE_SORTUSE, _("Sort")))
592     EVT_BUTTON(self, ID_UNIQUE_SORTUSE, self._OnSortList)
593 jonathan 629
594 jonathan 649 bsizer.Add(wxButton(self, ID_UNIQUE_REVUSE, _("Reverse")))
595     EVT_BUTTON(self, ID_UNIQUE_REVUSE, self._OnReverseList)
596 jonathan 629
597 jonathan 649 psizer.Add(bsizer, 0, wxGROW, 0)
598    
599 jonathan 629 sizer.Add(psizer, 1, wxGROW, 0)
600    
601    
602     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 jonathan 649 def _OnSortList(self, event):
622     id = event.GetId()
623 jonathan 629
624 jonathan 649 if id == ID_UNIQUE_SORTUSE:
625     list = self.list_use
626     else:
627     list = self.list_avail
628 jonathan 629
629 jonathan 649 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 jonathan 629 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 jonathan 607 wxPanel.__init__(self, parent, -1)
717    
718 jonathan 629 topSizer = wxStaticBoxSizer(wxStaticBox(self, -1, ""), wxHORIZONTAL)
719 jonathan 607
720 jonathan 629 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 jonathan 649 bmp = resource.GetBitmapResource(USE_BMP, wxBITMAP_TYPE_XPM)
738 jonathan 629 bsizer = wxBoxSizer(wxVERTICAL)
739 jonathan 649 bsizer.Add(wxBitmapButton(self, ID_CUSTOMRAMP_COPYSTART, bmp),
740 jonathan 629 0, wxGROW | wxALL, 4)
741 jonathan 649 bmp = resource.GetBitmapResource(USENOT_BMP, wxBITMAP_TYPE_XPM)
742     bsizer.Add(wxBitmapButton(self, ID_CUSTOMRAMP_COPYEND, bmp),
743 jonathan 629 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 jonathan 635 def GetRamp(self):
779     return CustomRamp(self.startPropCtrl.GetProperties(),
780     self.endPropCtrl.GetProperties())
781 jonathan 629
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 jonathan 607 class ClassGenerator:
795    
796 jonathan 635 def GenSingletonsFromList(self, list, numGroups, ramp):
797 jonathan 607 """Generate a new classification consisting solely of singletons.
798    
799     The resulting classification will consist of at most 'numGroups'
800     groups whose group properties ramp between 'prop1' and 'prop2'. There
801     could be fewer groups if 'list' contains fewer that 'numGroups' items.
802    
803     list -- any object that implements the iterator interface
804    
805     numGroups -- how many groups to generate. This can not be
806     determined while the classification is being
807     generated because the stepping values must
808     be precalculated to ramp between prop1 and prop2.
809    
810     prop1 -- initial group property values
811    
812     prop2 -- final group property values
813     """
814    
815     clazz = Classification()
816     if numGroups == 0: return clazz
817    
818 jonathan 635 ramp.SetNumGroups(numGroups)
819    
820     for value, prop in zip(list, ramp):
821 jonathan 614 clazz.AppendGroup(ClassGroupSingleton(value, prop))
822 jonathan 607
823     return clazz
824    
825 jonathan 635 def GenSingletons(self, min, max, numGroups, ramp):
826 jonathan 607
827     clazz = Classification()
828 jonathan 629
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 jonathan 635 ramp.SetNumGroups(numGroups)
836    
837     for prop in ramp:
838 jonathan 629 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 jonathan 635 ramp, intStep = False):
848 jonathan 629 """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()
858 jonathan 607 if numGroups == 0: return clazz
859    
860 jonathan 635 ramp.SetNumGroups(numGroups)
861    
862 jonathan 629 step = Str2Num(str((max - min) / float(numGroups)))
863 jonathan 607
864 jonathan 629 if intStep:
865     step = int(step)
866    
867 jonathan 607 cur_min = min
868     cur_max = cur_min + step
869    
870     i = 0
871 jonathan 635 for prop in ramp:
872 jonathan 607
873     if i == (numGroups - 1):
874     cur_max = max
875    
876     # this check guards against rounding issues
877     if cur_min != cur_max:
878 jonathan 629 clazz.AppendGroup(
879     ClassGroupRange(
880     Str2Num(str(cur_min)),
881     Str2Num(str(cur_max)),
882     prop))
883 jonathan 607
884     cur_min = cur_max
885     cur_max += step
886     i += 1
887    
888     return clazz
889    
890 jonathan 629 CLR = 0
891     STEP = 1
892     class CustomRamp:
893 jonathan 607
894 jonathan 635 def __init__(self, prop1, prop2):
895     self.prop1 = prop1
896     self.prop2 = prop2
897 jonathan 607
898 jonathan 635 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     if num <= 0:
909     return False
910    
911 jonathan 607 self.count = int(num)
912     num = float(num)
913    
914 jonathan 635 prop1 = self.prop1
915     prop2 = self.prop2
916    
917 jonathan 629 clr = prop1.GetLineColor()
918     lineColor2 = prop2.GetLineColor()
919    
920     self.noLine = clr is not Color.Transparent \
921     and lineColor2 is not Color.Transparent
922 jonathan 607
923    
924 jonathan 629 self.lineInfo = self.__GetColorInfo(prop1.GetLineColor(),
925     prop2.GetLineColor(),
926     num)
927 jonathan 607
928 jonathan 629 self.fillInfo = self.__GetColorInfo(prop1.GetFill(),
929     prop2.GetFill(),
930     num)
931 jonathan 607
932 jonathan 629 self.lineWidth = prop1.GetLineWidth()
933     self.lineWidthStep = (prop2.GetLineWidth() - self.lineWidth) / num
934 jonathan 607
935 jonathan 635 return True
936 jonathan 607
937     def next(self):
938     if self.count == 0:
939     raise StopIteration
940    
941     prop = ClassGroupProperties()
942    
943 jonathan 629 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 jonathan 607
950 jonathan 629 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 jonathan 607
954 jonathan 629 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))
967     self.lineWidth += self.lineWidthStep
968    
969 jonathan 607 self.count -= 1
970    
971     return prop
972    
973 jonathan 629 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 jonathan 635
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 jonathan 649 class GreyRamp(MonochromaticRamp):
1014     def __init__(self):
1015 jonathan 654 MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(0, 0, 0))
1016 jonathan 649
1017 jonathan 635 class RedRamp(MonochromaticRamp):
1018     def __init__(self):
1019 jonathan 654 MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(.8, 0, 0))
1020 jonathan 635
1021     class GreenRamp(MonochromaticRamp):
1022     def __init__(self):
1023 jonathan 654 MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(0, .8, 0))
1024 jonathan 635
1025     class BlueRamp(MonochromaticRamp):
1026     def __init__(self):
1027 jonathan 654 MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(0, 0, .8))
1028 jonathan 635
1029 jonathan 649 class HotToColdRamp:
1030    
1031     def __iter__(self):
1032     return self
1033    
1034     def GetRamp(self):
1035     return self
1036    
1037     def SetNumGroups(self, num):
1038     if num < 0:
1039     return False
1040    
1041     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
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    

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26