/[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 2470 - (hide annotations)
Thu Dec 16 11:00:10 2004 UTC (20 years, 2 months ago) by bh
Original Path: trunk/thuban/Thuban/UI/projdialog.py
File MIME type: text/x-python
File size: 37665 byte(s)
Fix for RT#2237

(ProjFrame._show_proj_panel): If the
panel to be shown is the UnknownProjPanel disable the OK and Try
buttons.  Otherwise enable them.
(ProjFrame.__GetProjection): The UnknownProjPanel returns None for
the parameters.  In that case __GetProjection also returns None
now.

1 bh 2470 # Copyright (c) 2003, 2004 by Intevation GmbH
2 jonathan 751 # 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 frank 2051 dlg = wxFileDialog(self, _("Import"),
307     self.parent.application.Path("projection"), style = wxOPEN)
308 jonathan 730
309     if dlg.ShowModal() == wxID_OK:
310     path = dlg.GetPath()
311    
312 bh 1833 ThubanBeginBusyCursor()
313 jonathan 730 try:
314 bh 1833 try:
315     projFile, warnings = read_proj_file(path)
316     except IOError, (errno, errstr):
317     self.__ShowError(dlg.GetPath(), errstr)
318     else:
319     self.show_warnings(_("Warnings"), path, warnings)
320     for proj in projFile.GetProjections():
321     self.__usrProjFile.Add(proj)
322     self.write_proj_file(self.__usrProjFile)
323 frank 2051 self.parent.application.SetPath("projection", path)
324 bh 1833 finally:
325     ThubanEndBusyCursor()
326 jonathan 730 dlg.Destroy()
327    
328     def _OnExport(self, event):
329 bh 1851 """Handler for the 'Export' button.
330 jonathan 730
331 bh 1851 Ask the user for a filename and write the selected projections
332     to that file.
333     """
334     sel = self.projection_list.selected_projections()
335 jonathan 741 assert len(sel) != 0, "button should be disabled"
336 jonathan 730
337 frank 2051 dlg = wxFileDialog(self, _("Export"),
338     self.parent.application.Path("projection"),
339     style=wxSAVE|wxOVERWRITE_PROMPT)
340 jonathan 730
341     if dlg.ShowModal() == wxID_OK:
342 bh 1851 proj_file = ProjFile(dlg.GetPath())
343     for proj, pf in sel:
344 jonathan 741 if proj is not None:
345 bh 1851 proj_file.Add(proj)
346     self.write_proj_file(proj_file)
347 frank 2051 self.parent.application.SetPath("projection", dlg.GetPath())
348 jonathan 741
349 jonathan 730 dlg.Destroy()
350    
351     def _OnRemove(self, event):
352 bh 1851 """Handler for the 'Remove' button
353 jonathan 730
354 bh 1851 Remove any selected projection that came from the user's
355     ProjFile. If the user ProjFile was modified write it back to
356     disk.
357     """
358     sel = self.projection_list.selected_projections()
359 jonathan 730 assert len(sel) != 0, "button should be disabled!"
360    
361 bh 1851 modified = False
362     for proj, pf in sel:
363     if proj is not None and pf is self.__usrProjFile:
364     pf.Remove(proj)
365     modified = True
366 jonathan 730
367 bh 1851 if modified:
368     self.write_proj_file(self.__usrProjFile)
369 jonathan 730
370 bh 1933 def _OnShowEPSG(self, event):
371     """Handler for the EVT_CHECKBOX events from the EPSG check button
372    
373     If the button is checked add the EPSG_PROJ_FILE to the list of
374     projfiles shown by the projection list. Otherwise remove it
375     """
376 bh 1941 proj_files = [self.load_user_proj(),
377     self.load_system_proj(DEFAULT_PROJ_FILE)]
378 bh 1933 if self.check_epsg.IsChecked():
379 bh 1941 proj_files.append(self.load_system_proj(EPSG_PROJ_FILE))
380     if self.check_epsg_depr.IsChecked():
381     proj_files.append(self.load_system_proj(EPSG_DEPRECATED_PROJ_FILE))
382 bh 1933 self.projection_list.SetProjFiles(proj_files)
383    
384 jonathan 730 def _OnProjName(self, event):
385     self.__VerifyButtons()
386    
387 jonathan 751 def __ShowError(self, filename, errstr):
388 bh 1851 wxMessageDialog(self,
389     _("The following error occured:\n") +
390     filename + "\n" + errstr,
391 jonathan 751 _("Error"), wxOK | wxICON_ERROR).ShowModal()
392    
393 jonathan 730 def __VerifyButtons(self):
394 bh 1851 """Update button sensitivity"""
395 jonathan 751
396 bh 1851 num_sel = self.projection_list.GetSelectedItemCount()
397 jonathan 730
398     self.button_import.Enable(True)
399     self.button_export.Enable(True)
400     self.button_save.Enable(True)
401     self.button_remove.Enable(True)
402    
403 bh 1806 self.edit_box.Enable(True)
404 jonathan 730
405 jonathan 751 for ctrl in [self.button_import,
406     self.button_export,
407     self.button_remove,
408     self.button_save,
409     self.button_add,
410     self.projchoice,
411     self.projname,
412 bh 1806 self.edit_box]:
413 jonathan 751 ctrl.Enable(True)
414    
415     if self.curProjPanel is not None:
416     self.curProjPanel.Enable(True)
417    
418 bh 1851 if num_sel == 0:
419 jonathan 730 self.button_import.Enable(True)
420     self.button_export.Enable(False)
421     self.button_remove.Enable(False)
422 jonathan 880 self.button_save.Enable(False)
423 jonathan 730
424 bh 1851 elif num_sel == 1:
425 jonathan 730
426 bh 1851 selection = self.projection_list.selected_projections()
427     proj, projFile = selection[0]
428 jonathan 730
429     self.button_save.Enable(len(self.projname.GetValue()) > 0)
430     self.button_add.Enable(len(self.projname.GetValue()) > 0)
431    
432     if proj is None:
433 jonathan 751 # <None> is selected
434     for ctrl in [self.button_export,
435     self.button_remove,
436     self.button_save,
437     self.button_add,
438     self.projchoice,
439     self.projname]:
440     ctrl.Enable(False)
441    
442     if self.curProjPanel is not None:
443     self.curProjPanel.Enable(False)
444    
445     elif proj is self.originalProjection:
446 jonathan 730 self.button_remove.Enable(False)
447    
448     if projFile is None:
449     self.button_save.Enable(False)
450    
451     else:
452 bh 1806 self.edit_box.Enable(False)
453 jonathan 730
454 bh 1851 def proj_selection_changed(self, projs):
455     """Subscribed to the projection_list's PROJ_SELECTION_CHANGED message
456 jonathan 717
457 bh 1851 Update the dialog to reflect the new selection.
458     """
459     if len(projs) == 0:
460     self.projfilepath.SetLabel(_("No Projections selected"))
461     elif len(projs) == 1:
462     proj, projfile = projs[0]
463 jonathan 730 if proj is None:
464     # user selected <None>
465     self.projname.Clear()
466 bh 1851 self.projfilepath.SetLabel("")
467 jonathan 730 else:
468     if projfile is not None:
469 bh 1851 filename = os.path.basename(projfile.GetFilename())
470     self.projfilepath.SetLabel(_("Source of Projection: %s")
471     % filename)
472 jonathan 730 else:
473     # only None if the currently used projection is selected
474 bh 1851 self.projfilepath.SetLabel("")
475 jonathan 717
476 bh 1819 self.projname.SetValue(proj.Label())
477 jonathan 717
478 jonathan 730 myProjType = proj.GetParameter("proj")
479     i = 0
480 bh 1809 for projType, name, cls in self.projection_panel_defs:
481 jonathan 730 if myProjType == projType:
482 bh 1789 self.projchoice.Enable(True)
483 bh 1851 self.projchoice.SetSelection(i + 1)
484 jonathan 730 self.__DoOnProjChoice()
485 jonathan 751
486     #
487     # self.curProjPanel should not be null
488     # after a call to __DoOnProjChoice
489     #
490     assert self.curProjPanel is not None
491    
492 jonathan 730 self.curProjPanel.SetProjection(proj)
493 bh 1789 break
494 jonathan 730 i += 1
495 bh 1789 else:
496 bh 1851 self.projchoice.Select(0)
497 bh 1789 self.projchoice.Disable()
498 bh 1809 self._show_proj_panel(UnknownProjPanel)
499 jan 1858 assert self.curProjPanel is not None
500     self.curProjPanel.SetProjection(proj)
501 bh 1851 else:
502     self.projfilepath.SetLabel(_("Multiple Projections selected"))
503 jonathan 717
504 jonathan 730 self.__VerifyButtons()
505    
506 jonathan 717 def _OnProjChoice(self, event):
507     self.__DoOnProjChoice()
508    
509     def __DoOnProjChoice(self):
510 jonathan 751 """Create and layout a projection panel based on the selected
511     projection type.
512    
513     This is necessary to have in seperate method since calls to
514     wxChoice.SetSelection() do not trigger an event.
515    
516     At the end of this method self.curProjPanel will not be None
517     if there was a item selected.
518     """
519 jonathan 717 choice = self.projchoice
520    
521     sel = choice.GetSelection()
522 jonathan 730 if sel != -1:
523 bh 1809 proj_type = choice.GetClientData(sel)
524     for t, name, cls in self.projection_panel_defs:
525     if t == proj_type:
526     self._show_proj_panel(cls)
527     break
528     # FIXME: what to do if sel == -1?
529 jonathan 717
530 bh 1809 def _show_proj_panel(self, panel_class):
531 bh 1789 """Show the panel as the projection panel"""
532 bh 1809 if panel_class is UnknownProjPanel:
533 bh 2470 self.button_ok.Disable()
534     self.button_try.Disable()
535 bh 1809 self.edit_box.Disable()
536     self.nbsizer.Activate(self.unknown_projection_panel)
537     self.curProjPanel = self.unknown_projection_panel
538     else:
539 bh 2470 self.button_ok.Enable(True)
540     self.button_try.Enable(True)
541 bh 1809 self.edit_box.Enable(True)
542     self.unknown_projection_panel.Hide()
543     for panel in self.projection_panels:
544     if panel.__class__ is panel_class:
545     self.nbsizer.Activate(panel)
546     self.curProjPanel = panel
547 jonathan 717
548     def __SetProjection(self):
549 jonathan 751 """Set the receiver's projection."""
550 jonathan 717
551     #
552     # save the original projection only once in case
553     # we try to apply several different projections
554     #
555 jonathan 730 self.receiver.SetProjection(self.__GetProjection())
556 jonathan 717
557 jonathan 730 def __GetProjection(self):
558 jonathan 751 """Return a suitable Projection object based on the current
559     state of the dialog box selections.
560 jonathan 717
561 jonathan 730 Could be None.
562     """
563 jonathan 717
564 bh 1851 assert self.projection_list.GetSelectedItemCount() < 2, \
565     "button should be disabled"
566 jonathan 717
567 bh 1851 sel = self.projection_list.selected_projections()
568 jonathan 751 if len(sel) == 1:
569 bh 1851 if sel[0][0] is None:
570 jonathan 751 # <None> is selected
571     return None
572    
573 bh 1851 # self.curProjPanel should always contain the most relevant data
574     # for a projection
575 jonathan 730 if self.curProjPanel is not None:
576 bh 2470 parameters = self.curProjPanel.GetParameters()
577     if parameters is not None:
578     return Projection(parameters, self.projname.GetValue())
579 jonathan 717
580 jonathan 751 return None
581 jonathan 730
582 bh 1851 def load_user_proj(self):
583 bh 1933 """Return the user's ProjFile
584    
585     If the file has not yet been loaded by the dialog, load it first
586     with get_user_proj_file and cache it in self.__usrProjFile.
587    
588     Show a busy cursor while loading the file.
589 frank 2022
590     If the file is not available, leave a note to the console.
591 bh 1933 """
592     if self.__usrProjFile is None:
593     ThubanBeginBusyCursor()
594     try:
595 bh 1851 projfile, warnings = get_user_proj_file()
596 frank 2022 if warnings:
597     sys.stderr.write("".join(warnings))
598 bh 1851 self.__usrProjFile = projfile
599 bh 1933 finally:
600     ThubanEndBusyCursor()
601     return self.__usrProjFile
602 jonathan 751
603 bh 1933 def load_system_proj(self, name):
604     """Load the system ProjFile with the given name.
605    
606     If the file has not been loaded yet, load it first with
607     get_system_proj_file and put it into the cache. The name is
608     simply forwarded to get_system_proj_file.
609    
610     Show a busy cursor while loading the file.
611     """
612     if name not in self._sys_proj_files:
613     ThubanBeginBusyCursor()
614     try:
615     projfile, warnings = get_system_proj_file(name)
616 bh 1851 self.show_warnings(_("Warnings"), projfile.GetFilename(),
617     warnings)
618 bh 1933 self._sys_proj_files[name] = projfile
619     finally:
620     ThubanEndBusyCursor()
621     return self._sys_proj_files[name]
622 jonathan 717
623 bh 1833 def write_proj_file(self, proj_file):
624     """Write the ProjFile object proj_file back to its file
625 frank 976
626 bh 1833 Show a busy cursor while writing and if an error occurs show a
627     dialog with the error message.
628     """
629     try:
630     ThubanBeginBusyCursor()
631     try:
632     write_proj_file(proj_file)
633     finally:
634     ThubanEndBusyCursor()
635     except IOError, (errno, errstr):
636     self.__ShowError(proj_file.GetFilename(), errstr)
637    
638    
639    
640 jonathan 717 class ProjPanel(wxPanel):
641     """Base class for all projection panels."""
642    
643     def __init__(self, parent):
644     wxPanel.__init__(self, parent, -1)
645    
646     self.__ellps = wxChoice(self, -1)
647 bh 1851 self.ellpsData = [("", _("<Unknown>")),
648     ("airy" , _("Airy")),
649 jonathan 816 ("bessel", _("Bessel 1841")),
650 bh 1851 ("clrk66", _("Clarke 1866")),
651 jonathan 717 ("clrk80", _("Clarke 1880")),
652     ("GRS80" , _("GRS 1980 (IUGG, 1980)")),
653     ("intl" , _("International 1909 (Hayford)")),
654     ("WGS84" , _("WGS 84"))]
655    
656     for tag, name in self.ellpsData:
657     self.__ellps.Append(name, tag)
658    
659     self.__ellps.SetSelection(0)
660    
661     def _DoLayout(self, childPanel = None):
662    
663     panelSizer = wxBoxSizer(wxVERTICAL)
664    
665     sizer = wxBoxSizer(wxHORIZONTAL)
666 frank 976 sizer.Add(wxStaticText(self, -1, _("Ellipsoid:")), 0,
667     wxALL|wxALIGN_CENTER_VERTICAL, 4)
668 frank 1034 sizer.Add(self.__ellps, 1, wxALL|wxALIGN_CENTER_VERTICAL, 4)
669 jonathan 717 panelSizer.Add(sizer, 0, wxALL|wxEXPAND, 4)
670    
671 frank 976 if childPanel is not None:
672     panelSizer.Add(childPanel, 0, wxEXPAND, 0)
673    
674 jonathan 717 self.SetAutoLayout(1)
675     self.SetSizer(panelSizer)
676     panelSizer.Fit(self)
677     panelSizer.SetSizeHints(self)
678     self.Layout()
679    
680     def SetProjection(self, proj):
681     if proj is not None:
682     param = proj.GetParameter("ellps")
683     i = 0
684     for tag, name in self.ellpsData:
685     if param == tag:
686     self.__ellps.SetSelection(i)
687     return # returning early!
688     i += 1
689    
690     #
691     # if proj is none, or the parameter couldn't be found...
692     #
693     self.__ellps.SetSelection(0)
694    
695     def GetParameters(self):
696 bh 1851 ellps = self.__ellps.GetSelection()
697     if ellps > 0:
698     return ["ellps=" + self.__ellps.GetClientData(ellps)]
699     return []
700 jonathan 717
701    
702     ID_TMPANEL_LAT = 4001
703     ID_TMPANEL_LONG = 4002
704     ID_TMPANEL_FASLE_EAST = 4003
705     ID_TMPANEL_FALSE_NORTH = 4004
706     ID_TMPANEL_SCALE = 4005
707    
708     class UnknownProjPanel(ProjPanel):
709 bh 1789
710     """Panel for unknown projection types"""
711    
712 jonathan 730 def __init__(self, parent, receiver):
713 jonathan 717 ProjPanel.__init__(self, parent)
714    
715 jan 1858 self.__text = _("Thuban does not know the parameters\n"
716     "for the current projection and cannot\n"
717     "display a configuration panel.\n\n"
718     "The unidentified set of parameters is:\n\n")
719    
720     self.__textbox = wxTextCtrl(self, -1, self.__text, size=(100,200),
721     style=wxTE_READONLY|wxTE_MULTILINE|wxTE_LINEWRAP)
722 jonathan 717 self._DoLayout()
723    
724     def _DoLayout(self):
725     sizer = wxBoxSizer(wxVERTICAL)
726    
727 jan 1858 sizer.Add(self.__textbox, 0, wxALL|wxEXPAND, 4)
728 jonathan 717
729     ProjPanel._DoLayout(self, sizer)
730    
731     def GetProjName(self):
732     return "Unknown"
733    
734     def SetProjection(self, proj):
735 jan 1858 """Append the available parameters to the info text."""
736     text = self.__text
737     for param in proj.GetAllParameters():
738     text = text + '%s\n' % param
739     self.__textbox.SetValue(text)
740 jonathan 717
741     def GetParameters(self):
742     return None
743    
744     class TMPanel(ProjPanel):
745 jonathan 730 """Projection panel for Transverse Mercator."""
746 jonathan 717
747 jonathan 730 def __init__(self, parent, receiver):
748 jonathan 717 ProjPanel.__init__(self, parent)
749    
750     self.__latitude = wxTextCtrl(self, ID_TMPANEL_LAT)
751     self.__longitude = wxTextCtrl(self, ID_TMPANEL_LONG)
752     self.__falseEast = wxTextCtrl(self, ID_TMPANEL_FASLE_EAST)
753     self.__falseNorth = wxTextCtrl(self, ID_TMPANEL_FALSE_NORTH)
754 bh 1851 self.__scale = wxTextCtrl(self, ID_TMPANEL_SCALE)
755 jonathan 717
756     self._DoLayout()
757    
758     def _DoLayout(self):
759    
760 bh 1809 sizer = wxFlexGridSizer(4, 2, 0, 0)
761 jonathan 717 sizer.Add(wxStaticText(self, -1, _("Latitude:")), 0, wxALL, 4)
762     sizer.Add(self.__latitude, 0, wxALL, 4)
763 bh 1809 sizer.Add(wxStaticText(self, -1, _("Longitude:")), 0, wxALL, 4)
764     sizer.Add(self.__longitude, 0, wxALL, 4)
765 jonathan 717 sizer.Add(wxStaticText(self, -1, _("False Easting:")), 0, wxALL, 4)
766     sizer.Add(self.__falseEast, 0, wxALL, 4)
767     sizer.Add(wxStaticText(self, -1, _("False Northing:")), 0, wxALL, 4)
768     sizer.Add(self.__falseNorth, 0, wxALL, 4)
769     sizer.Add(wxStaticText(self, -1, _("Scale Factor:")), 0, wxALL, 4)
770     sizer.Add(self.__scale, 0, wxALL, 4)
771    
772     ProjPanel._DoLayout(self, sizer)
773    
774     def GetProjName(self):
775 jonathan 730 return _("Transverse Mercator")
776 jonathan 717
777     def SetProjection(self, proj):
778     ProjPanel.SetProjection(self, proj)
779    
780     self.__latitude.SetValue(proj.GetParameter("lat_0"))
781     self.__longitude.SetValue(proj.GetParameter("lon_0"))
782     self.__falseEast.SetValue(proj.GetParameter("x_0"))
783     self.__falseNorth.SetValue(proj.GetParameter("y_0"))
784     self.__scale.SetValue(proj.GetParameter("k"))
785    
786     ProjPanel.SetProjection(self, proj)
787    
788     def GetParameters(self):
789     params = ["proj=tmerc",
790     "lat_0=" + self.__latitude.GetValue(),
791     "lon_0=" + self.__longitude.GetValue(),
792     "x_0=" + self.__falseEast.GetValue(),
793     "y_0=" + self.__falseNorth.GetValue(),
794     "k=" + self.__scale.GetValue()]
795     params.extend(ProjPanel.GetParameters(self))
796     return params
797    
798     def Clear(self):
799     self.__latitude.Clear()
800     self.__longitude.Clear()
801     self.__falseEast.Clear()
802     self.__falseNorth.Clear()
803     self.__scale.Clear()
804    
805     ProjPanel.Clear(self)
806    
807     ID_UTMPANEL_ZONE = 4001
808     ID_UTMPANEL_SOUTH = 4002
809     ID_UTMPANEL_PROP = 4003
810    
811     class UTMPanel(ProjPanel):
812 jonathan 730 """Projection Panel for Universal Transverse Mercator."""
813 jonathan 717
814 jonathan 730 def __init__(self, parent, receiver):
815 jonathan 717 ProjPanel.__init__(self, parent)
816    
817 jonathan 730 self.receiver = receiver
818 jonathan 717
819     self.__zone = wxSpinCtrl(self, ID_UTMPANEL_ZONE, "1", min=1, max=60)
820 jonathan 816 self.__propButton = wxButton(self, ID_UTMPANEL_PROP, _("Propose"))
821 jonathan 717 self.__south = wxCheckBox(self, ID_UTMPANEL_SOUTH,
822     _("Southern Hemisphere"))
823    
824     self._DoLayout()
825    
826     EVT_BUTTON(self, ID_UTMPANEL_PROP, self._OnPropose)
827    
828     def _DoLayout(self):
829    
830     sizer = wxBoxSizer(wxVERTICAL)
831     psizer = wxBoxSizer(wxHORIZONTAL)
832     psizer.Add(wxStaticText(self, -1, _("Zone:")), 0, wxALL, 4)
833     psizer.Add(self.__zone, 0, wxALL, 4)
834     psizer.Add(self.__propButton, 0, wxALL, 4)
835     sizer.Add(psizer, 0, wxALL, 4)
836     sizer.Add(self.__south, 0, wxALL, 4)
837    
838     ProjPanel._DoLayout(self, sizer)
839    
840     def GetProjName(self):
841 jonathan 730 return _("Universal Transverse Mercator")
842 jonathan 717
843     def SetProjection(self, proj):
844     self.__zone.SetValue(int(proj.GetParameter("zone")))
845     self.__south.SetValue(proj.GetParameter("south") != "")
846     ProjPanel.SetProjection(self, proj)
847    
848     def GetParameters(self):
849     params = ["proj=utm", "zone=" + str(self.__zone.GetValue())]
850     if self.__south.IsChecked():
851     params.append("south")
852    
853     params.extend(ProjPanel.GetParameters(self))
854     return params
855    
856     def Clear(self):
857     self.__zone.SetValue(1)
858     self.__south.SetValue(False)
859     ProjPanel.Clear(self)
860    
861     def _OnPropose(self, event):
862 jan 1549 """Call the propose dialog.
863     If the receiver (e.g. the current map) has no bounding box,
864     inform the user accordingly.
865     """
866     bb = self.receiver.BoundingBox()
867     if bb is None:
868     dlg = wxMessageDialog(self,
869     _("Can not propose: No bounding box found."),
870     _("Projection: Propose UTM Zone"),
871     wxOK | wxICON_INFORMATION)
872     dlg.CenterOnParent()
873     result = dlg.ShowModal()
874     dlg.Destroy()
875     return
876    
877 jonathan 730 dlg = UTMProposeZoneDialog(self, self.receiver.BoundingBox())
878 jonathan 717 if dlg.ShowModal() == wxID_OK:
879     self.__zone.SetValue(dlg.GetProposedZone())
880    
881     class LCCPanel(ProjPanel):
882     """Projection Panel for Lambert Conic Conformal."""
883    
884 jonathan 730 def __init__(self, parent, receiver):
885 jonathan 717 ProjPanel.__init__(self, parent)
886    
887     self.__fspLatitude = wxTextCtrl(self, -1)
888     self.__sspLatitude = wxTextCtrl(self, -1)
889 bh 1851 self.__meridian = wxTextCtrl(self, -1)
890 jonathan 717 self.__originLat = wxTextCtrl(self, -1)
891     self.__falseEast = wxTextCtrl(self, -1)
892     self.__falseNorth = wxTextCtrl(self, -1)
893    
894     self._DoLayout()
895    
896     def _DoLayout(self):
897    
898     sizer = wxFlexGridSizer(6, 2, 0, 0)
899     sizer.Add(wxStaticText(self, -1,
900     _("Latitude of first standard parallel:")))
901     sizer.Add(self.__fspLatitude, 0, wxALL, 4)
902     sizer.Add(wxStaticText(self, -1,
903     _("Latitude of second standard parallel:")))
904     sizer.Add(self.__sspLatitude, 0, wxALL, 4)
905 frank 1135 sizer.Add(wxStaticText(self, -1, _("Central Meridian:")))
906     sizer.Add(self.__meridian, 0, wxALL, 4)
907 jonathan 717 sizer.Add(wxStaticText(self, -1, _("Latitude of origin:")))
908     sizer.Add(self.__originLat, 0, wxALL, 4)
909     sizer.Add(wxStaticText(self, -1, _("False Easting:")))
910     sizer.Add(self.__falseEast, 0, wxALL, 4)
911     sizer.Add(wxStaticText(self, -1, _("False Northing:")))
912     sizer.Add(self.__falseNorth, 0, wxALL, 4)
913    
914     ProjPanel._DoLayout(self, sizer)
915    
916     def GetProjName(self):
917     return _("Lambert Conic Conformal")
918    
919     def SetProjection(self, proj):
920     self.__fspLatitude.SetValue(proj.GetParameter("lat_1"))
921     self.__sspLatitude.SetValue(proj.GetParameter("lat_2"))
922     self.__originLat.SetValue(proj.GetParameter("lat_0"))
923     self.__meridian.SetValue(proj.GetParameter("lon_0"))
924     self.__falseEast.SetValue(proj.GetParameter("x_0"))
925     self.__falseNorth.SetValue(proj.GetParameter("y_0"))
926    
927     ProjPanel.SetProjection(self, proj)
928    
929     def GetParameters(self):
930     params = ["proj=lcc",
931     "lat_1=" + self.__fspLatitude.GetValue(),
932     "lat_2=" + self.__sspLatitude.GetValue(),
933     "lat_0=" + self.__originLat.GetValue(),
934     "lon_0=" + self.__meridian.GetValue(),
935     "x_0=" + self.__falseEast.GetValue(),
936     "y_0=" + self.__falseNorth.GetValue()]
937    
938     params.extend(ProjPanel.GetParameters(self))
939     return params
940    
941     def Clear(self):
942     self.__fspLatitude.Clear()
943     self.__sspLatitude.Clear()
944     self.__originLat.Clear()
945     self.__meridian.Clear()
946     self.__falseEast.Clear()
947     self.__falseNorth.Clear()
948    
949     ProjPanel.Clear(self)
950    
951     class GeoPanel(ProjPanel):
952     """Projection Panel for a Geographic Projection."""
953    
954 jonathan 730 def __init__(self, parent, receiver):
955 jonathan 717 ProjPanel.__init__(self, parent)
956    
957 jonathan 964 self.__choices = [(_("Degrees"), "0.017453"),
958     (_("Radians"), "1")]
959 jonathan 797
960     self.__scale = wxChoice(self, -1)
961     for choice, value in self.__choices:
962     self.__scale.Append(choice, value)
963    
964     self._DoLayout()
965    
966 jonathan 717 def GetProjName(self):
967     return _("Geographic")
968    
969     def SetProjection(self, proj):
970 jonathan 797 value = proj.GetParameter("to_meter")
971     for i in range(len(self.__choices)):
972     choice, data = self.__choices[i]
973     if value == data:
974     self.__scale.SetSelection(i)
975 jonathan 717 ProjPanel.SetProjection(self, proj)
976    
977     def GetParameters(self):
978 jonathan 797 params = ["proj=latlong",
979     "to_meter=%s" % self.__scale.GetClientData(
980     self.__scale.GetSelection())]
981    
982 jonathan 717 params.extend(ProjPanel.GetParameters(self))
983     return params
984    
985     def Clear(self):
986     ProjPanel.Clear(self)
987    
988 jonathan 797 def _DoLayout(self):
989     sizer = wxBoxSizer(wxHORIZONTAL)
990 jonathan 717
991 jonathan 797 sizer.Add(wxStaticText(self, -1, _("Source Data is in: ")),
992 frank 976 0, wxALL|wxALIGN_CENTER_VERTICAL, 4)
993 jonathan 797 sizer.Add(self.__scale, 1, wxEXPAND|wxALL, 4)
994    
995     self.__scale.SetSelection(0)
996    
997     ProjPanel._DoLayout(self, sizer)
998    
999    
1000 jonathan 717 ID_UTM_PROPOSE_ZONE_DIALOG_TAKE = 4001
1001     ID_UTM_PROPOSE_ZONE_DIALOG_CANCEL = 4002
1002     class UTMProposeZoneDialog(wxDialog):
1003 bh 1566
1004 jonathan 717 """Propose a sensible Zone considering the current map extent."""
1005 bh 1566
1006 jonathan 717 def __init__(self, parent, (x, y, x2, y2)):
1007     wxDialog.__init__(self, parent, -1, _("Projection: Propose UTM Zone"),
1008     wxDefaultPosition, wxSize(200, 100))
1009     self.parent = parent
1010     x = x + 180
1011     x2 = x2 + 180
1012     center = (x2 - x) / 2 + x
1013     self.proposedZone = int(center / 6 + 1)
1014     self.dialogLayout()
1015 bh 1566
1016 jonathan 717 def dialogLayout(self):
1017     topBox = wxBoxSizer(wxVERTICAL)
1018 bh 1566
1019 jonathan 717 textBox = wxBoxSizer(wxVERTICAL)
1020 bh 1566 textBox.Add(wxStaticText(self, -1, _("The current map extent center "
1021     "lies in UTM Zone")),
1022 jonathan 717 0, wxALIGN_CENTER|wxALL, 4)
1023     textBox.Add(wxStaticText(self, -1, str(self.proposedZone)),
1024     0, wxALIGN_CENTER|wxALL, 4)
1025 bh 1566
1026 jonathan 717 topBox.Add(textBox, 1, wxEXPAND|wxALL, 4)
1027 bh 1566
1028 jonathan 717 buttonBox = wxBoxSizer(wxHORIZONTAL)
1029     buttonBox.Add(wxButton(self, ID_UTM_PROPOSE_ZONE_DIALOG_TAKE,
1030     _("Take")), 0, wxALL, 4)
1031     buttonBox.Add(wxButton(self, ID_UTM_PROPOSE_ZONE_DIALOG_CANCEL,
1032     _("Cancel")), 0, wxALL, 4)
1033     topBox.Add(buttonBox, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 10)
1034     EVT_BUTTON(self, ID_UTM_PROPOSE_ZONE_DIALOG_TAKE, self.OnTake)
1035     EVT_BUTTON(self, ID_UTM_PROPOSE_ZONE_DIALOG_CANCEL, self.OnCancel)
1036 bh 1566
1037 jonathan 717 self.SetAutoLayout(True)
1038     self.SetSizer(topBox)
1039     topBox.Fit(self)
1040     topBox.SetSizeHints(self)
1041 bh 1566
1042 jonathan 717 def OnTake(self, event):
1043     self.EndModal(wxID_OK)
1044 bh 1566
1045 jonathan 717 def OnCancel(self, event):
1046     self.EndModal(wxID_CANCEL)
1047    
1048     def GetProposedZone(self):
1049     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