/[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 660 - (show annotations)
Mon Apr 14 14:15:44 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: 33866 byte(s)
(ClassGenDialog.__init__): Actively set the current selections in the combo
boxes. This is needed under Windows.

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26