Skip to content

Commit

Permalink
add a vtk control
Browse files Browse the repository at this point in the history
  • Loading branch information
sccolbert committed Feb 11, 2014
1 parent 2ab09c6 commit b042621
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 0 deletions.
6 changes: 6 additions & 0 deletions enaml/qt/qt_factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,11 @@ def tool_bar_factory():
return QtToolBar


def vtk_canvas_factory():
from .qt_vtk_canvas import QtVTKCanvas
return QtVTKCanvas


def web_view_factory():
from .qt_web_view import QtWebView
return QtWebView
Expand Down Expand Up @@ -339,6 +344,7 @@ def window_factory():
'TimeSelector': time_selector_factory,
'Timer': timer_factory,
'ToolBar': tool_bar_factory,
'VTKCanvas': vtk_canvas_factory,
'WebView': web_view_factory,
'Window': window_factory,
}
97 changes: 97 additions & 0 deletions enaml/qt/qt_vtk_canvas.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#------------------------------------------------------------------------------
# Copyright (c) 2013, Nucleic Development Team.
#
# Distributed under the terms of the Modified BSD License.
#
# The full license is in the file COPYING.txt, distributed with this software.
#------------------------------------------------------------------------------
from atom.api import Typed

from enaml.widgets.vtk_canvas import ProxyVTKCanvas

from vtk.qt4.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor

from .QtGui import QFrame, QVBoxLayout

from .qt_control import QtControl


class QtVTKCanvas(QtControl, ProxyVTKCanvas):
""" A Qt implementation of an Enaml ProxyVTKCanvas.
"""
#: A reference to the widget created by the proxy.
widget = Typed(QFrame)

#: A reference to the underlying vtk widget.
vtk_widget = Typed(QVTKRenderWindowInteractor)

#: The set of current renderers installed on the window.
_current_renderers = Typed(set, ())

#--------------------------------------------------------------------------
# Initialization API
#--------------------------------------------------------------------------
def create_widget(self):
""" Create the underlying widget.
"""
# The vtk widget is nested in a QFrame because the Qt render
# window interactor does not support reparenting.
widget = QFrame(self.parent_widget())
vtk_widget = QVTKRenderWindowInteractor(widget)
layout = QVBoxLayout()
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(0)
layout.addWidget(vtk_widget)
widget.setLayout(layout)
self.widget = widget
self.vtk_widget = vtk_widget

def init_widget(self):
""" Initialize the underlying widget.
"""
super(QtVTKCanvas, self).init_widget()
self._refresh_renderers()
self.vtk_widget.Initialize()

#--------------------------------------------------------------------------
# ProxyVTKCanvas API
#--------------------------------------------------------------------------
def set_renderer(self, renderer):
""" Set the renderer for the widget.
"""
self._refresh_renderers()

def set_renderers(self, renderers):
""" Set the renderers for the widget.
"""
self._refresh_renderers()

def render(self):
""" Request a render of the underlying scene.
"""
self.vtk_widget.Render()

#--------------------------------------------------------------------------
# Private API
#--------------------------------------------------------------------------
def _refresh_renderers(self):
""" Refresh the renderers installed on the render window.
"""
d = self.declaration
old = self._current_renderers
new = set(filter(None, [d.renderer] + d.renderers))
to_remove = old.difference(new)
to_add = new.difference(old)
window = self.vtk_widget.GetRenderWindow()
for r in to_remove:
window.RemoveRenderer(r)
for r in to_add:
window.AddRenderer(r)
self._current_renderers = new
1 change: 1 addition & 0 deletions enaml/widgets/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,6 @@
from .time_selector import TimeSelector
from .timer import Timer
from .tool_bar import ToolBar
from .vtk_canvas import VTKCanvas
from .web_view import WebView
from .window import Window
76 changes: 76 additions & 0 deletions enaml/widgets/vtk_canvas.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#------------------------------------------------------------------------------
# Copyright (c) 2013, Nucleic Development Team.
#
# Distributed under the terms of the Modified BSD License.
#
# The full license is in the file COPYING.txt, distributed with this software.
#------------------------------------------------------------------------------
from atom.api import (
List, Typed, ForwardTyped, ForwardInstance, observe, set_default
)

from enaml.core.declarative import d_

from .control import Control, ProxyControl


#: Delay the import of vtk until needed. This removes the hard dependecy
#: on vtk for the rest of the Enaml code base.
def vtkRenderer():
from vtk import vtkRenderer
return vtkRenderer


class ProxyVTKCanvas(ProxyControl):
""" The abstract definition of a proxy VTKCanvas object.
"""
#: A reference to the VTKCanvas declaration.
declaration = ForwardTyped(lambda: VTKCanvas)

def set_renderer(self, renderer):
raise NotImplementedError

def set_renderers(self, renderers):
raise NotImplementedError

def render(self):
raise NotImplementedError


class VTKCanvas(Control):
""" A control which can be used to embded vtk renderers.
"""
#: The vtk renderer to display in the window. This should be used
#: if only a single renderer is required for the scene.
renderer = d_(ForwardInstance(vtkRenderer))

#: The list of vtk renderers to display in the window. This should
#: be used if multiple renderers are required for the scene.
renderers = d_(List(ForwardInstance(vtkRenderer)))

#: A VTKCanvas expands freely in height and width by default.
hug_width = set_default('ignore')
hug_height = set_default('ignore')

#: A reference to the ProxyVTKCanvas object.
proxy = Typed(ProxyVTKCanvas)

def render(self):
""" Request a render of the underlying scene.
"""
if self.proxy_is_active:
self.proxy.render()

#--------------------------------------------------------------------------
# Observers
#--------------------------------------------------------------------------
@observe('renderer', 'renderers')
def _update_proxy(self, change):
""" An observer which sends state change to the proxy.
"""
# The superclass handler implementation is sufficient.
super(VTKCanvas, self)._update_proxy(change)

0 comments on commit b042621

Please sign in to comment.