/[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 635 - (hide annotations)
Wed Apr 9 15:42:25 2003 UTC (21 years, 11 months ago) by jonathan
Original Path: trunk/thuban/Thuban/UI/classgen.py
File MIME type: text/x-python
File size: 30912 byte(s)
Modifications to allow simple addition and selection of new color schemes.
(MonochromaticRamp): New. Generates a ramp between two colors.
(RedRamp): New. Generates a ramp of all red.
(GreenRamp): New. Generates a ramp of all green.
(BlueRamp): New. Generates a ramp of all blue.

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26