/[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 2561 - (hide annotations)
Tue Feb 8 20:34:29 2005 UTC (20 years ago) by bh
Original Path: trunk/thuban/Thuban/UI/projdialog.py
File MIME type: text/x-python
File size: 37713 byte(s)
More wxPython 2.5 changes.  This time taken from a patch from
Daniel Calvelo Aros.

* Thuban/UI/tableview.py (QueryTableFrame.__init__)
(QueryTableFrame.__init__): Pass the size of a spacer as a single
item.

* Thuban/UI/projdialog.py (ProjFrame.build_dialog)
(ProjFrame.build_dialog): Pass the size of a spacer as a single
item.

* Thuban/UI/dbdialog.py (ChooseDBTableDialog.__init__): Pass the
size of a spacer as a single item.

* Thuban/UI/classifier.py (Classifier.dialog_layout): Pass the
size of a spacer as a single item.

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