diff --git a/Code/Mantid/DataHandling/inc/MantidDataHandling/CreateSampleShape.h b/Code/Mantid/DataHandling/inc/MantidDataHandling/CreateSampleShape.h
new file mode 100644
index 0000000000000000000000000000000000000000..ea4d00eea4fc991f422e7912fd925f90915b83cf
--- /dev/null
+++ b/Code/Mantid/DataHandling/inc/MantidDataHandling/CreateSampleShape.h
@@ -0,0 +1,68 @@
+#ifndef MANTID_DATAHANDLING_CREATESAMPLESHAPE_H_
+#define MANTID_DATAHANDLING_CREATESAMPLESHAPE_H_
+
+//--------------------------------
+// Includes
+//--------------------------------
+#include "MantidAPI/Algorithm.h"
+
+namespace Mantid
+{
+namespace DataHandling
+{
+
+/** 
+    This class allows the shape of the sample to be defined by using the allowed XML
+    expressions
+
+    @author Martyn Gigg, Tessella Support Services plc
+    @date 13/03/2009
+
+    Copyright © 2009 STFC Rutherford Appleton Laboratories
+
+    This file is part of Mantid.
+
+    Mantid is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    Mantid is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+    File change history is stored at: <https://svn.mantidproject.org/mantid/trunk/Code/Mantid>
+    Code Documentation is available at: <http://doxygen.mantidproject.org>    
+*/
+class CreateSampleShape : public Mantid::API::Algorithm
+{
+public:
+  /// (Empty) Constructor
+  CreateSampleShape() : Mantid::API::Algorithm() {}
+  /// Virtual destructor
+  virtual ~CreateSampleShape() {}
+  /// Algorithm's name
+  virtual const std::string name() const { return "CreateSampleShape"; }
+  /// Algorithm's version
+  virtual const int version() const { return (1); }
+  /// Algorithm's category for identification
+  virtual const std::string category() const { return "General"; }
+
+private:
+  /// Initialisation code
+  void init();
+  ///Execution code
+  void exec();
+
+  /// Static reference to the logger class
+  static Mantid::Kernel::Logger& g_log;
+};
+
+}
+}
+
+#endif /* MANTID_DATAHANDLING_CREATESAMPLESHAPE_H_*/
diff --git a/Code/Mantid/DataHandling/src/CreateSampleShape.cpp b/Code/Mantid/DataHandling/src/CreateSampleShape.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0ce21aa431d63f28e0db058b841081075f6c0811
--- /dev/null
+++ b/Code/Mantid/DataHandling/src/CreateSampleShape.cpp
@@ -0,0 +1,42 @@
+//--------------------------------
+// Includes
+//--------------------------------
+#include "MantidDataHandling/CreateSampleShape.h"
+#include "MantidGeometry/ShapeFactory.h"
+#include "MantidAPI/MatrixWorkspace.h"
+
+namespace Mantid
+{
+namespace DataHandling
+{
+  // Register the algorithm into the AlgorithmFactory
+  //  DECLARE_ALGORITHM(CreateSampleShape)
+}
+}
+
+using namespace Mantid::DataHandling;
+
+// Get a reference to the logger. It is used to print out information, warning and error messages
+Mantid::Kernel::Logger& CreateSampleShape::g_log = Mantid::Kernel::Logger::get("CreateSampleShape");
+
+
+
+/**
+ * Initialize the algorithm
+ */
+void CreateSampleShape::init()
+{
+  using namespace Mantid::Kernel;
+  using namespace Mantid::API;
+  declareProperty(new WorkspaceProperty<MatrixWorkspace>("Workspace","",Direction::Input));
+  declareProperty("ShapeXML","",new MandatoryValidator<std::string>());
+}
+
+/**
+ * Execute the algorithm
+ */
+void CreateSampleShape::exec()
+{
+  
+}
+
diff --git a/Code/qtiplot/MantidQt/CustomDialogs/inc/CreateSampleShapeDialog.h b/Code/qtiplot/MantidQt/CustomDialogs/inc/CreateSampleShapeDialog.h
new file mode 100644
index 0000000000000000000000000000000000000000..621f08db1e1e749821e0083fc6bae076a29330a6
--- /dev/null
+++ b/Code/qtiplot/MantidQt/CustomDialogs/inc/CreateSampleShapeDialog.h
@@ -0,0 +1,188 @@
+#ifndef MANTIDQT_CUSTOMDIALOGS_CREATESAMPLESHAPEDIALOG_H_
+#define MANTIDQT_CUSTOMDIALOGS_CREATESAMPLESHAPEDIALOG_H_
+
+//---------------------------
+// Includes
+//--------------------------
+#include "MantidQtCustomDialogs/ui_CreateSampleShapeDialog.h"
+#include "MantidQtAPI/AlgorithmDialog.h"
+
+#include <QTreeWidget>
+#include <QItemDelegate>
+#include <QPoint>
+#include <QHash>
+#include <QMap>
+#include <QVector>
+
+//-----------------------------------
+// Qt Forward declarations
+//---------------------------------
+
+namespace MantidQt
+{
+namespace CustomDialogs
+{
+
+class BinaryTreeWidget;
+class BinaryTreeWidgetItem;
+class ShapeDetails;
+
+/** 
+    This class gives specialised dialog for the sample shape definition
+    algorithm
+
+    @author Martyn Gigg, Tessella Support Services plc
+    @date 13/03/2009
+
+    Copyright &copy; 2009 STFC Rutherford Appleton Laboratories
+
+    This file is part of Mantid.
+
+    Mantid is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    Mantid is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+    File change history is stored at: <https://svn.mantidproject.org/mantid/trunk/Code/Mantid>
+    Code Documentation is available at: <http://doxygen.mantidproject.org>    
+*/
+class CreateSampleShapeDialog : public MantidQt::API::AlgorithmDialog
+{
+  Q_OBJECT
+
+public:
+  
+  /// Default constructor
+  CreateSampleShapeDialog(QWidget *parent = 0);
+  /// Destructor
+  ~CreateSampleShapeDialog();
+
+public slots:
+  ///Context menu request
+  void handleTreeContextMenuRequest(const QPoint & pos);
+
+  ///Add a new child shape
+  void addChildShape(QAction *shape);
+
+  // Setup the details box based currently selected item
+  void setupDetailsBox();
+
+private:
+
+  /// Initialize the layout
+  virtual void initLayout();
+  
+  /// Get the input out of the dialog
+  virtual void parseInput();
+
+  /**@name Details setup functions */
+  //@{
+  /// Setup the box for a sphere
+  ShapeDetails* setupSphereDetails() const;
+
+  /// Setup the box for a cylinder
+  ShapeDetails* setupCylinderDetails() const;
+  //@}
+
+private:
+  /// The form generated with Qt Designer
+  Ui::CreateSampleShapeDialog m_uiForm;
+
+  /// A pointer to the model for the shape tree
+  BinaryTreeWidget *m_shapeTree;
+
+  /// A map of shape names to function pointers
+  typedef ShapeDetails* (CreateSampleShapeDialog::*MemFuncGetter)() const;
+  QHash<QString, MemFuncGetter> m_setup_functions;
+
+  ///A map of QTreeWidgetItem objects to their details objects
+  QMap<BinaryTreeWidgetItem*, ShapeDetails*> m_details_map;
+};
+
+/**
+ * A custom item to use in the BinaryTree widget
+ */
+class BinaryTreeWidgetItem : public QTreeWidgetItem
+{
+
+public:
+  /// Default Constructor
+  BinaryTreeWidgetItem(int type = QTreeWidgetItem::UserType);
+
+  /// Constructor taking a string list and an optional type
+  BinaryTreeWidgetItem(const QStringList & strings, int type = QTreeWidgetItem::UserType);
+
+  /// Add a child item 
+  bool addChildItem(BinaryTreeWidgetItem *child);
+
+  /// A pointer to the left child
+  BinaryTreeWidgetItem* leftChild() const;
+
+  /// A pointer to the right child
+  BinaryTreeWidgetItem* rightChild() const;
+
+private:
+  /// The index of the left child (0 or 1)
+  int m_left_index;
+  /// The index of the right child (0 or 1)
+  int m_right_index;
+};
+
+/**
+ * A widget to implement a binary tree display.
+ */
+class BinaryTreeWidget : public QTreeWidget
+{
+  Q_OBJECT
+  
+public:
+  /// Default constructor
+  BinaryTreeWidget(QWidget *parent = 0);
+
+  /// Check that we have a full binary tree
+  bool isFullTree() const;
+
+  //Return the root of the binary tree
+  BinaryTreeWidgetItem* root() const;
+
+  /// Recurse through the tree in a pre-order
+  void traverseByPreorder(BinaryTreeWidgetItem* node);
+};
+
+/**
+ * A custom delegate class used for item editing
+ */
+class ComboBoxDelegate : public QItemDelegate
+{
+  Q_OBJECT
+
+public:
+  /// Default constructor
+  ComboBoxDelegate(QWidget *parent = 0);
+
+  QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
+			const QModelIndex &index) const;
+  
+  void setEditorData(QWidget *editor, const QModelIndex &index) const;
+  void setModelData(QWidget *editor, QAbstractItemModel *model,
+		    const QModelIndex &index) const;
+  
+  void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const;
+
+private:
+  /// A custom data role
+  static int g_idata_role;
+};
+
+}
+}
+
+#endif //MANTIDQT_CUSTOMDIALOGS_CREATESAMPLESHAPE_H_
diff --git a/Code/qtiplot/MantidQt/CustomDialogs/inc/CreateSampleShapeDialog.ui b/Code/qtiplot/MantidQt/CustomDialogs/inc/CreateSampleShapeDialog.ui
new file mode 100644
index 0000000000000000000000000000000000000000..bd056d143ea73b0ba2d328c9e33c443be32867ef
--- /dev/null
+++ b/Code/qtiplot/MantidQt/CustomDialogs/inc/CreateSampleShapeDialog.ui
@@ -0,0 +1,173 @@
+<ui version="4.0" >
+ <class>CreateSampleShapeDialog</class>
+ <widget class="QDialog" name="CreateSampleShapeDialog" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>866</width>
+    <height>360</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>Sample Shape Definition</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout" >
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout" >
+     <item>
+      <widget class="QGroupBox" name="shape_box" >
+       <property name="sizePolicy" >
+        <sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="title" >
+        <string>Object Tree</string>
+       </property>
+       <layout class="QHBoxLayout" name="horizontalLayout_3" />
+      </widget>
+     </item>
+     <item>
+      <widget class="QGroupBox" name="details_box" >
+       <property name="sizePolicy" >
+        <sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="title" >
+        <string>Details</string>
+       </property>
+       <layout class="QVBoxLayout" name="verticalLayout_2" >
+        <item>
+         <widget class="QScrollArea" name="details_scroll" >
+          <property name="frameShape" >
+           <enum>QFrame::NoFrame</enum>
+          </property>
+          <property name="frameShadow" >
+           <enum>QFrame::Raised</enum>
+          </property>
+          <property name="widgetResizable" >
+           <bool>true</bool>
+          </property>
+          <widget class="QWidget" name="scrollAreaWidgetContents" >
+           <property name="geometry" >
+            <rect>
+             <x>0</x>
+             <y>0</y>
+             <width>256</width>
+             <height>264</height>
+            </rect>
+           </property>
+          </widget>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item>
+      <widget class="QGroupBox" name="three_d_box" >
+       <property name="sizePolicy" >
+        <sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="title" >
+        <string>3D View</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout_2" >
+     <item>
+      <spacer name="horizontalSpacer" >
+       <property name="orientation" >
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0" >
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QPushButton" name="createBtn" >
+       <property name="text" >
+        <string>Create</string>
+       </property>
+       <property name="default" >
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="cancelBtn" >
+       <property name="text" >
+        <string>Cancel</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>createBtn</sender>
+   <signal>clicked()</signal>
+   <receiver>CreateSampleShapeDialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>741</x>
+     <y>379</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>438</x>
+     <y>201</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>cancelBtn</sender>
+   <signal>clicked()</signal>
+   <receiver>CreateSampleShapeDialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>827</x>
+     <y>379</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>438</x>
+     <y>201</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+ <designerdata>
+  <property name="gridDeltaX" >
+   <number>10</number>
+  </property>
+  <property name="gridDeltaY" >
+   <number>10</number>
+  </property>
+  <property name="gridSnapX" >
+   <bool>false</bool>
+  </property>
+  <property name="gridSnapY" >
+   <bool>false</bool>
+  </property>
+  <property name="gridVisible" >
+   <bool>true</bool>
+  </property>
+ </designerdata>
+</ui>
diff --git a/Code/qtiplot/MantidQt/CustomDialogs/inc/SampleShapeHelpers.h b/Code/qtiplot/MantidQt/CustomDialogs/inc/SampleShapeHelpers.h
new file mode 100644
index 0000000000000000000000000000000000000000..64e8a76ae847df21839d9d16a28f753c410a33f0
--- /dev/null
+++ b/Code/qtiplot/MantidQt/CustomDialogs/inc/SampleShapeHelpers.h
@@ -0,0 +1,161 @@
+#ifndef MANTIDQT_CUSTOMDIALOGS_SAMPLESHAPEHELPERS_H_
+#define MANTIDQT_CUSTOMDIALOGS_SAMPLESHAPEHELPERS_H_
+
+//--------------------------------------
+// Includes
+//--------------------------------------
+#include <QWidget>
+#include <QGroupBox>
+
+//--------------------------------------
+// Qt forward declarations
+//--------------------------------------
+class QLineEdit;
+class QComboBox;
+class QRadioButton;
+class QLabel;
+
+/**
+ * The classes defined here encapuslate the layout and
+ * parameters of the individual shapes within Mantid. Each is
+ * a widget that is to be displayed within the CreateSampleShapeDialog.
+ * The base class exists so that they can be stored in a container.
+ */
+namespace MantidQt
+{
+namespace CustomDialogs
+{
+
+/**
+ * A custom group box for a 3D point
+ */
+class PointGroupBox : public QGroupBox
+{
+  Q_OBJECT;
+
+public:
+  //Default constructor
+  PointGroupBox(QWidget* parent = 0);
+
+  ///Write the element tag for a 3D point
+  QString write3DElement(const QString & elem_name) const;
+
+private slots:
+  // Switch to cartesian coordinates
+  void changeToCartesian();
+  // Switch to spherical coordinates
+  void changeToSpherical();
+  
+private:
+  //Labels for fields
+  QLabel *m_xlabel, *m_ylabel, *m_zlabel;
+  // Edit fields (also used for r,theta,phi) if in spherical mode
+  QLineEdit *m_midx, *m_midy, *m_midz;
+  //Unit choice boxes (x is used for r in spherical mode)
+  QComboBox *m_xunits, *m_yunits, *m_zunits;
+  //Radio button selection for coordinates
+  QRadioButton *m_cartesian, *m_spherical;
+  //The current coordinate system (0 = cartesian, 1 = spherical)
+  int m_icoord;
+};
+
+
+/**
+ * The base class for the details widgets
+ */
+class ShapeDetails : public QWidget
+{
+  Q_OBJECT
+
+public:
+  ///Constructor
+  ShapeDetails(QWidget *parent = 0) : QWidget(parent) {}
+  ///Constructor
+  virtual ~ShapeDetails() {}
+
+  ///Write out the XML definition for this shape
+  virtual QString writeXML() const = 0;
+
+  /// Get the id string
+  QString getShapeID() const
+  { 
+    return m_idvalue;
+  }
+
+  ///Create a new length units box
+  static  QComboBox* createLengthUnitsCombo();
+  // Units enum
+  enum Unit { millimetre = 0, centimetre = 1, metre = 2 };
+  // Convert a string value from the given unit to metres
+  static QString convertToMetres(const QString & value, Unit start_unit);
+
+protected:
+  /// ID string of this object
+  QString m_idvalue;
+
+};
+
+/**
+ * A widget to define a sphere 
+ */
+class SphereDetails : public ShapeDetails
+{
+  Q_OBJECT
+
+private:
+  /// The number of objects that currently exist
+  static int g_nspheres;
+
+public:
+  ///Default constructor
+  SphereDetails(QWidget *parent = 0);
+
+  ///Default destructor 
+  ~SphereDetails() { --g_nspheres; }
+
+  //Write the XML definition of a sphere
+  QString writeXML() const;
+
+private:
+  /// Line edit for radius value
+  QLineEdit *m_radius_box;
+  /// Radius unit choice
+  QComboBox *m_runits;
+  /// Centre point group box
+  PointGroupBox *m_centre;
+};
+
+/**
+ * A widget to define a cylinder 
+ */
+class CylinderDetails : public ShapeDetails
+{
+  Q_OBJECT
+
+private:
+  /// The number of objects that currently exist
+  static int g_ncylinders;
+
+public:
+  ///Default constructor
+  CylinderDetails(QWidget *parent = 0);
+
+  ///Default destructor 
+  ~CylinderDetails() { --g_ncylinders; }
+
+  //Write the XML definition of a sphere
+  QString writeXML() const;
+
+private:
+  /// Line edits to enter values
+  QLineEdit *m_radius_box, *m_height_box;
+  //Unit choice boxes
+  QComboBox *m_runits, *m_hunits;
+  /// Centre and axis point boxes
+  PointGroupBox *m_lower_centre, *m_axis;
+};
+
+}
+}
+
+#endif // MANTIDQT_CUSTOMDIALOGS_SAMPLESHAPEHELPERS_H_
diff --git a/Code/qtiplot/MantidQt/CustomDialogs/src/CreateSampleShapeDialog.cpp b/Code/qtiplot/MantidQt/CustomDialogs/src/CreateSampleShapeDialog.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0aecd5a31f14ae6e830a31fb0d62a2cc3528d9fe
--- /dev/null
+++ b/Code/qtiplot/MantidQt/CustomDialogs/src/CreateSampleShapeDialog.cpp
@@ -0,0 +1,339 @@
+//---------------------------
+// Includes
+//--------------------------
+#include "MantidQtCustomDialogs/CreateSampleShapeDialog.h"
+#include "MantidQtAPI/AlgorithmInputHistory.h"
+#include "MantidQtCustomDialogs/SampleShapeHelpers.h"
+
+#include <QMenu>
+#include <QLabel>
+#include <QLineEdit>
+#include <QComboBox>
+
+#include <QMessageBox>
+#include <iostream>
+
+//Add this class to the list of specialised dialogs in this namespace
+namespace MantidQt
+{
+namespace CustomDialogs
+{
+  DECLARE_DIALOG(CreateSampleShapeDialog);
+}
+}
+
+// Just to save writing this everywhere 
+using namespace MantidQt::CustomDialogs;
+
+//---------------------------------------
+// Public member functions
+//---------------------------------------
+/**
+ * Constructor
+ */
+CreateSampleShapeDialog::CreateSampleShapeDialog(QWidget *parent) :
+  AlgorithmDialog(parent), m_setup_functions(), m_details_map()
+{
+}
+
+/**
+ * Destructor
+ */
+CreateSampleShapeDialog::~CreateSampleShapeDialog()
+{
+  QMutableMapIterator<BinaryTreeWidgetItem*, ShapeDetails*> itr(m_details_map);
+  while( itr.hasNext() ) {
+    itr.next();
+    ShapeDetails* obj = itr.value();
+    itr.remove();
+    delete obj;
+ }
+}
+
+/**
+ * Set up the dialog
+ */
+void CreateSampleShapeDialog::initLayout()
+{
+  //The main setup function
+  m_uiForm.setupUi(this);
+  
+  //Setup the function pointer map
+  m_setup_functions.clear();
+  m_setup_functions["sphere"] = &CreateSampleShapeDialog::setupSphereDetails;
+  m_setup_functions["cylinder"] = &CreateSampleShapeDialog::setupCylinderDetails;
+
+  //The binary tree
+  m_shapeTree = new BinaryTreeWidget(this);
+  m_shapeTree->setColumnCount(1);
+  m_shapeTree->setHeaderLabel("");
+  m_shapeTree->setContextMenuPolicy(Qt::CustomContextMenu);
+  m_shapeTree->insertTopLevelItem(0, new BinaryTreeWidgetItem(QStringList("complete-shape")));
+  m_shapeTree->setSelectionBehavior(QAbstractItemView::SelectItems);
+  connect(m_shapeTree, SIGNAL(customContextMenuRequested(const QPoint &)), 
+	  this, SLOT(handleTreeContextMenuRequest(const QPoint &)));
+  connect(m_shapeTree, SIGNAL(itemSelectionChanged()), this, SLOT(setupDetailsBox()));
+  
+  m_uiForm.shape_box->layout()->addWidget(m_shapeTree);
+}
+
+/**
+ * Retrieve the input from the dialog
+ */
+void CreateSampleShapeDialog::parseInput()
+{
+  BinaryTreeWidgetItem* root_item = m_shapeTree->root();
+  m_shapeTree->traverseByPreorder(root_item);
+
+}
+
+/**
+ * This slot is called when a context menu is requested inside the tree widget
+ */
+void CreateSampleShapeDialog::handleTreeContextMenuRequest(const QPoint & pos)
+{
+  QMenu *context_menu = new QMenu(m_shapeTree);
+  //pos is in widget coordinates
+  QTreeWidgetItem *item = m_shapeTree->itemAt(pos);
+  if( !item ) return;
+  
+  QMenu *submenu = new QMenu("Add child shape");
+  QStringList shapes = m_setup_functions.keys();
+  QStringListIterator itr(shapes);
+  while( itr.hasNext() )
+  {
+    submenu->addAction(new QAction(itr.next(), submenu));
+  }
+
+  connect(submenu, SIGNAL(triggered(QAction*)), this, SLOT(addChildShape(QAction*)));
+  
+  context_menu->addMenu(submenu);
+  context_menu->popup(QCursor::pos());
+}
+
+/**
+ * Add a new child shape
+ * @param shape The action that emitted the signal
+ */
+void CreateSampleShapeDialog::addChildShape(QAction *shape)
+{
+  //Get the selected item
+  BinaryTreeWidgetItem *parent = dynamic_cast<BinaryTreeWidgetItem*>(m_shapeTree->selectedItems()[0]);
+  if( parent->childCount() == 2 ) return;
+
+  BinaryTreeWidgetItem *child = new BinaryTreeWidgetItem(QStringList(shape->text()));
+  //Bit-wise AND with negated value of Qt::ItemIsEditable i.e. disable editing
+  child->setFlags(parent->flags() & ~Qt::ItemIsEditable);
+  parent->addChildItem(child);
+
+  //Reset properites of the parent to reflect the fact that it is not a primitive shape
+  QFont font = parent->font(0);
+  font.setBold(true);
+  parent->setFont(0, font);
+  parent->setData(0, Qt::DisplayRole, "intersection");
+  parent->setData(0, Qt::UserRole, 0);
+  parent->setFlags(parent->flags() | Qt::ItemIsEditable);
+
+  m_shapeTree->setCurrentItem(child);
+  m_shapeTree->expandAll();
+}
+
+/**
+ * Setup the layout for the details box based upon the item given
+ */
+void CreateSampleShapeDialog::setupDetailsBox()
+{
+  QList<QTreeWidgetItem*> selection = m_shapeTree->selectedItems();
+  if( selection.isEmpty() ) return;
+  
+  // Remove the current widget if one exists in the scroll area
+  if( m_uiForm.details_scroll->widget() ) m_uiForm.details_scroll->takeWidget();
+
+  BinaryTreeWidgetItem *item = dynamic_cast<BinaryTreeWidgetItem*>(selection[0]);
+  QString shapename = item->text(0);
+  if( m_setup_functions.contains(shapename) )
+  {
+    ShapeDetails *obj = NULL; 
+    if( m_details_map.contains(item) )
+    {
+      obj = m_details_map.value(item);
+    }
+    else 
+    {
+      // MemFuncGetter is a typedef for a function pointer
+      MemFuncGetter details_func = m_setup_functions.value(shapename);
+      // The '->*' operator has low precedence, hence the need for brackets
+      obj = (this->*details_func)();
+      m_details_map.insert(item, obj);
+    }
+    //Set it as the currently displayed widget
+    m_uiForm.details_scroll->setWidget(obj);    
+  }
+  
+}
+
+//---------------------------------------------
+// Details tab set up functions
+//--------------------------------------------
+/**
+ * Setup the details box for a sphere
+ * @param item The sphere item in the list
+ * @return A pointer to the details object
+ */
+ShapeDetails* CreateSampleShapeDialog::setupSphereDetails() const
+{
+  return new SphereDetails;
+}
+
+/**
+ * Setup the details box for a cylinder
+ * @param item The sphere item in the list
+ */
+ShapeDetails* CreateSampleShapeDialog::setupCylinderDetails() const
+{
+  return new CylinderDetails;
+}
+
+
+//=================================================================
+//=================================================================
+
+//------------------------------------------------
+// BinaryTreeWidgetItem
+//------------------------------------------------
+/**
+ * Default constructor
+ * @param type The type of the item
+ */
+BinaryTreeWidgetItem::BinaryTreeWidgetItem(int type) 
+  : QTreeWidgetItem(type), m_left_index(0), m_right_index(1)
+{
+}
+
+/**
+ * Construct an item with a string list of column texts to add
+ * @param A list of strings to appear as the column texts
+ * @param type Qt or User defined 
+ */
+BinaryTreeWidgetItem::BinaryTreeWidgetItem(const QStringList & strings, int type) 
+  : QTreeWidgetItem(strings, type), m_left_index(0), m_right_index(1)
+{
+}
+
+/**
+ * Add a child item. This will only succeed if there are fewer than 2 children currently
+ */
+bool BinaryTreeWidgetItem::addChildItem(BinaryTreeWidgetItem* child)
+{
+  if( childCount() >= 2 ) return false;
+  
+  // Call sub-class function
+  this->addChild(child);
+  return true;
+}
+
+/**
+ * A pointer to the left child. It can be NULL
+ */
+BinaryTreeWidgetItem* BinaryTreeWidgetItem::leftChild() const
+{
+  return dynamic_cast<BinaryTreeWidgetItem*>(this->child(m_left_index));
+}
+
+/**
+ * A pointer to the right child. It can be NULL
+ */
+BinaryTreeWidgetItem* BinaryTreeWidgetItem::rightChild() const
+{
+  return dynamic_cast<BinaryTreeWidgetItem*>(this->child(m_right_index));
+}
+
+
+
+//------------------------------------------------
+// BinaryTreeWidget
+//------------------------------------------------
+
+/**
+ * Default constructor
+ */
+BinaryTreeWidget::BinaryTreeWidget(QWidget *parent) : QTreeWidget(parent)
+{
+  ComboBoxDelegate *delegate = new ComboBoxDelegate(this);
+  setItemDelegate(delegate);
+}
+
+/**
+ * Gets the root item for the tree
+ */
+BinaryTreeWidgetItem* BinaryTreeWidget::root() const
+{
+  return dynamic_cast<BinaryTreeWidgetItem*>(invisibleRootItem()->child(0));
+}
+
+/**
+ * Recurse through the tree in a pre-order manner
+ */
+void BinaryTreeWidget::traverseByPreorder(BinaryTreeWidgetItem* node)
+{
+  // For the time begin just print the string that we get
+  QString itext = node->text(0);
+  if( itext.startsWith("i") ) itext = "x";
+  else if( itext.startsWith("u") ) itext = "+";
+  else if( itext.startsWith("d") ) itext = "-";
+  else {}
+
+  std::cerr << itext.toStdString() << " ";
+  if( node->leftChild() ) traverseByPreorder(node->leftChild());
+  if( node->rightChild() ) traverseByPreorder(node->rightChild());
+}
+
+
+//------------------------------------------------
+// ComboBoxDelegate
+//------------------------------------------------
+/// A user defined data type
+int ComboBoxDelegate::g_idata_role = 100;
+
+/**
+ * Default constructor
+ */
+ComboBoxDelegate::ComboBoxDelegate(QWidget *parent) : QItemDelegate(parent) 
+{
+}
+
+QWidget *ComboBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &,
+					  const QModelIndex &) const
+{
+  QComboBox *editor = new QComboBox(parent);
+  editor->addItem("union");
+  editor->addItem("intersection");
+  editor->addItem("difference");
+  
+  return editor;
+}
+
+void ComboBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
+{
+  int value = index.model()->data(index, g_idata_role).toInt();
+  
+  QComboBox *combo_box = qobject_cast<QComboBox*>(editor);
+  combo_box->setCurrentIndex(value);
+}
+
+void ComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
+				   const QModelIndex &index) const
+{
+  QComboBox *combo_box = static_cast<QComboBox*>(editor);
+  int boxitem = combo_box->currentIndex();
+  QString value = combo_box->itemText(boxitem);
+
+  model->setData(index, boxitem, g_idata_role);
+  model->setData(index, value, Qt::DisplayRole);
+}
+
+void ComboBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, 
+					   const QModelIndex &) const
+{
+  editor->setGeometry(option.rect);
+}
diff --git a/Code/qtiplot/MantidQt/CustomDialogs/src/SampleShapeHelpers.cpp b/Code/qtiplot/MantidQt/CustomDialogs/src/SampleShapeHelpers.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d2e2433cb4cdf691801c1823c8e3a1e1b0b3502a
--- /dev/null
+++ b/Code/qtiplot/MantidQt/CustomDialogs/src/SampleShapeHelpers.cpp
@@ -0,0 +1,289 @@
+//------------------------------------------
+// Includes
+//-----------------------------------------
+#include "MantidQtCustomDialogs/SampleShapeHelpers.h"
+
+#include <QLabel>
+#include <QLineEdit>
+#include <QComboBox>
+#include <QGridLayout>
+#include <QRadioButton>
+
+using namespace MantidQt::CustomDialogs;
+
+//-----------------------------------------//
+//         PointGroupBox helper class
+//----------------------------------------//
+PointGroupBox::PointGroupBox(QWidget* parent) : QGroupBox(parent), m_icoord(0)
+{
+  QGridLayout *grid = new QGridLayout;
+  
+  // The line edit fields
+  m_midx = new QLineEdit;
+  m_midy = new QLineEdit;
+  m_midz = new QLineEdit;
+
+  m_xunits = ShapeDetails::createLengthUnitsCombo();
+  m_yunits = ShapeDetails::createLengthUnitsCombo();
+  m_zunits = ShapeDetails::createLengthUnitsCombo();
+
+  // Radio selections
+  m_cartesian = new QRadioButton("Cartesian");
+  m_cartesian->setChecked(true);
+  m_spherical = new QRadioButton("Spherical");
+
+  connect(m_cartesian, SIGNAL(clicked(bool)), this, SLOT(changeToCartesian()));
+  connect(m_spherical, SIGNAL(clicked(bool)), this, SLOT(changeToSpherical()));
+
+  int row(0);
+  grid->addWidget(m_cartesian, row, 0, 1, 2);
+  grid->addWidget(m_spherical, row, 2, 1, 2);
+  ++row;
+  //labels
+  m_xlabel = new QLabel("x: ");
+  m_ylabel = new QLabel("y: ");
+  m_zlabel = new QLabel("z: ");
+  
+  // x
+  grid->addWidget(m_xlabel, row, 0, Qt::AlignRight);
+  grid->addWidget(m_midx, row, 1);
+  grid->addWidget(m_xunits, row, 2);
+  ++row;
+  // y
+  grid->addWidget(m_ylabel, row, 0);//, Qt::AlignRight);
+  grid->addWidget(m_midy, row, 1);
+  grid->addWidget(m_yunits, row, 2);
+  ++row;
+  // z
+  grid->addWidget(m_zlabel, row, 0, Qt::AlignRight);
+  grid->addWidget(m_midz, row, 1);
+  grid->addWidget(m_zunits, row, 2);
+  
+  setLayout(grid);
+}
+
+// Switch to cartesian coordinates
+void PointGroupBox::changeToCartesian()
+{
+  if( m_icoord == 0 ) return;
+
+  m_xlabel->setText("x: ");
+  m_ylabel->setText("y: ");
+  m_zlabel->setText("z: ");
+
+  m_yunits->setEnabled(true);
+  m_zunits->setEnabled(true);
+
+  m_icoord = 0;
+}
+
+// Switch to spherical coordinates
+void PointGroupBox::changeToSpherical()
+{
+  if( m_icoord == 1 ) return;
+
+  m_xlabel->setText("r: ");
+  m_ylabel->setText("theta: ");
+  m_zlabel->setText("phi: ");
+
+  //Units are in degrees for theta and phi
+  m_yunits->setEnabled(false);
+  m_zunits->setEnabled(false);
+
+  m_icoord = 1;
+}
+
+/**
+ * Write the element tag for a 3D point.
+ * elem_name The name of the element
+ */
+QString PointGroupBox::write3DElement(const QString & elem_name) const
+{
+  QString valx("0.0"), valy("0.0"), valz("0.0");
+  if( !m_midx->text().isEmpty() )
+  {
+    valx = ShapeDetails::convertToMetres(m_midx->text(), ShapeDetails::Unit(m_xunits->currentIndex()));
+  }
+  if( !m_midy->text().isEmpty() )
+  {
+    if( m_icoord == 0 )
+    {
+      valy = ShapeDetails::convertToMetres(m_midy->text(), ShapeDetails::Unit(m_yunits->currentIndex()));
+    }
+    else 
+    {
+      valy = m_midy->text();
+    }      
+  }
+  if( !m_midz->text().isEmpty() )
+  {
+    if( m_icoord == 0 )
+    {
+      valz = ShapeDetails::convertToMetres(m_midz->text(), ShapeDetails::Unit(m_zunits->currentIndex()));
+    }
+    else 
+    {
+      valz = m_midz->text();
+    }      
+  }
+  QString tag;
+  if( m_icoord == 0 )
+  {
+    tag = "<" + elem_name + " x=\"" + valx + "\" y=\"" + valy + "\" z= \"" + valz + "\" />\n";
+  }
+  else
+  {
+    tag = "<" + elem_name + " r=\"" + valx + "\" t=\"" + valy + "\" p= \"" + valz + "\" />\n";
+  }
+  return tag;
+}
+
+//----------------------------------------------------//
+//         Base ShapeDetails
+//---------------------------------------------------//
+/**
+ * Create a QComboBox filled with length units (static)
+ */
+QComboBox* ShapeDetails::createLengthUnitsCombo()
+{
+  QComboBox *units = new QComboBox;
+  QStringList unit_labels("mm");
+  unit_labels << "cm" << "m";
+  units->addItems(unit_labels);
+  return units;
+}
+
+/** Convert a string value from the given unit to metres (static)
+ * @param value The value to change
+ * @param start_unit Initial unit
+ * @returns A new string value in metres
+ */
+QString ShapeDetails::convertToMetres(const QString & value, Unit start_unit)
+{
+  QString converted;
+  switch( start_unit )
+  {
+  case ShapeDetails::centimetre: 
+    converted = QString::number(value.toDouble() / 100.0);
+    break;
+  case ShapeDetails::millimetre: 
+    converted = QString::number(value.toDouble() / 1000.0);
+    break;
+  default: 
+    converted = value;
+  }
+  return converted;
+}
+
+//--------------------------------------------//
+//                Sphere 
+//--------------------------------------------//
+/// Static counter
+int SphereDetails::g_nspheres = 0;
+
+/// Default constructor
+SphereDetails::SphereDetails(QWidget *parent) : ShapeDetails(parent)
+{
+  //Update number of sphere objects and the set the ID of this one
+  ++g_nspheres;
+  m_idvalue = "sphere-" + QString::number(g_nspheres);
+
+  QVBoxLayout *main_layout = new QVBoxLayout(this);
+  //radius
+  m_radius_box = new QLineEdit;
+  m_runits = createLengthUnitsCombo();
+  QHBoxLayout *rad_layout = new QHBoxLayout;
+  rad_layout->addWidget(new QLabel("Radius: "));
+  rad_layout->addWidget(m_radius_box);
+  rad_layout->addWidget(m_runits);
+
+  m_centre = new PointGroupBox;
+  m_centre->setTitle("Centre");
+  
+  main_layout->addLayout(rad_layout);
+  main_layout->addWidget(m_centre);
+}
+
+/**
+ * Write the XML definition
+ */
+QString SphereDetails::writeXML() const
+{
+  QString valr("0.0");
+  if( !m_radius_box->text().isEmpty() )
+  {
+    valr = convertToMetres(m_radius_box->text(), ShapeDetails::Unit(m_runits->currentIndex()));
+  }
+  QString xmldef = 
+    "<sphere id=\"" + m_idvalue + "\" />\n" + m_centre->write3DElement("centre") +
+    "<radius val=\"" + valr + "\" />\n"
+    "</sphere>\n";
+  return xmldef;
+}
+
+//-----------------------------------------//
+//                Cylinder
+//-----------------------------------------//
+/// Static counter
+int CylinderDetails::g_ncylinders = 0;
+
+/// Default constructor
+CylinderDetails::CylinderDetails(QWidget *parent) : ShapeDetails(parent)
+{
+  /// Update number of sphere objects and the set the ID of this one
+  ++g_ncylinders;
+  m_idvalue = "cylinder-" + QString::number(g_ncylinders);
+
+  QVBoxLayout *main_layout = new QVBoxLayout(this);
+  //radius
+  m_radius_box = new QLineEdit;
+  m_runits = createLengthUnitsCombo();
+  QHBoxLayout *rad_layout = new QHBoxLayout;
+  rad_layout->addWidget(new QLabel("Radius: "));
+  rad_layout->addWidget(m_radius_box);
+  rad_layout->addWidget(m_runits);
+
+  //height
+  m_height_box = new QLineEdit;
+  m_hunits = createLengthUnitsCombo();
+  QHBoxLayout *hgt_layout = new QHBoxLayout;
+  hgt_layout->addWidget(new QLabel("Height:  "));
+  hgt_layout->addWidget(m_height_box);
+  hgt_layout->addWidget(m_hunits);
+
+  //Point boxes
+  m_lower_centre = new PointGroupBox;
+  m_lower_centre->setTitle("Bottom Base Centre");
+
+  m_axis = new PointGroupBox;
+  m_axis->setTitle("Axis");
+  
+  main_layout->addLayout(rad_layout);
+  main_layout->addLayout(hgt_layout);
+  main_layout->addWidget(m_lower_centre);
+  main_layout->addWidget(m_axis);
+}
+
+/**
+ * Write the XML definition
+ */
+QString CylinderDetails::writeXML() const
+{
+  QString valr("0.0"), valh("0.0");
+  if( !m_radius_box->text().isEmpty() )
+  {
+    valr = convertToMetres(m_radius_box->text(), ShapeDetails::Unit(m_runits->currentIndex()));
+  }
+  if( !m_height_box->text().isEmpty() )
+  {
+    valh = convertToMetres(m_height_box->text(), ShapeDetails::Unit(m_hunits->currentIndex()));
+  }
+  QString xmldef = 
+    "<cylinder id=\"" + m_idvalue + "\" />\n"
+    "<radius val=\"" + valr + "\" />\n"
+    "<height val=\"" + valh + "\" />\n" + 
+    m_lower_centre->write3DElement("centre-of-bottom-base") +
+    m_axis->write3DElement("axis") +
+    "</cylinder>\n";
+  return xmldef;
+}