/[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 550 - (show annotations)
Thu Mar 20 09:45:19 2003 UTC (21 years, 11 months ago) by jonathan
Original Path: trunk/thuban/Thuban/UI/mainwindow.py
File MIME type: text/x-python
File size: 29818 byte(s)
New code to open the legend.

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