/[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 1795 - (show annotations)
Wed Oct 8 17:35:52 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: 35788 byte(s)
(ProjFrame.__set_properties): Remove the
length limit on the projname text control

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 def __do_layout(self):
566 # originally generated by wxGlade
567
568 self.topBox = wxBoxSizer(wxVERTICAL)
569 self.sizer_panel = wxBoxSizer(wxVERTICAL)
570 sizer_6 = wxBoxSizer(wxHORIZONTAL)
571 self.sizer_mainbttns = wxBoxSizer(wxHORIZONTAL)
572 self.sizer_mainctrls = wxBoxSizer(wxHORIZONTAL)
573 self.sizer_edit = wxStaticBoxSizer(wxStaticBox(self.panel_edit, -1, _("Edit")), wxHORIZONTAL)
574 sizer_11 = wxBoxSizer(wxVERTICAL)
575 self.sizer_projctrls = wxBoxSizer(wxVERTICAL)
576 sizer_14 = wxBoxSizer(wxHORIZONTAL)
577 sizer_13 = wxBoxSizer(wxHORIZONTAL)
578 sizer_15 = wxBoxSizer(wxVERTICAL)
579 sizer_15.Add(self.button_import, 0, wxALL, 4)
580 sizer_15.Add(self.button_export, 0, wxALL, 4)
581 sizer_15.Add(20, 20, 0, wxEXPAND, 0)
582 sizer_15.Add(self.button_remove, 0, wxALL|wxALIGN_BOTTOM, 4)
583
584 # list controls
585 grid_sizer_1 = wxFlexGridSizer(3, 2, 0, 0)
586 grid_sizer_1.Add(self.label_5, 0, wxLEFT|wxRIGHT|wxTOP, 4)
587 grid_sizer_1.Add(20, 20, 0, wxEXPAND, 0)
588 grid_sizer_1.Add(self.availprojs, 1, wxALL|wxEXPAND|wxADJUST_MINSIZE, 4)
589 grid_sizer_1.Add(sizer_15, 0, wxALL|wxEXPAND, 4)
590 grid_sizer_1.Add(self.projfilepath, 0, wxEXPAND|wxALL|wxADJUST_MINSIZE, 4)
591 grid_sizer_1.AddGrowableRow(1)
592 grid_sizer_1.AddGrowableCol(0)
593
594 # edit controls
595 sizer_13.Add(self.label_2, 0, wxALL|wxALIGN_CENTER_VERTICAL, 4)
596 sizer_13.Add(self.projname, 1, wxALL, 4)
597 self.sizer_projctrls.Add(sizer_13, 0, wxEXPAND, 0)
598 sizer_14.Add(self.label_3, 0, wxALL|wxALIGN_CENTER_VERTICAL, 4)
599 sizer_14.Add(self.projchoice, 1, wxALL|wxALIGN_CENTER_VERTICAL, 4)
600 self.sizer_projctrls.Add(sizer_14, 0, wxEXPAND, 0)
601 self.sizer_edit.Add(self.sizer_projctrls, 1, wxEXPAND, 0)
602 sizer_11.Add(self.button_new, 0, wxEXPAND|wxALL, 4)
603 sizer_11.Add(self.button_add, 0, wxEXPAND|wxALL, 4)
604 sizer_11.Add(20, 20, 0, wxEXPAND, 0)
605 sizer_11.Add(self.button_save, 0, wxEXPAND|wxALL|wxALIGN_BOTTOM, 4)
606 self.sizer_edit.Add(sizer_11, 0, wxALL|wxEXPAND, 4)
607
608 sizer_6.Add(self.button_try, 0, wxRIGHT| wxEXPAND, 10)
609 sizer_6.Add(self.button_revert, 0, wxRIGHT| wxEXPAND, 10)
610 sizer_6.Add(self.button_ok, 0, wxRIGHT| wxEXPAND, 10)
611 sizer_6.Add(self.button_close, 0, wxRIGHT| wxEXPAND, 10)
612
613 self.panel_1.SetAutoLayout(1)
614 self.panel_1.SetSizer(grid_sizer_1)
615 grid_sizer_1.Fit(self.panel_1)
616 grid_sizer_1.SetSizeHints(self.panel_1)
617
618 self.panel_edit.SetAutoLayout(1)
619 self.panel_edit.SetSizer(self.sizer_edit)
620 self.sizer_edit.Fit(self.panel_edit)
621 self.sizer_edit.SetSizeHints(self.panel_edit)
622
623 self.sizer_mainctrls.Add(self.panel_1, 0,
624 wxALL|wxEXPAND|wxADJUST_MINSIZE, 0)
625 self.sizer_mainctrls.Add(self.panel_edit, 1,
626 wxALL|wxEXPAND|wxADJUST_MINSIZE, 0)
627
628 self.sizer_mainbttns.Add(sizer_6, 0,
629 wxALL|wxEXPAND|wxADJUST_MINSIZE, 10)
630
631 self.topBox.Add(self.sizer_mainctrls, 1, wxALL|wxEXPAND, 4)
632 self.topBox.Add(self.sizer_mainbttns, 0, wxALIGN_RIGHT|wxBOTTOM, 0)
633
634 self.SetAutoLayout(1)
635 self.SetSizer(self.topBox)
636 self.topBox.Fit(self)
637 self.topBox.SetSizeHints(self)
638 self.Layout()
639
640 # end of class ProjFrame
641
642
643 class ProjPanel(wxPanel):
644 """Base class for all projection panels."""
645
646 def __init__(self, parent):
647 wxPanel.__init__(self, parent, -1)
648
649 self.__ellps = wxChoice(self, -1)
650 self.ellpsData = [("airy" , _("Airy")),
651 ("bessel", _("Bessel 1841")),
652 ("clrk66", _("Clarke 1866")),
653 ("clrk80", _("Clarke 1880")),
654 ("GRS80" , _("GRS 1980 (IUGG, 1980)")),
655 ("intl" , _("International 1909 (Hayford)")),
656 ("WGS84" , _("WGS 84"))]
657
658 for tag, name in self.ellpsData:
659 self.__ellps.Append(name, tag)
660
661 self.__ellps.SetSelection(0)
662
663 def _DoLayout(self, childPanel = None):
664
665 panelSizer = wxBoxSizer(wxVERTICAL)
666
667 sizer = wxBoxSizer(wxHORIZONTAL)
668 sizer.Add(wxStaticText(self, -1, _("Ellipsoid:")), 0,
669 wxALL|wxALIGN_CENTER_VERTICAL, 4)
670 sizer.Add(self.__ellps, 1, wxALL|wxALIGN_CENTER_VERTICAL, 4)
671 panelSizer.Add(sizer, 0, wxALL|wxEXPAND, 4)
672
673 if childPanel is not None:
674 panelSizer.Add(childPanel, 0, wxEXPAND, 0)
675
676 self.SetAutoLayout(1)
677 self.SetSizer(panelSizer)
678 panelSizer.Fit(self)
679 panelSizer.SetSizeHints(self)
680 self.Layout()
681
682 def SetProjection(self, proj):
683 if proj is not None:
684 param = proj.GetParameter("ellps")
685 i = 0
686 for tag, name in self.ellpsData:
687 if param == tag:
688 self.__ellps.SetSelection(i)
689 return # returning early!
690 i += 1
691
692 #
693 # if proj is none, or the parameter couldn't be found...
694 #
695 self.__ellps.SetSelection(0)
696
697 def GetParameters(self):
698 return ["ellps=" + self.__ellps.GetClientData(
699 self.__ellps.GetSelection())]
700
701
702 ID_TMPANEL_LAT = 4001
703 ID_TMPANEL_LONG = 4002
704 ID_TMPANEL_FASLE_EAST = 4003
705 ID_TMPANEL_FALSE_NORTH = 4004
706 ID_TMPANEL_SCALE = 4005
707
708 class UnknownProjPanel(ProjPanel):
709
710 """Panel for unknown projection types"""
711
712 def __init__(self, parent, receiver):
713 ProjPanel.__init__(self, parent)
714
715 self._DoLayout()
716
717 def _DoLayout(self):
718 sizer = wxBoxSizer(wxVERTICAL)
719
720 sizer.Add(wxStaticText(self, -1,
721 _("Thuban does not know the parameters for the"
722 " current projection\n"
723 "and cannot display a configuration panel.")))
724
725 ProjPanel._DoLayout(self, sizer)
726
727 def GetProjName(self):
728 return "Unknown"
729
730 def SetProjection(self, proj):
731 pass
732
733 def GetParameters(self):
734 return None
735
736 class TMPanel(ProjPanel):
737 """Projection panel for Transverse Mercator."""
738
739 def __init__(self, parent, receiver):
740 ProjPanel.__init__(self, parent)
741
742 self.__latitude = wxTextCtrl(self, ID_TMPANEL_LAT)
743 self.__longitude = wxTextCtrl(self, ID_TMPANEL_LONG)
744 self.__scale = wxTextCtrl(self, ID_TMPANEL_SCALE)
745 self.__falseEast = wxTextCtrl(self, ID_TMPANEL_FASLE_EAST)
746 self.__falseNorth = wxTextCtrl(self, ID_TMPANEL_FALSE_NORTH)
747
748 self._DoLayout()
749
750 def _DoLayout(self):
751
752 sizer = wxFlexGridSizer(4, 4, 0, 0)
753 sizer.Add(wxStaticText(self, -1, _("Latitude:")), 0, wxALL, 4)
754 sizer.Add(self.__latitude, 0, wxALL, 4)
755 sizer.Add(wxStaticText(self, -1, _("False Easting:")), 0, wxALL, 4)
756 sizer.Add(self.__falseEast, 0, wxALL, 4)
757 sizer.Add(wxStaticText(self, -1, _("Longitude:")), 0, wxALL, 4)
758 sizer.Add(self.__longitude, 0, wxALL, 4)
759 sizer.Add(wxStaticText(self, -1, _("False Northing:")), 0, wxALL, 4)
760 sizer.Add(self.__falseNorth, 0, wxALL, 4)
761 sizer.Add(wxStaticText(self, -1, _("Scale Factor:")), 0, wxALL, 4)
762 sizer.Add(self.__scale, 0, wxALL, 4)
763
764 ProjPanel._DoLayout(self, sizer)
765
766 def GetProjName(self):
767 return _("Transverse Mercator")
768
769 def SetProjection(self, proj):
770 ProjPanel.SetProjection(self, proj)
771
772 self.__latitude.SetValue(proj.GetParameter("lat_0"))
773 self.__longitude.SetValue(proj.GetParameter("lon_0"))
774 self.__falseEast.SetValue(proj.GetParameter("x_0"))
775 self.__falseNorth.SetValue(proj.GetParameter("y_0"))
776 self.__scale.SetValue(proj.GetParameter("k"))
777
778 ProjPanel.SetProjection(self, proj)
779
780 def GetParameters(self):
781 params = ["proj=tmerc",
782 "lat_0=" + self.__latitude.GetValue(),
783 "lon_0=" + self.__longitude.GetValue(),
784 "x_0=" + self.__falseEast.GetValue(),
785 "y_0=" + self.__falseNorth.GetValue(),
786 "k=" + self.__scale.GetValue()]
787 params.extend(ProjPanel.GetParameters(self))
788 return params
789
790 def Clear(self):
791 self.__latitude.Clear()
792 self.__longitude.Clear()
793 self.__falseEast.Clear()
794 self.__falseNorth.Clear()
795 self.__scale.Clear()
796
797 ProjPanel.Clear(self)
798
799 ID_UTMPANEL_ZONE = 4001
800 ID_UTMPANEL_SOUTH = 4002
801 ID_UTMPANEL_PROP = 4003
802
803 class UTMPanel(ProjPanel):
804 """Projection Panel for Universal Transverse Mercator."""
805
806 def __init__(self, parent, receiver):
807 ProjPanel.__init__(self, parent)
808
809 self.receiver = receiver
810
811 self.__zone = wxSpinCtrl(self, ID_UTMPANEL_ZONE, "1", min=1, max=60)
812 self.__propButton = wxButton(self, ID_UTMPANEL_PROP, _("Propose"))
813 self.__south = wxCheckBox(self, ID_UTMPANEL_SOUTH,
814 _("Southern Hemisphere"))
815
816 self._DoLayout()
817
818 EVT_BUTTON(self, ID_UTMPANEL_PROP, self._OnPropose)
819
820 def _DoLayout(self):
821
822 sizer = wxBoxSizer(wxVERTICAL)
823 psizer = wxBoxSizer(wxHORIZONTAL)
824 psizer.Add(wxStaticText(self, -1, _("Zone:")), 0, wxALL, 4)
825 psizer.Add(self.__zone, 0, wxALL, 4)
826 psizer.Add(self.__propButton, 0, wxALL, 4)
827 sizer.Add(psizer, 0, wxALL, 4)
828 sizer.Add(self.__south, 0, wxALL, 4)
829
830 ProjPanel._DoLayout(self, sizer)
831
832 def GetProjName(self):
833 return _("Universal Transverse Mercator")
834
835 def SetProjection(self, proj):
836 self.__zone.SetValue(int(proj.GetParameter("zone")))
837 self.__south.SetValue(proj.GetParameter("south") != "")
838 ProjPanel.SetProjection(self, proj)
839
840 def GetParameters(self):
841 params = ["proj=utm", "zone=" + str(self.__zone.GetValue())]
842 if self.__south.IsChecked():
843 params.append("south")
844
845 params.extend(ProjPanel.GetParameters(self))
846 return params
847
848 def Clear(self):
849 self.__zone.SetValue(1)
850 self.__south.SetValue(False)
851 ProjPanel.Clear(self)
852
853 def _OnPropose(self, event):
854 """Call the propose dialog.
855 If the receiver (e.g. the current map) has no bounding box,
856 inform the user accordingly.
857 """
858 bb = self.receiver.BoundingBox()
859 if bb is None:
860 dlg = wxMessageDialog(self,
861 _("Can not propose: No bounding box found."),
862 _("Projection: Propose UTM Zone"),
863 wxOK | wxICON_INFORMATION)
864 dlg.CenterOnParent()
865 result = dlg.ShowModal()
866 dlg.Destroy()
867 return
868
869 dlg = UTMProposeZoneDialog(self, self.receiver.BoundingBox())
870 if dlg.ShowModal() == wxID_OK:
871 self.__zone.SetValue(dlg.GetProposedZone())
872
873 class LCCPanel(ProjPanel):
874 """Projection Panel for Lambert Conic Conformal."""
875
876 def __init__(self, parent, receiver):
877 ProjPanel.__init__(self, parent)
878
879 self.__fspLatitude = wxTextCtrl(self, -1)
880 self.__sspLatitude = wxTextCtrl(self, -1)
881 self.__originLat = wxTextCtrl(self, -1)
882 self.__meridian = wxTextCtrl(self, -1)
883 self.__falseEast = wxTextCtrl(self, -1)
884 self.__falseNorth = wxTextCtrl(self, -1)
885
886 self._DoLayout()
887
888 def _DoLayout(self):
889
890 sizer = wxFlexGridSizer(6, 2, 0, 0)
891 sizer.Add(wxStaticText(self, -1,
892 _("Latitude of first standard parallel:")))
893 sizer.Add(self.__fspLatitude, 0, wxALL, 4)
894 sizer.Add(wxStaticText(self, -1,
895 _("Latitude of second standard parallel:")))
896 sizer.Add(self.__sspLatitude, 0, wxALL, 4)
897 sizer.Add(wxStaticText(self, -1, _("Central Meridian:")))
898 sizer.Add(self.__meridian, 0, wxALL, 4)
899 sizer.Add(wxStaticText(self, -1, _("Latitude of origin:")))
900 sizer.Add(self.__originLat, 0, wxALL, 4)
901 sizer.Add(wxStaticText(self, -1, _("False Easting:")))
902 sizer.Add(self.__falseEast, 0, wxALL, 4)
903 sizer.Add(wxStaticText(self, -1, _("False Northing:")))
904 sizer.Add(self.__falseNorth, 0, wxALL, 4)
905
906 ProjPanel._DoLayout(self, sizer)
907
908 def GetProjName(self):
909 return _("Lambert Conic Conformal")
910
911 def SetProjection(self, proj):
912 self.__fspLatitude.SetValue(proj.GetParameter("lat_1"))
913 self.__sspLatitude.SetValue(proj.GetParameter("lat_2"))
914 self.__originLat.SetValue(proj.GetParameter("lat_0"))
915 self.__meridian.SetValue(proj.GetParameter("lon_0"))
916 self.__falseEast.SetValue(proj.GetParameter("x_0"))
917 self.__falseNorth.SetValue(proj.GetParameter("y_0"))
918
919 ProjPanel.SetProjection(self, proj)
920
921 def GetParameters(self):
922 params = ["proj=lcc",
923 "lat_1=" + self.__fspLatitude.GetValue(),
924 "lat_2=" + self.__sspLatitude.GetValue(),
925 "lat_0=" + self.__originLat.GetValue(),
926 "lon_0=" + self.__meridian.GetValue(),
927 "x_0=" + self.__falseEast.GetValue(),
928 "y_0=" + self.__falseNorth.GetValue()]
929
930 params.extend(ProjPanel.GetParameters(self))
931 return params
932
933 def Clear(self):
934 self.__fspLatitude.Clear()
935 self.__sspLatitude.Clear()
936 self.__originLat.Clear()
937 self.__meridian.Clear()
938 self.__falseEast.Clear()
939 self.__falseNorth.Clear()
940
941 ProjPanel.Clear(self)
942
943 class GeoPanel(ProjPanel):
944 """Projection Panel for a Geographic Projection."""
945
946 def __init__(self, parent, receiver):
947 ProjPanel.__init__(self, parent)
948
949 self.__choices = [(_("Degrees"), "0.017453"),
950 (_("Radians"), "1")]
951
952 self.__scale = wxChoice(self, -1)
953 for choice, value in self.__choices:
954 self.__scale.Append(choice, value)
955
956 self._DoLayout()
957
958 def GetProjName(self):
959 return _("Geographic")
960
961 def SetProjection(self, proj):
962 value = proj.GetParameter("to_meter")
963 for i in range(len(self.__choices)):
964 choice, data = self.__choices[i]
965 if value == data:
966 self.__scale.SetSelection(i)
967 ProjPanel.SetProjection(self, proj)
968
969 def GetParameters(self):
970 params = ["proj=latlong",
971 "to_meter=%s" % self.__scale.GetClientData(
972 self.__scale.GetSelection())]
973
974 params.extend(ProjPanel.GetParameters(self))
975 return params
976
977 def Clear(self):
978 ProjPanel.Clear(self)
979
980 def _DoLayout(self):
981 sizer = wxBoxSizer(wxHORIZONTAL)
982
983 sizer.Add(wxStaticText(self, -1, _("Source Data is in: ")),
984 0, wxALL|wxALIGN_CENTER_VERTICAL, 4)
985 sizer.Add(self.__scale, 1, wxEXPAND|wxALL, 4)
986
987 self.__scale.SetSelection(0)
988
989 ProjPanel._DoLayout(self, sizer)
990
991
992 ID_UTM_PROPOSE_ZONE_DIALOG_TAKE = 4001
993 ID_UTM_PROPOSE_ZONE_DIALOG_CANCEL = 4002
994 class UTMProposeZoneDialog(wxDialog):
995
996 """Propose a sensible Zone considering the current map extent."""
997
998 def __init__(self, parent, (x, y, x2, y2)):
999 wxDialog.__init__(self, parent, -1, _("Projection: Propose UTM Zone"),
1000 wxDefaultPosition, wxSize(200, 100))
1001 self.parent = parent
1002 x = x + 180
1003 x2 = x2 + 180
1004 center = (x2 - x) / 2 + x
1005 self.proposedZone = int(center / 6 + 1)
1006 self.dialogLayout()
1007
1008 def dialogLayout(self):
1009 topBox = wxBoxSizer(wxVERTICAL)
1010
1011 textBox = wxBoxSizer(wxVERTICAL)
1012 textBox.Add(wxStaticText(self, -1, _("The current map extent center "
1013 "lies in UTM Zone")),
1014 0, wxALIGN_CENTER|wxALL, 4)
1015 textBox.Add(wxStaticText(self, -1, str(self.proposedZone)),
1016 0, wxALIGN_CENTER|wxALL, 4)
1017
1018 topBox.Add(textBox, 1, wxEXPAND|wxALL, 4)
1019
1020 buttonBox = wxBoxSizer(wxHORIZONTAL)
1021 buttonBox.Add(wxButton(self, ID_UTM_PROPOSE_ZONE_DIALOG_TAKE,
1022 _("Take")), 0, wxALL, 4)
1023 buttonBox.Add(wxButton(self, ID_UTM_PROPOSE_ZONE_DIALOG_CANCEL,
1024 _("Cancel")), 0, wxALL, 4)
1025 topBox.Add(buttonBox, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 10)
1026 EVT_BUTTON(self, ID_UTM_PROPOSE_ZONE_DIALOG_TAKE, self.OnTake)
1027 EVT_BUTTON(self, ID_UTM_PROPOSE_ZONE_DIALOG_CANCEL, self.OnCancel)
1028
1029 self.SetAutoLayout(True)
1030 self.SetSizer(topBox)
1031 topBox.Fit(self)
1032 topBox.SetSizeHints(self)
1033
1034 def OnTake(self, event):
1035 self.EndModal(wxID_OK)
1036
1037 def OnCancel(self, event):
1038 self.EndModal(wxID_CANCEL)
1039
1040 def GetProposedZone(self):
1041 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