/[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 781 - (show annotations)
Tue Apr 29 16:53:38 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: 33215 byte(s)
Remove all uses of Str2Num.

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26