Skip to content
This repository has been archived by the owner on May 24, 2021. It is now read-only.

Commit

Permalink
Merge pull request #215 from blink1073/feature-traitsui-item
Browse files Browse the repository at this point in the history
Feature traitsui item
  • Loading branch information
sccolbert committed Dec 8, 2012
2 parents 4736b98 + f49c770 commit 944d549
Show file tree
Hide file tree
Showing 8 changed files with 276 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 @@ -197,6 +197,11 @@ def tool_bar_factory():
return QtToolBar


def traits_item_factory():
from .qt_traits_item import QtTraitsItem
return QtTraitsItem


def web_view_factory():
from .qt_web_view import QtWebView
return QtWebView
Expand Down Expand Up @@ -249,6 +254,7 @@ def register_default():
register('StackItem', stack_item_factory)
register('TimeSelector', time_selector_factory)
register('ToolBar', tool_bar_factory)
register('TraitsItem', traits_item_factory)
register('WebView', web_view_factory)
register('Window', window_factory)

76 changes: 76 additions & 0 deletions enaml/qt/qt_traits_item.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
from .qt.QtCore import Qt, QMargins
from .qt.QtGui import QWidget, QVBoxLayout, QFrame
from .qt_control import QtControl


class QtTraitsItem(QtControl):
""" A Qt implementation of an Enaml TraitsItem.
"""
#--------------------------------------------------------------------------
# Setup Methods
#--------------------------------------------------------------------------
def create_widget(self, parent, tree):
""" Create the underlying label widget.
"""
widget = QFrame(parent)
layout = QVBoxLayout(widget)
layout.setContentsMargins(QMargins(0, 0, 0, 0))
return widget

def create(self, tree):
""" Create and initialize the underlying widget.
"""
super(QtTraitsItem, self).create(tree)
self.model = tree['model']
self.view = tree['view']
self.handler = tree['handler']
self.ui = None

def init_layout(self):
'''Create the Traits UI widget and add to our layout
'''
super(QtTraitsItem, self).init_layout()
# guard against using a named view that is not supported by the model
if isinstance(self.view, (str, unicode)):
if self.model.trait_view(self.view) is None:
self.view = ''
# remove any previous widget before adding a new one
if self.ui:
self.widget().layout().removeWidget(self.ui.control)
self.ui.control.hide()
self.ui = self.model.edit_traits(parent=self.widget(), view=self.view,
handler=self.handler, kind='subpanel')
# on qt, we must set this explicitly
self.ui.control.setParent(self.widget())
self.widget().layout().addWidget(self.ui.control)
# allow the widget to resize when the view is changed
size = self.ui.control.sizeHint()
self.set_minimum_size((size.width(), size.height()))
self.size_hint_updated()

#--------------------------------------------------------------------------
# Message Handlers
#--------------------------------------------------------------------------
def on_action_set_model(self, content):
""" Handle the 'set_model' action from the Enaml widget.
"""
self.model = content['model']
self.init_layout()

def on_action_set_handler(self, content):
""" Handle the 'set_handler' action from the Enaml widget.
"""
self.handler = content['handler']
self.init_layout()

def on_action_set_view(self, content):
""" Handle the 'set_view' action from the Enaml widget.
"""
self.view = content['view']
self.init_layout()
1 change: 1 addition & 0 deletions enaml/widgets/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#from .text_editor import TextEditor
from .time_selector import TimeSelector
from .tool_bar import ToolBar
from .traits_item import TraitsItem
from .web_view import WebView
from .window import Window

48 changes: 48 additions & 0 deletions enaml/widgets/traits_item.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#------------------------------------------------------------------------------
# Copyright (c) 2011, Enthought, Inc.
# All rights reserved.
#------------------------------------------------------------------------------
from traits.api import HasTraits, Instance, Any, Trait, Str

from .control import Control


class TraitsItem(Control):
""" A control to display a traitsui item
"""
#: The item being displayed
model = Instance(HasTraits)

# optional : the desired handler for the model
handler = Instance('traitsui.api.Handler')

# optional: the desired view for the model
view = Trait('', Str, Instance('traitsui.api.View'))

#: How strongly a component hugs it's contents' width. TraitsItems ignore
#: the width hug by default, so they expand freely in width.
hug_width = 'ignore'
hug_height = 'ignore'

#--------------------------------------------------------------------------
# Initialization
#--------------------------------------------------------------------------
def snapshot(self):
""" Returns the dict of creation attributes for the control.
"""
snap = super(TraitsItem, self).snapshot()
snap['model'] = self.model
snap['handler'] = self.handler
snap['view'] = self.view
return snap

def bind(self):
""" A method called after initialization which allows the widget
to bind any event handlers necessary.
"""
super(TraitsItem, self).bind()
self.publish_attributes('model', 'handler', 'view')

6 changes: 6 additions & 0 deletions enaml/wx/wx_factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,11 @@ def tool_bar_factory():
return WxToolBar


def traits_item_factory():
from .wx_traits_item import WxTraitsItem
return WxTraitsItem


def window_factory():
from .wx_window import WxWindow
return WxWindow
Expand Down Expand Up @@ -188,5 +193,6 @@ def register_default():
register('SplitItem', split_item_factory)
register('Splitter', splitter_factory)
register('ToolBar', tool_bar_factory)
register('TraitsItem', traits_item_factory)
register('Window', window_factory)

75 changes: 75 additions & 0 deletions enaml/wx/wx_traits_item.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import wx

from .wx_control import WxControl


class WxTraitsItem(WxControl):
""" A Wx implementation of an Enaml TraitsUIItem.
"""
#--------------------------------------------------------------------------
# Setup Methods
#--------------------------------------------------------------------------
def create_widget(self, parent, tree):
""" Create the underlying label widget.
"""
widget = wx.Panel(parent, -1, style=wx.CLIP_CHILDREN)
vbox = wx.BoxSizer(wx.VERTICAL)
widget.SetSizer(vbox)
return widget

def create(self, tree):
""" Create and initialize the underlying widget.
"""
super(WxTraitsItem, self).create(tree)
self.model = tree['model']
self.view = tree['view']
self.handler = tree['handler']
self.ui = None

def init_layout(self):
'''Create the Traits UI widget and add to our layout
'''
super(WxTraitsItem, self).init_layout()
# guard against using a named view that is not supported by the model
if isinstance(self.view, (str, unicode)):
if self.model.trait_view(self.view) is None:
self.view = ''
# remove any previous widget before adding a new one
if self.ui:
self.widget().GetSizer().Remove(self.ui.control)
self.ui.control.Hide()
self.ui = self.model.edit_traits(parent=self.widget(), view=self.view,
handler=self.handler, kind='subpanel')
self.widget().GetSizer().Add(self.ui.control, 1,
wx.LEFT | wx.TOP | wx.GROW)
# allow the widget to resize when the view is changed
size = self.ui.control.GetSize()
self.set_minimum_size((size.width, size.height))
self.size_hint_updated()

#--------------------------------------------------------------------------
# Message Handlers
#--------------------------------------------------------------------------
def on_action_set_model(self, content):
""" Handle the 'set_model' action from the Enaml widget.
"""
self.model = content['model']
self.init_layout()

def on_action_set_handler(self, content):
""" Handle the 'set_handler' action from the Enaml widget.
"""
self.handler = content['handler']
self.init_layout()

def on_action_set_view(self, content):
""" Handle the 'set_view' action from the Enaml widget.
"""
self.view = content['view']
self.init_layout()
29 changes: 29 additions & 0 deletions examples/widgets/traits_item.enaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Note : You may have to set your ETS_TOOLKIT
# environmental value to match the enaml toolkit
# for example, if using QT
# import os
# os.environ['ETS_TOOLKIT'] = 'qt4'
from enaml.widgets.api import MainWindow, TraitsItem, Container, PushButton
from traits.api import HasTraits, Str
from traitsui.api import View


class Test(HasTraits):
a = Str('foo')
b = Str('bar')
traits_view = View('a', 'b')
other_view = View('b', 'a', 'a')


enamldef Main(MainWindow):
Container:
TraitsItem: titem:
model = Test()
view = View('a')
PushButton:
text = 'Change View'
clicked ::
if titem.view == 'other_view':
titem.view = 'traits_view'
else:
titem.view = 'other_view'
35 changes: 35 additions & 0 deletions examples/widgets/traits_mayavi.enaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# NOTE: If using PySide, upgrade to mayavi 4.2.0 for this to work
# You may have to set your ETS_TOOLKIT
# environmental value to match the enaml toolkit
# for example, if using QT
# import os
# os.environ['ETS_TOOLKIT'] = 'qt4'

from enaml.widgets.api import MainWindow, Container, TraitsItem

from traits.api import HasTraits, Instance, on_trait_change
from traitsui.api import View, Item
from mayavi.core.ui.api import MayaviScene, MlabSceneModel, SceneEditor


class Visualization(HasTraits):
scene = Instance(MlabSceneModel, ())

@on_trait_change('scene.activated')
def update_plot(self):
# This function is called when the view is opened. We don't
# populate the scene when the view is not yet open, as some
# VTK features require a GLContext.

# We can do normal mlab calls on the embedded scene.
self.scene.mlab.test_points3d()


enamldef Main(MainWindow):
Container:
TraitsItem:
model = Visualization()
view = View(Item('scene', editor=SceneEditor(scene_class=MayaviScene),
height=250, width=300, show_label=False),
resizable=True # We need this to resize with the parent widget
)

0 comments on commit 944d549

Please sign in to comment.