/[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 816 - (show annotations)
Mon May 5 15:05:16 2003 UTC (21 years, 10 months ago) by jonathan
Original Path: trunk/thuban/Thuban/UI/projdialog.py
File MIME type: text/x-python
File size: 34180 byte(s)
(ProjFrame.__init__): Rearrange the
        order that the controls are created so that tabbing works correctly.
(ProjFrame.OnApply): Renamed from _OnTry() to use wxDialog behaviour.
(ProjFrame.OnOK): Renamed from _OnOK() to use wxDialog behaviour.
(ProjFrame.OnCancel): Renamed from _OnClose() to use wxDialog behaviour.        (ProjPanel.__init__): Add "Airy" to the list of ellipsoids so we
        can provide the "UK National Grid" as a default projection.
(UTMPanel.__init__): Rearrange the order that the controls are
        created so that tabbing works correctly.

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