/[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 1858 - (hide annotations)
Fri Oct 24 15:12:58 2003 UTC (21 years, 4 months ago) by jan
Original Path: trunk/thuban/Thuban/UI/projdialog.py
File MIME type: text/x-python
File size: 35085 byte(s)
(ProjFrame.proj_selection_changed): Set the projection even for the
UnknownPanel.
(UnknownProjPanel.__init__): Define the text and create the textctrl
widget.
(UnknownProjPanel._DoLayout): Replaced static text widget by the
textctrl created in __init__.
(UnknownProjPanel.SetProjection): Set the text for the text ctrl
including the parameters of the projection.

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