/[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 1274 - (hide annotations)
Fri Jun 20 17:46:04 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: 31045 byte(s)
 Use Thuban[Begin|End]BusyCursor()
        instead of a direct call to wx[Begin|End]CusyCursor().
(GenUniquePanel._OnRetrieve): Set busy cursor while retrieving
        table data.

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