/[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 812 - (show annotations)
Mon May 5 15:04:06 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: 33423 byte(s)
(ClassGenDialog.__init__): Rearrange the
        order that the controls are created so that tabbing works correctly.
(ClassGenDialog.OnOK): Renamed from _OnGenerate() so that the
        wxDialog can handle the default button correctly.
(ClassGenDialog.OnCancel): Renamed from _OnCloseBtn() for the
        same reasons as for OnOK.
(GenUniformPanel._OnRetrieve): Call wxBeginBusyCursor/wxEndBusyCursor
        when we ask the table for the maximum/minimum values of a field
        which could take a very long time.

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26