/[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 621 - (hide annotations)
Mon Apr 7 10:14:50 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: 30512 byte(s)
Use False instead of false.
(MainWindow.ShowLegend): Remove unnecessary switch parameter.

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 jonathan 580 EVT_CLOSE(self, self._OnClose)
105 bh 6
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 jonathan 621 self.Close(False)
391 bh 6
392 jonathan 580 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 jonathan 580 DockFrame._OnClose(self, event)
402 bh 6 self.Destroy()
403    
404     def SetMap(self, map):
405     self.canvas.SetMap(map)
406 jonathan 563 #self.legendPanel.SetMap(map)
407 bh 6
408 bh 310 def Map(self):
409     """Return the map displayed by this mainwindow"""
410 jonathan 563
411     # sanity check
412     #assert(self.canvas.Map() is self.legendPanel.GetMap())
413    
414 bh 310 return self.canvas.Map()
415    
416 bh 37 def ShowSessionTree(self):
417     name = "session_tree"
418     dialog = self.get_open_dialog(name)
419     if dialog is None:
420 bh 227 dialog = tree.SessionTreeView(self, self.application, name)
421 bh 37 self.add_dialog(name, dialog)
422 jonathan 512 dialog.Show(True)
423 bh 37 else:
424     # FIXME: bring dialog to front here
425     pass
426    
427 jonathan 517
428 bh 6 def About(self):
429 jan 374 self.RunMessageBox(_("About"),
430 jonathan 517 _("Thuban v%s\n"
431     #"Build Date: %s\n"
432     "\n"
433     "Thuban is a program for\n"
434 bh 20 "exploring geographic data.\n"
435 jan 374 "Copyright (C) 2001-2003 Intevation GmbH.\n"
436 jonathan 517 "Thuban is licensed under the GNU GPL"
437     % __ThubanVersion__), #__BuildDate__)),
438 bh 20 wxOK | wxICON_INFORMATION)
439 bh 6
440     def AddLayer(self):
441 jan 374 dlg = wxFileDialog(self, _("Select a data file"), ".", "", "*.*",
442 bh 6 wxOPEN)
443     if dlg.ShowModal() == wxID_OK:
444     filename = dlg.GetPath()
445     title = os.path.splitext(os.path.basename(filename))[0]
446     layer = Layer(title, filename)
447 bh 18 map = self.canvas.Map()
448     has_layers = map.HasLayers()
449 bh 20 try:
450     map.AddLayer(layer)
451     except IOError:
452     # the layer couldn't be opened
453 jan 374 self.RunMessageBox(_("Add Layer"),
454     _("Can't open the file '%s'.") % filename)
455 bh 20 else:
456     if not has_layers:
457 bh 535 # if we're adding a layer to an empty map, fit the
458 bh 20 # new map to the window
459     self.canvas.FitMapToWindow()
460 bh 6 dlg.Destroy()
461    
462     def RemoveLayer(self):
463     layer = self.current_layer()
464     if layer is not None:
465     self.canvas.Map().RemoveLayer(layer)
466    
467 bh 299 def CanRemoveLayer(self):
468     """Return true if the currently selected layer can be deleted.
469    
470 jonathan 621 If no layer is selected return False.
471 bh 299
472     The return value of this method determines whether the remove
473     layer command is sensitive in menu.
474     """
475     layer = self.current_layer()
476     if layer is not None:
477     return self.canvas.Map().CanRemoveLayer(layer)
478 jonathan 621 return False
479 bh 299
480 bh 6 def RaiseLayer(self):
481     layer = self.current_layer()
482     if layer is not None:
483     self.canvas.Map().RaiseLayer(layer)
484 bh 222
485 bh 6 def LowerLayer(self):
486     layer = self.current_layer()
487     if layer is not None:
488     self.canvas.Map().LowerLayer(layer)
489    
490     def current_layer(self):
491     """Return the currently selected layer.
492    
493     If no layer is selected, return None
494     """
495 bh 535 return self.canvas.SelectedLayer()
496 bh 6
497     def has_selected_layer(self):
498     """Return true if a layer is currently selected"""
499 bh 535 return self.canvas.HasSelectedLayer()
500 bh 6
501     def choose_color(self):
502     """Run the color selection dialog and return the selected color.
503    
504     If the user cancels, return None.
505     """
506     dlg = wxColourDialog(self)
507     color = None
508     if dlg.ShowModal() == wxID_OK:
509     data = dlg.GetColourData()
510     wxc = data.GetColour()
511     color = Color(wxc.Red() / 255.0,
512     wxc.Green() / 255.0,
513     wxc.Blue() / 255.0)
514     dlg.Destroy()
515     return color
516    
517     def LayerFillColor(self):
518     layer = self.current_layer()
519     if layer is not None:
520     color = self.choose_color()
521     if color is not None:
522 jonathan 450 layer.GetClassification().SetDefaultFill(color)
523 bh 6
524     def LayerTransparentFill(self):
525     layer = self.current_layer()
526     if layer is not None:
527 jonathan 610 layer.GetClassification().SetDefaultFill(Color.Transparent)
528 bh 6
529     def LayerOutlineColor(self):
530     layer = self.current_layer()
531     if layer is not None:
532     color = self.choose_color()
533     if color is not None:
534 jonathan 469 layer.GetClassification().SetDefaultLineColor(color)
535 bh 6
536     def LayerNoOutline(self):
537     layer = self.current_layer()
538     if layer is not None:
539 jonathan 610 layer.GetClassification().SetDefaultLineColor(Color.Transparent)
540 bh 6
541     def HideLayer(self):
542     layer = self.current_layer()
543     if layer is not None:
544     layer.SetVisible(0)
545    
546     def ShowLayer(self):
547     layer = self.current_layer()
548     if layer is not None:
549     layer.SetVisible(1)
550    
551     def LayerShowTable(self):
552     layer = self.current_layer()
553     if layer is not None:
554 bh 31 table = layer.table
555     name = "table_view" + str(id(table))
556     dialog = self.get_open_dialog(name)
557     if dialog is None:
558 bh 535 dialog = tableview.LayerTableFrame(self, name,
559     _("Table: %s") % layer.Title(),
560 bh 278 layer, table)
561 bh 31 self.add_dialog(name, dialog)
562     dialog.Show(true)
563     else:
564     # FIXME: bring dialog to front here
565     pass
566 bh 6
567     def Projection(self):
568     map = self.canvas.Map()
569     proj = map.projection
570     if proj is None:
571 jan 110 proj4Dlg = proj4dialog.Proj4Dialog(NULL, None, map.BoundingBox())
572 bh 6 else:
573 jan 110 proj4Dlg = proj4dialog.Proj4Dialog(NULL, map.projection.params,
574     map.BoundingBox())
575 bh 6 if proj4Dlg.ShowModal() == wxID_OK:
576     params = proj4Dlg.GetParams()
577     if params is not None:
578     proj = Projection(params)
579     else:
580     proj = None
581     map.SetProjection(proj)
582     proj4Dlg.Destroy()
583    
584 jonathan 363 def Classify(self):
585    
586 jonathan 487 #
587     # the menu option for this should only be available if there
588     # is a current layer, so we don't need to check if the
589     # current layer is None
590     #
591    
592     layer = self.current_layer()
593 jonathan 550 self.OpenClassifier(layer)
594    
595 jonathan 573 def OpenClassifier(self, layer, group = None):
596 jonathan 487 name = "classifier" + str(id(layer))
597     dialog = self.get_open_dialog(name)
598    
599     if dialog is None:
600 jonathan 573 dialog = classifier.Classifier(self, name, layer, group)
601 jonathan 487 self.add_dialog(name, dialog)
602     dialog.Show()
603 jonathan 573 dialog.Raise()
604 jonathan 487
605 jonathan 550
606 jonathan 621 def ShowLegend(self):
607 jonathan 550 name = "legend"
608 jonathan 573 dialog = self.FindRegisteredDock(name)
609 jonathan 550
610     if dialog is None:
611 jonathan 573 title = "Legend: %s" % self.Map().Title()
612     dialog = self.CreateDock(name, -1, title, wxLAYOUT_LEFT)
613     legend.LegendPanel(dialog, None, self)
614 jonathan 580 dialog.Dock()
615 jonathan 563
616 jonathan 573 dialog.GetPanel().SetMap(self.Map())
617 jonathan 563 dialog.Show()
618    
619 bh 6 def ZoomInTool(self):
620     self.canvas.ZoomInTool()
621    
622     def ZoomOutTool(self):
623     self.canvas.ZoomOutTool()
624    
625     def PanTool(self):
626     self.canvas.PanTool()
627    
628     def IdentifyTool(self):
629     self.canvas.IdentifyTool()
630 bh 49 self.identify_view_on_demand(None, None)
631 bh 6
632     def LabelTool(self):
633     self.canvas.LabelTool()
634    
635     def FullExtent(self):
636     self.canvas.FitMapToWindow()
637    
638     def PrintMap(self):
639     self.canvas.Print()
640    
641 bh 535 def identify_view_on_demand(self, layer, shapes):
642 bh 31 name = "identify_view"
643     if self.canvas.CurrentTool() == "IdentifyTool":
644     if not self.dialog_open(name):
645 bh 535 dialog = identifyview.IdentifyView(self, name)
646 bh 31 self.add_dialog(name, dialog)
647 jonathan 563 dialog.Show(True)
648 bh 31 else:
649 bh 33 # FIXME: bring dialog to front?
650 bh 31 pass
651 bh 6
652     #
653     # Define all the commands available in the main window
654     #
655    
656    
657     # Helper functions to define common command implementations
658     def call_method(context, methodname, *args):
659 bh 222 """Call the mainwindow's method methodname with args *args"""
660     apply(getattr(context.mainwindow, methodname), args)
661 bh 6
662 jan 110 def _method_command(name, title, method, helptext = "",
663     icon = "", sensitive = None):
664 bh 222 """Add a command implemented by a method of the mainwindow object"""
665 bh 6 registry.Add(Command(name, title, call_method, args=(method,),
666 jan 110 helptext = helptext, icon = icon,
667     sensitive = sensitive))
668    
669 bh 270 def make_check_current_tool(toolname):
670     """Return a function that tests if the currently active tool is toolname
671    
672     The returned function can be called with the context and returns
673     true iff the currently active tool's name is toolname. It's directly
674     usable as the 'checked' callback of a command.
675     """
676     def check_current_tool(context, name=toolname):
677     return context.mainwindow.canvas.CurrentTool() == name
678     return check_current_tool
679    
680 bh 6 def _tool_command(name, title, method, toolname, helptext = "",
681 bh 310 icon = "", sensitive = None):
682 bh 6 """Add a tool command"""
683 bh 357 registry.Add(ToolCommand(name, title, call_method, args=(method,),
684     helptext = helptext, icon = icon,
685     checked = make_check_current_tool(toolname),
686     sensitive = sensitive))
687 bh 6
688     def _has_selected_layer(context):
689     """Return true if a layer is selected in the context"""
690 bh 222 return context.mainwindow.has_selected_layer()
691 bh 6
692 bh 299 def _can_remove_layer(context):
693     return context.mainwindow.CanRemoveLayer()
694    
695 jan 264 def _has_tree_window_shown(context):
696     """Return true if the tree window is shown"""
697     return context.mainwindow.get_open_dialog("session_tree") is None
698    
699 bh 310 def _has_visible_map(context):
700     """Return true iff theres a visible map in the mainwindow.
701    
702     A visible map is a map with at least one visible layer."""
703     map = context.mainwindow.Map()
704     if map is not None:
705     for layer in map.Layers():
706     if layer.Visible():
707     return 1
708     return 0
709    
710 jonathan 550 def _has_legend_shown(context):
711     """Return true if the legend window is shown"""
712 jonathan 573 return context.mainwindow.FindRegisteredDock("legend") is None
713 bh 310
714 jonathan 550
715 bh 6 # File menu
716 jan 374 _method_command("new_session", _("&New Session"), "NewSession")
717     _method_command("open_session", _("&Open Session"), "OpenSession")
718     _method_command("save_session", _("&Save Session"), "SaveSession")
719     _method_command("save_session_as", _("Save Session &As"), "SaveSessionAs")
720 jonathan 616 _method_command("show_session_tree", _("Session &Tree"), "ShowSessionTree",
721 jan 264 sensitive = _has_tree_window_shown)
722 jonathan 616 _method_command("show_legend", _("Legend"), "ShowLegend",
723     sensitive = _has_legend_shown)
724 jan 374 _method_command("exit", _("E&xit"), "Exit")
725 bh 6
726     # Help menu
727 jan 374 _method_command("help_about", _("&About"), "About")
728 bh 6
729    
730     # Map menu
731 jan 374 _method_command("map_projection", _("Pro&jection"), "Projection")
732 bh 6
733 jan 374 _tool_command("map_zoom_in_tool", _("&Zoom in"), "ZoomInTool", "ZoomInTool",
734     helptext = _("Switch to map-mode 'zoom-in'"), icon = "zoom_in",
735 bh 310 sensitive = _has_visible_map)
736 jan 374 _tool_command("map_zoom_out_tool", _("Zoom &out"), "ZoomOutTool", "ZoomOutTool",
737     helptext = _("Switch to map-mode 'zoom-out'"), icon = "zoom_out",
738 bh 310 sensitive = _has_visible_map)
739 jan 374 _tool_command("map_pan_tool", _("&Pan"), "PanTool", "PanTool",
740     helptext = _("Switch to map-mode 'pan'"), icon = "pan",
741 bh 310 sensitive = _has_visible_map)
742 jan 374 _tool_command("map_identify_tool", _("&Identify"), "IdentifyTool",
743     "IdentifyTool",
744     helptext = _("Switch to map-mode 'identify'"), icon = "identify",
745 bh 310 sensitive = _has_visible_map)
746 jan 374 _tool_command("map_label_tool", _("&Label"), "LabelTool", "LabelTool",
747     helptext = _("Add/Remove labels"), icon = "label",
748 bh 310 sensitive = _has_visible_map)
749 jan 374 _method_command("map_full_extent", _("&Full extent"), "FullExtent",
750     helptext = _("Full Extent"), icon = "fullextent",
751 bh 310 sensitive = _has_visible_map)
752 jan 374 _method_command("map_print", _("Prin&t"), "PrintMap",
753     helptext = _("Print the map"))
754 bh 6
755     # Layer menu
756 jan 374 _method_command("layer_add", _("&Add Layer"), "AddLayer",
757     helptext = _("Add a new layer to active map"))
758     _method_command("layer_remove", _("&Remove Layer"), "RemoveLayer",
759     helptext = _("Remove selected layer(s)"),
760 bh 299 sensitive = _can_remove_layer)
761 jan 374 _method_command("layer_fill_color", _("&Fill Color"), "LayerFillColor",
762     helptext = _("Set the fill color of selected layer(s)"),
763 bh 6 sensitive = _has_selected_layer)
764 jan 374 _method_command("layer_transparent_fill", _("&Transparent Fill"),
765 bh 6 "LayerTransparentFill",
766 jan 374 helptext = _("Do not fill the selected layer(s)"),
767 bh 6 sensitive = _has_selected_layer)
768 jan 374 _method_command("layer_outline_color", _("&Outline Color"), "LayerOutlineColor",
769     helptext = _("Set the outline color of selected layer(s)"),
770 bh 6 sensitive = _has_selected_layer)
771 jan 374 _method_command("layer_no_outline", _("&No Outline"), "LayerNoOutline",
772     helptext= _("Do not draw the outline of the selected layer(s)"),
773 bh 6 sensitive = _has_selected_layer)
774 jan 374 _method_command("layer_raise", _("&Raise"), "RaiseLayer",
775     helptext = _("Raise selected layer(s)"),
776 bh 6 sensitive = _has_selected_layer)
777 jan 374 _method_command("layer_lower", _("&Lower"), "LowerLayer",
778     helptext = _("Lower selected layer(s)"),
779 bh 6 sensitive = _has_selected_layer)
780 jan 374 _method_command("layer_show", _("&Show"), "ShowLayer",
781     helptext = _("Make selected layer(s) visible"),
782 bh 6 sensitive = _has_selected_layer)
783 jan 374 _method_command("layer_hide", _("&Hide"), "HideLayer",
784     helptext = _("Make selected layer(s) unvisible"),
785 bh 6 sensitive = _has_selected_layer)
786 jan 374 _method_command("layer_show_table", _("Show Ta&ble"), "LayerShowTable",
787     helptext = _("Show the selected layer's table"),
788 bh 6 sensitive = _has_selected_layer)
789 jan 374 _method_command("layer_classifier", _("Classify"), "Classify",
790 jonathan 363 sensitive = _has_selected_layer)
791 bh 188
792     # the menu structure
793     main_menu = Menu("<main>", "<main>",
794 jan 374 [Menu("file", _("&File"),
795 bh 188 ["new_session", "open_session", None,
796     "save_session", "save_session_as", None,
797 jonathan 616 "show_session_tree",
798 jonathan 550 "show_legend", None,
799 bh 188 "exit"]),
800 jan 374 Menu("map", _("&Map"),
801 bh 188 ["layer_add", "layer_remove",
802     None,
803     "map_projection",
804     None,
805     "map_zoom_in_tool", "map_zoom_out_tool",
806     "map_pan_tool", "map_identify_tool", "map_label_tool",
807     None,
808     "map_full_extent",
809     None,
810     "map_print"]),
811 jan 374 Menu("layer", _("&Layer"),
812 bh 188 ["layer_fill_color", "layer_transparent_fill",
813     "layer_outline_color", "layer_no_outline",
814     None,
815     "layer_raise", "layer_lower",
816     None,
817     "layer_show", "layer_hide",
818     None,
819 jonathan 363 "layer_show_table",
820     None,
821     "layer_classifier"]),
822 jan 374 Menu("help", _("&Help"),
823 bh 188 ["help_about"])])
824 bh 191
825     # the main toolbar
826    
827     main_toolbar = Menu("<toolbar>", "<toolbar>",
828 frank 351 ["map_zoom_in_tool", "map_zoom_out_tool", "map_pan_tool",
829     "map_full_extent", None,
830     "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