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

Contents of /branches/WIP-pyshapelib-bramz/Thuban/UI/projdialog.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1190 - (show annotations)
Thu Jun 12 17:01:37 2003 UTC (21 years, 8 months ago) by jonathan
Original Path: trunk/thuban/Thuban/UI/projdialog.py
File MIME type: text/x-python
File size: 35029 byte(s)
(ProjFrame.__DoOnProjAvail): Clear
        the projfilepath if no projection is selected.

1 # Copyright (c) 2003 by Intevation GmbH
2 # Authors:
3 # Jonathan Coles <[email protected]>
4 # Frank Koormann <[email protected]>
5 #
6 # This program is free software under the GPL (>=v2)
7 # Read the file COPYING coming with Thuban for details.
8
9 import os, sys, math
10 from wxPython.wx import *
11
12 from Thuban import _
13
14 from Thuban.Model.proj import Projection, ProjFile
15
16 from Thuban.Model.resource import get_user_proj_files, get_system_proj_files, \
17 read_proj_file, write_proj_file
18 from Thuban.UI.dialogs import NonModalNonParentDialog
19
20
21 ID_PROJ_ADVANCED = 4001
22 ID_PROJ_PROJCHOICE = 4002
23 ID_PROJ_ADDTOLIST = 4003
24 ID_PROJ_NEW = 4004
25 ID_PROJ_REVERT = 4006
26 ID_PROJ_AVAIL = 4009
27 ID_PROJ_SAVE = 4010
28 ID_PROJ_IMPORT = 4011
29 ID_PROJ_EXPORT = 4012
30 ID_PROJ_REMOVE = 4013
31 ID_PROJ_PROJNAME = 4014
32
33 CLIENT_PROJ = 0
34 CLIENT_PROJFILE = 1
35
36 class ProjFrame(NonModalNonParentDialog):
37
38 def __init__(self, parent, name, title, receiver):
39 """Initialize the projection dialog.
40
41 receiver -- An object that implements the following methods:
42 SetProjection(projection)
43 GetProjection()
44 """
45
46 self.receiver = receiver
47 self.haveTried = False
48 self.curProjPanel = None
49
50 self.projPanels = []
51 self.projPanels.append(
52 ("tmerc", _("Transverse Mercator"), TMPanel))
53 self.projPanels.append(
54 ("utm", _("Universal Transverse Mercator"), UTMPanel))
55 self.projPanels.append(
56 ("lcc", _("Lambert Conic Conformal"), LCCPanel))
57 self.projPanels.append(
58 ("latlong", _("Geographic"), GeoPanel))
59
60 NonModalNonParentDialog.__init__(self, parent, name, title)
61 # originally generate by wxGlade
62 self.panel_1 = wxPanel(self, -1)
63 self.panel_edit = wxPanel(self, -1)
64 self.label_5 = wxStaticText(self.panel_1, -1,
65 _("Available Projections:"))
66
67 # Projection List specific actions (Import/Export/Remove)
68 self.button_import = wxButton(self.panel_1, ID_PROJ_IMPORT,
69 _("Import..."))
70 self.button_export = wxButton(self.panel_1, ID_PROJ_EXPORT,
71 _("Export..."))
72 self.button_remove = wxButton(self.panel_1, ID_PROJ_REMOVE,
73 _("Remove"))
74
75 # The Projection List
76 self.availprojs = wxListBox(self.panel_1, ID_PROJ_AVAIL,
77 style=wxLB_EXTENDED|wxLB_SORT)
78 self.projfilepath = wxStaticText(self.panel_1, -1, "")
79
80 # Projection Specific Entries (Name/Projection)
81 self.label_2 = wxStaticText(self.panel_edit, -1, _("Name:"))
82 self.projname = wxTextCtrl(self.panel_edit, ID_PROJ_PROJNAME, "")
83 self.label_3 = wxStaticText(self.panel_edit, -1, _("Projection:"))
84 self.projchoice = wxChoice(self.panel_edit, ID_PROJ_PROJCHOICE)
85
86 # Projection Specific actions (New/Save/Add)
87 self.button_new = wxButton(self.panel_edit, ID_PROJ_NEW, _("New"))
88 self.button_add = wxButton(self.panel_edit, ID_PROJ_ADDTOLIST,
89 _("Add to List"))
90 self.button_save = wxButton(self.panel_edit, ID_PROJ_SAVE,_("Update"))
91
92 # Main Action buttons (Try/Revert/OK/Close)
93 self.button_try = wxButton(self, wxID_APPLY, _("Try"))
94 self.button_revert = wxButton(self, ID_PROJ_REVERT,
95 _("Revert"))
96 self.button_ok = wxButton(self, wxID_OK, _("OK"))
97 self.button_ok.SetDefault()
98 self.button_close = wxButton(self, wxID_CANCEL,
99 _("Close"))
100
101 self.__set_properties()
102 self.__do_layout()
103
104 # wxGlade
105
106 # Fill the projection choice list.
107 for proj, name, clazz in self.projPanels:
108 self.projchoice.Append(name, [clazz, None])
109
110 self.originalProjection = self.receiver.GetProjection()
111
112 self.__DoOnProjAvail()
113 self.button_ok.SetFocus()
114 self.availprojs.SetFocus()
115
116 EVT_BUTTON(self, wxID_APPLY, self.OnApply)
117 EVT_BUTTON(self, ID_PROJ_REVERT, self._OnRevert)
118 EVT_BUTTON(self, wxID_OK, self.OnOK)
119 EVT_BUTTON(self, wxID_CANCEL, self.OnCancel)
120 EVT_CHOICE(self, ID_PROJ_PROJCHOICE, self._OnProjChoice)
121 EVT_LISTBOX(self, ID_PROJ_AVAIL, self._OnProjAvail)
122 EVT_BUTTON(self, ID_PROJ_IMPORT, self._OnImport)
123 EVT_BUTTON(self, ID_PROJ_EXPORT, self._OnExport)
124 EVT_BUTTON(self, ID_PROJ_REMOVE, self._OnRemove)
125
126 EVT_BUTTON(self, ID_PROJ_NEW, self._OnNew)
127 EVT_BUTTON(self, ID_PROJ_SAVE, self._OnSave)
128 EVT_BUTTON(self, ID_PROJ_ADDTOLIST, self._OnAddToList)
129
130 EVT_TEXT(self, ID_PROJ_PROJNAME, self._OnProjName)
131
132 def OnApply(self, event):
133 self.__SetProjection()
134 self.haveTried = True
135
136 def OnOK(self, event):
137 self.__SetProjection()
138 self.Close()
139
140 def OnCancel(self, event):
141 """Cancel just closes the dialog, but we call it cancel so we
142 can overload the functionality of wxDialog.
143 """
144 self.Close()
145
146 def _OnRevert(self, event):
147 if self.haveTried:
148 self.receiver.SetProjection(self.originalProjection)
149 self.haveTried = False
150
151 def _OnNew(self, event):
152
153 # clear all selections
154 sel = self.availprojs.GetSelections()
155 for index in sel:
156 self.availprojs.SetSelection(index, False)
157
158 self.projname.Clear()
159
160 # supply a projection panel if there wasn't one
161 if self.curProjPanel is None:
162 self.projchoice.SetSelection(0)
163 self.__DoOnProjChoice()
164
165 self.curProjPanel.Clear()
166
167 def _OnSave(self, event):
168
169 sel = self.availprojs.GetSelections()
170 assert len(sel) == 1, "button shouldn't be enabled"
171
172 proj, projfile = self.availprojs.GetClientData(sel[0])
173
174 assert proj is not None and projfile is not None
175
176 newproj = self.__GetProjection()
177
178 if newproj is not None:
179 projfile.Replace(proj, newproj)
180 try:
181 write_proj_file(projfile)
182 except IOError, (errno, errstr):
183 self.__ShowError(projfile.GetFilename(), errstr)
184 self.availprojs.SetClientData(sel[0], [newproj, projfile])
185
186 self.__FillAvailList( selectProj = newproj.GetName())
187
188 def _OnAddToList(self, event):
189
190 proj = self.__GetProjection()
191 if proj is not None:
192 self.__usrProjFile.Add(proj)
193 try:
194 write_proj_file(self.__usrProjFile)
195 except IOError, (errno, errstr):
196 self.__ShowError(self.__userProjFile.GetFilename(), errstr)
197
198 self.__FillAvailList( selectProj = proj.GetName())
199
200 def _OnProjAvail(self, event):
201 self.__DoOnProjAvail()
202
203 def _OnImport(self, event):
204
205 dlg = wxFileDialog(self, _("Import"), style = wxOPEN)
206
207 if dlg.ShowModal() == wxID_OK:
208 path = dlg.GetPath()
209
210 try:
211 projFile = read_proj_file(path)
212 for proj in projFile.GetProjections():
213 self.__usrProjFile.Add(proj)
214 write_proj_file(self.__usrProjFile)
215 except IOError, (errno, errstr):
216 self.__ShowError(dlg.GetPath(), errstr)
217
218 self.__FillAvailList()
219
220 dlg.Destroy()
221
222 def _OnExport(self, event):
223
224 sel = self.availprojs.GetSelections()
225 assert len(sel) != 0, "button should be disabled"
226
227 dlg = wxFileDialog(self, _("Export"),
228 style = wxSAVE|wxOVERWRITE_PROMPT)
229
230 if dlg.ShowModal() == wxID_OK:
231 path = dlg.GetPath()
232
233 projFile = ProjFile(path)
234
235 for i in sel:
236 proj = self.availprojs.GetClientData(i)[CLIENT_PROJ]
237 if proj is not None:
238 projFile.Add(proj)
239
240 try:
241 write_proj_file(projFile)
242 except IOError, (errno, errstr):
243 self.__ShowError(dlg.GetPath(), errstr)
244
245 dlg.Destroy()
246
247 def _OnRemove(self, event):
248
249 sel = self.availprojs.GetSelections()
250 assert len(sel) != 0, "button should be disabled!"
251
252 #
253 # remove the items backwards so the indices don't change
254 #
255 sel = list(sel)
256 sel.sort()
257 sel.reverse()
258
259 newselection = -1
260 if len(sel) == 1:
261 newselection = sel[0] - 1
262 if newselection < 0:
263 newselection = 0
264
265 for i in sel:
266 proj, projfile = self.availprojs.GetClientData(i)
267
268 #
269 # this could be the case if they selected <None> or
270 # the currently used projection
271 #
272 if proj is not None and projfile is not None:
273 projfile.Remove(proj)
274
275 try:
276 write_proj_file(projfile)
277 except IOError, (errno, errstr):
278 self.__ShowError(projfile.GetFilename(), errstr)
279
280 self.__FillAvailList()
281
282 #
283 # this *could* produce incorrect results if the .proj files
284 # change between the last list update and this selection
285 # because the list has been repopulated.
286 #
287 if newselection != -1 and self.availprojs.GetCount() > 0:
288 self.availprojs.SetSelection(newselection)
289
290 self.__VerifyButtons()
291
292 def _OnProjName(self, event):
293 self.__VerifyButtons()
294
295 def __ShowError(self, filename, errstr):
296 wxMessageDialog(self,
297 _("The following error occured:\n") +
298 filename + "\n" + errstr,
299 _("Error"), wxOK | wxICON_ERROR).ShowModal()
300
301 def __VerifyButtons(self):
302 """Enable or disable the appropriate buttons based on the
303 current state of the dialog.
304 """
305
306 sel = self.availprojs.GetSelections()
307
308 self.button_import.Enable(True)
309 self.button_export.Enable(True)
310 self.button_save.Enable(True)
311 self.button_remove.Enable(True)
312
313 self.panel_edit.Enable(True)
314
315 for ctrl in [self.button_import,
316 self.button_export,
317 self.button_remove,
318 self.button_save,
319 self.button_add,
320 self.projchoice,
321 self.projname,
322 self.panel_edit]:
323 ctrl.Enable(True)
324
325 if self.curProjPanel is not None:
326 self.curProjPanel.Enable(True)
327
328 if len(sel) == 0:
329 self.button_import.Enable(True)
330 self.button_export.Enable(False)
331 self.button_remove.Enable(False)
332 self.button_save.Enable(False)
333
334 elif len(sel) == 1:
335
336 proj, projFile = self.availprojs.GetClientData(sel[0])
337
338 self.button_save.Enable(len(self.projname.GetValue()) > 0)
339 self.button_add.Enable(len(self.projname.GetValue()) > 0)
340
341 if proj is None:
342 # <None> is selected
343 for ctrl in [self.button_export,
344 self.button_remove,
345 self.button_save,
346 self.button_add,
347 self.projchoice,
348 self.projname]:
349 ctrl.Enable(False)
350
351 if self.curProjPanel is not None:
352 self.curProjPanel.Enable(False)
353
354 elif proj is self.originalProjection:
355 self.button_remove.Enable(False)
356
357 if projFile is None:
358 self.button_save.Enable(False)
359
360 else:
361 self.panel_edit.Enable(False)
362
363 def __DoOnProjAvail(self):
364
365 sel = self.availprojs.GetSelections()
366 if len(sel) == 1:
367
368 proj = self.availprojs.GetClientData(sel[0])[CLIENT_PROJ]
369 projfile = self.availprojs.GetClientData(sel[0])[CLIENT_PROJFILE]
370
371 if proj is None:
372 # user selected <None>
373 self.projname.Clear()
374 self.projfilepath.SetLabel(_("Projection File: "))
375 else:
376
377 if projfile is not None:
378 self.projfilepath.SetLabel(_("Projection File: ") +
379 os.path.basename(projfile.GetFilename()))
380 else:
381 # only None if the currently used projection is selected
382 self.projfilepath.SetLabel(_("Projection File: "))
383
384 self.projname.SetValue(proj.GetName())
385
386 myProjType = proj.GetParameter("proj")
387 i = 0
388 for projType, name, clazz in self.projPanels:
389 if myProjType == projType:
390 self.projchoice.SetSelection(i)
391 self.__DoOnProjChoice()
392
393 #
394 # self.curProjPanel should not be null
395 # after a call to __DoOnProjChoice
396 #
397 assert self.curProjPanel is not None
398
399 self.curProjPanel.SetProjection(proj)
400 i += 1
401
402 self.__VerifyButtons()
403
404 def _OnProjChoice(self, event):
405 self.__DoOnProjChoice()
406
407 def __DoOnProjChoice(self):
408 """Create and layout a projection panel based on the selected
409 projection type.
410
411 This is necessary to have in seperate method since calls to
412 wxChoice.SetSelection() do not trigger an event.
413
414 At the end of this method self.curProjPanel will not be None
415 if there was a item selected.
416 """
417
418 choice = self.projchoice
419
420 sel = choice.GetSelection()
421 if sel != -1:
422
423 clazz, obj = choice.GetClientData(sel)
424
425 if obj is None:
426 obj = clazz(self.panel_edit, self.receiver)
427 choice.SetClientData(sel, [clazz, obj])
428
429 if self.curProjPanel is not None:
430 self.curProjPanel.Hide()
431 self.sizer_projctrls.Remove(self.curProjPanel)
432
433 self.curProjPanel = obj
434 self.curProjPanel.Show()
435
436 self.sizer_projctrls.Add(self.curProjPanel, 1,
437 wxALL|wxEXPAND|wxADJUST_MINSIZE, 3)
438 self.sizer_projctrls.Layout()
439 self.Layout()
440 self.topBox.SetSizeHints(self)
441
442 def __SetProjection(self):
443 """Set the receiver's projection."""
444
445 #
446 # save the original projection only once in case
447 # we try to apply several different projections
448 #
449 self.receiver.SetProjection(self.__GetProjection())
450
451 def __GetProjection(self):
452 """Return a suitable Projection object based on the current
453 state of the dialog box selections.
454
455 Could be None.
456 """
457
458 sel = self.availprojs.GetSelections()
459 assert len(sel) < 2, "button should be disabled"
460
461
462 if len(sel) == 1:
463 proj = self.availprojs.GetClientData(sel[0])[CLIENT_PROJ]
464 if proj is None:
465 # <None> is selected
466 return None
467
468 #
469 # self.curProjPanel should always contain the most
470 # relevant data for a projection
471 #
472 if self.curProjPanel is not None:
473 return Projection(self.curProjPanel.GetParameters(),
474 self.projname.GetValue())
475
476 return None
477
478 def __FillAvailList(self, selectCurrent = False, selectProj = None):
479 """Populate the list of available projections.
480
481 selectCurrent -- if True, select the projection used by
482 the receiver, otherwise select nothing.
483 selectProj -- if set, select the projection found under the
484 specified name. This overwrites any other
485 selection estimate.
486 """
487
488 self.availprojs.Clear()
489
490 #
491 # the list can never be empty. there will always be
492 # at least this one item
493 #
494 self.availprojs.Append("<None>", (None, None))
495
496 projfile = get_system_proj_files()
497 projfile = projfile[0]
498 for proj in projfile.GetProjections():
499 self.availprojs.Append(proj.GetName(), [proj, projfile])
500 self.__sysProjFile = projfile
501
502 projfile = get_user_proj_files()
503 projfile = projfile[0]
504 for proj in projfile.GetProjections():
505 self.availprojs.Append(proj.GetName(), [proj, projfile])
506 self.__usrProjFile = projfile
507
508 #
509 # We add the current projection to the list at last.
510 # Since the list is resorted immediately a following FindString()
511 # determines the index correctly.
512 #
513 proj = self.receiver.GetProjection()
514 if proj is not None:
515 proj_item = _("%s (current)") % proj.GetName()
516 self.availprojs.Append(proj_item, [proj, None])
517 if selectCurrent:
518 self.availprojs.SetSelection(
519 self.availprojs.FindString(proj_item)
520 )
521 else:
522 if selectCurrent:
523 self.availprojs.SetSelection(
524 self.availprojs.FindString("<None>")
525 )
526 if selectProj:
527 self.availprojs.SetSelection(
528 self.availprojs.FindString(selectProj)
529 )
530
531
532
533 def __set_properties(self):
534
535 #self.availprojs.SetSelection(0)
536 self.projchoice.SetSelection(0)
537
538 self.__FillAvailList(selectCurrent = True)
539
540 self.projname.SetMaxLength(32)
541
542 def __do_layout(self):
543 # originally generated by wxGlade
544
545 self.topBox = wxBoxSizer(wxVERTICAL)
546 self.sizer_panel = wxBoxSizer(wxVERTICAL)
547 sizer_6 = wxBoxSizer(wxHORIZONTAL)
548 self.sizer_mainbttns = wxBoxSizer(wxHORIZONTAL)
549 self.sizer_mainctrls = wxBoxSizer(wxHORIZONTAL)
550 self.sizer_edit = wxStaticBoxSizer(wxStaticBox(self.panel_edit, -1, _("Edit")), wxHORIZONTAL)
551 sizer_11 = wxBoxSizer(wxVERTICAL)
552 self.sizer_projctrls = wxBoxSizer(wxVERTICAL)
553 sizer_14 = wxBoxSizer(wxHORIZONTAL)
554 sizer_13 = wxBoxSizer(wxHORIZONTAL)
555 sizer_15 = wxBoxSizer(wxVERTICAL)
556 sizer_15.Add(self.button_import, 0, wxALL, 4)
557 sizer_15.Add(self.button_export, 0, wxALL, 4)
558 sizer_15.Add(20, 20, 0, wxEXPAND, 0)
559 sizer_15.Add(self.button_remove, 0, wxALL|wxALIGN_BOTTOM, 4)
560
561 # list controls
562 grid_sizer_1 = wxFlexGridSizer(3, 2, 0, 0)
563 grid_sizer_1.Add(self.label_5, 0, wxLEFT|wxRIGHT|wxTOP, 4)
564 grid_sizer_1.Add(20, 20, 0, wxEXPAND, 0)
565 grid_sizer_1.Add(self.availprojs, 1, wxALL|wxEXPAND|wxADJUST_MINSIZE, 4)
566 grid_sizer_1.Add(sizer_15, 0, wxALL|wxEXPAND, 4)
567 grid_sizer_1.Add(self.projfilepath, 0, wxEXPAND|wxALL|wxADJUST_MINSIZE, 4)
568 grid_sizer_1.AddGrowableRow(1)
569 grid_sizer_1.AddGrowableCol(0)
570
571 # edit controls
572 sizer_13.Add(self.label_2, 0, wxALL|wxALIGN_CENTER_VERTICAL, 4)
573 sizer_13.Add(self.projname, 1, wxALL, 4)
574 self.sizer_projctrls.Add(sizer_13, 0, wxEXPAND, 0)
575 sizer_14.Add(self.label_3, 0, wxALL|wxALIGN_CENTER_VERTICAL, 4)
576 sizer_14.Add(self.projchoice, 1, wxALL|wxALIGN_CENTER_VERTICAL, 4)
577 self.sizer_projctrls.Add(sizer_14, 0, wxEXPAND, 0)
578 self.sizer_edit.Add(self.sizer_projctrls, 1, wxEXPAND, 0)
579 sizer_11.Add(self.button_new, 0, wxEXPAND|wxALL, 4)
580 sizer_11.Add(self.button_add, 0, wxEXPAND|wxALL, 4)
581 sizer_11.Add(20, 20, 0, wxEXPAND, 0)
582 sizer_11.Add(self.button_save, 0, wxEXPAND|wxALL|wxALIGN_BOTTOM, 4)
583 self.sizer_edit.Add(sizer_11, 0, wxALL|wxEXPAND, 4)
584
585 sizer_6.Add(self.button_try, 0, wxRIGHT| wxEXPAND, 10)
586 sizer_6.Add(self.button_revert, 0, wxRIGHT| wxEXPAND, 10)
587 sizer_6.Add(self.button_ok, 0, wxRIGHT| wxEXPAND, 10)
588 sizer_6.Add(self.button_close, 0, wxRIGHT| wxEXPAND, 10)
589
590 self.panel_1.SetAutoLayout(1)
591 self.panel_1.SetSizer(grid_sizer_1)
592 grid_sizer_1.Fit(self.panel_1)
593 grid_sizer_1.SetSizeHints(self.panel_1)
594
595 self.panel_edit.SetAutoLayout(1)
596 self.panel_edit.SetSizer(self.sizer_edit)
597 self.sizer_edit.Fit(self.panel_edit)
598 self.sizer_edit.SetSizeHints(self.panel_edit)
599
600 self.sizer_mainctrls.Add(self.panel_1, 0,
601 wxALL|wxEXPAND|wxADJUST_MINSIZE, 0)
602 self.sizer_mainctrls.Add(self.panel_edit, 1,
603 wxALL|wxEXPAND|wxADJUST_MINSIZE, 0)
604
605 self.sizer_mainbttns.Add(sizer_6, 0,
606 wxALL|wxEXPAND|wxADJUST_MINSIZE, 10)
607
608 self.topBox.Add(self.sizer_mainctrls, 1, wxALL|wxEXPAND, 4)
609 self.topBox.Add(self.sizer_mainbttns, 0, wxALIGN_RIGHT|wxBOTTOM, 0)
610
611 self.SetAutoLayout(1)
612 self.SetSizer(self.topBox)
613 self.topBox.Fit(self)
614 self.topBox.SetSizeHints(self)
615 self.Layout()
616
617 # end of class ProjFrame
618
619
620 class ProjPanel(wxPanel):
621 """Base class for all projection panels."""
622
623 def __init__(self, parent):
624 wxPanel.__init__(self, parent, -1)
625
626 self.__ellps = wxChoice(self, -1)
627 self.ellpsData = [("airy" , _("Airy")),
628 ("bessel", _("Bessel 1841")),
629 ("clrk66", _("Clarke 1866")),
630 ("clrk80", _("Clarke 1880")),
631 ("GRS80" , _("GRS 1980 (IUGG, 1980)")),
632 ("intl" , _("International 1909 (Hayford)")),
633 ("WGS84" , _("WGS 84"))]
634
635 for tag, name in self.ellpsData:
636 self.__ellps.Append(name, tag)
637
638 self.__ellps.SetSelection(0)
639
640 def _DoLayout(self, childPanel = None):
641
642 panelSizer = wxBoxSizer(wxVERTICAL)
643
644 sizer = wxBoxSizer(wxHORIZONTAL)
645 sizer.Add(wxStaticText(self, -1, _("Ellipsoid:")), 0,
646 wxALL|wxALIGN_CENTER_VERTICAL, 4)
647 sizer.Add(self.__ellps, 1, wxALL|wxALIGN_CENTER_VERTICAL, 4)
648 panelSizer.Add(sizer, 0, wxALL|wxEXPAND, 4)
649
650 if childPanel is not None:
651 panelSizer.Add(childPanel, 0, wxEXPAND, 0)
652
653 self.SetAutoLayout(1)
654 self.SetSizer(panelSizer)
655 panelSizer.Fit(self)
656 panelSizer.SetSizeHints(self)
657 self.Layout()
658
659 def SetProjection(self, proj):
660 if proj is not None:
661 param = proj.GetParameter("ellps")
662 i = 0
663 for tag, name in self.ellpsData:
664 if param == tag:
665 self.__ellps.SetSelection(i)
666 return # returning early!
667 i += 1
668
669 #
670 # if proj is none, or the parameter couldn't be found...
671 #
672 self.__ellps.SetSelection(0)
673
674 def GetParameters(self):
675 return ["ellps=" + self.__ellps.GetClientData(
676 self.__ellps.GetSelection())]
677
678
679 ID_TMPANEL_LAT = 4001
680 ID_TMPANEL_LONG = 4002
681 ID_TMPANEL_FASLE_EAST = 4003
682 ID_TMPANEL_FALSE_NORTH = 4004
683 ID_TMPANEL_SCALE = 4005
684
685 class UnknownProjPanel(ProjPanel):
686 def __init__(self, parent, receiver):
687 ProjPanel.__init__(self, parent)
688
689 self._DoLayout()
690
691 def _DoLayout(self):
692 sizer = wxBoxSizer(wxVERTICAL)
693
694 sizer.Add(wxStaticText(self, -1,
695 _("Thuban does not know the parameters for the " +
696 "current projection and cannot display a " +
697 "configuration panel.")))
698
699 ProjPanel._DoLayout(self, sizer)
700
701 def GetProjName(self):
702 return "Unknown"
703
704 def SetProjection(self, proj):
705 pass
706
707 def GetParameters(self):
708 return None
709
710 class TMPanel(ProjPanel):
711 """Projection panel for Transverse Mercator."""
712
713 def __init__(self, parent, receiver):
714 ProjPanel.__init__(self, parent)
715
716 self.__latitude = wxTextCtrl(self, ID_TMPANEL_LAT)
717 self.__longitude = wxTextCtrl(self, ID_TMPANEL_LONG)
718 self.__scale = wxTextCtrl(self, ID_TMPANEL_SCALE)
719 self.__falseEast = wxTextCtrl(self, ID_TMPANEL_FASLE_EAST)
720 self.__falseNorth = wxTextCtrl(self, ID_TMPANEL_FALSE_NORTH)
721
722 self._DoLayout()
723
724 def _DoLayout(self):
725
726 sizer = wxFlexGridSizer(4, 4, 0, 0)
727 sizer.Add(wxStaticText(self, -1, _("Latitude:")), 0, wxALL, 4)
728 sizer.Add(self.__latitude, 0, wxALL, 4)
729 sizer.Add(wxStaticText(self, -1, _("False Easting:")), 0, wxALL, 4)
730 sizer.Add(self.__falseEast, 0, wxALL, 4)
731 sizer.Add(wxStaticText(self, -1, _("Longitude:")), 0, wxALL, 4)
732 sizer.Add(self.__longitude, 0, wxALL, 4)
733 sizer.Add(wxStaticText(self, -1, _("False Northing:")), 0, wxALL, 4)
734 sizer.Add(self.__falseNorth, 0, wxALL, 4)
735 sizer.Add(wxStaticText(self, -1, _("Scale Factor:")), 0, wxALL, 4)
736 sizer.Add(self.__scale, 0, wxALL, 4)
737
738 ProjPanel._DoLayout(self, sizer)
739
740 def GetProjName(self):
741 return _("Transverse Mercator")
742
743 def SetProjection(self, proj):
744 ProjPanel.SetProjection(self, proj)
745
746 self.__latitude.SetValue(proj.GetParameter("lat_0"))
747 self.__longitude.SetValue(proj.GetParameter("lon_0"))
748 self.__falseEast.SetValue(proj.GetParameter("x_0"))
749 self.__falseNorth.SetValue(proj.GetParameter("y_0"))
750 self.__scale.SetValue(proj.GetParameter("k"))
751
752 ProjPanel.SetProjection(self, proj)
753
754 def GetParameters(self):
755 params = ["proj=tmerc",
756 "lat_0=" + self.__latitude.GetValue(),
757 "lon_0=" + self.__longitude.GetValue(),
758 "x_0=" + self.__falseEast.GetValue(),
759 "y_0=" + self.__falseNorth.GetValue(),
760 "k=" + self.__scale.GetValue()]
761 params.extend(ProjPanel.GetParameters(self))
762 return params
763
764 def Clear(self):
765 self.__latitude.Clear()
766 self.__longitude.Clear()
767 self.__falseEast.Clear()
768 self.__falseNorth.Clear()
769 self.__scale.Clear()
770
771 ProjPanel.Clear(self)
772
773 ID_UTMPANEL_ZONE = 4001
774 ID_UTMPANEL_SOUTH = 4002
775 ID_UTMPANEL_PROP = 4003
776
777 class UTMPanel(ProjPanel):
778 """Projection Panel for Universal Transverse Mercator."""
779
780 def __init__(self, parent, receiver):
781 ProjPanel.__init__(self, parent)
782
783 self.receiver = receiver
784
785 self.__zone = wxSpinCtrl(self, ID_UTMPANEL_ZONE, "1", min=1, max=60)
786 self.__propButton = wxButton(self, ID_UTMPANEL_PROP, _("Propose"))
787 self.__south = wxCheckBox(self, ID_UTMPANEL_SOUTH,
788 _("Southern Hemisphere"))
789
790 self._DoLayout()
791
792 EVT_BUTTON(self, ID_UTMPANEL_PROP, self._OnPropose)
793
794 def _DoLayout(self):
795
796 sizer = wxBoxSizer(wxVERTICAL)
797 psizer = wxBoxSizer(wxHORIZONTAL)
798 psizer.Add(wxStaticText(self, -1, _("Zone:")), 0, wxALL, 4)
799 psizer.Add(self.__zone, 0, wxALL, 4)
800 psizer.Add(self.__propButton, 0, wxALL, 4)
801 sizer.Add(psizer, 0, wxALL, 4)
802 sizer.Add(self.__south, 0, wxALL, 4)
803
804 ProjPanel._DoLayout(self, sizer)
805
806 def GetProjName(self):
807 return _("Universal Transverse Mercator")
808
809 def SetProjection(self, proj):
810 self.__zone.SetValue(int(proj.GetParameter("zone")))
811 self.__south.SetValue(proj.GetParameter("south") != "")
812 ProjPanel.SetProjection(self, proj)
813
814 def GetParameters(self):
815 params = ["proj=utm", "zone=" + str(self.__zone.GetValue())]
816 if self.__south.IsChecked():
817 params.append("south")
818
819 params.extend(ProjPanel.GetParameters(self))
820 return params
821
822 def Clear(self):
823 self.__zone.SetValue(1)
824 self.__south.SetValue(False)
825 ProjPanel.Clear(self)
826
827 def _OnPropose(self, event):
828 UTMProposeZoneDialog
829 dlg = UTMProposeZoneDialog(self, self.receiver.BoundingBox())
830 if dlg.ShowModal() == wxID_OK:
831 self.__zone.SetValue(dlg.GetProposedZone())
832
833 class LCCPanel(ProjPanel):
834 """Projection Panel for Lambert Conic Conformal."""
835
836 def __init__(self, parent, receiver):
837 ProjPanel.__init__(self, parent)
838
839 self.__fspLatitude = wxTextCtrl(self, -1)
840 self.__sspLatitude = wxTextCtrl(self, -1)
841 self.__originLat = wxTextCtrl(self, -1)
842 self.__meridian = wxTextCtrl(self, -1)
843 self.__falseEast = wxTextCtrl(self, -1)
844 self.__falseNorth = wxTextCtrl(self, -1)
845
846 self._DoLayout()
847
848 def _DoLayout(self):
849
850 sizer = wxFlexGridSizer(6, 2, 0, 0)
851 sizer.Add(wxStaticText(self, -1,
852 _("Latitude of first standard parallel:")))
853 sizer.Add(self.__fspLatitude, 0, wxALL, 4)
854 sizer.Add(wxStaticText(self, -1,
855 _("Latitude of second standard parallel:")))
856 sizer.Add(self.__sspLatitude, 0, wxALL, 4)
857 sizer.Add(wxStaticText(self, -1, _("Central Meridian:")))
858 sizer.Add(self.__meridian, 0, wxALL, 4)
859 sizer.Add(wxStaticText(self, -1, _("Latitude of origin:")))
860 sizer.Add(self.__originLat, 0, wxALL, 4)
861 sizer.Add(wxStaticText(self, -1, _("False Easting:")))
862 sizer.Add(self.__falseEast, 0, wxALL, 4)
863 sizer.Add(wxStaticText(self, -1, _("False Northing:")))
864 sizer.Add(self.__falseNorth, 0, wxALL, 4)
865
866 ProjPanel._DoLayout(self, sizer)
867
868 def GetProjName(self):
869 return _("Lambert Conic Conformal")
870
871 def SetProjection(self, proj):
872 self.__fspLatitude.SetValue(proj.GetParameter("lat_1"))
873 self.__sspLatitude.SetValue(proj.GetParameter("lat_2"))
874 self.__originLat.SetValue(proj.GetParameter("lat_0"))
875 self.__meridian.SetValue(proj.GetParameter("lon_0"))
876 self.__falseEast.SetValue(proj.GetParameter("x_0"))
877 self.__falseNorth.SetValue(proj.GetParameter("y_0"))
878
879 ProjPanel.SetProjection(self, proj)
880
881 def GetParameters(self):
882 params = ["proj=lcc",
883 "lat_1=" + self.__fspLatitude.GetValue(),
884 "lat_2=" + self.__sspLatitude.GetValue(),
885 "lat_0=" + self.__originLat.GetValue(),
886 "lon_0=" + self.__meridian.GetValue(),
887 "x_0=" + self.__falseEast.GetValue(),
888 "y_0=" + self.__falseNorth.GetValue()]
889
890 params.extend(ProjPanel.GetParameters(self))
891 return params
892
893 def Clear(self):
894 self.__fspLatitude.Clear()
895 self.__sspLatitude.Clear()
896 self.__originLat.Clear()
897 self.__meridian.Clear()
898 self.__falseEast.Clear()
899 self.__falseNorth.Clear()
900
901 ProjPanel.Clear(self)
902
903 class GeoPanel(ProjPanel):
904 """Projection Panel for a Geographic Projection."""
905
906 def __init__(self, parent, receiver):
907 ProjPanel.__init__(self, parent)
908
909 self.__choices = [(_("Degrees"), "0.017453"),
910 (_("Radians"), "1")]
911
912 self.__scale = wxChoice(self, -1)
913 for choice, value in self.__choices:
914 self.__scale.Append(choice, value)
915
916 self._DoLayout()
917
918 def GetProjName(self):
919 return _("Geographic")
920
921 def SetProjection(self, proj):
922 value = proj.GetParameter("to_meter")
923 for i in range(len(self.__choices)):
924 choice, data = self.__choices[i]
925 if value == data:
926 self.__scale.SetSelection(i)
927 ProjPanel.SetProjection(self, proj)
928
929 def GetParameters(self):
930 params = ["proj=latlong",
931 "to_meter=%s" % self.__scale.GetClientData(
932 self.__scale.GetSelection())]
933
934 params.extend(ProjPanel.GetParameters(self))
935 return params
936
937 def Clear(self):
938 ProjPanel.Clear(self)
939
940 def _DoLayout(self):
941 sizer = wxBoxSizer(wxHORIZONTAL)
942
943 sizer.Add(wxStaticText(self, -1, _("Source Data is in: ")),
944 0, wxALL|wxALIGN_CENTER_VERTICAL, 4)
945 sizer.Add(self.__scale, 1, wxEXPAND|wxALL, 4)
946
947 self.__scale.SetSelection(0)
948
949 ProjPanel._DoLayout(self, sizer)
950
951
952 ID_UTM_PROPOSE_ZONE_DIALOG_TAKE = 4001
953 ID_UTM_PROPOSE_ZONE_DIALOG_CANCEL = 4002
954 class UTMProposeZoneDialog(wxDialog):
955
956 """Propose a sensible Zone considering the current map extent."""
957
958 def __init__(self, parent, (x, y, x2, y2)):
959 wxDialog.__init__(self, parent, -1, _("Projection: Propose UTM Zone"),
960 wxDefaultPosition, wxSize(200, 100))
961 self.parent = parent
962 #x, y, x2, y2 = elf.parent.parent.map_bounding_box
963 x = x + 180
964 x2 = x2 + 180
965 center = (x2 - x) / 2 + x
966 self.proposedZone = int(center / 6 + 1)
967 self.dialogLayout()
968
969 def dialogLayout(self):
970 topBox = wxBoxSizer(wxVERTICAL)
971
972 textBox = wxBoxSizer(wxVERTICAL)
973 textBox.Add(wxStaticText(self, -1, _("The current map extent center " +
974 "lies in UTM Zone")),
975 0, wxALIGN_CENTER|wxALL, 4)
976 textBox.Add(wxStaticText(self, -1, str(self.proposedZone)),
977 0, wxALIGN_CENTER|wxALL, 4)
978
979 topBox.Add(textBox, 1, wxEXPAND|wxALL, 4)
980
981 buttonBox = wxBoxSizer(wxHORIZONTAL)
982 buttonBox.Add(wxButton(self, ID_UTM_PROPOSE_ZONE_DIALOG_TAKE,
983 _("Take")), 0, wxALL, 4)
984 buttonBox.Add(wxButton(self, ID_UTM_PROPOSE_ZONE_DIALOG_CANCEL,
985 _("Cancel")), 0, wxALL, 4)
986 topBox.Add(buttonBox, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 10)
987 EVT_BUTTON(self, ID_UTM_PROPOSE_ZONE_DIALOG_TAKE, self.OnTake)
988 EVT_BUTTON(self, ID_UTM_PROPOSE_ZONE_DIALOG_CANCEL, self.OnCancel)
989
990 self.SetAutoLayout(True)
991 self.SetSizer(topBox)
992 topBox.Fit(self)
993 topBox.SetSizeHints(self)
994
995 def OnTake(self, event):
996 self.EndModal(wxID_OK)
997
998 def OnCancel(self, event):
999 self.EndModal(wxID_CANCEL)
1000
1001 def GetProposedZone(self):
1002 return self.proposedZone

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26