/[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 1809 - (show annotations)
Fri Oct 10 17:00:17 2003 UTC (21 years, 4 months ago) by bh
Original Path: trunk/thuban/Thuban/UI/projdialog.py
File MIME type: text/x-python
File size: 34912 byte(s)
(ProjFrame.build_dialog): Instantiate
all projection type specific panels and put them into a
NotebookLikeSizer. This way the dialog doesn't change its size
when a different projection is selected
(ProjFrame.__init__): Rename projection_panels
projection_panel_defs and reuse projection_panels for a list of
the instantiated panels.
(ProjFrame._show_proj_panel, ProjFrame.__DoOnProjAvail)
(ProjFrame.__DoOnProjChoice): Changes due to the new handling of
the panels
(UnknownProjPanel._DoLayout): Place the newlines in the message
differently to make the panel narrower.
(TMPanel._DoLayout): Layout the parameters in one column.

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