/[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 1034 - (show annotations)
Mon May 26 16:28:33 2003 UTC (21 years, 9 months ago) by frank
Original Path: trunk/thuban/Thuban/UI/projdialog.py
File MIME type: text/x-python
File size: 34310 byte(s)
(ProjFrame.__do_layout, ProjPanel._DoLayout): Center Choices.

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