/[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 877 - (show annotations)
Fri May 9 16:32:17 2003 UTC (21 years, 10 months ago) by jonathan
Original Path: trunk/thuban/Thuban/UI/classgen.py
File MIME type: text/x-python
File size: 29979 byte(s)
Explicit imports.
(ClassGenDialog.__init__): Clean up the code and add support for Quantiles.
(ClassGenDialog.OnOK): Add support for Quantiles.
(GenQuantilesPanel): New. Input panel for Quantiles.
(ClassGenerator, CustomRamp, MonochromaticRamp, GreyRamp, RedRamp,
        GreenRamp, BlueRamp, HotToColdRamp): Move to Thuban/Model/classgen.py

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26