/[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 1566 - (hide annotations)
Fri Aug 8 13:01:30 2003 UTC (21 years, 7 months ago) by bh
Original Path: trunk/thuban/Thuban/UI/projdialog.py
File MIME type: text/x-python
File size: 34793 byte(s)
Make sure translated strings are recognized as one string literal.

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