/[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 1341 - (hide annotations)
Tue Jul 1 16:10:42 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: 30937 byte(s)
Fixes RTbug #1972.
(ClassGenDialog.__init__): Color ramps are now instances
        already so we don't need to create any new objects.
(ClassGenDialog.OnOK): Check for numGroups is no longer
        necessary because we never use it.

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