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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 911 - (show 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 # Copyright (C) 2001, 2002, 2003 by Intevation GmbH
2 # Authors:
3 # Jan-Oliver Wagner <[email protected]>
4 # Bernhard Herzog <[email protected]>
5 # Frank Koormann <[email protected]>
6 #
7 # This program is free software under the GPL (>=v2)
8 # Read the file COPYING coming with Thuban for details.
9
10 """
11 The main window
12 """
13
14 __version__ = "$Revision$"
15
16 __ThubanVersion__ = "0.2" #"$THUBAN_0_2$"
17 #__BuildDate__ = "$Date$"
18
19 import os
20
21 from wxPython.wx import *
22
23 import Thuban
24 from Thuban import _
25 from Thuban.Model.session import create_empty_session
26 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 from Thuban.UI.classifier import Classifier
35 import legend
36 from menu import Menu
37
38 from context import Context
39 from command import registry, Command, ToolCommand
40 from messages import LAYER_SELECTED, SHAPES_SELECTED, VIEW_POSITION
41
42 from Thuban.UI.dock import DockFrame
43 from Thuban.UI.join import JoinDialog
44
45 import resource
46
47 import projdialog
48
49
50
51 class MainWindow(DockFrame):
52
53 # 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 "SelectedShapes": "canvas",
66 }
67
68 def __init__(self, parent, ID, title, application, interactor,
69 initial_message = None, size = wxSize(-1, -1)):
70 DockFrame.__init__(self, parent, ID, title, wxDefaultPosition, size)
71 #wxFrame.__init__(self, parent, ID, title, wxDefaultPosition, size)
72
73 self.application = application
74
75 self.CreateStatusBar()
76 if initial_message:
77 self.SetStatusText(initial_message)
78
79 self.identify_view = None
80
81 self.init_ids()
82
83 # creat the menubar from the main_menu description
84 self.SetMenuBar(self.build_menu_bar(main_menu))
85
86 # Similarly, create the toolbar from main_toolbar
87 toolbar = self.build_toolbar(main_toolbar)
88 # call Realize to make sure that the tools appear.
89 toolbar.Realize()
90
91
92 # Create the map canvas
93 canvas = view.MapCanvas(self, -1)
94 canvas.Subscribe(VIEW_POSITION, self.view_position_changed)
95 canvas.Subscribe(SHAPES_SELECTED, self.identify_view_on_demand)
96 self.canvas = canvas
97
98 self.SetMainWindow(self.canvas)
99
100 self.SetAutoLayout(True)
101
102 self.init_dialogs()
103
104 EVT_CLOSE(self, self._OnClose)
105
106 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 def init_ids(self):
138 """Initialize the ids"""
139 self.current_id = 6000
140 self.id_to_name = {}
141 self.name_to_id = {}
142 self.events_bound = {}
143
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
156 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 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 """Return a wxMenu built from the menu description menudesc"""
176 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 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 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 self.bind_command_events(command, ID)
230 else:
231 print _("Unknown command %s") % name
232
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 bitmap = resource.GetBitmapResource(command.Icon(),
247 wxBITMAP_TYPE_XPM)
248 toolbar.AddTool(ID, bitmap,
249 shortHelpString = command.HelpText(),
250 isToggle = command.IsCheckCommand())
251 self.bind_command_events(command, ID)
252 else:
253 print _("Unknown command %s") % name
254
255 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 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 command.Execute(self.Context())
265 else:
266 print _("Unknown command ID %d") % event.GetId()
267
268 def update_command_ui(self, event):
269 #print "update_command_ui", self.id_to_name[event.GetId()]
270 context = self.Context()
271 command = registry.Command(self.id_to_name[event.GetId()])
272 if command is not None:
273 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 event.SetText(command.DynText(context))
284 if command.IsCheckCommand():
285 event.Check(command.Checked(context))
286
287 def RunMessageBox(self, title, text, flags = wxOK | wxICON_INFORMATION):
288 """Run a modal message box with the given text, title and flags
289 and return the result"""
290 dlg = wxMessageDialog(self, text, title, flags)
291 dlg.CenterOnParent()
292 result = dlg.ShowModal()
293 dlg.Destroy()
294 return result
295
296 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 raise RuntimeError(_("The Dialog named %s is already open") % name)
306 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 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 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 self.SetStatusText(text)
333
334 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 if self.application.session.WasModified():
344 flags = wxYES_NO | wxICON_QUESTION
345 if can_veto:
346 flags = flags | wxCANCEL
347 result = self.RunMessageBox(_("Exit"),
348 _("The session has been modified."
349 " 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 def prepare_new_session(self):
358 for d in self.dialogs.values():
359 if not isinstance(d, tree.SessionTreeView):
360 d.Close()
361
362 def NewSession(self):
363 self.save_modified_session()
364 self.prepare_new_session()
365 self.application.SetSession(create_empty_session())
366
367 def OpenSession(self):
368 self.save_modified_session()
369 dlg = wxFileDialog(self, _("Open Session"), ".", "",
370 "Thuban Session File (*.thuban)|*.thuban", wxOPEN)
371 if dlg.ShowModal() == wxID_OK:
372 self.prepare_new_session()
373 self.application.OpenSession(dlg.GetPath())
374 dlg.Destroy()
375
376 def SaveSession(self):
377 if self.application.session.filename == None:
378 self.SaveSessionAs()
379 else:
380 self.application.SaveSession()
381
382 def SaveSessionAs(self):
383 dlg = wxFileDialog(self, _("Save Session As"), ".", "",
384 "Thuban Session File (*.thuban)|*.thuban",
385 wxSAVE|wxOVERWRITE_PROMPT)
386 if dlg.ShowModal() == wxID_OK:
387 self.application.session.SetFilename(dlg.GetPath())
388 self.application.SaveSession()
389 dlg.Destroy()
390
391 def Exit(self):
392 self.Close(False)
393
394 def _OnClose(self, event):
395 result = self.save_modified_session(can_veto = event.CanVeto())
396 if result == wxID_CANCEL:
397 event.Veto()
398 else:
399 # 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 DockFrame._OnClose(self, event)
404 self.Destroy()
405
406 def SetMap(self, map):
407 self.canvas.SetMap(map)
408 self.__SetTitle(map.Title())
409
410 dialog = self.FindRegisteredDock("legend")
411 if dialog is not None:
412 dialog.GetPanel().SetMap(self.Map())
413
414 def Map(self):
415 """Return the map displayed by this mainwindow"""
416
417 return self.canvas.Map()
418
419 def ToggleSessionTree(self):
420 """If the session tree is shown close it otherwise create a new tree"""
421 name = "session_tree"
422 dialog = self.get_open_dialog(name)
423 if dialog is None:
424 dialog = tree.SessionTreeView(self, self.application, name)
425 self.add_dialog(name, dialog)
426 dialog.Show(True)
427 else:
428 dialog.Close()
429
430 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
434 def About(self):
435 self.RunMessageBox(_("About"),
436 _("Thuban v%s\n"
437 #"Build Date: %s\n"
438 "\n"
439 "Thuban is a program for\n"
440 "exploring geographic data.\n"
441 "Copyright (C) 2001-2003 Intevation GmbH.\n"
442 "Thuban is licensed under the GNU GPL"
443 % __ThubanVersion__), #__BuildDate__)),
444 wxOK | wxICON_INFORMATION)
445
446 def AddLayer(self):
447 dlg = wxFileDialog(self, _("Select a data file"), ".", "", "*.*",
448 wxOPEN)
449 if dlg.ShowModal() == wxID_OK:
450 filename = dlg.GetPath()
451 title = os.path.splitext(os.path.basename(filename))[0]
452 store = self.application.Session().OpenShapefile(filename)
453 layer = Layer(title, store)
454 map = self.canvas.Map()
455 has_layers = map.HasLayers()
456 try:
457 map.AddLayer(layer)
458 except IOError:
459 # the layer couldn't be opened
460 self.RunMessageBox(_("Add Layer"),
461 _("Can't open the file '%s'.") % filename)
462 else:
463 if not has_layers:
464 # if we're adding a layer to an empty map, fit the
465 # new map to the window
466 self.canvas.FitMapToWindow()
467 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 def CanRemoveLayer(self):
475 """Return true if the currently selected layer can be deleted.
476
477 If no layer is selected return False.
478
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 return False
486
487 def RaiseLayer(self):
488 layer = self.current_layer()
489 if layer is not None:
490 self.canvas.Map().RaiseLayer(layer)
491
492 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 return self.canvas.SelectedLayer()
503
504 def has_selected_layer(self):
505 """Return true if a layer is currently selected"""
506 return self.canvas.HasSelectedLayer()
507
508 def has_selected_shapes(self):
509 """Return true if a shape is currently selected"""
510 return self.canvas.HasSelectedShapes()
511
512 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 table = layer.table
526 name = "table_view" + str(id(table))
527 dialog = self.get_open_dialog(name)
528 if dialog is None:
529 dialog = tableview.LayerTableFrame(self, name,
530 _("Table: %s") % layer.Title(),
531 layer, table)
532 self.add_dialog(name, dialog)
533 dialog.Show(true)
534 else:
535 # FIXME: bring dialog to front here
536 pass
537
538 def MapProjection(self):
539
540 name = "map_projection"
541 dialog = self.get_open_dialog(name)
542
543 if dialog is None:
544 map = self.canvas.Map()
545 dialog = projdialog.ProjFrame(self, name,
546 _("Map Projection: %s") % map.Title(), map)
547 self.add_dialog(name, dialog)
548 dialog.Show()
549 dialog.Raise()
550
551 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 dialog = projdialog.ProjFrame(self, name,
561 _("Layer Projection: %s") % layer.Title(), layer)
562 self.add_dialog(name, dialog)
563 dialog.Show()
564 dialog.Raise()
565
566 def LayerEditProperties(self):
567
568 #
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 self.OpenLayerProperties(layer)
576
577 def OpenLayerProperties(self, layer, group = None):
578 name = "layer_properties" + str(id(layer))
579 dialog = self.get_open_dialog(name)
580
581 if dialog is None:
582 dialog = Classifier(self, name, layer, group)
583 self.add_dialog(name, dialog)
584 dialog.Show()
585 dialog.Raise()
586
587 def LayerJoinTable(self):
588 print "LayerJoinTable"
589
590 def LayerUnjoinTable(self):
591 print "LayerUnjoinTable"
592
593 def ShowLegend(self):
594 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 name = "legend"
600 dialog = self.FindRegisteredDock(name)
601
602 if dialog is None:
603 dialog = self.CreateDock(name, -1, _("Legend"), wxLAYOUT_LEFT)
604 legend.LegendPanel(dialog, None, self)
605 dialog.Dock()
606 dialog.GetPanel().SetMap(self.Map())
607 dialog.Show()
608 else:
609 dialog.Show(not dialog.IsShown())
610
611 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
616 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 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 self.identify_view_on_demand(None, None)
656
657 def LabelTool(self):
658 self.canvas.LabelTool()
659
660 def FullExtent(self):
661 self.canvas.FitMapToWindow()
662
663 def FullLayerExtent(self):
664 self.canvas.FitLayerToWindow(self.current_layer())
665
666 def FullSelectionExtent(self):
667 self.canvas.FitSelectedToWindow()
668
669 def ExportMap(self):
670 self.canvas.Export()
671
672 def PrintMap(self):
673 self.canvas.Print()
674
675 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 def identify_view_on_demand(self, layer, shapes):
687 """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 name = "identify_view"
701 if self.canvas.CurrentTool() == "IdentifyTool":
702 if not self.dialog_open(name):
703 dialog = identifyview.IdentifyView(self, name)
704 self.add_dialog(name, dialog)
705 dialog.Show(True)
706 else:
707 # FIXME: bring dialog to front?
708 pass
709
710 def __SetTitle(self, title):
711 self.SetTitle("Thuban - " + title)
712
713 #
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 """Call the mainwindow's method methodname with args *args"""
721 apply(getattr(context.mainwindow, methodname), args)
722
723 def _method_command(name, title, method, helptext = "",
724 icon = "", sensitive = None, checked = None):
725 """Add a command implemented by a method of the mainwindow object"""
726 registry.Add(Command(name, title, call_method, args=(method,),
727 helptext = helptext, icon = icon,
728 sensitive = sensitive, checked = checked))
729
730 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 def _tool_command(name, title, method, toolname, helptext = "",
742 icon = "", sensitive = None):
743 """Add a tool command"""
744 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
749 def _has_selected_layer(context):
750 """Return true if a layer is selected in the context"""
751 return context.mainwindow.has_selected_layer()
752
753 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 def _can_remove_layer(context):
758 return context.mainwindow.CanRemoveLayer()
759
760 def _has_tree_window_shown(context):
761 """Return true if the tree window is shown"""
762 return context.mainwindow.SessionTreeShown()
763
764 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 def _has_legend_shown(context):
776 """Return true if the legend window is shown"""
777 return context.mainwindow.LegendShown()
778
779
780 # File menu
781 _method_command("new_session", _("&New Session"), "NewSession")
782 _method_command("open_session", _("&Open Session..."), "OpenSession")
783 _method_command("save_session", _("&Save Session"), "SaveSession")
784 _method_command("save_session_as", _("Save Session &As..."), "SaveSessionAs")
785 _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 _method_command("exit", _("E&xit"), "Exit")
790
791 # Help menu
792 _method_command("help_about", _("&About..."), "About")
793
794
795 # Map menu
796 _method_command("map_projection", _("Pro&jection..."), "MapProjection")
797
798 _tool_command("map_zoom_in_tool", _("&Zoom in"), "ZoomInTool", "ZoomInTool",
799 helptext = _("Switch to map-mode 'zoom-in'"), icon = "zoom_in",
800 sensitive = _has_visible_map)
801 _tool_command("map_zoom_out_tool", _("Zoom &out"), "ZoomOutTool", "ZoomOutTool",
802 helptext = _("Switch to map-mode 'zoom-out'"), icon = "zoom_out",
803 sensitive = _has_visible_map)
804 _tool_command("map_pan_tool", _("&Pan"), "PanTool", "PanTool",
805 helptext = _("Switch to map-mode 'pan'"), icon = "pan",
806 sensitive = _has_visible_map)
807 _tool_command("map_identify_tool", _("&Identify"), "IdentifyTool",
808 "IdentifyTool",
809 helptext = _("Switch to map-mode 'identify'"), icon = "identify",
810 sensitive = _has_visible_map)
811 _tool_command("map_label_tool", _("&Label"), "LabelTool", "LabelTool",
812 helptext = _("Add/Remove labels"), icon = "label",
813 sensitive = _has_visible_map)
814 _method_command("map_full_extent", _("&Full extent"), "FullExtent",
815 helptext = _("Full Extent"), icon = "fullextent",
816 sensitive = _has_visible_map)
817 _method_command("layer_full_extent", _("&Full layer extent"), "FullLayerExtent",
818 helptext = _("Full Layer Extent"), icon = "fulllayerextent",
819 sensitive = _has_selected_layer)
820 _method_command("selected_full_extent", _("&Full selection extent"), "FullSelectionExtent",
821 helptext = _("Full Selection Extent"), icon = "fullselextent",
822 sensitive = _has_selected_shapes)
823 _method_command("map_export", _("E&xport"), "ExportMap",
824 helptext = _("Export the map to file"))
825 _method_command("map_print", _("Prin&t"), "PrintMap",
826 helptext = _("Print the map"))
827 _method_command("map_rename", _("&Rename..."), "RenameMap",
828 helptext = _("Rename the map"))
829 _method_command("layer_add", _("&Add Layer..."), "AddLayer",
830 helptext = _("Add a new layer to active map"))
831 _method_command("layer_remove", _("&Remove Layer"), "RemoveLayer",
832 helptext = _("Remove selected layer(s)"),
833 sensitive = _can_remove_layer)
834
835 # Layer menu
836 _method_command("layer_projection", _("Pro&jection..."), "LayerProjection",
837 sensitive = _has_selected_layer)
838 _method_command("layer_raise", _("&Raise"), "RaiseLayer",
839 helptext = _("Raise selected layer(s)"),
840 sensitive = _has_selected_layer)
841 _method_command("layer_lower", _("&Lower"), "LowerLayer",
842 helptext = _("Lower selected layer(s)"),
843 sensitive = _has_selected_layer)
844 _method_command("layer_show", _("&Show"), "ShowLayer",
845 helptext = _("Make selected layer(s) visible"),
846 sensitive = _has_selected_layer)
847 _method_command("layer_hide", _("&Hide"), "HideLayer",
848 helptext = _("Make selected layer(s) unvisible"),
849 sensitive = _has_selected_layer)
850 _method_command("layer_show_table", _("Show Ta&ble"), "LayerShowTable",
851 helptext = _("Show the selected layer's table"),
852 sensitive = _has_selected_layer)
853 _method_command("layer_properties", _("&Properties..."), "LayerEditProperties",
854 sensitive = _has_selected_layer)
855 _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
860 # 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 # Export only under Windows ...
868 map_menu = ["layer_add", "layer_remove", "map_rename",
869 None,
870 "map_projection",
871 None,
872 "map_zoom_in_tool", "map_zoom_out_tool",
873 "map_pan_tool",
874 "map_full_extent",
875 "layer_full_extent",
876 "selected_full_extent",
877 None,
878 "map_identify_tool", "map_label_tool",
879 None,
880 "toggle_legend",
881 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 Menu("layer", _("&Layer"),
895 ["layer_raise", "layer_lower",
896 None,
897 "layer_show", "layer_hide",
898 None,
899 "layer_projection",
900 None,
901 "layer_show_table",
902 "layer_jointable",
903 "layer_unjointable",
904 None,
905 "layer_properties"]),
906 Menu("table", _("&Table"),
907 ["table_open", "table_close",
908 None,
909 "table_show", "table_hide",
910 None,
911 "table_join"]),
912 Menu("help", _("&Help"),
913 ["help_about"])])
914
915 # the main toolbar
916
917 main_toolbar = Menu("<toolbar>", "<toolbar>",
918 ["map_zoom_in_tool", "map_zoom_out_tool", "map_pan_tool",
919 "map_full_extent",
920 "layer_full_extent",
921 "selected_full_extent",
922 None,
923 "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