/[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 704 - (show annotations)
Tue Apr 22 16:55:50 2003 UTC (21 years, 10 months ago) by bh
Original Path: trunk/thuban/Thuban/UI/mainwindow.py
File MIME type: text/x-python
File size: 29737 byte(s)
Remove some unused imports and global
constants

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