/[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 903 - (show annotations)
Wed May 14 11:16:28 2003 UTC (21 years, 9 months ago) by jonathan
Original Path: trunk/thuban/Thuban/UI/projdialog.py
File MIME type: text/x-python
File size: 34199 byte(s)
(ProjFrame.__do_layout): Fix Windows layout bug with the 'Projection' label.

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