1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
"""The MayaVi Engine meant to be used with Envisage.
"""
# Author: Prabhu Ramachandran <prabhu_r@users.sf.net>
# Copyright (c) 2005-2020, Enthought, Inc.
# License: BSD Style.
# Standard library imports.
import logging
# Enthought library imports.
from traits.api import Instance, on_trait_change, Str
from tvtk.plugins.scene.i_scene_manager import \
ISceneManager
from tvtk.plugins.scene.ui.actions import NewScene
from tvtk.plugins.scene import scene_editor
from pyface.api import GUI
from pyface.workbench.api import WorkbenchWindow
from apptools.scripting.api import recordable
# Local imports.
from mayavi.core.engine import Engine
logger = logging.getLogger()
######################################################################
# `EnvisageEngine` class
######################################################################
class EnvisageEngine(Engine):
# The version of this class. Used for persistence.
__version__ = 0
# The envisage application.
window = Instance(WorkbenchWindow)
# Our name.
name = Str('Mayavi Envisage Engine')
######################################################################
# `object` interface
######################################################################
def __get_pure_state__(self):
d = super(EnvisageEngine, self).__get_pure_state__()
for x in ['window',]:
d.pop(x, None)
return d
######################################################################
# `Engine` interface
######################################################################
def start(self):
"""This starts the engine. Only after the engine starts is it
possible to use mayavi. This particular method is called
automatically when the window is opened."""
if self.running:
return
# Add all the existing scenes from the scene plugin.
scene_manager = self.window.get_service(ISceneManager)
for scene in scene_manager.scenes:
self.add_scene(scene)
# Setup a handler that is invoked when a new Scene is
# added/removed.
scene_manager.on_trait_change(self._scene_editors_changed,
'scenes_items')
# Call the parent start method.
super(EnvisageEngine, self).start()
logger.debug ('--------- EnvisageEngine started ----------')
def stop(self):
# Call the parent stop method.
super(EnvisageEngine, self).stop()
@recordable
def new_scene(self, viewer=None, name=None, **kwargs):
""" Creates a new VTK scene window.
For the time being the extra kwargs are ignored with the
envisage engine.
"""
action = NewScene(window=self.window)
editor = action.perform(None)
if name is not None:
editor.name = name
# Flush the UI.
GUI.process_events()
return self.scenes[-1]
@recordable
def close_scene(self, scene):
"""Given a VTK scene instance, this method closes it.
"""
active_window = self.window
s = scene.scene
for editor in active_window.editors[:]:
if isinstance(editor, scene_editor.SceneEditor):
if id(editor.scene) == id(s):
editor.close()
break
# Flush the UI.
GUI.process_events()
######################################################################
# Non-public interface
######################################################################
def _scene_editors_changed(self, list_event):
"""This is called when the items of the editors trait of the
SceneManager change. This is used to update `self.scenes`."""
# Remove any removed scenes.
for scene in list_event.removed:
self.remove_scene(scene)
# Add any new scenes.
for scene in list_event.added:
self.add_scene(scene)
@on_trait_change('window:opened')
def _on_window_opened(self, obj, trait_name, old, new):
"""We start the engine when the window is opened."""
if trait_name == 'opened':
self.start()
@on_trait_change('window:closed')
def _on_window_closed(self, obj, trait_name, old, new):
"""We stop the engine when the window is closed."""
if trait_name == 'closed':
self.stop()
def _window_changed(self, old, new):
"""Static trait handler."""
# This is needed since the service may be offered *after* the
# window is opened in which case the _on_window_opened will do
# nothing.
sm = new.get_service(ISceneManager)
if sm is not None:
self.start()
@on_trait_change('window:editors[]')
def _sync_scene_editor_name(self, obj, trait_name, old, new):
"""Synchronize the Mayavi scene's name trait with that of the
editor's name."""
if trait_name.startswith('editors'):
scenes = list(self.scenes)
scenes.reverse()
for editor in new:
if not hasattr(editor, 'scene'):
continue
for scene in scenes:
if id(editor.scene) == id(scene.scene):
editor.name = scene.name
scene.sync_trait('name', editor, 'name')
break
|