/[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 911 - (hide annotations)
Fri May 16 16:24:17 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: 33720 byte(s)
(MainWindow.ExportMap()): New. Added also new method_command to call
	ExportMap, with platform dependency (only __WXMSW__)

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