/[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 978 - (hide annotations)
Thu May 22 11:40:32 2003 UTC (21 years, 9 months ago) by frank
Original Path: trunk/thuban/Thuban/UI/classgen.py
File MIME type: text/x-python
File size: 30503 byte(s)
UI polishing updates: Place main buttons (OK, Cancel, etc) in the
lower right corner, center labels for selections, initialize controls
in reasonable order for keyboard navigation.
(ClassGenDialog.__DoOnGenTypeSelect): Moved initialization of the
	different classification types from here to __init__.
(GenUniquePanel.__init__): Set the column width of the first field
	in the Field ListCtrl to the full width.

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