/[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 374 - (show annotations)
Mon Jan 27 14:20:02 2003 UTC (22 years, 1 month ago) by jan
Original Path: trunk/thuban/Thuban/UI/mainwindow.py
File MIME type: text/x-python
File size: 26451 byte(s)
Replace user string by _() for i18n.

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 NewSession(self):
300 self.save_modified_session()
301 self.application.SetSession(create_empty_session())
302
303 def OpenSession(self):
304 self.save_modified_session()
305 dlg = wxFileDialog(self, _("Select a session file"), ".", "",
306 "*.thuban", wxOPEN)
307 if dlg.ShowModal() == wxID_OK:
308 self.application.OpenSession(dlg.GetPath())
309 dlg.Destroy()
310
311 def SaveSession(self):
312 if self.application.session.filename == None:
313 self.SaveSessionAs()
314 self.application.SaveSession()
315
316 def SaveSessionAs(self):
317 dlg = wxFileDialog(self, _("Enter a filename for session"), ".", "",
318 "*.thuban", wxOPEN)
319 if dlg.ShowModal() == wxID_OK:
320 self.application.session.SetFilename(dlg.GetPath())
321 self.application.SaveSession()
322 dlg.Destroy()
323
324 def Exit(self):
325 self.Close(false)
326
327 def OnClose(self, event):
328 result = self.save_modified_session(can_veto = event.CanVeto())
329 if result == wxID_CANCEL:
330 event.Veto()
331 else:
332 # FIXME: it would be better to tie the unsubscription to
333 # wx's destroy event, but that isn't implemented for wxGTK
334 # yet.
335 self.canvas.Unsubscribe(VIEW_POSITION, self.view_position_changed)
336 self.Destroy()
337
338 def SetMap(self, map):
339 self.canvas.SetMap(map)
340
341 def Map(self):
342 """Return the map displayed by this mainwindow"""
343 return self.canvas.Map()
344
345 def ShowSessionTree(self):
346 name = "session_tree"
347 dialog = self.get_open_dialog(name)
348 if dialog is None:
349 dialog = tree.SessionTreeView(self, self.application, name)
350 self.add_dialog(name, dialog)
351 dialog.Show(true)
352 else:
353 # FIXME: bring dialog to front here
354 pass
355
356 def About(self):
357 self.RunMessageBox(_("About"),
358 _("Thuban is a program for\n"
359 "exploring geographic data.\n"
360 "Copyright (C) 2001-2003 Intevation GmbH.\n"
361 "Thuban is licensed under the GPL"),
362 wxOK | wxICON_INFORMATION)
363
364 def AddLayer(self):
365 dlg = wxFileDialog(self, _("Select a data file"), ".", "", "*.*",
366 wxOPEN)
367 if dlg.ShowModal() == wxID_OK:
368 filename = dlg.GetPath()
369 title = os.path.splitext(os.path.basename(filename))[0]
370 layer = Layer(title, filename)
371 map = self.canvas.Map()
372 has_layers = map.HasLayers()
373 try:
374 map.AddLayer(layer)
375 except IOError:
376 # the layer couldn't be opened
377 self.RunMessageBox(_("Add Layer"),
378 _("Can't open the file '%s'.") % filename)
379 else:
380 if not has_layers:
381 # if we're adding a layer to an empty map, for the
382 # new map to the window
383 self.canvas.FitMapToWindow()
384 dlg.Destroy()
385
386 def RemoveLayer(self):
387 layer = self.current_layer()
388 if layer is not None:
389 self.canvas.Map().RemoveLayer(layer)
390
391 def CanRemoveLayer(self):
392 """Return true if the currently selected layer can be deleted.
393
394 If no layer is selected return false.
395
396 The return value of this method determines whether the remove
397 layer command is sensitive in menu.
398 """
399 layer = self.current_layer()
400 if layer is not None:
401 return self.canvas.Map().CanRemoveLayer(layer)
402 return 0
403
404 def RaiseLayer(self):
405 layer = self.current_layer()
406 if layer is not None:
407 self.canvas.Map().RaiseLayer(layer)
408
409 def LowerLayer(self):
410 layer = self.current_layer()
411 if layer is not None:
412 self.canvas.Map().LowerLayer(layer)
413
414 def current_layer(self):
415 """Return the currently selected layer.
416
417 If no layer is selected, return None
418 """
419 return self.interactor.SelectedLayer()
420
421 def has_selected_layer(self):
422 """Return true if a layer is currently selected"""
423 return self.interactor.HasSelectedLayer()
424
425 def choose_color(self):
426 """Run the color selection dialog and return the selected color.
427
428 If the user cancels, return None.
429 """
430 dlg = wxColourDialog(self)
431 color = None
432 if dlg.ShowModal() == wxID_OK:
433 data = dlg.GetColourData()
434 wxc = data.GetColour()
435 color = Color(wxc.Red() / 255.0,
436 wxc.Green() / 255.0,
437 wxc.Blue() / 255.0)
438 dlg.Destroy()
439 return color
440
441 def LayerFillColor(self):
442 layer = self.current_layer()
443 if layer is not None:
444 color = self.choose_color()
445 if color is not None:
446 layer.SetFill(color)
447
448 def LayerTransparentFill(self):
449 layer = self.current_layer()
450 if layer is not None:
451 layer.SetFill(None)
452
453 def LayerOutlineColor(self):
454 layer = self.current_layer()
455 if layer is not None:
456 color = self.choose_color()
457 if color is not None:
458 layer.SetStroke(color)
459
460 def LayerNoOutline(self):
461 layer = self.current_layer()
462 if layer is not None:
463 layer.SetStroke(None)
464
465 def HideLayer(self):
466 layer = self.current_layer()
467 if layer is not None:
468 layer.SetVisible(0)
469
470 def ShowLayer(self):
471 layer = self.current_layer()
472 if layer is not None:
473 layer.SetVisible(1)
474
475 def LayerShowTable(self):
476 layer = self.current_layer()
477 if layer is not None:
478 table = layer.table
479 name = "table_view" + str(id(table))
480 dialog = self.get_open_dialog(name)
481 if dialog is None:
482 dialog = tableview.LayerTableFrame(self, self.interactor, name,
483 _("Table: %s") % layer.Title(),
484 layer, table)
485 self.add_dialog(name, dialog)
486 dialog.Show(true)
487 else:
488 # FIXME: bring dialog to front here
489 pass
490
491 def Projection(self):
492 map = self.canvas.Map()
493 proj = map.projection
494 if proj is None:
495 proj4Dlg = proj4dialog.Proj4Dialog(NULL, None, map.BoundingBox())
496 else:
497 proj4Dlg = proj4dialog.Proj4Dialog(NULL, map.projection.params,
498 map.BoundingBox())
499 if proj4Dlg.ShowModal() == wxID_OK:
500 params = proj4Dlg.GetParams()
501 if params is not None:
502 proj = Projection(params)
503 else:
504 proj = None
505 map.SetProjection(proj)
506 proj4Dlg.Destroy()
507
508 def Classify(self):
509 classifyDlg = classifier.Classifier(NULL, self.current_layer())
510
511 classifyDlg.ShowModal()
512 classifyDlg.Destroy()
513
514 def ZoomInTool(self):
515 self.canvas.ZoomInTool()
516
517 def ZoomOutTool(self):
518 self.canvas.ZoomOutTool()
519
520 def PanTool(self):
521 self.canvas.PanTool()
522
523 def IdentifyTool(self):
524 self.canvas.IdentifyTool()
525 self.identify_view_on_demand(None, None)
526
527 def LabelTool(self):
528 self.canvas.LabelTool()
529
530 def FullExtent(self):
531 self.canvas.FitMapToWindow()
532
533 def PrintMap(self):
534 self.canvas.Print()
535
536 def identify_view_on_demand(self, layer, shape):
537 name = "identify_view"
538 if self.canvas.CurrentTool() == "IdentifyTool":
539 if not self.dialog_open(name):
540 dialog = identifyview.IdentifyView(self, self.interactor, name)
541 self.add_dialog(name, dialog)
542 dialog.Show(true)
543 else:
544 # FIXME: bring dialog to front?
545 pass
546
547 #
548 # Define all the commands available in the main window
549 #
550
551
552 # Helper functions to define common command implementations
553 def call_method(context, methodname, *args):
554 """Call the mainwindow's method methodname with args *args"""
555 apply(getattr(context.mainwindow, methodname), args)
556
557 def _method_command(name, title, method, helptext = "",
558 icon = "", sensitive = None):
559 """Add a command implemented by a method of the mainwindow object"""
560 registry.Add(Command(name, title, call_method, args=(method,),
561 helptext = helptext, icon = icon,
562 sensitive = sensitive))
563
564 def make_check_current_tool(toolname):
565 """Return a function that tests if the currently active tool is toolname
566
567 The returned function can be called with the context and returns
568 true iff the currently active tool's name is toolname. It's directly
569 usable as the 'checked' callback of a command.
570 """
571 def check_current_tool(context, name=toolname):
572 return context.mainwindow.canvas.CurrentTool() == name
573 return check_current_tool
574
575 def _tool_command(name, title, method, toolname, helptext = "",
576 icon = "", sensitive = None):
577 """Add a tool command"""
578 registry.Add(ToolCommand(name, title, call_method, args=(method,),
579 helptext = helptext, icon = icon,
580 checked = make_check_current_tool(toolname),
581 sensitive = sensitive))
582
583 def _has_selected_layer(context):
584 """Return true if a layer is selected in the context"""
585 return context.mainwindow.has_selected_layer()
586
587 def _can_remove_layer(context):
588 return context.mainwindow.CanRemoveLayer()
589
590 def _has_tree_window_shown(context):
591 """Return true if the tree window is shown"""
592 return context.mainwindow.get_open_dialog("session_tree") is None
593
594 def _has_visible_map(context):
595 """Return true iff theres a visible map in the mainwindow.
596
597 A visible map is a map with at least one visible layer."""
598 map = context.mainwindow.Map()
599 if map is not None:
600 for layer in map.Layers():
601 if layer.Visible():
602 return 1
603 return 0
604
605
606 # File menu
607 _method_command("new_session", _("&New Session"), "NewSession")
608 _method_command("open_session", _("&Open Session"), "OpenSession")
609 _method_command("save_session", _("&Save Session"), "SaveSession")
610 _method_command("save_session_as", _("Save Session &As"), "SaveSessionAs")
611 _method_command("show_session_tree", _("Show Session &Tree"), "ShowSessionTree",
612 sensitive = _has_tree_window_shown)
613 _method_command("exit", _("E&xit"), "Exit")
614
615 # Help menu
616 _method_command("help_about", _("&About"), "About")
617
618
619 # Map menu
620 _method_command("map_projection", _("Pro&jection"), "Projection")
621
622 _tool_command("map_zoom_in_tool", _("&Zoom in"), "ZoomInTool", "ZoomInTool",
623 helptext = _("Switch to map-mode 'zoom-in'"), icon = "zoom_in",
624 sensitive = _has_visible_map)
625 _tool_command("map_zoom_out_tool", _("Zoom &out"), "ZoomOutTool", "ZoomOutTool",
626 helptext = _("Switch to map-mode 'zoom-out'"), icon = "zoom_out",
627 sensitive = _has_visible_map)
628 _tool_command("map_pan_tool", _("&Pan"), "PanTool", "PanTool",
629 helptext = _("Switch to map-mode 'pan'"), icon = "pan",
630 sensitive = _has_visible_map)
631 _tool_command("map_identify_tool", _("&Identify"), "IdentifyTool",
632 "IdentifyTool",
633 helptext = _("Switch to map-mode 'identify'"), icon = "identify",
634 sensitive = _has_visible_map)
635 _tool_command("map_label_tool", _("&Label"), "LabelTool", "LabelTool",
636 helptext = _("Add/Remove labels"), icon = "label",
637 sensitive = _has_visible_map)
638 _method_command("map_full_extent", _("&Full extent"), "FullExtent",
639 helptext = _("Full Extent"), icon = "fullextent",
640 sensitive = _has_visible_map)
641 _method_command("map_print", _("Prin&t"), "PrintMap",
642 helptext = _("Print the map"))
643
644 # Layer menu
645 _method_command("layer_add", _("&Add Layer"), "AddLayer",
646 helptext = _("Add a new layer to active map"))
647 _method_command("layer_remove", _("&Remove Layer"), "RemoveLayer",
648 helptext = _("Remove selected layer(s)"),
649 sensitive = _can_remove_layer)
650 _method_command("layer_fill_color", _("&Fill Color"), "LayerFillColor",
651 helptext = _("Set the fill color of selected layer(s)"),
652 sensitive = _has_selected_layer)
653 _method_command("layer_transparent_fill", _("&Transparent Fill"),
654 "LayerTransparentFill",
655 helptext = _("Do not fill the selected layer(s)"),
656 sensitive = _has_selected_layer)
657 _method_command("layer_outline_color", _("&Outline Color"), "LayerOutlineColor",
658 helptext = _("Set the outline color of selected layer(s)"),
659 sensitive = _has_selected_layer)
660 _method_command("layer_no_outline", _("&No Outline"), "LayerNoOutline",
661 helptext= _("Do not draw the outline of the selected layer(s)"),
662 sensitive = _has_selected_layer)
663 _method_command("layer_raise", _("&Raise"), "RaiseLayer",
664 helptext = _("Raise selected layer(s)"),
665 sensitive = _has_selected_layer)
666 _method_command("layer_lower", _("&Lower"), "LowerLayer",
667 helptext = _("Lower selected layer(s)"),
668 sensitive = _has_selected_layer)
669 _method_command("layer_show", _("&Show"), "ShowLayer",
670 helptext = _("Make selected layer(s) visible"),
671 sensitive = _has_selected_layer)
672 _method_command("layer_hide", _("&Hide"), "HideLayer",
673 helptext = _("Make selected layer(s) unvisible"),
674 sensitive = _has_selected_layer)
675 _method_command("layer_show_table", _("Show Ta&ble"), "LayerShowTable",
676 helptext = _("Show the selected layer's table"),
677 sensitive = _has_selected_layer)
678
679 _method_command("layer_classifier", _("Classify"), "Classify",
680 sensitive = _has_selected_layer)
681
682 # the menu structure
683 main_menu = Menu("<main>", "<main>",
684 [Menu("file", _("&File"),
685 ["new_session", "open_session", None,
686 "save_session", "save_session_as", None,
687 "show_session_tree", None,
688 "exit"]),
689 Menu("map", _("&Map"),
690 ["layer_add", "layer_remove",
691 None,
692 "map_projection",
693 None,
694 "map_zoom_in_tool", "map_zoom_out_tool",
695 "map_pan_tool", "map_identify_tool", "map_label_tool",
696 None,
697 "map_full_extent",
698 None,
699 "map_print"]),
700 Menu("layer", _("&Layer"),
701 ["layer_fill_color", "layer_transparent_fill",
702 "layer_outline_color", "layer_no_outline",
703 None,
704 "layer_raise", "layer_lower",
705 None,
706 "layer_show", "layer_hide",
707 None,
708 "layer_show_table",
709 None,
710 "layer_classifier"]),
711 Menu("help", _("&Help"),
712 ["help_about"])])
713
714 # the main toolbar
715
716 main_toolbar = Menu("<toolbar>", "<toolbar>",
717 ["map_zoom_in_tool", "map_zoom_out_tool", "map_pan_tool",
718 "map_full_extent", None,
719 "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