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

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

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

revision 20 by bh, Tue Sep 4 16:44:31 2001 UTC revision 188 by bh, Tue May 28 12:38:45 2002 UTC
# Line 1  Line 1 
1  # Copyright (C) 2001 by Intevation GmbH  # Copyright (C) 2001, 2002 by Intevation GmbH
2  # Authors:  # Authors:
3  # Jan-Oliver Wagner <[email protected]>  # Jan-Oliver Wagner <[email protected]>
4  # Bernhard Herzog <[email protected]>  # Bernhard Herzog <[email protected]>
# Line 12  The main window Line 12  The main window
12    
13  __version__ = "$Revision$"  __version__ = "$Revision$"
14    
15  import sys, os  import os
16    
17  from wxPython.wx import *  from wxPython.wx import *
18    
19  import Thuban  import Thuban
20  from Thuban.Model.session import Session  from Thuban.Model.session import create_empty_session
 from Thuban.Model.map import Map  
21  from Thuban.Model.layer import Layer  from Thuban.Model.layer import Layer
22  from Thuban.Model.color import Color  from Thuban.Model.color import Color
23  from Thuban.Model.proj import Projection  from Thuban.Model.proj import Projection
# Line 27  import view Line 26  import view
26  import tree  import tree
27  import proj4dialog  import proj4dialog
28  import tableview, identifyview  import tableview, identifyview
29    from menu import Menu
30    
31  import main  import main
32  from command import registry, Command  from command import registry, Command
33    from messages import SELECTED_SHAPE, VIEW_POSITION
34    
35    
36  # the directory where the toolbar icons are stored  # the directory where the toolbar icons are stored
# Line 39  bitmapext = ".xpm" Line 40  bitmapext = ".xpm"
40    
41  class MainWindow(wxFrame):  class MainWindow(wxFrame):
42    
43      def __init__(self, parent, ID):      def __init__(self, parent, ID, interactor):
44          wxFrame.__init__(self, parent, ID, 'Thuban',          wxFrame.__init__(self, parent, ID, 'Thuban',
45                           wxDefaultPosition, wxSize(400, 300))                           wxDefaultPosition, wxSize(400, 300))
46    
47            self.interactor = interactor
48    
49          self.CreateStatusBar()          self.CreateStatusBar()
50          self.SetStatusText("This is the wxPython-based "          self.SetStatusText("This is the wxPython-based "
51                        "Graphical User Interface for exploring geographic data")                        "Graphical User Interface for exploring geographic data")
# Line 51  class MainWindow(wxFrame): Line 54  class MainWindow(wxFrame):
54    
55          self.init_ids()          self.init_ids()
56    
57          menuBar = wxMenuBar()          #main_menu.print_menu()
58            self.SetMenuBar(self.build_menu_bar(main_menu))
         menu = wxMenu()  
         menuBar.Append(menu, "&File");  
         for name in ["new_session", "open_session", None,  
                      "save_session", "save_session_as", None,  
                      "exit"]:  
             self.add_menu_command(menu, name)  
   
         menu = wxMenu()  
         menuBar.Append(menu, "&Map");  
         for name in ["map_projection",  
                      None,  
                      "map_zoom_in_tool", "map_zoom_out_tool", "map_pan_tool",  
                      "map_identify_tool", "map_label_tool",  
                      None,  
                      "map_full_extent",  
                      None,  
                      "map_print"]:  
             self.add_menu_command(menu, name)  
   
         menu = wxMenu()  
         menuBar.Append(menu, "&Layer");  
         for name in ["layer_add", "layer_remove",  
                      None,  
                      "layer_fill_color", "layer_transparent_fill",  
                      "layer_ourline_color", "layer_no_outline",  
                      None,  
                      "layer_raise", "layer_lower",  
                      None,  
                      "layer_show", "layer_hide",  
                      None,  
                      "layer_show_table"]:  
             self.add_menu_command(menu, name)  
   
         menu = wxMenu()  
         menuBar.Append(menu, "&Help");  
         self.add_menu_command(menu, "help_about")  
   
         self.SetMenuBar(menuBar)  
59    
60          # toolbar          # toolbar
61          toolbar = self.CreateToolBar(wxTB_3DBUTTONS)          toolbar = self.CreateToolBar(wxTB_3DBUTTONS)
62    
63            # set the size of the tools' bitmaps. Not needed on wxGTK, but
64            # on Windows. We probably shouldn't hardwire the bitmap size
65            # here
66            toolbar.SetToolBitmapSize(wxSize(24, 24))
67    
68          for name in ["map_zoom_in_tool", "map_zoom_out_tool", "map_pan_tool",          for name in ["map_zoom_in_tool", "map_zoom_out_tool", "map_pan_tool",
69                       "map_identify_tool", "map_label_tool"]:                       "map_identify_tool", "map_label_tool", "map_full_extent"]:
70              self.add_toolbar_command(toolbar, name)              self.add_toolbar_command(toolbar, name)
71          # call Realize to make sure that the tools appear.          # call Realize to make sure that the tools appear.
72          toolbar.Realize()          toolbar.Realize()
73    
74          # Create the map canvas          # Create the map canvas
75          canvas = view.MapCanvas(self, -1)          canvas = view.MapCanvas(self, -1, interactor)
76            canvas.Subscribe(VIEW_POSITION, self.view_position_changed)
77          self.canvas = canvas          self.canvas = canvas
78    
79            self.init_dialogs()
80    
81            interactor.Subscribe(SELECTED_SHAPE, self.identify_view_on_demand)
82    
83          EVT_CLOSE(self, self.OnClose)          EVT_CLOSE(self, self.OnClose)
84    
85      def init_ids(self):      def init_ids(self):
# Line 123  class MainWindow(wxFrame): Line 99  class MainWindow(wxFrame):
99              self.name_to_id[name] = ID              self.name_to_id[name] = ID
100              self.id_to_name[ID] = name              self.id_to_name[ID] = name
101          return ID          return ID
102            
103        def build_menu_bar(self, menudesc):
104            """Build and return the menu bar from the menu description"""
105            menu_bar = wxMenuBar()
106    
107            for item in menudesc.items:
108                # here the items must all be Menu instances themselves
109                menu_bar.Append(self.build_menu(item), item.title)
110    
111            return menu_bar
112    
113        def build_menu(self, menudesc):
114            """Build and return a wxMenu from a menudescription"""
115            wxmenu = wxMenu()
116            last = None
117            for item in menudesc.items:
118                # here the items must all be Menu instances themselves
119                if item is None:
120                    # a separator. Only add one if the last item was not a
121                    # separator
122                    if last is not None:
123                        wxmenu.AppendSeparator()
124                elif isinstance(item, Menu):
125                    # a submenu
126                    wxmenu.AppendMenu(wxNewId(), item.title, self.build_menu(item))
127                else:
128                    # must the name the name of a command
129                    self.add_menu_command(wxmenu, item)
130                last = item
131            return wxmenu
132    
133      def add_menu_command(self, menu, name):      def add_menu_command(self, menu, name):
134          """Add the command with name name to the menu menu.          """Add the command with name name to the menu menu.
135    
# Line 182  class MainWindow(wxFrame): Line 188  class MainWindow(wxFrame):
188                  event.Check(command.Checked(self))                  event.Check(command.Checked(self))
189    
190      def RunMessageBox(self, title, text, flags = wxOK | wxICON_INFORMATION):      def RunMessageBox(self, title, text, flags = wxOK | wxICON_INFORMATION):
191          """Run a modla message box with the given text, title and flags          """Run a modal message box with the given text, title and flags
192          and return the result"""          and return the result"""
193          dlg = wxMessageDialog(self, text, title, flags)          dlg = wxMessageDialog(self, text, title, flags)
194          result = dlg.ShowModal()          result = dlg.ShowModal()
195          dlg.Destroy()          dlg.Destroy()
196          return result          return result
197    
198        def init_dialogs(self):
199            """Initialize the dialog handling"""
200            # The mainwindow maintains a dict mapping names to open
201            # non-modal dialogs. The dialogs are put into this dict when
202            # they're created and removed when they're closed
203            self.dialogs = {}
204    
205        def add_dialog(self, name, dialog):
206            if self.dialogs.has_key(name):
207                raise RuntimeError("The Dialog named %s is already open" % name)
208            self.dialogs[name] = dialog
209    
210        def dialog_open(self, name):
211            return self.dialogs.has_key(name)
212    
213        def remove_dialog(self, name):
214            del self.dialogs[name]
215    
216        def get_open_dialog(self, name):
217            return self.dialogs.get(name)
218    
219        def view_position_changed(self):
220            pos = self.canvas.CurrentPosition()
221            if pos is not None:
222                text = "(%10.10g, %10.10g)" % pos
223            else:
224                text = ""
225            self.SetStatusText(text)
226    
227        def save_modified_session(self, can_veto = 1):
228            """If the current session has been modified, ask the user
229            whether to save it and do so if requested. Return the outcome of
230            the dialog (either wxID_OK, wxID_CANCEL or wxID_NO). If the
231            dialog wasn't run return wxID_NO.
232    
233            If the can_veto parameter is true (default) the dialog includes
234            a cancel button, otherwise not.
235            """
236            if main.app.session.WasModified():
237                flags = wxYES_NO | wxICON_QUESTION
238                if can_veto:
239                    flags = flags | wxCANCEL
240                result = self.RunMessageBox("Exit",
241                                            ("The session has been modified."
242                                             " Do you want to save it?"),
243                                            flags)
244                if result == wxID_YES:
245                    self.SaveSession()
246            else:
247                result = wxID_NO
248            return result
249    
250      def NewSession(self):      def NewSession(self):
251          session = Session("")          self.save_modified_session()
252          session.AddMap(Map(""))          main.app.SetSession(create_empty_session())
         main.app.SetSession(session)  
253    
254      def OpenSession(self):      def OpenSession(self):
255            self.save_modified_session()
256          dlg = wxFileDialog(self, "Select a session file", ".", "",          dlg = wxFileDialog(self, "Select a session file", ".", "",
257                             "*.session", wxOPEN)                             "*.thuban", wxOPEN)
258          if dlg.ShowModal() == wxID_OK:          if dlg.ShowModal() == wxID_OK:
259              main.app.OpenSession(dlg.GetPath())              main.app.OpenSession(dlg.GetPath())
260          dlg.Destroy()          dlg.Destroy()
261    
262      def SaveSession(self):      def SaveSession(self):
263            if main.app.session.filename == None:
264                self.SaveSessionAs()
265          main.app.SaveSession()          main.app.SaveSession()
266    
267      def SaveSessionAs(self):      def SaveSessionAs(self):
268          dlg = wxFileDialog(self, "Enter a filename for session", ".", "",          dlg = wxFileDialog(self, "Enter a filename for session", ".", "",
269                             "*.session", wxOPEN)                             "*.thuban", wxOPEN)
270          if dlg.ShowModal() == wxID_OK:          if dlg.ShowModal() == wxID_OK:
271              main.app.session.SetFilename(dlg.GetPath())              main.app.session.SetFilename(dlg.GetPath())
272              main.app.SaveSession()              main.app.SaveSession()
# Line 216  class MainWindow(wxFrame): Line 276  class MainWindow(wxFrame):
276          self.Close(false)          self.Close(false)
277    
278      def OnClose(self, event):      def OnClose(self, event):
279          veto = 0          result = self.save_modified_session(can_veto = event.CanVeto())
280          if main.app.session.WasModified():          if result == wxID_CANCEL:
             flags = wxYES_NO | wxICON_QUESTION  
             if event.CanVeto():  
                 flags = flags | wxCANCEL  
             result = self.RunMessageBox("Exit",  
                                         ("The session has been modified."  
                                          " Do you want to save it?"),  
                                         flags)  
             if result == wxID_YES:  
                 self.SaveSession()  
             elif result == wxID_CANCEL:  
                 veto = 1  
   
         if veto:  
281              event.Veto()              event.Veto()
282          else:          else:
283              self.Destroy()              self.Destroy()
# Line 238  class MainWindow(wxFrame): Line 285  class MainWindow(wxFrame):
285      def SetMap(self, map):      def SetMap(self, map):
286          self.canvas.SetMap(map)          self.canvas.SetMap(map)
287    
288        def ShowSessionTree(self):
289            name = "session_tree"
290            dialog = self.get_open_dialog(name)
291            if dialog is None:
292                dialog = tree.SessionTreeView(self, main.app, name)
293                self.add_dialog(name, dialog)
294                dialog.Show(true)
295            else:
296                # FIXME: bring dialog to front here
297                pass
298    
299      def About(self):      def About(self):
300          self.RunMessageBox("About",          self.RunMessageBox("About",
301                             ("Thuban is a program for\n"                             ("Thuban is a program for\n"
# Line 247  class MainWindow(wxFrame): Line 305  class MainWindow(wxFrame):
305                             wxOK | wxICON_INFORMATION)                             wxOK | wxICON_INFORMATION)
306    
307      def AddLayer(self):      def AddLayer(self):
308          dlg = wxFileDialog(self, "Select a session file", ".", "", "*.*",          dlg = wxFileDialog(self, "Select a data file", ".", "", "*.*",
309                             wxOPEN)                             wxOPEN)
310          if dlg.ShowModal() == wxID_OK:          if dlg.ShowModal() == wxID_OK:
311              filename = dlg.GetPath()              filename = dlg.GetPath()
# Line 288  class MainWindow(wxFrame): Line 346  class MainWindow(wxFrame):
346    
347          If no layer is selected, return None          If no layer is selected, return None
348          """          """
349          tree = main.app.tree.tree          return self.interactor.SelectedLayer()
         layer = tree.GetPyData(tree.GetSelection())  
         if isinstance(layer, Layer):  
             return layer  
         return None  
350    
351      def has_selected_layer(self):      def has_selected_layer(self):
352          """Return true if a layer is currently selected"""          """Return true if a layer is currently selected"""
353          tree = main.app.tree.tree          return self.interactor.HasSelectedLayer()
         layer = tree.GetPyData(tree.GetSelection())  
         return isinstance(layer, Layer)  
354    
355      def choose_color(self):      def choose_color(self):
356          """Run the color selection dialog and return the selected color.          """Run the color selection dialog and return the selected color.
# Line 353  class MainWindow(wxFrame): Line 405  class MainWindow(wxFrame):
405      def LayerShowTable(self):      def LayerShowTable(self):
406          layer = self.current_layer()          layer = self.current_layer()
407          if layer is not None:          if layer is not None:
408              tv = tableview.TableFrame(self, layer.table)              table = layer.table
409              tv.Show(true)              name = "table_view" + str(id(table))
410                dialog = self.get_open_dialog(name)
411                if dialog is None:
412                    dialog = tableview.TableFrame(self, self.interactor, name,
413                                                  "Table: %s" % layer.Title(),
414                                                  layer, table)
415                    self.add_dialog(name, dialog)
416                    dialog.Show(true)
417                else:
418                    # FIXME: bring dialog to front here
419                    pass
420    
421      def Projection(self):      def Projection(self):
422          map = self.canvas.Map()          map = self.canvas.Map()
423          proj = map.projection          proj = map.projection
424          if proj is None:          if proj is None:
425              proj4Dlg = proj4dialog.Proj4Dialog(NULL, None)              proj4Dlg = proj4dialog.Proj4Dialog(NULL, None, map.BoundingBox())
426          else:          else:
427              proj4Dlg = proj4dialog.Proj4Dialog(NULL, map.projection.params)              proj4Dlg = proj4dialog.Proj4Dialog(NULL, map.projection.params,
428                                                   map.BoundingBox())
429          if proj4Dlg.ShowModal() == wxID_OK:          if proj4Dlg.ShowModal() == wxID_OK:
430              params = proj4Dlg.GetParams()              params = proj4Dlg.GetParams()
431              if params is not None:              if params is not None:
# Line 382  class MainWindow(wxFrame): Line 445  class MainWindow(wxFrame):
445          self.canvas.PanTool()          self.canvas.PanTool()
446    
447      def IdentifyTool(self):      def IdentifyTool(self):
         if self.identify_view is None:  
             self.identify_view = identifyview.IdentifyView(self, main.app)  
             self.identify_view.Show(true)  
448          self.canvas.IdentifyTool()          self.canvas.IdentifyTool()
449            self.identify_view_on_demand(None, None)
450    
451      def LabelTool(self):      def LabelTool(self):
452          self.canvas.LabelTool()          self.canvas.LabelTool()
# Line 396  class MainWindow(wxFrame): Line 457  class MainWindow(wxFrame):
457      def PrintMap(self):      def PrintMap(self):
458          self.canvas.Print()          self.canvas.Print()
459    
460        def identify_view_on_demand(self, layer, shape):
461            name = "identify_view"
462            if self.canvas.CurrentTool() == "IdentifyTool":
463                if not self.dialog_open(name):
464                    dialog = identifyview.IdentifyView(self, self.interactor, name)
465                    self.add_dialog(name, dialog)
466                    dialog.Show(true)
467                else:
468                    # FIXME: bring dialog to front?
469                    pass
470    
471  #  #
472  # Define all the commands available in the main window  # Define all the commands available in the main window
# Line 407  def call_method(context, methodname, *ar Line 478  def call_method(context, methodname, *ar
478      """Call the context's method methodname with args *args"""      """Call the context's method methodname with args *args"""
479      apply(getattr(context, methodname), args)      apply(getattr(context, methodname), args)
480    
481  def _method_command(name, title, method, helptext = "", sensitive = None):  def _method_command(name, title, method, helptext = "",
482                        icon = "", sensitive = None):
483      """Add a command implemented by a method of the context object"""      """Add a command implemented by a method of the context object"""
484      registry.Add(Command(name, title, call_method, args=(method,),      registry.Add(Command(name, title, call_method, args=(method,),
485                           helptext = helptext, sensitive = sensitive))                           helptext = helptext, icon = icon,
486                             sensitive = sensitive))
487    
488  def _tool_command(name, title, method, toolname, helptext = "",  def _tool_command(name, title, method, toolname, helptext = "",
489                    icon = ""):                    icon = ""):
490      """Add a tool command"""      """Add a tool command"""
# Line 429  _method_command("new_session", "&New Ses Line 503  _method_command("new_session", "&New Ses
503  _method_command("open_session", "&Open Session", "OpenSession")  _method_command("open_session", "&Open Session", "OpenSession")
504  _method_command("save_session", "&Save Session", "SaveSession")  _method_command("save_session", "&Save Session", "SaveSession")
505  _method_command("save_session_as", "Save Session &As", "SaveSessionAs")  _method_command("save_session_as", "Save Session &As", "SaveSessionAs")
506    _method_command("show_session_tree", "Show Session &Tree", "ShowSessionTree")
507  _method_command("exit", "&Exit", "Exit")  _method_command("exit", "&Exit", "Exit")
508    
509  # Help menu  # Help menu
# Line 448  _tool_command("map_identify_tool", "&Ide Line 523  _tool_command("map_identify_tool", "&Ide
523                helptext = "Switch to map-mode 'identify'", icon = "identify")                helptext = "Switch to map-mode 'identify'", icon = "identify")
524  _tool_command("map_label_tool", "&Label", "LabelTool", "LabelTool",  _tool_command("map_label_tool", "&Label", "LabelTool", "LabelTool",
525                helptext = "Add/Remove labels", icon = "label")                helptext = "Add/Remove labels", icon = "label")
526  _method_command("map_full_extent", "&Full extent", "FullExtent")  _method_command("map_full_extent", "&Full extent", "FullExtent",
527                   helptext = "Full Extent", icon = "fullextent")
528  _method_command("map_print", "Prin&t", "PrintMap", helptext = "Print the map")  _method_command("map_print", "Prin&t", "PrintMap", helptext = "Print the map")
529    
530  # Layer menu  # Layer menu
531  _method_command("layer_add", "&Add", "AddLayer",  _method_command("layer_add", "&Add Layer", "AddLayer",
532                  helptext = "Add a new layer to active map")                  helptext = "Add a new layer to active map")
533  _method_command("layer_remove", "&Remove", "RemoveLayer",  _method_command("layer_remove", "&Remove Layer", "RemoveLayer",
534                  helptext = "Remove selected layer(s)",                  helptext = "Remove selected layer(s)",
535                  sensitive = _has_selected_layer)                  sensitive = _has_selected_layer)
536  _method_command("layer_fill_color", "&Fill Color", "LayerFillColor",  _method_command("layer_fill_color", "&Fill Color", "LayerFillColor",
# Line 464  _method_command("layer_transparent_fill" Line 540  _method_command("layer_transparent_fill"
540                  "LayerTransparentFill",                  "LayerTransparentFill",
541                  helptext = "Do not fill the selected layer(s)",                  helptext = "Do not fill the selected layer(s)",
542                  sensitive = _has_selected_layer)                  sensitive = _has_selected_layer)
543  _method_command("layer_ourline_color", "&Outline Color", "LayerOutlineColor",  _method_command("layer_outline_color", "&Outline Color", "LayerOutlineColor",
544                  helptext = "Set the outline color of selected layer(s)",                  helptext = "Set the outline color of selected layer(s)",
545                  sensitive = _has_selected_layer)                  sensitive = _has_selected_layer)
546  _method_command("layer_no_outline", "&No Outline", "LayerNoOutline",  _method_command("layer_no_outline", "&No Outline", "LayerNoOutline",
# Line 485  _method_command("layer_hide", "&Hide", " Line 561  _method_command("layer_hide", "&Hide", "
561  _method_command("layer_show_table", "Show Ta&ble", "LayerShowTable",  _method_command("layer_show_table", "Show Ta&ble", "LayerShowTable",
562                  helptext = "Show the selected layer's table",                  helptext = "Show the selected layer's table",
563                  sensitive = _has_selected_layer)                  sensitive = _has_selected_layer)
564    
565    
566    # the menu structure
567    main_menu = Menu("<main>", "<main>",
568                     [Menu("file", "&File",
569                           ["new_session", "open_session", None,
570                            "save_session", "save_session_as", None,
571                            "show_session_tree", None,
572                            "exit"]),
573                      Menu("map", "&Map",
574                           ["layer_add", "layer_remove",
575                            None,
576                            "map_projection",
577                            None,
578                            "map_zoom_in_tool", "map_zoom_out_tool",
579                            "map_pan_tool", "map_identify_tool", "map_label_tool",
580                            None,
581                            "map_full_extent",
582                            None,
583                            "map_print"]),
584                      Menu("layer", "&Layer",
585                           ["layer_fill_color", "layer_transparent_fill",
586                            "layer_outline_color", "layer_no_outline",
587                            None,
588                            "layer_raise", "layer_lower",
589                            None,
590                            "layer_show", "layer_hide",
591                            None,
592                            "layer_show_table"]),
593                      Menu("help", "&Help",
594                           ["help_about"])])

Legend:
Removed from v.20  
changed lines
  Added in v.188

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26