/[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 1274 - (show annotations)
Fri Jun 20 17:46:04 2003 UTC (21 years, 8 months ago) by jonathan
Original Path: trunk/thuban/Thuban/UI/classgen.py
File MIME type: text/x-python
File size: 31045 byte(s)
 Use Thuban[Begin|End]BusyCursor()
        instead of a direct call to wx[Begin|End]CusyCursor().
(GenUniquePanel._OnRetrieve): Set busy cursor while retrieving
        table data.

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26