/[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 1861 - (hide annotations)
Fri Oct 24 16:03:03 2003 UTC (21 years, 4 months ago) by jan
Original Path: trunk/thuban/Thuban/UI/projdialog.py
File MIME type: text/x-python
File size: 35165 byte(s)
(ProjFrame.__init__): Added 'longlat' as alias for 'latlong'.

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