/[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 150 - (hide annotations)
Tue May 7 16:55:38 2002 UTC (22 years, 10 months ago) by bh
Original Path: trunk/thuban/Thuban/UI/mainwindow.py
File MIME type: text/x-python
File size: 20404 byte(s)
	* Thuban/UI/mainwindow.py (MainWindow.__init__): Add the "Show
	Session Tree" command to the file menu.

1 bh 123 # Copyright (C) 2001, 2002 by Intevation GmbH
2 bh 6 # Authors:
3     # Jan-Oliver Wagner <[email protected]>
4     # Bernhard Herzog <[email protected]>
5     #
6     # This program is free software under the GPL (>=v2)
7     # Read the file COPYING coming with Thuban for details.
8    
9     """
10     The main window
11     """
12    
13     __version__ = "$Revision$"
14    
15     import sys, os
16    
17     from wxPython.wx import *
18    
19     import Thuban
20 bh 58 from Thuban.Model.session import Session, create_empty_session
21 bh 6 from Thuban.Model.map import Map
22     from Thuban.Model.layer import Layer
23     from Thuban.Model.color import Color
24     from Thuban.Model.proj import Projection
25    
26     import view
27     import tree
28     import proj4dialog
29     import tableview, identifyview
30    
31     import main
32     from command import registry, Command
33 bh 123 from messages import SELECTED_SHAPE, VIEW_POSITION
34 bh 6
35    
36     # the directory where the toolbar icons are stored
37     bitmapdir = os.path.join(Thuban.__path__[0], os.pardir, "Resources", "Bitmaps")
38     bitmapext = ".xpm"
39    
40    
41     class MainWindow(wxFrame):
42    
43 bh 24 def __init__(self, parent, ID, interactor):
44 bh 6 wxFrame.__init__(self, parent, ID, 'Thuban',
45     wxDefaultPosition, wxSize(400, 300))
46    
47 bh 37 self.interactor = interactor
48    
49 bh 6 self.CreateStatusBar()
50     self.SetStatusText("This is the wxPython-based "
51     "Graphical User Interface for exploring geographic data")
52    
53     self.identify_view = None
54    
55     self.init_ids()
56    
57     menuBar = wxMenuBar()
58    
59     menu = wxMenu()
60     menuBar.Append(menu, "&File");
61     for name in ["new_session", "open_session", None,
62     "save_session", "save_session_as", None,
63 bh 150 "show_session_tree", None,
64 bh 6 "exit"]:
65     self.add_menu_command(menu, name)
66    
67     menu = wxMenu()
68     menuBar.Append(menu, "&Map");
69 bh 84 for name in ["layer_add", "layer_remove",
70 bh 6 None,
71 bh 84 "map_projection",
72     None,
73 bh 6 "map_zoom_in_tool", "map_zoom_out_tool", "map_pan_tool",
74     "map_identify_tool", "map_label_tool",
75     None,
76     "map_full_extent",
77     None,
78     "map_print"]:
79     self.add_menu_command(menu, name)
80    
81     menu = wxMenu()
82     menuBar.Append(menu, "&Layer");
83 bh 84 for name in ["layer_fill_color", "layer_transparent_fill",
84 bh 6 "layer_ourline_color", "layer_no_outline",
85     None,
86     "layer_raise", "layer_lower",
87     None,
88     "layer_show", "layer_hide",
89     None,
90     "layer_show_table"]:
91     self.add_menu_command(menu, name)
92    
93     menu = wxMenu()
94     menuBar.Append(menu, "&Help");
95     self.add_menu_command(menu, "help_about")
96    
97     self.SetMenuBar(menuBar)
98    
99     # toolbar
100     toolbar = self.CreateToolBar(wxTB_3DBUTTONS)
101 bh 58
102     # set the size of the tools' bitmaps. Not needed on wxGTK, but
103     # on Windows. We probably shouldn't hardwire the bitmap size
104     # here
105     toolbar.SetToolBitmapSize(wxSize(24, 24))
106    
107 bh 6 for name in ["map_zoom_in_tool", "map_zoom_out_tool", "map_pan_tool",
108 jan 110 "map_identify_tool", "map_label_tool", "map_full_extent"]:
109 bh 6 self.add_toolbar_command(toolbar, name)
110 bh 13 # call Realize to make sure that the tools appear.
111     toolbar.Realize()
112 bh 6
113     # Create the map canvas
114 bh 24 canvas = view.MapCanvas(self, -1, interactor)
115 bh 123 canvas.Subscribe(VIEW_POSITION, self.view_position_changed)
116 bh 6 self.canvas = canvas
117    
118 bh 31 self.init_dialogs()
119    
120     interactor.Subscribe(SELECTED_SHAPE, self.identify_view_on_demand)
121    
122 bh 6 EVT_CLOSE(self, self.OnClose)
123    
124     def init_ids(self):
125     """Initialize the ids"""
126     self.current_id = 6000
127     self.id_to_name = {}
128     self.name_to_id = {}
129    
130     def get_id(self, name):
131     """Return the wxWindows id for the command named name.
132    
133     Create a new one if there isn't one yet"""
134     ID = self.name_to_id.get(name)
135     if ID is None:
136     ID = self.current_id
137     self.current_id = self.current_id + 1
138     self.name_to_id[name] = ID
139     self.id_to_name[ID] = name
140     return ID
141    
142     def add_menu_command(self, menu, name):
143     """Add the command with name name to the menu menu.
144    
145     If name is None, add a separator.
146     """
147     if name is None:
148     menu.AppendSeparator()
149     else:
150     command = registry.Command(name)
151     if command is not None:
152     ID = self.get_id(name)
153     menu.Append(ID, command.Title(), command.HelpText(),
154     command.IsCheckCommand())
155     EVT_MENU(self, ID, self.invoke_command)
156     if command.IsDynamic():
157     EVT_UPDATE_UI(self, ID, self.update_command_ui)
158     else:
159     print "Unknown command %s" % name
160    
161     def add_toolbar_command(self, toolbar, name):
162     """Add the command with name name to the toolbar toolbar.
163    
164     If name is None, add a separator.
165     """
166     # Assume that all toolbar commands are also menu commmands so
167     # that we don't have to add the event handlers here
168     if name is None:
169     toolbar.AddSeparator()
170     else:
171     command = registry.Command(name)
172     if command is not None:
173     ID = self.get_id(name)
174     filename = os.path.join(bitmapdir, command.Icon()) + bitmapext
175     bitmap = wxBitmap(filename, wxBITMAP_TYPE_XPM)
176     toolbar.AddTool(ID, bitmap,
177     shortHelpString = command.HelpText(),
178     isToggle = command.IsCheckCommand())
179     else:
180     print "Unknown command %s" % name
181    
182     def invoke_command(self, event):
183     name = self.id_to_name.get(event.GetId())
184     if name is not None:
185     command = registry.Command(name)
186     command.Execute(self)
187     else:
188     print "Unknown command ID %d" % event.GetId()
189    
190     def update_command_ui(self, event):
191     #print "update_command_ui", self.id_to_name[event.GetId()]
192     command = registry.Command(self.id_to_name[event.GetId()])
193     if command is not None:
194     event.Enable(command.Sensitive(self))
195     event.SetText(command.DynText(self))
196 bh 13 if command.IsCheckCommand():
197     event.Check(command.Checked(self))
198 bh 6
199 bh 20 def RunMessageBox(self, title, text, flags = wxOK | wxICON_INFORMATION):
200     """Run a modla message box with the given text, title and flags
201     and return the result"""
202     dlg = wxMessageDialog(self, text, title, flags)
203     result = dlg.ShowModal()
204     dlg.Destroy()
205     return result
206    
207 bh 31 def init_dialogs(self):
208     """Initialize the dialog handling"""
209     # The mainwindow maintains a dict mapping names to open
210     # non-modal dialogs. The dialogs are put into this dict when
211     # they're created and removed when they're closed
212     self.dialogs = {}
213    
214     def add_dialog(self, name, dialog):
215     if self.dialogs.has_key(name):
216     raise RuntimeError("The Dialog named %s is already open" % name)
217     self.dialogs[name] = dialog
218    
219     def dialog_open(self, name):
220     return self.dialogs.has_key(name)
221    
222     def remove_dialog(self, name):
223     del self.dialogs[name]
224    
225     def get_open_dialog(self, name):
226     return self.dialogs.get(name)
227    
228 bh 123 def view_position_changed(self):
229     pos = self.canvas.CurrentPosition()
230     if pos is not None:
231     text = "(%10.10g, %10.10g)" % pos
232     else:
233     text = ""
234     self.SetStatusText(text)
235    
236 bh 58 def save_modified_session(self, can_veto = 1):
237     """If the current session has been modified, ask the user
238     whether to save it and do so if requested. Return the outcome of
239     the dialog (either wxID_OK, wxID_CANCEL or wxID_NO). If the
240     dialog wasn't run return wxID_NO.
241    
242     If the can_veto parameter is true (default) the dialog includes
243     a cancel button, otherwise not.
244     """
245     if main.app.session.WasModified():
246     flags = wxYES_NO | wxICON_QUESTION
247     if can_veto:
248     flags = flags | wxCANCEL
249     result = self.RunMessageBox("Exit",
250     ("The session has been modified."
251     " Do you want to save it?"),
252     flags)
253     if result == wxID_YES:
254     self.SaveSession()
255     else:
256     result = wxID_NO
257     return result
258    
259 bh 6 def NewSession(self):
260 bh 58 self.save_modified_session()
261     main.app.SetSession(create_empty_session())
262 bh 6
263     def OpenSession(self):
264 bh 58 self.save_modified_session()
265 bh 6 dlg = wxFileDialog(self, "Select a session file", ".", "",
266 bh 130 "*.thuban", wxOPEN)
267 bh 6 if dlg.ShowModal() == wxID_OK:
268     main.app.OpenSession(dlg.GetPath())
269     dlg.Destroy()
270    
271     def SaveSession(self):
272 jan 102 if main.app.session.filename == None:
273     self.SaveSessionAs()
274 bh 6 main.app.SaveSession()
275    
276     def SaveSessionAs(self):
277     dlg = wxFileDialog(self, "Enter a filename for session", ".", "",
278 bh 130 "*.thuban", wxOPEN)
279 bh 6 if dlg.ShowModal() == wxID_OK:
280     main.app.session.SetFilename(dlg.GetPath())
281     main.app.SaveSession()
282     dlg.Destroy()
283    
284     def Exit(self):
285     self.Close(false)
286    
287     def OnClose(self, event):
288 bh 58 result = self.save_modified_session(can_veto = event.CanVeto())
289     if result == wxID_CANCEL:
290 bh 6 event.Veto()
291     else:
292     self.Destroy()
293    
294     def SetMap(self, map):
295     self.canvas.SetMap(map)
296    
297 bh 37 def ShowSessionTree(self):
298     name = "session_tree"
299     dialog = self.get_open_dialog(name)
300     if dialog is None:
301     dialog = tree.SessionTreeView(self, main.app, name)
302     self.add_dialog(name, dialog)
303     dialog.Show(true)
304     else:
305     # FIXME: bring dialog to front here
306     pass
307    
308 bh 6 def About(self):
309 bh 20 self.RunMessageBox("About",
310     ("Thuban is a program for\n"
311     "exploring geographic data.\n"
312     "Copyright (C) 2001 Intevation GmbH.\n"
313     "Thuban is licensed under the GPL"),
314     wxOK | wxICON_INFORMATION)
315 bh 6
316     def AddLayer(self):
317 frank 119 dlg = wxFileDialog(self, "Select a data file", ".", "", "*.*",
318 bh 6 wxOPEN)
319     if dlg.ShowModal() == wxID_OK:
320     filename = dlg.GetPath()
321     title = os.path.splitext(os.path.basename(filename))[0]
322     layer = Layer(title, filename)
323 bh 18 map = self.canvas.Map()
324     has_layers = map.HasLayers()
325 bh 20 try:
326     map.AddLayer(layer)
327     except IOError:
328     # the layer couldn't be opened
329     self.RunMessageBox("Add Layer",
330     "Can't open the file '%s'." % filename)
331     else:
332     if not has_layers:
333     # if we're adding a layer to an empty map, for the
334     # new map to the window
335     self.canvas.FitMapToWindow()
336 bh 6 dlg.Destroy()
337    
338     def RemoveLayer(self):
339     layer = self.current_layer()
340     if layer is not None:
341     self.canvas.Map().RemoveLayer(layer)
342    
343     def RaiseLayer(self):
344     layer = self.current_layer()
345     if layer is not None:
346     self.canvas.Map().RaiseLayer(layer)
347    
348     def LowerLayer(self):
349     layer = self.current_layer()
350     if layer is not None:
351     self.canvas.Map().LowerLayer(layer)
352    
353     def current_layer(self):
354     """Return the currently selected layer.
355    
356     If no layer is selected, return None
357     """
358 bh 37 return self.interactor.SelectedLayer()
359 bh 6
360     def has_selected_layer(self):
361     """Return true if a layer is currently selected"""
362 bh 37 return self.interactor.HasSelectedLayer()
363 bh 6
364     def choose_color(self):
365     """Run the color selection dialog and return the selected color.
366    
367     If the user cancels, return None.
368     """
369     dlg = wxColourDialog(self)
370     color = None
371     if dlg.ShowModal() == wxID_OK:
372     data = dlg.GetColourData()
373     wxc = data.GetColour()
374     color = Color(wxc.Red() / 255.0,
375     wxc.Green() / 255.0,
376     wxc.Blue() / 255.0)
377     dlg.Destroy()
378     return color
379    
380     def LayerFillColor(self):
381     layer = self.current_layer()
382     if layer is not None:
383     color = self.choose_color()
384     if color is not None:
385     layer.SetFill(color)
386    
387     def LayerTransparentFill(self):
388     layer = self.current_layer()
389     if layer is not None:
390     layer.SetFill(None)
391    
392     def LayerOutlineColor(self):
393     layer = self.current_layer()
394     if layer is not None:
395     color = self.choose_color()
396     if color is not None:
397     layer.SetStroke(color)
398    
399     def LayerNoOutline(self):
400     layer = self.current_layer()
401     if layer is not None:
402     layer.SetStroke(None)
403    
404     def HideLayer(self):
405     layer = self.current_layer()
406     if layer is not None:
407     layer.SetVisible(0)
408    
409     def ShowLayer(self):
410     layer = self.current_layer()
411     if layer is not None:
412     layer.SetVisible(1)
413    
414     def LayerShowTable(self):
415     layer = self.current_layer()
416     if layer is not None:
417 bh 31 table = layer.table
418     name = "table_view" + str(id(table))
419     dialog = self.get_open_dialog(name)
420     if dialog is None:
421 bh 37 dialog = tableview.TableFrame(self, self.interactor, name,
422 bh 31 "Table: %s" % layer.Title(),
423 bh 33 layer, table)
424 bh 31 self.add_dialog(name, dialog)
425     dialog.Show(true)
426     else:
427     # FIXME: bring dialog to front here
428     pass
429 bh 6
430     def Projection(self):
431     map = self.canvas.Map()
432     proj = map.projection
433     if proj is None:
434 jan 110 proj4Dlg = proj4dialog.Proj4Dialog(NULL, None, map.BoundingBox())
435 bh 6 else:
436 jan 110 proj4Dlg = proj4dialog.Proj4Dialog(NULL, map.projection.params,
437     map.BoundingBox())
438 bh 6 if proj4Dlg.ShowModal() == wxID_OK:
439     params = proj4Dlg.GetParams()
440     if params is not None:
441     proj = Projection(params)
442     else:
443     proj = None
444     map.SetProjection(proj)
445     proj4Dlg.Destroy()
446    
447     def ZoomInTool(self):
448     self.canvas.ZoomInTool()
449    
450     def ZoomOutTool(self):
451     self.canvas.ZoomOutTool()
452    
453     def PanTool(self):
454     self.canvas.PanTool()
455    
456     def IdentifyTool(self):
457     self.canvas.IdentifyTool()
458 bh 49 self.identify_view_on_demand(None, None)
459 bh 6
460     def LabelTool(self):
461     self.canvas.LabelTool()
462    
463     def FullExtent(self):
464     self.canvas.FitMapToWindow()
465    
466     def PrintMap(self):
467     self.canvas.Print()
468    
469 bh 31 def identify_view_on_demand(self, layer, shape):
470     name = "identify_view"
471     if self.canvas.CurrentTool() == "IdentifyTool":
472     if not self.dialog_open(name):
473 bh 37 dialog = identifyview.IdentifyView(self, self.interactor, name)
474 bh 31 self.add_dialog(name, dialog)
475     dialog.Show(true)
476     else:
477 bh 33 # FIXME: bring dialog to front?
478 bh 31 pass
479 bh 6
480     #
481     # Define all the commands available in the main window
482     #
483    
484    
485     # Helper functions to define common command implementations
486     def call_method(context, methodname, *args):
487     """Call the context's method methodname with args *args"""
488     apply(getattr(context, methodname), args)
489    
490 jan 110 def _method_command(name, title, method, helptext = "",
491     icon = "", sensitive = None):
492 bh 6 """Add a command implemented by a method of the context object"""
493     registry.Add(Command(name, title, call_method, args=(method,),
494 jan 110 helptext = helptext, icon = icon,
495     sensitive = sensitive))
496    
497 bh 6 def _tool_command(name, title, method, toolname, helptext = "",
498     icon = ""):
499     """Add a tool command"""
500     def check_current_tool(context, name=toolname):
501     return context.canvas.CurrentTool() == name
502     registry.Add(Command(name, title, call_method, args=(method,),
503     helptext = helptext, icon = icon,
504     checked = check_current_tool))
505    
506     def _has_selected_layer(context):
507     """Return true if a layer is selected in the context"""
508     return context.has_selected_layer()
509    
510     # File menu
511     _method_command("new_session", "&New Session", "NewSession")
512     _method_command("open_session", "&Open Session", "OpenSession")
513     _method_command("save_session", "&Save Session", "SaveSession")
514     _method_command("save_session_as", "Save Session &As", "SaveSessionAs")
515 bh 150 _method_command("show_session_tree", "Show Session &Tree", "ShowSessionTree")
516 bh 6 _method_command("exit", "&Exit", "Exit")
517    
518     # Help menu
519     _method_command("help_about", "&About", "About")
520    
521    
522     # Map menu
523     _method_command("map_projection", "Pro&jection", "Projection")
524    
525     _tool_command("map_zoom_in_tool", "&Zoom in", "ZoomInTool", "ZoomInTool",
526     helptext = "Switch to map-mode 'zoom-in'", icon = "zoom_in")
527     _tool_command("map_zoom_out_tool", "Zoom &out", "ZoomOutTool", "ZoomOutTool",
528     helptext = "Switch to map-mode 'zoom-out'", icon = "zoom_out")
529     _tool_command("map_pan_tool", "&Pan", "PanTool", "PanTool",
530     helptext = "Switch to map-mode 'pan'", icon = "pan")
531     _tool_command("map_identify_tool", "&Identify", "IdentifyTool", "IdentifyTool",
532     helptext = "Switch to map-mode 'identify'", icon = "identify")
533     _tool_command("map_label_tool", "&Label", "LabelTool", "LabelTool",
534     helptext = "Add/Remove labels", icon = "label")
535 jan 110 _method_command("map_full_extent", "&Full extent", "FullExtent",
536     helptext = "Full Extent", icon = "fullextent")
537 bh 6 _method_command("map_print", "Prin&t", "PrintMap", helptext = "Print the map")
538    
539     # Layer menu
540 bh 84 _method_command("layer_add", "&Add Layer", "AddLayer",
541 bh 6 helptext = "Add a new layer to active map")
542 bh 84 _method_command("layer_remove", "&Remove Layer", "RemoveLayer",
543 bh 6 helptext = "Remove selected layer(s)",
544     sensitive = _has_selected_layer)
545     _method_command("layer_fill_color", "&Fill Color", "LayerFillColor",
546     helptext = "Set the fill color of selected layer(s)",
547     sensitive = _has_selected_layer)
548     _method_command("layer_transparent_fill", "&Transparent Fill",
549     "LayerTransparentFill",
550     helptext = "Do not fill the selected layer(s)",
551     sensitive = _has_selected_layer)
552     _method_command("layer_ourline_color", "&Outline Color", "LayerOutlineColor",
553     helptext = "Set the outline color of selected layer(s)",
554     sensitive = _has_selected_layer)
555     _method_command("layer_no_outline", "&No Outline", "LayerNoOutline",
556     helptext = "Do not draw the outline of the selected layer(s)",
557     sensitive = _has_selected_layer)
558     _method_command("layer_raise", "&Raise", "RaiseLayer",
559     helptext = "Raise selected layer(s)",
560     sensitive = _has_selected_layer)
561     _method_command("layer_lower", "&Lower", "LowerLayer",
562     helptext = "Lower selected layer(s)",
563     sensitive = _has_selected_layer)
564     _method_command("layer_show", "&Show", "ShowLayer",
565     helptext = "Make selected layer(s) visible",
566     sensitive = _has_selected_layer)
567     _method_command("layer_hide", "&Hide", "HideLayer",
568     helptext = "Make selected layer(s) unvisible",
569     sensitive = _has_selected_layer)
570     _method_command("layer_show_table", "Show Ta&ble", "LayerShowTable",
571     helptext = "Show the selected layer's table",
572     sensitive = _has_selected_layer)

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26