/[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 1833 - (hide annotations)
Mon Oct 20 11:00:57 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: 35282 byte(s)
(ProjFrame.write_proj_file): New. helper
method to write a projfile and display a busy cursor and error
dialogs.
(ProjFrame._OnSave, ProjFrame._OnAddToList, ProjFrame._OnImport)
(ProjFrame._OnExport, ProjFrame._OnRemove): Use write_proj_file
(ProjFrame.__FillAvailList): Translate "<None>" too and display a
busy cursor while loading the user and system prj files.

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