/[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 49 - (show annotations)
Mon Sep 10 16:03:59 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: 18896 byte(s)
(MainWindow.IdentifyTool): Popup the identify view immediately

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