/[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 2191 - (hide annotations)
Thu Apr 22 15:45:01 2004 UTC (20 years, 10 months ago) by jan
Original Path: trunk/thuban/Thuban/UI/classgen.py
File MIME type: text/x-python
File size: 32359 byte(s)
(GenUniquePanel.__init__): Fixed two strings to be i18n now.

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