/[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 119 - (hide annotations)
Fri Apr 26 09:30:41 2002 UTC (22 years, 10 months ago) by frank
Original Path: trunk/thuban/Thuban/UI/mainwindow.py
File MIME type: text/x-python
File size: 19966 byte(s)
AddLayer: Dialog title changed: s/session/data

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 jan 110 "map_identify_tool", "map_label_tool", "map_full_extent"]:
108 bh 6 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 frank 119 dlg = wxFileDialog(self, "Select a data file", ".", "", "*.*",
308 bh 6 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 jan 110 proj4Dlg = proj4dialog.Proj4Dialog(NULL, None, map.BoundingBox())
425 bh 6 else:
426 jan 110 proj4Dlg = proj4dialog.Proj4Dialog(NULL, map.projection.params,
427     map.BoundingBox())
428 bh 6 if proj4Dlg.ShowModal() == wxID_OK:
429     params = proj4Dlg.GetParams()
430     if params is not None:
431     proj = Projection(params)
432     else:
433     proj = None
434     map.SetProjection(proj)
435     proj4Dlg.Destroy()
436    
437     def ZoomInTool(self):
438     self.canvas.ZoomInTool()
439    
440     def ZoomOutTool(self):
441     self.canvas.ZoomOutTool()
442    
443     def PanTool(self):
444     self.canvas.PanTool()
445    
446     def IdentifyTool(self):
447     self.canvas.IdentifyTool()
448 bh 49 self.identify_view_on_demand(None, None)
449 bh 6
450     def LabelTool(self):
451     self.canvas.LabelTool()
452    
453     def FullExtent(self):
454     self.canvas.FitMapToWindow()
455    
456     def PrintMap(self):
457     self.canvas.Print()
458    
459 bh 31 def identify_view_on_demand(self, layer, shape):
460     name = "identify_view"
461     if self.canvas.CurrentTool() == "IdentifyTool":
462     if not self.dialog_open(name):
463 bh 37 dialog = identifyview.IdentifyView(self, self.interactor, name)
464 bh 31 self.add_dialog(name, dialog)
465     dialog.Show(true)
466     else:
467 bh 33 # FIXME: bring dialog to front?
468 bh 31 pass
469 bh 6
470     #
471     # Define all the commands available in the main window
472     #
473    
474    
475     # Helper functions to define common command implementations
476     def call_method(context, methodname, *args):
477     """Call the context's method methodname with args *args"""
478     apply(getattr(context, methodname), args)
479    
480 jan 110 def _method_command(name, title, method, helptext = "",
481     icon = "", sensitive = None):
482 bh 6 """Add a command implemented by a method of the context object"""
483     registry.Add(Command(name, title, call_method, args=(method,),
484 jan 110 helptext = helptext, icon = icon,
485     sensitive = sensitive))
486    
487 bh 6 def _tool_command(name, title, method, toolname, helptext = "",
488     icon = ""):
489     """Add a tool command"""
490     def check_current_tool(context, name=toolname):
491     return context.canvas.CurrentTool() == name
492     registry.Add(Command(name, title, call_method, args=(method,),
493     helptext = helptext, icon = icon,
494     checked = check_current_tool))
495    
496     def _has_selected_layer(context):
497     """Return true if a layer is selected in the context"""
498     return context.has_selected_layer()
499    
500     # File menu
501     _method_command("new_session", "&New Session", "NewSession")
502     _method_command("open_session", "&Open Session", "OpenSession")
503     _method_command("save_session", "&Save Session", "SaveSession")
504     _method_command("save_session_as", "Save Session &As", "SaveSessionAs")
505     _method_command("exit", "&Exit", "Exit")
506    
507     # Help menu
508     _method_command("help_about", "&About", "About")
509    
510    
511     # Map menu
512     _method_command("map_projection", "Pro&jection", "Projection")
513    
514     _tool_command("map_zoom_in_tool", "&Zoom in", "ZoomInTool", "ZoomInTool",
515     helptext = "Switch to map-mode 'zoom-in'", icon = "zoom_in")
516     _tool_command("map_zoom_out_tool", "Zoom &out", "ZoomOutTool", "ZoomOutTool",
517     helptext = "Switch to map-mode 'zoom-out'", icon = "zoom_out")
518     _tool_command("map_pan_tool", "&Pan", "PanTool", "PanTool",
519     helptext = "Switch to map-mode 'pan'", icon = "pan")
520     _tool_command("map_identify_tool", "&Identify", "IdentifyTool", "IdentifyTool",
521     helptext = "Switch to map-mode 'identify'", icon = "identify")
522     _tool_command("map_label_tool", "&Label", "LabelTool", "LabelTool",
523     helptext = "Add/Remove labels", icon = "label")
524 jan 110 _method_command("map_full_extent", "&Full extent", "FullExtent",
525     helptext = "Full Extent", icon = "fullextent")
526 bh 6 _method_command("map_print", "Prin&t", "PrintMap", helptext = "Print the map")
527    
528     # Layer menu
529 bh 84 _method_command("layer_add", "&Add Layer", "AddLayer",
530 bh 6 helptext = "Add a new layer to active map")
531 bh 84 _method_command("layer_remove", "&Remove Layer", "RemoveLayer",
532 bh 6 helptext = "Remove selected layer(s)",
533     sensitive = _has_selected_layer)
534     _method_command("layer_fill_color", "&Fill Color", "LayerFillColor",
535     helptext = "Set the fill color of selected layer(s)",
536     sensitive = _has_selected_layer)
537     _method_command("layer_transparent_fill", "&Transparent Fill",
538     "LayerTransparentFill",
539     helptext = "Do not fill the selected layer(s)",
540     sensitive = _has_selected_layer)
541     _method_command("layer_ourline_color", "&Outline Color", "LayerOutlineColor",
542     helptext = "Set the outline color of selected layer(s)",
543     sensitive = _has_selected_layer)
544     _method_command("layer_no_outline", "&No Outline", "LayerNoOutline",
545     helptext = "Do not draw the outline of the selected layer(s)",
546     sensitive = _has_selected_layer)
547     _method_command("layer_raise", "&Raise", "RaiseLayer",
548     helptext = "Raise selected layer(s)",
549     sensitive = _has_selected_layer)
550     _method_command("layer_lower", "&Lower", "LowerLayer",
551     helptext = "Lower selected layer(s)",
552     sensitive = _has_selected_layer)
553     _method_command("layer_show", "&Show", "ShowLayer",
554     helptext = "Make selected layer(s) visible",
555     sensitive = _has_selected_layer)
556     _method_command("layer_hide", "&Hide", "HideLayer",
557     helptext = "Make selected layer(s) unvisible",
558     sensitive = _has_selected_layer)
559     _method_command("layer_show_table", "Show Ta&ble", "LayerShowTable",
560     helptext = "Show the selected layer's table",
561     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