From e9dbe335ee6d5cc27679fc751b208a2cba338ddb Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Sun, 2 Dec 2012 00:51:14 -0600 Subject: [PATCH 1/4] Initial commit of traitsui_item widget in qt and wx with basic and mayavi examples. --- enaml/qt/qt_factories.py | 6 ++ enaml/qt/qt_traitsui_item.py | 98 ++++++++++++++++++++++++++ enaml/widgets/api.py | 1 + enaml/widgets/traitsui_item.py | 49 +++++++++++++ enaml/wx/wx_factories.py | 6 ++ enaml/wx/wx_traitsui_item.py | 53 ++++++++++++++ examples/widgets/traitsui_item.enaml | 22 ++++++ examples/widgets/traitsui_mayavi.enaml | 34 +++++++++ 8 files changed, 269 insertions(+) create mode 100755 enaml/qt/qt_traitsui_item.py create mode 100755 enaml/widgets/traitsui_item.py create mode 100644 enaml/wx/wx_traitsui_item.py create mode 100644 examples/widgets/traitsui_item.enaml create mode 100644 examples/widgets/traitsui_mayavi.enaml diff --git a/enaml/qt/qt_factories.py b/enaml/qt/qt_factories.py index 1a141cf3..ae7053c1 100644 --- a/enaml/qt/qt_factories.py +++ b/enaml/qt/qt_factories.py @@ -197,6 +197,11 @@ def tool_bar_factory(): return QtToolBar +def traitsui_item_factory(): + from .qt_traitsui_item import QtTraitsUIItem + return QtTraitsUIItem + + def web_view_factory(): from .qt_web_view import QtWebView return QtWebView @@ -249,6 +254,7 @@ def register_default(): register('StackItem', stack_item_factory) register('TimeSelector', time_selector_factory) register('ToolBar', tool_bar_factory) + register('TraitsUIItem', traitsui_item_factory) register('WebView', web_view_factory) register('Window', window_factory) diff --git a/enaml/qt/qt_traitsui_item.py b/enaml/qt/qt_traitsui_item.py new file mode 100755 index 00000000..6e004612 --- /dev/null +++ b/enaml/qt/qt_traitsui_item.py @@ -0,0 +1,98 @@ +from .qt.QtCore import Qt, QMargins +from .qt.QtGui import QWidget, QVBoxLayout +from .qt_control import QtControl + + +class QtTraitsUIItem(QtControl): + """ A Qt implementation of an Enaml TraitsUIItem. + + """ + #-------------------------------------------------------------------------- + # Setup Methods + #-------------------------------------------------------------------------- + def create_widget(self, parent, tree): + """ Create the underlying label widget. + + """ + model = tree['model'] + ui = model.edit_traits(parent=parent, view=tree['view'], + handler=tree['handler'], kind='subpanel') + # on qt, we must set this explicitly + ui.control.setParent(parent) + # if parent is a main window, we need to ensure proper sizing + if hasattr(parent, 'centralWidget'): + size = ui.control.sizeHint() + ui.control.setMinimumSize(size) + parent.setMinimumSize(size) + return ui.control + + def create(self, tree): + """ Create and initialize the underlying widget. + + """ + super(QtTraitsUIItem, self).create(tree) + + #-------------------------------------------------------------------------- + # Message Handlers + #-------------------------------------------------------------------------- + def on_action_set_model(self, content): + """ Handle the 'set_model' action from the Enaml widget. + + """ + raise NotImplementedError + + def on_action_set_handler(self, content): + """ Handle the 'set_handler' action from the Enaml widget. + + """ + raise NotImplementedError + + def on_action_set_view(self, content): + """ Handle the 'set_view' action from the Enaml widget. + + """ + raise NotImplementedError + ''' + #-------------------------------------------------------------------------- + # Widget Update Methods + #-------------------------------------------------------------------------- + def set_model(self, model): + """ Set the model for the underlying widget. + + """ + self.model = model + + def set_handler(self, handler): + """ Set the handler for the underlying widget. + + """ + self.handler = handler + + def set_view(self, view): + """ Set the view in the underlying widget. + + """ + self.view = view + widget = self.widget() + # support changing views + layout = widget.layout() + if not layout: + layout = QVBoxLayout(widget) + layout.setContentsMargins(QMargins(0, 0, 0, 0)) + else: + layout.removeWidget(self.ui.control) + self.ui.control.hide() + # create the view and add it to our layout + self.ui = ui = self.model.edit_traits(parent=widget, view=view, + handler=self.handler, kind='subpanel') + layout.addWidget(ui.control) + # TraitsUI doesn't properly set the parent on Qt + ui.control.setParent(widget) + # make sure the widget scales appropriately + # (especially when view changes) + size = ui.control.sizeHint() + self.set_minimum_size((size.width(), size.height())) + self.size_hint_updated() + parent = self.parent() + + ''' \ No newline at end of file diff --git a/enaml/widgets/api.py b/enaml/widgets/api.py index 3c30dcde..2a62ae0a 100644 --- a/enaml/widgets/api.py +++ b/enaml/widgets/api.py @@ -44,6 +44,7 @@ #from .text_editor import TextEditor from .time_selector import TimeSelector from .tool_bar import ToolBar +from .traitsui_item import TraitsUIItem from .web_view import WebView from .window import Window diff --git a/enaml/widgets/traitsui_item.py b/enaml/widgets/traitsui_item.py new file mode 100755 index 00000000..9aae3906 --- /dev/null +++ b/enaml/widgets/traitsui_item.py @@ -0,0 +1,49 @@ +#------------------------------------------------------------------------------ +# Copyright (c) 2011, Enthought, Inc. +# All rights reserved. +#------------------------------------------------------------------------------ +from traits.api import HasTraits, Instance, Any +from traitsui.api import Handler + +from .control import Control + + +class TraitsUIItem(Control): + """ A control to display a traitsui item + + """ + #: The item being displayed + model = Instance(HasTraits) + + # optional : the desired handler for the model + handler = Instance(Handler) + + # optional: the desired view for the model + view = Any + + #: How strongly a component hugs it's contents' width. TraitsUIItems 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(TraitsUIItem, 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(TraitsUIItem, self).bind() + self.publish_attributes('model', 'handler', 'view') + diff --git a/enaml/wx/wx_factories.py b/enaml/wx/wx_factories.py index 44b8185f..2a6148fb 100644 --- a/enaml/wx/wx_factories.py +++ b/enaml/wx/wx_factories.py @@ -152,6 +152,11 @@ def tool_bar_factory(): return WxToolBar +def traitsui_item_factory(): + from .wx_traitsui_item import WxTraitsUIItem + return WxTraitsUIItem + + def window_factory(): from .wx_window import WxWindow return WxWindow @@ -188,5 +193,6 @@ def register_default(): register('SplitItem', split_item_factory) register('Splitter', splitter_factory) register('ToolBar', tool_bar_factory) + register('TraitsUIItem', traitsui_item_factory) register('Window', window_factory) diff --git a/enaml/wx/wx_traitsui_item.py b/enaml/wx/wx_traitsui_item.py new file mode 100644 index 00000000..556bdb95 --- /dev/null +++ b/enaml/wx/wx_traitsui_item.py @@ -0,0 +1,53 @@ +import wx + +from .wx_control import WxControl + + +class WxTraitsUIItem(WxControl): + """ A Wx implementation of an Enaml TraitsUIItem. + + """ + #-------------------------------------------------------------------------- + # Setup Methods + #-------------------------------------------------------------------------- + def create_widget(self, parent, tree): + """ Create the underlying label widget. + + """ + model = tree['model'] + ui = model.edit_traits(parent=parent, view=tree['view'], + handler=tree['handler'], kind='subpanel') + # if parent is a main window, we need to ensure proper sizing + if hasattr(parent, 'SetCentralWidget'): + size = ui.control.GetSize() + ui.control.SetMinSize(size) + parent.SetMinSize(size) + parent.SetSize(size) + return ui.control + + def create(self, tree): + """ Create and initialize the underlying widget. + + """ + super(WxTraitsUIItem, self).create(tree) + + #-------------------------------------------------------------------------- + # Message Handlers + #-------------------------------------------------------------------------- + def on_action_set_model(self, content): + """ Handle the 'set_model' action from the Enaml widget. + + """ + raise NotImplementedError + + def on_action_set_handler(self, content): + """ Handle the 'set_handler' action from the Enaml widget. + + """ + raise NotImplementedError + + def on_action_set_view(self, content): + """ Handle the 'set_view' action from the Enaml widget. + + """ + raise NotImplementedError \ No newline at end of file diff --git a/examples/widgets/traitsui_item.enaml b/examples/widgets/traitsui_item.enaml new file mode 100644 index 00000000..d38b3539 --- /dev/null +++ b/examples/widgets/traitsui_item.enaml @@ -0,0 +1,22 @@ +# 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, TraitsUIItem +from traits.api import HasTraits, Str +from traitsui.api import View +import sys +print sys.argv + +class Test(HasTraits): + a = Str('foo') + b = Str('bar') + traits_view = View('a', 'b') + other_view = View('b', 'a', 'a') + + +enamldef Main(MainWindow): + TraitsUIItem: titem: + model = Test() + view = 'other_view' diff --git a/examples/widgets/traitsui_mayavi.enaml b/examples/widgets/traitsui_mayavi.enaml new file mode 100644 index 00000000..f5735ac9 --- /dev/null +++ b/examples/widgets/traitsui_mayavi.enaml @@ -0,0 +1,34 @@ +# 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, TraitsUIItem + +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): + TraitsUIItem: + 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 + ) From 5e4978d89d5b04bceda0cdf7f604559d0d9729b6 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Sun, 2 Dec 2012 14:57:08 -0600 Subject: [PATCH 2/4] Name->TraitsItem, Qt widget uses QFrame and is dynamic, removed traitsui import in widgets.api --- enaml/qt/qt_factories.py | 8 +- enaml/qt/qt_traits_item.py | 69 +++++++++++++ enaml/qt/qt_traitsui_item.py | 98 ------------------- enaml/widgets/api.py | 2 +- .../{traitsui_item.py => traits_item.py} | 11 +-- enaml/wx/wx_factories.py | 8 +- ...{wx_traitsui_item.py => wx_traits_item.py} | 4 +- ...{traitsui_item.enaml => traits_item.enaml} | 19 ++-- ...itsui_mayavi.enaml => traits_mayavi.enaml} | 15 +-- 9 files changed, 106 insertions(+), 128 deletions(-) create mode 100755 enaml/qt/qt_traits_item.py delete mode 100755 enaml/qt/qt_traitsui_item.py rename enaml/widgets/{traitsui_item.py => traits_item.py} (86%) rename enaml/wx/{wx_traitsui_item.py => wx_traits_item.py} (95%) rename examples/widgets/{traitsui_item.enaml => traits_item.enaml} (50%) rename examples/widgets/{traitsui_mayavi.enaml => traits_mayavi.enaml} (69%) diff --git a/enaml/qt/qt_factories.py b/enaml/qt/qt_factories.py index ae7053c1..9c9e2cfe 100644 --- a/enaml/qt/qt_factories.py +++ b/enaml/qt/qt_factories.py @@ -197,9 +197,9 @@ def tool_bar_factory(): return QtToolBar -def traitsui_item_factory(): - from .qt_traitsui_item import QtTraitsUIItem - return QtTraitsUIItem +def traits_item_factory(): + from .qt_traits_item import QtTraitsItem + return QtTraitsItem def web_view_factory(): @@ -254,7 +254,7 @@ def register_default(): register('StackItem', stack_item_factory) register('TimeSelector', time_selector_factory) register('ToolBar', tool_bar_factory) - register('TraitsUIItem', traitsui_item_factory) + register('TraitsItem', traits_item_factory) register('WebView', web_view_factory) register('Window', window_factory) diff --git a/enaml/qt/qt_traits_item.py b/enaml/qt/qt_traits_item.py new file mode 100755 index 00000000..b744b065 --- /dev/null +++ b/enaml/qt/qt_traits_item.py @@ -0,0 +1,69 @@ +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 + ''' + # guard against using a view that is not supported by the model + if not self.model.trait_view(self.view): + 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) + + #-------------------------------------------------------------------------- + # 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'] + + def on_action_set_view(self, content): + """ Handle the 'set_view' action from the Enaml widget. + + """ + self.view = content['view'] + self.init_layout() \ No newline at end of file diff --git a/enaml/qt/qt_traitsui_item.py b/enaml/qt/qt_traitsui_item.py deleted file mode 100755 index 6e004612..00000000 --- a/enaml/qt/qt_traitsui_item.py +++ /dev/null @@ -1,98 +0,0 @@ -from .qt.QtCore import Qt, QMargins -from .qt.QtGui import QWidget, QVBoxLayout -from .qt_control import QtControl - - -class QtTraitsUIItem(QtControl): - """ A Qt implementation of an Enaml TraitsUIItem. - - """ - #-------------------------------------------------------------------------- - # Setup Methods - #-------------------------------------------------------------------------- - def create_widget(self, parent, tree): - """ Create the underlying label widget. - - """ - model = tree['model'] - ui = model.edit_traits(parent=parent, view=tree['view'], - handler=tree['handler'], kind='subpanel') - # on qt, we must set this explicitly - ui.control.setParent(parent) - # if parent is a main window, we need to ensure proper sizing - if hasattr(parent, 'centralWidget'): - size = ui.control.sizeHint() - ui.control.setMinimumSize(size) - parent.setMinimumSize(size) - return ui.control - - def create(self, tree): - """ Create and initialize the underlying widget. - - """ - super(QtTraitsUIItem, self).create(tree) - - #-------------------------------------------------------------------------- - # Message Handlers - #-------------------------------------------------------------------------- - def on_action_set_model(self, content): - """ Handle the 'set_model' action from the Enaml widget. - - """ - raise NotImplementedError - - def on_action_set_handler(self, content): - """ Handle the 'set_handler' action from the Enaml widget. - - """ - raise NotImplementedError - - def on_action_set_view(self, content): - """ Handle the 'set_view' action from the Enaml widget. - - """ - raise NotImplementedError - ''' - #-------------------------------------------------------------------------- - # Widget Update Methods - #-------------------------------------------------------------------------- - def set_model(self, model): - """ Set the model for the underlying widget. - - """ - self.model = model - - def set_handler(self, handler): - """ Set the handler for the underlying widget. - - """ - self.handler = handler - - def set_view(self, view): - """ Set the view in the underlying widget. - - """ - self.view = view - widget = self.widget() - # support changing views - layout = widget.layout() - if not layout: - layout = QVBoxLayout(widget) - layout.setContentsMargins(QMargins(0, 0, 0, 0)) - else: - layout.removeWidget(self.ui.control) - self.ui.control.hide() - # create the view and add it to our layout - self.ui = ui = self.model.edit_traits(parent=widget, view=view, - handler=self.handler, kind='subpanel') - layout.addWidget(ui.control) - # TraitsUI doesn't properly set the parent on Qt - ui.control.setParent(widget) - # make sure the widget scales appropriately - # (especially when view changes) - size = ui.control.sizeHint() - self.set_minimum_size((size.width(), size.height())) - self.size_hint_updated() - parent = self.parent() - - ''' \ No newline at end of file diff --git a/enaml/widgets/api.py b/enaml/widgets/api.py index 2a62ae0a..81f23244 100644 --- a/enaml/widgets/api.py +++ b/enaml/widgets/api.py @@ -44,7 +44,7 @@ #from .text_editor import TextEditor from .time_selector import TimeSelector from .tool_bar import ToolBar -from .traitsui_item import TraitsUIItem +from .traits_item import TraitsItem from .web_view import WebView from .window import Window diff --git a/enaml/widgets/traitsui_item.py b/enaml/widgets/traits_item.py similarity index 86% rename from enaml/widgets/traitsui_item.py rename to enaml/widgets/traits_item.py index 9aae3906..bd169f58 100755 --- a/enaml/widgets/traitsui_item.py +++ b/enaml/widgets/traits_item.py @@ -3,12 +3,11 @@ # All rights reserved. #------------------------------------------------------------------------------ from traits.api import HasTraits, Instance, Any -from traitsui.api import Handler from .control import Control -class TraitsUIItem(Control): +class TraitsItem(Control): """ A control to display a traitsui item """ @@ -16,12 +15,12 @@ class TraitsUIItem(Control): model = Instance(HasTraits) # optional : the desired handler for the model - handler = Instance(Handler) + handler = Instance('Handler') # optional: the desired view for the model view = Any - #: How strongly a component hugs it's contents' width. TraitsUIItems ignore + #: 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' @@ -33,7 +32,7 @@ def snapshot(self): """ Returns the dict of creation attributes for the control. """ - snap = super(TraitsUIItem, self).snapshot() + snap = super(TraitsItem, self).snapshot() snap['model'] = self.model snap['handler'] = self.handler snap['view'] = self.view @@ -44,6 +43,6 @@ def bind(self): to bind any event handlers necessary. """ - super(TraitsUIItem, self).bind() + super(TraitsItem, self).bind() self.publish_attributes('model', 'handler', 'view') diff --git a/enaml/wx/wx_factories.py b/enaml/wx/wx_factories.py index 2a6148fb..a3dbb952 100644 --- a/enaml/wx/wx_factories.py +++ b/enaml/wx/wx_factories.py @@ -152,9 +152,9 @@ def tool_bar_factory(): return WxToolBar -def traitsui_item_factory(): - from .wx_traitsui_item import WxTraitsUIItem - return WxTraitsUIItem +def traits_item_factory(): + from .wx_traits_item import WxTraitsItem + return WxTraitsItem def window_factory(): @@ -193,6 +193,6 @@ def register_default(): register('SplitItem', split_item_factory) register('Splitter', splitter_factory) register('ToolBar', tool_bar_factory) - register('TraitsUIItem', traitsui_item_factory) + register('TraitItem', traits_item_factory) register('Window', window_factory) diff --git a/enaml/wx/wx_traitsui_item.py b/enaml/wx/wx_traits_item.py similarity index 95% rename from enaml/wx/wx_traitsui_item.py rename to enaml/wx/wx_traits_item.py index 556bdb95..8f235e07 100644 --- a/enaml/wx/wx_traitsui_item.py +++ b/enaml/wx/wx_traits_item.py @@ -3,7 +3,7 @@ from .wx_control import WxControl -class WxTraitsUIItem(WxControl): +class WxTraitsItem(WxControl): """ A Wx implementation of an Enaml TraitsUIItem. """ @@ -29,7 +29,7 @@ def create(self, tree): """ Create and initialize the underlying widget. """ - super(WxTraitsUIItem, self).create(tree) + super(WxTraitsItem, self).create(tree) #-------------------------------------------------------------------------- # Message Handlers diff --git a/examples/widgets/traitsui_item.enaml b/examples/widgets/traits_item.enaml similarity index 50% rename from examples/widgets/traitsui_item.enaml rename to examples/widgets/traits_item.enaml index d38b3539..fac16947 100644 --- a/examples/widgets/traitsui_item.enaml +++ b/examples/widgets/traits_item.enaml @@ -3,11 +3,10 @@ # for example, if using QT # import os # os.environ['ETS_TOOLKIT'] = 'qt4' -from enaml.widgets.api import MainWindow, TraitsUIItem +from enaml.widgets.api import MainWindow, TraitsItem, Container, PushButton from traits.api import HasTraits, Str from traitsui.api import View -import sys -print sys.argv + class Test(HasTraits): a = Str('foo') @@ -17,6 +16,14 @@ class Test(HasTraits): enamldef Main(MainWindow): - TraitsUIItem: titem: - model = Test() - view = 'other_view' + Container: + TraitsItem: titem: + model = Test() + view = 'other_view' + PushButton: + text = 'Change View' + clicked :: + if titem.view == 'other_view': + titem.view = 'traits_view' + else: + titem.view = 'other_view' diff --git a/examples/widgets/traitsui_mayavi.enaml b/examples/widgets/traits_mayavi.enaml similarity index 69% rename from examples/widgets/traitsui_mayavi.enaml rename to examples/widgets/traits_mayavi.enaml index f5735ac9..2f128ef6 100644 --- a/examples/widgets/traitsui_mayavi.enaml +++ b/examples/widgets/traits_mayavi.enaml @@ -5,7 +5,7 @@ # import os # os.environ['ETS_TOOLKIT'] = 'qt4' -from enaml.widgets.api import MainWindow, Container, TraitsUIItem +from enaml.widgets.api import MainWindow, Container, TraitsItem from traits.api import HasTraits, Instance, on_trait_change from traitsui.api import View, Item @@ -26,9 +26,10 @@ class Visualization(HasTraits): enamldef Main(MainWindow): - TraitsUIItem: - 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 - ) + 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 + ) From f7d3adca3b597fb322c3c6e2d62fc4175c912862 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Sun, 2 Dec 2012 15:26:53 -0600 Subject: [PATCH 3/4] Ensured that when a traits view is changed, the widget size scales with it. --- enaml/qt/qt_traits_item.py | 3 +++ examples/widgets/traits_item.enaml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/enaml/qt/qt_traits_item.py b/enaml/qt/qt_traits_item.py index b744b065..66f277f9 100755 --- a/enaml/qt/qt_traits_item.py +++ b/enaml/qt/qt_traits_item.py @@ -44,6 +44,9 @@ def init_layout(self): # on qt, we must set this explicitly self.ui.control.setParent(self.widget()) self.widget().layout().addWidget(self.ui.control) + size = self.ui.control.sizeHint() + self.set_minimum_size((size.width(), size.height())) + self.size_hint_updated() #-------------------------------------------------------------------------- # Message Handlers diff --git a/examples/widgets/traits_item.enaml b/examples/widgets/traits_item.enaml index fac16947..1d5e52bb 100644 --- a/examples/widgets/traits_item.enaml +++ b/examples/widgets/traits_item.enaml @@ -19,7 +19,7 @@ enamldef Main(MainWindow): Container: TraitsItem: titem: model = Test() - view = 'other_view' + view = '' PushButton: text = 'Change View' clicked :: From f49c7708603273f81a8f5573cf5523b84ab5c519 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Sun, 2 Dec 2012 20:14:15 -0600 Subject: [PATCH 4/4] Updated wx to use a panel and be dynamic, improved view and handler validation --- enaml/qt/qt_traits_item.py | 10 +++++-- enaml/widgets/traits_item.py | 6 ++-- enaml/wx/wx_factories.py | 2 +- enaml/wx/wx_traits_item.py | 48 ++++++++++++++++++++++-------- examples/widgets/traits_item.enaml | 2 +- 5 files changed, 47 insertions(+), 21 deletions(-) diff --git a/enaml/qt/qt_traits_item.py b/enaml/qt/qt_traits_item.py index 66f277f9..218fb324 100755 --- a/enaml/qt/qt_traits_item.py +++ b/enaml/qt/qt_traits_item.py @@ -32,9 +32,11 @@ def create(self, tree): def init_layout(self): '''Create the Traits UI widget and add to our layout ''' - # guard against using a view that is not supported by the model - if not self.model.trait_view(self.view): - self.view = '' + 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) @@ -44,6 +46,7 @@ def init_layout(self): # 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() @@ -63,6 +66,7 @@ def on_action_set_handler(self, content): """ self.handler = content['handler'] + self.init_layout() def on_action_set_view(self, content): """ Handle the 'set_view' action from the Enaml widget. diff --git a/enaml/widgets/traits_item.py b/enaml/widgets/traits_item.py index bd169f58..2ef0aa2a 100755 --- a/enaml/widgets/traits_item.py +++ b/enaml/widgets/traits_item.py @@ -2,7 +2,7 @@ # Copyright (c) 2011, Enthought, Inc. # All rights reserved. #------------------------------------------------------------------------------ -from traits.api import HasTraits, Instance, Any +from traits.api import HasTraits, Instance, Any, Trait, Str from .control import Control @@ -15,10 +15,10 @@ class TraitsItem(Control): model = Instance(HasTraits) # optional : the desired handler for the model - handler = Instance('Handler') + handler = Instance('traitsui.api.Handler') # optional: the desired view for the model - view = Any + 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. diff --git a/enaml/wx/wx_factories.py b/enaml/wx/wx_factories.py index a3dbb952..9c102fb9 100644 --- a/enaml/wx/wx_factories.py +++ b/enaml/wx/wx_factories.py @@ -193,6 +193,6 @@ def register_default(): register('SplitItem', split_item_factory) register('Splitter', splitter_factory) register('ToolBar', tool_bar_factory) - register('TraitItem', traits_item_factory) + register('TraitsItem', traits_item_factory) register('Window', window_factory) diff --git a/enaml/wx/wx_traits_item.py b/enaml/wx/wx_traits_item.py index 8f235e07..b240c963 100644 --- a/enaml/wx/wx_traits_item.py +++ b/enaml/wx/wx_traits_item.py @@ -14,22 +14,41 @@ def create_widget(self, parent, tree): """ Create the underlying label widget. """ - model = tree['model'] - ui = model.edit_traits(parent=parent, view=tree['view'], - handler=tree['handler'], kind='subpanel') - # if parent is a main window, we need to ensure proper sizing - if hasattr(parent, 'SetCentralWidget'): - size = ui.control.GetSize() - ui.control.SetMinSize(size) - parent.SetMinSize(size) - parent.SetSize(size) - return ui.control + 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 @@ -38,16 +57,19 @@ def on_action_set_model(self, content): """ Handle the 'set_model' action from the Enaml widget. """ - raise NotImplementedError + self.model = content['model'] + self.init_layout() def on_action_set_handler(self, content): """ Handle the 'set_handler' action from the Enaml widget. """ - raise NotImplementedError + self.handler = content['handler'] + self.init_layout() def on_action_set_view(self, content): """ Handle the 'set_view' action from the Enaml widget. """ - raise NotImplementedError \ No newline at end of file + self.view = content['view'] + self.init_layout() \ No newline at end of file diff --git a/examples/widgets/traits_item.enaml b/examples/widgets/traits_item.enaml index 1d5e52bb..1c0b71f9 100644 --- a/examples/widgets/traits_item.enaml +++ b/examples/widgets/traits_item.enaml @@ -19,7 +19,7 @@ enamldef Main(MainWindow): Container: TraitsItem: titem: model = Test() - view = '' + view = View('a') PushButton: text = 'Change View' clicked ::