/[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 573 - (hide annotations)
Fri Mar 28 17:07:06 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: 30454 byte(s)
Removed legend specific code and replaced it with calls to the new dock code.

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