/[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 622 - (hide annotations)
Mon Apr 7 10:54:32 2003 UTC (21 years, 11 months ago) by bh
Original Path: trunk/thuban/Thuban/UI/mainwindow.py
File MIME type: text/x-python
File size: 31146 byte(s)
(MainWindow.ShowSessionTree): Removed in
favor of ToggleSessionTree
(MainWindow.ToggleSessionTree): New method to toggle visibility of
the session tree.
(MainWindow.SessionTreeShown): New method to return whether the
session tree is currently shown.
(MainWindow.ToggleLegend): New method to toggle visibility of the
legend
(MainWindow.ShowLegend): Implement in terms of ToggleLegend and
LegendShown
(MainWindow.LegendShown): New method to return whether the legend
is currently shown.
(_method_command): Add checked parameter so we can define check
menu items
(_has_tree_window_shown, _has_legend_shown): Use the appropriate
mainwindow methods.
(show_session_tree, show_legend commands): Removed.
(toggle_session_tree, toggle_legend commands): New commands to
toggle the visibility of the dialogs

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