/[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 2022 - (hide annotations)
Fri Dec 5 13:36:10 2003 UTC (21 years, 3 months ago) by frank
Original Path: trunk/thuban/Thuban/UI/projdialog.py
File MIME type: text/x-python
File size: 37171 byte(s)
Thuban/UI/projdialog.py (load_user_proj): If user.proj is missing
	write warning to stderr instead of rising a warning dialog

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