/[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 629 - (hide annotations)
Wed Apr 9 10:09:44 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: 28591 byte(s)
Renamed GenRangePanel to GenUniformPanel.
(GenUniquePanel): New. Controls to allow the user to select
        which unique field values they would like in the classification.
(CustomRampPanel): Code that was in ClassGenDialog that allows
        the user to select the properties for a custom ramp.
(ClassGenerator.GenUniformDistribution): Was called GenerateRanges.

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26