/[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 1566 by bh, Fri Aug 8 13:01:30 2003 UTC revision 1933 by bh, Tue Nov 11 16:37:53 2003 UTC
# Line 13  __version__ = "$Revision$" Line 13  __version__ = "$Revision$"
13  # $Source$  # $Source$
14  # $Id$  # $Id$
15    
16  import os, sys, math  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 get_user_proj_files, get_system_proj_files, \  from Thuban.Model.resource import get_user_proj_file, get_system_proj_file, \
24                                    read_proj_file, write_proj_file                                    read_proj_file, write_proj_file, \
25                                      DEFAULT_PROJ_FILE, EPSG_PROJ_FILE
26  from Thuban.UI.dialogs import NonModalNonParentDialog  from Thuban.UI.dialogs import NonModalNonParentDialog
27    
28    from common import ThubanBeginBusyCursor, ThubanEndBusyCursor
29    from sizers import NotebookLikeSizer
30    from projlist import PROJ_SELECTION_CHANGED, ProjectionList
31    from common import ThubanBeginBusyCursor, ThubanEndBusyCursor
32    
33    
34    
 ID_PROJ_ADVANCED  = 4001  
35  ID_PROJ_PROJCHOICE = 4002  ID_PROJ_PROJCHOICE = 4002
36  ID_PROJ_ADDTOLIST    = 4003  ID_PROJ_ADDTOLIST    = 4003
37  ID_PROJ_NEW       = 4004  ID_PROJ_NEW       = 4004
# Line 49  class ProjFrame(NonModalNonParentDialog) Line 55  class ProjFrame(NonModalNonParentDialog)
55                          SetProjection(projection)                          SetProjection(projection)
56                          GetProjection()                          GetProjection()
57          """          """
58                    NonModalNonParentDialog.__init__(self, parent, name, title)
59    
60            self.projection_panel_defs = [
61                ("tmerc", _("Transverse Mercator"), TMPanel),
62                ("utm", _("Universal Transverse Mercator"), UTMPanel),
63                ("lcc", _("Lambert Conic Conformal"), LCCPanel),
64                ("latlong", _("Geographic"), GeoPanel),
65                ("longlat", _("Geographic"), GeoPanel)]#longlat is an alias of proj
66          self.receiver = receiver          self.receiver = receiver
67          self.haveTried = False          self.haveTried = False
68          self.curProjPanel = None          self.curProjPanel = None
69            self.__usrProjFile = None
70            self._sys_proj_files = {}
71    
72          self.projPanels = []          self.build_dialog()
73          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))  
74    
75          NonModalNonParentDialog.__init__(self, parent, name, title)          self.originalProjection = self.receiver.GetProjection()
76          # originally generate by wxGlade  
77          self.panel_1 = wxPanel(self, -1)          self.projection_list.SelectProjection(self.originalProjection)
78          self.panel_edit = wxPanel(self, -1)          self.projection_list.SetFocus()
79          self.label_5 = wxStaticText(self.panel_1, -1,  
80                          _("Available Projections:"))      def build_dialog(self):
81            """Build the dialog's widgets and set the event handlers"""
82            self.topBox = top_box = wxBoxSizer(wxVERTICAL)
83    
84            main_box = wxBoxSizer(wxHORIZONTAL)
85            top_box.Add(main_box, 1, wxALL|wxEXPAND)
86    
87            #
88            #    The projection list and associated controls
89            #
90            vbox = wxBoxSizer(wxVERTICAL)
91            main_box.Add(vbox, 4, wxALL|wxEXPAND)
92    
93            #label = wxStaticText(self, -1, _("Available Projections:"))
94            #vbox.Add(label, 0, wxLEFT|wxRIGHT|wxTOP, 4)
95    
96            hbox = wxBoxSizer(wxHORIZONTAL)
97            vbox.Add(hbox, 1, wxALL|wxEXPAND)
98            proj_files = [self.load_user_proj(),
99                          self.load_system_proj(DEFAULT_PROJ_FILE)]
100            self.projection_list = ProjectionList(self, proj_files,
101                                                  self.receiver.GetProjection())
102            hbox.Add(self.projection_list, 1, wxALL|wxEXPAND|wxADJUST_MINSIZE, 4)
103            self.projection_list.Subscribe(PROJ_SELECTION_CHANGED,
104                                           self.proj_selection_changed)
105    
106          # Projection List specific actions (Import/Export/Remove)          # Projection List specific actions (Import/Export/Remove)
107          self.button_import = wxButton(self.panel_1, ID_PROJ_IMPORT,          buttons = wxBoxSizer(wxVERTICAL)
108                                        _("Import..."))          hbox.Add(buttons, 0, wxALL)
109          self.button_export = wxButton(self.panel_1, ID_PROJ_EXPORT,          self.button_import = wxButton(self, ID_PROJ_IMPORT, _("Import..."))
110                                        _("Export..."))          EVT_BUTTON(self, ID_PROJ_IMPORT, self._OnImport)
111          self.button_remove = wxButton(self.panel_1, ID_PROJ_REMOVE,          buttons.Add(self.button_import, 1, wxALL|wxEXPAND, 4)
112                                        _("Remove"))          self.button_export = wxButton(self, ID_PROJ_EXPORT, _("Export..."))
113            EVT_BUTTON(self, ID_PROJ_EXPORT, self._OnExport)
114          # The Projection List          buttons.Add(self.button_export, 1, wxALL|wxEXPAND, 4)
115          self.availprojs = wxListBox(self.panel_1, ID_PROJ_AVAIL,          buttons.Add(20, 20, 0, wxEXPAND, 0)
116                                      style=wxLB_EXTENDED|wxLB_SORT)          self.button_remove = wxButton(self, ID_PROJ_REMOVE, _("Remove"))
117          self.projfilepath = wxStaticText(self.panel_1, -1, "")          EVT_BUTTON(self, ID_PROJ_REMOVE, self._OnRemove)
118            buttons.Add(self.button_remove, 1, wxALL|wxEXPAND, 4)
119    
120          # Projection Specific Entries (Name/Projection)          self.check_epsg = wxCheckBox(self, -1, _("Show EPSG"))
121          self.label_2 = wxStaticText(self.panel_edit, -1, _("Name:"))          EVT_CHECKBOX(self, self.check_epsg.GetId(), self._OnShowEPSG)
122          self.projname = wxTextCtrl(self.panel_edit, ID_PROJ_PROJNAME, "")          buttons.Add(self.check_epsg, 1, wxALL|wxEXPAND, 4)
         self.label_3 = wxStaticText(self.panel_edit, -1, _("Projection:"))  
         self.projchoice = wxChoice(self.panel_edit, ID_PROJ_PROJCHOICE)  
123    
124          # Projection Specific actions (New/Save/Add)          # The file path
125          self.button_new = wxButton(self.panel_edit, ID_PROJ_NEW, _("New"))          self.projfilepath = wxStaticText(self, -1, "")
126          self.button_add = wxButton(self.panel_edit, ID_PROJ_ADDTOLIST,          vbox.Add(self.projfilepath, 0, wxALL|wxEXPAND)
                                       _("Add to List"))  
         self.button_save = wxButton(self.panel_edit, ID_PROJ_SAVE,_("Update"))  
127    
128          # Main Action buttons (Try/Revert/OK/Close)          #
129          self.button_try = wxButton(self, wxID_APPLY, _("Try"))          #   The projection editor part
130          self.button_revert = wxButton(self, ID_PROJ_REVERT,          #
131                                        _("Revert"))          self.edit_box = wxStaticBox(self, -1, _("Edit"))
132          self.button_ok = wxButton(self, wxID_OK, _("OK"))          sizer_edit = wxStaticBoxSizer(self.edit_box, wxHORIZONTAL)
133          self.button_ok.SetDefault()          main_box.Add(sizer_edit, 5, wxALL|wxEXPAND)
         self.button_close = wxButton(self, wxID_CANCEL,  
                                      _("Close"))  
134    
135          self.__set_properties()          # Projection Specific Entries (Name/Projection)
136          self.__do_layout()          self.sizer_projctrls = wxBoxSizer(wxVERTICAL)
137            sizer_edit.Add(self.sizer_projctrls, 1, wxALL|wxEXPAND)
138    
139          # wxGlade          hbox = wxBoxSizer(wxHORIZONTAL)
140            self.sizer_projctrls.Add(hbox, 0, wxALL|wxEXPAND)
141            label = wxStaticText(self, -1, _("Name:"))
142            hbox.Add(label, 0, wxALL|wxALIGN_CENTER_VERTICAL, 4)
143            self.projname = wxTextCtrl(self, ID_PROJ_PROJNAME, "")
144            EVT_TEXT(self, ID_PROJ_PROJNAME, self._OnProjName)
145            hbox.Add(self.projname, 1, wxALL|wxEXPAND, 4)
146    
147            hbox = wxBoxSizer(wxHORIZONTAL)
148            self.sizer_projctrls.Add(hbox, 0, wxALL|wxEXPAND)
149            label = wxStaticText(self, -1, _("Projection:"))
150            hbox.Add(label, 0, wxALL|wxALIGN_CENTER_VERTICAL, 4)
151            self.projchoice = wxChoice(self, ID_PROJ_PROJCHOICE)
152            self.projchoice.SetSelection(0)
153            EVT_CHOICE(self, ID_PROJ_PROJCHOICE, self._OnProjChoice)
154            hbox.Add(self.projchoice, 1, wxALL|wxEXPAND, 4)
155          # Fill the projection choice list.          # Fill the projection choice list.
156          for proj, name, clazz in self.projPanels:          self.nbsizer = NotebookLikeSizer()
157              self.projchoice.Append(name, [clazz, None])          self.sizer_projctrls.Add(self.nbsizer, 1,
158                                     wxALL|wxEXPAND|wxADJUST_MINSIZE, 3)
159            self.projection_panels = []
160            self.projchoice.Append(_("<Unknown>"), "")
161            for proj_type, name, cls in self.projection_panel_defs:
162                self.projchoice.Append(name, proj_type)
163                panel = cls(self, self.receiver)
164                panel.Hide()
165                panel.projection_index = len(self.projection_panels)
166                panel.projection_type = proj_type
167                self.projection_panels.append(panel)
168                self.nbsizer.Add(panel)
169            self.unknown_projection_panel = UnknownProjPanel(self, self.receiver)
170            self.unknown_projection_panel.Hide()
171            self.nbsizer.Add(self.unknown_projection_panel)
172    
173          self.originalProjection = self.receiver.GetProjection()          # Projection Specific actions (New/Save/Add)
174            buttons = wxBoxSizer(wxVERTICAL)
175            sizer_edit.Add(buttons, 0, wxALL)
176            self.button_new = wxButton(self, ID_PROJ_NEW, _("New"))
177            EVT_BUTTON(self, ID_PROJ_NEW, self._OnNew)
178            buttons.Add(self.button_new, 0, wxEXPAND|wxALL, 4)
179            self.button_add = wxButton(self, ID_PROJ_ADDTOLIST, _("Add to List"))
180            EVT_BUTTON(self, ID_PROJ_ADDTOLIST, self._OnAddToList)
181            buttons.Add(self.button_add, 0, wxEXPAND|wxALL, 4)
182            buttons.Add(20, 20, 0, wxEXPAND, 0)
183            self.button_save = wxButton(self, ID_PROJ_SAVE,_("Update"))
184            EVT_BUTTON(self, ID_PROJ_SAVE, self._OnSave)
185            buttons.Add(self.button_save, 0, wxEXPAND|wxALL|wxALIGN_BOTTOM, 4)
186    
187          self.__DoOnProjAvail()          #
188          self.button_ok.SetFocus()          # Main Action buttons (Try/Revert/OK/Close)
189          self.availprojs.SetFocus()          #
190                    buttons = wxBoxSizer(wxHORIZONTAL)
191            top_box.Add(buttons, 0, wxALL|wxALIGN_RIGHT, 10)
192            self.button_try = wxButton(self, wxID_APPLY, _("Try"))
193          EVT_BUTTON(self, wxID_APPLY, self.OnApply)          EVT_BUTTON(self, wxID_APPLY, self.OnApply)
194            buttons.Add(self.button_try, 0, wxRIGHT, 10)
195            self.button_revert = wxButton(self, ID_PROJ_REVERT, _("Revert"))
196          EVT_BUTTON(self, ID_PROJ_REVERT, self._OnRevert)          EVT_BUTTON(self, ID_PROJ_REVERT, self._OnRevert)
197            buttons.Add(self.button_revert, 0, wxRIGHT, 10)
198            self.button_ok = wxButton(self, wxID_OK, _("OK"))
199          EVT_BUTTON(self, wxID_OK, self.OnOK)          EVT_BUTTON(self, wxID_OK, self.OnOK)
200            self.button_ok.SetDefault()
201            buttons.Add(self.button_ok, 0, wxRIGHT, 10)
202            self.button_close = wxButton(self, wxID_CANCEL, _("Close"))
203          EVT_BUTTON(self, wxID_CANCEL, self.OnCancel)          EVT_BUTTON(self, wxID_CANCEL, self.OnCancel)
204          EVT_CHOICE(self, ID_PROJ_PROJCHOICE, self._OnProjChoice)          buttons.Add(self.button_close, 0, wxRIGHT, 10)
         EVT_LISTBOX(self, ID_PROJ_AVAIL, self._OnProjAvail)  
         EVT_BUTTON(self, ID_PROJ_IMPORT, self._OnImport)  
         EVT_BUTTON(self, ID_PROJ_EXPORT, self._OnExport)  
         EVT_BUTTON(self, ID_PROJ_REMOVE, self._OnRemove)  
205    
         EVT_BUTTON(self, ID_PROJ_NEW, self._OnNew)  
         EVT_BUTTON(self, ID_PROJ_SAVE, self._OnSave)  
         EVT_BUTTON(self, ID_PROJ_ADDTOLIST, self._OnAddToList)  
206    
207          EVT_TEXT(self, ID_PROJ_PROJNAME, self._OnProjName)          #
208            # Automatic Layout
209            #
210            self.SetAutoLayout(1)
211            self.SetSizer(top_box)
212            top_box.Fit(self)
213            top_box.SetSizeHints(self)
214    
215        def OnClose(self, event):
216            self.projection_list.Unsubscribe(PROJ_SELECTION_CHANGED,
217                                             self.proj_selection_changed)
218            # Destroy the projection list explicitly so that it properly
219            # unsubscribes everything. It would be cleaner if the projection
220            # could do this by itself but wx doesn't always send destroy
221            # events for non-top-level widgets
222            self.projection_list.Destroy()
223            NonModalNonParentDialog.OnClose(self, event)
224    
225      def OnApply(self, event):      def OnApply(self, event):
226          self.__SetProjection()          self.__SetProjection()
# Line 157  class ProjFrame(NonModalNonParentDialog) Line 243  class ProjFrame(NonModalNonParentDialog)
243    
244      def _OnNew(self, event):      def _OnNew(self, event):
245    
246          # clear all selections          self.projection_list.ClearSelection()
         sel = self.availprojs.GetSelections()  
         for index in sel:  
             self.availprojs.SetSelection(index, False)  
   
247          self.projname.Clear()          self.projname.Clear()
248    
249          # supply a projection panel if there wasn't one          # supply a projection panel if there wasn't one
# Line 169  class ProjFrame(NonModalNonParentDialog) Line 251  class ProjFrame(NonModalNonParentDialog)
251              self.projchoice.SetSelection(0)              self.projchoice.SetSelection(0)
252              self.__DoOnProjChoice()              self.__DoOnProjChoice()
253    
254          self.curProjPanel.Clear()          if self.curProjPanel is not None:
255                self.curProjPanel.Clear()
256    
257      def _OnSave(self, event):      def _OnSave(self, event):
258    
259          sel = self.availprojs.GetSelections()          sel = self.projection_list.selected_projections()
260          assert len(sel) == 1,  "button shouldn't be enabled"          assert len(sel) == 1,  "button shouldn't be enabled"
261    
262          proj, projfile = self.availprojs.GetClientData(sel[0])          proj, projfile = sel[0]
263    
264          assert proj is not None and projfile is not None          assert proj is not None and projfile is not None
265    
266          newproj = self.__GetProjection()          newproj = self.__GetProjection()
267    
268          if newproj is not None:          if newproj is not None:
269                # FIXME: we should only allow this for the user proj file.
270              projfile.Replace(proj, newproj)              projfile.Replace(proj, newproj)
271              try:              self.write_proj_file(projfile)
272                  write_proj_file(projfile)              self.projection_list.SelectProjection(newproj)
             except IOError, (errno, errstr):  
                 self.__ShowError(projfile.GetFilename(), errstr)  
             self.availprojs.SetClientData(sel[0], [newproj, projfile])  
   
             self.__FillAvailList( selectProj = newproj.GetName())  
273    
274      def _OnAddToList(self, event):      def _OnAddToList(self, event):
275    
276          proj = self.__GetProjection()          proj = self.__GetProjection()
277          if proj is not None:          if proj is not None:
278              self.__usrProjFile.Add(proj)              self.__usrProjFile.Add(proj)
279              try:              self.write_proj_file(self.__usrProjFile)
280                  write_proj_file(self.__usrProjFile)              self.projection_list.SelectProjection(proj)
             except IOError, (errno, errstr):  
                 self.__ShowError(self.__userProjFile.GetFilename(), errstr)  
281    
282              self.__FillAvailList( selectProj = proj.GetName())      def show_warnings(self, title, filename, warnings):
283            """Show the warnings (a list of strings) in a dialog
284    
285      def _OnProjAvail(self, event):          If the list is empty no dialog will be shown.
286          self.__DoOnProjAvail()          """
287            if warnings:
288                text = (_('Warnings when reading "%s":\n\n%s')
289                        % (filename, "\n\n".join(warnings)))
290                self.parent.RunMessageBox(title, text)
291    
292      def _OnImport(self, event):      def _OnImport(self, event):
293            """Handler for the 'Import' button
294    
295            Ask the user for a filename, read the projections from that file
296            add them to the user ProjFile object and write the user file
297            back to disk.
298            """
299          dlg = wxFileDialog(self, _("Import"), style = wxOPEN)          dlg = wxFileDialog(self, _("Import"), style = wxOPEN)
300    
301          if dlg.ShowModal() == wxID_OK:          if dlg.ShowModal() == wxID_OK:
302              path = dlg.GetPath()              path = dlg.GetPath()
303    
304                ThubanBeginBusyCursor()
305              try:              try:
306                  projFile = read_proj_file(path)                  try:
307                  for proj in projFile.GetProjections():                      projFile, warnings = read_proj_file(path)
308                      self.__usrProjFile.Add(proj)                  except IOError, (errno, errstr):
309                  write_proj_file(self.__usrProjFile)                      self.__ShowError(dlg.GetPath(), errstr)
310              except IOError, (errno, errstr):                  else:
311                  self.__ShowError(dlg.GetPath(), errstr)                      self.show_warnings(_("Warnings"), path, warnings)
312                        for proj in projFile.GetProjections():
313              self.__FillAvailList()                          self.__usrProjFile.Add(proj)
314                        self.write_proj_file(self.__usrProjFile)
315                finally:
316                    ThubanEndBusyCursor()
317          dlg.Destroy()          dlg.Destroy()
318    
319      def _OnExport(self, event):      def _OnExport(self, event):
320            """Handler for the 'Export' button.
321    
322          sel = self.availprojs.GetSelections()          Ask the user for a filename and write the selected projections
323            to that file.
324            """
325            sel = self.projection_list.selected_projections()
326          assert len(sel) != 0, "button should be disabled"          assert len(sel) != 0, "button should be disabled"
327    
328          dlg = wxFileDialog(self, _("Export"),          dlg = wxFileDialog(self, _("Export"), style=wxSAVE|wxOVERWRITE_PROMPT)
                         style = wxSAVE|wxOVERWRITE_PROMPT)  
329    
330          if dlg.ShowModal() == wxID_OK:          if dlg.ShowModal() == wxID_OK:
331              path = dlg.GetPath()              proj_file = ProjFile(dlg.GetPath())
332                for proj, pf in sel:
             projFile = ProjFile(path)  
   
             for i in sel:  
                 proj = self.availprojs.GetClientData(i)[CLIENT_PROJ]  
333                  if proj is not None:                  if proj is not None:
334                      projFile.Add(proj)                      proj_file.Add(proj)
335                self.write_proj_file(proj_file)
             try:  
                 write_proj_file(projFile)  
             except IOError, (errno, errstr):  
                 self.__ShowError(dlg.GetPath(), errstr)  
336    
337          dlg.Destroy()          dlg.Destroy()
338    
339      def _OnRemove(self, event):      def _OnRemove(self, event):
340            """Handler for the 'Remove' button
341    
342          sel = self.availprojs.GetSelections()          Remove any selected projection that came from the user's
343            ProjFile. If the user ProjFile was modified write it back to
344            disk.
345            """
346            sel = self.projection_list.selected_projections()
347          assert len(sel) != 0, "button should be disabled!"          assert len(sel) != 0, "button should be disabled!"
348    
349          #          modified = False
350          # remove the items backwards so the indices don't change          for proj, pf in sel:
351          #              if proj is not None and pf is self.__usrProjFile:
352          sel = list(sel)                  pf.Remove(proj)
353          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)  
354    
355          try:          if modified:
356              write_proj_file(projfile)              self.write_proj_file(self.__usrProjFile)
         except IOError, (errno, errstr):  
             self.__ShowError(projfile.GetFilename(), errstr)  
357    
358          self.__FillAvailList()      def _OnShowEPSG(self, event):
359            """Handler for the EVT_CHECKBOX events from the EPSG check button
360    
361          #          If the button is checked add the EPSG_PROJ_FILE to the list of
362          # this *could* produce incorrect results if the .proj files          projfiles shown by the projection list. Otherwise remove it
363          # change between the last list update and this selection          """
364          # because the list has been repopulated.          if self.check_epsg.IsChecked():
365          #              proj_files = [self.load_user_proj(),
366          if newselection != -1 and self.availprojs.GetCount() > 0:                            self.load_system_proj(DEFAULT_PROJ_FILE),
367              self.availprojs.SetSelection(newselection)                            self.load_system_proj(EPSG_PROJ_FILE)]
368            else:
369          self.__VerifyButtons()              proj_files = [self.load_user_proj(),
370                              self.load_system_proj(DEFAULT_PROJ_FILE)]
371            self.projection_list.SetProjFiles(proj_files)
372    
373      def _OnProjName(self, event):      def _OnProjName(self, event):
374          self.__VerifyButtons()          self.__VerifyButtons()
375    
376      def __ShowError(self, filename, errstr):      def __ShowError(self, filename, errstr):
377          wxMessageDialog(self,          wxMessageDialog(self,
378              _("The following error occured:\n") +              _("The following error occured:\n") +
379              filename + "\n" + errstr,              filename + "\n" + errstr,
380              _("Error"), wxOK | wxICON_ERROR).ShowModal()              _("Error"), wxOK | wxICON_ERROR).ShowModal()
381    
382      def __VerifyButtons(self):      def __VerifyButtons(self):
383          """Enable or disable the appropriate buttons based on the          """Update button sensitivity"""
         current state of the dialog.  
         """  
384    
385          sel = self.availprojs.GetSelections()          num_sel = self.projection_list.GetSelectedItemCount()
386    
387          self.button_import.Enable(True)          self.button_import.Enable(True)
388          self.button_export.Enable(True)          self.button_export.Enable(True)
389          self.button_save.Enable(True)          self.button_save.Enable(True)
390          self.button_remove.Enable(True)          self.button_remove.Enable(True)
391    
392          self.panel_edit.Enable(True)          self.edit_box.Enable(True)
393    
394          for ctrl in [self.button_import,          for ctrl in [self.button_import,
395                       self.button_export,                       self.button_export,
# Line 326  class ProjFrame(NonModalNonParentDialog) Line 398  class ProjFrame(NonModalNonParentDialog)
398                       self.button_add,                       self.button_add,
399                       self.projchoice,                       self.projchoice,
400                       self.projname,                       self.projname,
401                       self.panel_edit]:                       self.edit_box]:
402              ctrl.Enable(True)              ctrl.Enable(True)
403    
404          if self.curProjPanel is not None:          if self.curProjPanel is not None:
405              self.curProjPanel.Enable(True)              self.curProjPanel.Enable(True)
406    
407          if len(sel) == 0:          if num_sel == 0:
408              self.button_import.Enable(True)              self.button_import.Enable(True)
409              self.button_export.Enable(False)              self.button_export.Enable(False)
410              self.button_remove.Enable(False)              self.button_remove.Enable(False)
411              self.button_save.Enable(False)              self.button_save.Enable(False)
412    
413          elif len(sel) == 1:          elif num_sel == 1:
414    
415              proj, projFile = self.availprojs.GetClientData(sel[0])              selection = self.projection_list.selected_projections()
416                proj, projFile = selection[0]
417    
418              self.button_save.Enable(len(self.projname.GetValue()) > 0)              self.button_save.Enable(len(self.projname.GetValue()) > 0)
419              self.button_add.Enable(len(self.projname.GetValue()) > 0)              self.button_add.Enable(len(self.projname.GetValue()) > 0)
# Line 365  class ProjFrame(NonModalNonParentDialog) Line 438  class ProjFrame(NonModalNonParentDialog)
438                  self.button_save.Enable(False)                  self.button_save.Enable(False)
439    
440          else:          else:
441              self.panel_edit.Enable(False)              self.edit_box.Enable(False)
   
     def __DoOnProjAvail(self):  
442    
443          sel = self.availprojs.GetSelections()      def proj_selection_changed(self, projs):
444          if len(sel) == 1:          """Subscribed to the projection_list's PROJ_SELECTION_CHANGED message
   
             proj = self.availprojs.GetClientData(sel[0])[CLIENT_PROJ]  
             projfile = self.availprojs.GetClientData(sel[0])[CLIENT_PROJFILE]  
445    
446            Update the dialog to reflect the new selection.
447            """
448            if len(projs) == 0:
449                self.projfilepath.SetLabel(_("No Projections selected"))
450            elif len(projs) == 1:
451                proj, projfile = projs[0]
452              if proj is None:              if proj is None:
453                  # user selected <None>                  # user selected <None>
454                  self.projname.Clear()                  self.projname.Clear()
455                  self.projfilepath.SetLabel(_("Projection File: "))                  self.projfilepath.SetLabel("")
456              else:              else:
               
457                  if projfile is not None:                  if projfile is not None:
458                      self.projfilepath.SetLabel(_("Projection File: ") +                      filename = os.path.basename(projfile.GetFilename())
459                          os.path.basename(projfile.GetFilename()))                      self.projfilepath.SetLabel(_("Source of Projection: %s")
460                                                   % filename)
461                  else:                  else:
462                      # only None if the currently used projection is selected                      # only None if the currently used projection is selected
463                      self.projfilepath.SetLabel(_("Projection File: "))                      self.projfilepath.SetLabel("")
464    
465                  self.projname.SetValue(proj.GetName())                  self.projname.SetValue(proj.Label())
466    
467                  myProjType = proj.GetParameter("proj")                  myProjType = proj.GetParameter("proj")
468                  i = 0                  i = 0
469                  for projType, name, clazz in self.projPanels:                  for projType, name, cls in self.projection_panel_defs:
470                      if myProjType == projType:                      if myProjType == projType:
471                          self.projchoice.SetSelection(i)                          self.projchoice.Enable(True)
472                            self.projchoice.SetSelection(i + 1)
473                          self.__DoOnProjChoice()                          self.__DoOnProjChoice()
474    
475                          #                          #
# Line 404  class ProjFrame(NonModalNonParentDialog) Line 479  class ProjFrame(NonModalNonParentDialog)
479                          assert self.curProjPanel is not None                          assert self.curProjPanel is not None
480    
481                          self.curProjPanel.SetProjection(proj)                          self.curProjPanel.SetProjection(proj)
482                            break
483                      i += 1                      i += 1
484                    else:
485                        self.projchoice.Select(0)
486                        self.projchoice.Disable()
487                        self._show_proj_panel(UnknownProjPanel)
488                        assert self.curProjPanel is not None
489                        self.curProjPanel.SetProjection(proj)
490            else:
491                self.projfilepath.SetLabel(_("Multiple Projections selected"))
492    
493          self.__VerifyButtons()          self.__VerifyButtons()
494    
# Line 421  class ProjFrame(NonModalNonParentDialog) Line 505  class ProjFrame(NonModalNonParentDialog)
505          At the end of this method self.curProjPanel will not be None          At the end of this method self.curProjPanel will not be None
506          if there was a item selected.          if there was a item selected.
507          """          """
   
508          choice = self.projchoice          choice = self.projchoice
509    
510          sel = choice.GetSelection()          sel = choice.GetSelection()
511          if sel != -1:          if sel != -1:
512                proj_type = choice.GetClientData(sel)
513              clazz, obj = choice.GetClientData(sel)              for t, name, cls in self.projection_panel_defs:
514                    if t == proj_type:
515              if obj is None:                      self._show_proj_panel(cls)
516                  obj = clazz(self.panel_edit, self.receiver)                      break
517                  choice.SetClientData(sel, [clazz, obj])          # FIXME: what to do if sel == -1?
518    
519              if self.curProjPanel is not None:      def _show_proj_panel(self, panel_class):
520                  self.curProjPanel.Hide()          """Show the panel as the projection panel"""
521                  self.sizer_projctrls.Remove(self.curProjPanel)          if panel_class is UnknownProjPanel:
522                self.edit_box.Disable()
523              self.curProjPanel = obj              self.nbsizer.Activate(self.unknown_projection_panel)
524              self.curProjPanel.Show()              self.curProjPanel = self.unknown_projection_panel
525            else:
526              self.sizer_projctrls.Add(self.curProjPanel, 1,              self.edit_box.Enable(True)
527                  wxALL|wxEXPAND|wxADJUST_MINSIZE, 3)              self.unknown_projection_panel.Hide()
528              self.sizer_projctrls.Layout()              for panel in self.projection_panels:
529              self.Layout()                  if panel.__class__ is panel_class:
530              self.topBox.SetSizeHints(self)                      self.nbsizer.Activate(panel)
531                        self.curProjPanel = panel
532    
533      def __SetProjection(self):      def __SetProjection(self):
534          """Set the receiver's projection."""          """Set the receiver's projection."""
# Line 462  class ProjFrame(NonModalNonParentDialog) Line 546  class ProjFrame(NonModalNonParentDialog)
546          Could be None.          Could be None.
547          """          """
548    
549          sel = self.availprojs.GetSelections()          assert self.projection_list.GetSelectedItemCount() < 2, \
550          assert len(sel) < 2, "button should be disabled"                 "button should be disabled"
   
551    
552            sel = self.projection_list.selected_projections()
553          if len(sel) == 1:          if len(sel) == 1:
554              proj = self.availprojs.GetClientData(sel[0])[CLIENT_PROJ]              if sel[0][0] is None:
             if proj is None:  
555                  # <None> is selected                  # <None> is selected
556                  return None                  return None
557    
558          #          # self.curProjPanel should always contain the most relevant data
559          # self.curProjPanel should always contain the most          # for a projection
         # relevant data for a projection  
         #  
560          if self.curProjPanel is not None:          if self.curProjPanel is not None:
561              return Projection(self.curProjPanel.GetParameters(),              return Projection(self.curProjPanel.GetParameters(),
562                                self.projname.GetValue())                                self.projname.GetValue())
563    
564          return None          return None
565    
566      def __FillAvailList(self, selectCurrent = False, selectProj = None):      def load_user_proj(self):
567          """Populate the list of available projections.          """Return the user's ProjFile
           
         selectCurrent -- if True, select the projection used by  
                          the receiver, otherwise select nothing.  
         selectProj    -- if set, select the projection found under the  
                          specified name. This overwrites any other  
                          selection estimate.  
         """  
   
         self.availprojs.Clear()  
   
         #  
         # the list can never be empty. there will always be  
         # at least this one item  
         #  
         self.availprojs.Append("<None>", (None, None))  
568    
569          projfile = get_system_proj_files()          If the file has not yet been loaded by the dialog, load it first
570          projfile = projfile[0]          with get_user_proj_file and cache it in self.__usrProjFile.
         for proj in projfile.GetProjections():  
             self.availprojs.Append(proj.GetName(), [proj, projfile])  
         self.__sysProjFile = projfile  
571    
572          projfile = get_user_proj_files()          Show a busy cursor while loading the file.
573          projfile = projfile[0]          """
574          for proj in projfile.GetProjections():          if self.__usrProjFile is None:
575              self.availprojs.Append(proj.GetName(), [proj, projfile])              ThubanBeginBusyCursor()
576          self.__usrProjFile = projfile              try:
577                    projfile, warnings = get_user_proj_file()
578          #                  self.show_warnings(_("Warnings"), projfile.GetFilename(),
579          # We add the current projection to the list at last.                                     warnings)
580          # Since the list is resorted immediately a following FindString()                  self.__usrProjFile = projfile
581          # determines the index correctly.              finally:
582          #                  ThubanEndBusyCursor()
583          proj = self.receiver.GetProjection()          return self.__usrProjFile
584          if proj is not None:  
585              proj_item = _("%s (current)") % proj.GetName()      def load_system_proj(self, name):
586              self.availprojs.Append(proj_item, [proj, None])          """Load the system ProjFile with the given name.
587              if selectCurrent:  
588                  self.availprojs.SetSelection(          If the file has not been loaded yet, load it first with
589                          self.availprojs.FindString(proj_item)          get_system_proj_file and put it into the cache. The name is
590                      )          simply forwarded to get_system_proj_file.
         else:  
             if selectCurrent:  
                 self.availprojs.SetSelection(  
                         self.availprojs.FindString("<None>")  
                     )  
         if selectProj:  
             self.availprojs.SetSelection(  
                         self.availprojs.FindString(selectProj)  
                     )  
   
                   
   
     def __set_properties(self):  
   
         #self.availprojs.SetSelection(0)  
         self.projchoice.SetSelection(0)  
   
         self.__FillAvailList(selectCurrent = True)  
   
         self.projname.SetMaxLength(32)  
   
     def __do_layout(self):  
         # originally generated by wxGlade  
   
         self.topBox = wxBoxSizer(wxVERTICAL)  
         self.sizer_panel = wxBoxSizer(wxVERTICAL)  
         sizer_6 = wxBoxSizer(wxHORIZONTAL)  
         self.sizer_mainbttns = wxBoxSizer(wxHORIZONTAL)  
         self.sizer_mainctrls = wxBoxSizer(wxHORIZONTAL)  
         self.sizer_edit = wxStaticBoxSizer(wxStaticBox(self.panel_edit, -1, _("Edit")), wxHORIZONTAL)  
         sizer_11 = wxBoxSizer(wxVERTICAL)  
         self.sizer_projctrls = wxBoxSizer(wxVERTICAL)  
         sizer_14 = wxBoxSizer(wxHORIZONTAL)  
         sizer_13 = wxBoxSizer(wxHORIZONTAL)  
         sizer_15 = wxBoxSizer(wxVERTICAL)  
         sizer_15.Add(self.button_import, 0, wxALL, 4)  
         sizer_15.Add(self.button_export, 0, wxALL, 4)  
         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, wxEXPAND|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|wxALIGN_CENTER_VERTICAL, 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, wxEXPAND|wxALL, 4)  
         sizer_11.Add(self.button_add, 0, wxEXPAND|wxALL, 4)  
         sizer_11.Add(20, 20, 0, wxEXPAND, 0)  
         sizer_11.Add(self.button_save, 0, wxEXPAND|wxALL|wxALIGN_BOTTOM, 4)  
         self.sizer_edit.Add(sizer_11, 0, wxALL|wxEXPAND, 4)  
   
         sizer_6.Add(self.button_try, 0, wxRIGHT| wxEXPAND, 10)  
         sizer_6.Add(self.button_revert, 0, wxRIGHT| wxEXPAND, 10)  
         sizer_6.Add(self.button_ok, 0, wxRIGHT| wxEXPAND, 10)  
         sizer_6.Add(self.button_close, 0, wxRIGHT| wxEXPAND, 10)  
   
         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.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)  
591    
592          self.sizer_mainbttns.Add(sizer_6, 0,          Show a busy cursor while loading the file.
593              wxALL|wxEXPAND|wxADJUST_MINSIZE, 10)          """
594            if name not in self._sys_proj_files:
595                ThubanBeginBusyCursor()
596                try:
597                    projfile, warnings = get_system_proj_file(name)
598                    self.show_warnings(_("Warnings"), projfile.GetFilename(),
599                                       warnings)
600                    self._sys_proj_files[name] = projfile
601                finally:
602                    ThubanEndBusyCursor()
603            return self._sys_proj_files[name]
604    
605          self.topBox.Add(self.sizer_mainctrls, 1, wxALL|wxEXPAND, 4)      def write_proj_file(self, proj_file):
606          self.topBox.Add(self.sizer_mainbttns, 0, wxALIGN_RIGHT|wxBOTTOM, 0)          """Write the ProjFile object proj_file back to its file
607    
608          self.SetAutoLayout(1)          Show a busy cursor while writing and if an error occurs show a
609          self.SetSizer(self.topBox)          dialog with the error message.
610          self.topBox.Fit(self)          """
611          self.topBox.SetSizeHints(self)          try:
612          self.Layout()              ThubanBeginBusyCursor()
613                try:
614                    write_proj_file(proj_file)
615                finally:
616                    ThubanEndBusyCursor()
617            except IOError, (errno, errstr):
618                self.__ShowError(proj_file.GetFilename(), errstr)
619    
 # end of class ProjFrame  
620    
621    
622  class ProjPanel(wxPanel):  class ProjPanel(wxPanel):
# Line 631  class ProjPanel(wxPanel): Line 626  class ProjPanel(wxPanel):
626          wxPanel.__init__(self, parent, -1)          wxPanel.__init__(self, parent, -1)
627    
628          self.__ellps = wxChoice(self, -1)          self.__ellps = wxChoice(self, -1)
629          self.ellpsData = [("airy"  , _("Airy")),          self.ellpsData = [("", _("<Unknown>")),
630                              ("airy"  , _("Airy")),
631                            ("bessel", _("Bessel 1841")),                            ("bessel", _("Bessel 1841")),
632                            ("clrk66", _("Clarke 1866")),                            ("clrk66", _("Clarke 1866")),
633                            ("clrk80", _("Clarke 1880")),                            ("clrk80", _("Clarke 1880")),
634                            ("GRS80" , _("GRS 1980 (IUGG, 1980)")),                            ("GRS80" , _("GRS 1980 (IUGG, 1980)")),
635                            ("intl"  , _("International 1909 (Hayford)")),                            ("intl"  , _("International 1909 (Hayford)")),
# Line 679  class ProjPanel(wxPanel): Line 675  class ProjPanel(wxPanel):
675          self.__ellps.SetSelection(0)          self.__ellps.SetSelection(0)
676    
677      def GetParameters(self):      def GetParameters(self):
678          return ["ellps=" + self.__ellps.GetClientData(          ellps = self.__ellps.GetSelection()
679                                          self.__ellps.GetSelection())]          if ellps > 0:
680                return ["ellps=" + self.__ellps.GetClientData(ellps)]
681            return []
682    
683    
684  ID_TMPANEL_LAT = 4001  ID_TMPANEL_LAT = 4001
# Line 690  ID_TMPANEL_FALSE_NORTH = 4004 Line 688  ID_TMPANEL_FALSE_NORTH = 4004
688  ID_TMPANEL_SCALE = 4005  ID_TMPANEL_SCALE = 4005
689    
690  class UnknownProjPanel(ProjPanel):  class UnknownProjPanel(ProjPanel):
691    
692        """Panel for unknown projection types"""
693    
694      def __init__(self, parent, receiver):      def __init__(self, parent, receiver):
695          ProjPanel.__init__(self, parent)          ProjPanel.__init__(self, parent)
696    
697            self.__text = _("Thuban does not know the parameters\n"
698                            "for the current projection and cannot\n"
699                            "display a configuration panel.\n\n"
700                            "The unidentified set of parameters is:\n\n")
701    
702            self.__textbox = wxTextCtrl(self, -1, self.__text, size=(100,200),
703                                style=wxTE_READONLY|wxTE_MULTILINE|wxTE_LINEWRAP)
704          self._DoLayout()          self._DoLayout()
705    
706      def _DoLayout(self):      def _DoLayout(self):
707          sizer = wxBoxSizer(wxVERTICAL)          sizer = wxBoxSizer(wxVERTICAL)
708    
709          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.")))  
710    
711          ProjPanel._DoLayout(self, sizer)          ProjPanel._DoLayout(self, sizer)
712    
# Line 709  class UnknownProjPanel(ProjPanel): Line 714  class UnknownProjPanel(ProjPanel):
714          return "Unknown"          return "Unknown"
715    
716      def SetProjection(self, proj):      def SetProjection(self, proj):
717          pass          """Append the available parameters to the info text."""
718            text = self.__text
719            for param in proj.GetAllParameters():
720                text = text + '%s\n' % param
721            self.__textbox.SetValue(text)
722    
723      def GetParameters(self):      def GetParameters(self):
724          return None          return None
# Line 722  class TMPanel(ProjPanel): Line 731  class TMPanel(ProjPanel):
731    
732          self.__latitude = wxTextCtrl(self, ID_TMPANEL_LAT)          self.__latitude = wxTextCtrl(self, ID_TMPANEL_LAT)
733          self.__longitude = wxTextCtrl(self, ID_TMPANEL_LONG)          self.__longitude = wxTextCtrl(self, ID_TMPANEL_LONG)
         self.__scale = wxTextCtrl(self, ID_TMPANEL_SCALE)  
734          self.__falseEast = wxTextCtrl(self, ID_TMPANEL_FASLE_EAST)          self.__falseEast = wxTextCtrl(self, ID_TMPANEL_FASLE_EAST)
735          self.__falseNorth = wxTextCtrl(self, ID_TMPANEL_FALSE_NORTH)          self.__falseNorth = wxTextCtrl(self, ID_TMPANEL_FALSE_NORTH)
736            self.__scale = wxTextCtrl(self, ID_TMPANEL_SCALE)
737    
738          self._DoLayout()          self._DoLayout()
739    
740      def _DoLayout(self):      def _DoLayout(self):
741    
742          sizer = wxFlexGridSizer(4, 4, 0, 0)          sizer = wxFlexGridSizer(4, 2, 0, 0)
743          sizer.Add(wxStaticText(self, -1, _("Latitude:")), 0, wxALL, 4)          sizer.Add(wxStaticText(self, -1, _("Latitude:")), 0, wxALL, 4)
744          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)  
745          sizer.Add(wxStaticText(self, -1, _("Longitude:")), 0, wxALL, 4)          sizer.Add(wxStaticText(self, -1, _("Longitude:")), 0, wxALL, 4)
746          sizer.Add(self.__longitude, 0, wxALL, 4)          sizer.Add(self.__longitude, 0, wxALL, 4)
747            sizer.Add(wxStaticText(self, -1, _("False Easting:")), 0, wxALL, 4)
748            sizer.Add(self.__falseEast, 0, wxALL, 4)
749          sizer.Add(wxStaticText(self, -1, _("False Northing:")), 0, wxALL, 4)          sizer.Add(wxStaticText(self, -1, _("False Northing:")), 0, wxALL, 4)
750          sizer.Add(self.__falseNorth, 0, wxALL, 4)          sizer.Add(self.__falseNorth, 0, wxALL, 4)
751          sizer.Add(wxStaticText(self, -1, _("Scale Factor:")), 0, wxALL, 4)          sizer.Add(wxStaticText(self, -1, _("Scale Factor:")), 0, wxALL, 4)
# Line 859  class LCCPanel(ProjPanel): Line 868  class LCCPanel(ProjPanel):
868                    
869          self.__fspLatitude = wxTextCtrl(self, -1)          self.__fspLatitude = wxTextCtrl(self, -1)
870          self.__sspLatitude = wxTextCtrl(self, -1)          self.__sspLatitude = wxTextCtrl(self, -1)
         self.__originLat   = wxTextCtrl(self, -1)  
871          self.__meridian    = wxTextCtrl(self, -1)          self.__meridian    = wxTextCtrl(self, -1)
872            self.__originLat   = wxTextCtrl(self, -1)
873          self.__falseEast   = wxTextCtrl(self, -1)          self.__falseEast   = wxTextCtrl(self, -1)
874          self.__falseNorth  = wxTextCtrl(self, -1)          self.__falseNorth  = wxTextCtrl(self, -1)
875    

Legend:
Removed from v.1566  
changed lines
  Added in v.1933

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26