/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/UI/projdialog.py
ViewVC logotype

Contents of /branches/WIP-pyshapelib-bramz/Thuban/UI/projdialog.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1789 - (show annotations)
Wed Oct 8 13:10:45 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: 35828 byte(s)
(ProjFrame.__DoOnProjAvail): When the
projection type of the currently selected projection is not known,
i.e. there's no panel for it, use the UnknownProjPanel
(ProjFrame.__DoOnProjChoice, ProjFrame._show_proj_panel): Split
the actual replacing of the proj panel into the new method
_show_proj_panel.
(UnknownProjPanel): Add doc-string.
(UnknownProjPanel._DoLayout): Insert a newline into the text so
that the panel is not so wide.

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