Forráskód Böngészése

Add ctkLayoutManager to conveniently handle layouts with XML

Add associated test ctkLayoutManagerTest1 and a utility class
 ctkSimpleLayoutManager.
Julien Finet 14 éve
szülő
commit
04a4328db4

+ 6 - 0
Libs/Widgets/CMakeLists.txt

@@ -58,6 +58,8 @@ SET(KIT_SRCS
   ctkFontButton.h
   ctkIconEnginePlugin.cpp
   ctkIconEnginePlugin.h
+  ctkLayoutManager.cpp
+  ctkLayoutManager.h
   ctkMaterialPropertyPreviewLabel.cpp
   ctkMaterialPropertyPreviewLabel.h
   ctkMaterialPropertyWidget.cpp
@@ -85,6 +87,8 @@ SET(KIT_SRCS
   ctkSettingsDialog.h
   ctkSettingsPanel.cpp
   ctkSettingsPanel.h
+  ctkSimpleLayoutManager.cpp
+  ctkSimpleLayoutManager.h
   ctkQImageView.cpp
   ctkQImageView.h
   ctkSliderWidget.cpp
@@ -165,6 +169,7 @@ SET(KIT_MOC_SRCS
   ctkFlowLayout.h
   ctkFontButton.h
   ctkIconEnginePlugin.h
+  ctkLayoutManager.h
   ctkMaterialPropertyPreviewLabel.h
   ctkMaterialPropertyWidget.h
   ctkMatrixWidget.h
@@ -178,6 +183,7 @@ SET(KIT_MOC_SRCS
   ctkSettings.h
   ctkSettingsDialog.h
   ctkSettingsPanel.h
+  ctkSimpleLayoutManager.h
   ctkQImageView.h
   ctkSliderWidget.h
   ctkTestApplication.h

+ 2 - 0
Libs/Widgets/Testing/Cpp/CMakeLists.txt

@@ -28,6 +28,7 @@ CREATE_TEST_SOURCELIST(Tests ${KIT}CppTests.cxx
   ctkFittedTextBrowserTest1.cpp
   ctkFlowLayoutTest1.cpp
   ctkFontButtonTest1.cpp
+  ctkLayoutManagerTest1.cpp
   ctkMaterialPropertyPreviewLabelTest1.cpp
   ctkMaterialPropertyWidgetTest1.cpp
   ctkMatrixWidgetTest1.cpp
@@ -115,6 +116,7 @@ SIMPLE_TEST( ctkFileDialogTest1 )
 SIMPLE_TEST( ctkFittedTextBrowserTest1 )
 SIMPLE_TEST( ctkFlowLayoutTest1 )
 SIMPLE_TEST( ctkFontButtonTest1 )
+SIMPLE_TEST( ctkLayoutManagerTest1 )
 SIMPLE_TEST( ctkMaterialPropertyPreviewLabelTest1 )
 SIMPLE_TEST( ctkMaterialPropertyWidgetTest1 )
 SIMPLE_TEST( ctkMatrixWidgetTest1 )

+ 174 - 0
Libs/Widgets/Testing/Cpp/ctkLayoutManagerTest1.cpp

@@ -0,0 +1,174 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.commontk.org/LICENSE
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=========================================================================*/
+
+// Qt includse
+#include <QApplication>
+#include <QPushButton>
+#include <QTimer>
+
+// CTK includes
+#include "ctkSimpleLayoutManager.h"
+
+// STD includes
+#include <iostream>
+
+QString simpleLayout("<layout><item><view/></item></layout>");
+QString vboxLayout("<layout type=\"vertical\"><item><view/></item><item><view/></item></layout>");
+QString gridLayout(
+"<layout type=\"grid\">"
+" <item><view/></item>"
+" <item col=\"1\"><view/></item>"
+" <item row=\"1\"><view/></item>"
+" <item row=\"1\" column=\"1\"><view/></item>"
+" <item row=\"2\" colspan=\"2\"><view/></item>"
+" <item row=\"3\" rowspan=\"2\"><view/></item>"
+"</layout>");
+QString tabLayout(
+"<layout type=\"tab\">"
+" <item><view name=\"tab1\"/></item>"
+" <item><view name=\"tab2\"/></item>"
+" <item><view name=\"tab3\"/></item>"
+"</layout>");
+QString nestedLayout(
+"<layout type=\"tab\">"
+" <item>"
+"  <layout type=\"horizontal\">"
+"   <item><view/></item>"
+"   <item>"
+"    <layout type=\"vertical\">"
+"     <item><view/></item>"
+"     <item><view/></item>"
+"     <item>"
+"      <layout type=\"grid\">"
+"       <item row=\"0\" column=\"1\"><view/></item>"
+"       <item row=\"1\" column=\"0\"><view/></item>"
+"      </layout>"
+"     </item>"
+"    </layout>"
+"   </item>"
+"   <item><view/></item>"
+"  </layout>"
+" </item>"
+" <item><view name=\"tab2\"/></item>"
+" <item><view name=\"tab3\"/></item>"
+"</layout>");
+
+class ctkPushButton: public QPushButton
+{
+  Q_OBJECT
+public:
+  Q_INVOKABLE ctkPushButton(): QPushButton(0){}
+};
+
+//-----------------------------------------------------------------------------
+int ctkLayoutManagerTest1(int argc, char * argv [] )
+{
+  QApplication app(argc, argv);
+
+  QWidget viewport;
+  viewport.setWindowTitle("Simple layout");
+  ctkSimpleLayoutManager layoutManager;
+
+  layoutManager.setViewport(&viewport);
+  if (layoutManager.viewport() != &viewport)
+    {
+    std::cerr << __LINE__ << ": ctkLayoutManager::setViewport() failed."
+              << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  //layoutManager.setViewMetaObject(QPushButton::staticMetaObject);
+  ctkTemplateInstanciator<QPushButton> pButtonInstanciator;
+  layoutManager.setViewInstanciator(&pButtonInstanciator);
+
+  QDomDocument simpleLayoutDoc("simplelayout");
+  bool res = simpleLayoutDoc.setContent(simpleLayout);
+  Q_ASSERT(res);
+  QDomDocument vboxLayoutDoc("vboxlayout");
+  res = vboxLayoutDoc.setContent(vboxLayout);
+  Q_ASSERT(res);
+  QDomDocument gridLayoutDoc("gridlayout");
+  res = gridLayoutDoc.setContent(gridLayout);
+  Q_ASSERT(res);
+  QDomDocument tabLayoutDoc("tablayout");
+  res = tabLayoutDoc.setContent(tabLayout);
+  Q_ASSERT(res);
+  QDomDocument nestedLayoutDoc("nestedlayout");
+  res = nestedLayoutDoc.setContent(nestedLayout);
+  Q_ASSERT(res);
+
+  layoutManager.setLayout(simpleLayoutDoc);
+  if (layoutManager.layout() != simpleLayoutDoc)
+    {
+    std::cerr << __LINE__ << ": ctkSimpleLayoutManager::setLayout() failed."
+              << std::endl;
+    return EXIT_FAILURE;
+    }
+  viewport.show();
+
+
+  QWidget vbox;
+  vbox.setWindowTitle("Vertical Box Layout");
+  ctkSimpleLayoutManager vboxLayoutManager;
+  vboxLayoutManager.setViewInstanciator(&pButtonInstanciator);
+  vboxLayoutManager.setLayout(vboxLayoutDoc);
+  vboxLayoutManager.setViewport(&vbox);
+  vbox.show();
+
+  QWidget grid;
+  grid.setWindowTitle("Grid Layout");
+  ctkSimpleLayoutManager gridLayoutManager;
+  gridLayoutManager.setViewInstanciator(&pButtonInstanciator);
+  gridLayoutManager.setLayout(gridLayoutDoc);
+  gridLayoutManager.setViewport(&grid);
+  grid.show();
+
+  QWidget tab;
+  grid.setWindowTitle("Tab Layout");
+  ctkSimpleLayoutManager tabLayoutManager;
+  tabLayoutManager.setViewInstanciator(&pButtonInstanciator);
+  tabLayoutManager.setLayout(tabLayoutDoc);
+  tabLayoutManager.setViewport(&tab);
+  tab.show();
+
+  QWidget nested;
+  grid.setWindowTitle("Nested Layout");
+  ctkSimpleLayoutManager nestedLayoutManager;
+  nestedLayoutManager.setViewInstanciator(&pButtonInstanciator);
+  nestedLayoutManager.setLayout(nestedLayoutDoc);
+  nestedLayoutManager.setViewport(&nested);
+  nested.show();
+
+  QWidget tabToSimple;
+  tabToSimple.setWindowTitle("Tab to Simple Layout");
+  ctkSimpleLayoutManager tabToSimpleLayoutManager;
+  tabToSimpleLayoutManager.setViewInstanciator(&pButtonInstanciator);
+  tabToSimpleLayoutManager.setLayout(tabLayoutDoc);
+  tabToSimpleLayoutManager.setViewport(&tabToSimple);
+  tabToSimple.show();
+  tabToSimpleLayoutManager.setLayout(simpleLayoutDoc);
+
+  if (argc < 2 || QString(argv[1]) != "-I" )
+    {
+    QTimer::singleShot(200, &app, SLOT(quit()));
+    }
+
+  return app.exec();
+}

+ 354 - 0
Libs/Widgets/ctkLayoutManager.cpp

@@ -0,0 +1,354 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.commontk.org/LICENSE
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=========================================================================*/
+
+// Qt includes
+#include <QDebug>
+#include <QGridLayout>
+#include <QHBoxLayout>
+#include <QLayout>
+#include <QTabWidget>
+#include <QVBoxLayout>
+#include <QWidget>
+
+// CTK includes
+#include "ctkLayoutManager.h"
+#include "ctkLayoutManager_p.h"
+
+//-----------------------------------------------------------------------------
+ctkLayoutManagerPrivate::ctkLayoutManagerPrivate(ctkLayoutManager& object)
+  :q_ptr(&object)
+{
+  this->Viewport = 0;
+}
+
+//-----------------------------------------------------------------------------
+ctkLayoutManagerPrivate::~ctkLayoutManagerPrivate()
+{
+}
+
+//-----------------------------------------------------------------------------
+void ctkLayoutManagerPrivate::init()
+{
+  //Q_Q(ctkLayoutManager);
+}
+
+//-----------------------------------------------------------------------------
+void ctkLayoutManagerPrivate::clearLayout(QLayout* layout)
+{
+  if (!layout)
+    {
+    return;
+    }
+  QLayoutItem * layoutItem = 0;
+  while ((layoutItem = layout->takeAt(0)) != 0)
+    {
+    if (layoutItem->widget())
+      {
+      layoutItem->widget()->setVisible(false);
+      layout->removeWidget(layoutItem->widget());
+      }
+    else if (layoutItem->layout())
+      {
+      this->clearLayout(layoutItem->layout());
+      }
+    }
+  if (layout->parentWidget() && layout->parentWidget()->layout() == layout)
+    {
+    delete layout;
+    }
+}
+
+//-----------------------------------------------------------------------------
+// ctkLayoutManager
+//-----------------------------------------------------------------------------
+ctkLayoutManager::ctkLayoutManager(QObject* parentObject)
+  : QObject(parentObject)
+  , d_ptr(new ctkLayoutManagerPrivate(*this))
+{
+  Q_D(ctkLayoutManager);
+  d->init();
+}
+
+//-----------------------------------------------------------------------------
+ctkLayoutManager::ctkLayoutManager(QWidget* viewport, QObject* parentObject)
+  : QObject(parentObject)
+  , d_ptr(new ctkLayoutManagerPrivate(*this))
+{
+  Q_D(ctkLayoutManager);
+  d->init();
+  this->setViewport(viewport);
+}
+
+//-----------------------------------------------------------------------------
+ctkLayoutManager::ctkLayoutManager(ctkLayoutManagerPrivate* ptr,
+                                   QWidget* viewport, QObject* parentObject)
+  : QObject(parentObject)
+  , d_ptr(ptr)
+{
+  Q_D(ctkLayoutManager);
+  d->init();
+  this->setViewport(viewport);
+}
+
+//-----------------------------------------------------------------------------
+ctkLayoutManager::~ctkLayoutManager()
+{
+
+}
+
+//-----------------------------------------------------------------------------
+void ctkLayoutManager::refresh()
+{
+  Q_D(ctkLayoutManager);
+  if (!d->Viewport)
+    {
+    return;
+    }
+  // TODO: post an event on the event queue
+  bool updatesEnabled = d->Viewport->updatesEnabled();
+  d->Viewport->setUpdatesEnabled(false);
+  this->clearLayout();
+  this->setupLayout();
+  d->Viewport->setUpdatesEnabled(updatesEnabled);
+}
+
+//-----------------------------------------------------------------------------
+void ctkLayoutManager::clearLayout()
+{
+  Q_D(ctkLayoutManager);
+  if (!d->Viewport)
+    {
+    return;
+    }
+  // TODO: post an event on the event queue
+  d->clearLayout(d->Viewport->layout());
+}
+
+//-----------------------------------------------------------------------------
+void ctkLayoutManager::setupLayout()
+{
+  Q_D(ctkLayoutManager);
+  if (!d->Viewport || d->Layout.isNull() ||
+      d->Layout.documentElement().isNull())
+    {
+    return;
+    }
+  d->Views.clear();
+  Q_ASSERT(!d->Viewport->layout());
+  QLayoutItem* layoutItem = this->processElement(
+    d->Layout.documentElement());
+  Q_ASSERT(layoutItem);
+  QLayout* layout = layoutItem->layout();
+  if (!layout)
+    {
+    QHBoxLayout* hboxLayout = new QHBoxLayout(0);
+    hboxLayout->addItem(layoutItem);
+    layout = hboxLayout;
+    }
+  // setting the layout to the widget will reparent all the 1 level widgets.
+  // Unfortunately, it has the side effect of hiding
+  // (testAttribute(Qt::WA_WState_Hidden)) the widgets that were already having
+  // a parent (read doc for QWidget::isHidden()).
+  // we then need to manually display the widgets again. Views is not probably
+  // not the best list to use to retrieve the widgets to remove the hidden flag
+  // it seems to fit the bill for the moment so we can keep using it.
+  d->Viewport->setLayout(layout);
+  foreach(QWidget* view, d->Views)
+    {
+    view->setHidden(false);
+    }
+}
+
+//-----------------------------------------------------------------------------
+void ctkLayoutManager::setViewport(QWidget* viewport)
+{
+  Q_D(ctkLayoutManager);
+  if (viewport == d->Viewport)
+    {
+    return;
+    }
+  this->clearLayout();
+  foreach(QWidget* view, d->Views)
+    {
+    if (view->parent() == d->Viewport)
+      {
+      view->setParent(0);
+      // reparenting looses the visibility attribute and we want them hidden
+      view->setVisible(false);
+      }
+    }
+  d->Viewport = viewport;
+  this->onViewportChanged();
+}
+
+//-----------------------------------------------------------------------------
+QWidget* ctkLayoutManager::viewport()const
+{
+  Q_D(const ctkLayoutManager);
+  return d->Viewport;
+}
+
+//-----------------------------------------------------------------------------
+void ctkLayoutManager::onViewportChanged()
+{
+  this->refresh();
+}
+
+//-----------------------------------------------------------------------------
+void ctkLayoutManager::setLayout(const QDomDocument& newLayout)
+{
+  Q_D(ctkLayoutManager);
+  if (newLayout == d->Layout)
+    {
+    return;
+    }
+  d->Layout = newLayout;
+  this->refresh();
+}
+
+//-----------------------------------------------------------------------------
+const QDomDocument ctkLayoutManager::layout()const
+{
+  Q_D(const ctkLayoutManager);
+  return d->Layout;
+}
+
+//-----------------------------------------------------------------------------
+QLayoutItem* ctkLayoutManager::processElement(QDomElement element)
+{
+  Q_ASSERT(!element.isNull());
+  if (element.tagName() == "layout")
+    {
+    return this->processLayoutElement(element);
+    }
+  else if (element.tagName() == "view")
+    {
+    return new QWidgetItem(this->processViewElement(element));
+    }
+  qDebug() << element.tagName() << element.text();
+  Q_ASSERT(element.tagName() != "layout" && element.tagName() != "view");
+  return 0;
+}
+
+//-----------------------------------------------------------------------------
+QLayoutItem* ctkLayoutManager::processLayoutElement(QDomElement layoutElement)
+{
+  Q_ASSERT(layoutElement.tagName() == "layout");
+
+  QLayoutItem* layoutItem = this->layoutFromXML(layoutElement);
+  QLayout* layout = layoutItem->layout();
+
+  if (layout)
+    {
+    layout->setContentsMargins(0,0,0,0);
+    layout->setSpacing(0);
+    }
+  for(QDomNode child = layoutElement.firstChild();
+      !child.isNull();
+      child = child.nextSibling())
+    {
+    // ignore children that are not QDomElement
+    if (child.toElement().isNull())
+      {
+      continue;
+      }
+    this->processItemElement(child.toElement(), layoutItem);
+    }
+  return layoutItem;
+}
+
+//-----------------------------------------------------------------------------
+QLayoutItem* ctkLayoutManager::layoutFromXML(QDomElement layoutElement)
+{
+  Q_ASSERT(layoutElement.tagName() == "layout");
+  QString type = layoutElement.attribute("type", "horizontal");
+  if (type == "vertical")
+    {
+    return new QVBoxLayout();
+    }
+  else if (type == "horizontal")
+    {
+    return new QHBoxLayout();
+    }
+  else if (type == "grid")
+    {
+    return new QGridLayout();
+    }
+  else if (type == "tab")
+    {
+    return new QWidgetItem(new QTabWidget());
+    }
+  return 0;
+}
+
+//-----------------------------------------------------------------------------
+void ctkLayoutManager::processItemElement(QDomElement itemElement, QLayoutItem* layoutItem)
+{
+  Q_ASSERT(itemElement.tagName() == "item");
+  Q_ASSERT(itemElement.childNodes().count() == 1);
+  QLayoutItem* childItem = this->processElement(itemElement.firstChild().toElement());
+  QLayout* layout = layoutItem->layout();
+  QGridLayout* gridLayout = qobject_cast<QGridLayout*>(layout);
+  QLayout* genericLayout = qobject_cast<QLayout*>(layout);
+  QTabWidget* tabWidget = qobject_cast<QTabWidget*>(layoutItem->widget());
+
+  if (gridLayout)
+    {
+    int row = itemElement.attribute("row", QString::number(0)).toInt();
+    int col = itemElement.attribute("column", QString::number(0)).toInt();
+    int rowSpan = itemElement.attribute("rowspan", QString::number(1)).toInt();
+    int colSpan = itemElement.attribute("colspan", QString::number(1)).toInt();
+    gridLayout->addItem(childItem, row, col, rowSpan, colSpan);
+    }
+  else if (genericLayout)
+    {
+    genericLayout->addItem(childItem);
+    }
+  else if (tabWidget)
+    {
+    QWidget* childWidget = childItem->widget();
+    if (!childWidget)
+      {
+      childWidget = new QWidget();
+      childWidget->setLayout(childItem->layout());
+      }
+    tabWidget->addTab(childWidget, itemElement.attribute("name"));
+    }
+}
+
+//-----------------------------------------------------------------------------
+QWidget* ctkLayoutManager::processViewElement(QDomElement viewElement)
+{
+  Q_D(ctkLayoutManager);
+  Q_ASSERT(viewElement.tagName() == "view");
+  QWidget* view = this->viewFromXML(viewElement);
+  Q_ASSERT(view);
+  view->setVisible(true);
+  d->Views.insert(view);
+  return view;
+}
+
+//-----------------------------------------------------------------------------
+QWidget* ctkLayoutManager::viewFromXML(QDomElement viewElement)
+{
+  Q_UNUSED(viewElement);
+  // default, for testing purpose. Must be reimplemented
+  return new QWidget(0);
+}

+ 79 - 0
Libs/Widgets/ctkLayoutManager.h

@@ -0,0 +1,79 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.commontk.org/LICENSE
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=========================================================================*/
+
+#ifndef __ctkLayoutManager_h
+#define __ctkLayoutManager_h
+
+// Qt includes
+#include <QObject>
+#include <QDomDocument>
+class QLayoutItem;
+
+// CTK includes
+#include "ctkWidgetsExport.h"
+class ctkLayoutManagerPrivate;
+
+/// ctkLayoutManager is
+class CTK_WIDGETS_EXPORT ctkLayoutManager: public QObject
+{
+  Q_OBJECT
+
+public:
+  /// Constructor
+  ctkLayoutManager(QObject* parent = 0);
+  explicit ctkLayoutManager(QWidget* viewport, QObject* parent);
+
+  /// Destructor
+  virtual ~ctkLayoutManager();
+
+  void setViewport(QWidget* widget);
+  QWidget* viewport()const;
+
+  void refresh();
+
+public slots:
+
+signals:
+  void layoutChanged();
+
+protected:
+  QScopedPointer<ctkLayoutManagerPrivate> d_ptr;
+  ctkLayoutManager(ctkLayoutManagerPrivate* ptr, QWidget* viewport, QObject* parent);
+
+  virtual void onViewportChanged();
+  void clearLayout();
+  void setupLayout();
+
+  virtual void setLayout(const QDomDocument& newLayout);
+  const QDomDocument layout()const;
+
+  virtual QLayoutItem* processElement(QDomElement element);
+  virtual QLayoutItem* processLayoutElement(QDomElement layoutElement);
+  virtual QLayoutItem* layoutFromXML(QDomElement layoutElement);
+  virtual void         processItemElement(QDomElement layoutElement, QLayoutItem* layoutItem);
+  virtual QWidget*     processViewElement(QDomElement layoutElement);
+  virtual QWidget*     viewFromXML(QDomElement layoutElement);
+
+private:
+  Q_DECLARE_PRIVATE(ctkLayoutManager);
+  Q_DISABLE_COPY(ctkLayoutManager);
+};
+
+#endif

+ 55 - 0
Libs/Widgets/ctkLayoutManager_p.h

@@ -0,0 +1,55 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+  http://www.commontk.org/LICENSE
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+  =========================================================================*/
+
+#ifndef __ctkLayoutManager_p_h
+#define __ctkLayoutManager_p_h
+
+// Qt includes
+#include <QDomDocument>
+#include <QObject>
+#include <QSet>
+
+class QLayout;
+class QWidget;
+
+// CTK includes
+#include "ctkLayoutManager.h"
+
+//-----------------------------------------------------------------------------
+class CTK_WIDGETS_EXPORT ctkLayoutManagerPrivate
+{
+  Q_DECLARE_PUBLIC(ctkLayoutManager);
+
+protected:
+  ctkLayoutManager* const q_ptr;
+
+public:
+  ctkLayoutManagerPrivate(ctkLayoutManager& object);
+  virtual ~ctkLayoutManagerPrivate();
+
+  virtual void init();
+  void clearLayout(QLayout* layout);
+
+  QWidget*       Viewport;
+  QDomDocument   Layout;
+  QSet<QWidget*> Views;
+};
+
+#endif

+ 110 - 0
Libs/Widgets/ctkSimpleLayoutManager.cpp

@@ -0,0 +1,110 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.commontk.org/LICENSE
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=========================================================================*/
+
+// Qt includes
+#include <QDebug>
+#include <QWidget>
+
+// CTK includes
+#include "ctkSimpleLayoutManager.h"
+#include "ctkLayoutManager_p.h"
+
+//-----------------------------------------------------------------------------
+class ctkSimpleLayoutManagerPrivate: public ctkLayoutManagerPrivate
+{
+public:
+  ctkSimpleLayoutManagerPrivate(ctkLayoutManager& object);
+  //QMetaObject ViewMetaObject;
+  ctkWidgetInstanciator* ViewInstanciator;
+};
+
+//-----------------------------------------------------------------------------
+ctkSimpleLayoutManagerPrivate::ctkSimpleLayoutManagerPrivate(ctkLayoutManager& object)
+  : ctkLayoutManagerPrivate(object)
+{
+  //this->ViewMetaObject = QWidget::staticMetaObject;
+  this->ViewInstanciator = 0;
+}
+
+//-----------------------------------------------------------------------------
+// ctkSimpleLayoutManager
+//-----------------------------------------------------------------------------
+ctkSimpleLayoutManager::ctkSimpleLayoutManager(QObject* parentObject)
+  : ctkLayoutManager(new ctkSimpleLayoutManagerPrivate(*this), 0, parentObject)
+{
+}
+
+//-----------------------------------------------------------------------------
+ctkSimpleLayoutManager::ctkSimpleLayoutManager(QWidget* viewport, QObject* parentObject)
+  : ctkLayoutManager(new ctkSimpleLayoutManagerPrivate(*this), viewport, parentObject)
+{
+}
+
+//-----------------------------------------------------------------------------
+ctkSimpleLayoutManager::~ctkSimpleLayoutManager()
+{
+
+}
+/*
+//-----------------------------------------------------------------------------
+void ctkSimpleLayoutManager::setViewMetaObject(const QMetaObject& viewMetaObject)
+{
+  Q_D(ctkSimpleLayoutManager);
+  d->ViewMetaObject = viewMetaObject;
+  this->refresh();
+}
+
+//-----------------------------------------------------------------------------
+const QMetaObject ctkSimpleLayoutManager::viewMetaObject()const
+{
+  Q_D(const ctkSimpleLayoutManager);
+  return d->ViewMetaObject;
+}
+*/
+
+//-----------------------------------------------------------------------------
+void ctkSimpleLayoutManager::setViewInstanciator(ctkWidgetInstanciator* instanciator)
+{
+  Q_D(ctkSimpleLayoutManager);
+  d->ViewInstanciator = instanciator;
+  this->refresh();
+}
+
+//-----------------------------------------------------------------------------
+ctkWidgetInstanciator* ctkSimpleLayoutManager::viewInstanciator()const
+{
+  Q_D(const ctkSimpleLayoutManager);
+  return d->ViewInstanciator;
+}
+
+//-----------------------------------------------------------------------------
+QWidget* ctkSimpleLayoutManager::viewFromXML(QDomElement viewElement)
+{
+  Q_UNUSED(viewElement);
+  Q_D(ctkSimpleLayoutManager);
+  //QObject* newView = d->ViewMetaObject.newInstance();
+  //Q_ASSERT(qobject_cast<QWidget*>(newView));
+  //return qobject_cast<QWidget*>(newView);
+  if (!d->ViewInstanciator)
+    {
+    return 0;
+    }
+  return d->ViewInstanciator->createWidget();
+}

+ 69 - 0
Libs/Widgets/ctkSimpleLayoutManager.h

@@ -0,0 +1,69 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.commontk.org/LICENSE
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=========================================================================*/
+
+#ifndef __ctkSimpleLayoutManager_h
+#define __ctkSimpleLayoutManager_h
+
+// Qt includes
+#include <QMetaObject>
+
+// CTK includes
+#include "ctkLayoutManager.h"
+class ctkSimpleLayoutManagerPrivate;
+
+struct ctkWidgetInstanciator
+{
+  virtual QWidget* createWidget() = 0;
+};
+
+template<class T>
+struct ctkTemplateInstanciator:public ctkWidgetInstanciator
+{
+  virtual QWidget* createWidget() {return new T;}
+};
+
+/// Utility class to access control on the DomDocument layout
+class CTK_WIDGETS_EXPORT ctkSimpleLayoutManager: public ctkLayoutManager
+{
+  Q_OBJECT
+public:
+  ctkSimpleLayoutManager(QObject* parent = 0);
+  explicit ctkSimpleLayoutManager(QWidget* viewport, QObject* parent);
+  virtual ~ctkSimpleLayoutManager();
+
+  using ctkLayoutManager::setLayout;
+  using ctkLayoutManager::layout;
+
+  // Note the default constructor of the class must be declared with
+  // Q_INVOKABLE.
+  //void setViewMetaObject(const QMetaObject& viewMetaObject);
+  //const QMetaObject viewMetaObject()const;
+  void setViewInstanciator(ctkWidgetInstanciator* instanciator);
+  ctkWidgetInstanciator* viewInstanciator()const;
+
+protected:
+ virtual QWidget* viewFromXML(QDomElement viewElement);
+
+private:
+  Q_DECLARE_PRIVATE(ctkSimpleLayoutManager);
+  Q_DISABLE_COPY(ctkSimpleLayoutManager);
+};
+
+#endif