/[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 711 - (show annotations)
Wed Apr 23 08:46:23 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: 33488 byte(s)
(ClassGenDialog.__init__): Use a wxChoice control instead of a wxComboBox.
        wxChoice controls do not generate events as the uses highlights
        possible choices which fixes problems with resizing the dialog when
        the use selects an option.

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
22 import classifier
23
24 import resource
25
26 from Thuban.common import Str2Num
27
28 ID_CLASSGEN_GEN = 4001
29 ID_CLASSGEN_CLOSE = 4002
30 ID_CLASSGEN_GENCOMBO = 4007
31 ID_CLASSGEN_PROPCOMBO = 4008
32
33 USEALL_BMP = "group_use_all"
34 USE_BMP = "group_use"
35 USENOT_BMP = "group_use_not"
36 USENONE_BMP = "group_use_none"
37
38 GENCOMBOSTR_UNIFORM = _("Uniform Distribution")
39 GENCOMBOSTR_UNIQUE = _("Unique Values")
40
41 PROPCOMBOSTR_CUSTOM = _("Custom Ramp")
42 PROPCOMBOSTR_GREY = _("Grey Ramp")
43 PROPCOMBOSTR_RED = _("Red Ramp")
44 PROPCOMBOSTR_GREEN = _("Green Ramp")
45 PROPCOMBOSTR_BLUE = _("Blue Ramp")
46 PROPCOMBOSTR_HOT2COLD = _("Hot-to-Cold Ramp")
47
48 class ClassGenDialog(wxDialog):
49
50 def __init__(self, parent, layer, fieldName):
51 """Inialize the class generating dialog.
52
53 parent -- this must be an instance of the Classifier class
54 """
55
56 wxDialog.__init__(self, parent, -1, _("Generate Classification"),
57 style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
58
59 self.parent = parent
60 self.clazz = None
61
62 self.type, name, width, prec = layer.table.field_info_by_name(fieldName)
63
64 #############
65 # we need to create genButton first because when we create the
66 # panels they will call AllowGenerate() which uses genButton.
67 #
68 buttonSizer = wxBoxSizer(wxHORIZONTAL)
69 self.genButton = wxButton(self, ID_CLASSGEN_GEN, _("Generate"))
70
71 buttonSizer.Add(self.genButton, 0, wxALL, 4)
72 buttonSizer.Add(60, 20, 0, wxALL, 4)
73 buttonSizer.Add(wxButton(self, ID_CLASSGEN_CLOSE, _("Close")),
74 0, wxALL, 4)
75
76 #############
77
78 sizer = wxBoxSizer(wxVERTICAL)
79
80 sizer.Add(wxStaticText(self, -1, _("Field: %s") % fieldName),
81 0, wxALL, 4)
82 sizer.Add(wxStaticText(
83 self, -1,
84 _("Data Type: %s") % classifier.Classifier.type2string[self.type]),
85 0, wxALL, 4)
86
87 psizer = wxBoxSizer(wxHORIZONTAL)
88 psizer.Add(wxStaticText(self, -1, _("Generate:")),
89 0, wxALIGN_CENTER_VERTICAL, 0)
90
91 self.genCombo = wxChoice(self, ID_CLASSGEN_GENCOMBO)
92 psizer.Add(self.genCombo, 1, wxALL | wxGROW, 4)
93 EVT_CHOICE(self, ID_CLASSGEN_GENCOMBO, self._OnGenTypeSelect)
94
95 sizer.Add(psizer, 0, wxALL | wxGROW, 4)
96
97 #############
98
99 self.genPanel = None
100
101 panel = GenUniquePanel(self, layer, fieldName, self.type)
102 self.genCombo.Append(GENCOMBOSTR_UNIQUE, panel)
103 sizer.Add(panel, 1, wxGROW | wxALL, 4)
104
105 self.genPanel = panel
106
107 if self.type in (FIELDTYPE_INT, FIELDTYPE_DOUBLE):
108 panel = GenUniformPanel(self, layer, fieldName, self.type)
109 self.genCombo.Append(GENCOMBOSTR_UNIFORM, panel)
110 sizer.Add(panel, 1, wxGROW | wxALL, 4)
111 sizer.Show(panel, False)
112
113 self.genCombo.SetSelection(0)
114
115 #############
116
117 psizer = wxBoxSizer(wxHORIZONTAL)
118 psizer.Add(wxStaticText(self, -1, _("Color Scheme:")),
119 0, wxALIGN_CENTER_VERTICAL, 0)
120
121 self.propCombo = wxChoice(self, ID_CLASSGEN_PROPCOMBO)
122 psizer.Add(self.propCombo, 1, wxALL | wxGROW, 4)
123 EVT_CHOICE(self, ID_CLASSGEN_PROPCOMBO, self._OnPropTypeSelect)
124 sizer.Add(psizer, 0, wxALL | wxGROW, 4)
125
126 #############
127
128 self.propPanel = None
129 panel = CustomRampPanel(self, layer.ShapeType())
130 sizer.Add(panel, 1, wxALL | wxGROW, 4)
131 sizer.Show(panel, False)
132
133 self.propCombo.Append(PROPCOMBOSTR_GREY, GreyRamp())
134 self.propCombo.Append(PROPCOMBOSTR_RED, RedRamp())
135 self.propCombo.Append(PROPCOMBOSTR_GREEN, GreenRamp())
136 self.propCombo.Append(PROPCOMBOSTR_BLUE, BlueRamp())
137 self.propCombo.Append(PROPCOMBOSTR_HOT2COLD, HotToColdRamp())
138 self.propCombo.Append(PROPCOMBOSTR_CUSTOM, panel)
139
140 self.propCombo.SetSelection(0)
141
142
143 #############
144
145 sizer.Add(buttonSizer, 0,
146 wxALL | wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL, 4)
147
148
149 self.SetSizer(sizer)
150 self.SetAutoLayout(True)
151 sizer.SetSizeHints(self)
152
153 self.sizer = sizer
154
155 EVT_BUTTON(self, ID_CLASSGEN_GEN, self._OnGenerate)
156 EVT_BUTTON(self, ID_CLASSGEN_CLOSE, self._OnCloseBtn)
157
158 def GetClassification(self):
159 return self.clazz
160
161 def AllowGenerate(self, on):
162 pass #self.genButton.Enable(on)
163
164 def _OnGenerate(self, event):
165
166 index = self.genCombo.GetSelection()
167
168 genSel = self.genCombo.GetString(index)
169 genPanel = self.genCombo.GetClientData(index)
170
171 propPanel = self.propPanel
172
173 if genSel in (GENCOMBOSTR_UNIFORM, GENCOMBOSTR_UNIQUE):
174 numGroups = genPanel.GetNumGroups()
175
176 index = self.propCombo.GetSelection()
177
178 propSel = self.propCombo.GetString(index)
179 propPanel = self.propCombo.GetClientData(index)
180
181 ramp = propPanel.GetRamp()
182
183 if genSel == GENCOMBOSTR_UNIFORM:
184
185 min = genPanel.GetMin()
186 max = genPanel.GetMax()
187
188 if min is not None \
189 and max is not None \
190 and numGroups is not None:
191
192 self.clazz = ClassGenerator().GenUnifromDistribution(
193 min, max, numGroups, ramp,
194 self.type == FIELDTYPE_INT)
195
196 self.parent._SetClassification(self.clazz)
197
198 elif genSel == GENCOMBOSTR_UNIQUE:
199
200 list = genPanel.GetValueList()
201
202 if len(list) > 0 \
203 and numGroups is not None:
204
205 self.clazz = ClassGenerator().GenSingletonsFromList(
206 list, numGroups, ramp)
207
208 self.parent._SetClassification(self.clazz)
209
210 def _OnCloseBtn(self, event):
211 self.Close()
212
213 def _OnGenTypeSelect(self, event):
214
215 combo = event.GetEventObject()
216
217 selIndex = combo.GetSelection()
218
219 if self.genPanel is not None:
220 self.sizer.Show(self.genPanel, False)
221
222 self.genPanel = combo.GetClientData(selIndex)
223 if self.genPanel is not None:
224 self.sizer.Show(self.genPanel, True)
225
226 self.sizer.SetSizeHints(self)
227 self.sizer.Layout()
228
229 def _OnPropTypeSelect(self, event):
230 combo = event.GetEventObject()
231
232 selIndex = combo.GetSelection()
233 sel = combo.GetString(selIndex)
234
235 if isinstance(self.propPanel, wxPanel):
236 self.sizer.Show(self.propPanel, False)
237
238 self.propPanel = combo.GetClientData(selIndex)
239
240 if isinstance(self.propPanel, wxPanel):
241 self.sizer.Show(self.propPanel, True)
242
243 self.sizer.SetSizeHints(self)
244 self.sizer.Layout()
245
246
247 ID_UNIFORM_MIN = 4001
248 ID_UNIFORM_MAX = 4002
249 ID_UNIFORM_NGROUPS = 4003
250 ID_UNIFORM_STEP = 4004
251 ID_UNIFORM_RETRIEVE = 4005
252
253 class GenUniformPanel(wxPanel):
254
255 def __init__(self, parent, layer, fieldName, fieldType):
256 wxPanel.__init__(self, parent, -1)
257
258 self.parent = parent
259 self.layer = layer
260 self.fieldName = fieldName
261 self.fieldType = fieldType
262
263 topSizer = wxStaticBoxSizer(wxStaticBox(self, -1, ""),
264 wxVERTICAL)
265
266 #############
267
268 sizer = wxBoxSizer(wxHORIZONTAL)
269
270 sizer.Add(wxStaticText(self, -1, _("Min:")), 0, wxALL, 4)
271 self.minCtrl = wxTextCtrl(self, ID_UNIFORM_MIN, style=wxTE_RIGHT)
272 sizer.Add(self.minCtrl, 1, wxALL, 4)
273 EVT_TEXT(self, ID_UNIFORM_MIN, self._OnRangeChanged)
274
275 sizer.Add(wxStaticText(self, -1, _("Max:")), 0, wxALL, 4)
276 self.maxCtrl = wxTextCtrl(self, ID_UNIFORM_MAX, style=wxTE_RIGHT)
277 sizer.Add(self.maxCtrl, 1, wxALL, 4)
278 EVT_TEXT(self, ID_UNIFORM_MAX, self._OnRangeChanged)
279
280 sizer.Add(wxButton(self, ID_UNIFORM_RETRIEVE, _("Retrieve From Table")),
281 0, wxALL, 4)
282 EVT_BUTTON(self, ID_UNIFORM_RETRIEVE, self._OnRetrieve)
283
284 topSizer.Add(sizer, 1, wxGROW, 0)
285
286 #############
287
288 sizer = wxBoxSizer(wxHORIZONTAL)
289
290 sizer.Add(wxStaticText(self, -1, _("Number of Groups:")), 0, wxALL, 4)
291 self.numGroupsCtrl = wxSpinCtrl(self, ID_UNIFORM_NGROUPS,
292 style=wxTE_RIGHT)
293 EVT_TEXT(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)
294 EVT_SPINCTRL(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)
295 sizer.Add(self.numGroupsCtrl, 1, wxALL, 4)
296
297 sizer.Add(wxStaticText(self, -1, _("Stepping:")), 0, wxALL, 4)
298 self.stepCtrl = wxTextCtrl(self, ID_UNIFORM_STEP, style=wxTE_RIGHT)
299 EVT_TEXT(self, ID_UNIFORM_STEP, self._OnSteppingChanged)
300 sizer.Add(self.stepCtrl , 1, wxALL, 4)
301
302 topSizer.Add(sizer, 1, wxGROW, 0)
303
304 #############
305
306 self.SetSizer(topSizer)
307 self.SetAutoLayout(True)
308 topSizer.SetSizeHints(self)
309
310 self.numGroupsChanging = False
311 self.steppingChanging = False
312
313 self.numGroupsCtrl.SetRange(1, sys.maxint)
314
315 self.numGroupsCtrl.SetValue(1)
316 self.stepCtrl.SetValue("1")
317 self.maxCtrl.SetValue("0")
318 self.minCtrl.SetValue("0")
319 self.minCtrl.SetFocus()
320
321 def GetNumGroups(self):
322 value = self.numGroupsCtrl.GetValue()
323 return self.__GetValidatedTypeEntry(self.numGroupsCtrl,
324 value,
325 FIELDTYPE_INT,
326 None)
327
328 def GetStepping(self):
329 step = self.stepCtrl.GetValue()
330 return self.__GetValidatedTypeEntry(self.stepCtrl,
331 step,
332 self.fieldType,
333 0)
334
335 def GetMin(self):
336 min = self.minCtrl.GetValue()
337 max = self.maxCtrl.GetValue()
338 return self.__GetValidatedTypeEntry(self.minCtrl,
339 min,
340 self.fieldType,
341 max)
342
343 def GetMax(self):
344 min = self.minCtrl.GetValue()
345 max = self.maxCtrl.GetValue()
346 return self.__GetValidatedTypeEntry(self.maxCtrl,
347 max,
348 self.fieldType,
349 min)
350
351 def _OnRangeChanged(self, event):
352
353 hasFocus = wxWindow_FindFocus() == event.GetEventObject()
354 min = self.GetMin()
355 max = self.GetMax()
356
357 on = min is not None \
358 and max is not None
359
360 self.numGroupsCtrl.Enable(on)
361 self.stepCtrl.Enable(on)
362
363 ngroups = self.GetNumGroups()
364
365 if ngroups is not None \
366 and min is not None \
367 and max is not None \
368 and ngroups != 0:
369
370 #self.stepCtrl.SetValue(str((max - min) / ngroups))
371 self.stepCtrl.SetValue(str(self.__CalcStepping(min, max, ngroups)))
372 #self.numGroupsCtrl.SetValue(ngroups)
373
374 self.parent.AllowGenerate(self.GetStepping() is not None)
375 else:
376 self.parent.AllowGenerate(False)
377
378
379 if hasFocus:
380 event.GetEventObject().SetFocus()
381
382 def _OnNumGroupsChanged(self, event):
383 if self.steppingChanging:
384 self.steppingChanging = False
385 return
386
387
388 obj = event.GetEventObject()
389 ngroups = self.GetNumGroups()
390 min = self.GetMin()
391 max = self.GetMax()
392
393 if ngroups is not None \
394 and min is not None \
395 and max is not None \
396 and ngroups != 0:
397
398 #
399 # changing the value in the stepCtrl sends an event
400 # that the control is changing, at which point
401 # we try to update the numGroupsCtrl. This causes
402 # an infinite recursion. This flag and the one
403 # called steppingChanging tries to prevent the recursion.
404 #
405 self.numGroupsChanging = True
406
407 self.stepCtrl.SetValue(str(self.__CalcStepping(min, max, ngroups)))
408
409 self.parent.AllowGenerate(self.GetStepping() is not None)
410 else:
411 self.parent.AllowGenerate(False)
412
413
414 def _OnSteppingChanged(self, event):
415 if self.numGroupsChanging:
416 self.numGroupsChanging = False
417 return
418
419 step = self.GetStepping()
420 min = self.GetMin()
421 max = self.GetMax()
422
423 if step is not None \
424 and min is not None \
425 and max is not None \
426 and step != 0:
427
428 #
429 # see note in _OnNumGroupsChanged
430 #
431 self.steppingChanging = True
432 self.numGroupsCtrl.SetValue(self.__CalcNumGroups(min, max, step))
433
434 self.parent.AllowGenerate(self.GetNumGroups() is not None)
435 else:
436 self.parent.AllowGenerate(False)
437
438 def _OnRetrieve(self, event):
439
440 if self.layer.table is not None:
441 range = self.layer.table.field_range(self.fieldName)
442 self.minCtrl.SetValue(str(range[0][0]))
443 self.maxCtrl.SetValue(str(range[1][0]))
444
445 def __GetValidatedTypeEntry(self, win, value, type, badValue = None):
446
447 if type == FIELDTYPE_INT:
448 func = int
449 elif type == FIELDTYPE_DOUBLE:
450 func = float
451 elif type == FIELDTYPE_STRING:
452 func = str
453 else:
454 assert False, "Unsupported FIELDTYPE"
455 pass
456
457 if self.__ValidateEntry(win, value, func, badValue):
458 return func(value)
459
460 return None
461
462 def __ValidateEntry(self, win, value, test, badValue = None):
463
464 valid = value != ""
465
466 try:
467 if valid:
468 value = test(value)
469
470 if badValue is not None:
471 valid = value != test(badValue)
472 except ValueError:
473 valid = False
474
475 if valid:
476 win.SetForegroundColour(wxBLACK)
477 else:
478 win.SetForegroundColour(wxRED)
479
480 win.Refresh()
481
482 return valid
483
484 def __CalcStepping(self, min, max, ngroups):
485 step = Str2Num(str((max - min) / float(ngroups)))
486 if self.fieldType == FIELDTYPE_INT:
487 step = int(step)
488
489 return step
490
491 def __CalcNumGroups(self, min, max, step):
492 n = int((max - min) / step)
493 if n == 0:
494 n = 1
495
496 if self.fieldType == FIELDTYPE_INT and step == 1:
497 n += 1
498
499 return n
500
501
502 ID_UNIQUE_RETRIEVE = 4001
503 ID_UNIQUE_USEALL = 4002
504 ID_UNIQUE_USE = 4003
505 ID_UNIQUE_DONTUSE = 4004
506 ID_UNIQUE_USENONE = 4005
507 ID_UNIQUE_SORTAVAIL = 4006
508 ID_UNIQUE_SORTUSE = 4007
509 ID_UNIQUE_REVAVAIL = 4008
510 ID_UNIQUE_REVUSE = 4009
511
512 class GenUniquePanel(wxPanel):
513
514 def __init__(self, parent, layer, fieldName, fieldType):
515 wxPanel.__init__(self, parent, -1)
516
517 self.parent = parent
518 self.layer = layer
519 self.fieldName = fieldName
520 self.fieldType = fieldType
521
522 topSizer = wxStaticBoxSizer(wxStaticBox(self, -1, ""),
523 wxVERTICAL)
524
525
526 #bsizer = wxBoxSizer(wxVERTICAL)
527 topSizer.Add(wxButton(self, ID_UNIQUE_RETRIEVE,
528 _("Retrieve From Table")),
529 0, wxALL | wxALIGN_RIGHT, 4)
530
531 EVT_BUTTON(self, ID_UNIQUE_RETRIEVE, self._OnRetrieve)
532
533 #topSizer.Add(bsizer, 0, wxALL, 4)
534
535 sizer = wxBoxSizer(wxHORIZONTAL)
536
537 self.dataList = []
538
539 psizer = wxBoxSizer(wxVERTICAL)
540 self.list_avail = wxListCtrl(self, -1,
541 style=wxLC_REPORT | wxLC_SINGLE_SEL)
542 self.list_avail.InsertColumn(0, "Available")
543 self.list_avail_data = []
544 psizer.Add(self.list_avail, 1, wxGROW, 0)
545
546 bsizer = wxBoxSizer(wxHORIZONTAL)
547 bsizer.Add(wxButton(self, ID_UNIQUE_SORTAVAIL, _("Sort")))
548 EVT_BUTTON(self, ID_UNIQUE_SORTAVAIL, self._OnSortList)
549
550 bsizer.Add(wxButton(self, ID_UNIQUE_REVAVAIL, _("Reverse")))
551 EVT_BUTTON(self, ID_UNIQUE_REVAVAIL, self._OnReverseList)
552
553 psizer.Add(bsizer, 0, wxGROW, 0)
554 sizer.Add(psizer, 1, wxGROW, 0)
555
556
557 bsizer = wxBoxSizer(wxVERTICAL)
558
559 bmp = resource.GetBitmapResource(USEALL_BMP, wxBITMAP_TYPE_XPM)
560 bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USEALL, bmp),
561 0, wxGROW | wxALL, 4)
562 bmp = resource.GetBitmapResource(USE_BMP, wxBITMAP_TYPE_XPM)
563 bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USE, bmp),
564 0, wxGROW | wxALL, 4)
565 bmp = resource.GetBitmapResource(USENOT_BMP, wxBITMAP_TYPE_XPM)
566 bsizer.Add(wxBitmapButton(self, ID_UNIQUE_DONTUSE, bmp),
567 0, wxGROW | wxALL, 4)
568 bmp = resource.GetBitmapResource(USENONE_BMP, wxBITMAP_TYPE_XPM)
569 bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USENONE, bmp),
570 0, wxGROW | wxALL, 4)
571
572 EVT_BUTTON(self, ID_UNIQUE_USEALL, self._OnUseAll)
573 EVT_BUTTON(self, ID_UNIQUE_USE, self._OnUse)
574 EVT_BUTTON(self, ID_UNIQUE_DONTUSE, self._OnDontUse)
575 EVT_BUTTON(self, ID_UNIQUE_USENONE, self._OnUseNone)
576
577 sizer.Add(bsizer, 0, wxALL | wxALIGN_CENTER_VERTICAL, 4)
578
579 psizer = wxBoxSizer(wxVERTICAL)
580 self.list_use = wxListCtrl(self, -1,
581 style=wxLC_REPORT | wxLC_SINGLE_SEL)
582 self.list_use.InsertColumn(0, "Use")
583 self.list_use_data = []
584 psizer.Add(self.list_use, 1, wxGROW, 0)
585
586 bsizer = wxBoxSizer(wxHORIZONTAL)
587 bsizer.Add(wxButton(self, ID_UNIQUE_SORTUSE, _("Sort")))
588 EVT_BUTTON(self, ID_UNIQUE_SORTUSE, self._OnSortList)
589
590 bsizer.Add(wxButton(self, ID_UNIQUE_REVUSE, _("Reverse")))
591 EVT_BUTTON(self, ID_UNIQUE_REVUSE, self._OnReverseList)
592
593 psizer.Add(bsizer, 0, wxGROW, 0)
594
595 sizer.Add(psizer, 1, wxGROW, 0)
596
597
598 topSizer.Add(sizer, 1, wxGROW, 0)
599
600 self.SetSizer(topSizer)
601 self.SetAutoLayout(True)
602 topSizer.SetSizeHints(self)
603
604 self.parent.AllowGenerate(False)
605
606 self.mylist = ["Hallo", "Welt!", "Wie", "geht", "es", "dir", "?"]
607
608 def GetNumGroups(self):
609 return self.list_use.GetItemCount()
610
611 def GetValueList(self):
612 list = []
613 for i in range(self.list_use.GetItemCount()):
614 list.append(self.dataList[self.list_use.GetItemData(i)])
615 return list
616
617 def _OnSortList(self, event):
618 id = event.GetId()
619
620 if id == ID_UNIQUE_SORTUSE:
621 list = self.list_use
622 else:
623 list = self.list_avail
624
625 list.SortItems(lambda i1, i2: cmp(self.dataList[i1],
626 self.dataList[i2]))
627
628 def _OnReverseList(self, event):
629 id = event.GetId()
630
631 if id == ID_UNIQUE_REVUSE:
632 list = self.list_use
633 else:
634 list = self.list_avail
635
636 #
637 # always returning 1 reverses the list
638 #
639 list.SortItems(lambda i1, i2: 1)
640
641 def _OnRetrieve(self, event):
642 self.list_use.DeleteAllItems()
643 self.list_use_data = []
644 self.list_avail.DeleteAllItems()
645 self.list_avail_data = []
646
647 list = self.layer.table.GetUniqueValues(self.fieldName)
648 index = 0
649 for v in list:
650 self.dataList.append(v)
651 i = self.list_avail.InsertStringItem(index, str(v))
652 self.list_avail.SetItemData(index, i)
653
654 self.list_avail_data.append(v)
655 index += 1
656
657 def _OnUseAll(self, event):
658 for i in range(self.list_avail.GetItemCount()):
659 self.__MoveListItem(0, self.list_avail, self.list_use)
660
661 def _OnUse(self, event):
662 self.__MoveSelectedItems(self.list_avail, self.list_use)
663
664 def _OnDontUse(self, event):
665 self.__MoveSelectedItems(self.list_use, self.list_avail)
666
667 def _OnUseNone(self, event):
668
669 for i in range(self.list_use.GetItemCount()):
670 self.__MoveListItem(0, self.list_use, self.list_avail)
671
672 def __MoveSelectedItems(self, list_src, list_dest):
673 while True:
674 index = list_src.GetNextItem(-1,
675 wxLIST_NEXT_ALL,
676 wxLIST_STATE_SELECTED)
677
678 if index == -1:
679 break
680
681 self.__MoveListItem(index, list_src, list_dest)
682
683
684 def __MoveListItem(self, index, list_src, list_dest):
685
686 item = list_src.GetItem(index)
687
688 x = list_dest.InsertStringItem(
689 list_dest.GetItemCount(),
690 str(self.dataList[item.GetData()]))
691
692 list_dest.SetItemData(x, item.GetData())
693
694 list_src.DeleteItem(index)
695
696 # def _OnListSize(self, event):
697 # list = event.GetEventObject()
698
699 # list.SetColumnWidth(0, event.GetSize().GetWidth())
700 #
701
702 ID_CUSTOMRAMP_COPYSTART = 4001
703 ID_CUSTOMRAMP_COPYEND = 4002
704 ID_CUSTOMRAMP_EDITSTART = 4003
705 ID_CUSTOMRAMP_EDITEND = 4004
706 ID_CUSTOMRAMP_SPROP = 4005
707 ID_CUSTOMRAMP_EPROP = 4006
708
709 class CustomRampPanel(wxPanel):
710
711 def __init__(self, parent, shapeType):
712 wxPanel.__init__(self, parent, -1)
713
714 topSizer = wxStaticBoxSizer(wxStaticBox(self, -1, ""), wxHORIZONTAL)
715
716 bsizer = wxBoxSizer(wxVERTICAL)
717 bsizer.Add(wxStaticText(self, -1, _("Start:")), 0, wxALL | wxCENTER, 4)
718 self.startPropCtrl = classifier.ClassGroupPropertiesCtrl(
719 self, ID_CUSTOMRAMP_SPROP,
720 ClassGroupProperties(), shapeType,
721 style=wxSIMPLE_BORDER, size=(40, 20))
722 bsizer.Add(self.startPropCtrl, 1, wxGROW | wxALL | wxCENTER, 4)
723 bsizer.Add(wxButton(self, ID_CUSTOMRAMP_EDITSTART, _("Change")),
724 0, wxGROW | wxALL | wxCENTER, 4)
725
726 topSizer.Add(bsizer,
727 1, wxALL \
728 | wxSHAPED \
729 | wxALIGN_CENTER_HORIZONTAL \
730 | wxALIGN_CENTER_VERTICAL, \
731 4)
732
733 bmp = resource.GetBitmapResource(USE_BMP, wxBITMAP_TYPE_XPM)
734 bsizer = wxBoxSizer(wxVERTICAL)
735 bsizer.Add(wxBitmapButton(self, ID_CUSTOMRAMP_COPYSTART, bmp),
736 0, wxGROW | wxALL, 4)
737 bmp = resource.GetBitmapResource(USENOT_BMP, wxBITMAP_TYPE_XPM)
738 bsizer.Add(wxBitmapButton(self, ID_CUSTOMRAMP_COPYEND, bmp),
739 0, wxGROW | wxALL, 4)
740
741 topSizer.Add(bsizer,
742 0, wxALL \
743 | wxALIGN_CENTER_HORIZONTAL \
744 | wxALIGN_CENTER_VERTICAL,
745 4)
746
747 bsizer = wxBoxSizer(wxVERTICAL)
748 bsizer.Add(wxStaticText(self, -1, _("End:")), 0, wxALL | wxCENTER, 4)
749 self.endPropCtrl = classifier.ClassGroupPropertiesCtrl(
750 self, ID_CUSTOMRAMP_EPROP,
751 ClassGroupProperties(), shapeType,
752 style=wxSIMPLE_BORDER, size=(40, 20))
753 bsizer.Add(self.endPropCtrl, 1, wxGROW | wxALL | wxCENTER, 4)
754 bsizer.Add(wxButton(self, ID_CUSTOMRAMP_EDITEND, _("Change")),
755 0, wxGROW | wxALL | wxCENTER, 4)
756
757 topSizer.Add(bsizer,
758 1, wxALL \
759 | wxSHAPED \
760 | wxALIGN_RIGHT \
761 | wxALIGN_CENTER_HORIZONTAL \
762 | wxALIGN_CENTER_VERTICAL,
763 4)
764
765 EVT_BUTTON(self, ID_CUSTOMRAMP_COPYSTART, self._OnCopyStart)
766 EVT_BUTTON(self, ID_CUSTOMRAMP_COPYEND, self._OnCopyEnd)
767 EVT_BUTTON(self, ID_CUSTOMRAMP_EDITSTART, self._OnEditStart)
768 EVT_BUTTON(self, ID_CUSTOMRAMP_EDITEND, self._OnEditEnd)
769
770 self.SetSizer(topSizer)
771 self.SetAutoLayout(True)
772 topSizer.SetSizeHints(self)
773
774 def GetRamp(self):
775 return CustomRamp(self.startPropCtrl.GetProperties(),
776 self.endPropCtrl.GetProperties())
777
778 def _OnCopyStart(self, event):
779 self.endPropCtrl.SetProperties(self.startPropCtrl.GetProperties())
780
781 def _OnCopyEnd(self, event):
782 self.startPropCtrl.SetProperties(self.endPropCtrl.GetProperties())
783
784 def _OnEditStart(self, event):
785 self.startPropCtrl.DoEdit()
786
787 def _OnEditEnd(self, event):
788 self.endPropCtrl.DoEdit()
789
790 class ClassGenerator:
791
792 def GenSingletonsFromList(self, list, numGroups, ramp):
793 """Generate a new classification consisting solely of singletons.
794
795 The resulting classification will consist of at most 'numGroups'
796 groups whose group properties ramp between 'prop1' and 'prop2'. There
797 could be fewer groups if 'list' contains fewer that 'numGroups' items.
798
799 list -- any object that implements the iterator interface
800
801 numGroups -- how many groups to generate. This can not be
802 determined while the classification is being
803 generated because the stepping values must
804 be precalculated to ramp between prop1 and prop2.
805
806 prop1 -- initial group property values
807
808 prop2 -- final group property values
809 """
810
811 clazz = Classification()
812 if numGroups == 0: return clazz
813
814 ramp.SetNumGroups(numGroups)
815
816 for value, prop in zip(list, ramp):
817 clazz.AppendGroup(ClassGroupSingleton(value, prop))
818
819 return clazz
820
821 def GenSingletons(self, min, max, numGroups, ramp):
822
823 clazz = Classification()
824
825 #step = int((max - min) / float(numGroups))
826 step = int(Str2Num(str((max - min + 1) / float(numGroups))))
827
828 if numGroups > 0:
829 cur_value = min
830
831 ramp.SetNumGroups(numGroups)
832
833 for prop in ramp:
834 clazz.AppendGroup(
835 ClassGroupSingleton(
836 Str2Num(str(cur_value)),
837 prop))
838 cur_value += step
839
840 return clazz
841
842 def GenUnifromDistribution(self, min, max, numGroups,
843 ramp, intStep = False):
844 """Generate a classification with numGroups range groups
845 each with the same interval.
846
847 intStep -- force the calculated stepping to an integer.
848 Useful if the values are integers but the
849 number of groups specified doesn't evenly
850 divide (max - min).
851 """
852
853 clazz = Classification()
854 if numGroups == 0: return clazz
855
856 ramp.SetNumGroups(numGroups)
857
858 step = Str2Num(str((max - min) / float(numGroups)))
859
860 if intStep:
861 step = int(step)
862
863 cur_min = min
864 cur_max = cur_min + step
865
866 i = 0
867 for prop in ramp:
868
869 if i == (numGroups - 1):
870 cur_max = max
871
872 # this check guards against rounding issues
873 if cur_min != cur_max:
874 clazz.AppendGroup(
875 ClassGroupRange(
876 Str2Num(str(cur_min)),
877 Str2Num(str(cur_max)),
878 prop))
879
880 cur_min = cur_max
881 cur_max += step
882 i += 1
883
884 return clazz
885
886 CLR = 0
887 STEP = 1
888 class CustomRamp:
889
890 def __init__(self, prop1, prop2):
891 self.prop1 = prop1
892 self.prop2 = prop2
893
894 self.count = 0
895
896 def __iter__(self):
897 return self
898
899 def GetRamp(self):
900 return self
901
902 def SetNumGroups(self, num):
903
904 if num <= 0:
905 return False
906
907 self.count = int(num)
908 num = float(num)
909
910 prop1 = self.prop1
911 prop2 = self.prop2
912
913 clr = prop1.GetLineColor()
914 lineColor2 = prop2.GetLineColor()
915
916 self.noLine = clr is not Color.Transparent \
917 and lineColor2 is not Color.Transparent
918
919
920 self.lineInfo = self.__GetColorInfo(prop1.GetLineColor(),
921 prop2.GetLineColor(),
922 num)
923
924 self.fillInfo = self.__GetColorInfo(prop1.GetFill(),
925 prop2.GetFill(),
926 num)
927
928 self.lineWidth = prop1.GetLineWidth()
929 self.lineWidthStep = (prop2.GetLineWidth() - self.lineWidth) / num
930
931 return True
932
933 def next(self):
934 if self.count == 0:
935 raise StopIteration
936
937 prop = ClassGroupProperties()
938
939 if self.lineInfo is None:
940 prop.SetLineColor(Color.Transparent)
941 else:
942 prop.SetLineColor(Color(self.lineInfo[CLR][0] / 255,
943 self.lineInfo[CLR][1] / 255,
944 self.lineInfo[CLR][2] / 255))
945
946 self.lineInfo[CLR][0] += self.lineInfo[STEP][0]
947 self.lineInfo[CLR][1] += self.lineInfo[STEP][1]
948 self.lineInfo[CLR][2] += self.lineInfo[STEP][2]
949
950 if self.fillInfo is None:
951 prop.SetFill(Color.Transparent)
952 else:
953 prop.SetFill(Color(self.fillInfo[CLR][0] / 255,
954 self.fillInfo[CLR][1] / 255,
955 self.fillInfo[CLR][2] / 255))
956
957 self.fillInfo[CLR][0] += self.fillInfo[STEP][0]
958 self.fillInfo[CLR][1] += self.fillInfo[STEP][1]
959 self.fillInfo[CLR][2] += self.fillInfo[STEP][2]
960
961
962 prop.SetLineWidth(int(self.lineWidth))
963 self.lineWidth += self.lineWidthStep
964
965 self.count -= 1
966
967 return prop
968
969 def __GetColorInfo(self, color1, color2, numGroups):
970
971 if color1 is Color.Transparent and color2 is Color.Transparent:
972 #
973 # returning early
974 #
975 return None
976 elif color1 is not Color.Transparent and color2 is Color.Transparent:
977 color = [color1.red * 255,
978 color1.green * 255,
979 color1.blue * 255]
980 step = (0, 0, 0)
981 elif color1 is Color.Transparent and color2 is not Color.Transparent:
982 color = [color2.red * 255,
983 color2.green * 255,
984 color2.blue * 255]
985 step = (0, 0, 0)
986 else:
987 color = [color1.red * 255,
988 color1.green * 255,
989 color1.blue * 255]
990 step = ((color2.red * 255 - color1.red * 255) / numGroups,
991 (color2.green * 255 - color1.green * 255) / numGroups,
992 (color2.blue * 255 - color1.blue * 255) / numGroups)
993
994
995 return (color, step)
996
997 class MonochromaticRamp(CustomRamp):
998 def __init__(self, start, end):
999 sp = ClassGroupProperties()
1000 sp.SetLineColor(start)
1001 sp.SetFill(start)
1002
1003 ep = ClassGroupProperties()
1004 ep.SetLineColor(end)
1005 ep.SetFill(end)
1006
1007 CustomRamp.__init__(self, sp, ep)
1008
1009 class GreyRamp(MonochromaticRamp):
1010 def __init__(self):
1011 MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(0, 0, 0))
1012
1013 class RedRamp(MonochromaticRamp):
1014 def __init__(self):
1015 MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(.8, 0, 0))
1016
1017 class GreenRamp(MonochromaticRamp):
1018 def __init__(self):
1019 MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(0, .8, 0))
1020
1021 class BlueRamp(MonochromaticRamp):
1022 def __init__(self):
1023 MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(0, 0, .8))
1024
1025 class HotToColdRamp:
1026
1027 def __iter__(self):
1028 return self
1029
1030 def GetRamp(self):
1031 return self
1032
1033 def SetNumGroups(self, num):
1034 if num < 0:
1035 return False
1036
1037 self.num = float(num)
1038 self.index = 0
1039
1040 return True
1041
1042 def next(self):
1043 if self.index == self.num:
1044 raise StopIteration
1045
1046 clr = [1.0, 1.0, 1.0]
1047
1048 if self.index < (.25 * self.num):
1049 clr[0] = 0
1050 clr[1] = 4 * self.index / self.num
1051 elif self.index < (.5 * self.num):
1052 clr[0] = 0
1053 clr[2] = 1 + 4 * (.25 * self.num - self.index) / self.num
1054 elif self.index < (.75 * self.num):
1055 clr[0] = 4 * (self.index - .5 * self.num) / self.num
1056 clr[2] = 0
1057 else:
1058 clr[1] = 1 + 4 * (.75 * self.num - self.index) / self.num
1059 clr[2] = 0
1060
1061 self.index += 1
1062
1063 prop = ClassGroupProperties()
1064 prop.SetLineColor(Color(clr[0], clr[1], clr[2]))
1065 prop.SetFill(Color(clr[0], clr[1], clr[2]))
1066
1067 return prop
1068
1069 #class Colors16Ramp:
1070 #
1071 #def __iter__(self):
1072 #return self
1073 #
1074 #def GetRamp(self):
1075 #return self
1076 #
1077 #def SetNumGroups(self, num):
1078 #if num < 0:
1079 #return False
1080 #
1081 #self.index = 0
1082 #
1083 #return True
1084
1085

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26