/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/UI/classgen.py
ViewVC logotype

Annotation of /branches/WIP-pyshapelib-bramz/Thuban/UI/classgen.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 812 - (hide 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 jonathan 607 # 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 jonathan 677 import sys
9    
10 jonathan 607 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 jonathan 629 import classifier
23    
24 jonathan 649 import resource
25    
26 jonathan 635 ID_CLASSGEN_GENCOMBO = 4007
27     ID_CLASSGEN_PROPCOMBO = 4008
28 jonathan 607
29 jonathan 649 USEALL_BMP = "group_use_all"
30     USE_BMP = "group_use"
31     USENOT_BMP = "group_use_not"
32     USENONE_BMP = "group_use_none"
33    
34 jonathan 635 GENCOMBOSTR_UNIFORM = _("Uniform Distribution")
35     GENCOMBOSTR_UNIQUE = _("Unique Values")
36 jonathan 629
37 jonathan 649 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 jonathan 635
44 jonathan 607 class ClassGenDialog(wxDialog):
45    
46 jonathan 629 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 jonathan 607 wxDialog.__init__(self, parent, -1, _("Generate Classification"),
53     style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
54    
55 jonathan 629 self.parent = parent
56 jonathan 607 self.clazz = None
57    
58 jonathan 629 self.type, name, width, prec = layer.table.field_info_by_name(fieldName)
59 jonathan 607
60 jonathan 629 #############
61     # we need to create genButton first because when we create the
62     # panels they will call AllowGenerate() which uses genButton.
63     #
64 jonathan 812 self.genButton = wxButton(self, wxID_OK, _("Generate"))
65     self.genButton.SetDefault()
66 jonathan 629
67 jonathan 812 self.genChoice = wxChoice(self, ID_CLASSGEN_GENCOMBO)
68 jonathan 607
69 jonathan 812 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 jonathan 629 #############
94 jonathan 607
95 jonathan 629 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 jonathan 649 _("Data Type: %s") % classifier.Classifier.type2string[self.type]),
102 jonathan 629 0, wxALL, 4)
103    
104     psizer = wxBoxSizer(wxHORIZONTAL)
105 jonathan 635 psizer.Add(wxStaticText(self, -1, _("Generate:")),
106 jonathan 629 0, wxALIGN_CENTER_VERTICAL, 0)
107 jonathan 728 psizer.Add(self.genChoice, 1, wxALL | wxGROW, 4)
108 jonathan 629
109     sizer.Add(psizer, 0, wxALL | wxGROW, 4)
110 jonathan 812 sizer.Add(self.genPanel, 1, wxGROW | wxALL, 4)
111 jonathan 629
112 jonathan 812 sizer.Show(uniq_panel, True)
113 jonathan 629 if self.type in (FIELDTYPE_INT, FIELDTYPE_DOUBLE):
114 jonathan 812 sizer.Add(uni_panel, 1, wxGROW | wxALL, 4)
115     sizer.Show(uni_panel, False)
116 jonathan 629
117 jonathan 635 psizer = wxBoxSizer(wxHORIZONTAL)
118 jonathan 660 psizer.Add(wxStaticText(self, -1, _("Color Scheme:")),
119 jonathan 635 0, wxALIGN_CENTER_VERTICAL, 0)
120     psizer.Add(self.propCombo, 1, wxALL | wxGROW, 4)
121     sizer.Add(psizer, 0, wxALL | wxGROW, 4)
122 jonathan 629
123 jonathan 812 sizer.Add(custom_ramp_panel, 1, wxGROW | wxALL, 4)
124     sizer.Show(custom_ramp_panel, False)
125 jonathan 629
126 jonathan 812 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 jonathan 607 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 jonathan 629 self.sizer = sizer
139    
140 jonathan 812 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 jonathan 607
145 jonathan 812
146     self.genChoice.SetFocus()
147    
148 jonathan 607 def GetClassification(self):
149     return self.clazz
150    
151     def AllowGenerate(self, on):
152 jonathan 629 pass #self.genButton.Enable(on)
153 jonathan 607
154 jonathan 812 def OnOK(self, event):
155     """This is really the generate button, but we want to override
156     the wxDialog class.
157     """
158 jonathan 607
159 jonathan 728 index = self.genChoice.GetSelection()
160 jonathan 607
161 jonathan 728 genSel = self.genChoice.GetString(index)
162     genPanel = self.genChoice.GetClientData(index)
163 jonathan 635
164 jonathan 629 propPanel = self.propPanel
165 jonathan 607
166 jonathan 635 if genSel in (GENCOMBOSTR_UNIFORM, GENCOMBOSTR_UNIQUE):
167 jonathan 629 numGroups = genPanel.GetNumGroups()
168 jonathan 607
169 jonathan 635 index = self.propCombo.GetSelection()
170 jonathan 629
171 jonathan 635 propSel = self.propCombo.GetString(index)
172     propPanel = self.propCombo.GetClientData(index)
173 jonathan 629
174 jonathan 635 ramp = propPanel.GetRamp()
175 jonathan 629
176 jonathan 635 if genSel == GENCOMBOSTR_UNIFORM:
177 jonathan 629
178 jonathan 635 min = genPanel.GetMin()
179     max = genPanel.GetMax()
180 jonathan 629
181 jonathan 635 if min is not None \
182     and max is not None \
183     and numGroups is not None:
184 jonathan 629
185 jonathan 635 self.clazz = ClassGenerator().GenUnifromDistribution(
186     min, max, numGroups, ramp,
187     self.type == FIELDTYPE_INT)
188 jonathan 629
189 jonathan 635 self.parent._SetClassification(self.clazz)
190 jonathan 629
191 jonathan 635 elif genSel == GENCOMBOSTR_UNIQUE:
192 jonathan 629
193 jonathan 635 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 jonathan 812 def OnCancel(self, event):
204 jonathan 629 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 jonathan 635 def _OnPropTypeSelect(self, event):
223     combo = event.GetEventObject()
224 jonathan 629
225 jonathan 635 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 jonathan 629 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 jonathan 607 wxPanel.__init__(self, parent, -1)
250    
251     self.parent = parent
252 jonathan 629 self.layer = layer
253     self.fieldName = fieldName
254 jonathan 607 self.fieldType = fieldType
255    
256 jonathan 629 topSizer = wxStaticBoxSizer(wxStaticBox(self, -1, ""),
257 jonathan 607 wxVERTICAL)
258    
259 jonathan 629 #############
260    
261 jonathan 607 sizer = wxBoxSizer(wxHORIZONTAL)
262    
263     sizer.Add(wxStaticText(self, -1, _("Min:")), 0, wxALL, 4)
264 jonathan 629 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 jonathan 607
268     sizer.Add(wxStaticText(self, -1, _("Max:")), 0, wxALL, 4)
269 jonathan 629 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 jonathan 607
273 jonathan 629 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 jonathan 607 sizer = wxBoxSizer(wxHORIZONTAL)
282 jonathan 629
283 jonathan 607 sizer.Add(wxStaticText(self, -1, _("Number of Groups:")), 0, wxALL, 4)
284 jonathan 660 self.numGroupsCtrl = wxSpinCtrl(self, ID_UNIFORM_NGROUPS,
285     style=wxTE_RIGHT)
286 jonathan 629 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 jonathan 607
290     sizer.Add(wxStaticText(self, -1, _("Stepping:")), 0, wxALL, 4)
291 jonathan 629 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 jonathan 607
295 jonathan 629 topSizer.Add(sizer, 1, wxGROW, 0)
296    
297     #############
298    
299 jonathan 607 self.SetSizer(topSizer)
300     self.SetAutoLayout(True)
301     topSizer.SetSizeHints(self)
302    
303     self.numGroupsChanging = False
304     self.steppingChanging = False
305    
306 jonathan 677 self.numGroupsCtrl.SetRange(1, sys.maxint)
307 jonathan 607
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 jonathan 629 #self.stepCtrl.SetValue(str((max - min) / ngroups))
364     self.stepCtrl.SetValue(str(self.__CalcStepping(min, max, ngroups)))
365     #self.numGroupsCtrl.SetValue(ngroups)
366 jonathan 607
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 jonathan 629 self.stepCtrl.SetValue(str(self.__CalcStepping(min, max, ngroups)))
401    
402 jonathan 607 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 jonathan 629 self.numGroupsCtrl.SetValue(self.__CalcNumGroups(min, max, step))
426 jonathan 607
427     self.parent.AllowGenerate(self.GetNumGroups() is not None)
428     else:
429     self.parent.AllowGenerate(False)
430    
431 jonathan 629 def _OnRetrieve(self, event):
432    
433     if self.layer.table is not None:
434 jonathan 812 wxBeginBusyCursor()
435 jonathan 629 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 jonathan 812 wxEndBusyCursor()
439 jonathan 629
440 jonathan 607 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 jonathan 620 win.Refresh()
476    
477 jonathan 607 return valid
478 jonathan 629
479     def __CalcStepping(self, min, max, ngroups):
480 jonathan 781 step = (max - min) / float(ngroups)
481 jonathan 629 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 jonathan 649 ID_UNIQUE_REVAVAIL = 4008
505     ID_UNIQUE_REVUSE = 4009
506 jonathan 629
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 jonathan 649 #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 jonathan 629 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 jonathan 649 bsizer = wxBoxSizer(wxHORIZONTAL)
542     bsizer.Add(wxButton(self, ID_UNIQUE_SORTAVAIL, _("Sort")))
543     EVT_BUTTON(self, ID_UNIQUE_SORTAVAIL, self._OnSortList)
544 jonathan 629
545 jonathan 649 bsizer.Add(wxButton(self, ID_UNIQUE_REVAVAIL, _("Reverse")))
546     EVT_BUTTON(self, ID_UNIQUE_REVAVAIL, self._OnReverseList)
547 jonathan 629
548 jonathan 649 psizer.Add(bsizer, 0, wxGROW, 0)
549 jonathan 629 sizer.Add(psizer, 1, wxGROW, 0)
550    
551 jonathan 607
552 jonathan 629 bsizer = wxBoxSizer(wxVERTICAL)
553 jonathan 649
554     bmp = resource.GetBitmapResource(USEALL_BMP, wxBITMAP_TYPE_XPM)
555     bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USEALL, bmp),
556 jonathan 629 0, wxGROW | wxALL, 4)
557 jonathan 649 bmp = resource.GetBitmapResource(USE_BMP, wxBITMAP_TYPE_XPM)
558     bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USE, bmp),
559 jonathan 629 0, wxGROW | wxALL, 4)
560 jonathan 649 bmp = resource.GetBitmapResource(USENOT_BMP, wxBITMAP_TYPE_XPM)
561     bsizer.Add(wxBitmapButton(self, ID_UNIQUE_DONTUSE, bmp),
562 jonathan 629 0, wxGROW | wxALL, 4)
563 jonathan 649 bmp = resource.GetBitmapResource(USENONE_BMP, wxBITMAP_TYPE_XPM)
564     bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USENONE, bmp),
565 jonathan 629 0, wxGROW | wxALL, 4)
566 jonathan 607
567 jonathan 629 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 jonathan 607
572 jonathan 629 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 jonathan 649 bsizer = wxBoxSizer(wxHORIZONTAL)
582     bsizer.Add(wxButton(self, ID_UNIQUE_SORTUSE, _("Sort")))
583     EVT_BUTTON(self, ID_UNIQUE_SORTUSE, self._OnSortList)
584 jonathan 629
585 jonathan 649 bsizer.Add(wxButton(self, ID_UNIQUE_REVUSE, _("Reverse")))
586     EVT_BUTTON(self, ID_UNIQUE_REVUSE, self._OnReverseList)
587 jonathan 629
588 jonathan 649 psizer.Add(bsizer, 0, wxGROW, 0)
589    
590 jonathan 629 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 jonathan 649 def _OnSortList(self, event):
613     id = event.GetId()
614 jonathan 629
615 jonathan 649 if id == ID_UNIQUE_SORTUSE:
616     list = self.list_use
617     else:
618     list = self.list_avail
619 jonathan 629
620 jonathan 649 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 jonathan 629 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 jonathan 607 wxPanel.__init__(self, parent, -1)
708    
709 jonathan 629 topSizer = wxStaticBoxSizer(wxStaticBox(self, -1, ""), wxHORIZONTAL)
710 jonathan 607
711 jonathan 629 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 jonathan 649 bmp = resource.GetBitmapResource(USE_BMP, wxBITMAP_TYPE_XPM)
729 jonathan 629 bsizer = wxBoxSizer(wxVERTICAL)
730 jonathan 649 bsizer.Add(wxBitmapButton(self, ID_CUSTOMRAMP_COPYSTART, bmp),
731 jonathan 629 0, wxGROW | wxALL, 4)
732 jonathan 649 bmp = resource.GetBitmapResource(USENOT_BMP, wxBITMAP_TYPE_XPM)
733     bsizer.Add(wxBitmapButton(self, ID_CUSTOMRAMP_COPYEND, bmp),
734 jonathan 629 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 jonathan 635 def GetRamp(self):
770     return CustomRamp(self.startPropCtrl.GetProperties(),
771     self.endPropCtrl.GetProperties())
772 jonathan 629
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 jonathan 607 class ClassGenerator:
786    
787 jonathan 635 def GenSingletonsFromList(self, list, numGroups, ramp):
788 jonathan 607 """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 jonathan 635 ramp.SetNumGroups(numGroups)
810    
811     for value, prop in zip(list, ramp):
812 jonathan 614 clazz.AppendGroup(ClassGroupSingleton(value, prop))
813 jonathan 607
814     return clazz
815    
816 jonathan 635 def GenSingletons(self, min, max, numGroups, ramp):
817 jonathan 607
818     clazz = Classification()
819 jonathan 629
820     #step = int((max - min) / float(numGroups))
821    
822     if numGroups > 0:
823 jonathan 781
824     step = int((max - min + 1) / float(numGroups))
825 jonathan 629 cur_value = min
826    
827 jonathan 635 ramp.SetNumGroups(numGroups)
828    
829     for prop in ramp:
830 jonathan 781 clazz.AppendGroup(ClassGroupSingleton(cur_value), prop)
831 jonathan 629 cur_value += step
832    
833     return clazz
834    
835     def GenUnifromDistribution(self, min, max, numGroups,
836 jonathan 635 ramp, intStep = False):
837 jonathan 629 """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 jonathan 607 if numGroups == 0: return clazz
848    
849 jonathan 635 ramp.SetNumGroups(numGroups)
850    
851 jonathan 781 step = (max - min) / float(numGroups)
852 jonathan 607
853 jonathan 629 if intStep:
854     step = int(step)
855    
856 jonathan 607 cur_min = min
857     cur_max = cur_min + step
858    
859     i = 0
860 jonathan 635 for prop in ramp:
861 jonathan 607
862     if i == (numGroups - 1):
863     cur_max = max
864    
865     # this check guards against rounding issues
866     if cur_min != cur_max:
867 jonathan 781 clazz.AppendGroup(ClassGroupRange(cur_min, cur_max, prop))
868 jonathan 607
869     cur_min = cur_max
870     cur_max += step
871     i += 1
872    
873     return clazz
874    
875 jonathan 629 CLR = 0
876     STEP = 1
877     class CustomRamp:
878 jonathan 607
879 jonathan 635 def __init__(self, prop1, prop2):
880     self.prop1 = prop1
881     self.prop2 = prop2
882 jonathan 607
883 jonathan 635 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 jonathan 607 self.count = int(num)
897     num = float(num)
898    
899 jonathan 635 prop1 = self.prop1
900     prop2 = self.prop2
901    
902 jonathan 629 clr = prop1.GetLineColor()
903     lineColor2 = prop2.GetLineColor()
904    
905     self.noLine = clr is not Color.Transparent \
906     and lineColor2 is not Color.Transparent
907 jonathan 607
908    
909 jonathan 629 self.lineInfo = self.__GetColorInfo(prop1.GetLineColor(),
910     prop2.GetLineColor(),
911     num)
912 jonathan 607
913 jonathan 629 self.fillInfo = self.__GetColorInfo(prop1.GetFill(),
914     prop2.GetFill(),
915     num)
916 jonathan 607
917 jonathan 629 self.lineWidth = prop1.GetLineWidth()
918     self.lineWidthStep = (prop2.GetLineWidth() - self.lineWidth) / num
919 jonathan 607
920 jonathan 635 return True
921 jonathan 607
922     def next(self):
923     if self.count == 0:
924     raise StopIteration
925    
926     prop = ClassGroupProperties()
927    
928 jonathan 629 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 jonathan 607
935 jonathan 629 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 jonathan 607
939 jonathan 629 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 jonathan 607 self.count -= 1
955    
956     return prop
957    
958 jonathan 629 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 jonathan 635
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 jonathan 649 class GreyRamp(MonochromaticRamp):
999     def __init__(self):
1000 jonathan 654 MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(0, 0, 0))
1001 jonathan 649
1002 jonathan 635 class RedRamp(MonochromaticRamp):
1003     def __init__(self):
1004 jonathan 654 MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(.8, 0, 0))
1005 jonathan 635
1006     class GreenRamp(MonochromaticRamp):
1007     def __init__(self):
1008 jonathan 654 MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(0, .8, 0))
1009 jonathan 635
1010     class BlueRamp(MonochromaticRamp):
1011     def __init__(self):
1012 jonathan 654 MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(0, 0, .8))
1013 jonathan 635
1014 jonathan 649 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