/[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 677 - (show annotations)
Tue Apr 15 19:21:01 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: 33694 byte(s)
(GenUniformPanel): Fix spin control weirdness by setting the range to
        (1, maxint).

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26