/[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 502 - (show annotations)
Mon Mar 10 15:11:53 2003 UTC (22 years ago) by jonathan
Original Path: trunk/thuban/Thuban/UI/mainwindow.py
File MIME type: text/x-python
File size: 27188 byte(s)
(MainWindow.prepare_new_session): Call Close() instead of Shutdown().

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