/[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 1806 - (hide annotations)
Fri Oct 10 10:36:34 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: 34177 byte(s)
(ProjFrame.build_dialog): New method
that contains all the setup for the dialog's widgets, layout and
event handling.
(__): Call build_dialog to build the dialog.
(ProjFrame.__set_properties, ProjFrame.__do_layout): Removed.
Their functionality is now in build_dialog
(ProjFrame.__VerifyButtons, ProjFrame.__VerifyButtons)
(ProjFrame.__DoOnProjAvail, ProjFrame.__DoOnProjAvail)
(ProjFrame.__DoOnProjChoice): Small updates due to slightly
different widget names and hierarchy introduced with build_dialog.

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