/[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 1941 - (hide annotations)
Tue Nov 11 18:27:48 2003 UTC (21 years, 3 months ago) by bh
Original Path: trunk/thuban/Thuban/UI/projdialog.py
File MIME type: text/x-python
File size: 37133 byte(s)
(ProjFrame.build_dialog): Add a space
above the EPS widgets, introduce a check box for the deprecated
eps projections and a label for the epsg widgets
(ProjFrame._OnShowEPSG): Handle the deprecated EPSG projections
too

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     """
580     if self.__usrProjFile is None:
581     ThubanBeginBusyCursor()
582     try:
583 bh 1851 projfile, warnings = get_user_proj_file()
584     self.show_warnings(_("Warnings"), projfile.GetFilename(),
585     warnings)
586     self.__usrProjFile = projfile
587 bh 1933 finally:
588     ThubanEndBusyCursor()
589     return self.__usrProjFile
590 jonathan 751
591 bh 1933 def load_system_proj(self, name):
592     """Load the system ProjFile with the given name.
593    
594     If the file has not been loaded yet, load it first with
595     get_system_proj_file and put it into the cache. The name is
596     simply forwarded to get_system_proj_file.
597    
598     Show a busy cursor while loading the file.
599     """
600     if name not in self._sys_proj_files:
601     ThubanBeginBusyCursor()
602     try:
603     projfile, warnings = get_system_proj_file(name)
604 bh 1851 self.show_warnings(_("Warnings"), projfile.GetFilename(),
605     warnings)
606 bh 1933 self._sys_proj_files[name] = projfile
607     finally:
608     ThubanEndBusyCursor()
609     return self._sys_proj_files[name]
610 jonathan 717
611 bh 1833 def write_proj_file(self, proj_file):
612     """Write the ProjFile object proj_file back to its file
613 frank 976
614 bh 1833 Show a busy cursor while writing and if an error occurs show a
615     dialog with the error message.
616     """
617     try:
618     ThubanBeginBusyCursor()
619     try:
620     write_proj_file(proj_file)
621     finally:
622     ThubanEndBusyCursor()
623     except IOError, (errno, errstr):
624     self.__ShowError(proj_file.GetFilename(), errstr)
625    
626    
627    
628 jonathan 717 class ProjPanel(wxPanel):
629     """Base class for all projection panels."""
630    
631     def __init__(self, parent):
632     wxPanel.__init__(self, parent, -1)
633    
634     self.__ellps = wxChoice(self, -1)
635 bh 1851 self.ellpsData = [("", _("<Unknown>")),
636     ("airy" , _("Airy")),
637 jonathan 816 ("bessel", _("Bessel 1841")),
638 bh 1851 ("clrk66", _("Clarke 1866")),
639 jonathan 717 ("clrk80", _("Clarke 1880")),
640     ("GRS80" , _("GRS 1980 (IUGG, 1980)")),
641     ("intl" , _("International 1909 (Hayford)")),
642     ("WGS84" , _("WGS 84"))]
643    
644     for tag, name in self.ellpsData:
645     self.__ellps.Append(name, tag)
646    
647     self.__ellps.SetSelection(0)
648    
649     def _DoLayout(self, childPanel = None):
650    
651     panelSizer = wxBoxSizer(wxVERTICAL)
652    
653     sizer = wxBoxSizer(wxHORIZONTAL)
654 frank 976 sizer.Add(wxStaticText(self, -1, _("Ellipsoid:")), 0,
655     wxALL|wxALIGN_CENTER_VERTICAL, 4)
656 frank 1034 sizer.Add(self.__ellps, 1, wxALL|wxALIGN_CENTER_VERTICAL, 4)
657 jonathan 717 panelSizer.Add(sizer, 0, wxALL|wxEXPAND, 4)
658    
659 frank 976 if childPanel is not None:
660     panelSizer.Add(childPanel, 0, wxEXPAND, 0)
661    
662 jonathan 717 self.SetAutoLayout(1)
663     self.SetSizer(panelSizer)
664     panelSizer.Fit(self)
665     panelSizer.SetSizeHints(self)
666     self.Layout()
667    
668     def SetProjection(self, proj):
669     if proj is not None:
670     param = proj.GetParameter("ellps")
671     i = 0
672     for tag, name in self.ellpsData:
673     if param == tag:
674     self.__ellps.SetSelection(i)
675     return # returning early!
676     i += 1
677    
678     #
679     # if proj is none, or the parameter couldn't be found...
680     #
681     self.__ellps.SetSelection(0)
682    
683     def GetParameters(self):
684 bh 1851 ellps = self.__ellps.GetSelection()
685     if ellps > 0:
686     return ["ellps=" + self.__ellps.GetClientData(ellps)]
687     return []
688 jonathan 717
689    
690     ID_TMPANEL_LAT = 4001
691     ID_TMPANEL_LONG = 4002
692     ID_TMPANEL_FASLE_EAST = 4003
693     ID_TMPANEL_FALSE_NORTH = 4004
694     ID_TMPANEL_SCALE = 4005
695    
696     class UnknownProjPanel(ProjPanel):
697 bh 1789
698     """Panel for unknown projection types"""
699    
700 jonathan 730 def __init__(self, parent, receiver):
701 jonathan 717 ProjPanel.__init__(self, parent)
702    
703 jan 1858 self.__text = _("Thuban does not know the parameters\n"
704     "for the current projection and cannot\n"
705     "display a configuration panel.\n\n"
706     "The unidentified set of parameters is:\n\n")
707    
708     self.__textbox = wxTextCtrl(self, -1, self.__text, size=(100,200),
709     style=wxTE_READONLY|wxTE_MULTILINE|wxTE_LINEWRAP)
710 jonathan 717 self._DoLayout()
711    
712     def _DoLayout(self):
713     sizer = wxBoxSizer(wxVERTICAL)
714    
715 jan 1858 sizer.Add(self.__textbox, 0, wxALL|wxEXPAND, 4)
716 jonathan 717
717     ProjPanel._DoLayout(self, sizer)
718    
719     def GetProjName(self):
720     return "Unknown"
721    
722     def SetProjection(self, proj):
723 jan 1858 """Append the available parameters to the info text."""
724     text = self.__text
725     for param in proj.GetAllParameters():
726     text = text + '%s\n' % param
727     self.__textbox.SetValue(text)
728 jonathan 717
729     def GetParameters(self):
730     return None
731    
732     class TMPanel(ProjPanel):
733 jonathan 730 """Projection panel for Transverse Mercator."""
734 jonathan 717
735 jonathan 730 def __init__(self, parent, receiver):
736 jonathan 717 ProjPanel.__init__(self, parent)
737    
738     self.__latitude = wxTextCtrl(self, ID_TMPANEL_LAT)
739     self.__longitude = wxTextCtrl(self, ID_TMPANEL_LONG)
740     self.__falseEast = wxTextCtrl(self, ID_TMPANEL_FASLE_EAST)
741     self.__falseNorth = wxTextCtrl(self, ID_TMPANEL_FALSE_NORTH)
742 bh 1851 self.__scale = wxTextCtrl(self, ID_TMPANEL_SCALE)
743 jonathan 717
744     self._DoLayout()
745    
746     def _DoLayout(self):
747    
748 bh 1809 sizer = wxFlexGridSizer(4, 2, 0, 0)
749 jonathan 717 sizer.Add(wxStaticText(self, -1, _("Latitude:")), 0, wxALL, 4)
750     sizer.Add(self.__latitude, 0, wxALL, 4)
751 bh 1809 sizer.Add(wxStaticText(self, -1, _("Longitude:")), 0, wxALL, 4)
752     sizer.Add(self.__longitude, 0, wxALL, 4)
753 jonathan 717 sizer.Add(wxStaticText(self, -1, _("False Easting:")), 0, wxALL, 4)
754     sizer.Add(self.__falseEast, 0, wxALL, 4)
755     sizer.Add(wxStaticText(self, -1, _("False Northing:")), 0, wxALL, 4)
756     sizer.Add(self.__falseNorth, 0, wxALL, 4)
757     sizer.Add(wxStaticText(self, -1, _("Scale Factor:")), 0, wxALL, 4)
758     sizer.Add(self.__scale, 0, wxALL, 4)
759    
760     ProjPanel._DoLayout(self, sizer)
761    
762     def GetProjName(self):
763 jonathan 730 return _("Transverse Mercator")
764 jonathan 717
765     def SetProjection(self, proj):
766     ProjPanel.SetProjection(self, proj)
767    
768     self.__latitude.SetValue(proj.GetParameter("lat_0"))
769     self.__longitude.SetValue(proj.GetParameter("lon_0"))
770     self.__falseEast.SetValue(proj.GetParameter("x_0"))
771     self.__falseNorth.SetValue(proj.GetParameter("y_0"))
772     self.__scale.SetValue(proj.GetParameter("k"))
773    
774     ProjPanel.SetProjection(self, proj)
775    
776     def GetParameters(self):
777     params = ["proj=tmerc",
778     "lat_0=" + self.__latitude.GetValue(),
779     "lon_0=" + self.__longitude.GetValue(),
780     "x_0=" + self.__falseEast.GetValue(),
781     "y_0=" + self.__falseNorth.GetValue(),
782     "k=" + self.__scale.GetValue()]
783     params.extend(ProjPanel.GetParameters(self))
784     return params
785    
786     def Clear(self):
787     self.__latitude.Clear()
788     self.__longitude.Clear()
789     self.__falseEast.Clear()
790     self.__falseNorth.Clear()
791     self.__scale.Clear()
792    
793     ProjPanel.Clear(self)
794    
795     ID_UTMPANEL_ZONE = 4001
796     ID_UTMPANEL_SOUTH = 4002
797     ID_UTMPANEL_PROP = 4003
798    
799     class UTMPanel(ProjPanel):
800 jonathan 730 """Projection Panel for Universal Transverse Mercator."""
801 jonathan 717
802 jonathan 730 def __init__(self, parent, receiver):
803 jonathan 717 ProjPanel.__init__(self, parent)
804    
805 jonathan 730 self.receiver = receiver
806 jonathan 717
807     self.__zone = wxSpinCtrl(self, ID_UTMPANEL_ZONE, "1", min=1, max=60)
808 jonathan 816 self.__propButton = wxButton(self, ID_UTMPANEL_PROP, _("Propose"))
809 jonathan 717 self.__south = wxCheckBox(self, ID_UTMPANEL_SOUTH,
810     _("Southern Hemisphere"))
811    
812     self._DoLayout()
813    
814     EVT_BUTTON(self, ID_UTMPANEL_PROP, self._OnPropose)
815    
816     def _DoLayout(self):
817    
818     sizer = wxBoxSizer(wxVERTICAL)
819     psizer = wxBoxSizer(wxHORIZONTAL)
820     psizer.Add(wxStaticText(self, -1, _("Zone:")), 0, wxALL, 4)
821     psizer.Add(self.__zone, 0, wxALL, 4)
822     psizer.Add(self.__propButton, 0, wxALL, 4)
823     sizer.Add(psizer, 0, wxALL, 4)
824     sizer.Add(self.__south, 0, wxALL, 4)
825    
826     ProjPanel._DoLayout(self, sizer)
827    
828     def GetProjName(self):
829 jonathan 730 return _("Universal Transverse Mercator")
830 jonathan 717
831     def SetProjection(self, proj):
832     self.__zone.SetValue(int(proj.GetParameter("zone")))
833     self.__south.SetValue(proj.GetParameter("south") != "")
834     ProjPanel.SetProjection(self, proj)
835    
836     def GetParameters(self):
837     params = ["proj=utm", "zone=" + str(self.__zone.GetValue())]
838     if self.__south.IsChecked():
839     params.append("south")
840    
841     params.extend(ProjPanel.GetParameters(self))
842     return params
843    
844     def Clear(self):
845     self.__zone.SetValue(1)
846     self.__south.SetValue(False)
847     ProjPanel.Clear(self)
848    
849     def _OnPropose(self, event):
850 jan 1549 """Call the propose dialog.
851     If the receiver (e.g. the current map) has no bounding box,
852     inform the user accordingly.
853     """
854     bb = self.receiver.BoundingBox()
855     if bb is None:
856     dlg = wxMessageDialog(self,
857     _("Can not propose: No bounding box found."),
858     _("Projection: Propose UTM Zone"),
859     wxOK | wxICON_INFORMATION)
860     dlg.CenterOnParent()
861     result = dlg.ShowModal()
862     dlg.Destroy()
863     return
864    
865 jonathan 730 dlg = UTMProposeZoneDialog(self, self.receiver.BoundingBox())
866 jonathan 717 if dlg.ShowModal() == wxID_OK:
867     self.__zone.SetValue(dlg.GetProposedZone())
868    
869     class LCCPanel(ProjPanel):
870     """Projection Panel for Lambert Conic Conformal."""
871    
872 jonathan 730 def __init__(self, parent, receiver):
873 jonathan 717 ProjPanel.__init__(self, parent)
874    
875     self.__fspLatitude = wxTextCtrl(self, -1)
876     self.__sspLatitude = wxTextCtrl(self, -1)
877 bh 1851 self.__meridian = wxTextCtrl(self, -1)
878 jonathan 717 self.__originLat = wxTextCtrl(self, -1)
879     self.__falseEast = wxTextCtrl(self, -1)
880     self.__falseNorth = wxTextCtrl(self, -1)
881    
882     self._DoLayout()
883    
884     def _DoLayout(self):
885    
886     sizer = wxFlexGridSizer(6, 2, 0, 0)
887     sizer.Add(wxStaticText(self, -1,
888     _("Latitude of first standard parallel:")))
889     sizer.Add(self.__fspLatitude, 0, wxALL, 4)
890     sizer.Add(wxStaticText(self, -1,
891     _("Latitude of second standard parallel:")))
892     sizer.Add(self.__sspLatitude, 0, wxALL, 4)
893 frank 1135 sizer.Add(wxStaticText(self, -1, _("Central Meridian:")))
894     sizer.Add(self.__meridian, 0, wxALL, 4)
895 jonathan 717 sizer.Add(wxStaticText(self, -1, _("Latitude of origin:")))
896     sizer.Add(self.__originLat, 0, wxALL, 4)
897     sizer.Add(wxStaticText(self, -1, _("False Easting:")))
898     sizer.Add(self.__falseEast, 0, wxALL, 4)
899     sizer.Add(wxStaticText(self, -1, _("False Northing:")))
900     sizer.Add(self.__falseNorth, 0, wxALL, 4)
901    
902     ProjPanel._DoLayout(self, sizer)
903    
904     def GetProjName(self):
905     return _("Lambert Conic Conformal")
906    
907     def SetProjection(self, proj):
908     self.__fspLatitude.SetValue(proj.GetParameter("lat_1"))
909     self.__sspLatitude.SetValue(proj.GetParameter("lat_2"))
910     self.__originLat.SetValue(proj.GetParameter("lat_0"))
911     self.__meridian.SetValue(proj.GetParameter("lon_0"))
912     self.__falseEast.SetValue(proj.GetParameter("x_0"))
913     self.__falseNorth.SetValue(proj.GetParameter("y_0"))
914    
915     ProjPanel.SetProjection(self, proj)
916    
917     def GetParameters(self):
918     params = ["proj=lcc",
919     "lat_1=" + self.__fspLatitude.GetValue(),
920     "lat_2=" + self.__sspLatitude.GetValue(),
921     "lat_0=" + self.__originLat.GetValue(),
922     "lon_0=" + self.__meridian.GetValue(),
923     "x_0=" + self.__falseEast.GetValue(),
924     "y_0=" + self.__falseNorth.GetValue()]
925    
926     params.extend(ProjPanel.GetParameters(self))
927     return params
928    
929     def Clear(self):
930     self.__fspLatitude.Clear()
931     self.__sspLatitude.Clear()
932     self.__originLat.Clear()
933     self.__meridian.Clear()
934     self.__falseEast.Clear()
935     self.__falseNorth.Clear()
936    
937     ProjPanel.Clear(self)
938    
939     class GeoPanel(ProjPanel):
940     """Projection Panel for a Geographic Projection."""
941    
942 jonathan 730 def __init__(self, parent, receiver):
943 jonathan 717 ProjPanel.__init__(self, parent)
944    
945 jonathan 964 self.__choices = [(_("Degrees"), "0.017453"),
946     (_("Radians"), "1")]
947 jonathan 797
948     self.__scale = wxChoice(self, -1)
949     for choice, value in self.__choices:
950     self.__scale.Append(choice, value)
951    
952     self._DoLayout()
953    
954 jonathan 717 def GetProjName(self):
955     return _("Geographic")
956    
957     def SetProjection(self, proj):
958 jonathan 797 value = proj.GetParameter("to_meter")
959     for i in range(len(self.__choices)):
960     choice, data = self.__choices[i]
961     if value == data:
962     self.__scale.SetSelection(i)
963 jonathan 717 ProjPanel.SetProjection(self, proj)
964    
965     def GetParameters(self):
966 jonathan 797 params = ["proj=latlong",
967     "to_meter=%s" % self.__scale.GetClientData(
968     self.__scale.GetSelection())]
969    
970 jonathan 717 params.extend(ProjPanel.GetParameters(self))
971     return params
972    
973     def Clear(self):
974     ProjPanel.Clear(self)
975    
976 jonathan 797 def _DoLayout(self):
977     sizer = wxBoxSizer(wxHORIZONTAL)
978 jonathan 717
979 jonathan 797 sizer.Add(wxStaticText(self, -1, _("Source Data is in: ")),
980 frank 976 0, wxALL|wxALIGN_CENTER_VERTICAL, 4)
981 jonathan 797 sizer.Add(self.__scale, 1, wxEXPAND|wxALL, 4)
982    
983     self.__scale.SetSelection(0)
984    
985     ProjPanel._DoLayout(self, sizer)
986    
987    
988 jonathan 717 ID_UTM_PROPOSE_ZONE_DIALOG_TAKE = 4001
989     ID_UTM_PROPOSE_ZONE_DIALOG_CANCEL = 4002
990     class UTMProposeZoneDialog(wxDialog):
991 bh 1566
992 jonathan 717 """Propose a sensible Zone considering the current map extent."""
993 bh 1566
994 jonathan 717 def __init__(self, parent, (x, y, x2, y2)):
995     wxDialog.__init__(self, parent, -1, _("Projection: Propose UTM Zone"),
996     wxDefaultPosition, wxSize(200, 100))
997     self.parent = parent
998     x = x + 180
999     x2 = x2 + 180
1000     center = (x2 - x) / 2 + x
1001     self.proposedZone = int(center / 6 + 1)
1002     self.dialogLayout()
1003 bh 1566
1004 jonathan 717 def dialogLayout(self):
1005     topBox = wxBoxSizer(wxVERTICAL)
1006 bh 1566
1007 jonathan 717 textBox = wxBoxSizer(wxVERTICAL)
1008 bh 1566 textBox.Add(wxStaticText(self, -1, _("The current map extent center "
1009     "lies in UTM Zone")),
1010 jonathan 717 0, wxALIGN_CENTER|wxALL, 4)
1011     textBox.Add(wxStaticText(self, -1, str(self.proposedZone)),
1012     0, wxALIGN_CENTER|wxALL, 4)
1013 bh 1566
1014 jonathan 717 topBox.Add(textBox, 1, wxEXPAND|wxALL, 4)
1015 bh 1566
1016 jonathan 717 buttonBox = wxBoxSizer(wxHORIZONTAL)
1017     buttonBox.Add(wxButton(self, ID_UTM_PROPOSE_ZONE_DIALOG_TAKE,
1018     _("Take")), 0, wxALL, 4)
1019     buttonBox.Add(wxButton(self, ID_UTM_PROPOSE_ZONE_DIALOG_CANCEL,
1020     _("Cancel")), 0, wxALL, 4)
1021     topBox.Add(buttonBox, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 10)
1022     EVT_BUTTON(self, ID_UTM_PROPOSE_ZONE_DIALOG_TAKE, self.OnTake)
1023     EVT_BUTTON(self, ID_UTM_PROPOSE_ZONE_DIALOG_CANCEL, self.OnCancel)
1024 bh 1566
1025 jonathan 717 self.SetAutoLayout(True)
1026     self.SetSizer(topBox)
1027     topBox.Fit(self)
1028     topBox.SetSizeHints(self)
1029 bh 1566
1030 jonathan 717 def OnTake(self, event):
1031     self.EndModal(wxID_OK)
1032 bh 1566
1033 jonathan 717 def OnCancel(self, event):
1034     self.EndModal(wxID_CANCEL)
1035    
1036     def GetProposedZone(self):
1037     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