/[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 978 - (show annotations)
Thu May 22 11:40:32 2003 UTC (21 years, 9 months ago) by frank
Original Path: trunk/thuban/Thuban/UI/classgen.py
File MIME type: text/x-python
File size: 30503 byte(s)
UI polishing updates: Place main buttons (OK, Cancel, etc) in the
lower right corner, center labels for selections, initialize controls
in reasonable order for keyboard navigation.
(ClassGenDialog.__DoOnGenTypeSelect): Moved initialization of the
	different classification types from here to __init__.
(GenUniquePanel.__init__): Set the column width of the first field
	in the Field ListCtrl to the full width.

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26