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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 923 - (hide annotations)
Mon May 19 09:12:25 2003 UTC (21 years, 9 months ago) by frank
Original Path: trunk/thuban/Thuban/UI/mainwindow.py
File MIME type: text/x-python
File size: 34112 byte(s)
Extended version information: Display Thuban, wxPython and Python version.

1 bh 535 # Copyright (C) 2001, 2002, 2003 by Intevation GmbH
2 bh 6 # Authors:
3     # Jan-Oliver Wagner <[email protected]>
4     # Bernhard Herzog <[email protected]>
5 frank 911 # Frank Koormann <[email protected]>
6 bh 6 #
7     # This program is free software under the GPL (>=v2)
8     # Read the file COPYING coming with Thuban for details.
9    
10     """
11     The main window
12     """
13    
14     __version__ = "$Revision$"
15    
16 jonathan 517 __ThubanVersion__ = "0.2" #"$THUBAN_0_2$"
17     #__BuildDate__ = "$Date$"
18    
19 bh 188 import os
20 bh 6
21     from wxPython.wx import *
22 frank 923 from wxPython.wx import __version__ as wxPython_version
23 bh 6
24     import Thuban
25 frank 923 import Thuban.version
26    
27 jan 374 from Thuban import _
28 bh 188 from Thuban.Model.session import create_empty_session
29 bh 6 from Thuban.Model.layer import Layer
30     from Thuban.Model.color import Color
31     from Thuban.Model.proj import Projection
32    
33     import view
34     import tree
35     import proj4dialog
36     import tableview, identifyview
37 jonathan 633 from Thuban.UI.classifier import Classifier
38 jonathan 550 import legend
39 bh 188 from menu import Menu
40 bh 6
41 bh 222 from context import Context
42 bh 357 from command import registry, Command, ToolCommand
43 bh 704 from messages import LAYER_SELECTED, SHAPES_SELECTED, VIEW_POSITION
44 bh 6
45 bh 704 from Thuban.UI.dock import DockFrame
46 jonathan 879 from Thuban.UI.join import JoinDialog
47 bh 6
48 jonathan 653 import resource
49 jonathan 563
50 jonathan 713 import projdialog
51 jonathan 653
52 bh 6
53 jonathan 713
54 jonathan 573 class MainWindow(DockFrame):
55 bh 6
56 bh 535 # Some messages that can be subscribed/unsubscribed directly through
57     # the MapCanvas come in fact from other objects. This is a map to
58     # map those messages to the names of the instance variables they
59     # actually come from. This delegation is implemented in the
60     # Subscribe and unsubscribed methods
61     delegated_messages = {LAYER_SELECTED: "canvas",
62     SHAPES_SELECTED: "canvas"}
63    
64     # Methods delegated to some instance variables. The delegation is
65     # implemented in the __getattr__ method.
66     delegated_methods = {"SelectLayer": "canvas",
67     "SelectShapes": "canvas",
68 jonathan 879 "SelectedShapes": "canvas",
69 bh 535 }
70    
71 bh 235 def __init__(self, parent, ID, title, application, interactor,
72 bh 238 initial_message = None, size = wxSize(-1, -1)):
73 jonathan 573 DockFrame.__init__(self, parent, ID, title, wxDefaultPosition, size)
74     #wxFrame.__init__(self, parent, ID, title, wxDefaultPosition, size)
75 bh 6
76 bh 227 self.application = application
77 bh 37
78 bh 6 self.CreateStatusBar()
79 bh 235 if initial_message:
80     self.SetStatusText(initial_message)
81 bh 6
82     self.identify_view = None
83    
84     self.init_ids()
85    
86 bh 191 # creat the menubar from the main_menu description
87 bh 188 self.SetMenuBar(self.build_menu_bar(main_menu))
88 bh 6
89 bh 191 # Similarly, create the toolbar from main_toolbar
90     toolbar = self.build_toolbar(main_toolbar)
91 bh 13 # call Realize to make sure that the tools appear.
92     toolbar.Realize()
93 bh 6
94 jonathan 563
95 bh 6 # Create the map canvas
96 bh 535 canvas = view.MapCanvas(self, -1)
97 bh 123 canvas.Subscribe(VIEW_POSITION, self.view_position_changed)
98 bh 535 canvas.Subscribe(SHAPES_SELECTED, self.identify_view_on_demand)
99 bh 6 self.canvas = canvas
100    
101 jonathan 573 self.SetMainWindow(self.canvas)
102    
103 jonathan 563 self.SetAutoLayout(True)
104    
105 bh 31 self.init_dialogs()
106    
107 jonathan 580 EVT_CLOSE(self, self._OnClose)
108 bh 6
109 bh 535 def Subscribe(self, channel, *args):
110     """Subscribe a function to a message channel.
111    
112     If channel is one of the delegated messages call the appropriate
113     object's Subscribe method. Otherwise do nothing.
114     """
115     if channel in self.delegated_messages:
116     object = getattr(self, self.delegated_messages[channel])
117     object.Subscribe(channel, *args)
118     else:
119     print "Trying to subscribe to unsupported channel %s" % channel
120    
121     def Unsubscribe(self, channel, *args):
122     """Unsubscribe a function from a message channel.
123    
124     If channel is one of the delegated messages call the appropriate
125     object's Unsubscribe method. Otherwise do nothing.
126     """
127     if channel in self.delegated_messages:
128     object = getattr(self, self.delegated_messages[channel])
129     object.Unsubscribe(channel, *args)
130    
131     def __getattr__(self, attr):
132     """If attr is one of the delegated methods return that method
133    
134     Otherwise raise AttributeError.
135     """
136     if attr in self.delegated_methods:
137     return getattr(getattr(self, self.delegated_methods[attr]), attr)
138     raise AttributeError(attr)
139    
140 bh 6 def init_ids(self):
141     """Initialize the ids"""
142     self.current_id = 6000
143     self.id_to_name = {}
144     self.name_to_id = {}
145 bh 193 self.events_bound = {}
146 bh 6
147     def get_id(self, name):
148     """Return the wxWindows id for the command named name.
149    
150     Create a new one if there isn't one yet"""
151     ID = self.name_to_id.get(name)
152     if ID is None:
153     ID = self.current_id
154     self.current_id = self.current_id + 1
155     self.name_to_id[name] = ID
156     self.id_to_name[ID] = name
157     return ID
158 bh 188
159 bh 193 def bind_command_events(self, command, ID):
160     """Bind the necessary events for the given command and ID"""
161     if not self.events_bound.has_key(ID):
162     # the events haven't been bound yet
163     EVT_MENU(self, ID, self.invoke_command)
164     if command.IsDynamic():
165     EVT_UPDATE_UI(self, ID, self.update_command_ui)
166    
167 bh 188 def build_menu_bar(self, menudesc):
168     """Build and return the menu bar from the menu description"""
169     menu_bar = wxMenuBar()
170    
171     for item in menudesc.items:
172     # here the items must all be Menu instances themselves
173     menu_bar.Append(self.build_menu(item), item.title)
174    
175     return menu_bar
176    
177     def build_menu(self, menudesc):
178 bh 314 """Return a wxMenu built from the menu description menudesc"""
179 bh 188 wxmenu = wxMenu()
180     last = None
181     for item in menudesc.items:
182     if item is None:
183     # a separator. Only add one if the last item was not a
184     # separator
185     if last is not None:
186     wxmenu.AppendSeparator()
187     elif isinstance(item, Menu):
188     # a submenu
189     wxmenu.AppendMenu(wxNewId(), item.title, self.build_menu(item))
190     else:
191     # must the name the name of a command
192     self.add_menu_command(wxmenu, item)
193     last = item
194     return wxmenu
195    
196 bh 191 def build_toolbar(self, toolbardesc):
197     """Build and return the main toolbar window from a toolbar description
198    
199     The parameter should be an instance of the Menu class but it
200     should not contain submenus.
201     """
202     toolbar = self.CreateToolBar(wxTB_3DBUTTONS)
203    
204     # set the size of the tools' bitmaps. Not needed on wxGTK, but
205     # on Windows, although it doesn't work very well there. It seems
206     # that only 16x16 icons are really supported on windows.
207     # We probably shouldn't hardwire the bitmap size here.
208     toolbar.SetToolBitmapSize(wxSize(24, 24))
209    
210     for item in toolbardesc.items:
211     if item is None:
212     toolbar.AddSeparator()
213     else:
214     # assume it's a string.
215     self.add_toolbar_command(toolbar, item)
216    
217     return toolbar
218    
219 bh 6 def add_menu_command(self, menu, name):
220     """Add the command with name name to the menu menu.
221    
222     If name is None, add a separator.
223     """
224     if name is None:
225     menu.AppendSeparator()
226     else:
227     command = registry.Command(name)
228     if command is not None:
229     ID = self.get_id(name)
230     menu.Append(ID, command.Title(), command.HelpText(),
231     command.IsCheckCommand())
232 bh 193 self.bind_command_events(command, ID)
233 bh 6 else:
234 jan 374 print _("Unknown command %s") % name
235 bh 6
236     def add_toolbar_command(self, toolbar, name):
237     """Add the command with name name to the toolbar toolbar.
238    
239     If name is None, add a separator.
240     """
241     # Assume that all toolbar commands are also menu commmands so
242     # that we don't have to add the event handlers here
243     if name is None:
244     toolbar.AddSeparator()
245     else:
246     command = registry.Command(name)
247     if command is not None:
248     ID = self.get_id(name)
249 jonathan 653 bitmap = resource.GetBitmapResource(command.Icon(),
250     wxBITMAP_TYPE_XPM)
251 bh 6 toolbar.AddTool(ID, bitmap,
252     shortHelpString = command.HelpText(),
253     isToggle = command.IsCheckCommand())
254 bh 193 self.bind_command_events(command, ID)
255 bh 6 else:
256 jan 374 print _("Unknown command %s") % name
257 bh 6
258 bh 281 def Context(self):
259     """Return the context object for a command invoked from this window
260     """
261     return Context(self.application, self.application.Session(), self)
262    
263 bh 6 def invoke_command(self, event):
264     name = self.id_to_name.get(event.GetId())
265     if name is not None:
266     command = registry.Command(name)
267 bh 281 command.Execute(self.Context())
268 bh 6 else:
269 jan 374 print _("Unknown command ID %d") % event.GetId()
270 bh 6
271     def update_command_ui(self, event):
272     #print "update_command_ui", self.id_to_name[event.GetId()]
273 bh 281 context = self.Context()
274 bh 6 command = registry.Command(self.id_to_name[event.GetId()])
275     if command is not None:
276 bh 357 sensitive = command.Sensitive(context)
277     event.Enable(sensitive)
278     if command.IsTool() and not sensitive and command.Checked(context):
279     # When a checked tool command is disabled deselect all
280     # tools. Otherwise the tool would remain active but it
281     # might lead to errors if the tools stays active. This
282     # problem occurred in GREAT-ER and this fixes it, but
283     # it's not clear to me whether this is really the best
284     # way to do it (BH, 20021206).
285     self.canvas.SelectTool(None)
286 bh 222 event.SetText(command.DynText(context))
287 bh 13 if command.IsCheckCommand():
288 bh 357 event.Check(command.Checked(context))
289 bh 6
290 bh 20 def RunMessageBox(self, title, text, flags = wxOK | wxICON_INFORMATION):
291 bh 181 """Run a modal message box with the given text, title and flags
292 bh 20 and return the result"""
293     dlg = wxMessageDialog(self, text, title, flags)
294 bh 316 dlg.CenterOnParent()
295 bh 20 result = dlg.ShowModal()
296     dlg.Destroy()
297     return result
298    
299 bh 31 def init_dialogs(self):
300     """Initialize the dialog handling"""
301     # The mainwindow maintains a dict mapping names to open
302     # non-modal dialogs. The dialogs are put into this dict when
303     # they're created and removed when they're closed
304     self.dialogs = {}
305    
306     def add_dialog(self, name, dialog):
307     if self.dialogs.has_key(name):
308 jan 374 raise RuntimeError(_("The Dialog named %s is already open") % name)
309 bh 31 self.dialogs[name] = dialog
310    
311     def dialog_open(self, name):
312     return self.dialogs.has_key(name)
313    
314     def remove_dialog(self, name):
315     del self.dialogs[name]
316    
317     def get_open_dialog(self, name):
318     return self.dialogs.get(name)
319    
320 bh 123 def view_position_changed(self):
321     pos = self.canvas.CurrentPosition()
322     if pos is not None:
323     text = "(%10.10g, %10.10g)" % pos
324     else:
325     text = ""
326 bh 321 self.set_position_text(text)
327    
328     def set_position_text(self, text):
329     """Set the statusbar text showing the current position.
330    
331     By default the text is shown in field 0 of the status bar.
332     Override this method in derived classes to put it into a
333     different field of the statusbar.
334     """
335 bh 123 self.SetStatusText(text)
336    
337 bh 58 def save_modified_session(self, can_veto = 1):
338     """If the current session has been modified, ask the user
339     whether to save it and do so if requested. Return the outcome of
340     the dialog (either wxID_OK, wxID_CANCEL or wxID_NO). If the
341     dialog wasn't run return wxID_NO.
342    
343     If the can_veto parameter is true (default) the dialog includes
344     a cancel button, otherwise not.
345     """
346 bh 227 if self.application.session.WasModified():
347 bh 58 flags = wxYES_NO | wxICON_QUESTION
348     if can_veto:
349     flags = flags | wxCANCEL
350 jan 374 result = self.RunMessageBox(_("Exit"),
351     _("The session has been modified."
352 bh 58 " Do you want to save it?"),
353     flags)
354     if result == wxID_YES:
355     self.SaveSession()
356     else:
357     result = wxID_NO
358     return result
359    
360 jonathan 487 def prepare_new_session(self):
361     for d in self.dialogs.values():
362     if not isinstance(d, tree.SessionTreeView):
363 jonathan 502 d.Close()
364 jonathan 487
365 bh 6 def NewSession(self):
366 bh 58 self.save_modified_session()
367 jonathan 487 self.prepare_new_session()
368 bh 227 self.application.SetSession(create_empty_session())
369 bh 6
370     def OpenSession(self):
371 bh 58 self.save_modified_session()
372 jonathan 879 dlg = wxFileDialog(self, _("Open Session"), ".", "",
373     "Thuban Session File (*.thuban)|*.thuban", wxOPEN)
374 bh 6 if dlg.ShowModal() == wxID_OK:
375 jonathan 487 self.prepare_new_session()
376 bh 227 self.application.OpenSession(dlg.GetPath())
377 bh 6 dlg.Destroy()
378    
379     def SaveSession(self):
380 bh 227 if self.application.session.filename == None:
381 jan 102 self.SaveSessionAs()
382 jonathan 487 else:
383     self.application.SaveSession()
384 bh 6
385     def SaveSessionAs(self):
386 jonathan 431 dlg = wxFileDialog(self, _("Save Session As"), ".", "",
387 jonathan 879 "Thuban Session File (*.thuban)|*.thuban",
388     wxSAVE|wxOVERWRITE_PROMPT)
389 bh 6 if dlg.ShowModal() == wxID_OK:
390 bh 227 self.application.session.SetFilename(dlg.GetPath())
391     self.application.SaveSession()
392 bh 6 dlg.Destroy()
393    
394     def Exit(self):
395 jonathan 621 self.Close(False)
396 bh 6
397 jonathan 580 def _OnClose(self, event):
398 bh 58 result = self.save_modified_session(can_veto = event.CanVeto())
399     if result == wxID_CANCEL:
400 bh 6 event.Veto()
401     else:
402 bh 307 # FIXME: it would be better to tie the unsubscription to
403     # wx's destroy event, but that isn't implemented for wxGTK
404     # yet.
405     self.canvas.Unsubscribe(VIEW_POSITION, self.view_position_changed)
406 jonathan 580 DockFrame._OnClose(self, event)
407 bh 6 self.Destroy()
408    
409     def SetMap(self, map):
410     self.canvas.SetMap(map)
411 jonathan 653 self.__SetTitle(map.Title())
412 bh 6
413 jonathan 768 dialog = self.FindRegisteredDock("legend")
414     if dialog is not None:
415     dialog.GetPanel().SetMap(self.Map())
416    
417 bh 310 def Map(self):
418     """Return the map displayed by this mainwindow"""
419 jonathan 563
420 bh 310 return self.canvas.Map()
421    
422 bh 622 def ToggleSessionTree(self):
423     """If the session tree is shown close it otherwise create a new tree"""
424 bh 37 name = "session_tree"
425     dialog = self.get_open_dialog(name)
426     if dialog is None:
427 bh 227 dialog = tree.SessionTreeView(self, self.application, name)
428 bh 37 self.add_dialog(name, dialog)
429 jonathan 512 dialog.Show(True)
430 bh 37 else:
431 bh 622 dialog.Close()
432 bh 37
433 bh 622 def SessionTreeShown(self):
434     """Return true iff the session tree is currently shown"""
435     return self.get_open_dialog("session_tree") is not None
436 jonathan 517
437 bh 6 def About(self):
438 jan 374 self.RunMessageBox(_("About"),
439 frank 923 _("Thuban %s\n"
440 jonathan 517 #"Build Date: %s\n"
441 frank 923 "using:\n"
442     " %s\n"
443     " %s\n\n"
444 jonathan 517 "Thuban is a program for\n"
445 bh 20 "exploring geographic data.\n"
446 jan 374 "Copyright (C) 2001-2003 Intevation GmbH.\n"
447 jonathan 517 "Thuban is licensed under the GNU GPL"
448 frank 923 % (Thuban.version.longversion,
449     "wxPython %s" % wxPython_version,
450     "Python %d.%d.%d" % sys.version_info[:3]
451     )),
452     # % __ThubanVersion__), #__BuildDate__)),
453 bh 20 wxOK | wxICON_INFORMATION)
454 bh 6
455     def AddLayer(self):
456 jan 374 dlg = wxFileDialog(self, _("Select a data file"), ".", "", "*.*",
457 bh 6 wxOPEN)
458     if dlg.ShowModal() == wxID_OK:
459     filename = dlg.GetPath()
460     title = os.path.splitext(os.path.basename(filename))[0]
461 bh 723 store = self.application.Session().OpenShapefile(filename)
462     layer = Layer(title, store)
463 bh 18 map = self.canvas.Map()
464     has_layers = map.HasLayers()
465 bh 20 try:
466     map.AddLayer(layer)
467     except IOError:
468     # the layer couldn't be opened
469 jan 374 self.RunMessageBox(_("Add Layer"),
470     _("Can't open the file '%s'.") % filename)
471 bh 20 else:
472     if not has_layers:
473 bh 535 # if we're adding a layer to an empty map, fit the
474 bh 20 # new map to the window
475     self.canvas.FitMapToWindow()
476 bh 6 dlg.Destroy()
477    
478     def RemoveLayer(self):
479     layer = self.current_layer()
480     if layer is not None:
481     self.canvas.Map().RemoveLayer(layer)
482    
483 bh 299 def CanRemoveLayer(self):
484     """Return true if the currently selected layer can be deleted.
485    
486 jonathan 621 If no layer is selected return False.
487 bh 299
488     The return value of this method determines whether the remove
489     layer command is sensitive in menu.
490     """
491     layer = self.current_layer()
492     if layer is not None:
493     return self.canvas.Map().CanRemoveLayer(layer)
494 jonathan 621 return False
495 bh 299
496 bh 6 def RaiseLayer(self):
497     layer = self.current_layer()
498     if layer is not None:
499     self.canvas.Map().RaiseLayer(layer)
500 bh 222
501 bh 6 def LowerLayer(self):
502     layer = self.current_layer()
503     if layer is not None:
504     self.canvas.Map().LowerLayer(layer)
505    
506     def current_layer(self):
507     """Return the currently selected layer.
508    
509     If no layer is selected, return None
510     """
511 bh 535 return self.canvas.SelectedLayer()
512 bh 6
513     def has_selected_layer(self):
514     """Return true if a layer is currently selected"""
515 bh 535 return self.canvas.HasSelectedLayer()
516 bh 6
517 jonathan 829 def has_selected_shapes(self):
518     """Return true if a shape is currently selected"""
519     return self.canvas.HasSelectedShapes()
520    
521 bh 6 def HideLayer(self):
522     layer = self.current_layer()
523     if layer is not None:
524     layer.SetVisible(0)
525    
526     def ShowLayer(self):
527     layer = self.current_layer()
528     if layer is not None:
529     layer.SetVisible(1)
530    
531     def LayerShowTable(self):
532     layer = self.current_layer()
533     if layer is not None:
534 bh 31 table = layer.table
535     name = "table_view" + str(id(table))
536     dialog = self.get_open_dialog(name)
537     if dialog is None:
538 bh 535 dialog = tableview.LayerTableFrame(self, name,
539     _("Table: %s") % layer.Title(),
540 bh 278 layer, table)
541 bh 31 self.add_dialog(name, dialog)
542     dialog.Show(true)
543     else:
544     # FIXME: bring dialog to front here
545     pass
546 bh 6
547 jonathan 729 def MapProjection(self):
548 bh 6
549 jonathan 729 name = "map_projection"
550 jonathan 713 dialog = self.get_open_dialog(name)
551    
552     if dialog is None:
553     map = self.canvas.Map()
554 jonathan 750 dialog = projdialog.ProjFrame(self, name,
555     _("Map Projection: %s") % map.Title(), map)
556 jonathan 713 self.add_dialog(name, dialog)
557     dialog.Show()
558     dialog.Raise()
559    
560 jonathan 729 def LayerProjection(self):
561    
562     layer = self.current_layer()
563    
564     name = "layer_projection" + str(id(layer))
565     dialog = self.get_open_dialog(name)
566    
567     if dialog is None:
568     map = self.canvas.Map()
569 jonathan 750 dialog = projdialog.ProjFrame(self, name,
570     _("Layer Projection: %s") % layer.Title(), layer)
571 jonathan 729 self.add_dialog(name, dialog)
572     dialog.Show()
573     dialog.Raise()
574    
575 jonathan 640 def LayerEditProperties(self):
576 jonathan 363
577 jonathan 487 #
578     # the menu option for this should only be available if there
579     # is a current layer, so we don't need to check if the
580     # current layer is None
581     #
582    
583     layer = self.current_layer()
584 jonathan 640 self.OpenLayerProperties(layer)
585 jonathan 550
586 jonathan 640 def OpenLayerProperties(self, layer, group = None):
587     name = "layer_properties" + str(id(layer))
588 jonathan 487 dialog = self.get_open_dialog(name)
589    
590     if dialog is None:
591 jonathan 633 dialog = Classifier(self, name, layer, group)
592 jonathan 487 self.add_dialog(name, dialog)
593     dialog.Show()
594 jonathan 573 dialog.Raise()
595 jonathan 487
596 jonathan 879 def LayerJoinTable(self):
597     print "LayerJoinTable"
598 jonathan 550
599 jonathan 879 def LayerUnjoinTable(self):
600     print "LayerUnjoinTable"
601    
602 jonathan 621 def ShowLegend(self):
603 bh 622 if not self.LegendShown():
604     self.ToggleLegend()
605    
606     def ToggleLegend(self):
607     """Show the legend if it's not shown otherwise hide it again"""
608 jonathan 550 name = "legend"
609 jonathan 573 dialog = self.FindRegisteredDock(name)
610 jonathan 550
611     if dialog is None:
612 jonathan 640 dialog = self.CreateDock(name, -1, _("Legend"), wxLAYOUT_LEFT)
613 jonathan 573 legend.LegendPanel(dialog, None, self)
614 jonathan 580 dialog.Dock()
615 bh 622 dialog.GetPanel().SetMap(self.Map())
616     dialog.Show()
617     else:
618     dialog.Show(not dialog.IsShown())
619 jonathan 563
620 bh 622 def LegendShown(self):
621     """Return true iff the legend is currently open"""
622     dialog = self.FindRegisteredDock("legend")
623     return dialog is not None and dialog.IsShown()
624 jonathan 563
625 jonathan 879 def TableOpen(self):
626     print "TableOpen"
627     dlg = wxFileDialog(self, _("Open Table"), ".", "",
628     "DBF Files (*.dbf)|*.dbf|" +
629     "CSV Files (*.csv)|*.csv|" +
630     "All Files (*.*)|*.*",
631     wxOPEN)
632     if dlg.ShowModal() == wxID_OK:
633     #self.application.session.OpenTable(dlg.GetPath())
634     pass
635    
636     dlg.Destroy()
637    
638     def TableClose(self):
639     print "TableClose"
640    
641     def TableShow(self):
642     print "TableShow"
643    
644     def TableHide(self):
645     print "TableHide"
646    
647     def TableJoin(self):
648     print "TableJoin"
649     dlg = JoinDialog(self, _("Join Tables"), self.application.session)
650     if dlg.ShowModal() == wxID_OK:
651     print "OK"
652    
653 bh 6 def ZoomInTool(self):
654     self.canvas.ZoomInTool()
655    
656     def ZoomOutTool(self):
657     self.canvas.ZoomOutTool()
658    
659     def PanTool(self):
660     self.canvas.PanTool()
661    
662     def IdentifyTool(self):
663     self.canvas.IdentifyTool()
664 bh 49 self.identify_view_on_demand(None, None)
665 bh 6
666     def LabelTool(self):
667     self.canvas.LabelTool()
668    
669     def FullExtent(self):
670     self.canvas.FitMapToWindow()
671    
672 jonathan 821 def FullLayerExtent(self):
673     self.canvas.FitLayerToWindow(self.current_layer())
674    
675 jonathan 829 def FullSelectionExtent(self):
676     self.canvas.FitSelectedToWindow()
677    
678 frank 911 def ExportMap(self):
679     self.canvas.Export()
680    
681 bh 6 def PrintMap(self):
682     self.canvas.Print()
683    
684 jonathan 653 def RenameMap(self):
685     dlg = wxTextEntryDialog(self, "Map Title: ", "Rename Map",
686     self.Map().Title())
687     if dlg.ShowModal() == wxID_OK:
688     title = dlg.GetValue()
689     if title != "":
690     self.Map().SetTitle(title)
691     self.__SetTitle(title)
692    
693     dlg.Destroy()
694    
695 bh 535 def identify_view_on_demand(self, layer, shapes):
696 bh 787 """Subscribed to the canvas' SHAPES_SELECTED message
697    
698     If the current tool is the identify tool, at least one shape is
699     selected and the identify dialog is not shown, show the dialog.
700     """
701     # If the selection has become empty we don't need to do
702     # anything. Otherwise it could happen that the dialog was popped
703     # up when the selection became empty, e.g. when a new selection
704     # is opened while the identify tool is active and dialog had
705     # been closed
706     if not shapes:
707     return
708    
709 bh 31 name = "identify_view"
710     if self.canvas.CurrentTool() == "IdentifyTool":
711     if not self.dialog_open(name):
712 bh 535 dialog = identifyview.IdentifyView(self, name)
713 bh 31 self.add_dialog(name, dialog)
714 jonathan 563 dialog.Show(True)
715 bh 31 else:
716 bh 33 # FIXME: bring dialog to front?
717 bh 31 pass
718 bh 6
719 jonathan 653 def __SetTitle(self, title):
720     self.SetTitle("Thuban - " + title)
721    
722 bh 6 #
723     # Define all the commands available in the main window
724     #
725    
726    
727     # Helper functions to define common command implementations
728     def call_method(context, methodname, *args):
729 bh 222 """Call the mainwindow's method methodname with args *args"""
730     apply(getattr(context.mainwindow, methodname), args)
731 bh 6
732 jan 110 def _method_command(name, title, method, helptext = "",
733 bh 622 icon = "", sensitive = None, checked = None):
734 bh 222 """Add a command implemented by a method of the mainwindow object"""
735 bh 6 registry.Add(Command(name, title, call_method, args=(method,),
736 jan 110 helptext = helptext, icon = icon,
737 bh 622 sensitive = sensitive, checked = checked))
738 jan 110
739 bh 270 def make_check_current_tool(toolname):
740     """Return a function that tests if the currently active tool is toolname
741    
742     The returned function can be called with the context and returns
743     true iff the currently active tool's name is toolname. It's directly
744     usable as the 'checked' callback of a command.
745     """
746     def check_current_tool(context, name=toolname):
747     return context.mainwindow.canvas.CurrentTool() == name
748     return check_current_tool
749    
750 bh 6 def _tool_command(name, title, method, toolname, helptext = "",
751 bh 310 icon = "", sensitive = None):
752 bh 6 """Add a tool command"""
753 bh 357 registry.Add(ToolCommand(name, title, call_method, args=(method,),
754     helptext = helptext, icon = icon,
755     checked = make_check_current_tool(toolname),
756     sensitive = sensitive))
757 bh 6
758     def _has_selected_layer(context):
759     """Return true if a layer is selected in the context"""
760 bh 222 return context.mainwindow.has_selected_layer()
761 bh 6
762 jonathan 829 def _has_selected_shapes(context):
763     """Return true if a layer is selected in the context"""
764     return context.mainwindow.has_selected_shapes()
765    
766 bh 299 def _can_remove_layer(context):
767     return context.mainwindow.CanRemoveLayer()
768    
769 jan 264 def _has_tree_window_shown(context):
770     """Return true if the tree window is shown"""
771 bh 622 return context.mainwindow.SessionTreeShown()
772 jan 264
773 bh 310 def _has_visible_map(context):
774     """Return true iff theres a visible map in the mainwindow.
775    
776     A visible map is a map with at least one visible layer."""
777     map = context.mainwindow.Map()
778     if map is not None:
779     for layer in map.Layers():
780     if layer.Visible():
781     return 1
782     return 0
783    
784 jonathan 550 def _has_legend_shown(context):
785     """Return true if the legend window is shown"""
786 bh 622 return context.mainwindow.LegendShown()
787 bh 310
788 jonathan 550
789 bh 6 # File menu
790 jan 374 _method_command("new_session", _("&New Session"), "NewSession")
791 jonathan 815 _method_command("open_session", _("&Open Session..."), "OpenSession")
792 jan 374 _method_command("save_session", _("&Save Session"), "SaveSession")
793 jonathan 815 _method_command("save_session_as", _("Save Session &As..."), "SaveSessionAs")
794 bh 622 _method_command("toggle_session_tree", _("Session &Tree"), "ToggleSessionTree",
795     checked = _has_tree_window_shown)
796     _method_command("toggle_legend", _("Legend"), "ToggleLegend",
797     checked = _has_legend_shown)
798 jan 374 _method_command("exit", _("E&xit"), "Exit")
799 bh 6
800     # Help menu
801 jonathan 815 _method_command("help_about", _("&About..."), "About")
802 bh 6
803    
804     # Map menu
805 jonathan 815 _method_command("map_projection", _("Pro&jection..."), "MapProjection")
806 bh 6
807 jan 374 _tool_command("map_zoom_in_tool", _("&Zoom in"), "ZoomInTool", "ZoomInTool",
808     helptext = _("Switch to map-mode 'zoom-in'"), icon = "zoom_in",
809 bh 310 sensitive = _has_visible_map)
810 jan 374 _tool_command("map_zoom_out_tool", _("Zoom &out"), "ZoomOutTool", "ZoomOutTool",
811     helptext = _("Switch to map-mode 'zoom-out'"), icon = "zoom_out",
812 bh 310 sensitive = _has_visible_map)
813 jan 374 _tool_command("map_pan_tool", _("&Pan"), "PanTool", "PanTool",
814     helptext = _("Switch to map-mode 'pan'"), icon = "pan",
815 bh 310 sensitive = _has_visible_map)
816 jan 374 _tool_command("map_identify_tool", _("&Identify"), "IdentifyTool",
817     "IdentifyTool",
818     helptext = _("Switch to map-mode 'identify'"), icon = "identify",
819 bh 310 sensitive = _has_visible_map)
820 jan 374 _tool_command("map_label_tool", _("&Label"), "LabelTool", "LabelTool",
821     helptext = _("Add/Remove labels"), icon = "label",
822 bh 310 sensitive = _has_visible_map)
823 jan 374 _method_command("map_full_extent", _("&Full extent"), "FullExtent",
824     helptext = _("Full Extent"), icon = "fullextent",
825 bh 310 sensitive = _has_visible_map)
826 jonathan 821 _method_command("layer_full_extent", _("&Full layer extent"), "FullLayerExtent",
827 jonathan 829 helptext = _("Full Layer Extent"), icon = "fulllayerextent",
828 jonathan 821 sensitive = _has_selected_layer)
829 jonathan 829 _method_command("selected_full_extent", _("&Full selection extent"), "FullSelectionExtent",
830     helptext = _("Full Selection Extent"), icon = "fullselextent",
831     sensitive = _has_selected_shapes)
832 frank 911 _method_command("map_export", _("E&xport"), "ExportMap",
833     helptext = _("Export the map to file"))
834 jan 374 _method_command("map_print", _("Prin&t"), "PrintMap",
835     helptext = _("Print the map"))
836 jonathan 815 _method_command("map_rename", _("&Rename..."), "RenameMap",
837 jonathan 653 helptext = _("Rename the map"))
838 jonathan 815 _method_command("layer_add", _("&Add Layer..."), "AddLayer",
839 jan 374 helptext = _("Add a new layer to active map"))
840     _method_command("layer_remove", _("&Remove Layer"), "RemoveLayer",
841     helptext = _("Remove selected layer(s)"),
842 bh 299 sensitive = _can_remove_layer)
843 jonathan 729
844     # Layer menu
845 jonathan 815 _method_command("layer_projection", _("Pro&jection..."), "LayerProjection",
846 jonathan 729 sensitive = _has_selected_layer)
847 jan 374 _method_command("layer_raise", _("&Raise"), "RaiseLayer",
848     helptext = _("Raise selected layer(s)"),
849 bh 6 sensitive = _has_selected_layer)
850 jan 374 _method_command("layer_lower", _("&Lower"), "LowerLayer",
851     helptext = _("Lower selected layer(s)"),
852 bh 6 sensitive = _has_selected_layer)
853 jan 374 _method_command("layer_show", _("&Show"), "ShowLayer",
854     helptext = _("Make selected layer(s) visible"),
855 bh 6 sensitive = _has_selected_layer)
856 jan 374 _method_command("layer_hide", _("&Hide"), "HideLayer",
857     helptext = _("Make selected layer(s) unvisible"),
858 bh 6 sensitive = _has_selected_layer)
859 jan 374 _method_command("layer_show_table", _("Show Ta&ble"), "LayerShowTable",
860     helptext = _("Show the selected layer's table"),
861 bh 6 sensitive = _has_selected_layer)
862 jonathan 815 _method_command("layer_properties", _("&Properties..."), "LayerEditProperties",
863 jonathan 363 sensitive = _has_selected_layer)
864 jonathan 879 _method_command("layer_jointable", _("&Join Table..."), "LayerJoinTable",
865     sensitive = _has_selected_layer)
866     _method_command("layer_unjointable", _("&Unjoin Table..."), "LayerUnjoinTable",
867     sensitive = _has_selected_layer)
868 bh 188
869 jonathan 879 # Table menu
870     _method_command("table_open", _("&Open..."), "TableOpen")
871     _method_command("table_close", _("&Close"), "TableClose")
872     _method_command("table_show", _("&Show"), "TableShow")
873     _method_command("table_hide", _("&Hide"), "TableHide")
874     _method_command("table_join", _("&Join..."), "TableJoin")
875    
876 frank 911 # Export only under Windows ...
877     map_menu = ["layer_add", "layer_remove", "map_rename",
878 bh 188 None,
879     "map_projection",
880     None,
881     "map_zoom_in_tool", "map_zoom_out_tool",
882 jonathan 829 "map_pan_tool",
883     "map_full_extent",
884     "layer_full_extent",
885     "selected_full_extent",
886 bh 188 None,
887 jonathan 815 "map_identify_tool", "map_label_tool",
888 bh 188 None,
889 bh 624 "toggle_legend",
890 frank 911 None]
891     if wxPlatform == '__WXMSW__':
892     map_menu.append("map_export")
893     map_menu.append("map_print")
894    
895     # the menu structure
896     main_menu = Menu("<main>", "<main>",
897     [Menu("file", _("&File"),
898     ["new_session", "open_session", None,
899     "save_session", "save_session_as", None,
900     "toggle_session_tree", None,
901     "exit"]),
902     Menu("map", _("&Map"), map_menu),
903 jan 374 Menu("layer", _("&Layer"),
904 jonathan 640 ["layer_raise", "layer_lower",
905 bh 188 None,
906     "layer_show", "layer_hide",
907     None,
908 jonathan 879 "layer_projection",
909     None,
910 jonathan 363 "layer_show_table",
911 jonathan 879 "layer_jointable",
912     "layer_unjointable",
913 jonathan 363 None,
914 jonathan 815 "layer_properties"]),
915 jonathan 879 Menu("table", _("&Table"),
916     ["table_open", "table_close",
917     None,
918     "table_show", "table_hide",
919     None,
920     "table_join"]),
921 jan 374 Menu("help", _("&Help"),
922 bh 188 ["help_about"])])
923 bh 191
924     # the main toolbar
925    
926     main_toolbar = Menu("<toolbar>", "<toolbar>",
927 frank 351 ["map_zoom_in_tool", "map_zoom_out_tool", "map_pan_tool",
928 jonathan 829 "map_full_extent",
929     "layer_full_extent",
930     "selected_full_extent",
931     None,
932 frank 351 "map_identify_tool", "map_label_tool"])

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26