/[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 517 - (show annotations)
Tue Mar 11 17:28:39 2003 UTC (22 years ago) by jonathan
Original Path: trunk/thuban/Thuban/UI/mainwindow.py
File MIME type: text/x-python
File size: 27452 byte(s)
About window shows version number.

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