/[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 102 - (hide annotations)
Fri Apr 19 14:22:25 2002 UTC (22 years, 10 months ago) by jan
Original Path: trunk/thuban/Thuban/UI/mainwindow.py
File MIME type: text/x-python
File size: 19733 byte(s)
launch save as dialog for saving new sessions

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