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

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

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26