/[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 1219 - (show annotations)
Mon Jun 16 17:42:54 2003 UTC (21 years, 8 months ago) by bh
Original Path: trunk/thuban/Thuban/UI/classgen.py
File MIME type: text/x-python
File size: 30817 byte(s)
Update to the layer interface: Direct access to the table,
shapetable, shapefile and filename attributes is now actively
deprecated by issuing deprecation warnings for all places where
this happens.

* Thuban/Model/layer.py (Layer.__getattr__): New. Implement access
to the instance variables table, shapetable, shapefile and
filename via __getattr__ so that we can issue a deprecation
warning.
(Layer.SetShapeStore): Don't set the deprecated instance variables
any more
(Layer.SetShapeStore): Don't use deprecated layer instance
variables
(Layer.Destroy): No need to explicitly remove the instance
variables any more
(Layer.GetFieldType, Layer.Shape): Don't use deprecated layer
instance variables

* Thuban/UI/classgen.py (ClassGenDialog.__init__)
(GenUniformPanel._OnRetrieve, GenUniquePanel._OnRetrieve)
(GenQuantilesPanel.GetList, GenQuantilesPanel.OnRetrieve): Don't
use deprecated layer instance variables

* Thuban/UI/classifier.py (Classifier.__init__): Don't use
deprecated layer instance variables

* Thuban/UI/identifyview.py (IdentifyListCtrl.selected_shape)
(IdentifyGridCtrl.selected_shape): Don't set the deprecated layer
instance variables

* Thuban/UI/tableview.py (LayerTableGrid.select_shapes): Don't use
deprecated layer instance variables

* Thuban/UI/mainwindow.py (MainWindow.LayerShowTable): Don't use
deprecated layer instance variables

* Thuban/Model/save.py (SessionSaver.write_layer): Don't use
deprecated layer instance variables

* Thuban/UI/renderer.py (MapRenderer.draw_shape_layer)
(MapRenderer.polygon_render_param): Don't use deprecated layer instance
variables

* test/runtests.py (main): Turn Thuban's deprecation warnings into
errors so that they're cought by the tests

* test/test_load.py (TestSingleLayer.test): Don't use deprecated
layer instance variables

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 ClassGroupProperties
15
16 from Thuban.Model.table import FIELDTYPE_INT, FIELDTYPE_DOUBLE, \
17 FIELDTYPE_STRING
18
19 from Thuban.Model.range import Range
20
21 import classifier, resource
22
23 from Thuban.Model.classgen import \
24 generate_uniform_distribution, generate_singletons, generate_quantiles, \
25 CustomRamp, GreyRamp, RedRamp, GreenRamp, BlueRamp, GreenToRedRamp, \
26 HotToColdRamp
27
28 USEALL_BMP = "group_use_all"
29 USE_BMP = "group_use"
30 USENOT_BMP = "group_use_not"
31 USENONE_BMP = "group_use_none"
32
33 GENCOMBOSTR_UNIFORM = _("Uniform Distribution")
34 GENCOMBOSTR_UNIQUE = _("Unique Values")
35 GENCOMBOSTR_QUANTILES = _("Quantiles from Table")
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_GREEN2RED = _("Green-to-Red Ramp")
43 PROPCOMBOSTR_HOT2COLD = _("Hot-to-Cold Ramp")
44
45 ID_CLASSGEN_GENCOMBO = 4007
46 ID_CLASSGEN_PROPCOMBO = 4008
47
48 class ClassGenDialog(wxDialog):
49
50 def __init__(self, parent, layer, fieldName):
51 """Inialize the class generating dialog.
52
53 parent -- this must be an instance of the Classifier class
54 """
55
56 wxDialog.__init__(self, parent, -1, _("Generate Classification"),
57 style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
58
59 self.parent = parent
60 self.layer = layer
61 self.clazz = None
62
63 col = layer.ShapeStore().Table().Column(fieldName)
64 self.type = col.type
65
66 self.fieldName = fieldName
67 self.fieldType = self.type
68
69 self.curGenPanel = None
70
71 self.genpanels = []
72
73 #############
74 # we need to create genButton first because when we create the
75 # panels they will call AllowGenerate() which uses genButton.
76 #
77 self.genButton = wxButton(self, wxID_OK, _("Generate"))
78 self.genButton.SetDefault()
79 self.cancelButton = wxButton(self, wxID_CANCEL, _("Close"))
80
81 self.genChoice = wxChoice(self, ID_CLASSGEN_GENCOMBO)
82
83 self.genpanels.append((GENCOMBOSTR_UNIQUE, GenUniquePanel))
84 if self.type in (FIELDTYPE_INT, FIELDTYPE_DOUBLE):
85 self.genpanels.append((GENCOMBOSTR_UNIFORM, GenUniformPanel))
86 self.genpanels.append((GENCOMBOSTR_QUANTILES, GenQuantilesPanel))
87
88 for name, clazz in self.genpanels:
89 self.genChoice.Append(name, [clazz, None])
90
91 self.genChoice.SetSelection(0)
92
93 for i in range(self.genChoice.GetCount()):
94 clazz, obj = self.genChoice.GetClientData(i)
95
96 if obj is None:
97 obj = clazz(self, self.layer, self.fieldName, self.fieldType)
98 obj.Hide()
99 self.genChoice.SetClientData(i, [clazz, obj])
100
101
102 #############
103
104 sizer = wxBoxSizer(wxVERTICAL)
105
106 sizer.Add(wxStaticText(self, -1, _("Field: %s") % fieldName),
107 0, wxALL, 4)
108 sizer.Add(wxStaticText(
109 self, -1,
110 _("Data Type: %s") % classifier.Classifier.type2string[self.type]),
111 0, wxALL, 4)
112
113 psizer = wxBoxSizer(wxHORIZONTAL)
114 psizer.Add(wxStaticText(self, -1, _("Generate:")),
115 0, wxALIGN_CENTER_VERTICAL, 0)
116 psizer.Add(self.genChoice, 1, wxALL | wxGROW, 4)
117
118 sizer.Add(psizer, 0, wxALL | wxGROW, 4)
119
120 self.sizer_genPanel = wxBoxSizer(wxVERTICAL)
121 sizer.Add(self.sizer_genPanel, 1, wxGROW | wxALL, 4)
122
123 psizer = wxBoxSizer(wxHORIZONTAL)
124 psizer.Add(wxStaticText(self, -1, _("Color Scheme:")),
125 0, wxALIGN_CENTER_VERTICAL, 0)
126
127 # Properties (Ramp) ComboBox
128 self.propCombo = wxChoice(self, ID_CLASSGEN_PROPCOMBO)
129
130 self.propPanel = None
131 custom_ramp_panel = CustomRampPanel(self, layer.ShapeType())
132
133 self.propCombo.Append(PROPCOMBOSTR_GREY, GreyRamp())
134 self.propCombo.Append(PROPCOMBOSTR_RED, RedRamp())
135 self.propCombo.Append(PROPCOMBOSTR_GREEN, GreenRamp())
136 self.propCombo.Append(PROPCOMBOSTR_BLUE, BlueRamp())
137 self.propCombo.Append(PROPCOMBOSTR_GREEN2RED, GreenToRedRamp())
138 self.propCombo.Append(PROPCOMBOSTR_HOT2COLD, HotToColdRamp())
139 self.propCombo.Append(PROPCOMBOSTR_CUSTOM, custom_ramp_panel)
140
141 self.propCombo.SetSelection(0)
142
143 psizer.Add(self.propCombo, 1, wxALL | wxGROW, 4)
144 sizer.Add(psizer, 0, wxALL | wxGROW, 4)
145
146 sizer.Add(custom_ramp_panel, 1, wxGROW | wxALL, 4)
147 sizer.Show(custom_ramp_panel, False)
148
149 # Finally place the main buttons
150 buttonSizer = wxBoxSizer(wxHORIZONTAL)
151 buttonSizer.Add(self.genButton, 0, wxRIGHT|wxEXPAND, 10)
152 buttonSizer.Add(self.cancelButton, 0, wxRIGHT|wxEXPAND, 10)
153 sizer.Add(buttonSizer, 0, wxALIGN_RIGHT|wxBOTTOM|wxTOP, 10)
154
155 self.SetSizer(sizer)
156 self.SetAutoLayout(True)
157 sizer.SetSizeHints(self)
158
159 self.topBox = sizer
160
161 self.__DoOnGenTypeSelect()
162
163 EVT_CHOICE(self, ID_CLASSGEN_GENCOMBO, self._OnGenTypeSelect)
164 EVT_CHOICE(self, ID_CLASSGEN_PROPCOMBO, self._OnPropTypeSelect)
165 EVT_BUTTON(self, wxID_OK, self.OnOK)
166 EVT_BUTTON(self, wxID_CANCEL, self.OnCancel)
167
168 self.__DoOnGenTypeSelect()
169
170 self.genChoice.SetFocus()
171
172 def GetClassification(self):
173 return self.clazz
174
175 def AllowGenerate(self, on):
176 pass #self.genButton.Enable(on)
177
178 def OnOK(self, event):
179 """This is really the generate button, but we want to override
180 the wxDialog class.
181 """
182
183 index = self.genChoice.GetSelection()
184
185 assert index != -1, "button should be disabled!"
186
187 genSel = self.genChoice.GetString(index)
188 clazz, genPanel = self.genChoice.GetClientData(index)
189
190 propPanel = self.propPanel
191
192 if genSel in (GENCOMBOSTR_UNIFORM, \
193 GENCOMBOSTR_UNIQUE, \
194 GENCOMBOSTR_QUANTILES):
195
196 numGroups = genPanel.GetNumGroups()
197
198 index = self.propCombo.GetSelection()
199
200 propSel = self.propCombo.GetString(index)
201 propPanel = self.propCombo.GetClientData(index)
202
203 ramp = propPanel.GetRamp()
204
205 if genSel == GENCOMBOSTR_UNIFORM:
206
207 min = genPanel.GetMin()
208 max = genPanel.GetMax()
209
210 if min is not None \
211 and max is not None \
212 and numGroups is not None:
213
214 self.clazz = generate_uniform_distribution(
215 min, max, numGroups, ramp,
216 self.type == FIELDTYPE_INT)
217
218 self.parent._SetClassification(self.clazz)
219
220 elif genSel == GENCOMBOSTR_UNIQUE:
221
222 list = genPanel.GetValueList()
223
224 if len(list) > 0 \
225 and numGroups is not None:
226
227 self.clazz = generate_singletons(
228 list, numGroups, ramp)
229
230 self.parent._SetClassification(self.clazz)
231
232 elif genSel == GENCOMBOSTR_QUANTILES:
233
234 _range = genPanel.GetRange()
235 _list = genPanel.GetList()
236 _list.sort()
237
238 delta = 1 / float(numGroups)
239 percents = [delta * i for i in range(1, numGroups + 1)]
240 adjusted, self.clazz = \
241 generate_quantiles(_list, percents, ramp, _range)
242
243 if adjusted:
244 dlg = wxMessageDialog(self,
245 _("Based on the data from the table and the input\n" +
246 "values, the exact quantiles could not be generated.\n\n" +
247 "Accept a close estimate?"),
248 _("Problem with Quantiles"),
249
250 wxYES_NO|wxYES_DEFAULT|wxICON_QUESTION)
251 if dlg.ShowModal() == wxID_YES:
252 self.parent._SetClassification(self.clazz)
253 else:
254 self.parent._SetClassification(self.clazz)
255
256 def OnCancel(self, event):
257 self.Close()
258
259 def _OnGenTypeSelect(self, event):
260 self.__DoOnGenTypeSelect()
261 return
262
263 combo = event.GetEventObject()
264
265 selIndex = combo.GetSelection()
266
267 if self.genPanel is not None:
268 self.topBox.Show(self.genPanel, False)
269
270 self.genPanel = combo.GetClientData(selIndex)
271 if self.genPanel is not None:
272 self.topBox.Show(self.genPanel, True)
273
274 self.topBox.SetSizeHints(self)
275 self.topBox.Layout()
276
277 def _OnPropTypeSelect(self, event):
278 combo = event.GetEventObject()
279
280 selIndex = combo.GetSelection()
281 sel = combo.GetString(selIndex)
282
283 if isinstance(self.propPanel, wxPanel):
284 self.topBox.Show(self.propPanel, False)
285
286 self.propPanel = combo.GetClientData(selIndex)
287
288 if isinstance(self.propPanel, wxPanel):
289 self.topBox.Show(self.propPanel, True)
290
291 self.topBox.SetSizeHints(self)
292 self.topBox.Layout()
293
294 def __DoOnGenTypeSelect(self):
295 choice = self.genChoice
296
297 sel = choice.GetSelection()
298 if sel == -1: return
299
300 clazz, obj = choice.GetClientData(sel)
301
302 if self.curGenPanel is not None:
303 self.curGenPanel.Hide()
304 self.sizer_genPanel.Remove(self.curGenPanel)
305
306 self.curGenPanel = obj
307 self.curGenPanel.Show()
308
309 self.sizer_genPanel.Add(self.curGenPanel, 1,
310 wxALL|wxEXPAND|wxADJUST_MINSIZE, 3)
311 self.sizer_genPanel.Layout()
312 self.Layout()
313 self.topBox.SetSizeHints(self)
314
315 ID_UNIFORM_MIN = 4001
316 ID_UNIFORM_MAX = 4002
317 ID_UNIFORM_NGROUPS = 4003
318 ID_UNIFORM_STEP = 4004
319 ID_UNIFORM_RETRIEVE = 4005
320
321 class GenUniformPanel(wxPanel):
322
323 def __init__(self, parent, layer, fieldName, fieldType):
324 wxPanel.__init__(self, parent, -1)
325
326 self.parent = parent
327 self.layer = layer
328 self.fieldName = fieldName
329 self.fieldType = fieldType
330
331 topSizer = wxStaticBoxSizer(wxStaticBox(self, -1, ""),
332 wxVERTICAL)
333
334 #############
335
336 sizer = wxBoxSizer(wxHORIZONTAL)
337
338 sizer.Add(wxStaticText(self, -1, _("Min:")), 0, wxALL, 4)
339 self.minCtrl = wxTextCtrl(self, ID_UNIFORM_MIN, style=wxTE_RIGHT)
340 sizer.Add(self.minCtrl, 1, wxALL, 4)
341 EVT_TEXT(self, ID_UNIFORM_MIN, self._OnRangeChanged)
342
343 sizer.Add(wxStaticText(self, -1, _("Max:")), 0, wxALL, 4)
344 self.maxCtrl = wxTextCtrl(self, ID_UNIFORM_MAX, style=wxTE_RIGHT)
345 sizer.Add(self.maxCtrl, 1, wxALL, 4)
346 EVT_TEXT(self, ID_UNIFORM_MAX, self._OnRangeChanged)
347
348 sizer.Add(wxButton(self, ID_UNIFORM_RETRIEVE, _("Retrieve From Table")),
349 0, wxALL, 4)
350 EVT_BUTTON(self, ID_UNIFORM_RETRIEVE, self._OnRetrieve)
351
352 topSizer.Add(sizer, 1, wxGROW, 0)
353
354 #############
355
356 sizer = wxBoxSizer(wxHORIZONTAL)
357
358 sizer.Add(wxStaticText(self, -1, _("Number of Groups:")), 0, wxALL, 4)
359 self.numGroupsCtrl = wxSpinCtrl(self, ID_UNIFORM_NGROUPS,
360 style=wxTE_RIGHT)
361 EVT_TEXT(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)
362 EVT_SPINCTRL(self, ID_UNIFORM_NGROUPS, self._OnNumGroupsChanged)
363 sizer.Add(self.numGroupsCtrl, 1, wxALL, 4)
364
365 sizer.Add(wxStaticText(self, -1, _("Stepping:")), 0, wxALL, 4)
366 self.stepCtrl = wxTextCtrl(self, ID_UNIFORM_STEP, style=wxTE_RIGHT)
367 EVT_TEXT(self, ID_UNIFORM_STEP, self._OnSteppingChanged)
368 sizer.Add(self.stepCtrl , 1, wxALL, 4)
369
370 topSizer.Add(sizer, 1, wxGROW, 0)
371
372 #############
373
374 self.SetSizer(topSizer)
375 self.SetAutoLayout(True)
376 topSizer.SetSizeHints(self)
377
378 self.numGroupsChanging = False
379 self.steppingChanging = False
380
381 self.numGroupsCtrl.SetRange(1, sys.maxint)
382
383 self.numGroupsCtrl.SetValue(1)
384 self.stepCtrl.SetValue("1")
385 self.maxCtrl.SetValue("0")
386 self.minCtrl.SetValue("0")
387 self.minCtrl.SetFocus()
388
389 def GetNumGroups(self):
390 value = self.numGroupsCtrl.GetValue()
391 return self.__GetValidatedTypeEntry(self.numGroupsCtrl,
392 value,
393 FIELDTYPE_INT,
394 None)
395
396 def GetStepping(self):
397 step = self.stepCtrl.GetValue()
398 return self.__GetValidatedTypeEntry(self.stepCtrl,
399 step,
400 self.fieldType,
401 0)
402
403 def GetMin(self):
404 min = self.minCtrl.GetValue()
405 max = self.maxCtrl.GetValue()
406 return self.__GetValidatedTypeEntry(self.minCtrl,
407 min,
408 self.fieldType,
409 max)
410
411 def GetMax(self):
412 min = self.minCtrl.GetValue()
413 max = self.maxCtrl.GetValue()
414 return self.__GetValidatedTypeEntry(self.maxCtrl,
415 max,
416 self.fieldType,
417 min)
418
419 def _OnRangeChanged(self, event):
420
421 hasFocus = wxWindow_FindFocus() == event.GetEventObject()
422 min = self.GetMin()
423 max = self.GetMax()
424
425 on = min is not None \
426 and max is not None
427
428 self.numGroupsCtrl.Enable(on)
429 self.stepCtrl.Enable(on)
430
431 ngroups = self.GetNumGroups()
432
433 if ngroups is not None \
434 and min is not None \
435 and max is not None \
436 and ngroups != 0:
437
438 #self.stepCtrl.SetValue(str((max - min) / ngroups))
439 self.stepCtrl.SetValue(str(self.__CalcStepping(min, max, ngroups)))
440 #self.numGroupsCtrl.SetValue(ngroups)
441
442 self.parent.AllowGenerate(self.GetStepping() is not None)
443 else:
444 self.parent.AllowGenerate(False)
445
446
447 if hasFocus:
448 event.GetEventObject().SetFocus()
449
450 def _OnNumGroupsChanged(self, event):
451 if self.steppingChanging:
452 self.steppingChanging = False
453 return
454
455
456 obj = event.GetEventObject()
457 ngroups = self.GetNumGroups()
458 min = self.GetMin()
459 max = self.GetMax()
460
461 if ngroups is not None \
462 and min is not None \
463 and max is not None \
464 and ngroups != 0:
465
466 #
467 # changing the value in the stepCtrl sends an event
468 # that the control is changing, at which point
469 # we try to update the numGroupsCtrl. This causes
470 # an infinite recursion. This flag and the one
471 # called steppingChanging tries to prevent the recursion.
472 #
473 self.numGroupsChanging = True
474
475 self.stepCtrl.SetValue(str(self.__CalcStepping(min, max, ngroups)))
476
477 self.parent.AllowGenerate(self.GetStepping() is not None)
478 else:
479 self.parent.AllowGenerate(False)
480
481
482 def _OnSteppingChanged(self, event):
483 if self.numGroupsChanging:
484 self.numGroupsChanging = False
485 return
486
487 step = self.GetStepping()
488 min = self.GetMin()
489 max = self.GetMax()
490
491 if step is not None \
492 and min is not None \
493 and max is not None \
494 and step != 0:
495
496 #
497 # see note in _OnNumGroupsChanged
498 #
499 self.steppingChanging = True
500 self.numGroupsCtrl.SetValue(self.__CalcNumGroups(min, max, step))
501
502 self.parent.AllowGenerate(self.GetNumGroups() is not None)
503 else:
504 self.parent.AllowGenerate(False)
505
506 def _OnRetrieve(self, event):
507 table = self.layer.ShapeStore().Table()
508 if table is not None:
509 wxBeginBusyCursor()
510 try:
511 min, max = table.ValueRange(self.fieldName)
512 self.minCtrl.SetValue(str(min))
513 self.maxCtrl.SetValue(str(max))
514 finally:
515 wxEndBusyCursor()
516
517 def __GetValidatedTypeEntry(self, win, value, type, badValue = None):
518
519 if type == FIELDTYPE_INT:
520 func = int
521 elif type == FIELDTYPE_DOUBLE:
522 func = float
523 elif type == FIELDTYPE_STRING:
524 func = str
525 else:
526 assert False, "Unsupported FIELDTYPE"
527 pass
528
529 if self.__ValidateEntry(win, value, func, badValue):
530 return func(value)
531
532 return None
533
534 def __ValidateEntry(self, win, value, test, badValue = None):
535
536 valid = value != ""
537
538 try:
539 if valid:
540 value = test(value)
541
542 if badValue is not None:
543 valid = value != test(badValue)
544 except ValueError:
545 valid = False
546
547 if valid:
548 win.SetForegroundColour(wxBLACK)
549 else:
550 win.SetForegroundColour(wxRED)
551
552 win.Refresh()
553
554 return valid
555
556 def __CalcStepping(self, min, max, ngroups):
557 if self.fieldType == FIELDTYPE_INT:
558 step = int((max - min + 1) / float(ngroups))
559 else:
560 step = (max - min) / float(ngroups)
561
562 return step
563
564 def __CalcNumGroups(self, min, max, step):
565 n = int((max - min) / step)
566 if n == 0:
567 n = 1
568
569 if self.fieldType == FIELDTYPE_INT and step == 1:
570 n += 1
571
572 return n
573
574
575 ID_UNIQUE_RETRIEVE = 4001
576 ID_UNIQUE_USEALL = 4002
577 ID_UNIQUE_USE = 4003
578 ID_UNIQUE_DONTUSE = 4004
579 ID_UNIQUE_USENONE = 4005
580 ID_UNIQUE_SORTAVAIL = 4006
581 ID_UNIQUE_SORTUSE = 4007
582 ID_UNIQUE_REVAVAIL = 4008
583 ID_UNIQUE_REVUSE = 4009
584
585 class GenUniquePanel(wxPanel):
586
587 def __init__(self, parent, layer, fieldName, fieldType):
588 wxPanel.__init__(self, parent, -1)
589
590 self.parent = parent
591 self.layer = layer
592 self.fieldName = fieldName
593 self.fieldType = fieldType
594
595 topSizer = wxStaticBoxSizer(wxStaticBox(self, -1, ""),
596 wxVERTICAL)
597
598
599 #bsizer = wxBoxSizer(wxVERTICAL)
600 topSizer.Add(wxButton(self, ID_UNIQUE_RETRIEVE,
601 _("Retrieve From Table")),
602 0, wxALL | wxALIGN_RIGHT, 4)
603
604 EVT_BUTTON(self, ID_UNIQUE_RETRIEVE, self._OnRetrieve)
605
606 #topSizer.Add(bsizer, 0, wxALL, 4)
607
608 sizer = wxBoxSizer(wxHORIZONTAL)
609
610 self.dataList = []
611
612 psizer = wxBoxSizer(wxVERTICAL)
613 self.list_avail = wxListCtrl(self, -1,
614 style=wxLC_REPORT | wxLC_SINGLE_SEL)
615 self.list_avail.InsertColumn(0, "Available")
616 self.list_avail_data = []
617 psizer.Add(self.list_avail, 1, wxGROW, 0)
618
619 bsizer = wxBoxSizer(wxHORIZONTAL)
620 bsizer.Add(wxButton(self, ID_UNIQUE_SORTAVAIL, _("Sort")))
621 EVT_BUTTON(self, ID_UNIQUE_SORTAVAIL, self._OnSortList)
622
623 bsizer.Add(wxButton(self, ID_UNIQUE_REVAVAIL, _("Reverse")))
624 EVT_BUTTON(self, ID_UNIQUE_REVAVAIL, self._OnReverseList)
625
626 psizer.Add(bsizer, 0, wxGROW, 0)
627 sizer.Add(psizer, 1, wxGROW, 0)
628
629
630 bsizer = wxBoxSizer(wxVERTICAL)
631
632 bmp = resource.GetBitmapResource(USEALL_BMP, wxBITMAP_TYPE_XPM)
633 bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USEALL, bmp),
634 0, wxGROW | wxALL, 4)
635 bmp = resource.GetBitmapResource(USE_BMP, wxBITMAP_TYPE_XPM)
636 bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USE, bmp),
637 0, wxGROW | wxALL, 4)
638 bmp = resource.GetBitmapResource(USENOT_BMP, wxBITMAP_TYPE_XPM)
639 bsizer.Add(wxBitmapButton(self, ID_UNIQUE_DONTUSE, bmp),
640 0, wxGROW | wxALL, 4)
641 bmp = resource.GetBitmapResource(USENONE_BMP, wxBITMAP_TYPE_XPM)
642 bsizer.Add(wxBitmapButton(self, ID_UNIQUE_USENONE, bmp),
643 0, wxGROW | wxALL, 4)
644
645 EVT_BUTTON(self, ID_UNIQUE_USEALL, self._OnUseAll)
646 EVT_BUTTON(self, ID_UNIQUE_USE, self._OnUse)
647 EVT_BUTTON(self, ID_UNIQUE_DONTUSE, self._OnDontUse)
648 EVT_BUTTON(self, ID_UNIQUE_USENONE, self._OnUseNone)
649
650 sizer.Add(bsizer, 0, wxALL | wxALIGN_CENTER_VERTICAL, 4)
651
652 psizer = wxBoxSizer(wxVERTICAL)
653 self.list_use = wxListCtrl(self, -1,
654 style=wxLC_REPORT | wxLC_SINGLE_SEL)
655 self.list_use.InsertColumn(0, "Use")
656 self.list_use_data = []
657 psizer.Add(self.list_use, 1, wxGROW, 0)
658
659 bsizer = wxBoxSizer(wxHORIZONTAL)
660 bsizer.Add(wxButton(self, ID_UNIQUE_SORTUSE, _("Sort")))
661 EVT_BUTTON(self, ID_UNIQUE_SORTUSE, self._OnSortList)
662
663 bsizer.Add(wxButton(self, ID_UNIQUE_REVUSE, _("Reverse")))
664 EVT_BUTTON(self, ID_UNIQUE_REVUSE, self._OnReverseList)
665
666 psizer.Add(bsizer, 0, wxGROW, 0)
667
668 sizer.Add(psizer, 1, wxGROW, 0)
669
670
671 topSizer.Add(sizer, 1, wxGROW, 0)
672
673 self.SetSizer(topSizer)
674 self.SetAutoLayout(True)
675 topSizer.SetSizeHints(self)
676
677 width, height = self.list_avail.GetSizeTuple()
678 self.list_avail.SetColumnWidth(0,width)
679 width, height = self.list_use.GetSizeTuple()
680 self.list_use.SetColumnWidth(0,width)
681
682 self.parent.AllowGenerate(False)
683
684 def GetNumGroups(self):
685 return self.list_use.GetItemCount()
686
687 def GetValueList(self):
688 list = []
689 for i in range(self.list_use.GetItemCount()):
690 list.append(self.dataList[self.list_use.GetItemData(i)])
691 return list
692
693 def _OnSortList(self, event):
694 id = event.GetId()
695
696 if id == ID_UNIQUE_SORTUSE:
697 list = self.list_use
698 else:
699 list = self.list_avail
700
701 list.SortItems(lambda i1, i2: cmp(self.dataList[i1],
702 self.dataList[i2]))
703
704 def _OnReverseList(self, event):
705 id = event.GetId()
706
707 if id == ID_UNIQUE_REVUSE:
708 list = self.list_use
709 else:
710 list = self.list_avail
711
712 #
713 # always returning 1 reverses the list
714 #
715 list.SortItems(lambda i1, i2: 1)
716
717 def _OnRetrieve(self, event):
718 self.list_use.DeleteAllItems()
719 self.list_use_data = []
720 self.list_avail.DeleteAllItems()
721 self.list_avail_data = []
722
723 list = self.layer.ShapeStore().Table().UniqueValues(self.fieldName)
724 index = 0
725 for v in list:
726 self.dataList.append(v)
727 i = self.list_avail.InsertStringItem(index, str(v))
728 self.list_avail.SetItemData(index, i)
729
730 self.list_avail_data.append(v)
731 index += 1
732
733 def _OnUseAll(self, event):
734 for i in range(self.list_avail.GetItemCount()):
735 self.__MoveListItem(0, self.list_avail, self.list_use)
736
737 def _OnUse(self, event):
738 self.__MoveSelectedItems(self.list_avail, self.list_use)
739
740 def _OnDontUse(self, event):
741 self.__MoveSelectedItems(self.list_use, self.list_avail)
742
743 def _OnUseNone(self, event):
744
745 for i in range(self.list_use.GetItemCount()):
746 self.__MoveListItem(0, self.list_use, self.list_avail)
747
748 def __MoveSelectedItems(self, list_src, list_dest):
749 while True:
750 index = list_src.GetNextItem(-1,
751 wxLIST_NEXT_ALL,
752 wxLIST_STATE_SELECTED)
753
754 if index == -1:
755 break
756
757 self.__MoveListItem(index, list_src, list_dest)
758
759
760 def __MoveListItem(self, index, list_src, list_dest):
761
762 item = list_src.GetItem(index)
763
764 x = list_dest.InsertStringItem(
765 list_dest.GetItemCount(),
766 str(self.dataList[item.GetData()]))
767
768 list_dest.SetItemData(x, item.GetData())
769
770 list_src.DeleteItem(index)
771
772 # def _OnListSize(self, event):
773 # list = event.GetEventObject()
774
775 # list.SetColumnWidth(0, event.GetSize().GetWidth())
776 #
777
778 ID_QUANTILES_RANGE = 4001
779 ID_QUANTILES_RETRIEVE = 4002
780
781 class GenQuantilesPanel(wxPanel):
782
783 def __init__(self, parent, layer, fieldName, fieldType):
784 wxPanel.__init__(self, parent, -1)
785
786 self.parent = parent
787 self.layer = layer
788 self.fieldName = fieldName
789 self.fieldType = fieldType
790
791 topBox = wxStaticBoxSizer(wxStaticBox(self, -1, ""),
792 wxVERTICAL)
793
794 self.text_range = wxTextCtrl(self, ID_QUANTILES_RANGE, "")
795 self.button_retrieve = wxButton(self, ID_QUANTILES_RETRIEVE,
796 _("Retrieve from Table"))
797
798 self.spin_numClasses = wxSpinCtrl(self, -1, style=wxTE_RIGHT)
799 self.spin_numClasses.SetRange(1, sys.maxint)
800 self.spin_numClasses.SetValue(1)
801
802
803 sizer = wxBoxSizer(wxHORIZONTAL)
804 sizer.Add(wxStaticText(self, -1, _("Apply to Range")), 0, wxALL, 4)
805 sizer.Add(self.text_range, 1, wxALL, 4)
806 sizer.Add(self.button_retrieve, 0, wxALL, 4)
807
808 topBox.Add(sizer, 0, wxEXPAND, 0)
809
810 sizer = wxBoxSizer(wxHORIZONTAL)
811 sizer.Add(wxStaticText(self, -1, _("Number of Classes:")), 0, wxALL, 4)
812 sizer.Add(self.spin_numClasses, 1, wxALL, 4)
813
814 topBox.Add(sizer, 0, wxEXPAND, 0)
815
816 self.SetSizer(topBox)
817 self.SetAutoLayout(True)
818 topBox.Fit(self)
819 topBox.SetSizeHints(self)
820
821 EVT_TEXT(self, ID_QUANTILES_RANGE, self.OnRangeText)
822 EVT_BUTTON(self, ID_QUANTILES_RETRIEVE, self.OnRetrieve)
823
824 self.__range = None
825
826 def GetNumGroups(self):
827 return self.spin_numClasses.GetValue()
828
829 def GetRange(self):
830 assert self.__range is not None
831
832 return self.__range
833
834 def GetList(self):
835 _list = []
836 table = self.layer.ShapeStore().Table()
837 if table is not None:
838 wxBeginBusyCursor()
839 try:
840 #
841 # FIXME: Replace with a call to table when the method
842 # has been written to get all the values
843 #
844 for i in range(table.NumRows()):
845 _list.append(table.ReadValue(i, self.fieldName))
846 finally:
847 wxEndBusyCursor()
848
849 return _list
850
851 def OnRangeText(self, event):
852
853 try:
854 self.__range = Range(self.text_range.GetValue())
855 except ValueError:
856 self.__range = None
857
858 if self.__range is not None:
859 self.text_range.SetForegroundColour(wxBLACK)
860 else:
861 self.text_range.SetForegroundColour(wxRED)
862
863 def OnRetrieve(self, event):
864 table = self.layer.ShapeStore().Table()
865 if table is not None:
866 wxBeginBusyCursor()
867 try:
868 min, max = table.ValueRange(self.fieldName)
869 self.text_range.SetValue("[" + str(min) + ";" + str(max) + "]")
870 finally:
871 wxEndBusyCursor()
872
873 ID_CUSTOMRAMP_COPYSTART = 4001
874 ID_CUSTOMRAMP_COPYEND = 4002
875 ID_CUSTOMRAMP_EDITSTART = 4003
876 ID_CUSTOMRAMP_EDITEND = 4004
877 ID_CUSTOMRAMP_SPROP = 4005
878 ID_CUSTOMRAMP_EPROP = 4006
879
880 class CustomRampPanel(wxPanel):
881
882 def __init__(self, parent, shapeType):
883 wxPanel.__init__(self, parent, -1)
884
885 topSizer = wxStaticBoxSizer(wxStaticBox(self, -1, ""), wxHORIZONTAL)
886
887 bsizer = wxBoxSizer(wxVERTICAL)
888 bsizer.Add(wxStaticText(self, -1, _("Start:")), 0, wxALL | wxCENTER, 4)
889 self.startPropCtrl = classifier.ClassGroupPropertiesCtrl(
890 self, ID_CUSTOMRAMP_SPROP,
891 ClassGroupProperties(), shapeType,
892 style=wxSIMPLE_BORDER, size=(40, 20))
893 bsizer.Add(self.startPropCtrl, 1, wxGROW | wxALL | wxCENTER, 4)
894 bsizer.Add(wxButton(self, ID_CUSTOMRAMP_EDITSTART, _("Change")),
895 0, wxGROW | wxALL | wxCENTER, 4)
896
897 topSizer.Add(bsizer,
898 1, wxALL \
899 | wxSHAPED \
900 | wxALIGN_CENTER_HORIZONTAL \
901 | wxALIGN_CENTER_VERTICAL, \
902 4)
903
904 bmp = resource.GetBitmapResource(USE_BMP, wxBITMAP_TYPE_XPM)
905 bsizer = wxBoxSizer(wxVERTICAL)
906 bsizer.Add(wxBitmapButton(self, ID_CUSTOMRAMP_COPYSTART, bmp),
907 0, wxGROW | wxALL, 4)
908 bmp = resource.GetBitmapResource(USENOT_BMP, wxBITMAP_TYPE_XPM)
909 bsizer.Add(wxBitmapButton(self, ID_CUSTOMRAMP_COPYEND, bmp),
910 0, wxGROW | wxALL, 4)
911
912 topSizer.Add(bsizer,
913 0, wxALL \
914 | wxALIGN_CENTER_HORIZONTAL \
915 | wxALIGN_CENTER_VERTICAL,
916 4)
917
918 bsizer = wxBoxSizer(wxVERTICAL)
919 bsizer.Add(wxStaticText(self, -1, _("End:")), 0, wxALL | wxCENTER, 4)
920 self.endPropCtrl = classifier.ClassGroupPropertiesCtrl(
921 self, ID_CUSTOMRAMP_EPROP,
922 ClassGroupProperties(), shapeType,
923 style=wxSIMPLE_BORDER, size=(40, 20))
924 bsizer.Add(self.endPropCtrl, 1, wxGROW | wxALL | wxCENTER, 4)
925 bsizer.Add(wxButton(self, ID_CUSTOMRAMP_EDITEND, _("Change")),
926 0, wxGROW | wxALL | wxCENTER, 4)
927
928 topSizer.Add(bsizer,
929 1, wxALL \
930 | wxSHAPED \
931 | wxALIGN_RIGHT \
932 | wxALIGN_CENTER_HORIZONTAL \
933 | wxALIGN_CENTER_VERTICAL,
934 4)
935
936 EVT_BUTTON(self, ID_CUSTOMRAMP_COPYSTART, self._OnCopyStart)
937 EVT_BUTTON(self, ID_CUSTOMRAMP_COPYEND, self._OnCopyEnd)
938 EVT_BUTTON(self, ID_CUSTOMRAMP_EDITSTART, self._OnEditStart)
939 EVT_BUTTON(self, ID_CUSTOMRAMP_EDITEND, self._OnEditEnd)
940
941 self.SetSizer(topSizer)
942 self.SetAutoLayout(True)
943 topSizer.SetSizeHints(self)
944
945 def GetRamp(self):
946 return CustomRamp(self.startPropCtrl.GetProperties(),
947 self.endPropCtrl.GetProperties())
948
949 def _OnCopyStart(self, event):
950 self.endPropCtrl.SetProperties(self.startPropCtrl.GetProperties())
951
952 def _OnCopyEnd(self, event):
953 self.startPropCtrl.SetProperties(self.endPropCtrl.GetProperties())
954
955 def _OnEditStart(self, event):
956 self.startPropCtrl.DoEdit()
957
958 def _OnEditEnd(self, event):
959 self.endPropCtrl.DoEdit()
960
961

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26