/[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 1526 - (hide annotations)
Wed Jul 30 15:43:06 2003 UTC (21 years, 7 months ago) by jonathan
Original Path: trunk/thuban/Thuban/UI/classgen.py
File MIME type: text/x-python
File size: 32196 byte(s)
 Use renamed Ramp instances.

1 jonathan 607 # Copyright (c) 2003 by Intevation GmbH
2     # Authors:
3     # Jonathan Coles <[email protected]>
4     #
5     # This program is free software under the GPL (>=v2)
6     # Read the file COPYING coming with Thuban for details.
7    
8 jonathan 677 import sys
9    
10 jonathan 607 from Thuban import _
11    
12     from wxPython.wx import *
13    
14 bh 907 from Thuban.Model.classification import ClassGroupProperties
15 jonathan 607
16 bh 907 from Thuban.Model.table import FIELDTYPE_INT, FIELDTYPE_DOUBLE, \
17 jonathan 607 FIELDTYPE_STRING
18    
19 jonathan 1391 from Thuban.Model.layer import SHAPETYPE_ARC
20 jonathan 877 from Thuban.Model.range import Range
21 jonathan 1274 from Thuban.UI.common import ThubanBeginBusyCursor, ThubanEndBusyCursor
22 jonathan 607
23 jonathan 877 import classifier, resource
24 jonathan 629
25 jonathan 1100 from Thuban.Model.classgen import \
26 jonathan 1163 generate_uniform_distribution, generate_singletons, generate_quantiles, \
27 jonathan 1526 CustomRamp, grey_ramp, red_ramp, green_ramp, blue_ramp, green_to_red_ramp, \
28 jonathan 1432 HotToColdRamp, FixedRamp
29 jonathan 649
30 jonathan 1391
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 877 GENCOMBOSTR_QUANTILES = _("Quantiles from Table")
39 jonathan 629
40 jonathan 649 PROPCOMBOSTR_CUSTOM = _("Custom Ramp")
41     PROPCOMBOSTR_GREY = _("Grey Ramp")
42     PROPCOMBOSTR_RED = _("Red Ramp")
43     PROPCOMBOSTR_GREEN = _("Green Ramp")
44     PROPCOMBOSTR_BLUE = _("Blue Ramp")
45 jonathan 877 PROPCOMBOSTR_GREEN2RED = _("Green-to-Red Ramp")
46 jonathan 649 PROPCOMBOSTR_HOT2COLD = _("Hot-to-Cold Ramp")
47 jonathan 635
48 jonathan 877 ID_CLASSGEN_GENCOMBO = 4007
49     ID_CLASSGEN_PROPCOMBO = 4008
50    
51 jonathan 1391 ID_BORDER_COLOR = 4009
52     ID_BORDER_COLOR_CHANGE = 4010
53    
54 jonathan 607 class ClassGenDialog(wxDialog):
55 bh 834
56 jonathan 629 def __init__(self, parent, layer, fieldName):
57     """Inialize the class generating dialog.
58    
59     parent -- this must be an instance of the Classifier class
60     """
61    
62 jonathan 607 wxDialog.__init__(self, parent, -1, _("Generate Classification"),
63     style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
64 bh 834
65 jonathan 629 self.parent = parent
66 jonathan 877 self.layer = layer
67 jonathan 607 self.clazz = None
68    
69 bh 1219 col = layer.ShapeStore().Table().Column(fieldName)
70 bh 834 self.type = col.type
71 jonathan 607
72 jonathan 877 self.fieldName = fieldName
73     self.fieldType = self.type
74    
75     self.curGenPanel = None
76    
77     self.genpanels = []
78    
79 jonathan 629 #############
80     # we need to create genButton first because when we create the
81     # panels they will call AllowGenerate() which uses genButton.
82     #
83 jonathan 812 self.genButton = wxButton(self, wxID_OK, _("Generate"))
84 jonathan 1341 self.cancelButton = wxButton(self, wxID_CANCEL, _("Close"))
85 jonathan 812 self.genButton.SetDefault()
86 frank 978
87 jonathan 812 self.genChoice = wxChoice(self, ID_CLASSGEN_GENCOMBO)
88 jonathan 607
89 jonathan 877 self.genpanels.append((GENCOMBOSTR_UNIQUE, GenUniquePanel))
90     if self.type in (FIELDTYPE_INT, FIELDTYPE_DOUBLE):
91     self.genpanels.append((GENCOMBOSTR_UNIFORM, GenUniformPanel))
92     self.genpanels.append((GENCOMBOSTR_QUANTILES, GenQuantilesPanel))
93 jonathan 812
94 jonathan 877 for name, clazz in self.genpanels:
95     self.genChoice.Append(name, [clazz, None])
96 jonathan 812
97     self.genChoice.SetSelection(0)
98    
99 frank 978 for i in range(self.genChoice.GetCount()):
100     clazz, obj = self.genChoice.GetClientData(i)
101 jonathan 812
102 frank 978 if obj is None:
103     obj = clazz(self, self.layer, self.fieldName, self.fieldType)
104     obj.Hide()
105     self.genChoice.SetClientData(i, [clazz, obj])
106 jonathan 812
107    
108 jonathan 629 #############
109 jonathan 607
110 jonathan 629 sizer = wxBoxSizer(wxVERTICAL)
111    
112     sizer.Add(wxStaticText(self, -1, _("Field: %s") % fieldName),
113     0, wxALL, 4)
114     sizer.Add(wxStaticText(
115     self, -1,
116 jonathan 649 _("Data Type: %s") % classifier.Classifier.type2string[self.type]),
117 jonathan 629 0, wxALL, 4)
118    
119     psizer = wxBoxSizer(wxHORIZONTAL)
120 jonathan 635 psizer.Add(wxStaticText(self, -1, _("Generate:")),
121 jonathan 629 0, wxALIGN_CENTER_VERTICAL, 0)
122 jonathan 728 psizer.Add(self.genChoice, 1, wxALL | wxGROW, 4)
123 jonathan 629
124     sizer.Add(psizer, 0, wxALL | wxGROW, 4)
125    
126 jonathan 877 self.sizer_genPanel = wxBoxSizer(wxVERTICAL)
127     sizer.Add(self.sizer_genPanel, 1, wxGROW | wxALL, 4)
128 jonathan 629
129 jonathan 635 psizer = wxBoxSizer(wxHORIZONTAL)
130 jonathan 660 psizer.Add(wxStaticText(self, -1, _("Color Scheme:")),
131 jonathan 635 0, wxALIGN_CENTER_VERTICAL, 0)
132 frank 978
133     # Properties (Ramp) ComboBox
134     self.propCombo = wxChoice(self, ID_CLASSGEN_PROPCOMBO)
135    
136     self.propPanel = None
137     custom_ramp_panel = CustomRampPanel(self, layer.ShapeType())
138    
139 jonathan 1526 self.propCombo.Append(PROPCOMBOSTR_GREY, grey_ramp)
140     self.propCombo.Append(PROPCOMBOSTR_RED, red_ramp)
141     self.propCombo.Append(PROPCOMBOSTR_GREEN, green_ramp)
142     self.propCombo.Append(PROPCOMBOSTR_BLUE, blue_ramp)
143     self.propCombo.Append(PROPCOMBOSTR_GREEN2RED, green_to_red_ramp)
144 frank 978 self.propCombo.Append(PROPCOMBOSTR_HOT2COLD, HotToColdRamp())
145     self.propCombo.Append(PROPCOMBOSTR_CUSTOM, custom_ramp_panel)
146    
147     self.propCombo.SetSelection(0)
148    
149 jonathan 635 psizer.Add(self.propCombo, 1, wxALL | wxGROW, 4)
150     sizer.Add(psizer, 0, wxALL | wxGROW, 4)
151 jonathan 629
152 jonathan 1391 if layer.ShapeType() != SHAPETYPE_ARC:
153     psizer = wxBoxSizer(wxHORIZONTAL)
154     self.fix_border_check = wxCheckBox(self, -1, _("Fix Border Color"))
155     psizer.Add(self.fix_border_check, 0, wxALL | wxGROW, 4)
156     self.border_color = classifier.ClassGroupPropertiesCtrl(
157     self, ID_BORDER_COLOR,
158     ClassGroupProperties(), SHAPETYPE_ARC,
159     style=wxSIMPLE_BORDER, size=(40, 20))
160     psizer.Add(self.border_color, 0, wxALL | wxGROW, 4)
161     psizer.Add(wxButton(self, ID_BORDER_COLOR_CHANGE, _("Change")),
162     0, wxALL, 4)
163     sizer.Add(psizer, 0, wxALL | wxGROW, 4)
164     EVT_BUTTON(self, ID_BORDER_COLOR_CHANGE, self.OnBorderColorChange)
165     else:
166     self.border_color = None
167    
168 jonathan 812 sizer.Add(custom_ramp_panel, 1, wxGROW | wxALL, 4)
169     sizer.Show(custom_ramp_panel, False)
170 jonathan 629
171 frank 978 # Finally place the main buttons
172 jonathan 812 buttonSizer = wxBoxSizer(wxHORIZONTAL)
173 frank 978 buttonSizer.Add(self.genButton, 0, wxRIGHT|wxEXPAND, 10)
174     buttonSizer.Add(self.cancelButton, 0, wxRIGHT|wxEXPAND, 10)
175     sizer.Add(buttonSizer, 0, wxALIGN_RIGHT|wxBOTTOM|wxTOP, 10)
176 jonathan 607
177     self.SetSizer(sizer)
178     self.SetAutoLayout(True)
179     sizer.SetSizeHints(self)
180    
181 jonathan 877 self.topBox = sizer
182 jonathan 629
183 jonathan 877 self.__DoOnGenTypeSelect()
184    
185 jonathan 812 EVT_CHOICE(self, ID_CLASSGEN_GENCOMBO, self._OnGenTypeSelect)
186     EVT_CHOICE(self, ID_CLASSGEN_PROPCOMBO, self._OnPropTypeSelect)
187     EVT_BUTTON(self, wxID_OK, self.OnOK)
188     EVT_BUTTON(self, wxID_CANCEL, self.OnCancel)
189 jonathan 607
190 jonathan 877 self.__DoOnGenTypeSelect()
191 jonathan 812
192     self.genChoice.SetFocus()
193    
194 jonathan 607 def GetClassification(self):
195     return self.clazz
196    
197     def AllowGenerate(self, on):
198 jonathan 629 pass #self.genButton.Enable(on)
199 jonathan 607
200 jonathan 812 def OnOK(self, event):
201     """This is really the generate button, but we want to override
202     the wxDialog class.
203     """
204 jonathan 607
205 jonathan 728 index = self.genChoice.GetSelection()
206 jonathan 607
207 jonathan 877 assert index != -1, "button should be disabled!"
208    
209 jonathan 728 genSel = self.genChoice.GetString(index)
210 jonathan 877 clazz, genPanel = self.genChoice.GetClientData(index)
211 jonathan 635
212 jonathan 629 propPanel = self.propPanel
213 jonathan 607
214 jonathan 877 if genSel in (GENCOMBOSTR_UNIFORM, \
215     GENCOMBOSTR_UNIQUE, \
216     GENCOMBOSTR_QUANTILES):
217    
218 jonathan 629 numGroups = genPanel.GetNumGroups()
219 jonathan 607
220 jonathan 635 index = self.propCombo.GetSelection()
221 jonathan 629
222 jonathan 635 propSel = self.propCombo.GetString(index)
223     propPanel = self.propCombo.GetClientData(index)
224 jonathan 629
225 jonathan 635 ramp = propPanel.GetRamp()
226 jonathan 1391 if self.border_color and self.fix_border_check.IsChecked():
227     props = self.border_color.GetProperties()
228 jonathan 1432 ramp = FixedRamp(ramp,
229     (props.GetLineColor(), props.GetLineWidth(), None))
230 jonathan 629
231 jonathan 635 if genSel == GENCOMBOSTR_UNIFORM:
232 jonathan 629
233 jonathan 635 min = genPanel.GetMin()
234     max = genPanel.GetMax()
235 jonathan 629
236 jonathan 635 if min is not None \
237     and max is not None \
238     and numGroups is not None:
239 jonathan 629
240 jonathan 1163 self.clazz = generate_uniform_distribution(
241 jonathan 635 min, max, numGroups, ramp,
242 jonathan 1432 self.type == FIELDTYPE_INT)
243 jonathan 629
244 jonathan 635 self.parent._SetClassification(self.clazz)
245 jonathan 629
246 jonathan 635 elif genSel == GENCOMBOSTR_UNIQUE:
247 jonathan 629
248 jonathan 635 list = genPanel.GetValueList()
249    
250 jonathan 1341 if len(list) > 0:
251 jonathan 1432 self.clazz = generate_singletons(list, ramp)
252 jonathan 635 self.parent._SetClassification(self.clazz)
253    
254 jonathan 877 elif genSel == GENCOMBOSTR_QUANTILES:
255    
256     _range = genPanel.GetRange()
257     _list = genPanel.GetList()
258     _list.sort()
259    
260     delta = 1 / float(numGroups)
261     percents = [delta * i for i in range(1, numGroups + 1)]
262     adjusted, self.clazz = \
263 jonathan 1432 generate_quantiles(_list, percents, ramp, _range)
264 jonathan 877
265     if adjusted:
266     dlg = wxMessageDialog(self,
267     _("Based on the data from the table and the input\n" +
268     "values, the exact quantiles could not be generated.\n\n" +
269     "Accept a close estimate?"),
270     _("Problem with Quantiles"),
271    
272     wxYES_NO|wxYES_DEFAULT|wxICON_QUESTION)
273     if dlg.ShowModal() == wxID_YES:
274     self.parent._SetClassification(self.clazz)
275     else:
276     self.parent._SetClassification(self.clazz)
277    
278 jonathan 812 def OnCancel(self, event):
279 jonathan 629 self.Close()
280    
281 jonathan 1391 def OnBorderColorChange(self, event):
282     self.border_color.DoEdit()
283    
284 jonathan 629 def _OnGenTypeSelect(self, event):
285 jonathan 877 self.__DoOnGenTypeSelect()
286     return
287 jonathan 629
288     combo = event.GetEventObject()
289    
290     selIndex = combo.GetSelection()
291    
292     if self.genPanel is not None:
293 jonathan 877 self.topBox.Show(self.genPanel, False)
294 jonathan 629
295     self.genPanel = combo.GetClientData(selIndex)
296     if self.genPanel is not None:
297 jonathan 877 self.topBox.Show(self.genPanel, True)
298 jonathan 629
299 jonathan 877 self.topBox.SetSizeHints(self)
300     self.topBox.Layout()
301 jonathan 629
302 jonathan 635 def _OnPropTypeSelect(self, event):
303     combo = event.GetEventObject()
304 jonathan 629
305 jonathan 635 selIndex = combo.GetSelection()
306     sel = combo.GetString(selIndex)
307    
308     if isinstance(self.propPanel, wxPanel):
309 jonathan 877 self.topBox.Show(self.propPanel, False)
310 jonathan 635
311     self.propPanel = combo.GetClientData(selIndex)
312    
313     if isinstance(self.propPanel, wxPanel):
314 jonathan 877 self.topBox.Show(self.propPanel, True)
315 jonathan 635
316 jonathan 877 self.topBox.SetSizeHints(self)
317     self.topBox.Layout()
318 jonathan 635
319 jonathan 877 def __DoOnGenTypeSelect(self):
320     choice = self.genChoice
321 jonathan 635
322 jonathan 877 sel = choice.GetSelection()
323     if sel == -1: return
324    
325     clazz, obj = choice.GetClientData(sel)
326    
327     if self.curGenPanel is not None:
328     self.curGenPanel.Hide()
329     self.sizer_genPanel.Remove(self.curGenPanel)
330    
331     self.curGenPanel = obj
332     self.curGenPanel.Show()
333    
334     self.sizer_genPanel.Add(self.curGenPanel, 1,
335     wxALL|wxEXPAND|wxADJUST_MINSIZE, 3)
336     self.sizer_genPanel.Layout()
337     self.Layout()
338     self.topBox.SetSizeHints(self)
339    
340 jonathan 629 ID_UNIFORM_MIN = 4001
341     ID_UNIFORM_MAX = 4002
342     ID_UNIFORM_NGROUPS = 4003
343     ID_UNIFORM_STEP = 4004
344     ID_UNIFORM_RETRIEVE = 4005
345    
346     class GenUniformPanel(wxPanel):
347    
348     def __init__(self, parent, layer, fieldName, fieldType):
349 jonathan 607 wxPanel.__init__(self, parent, -1)
350    
351     self.parent = parent
352 jonathan 629 self.layer = layer
353     self.fieldName = fieldName
354 jonathan 607 self.fieldType = fieldType
355    
356 jonathan 629 topSizer = wxStaticBoxSizer(wxStaticBox(self, -1, ""),
357 jonathan 607 wxVERTICAL)
358    
359 jonathan 629 #############
360    
361 jonathan 607 sizer = wxBoxSizer(wxHORIZONTAL)
362    
363     sizer.Add(wxStaticText(self, -1, _("Min:")), 0, wxALL, 4)
364 jonathan 629 self.minCtrl = wxTextCtrl(self, ID_UNIFORM_MIN, style=wxTE_RIGHT)
365     sizer.Add(self.minCtrl, 1, wxALL, 4)
366     EVT_TEXT(self, ID_UNIFORM_MIN, self._OnRangeChanged)
367 jonathan 607
368     sizer.Add(wxStaticText(self, -1, _("Max:")), 0, wxALL, 4)
369 jonathan 629 self.maxCtrl = wxTextCtrl(self, ID_UNIFORM_MAX, style=wxTE_RIGHT)
370     sizer.Add(self.maxCtrl, 1, wxALL, 4)
371     EVT_TEXT(self, ID_UNIFORM_MAX, self._OnRangeChanged)
372 jonathan 607
373 jonathan 629 sizer.Add(wxButton(self, ID_UNIFORM_RETRIEVE, _("Retrieve From Table")),
374     0, wxALL, 4)
375     EVT_BUTTON(self, ID_UNIFORM_RETRIEVE, self._OnRetrieve)
376    
377     topSizer.Add(sizer, 1, wxGROW, 0)
378    
379     #############
380    
381 jonathan 607 sizer = wxBoxSizer(wxHORIZONTAL)
382 jonathan 629
383 jonathan 607 sizer.Add(wxStaticText(self, -1, _("Number of Groups:")), 0, wxALL, 4)
384 jonathan 660 self.numGroupsCtrl = wxSpinCtrl(self, ID_UNIFORM_NGROUPS,
385     style=wxTE_RIGHT)
386 jonathan 629 EVT_TEXT(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)
387     EVT_SPINCTRL(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)
388     sizer.Add(self.numGroupsCtrl, 1, wxALL, 4)
389 jonathan 607
390     sizer.Add(wxStaticText(self, -1, _("Stepping:")), 0, wxALL, 4)
391 jonathan 629 self.stepCtrl = wxTextCtrl(self, ID_UNIFORM_STEP, style=wxTE_RIGHT)
392     EVT_TEXT(self, ID_UNIFORM_STEP, self._OnSteppingChanged)
393     sizer.Add(self.stepCtrl , 1, wxALL, 4)
394 jonathan 607
395 jonathan 629 topSizer.Add(sizer, 1, wxGROW, 0)
396    
397     #############
398    
399 jonathan 607 self.SetSizer(topSizer)
400     self.SetAutoLayout(True)
401     topSizer.SetSizeHints(self)
402    
403     self.numGroupsChanging = False
404     self.steppingChanging = False
405    
406 jonathan 677 self.numGroupsCtrl.SetRange(1, sys.maxint)
407 jonathan 607
408     self.numGroupsCtrl.SetValue(1)
409     self.stepCtrl.SetValue("1")
410     self.maxCtrl.SetValue("0")
411     self.minCtrl.SetValue("0")
412     self.minCtrl.SetFocus()
413    
414     def GetNumGroups(self):
415     value = self.numGroupsCtrl.GetValue()
416     return self.__GetValidatedTypeEntry(self.numGroupsCtrl,
417     value,
418     FIELDTYPE_INT,
419     None)
420    
421     def GetStepping(self):
422     step = self.stepCtrl.GetValue()
423     return self.__GetValidatedTypeEntry(self.stepCtrl,
424     step,
425     self.fieldType,
426     0)
427    
428     def GetMin(self):
429     min = self.minCtrl.GetValue()
430     max = self.maxCtrl.GetValue()
431     return self.__GetValidatedTypeEntry(self.minCtrl,
432     min,
433     self.fieldType,
434     max)
435    
436     def GetMax(self):
437     min = self.minCtrl.GetValue()
438     max = self.maxCtrl.GetValue()
439     return self.__GetValidatedTypeEntry(self.maxCtrl,
440     max,
441     self.fieldType,
442     min)
443    
444     def _OnRangeChanged(self, event):
445    
446     hasFocus = wxWindow_FindFocus() == event.GetEventObject()
447     min = self.GetMin()
448     max = self.GetMax()
449    
450     on = min is not None \
451     and max is not None
452    
453     self.numGroupsCtrl.Enable(on)
454     self.stepCtrl.Enable(on)
455    
456     ngroups = self.GetNumGroups()
457    
458     if ngroups is not None \
459     and min is not None \
460     and max is not None \
461     and ngroups != 0:
462    
463 jonathan 629 #self.stepCtrl.SetValue(str((max - min) / ngroups))
464     self.stepCtrl.SetValue(str(self.__CalcStepping(min, max, ngroups)))
465     #self.numGroupsCtrl.SetValue(ngroups)
466 jonathan 607
467     self.parent.AllowGenerate(self.GetStepping() is not None)
468     else:
469     self.parent.AllowGenerate(False)
470    
471    
472     if hasFocus:
473     event.GetEventObject().SetFocus()
474    
475     def _OnNumGroupsChanged(self, event):
476     if self.steppingChanging:
477     self.steppingChanging = False
478     return
479    
480    
481     obj = event.GetEventObject()
482     ngroups = self.GetNumGroups()
483     min = self.GetMin()
484     max = self.GetMax()
485    
486     if ngroups is not None \
487     and min is not None \
488     and max is not None \
489     and ngroups != 0:
490    
491     #
492     # changing the value in the stepCtrl sends an event
493     # that the control is changing, at which point
494     # we try to update the numGroupsCtrl. This causes
495     # an infinite recursion. This flag and the one
496     # called steppingChanging tries to prevent the recursion.
497     #
498     self.numGroupsChanging = True
499    
500 jonathan 629 self.stepCtrl.SetValue(str(self.__CalcStepping(min, max, ngroups)))
501    
502 jonathan 607 self.parent.AllowGenerate(self.GetStepping() is not None)
503     else:
504     self.parent.AllowGenerate(False)
505    
506    
507     def _OnSteppingChanged(self, event):
508     if self.numGroupsChanging:
509     self.numGroupsChanging = False
510     return
511    
512     step = self.GetStepping()
513     min = self.GetMin()
514     max = self.GetMax()
515    
516     if step is not None \
517     and min is not None \
518     and max is not None \
519     and step != 0:
520    
521     #
522     # see note in _OnNumGroupsChanged
523     #
524     self.steppingChanging = True
525 jonathan 629 self.numGroupsCtrl.SetValue(self.__CalcNumGroups(min, max, step))
526 jonathan 607
527     self.parent.AllowGenerate(self.GetNumGroups() is not None)
528     else:
529     self.parent.AllowGenerate(False)
530    
531 jonathan 629 def _OnRetrieve(self, event):
532 bh 1219 table = self.layer.ShapeStore().Table()
533     if table is not None:
534 jonathan 1274 ThubanBeginBusyCursor()
535 jonathan 1100 try:
536 bh 1219 min, max = table.ValueRange(self.fieldName)
537 jonathan 1100 self.minCtrl.SetValue(str(min))
538     self.maxCtrl.SetValue(str(max))
539     finally:
540 jonathan 1274 ThubanEndBusyCursor()
541 jonathan 629
542 jonathan 607 def __GetValidatedTypeEntry(self, win, value, type, badValue = None):
543    
544     if type == FIELDTYPE_INT:
545     func = int
546     elif type == FIELDTYPE_DOUBLE:
547     func = float
548     elif type == FIELDTYPE_STRING:
549     func = str
550     else:
551     assert False, "Unsupported FIELDTYPE"
552     pass
553    
554     if self.__ValidateEntry(win, value, func, badValue):
555     return func(value)
556    
557     return None
558    
559     def __ValidateEntry(self, win, value, test, badValue = None):
560    
561     valid = value != ""
562    
563     try:
564     if valid:
565     value = test(value)
566    
567     if badValue is not None:
568     valid = value != test(badValue)
569     except ValueError:
570     valid = False
571    
572     if valid:
573     win.SetForegroundColour(wxBLACK)
574     else:
575     win.SetForegroundColour(wxRED)
576    
577 jonathan 620 win.Refresh()
578    
579 jonathan 607 return valid
580 jonathan 629
581     def __CalcStepping(self, min, max, ngroups):
582     if self.fieldType == FIELDTYPE_INT:
583 jonathan 1163 step = int((max - min + 1) / float(ngroups))
584     else:
585     step = (max - min) / float(ngroups)
586 jonathan 629
587     return step
588    
589     def __CalcNumGroups(self, min, max, step):
590     n = int((max - min) / step)
591     if n == 0:
592     n = 1
593    
594     if self.fieldType == FIELDTYPE_INT and step == 1:
595     n += 1
596    
597     return n
598    
599    
600     ID_UNIQUE_RETRIEVE = 4001
601     ID_UNIQUE_USEALL = 4002
602     ID_UNIQUE_USE = 4003
603     ID_UNIQUE_DONTUSE = 4004
604     ID_UNIQUE_USENONE = 4005
605     ID_UNIQUE_SORTAVAIL = 4006
606     ID_UNIQUE_SORTUSE = 4007
607 jonathan 649 ID_UNIQUE_REVAVAIL = 4008
608     ID_UNIQUE_REVUSE = 4009
609 jonathan 629
610     class GenUniquePanel(wxPanel):
611    
612     def __init__(self, parent, layer, fieldName, fieldType):
613     wxPanel.__init__(self, parent, -1)
614    
615     self.parent = parent
616     self.layer = layer
617     self.fieldName = fieldName
618     self.fieldType = fieldType
619    
620     topSizer = wxStaticBoxSizer(wxStaticBox(self, -1, ""),
621     wxVERTICAL)
622    
623    
624 jonathan 649 #bsizer = wxBoxSizer(wxVERTICAL)
625     topSizer.Add(wxButton(self, ID_UNIQUE_RETRIEVE,
626     _("Retrieve From Table")),
627     0, wxALL | wxALIGN_RIGHT, 4)
628    
629     EVT_BUTTON(self, ID_UNIQUE_RETRIEVE, self._OnRetrieve)
630    
631     #topSizer.Add(bsizer, 0, wxALL, 4)
632    
633 jonathan 629 sizer = wxBoxSizer(wxHORIZONTAL)
634    
635     self.dataList = []
636    
637     psizer = wxBoxSizer(wxVERTICAL)
638     self.list_avail = wxListCtrl(self, -1,
639     style=wxLC_REPORT | wxLC_SINGLE_SEL)
640     self.list_avail.InsertColumn(0, "Available")
641     self.list_avail_data = []
642     psizer.Add(self.list_avail, 1, wxGROW, 0)
643    
644 jonathan 649 bsizer = wxBoxSizer(wxHORIZONTAL)
645     bsizer.Add(wxButton(self, ID_UNIQUE_SORTAVAIL, _("Sort")))
646     EVT_BUTTON(self, ID_UNIQUE_SORTAVAIL, self._OnSortList)
647 jonathan 629
648 jonathan 649 bsizer.Add(wxButton(self, ID_UNIQUE_REVAVAIL, _("Reverse")))
649     EVT_BUTTON(self, ID_UNIQUE_REVAVAIL, self._OnReverseList)
650 jonathan 629
651 jonathan 649 psizer.Add(bsizer, 0, wxGROW, 0)
652 jonathan 629 sizer.Add(psizer, 1, wxGROW, 0)
653    
654 jonathan 607
655 jonathan 629 bsizer = wxBoxSizer(wxVERTICAL)
656 jonathan 649
657     bmp = resource.GetBitmapResource(USEALL_BMP, wxBITMAP_TYPE_XPM)
658     bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USEALL, bmp),
659 jonathan 629 0, wxGROW | wxALL, 4)
660 jonathan 649 bmp = resource.GetBitmapResource(USE_BMP, wxBITMAP_TYPE_XPM)
661     bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USE, bmp),
662 jonathan 629 0, wxGROW | wxALL, 4)
663 jonathan 649 bmp = resource.GetBitmapResource(USENOT_BMP, wxBITMAP_TYPE_XPM)
664     bsizer.Add(wxBitmapButton(self, ID_UNIQUE_DONTUSE, bmp),
665 jonathan 629 0, wxGROW | wxALL, 4)
666 jonathan 649 bmp = resource.GetBitmapResource(USENONE_BMP, wxBITMAP_TYPE_XPM)
667     bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USENONE, bmp),
668 jonathan 629 0, wxGROW | wxALL, 4)
669 jonathan 607
670 jonathan 629 EVT_BUTTON(self, ID_UNIQUE_USEALL, self._OnUseAll)
671     EVT_BUTTON(self, ID_UNIQUE_USE, self._OnUse)
672     EVT_BUTTON(self, ID_UNIQUE_DONTUSE, self._OnDontUse)
673     EVT_BUTTON(self, ID_UNIQUE_USENONE, self._OnUseNone)
674 jonathan 607
675 jonathan 629 sizer.Add(bsizer, 0, wxALL | wxALIGN_CENTER_VERTICAL, 4)
676    
677     psizer = wxBoxSizer(wxVERTICAL)
678     self.list_use = wxListCtrl(self, -1,
679     style=wxLC_REPORT | wxLC_SINGLE_SEL)
680     self.list_use.InsertColumn(0, "Use")
681     self.list_use_data = []
682     psizer.Add(self.list_use, 1, wxGROW, 0)
683    
684 jonathan 649 bsizer = wxBoxSizer(wxHORIZONTAL)
685     bsizer.Add(wxButton(self, ID_UNIQUE_SORTUSE, _("Sort")))
686     EVT_BUTTON(self, ID_UNIQUE_SORTUSE, self._OnSortList)
687 jonathan 629
688 jonathan 649 bsizer.Add(wxButton(self, ID_UNIQUE_REVUSE, _("Reverse")))
689     EVT_BUTTON(self, ID_UNIQUE_REVUSE, self._OnReverseList)
690 jonathan 629
691 jonathan 649 psizer.Add(bsizer, 0, wxGROW, 0)
692    
693 jonathan 629 sizer.Add(psizer, 1, wxGROW, 0)
694    
695    
696     topSizer.Add(sizer, 1, wxGROW, 0)
697    
698     self.SetSizer(topSizer)
699     self.SetAutoLayout(True)
700     topSizer.SetSizeHints(self)
701    
702 frank 978 width, height = self.list_avail.GetSizeTuple()
703     self.list_avail.SetColumnWidth(0,width)
704     width, height = self.list_use.GetSizeTuple()
705     self.list_use.SetColumnWidth(0,width)
706    
707 jonathan 629 self.parent.AllowGenerate(False)
708    
709     def GetNumGroups(self):
710     return self.list_use.GetItemCount()
711    
712     def GetValueList(self):
713     list = []
714     for i in range(self.list_use.GetItemCount()):
715     list.append(self.dataList[self.list_use.GetItemData(i)])
716     return list
717    
718 jonathan 649 def _OnSortList(self, event):
719     id = event.GetId()
720 jonathan 629
721 jonathan 649 if id == ID_UNIQUE_SORTUSE:
722     list = self.list_use
723     else:
724     list = self.list_avail
725 jonathan 629
726 jonathan 649 list.SortItems(lambda i1, i2: cmp(self.dataList[i1],
727     self.dataList[i2]))
728    
729     def _OnReverseList(self, event):
730     id = event.GetId()
731    
732     if id == ID_UNIQUE_REVUSE:
733     list = self.list_use
734     else:
735     list = self.list_avail
736    
737     #
738     # always returning 1 reverses the list
739     #
740     list.SortItems(lambda i1, i2: 1)
741    
742 jonathan 629 def _OnRetrieve(self, event):
743     self.list_use.DeleteAllItems()
744     self.list_use_data = []
745     self.list_avail.DeleteAllItems()
746     self.list_avail_data = []
747    
748 jonathan 1274 ThubanBeginBusyCursor()
749     try:
750     list = self.layer.ShapeStore().Table().UniqueValues(self.fieldName)
751     index = 0
752     for v in list:
753     self.dataList.append(v)
754     i = self.list_avail.InsertStringItem(index, str(v))
755     self.list_avail.SetItemData(index, i)
756    
757     self.list_avail_data.append(v)
758     index += 1
759     finally:
760     ThubanEndBusyCursor()
761 jonathan 629
762     def _OnUseAll(self, event):
763     for i in range(self.list_avail.GetItemCount()):
764     self.__MoveListItem(0, self.list_avail, self.list_use)
765    
766     def _OnUse(self, event):
767     self.__MoveSelectedItems(self.list_avail, self.list_use)
768    
769     def _OnDontUse(self, event):
770     self.__MoveSelectedItems(self.list_use, self.list_avail)
771    
772     def _OnUseNone(self, event):
773    
774     for i in range(self.list_use.GetItemCount()):
775     self.__MoveListItem(0, self.list_use, self.list_avail)
776    
777     def __MoveSelectedItems(self, list_src, list_dest):
778     while True:
779     index = list_src.GetNextItem(-1,
780     wxLIST_NEXT_ALL,
781     wxLIST_STATE_SELECTED)
782    
783     if index == -1:
784     break
785    
786     self.__MoveListItem(index, list_src, list_dest)
787    
788    
789     def __MoveListItem(self, index, list_src, list_dest):
790    
791     item = list_src.GetItem(index)
792    
793     x = list_dest.InsertStringItem(
794     list_dest.GetItemCount(),
795     str(self.dataList[item.GetData()]))
796    
797     list_dest.SetItemData(x, item.GetData())
798    
799     list_src.DeleteItem(index)
800    
801     # def _OnListSize(self, event):
802     # list = event.GetEventObject()
803    
804     # list.SetColumnWidth(0, event.GetSize().GetWidth())
805     #
806    
807 jonathan 877 ID_QUANTILES_RANGE = 4001
808     ID_QUANTILES_RETRIEVE = 4002
809    
810     class GenQuantilesPanel(wxPanel):
811    
812     def __init__(self, parent, layer, fieldName, fieldType):
813     wxPanel.__init__(self, parent, -1)
814    
815     self.parent = parent
816     self.layer = layer
817     self.fieldName = fieldName
818     self.fieldType = fieldType
819    
820     topBox = wxStaticBoxSizer(wxStaticBox(self, -1, ""),
821     wxVERTICAL)
822    
823     self.text_range = wxTextCtrl(self, ID_QUANTILES_RANGE, "")
824     self.button_retrieve = wxButton(self, ID_QUANTILES_RETRIEVE,
825     _("Retrieve from Table"))
826    
827     self.spin_numClasses = wxSpinCtrl(self, -1, style=wxTE_RIGHT)
828     self.spin_numClasses.SetRange(1, sys.maxint)
829     self.spin_numClasses.SetValue(1)
830    
831    
832     sizer = wxBoxSizer(wxHORIZONTAL)
833     sizer.Add(wxStaticText(self, -1, _("Apply to Range")), 0, wxALL, 4)
834     sizer.Add(self.text_range, 1, wxALL, 4)
835     sizer.Add(self.button_retrieve, 0, wxALL, 4)
836    
837     topBox.Add(sizer, 0, wxEXPAND, 0)
838    
839     sizer = wxBoxSizer(wxHORIZONTAL)
840     sizer.Add(wxStaticText(self, -1, _("Number of Classes:")), 0, wxALL, 4)
841     sizer.Add(self.spin_numClasses, 1, wxALL, 4)
842    
843     topBox.Add(sizer, 0, wxEXPAND, 0)
844    
845     self.SetSizer(topBox)
846     self.SetAutoLayout(True)
847     topBox.Fit(self)
848     topBox.SetSizeHints(self)
849    
850     EVT_TEXT(self, ID_QUANTILES_RANGE, self.OnRangeText)
851     EVT_BUTTON(self, ID_QUANTILES_RETRIEVE, self.OnRetrieve)
852    
853     self.__range = None
854    
855     def GetNumGroups(self):
856     return self.spin_numClasses.GetValue()
857    
858     def GetRange(self):
859     assert self.__range is not None
860    
861     return self.__range
862    
863     def GetList(self):
864 jonathan 898 _list = []
865 bh 1219 table = self.layer.ShapeStore().Table()
866     if table is not None:
867 jonathan 1274 ThubanBeginBusyCursor()
868 jonathan 1100 try:
869     #
870     # FIXME: Replace with a call to table when the method
871     # has been written to get all the values
872     #
873     for i in range(table.NumRows()):
874     _list.append(table.ReadValue(i, self.fieldName))
875     finally:
876 jonathan 1274 ThubanEndBusyCursor()
877 jonathan 898
878     return _list
879 jonathan 877
880     def OnRangeText(self, event):
881    
882     try:
883     self.__range = Range(self.text_range.GetValue())
884     except ValueError:
885     self.__range = None
886    
887     if self.__range is not None:
888     self.text_range.SetForegroundColour(wxBLACK)
889     else:
890     self.text_range.SetForegroundColour(wxRED)
891    
892     def OnRetrieve(self, event):
893 bh 1219 table = self.layer.ShapeStore().Table()
894     if table is not None:
895 jonathan 1274 ThubanBeginBusyCursor()
896 jonathan 1100 try:
897 bh 1219 min, max = table.ValueRange(self.fieldName)
898 jonathan 1100 self.text_range.SetValue("[" + str(min) + ";" + str(max) + "]")
899     finally:
900 jonathan 1274 ThubanEndBusyCursor()
901 jonathan 877
902 jonathan 629 ID_CUSTOMRAMP_COPYSTART = 4001
903     ID_CUSTOMRAMP_COPYEND = 4002
904     ID_CUSTOMRAMP_EDITSTART = 4003
905     ID_CUSTOMRAMP_EDITEND = 4004
906     ID_CUSTOMRAMP_SPROP = 4005
907     ID_CUSTOMRAMP_EPROP = 4006
908    
909     class CustomRampPanel(wxPanel):
910    
911     def __init__(self, parent, shapeType):
912 jonathan 607 wxPanel.__init__(self, parent, -1)
913    
914 jonathan 629 topSizer = wxStaticBoxSizer(wxStaticBox(self, -1, ""), wxHORIZONTAL)
915 jonathan 607
916 jonathan 629 bsizer = wxBoxSizer(wxVERTICAL)
917     bsizer.Add(wxStaticText(self, -1, _("Start:")), 0, wxALL | wxCENTER, 4)
918     self.startPropCtrl = classifier.ClassGroupPropertiesCtrl(
919     self, ID_CUSTOMRAMP_SPROP,
920     ClassGroupProperties(), shapeType,
921     style=wxSIMPLE_BORDER, size=(40, 20))
922     bsizer.Add(self.startPropCtrl, 1, wxGROW | wxALL | wxCENTER, 4)
923     bsizer.Add(wxButton(self, ID_CUSTOMRAMP_EDITSTART, _("Change")),
924     0, wxGROW | wxALL | wxCENTER, 4)
925    
926     topSizer.Add(bsizer,
927     1, wxALL \
928     | wxSHAPED \
929     | wxALIGN_CENTER_HORIZONTAL \
930     | wxALIGN_CENTER_VERTICAL, \
931     4)
932    
933 jonathan 649 bmp = resource.GetBitmapResource(USE_BMP, wxBITMAP_TYPE_XPM)
934 jonathan 629 bsizer = wxBoxSizer(wxVERTICAL)
935 jonathan 649 bsizer.Add(wxBitmapButton(self, ID_CUSTOMRAMP_COPYSTART, bmp),
936 jonathan 629 0, wxGROW | wxALL, 4)
937 jonathan 649 bmp = resource.GetBitmapResource(USENOT_BMP, wxBITMAP_TYPE_XPM)
938     bsizer.Add(wxBitmapButton(self, ID_CUSTOMRAMP_COPYEND, bmp),
939 jonathan 629 0, wxGROW | wxALL, 4)
940    
941     topSizer.Add(bsizer,
942     0, wxALL \
943     | wxALIGN_CENTER_HORIZONTAL \
944     | wxALIGN_CENTER_VERTICAL,
945     4)
946    
947     bsizer = wxBoxSizer(wxVERTICAL)
948     bsizer.Add(wxStaticText(self, -1, _("End:")), 0, wxALL | wxCENTER, 4)
949     self.endPropCtrl = classifier.ClassGroupPropertiesCtrl(
950     self, ID_CUSTOMRAMP_EPROP,
951     ClassGroupProperties(), shapeType,
952     style=wxSIMPLE_BORDER, size=(40, 20))
953     bsizer.Add(self.endPropCtrl, 1, wxGROW | wxALL | wxCENTER, 4)
954     bsizer.Add(wxButton(self, ID_CUSTOMRAMP_EDITEND, _("Change")),
955     0, wxGROW | wxALL | wxCENTER, 4)
956    
957     topSizer.Add(bsizer,
958     1, wxALL \
959     | wxSHAPED \
960     | wxALIGN_RIGHT \
961     | wxALIGN_CENTER_HORIZONTAL \
962     | wxALIGN_CENTER_VERTICAL,
963     4)
964    
965     EVT_BUTTON(self, ID_CUSTOMRAMP_COPYSTART, self._OnCopyStart)
966     EVT_BUTTON(self, ID_CUSTOMRAMP_COPYEND, self._OnCopyEnd)
967     EVT_BUTTON(self, ID_CUSTOMRAMP_EDITSTART, self._OnEditStart)
968     EVT_BUTTON(self, ID_CUSTOMRAMP_EDITEND, self._OnEditEnd)
969    
970     self.SetSizer(topSizer)
971     self.SetAutoLayout(True)
972     topSizer.SetSizeHints(self)
973    
974 jonathan 635 def GetRamp(self):
975     return CustomRamp(self.startPropCtrl.GetProperties(),
976     self.endPropCtrl.GetProperties())
977 jonathan 629
978     def _OnCopyStart(self, event):
979     self.endPropCtrl.SetProperties(self.startPropCtrl.GetProperties())
980    
981     def _OnCopyEnd(self, event):
982     self.startPropCtrl.SetProperties(self.endPropCtrl.GetProperties())
983    
984     def _OnEditStart(self, event):
985     self.startPropCtrl.DoEdit()
986    
987     def _OnEditEnd(self, event):
988     self.endPropCtrl.DoEdit()
989    
990 jonathan 877

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26