/[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 1542 - (show annotations)
Fri Aug 1 16:13:49 2003 UTC (21 years, 7 months ago) by bh
Original Path: trunk/thuban/Thuban/UI/projdialog.py
File MIME type: text/x-python
File size: 35020 byte(s)
Insert cvs keywords and doc-strings.

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