/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/UI/classgen.py
ViewVC logotype

Contents of /branches/WIP-pyshapelib-bramz/Thuban/UI/classgen.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1100 - (show annotations)
Fri May 30 06:28:21 2003 UTC (21 years, 9 months ago) by jonathan
Original Path: trunk/thuban/Thuban/UI/classgen.py
File MIME type: text/x-python
File size: 30680 byte(s)
Use classgen functions that were part
        of the ClassGenerator class. Put try/finally blocks around
        code that uses wxBeginBusyCursor()/wxEndBusyCursor(). Fixes
        RTBug #1904.

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

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26