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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1819 - (hide annotations)
Mon Oct 13 15:55:43 2003 UTC (21 years, 4 months ago) by bh
Original Path: trunk/thuban/Thuban/UI/projdialog.py
File MIME type: text/x-python
File size: 34900 byte(s)
(ProjFrame._OnSave)
(ProjFrame._OnAddToList, ProjFrame.__DoOnProjAvail)
(ProjFrame.__FillAvailList): Use the projection's Label method to
get the string for the list box

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