/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/UI/projdialog.py
ViewVC logotype

Diff of /branches/WIP-pyshapelib-bramz/Thuban/UI/projdialog.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 730 by jonathan, Thu Apr 24 16:07:41 2003 UTC revision 2470 by bh, Thu Dec 16 11:00:10 2004 UTC
# Line 1  Line 1 
1  #!/usr/bin/env python  # Copyright (c) 2003, 2004 by Intevation GmbH
2  # generated by wxGlade 0.2.1 on Thu Apr 17 11:51:39 2003  # 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  import os
17  from wxPython.wx import *  from wxPython.wx import *
18    
19  from Thuban import _  from Thuban import _
20    
21  from Thuban.Model.proj import Projection, ProjFile  from Thuban.Model.proj import Projection, ProjFile
22    
23  from Thuban.Model.resource import GetUserProjFiles, GetSystemProjFiles, \  from Thuban.Model.resource import get_user_proj_file, get_system_proj_file, \
24                                    ReadProjFile, WriteProjFile                                    read_proj_file, write_proj_file, \
25  from Thuban.UI.dialogs import NonModalDialog                                    DEFAULT_PROJ_FILE, EPSG_PROJ_FILE, \
26                                      EPSG_DEPRECATED_PROJ_FILE
27    from Thuban.UI.dialogs import NonModalNonParentDialog
28    
29    from common import ThubanBeginBusyCursor, ThubanEndBusyCursor
30    from sizers import NotebookLikeSizer
31    from projlist import PROJ_SELECTION_CHANGED, ProjectionList
32    from common import ThubanBeginBusyCursor, ThubanEndBusyCursor
33    
34    
35    
 ID_PROJ_ADVANCED  = 4001  
36  ID_PROJ_PROJCHOICE = 4002  ID_PROJ_PROJCHOICE = 4002
37  ID_PROJ_SAVEAS    = 4003  ID_PROJ_ADDTOLIST    = 4003
38  ID_PROJ_NEW       = 4004  ID_PROJ_NEW       = 4004
 ID_PROJ_TRY       = 4005  
39  ID_PROJ_REVERT    = 4006  ID_PROJ_REVERT    = 4006
 ID_PROJ_OK        = 4007  
 ID_PROJ_CLOSE     = 4008  
40  ID_PROJ_AVAIL     = 4009  ID_PROJ_AVAIL     = 4009
41  ID_PROJ_SAVE      = 4010  ID_PROJ_SAVE      = 4010
42  ID_PROJ_IMPORT    = 4011  ID_PROJ_IMPORT    = 4011
# Line 31  ID_PROJ_PROJNAME  = 4014 Line 47  ID_PROJ_PROJNAME  = 4014
47  CLIENT_PROJ = 0  CLIENT_PROJ = 0
48  CLIENT_PROJFILE = 1  CLIENT_PROJFILE = 1
49    
50  class ProjFrame(NonModalDialog):  class ProjFrame(NonModalNonParentDialog):
51    
52      def __init__(self, parent, name, receiver, *args, **kwds):      def __init__(self, parent, name, title, receiver):
53          """Initialize the projection dialog.          """Initialize the projection dialog.
54    
55          receiver -- An object that implements the following methods:          receiver -- An object that implements the following methods:
56                          SetProjection(projection)                          SetProjection(projection)
57                          GetProjection()                          GetProjection()
58          """          """
59                    NonModalNonParentDialog.__init__(self, parent, name, title)
60    
61            self.projection_panel_defs = [
62                ("tmerc", _("Transverse Mercator"), TMPanel),
63                ("utm", _("Universal Transverse Mercator"), UTMPanel),
64                ("lcc", _("Lambert Conic Conformal"), LCCPanel),
65                ("latlong", _("Geographic"), GeoPanel),
66                ("longlat", _("Geographic"), GeoPanel)]#longlat is an alias of proj
67          self.receiver = receiver          self.receiver = receiver
68          self.originalProjection = -1          self.haveTried = False
69          self.curProjPanel = None          self.curProjPanel = None
70            self.__usrProjFile = None
71            self._sys_proj_files = {}
72    
73          self.projPanels = []          self.build_dialog()
74          self.projPanels.append(          self.Layout()
             ("tmerc", _("Transverse Mercator"), TMPanel))  
         self.projPanels.append(  
             ("utm", _("Universal Transverse Mercator"), UTMPanel))  
         self.projPanels.append(  
             ("lcc", _("Lambert Conic Conformal"), LCCPanel))  
         self.projPanels.append(  
             ("latlong", _("Geographic"), GeoPanel))  
   
         NonModalDialog.__init__(self, parent, name, "")  
         # originally generate by wxGlade  
         self.panel_1 = wxPanel(self, -1)  
         self.panel_edit = wxPanel(self, -1)  
         self.panel_buttons = wxPanel(self, -1)  
         self.label_5 = wxStaticText(self.panel_1, -1, _("Available Projections:"))  
         self.availprojs = wxListBox(self.panel_1, ID_PROJ_AVAIL, style=wxLB_EXTENDED |wxLB_SORT)  
         self.projfilepath = wxStaticText(self.panel_1, -1, "")  
         self.label_2 = wxStaticText(self.panel_edit, -1, _("Name:"))  
         self.projname = wxTextCtrl(self.panel_edit, ID_PROJ_PROJNAME, "")  
         self.label_3 = wxStaticText(self.panel_edit, -1, _("Projection:"))  
         self.projchoice = wxChoice(self.panel_edit, ID_PROJ_PROJCHOICE)  
         self.button_import = wxButton(self.panel_1, ID_PROJ_IMPORT, _("Import..."))  
         self.button_export = wxButton(self.panel_1, ID_PROJ_EXPORT, _("Export..."))  
         self.button_remove = wxButton(self.panel_1, ID_PROJ_REMOVE, _("Remove"))  
         self.button_new = wxButton(self.panel_edit, ID_PROJ_NEW, _("New"))  
         self.button_save = wxButton(self.panel_edit, ID_PROJ_SAVE,_("Save"))  
         self.button_add = wxButton(self.panel_edit, ID_PROJ_SAVEAS,  
                                       _("Add to List"))  
         self.button_try = wxButton(self.panel_buttons, ID_PROJ_TRY, _("Try"))  
         self.button_revert = wxButton(self.panel_buttons, ID_PROJ_REVERT, _("Revert"))  
         self.button_ok = wxButton(self.panel_buttons, ID_PROJ_OK, _("OK"))  
         self.button_close = wxButton(self.panel_buttons, ID_PROJ_CLOSE, _("Close"))  
   
         self.__set_properties()  
         self.__do_layout()  
         # wxGlade  
75    
76          self.__DoOnProjAvail()          self.originalProjection = self.receiver.GetProjection()
77            
78          EVT_BUTTON(self, ID_PROJ_TRY, self._OnTry)          self.projection_list.SelectProjection(self.originalProjection)
79          EVT_BUTTON(self, ID_PROJ_REVERT, self._OnRevert)          self.projection_list.SetFocus()
80          EVT_BUTTON(self, ID_PROJ_OK, self._OnOK)  
81          EVT_BUTTON(self, ID_PROJ_CLOSE, self._OnClose)      def build_dialog(self):
82          EVT_CHOICE(self, ID_PROJ_PROJCHOICE, self._OnProjChoice)          """Build the dialog's widgets and set the event handlers"""
83          EVT_LISTBOX(self, ID_PROJ_AVAIL, self._OnProjAvail)          self.topBox = top_box = wxBoxSizer(wxVERTICAL)
84    
85            main_box = wxBoxSizer(wxHORIZONTAL)
86            top_box.Add(main_box, 1, wxALL|wxEXPAND)
87    
88            #
89            #    The projection list and associated controls
90            #
91            vbox = wxBoxSizer(wxVERTICAL)
92            main_box.Add(vbox, 4, wxALL|wxEXPAND)
93    
94            #label = wxStaticText(self, -1, _("Available Projections:"))
95            #vbox.Add(label, 0, wxLEFT|wxRIGHT|wxTOP, 4)
96    
97            hbox = wxBoxSizer(wxHORIZONTAL)
98            vbox.Add(hbox, 1, wxALL|wxEXPAND)
99            proj_files = [self.load_user_proj(),
100                          self.load_system_proj(DEFAULT_PROJ_FILE)]
101            self.projection_list = ProjectionList(self, proj_files,
102                                                  self.receiver.GetProjection())
103            hbox.Add(self.projection_list, 1, wxALL|wxEXPAND|wxADJUST_MINSIZE, 4)
104            self.projection_list.Subscribe(PROJ_SELECTION_CHANGED,
105                                           self.proj_selection_changed)
106    
107            # Projection List specific actions (Import/Export/Remove)
108            buttons = wxBoxSizer(wxVERTICAL)
109            hbox.Add(buttons, 0, wxALL)
110            self.button_import = wxButton(self, ID_PROJ_IMPORT, _("Import..."))
111          EVT_BUTTON(self, ID_PROJ_IMPORT, self._OnImport)          EVT_BUTTON(self, ID_PROJ_IMPORT, self._OnImport)
112            buttons.Add(self.button_import, 1, wxALL|wxEXPAND, 4)
113            self.button_export = wxButton(self, ID_PROJ_EXPORT, _("Export..."))
114          EVT_BUTTON(self, ID_PROJ_EXPORT, self._OnExport)          EVT_BUTTON(self, ID_PROJ_EXPORT, self._OnExport)
115            buttons.Add(self.button_export, 1, wxALL|wxEXPAND, 4)
116            buttons.Add(20, 20, 0, wxEXPAND, 0)
117            self.button_remove = wxButton(self, ID_PROJ_REMOVE, _("Remove"))
118          EVT_BUTTON(self, ID_PROJ_REMOVE, self._OnRemove)          EVT_BUTTON(self, ID_PROJ_REMOVE, self._OnRemove)
119            buttons.Add(self.button_remove, 1, wxALL|wxEXPAND, 4)
120    
121            buttons.Add(20, 20, 0, wxEXPAND, 0)
122            label = wxStaticText(self, -1, _("Show EPSG:"))
123            buttons.Add(label, 0, wxLEFT|wxRIGHT|wxTOP, 4)
124            self.check_epsg = wxCheckBox(self, -1, _("Normal"))
125            EVT_CHECKBOX(self, self.check_epsg.GetId(), self._OnShowEPSG)
126            buttons.Add(self.check_epsg, 1, wxALL|wxEXPAND, 4)
127            self.check_epsg_depr = wxCheckBox(self, -1, _("Deprecated"))
128            EVT_CHECKBOX(self, self.check_epsg_depr.GetId(), self._OnShowEPSG)
129            buttons.Add(self.check_epsg_depr, 1, wxALL|wxEXPAND, 4)
130    
131            # The file path
132            self.projfilepath = wxStaticText(self, -1, "")
133            vbox.Add(self.projfilepath, 0, wxALL|wxEXPAND)
134    
135            #
136            #   The projection editor part
137            #
138            self.edit_box = wxStaticBox(self, -1, _("Edit"))
139            sizer_edit = wxStaticBoxSizer(self.edit_box, wxHORIZONTAL)
140            main_box.Add(sizer_edit, 5, wxALL|wxEXPAND)
141    
142            # Projection Specific Entries (Name/Projection)
143            self.sizer_projctrls = wxBoxSizer(wxVERTICAL)
144            sizer_edit.Add(self.sizer_projctrls, 1, wxALL|wxEXPAND)
145    
146            hbox = wxBoxSizer(wxHORIZONTAL)
147            self.sizer_projctrls.Add(hbox, 0, wxALL|wxEXPAND)
148            label = wxStaticText(self, -1, _("Name:"))
149            hbox.Add(label, 0, wxALL|wxALIGN_CENTER_VERTICAL, 4)
150            self.projname = wxTextCtrl(self, ID_PROJ_PROJNAME, "")
151            EVT_TEXT(self, ID_PROJ_PROJNAME, self._OnProjName)
152            hbox.Add(self.projname, 1, wxALL|wxEXPAND, 4)
153    
154            hbox = wxBoxSizer(wxHORIZONTAL)
155            self.sizer_projctrls.Add(hbox, 0, wxALL|wxEXPAND)
156            label = wxStaticText(self, -1, _("Projection:"))
157            hbox.Add(label, 0, wxALL|wxALIGN_CENTER_VERTICAL, 4)
158            self.projchoice = wxChoice(self, ID_PROJ_PROJCHOICE)
159            self.projchoice.SetSelection(0)
160            EVT_CHOICE(self, ID_PROJ_PROJCHOICE, self._OnProjChoice)
161            hbox.Add(self.projchoice, 1, wxALL|wxEXPAND, 4)
162            # Fill the projection choice list.
163            self.nbsizer = NotebookLikeSizer()
164            self.sizer_projctrls.Add(self.nbsizer, 1,
165                                     wxALL|wxEXPAND|wxADJUST_MINSIZE, 3)
166            self.projection_panels = []
167            self.projchoice.Append(_("<Unknown>"), "")
168            for proj_type, name, cls in self.projection_panel_defs:
169                self.projchoice.Append(name, proj_type)
170                panel = cls(self, self.receiver)
171                panel.Hide()
172                panel.projection_index = len(self.projection_panels)
173                panel.projection_type = proj_type
174                self.projection_panels.append(panel)
175                self.nbsizer.Add(panel)
176            self.unknown_projection_panel = UnknownProjPanel(self, self.receiver)
177            self.unknown_projection_panel.Hide()
178            self.nbsizer.Add(self.unknown_projection_panel)
179    
180            # Projection Specific actions (New/Save/Add)
181            buttons = wxBoxSizer(wxVERTICAL)
182            sizer_edit.Add(buttons, 0, wxALL)
183            self.button_new = wxButton(self, ID_PROJ_NEW, _("New"))
184          EVT_BUTTON(self, ID_PROJ_NEW, self._OnNew)          EVT_BUTTON(self, ID_PROJ_NEW, self._OnNew)
185            buttons.Add(self.button_new, 0, wxEXPAND|wxALL, 4)
186            self.button_add = wxButton(self, ID_PROJ_ADDTOLIST, _("Add to List"))
187            EVT_BUTTON(self, ID_PROJ_ADDTOLIST, self._OnAddToList)
188            buttons.Add(self.button_add, 0, wxEXPAND|wxALL, 4)
189            buttons.Add(20, 20, 0, wxEXPAND, 0)
190            self.button_save = wxButton(self, ID_PROJ_SAVE,_("Update"))
191          EVT_BUTTON(self, ID_PROJ_SAVE, self._OnSave)          EVT_BUTTON(self, ID_PROJ_SAVE, self._OnSave)
192          EVT_BUTTON(self, ID_PROJ_SAVEAS, self._OnSaveAs)          buttons.Add(self.button_save, 0, wxEXPAND|wxALL|wxALIGN_BOTTOM, 4)
193    
194          EVT_TEXT(self, ID_PROJ_PROJNAME, self._OnProjName)          #
195            # Main Action buttons (Try/Revert/OK/Close)
196            #
197            buttons = wxBoxSizer(wxHORIZONTAL)
198            top_box.Add(buttons, 0, wxALL|wxALIGN_RIGHT, 10)
199            self.button_try = wxButton(self, wxID_APPLY, _("Try"))
200            EVT_BUTTON(self, wxID_APPLY, self.OnApply)
201            buttons.Add(self.button_try, 0, wxRIGHT, 10)
202            self.button_revert = wxButton(self, ID_PROJ_REVERT, _("Revert"))
203            EVT_BUTTON(self, ID_PROJ_REVERT, self._OnRevert)
204            buttons.Add(self.button_revert, 0, wxRIGHT, 10)
205            self.button_ok = wxButton(self, wxID_OK, _("OK"))
206            EVT_BUTTON(self, wxID_OK, self.OnOK)
207            self.button_ok.SetDefault()
208            buttons.Add(self.button_ok, 0, wxRIGHT, 10)
209            self.button_close = wxButton(self, wxID_CANCEL, _("Close"))
210            EVT_BUTTON(self, wxID_CANCEL, self.OnCancel)
211            buttons.Add(self.button_close, 0, wxRIGHT, 10)
212    
     def GetReceiver(self):  
         return self.receiver  
213    
214      def _OnTry(self, event):          #
215          self.__SetProjection()          # Automatic Layout
216            #
217            self.SetAutoLayout(1)
218            self.SetSizer(top_box)
219            top_box.Fit(self)
220            top_box.SetSizeHints(self)
221    
222        def OnClose(self, event):
223            self.projection_list.Unsubscribe(PROJ_SELECTION_CHANGED,
224                                             self.proj_selection_changed)
225            # Destroy the projection list explicitly so that it properly
226            # unsubscribes everything. It would be cleaner if the projection
227            # could do this by itself but wx doesn't always send destroy
228            # events for non-top-level widgets
229            self.projection_list.Destroy()
230            NonModalNonParentDialog.OnClose(self, event)
231    
232      def _OnRevert(self, event):      def OnApply(self, event):
233          if self.originalProjection != -1:          self.__SetProjection()
234              self.receiver.SetProjection(self.originalProjection)          self.haveTried = True
235    
236      def _OnOK(self, event):      def OnOK(self, event):
237          self.__SetProjection()          self.__SetProjection()
238          self.Close()          self.Close()
239    
240      def _OnClose(self, event):      def OnCancel(self, event):
241            """Cancel just closes the dialog, but we call it cancel so we
242            can overload the functionality of wxDialog.
243            """
244          self.Close()          self.Close()
245    
246        def _OnRevert(self, event):
247            if self.haveTried:
248                self.receiver.SetProjection(self.originalProjection)
249                self.haveTried = False
250    
251      def _OnNew(self, event):      def _OnNew(self, event):
252          self.__DoOnNew()  
253            self.projection_list.ClearSelection()
254            self.projname.Clear()
255    
256            # supply a projection panel if there wasn't one
257            if self.curProjPanel is None:
258                self.projchoice.SetSelection(0)
259                self.__DoOnProjChoice()
260    
261            if self.curProjPanel is not None:
262                self.curProjPanel.Clear()
263    
264      def _OnSave(self, event):      def _OnSave(self, event):
265    
266          sel = self.availprojs.GetSelections()          sel = self.projection_list.selected_projections()
267          assert len(sel) == 1,  "button shouldn't be enabled"          assert len(sel) == 1,  "button shouldn't be enabled"
268    
269          proj, projfile = self.availprojs.GetClientData(sel[0])          proj, projfile = sel[0]
270    
271          assert proj is not None and projfile is not None          assert proj is not None and projfile is not None
272    
273          newproj = self.__GetProjection()          newproj = self.__GetProjection()
274    
275          if newproj is not None:          if newproj is not None:
276              projfile.Remove(proj)              # FIXME: we should only allow this for the user proj file.
277              projfile.Add(newproj)              projfile.Replace(proj, newproj)
278              try:              self.write_proj_file(projfile)
279                  WriteProjFile(projfile)              self.projection_list.SelectProjection(newproj)
             except IOError, (errno, errstr):  
                 wxMessageDialog(self,  
                     _("The following error occured:\n") +  
                     projfile.GetFileName() + "\n" + errstr,  
                     _("Error"), wxOK | wxICON_ERROR).ShowModal()  
             self.__FillAvailList()  
280    
281      def _OnSaveAs(self, event):      def _OnAddToList(self, event):
282    
283          proj = self.__GetProjection()          proj = self.__GetProjection()
284          if proj is not None:          if proj is not None:
285              self.__usrProjFile.Add(proj)              self.__usrProjFile.Add(proj)
286              try:              self.write_proj_file(self.__usrProjFile)
287                  WriteProjFile(self.__usrProjFile)              self.projection_list.SelectProjection(proj)
             except IOError, (errno, errstr):  
                 wxMessageDialog(self,  
                     _("The following error occured:\n") +  
                     self.__usrProjFile.GetFileName() + "\n" + errstr,  
                     _("Error"), wxOK | wxICON_ERROR).ShowModal()  
             self.__FillAvailList()  
   
         return  
288    
289          """Save the projection somewhere.      def show_warnings(self, title, filename, warnings):
290            """Show the warnings (a list of strings) in a dialog
291    
292          There are three important cases to consider.          If the list is empty no dialog will be shown.
             1. the file already exists and the user wants to overwrite it.  
             2. the file already exists and the user wants to append the  
                current projection to the end of the file  
             3. the file doesn't exist and the user wants to create it  
   
         The list of available projections is then updated.  
293          """          """
294            if warnings:
295          proj = Projection(self.curProjPanel.GetParameters())              text = (_('Warnings when reading "%s":\n\n%s')
296          if self.projname.GetValue() != "":                      % (filename, "\n\n".join(warnings)))
297              proj.SetName(self.projname.GetValue())              self.parent.RunMessageBox(title, text)
   
         dlg = wxFileDialog(self, _("Save As"), style = wxSAVE)  
         if dlg.ShowModal() == wxID_OK:  
             path = dlg.GetPath()  
   
             if os.access(path, os.F_OK):  
                 # file already exists.  
                 if os.access(path, os.W_OK | os.R_OK):  
                   
                     # is it a .proj file?  
                     try:  
                         projFile = ReadProjFile(path)  
                     except:  
                         # obviously not.  
                         dlg = wxMessageDialog(self,  
                             path + _(" already exists. Overwrite?"),  
                             _(""),  
                             wxYES | wxNO)  
   
                         if dlg.ShowModal() == wxID_YES:  
                             projFile = ProjFile(path)  
                         else:  
                             return # returning early  
                     else:  
                         # ask the user to overwrite or append  
                         dlg = wxMessageDialog(self,  
                             _("The selected projection file already exists.\n"+  
                               "The current projection can be added to the " +  
                               "file, or it can completely replace the " +  
                               "selected file.\n\nShould the current " +  
                               "projection be added to the file?"),  
                             _("Question"),  
                             wxYES | wxNO | wxICON_QUESTION)  
   
                         if dlg.ShowModal() == wxID_NO:  
                             projFile = ProjFile(path)  
                 else:  
                     # can't access the file  
                     dlg = wxMessageDialog(self,  
                         _("Couldn't access ") + path,  
                         _(""),  
                         wxOK | wxICON | wxICON_EXCLAMATION)  
                     return  
   
             else:  
                 # file doesn't exist. make a new one.  
                 projFile = ProjFile(path)  
                   
             #  
             # if we get this far we have a valid projFile and  
             # can just write the file  
             #  
             projFile.Add(proj)  
             try:  
                 WriteProjFile(projFile)  
                 self.__FillAvailList()  
             except IOError, (errno, errstr):  
                 wxMessageDialog(self,  
                     _("The following error occured:\n") +  
                     dlg.GetPath() + "\n" + errstr,  
                     _("Error"), wxOK | wxICON_ERROR).ShowModal()  
         dlg.Destroy()  
   
     def _OnProjAvail(self, event):  
         self.__DoOnProjAvail()  
298    
299      def _OnImport(self, event):      def _OnImport(self, event):
300            """Handler for the 'Import' button
301    
302          dlg = wxFileDialog(self, _("Import"), style = wxOPEN)          Ask the user for a filename, read the projections from that file
303            add them to the user ProjFile object and write the user file
304            back to disk.
305            """
306            dlg = wxFileDialog(self, _("Import"),
307                    self.parent.application.Path("projection"), style = wxOPEN)
308    
309          if dlg.ShowModal() == wxID_OK:          if dlg.ShowModal() == wxID_OK:
310              path = dlg.GetPath()              path = dlg.GetPath()
311    
312                ThubanBeginBusyCursor()
313              try:              try:
314                  projFile = ReadProjFile(path)                  try:
315                  for proj in projFile.GetProjections():                      projFile, warnings = read_proj_file(path)
316                      self.__usrProjFile.Add(proj)                  except IOError, (errno, errstr):
317                  WriteProjFile(self.__usrProjFile)                      self.__ShowError(dlg.GetPath(), errstr)
318              except IOError, (errno, errstr):                  else:
319                  wxMessageDialog(self,                      self.show_warnings(_("Warnings"), path, warnings)
320                      _("The following error occured:\n") +                      for proj in projFile.GetProjections():
321                      dlg.GetPath() + "\n" + errstr,                          self.__usrProjFile.Add(proj)
322                      _("Error"), wxOK | wxICON_ERROR).ShowModal()                      self.write_proj_file(self.__usrProjFile)
323                        self.parent.application.SetPath("projection", path)
324              self.__FillAvailList()              finally:
325                    ThubanEndBusyCursor()
326          dlg.Destroy()          dlg.Destroy()
327    
328      def _OnExport(self, event):      def _OnExport(self, event):
329          proj = self.__GetProjection()          """Handler for the 'Export' button.
330    
331          if proj is None: return          Ask the user for a filename and write the selected projections
332            to that file.
333            """
334            sel = self.projection_list.selected_projections()
335            assert len(sel) != 0, "button should be disabled"
336    
337          dlg = wxFileDialog(self, _("Export"),          dlg = wxFileDialog(self, _("Export"),
338                             style = wxSAVE|wxOVERWRITE_PROMPT)                  self.parent.application.Path("projection"),
339                    style=wxSAVE|wxOVERWRITE_PROMPT)
340    
341          if dlg.ShowModal() == wxID_OK:          if dlg.ShowModal() == wxID_OK:
342              path = dlg.GetPath()              proj_file = ProjFile(dlg.GetPath())
343                for proj, pf in sel:
344              projFile = ProjFile(path)                  if proj is not None:
345              projFile.Add(proj)                      proj_file.Add(proj)
346              try:              self.write_proj_file(proj_file)
347                  WriteProjFile(projFile)              self.parent.application.SetPath("projection", dlg.GetPath())
             except IOError, (errno, errstr):  
                 wxMessageDialog(self,  
                     _("The following error occured:\n") +  
                     dlg.GetPath() + "\n" + errstr,  
                     _("Error"), wxOK | wxICON_ERROR).ShowModal()  
348    
349          dlg.Destroy()          dlg.Destroy()
350    
351      def _OnRemove(self, event):      def _OnRemove(self, event):
352            """Handler for the 'Remove' button
353    
354          sel = self.availprojs.GetSelections()          Remove any selected projection that came from the user's
355            ProjFile. If the user ProjFile was modified write it back to
356            disk.
357            """
358            sel = self.projection_list.selected_projections()
359          assert len(sel) != 0, "button should be disabled!"          assert len(sel) != 0, "button should be disabled!"
360    
361          #          modified = False
362          # remove the items backwards so the indices don't change          for proj, pf in sel:
363          #              if proj is not None and pf is self.__usrProjFile:
364          sel = list(sel)                  pf.Remove(proj)
365          sel.sort()                  modified = True
         sel.reverse()  
   
         newselection = -1  
         if len(sel) == 1:  
             newselection = sel[0] - 1  
             if newselection < 0:  
                 newselection = 0  
   
         for i in sel:  
             proj, projfile = self.availprojs.GetClientData(i)  
   
             #  
             # this could be the case if they selected <None> or  
             # the currently used projection  
             #  
             if proj is not None and projfile is not None:  
                 projfile.Remove(proj)  
   
         try:  
             WriteProjFile(projfile)  
         except IOError, (errno, errstr):  
             wxMessageDialog(self,  
                 _("The following error occured:\n") +  
                 projfile.GetFileName() + "\n" + errstr,  
                 _("Error"), wxOK | wxICON_ERROR).ShowModal()  
366    
367            if modified:
368                self.write_proj_file(self.__usrProjFile)
369    
370          self.__FillAvailList()      def _OnShowEPSG(self, event):
371            """Handler for the EVT_CHECKBOX events from the EPSG check button
372    
373          #          If the button is checked add the EPSG_PROJ_FILE to the list of
374          # this *could* produce incorrect results if the .proj files          projfiles shown by the projection list. Otherwise remove it
375          # change between the last list update and this selection          """
376          # because the list has been repopulated.          proj_files = [self.load_user_proj(),
377          #                        self.load_system_proj(DEFAULT_PROJ_FILE)]
378          if newselection != -1 and self.availprojs.GetCount() > 0:          if self.check_epsg.IsChecked():
379              self.availprojs.SetSelection(newselection)              proj_files.append(self.load_system_proj(EPSG_PROJ_FILE))
380            if self.check_epsg_depr.IsChecked():
381                proj_files.append(self.load_system_proj(EPSG_DEPRECATED_PROJ_FILE))
382            self.projection_list.SetProjFiles(proj_files)
383    
384      def _OnProjName(self, event):      def _OnProjName(self, event):
385          self.__VerifyButtons()          self.__VerifyButtons()
386    
387        def __ShowError(self, filename, errstr):
388            wxMessageDialog(self,
389                _("The following error occured:\n") +
390                filename + "\n" + errstr,
391                _("Error"), wxOK | wxICON_ERROR).ShowModal()
392    
393      def __VerifyButtons(self):      def __VerifyButtons(self):
394          sel = self.availprojs.GetSelections()          """Update button sensitivity"""
395    
396            num_sel = self.projection_list.GetSelectedItemCount()
397    
398          self.button_import.Enable(True)          self.button_import.Enable(True)
399          self.button_export.Enable(True)          self.button_export.Enable(True)
400          self.button_save.Enable(True)          self.button_save.Enable(True)
401          self.button_remove.Enable(True)          self.button_remove.Enable(True)
402    
403          self.panel_edit.Enable(True)          self.edit_box.Enable(True)
404    
405            for ctrl in [self.button_import,
406                         self.button_export,
407                         self.button_remove,
408                         self.button_save,
409                         self.button_add,
410                         self.projchoice,
411                         self.projname,
412                         self.edit_box]:
413                ctrl.Enable(True)
414    
415            if self.curProjPanel is not None:
416                self.curProjPanel.Enable(True)
417    
418          if len(sel) == 0:          if num_sel == 0:
419              self.button_import.Enable(True)              self.button_import.Enable(True)
420              self.button_export.Enable(False)              self.button_export.Enable(False)
421              self.button_remove.Enable(False)              self.button_remove.Enable(False)
422                self.button_save.Enable(False)
423    
424          elif len(sel) == 1:          elif num_sel == 1:
425    
426              proj, projFile = self.availprojs.GetClientData(sel[0])              selection = self.projection_list.selected_projections()
427                proj, projFile = selection[0]
428    
429              self.button_save.Enable(len(self.projname.GetValue()) > 0)              self.button_save.Enable(len(self.projname.GetValue()) > 0)
430              self.button_add.Enable(len(self.projname.GetValue()) > 0)              self.button_add.Enable(len(self.projname.GetValue()) > 0)
431    
432              if proj is None:              if proj is None:
433                  self.button_export.Enable(False)                  # <None> is selected
434                    for ctrl in [self.button_export,
435                                 self.button_remove,
436                                 self.button_save,
437                                 self.button_add,
438                                 self.projchoice,
439                                 self.projname]:
440                        ctrl.Enable(False)
441    
442                    if self.curProjPanel is not None:
443                        self.curProjPanel.Enable(False)
444    
445                elif proj is self.originalProjection:
446                  self.button_remove.Enable(False)                  self.button_remove.Enable(False)
447    
448              if projFile is None:              if projFile is None:
449                  self.button_save.Enable(False)                  self.button_save.Enable(False)
450    
451          else:          else:
452              self.panel_edit.Enable(False)              self.edit_box.Enable(False)
   
     def __DoOnNew(self):  
         sel = self.availprojs.GetSelections()  
         if len(sel) != 0:  
             self.availprojs.SetSelection(sel, False)  
         self.projname.Clear()  
         self.curProjPanel.Clear()  
   
     def __DoOnProjAvail(self):  
   
         sel = self.availprojs.GetSelections()  
         if len(sel) == 1:  
453    
454              proj = self.availprojs.GetClientData(sel[0])[CLIENT_PROJ]      def proj_selection_changed(self, projs):
455              projfile = self.availprojs.GetClientData(sel[0])[CLIENT_PROJFILE]          """Subscribed to the projection_list's PROJ_SELECTION_CHANGED message
456    
457            Update the dialog to reflect the new selection.
458            """
459            if len(projs) == 0:
460                self.projfilepath.SetLabel(_("No Projections selected"))
461            elif len(projs) == 1:
462                proj, projfile = projs[0]
463              if proj is None:              if proj is None:
464                  # user selected <None>                  # user selected <None>
465                  self.projname.Clear()                  self.projname.Clear()
466                    self.projfilepath.SetLabel("")
467              else:              else:
               
468                  if projfile is not None:                  if projfile is not None:
469                      self.projfilepath.SetLabel(projfile.GetFileName())                      filename = os.path.basename(projfile.GetFilename())
470                        self.projfilepath.SetLabel(_("Source of Projection: %s")
471                                                   % filename)
472                  else:                  else:
473                      # only None if the currently used projection is selected                      # only None if the currently used projection is selected
474                      self.projfilepath.SetLabel("")                      self.projfilepath.SetLabel("")
475    
476                  self.projname.SetValue(proj.GetName())                  self.projname.SetValue(proj.Label())
477    
478                  myProjType = proj.GetParameter("proj")                  myProjType = proj.GetParameter("proj")
479                  i = 0                  i = 0
480                  for projType, name, clazz in self.projPanels:                  for projType, name, cls in self.projection_panel_defs:
481                      if myProjType == projType:                      if myProjType == projType:
482                          self.projchoice.SetSelection(i)                          self.projchoice.Enable(True)
483                            self.projchoice.SetSelection(i + 1)
484                          self.__DoOnProjChoice()                          self.__DoOnProjChoice()
485    
486                            #
487                            # self.curProjPanel should not be null
488                            # after a call to __DoOnProjChoice
489                            #
490                            assert self.curProjPanel is not None
491    
492                          self.curProjPanel.SetProjection(proj)                          self.curProjPanel.SetProjection(proj)
493                            break
494                      i += 1                      i += 1
495                    else:
496                        self.projchoice.Select(0)
497                        self.projchoice.Disable()
498                        self._show_proj_panel(UnknownProjPanel)
499                        assert self.curProjPanel is not None
500                        self.curProjPanel.SetProjection(proj)
501            else:
502                self.projfilepath.SetLabel(_("Multiple Projections selected"))
503    
504          self.__VerifyButtons()          self.__VerifyButtons()
505    
# Line 410  class ProjFrame(NonModalDialog): Line 507  class ProjFrame(NonModalDialog):
507          self.__DoOnProjChoice()          self.__DoOnProjChoice()
508    
509      def __DoOnProjChoice(self):      def __DoOnProjChoice(self):
510            """Create and layout a projection panel based on the selected
511            projection type.
512    
513            This is necessary to have in seperate method since calls to
514            wxChoice.SetSelection() do not trigger an event.
515    
516            At the end of this method self.curProjPanel will not be None
517            if there was a item selected.
518            """
519          choice = self.projchoice          choice = self.projchoice
520    
521          sel = choice.GetSelection()          sel = choice.GetSelection()
522          if sel != -1:          if sel != -1:
523                proj_type = choice.GetClientData(sel)
524              clazz, obj = choice.GetClientData(sel)              for t, name, cls in self.projection_panel_defs:
525                    if t == proj_type:
526              if obj is None:                      self._show_proj_panel(cls)
527                  obj = clazz(self.panel_edit, self.receiver)                      break
528                  choice.SetClientData(sel, [clazz, obj])          # FIXME: what to do if sel == -1?
529    
530              if self.curProjPanel is not None:      def _show_proj_panel(self, panel_class):
531                  self.curProjPanel.Hide()          """Show the panel as the projection panel"""
532                  self.sizer_projctrls.Remove(self.curProjPanel)          if panel_class is UnknownProjPanel:
533                self.button_ok.Disable()
534              self.curProjPanel = obj              self.button_try.Disable()
535              self.curProjPanel.Show()              self.edit_box.Disable()
536                self.nbsizer.Activate(self.unknown_projection_panel)
537              self.sizer_projctrls.Add(self.curProjPanel, 1,              self.curProjPanel = self.unknown_projection_panel
538                  wxALL|wxEXPAND|wxADJUST_MINSIZE, 3)          else:
539              self.sizer_projctrls.Layout()              self.button_ok.Enable(True)
540              self.Layout()              self.button_try.Enable(True)
541              self.topBox.SetSizeHints(self)              self.edit_box.Enable(True)
542                self.unknown_projection_panel.Hide()
543                for panel in self.projection_panels:
544                    if panel.__class__ is panel_class:
545                        self.nbsizer.Activate(panel)
546                        self.curProjPanel = panel
547    
548      def __SetProjection(self):      def __SetProjection(self):
549            """Set the receiver's projection."""
550    
551          #          #
552          # save the original projection only once in case          # save the original projection only once in case
553          # we try to apply several different projections          # we try to apply several different projections
554          #          #
         if self.originalProjection == -1:  
             self.originalProjection = self.receiver.GetProjection()  
   
555          self.receiver.SetProjection(self.__GetProjection())          self.receiver.SetProjection(self.__GetProjection())
556    
557      def __GetProjection(self):      def __GetProjection(self):
558          """Return the packaged projection.          """Return a suitable Projection object based on the current
559            state of the dialog box selections.
560    
561          Could be None.          Could be None.
562          """          """
563    
564          proj = None          assert self.projection_list.GetSelectedItemCount() < 2, \
565                   "button should be disabled"
         if self.curProjPanel is not None:  
             proj = Projection(self.curProjPanel.GetParameters())  
             proj.SetName(self.projname.GetValue())  
   
         return proj  
566    
567      def __FillAvailList(self):          sel = self.projection_list.selected_projections()
568          self.availprojs.Clear()          if len(sel) == 1:
569                if sel[0][0] is None:
570          #                  # <None> is selected
571          # the list can never be empty. there will always be                  return None
         # at least this one item  
         #  
         self.availprojs.Append("<None>", (None, None))  
   
         self.__sysProjFile = None  
         self.__usrProjFile = None  
   
         projfile = GetSystemProjFiles()  
         if len(projfile) > 0:  
             projfile = projfile[0]  
             for proj in projfile.GetProjections():  
                 self.availprojs.Append(proj.GetName(), [proj, projfile])  
             self.__sysProjFile = projfile  
   
         projfile = GetUserProjFiles()  
         if len(projfile) > 0:  
             projfile = projfile[0]  
             for proj in projfile.GetProjections():  
                 self.availprojs.Append(proj.GetName(), [proj, projfile])  
             self.__usrProjFile = projfile  
   
 #       projfiles = GetSystemProjFiles()  
 #       for projfile in projfiles:  
 #           for proj in projfile.GetProjections():  
 #               self.availprojs.Append(proj.GetName(), [proj, projfile])  
 #       self.__sysProjFiles = projfiles  
   
 #       projfiles = GetUserProjFiles()  
 #       for projfile in projfiles:  
 #           for proj in projfile.GetProjections():  
 #               self.availprojs.Append(proj.GetName(), [proj, projfile])  
 #       self.__usrProjFiles = projfiles  
   
         proj = self.receiver.GetProjection()  
         if proj is not None:  
             self.availprojs.Append(proj.GetName() + _(" (current)"),  
                                    [proj, None])  
572    
573          for proj, name, clazz in self.projPanels:          # self.curProjPanel should always contain the most relevant data
574              self.projchoice.Append(name, [clazz, None])          # for a projection
575            if self.curProjPanel is not None:
576                parameters = self.curProjPanel.GetParameters()
577                if parameters is not None:
578                    return Projection(parameters, self.projname.GetValue())
579    
580      def __set_properties(self):          return None
         self.__FillAvailList()  
581    
582          # begin wxGlade: ProjFrame.__set_properties      def load_user_proj(self):
583          self.SetTitle(_("Projections"))          """Return the user's ProjFile
         self.availprojs.SetSelection(0)  
         self.projchoice.SetSelection(0)  
         # end wxGlade  
584    
585          self.projname.SetMaxLength(32)          If the file has not yet been loaded by the dialog, load it first
586            with get_user_proj_file and cache it in self.__usrProjFile.
587    
588      def __do_layout(self):          Show a busy cursor while loading the file.
589          # originally generated by wxGlade      
590            If the file is not available, leave a note to the console.
591            """
592            if self.__usrProjFile is None:
593                ThubanBeginBusyCursor()
594                try:
595                    projfile, warnings = get_user_proj_file()
596                    if warnings:
597                        sys.stderr.write("".join(warnings))
598                    self.__usrProjFile = projfile
599                finally:
600                    ThubanEndBusyCursor()
601            return self.__usrProjFile
602    
603        def load_system_proj(self, name):
604            """Load the system ProjFile with the given name.
605    
606            If the file has not been loaded yet, load it first with
607            get_system_proj_file and put it into the cache. The name is
608            simply forwarded to get_system_proj_file.
609    
610          self.topBox = wxBoxSizer(wxVERTICAL)          Show a busy cursor while loading the file.
611          self.sizer_panel = wxBoxSizer(wxVERTICAL)          """
612          sizer_6 = wxBoxSizer(wxHORIZONTAL)          if name not in self._sys_proj_files:
613          self.sizer_mainctrls = wxBoxSizer(wxHORIZONTAL)              ThubanBeginBusyCursor()
614          self.sizer_edit = wxStaticBoxSizer(wxStaticBox(self.panel_edit, -1, _("Edit")), wxHORIZONTAL)              try:
615          sizer_11 = wxBoxSizer(wxVERTICAL)                  projfile, warnings = get_system_proj_file(name)
616          self.sizer_projctrls = wxBoxSizer(wxVERTICAL)                  self.show_warnings(_("Warnings"), projfile.GetFilename(),
617          sizer_14 = wxBoxSizer(wxHORIZONTAL)                                     warnings)
618          sizer_13 = wxBoxSizer(wxHORIZONTAL)                  self._sys_proj_files[name] = projfile
619          sizer_15 = wxBoxSizer(wxVERTICAL)              finally:
620          sizer_15.Add(self.button_import, 0, wxALL, 4)                  ThubanEndBusyCursor()
621          sizer_15.Add(self.button_export, 0, wxALL, 4)          return self._sys_proj_files[name]
         sizer_15.Add(20, 20, 0, wxEXPAND, 0)  
         sizer_15.Add(self.button_remove, 0, wxALL|wxALIGN_BOTTOM, 4)  
   
         # list controls  
         grid_sizer_1 = wxFlexGridSizer(3, 2, 0, 0)  
         grid_sizer_1.Add(self.label_5, 0, wxLEFT|wxRIGHT|wxTOP, 4)  
         grid_sizer_1.Add(20, 20, 0, wxEXPAND, 0)  
         grid_sizer_1.Add(self.availprojs, 1, wxALL|wxEXPAND|wxADJUST_MINSIZE, 4)  
         grid_sizer_1.Add(sizer_15, 0, wxALL|wxEXPAND, 4)  
         grid_sizer_1.Add(self.projfilepath, 0, wxALL|wxADJUST_MINSIZE, 4)  
         grid_sizer_1.AddGrowableRow(1)  
         grid_sizer_1.AddGrowableCol(0)  
   
         # edit controls  
         sizer_13.Add(self.label_2, 0, wxALL|wxALIGN_CENTER_VERTICAL, 4)  
         sizer_13.Add(self.projname, 1, wxALL, 4)  
         self.sizer_projctrls.Add(sizer_13, 0, wxEXPAND, 0)  
         sizer_14.Add(self.label_3, 0, wxALL|wxALIGN_CENTER_VERTICAL, 4)  
         sizer_14.Add(self.projchoice, 1, wxALL|wxEXPAND|wxADJUST_MINSIZE, 4)  
         self.sizer_projctrls.Add(sizer_14, 0, wxEXPAND, 0)  
         self.sizer_edit.Add(self.sizer_projctrls, 1, wxEXPAND, 0)  
         sizer_11.Add(self.button_new, 0, wxALL|wxEXPAND, 4)  
         sizer_11.Add(self.button_save, 0, wxALL|wxEXPAND, 4)  
         sizer_11.Add(self.button_add, 0, wxALL|wxEXPAND, 4)  
         self.sizer_edit.Add(sizer_11, 0, wxALL|wxEXPAND, 4)  
   
         sizer_6.Add(20, 20, 1, wxEXPAND, 0)  
         sizer_6.Add(self.button_try, 0, wxALL, 4)  
         sizer_6.Add(20, 20, 1, 0, 0)  
         sizer_6.Add(self.button_revert, 0, wxALL, 4)  
         sizer_6.Add(20, 20, 1, 0, 0)  
         sizer_6.Add(self.button_ok, 0, wxALL, 4)  
         sizer_6.Add(20, 20, 1, 0, 0)  
         sizer_6.Add(self.button_close, 0, wxALL, 4)  
         sizer_6.Add(20, 20, 1, wxEXPAND, 0)  
   
         self.panel_1.SetAutoLayout(1)  
         self.panel_1.SetSizer(grid_sizer_1)  
         grid_sizer_1.Fit(self.panel_1)  
         grid_sizer_1.SetSizeHints(self.panel_1)  
   
         self.panel_edit.SetAutoLayout(1)  
         self.panel_edit.SetSizer(self.sizer_edit)  
         self.sizer_edit.Fit(self.panel_edit)  
         self.sizer_edit.SetSizeHints(self.panel_edit)  
   
         self.panel_buttons.SetAutoLayout(1)  
         self.panel_buttons.SetSizer(sizer_6)  
         sizer_6.Fit(self.panel_buttons)  
         sizer_6.SetSizeHints(self.panel_buttons)  
   
         self.sizer_mainctrls.Add(self.panel_1, 0,  
             wxALL|wxEXPAND|wxADJUST_MINSIZE, 0)  
         self.sizer_mainctrls.Add(self.panel_edit, 1,  
             wxALL|wxEXPAND|wxADJUST_MINSIZE, 0)  
622    
623          self.topBox.Add(self.sizer_mainctrls, 1, wxALL|wxEXPAND, 4)      def write_proj_file(self, proj_file):
624          self.topBox.Add(self.panel_buttons, 0, wxEXPAND, 0)          """Write the ProjFile object proj_file back to its file
625    
626          self.SetAutoLayout(1)          Show a busy cursor while writing and if an error occurs show a
627          self.SetSizer(self.topBox)          dialog with the error message.
628          self.topBox.Fit(self)          """
629          self.topBox.SetSizeHints(self)          try:
630          self.Layout()              ThubanBeginBusyCursor()
631                try:
632                    write_proj_file(proj_file)
633                finally:
634                    ThubanEndBusyCursor()
635            except IOError, (errno, errstr):
636                self.__ShowError(proj_file.GetFilename(), errstr)
637    
 # end of class ProjFrame  
638    
639    
640  class ProjPanel(wxPanel):  class ProjPanel(wxPanel):
# Line 606  class ProjPanel(wxPanel): Line 644  class ProjPanel(wxPanel):
644          wxPanel.__init__(self, parent, -1)          wxPanel.__init__(self, parent, -1)
645    
646          self.__ellps = wxChoice(self, -1)          self.__ellps = wxChoice(self, -1)
647          self.ellpsData = [("bessel", _("Bessel 1841")),          self.ellpsData = [("", _("<Unknown>")),
648                            ("clrk66", _("Clarke 1866")),                            ("airy"  , _("Airy")),
649                              ("bessel", _("Bessel 1841")),
650                              ("clrk66", _("Clarke 1866")),
651                            ("clrk80", _("Clarke 1880")),                            ("clrk80", _("Clarke 1880")),
652                            ("GRS80" , _("GRS 1980 (IUGG, 1980)")),                            ("GRS80" , _("GRS 1980 (IUGG, 1980)")),
653                            ("intl"  , _("International 1909 (Hayford)")),                            ("intl"  , _("International 1909 (Hayford)")),
# Line 622  class ProjPanel(wxPanel): Line 662  class ProjPanel(wxPanel):
662    
663          panelSizer = wxBoxSizer(wxVERTICAL)          panelSizer = wxBoxSizer(wxVERTICAL)
664    
         if childPanel is not None:  
             panelSizer.Add(childPanel, 0, wxALL|wxEXPAND, 4)  
               
665          sizer = wxBoxSizer(wxHORIZONTAL)          sizer = wxBoxSizer(wxHORIZONTAL)
666          sizer.Add(wxStaticText(self, -1, _("Ellipsoid:")), 0, wxALL, 4)          sizer.Add(wxStaticText(self, -1, _("Ellipsoid:")), 0,
667          sizer.Add(self.__ellps, 1, wxALL|wxEXPAND|wxADJUST_MINSIZE, 4)                                      wxALL|wxALIGN_CENTER_VERTICAL, 4)
668            sizer.Add(self.__ellps, 1, wxALL|wxALIGN_CENTER_VERTICAL, 4)
669          panelSizer.Add(sizer, 0, wxALL|wxEXPAND, 4)          panelSizer.Add(sizer, 0, wxALL|wxEXPAND, 4)
670    
671            if childPanel is not None:
672                panelSizer.Add(childPanel, 0, wxEXPAND, 0)
673                
674          self.SetAutoLayout(1)          self.SetAutoLayout(1)
675          self.SetSizer(panelSizer)          self.SetSizer(panelSizer)
676          panelSizer.Fit(self)          panelSizer.Fit(self)
# Line 652  class ProjPanel(wxPanel): Line 693  class ProjPanel(wxPanel):
693          self.__ellps.SetSelection(0)          self.__ellps.SetSelection(0)
694    
695      def GetParameters(self):      def GetParameters(self):
696          return ["ellps=" + self.__ellps.GetClientData(          ellps = self.__ellps.GetSelection()
697                                          self.__ellps.GetSelection())]          if ellps > 0:
698                return ["ellps=" + self.__ellps.GetClientData(ellps)]
699            return []
700    
701    
702  ID_TMPANEL_LAT = 4001  ID_TMPANEL_LAT = 4001
# Line 663  ID_TMPANEL_FALSE_NORTH = 4004 Line 706  ID_TMPANEL_FALSE_NORTH = 4004
706  ID_TMPANEL_SCALE = 4005  ID_TMPANEL_SCALE = 4005
707    
708  class UnknownProjPanel(ProjPanel):  class UnknownProjPanel(ProjPanel):
709    
710        """Panel for unknown projection types"""
711    
712      def __init__(self, parent, receiver):      def __init__(self, parent, receiver):
713          ProjPanel.__init__(self, parent)          ProjPanel.__init__(self, parent)
714    
715            self.__text = _("Thuban does not know the parameters\n"
716                            "for the current projection and cannot\n"
717                            "display a configuration panel.\n\n"
718                            "The unidentified set of parameters is:\n\n")
719    
720            self.__textbox = wxTextCtrl(self, -1, self.__text, size=(100,200),
721                                style=wxTE_READONLY|wxTE_MULTILINE|wxTE_LINEWRAP)
722          self._DoLayout()          self._DoLayout()
723    
724      def _DoLayout(self):      def _DoLayout(self):
725          sizer = wxBoxSizer(wxVERTICAL)          sizer = wxBoxSizer(wxVERTICAL)
726    
727          sizer.Add(wxStaticText(self, -1,          sizer.Add(self.__textbox, 0, wxALL|wxEXPAND, 4)
             _("Thuban does not know the parameters for the " +  
               "current projection and cannot display a " +  
               "configuration panel.")))  
728    
729          ProjPanel._DoLayout(self, sizer)          ProjPanel._DoLayout(self, sizer)
730    
# Line 682  class UnknownProjPanel(ProjPanel): Line 732  class UnknownProjPanel(ProjPanel):
732          return "Unknown"          return "Unknown"
733    
734      def SetProjection(self, proj):      def SetProjection(self, proj):
735          pass          """Append the available parameters to the info text."""
736            text = self.__text
737            for param in proj.GetAllParameters():
738                text = text + '%s\n' % param
739            self.__textbox.SetValue(text)
740    
741      def GetParameters(self):      def GetParameters(self):
742          return None          return None
# Line 703  class TMPanel(ProjPanel): Line 757  class TMPanel(ProjPanel):
757    
758      def _DoLayout(self):      def _DoLayout(self):
759    
760          sizer = wxFlexGridSizer(4, 4, 0, 0)          sizer = wxFlexGridSizer(4, 2, 0, 0)
761          sizer.Add(wxStaticText(self, -1, _("Latitude:")), 0, wxALL, 4)          sizer.Add(wxStaticText(self, -1, _("Latitude:")), 0, wxALL, 4)
762          sizer.Add(self.__latitude, 0, wxALL, 4)          sizer.Add(self.__latitude, 0, wxALL, 4)
         sizer.Add(wxStaticText(self, -1, _("False Easting:")), 0, wxALL, 4)  
         sizer.Add(self.__falseEast, 0, wxALL, 4)  
763          sizer.Add(wxStaticText(self, -1, _("Longitude:")), 0, wxALL, 4)          sizer.Add(wxStaticText(self, -1, _("Longitude:")), 0, wxALL, 4)
764          sizer.Add(self.__longitude, 0, wxALL, 4)          sizer.Add(self.__longitude, 0, wxALL, 4)
765            sizer.Add(wxStaticText(self, -1, _("False Easting:")), 0, wxALL, 4)
766            sizer.Add(self.__falseEast, 0, wxALL, 4)
767          sizer.Add(wxStaticText(self, -1, _("False Northing:")), 0, wxALL, 4)          sizer.Add(wxStaticText(self, -1, _("False Northing:")), 0, wxALL, 4)
768          sizer.Add(self.__falseNorth, 0, wxALL, 4)          sizer.Add(self.__falseNorth, 0, wxALL, 4)
769          sizer.Add(wxStaticText(self, -1, _("Scale Factor:")), 0, wxALL, 4)          sizer.Add(wxStaticText(self, -1, _("Scale Factor:")), 0, wxALL, 4)
# Line 763  class UTMPanel(ProjPanel): Line 817  class UTMPanel(ProjPanel):
817          self.receiver = receiver          self.receiver = receiver
818    
819          self.__zone = wxSpinCtrl(self, ID_UTMPANEL_ZONE, "1", min=1, max=60)          self.__zone = wxSpinCtrl(self, ID_UTMPANEL_ZONE, "1", min=1, max=60)
820            self.__propButton = wxButton(self, ID_UTMPANEL_PROP, _("Propose"))
821          self.__south = wxCheckBox(self, ID_UTMPANEL_SOUTH,          self.__south = wxCheckBox(self, ID_UTMPANEL_SOUTH,
822                                    _("Southern Hemisphere"))                                    _("Southern Hemisphere"))
         self.__propButton = wxButton(self, ID_UTMPANEL_PROP, _("Propose"))  
823    
824          self._DoLayout()          self._DoLayout()
825    
# Line 805  class UTMPanel(ProjPanel): Line 859  class UTMPanel(ProjPanel):
859          ProjPanel.Clear(self)          ProjPanel.Clear(self)
860    
861      def _OnPropose(self, event):      def _OnPropose(self, event):
862          UTMProposeZoneDialog          """Call the propose dialog.
863            If the receiver (e.g. the current map) has no bounding box,
864            inform the user accordingly.
865            """
866            bb = self.receiver.BoundingBox()
867            if bb is None:
868                dlg = wxMessageDialog(self,
869                        _("Can not propose: No bounding box found."),
870                        _("Projection: Propose UTM Zone"),
871                        wxOK | wxICON_INFORMATION)
872                dlg.CenterOnParent()
873                result = dlg.ShowModal()
874                dlg.Destroy()
875                return
876    
877          dlg = UTMProposeZoneDialog(self, self.receiver.BoundingBox())          dlg = UTMProposeZoneDialog(self, self.receiver.BoundingBox())
878          if dlg.ShowModal() == wxID_OK:          if dlg.ShowModal() == wxID_OK:
879              self.__zone.SetValue(dlg.GetProposedZone())              self.__zone.SetValue(dlg.GetProposedZone())
# Line 818  class LCCPanel(ProjPanel): Line 886  class LCCPanel(ProjPanel):
886                    
887          self.__fspLatitude = wxTextCtrl(self, -1)          self.__fspLatitude = wxTextCtrl(self, -1)
888          self.__sspLatitude = wxTextCtrl(self, -1)          self.__sspLatitude = wxTextCtrl(self, -1)
         self.__originLat   = wxTextCtrl(self, -1)  
889          self.__meridian    = wxTextCtrl(self, -1)          self.__meridian    = wxTextCtrl(self, -1)
890            self.__originLat   = wxTextCtrl(self, -1)
891          self.__falseEast   = wxTextCtrl(self, -1)          self.__falseEast   = wxTextCtrl(self, -1)
892          self.__falseNorth  = wxTextCtrl(self, -1)          self.__falseNorth  = wxTextCtrl(self, -1)
893    
# Line 834  class LCCPanel(ProjPanel): Line 902  class LCCPanel(ProjPanel):
902          sizer.Add(wxStaticText(self, -1,          sizer.Add(wxStaticText(self, -1,
903              _("Latitude of second standard parallel:")))              _("Latitude of second standard parallel:")))
904          sizer.Add(self.__sspLatitude, 0, wxALL, 4)          sizer.Add(self.__sspLatitude, 0, wxALL, 4)
         sizer.Add(wxStaticText(self, -1, _("Latitude of origin:")))  
         sizer.Add(self.__originLat, 0, wxALL, 4)  
905          sizer.Add(wxStaticText(self, -1, _("Central Meridian:")))          sizer.Add(wxStaticText(self, -1, _("Central Meridian:")))
906          sizer.Add(self.__meridian, 0, wxALL, 4)          sizer.Add(self.__meridian, 0, wxALL, 4)
907            sizer.Add(wxStaticText(self, -1, _("Latitude of origin:")))
908            sizer.Add(self.__originLat, 0, wxALL, 4)
909          sizer.Add(wxStaticText(self, -1, _("False Easting:")))          sizer.Add(wxStaticText(self, -1, _("False Easting:")))
910          sizer.Add(self.__falseEast, 0, wxALL, 4)          sizer.Add(self.__falseEast, 0, wxALL, 4)
911          sizer.Add(wxStaticText(self, -1, _("False Northing:")))          sizer.Add(wxStaticText(self, -1, _("False Northing:")))
# Line 885  class GeoPanel(ProjPanel): Line 953  class GeoPanel(ProjPanel):
953    
954      def __init__(self, parent, receiver):      def __init__(self, parent, receiver):
955          ProjPanel.__init__(self, parent)          ProjPanel.__init__(self, parent)
956          ProjPanel._DoLayout(self, None)  
957            self.__choices = [(_("Degrees"), "0.017453"),
958                              (_("Radians"), "1")]
959    
960            self.__scale = wxChoice(self, -1)
961            for choice, value in self.__choices:
962                self.__scale.Append(choice, value)
963    
964            self._DoLayout()
965    
966      def GetProjName(self):      def GetProjName(self):
967          return _("Geographic")          return _("Geographic")
968                    
969      def SetProjection(self, proj):      def SetProjection(self, proj):
970            value = proj.GetParameter("to_meter")
971            for i in range(len(self.__choices)):
972                choice, data = self.__choices[i]
973                if value == data:
974                    self.__scale.SetSelection(i)
975          ProjPanel.SetProjection(self, proj)          ProjPanel.SetProjection(self, proj)
976    
977      def GetParameters(self):      def GetParameters(self):
978          params = ["proj=latlong"]          params = ["proj=latlong",
979                      "to_meter=%s" % self.__scale.GetClientData(
980                                      self.__scale.GetSelection())]
981    
982          params.extend(ProjPanel.GetParameters(self))          params.extend(ProjPanel.GetParameters(self))
983          return params          return params
984    
985      def Clear(self):      def Clear(self):
986          ProjPanel.Clear(self)          ProjPanel.Clear(self)
987    
988        def _DoLayout(self):
989            sizer = wxBoxSizer(wxHORIZONTAL)
990    
991            sizer.Add(wxStaticText(self, -1, _("Source Data is in: ")),
992                      0, wxALL|wxALIGN_CENTER_VERTICAL, 4)
993            sizer.Add(self.__scale, 1, wxEXPAND|wxALL, 4)
994    
995            self.__scale.SetSelection(0)
996    
997            ProjPanel._DoLayout(self, sizer)
998    
999    
1000  ID_UTM_PROPOSE_ZONE_DIALOG_TAKE   = 4001  ID_UTM_PROPOSE_ZONE_DIALOG_TAKE   = 4001
1001  ID_UTM_PROPOSE_ZONE_DIALOG_CANCEL = 4002  ID_UTM_PROPOSE_ZONE_DIALOG_CANCEL = 4002
1002  class UTMProposeZoneDialog(wxDialog):  class UTMProposeZoneDialog(wxDialog):
1003                                                                                    
1004      """Propose a sensible Zone considering the current map extent."""      """Propose a sensible Zone considering the current map extent."""
1005                                                                                    
1006      def __init__(self, parent, (x, y, x2, y2)):      def __init__(self, parent, (x, y, x2, y2)):
1007          wxDialog.__init__(self, parent, -1, _("Projection: Propose UTM Zone"),          wxDialog.__init__(self, parent, -1, _("Projection: Propose UTM Zone"),
1008                            wxDefaultPosition, wxSize(200, 100))                            wxDefaultPosition, wxSize(200, 100))
1009          self.parent = parent          self.parent = parent
         #x, y, x2, y2 = elf.parent.parent.map_bounding_box  
1010          x = x + 180          x = x + 180
1011          x2 = x2 + 180          x2 = x2 + 180
1012          center = (x2 - x) / 2 + x          center = (x2 - x) / 2 + x
1013          self.proposedZone = int(center / 6 + 1)          self.proposedZone = int(center / 6 + 1)
1014          self.dialogLayout()          self.dialogLayout()
1015                                                                                    
1016      def dialogLayout(self):      def dialogLayout(self):
1017          topBox = wxBoxSizer(wxVERTICAL)          topBox = wxBoxSizer(wxVERTICAL)
1018                                                                                    
1019          textBox = wxBoxSizer(wxVERTICAL)          textBox = wxBoxSizer(wxVERTICAL)
1020          textBox.Add(wxStaticText(self, -1, _("The current map extent center " +          textBox.Add(wxStaticText(self, -1, _("The current map extent center "
1021                                             "lies in UTM Zone")),                                               "lies in UTM Zone")),
1022                      0, wxALIGN_CENTER|wxALL, 4)                      0, wxALIGN_CENTER|wxALL, 4)
1023          textBox.Add(wxStaticText(self, -1, str(self.proposedZone)),          textBox.Add(wxStaticText(self, -1, str(self.proposedZone)),
1024                      0, wxALIGN_CENTER|wxALL, 4)                      0, wxALIGN_CENTER|wxALL, 4)
1025                                                                                    
1026          topBox.Add(textBox, 1, wxEXPAND|wxALL, 4)          topBox.Add(textBox, 1, wxEXPAND|wxALL, 4)
1027                                                                                    
1028          buttonBox = wxBoxSizer(wxHORIZONTAL)          buttonBox = wxBoxSizer(wxHORIZONTAL)
1029          buttonBox.Add(wxButton(self, ID_UTM_PROPOSE_ZONE_DIALOG_TAKE,          buttonBox.Add(wxButton(self, ID_UTM_PROPOSE_ZONE_DIALOG_TAKE,
1030                        _("Take")), 0, wxALL, 4)                        _("Take")), 0, wxALL, 4)
# Line 939  class UTMProposeZoneDialog(wxDialog): Line 1033  class UTMProposeZoneDialog(wxDialog):
1033          topBox.Add(buttonBox, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 10)          topBox.Add(buttonBox, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 10)
1034          EVT_BUTTON(self, ID_UTM_PROPOSE_ZONE_DIALOG_TAKE, self.OnTake)          EVT_BUTTON(self, ID_UTM_PROPOSE_ZONE_DIALOG_TAKE, self.OnTake)
1035          EVT_BUTTON(self, ID_UTM_PROPOSE_ZONE_DIALOG_CANCEL, self.OnCancel)          EVT_BUTTON(self, ID_UTM_PROPOSE_ZONE_DIALOG_CANCEL, self.OnCancel)
1036                                                                                    
1037          self.SetAutoLayout(True)          self.SetAutoLayout(True)
1038          self.SetSizer(topBox)          self.SetSizer(topBox)
1039          topBox.Fit(self)          topBox.Fit(self)
1040          topBox.SetSizeHints(self)          topBox.SetSizeHints(self)
1041                                                                                    
1042      def OnTake(self, event):      def OnTake(self, event):
1043          self.EndModal(wxID_OK)          self.EndModal(wxID_OK)
1044                                                                                    
1045      def OnCancel(self, event):      def OnCancel(self, event):
1046          self.EndModal(wxID_CANCEL)          self.EndModal(wxID_CANCEL)
1047    

Legend:
Removed from v.730  
changed lines
  Added in v.2470

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26