/[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 123 - (hide annotations)
Mon Apr 29 18:05:04 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: 20280 byte(s)
	* Thuban/UI/mainwindow.py (MainWindow.__init__): Subscribe to the
	canvas' VIEW_POSITION event
	(MainWindow.view_position_changed): Handler for VIEW_POSITION.
	Update the text in the status-bar accordingly.

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