/[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 1786 - (hide annotations)
Wed Oct 8 10:39:11 2003 UTC (21 years, 5 months ago) by bh
Original Path: trunk/thuban/Thuban/UI/projdialog.py
File MIME type: text/x-python
File size: 35387 byte(s)
* Thuban/Model/resource.py (read_proj_file): Return the warnings
too. Update the doc-string
(get_proj_files): Removed. It wasn't used anywhere
(get_system_proj_files, get_system_proj_file): Rename to
get_system_proj_file and return the ProjFile object and not a list
of ProjFile objects. Update the callers.
(get_user_proj_files, get_user_proj_file): Rename to
get_user_proj_file return the ProjFile object and not a list of
ProjFile objects. Update the callers.
(ProjFileReader.__init__): New instance variable for the warnings.
Rename the __pf ivar to projfile. Update the methods referring to
__pf
(ProjFileReader.end_projection): Catch any errors raised when
instantiating the projection and record that as an error. The
projection will not be in the final ProjFile object.
(ProjFileReader.GetWarnings): New method to return the warnings.

* Thuban/UI/projdialog.py (ProjFrame.show_warnings): New method to
show the warnings from the projfile reader
(ProjFrame._OnImport): Deal with any warnings returned by
read_proj_file
(ProjFrame.__FillAvailList): Deal with any warnings returned by
get_system_proj_file or get_user_proj_file.

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