/[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 829 - (hide annotations)
Tue May 6 12:06:38 2003 UTC (21 years, 10 months ago) by jonathan
Original Path: trunk/thuban/Thuban/UI/mainwindow.py
File MIME type: text/x-python
File size: 31869 byte(s)
Added new "Full selection extent" menu option.
(MainWindow.has_selected_shapes): New. Returns true if there are
        any selected shapes.
(MainWindow.FullSelectionExtent): New. Calls
        MapCanvas.FitSelectedToWindow() when the user selects the menu option.
(_has_selected_shapes): New. Returns true if there are any selected shapes.

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