/[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 649 - (hide annotations)
Fri Apr 11 14:27:12 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: 33748 byte(s)
(GenUniquePanel.__init__): Reordered buttons,
        added images to the move buttons, added 'reverse' button.
(CustomRampPanel.__init__): Added images to the move buttons.
(GreyRamp): New. Generates a ramp from white to black.
(HotToColdRamp): New. Generates a ramp from cold to hot colors.

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 629 sizer.Add(panel, 0, wxGROW | wxALL, 4)
111     sizer.Show(panel, False)
112    
113     #############
114    
115 jonathan 635 psizer = wxBoxSizer(wxHORIZONTAL)
116     psizer.Add(wxStaticText(self, -1, _("Color Schemes:")),
117     0, wxALIGN_CENTER_VERTICAL, 0)
118 jonathan 629
119 jonathan 635 self.propCombo = wxComboBox(self,
120     ID_CLASSGEN_PROPCOMBO,
121     "", style = wxCB_READONLY)
122     psizer.Add(self.propCombo, 1, wxALL | wxGROW, 4)
123     EVT_COMBOBOX(self, ID_CLASSGEN_PROPCOMBO, self._OnPropTypeSelect)
124     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    
141    
142 jonathan 629 #############
143    
144 jonathan 607 sizer.Add(buttonSizer, 0,
145     wxALL | wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL, 4)
146    
147 jonathan 629
148 jonathan 607 self.SetSizer(sizer)
149     self.SetAutoLayout(True)
150     sizer.SetSizeHints(self)
151    
152 jonathan 629 self.sizer = sizer
153    
154 jonathan 607 EVT_BUTTON(self, ID_CLASSGEN_GEN, self._OnGenerate)
155 jonathan 629 EVT_BUTTON(self, ID_CLASSGEN_CLOSE, self._OnCloseBtn)
156 jonathan 607
157     def GetClassification(self):
158     return self.clazz
159    
160     def AllowGenerate(self, on):
161 jonathan 629 pass #self.genButton.Enable(on)
162 jonathan 607
163     def _OnGenerate(self, event):
164    
165 jonathan 635 index = self.genCombo.GetSelection()
166 jonathan 607
167 jonathan 635 genSel = self.genCombo.GetString(index)
168     genPanel = self.genCombo.GetClientData(index)
169    
170 jonathan 629 propPanel = self.propPanel
171 jonathan 607
172 jonathan 635 if genSel in (GENCOMBOSTR_UNIFORM, GENCOMBOSTR_UNIQUE):
173 jonathan 629 numGroups = genPanel.GetNumGroups()
174 jonathan 607
175 jonathan 635 index = self.propCombo.GetSelection()
176 jonathan 629
177 jonathan 635 propSel = self.propCombo.GetString(index)
178     propPanel = self.propCombo.GetClientData(index)
179 jonathan 629
180 jonathan 635 ramp = propPanel.GetRamp()
181 jonathan 629
182 jonathan 635 if genSel == GENCOMBOSTR_UNIFORM:
183 jonathan 629
184 jonathan 635 min = genPanel.GetMin()
185     max = genPanel.GetMax()
186 jonathan 629
187 jonathan 635 if min is not None \
188     and max is not None \
189     and numGroups is not None:
190 jonathan 629
191 jonathan 635 self.clazz = ClassGenerator().GenUnifromDistribution(
192     min, max, numGroups, ramp,
193     self.type == FIELDTYPE_INT)
194 jonathan 629
195 jonathan 635 self.parent._SetClassification(self.clazz)
196 jonathan 629
197 jonathan 635 elif genSel == GENCOMBOSTR_UNIQUE:
198 jonathan 629
199 jonathan 635 list = genPanel.GetValueList()
200    
201     if len(list) > 0 \
202     and numGroups is not None:
203    
204     self.clazz = ClassGenerator().GenSingletonsFromList(
205     list, numGroups, ramp)
206    
207     self.parent._SetClassification(self.clazz)
208    
209 jonathan 629 def _OnCloseBtn(self, event):
210     self.Close()
211    
212     def _OnGenTypeSelect(self, event):
213    
214     combo = event.GetEventObject()
215    
216     selIndex = combo.GetSelection()
217    
218     if self.genPanel is not None:
219     self.sizer.Show(self.genPanel, False)
220    
221     self.genPanel = combo.GetClientData(selIndex)
222     if self.genPanel is not None:
223     self.sizer.Show(self.genPanel, True)
224    
225     self.sizer.SetSizeHints(self)
226     self.sizer.Layout()
227    
228 jonathan 635 def _OnPropTypeSelect(self, event):
229     combo = event.GetEventObject()
230 jonathan 629
231 jonathan 635 selIndex = combo.GetSelection()
232     sel = combo.GetString(selIndex)
233    
234     if isinstance(self.propPanel, wxPanel):
235     self.sizer.Show(self.propPanel, False)
236    
237     self.propPanel = combo.GetClientData(selIndex)
238    
239     if isinstance(self.propPanel, wxPanel):
240     self.sizer.Show(self.propPanel, True)
241    
242     self.sizer.SetSizeHints(self)
243     self.sizer.Layout()
244    
245    
246 jonathan 629 ID_UNIFORM_MIN = 4001
247     ID_UNIFORM_MAX = 4002
248     ID_UNIFORM_NGROUPS = 4003
249     ID_UNIFORM_STEP = 4004
250     ID_UNIFORM_RETRIEVE = 4005
251    
252     class GenUniformPanel(wxPanel):
253    
254     def __init__(self, parent, layer, fieldName, fieldType):
255 jonathan 607 wxPanel.__init__(self, parent, -1)
256    
257     self.parent = parent
258 jonathan 629 self.layer = layer
259     self.fieldName = fieldName
260 jonathan 607 self.fieldType = fieldType
261    
262 jonathan 629 topSizer = wxStaticBoxSizer(wxStaticBox(self, -1, ""),
263 jonathan 607 wxVERTICAL)
264    
265 jonathan 629 #############
266    
267 jonathan 607 sizer = wxBoxSizer(wxHORIZONTAL)
268    
269     sizer.Add(wxStaticText(self, -1, _("Min:")), 0, wxALL, 4)
270 jonathan 629 self.minCtrl = wxTextCtrl(self, ID_UNIFORM_MIN, style=wxTE_RIGHT)
271     sizer.Add(self.minCtrl, 1, wxALL, 4)
272     EVT_TEXT(self, ID_UNIFORM_MIN, self._OnRangeChanged)
273 jonathan 607
274     sizer.Add(wxStaticText(self, -1, _("Max:")), 0, wxALL, 4)
275 jonathan 629 self.maxCtrl = wxTextCtrl(self, ID_UNIFORM_MAX, style=wxTE_RIGHT)
276     sizer.Add(self.maxCtrl, 1, wxALL, 4)
277     EVT_TEXT(self, ID_UNIFORM_MAX, self._OnRangeChanged)
278 jonathan 607
279 jonathan 629 sizer.Add(wxButton(self, ID_UNIFORM_RETRIEVE, _("Retrieve From Table")),
280     0, wxALL, 4)
281     EVT_BUTTON(self, ID_UNIFORM_RETRIEVE, self._OnRetrieve)
282    
283     topSizer.Add(sizer, 1, wxGROW, 0)
284    
285     #############
286    
287 jonathan 607 sizer = wxBoxSizer(wxHORIZONTAL)
288 jonathan 629
289 jonathan 607 sizer.Add(wxStaticText(self, -1, _("Number of Groups:")), 0, wxALL, 4)
290 jonathan 629 self.numGroupsCtrl = wxSpinCtrl(self, ID_UNIFORM_NGROUPS, style=wxTE_RIGHT)
291     EVT_TEXT(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)
292     EVT_SPINCTRL(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)
293     sizer.Add(self.numGroupsCtrl, 1, wxALL, 4)
294 jonathan 607
295     sizer.Add(wxStaticText(self, -1, _("Stepping:")), 0, wxALL, 4)
296 jonathan 629 self.stepCtrl = wxTextCtrl(self, ID_UNIFORM_STEP, style=wxTE_RIGHT)
297     EVT_TEXT(self, ID_UNIFORM_STEP, self._OnSteppingChanged)
298     sizer.Add(self.stepCtrl , 1, wxALL, 4)
299 jonathan 607
300 jonathan 629 topSizer.Add(sizer, 1, wxGROW, 0)
301    
302     #############
303    
304 jonathan 607 self.SetSizer(topSizer)
305     self.SetAutoLayout(True)
306     topSizer.SetSizeHints(self)
307    
308     self.numGroupsChanging = False
309     self.steppingChanging = False
310    
311     self.numGroupsCtrl.SetRange(1, 100)
312    
313     self.numGroupsCtrl.SetValue(1)
314     self.stepCtrl.SetValue("1")
315     self.maxCtrl.SetValue("0")
316     self.minCtrl.SetValue("0")
317     self.minCtrl.SetFocus()
318    
319     def GetNumGroups(self):
320     value = self.numGroupsCtrl.GetValue()
321     return self.__GetValidatedTypeEntry(self.numGroupsCtrl,
322     value,
323     FIELDTYPE_INT,
324     None)
325    
326     def GetStepping(self):
327     step = self.stepCtrl.GetValue()
328     return self.__GetValidatedTypeEntry(self.stepCtrl,
329     step,
330     self.fieldType,
331     0)
332    
333     def GetMin(self):
334     min = self.minCtrl.GetValue()
335     max = self.maxCtrl.GetValue()
336     return self.__GetValidatedTypeEntry(self.minCtrl,
337     min,
338     self.fieldType,
339     max)
340    
341     def GetMax(self):
342     min = self.minCtrl.GetValue()
343     max = self.maxCtrl.GetValue()
344     return self.__GetValidatedTypeEntry(self.maxCtrl,
345     max,
346     self.fieldType,
347     min)
348    
349     def _OnRangeChanged(self, event):
350    
351     hasFocus = wxWindow_FindFocus() == event.GetEventObject()
352     min = self.GetMin()
353     max = self.GetMax()
354    
355     on = min is not None \
356     and max is not None
357    
358     self.numGroupsCtrl.Enable(on)
359     self.stepCtrl.Enable(on)
360    
361     if on:
362     self.numGroupsCtrl.SetRange(1, abs(max - min) / 0.001)
363    
364     ngroups = self.GetNumGroups()
365    
366     if ngroups is not None \
367     and min is not None \
368     and max is not None \
369     and ngroups != 0:
370    
371 jonathan 629 #self.stepCtrl.SetValue(str((max - min) / ngroups))
372     self.stepCtrl.SetValue(str(self.__CalcStepping(min, max, ngroups)))
373     #self.numGroupsCtrl.SetValue(ngroups)
374 jonathan 607
375     self.parent.AllowGenerate(self.GetStepping() is not None)
376     else:
377     self.parent.AllowGenerate(False)
378    
379    
380     if hasFocus:
381     event.GetEventObject().SetFocus()
382    
383     def _OnNumGroupsChanged(self, event):
384     if self.steppingChanging:
385     self.steppingChanging = False
386     return
387    
388    
389     obj = event.GetEventObject()
390     ngroups = self.GetNumGroups()
391     min = self.GetMin()
392     max = self.GetMax()
393    
394     if ngroups >= self.numGroupsCtrl.GetMax():
395     self.numGroupsCtrl.SetRange(1, ngroups + 1)
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     MonochromaticRamp.__init__(self, Color(0, 0, 0), Color(1, 1, 1))
1016    
1017 jonathan 635 class RedRamp(MonochromaticRamp):
1018     def __init__(self):
1019     MonochromaticRamp.__init__(self, Color(.2, 0, 0), Color(1, 0, 0))
1020    
1021     class GreenRamp(MonochromaticRamp):
1022     def __init__(self):
1023     MonochromaticRamp.__init__(self, Color(0, .2, 0), Color(0, 1, 0))
1024    
1025     class BlueRamp(MonochromaticRamp):
1026     def __init__(self):
1027     MonochromaticRamp.__init__(self, Color(0, 0, .2), Color(0, 0, 1))
1028    
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