/[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 1854 - (hide annotations)
Wed Oct 22 09:38:36 2003 UTC (21 years, 4 months ago) by bh
Original Path: trunk/thuban/Thuban/UI/projdialog.py
File MIME type: text/x-python
File size: 34554 byte(s)
(ProjFrame.__init__): Do not set the
focus on the OK button, only on the projection list. That way the
list really has the focus initially
(ProjFrame.OnClose): Call the projection list's Destroy method to
make it unsubscribe all messages

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 bh 1851 else:
467     self.projfilepath.SetLabel(_("Multiple Projections selected"))
468 jonathan 717
469 jonathan 730 self.__VerifyButtons()
470    
471 jonathan 717 def _OnProjChoice(self, event):
472     self.__DoOnProjChoice()
473    
474     def __DoOnProjChoice(self):
475 jonathan 751 """Create and layout a projection panel based on the selected
476     projection type.
477    
478     This is necessary to have in seperate method since calls to
479     wxChoice.SetSelection() do not trigger an event.
480    
481     At the end of this method self.curProjPanel will not be None
482     if there was a item selected.
483     """
484 jonathan 717 choice = self.projchoice
485    
486     sel = choice.GetSelection()
487 jonathan 730 if sel != -1:
488 bh 1809 proj_type = choice.GetClientData(sel)
489     for t, name, cls in self.projection_panel_defs:
490     if t == proj_type:
491     self._show_proj_panel(cls)
492     break
493     # FIXME: what to do if sel == -1?
494 jonathan 717
495 bh 1809 def _show_proj_panel(self, panel_class):
496 bh 1789 """Show the panel as the projection panel"""
497 bh 1809 if panel_class is UnknownProjPanel:
498     self.edit_box.Disable()
499     self.nbsizer.Activate(self.unknown_projection_panel)
500     self.curProjPanel = self.unknown_projection_panel
501     else:
502     self.edit_box.Enable(True)
503     self.unknown_projection_panel.Hide()
504     for panel in self.projection_panels:
505     if panel.__class__ is panel_class:
506     self.nbsizer.Activate(panel)
507     self.curProjPanel = panel
508 jonathan 717
509     def __SetProjection(self):
510 jonathan 751 """Set the receiver's projection."""
511 jonathan 717
512     #
513     # save the original projection only once in case
514     # we try to apply several different projections
515     #
516 jonathan 730 self.receiver.SetProjection(self.__GetProjection())
517 jonathan 717
518 jonathan 730 def __GetProjection(self):
519 jonathan 751 """Return a suitable Projection object based on the current
520     state of the dialog box selections.
521 jonathan 717
522 jonathan 730 Could be None.
523     """
524 jonathan 717
525 bh 1851 assert self.projection_list.GetSelectedItemCount() < 2, \
526     "button should be disabled"
527 jonathan 717
528 bh 1851 sel = self.projection_list.selected_projections()
529 jonathan 751 if len(sel) == 1:
530 bh 1851 if sel[0][0] is None:
531 jonathan 751 # <None> is selected
532     return None
533    
534 bh 1851 # self.curProjPanel should always contain the most relevant data
535     # for a projection
536 jonathan 730 if self.curProjPanel is not None:
537 jonathan 751 return Projection(self.curProjPanel.GetParameters(),
538     self.projname.GetValue())
539 jonathan 717
540 jonathan 751 return None
541 jonathan 730
542 bh 1851 def load_user_proj(self):
543     ThubanBeginBusyCursor()
544     try:
545     if self.__usrProjFile is None:
546     projfile, warnings = get_user_proj_file()
547     self.show_warnings(_("Warnings"), projfile.GetFilename(),
548     warnings)
549     self.__usrProjFile = projfile
550     return self.__usrProjFile
551     finally:
552     ThubanEndBusyCursor()
553 jonathan 751
554 bh 1851 def load_system_proj(self):
555 bh 1833 ThubanBeginBusyCursor()
556     try:
557 bh 1851 if self.__sysProjFile is None:
558     projfile, warnings = get_system_proj_file()
559     self.show_warnings(_("Warnings"), projfile.GetFilename(),
560     warnings)
561     self.__sysProjFile = projfile
562     return self.__sysProjFile
563 bh 1833 finally:
564     ThubanEndBusyCursor()
565 jonathan 717
566 bh 1833 def write_proj_file(self, proj_file):
567     """Write the ProjFile object proj_file back to its file
568 frank 976
569 bh 1833 Show a busy cursor while writing and if an error occurs show a
570     dialog with the error message.
571     """
572     try:
573     ThubanBeginBusyCursor()
574     try:
575     write_proj_file(proj_file)
576     finally:
577     ThubanEndBusyCursor()
578     except IOError, (errno, errstr):
579     self.__ShowError(proj_file.GetFilename(), errstr)
580    
581    
582    
583 jonathan 717 class ProjPanel(wxPanel):
584     """Base class for all projection panels."""
585    
586     def __init__(self, parent):
587     wxPanel.__init__(self, parent, -1)
588    
589     self.__ellps = wxChoice(self, -1)
590 bh 1851 self.ellpsData = [("", _("<Unknown>")),
591     ("airy" , _("Airy")),
592 jonathan 816 ("bessel", _("Bessel 1841")),
593 bh 1851 ("clrk66", _("Clarke 1866")),
594 jonathan 717 ("clrk80", _("Clarke 1880")),
595     ("GRS80" , _("GRS 1980 (IUGG, 1980)")),
596     ("intl" , _("International 1909 (Hayford)")),
597     ("WGS84" , _("WGS 84"))]
598    
599     for tag, name in self.ellpsData:
600     self.__ellps.Append(name, tag)
601    
602     self.__ellps.SetSelection(0)
603    
604     def _DoLayout(self, childPanel = None):
605    
606     panelSizer = wxBoxSizer(wxVERTICAL)
607    
608     sizer = wxBoxSizer(wxHORIZONTAL)
609 frank 976 sizer.Add(wxStaticText(self, -1, _("Ellipsoid:")), 0,
610     wxALL|wxALIGN_CENTER_VERTICAL, 4)
611 frank 1034 sizer.Add(self.__ellps, 1, wxALL|wxALIGN_CENTER_VERTICAL, 4)
612 jonathan 717 panelSizer.Add(sizer, 0, wxALL|wxEXPAND, 4)
613    
614 frank 976 if childPanel is not None:
615     panelSizer.Add(childPanel, 0, wxEXPAND, 0)
616    
617 jonathan 717 self.SetAutoLayout(1)
618     self.SetSizer(panelSizer)
619     panelSizer.Fit(self)
620     panelSizer.SetSizeHints(self)
621     self.Layout()
622    
623     def SetProjection(self, proj):
624     if proj is not None:
625     param = proj.GetParameter("ellps")
626     i = 0
627     for tag, name in self.ellpsData:
628     if param == tag:
629     self.__ellps.SetSelection(i)
630     return # returning early!
631     i += 1
632    
633     #
634     # if proj is none, or the parameter couldn't be found...
635     #
636     self.__ellps.SetSelection(0)
637    
638     def GetParameters(self):
639 bh 1851 ellps = self.__ellps.GetSelection()
640     if ellps > 0:
641     return ["ellps=" + self.__ellps.GetClientData(ellps)]
642     return []
643 jonathan 717
644    
645     ID_TMPANEL_LAT = 4001
646     ID_TMPANEL_LONG = 4002
647     ID_TMPANEL_FASLE_EAST = 4003
648     ID_TMPANEL_FALSE_NORTH = 4004
649     ID_TMPANEL_SCALE = 4005
650    
651     class UnknownProjPanel(ProjPanel):
652 bh 1789
653     """Panel for unknown projection types"""
654    
655 jonathan 730 def __init__(self, parent, receiver):
656 jonathan 717 ProjPanel.__init__(self, parent)
657    
658     self._DoLayout()
659    
660     def _DoLayout(self):
661     sizer = wxBoxSizer(wxVERTICAL)
662    
663 bh 1579 sizer.Add(wxStaticText(self, -1,
664 bh 1809 _("Thuban does not know the parameters\n"
665     "for the current projection and cannot\n"
666     "display a configuration panel.")))
667 jonathan 717
668     ProjPanel._DoLayout(self, sizer)
669    
670     def GetProjName(self):
671     return "Unknown"
672    
673     def SetProjection(self, proj):
674     pass
675    
676     def GetParameters(self):
677     return None
678    
679     class TMPanel(ProjPanel):
680 jonathan 730 """Projection panel for Transverse Mercator."""
681 jonathan 717
682 jonathan 730 def __init__(self, parent, receiver):
683 jonathan 717 ProjPanel.__init__(self, parent)
684    
685     self.__latitude = wxTextCtrl(self, ID_TMPANEL_LAT)
686     self.__longitude = wxTextCtrl(self, ID_TMPANEL_LONG)
687     self.__falseEast = wxTextCtrl(self, ID_TMPANEL_FASLE_EAST)
688     self.__falseNorth = wxTextCtrl(self, ID_TMPANEL_FALSE_NORTH)
689 bh 1851 self.__scale = wxTextCtrl(self, ID_TMPANEL_SCALE)
690 jonathan 717
691     self._DoLayout()
692    
693     def _DoLayout(self):
694    
695 bh 1809 sizer = wxFlexGridSizer(4, 2, 0, 0)
696 jonathan 717 sizer.Add(wxStaticText(self, -1, _("Latitude:")), 0, wxALL, 4)
697     sizer.Add(self.__latitude, 0, wxALL, 4)
698 bh 1809 sizer.Add(wxStaticText(self, -1, _("Longitude:")), 0, wxALL, 4)
699     sizer.Add(self.__longitude, 0, wxALL, 4)
700 jonathan 717 sizer.Add(wxStaticText(self, -1, _("False Easting:")), 0, wxALL, 4)
701     sizer.Add(self.__falseEast, 0, wxALL, 4)
702     sizer.Add(wxStaticText(self, -1, _("False Northing:")), 0, wxALL, 4)
703     sizer.Add(self.__falseNorth, 0, wxALL, 4)
704     sizer.Add(wxStaticText(self, -1, _("Scale Factor:")), 0, wxALL, 4)
705     sizer.Add(self.__scale, 0, wxALL, 4)
706    
707     ProjPanel._DoLayout(self, sizer)
708    
709     def GetProjName(self):
710 jonathan 730 return _("Transverse Mercator")
711 jonathan 717
712     def SetProjection(self, proj):
713     ProjPanel.SetProjection(self, proj)
714    
715     self.__latitude.SetValue(proj.GetParameter("lat_0"))
716     self.__longitude.SetValue(proj.GetParameter("lon_0"))
717     self.__falseEast.SetValue(proj.GetParameter("x_0"))
718     self.__falseNorth.SetValue(proj.GetParameter("y_0"))
719     self.__scale.SetValue(proj.GetParameter("k"))
720    
721     ProjPanel.SetProjection(self, proj)
722    
723     def GetParameters(self):
724     params = ["proj=tmerc",
725     "lat_0=" + self.__latitude.GetValue(),
726     "lon_0=" + self.__longitude.GetValue(),
727     "x_0=" + self.__falseEast.GetValue(),
728     "y_0=" + self.__falseNorth.GetValue(),
729     "k=" + self.__scale.GetValue()]
730     params.extend(ProjPanel.GetParameters(self))
731     return params
732    
733     def Clear(self):
734     self.__latitude.Clear()
735     self.__longitude.Clear()
736     self.__falseEast.Clear()
737     self.__falseNorth.Clear()
738     self.__scale.Clear()
739    
740     ProjPanel.Clear(self)
741    
742     ID_UTMPANEL_ZONE = 4001
743     ID_UTMPANEL_SOUTH = 4002
744     ID_UTMPANEL_PROP = 4003
745    
746     class UTMPanel(ProjPanel):
747 jonathan 730 """Projection Panel for Universal Transverse Mercator."""
748 jonathan 717
749 jonathan 730 def __init__(self, parent, receiver):
750 jonathan 717 ProjPanel.__init__(self, parent)
751    
752 jonathan 730 self.receiver = receiver
753 jonathan 717
754     self.__zone = wxSpinCtrl(self, ID_UTMPANEL_ZONE, "1", min=1, max=60)
755 jonathan 816 self.__propButton = wxButton(self, ID_UTMPANEL_PROP, _("Propose"))
756 jonathan 717 self.__south = wxCheckBox(self, ID_UTMPANEL_SOUTH,
757     _("Southern Hemisphere"))
758    
759     self._DoLayout()
760    
761     EVT_BUTTON(self, ID_UTMPANEL_PROP, self._OnPropose)
762    
763     def _DoLayout(self):
764    
765     sizer = wxBoxSizer(wxVERTICAL)
766     psizer = wxBoxSizer(wxHORIZONTAL)
767     psizer.Add(wxStaticText(self, -1, _("Zone:")), 0, wxALL, 4)
768     psizer.Add(self.__zone, 0, wxALL, 4)
769     psizer.Add(self.__propButton, 0, wxALL, 4)
770     sizer.Add(psizer, 0, wxALL, 4)
771     sizer.Add(self.__south, 0, wxALL, 4)
772    
773     ProjPanel._DoLayout(self, sizer)
774    
775     def GetProjName(self):
776 jonathan 730 return _("Universal Transverse Mercator")
777 jonathan 717
778     def SetProjection(self, proj):
779     self.__zone.SetValue(int(proj.GetParameter("zone")))
780     self.__south.SetValue(proj.GetParameter("south") != "")
781     ProjPanel.SetProjection(self, proj)
782    
783     def GetParameters(self):
784     params = ["proj=utm", "zone=" + str(self.__zone.GetValue())]
785     if self.__south.IsChecked():
786     params.append("south")
787    
788     params.extend(ProjPanel.GetParameters(self))
789     return params
790    
791     def Clear(self):
792     self.__zone.SetValue(1)
793     self.__south.SetValue(False)
794     ProjPanel.Clear(self)
795    
796     def _OnPropose(self, event):
797 jan 1549 """Call the propose dialog.
798     If the receiver (e.g. the current map) has no bounding box,
799     inform the user accordingly.
800     """
801     bb = self.receiver.BoundingBox()
802     if bb is None:
803     dlg = wxMessageDialog(self,
804     _("Can not propose: No bounding box found."),
805     _("Projection: Propose UTM Zone"),
806     wxOK | wxICON_INFORMATION)
807     dlg.CenterOnParent()
808     result = dlg.ShowModal()
809     dlg.Destroy()
810     return
811    
812 jonathan 730 dlg = UTMProposeZoneDialog(self, self.receiver.BoundingBox())
813 jonathan 717 if dlg.ShowModal() == wxID_OK:
814     self.__zone.SetValue(dlg.GetProposedZone())
815    
816     class LCCPanel(ProjPanel):
817     """Projection Panel for Lambert Conic Conformal."""
818    
819 jonathan 730 def __init__(self, parent, receiver):
820 jonathan 717 ProjPanel.__init__(self, parent)
821    
822     self.__fspLatitude = wxTextCtrl(self, -1)
823     self.__sspLatitude = wxTextCtrl(self, -1)
824 bh 1851 self.__meridian = wxTextCtrl(self, -1)
825 jonathan 717 self.__originLat = wxTextCtrl(self, -1)
826     self.__falseEast = wxTextCtrl(self, -1)
827     self.__falseNorth = wxTextCtrl(self, -1)
828    
829     self._DoLayout()
830    
831     def _DoLayout(self):
832    
833     sizer = wxFlexGridSizer(6, 2, 0, 0)
834     sizer.Add(wxStaticText(self, -1,
835     _("Latitude of first standard parallel:")))
836     sizer.Add(self.__fspLatitude, 0, wxALL, 4)
837     sizer.Add(wxStaticText(self, -1,
838     _("Latitude of second standard parallel:")))
839     sizer.Add(self.__sspLatitude, 0, wxALL, 4)
840 frank 1135 sizer.Add(wxStaticText(self, -1, _("Central Meridian:")))
841     sizer.Add(self.__meridian, 0, wxALL, 4)
842 jonathan 717 sizer.Add(wxStaticText(self, -1, _("Latitude of origin:")))
843     sizer.Add(self.__originLat, 0, wxALL, 4)
844     sizer.Add(wxStaticText(self, -1, _("False Easting:")))
845     sizer.Add(self.__falseEast, 0, wxALL, 4)
846     sizer.Add(wxStaticText(self, -1, _("False Northing:")))
847     sizer.Add(self.__falseNorth, 0, wxALL, 4)
848    
849     ProjPanel._DoLayout(self, sizer)
850    
851     def GetProjName(self):
852     return _("Lambert Conic Conformal")
853    
854     def SetProjection(self, proj):
855     self.__fspLatitude.SetValue(proj.GetParameter("lat_1"))
856     self.__sspLatitude.SetValue(proj.GetParameter("lat_2"))
857     self.__originLat.SetValue(proj.GetParameter("lat_0"))
858     self.__meridian.SetValue(proj.GetParameter("lon_0"))
859     self.__falseEast.SetValue(proj.GetParameter("x_0"))
860     self.__falseNorth.SetValue(proj.GetParameter("y_0"))
861    
862     ProjPanel.SetProjection(self, proj)
863    
864     def GetParameters(self):
865     params = ["proj=lcc",
866     "lat_1=" + self.__fspLatitude.GetValue(),
867     "lat_2=" + self.__sspLatitude.GetValue(),
868     "lat_0=" + self.__originLat.GetValue(),
869     "lon_0=" + self.__meridian.GetValue(),
870     "x_0=" + self.__falseEast.GetValue(),
871     "y_0=" + self.__falseNorth.GetValue()]
872    
873     params.extend(ProjPanel.GetParameters(self))
874     return params
875    
876     def Clear(self):
877     self.__fspLatitude.Clear()
878     self.__sspLatitude.Clear()
879     self.__originLat.Clear()
880     self.__meridian.Clear()
881     self.__falseEast.Clear()
882     self.__falseNorth.Clear()
883    
884     ProjPanel.Clear(self)
885    
886     class GeoPanel(ProjPanel):
887     """Projection Panel for a Geographic Projection."""
888    
889 jonathan 730 def __init__(self, parent, receiver):
890 jonathan 717 ProjPanel.__init__(self, parent)
891    
892 jonathan 964 self.__choices = [(_("Degrees"), "0.017453"),
893     (_("Radians"), "1")]
894 jonathan 797
895     self.__scale = wxChoice(self, -1)
896     for choice, value in self.__choices:
897     self.__scale.Append(choice, value)
898    
899     self._DoLayout()
900    
901 jonathan 717 def GetProjName(self):
902     return _("Geographic")
903    
904     def SetProjection(self, proj):
905 jonathan 797 value = proj.GetParameter("to_meter")
906     for i in range(len(self.__choices)):
907     choice, data = self.__choices[i]
908     if value == data:
909     self.__scale.SetSelection(i)
910 jonathan 717 ProjPanel.SetProjection(self, proj)
911    
912     def GetParameters(self):
913 jonathan 797 params = ["proj=latlong",
914     "to_meter=%s" % self.__scale.GetClientData(
915     self.__scale.GetSelection())]
916    
917 jonathan 717 params.extend(ProjPanel.GetParameters(self))
918     return params
919    
920     def Clear(self):
921     ProjPanel.Clear(self)
922    
923 jonathan 797 def _DoLayout(self):
924     sizer = wxBoxSizer(wxHORIZONTAL)
925 jonathan 717
926 jonathan 797 sizer.Add(wxStaticText(self, -1, _("Source Data is in: ")),
927 frank 976 0, wxALL|wxALIGN_CENTER_VERTICAL, 4)
928 jonathan 797 sizer.Add(self.__scale, 1, wxEXPAND|wxALL, 4)
929    
930     self.__scale.SetSelection(0)
931    
932     ProjPanel._DoLayout(self, sizer)
933    
934    
935 jonathan 717 ID_UTM_PROPOSE_ZONE_DIALOG_TAKE = 4001
936     ID_UTM_PROPOSE_ZONE_DIALOG_CANCEL = 4002
937     class UTMProposeZoneDialog(wxDialog):
938 bh 1566
939 jonathan 717 """Propose a sensible Zone considering the current map extent."""
940 bh 1566
941 jonathan 717 def __init__(self, parent, (x, y, x2, y2)):
942     wxDialog.__init__(self, parent, -1, _("Projection: Propose UTM Zone"),
943     wxDefaultPosition, wxSize(200, 100))
944     self.parent = parent
945     x = x + 180
946     x2 = x2 + 180
947     center = (x2 - x) / 2 + x
948     self.proposedZone = int(center / 6 + 1)
949     self.dialogLayout()
950 bh 1566
951 jonathan 717 def dialogLayout(self):
952     topBox = wxBoxSizer(wxVERTICAL)
953 bh 1566
954 jonathan 717 textBox = wxBoxSizer(wxVERTICAL)
955 bh 1566 textBox.Add(wxStaticText(self, -1, _("The current map extent center "
956     "lies in UTM Zone")),
957 jonathan 717 0, wxALIGN_CENTER|wxALL, 4)
958     textBox.Add(wxStaticText(self, -1, str(self.proposedZone)),
959     0, wxALIGN_CENTER|wxALL, 4)
960 bh 1566
961 jonathan 717 topBox.Add(textBox, 1, wxEXPAND|wxALL, 4)
962 bh 1566
963 jonathan 717 buttonBox = wxBoxSizer(wxHORIZONTAL)
964     buttonBox.Add(wxButton(self, ID_UTM_PROPOSE_ZONE_DIALOG_TAKE,
965     _("Take")), 0, wxALL, 4)
966     buttonBox.Add(wxButton(self, ID_UTM_PROPOSE_ZONE_DIALOG_CANCEL,
967     _("Cancel")), 0, wxALL, 4)
968     topBox.Add(buttonBox, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 10)
969     EVT_BUTTON(self, ID_UTM_PROPOSE_ZONE_DIALOG_TAKE, self.OnTake)
970     EVT_BUTTON(self, ID_UTM_PROPOSE_ZONE_DIALOG_CANCEL, self.OnCancel)
971 bh 1566
972 jonathan 717 self.SetAutoLayout(True)
973     self.SetSizer(topBox)
974     topBox.Fit(self)
975     topBox.SetSizeHints(self)
976 bh 1566
977 jonathan 717 def OnTake(self, event):
978     self.EndModal(wxID_OK)
979 bh 1566
980 jonathan 717 def OnCancel(self, event):
981     self.EndModal(wxID_CANCEL)
982    
983     def GetProposedZone(self):
984     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