/[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 31 - (hide annotations)
Thu Sep 6 13:32:39 2001 UTC (23 years, 6 months ago) by bh
Original Path: trunk/thuban/Thuban/UI/mainwindow.py
File MIME type: text/x-python
File size: 18709 byte(s)
	* Thuban/UI/mainwindow.py (MainWindow.init_dialogs):
	(MainWindow.add_dialog):
	(MainWindow.dialog_open):
	(MainWindow.remove_dialog):
	(MainWindow.get_open_dialog): New methods to maintain a dictionary
	of opened non-modal dialogs.

	(MainWindow.__init__): Initialize the new non-modal dictionary
	management code
	(MainWindow.LayerShowTable): maintain separate dialogs for each
	table using the non-modal dialog management code to only open a
	view once for each table.

	(MainWindow.IdentifyTool):
	(MainWindow.__init__):
	(MainWindow.identify_view_on_demand): Don't open the identify view
	in IdentifyTool anymore. This will be done automatically by the
	new method identify_view_on_demand which handles the
	SELECTED_SHAPE message so that the identify view will be opened on
	demand

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