/[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 660 - (hide annotations)
Mon Apr 14 14:15:44 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: 33866 byte(s)
(ClassGenDialog.__init__): Actively set the current selections in the combo
boxes. This is needed under Windows.

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26