/[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 1391 - (hide annotations)
Thu Jul 10 14:54:02 2003 UTC (21 years, 8 months ago) by jonathan
Original Path: trunk/thuban/Thuban/UI/classgen.py
File MIME type: text/x-python
File size: 32448 byte(s)
(ClassGenDialog.__init__): Add controls
        to allow the user to fix line color/width on generated groups.
(ClassGenDialog.OnOK): Use new 'fixes' parameter of the generate_*
        functions to optionally fix group properties.

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 877 CustomRamp, GreyRamp, RedRamp, GreenRamp, BlueRamp, GreenToRedRamp, \
28     HotToColdRamp
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 1341 self.propCombo.Append(PROPCOMBOSTR_GREY, GreyRamp)
140     self.propCombo.Append(PROPCOMBOSTR_RED, RedRamp)
141     self.propCombo.Append(PROPCOMBOSTR_GREEN, GreenRamp)
142     self.propCombo.Append(PROPCOMBOSTR_BLUE, BlueRamp)
143     self.propCombo.Append(PROPCOMBOSTR_GREEN2RED, GreenToRedRamp)
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     lineColor = props.GetLineColor()
229     lineWidth = props.GetLineWidth()
230     else:
231     lineColor = None
232     lineWidth = None
233 jonathan 629
234 jonathan 635 if genSel == GENCOMBOSTR_UNIFORM:
235 jonathan 629
236 jonathan 635 min = genPanel.GetMin()
237     max = genPanel.GetMax()
238 jonathan 629
239 jonathan 635 if min is not None \
240     and max is not None \
241     and numGroups is not None:
242 jonathan 629
243 jonathan 1163 self.clazz = generate_uniform_distribution(
244 jonathan 635 min, max, numGroups, ramp,
245 jonathan 1391 self.type == FIELDTYPE_INT,
246     fixes = (lineColor, lineWidth, None))
247 jonathan 629
248 jonathan 635 self.parent._SetClassification(self.clazz)
249 jonathan 629
250 jonathan 635 elif genSel == GENCOMBOSTR_UNIQUE:
251 jonathan 629
252 jonathan 635 list = genPanel.GetValueList()
253    
254 jonathan 1341 if len(list) > 0:
255 jonathan 1391 self.clazz = generate_singletons(list, ramp,
256     (lineColor, lineWidth, None))
257 jonathan 635 self.parent._SetClassification(self.clazz)
258    
259 jonathan 877 elif genSel == GENCOMBOSTR_QUANTILES:
260    
261     _range = genPanel.GetRange()
262     _list = genPanel.GetList()
263     _list.sort()
264    
265     delta = 1 / float(numGroups)
266     percents = [delta * i for i in range(1, numGroups + 1)]
267     adjusted, self.clazz = \
268 jonathan 1391 generate_quantiles(_list, percents, ramp, _range,
269     (lineColor, lineWidth, None))
270 jonathan 877
271     if adjusted:
272     dlg = wxMessageDialog(self,
273     _("Based on the data from the table and the input\n" +
274     "values, the exact quantiles could not be generated.\n\n" +
275     "Accept a close estimate?"),
276     _("Problem with Quantiles"),
277    
278     wxYES_NO|wxYES_DEFAULT|wxICON_QUESTION)
279     if dlg.ShowModal() == wxID_YES:
280     self.parent._SetClassification(self.clazz)
281     else:
282     self.parent._SetClassification(self.clazz)
283    
284 jonathan 812 def OnCancel(self, event):
285 jonathan 629 self.Close()
286    
287 jonathan 1391 def OnBorderColorChange(self, event):
288     self.border_color.DoEdit()
289    
290 jonathan 629 def _OnGenTypeSelect(self, event):
291 jonathan 877 self.__DoOnGenTypeSelect()
292     return
293 jonathan 629
294     combo = event.GetEventObject()
295    
296     selIndex = combo.GetSelection()
297    
298     if self.genPanel is not None:
299 jonathan 877 self.topBox.Show(self.genPanel, False)
300 jonathan 629
301     self.genPanel = combo.GetClientData(selIndex)
302     if self.genPanel is not None:
303 jonathan 877 self.topBox.Show(self.genPanel, True)
304 jonathan 629
305 jonathan 877 self.topBox.SetSizeHints(self)
306     self.topBox.Layout()
307 jonathan 629
308 jonathan 635 def _OnPropTypeSelect(self, event):
309     combo = event.GetEventObject()
310 jonathan 629
311 jonathan 635 selIndex = combo.GetSelection()
312     sel = combo.GetString(selIndex)
313    
314     if isinstance(self.propPanel, wxPanel):
315 jonathan 877 self.topBox.Show(self.propPanel, False)
316 jonathan 635
317     self.propPanel = combo.GetClientData(selIndex)
318    
319     if isinstance(self.propPanel, wxPanel):
320 jonathan 877 self.topBox.Show(self.propPanel, True)
321 jonathan 635
322 jonathan 877 self.topBox.SetSizeHints(self)
323     self.topBox.Layout()
324 jonathan 635
325 jonathan 877 def __DoOnGenTypeSelect(self):
326     choice = self.genChoice
327 jonathan 635
328 jonathan 877 sel = choice.GetSelection()
329     if sel == -1: return
330    
331     clazz, obj = choice.GetClientData(sel)
332    
333     if self.curGenPanel is not None:
334     self.curGenPanel.Hide()
335     self.sizer_genPanel.Remove(self.curGenPanel)
336    
337     self.curGenPanel = obj
338     self.curGenPanel.Show()
339    
340     self.sizer_genPanel.Add(self.curGenPanel, 1,
341     wxALL|wxEXPAND|wxADJUST_MINSIZE, 3)
342     self.sizer_genPanel.Layout()
343     self.Layout()
344     self.topBox.SetSizeHints(self)
345    
346 jonathan 629 ID_UNIFORM_MIN = 4001
347     ID_UNIFORM_MAX = 4002
348     ID_UNIFORM_NGROUPS = 4003
349     ID_UNIFORM_STEP = 4004
350     ID_UNIFORM_RETRIEVE = 4005
351    
352     class GenUniformPanel(wxPanel):
353    
354     def __init__(self, parent, layer, fieldName, fieldType):
355 jonathan 607 wxPanel.__init__(self, parent, -1)
356    
357     self.parent = parent
358 jonathan 629 self.layer = layer
359     self.fieldName = fieldName
360 jonathan 607 self.fieldType = fieldType
361    
362 jonathan 629 topSizer = wxStaticBoxSizer(wxStaticBox(self, -1, ""),
363 jonathan 607 wxVERTICAL)
364    
365 jonathan 629 #############
366    
367 jonathan 607 sizer = wxBoxSizer(wxHORIZONTAL)
368    
369     sizer.Add(wxStaticText(self, -1, _("Min:")), 0, wxALL, 4)
370 jonathan 629 self.minCtrl = wxTextCtrl(self, ID_UNIFORM_MIN, style=wxTE_RIGHT)
371     sizer.Add(self.minCtrl, 1, wxALL, 4)
372     EVT_TEXT(self, ID_UNIFORM_MIN, self._OnRangeChanged)
373 jonathan 607
374     sizer.Add(wxStaticText(self, -1, _("Max:")), 0, wxALL, 4)
375 jonathan 629 self.maxCtrl = wxTextCtrl(self, ID_UNIFORM_MAX, style=wxTE_RIGHT)
376     sizer.Add(self.maxCtrl, 1, wxALL, 4)
377     EVT_TEXT(self, ID_UNIFORM_MAX, self._OnRangeChanged)
378 jonathan 607
379 jonathan 629 sizer.Add(wxButton(self, ID_UNIFORM_RETRIEVE, _("Retrieve From Table")),
380     0, wxALL, 4)
381     EVT_BUTTON(self, ID_UNIFORM_RETRIEVE, self._OnRetrieve)
382    
383     topSizer.Add(sizer, 1, wxGROW, 0)
384    
385     #############
386    
387 jonathan 607 sizer = wxBoxSizer(wxHORIZONTAL)
388 jonathan 629
389 jonathan 607 sizer.Add(wxStaticText(self, -1, _("Number of Groups:")), 0, wxALL, 4)
390 jonathan 660 self.numGroupsCtrl = wxSpinCtrl(self, ID_UNIFORM_NGROUPS,
391     style=wxTE_RIGHT)
392 jonathan 629 EVT_TEXT(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)
393     EVT_SPINCTRL(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)
394     sizer.Add(self.numGroupsCtrl, 1, wxALL, 4)
395 jonathan 607
396     sizer.Add(wxStaticText(self, -1, _("Stepping:")), 0, wxALL, 4)
397 jonathan 629 self.stepCtrl = wxTextCtrl(self, ID_UNIFORM_STEP, style=wxTE_RIGHT)
398     EVT_TEXT(self, ID_UNIFORM_STEP, self._OnSteppingChanged)
399     sizer.Add(self.stepCtrl , 1, wxALL, 4)
400 jonathan 607
401 jonathan 629 topSizer.Add(sizer, 1, wxGROW, 0)
402    
403     #############
404    
405 jonathan 607 self.SetSizer(topSizer)
406     self.SetAutoLayout(True)
407     topSizer.SetSizeHints(self)
408    
409     self.numGroupsChanging = False
410     self.steppingChanging = False
411    
412 jonathan 677 self.numGroupsCtrl.SetRange(1, sys.maxint)
413 jonathan 607
414     self.numGroupsCtrl.SetValue(1)
415     self.stepCtrl.SetValue("1")
416     self.maxCtrl.SetValue("0")
417     self.minCtrl.SetValue("0")
418     self.minCtrl.SetFocus()
419    
420     def GetNumGroups(self):
421     value = self.numGroupsCtrl.GetValue()
422     return self.__GetValidatedTypeEntry(self.numGroupsCtrl,
423     value,
424     FIELDTYPE_INT,
425     None)
426    
427     def GetStepping(self):
428     step = self.stepCtrl.GetValue()
429     return self.__GetValidatedTypeEntry(self.stepCtrl,
430     step,
431     self.fieldType,
432     0)
433    
434     def GetMin(self):
435     min = self.minCtrl.GetValue()
436     max = self.maxCtrl.GetValue()
437     return self.__GetValidatedTypeEntry(self.minCtrl,
438     min,
439     self.fieldType,
440     max)
441    
442     def GetMax(self):
443     min = self.minCtrl.GetValue()
444     max = self.maxCtrl.GetValue()
445     return self.__GetValidatedTypeEntry(self.maxCtrl,
446     max,
447     self.fieldType,
448     min)
449    
450     def _OnRangeChanged(self, event):
451    
452     hasFocus = wxWindow_FindFocus() == event.GetEventObject()
453     min = self.GetMin()
454     max = self.GetMax()
455    
456     on = min is not None \
457     and max is not None
458    
459     self.numGroupsCtrl.Enable(on)
460     self.stepCtrl.Enable(on)
461    
462     ngroups = self.GetNumGroups()
463    
464     if ngroups is not None \
465     and min is not None \
466     and max is not None \
467     and ngroups != 0:
468    
469 jonathan 629 #self.stepCtrl.SetValue(str((max - min) / ngroups))
470     self.stepCtrl.SetValue(str(self.__CalcStepping(min, max, ngroups)))
471     #self.numGroupsCtrl.SetValue(ngroups)
472 jonathan 607
473     self.parent.AllowGenerate(self.GetStepping() is not None)
474     else:
475     self.parent.AllowGenerate(False)
476    
477    
478     if hasFocus:
479     event.GetEventObject().SetFocus()
480    
481     def _OnNumGroupsChanged(self, event):
482     if self.steppingChanging:
483     self.steppingChanging = False
484     return
485    
486    
487     obj = event.GetEventObject()
488     ngroups = self.GetNumGroups()
489     min = self.GetMin()
490     max = self.GetMax()
491    
492     if ngroups is not None \
493     and min is not None \
494     and max is not None \
495     and ngroups != 0:
496    
497     #
498     # changing the value in the stepCtrl sends an event
499     # that the control is changing, at which point
500     # we try to update the numGroupsCtrl. This causes
501     # an infinite recursion. This flag and the one
502     # called steppingChanging tries to prevent the recursion.
503     #
504     self.numGroupsChanging = True
505    
506 jonathan 629 self.stepCtrl.SetValue(str(self.__CalcStepping(min, max, ngroups)))
507    
508 jonathan 607 self.parent.AllowGenerate(self.GetStepping() is not None)
509     else:
510     self.parent.AllowGenerate(False)
511    
512    
513     def _OnSteppingChanged(self, event):
514     if self.numGroupsChanging:
515     self.numGroupsChanging = False
516     return
517    
518     step = self.GetStepping()
519     min = self.GetMin()
520     max = self.GetMax()
521    
522     if step is not None \
523     and min is not None \
524     and max is not None \
525     and step != 0:
526    
527     #
528     # see note in _OnNumGroupsChanged
529     #
530     self.steppingChanging = True
531 jonathan 629 self.numGroupsCtrl.SetValue(self.__CalcNumGroups(min, max, step))
532 jonathan 607
533     self.parent.AllowGenerate(self.GetNumGroups() is not None)
534     else:
535     self.parent.AllowGenerate(False)
536    
537 jonathan 629 def _OnRetrieve(self, event):
538 bh 1219 table = self.layer.ShapeStore().Table()
539     if table is not None:
540 jonathan 1274 ThubanBeginBusyCursor()
541 jonathan 1100 try:
542 bh 1219 min, max = table.ValueRange(self.fieldName)
543 jonathan 1100 self.minCtrl.SetValue(str(min))
544     self.maxCtrl.SetValue(str(max))
545     finally:
546 jonathan 1274 ThubanEndBusyCursor()
547 jonathan 629
548 jonathan 607 def __GetValidatedTypeEntry(self, win, value, type, badValue = None):
549    
550     if type == FIELDTYPE_INT:
551     func = int
552     elif type == FIELDTYPE_DOUBLE:
553     func = float
554     elif type == FIELDTYPE_STRING:
555     func = str
556     else:
557     assert False, "Unsupported FIELDTYPE"
558     pass
559    
560     if self.__ValidateEntry(win, value, func, badValue):
561     return func(value)
562    
563     return None
564    
565     def __ValidateEntry(self, win, value, test, badValue = None):
566    
567     valid = value != ""
568    
569     try:
570     if valid:
571     value = test(value)
572    
573     if badValue is not None:
574     valid = value != test(badValue)
575     except ValueError:
576     valid = False
577    
578     if valid:
579     win.SetForegroundColour(wxBLACK)
580     else:
581     win.SetForegroundColour(wxRED)
582    
583 jonathan 620 win.Refresh()
584    
585 jonathan 607 return valid
586 jonathan 629
587     def __CalcStepping(self, min, max, ngroups):
588     if self.fieldType == FIELDTYPE_INT:
589 jonathan 1163 step = int((max - min + 1) / float(ngroups))
590     else:
591     step = (max - min) / float(ngroups)
592 jonathan 629
593     return step
594    
595     def __CalcNumGroups(self, min, max, step):
596     n = int((max - min) / step)
597     if n == 0:
598     n = 1
599    
600     if self.fieldType == FIELDTYPE_INT and step == 1:
601     n += 1
602    
603     return n
604    
605    
606     ID_UNIQUE_RETRIEVE = 4001
607     ID_UNIQUE_USEALL = 4002
608     ID_UNIQUE_USE = 4003
609     ID_UNIQUE_DONTUSE = 4004
610     ID_UNIQUE_USENONE = 4005
611     ID_UNIQUE_SORTAVAIL = 4006
612     ID_UNIQUE_SORTUSE = 4007
613 jonathan 649 ID_UNIQUE_REVAVAIL = 4008
614     ID_UNIQUE_REVUSE = 4009
615 jonathan 629
616     class GenUniquePanel(wxPanel):
617    
618     def __init__(self, parent, layer, fieldName, fieldType):
619     wxPanel.__init__(self, parent, -1)
620    
621     self.parent = parent
622     self.layer = layer
623     self.fieldName = fieldName
624     self.fieldType = fieldType
625    
626     topSizer = wxStaticBoxSizer(wxStaticBox(self, -1, ""),
627     wxVERTICAL)
628    
629    
630 jonathan 649 #bsizer = wxBoxSizer(wxVERTICAL)
631     topSizer.Add(wxButton(self, ID_UNIQUE_RETRIEVE,
632     _("Retrieve From Table")),
633     0, wxALL | wxALIGN_RIGHT, 4)
634    
635     EVT_BUTTON(self, ID_UNIQUE_RETRIEVE, self._OnRetrieve)
636    
637     #topSizer.Add(bsizer, 0, wxALL, 4)
638    
639 jonathan 629 sizer = wxBoxSizer(wxHORIZONTAL)
640    
641     self.dataList = []
642    
643     psizer = wxBoxSizer(wxVERTICAL)
644     self.list_avail = wxListCtrl(self, -1,
645     style=wxLC_REPORT | wxLC_SINGLE_SEL)
646     self.list_avail.InsertColumn(0, "Available")
647     self.list_avail_data = []
648     psizer.Add(self.list_avail, 1, wxGROW, 0)
649    
650 jonathan 649 bsizer = wxBoxSizer(wxHORIZONTAL)
651     bsizer.Add(wxButton(self, ID_UNIQUE_SORTAVAIL, _("Sort")))
652     EVT_BUTTON(self, ID_UNIQUE_SORTAVAIL, self._OnSortList)
653 jonathan 629
654 jonathan 649 bsizer.Add(wxButton(self, ID_UNIQUE_REVAVAIL, _("Reverse")))
655     EVT_BUTTON(self, ID_UNIQUE_REVAVAIL, self._OnReverseList)
656 jonathan 629
657 jonathan 649 psizer.Add(bsizer, 0, wxGROW, 0)
658 jonathan 629 sizer.Add(psizer, 1, wxGROW, 0)
659    
660 jonathan 607
661 jonathan 629 bsizer = wxBoxSizer(wxVERTICAL)
662 jonathan 649
663     bmp = resource.GetBitmapResource(USEALL_BMP, wxBITMAP_TYPE_XPM)
664     bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USEALL, bmp),
665 jonathan 629 0, wxGROW | wxALL, 4)
666 jonathan 649 bmp = resource.GetBitmapResource(USE_BMP, wxBITMAP_TYPE_XPM)
667     bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USE, bmp),
668 jonathan 629 0, wxGROW | wxALL, 4)
669 jonathan 649 bmp = resource.GetBitmapResource(USENOT_BMP, wxBITMAP_TYPE_XPM)
670     bsizer.Add(wxBitmapButton(self, ID_UNIQUE_DONTUSE, bmp),
671 jonathan 629 0, wxGROW | wxALL, 4)
672 jonathan 649 bmp = resource.GetBitmapResource(USENONE_BMP, wxBITMAP_TYPE_XPM)
673     bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USENONE, bmp),
674 jonathan 629 0, wxGROW | wxALL, 4)
675 jonathan 607
676 jonathan 629 EVT_BUTTON(self, ID_UNIQUE_USEALL, self._OnUseAll)
677     EVT_BUTTON(self, ID_UNIQUE_USE, self._OnUse)
678     EVT_BUTTON(self, ID_UNIQUE_DONTUSE, self._OnDontUse)
679     EVT_BUTTON(self, ID_UNIQUE_USENONE, self._OnUseNone)
680 jonathan 607
681 jonathan 629 sizer.Add(bsizer, 0, wxALL | wxALIGN_CENTER_VERTICAL, 4)
682    
683     psizer = wxBoxSizer(wxVERTICAL)
684     self.list_use = wxListCtrl(self, -1,
685     style=wxLC_REPORT | wxLC_SINGLE_SEL)
686     self.list_use.InsertColumn(0, "Use")
687     self.list_use_data = []
688     psizer.Add(self.list_use, 1, wxGROW, 0)
689    
690 jonathan 649 bsizer = wxBoxSizer(wxHORIZONTAL)
691     bsizer.Add(wxButton(self, ID_UNIQUE_SORTUSE, _("Sort")))
692     EVT_BUTTON(self, ID_UNIQUE_SORTUSE, self._OnSortList)
693 jonathan 629
694 jonathan 649 bsizer.Add(wxButton(self, ID_UNIQUE_REVUSE, _("Reverse")))
695     EVT_BUTTON(self, ID_UNIQUE_REVUSE, self._OnReverseList)
696 jonathan 629
697 jonathan 649 psizer.Add(bsizer, 0, wxGROW, 0)
698    
699 jonathan 629 sizer.Add(psizer, 1, wxGROW, 0)
700    
701    
702     topSizer.Add(sizer, 1, wxGROW, 0)
703    
704     self.SetSizer(topSizer)
705     self.SetAutoLayout(True)
706     topSizer.SetSizeHints(self)
707    
708 frank 978 width, height = self.list_avail.GetSizeTuple()
709     self.list_avail.SetColumnWidth(0,width)
710     width, height = self.list_use.GetSizeTuple()
711     self.list_use.SetColumnWidth(0,width)
712    
713 jonathan 629 self.parent.AllowGenerate(False)
714    
715     def GetNumGroups(self):
716     return self.list_use.GetItemCount()
717    
718     def GetValueList(self):
719     list = []
720     for i in range(self.list_use.GetItemCount()):
721     list.append(self.dataList[self.list_use.GetItemData(i)])
722     return list
723    
724 jonathan 649 def _OnSortList(self, event):
725     id = event.GetId()
726 jonathan 629
727 jonathan 649 if id == ID_UNIQUE_SORTUSE:
728     list = self.list_use
729     else:
730     list = self.list_avail
731 jonathan 629
732 jonathan 649 list.SortItems(lambda i1, i2: cmp(self.dataList[i1],
733     self.dataList[i2]))
734    
735     def _OnReverseList(self, event):
736     id = event.GetId()
737    
738     if id == ID_UNIQUE_REVUSE:
739     list = self.list_use
740     else:
741     list = self.list_avail
742    
743     #
744     # always returning 1 reverses the list
745     #
746     list.SortItems(lambda i1, i2: 1)
747    
748 jonathan 629 def _OnRetrieve(self, event):
749     self.list_use.DeleteAllItems()
750     self.list_use_data = []
751     self.list_avail.DeleteAllItems()
752     self.list_avail_data = []
753    
754 jonathan 1274 ThubanBeginBusyCursor()
755     try:
756     list = self.layer.ShapeStore().Table().UniqueValues(self.fieldName)
757     index = 0
758     for v in list:
759     self.dataList.append(v)
760     i = self.list_avail.InsertStringItem(index, str(v))
761     self.list_avail.SetItemData(index, i)
762    
763     self.list_avail_data.append(v)
764     index += 1
765     finally:
766     ThubanEndBusyCursor()
767 jonathan 629
768     def _OnUseAll(self, event):
769     for i in range(self.list_avail.GetItemCount()):
770     self.__MoveListItem(0, self.list_avail, self.list_use)
771    
772     def _OnUse(self, event):
773     self.__MoveSelectedItems(self.list_avail, self.list_use)
774    
775     def _OnDontUse(self, event):
776     self.__MoveSelectedItems(self.list_use, self.list_avail)
777    
778     def _OnUseNone(self, event):
779    
780     for i in range(self.list_use.GetItemCount()):
781     self.__MoveListItem(0, self.list_use, self.list_avail)
782    
783     def __MoveSelectedItems(self, list_src, list_dest):
784     while True:
785     index = list_src.GetNextItem(-1,
786     wxLIST_NEXT_ALL,
787     wxLIST_STATE_SELECTED)
788    
789     if index == -1:
790     break
791    
792     self.__MoveListItem(index, list_src, list_dest)
793    
794    
795     def __MoveListItem(self, index, list_src, list_dest):
796    
797     item = list_src.GetItem(index)
798    
799     x = list_dest.InsertStringItem(
800     list_dest.GetItemCount(),
801     str(self.dataList[item.GetData()]))
802    
803     list_dest.SetItemData(x, item.GetData())
804    
805     list_src.DeleteItem(index)
806    
807     # def _OnListSize(self, event):
808     # list = event.GetEventObject()
809    
810     # list.SetColumnWidth(0, event.GetSize().GetWidth())
811     #
812    
813 jonathan 877 ID_QUANTILES_RANGE = 4001
814     ID_QUANTILES_RETRIEVE = 4002
815    
816     class GenQuantilesPanel(wxPanel):
817    
818     def __init__(self, parent, layer, fieldName, fieldType):
819     wxPanel.__init__(self, parent, -1)
820    
821     self.parent = parent
822     self.layer = layer
823     self.fieldName = fieldName
824     self.fieldType = fieldType
825    
826     topBox = wxStaticBoxSizer(wxStaticBox(self, -1, ""),
827     wxVERTICAL)
828    
829     self.text_range = wxTextCtrl(self, ID_QUANTILES_RANGE, "")
830     self.button_retrieve = wxButton(self, ID_QUANTILES_RETRIEVE,
831     _("Retrieve from Table"))
832    
833     self.spin_numClasses = wxSpinCtrl(self, -1, style=wxTE_RIGHT)
834     self.spin_numClasses.SetRange(1, sys.maxint)
835     self.spin_numClasses.SetValue(1)
836    
837    
838     sizer = wxBoxSizer(wxHORIZONTAL)
839     sizer.Add(wxStaticText(self, -1, _("Apply to Range")), 0, wxALL, 4)
840     sizer.Add(self.text_range, 1, wxALL, 4)
841     sizer.Add(self.button_retrieve, 0, wxALL, 4)
842    
843     topBox.Add(sizer, 0, wxEXPAND, 0)
844    
845     sizer = wxBoxSizer(wxHORIZONTAL)
846     sizer.Add(wxStaticText(self, -1, _("Number of Classes:")), 0, wxALL, 4)
847     sizer.Add(self.spin_numClasses, 1, wxALL, 4)
848    
849     topBox.Add(sizer, 0, wxEXPAND, 0)
850    
851     self.SetSizer(topBox)
852     self.SetAutoLayout(True)
853     topBox.Fit(self)
854     topBox.SetSizeHints(self)
855    
856     EVT_TEXT(self, ID_QUANTILES_RANGE, self.OnRangeText)
857     EVT_BUTTON(self, ID_QUANTILES_RETRIEVE, self.OnRetrieve)
858    
859     self.__range = None
860    
861     def GetNumGroups(self):
862     return self.spin_numClasses.GetValue()
863    
864     def GetRange(self):
865     assert self.__range is not None
866    
867     return self.__range
868    
869     def GetList(self):
870 jonathan 898 _list = []
871 bh 1219 table = self.layer.ShapeStore().Table()
872     if table is not None:
873 jonathan 1274 ThubanBeginBusyCursor()
874 jonathan 1100 try:
875     #
876     # FIXME: Replace with a call to table when the method
877     # has been written to get all the values
878     #
879     for i in range(table.NumRows()):
880     _list.append(table.ReadValue(i, self.fieldName))
881     finally:
882 jonathan 1274 ThubanEndBusyCursor()
883 jonathan 898
884     return _list
885 jonathan 877
886     def OnRangeText(self, event):
887    
888     try:
889     self.__range = Range(self.text_range.GetValue())
890     except ValueError:
891     self.__range = None
892    
893     if self.__range is not None:
894     self.text_range.SetForegroundColour(wxBLACK)
895     else:
896     self.text_range.SetForegroundColour(wxRED)
897    
898     def OnRetrieve(self, event):
899 bh 1219 table = self.layer.ShapeStore().Table()
900     if table is not None:
901 jonathan 1274 ThubanBeginBusyCursor()
902 jonathan 1100 try:
903 bh 1219 min, max = table.ValueRange(self.fieldName)
904 jonathan 1100 self.text_range.SetValue("[" + str(min) + ";" + str(max) + "]")
905     finally:
906 jonathan 1274 ThubanEndBusyCursor()
907 jonathan 877
908 jonathan 629 ID_CUSTOMRAMP_COPYSTART = 4001
909     ID_CUSTOMRAMP_COPYEND = 4002
910     ID_CUSTOMRAMP_EDITSTART = 4003
911     ID_CUSTOMRAMP_EDITEND = 4004
912     ID_CUSTOMRAMP_SPROP = 4005
913     ID_CUSTOMRAMP_EPROP = 4006
914    
915     class CustomRampPanel(wxPanel):
916    
917     def __init__(self, parent, shapeType):
918 jonathan 607 wxPanel.__init__(self, parent, -1)
919    
920 jonathan 629 topSizer = wxStaticBoxSizer(wxStaticBox(self, -1, ""), wxHORIZONTAL)
921 jonathan 607
922 jonathan 629 bsizer = wxBoxSizer(wxVERTICAL)
923     bsizer.Add(wxStaticText(self, -1, _("Start:")), 0, wxALL | wxCENTER, 4)
924     self.startPropCtrl = classifier.ClassGroupPropertiesCtrl(
925     self, ID_CUSTOMRAMP_SPROP,
926     ClassGroupProperties(), shapeType,
927     style=wxSIMPLE_BORDER, size=(40, 20))
928     bsizer.Add(self.startPropCtrl, 1, wxGROW | wxALL | wxCENTER, 4)
929     bsizer.Add(wxButton(self, ID_CUSTOMRAMP_EDITSTART, _("Change")),
930     0, wxGROW | wxALL | wxCENTER, 4)
931    
932     topSizer.Add(bsizer,
933     1, wxALL \
934     | wxSHAPED \
935     | wxALIGN_CENTER_HORIZONTAL \
936     | wxALIGN_CENTER_VERTICAL, \
937     4)
938    
939 jonathan 649 bmp = resource.GetBitmapResource(USE_BMP, wxBITMAP_TYPE_XPM)
940 jonathan 629 bsizer = wxBoxSizer(wxVERTICAL)
941 jonathan 649 bsizer.Add(wxBitmapButton(self, ID_CUSTOMRAMP_COPYSTART, bmp),
942 jonathan 629 0, wxGROW | wxALL, 4)
943 jonathan 649 bmp = resource.GetBitmapResource(USENOT_BMP, wxBITMAP_TYPE_XPM)
944     bsizer.Add(wxBitmapButton(self, ID_CUSTOMRAMP_COPYEND, bmp),
945 jonathan 629 0, wxGROW | wxALL, 4)
946    
947     topSizer.Add(bsizer,
948     0, wxALL \
949     | wxALIGN_CENTER_HORIZONTAL \
950     | wxALIGN_CENTER_VERTICAL,
951     4)
952    
953     bsizer = wxBoxSizer(wxVERTICAL)
954     bsizer.Add(wxStaticText(self, -1, _("End:")), 0, wxALL | wxCENTER, 4)
955     self.endPropCtrl = classifier.ClassGroupPropertiesCtrl(
956     self, ID_CUSTOMRAMP_EPROP,
957     ClassGroupProperties(), shapeType,
958     style=wxSIMPLE_BORDER, size=(40, 20))
959     bsizer.Add(self.endPropCtrl, 1, wxGROW | wxALL | wxCENTER, 4)
960     bsizer.Add(wxButton(self, ID_CUSTOMRAMP_EDITEND, _("Change")),
961     0, wxGROW | wxALL | wxCENTER, 4)
962    
963     topSizer.Add(bsizer,
964     1, wxALL \
965     | wxSHAPED \
966     | wxALIGN_RIGHT \
967     | wxALIGN_CENTER_HORIZONTAL \
968     | wxALIGN_CENTER_VERTICAL,
969     4)
970    
971     EVT_BUTTON(self, ID_CUSTOMRAMP_COPYSTART, self._OnCopyStart)
972     EVT_BUTTON(self, ID_CUSTOMRAMP_COPYEND, self._OnCopyEnd)
973     EVT_BUTTON(self, ID_CUSTOMRAMP_EDITSTART, self._OnEditStart)
974     EVT_BUTTON(self, ID_CUSTOMRAMP_EDITEND, self._OnEditEnd)
975    
976     self.SetSizer(topSizer)
977     self.SetAutoLayout(True)
978     topSizer.SetSizeHints(self)
979    
980 jonathan 635 def GetRamp(self):
981     return CustomRamp(self.startPropCtrl.GetProperties(),
982     self.endPropCtrl.GetProperties())
983 jonathan 629
984     def _OnCopyStart(self, event):
985     self.endPropCtrl.SetProperties(self.startPropCtrl.GetProperties())
986    
987     def _OnCopyEnd(self, event):
988     self.startPropCtrl.SetProperties(self.endPropCtrl.GetProperties())
989    
990     def _OnEditStart(self, event):
991     self.startPropCtrl.DoEdit()
992    
993     def _OnEditEnd(self, event):
994     self.endPropCtrl.DoEdit()
995    
996 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