/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/UI/mainwindow.py
ViewVC logotype

Annotation of /branches/WIP-pyshapelib-bramz/Thuban/UI/mainwindow.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 363 - (hide annotations)
Mon Jan 27 11:40:13 2003 UTC (22 years, 1 month ago) by jonathan
Original Path: trunk/thuban/Thuban/UI/mainwindow.py
File MIME type: text/x-python
File size: 26218 byte(s)
added 'Classify' option in 'Layer' menu

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