/[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 907 - (show annotations)
Fri May 16 15:01:04 2003 UTC (21 years, 9 months ago) by bh
Original Path: trunk/thuban/Thuban/UI/classgen.py
File MIME type: text/x-python
File size: 30103 byte(s)
* Thuban/Model/table.py (Table): Remove this compatibility alias
for DBFTable.

* test/test_table.py: Import DBFTable as Table because that alias
doesn't exist anymore.

* Thuban/UI/classgen.py: Remove some unused imports

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26