/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/UI/mainwindow.py
ViewVC logotype

Contents of /branches/WIP-pyshapelib-bramz/Thuban/UI/mainwindow.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 84 - (show annotations)
Wed Apr 3 15:21:46 2002 UTC (22 years, 11 months ago) by bh
Original Path: trunk/thuban/Thuban/UI/mainwindow.py
File MIME type: text/x-python
File size: 19654 byte(s)
	* Thuban/UI/mainwindow.py (MainWindow.__init__): Move the "Add
	Layer" and "Remove Layer" commands from the layer menu to the map
	menu

1 # 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, create_empty_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 from messages import SELECTED_SHAPE
34
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 def __init__(self, parent, ID, interactor):
44 wxFrame.__init__(self, parent, ID, 'Thuban',
45 wxDefaultPosition, wxSize(400, 300))
46
47 self.interactor = interactor
48
49 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 for name in ["layer_add", "layer_remove",
69 None,
70 "map_projection",
71 None,
72 "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 for name in ["layer_fill_color", "layer_transparent_fill",
83 "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
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 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 # call Realize to make sure that the tools appear.
110 toolbar.Realize()
111
112 # Create the map canvas
113 canvas = view.MapCanvas(self, -1, interactor)
114 self.canvas = canvas
115
116 self.init_dialogs()
117
118 interactor.Subscribe(SELECTED_SHAPE, self.identify_view_on_demand)
119
120 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 if command.IsCheckCommand():
195 event.Check(command.Checked(self))
196
197 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 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 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 def NewSession(self):
250 self.save_modified_session()
251 main.app.SetSession(create_empty_session())
252
253 def OpenSession(self):
254 self.save_modified_session()
255 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 main.app.SaveSession()
263
264 def SaveSessionAs(self):
265 dlg = wxFileDialog(self, "Enter a filename for session", ".", "",
266 "*.session", wxOPEN)
267 if dlg.ShowModal() == wxID_OK:
268 main.app.session.SetFilename(dlg.GetPath())
269 main.app.SaveSession()
270 dlg.Destroy()
271
272 def Exit(self):
273 self.Close(false)
274
275 def OnClose(self, event):
276 result = self.save_modified_session(can_veto = event.CanVeto())
277 if result == wxID_CANCEL:
278 event.Veto()
279 else:
280 self.Destroy()
281
282 def SetMap(self, map):
283 self.canvas.SetMap(map)
284
285 def ShowSessionTree(self):
286 name = "session_tree"
287 dialog = self.get_open_dialog(name)
288 if dialog is None:
289 dialog = tree.SessionTreeView(self, main.app, name)
290 self.add_dialog(name, dialog)
291 dialog.Show(true)
292 else:
293 # FIXME: bring dialog to front here
294 pass
295
296 def About(self):
297 self.RunMessageBox("About",
298 ("Thuban is a program for\n"
299 "exploring geographic data.\n"
300 "Copyright (C) 2001 Intevation GmbH.\n"
301 "Thuban is licensed under the GPL"),
302 wxOK | wxICON_INFORMATION)
303
304 def AddLayer(self):
305 dlg = wxFileDialog(self, "Select a session file", ".", "", "*.*",
306 wxOPEN)
307 if dlg.ShowModal() == wxID_OK:
308 filename = dlg.GetPath()
309 title = os.path.splitext(os.path.basename(filename))[0]
310 layer = Layer(title, filename)
311 map = self.canvas.Map()
312 has_layers = map.HasLayers()
313 try:
314 map.AddLayer(layer)
315 except IOError:
316 # the layer couldn't be opened
317 self.RunMessageBox("Add Layer",
318 "Can't open the file '%s'." % filename)
319 else:
320 if not has_layers:
321 # if we're adding a layer to an empty map, for the
322 # new map to the window
323 self.canvas.FitMapToWindow()
324 dlg.Destroy()
325
326 def RemoveLayer(self):
327 layer = self.current_layer()
328 if layer is not None:
329 self.canvas.Map().RemoveLayer(layer)
330
331 def RaiseLayer(self):
332 layer = self.current_layer()
333 if layer is not None:
334 self.canvas.Map().RaiseLayer(layer)
335
336 def LowerLayer(self):
337 layer = self.current_layer()
338 if layer is not None:
339 self.canvas.Map().LowerLayer(layer)
340
341 def current_layer(self):
342 """Return the currently selected layer.
343
344 If no layer is selected, return None
345 """
346 return self.interactor.SelectedLayer()
347
348 def has_selected_layer(self):
349 """Return true if a layer is currently selected"""
350 return self.interactor.HasSelectedLayer()
351
352 def choose_color(self):
353 """Run the color selection dialog and return the selected color.
354
355 If the user cancels, return None.
356 """
357 dlg = wxColourDialog(self)
358 color = None
359 if dlg.ShowModal() == wxID_OK:
360 data = dlg.GetColourData()
361 wxc = data.GetColour()
362 color = Color(wxc.Red() / 255.0,
363 wxc.Green() / 255.0,
364 wxc.Blue() / 255.0)
365 dlg.Destroy()
366 return color
367
368 def LayerFillColor(self):
369 layer = self.current_layer()
370 if layer is not None:
371 color = self.choose_color()
372 if color is not None:
373 layer.SetFill(color)
374
375 def LayerTransparentFill(self):
376 layer = self.current_layer()
377 if layer is not None:
378 layer.SetFill(None)
379
380 def LayerOutlineColor(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.SetStroke(color)
386
387 def LayerNoOutline(self):
388 layer = self.current_layer()
389 if layer is not None:
390 layer.SetStroke(None)
391
392 def HideLayer(self):
393 layer = self.current_layer()
394 if layer is not None:
395 layer.SetVisible(0)
396
397 def ShowLayer(self):
398 layer = self.current_layer()
399 if layer is not None:
400 layer.SetVisible(1)
401
402 def LayerShowTable(self):
403 layer = self.current_layer()
404 if layer is not None:
405 table = layer.table
406 name = "table_view" + str(id(table))
407 dialog = self.get_open_dialog(name)
408 if dialog is None:
409 dialog = tableview.TableFrame(self, self.interactor, name,
410 "Table: %s" % layer.Title(),
411 layer, table)
412 self.add_dialog(name, dialog)
413 dialog.Show(true)
414 else:
415 # FIXME: bring dialog to front here
416 pass
417
418 def Projection(self):
419 map = self.canvas.Map()
420 proj = map.projection
421 if proj is None:
422 proj4Dlg = proj4dialog.Proj4Dialog(NULL, None)
423 else:
424 proj4Dlg = proj4dialog.Proj4Dialog(NULL, map.projection.params)
425 if proj4Dlg.ShowModal() == wxID_OK:
426 params = proj4Dlg.GetParams()
427 if params is not None:
428 proj = Projection(params)
429 else:
430 proj = None
431 map.SetProjection(proj)
432 proj4Dlg.Destroy()
433
434 def ZoomInTool(self):
435 self.canvas.ZoomInTool()
436
437 def ZoomOutTool(self):
438 self.canvas.ZoomOutTool()
439
440 def PanTool(self):
441 self.canvas.PanTool()
442
443 def IdentifyTool(self):
444 self.canvas.IdentifyTool()
445 self.identify_view_on_demand(None, None)
446
447 def LabelTool(self):
448 self.canvas.LabelTool()
449
450 def FullExtent(self):
451 self.canvas.FitMapToWindow()
452
453 def PrintMap(self):
454 self.canvas.Print()
455
456 def identify_view_on_demand(self, layer, shape):
457 name = "identify_view"
458 if self.canvas.CurrentTool() == "IdentifyTool":
459 if not self.dialog_open(name):
460 dialog = identifyview.IdentifyView(self, self.interactor, name)
461 self.add_dialog(name, dialog)
462 dialog.Show(true)
463 else:
464 # FIXME: bring dialog to front?
465 pass
466
467 #
468 # Define all the commands available in the main window
469 #
470
471
472 # Helper functions to define common command implementations
473 def call_method(context, methodname, *args):
474 """Call the context's method methodname with args *args"""
475 apply(getattr(context, methodname), args)
476
477 def _method_command(name, title, method, helptext = "", sensitive = None):
478 """Add a command implemented by a method of the context object"""
479 registry.Add(Command(name, title, call_method, args=(method,),
480 helptext = helptext, sensitive = sensitive))
481 def _tool_command(name, title, method, toolname, helptext = "",
482 icon = ""):
483 """Add a tool command"""
484 def check_current_tool(context, name=toolname):
485 return context.canvas.CurrentTool() == name
486 registry.Add(Command(name, title, call_method, args=(method,),
487 helptext = helptext, icon = icon,
488 checked = check_current_tool))
489
490 def _has_selected_layer(context):
491 """Return true if a layer is selected in the context"""
492 return context.has_selected_layer()
493
494 # File menu
495 _method_command("new_session", "&New Session", "NewSession")
496 _method_command("open_session", "&Open Session", "OpenSession")
497 _method_command("save_session", "&Save Session", "SaveSession")
498 _method_command("save_session_as", "Save Session &As", "SaveSessionAs")
499 _method_command("exit", "&Exit", "Exit")
500
501 # Help menu
502 _method_command("help_about", "&About", "About")
503
504
505 # Map menu
506 _method_command("map_projection", "Pro&jection", "Projection")
507
508 _tool_command("map_zoom_in_tool", "&Zoom in", "ZoomInTool", "ZoomInTool",
509 helptext = "Switch to map-mode 'zoom-in'", icon = "zoom_in")
510 _tool_command("map_zoom_out_tool", "Zoom &out", "ZoomOutTool", "ZoomOutTool",
511 helptext = "Switch to map-mode 'zoom-out'", icon = "zoom_out")
512 _tool_command("map_pan_tool", "&Pan", "PanTool", "PanTool",
513 helptext = "Switch to map-mode 'pan'", icon = "pan")
514 _tool_command("map_identify_tool", "&Identify", "IdentifyTool", "IdentifyTool",
515 helptext = "Switch to map-mode 'identify'", icon = "identify")
516 _tool_command("map_label_tool", "&Label", "LabelTool", "LabelTool",
517 helptext = "Add/Remove labels", icon = "label")
518 _method_command("map_full_extent", "&Full extent", "FullExtent")
519 _method_command("map_print", "Prin&t", "PrintMap", helptext = "Print the map")
520
521 # Layer menu
522 _method_command("layer_add", "&Add Layer", "AddLayer",
523 helptext = "Add a new layer to active map")
524 _method_command("layer_remove", "&Remove Layer", "RemoveLayer",
525 helptext = "Remove selected layer(s)",
526 sensitive = _has_selected_layer)
527 _method_command("layer_fill_color", "&Fill Color", "LayerFillColor",
528 helptext = "Set the fill color of selected layer(s)",
529 sensitive = _has_selected_layer)
530 _method_command("layer_transparent_fill", "&Transparent Fill",
531 "LayerTransparentFill",
532 helptext = "Do not fill the selected layer(s)",
533 sensitive = _has_selected_layer)
534 _method_command("layer_ourline_color", "&Outline Color", "LayerOutlineColor",
535 helptext = "Set the outline color of selected layer(s)",
536 sensitive = _has_selected_layer)
537 _method_command("layer_no_outline", "&No Outline", "LayerNoOutline",
538 helptext = "Do not draw the outline of the selected layer(s)",
539 sensitive = _has_selected_layer)
540 _method_command("layer_raise", "&Raise", "RaiseLayer",
541 helptext = "Raise selected layer(s)",
542 sensitive = _has_selected_layer)
543 _method_command("layer_lower", "&Lower", "LowerLayer",
544 helptext = "Lower selected layer(s)",
545 sensitive = _has_selected_layer)
546 _method_command("layer_show", "&Show", "ShowLayer",
547 helptext = "Make selected layer(s) visible",
548 sensitive = _has_selected_layer)
549 _method_command("layer_hide", "&Hide", "HideLayer",
550 helptext = "Make selected layer(s) unvisible",
551 sensitive = _has_selected_layer)
552 _method_command("layer_show_table", "Show Ta&ble", "LayerShowTable",
553 helptext = "Show the selected layer's table",
554 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