[med-svn] [itksnap] 01/04: Imported Upstream version 3.4.0

Gert Wollny gert-guest at moszumanska.debian.org
Tue Jan 19 19:54:45 UTC 2016


This is an automated email from the git hooks/post-receive script.

gert-guest pushed a commit to branch master
in repository itksnap.

commit 4a6bbfc79774454205b311275403fa138150a74d
Author: Gert Wollny <gw.fossdev at gmail.com>
Date:   Mon Jan 11 13:31:42 2016 +0100

    Imported Upstream version 3.4.0
---
 .gitignore                                         |    2 +-
 CMake/GitBranch.cmake                              |   23 +
 CMake/standalone.cmake                             |   69 +-
 CMakeLists.txt                                     |  203 +++-
 CTestConfig.cmake                                  |   12 +-
 Common/IPCHandler.cxx                              |   27 +
 Common/IPCHandler.h                                |    5 +
 .../itkMaximumGradientMagnitudeImageFilter.h       |  152 +++
 .../itkMaximumGradientMagnitudeImageFilter.hxx     |  266 +++++
 Common/PropertyModel.h                             |   65 +-
 Common/SNAPCommon.cxx.in                           |    1 +
 Common/SNAPEventListenerCallbacks.h                |    3 +-
 Common/SNAPOpenGL.cxx                              |   34 +
 Common/SNAPOpenGL.h                                |    3 +
 GUI/Model/AnnotationModel.cxx                      |  778 ++++++++++++
 GUI/Model/AnnotationModel.h                        |  149 +++
 GUI/Model/CursorInspectionModel.cxx                |   48 +-
 GUI/Model/CursorInspectionModel.h                  |    6 +-
 GUI/Model/DisplayLayoutModel.cxx                   |   91 ++
 GUI/Model/DisplayLayoutModel.h                     |   40 +-
 GUI/Model/GenericSliceModel.cxx                    |  342 +++++-
 GUI/Model/GenericSliceModel.h                      |  107 +-
 GUI/Model/GlobalUIModel.cxx                        |  101 +-
 GUI/Model/GlobalUIModel.h                          |   35 +-
 GUI/Model/ImageIOWizardModel.cxx                   |  122 +-
 GUI/Model/ImageIOWizardModel.h                     |   92 ++
 GUI/Model/ImageRegistrationManager.cxx             |  175 +++
 GUI/Model/ImageRegistrationManager.h               |   70 ++
 GUI/Model/LayerGeneralPropertiesModel.cxx          |   50 +
 GUI/Model/LayerGeneralPropertiesModel.h            |   18 +-
 GUI/Model/LayerTableRowModel.cxx                   |   87 +-
 GUI/Model/LayerTableRowModel.h                     |   12 +
 GUI/Model/NumericPropertyToggleAdaptor.h           |    2 +-
 GUI/Model/OrthogonalSliceCursorNavigationModel.cxx |    8 +-
 GUI/Model/OrthogonalSliceCursorNavigationModel.h   |    2 +-
 GUI/Model/PaintbrushModel.cxx                      |  119 +-
 GUI/Model/PaintbrushModel.h                        |    8 +-
 GUI/Model/PolygonDrawingModel.cxx                  |   15 +-
 GUI/Model/PolygonDrawingModel.h                    |   11 +-
 GUI/Model/PolygonSettingsModel.cxx                 |   82 ++
 GUI/Model/PolygonSettingsModel.h                   |   41 +
 GUI/Model/SnakeWizardModel.cxx                     |  284 ++++-
 GUI/Model/SnakeWizardModel.h                       |   76 +-
 GUI/Model/SynchronizationModel.cxx                 |    3 +-
 GUI/Model/UIReporterDelegates.h                    |   10 +
 GUI/Model/UIState.h                                |    3 +-
 GUI/Qt/Components/AnnotationToolPanel.cxx          |   83 ++
 GUI/Qt/Components/AnnotationToolPanel.h            |   31 +
 GUI/Qt/Components/AnnotationToolPanel.ui           |  425 +++++++
 GUI/Qt/Components/CursorInspector.cxx              |  162 ++-
 GUI/Qt/Components/CursorInspector.h                |   20 +-
 GUI/Qt/Components/CursorInspector.ui               |  242 ++--
 GUI/Qt/Components/DisplayLayoutInspector.cxx       |    9 +
 GUI/Qt/Components/DisplayLayoutInspector.ui        |  119 +-
 GUI/Qt/Components/FileChooserPanelWithHistory.cxx  |   18 +-
 GUI/Qt/Components/FileChooserPanelWithHistory.h    |    1 +
 GUI/Qt/Components/GeneralLayerInspector.cxx        |   44 +-
 GUI/Qt/Components/GeneralLayerInspector.h          |    4 +
 GUI/Qt/Components/GeneralLayerInspector.ui         |  510 +++++++-
 GUI/Qt/Components/HistoryQListModel.cxx            |  146 ++-
 GUI/Qt/Components/HistoryQListModel.h              |   42 +-
 GUI/Qt/Components/LabelInspector.cxx               |   10 +-
 GUI/Qt/Components/LabelInspector.ui                |  531 ++++-----
 GUI/Qt/Components/LabelSelectionButton.cxx         |   20 +-
 GUI/Qt/Components/LatentITKEventNotifier.cxx       |   14 +-
 GUI/Qt/Components/LayerInspectorRowDelegate.cxx    |  248 +++-
 GUI/Qt/Components/LayerInspectorRowDelegate.h      |   59 +-
 GUI/Qt/Components/LayerInspectorRowDelegate.ui     |  570 +++++----
 GUI/Qt/Components/PaintbrushToolPanel.cxx          |   28 +
 GUI/Qt/Components/PaintbrushToolPanel.h            |    5 +-
 GUI/Qt/Components/PaintbrushToolPanel.ui           |  296 ++++-
 GUI/Qt/Components/PolygonToolPanel.cxx             |   51 +
 GUI/Qt/Components/PolygonToolPanel.h               |   27 +
 GUI/Qt/Components/PolygonToolPanel.ui              |  207 ++++
 GUI/Qt/Components/QtHideOnDeactivateContainer.cxx  |   24 +
 GUI/Qt/Components/QtHideOnDeactivateContainer.h    |   16 +
 GUI/Qt/Components/QtRendererPlatformSupport.cxx    |   49 +-
 GUI/Qt/Components/QtRendererPlatformSupport.h      |    8 +-
 GUI/Qt/Components/QtReporterDelegates.cxx          |   45 +-
 GUI/Qt/Components/QtWidgetActivator.cxx            |   18 +-
 GUI/Qt/Components/QtWidgetActivator.h              |   36 +-
 GUI/Qt/Components/RecentHistoryItemsView.cxx       |    6 +
 GUI/Qt/Components/SNAPComponent.h                  |    4 +
 GUI/Qt/Components/SNAPQtCommon.cxx                 |   50 +-
 GUI/Qt/Components/SNAPQtCommon.h                   |    3 +
 GUI/Qt/Components/SliceViewPanel.cxx               |  156 ++-
 GUI/Qt/Components/SliceViewPanel.h                 |   21 +-
 GUI/Qt/Components/SliceViewPanel.ui                |  391 +++++-
 GUI/Qt/Components/SnakeToolROIPanel.cxx            |    4 +
 GUI/Qt/Components/SnakeToolROIPanel.ui             |  227 ++--
 GUI/Qt/Components/SnakeWizardPanel.cxx             |  104 +-
 GUI/Qt/Components/SnakeWizardPanel.h               |   13 +-
 GUI/Qt/Components/SnakeWizardPanel.ui              |  382 ++++--
 GUI/Qt/Components/SynchronizationInspector.cxx     |    5 -
 GUI/Qt/Components/SynchronizationInspector.ui      |  107 +-
 GUI/Qt/Components/ZoomInspector.ui                 |  200 ++--
 GUI/Qt/Coupling/QtAbstractItemViewCoupling.h       |   82 +-
 GUI/Qt/Coupling/QtSliderCoupling.h                 |    5 +
 GUI/Qt/Coupling/QtWidgetCoupling.h                 |   35 +-
 GUI/Qt/Resources/SNAPResources.qrc                 |   57 +
 GUI/Qt/Resources/SNAPResources_Linux.qrc           |    2 +
 GUI/Qt/Resources/SNAPResources_MacOS.qrc           |    2 +
 GUI/Qt/Resources/SNAPResources_Windows.qrc         |    2 +
 GUI/Qt/Resources/annotation_28.png                 |  Bin 0 -> 1917 bytes
 GUI/Qt/Resources/context_gray_10.png               |  Bin 0 -> 395 bytes
 GUI/Qt/Resources/context_gray_10 at 2x.png            |  Bin 0 -> 690 bytes
 GUI/Qt/Resources/context_gray_12.png               |  Bin 0 -> 448 bytes
 GUI/Qt/Resources/context_gray_12 at 2x.png            |  Bin 0 -> 804 bytes
 GUI/Qt/Resources/context_gray_16.png               |  Bin 0 -> 1730 bytes
 GUI/Qt/Resources/context_gray_48.png               |  Bin 0 -> 1651 bytes
 .../Resources/html/tooltips/ModeTipTemplate.html   |   38 +
 GUI/Qt/Resources/html/tooltips/TipTableRow.html    |    6 +
 GUI/Qt/Resources/icons8_cursor_16.png              |  Bin 0 -> 524 bytes
 GUI/Qt/Resources/icons8_cursor_16 at 2x.png           |  Bin 0 -> 917 bytes
 GUI/Qt/Resources/icons8_down_12.png                |  Bin 0 -> 415 bytes
 GUI/Qt/Resources/icons8_down_12 at x2.png             |  Bin 0 -> 517 bytes
 GUI/Qt/Resources/icons8_film_reel_12.png           |  Bin 0 -> 472 bytes
 GUI/Qt/Resources/icons8_film_reel_12 at 2x.png        |  Bin 0 -> 870 bytes
 GUI/Qt/Resources/icons8_generic_text_16.png        |  Bin 0 -> 465 bytes
 GUI/Qt/Resources/icons8_generic_text_16 at 2x.png     |  Bin 0 -> 720 bytes
 GUI/Qt/Resources/icons8_invisible_12.png           |  Bin 0 -> 424 bytes
 GUI/Qt/Resources/icons8_invisible_12 at 2x.png        |  Bin 0 -> 672 bytes
 GUI/Qt/Resources/icons8_layers_16.png              |  Bin 0 -> 563 bytes
 GUI/Qt/Resources/icons8_layers_16 at 2x.png           |  Bin 0 -> 1018 bytes
 GUI/Qt/Resources/icons8_mouse_left_click_16.png    |  Bin 0 -> 517 bytes
 GUI/Qt/Resources/icons8_mouse_left_click_16 at 2x.png |  Bin 0 -> 937 bytes
 GUI/Qt/Resources/icons8_mouse_right_click_16.png   |  Bin 0 -> 517 bytes
 .../Resources/icons8_mouse_right_click_16 at 2x.png   |  Bin 0 -> 923 bytes
 GUI/Qt/Resources/icons8_mouse_scrolling_16.png     |  Bin 0 -> 532 bytes
 GUI/Qt/Resources/icons8_mouse_scrolling_16 at 2x.png  |  Bin 0 -> 989 bytes
 GUI/Qt/Resources/icons8_palette_16.png             |  Bin 0 -> 556 bytes
 GUI/Qt/Resources/icons8_palette_16 at 2x.png          |  Bin 0 -> 931 bytes
 GUI/Qt/Resources/icons8_pin-48.png                 |  Bin 0 -> 716 bytes
 GUI/Qt/Resources/icons8_pin_10.png                 |  Bin 0 -> 708 bytes
 GUI/Qt/Resources/icons8_pin_12.png                 |  Bin 0 -> 436 bytes
 GUI/Qt/Resources/icons8_pin_12 at 2x.png              |  Bin 0 -> 662 bytes
 GUI/Qt/Resources/icons8_redo-48.png                |  Bin 0 -> 727 bytes
 GUI/Qt/Resources/icons8_refresh-48.png             |  Bin 0 -> 741 bytes
 GUI/Qt/Resources/icons8_ruler_16.png               |  Bin 0 -> 527 bytes
 GUI/Qt/Resources/icons8_ruler_16 at 2x.png            |  Bin 0 -> 877 bytes
 GUI/Qt/Resources/icons8_slr_camera_12.png          |  Bin 0 -> 451 bytes
 GUI/Qt/Resources/icons8_slr_camera_12 at 2x.png       |  Bin 0 -> 723 bytes
 GUI/Qt/Resources/icons8_slr_camera_16.png          |  Bin 0 -> 568 bytes
 GUI/Qt/Resources/icons8_slr_camera_16 at 2x.png       |  Bin 0 -> 928 bytes
 GUI/Qt/Resources/icons8_star-48.png                |  Bin 0 -> 661 bytes
 GUI/Qt/Resources/icons8_star_12.png                |  Bin 0 -> 1769 bytes
 GUI/Qt/Resources/icons8_star_8.png                 |  Bin 0 -> 1631 bytes
 GUI/Qt/Resources/icons8_undo-48.png                |  Bin 0 -> 707 bytes
 GUI/Qt/Resources/icons8_unpin_12.png               |  Bin 0 -> 461 bytes
 GUI/Qt/Resources/icons8_unpin_12 at 2x.png            |  Bin 0 -> 753 bytes
 GUI/Qt/Resources/icons8_up_12.png                  |  Bin 0 -> 416 bytes
 GUI/Qt/Resources/icons8_up_12 at x2.png               |  Bin 0 -> 507 bytes
 GUI/Qt/Resources/icons8_visible_12.png             |  Bin 0 -> 420 bytes
 GUI/Qt/Resources/icons8_visible_12 at 2x.png          |  Bin 0 -> 655 bytes
 GUI/Qt/Resources/icons8_whitepin_16.png            |  Bin 0 -> 1013 bytes
 GUI/Qt/Resources/layout_thumb_16.png               |  Bin 0 -> 1238 bytes
 GUI/Qt/Resources/menu-arrow_8.png                  |  Bin 0 -> 1157 bytes
 GUI/Qt/Resources/menu-arrow_8 at 2x.png               |  Bin 0 -> 1258 bytes
 GUI/Qt/Resources/source/annotation_28.graffle      |  Bin 0 -> 2833 bytes
 GUI/Qt/View/AnnotationInteractionMode.cxx          |  137 +++
 GUI/Qt/View/AnnotationInteractionMode.h            |   45 +
 GUI/Qt/View/CrosshairsInteractionMode.cxx          |  140 ++-
 GUI/Qt/View/CrosshairsInteractionMode.h            |    4 +
 GUI/Qt/View/GenericSliceView.cxx                   |    7 +
 GUI/Qt/View/PaintbrushInteractionMode.cxx          |    6 +-
 GUI/Qt/View/PolygonDrawingInteractionMode.cxx      |    6 +-
 GUI/Qt/View/QtAbstractOpenGLBox.cxx                |   20 +-
 GUI/Qt/View/QtAbstractOpenGLBox.h                  |   19 +-
 GUI/Qt/View/QtInteractionDelegateWidget.cxx        |   89 +-
 GUI/Qt/View/QtInteractionDelegateWidget.h          |   25 +-
 GUI/Qt/View/QtVTKInteractionDelegateWidget.cxx     |    5 +-
 GUI/Qt/View/QtVTKRenderWindowBox.cxx               |   13 +-
 .../View/SliceWindowInteractionDelegateWidget.cxx  |   59 +-
 GUI/Qt/View/SliceWindowInteractionDelegateWidget.h |   10 +
 GUI/Qt/View/SnakeROIInteractionMode.cxx            |   25 +-
 GUI/Qt/View/ThumbnailInteractionMode.cxx           |  117 +-
 GUI/Qt/View/ThumbnailInteractionMode.h             |    8 +
 GUI/Qt/Windows/AboutDialog.ui                      |  102 +-
 GUI/Qt/Windows/DropActionDialog.ui                 |   20 +-
 GUI/Qt/Windows/ImageIOWizard.cxx                   |  166 ++-
 GUI/Qt/Windows/ImageIOWizard.h                     |   22 +-
 GUI/Qt/Windows/ImageIOWizard/OverlayRolePage.cxx   |   56 +
 GUI/Qt/Windows/ImageIOWizard/OverlayRolePage.h     |   31 +
 GUI/Qt/Windows/ImageIOWizard/OverlayRolePage.ui    |  222 ++++
 GUI/Qt/Windows/ImageIOWizard/RegistrationPage.cxx  |   92 ++
 GUI/Qt/Windows/ImageIOWizard/RegistrationPage.h    |   58 +
 GUI/Qt/Windows/ImageIOWizard/RegistrationPage.ui   |  154 +++
 GUI/Qt/Windows/LabelEditorDialog.cxx               |   14 +-
 GUI/Qt/Windows/LabelEditorDialog.ui                |   13 +-
 GUI/Qt/Windows/LayerInspectorDialog.cxx            |   43 +-
 GUI/Qt/Windows/LayerInspectorDialog.h              |    3 +
 GUI/Qt/Windows/LayerInspectorDialog.ui             |   24 +-
 GUI/Qt/Windows/MainControlPanel.cxx                |  257 ++--
 GUI/Qt/Windows/MainControlPanel.h                  |   15 +-
 GUI/Qt/Windows/MainControlPanel.ui                 | 1247 +++++++++++++++-----
 GUI/Qt/Windows/MainImageWindow.cxx                 |  562 ++++++++-
 GUI/Qt/Windows/MainImageWindow.h                   |   14 +-
 GUI/Qt/Windows/MainImageWindow.ui                  |  245 +++-
 .../Windows/MeshExportWizard/MeshExportWizard.cxx  |    4 +
 GUI/Qt/Windows/PreferencesDialog.cxx               |    5 +-
 GUI/Qt/Windows/PreferencesDialog.ui                |    8 +-
 GUI/Qt/Windows/SaveModifiedLayersDialog.cxx        |    8 +-
 GUI/Qt/Windows/SimpleFileDialogWithHistory.cxx     |    3 +
 GUI/Qt/Windows/SpeedImageDialog.cxx                |   40 +-
 GUI/Qt/Windows/SpeedImageDialog.h                  |    4 +-
 GUI/Qt/Windows/SpeedImageDialog.ui                 |  480 +++++++-
 GUI/Qt/Windows/SplashPanel.ui                      |    2 +-
 GUI/Qt/main.cxx                                    |  144 ++-
 GUI/Renderer/AbstractRenderer.h                    |    9 +-
 GUI/Renderer/AbstractVTKRenderer.cxx               |   12 +-
 GUI/Renderer/AbstractVTKRenderer.h                 |   11 +-
 GUI/Renderer/AbstractVTKSceneRenderer.cxx          |   27 +
 GUI/Renderer/AbstractVTKSceneRenderer.h            |    5 +
 GUI/Renderer/AnnotationRenderer.cxx                |  322 +++++
 GUI/Renderer/AnnotationRenderer.h                  |   33 +
 GUI/Renderer/ColorMapRenderer.cxx                  |    4 +-
 GUI/Renderer/ColorMapRenderer.h                    |    2 +-
 GUI/Renderer/CrosshairsRenderer.cxx                |    2 +-
 GUI/Renderer/EdgePreprocessingSettingsRenderer.cxx |    5 +
 GUI/Renderer/EdgePreprocessingSettingsRenderer.h   |    2 +
 GUI/Renderer/GMMRenderer.cxx                       |    5 +
 GUI/Renderer/GMMRenderer.h                         |    2 +
 GUI/Renderer/GenericSliceRenderer.cxx              |  323 +++--
 GUI/Renderer/GenericSliceRenderer.h                |   21 +-
 GUI/Renderer/IntensityCurveVTKRenderer.cxx         |   10 +-
 GUI/Renderer/IntensityCurveVTKRenderer.h           |    2 +
 GUI/Renderer/OptimizationProgressRenderer.cxx      |   96 ++
 GUI/Renderer/OptimizationProgressRenderer.h        |   46 +
 GUI/Renderer/PolygonDrawingRenderer.cxx            |    5 +-
 GUI/Renderer/PolygonScanConvert.cxx                |    2 +-
 GUI/Renderer/SliceWindowDecorationRenderer.cxx     |  109 +-
 GUI/Renderer/SliceWindowDecorationRenderer.h       |    1 +
 GUI/Renderer/SnakeModeRenderer.cxx                 |    3 +-
 GUI/Renderer/SnakeParameterPreviewRenderer.cxx     |    4 +-
 GUI/Renderer/SnakeParameterPreviewRenderer.h       |    2 +-
 GUI/Renderer/SnakeROIRenderer.cxx                  |    2 +-
 GUI/Renderer/ThresholdSettingsRenderer.cxx         |    7 +
 GUI/Renderer/ThresholdSettingsRenderer.h           |    2 +
 Logic/Common/ColorMap.cxx                          |   45 +-
 Logic/Common/ColorMap.h                            |    5 +
 Logic/Common/SNAPAppearanceSettings.cxx            |    8 +
 Logic/Common/SNAPAppearanceSettings.h              |    5 +
 Logic/Common/SNAPRegistryIO.cxx                    |    4 +
 Logic/Common/SNAPSegmentationROISettings.cxx       |    3 +-
 Logic/Common/SNAPSegmentationROISettings.h         |   10 +
 Logic/Framework/GenericImageData.cxx               |  250 +++-
 Logic/Framework/GenericImageData.h                 |   59 +-
 Logic/Framework/GlobalState.cxx                    |   15 +-
 Logic/Framework/GlobalState.h                      |   50 +-
 Logic/Framework/IRISApplication.cxx                |  448 ++++---
 Logic/Framework/IRISApplication.h                  |   50 +-
 Logic/Framework/ImageAnnotationData.cxx            |  196 +++
 Logic/Framework/ImageAnnotationData.h              |  181 +++
 Logic/Framework/ImageIODelegates.cxx               |   54 +-
 Logic/Framework/ImageIODelegates.h                 |   47 +-
 Logic/Framework/LayerIterator.cxx                  |    9 +
 Logic/Framework/LayerIterator.h                    |    2 +
 Logic/Framework/SNAPImageData.cxx                  |   63 +
 Logic/Framework/SNAPImageData.h                    |   22 +
 Logic/Framework/UndoDataManager.h                  |    5 +
 Logic/ImageWrapper/DisplayMappingPolicy.cxx        |    5 +
 Logic/ImageWrapper/DisplayMappingPolicy.h          |    6 +
 Logic/ImageWrapper/GuidedNativeImageIO.cxx         |   60 +-
 Logic/ImageWrapper/ImageWrapper.cxx                |  106 +-
 Logic/ImageWrapper/ImageWrapper.h                  |   40 +-
 Logic/ImageWrapper/ImageWrapperBase.h              |   43 +-
 Logic/ImageWrapper/NativeIntensityMappingPolicy.h  |   15 +
 Logic/ImageWrapper/ScalarImageWrapper.cxx          |   64 +-
 Logic/ImageWrapper/ScalarImageWrapper.h            |   38 +-
 Logic/ImageWrapper/VectorImageWrapper.cxx          |   16 +-
 Logic/ImageWrapper/VectorImageWrapper.h            |   10 +-
 Logic/Preprocessing/EdgePreprocessingImageFilter.h |    8 +-
 Logic/Preprocessing/ImageCollectionToImageFilter.h |   71 ++
 .../PreprocessingFilterConfigTraits.h              |    8 +
 .../RandomForest/RFClassificationEngine.cxx        |  105 +-
 .../RandomForest/RFClassificationEngine.h          |   30 +-
 .../RandomForest/RandomForestClassifier.cxx        |   32 +-
 .../RandomForest/RandomForestClassifier.h          |   40 +-
 .../RandomForestClassifyImageFilter.txx            |   85 +-
 Logic/Preprocessing/SlicePreviewFilterWrapper.h    |    4 +-
 Logic/Preprocessing/SlicePreviewFilterWrapper.txx  |    2 +-
 Logic/Preprocessing/Texture/MomentTextures.cxx     |  172 +++
 Logic/Preprocessing/Texture/MomentTextures.h       |   83 ++
 Logic/Slicing/IRISSlicer.h                         |   10 +
 Logic/Slicing/IRISSlicer.txx                       |   18 +-
 ReleaseNotes.txt                                   |  196 ++-
 Testing/GUI/Qt/SNAPTestQt.cxx                      |  175 +--
 Testing/GUI/Qt/SNAPTestQt.h                        |   17 +-
 Testing/GUI/Qt/Scripts/test_Library.js             |   12 +-
 Testing/GUI/Qt/Scripts/test_ProbeIntensity.js      |    2 +-
 Testing/GUI/Qt/Scripts/test_RandomForest.js        |    8 +-
 Testing/GUI/Qt/Scripts/test_RegionCompetition.js   |    6 +-
 Testing/GUI/Qt/Scripts/test_Workspace.js           |    4 +-
 Utilities/MacOS/BundleResources/dsstore.bin        |  Bin 15364 -> 12292 bytes
 294 files changed, 15389 insertions(+), 3374 deletions(-)

diff --git a/.gitignore b/.gitignore
index 252540c..9ada7eb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,6 @@
 # VIM swap files
 .*.sw?
-*.un~
+*~
 
 # MACOS files
 .DS_Store*
diff --git a/CMake/GitBranch.cmake b/CMake/GitBranch.cmake
new file mode 100644
index 0000000..81b2eb3
--- /dev/null
+++ b/CMake/GitBranch.cmake
@@ -0,0 +1,23 @@
+# This code assigns the git branch to a variable
+function(get_git_branch RESULTNAME)
+
+  # Find Git and its libraries
+  if(NOT GIT_FOUND)
+    find_package(Git QUIET)
+  endif(NOT GIT_FOUND)
+
+  if(GIT_FOUND)
+
+    # Call git to get branch id
+    execute_process(
+      COMMAND ${GIT_EXECUTABLE} rev-parse --abbrev-ref HEAD
+      WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+      OUTPUT_VARIABLE SNAP_VERSION_GIT_BRANCH
+      OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+    set(${RESULTNAME} ${SNAP_VERSION_GIT_BRANCH} PARENT_SCOPE)
+
+  endif(GIT_FOUND)
+
+endfunction()
+
diff --git a/CMake/standalone.cmake b/CMake/standalone.cmake
index de4162d..c73b292 100644
--- a/CMake/standalone.cmake
+++ b/CMake/standalone.cmake
@@ -13,28 +13,53 @@ INCLUDE (${VTK_USE_FILE})
 #############################################
 # REQUIRE QT                                #
 #############################################
-FIND_PACKAGE(Qt5Widgets)
-FIND_PACKAGE(Qt5OpenGL)
-FIND_PACKAGE(Qt5Concurrent)
-FIND_PACKAGE(Qt5Qml)
-
-SET(SNAP_QT5_INCLUDE_DIRS
-  ${Qt5Widgets_INCLUDE_DIRS}
-  ${Qt5OpenGL_INCLUDE_DIRS}
-  ${Qt5Concurrent_INCLUDE_DIRS}
-  ${Qt5Qml_INCLUDE_DIRS}
-)
-
-SET(SNAP_QT5_LIBRARIES
-  Qt5::Widgets
-  Qt5::OpenGL
-  Qt5::Concurrent
-  Qt5::Qml
-)
-
-# Set vars for the QT binary and library directories
-GET_FILENAME_COMPONENT(QT_BINARY_DIR "${Qt5Core_DIR}/../../../bin" ABSOLUTE)
-GET_FILENAME_COMPONENT(QT_LIBRARY_DIR "${Qt5Core_DIR}/../../" ABSOLUTE)
+IF(NOT SNAP_USE_QT4)
+
+  FIND_PACKAGE(Qt5Widgets)
+  FIND_PACKAGE(Qt5OpenGL)
+  FIND_PACKAGE(Qt5Concurrent)
+  FIND_PACKAGE(Qt5Qml)
+
+  SET(SNAP_QT_INCLUDE_DIRS
+    ${Qt5Widgets_INCLUDE_DIRS}
+    ${Qt5OpenGL_INCLUDE_DIRS}
+    ${Qt5Concurrent_INCLUDE_DIRS}
+    ${Qt5Qml_INCLUDE_DIRS}
+  )
+
+  SET(SNAP_QT_LIBRARIES
+    Qt5::Widgets
+    Qt5::OpenGL
+    Qt5::Concurrent
+    Qt5::Qml
+  )
+
+  # Set vars for the QT binary and library directories
+  GET_FILENAME_COMPONENT(QT_BINARY_DIR "${Qt5Core_DIR}/../../../bin" ABSOLUTE)
+  GET_FILENAME_COMPONENT(QT_LIBRARY_DIR "${Qt5Core_DIR}/../../" ABSOLUTE)
+
+  # Set the QTVERSION var
+  SET(QTVERSION ${Qt5Widgets_VERSION})
+
+ELSE(NOT SNAP_USE_QT4)
+
+  FIND_PACKAGE(Qt4 4.8 COMPONENTS QtCore QtGui QtOpenGL REQUIRED)
+  INCLUDE(${QT_USE_FILE})
+  ADD_DEFINITIONS(${QT_DEFINITIONS})
+
+  SET(SNAP_QT_INCLUDE_DIRS
+    ${QT_QTSCRIPT_INCLUDE_DIR}
+    ${QT_QTSCRIPTTOOLS_INCLUDE_DIR}
+  )
+
+  SET(SNAP_QT_LIBRARIES
+    ${QT_LIBRARIES}
+    ${QT_QTMAIN_LIBRARY}
+    ${QT_QTSCRIPT_LIBRARY}
+    ${QT_QTSCRIPTTOOLS_LIBRARY}
+  )
+
+ENDIF(NOT SNAP_USE_QT4)
 
 # Look for OpenGL.
 FIND_PACKAGE(OpenGL REQUIRED)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8350e69..e061b18 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -11,6 +11,10 @@ PROJECT(SNAP)
 #--------------------------------------------------------------------------------
 cmake_minimum_required(VERSION 2.8.12)
 
+IF(POLICY CMP0026)
+  cmake_policy(SET CMP0026 OLD)
+ENDIF(POLICY CMP0026)
+
 SET(CMAKE_MODULE_PATH ${SNAP_SOURCE_DIR}/CMake)
 
 #--------------------------------------------------------------------------------
@@ -50,13 +54,13 @@ endforeach()
 
 # These four fields should be modified when versions change
 SET(SNAP_VERSION_MAJOR 3)
-SET(SNAP_VERSION_MINOR 2)
+SET(SNAP_VERSION_MINOR 4)
 SET(SNAP_VERSION_PATCH 0)
 SET(SNAP_VERSION_QUALIFIER "")
 
 # These fields should also be modified each time
-SET(SNAP_VERSION_RELEASE_DATE "20141023")
-SET(SNAP_VERSION_RELEASE_DATE_FORMATTED "Oct 23, 2014")
+SET(SNAP_VERSION_RELEASE_DATE "20151130")
+SET(SNAP_VERSION_RELEASE_DATE_FORMATTED "Nov 30, 2015")
 
 # This field should only change when the format of the settings files changes
 # in a non backwards-compatible way
@@ -74,9 +78,20 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake/rpavlik/")
 include(GetGitRevisionDescription)
 get_git_head_revision(GIT_REFSPEC SNAP_VERSION_GIT_SHA1)
 
+# Get the current git branch
+include(GitBranch)
+get_git_branch(SNAP_VERSION_GIT_BRANCH)
+
+# Print the Git information
+MESSAGE(STATUS "   GIT Info: BRANCH ${SNAP_VERSION_GIT_BRANCH}, SHA: ${SNAP_VERSION_GIT_SHA1}")
+
 #--------------------------------------------------------------------------------
 # FIND PACKAGES IF BUILDING OUTSIDE INSIGHTAPPLICATIONS 
 #--------------------------------------------------------------------------------
+
+# Add option to build on qt 4.x
+OPTION(SNAP_USE_QT4 "Compile using Qt version 4.8 for compatibility with older systems and VNC/x2go" OFF)
+
 IF(DEFINED InsightApplications_SOURCE_DIR)
   SET(BUILD_OUTSIDE_INSIGHT_APPLICATIONS FALSE CACHE BOOL 
 	"Is SNAP being built separate from InsightApplications?")
@@ -118,7 +133,7 @@ IF(CMAKE_SYSTEM_NAME MATCHES Darwin)
 
   # TODO: when CMAKE_OSX_ARCHITECTURES is not set this causes an obscure
   # CMake error. Should generate a meaningful message instead
-  STRING(REPLACE ";" "-" ARCH ${CMAKE_OSX_ARCHITECTURES})
+  STRING(REPLACE ";" "-" ARCH "${CMAKE_OSX_ARCHITECTURES}")
   SET(CPACK_SYSTEM_NAME "MacOS-${ARCH}")
   MESSAGE(STATUS "   ARCH ${ARCH}")
   MESSAGE(STATUS "   CMAKE_OSX_ARCHITECTURES ${CMAKE_OSX_ARCHITECTURES}")
@@ -126,14 +141,17 @@ ENDIF(CMAKE_SYSTEM_NAME MATCHES Darwin)
 
 MESSAGE(STATUS "   CPACK_SYSTEM_NAME ${CPACK_SYSTEM_NAME}")
 
-SET(CPACK_PACKAGE_FILE_NAME "${CPACK_SOURCE_PACKAGE_FILE_NAME}-${CPACK_SYSTEM_NAME}")
+IF(NOT SNAP_USE_QT4)
+  SET(CPACK_PACKAGE_FILE_NAME "${CPACK_SOURCE_PACKAGE_FILE_NAME}-${CPACK_SYSTEM_NAME}")
+ELSE(NOT SNAP_USE_QT4)
+  SET(CPACK_PACKAGE_FILE_NAME "${CPACK_SOURCE_PACKAGE_FILE_NAME}-${CPACK_SYSTEM_NAME}-qt4")
+ENDIF(NOT SNAP_USE_QT4)
 
 MESSAGE(STATUS "   CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_FILE_NAME}")
 
 # Additional CPack resources
 SET(CPACK_RESOURCE_FILE_LICENSE "${SNAP_SOURCE_DIR}/COPYING")
 
-
 #--------------------------------------------------------------------------------
 # SOURCE FILE SPECIFICATION                 
 #--------------------------------------------------------------------------------
@@ -185,6 +203,7 @@ SET(LOGIC_CXX
   Logic/Framework/DefaultBehaviorSettings.cxx
   Logic/Framework/GenericImageData.cxx
   Logic/Framework/GlobalState.cxx
+  Logic/Framework/ImageAnnotationData.cxx
   Logic/Framework/ImageIODelegates.cxx
   Logic/Framework/IRISApplication.cxx
   Logic/Framework/IRISImageData.cxx
@@ -219,6 +238,7 @@ SET(LOGIC_CXX
   Logic/Preprocessing/GMM/UnsupervisedClustering.cxx
   Logic/Preprocessing/RandomForest/RFClassificationEngine.cxx
   Logic/Preprocessing/RandomForest/RandomForestClassifier.cxx
+  Logic/Preprocessing/Texture/MomentTextures.cxx
   Logic/Slicing/IntensityCurveVTK.cxx
   Logic/Slicing/IntensityToColorLookupTableImageFilter.cxx
   Logic/Slicing/LookupTableIntensityMappingFilter.cxx
@@ -280,6 +300,7 @@ SET(LOGIC_HEADERS
   Logic/Framework/DefaultBehaviorSettings.h
   Logic/Framework/GenericImageData.h
   Logic/Framework/GlobalState.h
+  Logic/Framework/ImageAnnotationData.h
   Logic/Framework/ImageIODelegates.h
   Logic/Framework/IRISApplication.h
   Logic/Framework/IRISImageData.h
@@ -345,6 +366,7 @@ SET(LOGIC_HEADERS
   Logic/Preprocessing/GMM/UnsupervisedClustering.h
   Logic/Preprocessing/RandomForest/RFClassificationEngine.h
   Logic/Preprocessing/RandomForest/RandomForestClassifier.h
+  Logic/Preprocessing/Texture/MomentTextures.h
   Logic/Slicing/IRISSlicer.h
   Logic/Slicing/IRISSlicer.txx
   Logic/Slicing/IntensityCurveInterface.h
@@ -356,6 +378,7 @@ SET(LOGIC_HEADERS
 
 # These files have the UI model code, which is GUI-TK independent
 SET(UI_GENERIC_CXX
+  GUI/Model/AnnotationModel.cxx
   GUI/Model/ColorLabelQuickListModel.cxx
   GUI/Model/ColorLabelPropertyModel.cxx
   GUI/Model/ColorMapModel.cxx
@@ -367,6 +390,7 @@ SET(UI_GENERIC_CXX
   GUI/Model/GlobalUIModel.cxx
   GUI/Model/ImageIOWizardModel.cxx
   GUI/Model/ImageInfoModel.cxx
+  GUI/Model/ImageRegistrationManager.cxx
   GUI/Model/IntensityCurveModel.cxx
   GUI/Model/LabelEditorModel.cxx
   GUI/Model/LayerGeneralPropertiesModel.cxx
@@ -377,6 +401,7 @@ SET(UI_GENERIC_CXX
   GUI/Model/PaintbrushModel.cxx
   GUI/Model/PaintbrushSettingsModel.cxx
   GUI/Model/PolygonDrawingModel.cxx
+  GUI/Model/PolygonSettingsModel.cxx
   GUI/Model/ReorientImageModel.cxx
   GUI/Model/SaveModifiedLayersModel.cxx
   GUI/Model/SliceWindowCoordinator.cxx
@@ -390,6 +415,7 @@ SET(UI_GENERIC_CXX
   GUI/Renderer/AbstractRenderer.cxx
   GUI/Renderer/AbstractVTKRenderer.cxx
   GUI/Renderer/AbstractVTKSceneRenderer.cxx
+  GUI/Renderer/AnnotationRenderer.cxx
   GUI/Renderer/ColorMapRenderer.cxx
   GUI/Renderer/CrosshairsRenderer.cxx
   GUI/Renderer/EdgePreprocessingSettingsRenderer.cxx
@@ -400,6 +426,7 @@ SET(UI_GENERIC_CXX
   GUI/Renderer/IntensityCurveVTKRenderer.cxx
   GUI/Renderer/LayerHistogramPlotAssembly.cxx
   GUI/Renderer/OpenGLSliceTexture.cxx
+  GUI/Renderer/OptimizationProgressRenderer.cxx
   GUI/Renderer/OrientationGraphicRenderer.cxx
   GUI/Renderer/PaintbrushRenderer.cxx
   GUI/Renderer/PolygonDrawingRenderer.cxx
@@ -421,6 +448,7 @@ SET(UI_GENERIC_CXX
 SET(UI_GENERIC_HEADERS
   GUI/Model/AbstractLayerAssociatedModel.h
   GUI/Model/AbstractLayerInfoItemSetDomain.h
+  GUI/Model/AnnotationModel.h
   GUI/Model/ColorMapModel.h
   GUI/Model/ColorLabelQuickListModel.h
   GUI/Model/ColorLabelPropertyModel.h
@@ -432,6 +460,7 @@ SET(UI_GENERIC_HEADERS
   GUI/Model/GlobalUIModel.h
   GUI/Model/ImageInfoModel.h
   GUI/Model/ImageIOWizardModel.h
+  GUI/Model/ImageRegistrationManager.h
   GUI/Model/IntensityCurveModel.h
   GUI/Model/LabelEditorModel.h
   GUI/Model/LayerGeneralPropertiesModel.h
@@ -441,6 +470,7 @@ SET(UI_GENERIC_HEADERS
   GUI/Model/OrthogonalSliceCursorNavigationModel.h
   GUI/Model/PaintbrushModel.h
   GUI/Model/PaintbrushSettingsModel.h
+  GUI/Model/PolygonSettingsModel.h
   GUI/Model/PolygonDrawingModel.h
   GUI/Model/ReorientImageModel.h
   GUI/Model/SaveModifiedLayersModel.h
@@ -459,6 +489,7 @@ SET(UI_GENERIC_HEADERS
   GUI/Renderer/AbstractRenderer.h
   GUI/Renderer/AbstractVTKRenderer.h
   GUI/Renderer/AbstractVTKSceneRenderer.h
+  GUI/Renderer/AnnotationRenderer.h
   GUI/Renderer/ColorMapRenderer.h
   GUI/Renderer/CrosshairsRenderer.h
   GUI/Renderer/EdgePreprocessingSettingsRenderer.h
@@ -468,6 +499,7 @@ SET(UI_GENERIC_HEADERS
   GUI/Renderer/GMMRenderer.h
   GUI/Renderer/IntensityCurveVTKRenderer.h
   GUI/Renderer/LayerHistogramPlotAssembly.h
+  GUI/Renderer/OptimizationProgressRenderer.h
   GUI/Renderer/OrientationGraphicRenderer.h
   GUI/Renderer/PaintbrushRenderer.h
   GUI/Renderer/PolygonDrawingRenderer.h
@@ -488,6 +520,7 @@ SET(UI_GENERIC_HEADERS
 
 # These files contain the Qt-specific user interface source code
 SET(UI_QT_CXX
+  GUI/Qt/Components/AnnotationToolPanel.cxx
   GUI/Qt/Components/CollapsableGroupBox.cxx
   GUI/Qt/Components/ColorLabelQuickListWidget.cxx
   GUI/Qt/Components/ColorMapInspector.cxx
@@ -505,10 +538,12 @@ SET(UI_QT_CXX
   GUI/Qt/Components/MetadataInspector.cxx
   GUI/Qt/Components/GeneralLayerInspector.cxx
   GUI/Qt/Components/PaintbrushToolPanel.cxx
+  GUI/Qt/Components/PolygonToolPanel.cxx
   GUI/Qt/Components/QActionButton.cxx
   GUI/Qt/Components/QColorButtonWidget.cxx
   GUI/Qt/Components/QDoubleSlider.cxx
   GUI/Qt/Components/QDoubleSliderWithEditor.cxx
+  GUI/Qt/Components/QtHideOnDeactivateContainer.cxx
   GUI/Qt/Components/QtIPCManager.cxx
   GUI/Qt/Components/QtRendererPlatformSupport.cxx
   GUI/Qt/Components/QtReporterDelegates.cxx
@@ -526,6 +561,7 @@ SET(UI_QT_CXX
   GUI/Qt/Components/ZoomInspector.cxx
   GUI/Qt/External/ColorWheel/ColorWheel.cxx
   GUI/Qt/ModelView/GMMTableModel.cxx
+  GUI/Qt/View/AnnotationInteractionMode.cxx
   GUI/Qt/View/ColorMapBox.cxx
   GUI/Qt/View/CrosshairsInteractionMode.cxx
   GUI/Qt/View/GenericSliceView.cxx
@@ -545,6 +581,8 @@ SET(UI_QT_CXX
   GUI/Qt/Windows/DropActionDialog.cxx
   GUI/Qt/Windows/ImageIODialog.cxx
   GUI/Qt/Windows/ImageIOWizard.cxx
+  GUI/Qt/Windows/ImageIOWizard/OverlayRolePage.cxx
+  GUI/Qt/Windows/ImageIOWizard/RegistrationPage.cxx
   GUI/Qt/Windows/LabelEditorDialog.cxx
   GUI/Qt/Windows/LayerInspectorDialog.cxx
   GUI/Qt/Windows/LabelSelectionPopup.cxx
@@ -568,6 +606,7 @@ SET(UI_QT_CXX
 
 # The header files for the UI project
 SET(UI_MOC_HEADERS
+  GUI/Qt/Components/AnnotationToolPanel.h
   GUI/Qt/Components/CollapsableGroupBox.h
   GUI/Qt/Components/ColorLabelQuickListWidget.h
   GUI/Qt/Components/ColorMapInspector.h
@@ -585,10 +624,12 @@ SET(UI_MOC_HEADERS
   GUI/Qt/Components/MetadataInspector.h
   GUI/Qt/Components/GeneralLayerInspector.h
   GUI/Qt/Components/PaintbrushToolPanel.h
+  GUI/Qt/Components/PolygonToolPanel.h
   GUI/Qt/Components/QActionButton.h
   GUI/Qt/Components/QColorButtonWidget.h
   GUI/Qt/Components/QDoubleSlider.h
   GUI/Qt/Components/QDoubleSliderWithEditor.h
+  GUI/Qt/Components/QtHideOnDeactivateContainer.h
   GUI/Qt/Components/QtIPCManager.h
   GUI/Qt/Components/QtWarningDialog.h
   GUI/Qt/Components/QtWidgetActivator.h
@@ -604,6 +645,7 @@ SET(UI_MOC_HEADERS
   GUI/Qt/Coupling/QtWidgetCoupling.h
   GUI/Qt/External/ColorWheel/ColorWheel.h
   GUI/Qt/ModelView/GMMTableModel.h
+  GUI/Qt/View/AnnotationInteractionMode.h
   GUI/Qt/View/ColorMapBox.h
   GUI/Qt/View/CrosshairsInteractionMode.h
   GUI/Qt/View/GenericSliceView.h
@@ -622,6 +664,8 @@ SET(UI_MOC_HEADERS
   GUI/Qt/Windows/DropActionDialog.h
   GUI/Qt/Windows/ImageIODialog.h
   GUI/Qt/Windows/ImageIOWizard.h
+  GUI/Qt/Windows/ImageIOWizard/OverlayRolePage.h
+  GUI/Qt/Windows/ImageIOWizard/RegistrationPage.h
   GUI/Qt/Windows/LabelEditorDialog.h
   GUI/Qt/Windows/LayerInspectorDialog.h
   GUI/Qt/Windows/LabelSelectionPopup.h
@@ -669,6 +713,7 @@ SET(UI_NONMOC_HEADERS
 )
 
 SET(UI_FORMS
+  GUI/Qt/Components/AnnotationToolPanel.ui
   GUI/Qt/Components/CollapsableGroupBox.ui
   GUI/Qt/Components/ColorMapInspector.ui
   GUI/Qt/Components/ContrastInspector.ui
@@ -682,6 +727,7 @@ SET(UI_FORMS
   GUI/Qt/Components/MetadataInspector.ui
   GUI/Qt/Components/GeneralLayerInspector.ui
   GUI/Qt/Components/PaintbrushToolPanel.ui
+  GUI/Qt/Components/PolygonToolPanel.ui
   GUI/Qt/Components/QDoubleSliderWithEditor.ui
   GUI/Qt/Components/QtWarningDialog.ui
   GUI/Qt/Components/RecentHistoryItemsView.ui
@@ -694,6 +740,8 @@ SET(UI_FORMS
   GUI/Qt/Windows/AboutDialog.ui
   GUI/Qt/Windows/DropActionDialog.ui
   GUI/Qt/Windows/ImageIODialog.ui
+  GUI/Qt/Windows/ImageIOWizard/OverlayRolePage.ui
+  GUI/Qt/Windows/ImageIOWizard/RegistrationPage.ui
   GUI/Qt/Windows/LabelEditorDialog.ui
   GUI/Qt/Windows/LayerInspectorDialog.ui
   GUI/Qt/Windows/LabelSelectionPopup.ui
@@ -715,6 +763,9 @@ SET(UI_FORMS
 
 SET(UI_RESOURCES
   GUI/Qt/Resources/SNAPResources.qrc
+  GUI/Qt/Resources/SNAPResources_Linux.qrc
+  GUI/Qt/Resources/SNAPResources_MacOS.qrc
+  GUI/Qt/Resources/SNAPResources_Windows.qrc
   Testing/GUI/Qt/TestingScripts.qrc
 )
 
@@ -781,6 +832,7 @@ ELSE( CMAKE_GENERATOR MATCHES "Visual Studio 6" )
     ${SNAP_SOURCE_DIR}/Logic/Preprocessing
     ${SNAP_SOURCE_DIR}/Logic/Preprocessing/GMM
     ${SNAP_SOURCE_DIR}/Logic/Preprocessing/RandomForest
+    ${SNAP_SOURCE_DIR}/Logic/Preprocessing/Texture
     ${SNAP_SOURCE_DIR}/Logic/Slicing
     ${SNAP_SOURCE_DIR}/GUI
     ${SNAP_SOURCE_DIR}/GUI/Model
@@ -800,7 +852,7 @@ ELSE( CMAKE_GENERATOR MATCHES "Visual Studio 6" )
     ${SNAP_SOURCE_DIR}/Testing/GUI/Qt
     ${SNAP_BINARY_DIR}
     ${OPENGL_INCLUDE_PATH}
-    ${SNAP_QT5_INCLUDE_DIRS}
+    ${SNAP_QT_INCLUDE_DIRS}
   )
 
 ENDIF( CMAKE_GENERATOR MATCHES "Visual Studio 6" )
@@ -864,9 +916,15 @@ SET(SNAP_EXTERNAL_LIBS
 #--------------------------------------------------------------------------------
 
 # Wrap the QT input files
-QT5_WRAP_UI(UI_FORM_HEADERS ${UI_FORMS})
-QT5_WRAP_CPP(UI_WRAPPED_MOC_HEADERS ${UI_MOC_HEADERS})
-QT5_ADD_RESOURCES(UI_RESOURCES_RCC ${UI_RESOURCES})
+IF(NOT SNAP_USE_QT4)
+  QT5_WRAP_UI(UI_FORM_HEADERS ${UI_FORMS})
+  QT5_WRAP_CPP(UI_WRAPPED_MOC_HEADERS ${UI_MOC_HEADERS})
+  QT5_ADD_RESOURCES(UI_RESOURCES_RCC ${UI_RESOURCES})
+ELSE(NOT SNAP_USE_QT4)
+  QT4_WRAP_UI(UI_FORM_HEADERS ${UI_FORMS})
+  QT4_WRAP_CPP(UI_WRAPPED_MOC_HEADERS ${UI_MOC_HEADERS})
+  QT4_ADD_RESOURCES(UI_RESOURCES_RCC ${UI_RESOURCES})
+ENDIF(NOT SNAP_USE_QT4)
 
 # The SNAP logic library
 ADD_LIBRARY(itksnaplogic ${LOGIC_CXX} ${LOGIC_HEADERS})
@@ -884,7 +942,7 @@ ADD_LIBRARY(itksnapui_qt
 # two lines
 TARGET_LINK_LIBRARIES(itksnaplogic ${SNAP_EXTERNAL_LIBS})
 TARGET_LINK_LIBRARIES(itksnapui_model itksnaplogic ${SNAP_EXTERNAL_LIBS})
-TARGET_LINK_LIBRARIES(itksnapui_qt ${SNAP_QT5_LIBRARIES} ${SNAP_EXTERNAL_LIBS})
+TARGET_LINK_LIBRARIES(itksnapui_qt ${SNAP_QT_LIBRARIES} ${SNAP_EXTERNAL_LIBS})
 
 # Designate the SNAP internal libraries
 SET(SNAP_INTERNAL_LIBS itksnapui_qt itksnapui_model itksnaplogic)
@@ -943,6 +1001,11 @@ ENABLE_TESTING()
 
 include(BundleUtilities)
 
+# Acceleration factor for GUI tests
+SET(SNAP_GUI_TEST_ACCEL "1.0" CACHE STRING 
+    "Acceleration factor for GUI tests, use <1 on VMS and slow machines")
+MARK_AS_ADVANCED(SNAP_GUI_TEST_ACCEL)
+
 # The list of Qt animated GUI tests
 SET(GUI_TESTS
   Workspace
@@ -963,7 +1026,7 @@ FOREACH(GUI_TEST ${GUI_TESTS})
   ENDIF(APPLE)
     
   # Add the test
-  ADD_TEST(${GUI_TEST} ${GUI_TEST_EXE} --test ${GUI_TEST} --testdir "${TESTDATA_DIR}")
+  ADD_TEST(${GUI_TEST} ${GUI_TEST_EXE} --test ${GUI_TEST} --testacc ${SNAP_GUI_TEST_ACCEL} --testdir "${TESTDATA_DIR}")
 
   # Set the environment for the test to include Qt
   FILE(TO_NATIVE_PATH ${QT_BINARY_DIR} QT_BINARY_DIR_NATIVE)
@@ -973,7 +1036,7 @@ FOREACH(GUI_TEST ${GUI_TESTS})
   ELSE(WIN32)
     SET_PROPERTY(TEST ${GUI_TEST} APPEND PROPERTY ENVIRONMENT PATH="${QT_BINARY_DIR_NATIVE}:$ENV{PATH}")
   ENDIF(WIN32)
-  SET_PROPERTY(TEST ${GUI_TEST} PROPERTY TIMEOUT 120)
+  SET_PROPERTY(TEST ${GUI_TEST} PROPERTY TIMEOUT 180)
 
 ENDFOREACH(GUI_TEST)
 
@@ -987,10 +1050,17 @@ SET(TEST_ORIENTATION_WIDGET_CXX
   GUI/Renderer/OrientationWidget/Test_OrientationWidget/main.cxx
 )
 
-QT5_WRAP_UI(UI_ORIENTATION_WIDGET_SRCS 
-  GUI/Renderer/OrientationWidget/Test_OrientationWidget/OrientationWidgetGUI.ui)
-QT5_WRAP_CPP(MOC_ORIENTATION_WIDGET_SRCS 
-  GUI/Renderer/OrientationWidget/Test_OrientationWidget/OrientationWidgetGUI.h)
+IF(NOT SNAP_USE_QT4)
+  QT5_WRAP_UI(UI_ORIENTATION_WIDGET_SRCS 
+    GUI/Renderer/OrientationWidget/Test_OrientationWidget/OrientationWidgetGUI.ui)
+  QT5_WRAP_CPP(MOC_ORIENTATION_WIDGET_SRCS 
+    GUI/Renderer/OrientationWidget/Test_OrientationWidget/OrientationWidgetGUI.h)
+ELSE(NOT SNAP_USE_QT4)
+  QT4_WRAP_UI(UI_ORIENTATION_WIDGET_SRCS 
+    GUI/Renderer/OrientationWidget/Test_OrientationWidget/OrientationWidgetGUI.ui)
+  QT4_WRAP_CPP(MOC_ORIENTATION_WIDGET_SRCS 
+    GUI/Renderer/OrientationWidget/Test_OrientationWidget/OrientationWidgetGUI.h)
+ENDIF(NOT SNAP_USE_QT4)
 
 ADD_EXECUTABLE(Test_OrientationWidget
   ${TEST_ORIENTATION_WIDGET_CXX} ${TEST_ORIENTATION_WIDGET_HEADERS}
@@ -1064,29 +1134,49 @@ IF(APPLE)
   SET(CPACK_DMG_DS_STORE ${SNAP_SOURCE_DIR}/Utilities/MacOS/BundleResources/dsstore.bin)
   SET(CPACK_DMG_BACKGROUND_IMAGE ${SNAP_SOURCE_DIR}/Utilities/MacOS/BundleResources/background.png)
 
-  # Include the qt4 dependent libraries
-  include(DeployQt5)
+  IF(NOT SNAP_USE_QT4)
+
+    # Include the qt4 dependent libraries
+    include(DeployQt5)
+
+    # Make sure the GIF plugin is included
+    get_property(QT_GIF_PLUGIN TARGET Qt5::QGifPlugin PROPERTY LOCATION_RELEASE)
+
+    # Install with the plugin
+    install_qt5_executable(${SNAP_BUNDLE_NAME}.app "${QT_GIF_PLUGIN}")
 
-  # Make sure the GIF plugin is included
-  get_property(QT_GIF_PLUGIN TARGET Qt5::QGifPlugin PROPERTY LOCATION_RELEASE)
+  ELSE(NOT SNAP_USE_QT4)
 
-  # Install with the plugin
-  install_qt5_executable(${SNAP_BUNDLE_NAME}.app "${QT_GIF_PLUGIN}")
+    # Include the qt4 dependent libraries
+    include(DeployQt4)
+    install_qt4_executable(${SNAP_BUNDLE_NAME}.app "qsqlite;qgif")
+
+  ENDIF(NOT SNAP_USE_QT4)
 
 ELSEIF(WIN32)
 
   # Install to the bin directory
   INSTALL(TARGETS ${SNAP_BUNDLE_NAME} RUNTIME DESTINATION bin)
 
-  # Include the qt4 dependent libraries
-  include(DeployQt5)
+  IF(NOT SNAP_USE_QT4)
+
+      # Include the qt4 dependent libraries
+      include(DeployQt5)
+
+      # Make sure the GIF plugin is included
+      get_property(QT_WIN_PLUGIN TARGET Qt5::QWindowsIntegrationPlugin PROPERTY LOCATION_RELEASE)
+      get_property(QT_GIF_PLUGIN TARGET Qt5::QGifPlugin PROPERTY LOCATION_RELEASE)
+
+      # Install with the plugin
+      install_qt5_executable(bin/${SNAP_BUNDLE_NAME}.exe "${QT_GIF_PLUGIN};${QT_WIN_PLUGIN}")
+
+  ELSE(NOT SNAP_USE_QT4)
 
-  # Make sure the GIF plugin is included
-  get_property(QT_WIN_PLUGIN TARGET Qt5::QWindowsIntegrationPlugin PROPERTY LOCATION_RELEASE)
-  get_property(QT_GIF_PLUGIN TARGET Qt5::QGifPlugin PROPERTY LOCATION_RELEASE)
+      # Include the qt4 dependent libraries
+      include(DeployQt4)
+      install_qt4_executable(bin/${SNAP_BUNDLE_NAME}.exe "qsqlite;qgif")
 
-  # Install with the plugin
-  install_qt5_executable(bin/${SNAP_BUNDLE_NAME}.exe "${QT_GIF_PLUGIN};${QT_WIN_PLUGIN}")
+  ENDIF(NOT SNAP_USE_QT4)
 
   # On windows, we have to configure NSIS
   SET(CPACK_NSIS_INSTALLED_ICON_NAME "ITK-SNAP.exe")
@@ -1128,29 +1218,38 @@ ELSE()
   SET(CPACK_PACKAGE_EXECUTABLES "itksnap" "ITK-SNAP")
   INSTALL(TARGETS ${SNAP_BUNDLE_NAME} RUNTIME DESTINATION ${SNAP_MAIN_INSTALL_DIR})
 
-  # Include the qt4 dependent libraries
-  include(DeployQt5)
+  IF(NOT SNAP_USE_QT4)
 
-  # Add an option to not package QT plugins. This is needed for some special builds,
-  # for example on Debian
-  OPTION(SNAP_PACKAGE_QT_PLUGINS "Try to package Qt5 plugins with the executable" ON)
-  MARK_AS_ADVANCED(SNAP_PACKAGE_QT_PLUGINS)
+    # Include the qt4 dependent libraries
+    include(DeployQt5)
 
-  # Get the necessary plugins
-  IF(SNAP_PACKAGE_QT_PLUGINS)
+    # Add an option to not package QT plugins. This is needed for some special builds,
+    # for example on Debian
+    OPTION(SNAP_PACKAGE_QT_PLUGINS "Try to package Qt5 plugins with the executable" ON)
+    MARK_AS_ADVANCED(SNAP_PACKAGE_QT_PLUGINS)
 
-    get_property(QT_XCB_PLUGIN TARGET Qt5::QXcbIntegrationPlugin PROPERTY LOCATION_RELEASE)
-    get_property(QT_GIF_PLUGIN TARGET Qt5::QGifPlugin PROPERTY LOCATION_RELEASE)
+    # Get the necessary plugins
+    IF(SNAP_PACKAGE_QT_PLUGINS)
+
+      get_property(QT_XCB_PLUGIN TARGET Qt5::QXcbIntegrationPlugin PROPERTY LOCATION_RELEASE)
+      get_property(QT_GIF_PLUGIN TARGET Qt5::QGifPlugin PROPERTY LOCATION_RELEASE)
+
+      # Install the plugin
+      install_qt5_executable(${SNAP_MAIN_INSTALL_DIR}/${SNAP_EXE} "${QT_XCB_PLUGIN};${QT_GIF_PLUGIN}")
+
+    ELSE(SNAP_PACKAGE_QT_PLUGINS)
+
+      # Install the exe without plugins
+      install_qt5_executable(${SNAP_MAIN_INSTALL_DIR}/${SNAP_EXE})
 
-    # Install the plugin
-    install_qt5_executable(${SNAP_MAIN_INSTALL_DIR}/${SNAP_EXE} "${QT_XCB_PLUGIN};${QT_GIF_PLUGIN}")
+    ENDIF(SNAP_PACKAGE_QT_PLUGINS)
 
-  ELSE(SNAP_PACKAGE_QT_PLUGINS)
+  ELSE(NOT SNAP_USE_QT4)
 
-    # Install the exe without plugins
-    install_qt5_executable(${SNAP_MAIN_INSTALL_DIR}/${SNAP_EXE})
+    include(DeployQt4)
+    install_qt4_executable(${SNAP_MAIN_INSTALL_DIR}/${SNAP_EXE} "qgif")
 
-  ENDIF(SNAP_PACKAGE_QT_PLUGINS)
+  ENDIF(NOT SNAP_USE_QT4)
 
 ENDIF()
 
@@ -1195,7 +1294,13 @@ MARK_AS_ADVANCED(SCP_ARGUMENTS)
 SET(SCP_USERNAME "" CACHE STRING "SourceForge.net account id for uploads")
 MARK_AS_ADVANCED(SCP_USERNAME)
 
-SET(NIGHTLY_TARGET "itksnap-3.2-dev-nightly-${CPACK_SYSTEM_NAME}.${CPACK_EXTENSION}")
+IF(NOT SNAP_USE_QT4)
+  SET(NIGHTLY_TARGET "itksnap-nightly-${SNAP_VERSION_GIT_BRANCH}-${CPACK_SYSTEM_NAME}.${CPACK_EXTENSION}")
+  SET(EXPERIMENTAL_TARGET "itksnap-experimental-${SNAP_VERSION_GIT_BRANCH}-${CPACK_SYSTEM_NAME}.${CPACK_EXTENSION}")
+ELSE(NOT SNAP_USE_QT4)
+  SET(NIGHTLY_TARGET "itksnap-nightly-${SNAP_VERSION_GIT_BRANCH}-${CPACK_SYSTEM_NAME}-qt4.${CPACK_EXTENSION}")
+  SET(EXPERIMENTAL_TARGET "itksnap-experimental-${SNAP_VERSION_GIT_BRANCH}-${CPACK_SYSTEM_NAME}-qt4.${CPACK_EXTENSION}")
+ENDIF(NOT SNAP_USE_QT4)
 
 SET(SCP_ROOT "frs.sourceforge.net:/home/frs/project/i/it/itk-snap/itk-snap")
 
@@ -1211,9 +1316,9 @@ ADD_CUSTOM_TARGET(upload_nightly
 
 ADD_CUSTOM_TARGET(upload_experimental 
   VERBATIM COMMAND "${SCP_PROGRAM}" ${SCP_ARGUMENTS} 
-    ${CPACK_PACKAGE_FILE_NAME_WEXT} ${SCP_USERNAME},itk-snap@${SCP_ROOT}/Experimental/
+    ${CPACK_PACKAGE_FILE_NAME_WEXT} ${SCP_USERNAME},itk-snap@${SCP_ROOT}/Experimental/${EXPERIMENTAL_TARGET}
   DEPENDS ${CPACK_TARGET}
   WORKING_DIRECTORY ${SNAP_BINARY_DIR}
-  COMMENT "Uploading package ${CPACK_PACKAGE_FILE_NAME_WEXT} to SourceForge.net to Experimental directory")
+  COMMENT "Uploading package ${CPACK_PACKAGE_FILE_NAME_WEXT} to SourceForge.net as ${EXPERIMENTAL_TARGET}")
 
 
diff --git a/CTestConfig.cmake b/CTestConfig.cmake
index e65ddc2..2a7898b 100644
--- a/CTestConfig.cmake
+++ b/CTestConfig.cmake
@@ -1,13 +1,15 @@
 ## This file should be placed in the root directory of your project.
 ## Then modify the CMakeLists.txt file in the root directory of your
 ## project to incorporate the testing dashboard.
-## # The following are required to uses Dart and the Cdash dashboard
+##
+## # The following are required to submit to the CDash dashboard:
 ##   ENABLE_TESTING()
-##   INCLUDE(Dart)
-set(CTEST_PROJECT_NAME "ITK-SNAP 3.2")
-set(CTEST_NIGHTLY_START_TIME "00:00:00 EST")
+##   INCLUDE(CTest)
+
+set(CTEST_PROJECT_NAME "ITK-SNAP 3.4")
+set(CTEST_NIGHTLY_START_TIME "00:00:00 UTC")
 
 set(CTEST_DROP_METHOD "http")
 set(CTEST_DROP_SITE "itksnap.org")
-set(CTEST_DROP_LOCATION "/cdash/submit.php?project=ITK-SNAP+3.2")
+set(CTEST_DROP_LOCATION "/cdash/submit.php?project=ITK-SNAP+3.4")
 set(CTEST_DROP_SITE_CDASH TRUE)
diff --git a/Common/IPCHandler.cxx b/Common/IPCHandler.cxx
index 8b9a1aa..7f3b665 100644
--- a/Common/IPCHandler.cxx
+++ b/Common/IPCHandler.cxx
@@ -22,6 +22,7 @@ using namespace std;
   #include <sys/ipc.h>
   #include <sys/shm.h>
   #include <unistd.h>
+  #include <signal.h>
   #include <sys/time.h>
 #endif
 
@@ -117,6 +118,21 @@ bool IPCHandler::Read(void *target_ptr)
   return true;
 }
 
+bool IPCHandler::IsProcessRunning(int pid)
+{
+#ifdef WIN32
+  HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, (DWORD) pid);
+  DWORD exitCode = 0;
+  GetExitCodeProcess(hProcess, &exitCode);
+  CloseHandle(hProcess);
+  return (exitCode == STILL_ACTIVE);
+#else
+  // Send signal 0 to the PID
+  return (0 == kill(pid, 0));
+#endif
+
+}
+
 bool IPCHandler::ReadIfNew(void *target_ptr)
 {
   // Must have some shared memory
@@ -136,6 +152,17 @@ bool IPCHandler::ReadIfNew(void *target_ptr)
   if(m_LastSender == header->sender_pid && m_LastReceivedMessageID == header->message_id)
     return false;
 
+  // If the PID is known to be dead, ignore it
+  if(m_KnownDeadPIDs.find(header->sender_pid) != m_KnownDeadPIDs.end())
+    return false;
+
+  // Check if this is a dead PID
+  if(!this->IsProcessRunning(header->sender_pid))
+    {
+    m_KnownDeadPIDs.insert(header->sender_pid);
+    return false;
+    }
+
   // Store the last sender / id
   m_LastSender = header->sender_pid;
   m_LastReceivedMessageID = header->message_id;
diff --git a/Common/IPCHandler.h b/Common/IPCHandler.h
index fe64d67..75cb076 100644
--- a/Common/IPCHandler.h
+++ b/Common/IPCHandler.h
@@ -2,6 +2,7 @@
 #define IPCHANDLER_H
 
 #include <cstddef>
+#include <set>
 
 /**
  * Base class for IPCHandler. This class contains the definitions of the
@@ -73,6 +74,10 @@ protected:
   // Process ID and other values used by IPC
   long m_ProcessID, m_MessageID, m_LastSender, m_LastReceivedMessageID;
 
+  bool IsProcessRunning(int pid);
+
+  // List of known process ids, with status (0 = alive, -1 = dead)
+  std::set<long> m_KnownDeadPIDs;
 };
 
 
diff --git a/Common/ITKExtras/itkMaximumGradientMagnitudeImageFilter.h b/Common/ITKExtras/itkMaximumGradientMagnitudeImageFilter.h
new file mode 100644
index 0000000..67c8ab9
--- /dev/null
+++ b/Common/ITKExtras/itkMaximumGradientMagnitudeImageFilter.h
@@ -0,0 +1,152 @@
+#ifndef ITKMAXIMUMGRADIENTMAGNITUDEIMAGEFILTER_H
+#define ITKMAXIMUMGRADIENTMAGNITUDEIMAGEFILTER_H
+
+#include "itkImageToImageFilter.h"
+#include "itkSimpleDataObjectDecorator.h"
+
+#include <vector>
+
+#include "itkNumericTraits.h"
+
+namespace itk
+{
+/** \class MaximumGradientMagnitudeImageFilter
+ * \brief Computes the minimum and the maximum gradient magnitude of
+ * an image.
+ *
+ * It is templated over input image type only.
+ * This filter just copies the input image through this output to
+ * be included within the pipeline. The implementation uses the
+ * StatisticsImageFilter.
+ *
+ * \ingroup Operators
+ * \sa StatisticsImageFilter
+ * \ingroup ITKImageStatistics
+ */
+template< typename TInputImage >
+class MaximumGradientMagnitudeImageFilter:
+  public ImageToImageFilter< TInputImage, TInputImage >
+{
+public:
+  /** Extract dimension from input image. */
+  itkStaticConstMacro(InputImageDimension, unsigned int,
+                      TInputImage::ImageDimension);
+  itkStaticConstMacro(OutputImageDimension, unsigned int,
+                      TInputImage::ImageDimension);
+
+  /** Standard class typedefs. */
+  typedef MaximumGradientMagnitudeImageFilter            Self;
+  typedef ImageToImageFilter< TInputImage, TInputImage > Superclass;
+  typedef SmartPointer< Self >                           Pointer;
+  typedef SmartPointer< const Self >                     ConstPointer;
+
+  /** Image related typedefs. */
+  typedef typename TInputImage::Pointer InputImagePointer;
+
+  typedef typename TInputImage::RegionType RegionType;
+  typedef typename TInputImage::SizeType   SizeType;
+  typedef typename TInputImage::IndexType  IndexType;
+  typedef typename TInputImage::PixelType  PixelType;
+
+  /** Smart Pointer type to a DataObject. */
+  typedef typename DataObject::Pointer DataObjectPointer;
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self);
+
+  /** Run-time type information (and related methods). */
+  itkTypeMacro(MaximumGradientMagnitudeImageFilter, ImageToImageFilter);
+
+  /** Extract some information from the image types.  Dimensionality
+   * of the two images is assumed to be the same. */
+  itkStaticConstMacro(ImageDimension, unsigned int,
+                      TInputImage::ImageDimension);
+
+  /** Image typedef support. */
+  typedef TInputImage InputImageType;
+
+  /** Type of DataObjects used for scalar outputs */
+  typedef SimpleDataObjectDecorator< double > DoubleObjectType;
+
+  /** Return the computed Maximum. */
+  double GetMaximum() const
+  { return this->GetMaximumOutput()->Get(); }
+  DoubleObjectType * GetMaximumOutput();
+
+  const DoubleObjectType * GetMaximumOutput() const;
+
+  /** Make a DataObject of the correct type to be used as the specified
+   * output. */
+  typedef ProcessObject::DataObjectPointerArraySizeType DataObjectPointerArraySizeType;
+  using Superclass::MakeOutput;
+  virtual DataObjectPointer MakeOutput(DataObjectPointerArraySizeType idx);
+
+  /** Use the image spacing information in calculations. Use this option if you
+   *  want derivatives in physical space. Default is UseImageSpacingOn. */
+  void SetUseImageSpacingOn()
+  { this->SetUseImageSpacing(true); }
+
+  /** Ignore the image spacing. Use this option if you want derivatives in
+      isotropic pixel space.  Default is UseImageSpacingOn. */
+  void SetUseImageSpacingOff()
+  { this->SetUseImageSpacing(false); }
+
+  /** Set/Get whether or not the filter will use the spacing of the input
+      image in its calculations */
+  itkSetMacro(UseImageSpacing, bool);
+  itkGetConstMacro(UseImageSpacing, bool);
+
+
+#ifdef ITK_USE_CONCEPT_CHECKING
+  // Begin concept checking
+  itkConceptMacro( LessThanComparableCheck,
+                   ( Concept::LessThanComparable< PixelType > ) );
+  itkConceptMacro( GreaterThanComparableCheck,
+                   ( Concept::GreaterThanComparable< PixelType > ) );
+  itkConceptMacro( OStreamWritableCheck,
+                   ( Concept::OStreamWritable< PixelType > ) );
+  // End concept checking
+#endif
+
+protected:
+  MaximumGradientMagnitudeImageFilter();
+  virtual ~MaximumGradientMagnitudeImageFilter() {}
+  void PrintSelf(std::ostream & os, Indent indent) const;
+
+  /** Pass the input through unmodified. Do this by Grafting in the
+    AllocateOutputs method. */
+  void AllocateOutputs();
+
+  /** Initialize some accumulators before the threads run. */
+  void BeforeThreadedGenerateData();
+
+  /** Do final mean and variance computation from data accumulated in threads.
+    */
+  void AfterThreadedGenerateData();
+
+  /** Multi-thread version GenerateData. */
+  void  ThreadedGenerateData(const RegionType &
+                             outputRegionForThread,
+                             ThreadIdType threadId);
+
+  // Override since the filter needs all the data for the algorithm
+  void GenerateInputRequestedRegion();
+
+  // Override since the filter produces all of its output
+  void EnlargeOutputRequestedRegion(DataObject *data);
+
+private:
+  MaximumGradientMagnitudeImageFilter(const Self &); //purposely not implemented
+  void operator=(const Self &);            //purposely not implemented
+
+  std::vector< double > m_ThreadMax;
+
+  bool m_UseImageSpacing;
+};
+} // end namespace itk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "itkMaximumGradientMagnitudeImageFilter.hxx"
+#endif
+
+#endif // ITKMAXIMUMGRADIENTMAGNITUDEIMAGEFILTER_H
diff --git a/Common/ITKExtras/itkMaximumGradientMagnitudeImageFilter.hxx b/Common/ITKExtras/itkMaximumGradientMagnitudeImageFilter.hxx
new file mode 100644
index 0000000..a390e91
--- /dev/null
+++ b/Common/ITKExtras/itkMaximumGradientMagnitudeImageFilter.hxx
@@ -0,0 +1,266 @@
+#ifndef ITKMAXIMUMGRADIENTMAGNITUDEIMAGEFILTER_HXX
+#define ITKMAXIMUMGRADIENTMAGNITUDEIMAGEFILTER_HXX
+
+#include "itkMaximumGradientMagnitudeImageFilter.h"
+
+#include "itkConstNeighborhoodIterator.h"
+#include "itkNeighborhoodInnerProduct.h"
+#include "itkImageRegionIterator.h"
+#include "itkDerivativeOperator.h"
+#include "itkNeighborhoodAlgorithm.h"
+#include "itkProgressReporter.h"
+
+
+#include <vector>
+
+namespace itk
+{
+template< typename TInputImage >
+MaximumGradientMagnitudeImageFilter< TInputImage >
+::MaximumGradientMagnitudeImageFilter()
+{
+  this->SetNumberOfRequiredOutputs(2);
+  // first output is a copy of the image, DataObject created by
+  // superclass
+  //
+  // allocate the data objects for the remaining outputs which are
+  // just decorators around floating point types
+
+  typename DoubleObjectType::Pointer output =
+      static_cast<DoubleObjectType *>(this->MakeOutput(1).GetPointer());
+  this->ProcessObject::SetNthOutput(1, output.GetPointer());
+
+  this->GetMaximumOutput()->Set(0.0);
+
+  m_UseImageSpacing = true;
+}
+
+template< typename TInputImage >
+DataObject::Pointer
+MaximumGradientMagnitudeImageFilter< TInputImage >
+::MakeOutput(DataObjectPointerArraySizeType output)
+{
+  switch ( output )
+    {
+    case 0:
+      return TInputImage::New().GetPointer();
+      break;
+    case 1:
+      return DoubleObjectType::New().GetPointer();
+      break;
+    default:
+      // might as well make an image
+      return TInputImage::New().GetPointer();
+      break;
+    }
+}
+
+
+template< typename TInputImage >
+typename MaximumGradientMagnitudeImageFilter< TInputImage >::DoubleObjectType *
+MaximumGradientMagnitudeImageFilter< TInputImage >
+::GetMaximumOutput()
+{
+  return static_cast< DoubleObjectType * >( this->ProcessObject::GetOutput(1) );
+}
+
+template< typename TInputImage >
+const typename MaximumGradientMagnitudeImageFilter< TInputImage >::DoubleObjectType *
+MaximumGradientMagnitudeImageFilter< TInputImage >
+::GetMaximumOutput() const
+{
+  return static_cast< const DoubleObjectType * >( this->ProcessObject::GetOutput(1) );
+}
+
+template< typename TInputImage >
+void
+MaximumGradientMagnitudeImageFilter< TInputImage >
+::GenerateInputRequestedRegion()
+{
+  Superclass::GenerateInputRequestedRegion();
+  if ( this->GetInput() )
+    {
+    InputImagePointer image =
+      const_cast< typename Superclass::InputImageType * >( this->GetInput() );
+    image->SetRequestedRegionToLargestPossibleRegion();
+    }
+}
+
+template< typename TInputImage >
+void
+MaximumGradientMagnitudeImageFilter< TInputImage >
+::EnlargeOutputRequestedRegion(DataObject *data)
+{
+  Superclass::EnlargeOutputRequestedRegion(data);
+  data->SetRequestedRegionToLargestPossibleRegion();
+}
+
+template< typename TInputImage >
+void
+MaximumGradientMagnitudeImageFilter< TInputImage >
+::AllocateOutputs()
+{
+  // Pass the input through as the output
+  InputImagePointer image =
+    const_cast< TInputImage * >( this->GetInput() );
+
+  this->GraftOutput(image);
+
+  // Nothing that needs to be allocated for the remaining outputs
+}
+
+template< typename TInputImage >
+void
+MaximumGradientMagnitudeImageFilter< TInputImage >
+::BeforeThreadedGenerateData()
+{
+  ThreadIdType numberOfThreads = this->GetNumberOfThreads();
+
+  // Create the thread temporaries
+  m_ThreadMax = std::vector< double >(numberOfThreads, 0.0);
+}
+
+template< typename TInputImage >
+void
+MaximumGradientMagnitudeImageFilter< TInputImage >
+::AfterThreadedGenerateData()
+{
+  ThreadIdType i;
+  ThreadIdType numberOfThreads = this->GetNumberOfThreads();
+
+
+  // Find the min/max over all threads
+  double maximum = 0.0;
+  for ( i = 0; i < numberOfThreads; i++ )
+    {
+    if ( m_ThreadMax[i] > maximum )
+      {
+      maximum = m_ThreadMax[i];
+      }
+    }
+
+  // Set the outputs
+  this->GetMaximumOutput()->Set(maximum);
+}
+
+template< typename TInputImage >
+void
+MaximumGradientMagnitudeImageFilter< TInputImage >
+::ThreadedGenerateData(const RegionType & outputRegionForThread,
+                       ThreadIdType threadId)
+{
+  if ( outputRegionForThread.GetNumberOfPixels() == 0 )
+    return;
+
+  typedef float RealType;
+
+  // Local maximum
+  double localMax = 0.0;
+
+  unsigned int i;
+
+  ZeroFluxNeumannBoundaryCondition< TInputImage > nbc;
+
+  ConstNeighborhoodIterator< TInputImage > nit;
+  ConstNeighborhoodIterator< TInputImage > bit;
+
+  NeighborhoodInnerProduct< TInputImage, RealType > SIP;
+
+  // Allocate output
+  typename  InputImageType::ConstPointer input  = this->GetInput();
+
+  // Set up operators
+  DerivativeOperator< RealType, ImageDimension > op[ImageDimension];
+
+  for ( i = 0; i < ImageDimension; i++ )
+    {
+    op[i].SetDirection(0);
+    op[i].SetOrder(1);
+    op[i].CreateDirectional();
+
+    if ( m_UseImageSpacing == true )
+      {
+      if ( this->GetInput()->GetSpacing()[i] == 0.0 )
+        {
+        itkExceptionMacro(<< "Image spacing cannot be zero.");
+        }
+      else
+        {
+        op[i].ScaleCoefficients(1.0 / this->GetInput()->GetSpacing()[i]);
+        }
+      }
+    }
+
+  // Calculate iterator radius
+  Size< ImageDimension > radius;
+  for ( i = 0; i < ImageDimension; ++i )
+    {
+    radius[i]  = op[0].GetRadius()[0];
+    }
+
+  // Find the data-set boundary "faces"
+  typename NeighborhoodAlgorithm::ImageBoundaryFacesCalculator< TInputImage >::
+  FaceListType faceList;
+  NeighborhoodAlgorithm::ImageBoundaryFacesCalculator< TInputImage > bC;
+  faceList = bC(input, outputRegionForThread, radius);
+
+  typename NeighborhoodAlgorithm::ImageBoundaryFacesCalculator< TInputImage >::
+  FaceListType::iterator fit;
+  fit = faceList.begin();
+
+  // support progress methods/callbacks
+  ProgressReporter progress( this, threadId, outputRegionForThread.GetNumberOfPixels() );
+
+  // Process non-boundary face
+  nit = ConstNeighborhoodIterator< TInputImage >(radius, input, *fit);
+
+  std::slice          x_slice[ImageDimension];
+  const SizeValueType center = nit.Size() / 2;
+  for ( i = 0; i < ImageDimension; ++i )
+    {
+    x_slice[i] = std::slice( center - nit.GetStride(i) * radius[i],
+                             op[i].GetSize()[0], nit.GetStride(i) );
+    }
+
+  // Process each of the boundary faces.  These are N-d regions which border
+  // the edge of the buffer.
+  for ( fit = faceList.begin(); fit != faceList.end(); ++fit )
+    {
+    bit = ConstNeighborhoodIterator< InputImageType >(radius,
+                                                      input, *fit);
+    bit.OverrideBoundaryCondition(&nbc);
+    bit.GoToBegin();
+
+    while ( !bit.IsAtEnd() )
+      {
+      RealType a = NumericTraits< RealType >::Zero;
+      for ( i = 0; i < ImageDimension; ++i )
+        {
+        const RealType g = SIP(x_slice[i], bit, op[i]);
+        a += g * g;
+        }
+
+      if(localMax < a)
+        localMax = a;
+
+      ++bit;
+      progress.CompletedPixel();
+      }
+    }
+
+  m_ThreadMax[threadId] = vcl_sqrt(localMax);
+}
+
+template< typename TImage >
+void
+MaximumGradientMagnitudeImageFilter< TImage >
+::PrintSelf(std::ostream & os, Indent indent) const
+{
+  Superclass::PrintSelf(os, indent);
+
+  os << indent << "Maximum: "
+     << static_cast< typename NumericTraits< PixelType >::PrintType >( this->GetMaximum() )
+     << std::endl;
+}
+} // end namespace itk
+#endif
diff --git a/Common/PropertyModel.h b/Common/PropertyModel.h
index f05f6c8..3e0906b 100644
--- a/Common/PropertyModel.h
+++ b/Common/PropertyModel.h
@@ -272,18 +272,21 @@ protected:
   owns the data, as opposed to STLMapWrapperItemSetDomain, which references
   the data from another map. This implementation is useful for small domains
   where there is no cost in passing the domain by value.
+
+  This version does not support comparison between domains, and can not be used
+  in applications where the domain needs to be cached
   */
 template<class TVal, class TDesc>
-class SimpleItemSetDomain : public
+class SimpleNonAtomicItemSetDomain : public
     AbstractItemSetDomain<TVal, TDesc, typename std::map<TVal,TDesc>::const_iterator>
 {
 public:
   typedef std::map<TVal, TDesc> MapType;
   typedef typename MapType::const_iterator const_iterator;
-  typedef SimpleItemSetDomain<TVal, TDesc> Self;
+  typedef SimpleNonAtomicItemSetDomain<TVal, TDesc> Self;
   typedef AbstractItemSetDomain<TVal, TDesc, const_iterator> Superclass;
 
-  SimpleItemSetDomain() : Superclass() { }
+  SimpleNonAtomicItemSetDomain() : Superclass() { }
 
   const_iterator begin() const
     { return m_Map.begin(); }
@@ -311,22 +314,56 @@ public:
 
   const TDesc & operator [] (const TVal &key) const { return m_Map[key]; }
 
+  // Bogus - just compares to self
   virtual bool operator == (const Self &cmp) const
-    { return m_Map == cmp.m_Map; }
+    { return &m_Map == &cmp.m_Map; }
 
+  // Bogus - just compares to self
   virtual bool operator != (const Self &cmp) const
-    { return m_Map != cmp.m_Map; }
+    { return &m_Map != &cmp.m_Map; }
 
   // An atomic domain holds its own state, so it is possible to compare two
   // atomic domains to determine if they are the same or different. Domains
-  // that store references to external objects are not atomic.
-  virtual bool isAtomic() { return true; }
+  // that store references to external objects are not atomic. This class is
+  // not atomic because it does not support comparisons
+  virtual bool isAtomic() { return false; }
 
 protected:
   MapType m_Map;
 };
 
 /**
+  This is an item domain implementation that is just an stl::map, i.e., it
+  owns the data, as opposed to STLMapWrapperItemSetDomain, which references
+  the data from another map. This implementation is useful for small domains
+  where there is no cost in passing the domain by value.
+  */
+template<class TVal, class TDesc>
+class SimpleItemSetDomain : public
+    SimpleNonAtomicItemSetDomain<TVal, TDesc>
+{
+public:
+  typedef std::map<TVal, TDesc> MapType;
+  typedef typename MapType::const_iterator const_iterator;
+  typedef SimpleItemSetDomain<TVal, TDesc> Self;
+  typedef SimpleNonAtomicItemSetDomain<TVal, TDesc> Superclass;
+
+  SimpleItemSetDomain() : Superclass() { }
+
+  virtual bool operator == (const Self &cmp) const
+    { return this->m_Map == cmp.m_Map; }
+
+  virtual bool operator != (const Self &cmp) const
+    { return this->m_Map != cmp.m_Map; }
+
+  // An atomic domain holds its own state, so it is possible to compare two
+  // atomic domains to determine if they are the same or different. Domains
+  // that store references to external objects are not atomic.
+  virtual bool isAtomic() { return true; }
+};
+
+
+/**
  * States that can be checked for property models. We place this enum outside
  * of the class AbstractPropertyModel because this class is templated. This
  * enum is meant to be used with the SNAPUIFlag framework.
@@ -442,6 +479,7 @@ protected:
   AbstractPropertyModel()
   {
     Rebroadcast(this, ValueChangedEvent(), StateMachineChangeEvent());
+    Rebroadcast(this, DomainChangedEvent(), StateMachineChangeEvent());
   }
 };
 
@@ -554,6 +592,17 @@ NewSimpleConcreteProperty(TVal val)
   return p;
 }
 
+template <class TVal, class TDomain>
+SmartPtr< ConcretePropertyModel<TVal, TDomain> >
+NewConcreteProperty(TVal val, TDomain domain)
+{
+  typedef ConcretePropertyModel<TVal, TDomain> Prop;
+  SmartPtr<Prop> p = Prop::New();
+  p->SetValue(val);
+  p->SetDomain(domain);
+  return p;
+}
+
 
 
 /**
@@ -603,6 +652,8 @@ Make some typedefs. The macros below define types
 // Macros for standard types that support ranges
 MAKE_TYPEDEF_PM_RANGED(double,          Double)
 MAKE_TYPEDEF_PM_RANGED(float,           Float)
+MAKE_TYPEDEF_PM_RANGED(long,            Long)
+MAKE_TYPEDEF_PM_RANGED(unsigned long,   ULong)
 MAKE_TYPEDEF_PM_RANGED(int,             Int)
 MAKE_TYPEDEF_PM_RANGED(unsigned int,    UInt)
 MAKE_TYPEDEF_PM_RANGED(short,           Short)
diff --git a/Common/SNAPCommon.cxx.in b/Common/SNAPCommon.cxx.in
index 65dd03b..ad8c34b 100644
--- a/Common/SNAPCommon.cxx.in
+++ b/Common/SNAPCommon.cxx.in
@@ -37,6 +37,7 @@ const char SNAPCurrentVersionReleaseDate[] = "@SNAP_VERSION_RELEASE_DATE@";
 const char SNAPBuildInfo[] =
     "Build date        @SNAP_VERSION_COMPILE_DATE@\n"
     "Git commit hash   @SNAP_VERSION_GIT_SHA1@\n"
+    "Git branch        @SNAP_VERSION_GIT_BRANCH@\n"
     "Build site name   @SITE@\n"
     "Build OS          @CMAKE_HOST_SYSTEM@ @CMAKE_HOST_SYSTEM_PROCESSOR@\n"
     "Build type        @CMAKE_BUILD_TYPE@\n"
diff --git a/Common/SNAPEventListenerCallbacks.h b/Common/SNAPEventListenerCallbacks.h
index 14ad777..89fe732 100644
--- a/Common/SNAPEventListenerCallbacks.h
+++ b/Common/SNAPEventListenerCallbacks.h
@@ -22,7 +22,8 @@ unsigned long AddListener(itk::Object *sender,
 }
 
 template <class TObserver>
-unsigned long AddListener(itk::Object *sender,
+unsigned long
+AddListener(itk::Object *sender,
                  const itk::EventObject &event,
                  TObserver *observer,
                  void (TObserver::*memberFunction)(itk::Object*, const itk::EventObject &))
diff --git a/Common/SNAPOpenGL.cxx b/Common/SNAPOpenGL.cxx
index 306ac22..2c15aa3 100644
--- a/Common/SNAPOpenGL.cxx
+++ b/Common/SNAPOpenGL.cxx
@@ -37,3 +37,37 @@ gl_draw_circle_with_border(double x, double y, double r,
 
   glPopMatrix();
 }
+
+
+#ifdef __APPLE__
+
+#include <Availability.h>
+
+#if __MAC_10_8
+
+#include <GLKit/GLKMatrix4.h>
+
+void irisOrtho2D(double x, double w, double y, double h)
+{
+  GLKMatrix4 matrix = GLKMatrix4MakeOrtho(x, w, y, h, -1, 1);
+  glLoadMatrixf(matrix.m);
+}
+
+#else
+
+void irisOrtho2D(double x, double w, double y, double h)
+{
+  gluOrtho2D(x,w,y,h);
+}
+
+#endif // APPLE
+
+#else
+
+void irisOrtho2D(double x, double w, double y, double h)
+{
+  gluOrtho2D(x,w,y,h);
+}
+
+#endif
+
diff --git a/Common/SNAPOpenGL.h b/Common/SNAPOpenGL.h
index 0c9514d..e03ca96 100644
--- a/Common/SNAPOpenGL.h
+++ b/Common/SNAPOpenGL.h
@@ -95,4 +95,7 @@ gl_draw_circle_with_border(double x, double y, double r,
 
 Vector3d adjust_color_luminance(const Vector3d &color, double factor);
 
+// GLU functions are deprecated on Apple so we need our own versions
+void irisOrtho2D(double x, double w, double y, double h);
+
 #endif // __SNAPOpenGL_h_
diff --git a/GUI/Model/AnnotationModel.cxx b/GUI/Model/AnnotationModel.cxx
new file mode 100644
index 0000000..9602118
--- /dev/null
+++ b/GUI/Model/AnnotationModel.cxx
@@ -0,0 +1,778 @@
+#include "AnnotationModel.h"
+#include "GenericSliceModel.h"
+#include "IRISApplication.h"
+#include "GenericImageData.h"
+#include "ImageAnnotationData.h"
+#include "GlobalUIModel.h"
+#include <limits>
+
+void AnnotationModel::SetParent(GenericSliceModel *model)
+{
+  m_Parent = model;
+  Rebroadcast(m_Parent->GetDriver()->GetGlobalState()->GetAnnotationModeModel(),
+              ValueChangedEvent(), ModelUpdateEvent());
+}
+
+double AnnotationModel::GetLineLength(const Vector3f &xSliceA, const Vector3f &xSliceB)
+{
+  Vector2f pt1InAna = m_Parent->MapSliceToPhysicalWindow(xSliceA);
+  Vector2f pt2InAna = m_Parent->MapSliceToPhysicalWindow(xSliceB);
+  double length = (pt1InAna[0] - pt2InAna[0]) * (pt1InAna[0] - pt2InAna[0])
+                + (pt1InAna[1] - pt2InAna[1]) * (pt1InAna[1] - pt2InAna[1]);
+  length = sqrt(length);
+  return length;
+}
+
+double AnnotationModel::GetCurrentLineLength()
+{
+  return GetLineLength(m_CurrentLine.first, m_CurrentLine.second);
+}
+
+double AnnotationModel::GetCurrentLineLengthInPixels()
+{
+  Vector2f screen_offset =
+      m_Parent->MapSliceToWindow(m_CurrentLine.first) -
+      m_Parent->MapSliceToWindow(m_CurrentLine.second);
+
+  return screen_offset.magnitude() / m_Parent->GetSizeReporter()->GetViewportPixelRatio();
+}
+
+double AnnotationModel::GetAngleWithCurrentLine(const annot::LineSegmentAnnotation *lsa)
+{
+  // Process the current line
+  Vector2f v1 = m_Parent->MapSliceToPhysicalWindow(m_CurrentLine.first)
+                - m_Parent->MapSliceToPhysicalWindow(m_CurrentLine.second);
+  v1 /= sqrt(v1[0]*v1[0] + v1[1]*v1[1]);
+
+  // Process the annotation
+  Vector2f v2 = m_Parent->MapSliceToPhysicalWindow(
+                  m_Parent->MapImageToSlice(lsa->GetSegment().first))
+                -
+                m_Parent->MapSliceToPhysicalWindow(
+                  m_Parent->MapImageToSlice(lsa->GetSegment().second));
+  v2 /= sqrt(v2[0]*v2[0] + v2[1]*v2[1]);
+
+  // Compute the dot product and no need for the third components that are zeros
+  double angle = 180.0 * acos(fabs(v1[0]*v2[0]+v1[1]*v2[1])) / vnl_math::pi;
+  return angle;
+}
+
+void AnnotationModel::AdjustAngleToRoundDegree(LineSegment &line, int n_degrees)
+{
+  ImageAnnotationData *adata = this->GetAnnotations();
+
+  // Map the line segment from slice coordinates to window physical, where angles are
+  // computed
+  Vector2f p1 = m_Parent->MapSliceToPhysicalWindow(line.first);
+  Vector2f p2 = m_Parent->MapSliceToPhysicalWindow(line.second);
+
+  // Express the vector of the line in polar coordinates
+  double p_rad = (p2 - p1).magnitude();
+  double p_phase = atan2(p2[1] - p1[1], p2[0] - p1[0]) * 180.0 / vnl_math::pi;
+
+  // Current proposed adjustment
+  Vector2f p2_rot_best = p2;
+  double rot_best = std::numeric_limits<double>::infinity();
+
+  // Loop over all the lines
+  for(ImageAnnotationData::AnnotationConstIterator it = adata->GetAnnotations().begin();
+      it != adata->GetAnnotations().end(); ++it)
+    {
+    const annot::LineSegmentAnnotation *lsa =
+        dynamic_cast<const annot::LineSegmentAnnotation *>(it->GetPointer());
+    if(lsa && this->IsAnnotationVisible(lsa))
+      {
+      // Normalize the annotated line
+      Vector2f q1 = m_Parent->MapSliceToPhysicalWindow(
+                      m_Parent->MapImageToSlice(lsa->GetSegment().first));
+      Vector2f q2 = m_Parent->MapSliceToPhysicalWindow(
+                      m_Parent->MapImageToSlice(lsa->GetSegment().second));
+
+      // Get the phase of the line
+      double q_phase = atan2(q2[1] - q1[1], q2[0] - q1[0]) * 180.0 / vnl_math::pi;
+
+      // Compute the updated phase - now the difference in phase is fractional
+      double p_phase_round = q_phase + floor((p_phase - q_phase) / n_degrees + 0.5) * n_degrees;
+      double p_phase_shift = fabs(p_phase_round - p_phase);
+
+      // Map the rounded phase to the new p2 position
+      Vector2f p2_prop(
+            p1[0] + p_rad * cos(p_phase_round * vnl_math::pi / 180.0),
+            p1[1] + p_rad * sin(p_phase_round * vnl_math::pi / 180.0));
+
+      // Compare to current best
+      if(p_phase_shift < rot_best)
+        {
+        rot_best = p_phase_shift;
+        p2_rot_best = p2_prop;
+        }
+      }
+    }
+
+  // Map back
+  line.second = m_Parent->MapPhysicalWindowToSlice(p2_rot_best);
+}
+
+Vector3f AnnotationModel::GetAnnotationCenter(const AbstractAnnotation *annot)
+{
+  const annot::LineSegmentAnnotation *lsa = dynamic_cast<const annot::LineSegmentAnnotation *>(annot);
+  if(lsa)
+    {
+    return (m_Parent->MapImageToSlice(lsa->GetSegment().first)
+            + m_Parent->MapImageToSlice(lsa->GetSegment().second)) * 0.5f;
+    }
+
+
+  return Vector3f(0.f);
+}
+
+double AnnotationModel::GetDistanceToLine(const Vector3f &x1, const Vector3f &x2, const Vector3d &point)
+{
+  Vector2f p0 = m_Parent->MapSliceToWindow(x1);
+  Vector2f p1 = m_Parent->MapSliceToWindow(x2);
+  Vector2f x = m_Parent->MapSliceToWindow(to_float(point));
+
+  float alpha = dot_product(x - p0, p1 - p0) / dot_product(p1 - p0, p1 - p0);
+  if(alpha < 0)
+    alpha = 0;
+  if(alpha > 1)
+    alpha = 1;
+
+  Vector2f px = p0 * (1.0f - alpha) + p1 * alpha;
+  return (px - x).magnitude();
+
+}
+
+
+double AnnotationModel::GetDistanceToLine(LineSegment &line, const Vector3d &point)
+{
+  return GetDistanceToLine(line.first, line.second, point);
+}
+
+AnnotationMode AnnotationModel::GetAnnotationMode() const
+{
+  return m_Parent->GetDriver()->GetGlobalState()->GetAnnotationMode();
+}
+
+ImageAnnotationData *AnnotationModel::GetAnnotations()
+{
+  return m_Parent->GetDriver()->GetCurrentImageData()->GetAnnotations();
+}
+
+bool AnnotationModel::IsAnnotationVisible(const AnnotationModel::AbstractAnnotation *annot)
+{
+  return annot->IsVisible(
+        m_Parent->GetSliceDirectionInImageSpace(),
+        m_Parent->GetSliceIndex());
+}
+
+double AnnotationModel
+::GetPixelDistanceToAnnotation(
+    const AbstractAnnotation *annot,
+    const Vector3d &point)
+{
+  const annot::LineSegmentAnnotation *lsa = dynamic_cast<const annot::LineSegmentAnnotation *>(annot);
+  if(lsa)
+    {
+    const annot::LineSegment &seg = lsa->GetSegment();
+    Vector3f s1 = m_Parent->MapImageToSlice(seg.first);
+    Vector3f s2 = m_Parent->MapImageToSlice(seg.second);
+    return GetDistanceToLine(s1, s2, point);
+    }
+
+  const annot::LandmarkAnnotation *lma = dynamic_cast<const annot::LandmarkAnnotation *>(annot);
+  if(lma)
+    {
+    const annot::Landmark &landmark = lma->GetLandmark();
+    Vector3f s1, s2;
+    this->GetLandmarkArrowPoints(landmark, s1, s2);
+    return GetDistanceToLine(s1, s2, point);
+    }
+
+  return std::numeric_limits<double>::infinity();
+}
+
+AnnotationModel::AbstractAnnotation *
+AnnotationModel::GetAnnotationUnderCursor(const Vector3d &xSlice)
+{
+  ImageAnnotationData *adata = this->GetAnnotations();
+
+  // Current best annotation
+  AbstractAnnotation *asel = NULL;
+  double dist_min = std::numeric_limits<double>::infinity();
+  double dist_thresh = 5 * m_Parent->GetSizeReporter()->GetViewportPixelRatio();
+
+  // Loop over all annotations
+  for(ImageAnnotationData::AnnotationConstIterator it = adata->GetAnnotations().begin();
+      it != adata->GetAnnotations().end(); ++it)
+    {
+    AbstractAnnotation *a = *it;
+
+    // Test if annotation is visible in this plane
+    if(this->IsAnnotationVisible(a))
+      {
+      double dist = GetPixelDistanceToAnnotation(a, xSlice);
+      if(dist < dist_thresh && dist < dist_min)
+        {
+        asel = a;
+        dist_min = dist;
+        }
+      }
+    }
+
+  return asel;
+}
+
+bool AnnotationModel::ProcessPushEvent(const Vector3d &xSlice, bool shift_mod)
+{
+  // Get the annotation data
+  ImageAnnotationData *adata = this->GetAnnotations();
+
+  bool handled = false;
+  if(this->GetAnnotationMode() == ANNOTATION_RULER || this->GetAnnotationMode() == ANNOTATION_LANDMARK)
+    {
+    if(m_FlagDrawingLine)
+      {
+      // Complete drawing line
+      m_CurrentLine.second = to_float(xSlice);
+      handled = true;
+      }
+    else
+      {
+      m_CurrentLine.first = to_float(xSlice);
+      m_CurrentLine.second = to_float(xSlice);
+      m_FlagDrawingLine = true;
+      handled = true;
+      }
+    }
+
+  else if(this->GetAnnotationMode() == ANNOTATION_SELECT)
+    {
+    // Check if for any of the selected annotations, the click is close to the drag handle
+    int handle_idx = -1;
+    AbstractAnnotation *asel = this->GetSelectedHandleUnderCusror(xSlice, handle_idx);
+
+    // Find closest annotation under the cursor
+    if(!asel)
+      asel = this->GetAnnotationUnderCursor(xSlice);
+
+    // If the shift modifier is on, we add to the selection
+    if(shift_mod)
+      {
+      // Add to the selection
+      if(asel)
+        asel->SetSelected(!asel->GetSelected());
+      }
+    // If not clicked on a selected handle, process as a select operation
+    else if(handle_idx < 0)
+      {
+      // Clear the selection
+      for(ImageAnnotationData::AnnotationConstIterator it = adata->GetAnnotations().begin();
+          it != adata->GetAnnotations().end(); ++it)
+        (*it)->SetSelected(false);
+
+      // Select the clicked
+      if(asel)
+        asel->SetSelected(!asel->GetSelected());
+      }
+
+    // Store the position of the drag-start
+    if(asel)
+      {
+      m_MovingSelection = true;
+      m_DragStart = to_float(xSlice);
+      m_DragLast = to_float(xSlice);
+      m_MovingSelectionHandle = handle_idx;
+      m_MovingSelectionHandleAnnot = asel;
+      }
+    else
+      {
+      m_MovingSelection = false;
+      }
+
+    // We always consider the click as handled because otherwise it can be really annoying
+    // for the user if they miss an annotation and that results in the cross-hairs being
+    // moved to another location
+    handled = true;
+    }
+
+  if(handled)
+    InvokeEvent(ModelUpdateEvent());
+  return handled;
+}
+
+bool AnnotationModel::ProcessMoveEvent(const Vector3d &xSlice, bool shift_mod, bool drag)
+{
+  ImageAnnotationData *adata = this->GetAnnotations();
+  bool handled = false;
+  if(this->GetAnnotationMode() == ANNOTATION_RULER || this->GetAnnotationMode() == ANNOTATION_LANDMARK)
+    {
+    if(m_FlagDrawingLine)
+      {
+      // Accept the second point
+      m_CurrentLine.second = to_float(xSlice);
+
+      // If shift pressed, adjust the line to have a integral angle with one of existing
+      // lines
+      if(this->GetAnnotationMode() == ANNOTATION_RULER  && shift_mod)
+        {
+        this->AdjustAngleToRoundDegree(m_CurrentLine, 5);
+        }
+
+      handled = true;
+      }
+    }
+  else if(this->GetAnnotationMode() == ANNOTATION_SELECT && m_MovingSelection && drag)
+    {
+
+    // Compute the amount to move the annotation by
+    Vector3f p_last = m_Parent->MapSliceToImage(m_DragLast);
+    Vector3f p_now = m_Parent->MapSliceToImage(to_float(xSlice));
+    Vector3f p_delta = p_now - p_last;
+
+    // Process the move command on selected annotations
+    for(ImageAnnotationData::AnnotationIterator it = adata->GetAnnotations().begin();
+        it != adata->GetAnnotations().end(); ++it)
+      {
+      AbstractAnnotation *a = *it;
+
+      // Test if annotation is visible in this plane
+      if(m_MovingSelectionHandle < 0 && a->GetSelected() && this->IsAnnotationVisible(a))
+        {
+        // Move the annotation by this amount
+        a->MoveBy(p_delta);
+        }
+      else if(m_MovingSelectionHandle >= 0 && m_MovingSelectionHandleAnnot == a)
+        {
+        // Move the annotation handle by this amount
+        this->MoveAnnotationHandle(a, m_MovingSelectionHandle, p_delta);
+        }
+      }
+
+    // Store the update point
+    m_DragLast = to_float(xSlice);
+
+    // Event has been handled
+    handled = true;
+    }
+
+  if(handled)
+    this->InvokeEvent(ModelUpdateEvent());
+  return handled;
+}
+
+bool AnnotationModel::ProcessReleaseEvent(const Vector3d &xSlice, bool shift_mod)
+{
+  // Handle as a drag event
+  bool handled = this->ProcessMoveEvent(xSlice, shift_mod, true);
+
+  // If drawing line, complete the line drawing, as long as the line is long enough
+  if(m_FlagDrawingLine)
+    {
+    // If line is longer than a threshold of 5 pixel units, mark it as completed
+    if(this->GetCurrentLineLengthInPixels() > 5)
+      m_FlagDrawingLine = false;
+    }
+
+  return handled;
+}
+
+bool AnnotationModel::IsDrawingRuler()
+{
+  return this->GetAnnotationMode() == ANNOTATION_RULER && m_FlagDrawingLine;
+}
+
+void AnnotationModel::AcceptLine()
+{
+  // Get the length of the line in logical (non-retina) pixels
+  // Check that the length of the segment is at least 5 screen pixels
+
+
+  if(this->GetAnnotationMode() == ANNOTATION_RULER)
+    {
+    // Create the line in image space
+    annot::LineSegment ls = std::make_pair(
+                              m_Parent->MapSliceToImage(m_CurrentLine.first),
+                              m_Parent->MapSliceToImage(m_CurrentLine.second));
+    // Add the line
+    SmartPtr<annot::LineSegmentAnnotation> lsa = annot::LineSegmentAnnotation::New();
+    lsa->SetSegment(ls);
+    lsa->SetPlane(m_Parent->GetSliceDirectionInImageSpace());
+    lsa->SetVisibleInAllPlanes(false);
+    lsa->SetVisibleInAllSlices(false);
+    lsa->SetColor(m_Parent->GetParentUI()->GetGlobalState()->GetAnnotationColor());
+    lsa->SetSelected(false);
+
+    this->GetAnnotations()->AddAnnotation(lsa);
+    m_FlagDrawingLine = false;
+
+    this->InvokeEvent(ModelUpdateEvent());
+    }
+
+  else if(this->GetAnnotationMode() == ANNOTATION_LANDMARK)
+    {
+    // Create the line in image space
+    annot::Landmark lm;
+    lm.Text = this->GetCurrentAnnotationText();
+    lm.Pos = m_Parent->MapSliceToImage(m_CurrentLine.first);
+
+    // Set the default offset. The default offset corresponds to 5 screen pixels
+    // to the top right. We need to map this into image units
+    Vector2f xHeadWin = m_Parent->MapSliceToWindow(m_CurrentLine.first);
+    Vector2f xTailWin = m_Parent->MapSliceToWindow(m_CurrentLine.second);
+    Vector2f xHeadWinPhys = m_Parent->MapSliceToPhysicalWindow(m_CurrentLine.first);
+    Vector2f xTailWinPhys = m_Parent->MapSliceToPhysicalWindow(m_Parent->MapWindowToSlice(xTailWin));
+    lm.Offset = xTailWinPhys - xHeadWinPhys;
+
+    // Add the line
+    SmartPtr<annot::LandmarkAnnotation> lma = annot::LandmarkAnnotation::New();
+    lma->SetLandmark(lm);
+    lma->SetPlane(m_Parent->GetSliceDirectionInImageSpace());
+    lma->SetVisibleInAllPlanes(false);
+    lma->SetVisibleInAllSlices(false);
+    lma->SetColor(m_Parent->GetParentUI()->GetGlobalState()->GetAnnotationColor());
+    lma->SetSelected(false);
+
+    this->GetAnnotations()->AddAnnotation(lma);
+
+    this->InvokeEvent(ModelUpdateEvent());
+    }
+}
+
+void AnnotationModel::CancelLine()
+{
+  m_FlagDrawingLine = false;
+  this->InvokeEvent(ModelUpdateEvent());
+}
+
+void AnnotationModel::SelectAllOnSlice()
+{
+  ImageAnnotationData *adata = this->GetAnnotations();
+  for(ImageAnnotationData::AnnotationIterator it = adata->GetAnnotations().begin();
+      it != adata->GetAnnotations().end(); ++it)
+    {
+    AbstractAnnotation *a = *it;
+
+    // Test if annotation is visible in this plane
+    if(this->IsAnnotationVisible(a))
+      {
+      a->SetSelected(true);
+      }
+    }
+
+  this->InvokeEvent(ModelUpdateEvent());
+}
+
+void AnnotationModel::DeleteSelectedOnSlice()
+{
+  ImageAnnotationData *adata = this->GetAnnotations();
+  for(ImageAnnotationData::AnnotationIterator it = adata->GetAnnotations().begin();
+      it != adata->GetAnnotations().end(); )
+    {
+    AbstractAnnotation *a = *it;
+
+    // Test if annotation is visible in this plane
+    if(a->GetSelected() && this->IsAnnotationVisible(a))
+      {
+      it = adata->GetAnnotations().erase(it);
+      }
+    else
+      ++it;
+    }
+
+  this->InvokeEvent(ModelUpdateEvent());
+}
+
+void AnnotationModel::GoToNextAnnotation()
+{
+  this->GoToNextOrPrevAnnotation(1);
+}
+
+void AnnotationModel::GoToPreviousAnnotation()
+{
+  this->GoToNextOrPrevAnnotation(-1);
+}
+
+void AnnotationModel::GoToNextOrPrevAnnotation(int direction)
+{
+  // Create a list of all annotations in this slice view, sorted
+  typedef std::pair<long, AbstractAnnotation *> AnnotPair;
+  std::list<AnnotPair> annot_list;
+  typedef std::list<AnnotPair>::iterator AnnotIter;
+  typedef std::list<AnnotPair>::reverse_iterator AnnotRevIter;
+
+  // Find annotation that will serve as a reference point
+  AbstractAnnotation *ref_annot = NULL;
+  AbstractAnnotation *selected = NULL;
+
+  // Iterate through the annotations
+  ImageAnnotationData *adata = this->GetAnnotations();
+  for(ImageAnnotationData::AnnotationIterator it = adata->GetAnnotations().begin();
+      it != adata->GetAnnotations().end(); ++it)
+    {
+    AbstractAnnotation *a = *it;
+    if(a->IsVisible(m_Parent->GetSliceDirectionInImageSpace()))
+      {
+      // Create a pair for the current annotation
+      Vector3f ank_img = a->GetAnchorPoint(m_Parent->GetSliceDirectionInImageSpace());
+      Vector3f ank_slice = m_Parent->MapImageToSlice(ank_img);
+
+      long hash = ank_slice[2] * 100000000l + ank_slice[1] * 10000l + ank_slice[0];
+
+      AnnotPair pair = std::make_pair(hash, a);
+      annot_list.push_back(pair);
+
+      // If the annotation is on this slice and selected, us as a reference
+      if(this->IsAnnotationVisible(a) && a->GetSelected())
+        ref_annot = a;
+      }
+    }
+
+  // Test for degenerate cases
+  if(annot_list.size() == 1)
+    {
+    selected = annot_list.front().second;
+    }
+  else if(annot_list.size() > 1)
+    {
+    // Sort the annotations by slice, then by in-slice position
+    annot_list.sort();
+
+    // Find the reference annotation if it exists
+    if(ref_annot && direction > 0)
+      {
+      AnnotIter it_ref = annot_list.end();
+      for(AnnotIter it = annot_list.begin(); it!=annot_list.end(); ++it)
+        if(it->second == ref_annot)
+          it_ref = it;
+
+      ++it_ref;
+      if(it_ref == annot_list.end())
+        it_ref = annot_list.begin();
+
+      selected = it_ref->second;
+      }
+    else if(ref_annot && direction < 0)
+      {
+      AnnotRevIter it_ref = annot_list.rend();
+      for(AnnotRevIter it = annot_list.rbegin(); it!=annot_list.rend(); ++it)
+        if(it->second == ref_annot)
+          it_ref = it;
+
+      ++it_ref;
+      if(it_ref == annot_list.rend())
+        it_ref = annot_list.rbegin();
+
+      selected = it_ref->second;
+      }
+    else if(direction > 0)
+      {
+      // Start from the beginning and find something on the current slice or after it
+      for(AnnotIter it = annot_list.begin(); it!=annot_list.end(); ++it)
+        if(it->second->GetSliceIndex(m_Parent->GetSliceDirectionInImageSpace()) >=
+           m_Parent->GetSliceIndex())
+          {
+          selected = it->second;
+          break;
+          }
+
+      if(!selected)
+        selected = annot_list.front().second;
+      }
+    else
+      {
+      // Start from the beginning and find something on the current slice or after it
+      for(AnnotRevIter it = annot_list.rbegin(); it!=annot_list.rend(); --it)
+        if(it->second->GetSliceIndex(m_Parent->GetSliceDirectionInImageSpace()) <=
+           m_Parent->GetSliceIndex())
+          {
+          selected = it->second;
+          break;
+          }
+
+      if(!selected)
+        selected = annot_list.back().second;
+      }
+    }
+
+  // Deselect everything
+  for(ImageAnnotationData::AnnotationIterator it = adata->GetAnnotations().begin();
+      it != adata->GetAnnotations().end(); ++it)
+    {
+    (*it)->SetSelected(false);
+    }
+
+  // Select the clicked
+  if(selected)
+    {
+    // Select the next item
+    selected->SetSelected(true);
+
+    // Go to its plane
+    Vector3ui cursor = m_Parent->GetDriver()->GetCursorPosition();
+    cursor[m_Parent->GetSliceDirectionInImageSpace()] = selected->GetSliceIndex(m_Parent->GetSliceDirectionInImageSpace());
+    m_Parent->GetDriver()->SetCursorPosition(cursor);
+    }
+
+  // Fire event
+  this->InvokeEvent(ModelUpdateEvent());
+}
+
+bool AnnotationModel::TestPointInClickRadius(const Vector3f &xClickSlice,
+                                             const Vector3f &xPointSlice,
+                                             int logical_pixels)
+{
+  Vector2f clickW = m_Parent->MapSliceToWindow(xClickSlice);
+  Vector2f pointW = m_Parent->MapSliceToWindow(xPointSlice);
+  int vppr = m_Parent->GetSizeReporter()->GetViewportPixelRatio();
+
+  return
+      fabs(clickW[0] - pointW[0]) <= logical_pixels * vppr
+      &&
+      fabs(clickW[1] - pointW[1]) <= logical_pixels * vppr;
+}
+
+void AnnotationModel::MoveAnnotationHandle(
+    AnnotationModel::AbstractAnnotation *ann, int handle, const Vector3f &deltaPhys)
+{
+  // Draw all the line segments
+  annot::LineSegmentAnnotation *lsa =
+      dynamic_cast<annot::LineSegmentAnnotation *>(ann);
+  if(lsa)
+    {
+    annot::LineSegment ls = lsa->GetSegment();
+    if(handle == 0)
+      ls.first += deltaPhys;
+    else if(handle == 1)
+      ls.second += deltaPhys;
+    lsa->SetSegment(ls);
+    }
+
+  // Draw all the line segments
+  annot::LandmarkAnnotation *lma =
+      dynamic_cast<annot::LandmarkAnnotation *>(ann);
+  if(lma)
+    {
+    annot::Landmark lm = lma->GetLandmark();
+    if(handle == 0)
+      {
+      lm.Pos += deltaPhys;
+      }
+    else if(handle == 1)
+      {
+      Vector3f headXSlice = m_Parent->MapImageToSlice(lm.Pos);
+      Vector3f tailXSlice = m_Parent->MapPhysicalWindowToSlice(
+            m_Parent->MapSliceToPhysicalWindow(headXSlice) + lm.Offset);
+      Vector3f tailXImage = m_Parent->MapSliceToImage(tailXSlice);
+      Vector3f tailXImageMoved = tailXImage + deltaPhys;
+      Vector3f tailXSliceMoved = m_Parent->MapImageToSlice(tailXImageMoved);
+      Vector2f tailXPhysWinMoved = m_Parent->MapSliceToPhysicalWindow(tailXSliceMoved);
+      lm.Offset = tailXPhysWinMoved - m_Parent->MapSliceToPhysicalWindow(headXSlice);
+      }
+
+    lma->SetLandmark(lm);
+    }
+
+
+}
+
+annot::AbstractAnnotation *
+AnnotationModel::GetSelectedHandleUnderCusror(const Vector3d &xSlice, int &out_handle)
+{
+  // Get the annotation data
+  ImageAnnotationData *adata = this->GetAnnotations();
+
+  out_handle = -1;
+  for(ImageAnnotationData::AnnotationConstIterator it = adata->GetAnnotations().begin();
+      it != adata->GetAnnotations().end(); ++it)
+    {
+    if(this->IsAnnotationVisible(*it) && (*it)->GetSelected())
+      {
+      // Draw all the line segments
+      annot::LineSegmentAnnotation *lsa =
+          dynamic_cast<annot::LineSegmentAnnotation *>(it->GetPointer());
+      if(lsa)
+        {
+        // Draw the line
+        Vector3f p1 = m_Parent->MapImageToSlice(lsa->GetSegment().first);
+        Vector3f p2 = m_Parent->MapImageToSlice(lsa->GetSegment().second);
+
+        // Test if either of these points is close to the cursor
+        if(this->TestPointInClickRadius(to_float(xSlice), p1, 5))
+          out_handle = 0;
+        else if(this->TestPointInClickRadius(to_float(xSlice), p2, 5))
+          out_handle = 1;
+        }
+
+      annot::LandmarkAnnotation *lma =
+          dynamic_cast<annot::LandmarkAnnotation *>(it->GetPointer());
+      if(lma)
+        {
+        Vector3f xHeadSlice, xTailSlice;
+        annot::Landmark lm = lma->GetLandmark();
+        this->GetLandmarkArrowPoints(lm, xHeadSlice, xTailSlice);
+
+        // Test if either of these points is close to the cursor
+        if(this->TestPointInClickRadius(to_float(xSlice), xHeadSlice, 5))
+          out_handle = 0;
+        else if(this->TestPointInClickRadius(to_float(xSlice), xTailSlice, 5))
+          out_handle = 1;
+        }
+
+      if(out_handle >= 0)
+        return it->GetPointer();
+      }
+    }
+
+  return NULL;
+}
+
+bool AnnotationModel::CheckState(AnnotationModel::UIState state)
+{
+  switch(state)
+    {
+    case AnnotationModel::UIF_LINE_MODE:
+      return this->GetAnnotationMode() == ANNOTATION_RULER;
+      break;
+    case AnnotationModel::UIF_LANDMARK_MODE:
+      return this->GetAnnotationMode() == ANNOTATION_LANDMARK;
+      break;
+    case AnnotationModel::UIF_LINE_MODE_DRAWING:
+      // return this->IsDrawingRuler();
+      return this->GetFlagDrawingLine();
+      break;
+    case AnnotationModel::UIF_EDITING_MODE:
+      return this->GetAnnotationMode() == ANNOTATION_SELECT;
+      break;
+
+    }
+
+  return false;
+}
+
+bool AnnotationModel::IsHoveringOverAnnotation(const Vector3d &xSlice)
+{
+  return (this->GetAnnotationUnderCursor(xSlice) != NULL);
+}
+
+void AnnotationModel::GetLandmarkArrowPoints(const annot::Landmark &lm,
+                                             Vector3f &outHeadXSlice, Vector3f &outTailXSlice)
+{
+  // Get the head coordinates in slice units
+  outHeadXSlice = m_Parent->MapImageToSlice(lm.Pos);
+
+  // Get the tail coordinate in slice units
+  outTailXSlice = m_Parent->MapPhysicalWindowToSlice(
+        m_Parent->MapSliceToPhysicalWindow(outHeadXSlice) + lm.Offset);
+}
+
+AnnotationModel::AnnotationModel()
+{
+  m_FlagDrawingLine = false;
+  Rebroadcast(this, ModelUpdateEvent(), StateMachineChangeEvent());
+}
+
+AnnotationModel::~AnnotationModel()
+{
+
+}
diff --git a/GUI/Model/AnnotationModel.h b/GUI/Model/AnnotationModel.h
new file mode 100644
index 0000000..967f573
--- /dev/null
+++ b/GUI/Model/AnnotationModel.h
@@ -0,0 +1,149 @@
+#ifndef ANNOTATIONMODEL_H
+#define ANNOTATIONMODEL_H
+
+#include "AbstractModel.h"
+#include "PropertyModel.h"
+#include "SNAPCommon.h"
+#include "IRISException.h"
+#include "GlobalState.h"
+#include "ImageAnnotationData.h"
+
+#include <list>
+#include <utility>
+#include <set>
+
+class GenericSliceModel;
+
+
+/**
+ * @brief The UI model for slice annotation
+ */
+class AnnotationModel : public AbstractModel
+{
+public:
+
+  typedef annot::AbstractAnnotation AbstractAnnotation;
+  typedef annot::LineSegmentAnnotation LineSegmentAnnotation;
+  typedef annot::LandmarkAnnotation LandmarkAnnotation;
+
+  typedef annot::LineSegment LineSegment;
+
+  irisITKObjectMacro(AnnotationModel, AbstractModel)
+
+  // States
+  enum UIState {
+    UIF_LINE_MODE,
+    UIF_LINE_MODE_DRAWING,
+    UIF_LANDMARK_MODE,
+    UIF_EDITING_MODE
+  };
+
+
+  FIRES(StateMachineChangeEvent)
+
+  irisGetMacro(Parent, GenericSliceModel *)
+
+  void SetParent(GenericSliceModel *model);
+
+  /** Get the line drawing state */
+  irisGetMacro(FlagDrawingLine, bool)
+
+  /** Get the current line */
+  irisGetMacro(CurrentLine, const LineSegment &)
+
+  /** Whether we are moving something now */
+  irisIsMacro(MovingSelection)
+
+  /** Get the physical length of line segment */
+  double GetLineLength(const Vector3f &xSliceA, const Vector3f &xSliceB);
+
+  /** Get the physical length of current line */
+  double GetCurrentLineLength();
+
+  /** Get the length of the current line in logical (non-retina) screen pixel units */
+  double GetCurrentLineLengthInPixels();
+
+  /** Compute angle between two lines */
+  double GetAngleWithCurrentLine(const annot::LineSegmentAnnotation *lsa);
+
+  /** Helper function - get current annotation mode from GlobalState */
+  AnnotationMode GetAnnotationMode() const;
+
+  /** Helper function - get annotation data from IRISApplication */
+  ImageAnnotationData *GetAnnotations();
+
+  /** Test if an annotation is visible in this slice */
+  bool IsAnnotationVisible(const AbstractAnnotation *annot);
+
+
+  bool ProcessPushEvent(const Vector3d &xSlice, bool shift_mod);
+
+  bool ProcessMoveEvent(const Vector3d &xSlice, bool shift_mod, bool drag);
+
+  bool ProcessReleaseEvent(const Vector3d &xSlice, bool shift_mod);
+
+  bool IsDrawingRuler();
+
+  void AcceptLine();
+
+  void CancelLine();
+
+  void SelectAllOnSlice();
+
+  void DeleteSelectedOnSlice();
+
+  void GoToNextAnnotation();
+  void GoToPreviousAnnotation();
+
+  bool CheckState(UIState state);
+
+  bool IsHoveringOverAnnotation(const Vector3d &xSlice);
+
+  /** Set the text assigned to the current annotation */
+  irisGetSetMacro(CurrentAnnotationText, std::string)
+
+  Vector3f GetAnnotationCenter(const AbstractAnnotation *annot);
+
+  void GetLandmarkArrowPoints(const annot::Landmark &lm, Vector3f &outHeadXSlice, Vector3f &outTailXSlice);
+
+
+
+protected:
+
+  AnnotationModel();
+  virtual ~AnnotationModel();
+
+  // Parent model
+  GenericSliceModel *m_Parent;
+
+  // Current state for line drawing
+  bool m_FlagDrawingLine;
+  LineSegment m_CurrentLine;
+
+  // Motion-related variables
+  Vector3f m_DragStart, m_DragLast;
+  bool m_MovingSelection;
+  int m_MovingSelectionHandle;
+  annot::AbstractAnnotation *m_MovingSelectionHandleAnnot;
+
+  // Text assigned to the currently drawn annotation
+  std::string m_CurrentAnnotationText;
+
+  double GetDistanceToLine(const Vector3f &x1, const Vector3f &x2, const Vector3d &point);
+  double GetDistanceToLine(LineSegment &line, const Vector3d &point);
+  double GetPixelDistanceToAnnotation(const AbstractAnnotation *annot, const Vector3d &point);
+  void AdjustAngleToRoundDegree(LineSegment &ls, int n_degrees);
+  AbstractAnnotation *GetAnnotationUnderCursor(const Vector3d &xSlice);
+  void GoToNextOrPrevAnnotation(int direction);
+
+  annot::AbstractAnnotation *GetSelectedHandleUnderCusror(const Vector3d &xSlice, int &out_handle);
+
+  bool TestPointInClickRadius(const Vector3f &xClickSlice,
+                              const Vector3f &xPointSlice,
+                              int logical_pixels);
+
+  // Apply move command to annotation handle
+  void MoveAnnotationHandle(AbstractAnnotation *ann, int handle, const Vector3f &deltaPhys);
+};
+
+#endif // ANNOTATIONMODEL_H
diff --git a/GUI/Model/CursorInspectionModel.cxx b/GUI/Model/CursorInspectionModel.cxx
index 59de5ea..c0ad652 100644
--- a/GUI/Model/CursorInspectionModel.cxx
+++ b/GUI/Model/CursorInspectionModel.cxx
@@ -5,6 +5,7 @@
 #include "ColorLabelTable.h"
 #include "IntensityCurveModel.h"
 #include "ColorMapModel.h"
+#include "DisplayLayoutModel.h"
 
 #include <QtTableWidgetCoupling.h>
 
@@ -18,9 +19,8 @@
   data, so that we can see the values of all components at once.
   */
 CurrentVoxelInfoItemSetDomain
-::CurrentVoxelInfoItemSetDomain(
-    IRISApplication *app, int role_filter)
-  : Superclass(app, role_filter), m_Driver(app)
+::CurrentVoxelInfoItemSetDomain(GlobalUIModel *model, int role_filter)
+  : Superclass(model ? model->GetDriver() : NULL, role_filter), m_Model(model)
 {
 }
 
@@ -37,34 +37,38 @@ CurrentVoxelInfoItemSetDomain
   // Make sure that the layer is initialized
   if(it.GetLayer()->IsInitialized())
     {
-    // Get the cursor position
-    Vector3ui cursor = m_Driver->GetCursorPosition();
-
-    // Create a string output
-    std::ostringstream oss;
-
-    // Get the intensity or intensities that the user is seeing and the RGB
+    // Get the intensity under the cursor for this layer
     vnl_vector<double> v;
     ImageWrapperBase::DisplayPixelType disprgb;
     it.GetLayer()->GetVoxelUnderCursorDisplayedValueAndAppearance(v, disprgb);
 
-    // Print with varying degrees of precision
+    // Use good old sprintf!
+    char buffer[64];
+
     if(v.size() == 1)
       {
-      oss << std::setprecision(4);
-      oss << v[0];
+      sprintf(buffer, "%.4g", v[0]);
       }
     else if(v.size() == 3)
       {
-      oss << std::setprecision(2);
-      oss << v[0] << "," << v[1] << "," << v[2];
+      sprintf(buffer, "%.4g,%.4g,%.4g", v[0], v[1], v[2]);
       }
 
-    vox.IntensityValue = oss.str();
+    vox.IntensityValue = buffer;
 
     // Get the displayed color
     vox.Color = Vector3ui(disprgb[0], disprgb[1], disprgb[2]);
 
+    // Is the layer selected?
+    bool stacked = m_Model->GetDisplayLayoutModel()->GetSliceViewLayerLayoutModel()->GetValue() == LAYOUT_STACKED;
+    vox.isSelectedGroundLayer =
+        stacked && (
+          it.GetLayer()->GetUniqueId() ==
+          m_Driver->GetGlobalState()->GetSelectedLayerId());
+
+    // Is the layer sticky?
+    vox.isSticky = it.GetLayer()->IsSticky();
+
     // Return the description
     return vox;
     }
@@ -72,6 +76,8 @@ CurrentVoxelInfoItemSetDomain
     {
     vox.IntensityValue = "";
     vox.Color = Vector3ui(0);
+    vox.isSelectedGroundLayer = false;
+    vox.isSticky = false;
     }
 
   return vox;
@@ -104,7 +110,7 @@ void CursorInspectionModel::SetParentModel(GlobalUIModel *parent)
       OVERLAY_ROLE |
       SNAP_ROLE;
 
-  CurrentVoxelInfoItemSetDomain dom(app, role);
+  CurrentVoxelInfoItemSetDomain dom(parent, role);
   m_VoxelAtCursorModel->SetDomain(dom);
 
   // Make this model listen to events that affect its domain
@@ -117,6 +123,14 @@ void CursorInspectionModel::SetParentModel(GlobalUIModel *parent)
   m_VoxelAtCursorModel->Rebroadcast(
         app, WrapperMetadataChangeEvent(), DomainDescriptionChangedEvent());
 
+  m_VoxelAtCursorModel->Rebroadcast(
+        app->GetGlobalState()->GetSelectedLayerIdModel(),
+        ValueChangedEvent(), DomainDescriptionChangedEvent());
+
+  m_VoxelAtCursorModel->Rebroadcast(
+        m_Parent->GetDisplayLayoutModel()->GetSliceViewLayerLayoutModel(),
+        ValueChangedEvent(), DomainDescriptionChangedEvent());
+
   // Rebroadcast events from the parent as model update events. This could
   // have a little more granularity, but for the moment, mapping all these
   // events to a ModelUpdateEvent seems fine.
diff --git a/GUI/Model/CursorInspectionModel.h b/GUI/Model/CursorInspectionModel.h
index 9aa2f43..07e06a1 100644
--- a/GUI/Model/CursorInspectionModel.h
+++ b/GUI/Model/CursorInspectionModel.h
@@ -18,6 +18,8 @@ struct LayerCurrentVoxelInfo
   std::string LayerName;
   std::string IntensityValue;
   Vector3ui Color;
+  bool isSelectedGroundLayer;
+  bool isSticky;
 };
 
 /**
@@ -33,13 +35,13 @@ public:
 
   // Define the domain with the specificed filter
   CurrentVoxelInfoItemSetDomain(
-      IRISApplication *app = NULL, int role_filter = ALL_ROLES);
+      GlobalUIModel *model = NULL, int role_filter = ALL_ROLES);
 
   // Define the description method
   LayerCurrentVoxelInfo GetDescription(const LayerIterator &it) const;
 
 protected:
-  IRISApplication *m_Driver;
+  GlobalUIModel *m_Model;
 };
 
 // A concrete model encapsulating the above domain
diff --git a/GUI/Model/DisplayLayoutModel.cxx b/GUI/Model/DisplayLayoutModel.cxx
index 1867802..2b42bc9 100644
--- a/GUI/Model/DisplayLayoutModel.cxx
+++ b/GUI/Model/DisplayLayoutModel.cxx
@@ -2,6 +2,7 @@
 #include "GlobalUIModel.h"
 #include "IRISApplication.h"
 #include "GenericImageData.h"
+#include <algorithm>
 
 DisplayLayoutModel::DisplayLayoutModel()
 {
@@ -43,6 +44,17 @@ DisplayLayoutModel::DisplayLayoutModel()
   m_SliceViewLayerTilingModel->Rebroadcast(
         this, LayerLayoutChangeEvent(), ValueChangedEvent());
 
+  // The number of ground levels model
+  m_NumberOfGroundLevelLayersModel = wrapGetterSetterPairAsProperty(
+        this, &Self::GetNumberOfGroundLevelLayersValue);
+
+  // The derived model must react to changes to the internal values
+  m_NumberOfGroundLevelLayersModel->Rebroadcast(
+        this, LayerLayoutChangeEvent(), ValueChangedEvent());
+
+  // Thumbnail size
+  m_ThumbnailRelativeSizeModel = NewRangedConcreteProperty(16.0, 0.0, 40.0, 1.0);
+  Rebroadcast(m_ThumbnailRelativeSizeModel, ValueChangedEvent(), LayerLayoutChangeEvent());
 }
 
 void DisplayLayoutModel::SetParentModel(GlobalUIModel *parentModel)
@@ -76,6 +88,53 @@ DisplayLayoutModel::GetSliceViewLayerLayoutModel() const
   return m_ParentModel->GetGlobalState()->GetSliceViewLayerLayoutModel();
 }
 
+void DisplayLayoutModel::ToggleSliceViewLayerLayout()
+{
+  LayerLayout ll = this->GetSliceViewLayerLayoutModel()->GetValue();
+  if(ll == LAYOUT_TILED)
+    {
+    this->GetSliceViewLayerLayoutModel()->SetValue(LAYOUT_STACKED);
+    }
+  else
+    {
+    this->GetSliceViewLayerLayoutModel()->SetValue(LAYOUT_TILED);
+    }
+}
+
+void DisplayLayoutModel::ActivateNextLayerInTiledMode()
+{
+  // Make a list of ids that qualify
+  std::vector<unsigned long> ids;
+  this->GetGroundLevelLayerIds(ids);
+  if(ids.size() > 1)
+    {
+    std::vector<unsigned long>::iterator it =
+        std::find(ids.begin(), ids.end(), m_ParentModel->GetGlobalState()->GetSelectedLayerId());
+    if(it != ids.end())
+      {
+      std::rotate(ids.begin(), it, ids.end());
+      m_ParentModel->GetGlobalState()->SetSelectedLayerId(ids[1]);
+      }
+    }
+}
+
+void DisplayLayoutModel::ActivatePrevLayerInTiledMode()
+{
+  // Make a list of ids that qualify
+  std::vector<unsigned long> ids;
+  this->GetGroundLevelLayerIds(ids);
+  if(ids.size() > 1)
+    {
+    std::vector<unsigned long>::iterator it =
+        std::find(ids.begin(), ids.end(), m_ParentModel->GetGlobalState()->GetSelectedLayerId());
+    if(it != ids.end())
+      {
+      std::rotate(ids.begin(), it, ids.end());
+      m_ParentModel->GetGlobalState()->SetSelectedLayerId(ids.back());
+      }
+    }
+}
+
 bool DisplayLayoutModel
 ::GetNthViewPanelVisibilityValue(int panel, bool &value)
 {
@@ -196,6 +255,38 @@ void DisplayLayoutModel::UpdateSliceViewTiling()
     }
 }
 
+bool DisplayLayoutModel::GetNumberOfGroundLevelLayersValue(int &value)
+{
+  if(!m_ParentModel->GetDriver()->IsMainImageLoaded())
+    return false;
+
+  value = 0;
+  GenericImageData *id = m_ParentModel->GetDriver()->GetCurrentImageData();
+  for(LayerIterator it = id->GetLayers(); !it.IsAtEnd(); ++it)
+    {
+    if(it.GetRole() == MAIN_ROLE || !it.GetLayer()->IsSticky())
+      value++;
+    }
+
+  return true;
+}
+
+bool DisplayLayoutModel::GetGroundLevelLayerIds(std::vector<unsigned long> &ids)
+{
+  if(!m_ParentModel->GetDriver()->IsMainImageLoaded())
+    return false;
+
+  ids.clear();
+  GenericImageData *id = m_ParentModel->GetDriver()->GetCurrentImageData();
+  for(LayerIterator it = id->GetLayers(); !it.IsAtEnd(); ++it)
+    {
+    if(it.GetRole() == MAIN_ROLE || !it.GetLayer()->IsSticky())
+      ids.push_back(it.GetLayer()->GetUniqueId());
+    }
+
+  return true;
+}
+
 void DisplayLayoutModel::OnUpdate()
 {
   // If there has been a layer change event, we need to recompute the tiling
diff --git a/GUI/Model/DisplayLayoutModel.h b/GUI/Model/DisplayLayoutModel.h
index e784f8e..63814ae 100644
--- a/GUI/Model/DisplayLayoutModel.h
+++ b/GUI/Model/DisplayLayoutModel.h
@@ -45,7 +45,7 @@ public:
   void SetParentModel(GlobalUIModel *parentModel);
 
   /** Model managing the view panel layouts */
-  irisGetMacro(ViewPanelLayoutModel, AbstractViewPanelLayoutProperty *)
+  irisSimplePropertyAccessMacro(ViewPanelLayout, ViewPanelLayout)
 
   /**
    * Read-only boolean property models for the visibility of any specific
@@ -61,7 +61,24 @@ public:
    * on top of each other using transparency. Otherwise, each overlay is shown
    * in its own cell.
    */
-  irisGetMacro(SliceViewLayerTilingModel, AbstractSimpleUIntVec2Property *)
+  irisSimplePropertyAccessMacro(SliceViewLayerTiling, Vector2ui)
+
+  /**
+   * Model describing the number of 'ground-level' layers, i.e. layers that
+   * are drawn on their own, rather than overlayed on other layers
+   */
+  irisSimplePropertyAccessMacro(NumberOfGroundLevelLayers, int)
+
+  /**
+   * Get the list of ground level ids
+   */
+  bool GetGroundLevelLayerIds(std::vector<unsigned long> &ids);
+
+  /**
+   * Model describing the relative size of the thumbnails in thumbnail view,
+   * in percent.
+   */
+  irisRangedPropertyAccessMacro(ThumbnailRelativeSize, double)
 
   /**
    * A model for the layout of the layers in a slice view. This model sets
@@ -72,6 +89,17 @@ public:
   AbstractPropertyModel<LayerLayout, TrivialDomain> *GetSliceViewLayerLayoutModel() const;
 
   /**
+   * Toggle the stack/tiled state
+   */
+  void ToggleSliceViewLayerLayout();
+
+  /**
+   * Activate next or previous layer
+   */
+  void ActivateNextLayerInTiledMode();
+  void ActivatePrevLayerInTiledMode();
+
+  /**
    * Read-only boolean property models that dictate what icon should be
    * displayed in the expand/contract buttons in each slice view. There
    * are four of these models (one for each slice view), and they are of
@@ -104,6 +132,14 @@ protected:
   // The current tiling dimensons
   Vector2ui m_LayerTiling;
 
+  // The number of 'ground-level' layers, i.e. layers that are drawn on their own
+  // than overlayed on other layers
+  SmartPtr<AbstractSimpleIntProperty> m_NumberOfGroundLevelLayersModel;
+  bool GetNumberOfGroundLevelLayersValue(int &value);
+
+  // Thumbnail size
+  SmartPtr<ConcreteRangedDoubleProperty> m_ThumbnailRelativeSizeModel;
+
   virtual void OnUpdate();
 
   DisplayLayoutModel();
diff --git a/GUI/Model/GenericSliceModel.cxx b/GUI/Model/GenericSliceModel.cxx
index c90c673..8eb5b04 100644
--- a/GUI/Model/GenericSliceModel.cxx
+++ b/GUI/Model/GenericSliceModel.cxx
@@ -62,6 +62,15 @@ GenericSliceModel::GenericSliceModel()
         &Self::GetSliceIndexValueAndDomain,
         &Self::SetSlideIndexValue);
 
+  m_CurrentComponentInSelectedLayerModel =
+      wrapGetterSetterPairAsProperty(
+        this,
+        &Self::GetCurrentComponentInSelectedLayerValueAndDomain,
+        &Self::SetCurrentComponentInSelectedLayerValue);
+
+  // Nothing is hovered over
+  m_HoveredImageLayerIdModel = NewSimpleConcreteProperty(-1ul);
+  m_HoveredImageIsThumbnailModel = NewSimpleConcreteProperty(false);
 }
 
 void GenericSliceModel::Initialize(GlobalUIModel *model, int index)
@@ -87,6 +96,15 @@ void GenericSliceModel::Initialize(GlobalUIModel *model, int index)
   // Listen to cursor update events and rebroadcast them for the child model
   m_SliceIndexModel->Rebroadcast(model, CursorUpdateEvent(), ValueChangedEvent());
 
+  // Also listen for changes in the selected layer
+  AbstractSimpleULongProperty *selLayerModel = m_Driver->GetGlobalState()->GetSelectedLayerIdModel();
+  Rebroadcast(selLayerModel, ValueChangedEvent(), ModelUpdateEvent());
+
+  // The current component in selected layer model depends both on the selected model
+  // and on the layer metadata changes
+  m_CurrentComponentInSelectedLayerModel->Rebroadcast(selLayerModel, ValueChangedEvent(), DomainChangedEvent());
+  m_CurrentComponentInSelectedLayerModel->Rebroadcast(m_Driver, WrapperMetadataChangeEvent(), DomainChangedEvent());
+  m_CurrentComponentInSelectedLayerModel->Rebroadcast(model, LayerChangeEvent(), DomainChangedEvent());
 }
 
 void GenericSliceModel
@@ -121,6 +139,8 @@ void GenericSliceModel::OnUpdate()
           || m_EventBucket->HasEvent(DisplayLayoutModel::LayerLayoutChangeEvent())
           || m_EventBucket->HasEvent(ValueChangedEvent()))
     {
+    // Recompute the viewport layout and dimensions
+    this->UpdateViewportLayout();
 
     // We only react to the viewport resize if the zoom is not managed by the
     // coordinator. When zoom is managed, the coordinator will take care of
@@ -157,9 +177,7 @@ void GenericSliceModel::ComputeOptimalZoom()
   m_OptimalViewPosition = worldSize * 0.5f;
 
   // Reduce the width and height of the slice by the margin
-  Vector2ui size = this->GetSize();
-  Vector2i szCanvas =
-      Vector2i(size[0], size[1]) - Vector2i(2 * m_Margin);
+  Vector2ui szCanvas = this->GetCanvasSize();
 
   // Compute the ratios of window size to slice size
   Vector2f ratios(
@@ -220,6 +238,9 @@ GenericSliceModel
   // We have been initialized
   m_SliceInitialized = true;
 
+  // Update the viewport dimensions
+  UpdateViewportLayout();
+
   // Compute the optimal zoom for this slice
   ComputeOptimalZoom();
 
@@ -286,10 +307,10 @@ GenericSliceModel
     xSlice(0) * m_SliceSpacing(0),xSlice(1) * m_SliceSpacing(1));
 
   // Compute the window coordinates
-  Vector2ui size = this->GetSize();
+  Vector2ui size = this->GetCanvasSize();
   Vector2f uvWindow =
     m_ViewZoom * (uvScaled - m_ViewPosition) +
-      Vector2f(0.5f * size[0],0.5f * size[1]);
+      Vector2f(0.5f * size[0], 0.5f * size[1]);
 
   // That's it, the projection matrix is set up in the scaled-slice coordinates
   return uvWindow;
@@ -302,7 +323,7 @@ GenericSliceModel
   assert(IsSliceInitialized() && m_ViewZoom > 0);
 
   // Compute the scaled slice coordinates
-  Vector2ui size = this->GetSize();
+  Vector2ui size = this->GetCanvasSize();
   Vector2f winCenter(0.5f * size[0],0.5f * size[1]);
   Vector2f uvScaled =
     m_ViewPosition + (uvWindow - winCenter) / m_ViewZoom;
@@ -349,6 +370,20 @@ GenericSliceModel
   return uvPhysical;
 }
 
+Vector3f
+GenericSliceModel
+::MapPhysicalWindowToSlice(const Vector2f &uvPhysical)
+{
+  assert(IsSliceInitialized());
+
+  Vector3f xSlice;
+  xSlice[0] = uvPhysical[0] / m_SliceSpacing[0];
+  xSlice[1] = uvPhysical[1] / m_SliceSpacing[1];
+  xSlice[2] = this->GetCursorPositionInSliceCoordinates()[2];
+
+  return xSlice;
+}
+
 void
 GenericSliceModel
 ::ResetViewPosition()
@@ -414,6 +449,14 @@ void GenericSliceModel::CenterViewOnCursor()
   this->SetViewPositionRelativeToCursor(offset);
 }
 
+void GenericSliceModel::SetViewZoom(float zoom)
+{
+  assert(zoom > 0);
+  m_ViewZoom = zoom;
+  this->Modified();
+  this->InvokeEvent(SliceModelGeometryChangeEvent());
+}
+
 void GenericSliceModel::ZoomInOrOut(float factor)
 {
   float oldzoom = m_ViewZoom;
@@ -446,6 +489,19 @@ GenericSliceModel
   return gds->GetFlagDisplayZoomThumbnail() && (m_ViewZoom > m_OptimalZoom);
 }
 
+const SliceViewportLayout::SubViewport *GenericSliceModel::GetHoveredViewport()
+{
+  for(int i = 0; i < m_ViewportLayout.vpList.size(); i++)
+    {
+    const SliceViewportLayout::SubViewport *vpcand = &m_ViewportLayout.vpList[i];
+    if(vpcand->layer_id == this->GetHoveredImageLayerId()
+       && (vpcand->isThumbnail == this->GetHoveredImageIsThumbnail()))
+      return vpcand;
+    }
+
+  return NULL;
+}
+
 Vector3f GenericSliceModel::GetCursorPositionInSliceCoordinates()
 {
   Vector3ui cursorImageSpace = m_Driver->GetCursorPosition();
@@ -481,7 +537,7 @@ void GenericSliceModel::ComputeThumbnailProperties()
   float xThumbMax = gds->GetZoomThumbnailMaximumSize();
 
   // Recompute the fraction based on maximum size restriction
-  Vector2ui size = this->GetSize();
+  Vector2ui size = this->GetCanvasSize();
   float xNewFraction = xFraction;
   if( size[0] * xNewFraction > xThumbMax )
     xNewFraction = xThumbMax * 1.0f / size[0];
@@ -490,10 +546,10 @@ void GenericSliceModel::ComputeThumbnailProperties()
 
   // Set the position and size of the thumbnail, in pixels
   m_ThumbnailZoom = xNewFraction * m_OptimalZoom;
-  m_ThumbnailPosition.fill(5);
-  m_ThumbnailSize[0] =
+  m_ZoomThumbnailPosition.fill(5);
+  m_ZoomThumbnailSize[0] =
       (int)(m_SliceSize[0] * m_SliceSpacing[0] * m_ThumbnailZoom);
-  m_ThumbnailSize[1] =
+  m_ZoomThumbnailSize[1] =
       (int)(m_SliceSize[1] * m_SliceSpacing[1] * m_ThumbnailZoom);
 }
 
@@ -576,6 +632,64 @@ Vector2ui GenericSliceModel::GetSize()
   return Vector2ui(viewport[0] / cols, viewport[1] / rows);
 }
 
+Vector2ui GenericSliceModel::GetCanvasSize()
+{
+  assert(m_ViewportLayout.vpList.size() > 0);
+  assert(!m_ViewportLayout.vpList.front().isThumbnail);
+  return m_ViewportLayout.vpList.front().size;
+}
+
+void GenericSliceModel::GetNonThumbnailViewport(Vector2ui &pos, Vector2ui &size)
+{
+  // Initialize to the entire view
+  pos.fill(0);
+  size = m_SizeReporter->GetViewportSize();
+
+  DisplayLayoutModel *dlm = this->GetParentUI()->GetDisplayLayoutModel();
+  LayerLayout tiling = dlm->GetSliceViewLayerLayoutModel()->GetValue();
+
+  // Are thumbnails being used?
+  // TODO: this should be done through a state variable
+  if(tiling == LAYOUT_STACKED && dlm->GetNumberOfGroundLevelLayersModel()->GetValue() > 1)
+    {
+    for(int i = 0; i < m_ViewportLayout.vpList.size(); i++)
+      {
+      const SliceViewportLayout::SubViewport &sv = m_ViewportLayout.vpList[i];
+      if(!sv.isThumbnail)
+        {
+        pos = sv.pos;
+        size = sv.size;
+        break;
+        }
+      }
+    }
+}
+
+
+ImageWrapperBase *GenericSliceModel::GetThumbnailedLayerAtPosition(int x, int y)
+{
+  bool isThumb;
+  ImageWrapperBase *layer = this->GetContextLayerAtPosition(x, y, isThumb);
+  return isThumb ? layer : NULL;
+}
+
+ImageWrapperBase *GenericSliceModel::GetContextLayerAtPosition(int x, int y, bool &outIsThumbnail)
+{
+  x *= m_SizeReporter->GetViewportPixelRatio();
+  y *= m_SizeReporter->GetViewportPixelRatio();
+  for(int i = 0; i < m_ViewportLayout.vpList.size(); i++)
+    {
+    const SliceViewportLayout::SubViewport &sv = m_ViewportLayout.vpList[i];
+    if(x >= sv.pos[0] && y >= sv.pos[1]
+       && x < sv.pos[0] + sv.size[0] && y < sv.pos[1] + sv.size[1])
+      {
+      outIsThumbnail = sv.isThumbnail;
+      return m_Driver->GetCurrentImageData()->FindLayer(sv.layer_id, false);
+      }
+    }
+  return NULL;
+}
+
 
 bool GenericSliceModel
 ::GetSliceIndexValueAndDomain(int &value, NumericValueRange<int> *domain)
@@ -596,3 +710,211 @@ void GenericSliceModel::SetSlideIndexValue(int value)
   this->UpdateSliceIndex(value);
 }
 
+bool
+GenericSliceModel
+::GetCurrentComponentInSelectedLayerValueAndDomain(
+    unsigned int &value, NumericValueRange<unsigned int> *domain)
+{
+  // Make sure there is a layer selected and it's a multi-component layer
+  if(!m_Driver->IsMainImageLoaded())
+    return false;
+
+  ImageWrapperBase *layer =
+      m_Driver->GetCurrentImageData()->FindLayer(
+        m_Driver->GetGlobalState()->GetSelectedLayerId(), false);
+
+  if(!layer || layer->GetNumberOfComponents() <= 1)
+    return false;
+
+  // Make sure the display mode is to scroll through components
+  AbstractMultiChannelDisplayMappingPolicy *dpolicy =
+      static_cast<AbstractMultiChannelDisplayMappingPolicy *>(layer->GetDisplayMapping());
+
+  // Get the current display mode
+  MultiChannelDisplayMode mode = dpolicy->GetDisplayMode();
+
+  // Mode must be single component
+  if(!mode.IsSingleComponent())
+    return false;
+
+  // Finally we can return a value and range
+  value = mode.SelectedComponent;
+  if(domain)
+    domain->Set(0, layer->GetNumberOfComponents()-1, 1);
+
+  return true;
+}
+
+void GenericSliceModel::SetCurrentComponentInSelectedLayerValue(unsigned int value)
+{
+  // Get the target layer
+  ImageWrapperBase *layer =
+      m_Driver->GetCurrentImageData()->FindLayer(
+        m_Driver->GetGlobalState()->GetSelectedLayerId(), false);
+
+  assert(layer);
+
+  // Get the target policy
+  AbstractMultiChannelDisplayMappingPolicy *dpolicy =
+      static_cast<AbstractMultiChannelDisplayMappingPolicy *>(layer->GetDisplayMapping());
+  MultiChannelDisplayMode mode = dpolicy->GetDisplayMode();
+
+  assert(mode.IsSingleComponent());
+
+  // Update the mode
+  mode.SelectedComponent = value;
+  dpolicy->SetDisplayMode(mode);
+}
+
+void GenericSliceModel::UpdateViewportLayout()
+{
+  // Get the information about how the viewport is split into sub-viewports
+  DisplayLayoutModel *dlm = this->GetParentUI()->GetDisplayLayoutModel();
+  Vector2ui layout = dlm->GetSliceViewLayerTilingModel()->GetValue();
+  int nrows = (int) layout[0];
+  int ncols = (int) layout[1];
+
+  // Number of ground-level layers - together with the tiling, this determines
+  // the behavior of the display
+  int n_base_layers = dlm->GetNumberOfGroundLevelLayersModel()->GetValue();
+
+  // Get the dimensions of the main viewport (in real pixels, not logical pixels)
+  unsigned int w = m_SizeReporter->GetViewportSize()[0];
+  unsigned int h = m_SizeReporter->GetViewportSize()[1];
+
+  // Get the current image data
+  GenericImageData *id = this->GetDriver()->GetCurrentImageData();
+
+  // Clear the viewport array
+  m_ViewportLayout.vpList.clear();
+
+  // Is there anything to do?
+  if(!this->GetDriver()->IsMainImageLoaded())
+    return;
+
+  // Is tiling being used
+  if(nrows == 1 && ncols == 1)
+    {
+    // There is no tiling. One base layer is emphasized
+    if(n_base_layers == 1)
+      {
+      // There is only one base layer (main). It's viewport occupies the whole screen
+      SliceViewportLayout::SubViewport vp;
+      vp.pos = Vector2ui(0, 0);
+      vp.size = Vector2ui(w, h);
+      vp.isThumbnail = false;
+      vp.layer_id = id->GetMain()->GetUniqueId();
+      m_ViewportLayout.vpList.push_back(vp);
+      }
+    else
+      {
+      // We are in thumbnail mode. Draw the selected layer big and all the ground-level
+      // layers small, as thumbnails.
+      unsigned int margin = 4;
+
+      // The preferred width of the thumbnails (without margin)
+      int k = n_base_layers;
+
+      // This is a complicated calculation to make sure it all fits
+      double max_thumb_size = dlm->GetThumbnailRelativeSize() / 100.0;
+      double thumb_wd =
+          std::min(max_thumb_size * w - 2 * margin,
+                   (h - (1.0 + k) * margin) * (w - 2.0 * margin) / ((h - margin) * (1.0 + k)));
+
+      double thumb_hd = h * thumb_wd / (w - thumb_wd - 2.0 * margin);
+
+      // Round down the thumb sizes
+      unsigned int thumb_w = (unsigned int) thumb_wd;
+      unsigned int thumb_h = (unsigned int) thumb_hd;
+
+      // Set the bottom of the first thumbnail
+      unsigned int thumb_y = h - thumb_h - margin + 1;
+
+      // Go through eligible layers
+      for(LayerIterator it = id->GetLayers(); !it.IsAtEnd(); ++it)
+        {
+        if(it.GetRole() == MAIN_ROLE || !it.GetLayer()->IsSticky())
+          {
+          // Is this the visible layer?
+          if(this->GetDriver()->GetGlobalState()->GetSelectedLayerId()
+             == it.GetLayer()->GetUniqueId())
+            {
+            SliceViewportLayout::SubViewport vp;
+            vp.layer_id = it.GetLayer()->GetUniqueId();
+            vp.pos = Vector2ui(0, 0);
+            vp.size = Vector2ui(w - thumb_w - 2 * margin, h);
+            vp.isThumbnail = false;
+
+            // Notice we are sticking this viewport in the beginning! It's primary.
+            m_ViewportLayout.vpList.insert(m_ViewportLayout.vpList.begin(), vp);
+            }
+
+          // Either way, add the layer to the thumbnail region
+          SliceViewportLayout::SubViewport vp;
+          vp.layer_id = it.GetLayer()->GetUniqueId();
+          vp.pos = Vector2ui(w - thumb_w - margin, thumb_y);
+          vp.size = Vector2ui(thumb_w, thumb_h);
+          vp.isThumbnail = true;
+          m_ViewportLayout.vpList.push_back(vp);
+
+          thumb_y -= thumb_h + margin;
+          }
+        }
+      }
+    }
+  else
+    {
+    float cell_w = w / ncols;
+    float cell_h = h / nrows;
+    for(int irow = 0; irow < nrows; irow++)
+      for(int icol = 0; icol < ncols; icol++)
+        if(m_ViewportLayout.vpList.size() < n_base_layers)
+          {
+          SliceViewportLayout::SubViewport vp;
+          vp.pos = Vector2ui(icol * cell_w, (nrows - 1 - irow) * cell_h);
+          vp.size = Vector2ui(cell_w, cell_h);
+          vp.isThumbnail = false;
+          vp.layer_id = this->GetLayerForNthTile(irow, icol)->GetUniqueId();
+          m_ViewportLayout.vpList.push_back(vp);
+          }
+    }
+}
+
+ImageWrapperBase *GenericSliceModel::GetLayerForNthTile(int row, int col)
+{
+  // Number of divisions
+  DisplayLayoutModel *dlm = this->GetParentUI()->GetDisplayLayoutModel();
+  Vector2ui layout = dlm->GetSliceViewLayerTilingModel()->GetValue();
+  int nrows = (int) layout[0], ncols = (int) layout[1];
+
+  // This code is used if the layout is actually tiled
+  if(ncols > 1 || nrows > 1)
+    {
+    // How many layers to go until we get to the one we want to paint?
+    int togo = row * ncols + col;
+
+    // Skip all layers until we get to the sticky layer we want to paint
+    for(LayerIterator it(this->GetImageData()); !it.IsAtEnd(); ++it)
+      {
+      if(it.GetRole() == MAIN_ROLE || !it.GetLayer()->IsSticky())
+        {
+        if(togo == 0)
+          return it.GetLayer();
+        togo--;
+        }
+      }
+    }
+  else
+    {
+    for(LayerIterator it(this->GetImageData()); !it.IsAtEnd(); ++it)
+      {
+      if(it.GetLayer() && it.GetLayer()->GetUniqueId() ==
+         this->GetDriver()->GetGlobalState()->GetSelectedLayerId())
+        {
+        return it.GetLayer();
+        }
+      }
+    }
+
+  return NULL;
+}
diff --git a/GUI/Model/GenericSliceModel.h b/GUI/Model/GenericSliceModel.h
index 2e4ee24..fe232ab 100644
--- a/GUI/Model/GenericSliceModel.h
+++ b/GUI/Model/GenericSliceModel.h
@@ -47,6 +47,31 @@ itkEventMacro(SliceModelImageDimensionsChangeEvent, IRISEvent)
 itkEventMacro(SliceModelGeometryChangeEvent, IRISEvent)
 
 
+/**
+ * A structure describing viewport organization in a SNAP slice view.
+ * The viewport can be in a tiled state or in a main/thumbnail state.
+ *
+ * This class contains a list of viewports with corresponding IDs, as
+ * well as the 'primary' viewport, based on which zoom computations are
+ * made. The primary viewport is always the first viewport in the list
+ */
+struct SliceViewportLayout
+{
+public:
+  struct SubViewport {
+    // Size and position of the viewport
+    Vector2ui pos, size;
+
+    // Index of the associated image layer
+    unsigned long layer_id;
+
+    // Whether this is a thumbnail sub-view or a primary view
+    bool isThumbnail;
+  };
+
+  // List of subviewports
+  std::vector<SubViewport> vpList;
+};
 
 /**
   \class GenericSliceModel
@@ -131,6 +156,11 @@ public:
   Vector2f MapSliceToPhysicalWindow(const Vector3f &xSlice);
 
   /**
+   * Map a point in PHYISCAL window coordinates to a point in slice coordinates
+   */
+  Vector3f MapPhysicalWindowToSlice(const Vector2f &uvPhysical);
+
+  /**
    * Map a point in slice coordinates to a point in the image coordinates
    */
   Vector3f MapSliceToImage(const Vector3f &xSlice);
@@ -157,6 +187,12 @@ public:
   irisGetMacro(SliceIndexModel, AbstractRangedIntProperty *)
 
   /**
+   * Get the model than handles the selected component (timepoint) in the
+   * currently selected image
+   */
+  irisRangedPropertyAccessMacro(CurrentComponentInSelectedLayer, unsigned int)
+
+  /**
    * Set the index of the slice in the current view. This method will
    * update the cursor in the IRISApplication object
    */
@@ -187,7 +223,7 @@ public:
 
   /** Set the zoom factor (number of pixels on the screen per millimeter in
    * image space */
-  irisSetWithEventMacro(ViewZoom, float, SliceModelGeometryChangeEvent)
+  void SetViewZoom(float zoom);
 
   /**
    * Zoom in/out by a specified factor. This method will 'stop' at the optimal
@@ -226,6 +262,13 @@ public:
   /** Get the physical size of the window (updated from widget via events) */
   Vector2ui GetSize();
 
+  /**
+   * Get the size of the canvas on which the slice will be rendered. When the
+   * view is in tiled mode, this reports the size of one of the tiles. When the
+   * new is in main/thumbnail mode, this reports the size of the main view
+   */
+  Vector2ui GetCanvasSize();
+
   /** Has the slice model been initialized with image data? */
   irisIsMacro(SliceInitialized)
 
@@ -234,14 +277,40 @@ public:
 
   irisGetMacro(ImageData, GenericImageData *)
 
-  irisGetMacro(ThumbnailPosition, Vector2i)
-  irisGetMacro(ThumbnailSize, Vector2i)
+  irisGetMacro(ZoomThumbnailPosition, Vector2i)
+  irisGetMacro(ZoomThumbnailSize, Vector2i)
   irisGetMacro(ThumbnailZoom, float)
 
   irisGetMacro(ImageToDisplayTransform, const ImageCoordinateTransform &)
   irisGetMacro(DisplayToAnatomyTransform, const ImageCoordinateTransform &)
   irisGetMacro(DisplayToImageTransform, const ImageCoordinateTransform &)
 
+  irisGetMacro(ViewportLayout, const SliceViewportLayout &)
+
+  /**
+   * Get the viewport for decoration. This is either the entire viewport,
+   * or when the viewport is broken into thumbnail part and main part, the
+   * main part
+   */
+  void GetNonThumbnailViewport(Vector2ui &pos, Vector2ui &size);
+
+  /**
+   * Get the image layer for a context menu request, or NULL if requesting a
+   * context menu at a position should not be possible. TODO: this is kind of
+   * a weird place to house this code.
+   */
+  ImageWrapperBase *GetThumbnailedLayerAtPosition(int x, int y);
+
+  /**
+   * Get the layer that is in context for a position in the window. This can be
+   * a thumbnail layer or a regular layer. The third parameter is a boolean flag
+   * indicating whether the layer is a thumbnail or not.
+   */
+  ImageWrapperBase *GetContextLayerAtPosition(int x, int y, bool &outIsThumbnail);
+
+  /** Get the layer in a given tile, when using tiled views */
+  ImageWrapperBase *GetLayerForNthTile(int row, int col);
+
   /** Compute the canvas size needed to display slice at current zoom factor */
   Vector2i GetOptimalCanvasSize();
 
@@ -251,6 +320,15 @@ public:
   // Check whether the thumbnail should be drawn or not
   bool IsThumbnailOn();
 
+  /** A model representing the ID of the layer over which the mouse is hovering */
+  irisSimplePropertyAccessMacro(HoveredImageLayerId, unsigned long)
+
+  /** Whether the hovered image layer id is shown in thumbnail mode */
+  irisSimplePropertyAccessMacro(HoveredImageIsThumbnail, bool)
+
+  /** Get the viewport corresponding to the hovered layer */
+  const SliceViewportLayout::SubViewport *GetHoveredViewport();
+
   /**
     Merges a binary segmentation drawn on a slice into the main
     segmentation in SNAP. Returns the number of voxels changed.
@@ -260,6 +338,7 @@ public:
   unsigned int MergeSliceSegmentation(
         itk::Image<unsigned char, 2> *drawing);
 
+
 protected:
 
   GenericSliceModel();
@@ -274,9 +353,12 @@ protected:
   // Pointer to the image data
   GenericImageData *m_ImageData;
 
-  // Viewport size reporter
+  // Viewport size reporter (communicates with the UI about viewport size)
   ViewportSizeReporter *m_SizeReporter;
 
+  // Description of how the main viewport is divided into parts
+  SliceViewportLayout m_ViewportLayout;
+
   // Window id, equal to the direction in display space along which the
   // window shows slices
   int m_Id;
@@ -322,8 +404,9 @@ protected:
   // least in default zoom
   unsigned int m_Margin;
 
-  // The position and size of the zoom thumbnail
-  Vector2i m_ThumbnailPosition, m_ThumbnailSize;
+  // The position and size of the zoom thumbnail. These are in real pixel
+  // units on retina screens, not logical pixels.
+  Vector2i m_ZoomThumbnailPosition, m_ZoomThumbnailSize;
 
   // The zoom level in the thumbnail
   double m_ThumbnailZoom;
@@ -331,6 +414,10 @@ protected:
   // State of the model (whether it's been initialized)
   bool m_SliceInitialized;
 
+  /** Hovered over layer id */
+  SmartPtr<ConcreteSimpleULongProperty> m_HoveredImageLayerIdModel;
+  SmartPtr<ConcreteSimpleBooleanProperty> m_HoveredImageIsThumbnailModel;
+
   /** Access the next window in the slice pipeline */
   GenericSliceModel *GetNextSliceWindow();
 
@@ -338,6 +425,14 @@ protected:
   bool GetSliceIndexValueAndDomain(int &value, NumericValueRange<int> *domain);
   void SetSlideIndexValue(int value);
 
+  SmartPtr<AbstractRangedUIntProperty> m_CurrentComponentInSelectedLayerModel;
+  bool GetCurrentComponentInSelectedLayerValueAndDomain(unsigned int &value, NumericValueRange<unsigned int> *domain);
+  void SetCurrentComponentInSelectedLayerValue(unsigned int value);
+
+
+
+  /** Update the state of the viewport based on current layout settings */
+  void UpdateViewportLayout();
 };
 
 #endif // GENERICSLICEMODEL_H
diff --git a/GUI/Model/GlobalUIModel.cxx b/GUI/Model/GlobalUIModel.cxx
index feb7629..f2690d8 100644
--- a/GUI/Model/GlobalUIModel.cxx
+++ b/GUI/Model/GlobalUIModel.cxx
@@ -32,6 +32,7 @@
 #include <GenericSliceModel.h>
 #include <OrthogonalSliceCursorNavigationModel.h>
 #include <PolygonDrawingModel.h>
+#include <AnnotationModel.h>
 #include <SnakeROIModel.h>
 #include <SliceWindowCoordinator.h>
 #include <GenericImageData.h>
@@ -52,6 +53,7 @@
 #include <DisplayLayoutModel.h>
 #include <PaintbrushModel.h>
 #include <PaintbrushSettingsModel.h>
+#include "PolygonSettingsModel.h"
 #include <SynchronizationModel.h>
 #include <SnakeParameterModel.h>
 #include <SnakeROIResampleModel.h>
@@ -112,8 +114,16 @@ GlobalUIModel::GlobalUIModel()
 
     m_PaintbrushModel[i] = PaintbrushModel::New();
     m_PaintbrushModel[i]->SetParent(m_SliceModel[i]);
+
+    m_AnnotationModel[i] = AnnotationModel::New();
+    m_AnnotationModel[i]->SetParent(m_SliceModel[i]);
     }
 
+
+  // Polygon settings
+  m_PolygonSettingsModel = PolygonSettingsModel::New();
+  m_PolygonSettingsModel->SetParentModel(this);
+
   // Connect them together with the coordinator
   m_SliceCoordinator = SliceWindowCoordinator::New();
   m_SliceCoordinator->SetParentModel(this);
@@ -224,6 +234,13 @@ GlobalUIModel::GlobalUIModel()
   m_SnakeROISizeModel->Rebroadcast(
         m_Driver, MainImageDimensionsChangeEvent(), DomainChangedEvent());
 
+  m_SnakeROISeedWithCurrentSegmentationModel = wrapGetterSetterPairAsProperty(
+        this,
+        &Self::GetSnakeROISeedWithCurrentSegmentationValue,
+        &Self::SetSnakeROISeedWithCurrentSegmentationValue);
+
+  m_SnakeROISeedWithCurrentSegmentationModel->RebroadcastFromSourceProperty(
+        m_Driver->GetGlobalState()->GetSegmentationROISettingsModel());
 
   // Segmentation opacity models
   m_SegmentationOpacityModel = wrapGetterSetterPairAsProperty(
@@ -237,9 +254,6 @@ GlobalUIModel::GlobalUIModel()
   m_SegmentationVisibilityModel =
       NewNumericPropertyToggleAdaptor(m_SegmentationOpacityModel.GetPointer(), 0, 50);
 
-  // Simple toggle for whether controls for layer visibility and reorder are shown
-  m_LayerVisibilityEditableModel = NewSimpleConcreteProperty(false);
-
   // Listen to state changes from the slice coordinator
   Rebroadcast(m_SliceCoordinator, LinkedZoomUpdateEvent(), LinkedZoomUpdateEvent());
   Rebroadcast(m_SliceCoordinator, LinkedZoomUpdateEvent(), StateMachineChangeEvent());
@@ -251,6 +265,9 @@ GlobalUIModel::GlobalUIModel()
   Rebroadcast(m_Driver, LayerChangeEvent(), LayerChangeEvent());
   Rebroadcast(m_Driver, LayerChangeEvent(), StateMachineChangeEvent());
 
+  // Rebroadcast image layer change events
+  Rebroadcast(m_Driver, WrapperMetadataChangeEvent(), StateMachineChangeEvent());
+
   // Rebroadcast toolbar model change events (TODO: needed?)
   Rebroadcast(m_Driver->GetGlobalState()->GetToolbarModeModel(),
               ValueChangedEvent(), ToolbarModeChangeEvent());
@@ -275,6 +292,7 @@ GlobalUIModel::GlobalUIModel()
   progcmd->SetCallbackFunction(this, &GlobalUIModel::ProgressCallback);
   m_ProgressCommand = progcmd.GetPointer();
 
+
 }
 
 GlobalUIModel::~GlobalUIModel()
@@ -317,6 +335,17 @@ bool GlobalUIModel::CheckState(UIState state)
       return m_Driver->IsSnakeModeActive();
     case UIF_LEVEL_SET_ACTIVE:
       return m_Driver->IsSnakeModeLevelSetActive();
+    case UIF_MULTIPLE_BASE_LAYERS:
+      {
+      LayerIterator it = m_Driver->GetCurrentImageData()->GetLayers(
+                           MAIN_ROLE | OVERLAY_ROLE | SNAP_ROLE);
+      int n = 0;
+      for(; !it.IsAtEnd(); ++it)
+        if(it.GetLayer() && !it.GetLayer()->IsSticky())
+          ++n;
+
+      return n > 1;
+      }
     }
 
   return false;
@@ -352,19 +381,16 @@ void GlobalUIModel::ToggleOverlayVisibility()
 {
   // Are we in tiled mode or in stack mode?
   GenericImageData *id = m_Driver->GetCurrentImageData();
-  bool stack =
-      (m_DisplayLayoutModel->GetSliceViewLayerLayoutModel()->GetValue()
-       == LAYOUT_STACKED);
 
   // Remember what layer is current in the general properties model
   ImageWrapperBase *curr_layer = m_LayerGeneralPropertiesModel->GetLayer();
 
   // Apply the toggle for all overlays
-  for(LayerIterator it = id->GetLayers(OVERLAY_ROLE); !it.IsAtEnd(); ++it)
+  for(LayerIterator it = id->GetLayers(MAIN_ROLE | OVERLAY_ROLE | SNAP_ROLE); !it.IsAtEnd(); ++it)
     {
     // In stack mode, every overlay is affected. In tile mode, only stickly layers
     // are affected
-    if(stack || it.GetLayer()->IsSticky())
+    if(it.GetLayer()->IsSticky())
       {
       m_LayerGeneralPropertiesModel->SetLayer(it.GetLayer());
       m_LayerGeneralPropertiesModel->GetLayerVisibilityModel()->SetValue(
@@ -380,19 +406,16 @@ void GlobalUIModel::AdjustOverlayOpacity(int delta)
 {
   // Are we in tiled mode or in stack mode?
   GenericImageData *id = m_Driver->GetCurrentImageData();
-  bool stack =
-      (m_DisplayLayoutModel->GetSliceViewLayerLayoutModel()->GetValue()
-       == LAYOUT_STACKED);
 
   // Remember what layer is current in the general properties model
   ImageWrapperBase *curr_layer = m_LayerGeneralPropertiesModel->GetLayer();
 
   // Apply the toggle for all overlays
-  for(LayerIterator it = id->GetLayers(OVERLAY_ROLE); !it.IsAtEnd(); ++it)
+  for(LayerIterator it = id->GetLayers(MAIN_ROLE | OVERLAY_ROLE | SNAP_ROLE); !it.IsAtEnd(); ++it)
     {
     // In stack mode, every overlay is affected. In tile mode, only stickly layers
     // are affected
-    if(stack || it.GetLayer()->IsSticky())
+    if(it.GetLayer()->IsSticky())
       {
       m_LayerGeneralPropertiesModel->SetLayer(it.GetLayer());
       int op = m_LayerGeneralPropertiesModel->GetLayerOpacityModel()->GetValue();
@@ -643,6 +666,26 @@ void GlobalUIModel::SetSnakeROISizeValue(Vector3ui value)
   m_Driver->GetGlobalState()->SetSegmentationROI(roi);
 }
 
+bool GlobalUIModel::GetSnakeROISeedWithCurrentSegmentationValue(bool &value)
+{
+  // There has to be an image
+  if(!m_Driver->IsMainImageLoaded())
+    return false;
+
+  value = m_Driver->GetGlobalState()->GetSegmentationROISettings().IsSeedWithCurrentSegmentation();
+  return true;
+}
+
+void GlobalUIModel::SetSnakeROISeedWithCurrentSegmentationValue(bool value)
+{
+  SNAPSegmentationROISettings roi_settings =
+      m_Driver->GetGlobalState()->GetSegmentationROISettings();
+  roi_settings.SetSeedWithCurrentSegmentation(value);
+  m_Driver->GetGlobalState()->SetSegmentationROISettings(roi_settings);
+}
+
+
+
 bool
 GlobalUIModel::GetSegmentationOpacityValueAndRange(
     int &value, NumericValueRange<int> *domain)
@@ -665,11 +708,13 @@ void GlobalUIModel::SetSegmentationOpacityValue(int value)
 
 
 std::vector<std::string>
-GlobalUIModel::GetRecentHistoryItems(const char *historyCategory, unsigned int k)
+GlobalUIModel::GetRecentHistoryItems(const char *historyCategory, unsigned int k, bool global_history)
 {
   // Load the list of recent files from the history file
   const HistoryManager::HistoryListType &history =
-      this->GetSystemInterface()->GetHistoryManager()->GetGlobalHistory(historyCategory);
+      global_history
+      ? this->GetSystemInterface()->GetHistoryManager()->GetGlobalHistory(historyCategory)
+      : this->GetSystemInterface()->GetHistoryManager()->GetLocalHistory(historyCategory);
 
   std::vector<std::string> recent;
 
@@ -744,33 +789,9 @@ GlobalUIModel::CreateIOWizardModelForSave(ImageWrapperBase *layer, LayerRole rol
   SmartPtr<AbstractSaveImageDelegate> delegate =
       m_Driver->CreateSaveDelegateForLayer(layer, role);
 
-  // Figure out the category name
-  std::string category;
-  switch(role)
-    {
-    case MAIN_ROLE:
-      category = "Main Image";
-      break;
-    case OVERLAY_ROLE:
-      category = "Overlay Image";
-      break;
-    case SNAP_ROLE:
-      if(dynamic_cast<SpeedImageWrapper *>(layer))
-        category = "Speed Image";
-      else if(dynamic_cast<LevelSetImageWrapper *>(layer))
-        category = "Level Set Image";
-      break;
-    case LABEL_ROLE:
-      category = "Segmentation Image";
-      break;
-    case NO_ROLE:
-    case ALL_ROLES:
-      break;
-    }
-
   // Create a model for IO
   SmartPtr<ImageIOWizardModel> modelIO = ImageIOWizardModel::New();
-  modelIO->InitializeForSave(this, delegate, category.c_str());
+  modelIO->InitializeForSave(this, delegate, delegate->GetCategory().c_str());
 
   return modelIO;
 }
diff --git a/GUI/Model/GlobalUIModel.h b/GUI/Model/GlobalUIModel.h
index 249630b..e33af84 100644
--- a/GUI/Model/GlobalUIModel.h
+++ b/GUI/Model/GlobalUIModel.h
@@ -39,6 +39,7 @@ class SNAPAppearanceSettings;
 class GenericSliceModel;
 class OrthogonalSliceCursorNavigationModel;
 class PolygonDrawingModel;
+class AnnotationModel;
 class SliceWindowCoordinator;
 class GuidedNativeImageIO;
 class SystemInterface;
@@ -61,6 +62,7 @@ class ReorientImageModel;
 class DisplayLayoutModel;
 class PaintbrushModel;
 class PaintbrushSettingsModel;
+class PolygonSettingsModel;
 class LayerGeneralPropertiesModel;
 class SynchronizationModel;
 class SnakeParameterModel;
@@ -166,6 +168,12 @@ public:
     return m_PaintbrushModel[i];
   }
 
+  /** Get the annotation model for each slice */
+  AnnotationModel *GetAnnotationModel(unsigned int i) const
+  {
+    return m_AnnotationModel[i];
+  }
+
   /** Get the model for intensity curve navigation */
   irisGetMacro(IntensityCurveModel, IntensityCurveModel *)
 
@@ -202,6 +210,9 @@ public:
   /** Model for managing paintbrush settings */
   irisGetMacro(PaintbrushSettingsModel, PaintbrushSettingsModel *)
 
+  /** Model for managing polygon settings */
+  irisGetMacro(PolygonSettingsModel, PolygonSettingsModel *)
+
   /** Model for multi-session sync */
   irisGetMacro(SynchronizationModel, SynchronizationModel *)
 
@@ -234,15 +245,15 @@ public:
   irisGetMacro(SnakeROIIndexModel, AbstractRangedUIntVec3Property *)
   irisGetMacro(SnakeROISizeModel, AbstractRangedUIntVec3Property *)
 
+  /** Get the model for the snake mode segmentation carry over behavior */
+  irisSimplePropertyAccessMacro(SnakeROISeedWithCurrentSegmentation, bool)
+
   /** A model for overall segmentation opacity (int, range 0..100) */
   irisRangedPropertyAccessMacro(SegmentationOpacity, int)
 
   /** A model for the segmentation visibility on/off state */
   irisSimplePropertyAccessMacro(SegmentationVisibility, bool)
 
-  /** Whether layer visibility and organization properties are editable */
-  irisSimplePropertyAccessMacro(LayerVisibilityEditable, bool)
-
   /** Method to toggle overlay visibility (all or selected overlays) */
   void ToggleOverlayVisibility();
 
@@ -250,8 +261,8 @@ public:
   void AdjustOverlayOpacity(int delta);
 
   /** Get a list of k recent "things" that are tracked in history */
-  std::vector<std::string> GetRecentHistoryItems(
-      const char *historyCategory, unsigned int k = 5);
+  std::vector<std::string> GetRecentHistoryItems(const char *historyCategory,
+                                                 unsigned int k = 5, bool global_history = true);
 
   /** Check if a particular history is empty */
   bool IsHistoryEmpty(const char *historyCategory);
@@ -329,6 +340,9 @@ protected:
   // Models for paintbrush drawing
   SmartPtr<PaintbrushModel> m_PaintbrushModel[3];
 
+  // Models for annotation
+  SmartPtr<AnnotationModel> m_AnnotationModel[3];
+
   // Window coordinator
   SmartPtr<SliceWindowCoordinator> m_SliceCoordinator;
 
@@ -368,6 +382,9 @@ protected:
   // Paintbrush settings
   SmartPtr<PaintbrushSettingsModel> m_PaintbrushSettingsModel;
 
+  // Polygon settings
+  SmartPtr<PolygonSettingsModel> m_PolygonSettingsModel;
+
   // Synchronization
   SmartPtr<SynchronizationModel> m_SynchronizationModel;
 
@@ -397,6 +414,11 @@ protected:
       Vector3ui &value, NumericValueRange<Vector3ui> *range);
   void SetSnakeROISizeValue(Vector3ui value);
 
+  // What happens to segmentation on entering snake mode
+  SmartPtr<AbstractSimpleBooleanProperty> m_SnakeROISeedWithCurrentSegmentationModel;
+  bool GetSnakeROISeedWithCurrentSegmentationValue(bool &value);
+  void SetSnakeROISeedWithCurrentSegmentationValue(bool value);
+
   // The model for the mesh export wizard
   SmartPtr<MeshExportModel> m_MeshExportModel;
 
@@ -416,9 +438,6 @@ protected:
   SmartPtr<AbstractRangedIntProperty> m_SegmentationOpacityModel;
   SmartPtr<AbstractSimpleBooleanProperty> m_SegmentationVisibilityModel;
 
-  // Whether layer visibility and order are editable in the layer inspector
-  SmartPtr<ConcreteSimpleBooleanProperty> m_LayerVisibilityEditableModel;
-
   // Callbacks for the opacity model
   bool GetSegmentationOpacityValueAndRange(int &value, NumericValueRange<int> *domain);
   void SetSegmentationOpacityValue(int value);
diff --git a/GUI/Model/ImageIOWizardModel.cxx b/GUI/Model/ImageIOWizardModel.cxx
index b71e7eb..ac3f20d 100644
--- a/GUI/Model/ImageIOWizardModel.cxx
+++ b/GUI/Model/ImageIOWizardModel.cxx
@@ -6,6 +6,7 @@
 #include "ImageCoordinateGeometry.h"
 #include <itksys/SystemTools.hxx>
 #include "HistoryManager.h"
+#include "ColorMap.h"
 
 #include "IRISException.h"
 #include <sstream>
@@ -18,6 +19,51 @@ ImageIOWizardModel::ImageIOWizardModel()
   m_GuidedIO = NULL;
   m_LoadDelegate = NULL;
   m_SaveDelegate = NULL;
+  m_Overlay = false;
+  m_UseRegistration = false;
+  m_LoadedImage = NULL;
+
+  // Initialize various property models
+  m_StickyOverlayModel = wrapGetterSetterPairAsProperty(
+                           this,
+                           &Self::GetStickyOverlayValue,
+                           &Self::SetStickyOverlayValue);
+
+  m_StickyOverlayColorMapModel = wrapGetterSetterPairAsProperty(
+                                   this,
+                                   &Self::GetStickyOverlayColorMapValue,
+                                   &Self::SetStickyOverlayColorMapValue);
+
+  // Initialize the registration models
+
+  // Registration mode
+  RegistrationModeDomain reg_mode_domain;
+  reg_mode_domain[ImageRegistrationManager::RIGID] = "Rigid";
+  reg_mode_domain[ImageRegistrationManager::SIMILARITY] = "Rigid with uniform scaling";
+  reg_mode_domain[ImageRegistrationManager::AFFINE] = "Affine";
+  reg_mode_domain[ImageRegistrationManager::INITONLY] = "Initial alignment only";
+  m_RegistrationModeModel = NewConcreteProperty(ImageRegistrationManager::RIGID, reg_mode_domain);
+
+  // Registration metric
+  RegistrationMetricDomain reg_metric_domain;
+  reg_metric_domain[ImageRegistrationManager::NMI] = "Normalized mutual information";
+  reg_metric_domain[ImageRegistrationManager::NCC] = "Normalized cross-correlation";
+  reg_metric_domain[ImageRegistrationManager::SSD] = "Squared intensity difference";
+  m_RegistrationMetricModel = NewConcreteProperty(ImageRegistrationManager::NMI, reg_metric_domain);
+
+  // Registration initialization
+  RegistrationInitDomain reg_init_domain;
+  reg_init_domain[ImageRegistrationManager::HEADERS] = "Align based on image headers";
+  reg_init_domain[ImageRegistrationManager::CENTERS] = "Align image centers";
+  m_RegistrationInitModel = NewConcreteProperty(ImageRegistrationManager::HEADERS, reg_init_domain);
+
+  // Registration manager
+  m_RegistrationManager = ImageRegistrationManager::New();
+  Rebroadcast(m_RegistrationManager, itk::IterationEvent(), RegistrationProgressEvent());
+
+  // Optimization progress renderer
+  m_RegistrationProgressRenderer = OptimizationProgressRenderer::New();
+  m_RegistrationProgressRenderer->SetModel(this);
 }
 
 
@@ -35,6 +81,9 @@ ImageIOWizardModel
   m_LoadDelegate = NULL;
   m_SaveDelegate = delegate;
   m_SuggestedFilename = delegate->GetCurrentFilename();
+  m_UseRegistration = false;
+  m_Overlay = false;
+  m_LoadedImage = NULL;
 }
 
 void
@@ -51,6 +100,9 @@ ImageIOWizardModel
   m_GuidedIO = GuidedNativeImageIO::New();
   m_LoadDelegate = delegate;
   m_SaveDelegate = NULL;
+  m_UseRegistration = delegate->GetUseRegistration();
+  m_Overlay = delegate->IsOverlay();
+  m_LoadedImage = NULL;
 }
 
 ImageIOWizardModel::~ImageIOWizardModel()
@@ -270,9 +322,13 @@ ImageIOWizardModel::FileFormat ImageIOWizardModel::GetSelectedFormat()
   return GuidedNativeImageIO::GetFileFormat(m_Registry);
 }
 
+#include "GenericImageData.h"
 
 void ImageIOWizardModel::LoadImage(std::string filename)
 {
+  // There is no loaded image to start with
+  m_LoadedImage = NULL;
+
   try
   {
     // Clear the warnings
@@ -294,7 +350,8 @@ void ImageIOWizardModel::LoadImage(std::string filename)
     m_LoadDelegate->ValidateImage(m_GuidedIO, m_Warnings);
 
     // Update the application
-    m_LoadDelegate->UpdateApplicationWithImage(m_GuidedIO);
+    m_LoadedImage =
+        m_LoadDelegate->UpdateApplicationWithImage(m_GuidedIO);
 
     // Save the IO hints to the registry
     Registry regAssoc;
@@ -401,5 +458,68 @@ void ImageIOWizardModel::Finalize()
 {
 }
 
+void ImageIOWizardModel::PerformRegistration()
+{
+  m_RegistrationManager->PerformRegistration(m_Parent->GetDriver()->GetCurrentImageData(),
+                                             this->GetRegistrationMode(),
+                                             this->GetRegistrationMetric(),
+                                             this->GetRegistrationInit());
+}
+
+
+void ImageIOWizardModel::UpdateImageTransformFromRegistration()
+{
+  m_RegistrationManager->UpdateImageTransformFromRegistration(
+        m_Parent->GetDriver()->GetCurrentImageData());
+}
+
+double ImageIOWizardModel::GetRegistrationObjective()
+{
+  return m_RegistrationManager->GetRegistrationObjective();
+}
+
+bool ImageIOWizardModel::GetStickyOverlayValue(bool &value)
+{
+  // Make sure the image has already been loaded
+  if(!m_LoadedImage)
+    return false;
+
+  // Return the stickiness value
+  value = m_LoadedImage->IsSticky();
+  return true;
+}
+
+void ImageIOWizardModel::SetStickyOverlayValue(bool value)
+{
+  assert(m_LoadedImage);
+  m_LoadedImage->SetSticky(value);
+}
+
+bool ImageIOWizardModel::GetStickyOverlayColorMapValue(std::string &value)
+{
+  // Make sure the image has already been loaded
+  if(!m_LoadedImage || !m_LoadedImage->IsSticky())
+    return false;
+
+  // Get the display mapping policy (to get a color map)
+  ColorMap *cmap = m_LoadedImage->GetDefaultScalarRepresentation()->GetColorMap();
+  if(!cmap)
+    return false;
 
+  // Return the color map preset
+  value = ColorMap::GetPresetName(cmap->GetSystemPreset());
+  return true;
+}
+
+void ImageIOWizardModel::SetStickyOverlayColorMapValue(std::string value)
+{
+  assert(m_LoadedImage && m_LoadedImage->IsSticky());
 
+  ScalarImageWrapperBase *base = m_LoadedImage->GetDefaultScalarRepresentation();
+  for(int i = 0; i < ColorMap::COLORMAP_CUSTOM; i++)
+    if(value == ColorMap::GetPresetName((ColorMap::SystemPreset) i))
+      {
+      base->GetColorMap()->SetToSystemPreset((ColorMap::SystemPreset) i);
+      return;
+      }
+}
diff --git a/GUI/Model/ImageIOWizardModel.h b/GUI/Model/ImageIOWizardModel.h
index 3e04620..2ff4bf5 100644
--- a/GUI/Model/ImageIOWizardModel.h
+++ b/GUI/Model/ImageIOWizardModel.h
@@ -7,11 +7,14 @@
 #include "GuidedNativeImageIO.h"
 #include "Registry.h"
 #include "ImageIODelegates.h"
+#include "ImageRegistrationManager.h"
+#include "OptimizationProgressRenderer.h"
 
 class GlobalUIModel;
 
 namespace itk {
   class GDCMSeriesFileNames;
+  class FastMutexLock;
 }
 
 /**
@@ -28,6 +31,10 @@ public:
 
   irisITKObjectMacro(ImageIOWizardModel, AbstractModel)
 
+  itkEventMacro(RegistrationProgressEvent, IRISEvent)
+
+  FIRES(RegistrationProgressEvent)
+
   typedef GuidedNativeImageIO::FileFormat FileFormat;
   enum Mode { LOAD, SAVE };
 
@@ -191,6 +198,57 @@ public:
     */
   virtual void Finalize();
 
+  /**
+   * Set whether the IO module should use registration
+   */
+  irisGetMacro(UseRegistration, bool)
+
+  /**
+   * Is this an overlay?
+   */
+  irisIsMacro(Overlay)
+
+  /** Should the overlay be loaded as sticky */
+  irisSimplePropertyAccessMacro(StickyOverlay, bool)
+
+  /** Which is the colormap of the sticky overlay */
+  irisSimplePropertyAccessMacro(StickyOverlayColorMap, std::string)
+
+  // Registration mode typedefs
+  typedef ImageRegistrationManager::RegistrationMode RegistrationMode;
+  typedef ImageRegistrationManager::RegistrationMetric RegistrationMetric;
+  typedef ImageRegistrationManager::RegistrationInit RegistrationInit;
+
+  // Registration domains
+  typedef SimpleItemSetDomain<RegistrationMode, std::string> RegistrationModeDomain;
+  typedef SimpleItemSetDomain<RegistrationMetric, std::string> RegistrationMetricDomain;
+  typedef SimpleItemSetDomain<RegistrationInit, std::string> RegistrationInitDomain;
+
+  // Access to registration models
+  irisGenericPropertyAccessMacro(RegistrationMode, RegistrationMode, RegistrationModeDomain)
+  irisGenericPropertyAccessMacro(RegistrationMetric, RegistrationMetric, RegistrationMetricDomain)
+  irisGenericPropertyAccessMacro(RegistrationInit, RegistrationInit, RegistrationInitDomain)
+
+  /**
+   * Perform registration between loaded overlay and main image. This operation is meant to
+   * be executed in a separate thread. From time to time, it will place the registration
+   * results into a thread-safe variable and fire a progress event. Use the method
+   * UpdateImageTransformFromRegistration() to apply registration results to the displayed image
+   */
+  void PerformRegistration();
+
+  /**
+   * Apply the currently computed transform to the image being loaded - allowing the user to
+   * see the registration results on the fly
+   */
+  void UpdateImageTransformFromRegistration();
+
+  /** Get the value of the registration objective function */
+  double GetRegistrationObjective();
+
+  /** Get the progress renderer object */
+  irisGetMacro(RegistrationProgressRenderer, OptimizationProgressRenderer *)
+
 protected:
 
   // Standard ITK protected constructors
@@ -219,11 +277,45 @@ protected:
   // Registry containing auxiliary info
   Registry m_Registry;
 
+  // Whether the layer being loaded is an overlay
+  bool m_Overlay;
+
+  // Whether registration should be used to load this image
+  bool m_UseRegistration;
+
   // Suggested filename
   std::string m_SuggestedFilename;
 
   // DICOM support
   GuidedNativeImageIO::RegistryArray m_DicomContents;
+
+  // Overlay display behavior models
+  SmartPtr<AbstractSimpleBooleanProperty> m_StickyOverlayModel;
+  bool GetStickyOverlayValue(bool &value);
+  void SetStickyOverlayValue(bool value);
+
+  // Selected color map behavior model
+  SmartPtr<AbstractSimpleStringProperty> m_StickyOverlayColorMapModel;
+  bool GetStickyOverlayColorMapValue(std::string &value);
+  void SetStickyOverlayColorMapValue(std::string value);
+
+  // Registration models
+  typedef ConcretePropertyModel<RegistrationMode, RegistrationModeDomain> RegistrationModeModel;
+  typedef ConcretePropertyModel<RegistrationMetric, RegistrationMetricDomain> RegistrationMetricModel;
+  typedef ConcretePropertyModel<RegistrationInit, RegistrationInitDomain> RegistrationInitModel;
+
+  SmartPtr<RegistrationModeModel> m_RegistrationModeModel;
+  SmartPtr<RegistrationMetricModel> m_RegistrationMetricModel;
+  SmartPtr<RegistrationInitModel> m_RegistrationInitModel;
+
+  // Registration manager
+  SmartPtr<ImageRegistrationManager> m_RegistrationManager;
+
+  // Renderer used to plot the metric
+  SmartPtr<OptimizationProgressRenderer> m_RegistrationProgressRenderer;
+
+  // Pointer to the image layer that has been loaded
+  ImageWrapperBase *m_LoadedImage;
 };
 
 #endif // IMAGEIOWIZARDMODEL_H
diff --git a/GUI/Model/ImageRegistrationManager.cxx b/GUI/Model/ImageRegistrationManager.cxx
new file mode 100644
index 0000000..6fd24ae
--- /dev/null
+++ b/GUI/Model/ImageRegistrationManager.cxx
@@ -0,0 +1,175 @@
+#include "ImageRegistrationManager.h"
+#include "GenericImageData.h"
+
+#include <itkImageRegistrationMethodv4.h>
+#include <itkAffineTransform.h>
+#include <itkANTSNeighborhoodCorrelationImageToImageMetricv4.h>
+// #include <itkJointHistogramMutualInformationImageToImageMetricv4.h>
+#include <itkMattesMutualInformationImageToImageMetricv4.h>
+#include <itkMeanSquaresImageToImageMetricv4.h>
+#include <itkEuler3DTransform.h>
+#include <itkConjugateGradientLineSearchOptimizerv4.h>
+#include <itkRegistrationParameterScalesFromPhysicalShift.h>
+#include <itkFastMutexLock.h>
+
+#include <itkRecursiveGaussianImageFilter.h>
+
+ImageRegistrationManager::ImageRegistrationManager()
+{
+  m_RegistrationResultLock = itk::FastMutexLock::New();
+  m_RegistrationResult.Transform = TransformBase::New();
+}
+
+void ImageRegistrationManager::PerformRegistration(GenericImageData *imageData,
+                                                   RegistrationMode in_mode,
+                                                   RegistrationMetric in_metric,
+                                                   RegistrationInit in_init)
+{
+  // Get the things we will be registering
+  typedef itk::Image<float, 3> ImageType;
+
+  // The main image already loaded - this will be the fixed image
+  ImageWrapperBase *main = imageData->GetMain();
+  ImageWrapperBase *overlay = imageData->GetLastOverlay();
+
+  // Cast to floating point format
+  SmartPtr<ScalarImageWrapperBase::FloatImageSource> castMain =
+      main->GetDefaultScalarRepresentation()->CreateCastToFloatPipeline();
+
+  SmartPtr<ScalarImageWrapperBase::FloatImageSource> castOverlay =
+      overlay->GetDefaultScalarRepresentation()->CreateCastToFloatPipeline();
+
+  // Apply some default smoothing to the images, with standard deviation equal to twice
+  // the smallest image spacing
+  typedef itk::RecursiveGaussianImageFilter<ImageType, ImageType> SmoothFilter;
+  SmartPtr<SmoothFilter> smoothMain = SmoothFilter::New();
+  smoothMain->SetInput(castMain->GetOutput());
+  smoothMain->SetSigma(castMain->GetOutput()->GetSpacing().GetVnlVector().min_value() * 1.0);
+  smoothMain->InPlaceOn();
+
+  SmartPtr<SmoothFilter> smoothOverlay = SmoothFilter::New();
+  smoothOverlay->SetInput(castOverlay->GetOutput());
+  smoothOverlay->SetSigma(castOverlay->GetOutput()->GetSpacing().GetVnlVector().min_value() * 1.0);
+  smoothOverlay->InPlaceOn();
+
+  // Set up registration (for now, rigid is the default)
+  typedef itk::Euler3DTransform<double> TransformType;
+  typedef itk::ImageRegistrationMethodv4<ImageType, ImageType, TransformType> RegMethod;
+
+  // Set up the registration method
+  SmartPtr<RegMethod> method = RegMethod::New();
+
+  // Set the fixed and moving images
+  method->SetFixedImage(smoothMain->GetOutput());
+  method->SetMovingImage(smoothOverlay->GetOutput());
+
+  // Set the metric
+  typedef itk::MattesMutualInformationImageToImageMetricv4<ImageType, ImageType> MetricType;
+  SmartPtr<MetricType> metric = MetricType::New();
+
+  metric->SetNumberOfHistogramBins(32);
+  metric->SetUseMovingImageGradientFilter( false );
+  metric->SetUseFixedImageGradientFilter( false );
+  metric->SetUseFixedSampledPointSet( false );
+  metric->SetVirtualDomainFromImage(castMain->GetOutput());
+
+  method->SetMetric(metric);
+  method->SetMetricSamplingStrategy(RegMethod::REGULAR);
+  method->SetMetricSamplingPercentage(0.1);
+
+  // Set up the number of shrink levels
+  RegMethod::ShrinkFactorsArrayType shrinkArray(2);
+  shrinkArray[0] = 4;
+  shrinkArray[1] = 2;
+
+  method->SetNumberOfLevels(2);
+  method->SetShrinkFactorsPerLevel(shrinkArray);
+
+  RegMethod::SmoothingSigmasArrayType smoothArray(2);
+  smoothArray.fill(0.0);
+  method->SetSmoothingSigmasPerLevel(smoothArray);
+
+  // Set up the scales estimator
+  typedef itk::RegistrationParameterScalesFromPhysicalShift<MetricType> ScalesEstimatorType;
+  SmartPtr<ScalesEstimatorType> scalesEstimator = ScalesEstimatorType::New();
+  scalesEstimator->SetMetric( metric );
+  scalesEstimator->SetTransformForward( true );
+
+  // Set up the optimizer
+  typedef itk::ConjugateGradientLineSearchOptimizerv4Template<double> OptimizerType;
+  SmartPtr<OptimizerType> optimizer = OptimizerType::New();
+  optimizer->SetLowerLimit( 0 );
+  optimizer->SetUpperLimit( 2 );
+  optimizer->SetEpsilon( 0.2 );
+  optimizer->SetLearningRate( 0.25 );
+  optimizer->SetMaximumStepSizeInPhysicalUnits( 0.25 );
+  optimizer->SetNumberOfIterations( 1000 );
+  optimizer->SetScalesEstimator( scalesEstimator );
+  optimizer->SetDoEstimateScales( true );
+  optimizer->SetMinimumConvergenceValue( 1e-6 );
+  optimizer->SetConvergenceWindowSize( 10 );
+  optimizer->SetDoEstimateLearningRateAtEachIteration( true );
+  optimizer->SetDoEstimateLearningRateOnce( false );
+
+  // Set the optimizer
+  method->SetOptimizer(optimizer);
+
+  // Print out the optimizer status at every iteration.
+  typedef itk::MemberCommand<Self> CommandType;
+  SmartPtr<CommandType> command = CommandType::New();
+  command->SetCallbackFunction(this, &Self::OnRegistrationUpdate);
+  optimizer->AddObserver(itk::IterationEvent(), command);
+
+  // Perform registration
+  method->Update();
+}
+
+void
+ImageRegistrationManager
+::OnRegistrationUpdate(itk::Object *caller, const itk::EventObject &event)
+{
+  // Get the optimizer
+  OptimizerType *optimizer = static_cast<OptimizerType *>(caller);
+
+  // Obtain a lock on the registration result
+  m_RegistrationResultLock->Lock();
+
+  // Get the metric value
+  m_RegistrationResult.MetricValue = optimizer->GetValue();
+
+  // TODO: split by transform type!
+
+  // Get the parameters and convert them to a matrix
+  typedef itk::Euler3DTransform<double> TransformType;
+  SmartPtr<TransformType> transform = TransformType::New();
+  transform->SetParameters(optimizer->GetCurrentPosition());
+
+  m_RegistrationResult.Transform->SetMatrix(transform->GetMatrix());
+  m_RegistrationResult.Transform->SetOffset(transform->GetOffset());
+
+  // Release the lock on the registration result
+  m_RegistrationResultLock->Unlock();
+
+  // Fire an iteration event
+  InvokeEvent(itk::IterationEvent());
+}
+
+void ImageRegistrationManager::UpdateImageTransformFromRegistration(GenericImageData *imageData)
+{
+  // Make a copy of the registration result
+  m_RegistrationResultLock->Lock();
+  RegistrationResult result = m_RegistrationResult;
+  m_RegistrationResultLock->Unlock();
+
+  std::cout << "METRIC Value: " << result.MetricValue << std::endl;
+
+  // Apply the registration result to the data
+  imageData->GetLastOverlay()->SetITKTransform(
+        imageData->GetMain()->GetImageBase(), result.Transform);
+}
+
+double ImageRegistrationManager::GetRegistrationObjective()
+{
+  return m_RegistrationResult.MetricValue;
+}
+
diff --git a/GUI/Model/ImageRegistrationManager.h b/GUI/Model/ImageRegistrationManager.h
new file mode 100644
index 0000000..dcfe7a2
--- /dev/null
+++ b/GUI/Model/ImageRegistrationManager.h
@@ -0,0 +1,70 @@
+#ifndef IMAGEREGISTRATIONMANAGER_H
+#define IMAGEREGISTRATIONMANAGER_H
+
+#include "AbstractModel.h"
+#include "itkMatrixOffsetTransformBase.h"
+
+class GenericImageData;
+
+namespace itk {
+  class FastMutexLock;
+  template <class TFloat> class ConjugateGradientLineSearchOptimizerv4Template;
+  template <class TFloat, unsigned int VDim1, unsigned int VDim2> class MatrixOffsetTransformBase;
+}
+
+/**
+ * This class encapsulates the logic of rigid/affine image registration. It
+ * can perform registration and provide registration results.
+ */
+class ImageRegistrationManager : public AbstractModel
+{
+public:
+
+  irisITKObjectMacro(ImageRegistrationManager, AbstractModel)
+
+  // Registration enums
+  enum RegistrationMode { INITONLY = 0, RIGID, SIMILARITY, AFFINE, INVALID_MODE };
+  enum RegistrationMetric { NMI = 0, NCC, SSD, INVALID_METRIC };
+  enum RegistrationInit { HEADERS=0, CENTERS, INVALID_INIT };
+
+  // Perform registration with provided parameters
+  void PerformRegistration(GenericImageData *imageData,
+                           RegistrationMode mode,
+                           RegistrationMetric metric,
+                           RegistrationInit init);
+
+  // Update image data with the registration progress
+  void UpdateImageTransformFromRegistration(GenericImageData *imageData);
+
+  // Get the value of the objective function
+  double GetRegistrationObjective();
+
+protected:
+
+  ImageRegistrationManager();
+  ~ImageRegistrationManager() {}
+
+  void OnRegistrationUpdate(itk::Object *caller, const itk::EventObject &event);
+
+private:
+
+  // Registration typedefs
+  typedef itk::ConjugateGradientLineSearchOptimizerv4Template<double> OptimizerType;
+  typedef itk::MatrixOffsetTransformBase<double, 3, 3> TransformBase;
+
+  // Representation of the result of image registration
+  struct RegistrationResult {
+    double MetricValue;
+    SmartPtr<TransformBase> Transform;
+  };
+
+  // Thread-safe variable for storing registration results
+  RegistrationResult m_RegistrationResult;
+  SmartPtr<itk::FastMutexLock> m_RegistrationResultLock;
+
+  // Initial direction matrix of the image
+  vnl_matrix<double> m_InitialDirectionMatrix;
+  vnl_vector<double> m_InitialOrigin;
+};
+
+#endif // IMAGEREGISTRATIONMANAGER_H
diff --git a/GUI/Model/LayerGeneralPropertiesModel.cxx b/GUI/Model/LayerGeneralPropertiesModel.cxx
index cf8ea7c..8a8cc0a 100644
--- a/GUI/Model/LayerGeneralPropertiesModel.cxx
+++ b/GUI/Model/LayerGeneralPropertiesModel.cxx
@@ -45,6 +45,11 @@ LayerGeneralPropertiesModel::LayerGeneralPropertiesModel()
         &Self::GetNicknameValue,
         &Self::SetNicknameValue);
 
+  m_IsStickyModel = wrapGetterSetterPairAsProperty(
+        this,
+        &Self::GetIsStickyValue,
+        &Self::SetIsStickyValue);
+
 }
 
 LayerGeneralPropertiesModel::~LayerGeneralPropertiesModel()
@@ -114,6 +119,9 @@ bool LayerGeneralPropertiesModel::CheckState(LayerGeneralPropertiesModel::UIStat
   if(!m_Layer)
     return false;
 
+  // Defer to the row model when we can
+  LayerTableRowModel *row_model = this->GetSelectedLayerTableRowModel();
+
   switch(state)
     {
     case UIF_CAN_SWITCH_COMPONENTS:
@@ -125,11 +133,34 @@ bool LayerGeneralPropertiesModel::CheckState(LayerGeneralPropertiesModel::UIStat
       }
     case UIF_MULTICOMPONENT:
       return m_Layer->GetNumberOfComponents() > 1;
+
+    case UIF_IS_STICKINESS_EDITABLE:
+      return row_model->CheckState(LayerTableRowModel::UIF_PINNABLE)
+          || row_model->CheckState(LayerTableRowModel::UIF_UNPINNABLE);
+
+    case UIF_IS_OPACITY_EDITABLE:
+      return row_model->CheckState(LayerTableRowModel::UIF_OPACITY_EDITABLE);
+
+    case UIF_MOVABLE_UP:
+      return row_model->CheckState(LayerTableRowModel::UIF_MOVABLE_UP);
+
+    case UIF_MOVABLE_DOWN:
+      return row_model->CheckState(LayerTableRowModel::UIF_MOVABLE_DOWN);
     }
 
   return false;
 }
 
+void LayerGeneralPropertiesModel::MoveLayerUp()
+{
+  this->GetSelectedLayerTableRowModel()->MoveLayerUp();
+}
+
+void LayerGeneralPropertiesModel::MoveLayerDown()
+{
+  this->GetSelectedLayerTableRowModel()->MoveLayerDown();
+}
+
 bool LayerGeneralPropertiesModel
 ::GetDisplayModeValueAndRange(DisplayMode &value, DisplayModeDomain *domain)
 {
@@ -340,6 +371,25 @@ LayerGeneralPropertiesModel::GetLayerAsVector()
 }
 
 
+bool LayerGeneralPropertiesModel::GetIsStickyValue(bool &value)
+{
+  // Delegate to the row model for this
+  LayerTableRowModel *trm = GetSelectedLayerTableRowModel();
+  return trm ? trm->GetStickyModel()->GetValueAndDomain(value, NULL) : false;
+}
+
+void LayerGeneralPropertiesModel::SetIsStickyValue(bool value)
+{
+  // Delegate to the row model for this
+  LayerTableRowModel *trm = GetSelectedLayerTableRowModel();
+
+  // Calling this method will set the globally selected layer to the main layer
+  // because the globally selected layer cannot be sticky. However, we can still
+  // have a sticky layer selected in the layer inspector. So we override.
+  trm->GetStickyModel()->SetValue(value);  
+}
+
+
 AbstractMultiChannelDisplayMappingPolicy *
 LayerGeneralPropertiesModel::GetMultiChannelDisplayPolicy()
 {
diff --git a/GUI/Model/LayerGeneralPropertiesModel.h b/GUI/Model/LayerGeneralPropertiesModel.h
index 149c40d..49935fe 100644
--- a/GUI/Model/LayerGeneralPropertiesModel.h
+++ b/GUI/Model/LayerGeneralPropertiesModel.h
@@ -53,7 +53,11 @@ public:
   /** States for this model */
   enum UIState {
     UIF_MULTICOMPONENT,
-    UIF_CAN_SWITCH_COMPONENTS
+    UIF_CAN_SWITCH_COMPONENTS,
+    UIF_IS_STICKINESS_EDITABLE,
+    UIF_IS_OPACITY_EDITABLE,
+    UIF_MOVABLE_UP,
+    UIF_MOVABLE_DOWN
   };
 
   // Implementation of virtual functions from parent class
@@ -84,12 +88,19 @@ public:
   /** A model for the layer visibility on/off state */
   irisSimplePropertyAccessMacro(LayerVisibility, bool)
 
+  /** A model for the stickiness */
+  irisSimplePropertyAccessMacro(IsSticky, bool)
+
   /** A model for the filename */
   irisSimplePropertyAccessMacro(Filename, std::string)
 
   /** A model for the nickname */
   irisSimplePropertyAccessMacro(Nickname, std::string)
 
+  /** Move the layer up in the list */
+  void MoveLayerUp();
+  void MoveLayerDown();
+
 protected:
 
   LayerGeneralPropertiesModel();
@@ -128,6 +139,11 @@ protected:
   bool GetNicknameValue(std::string &value);
   void SetNicknameValue(std::string value);
 
+  // Stickiness
+  SmartPtr<AbstractSimpleBooleanProperty> m_IsStickyModel;
+  bool GetIsStickyValue(bool &value);
+  void SetIsStickyValue(bool value);
+
   // Get the current display settings
   VectorImageWrapperBase *GetLayerAsVector();
   AbstractMultiChannelDisplayMappingPolicy *GetMultiChannelDisplayPolicy();
diff --git a/GUI/Model/LayerTableRowModel.cxx b/GUI/Model/LayerTableRowModel.cxx
index 0232490..3d2425b 100644
--- a/GUI/Model/LayerTableRowModel.cxx
+++ b/GUI/Model/LayerTableRowModel.cxx
@@ -66,10 +66,15 @@ bool LayerTableRowModel::CheckState(UIState state)
     {
     // Opacity can be edited for all layers except the main image layer
     case LayerTableRowModel::UIF_OPACITY_EDITABLE:
-      return (m_LayerRole != MAIN_ROLE);
+      return (m_Layer->IsSticky());
 
+    // Pinnable means it's not sticky and may be overlayed (i.e., not main)
     case LayerTableRowModel::UIF_PINNABLE:
-      return (m_LayerRole != MAIN_ROLE && tiling);
+      return (m_LayerRole != MAIN_ROLE && !m_Layer->IsSticky());
+
+    // Unpinnable means it's not sticky and may be overlayed (i.e., not main)
+    case LayerTableRowModel::UIF_UNPINNABLE:
+      return (m_LayerRole != MAIN_ROLE && m_Layer->IsSticky());
 
     case LayerTableRowModel::UIF_MOVABLE_UP:
       return (m_LayerRole == OVERLAY_ROLE
@@ -167,6 +172,7 @@ void LayerTableRowModel::Initialize(GlobalUIModel *parentModel, ImageWrapperBase
               ValueChangedEvent(),
               StateMachineChangeEvent());
 
+  Rebroadcast(layer, WrapperMetadataChangeEvent(), StateMachineChangeEvent());
 }
 
 void LayerTableRowModel::MoveLayerUp()
@@ -190,6 +196,16 @@ bool LayerTableRowModel::IsMainLayer()
   return m_LayerRole == MAIN_ROLE;
 }
 
+void LayerTableRowModel::SetSelected(bool selected)
+{
+  // If the layer is selected and is not sticky, we set is as the currently visible
+  // layer in the render views
+  if(selected && !m_Layer->IsSticky())
+    {
+    m_ParentModel->GetGlobalState()->SetSelectedLayerId(m_Layer->GetUniqueId());
+    }
+}
+
 void LayerTableRowModel::CloseLayer()
 {
   // If this is an overlay, we unload it like this
@@ -221,6 +237,48 @@ void LayerTableRowModel::AutoAdjustContrast()
     }
 }
 
+#include "MomentTextures.h"
+
+void LayerTableRowModel::GenerateTextureFeatures()
+{
+  ScalarImageWrapperBase *scalar = dynamic_cast<ScalarImageWrapperBase *>(m_Layer);
+  if(scalar)
+    {
+    // Get the image out
+    SmartPtr<ScalarImageWrapperBase::CommonFormatImageType> common_rep =
+        scalar->GetCommonFormatImage();
+
+    /*
+    SmartPtr<ScalarImageWrapperBase::CommonFormatImageType> texture_image =
+        ScalarImageWrapperBase::CommonFormatImageType::New();
+
+    texture_image->CopyInformation(common_rep);
+    texture_image->SetRegions(common_rep->GetBufferedRegion());
+    texture_image->Allocate();*/
+
+    // Create a radius - hard-coded for now
+    itk::Size<3> radius; radius.Fill(2);
+
+    // Create a filter to generate textures
+    typedef AnatomicImageWrapperTraits<GreyType>::ImageType TextureImageType;
+    typedef bilwaj::MomentTextureFilter<
+        ScalarImageWrapperBase::CommonFormatImageType,
+        TextureImageType> MomentFilterType;
+
+    MomentFilterType::Pointer filter = MomentFilterType::New();
+    filter->SetInput(common_rep);
+    filter->SetRadius(radius);
+    filter->SetHighestDegree(3);
+    filter->Update();
+
+    // Create a new image wrapper
+    SmartPtr<AnatomicImageWrapper> newWrapper = AnatomicImageWrapper::New();
+    newWrapper->InitializeToWrapper(m_Layer, filter->GetOutput(), NULL, NULL);
+    newWrapper->SetDefaultNickname("Textures");
+    this->GetParentModel()->GetDriver()->AddDerivedOverlayImage(newWrapper);
+    }
+}
+
 std::string
 LayerTableRowModel::GetDisplayModeString(const MultiChannelDisplayMode &mode)
 {
@@ -233,18 +291,17 @@ LayerTableRowModel::GetDisplayModeString(const MultiChannelDisplayMode &mode)
   switch(mode.SelectedScalarRep)
     {
     case SCALAR_REP_COMPONENT:
-      oss << "Component ";
-      oss << (1 + mode.SelectedComponent);
+      oss << (1 + mode.SelectedComponent) << "/" << m_Layer->GetNumberOfComponents();
       return oss.str();
 
     case SCALAR_REP_MAGNITUDE:
-      return "Magnitude";
+      return "Mag";
 
     case SCALAR_REP_MAX:
-      return "Maximum";
+      return "Max";
 
     case SCALAR_REP_AVERAGE:
-      return "Average";
+      return "Avg";
 
     case NUMBER_OF_SCALAR_REPS:
       break;
@@ -343,16 +400,20 @@ void LayerTableRowModel::OnUpdate()
 
 bool LayerTableRowModel::GetLayerOpacityValueAndRange(int &value, NumericValueRange<int> *domain)
 {
-  if(!m_Layer) return false;
+  // For opacity to be defined, the layer must be sticky
+  if(!m_Layer || !m_Layer->IsSticky()) return false;
 
+  // Meaning of 'visible' is different for sticky and non-sticky layers
   value = (int)(100.0 * m_Layer->GetAlpha());
+
   if(domain)
     domain->Set(0, 100, 5);
+
   return true;
 }
-
-void LayerTableRowModel::SetLayerOpacityValue(int value)
+ void LayerTableRowModel::SetLayerOpacityValue(int value)
 {
+  assert(m_Layer && m_Layer->IsSticky());
   m_Layer->SetAlpha(value / 100.0);
 }
 
@@ -366,6 +427,12 @@ bool LayerTableRowModel::GetStickyValue(bool &value)
 
 void LayerTableRowModel::SetSticklyValue(bool value)
 {
+  // Make sure the selected ID is legitimate
+  if(m_ParentModel->GetGlobalState()->GetSelectedLayerId() == m_Layer->GetUniqueId())
+    {
+    m_ParentModel->GetGlobalState()->SetSelectedLayerId(
+          m_ParentModel->GetDriver()->GetCurrentImageData()->GetMain()->GetUniqueId());
+    }
   m_Layer->SetSticky(value);
 }
 
diff --git a/GUI/Model/LayerTableRowModel.h b/GUI/Model/LayerTableRowModel.h
index 01f8b1b..2ac37ce 100644
--- a/GUI/Model/LayerTableRowModel.h
+++ b/GUI/Model/LayerTableRowModel.h
@@ -60,6 +60,7 @@ public:
   enum UIState {
     UIF_OPACITY_EDITABLE,
     UIF_PINNABLE,
+    UIF_UNPINNABLE,
     UIF_MOVABLE_UP,
     UIF_MOVABLE_DOWN,
     UIF_CLOSABLE,
@@ -90,6 +91,11 @@ public:
   bool IsMainLayer();
 
   /**
+   * Mark the layer as selected
+   */
+  void SetSelected(bool selected);
+
+  /**
    * Close the current layer
    */
   void CloseLayer();
@@ -97,6 +103,12 @@ public:
   /** Auto-adjust contrast (via the IntensityCurveModel) */
   void AutoAdjustContrast();
 
+  /**
+   * Generate texture features from this layer
+   * TODO: this is a placeholder for the future more complex functionality
+   */
+  void GenerateTextureFeatures();
+
 
   typedef std::list<MultiChannelDisplayMode> DisplayModeList;
 
diff --git a/GUI/Model/NumericPropertyToggleAdaptor.h b/GUI/Model/NumericPropertyToggleAdaptor.h
index 97b899b..8bcc296 100644
--- a/GUI/Model/NumericPropertyToggleAdaptor.h
+++ b/GUI/Model/NumericPropertyToggleAdaptor.h
@@ -39,7 +39,7 @@ public:
 
   /** Set the default value when going from off state to on state */
   void SetDefaultOnValue(NumericValueType value)
-    { m_DefaultOnValue = value; }
+    { m_DefaultOnValue = value; m_LastOnValue = m_DefaultOnValue; }
 
   /** The default off value should be zero, but can be changed */
   void SetDefaultOffValue(NumericValueType value)
diff --git a/GUI/Model/OrthogonalSliceCursorNavigationModel.cxx b/GUI/Model/OrthogonalSliceCursorNavigationModel.cxx
index 9c19cbe..64e1a39 100644
--- a/GUI/Model/OrthogonalSliceCursorNavigationModel.cxx
+++ b/GUI/Model/OrthogonalSliceCursorNavigationModel.cxx
@@ -159,17 +159,17 @@ void OrthogonalSliceCursorNavigationModel
   m_Parent->GetDriver()->SetCursorPosition(xCrossClamped);
 }
 
-bool OrthogonalSliceCursorNavigationModel::CheckThumbnail(Vector2i xCanvas)
+bool OrthogonalSliceCursorNavigationModel::CheckZoomThumbnail(Vector2i xCanvas)
 {
   // Check if the event is inside of the thumbnail boundaries
-  Vector2i xThumb = m_Parent->GetThumbnailPosition();
-  Vector2i sThumb = m_Parent->GetThumbnailSize();
+  Vector2i xThumb = m_Parent->GetZoomThumbnailPosition();
+  Vector2i sThumb = m_Parent->GetZoomThumbnailSize();
   return (m_Parent->IsThumbnailOn() &&
     xCanvas[0] > xThumb[0] &&
     xCanvas[0] < xThumb[0] + sThumb[0] &&
     xCanvas[1] > xThumb[1] &&
           xCanvas[1] < xThumb[1] + sThumb[1]);
-  }
+}
 
 void OrthogonalSliceCursorNavigationModel
 ::ProcessThumbnailPanGesture(Vector2i uvOffset)
diff --git a/GUI/Model/OrthogonalSliceCursorNavigationModel.h b/GUI/Model/OrthogonalSliceCursorNavigationModel.h
index e1b3936..4c23cf5 100644
--- a/GUI/Model/OrthogonalSliceCursorNavigationModel.h
+++ b/GUI/Model/OrthogonalSliceCursorNavigationModel.h
@@ -68,7 +68,7 @@ public:
   void ProcessScrollGesture(float gLength);
 
   // Check if the user press position is inside the thumbnail
-  bool CheckThumbnail(Vector2i xCanvas);
+  bool CheckZoomThumbnail(Vector2i xCanvas);
 
   // Process pan operation (parameter is the gesture vector, i.e., mouse
   // drag or three-finger gesture)
diff --git a/GUI/Model/PaintbrushModel.cxx b/GUI/Model/PaintbrushModel.cxx
index 2182375..7a3b74a 100644
--- a/GUI/Model/PaintbrushModel.cxx
+++ b/GUI/Model/PaintbrushModel.cxx
@@ -152,6 +152,8 @@ PaintbrushModel::PaintbrushModel()
 {
   m_ReverseMode = false;
   m_Watershed = new BrushWatershedPipeline();
+  m_ContextLayerId = (unsigned long) -1;
+  m_IsEngaged = false;
 }
 
 PaintbrushModel::~PaintbrushModel()
@@ -241,26 +243,41 @@ bool PaintbrushModel::TestInside(const Vector3d &x, const PaintbrushSettings &ps
 
 bool
 PaintbrushModel
-::ProcessPushEvent(const Vector3f &xSlice, bool reverse_mode)
+::ProcessPushEvent(const Vector3f &xSlice, const Vector2ui &gridCell, bool reverse_mode)
 {
   // Get the paintbrush properties (TODO: should we own them?)
   PaintbrushSettings pbs =
       m_Parent->GetDriver()->GetGlobalState()->GetPaintbrushSettings();
 
-  // Compute the mouse position
-  ComputeMousePosition(xSlice);
+  // Store the unique ID of the layer in context
+  ImageWrapperBase *layer = m_Parent->GetLayerForNthTile(gridCell[0], gridCell[1]);
+  if(layer)
+    {
+    // Set the layer
+    m_ContextLayerId = layer->GetUniqueId();
+    m_IsEngaged = true;
 
-  // Check if the right button was pressed
-  ApplyBrush(reverse_mode, false);
+    // Compute the mouse position
+    ComputeMousePosition(xSlice);
 
-  // Store the reverse mode
-  m_ReverseMode = reverse_mode;
+    // Check if the right button was pressed
+    ApplyBrush(reverse_mode, false);
 
-  // Store this as the last apply position
-  m_LastApplyX = xSlice;
+    // Store the reverse mode
+    m_ReverseMode = reverse_mode;
 
-  // Eat the event unless cursor chasing is enabled
-  return pbs.chase ? 0 : 1;
+    // Store this as the last apply position
+    m_LastApplyX = xSlice;
+
+    // Eat the event unless cursor chasing is enabled
+    return pbs.chase ? 0 : 1;
+    }
+  else
+    {
+    m_ContextLayerId = (unsigned long) -1;
+    m_IsEngaged = false;
+    return 0;
+    }
 }
 
 bool
@@ -271,50 +288,59 @@ PaintbrushModel
   IRISApplication *driver = m_Parent->GetDriver();
   PaintbrushSettings pbs = driver->GetGlobalState()->GetPaintbrushSettings();
 
-  // The behavior is different for 'fast' regular brushes and adaptive brush. For the
-  // adaptive brush, dragging is disabled.
-  if(pbs.mode != PAINTBRUSH_WATERSHED || m_ReverseMode)
+  if(m_IsEngaged)
     {
-    // See how much we have moved since the last event. If we moved more than
-    // the value of the radius, we interpolate the path and place brush strokes
-    // along the path
-    if(pixelsMoved > pbs.radius)
+    // The behavior is different for 'fast' regular brushes and adaptive brush. For the
+    // adaptive brush, dragging is disabled.
+    if(pbs.mode != PAINTBRUSH_WATERSHED || m_ReverseMode)
       {
-      // Break up the path into steps
-      size_t nSteps = (int) ceil(pixelsMoved / pbs.radius);
-      for(size_t i = 0; i < nSteps; i++)
+      // See how much we have moved since the last event. If we moved more than
+      // the value of the radius, we interpolate the path and place brush strokes
+      // along the path
+      if(pixelsMoved > pbs.radius)
+        {
+        // Break up the path into steps
+        size_t nSteps = (int) ceil(pixelsMoved / pbs.radius);
+        for(size_t i = 0; i < nSteps; i++)
+          {
+          float t = (1.0 + i) / nSteps;
+          Vector3f X = t * m_LastApplyX + (1.0f - t) * xSlice;
+          ComputeMousePosition(X);
+          ApplyBrush(m_ReverseMode, true);
+          }
+        }
+      else
         {
-        float t = (1.0 + i) / nSteps;
-        Vector3f X = t * m_LastApplyX + (1.0f - t) * xSlice;
-        ComputeMousePosition(X);
+        // Find the pixel under the mouse
+        ComputeMousePosition(xSlice);
+
+        // Scan convert the points into the slice
         ApplyBrush(m_ReverseMode, true);
         }
-      }
-    else
-      {
-      // Find the pixel under the mouse
-      ComputeMousePosition(xSlice);
 
-      // Scan convert the points into the slice
-      ApplyBrush(m_ReverseMode, true);
+      // Store this as the last apply position
+      m_LastApplyX = xSlice;
       }
 
-    // Store this as the last apply position
-    m_LastApplyX = xSlice;
-    }
+    // If the mouse is being released, we need to commit the drawing
+    if(release)
+      {
+      driver->StoreUndoPoint("Drawing with paintbrush");
 
-  // If the mouse is being released, we need to commit the drawing
-  if(release)
-    {
-    driver->StoreUndoPoint("Drawing with paintbrush");
+      // TODO: this is ugly. The code for applying a brush should really be
+      // placed in the IRISApplication.
+      driver->InvokeEvent(SegmentationChangeEvent());
+
+      m_IsEngaged = false;
+      m_ContextLayerId = (unsigned long) -1;
+      }
 
-    // TODO: this is ugly. The code for applying a brush should really be
-    // placed in the IRISApplication.
-    driver->InvokeEvent(SegmentationChangeEvent());
+    // Eat the event unless cursor chasing is enabled
+    return pbs.chase ? 0 : 1;
     }
 
-  // Eat the event unless cursor chasing is enabled
-  return pbs.chase ? 0 : 1;
+  else
+    return 0;
 }
 
 bool PaintbrushModel::ProcessMouseMoveEvent(const Vector3f &xSlice)
@@ -399,9 +425,14 @@ PaintbrushModel::ApplyBrush(bool reverse_mode, bool dragging)
     {
     GenericImageData *gid = driver->GetCurrentImageData();
 
+    // Get the currently engaged layer
+    ImageWrapperBase *context_layer = gid->FindLayer(m_ContextLayerId, false);
+    if(!context_layer)
+      context_layer = gid->GetMain();
+
     // Precompute the watersheds
     m_Watershed->PrecomputeWatersheds(
-          gid->GetMain()->GetDefaultScalarRepresentation()->GetCommonFormatImage(),
+          context_layer->GetDefaultScalarRepresentation()->GetCommonFormatImage(),
           driver->GetCurrentImageData()->GetSegmentation()->GetImage(),
           xTestRegion, to_itkIndex(m_MousePosition), pbs.watershed.smooth_iterations);
 
diff --git a/GUI/Model/PaintbrushModel.h b/GUI/Model/PaintbrushModel.h
index fee5ff5..c663550 100644
--- a/GUI/Model/PaintbrushModel.h
+++ b/GUI/Model/PaintbrushModel.h
@@ -22,7 +22,7 @@ public:
 
   FIRES(PaintbrushMovedEvent)
 
-  bool ProcessPushEvent(const Vector3f &xSlice, bool reverse_mode);
+  bool ProcessPushEvent(const Vector3f &xSlice, const Vector2ui &gridCell, bool reverse_mode);
   bool ProcessDragEvent(const Vector3f &xSlice, const Vector3f &xSliceLast,
                         double pixelsMoved, bool release);
 
@@ -49,6 +49,12 @@ protected:
   // next segment
   Vector3f m_LastApplyX;
 
+  // Layer over which the drawing operation started
+  unsigned long m_ContextLayerId;
+
+  // Whether the push operation was in a paintable location
+  bool m_IsEngaged;
+
   PaintbrushModel();
   virtual ~PaintbrushModel();
 
diff --git a/GUI/Model/PolygonDrawingModel.cxx b/GUI/Model/PolygonDrawingModel.cxx
index 6e5e416..3e60b5f 100644
--- a/GUI/Model/PolygonDrawingModel.cxx
+++ b/GUI/Model/PolygonDrawingModel.cxx
@@ -29,10 +29,12 @@ PolygonDrawingModel
   m_State = INACTIVE_STATE;
   m_SelectedVertices = false;
   m_DraggingPickBox = false;
-  m_FreehandFittingRate = 8;
   m_StartX = 0; m_StartY = 0;
   m_PolygonSlice = PolygonSliceType::New();
   m_HoverOverFirstVertex = false;
+
+  m_FreehandFittingRateModel = NewRangedConcreteProperty(8.0, 0.0, 100.0, 1.0);
+
 }
 
 PolygonDrawingModel
@@ -44,8 +46,9 @@ PolygonDrawingModel
 Vector2f
 PolygonDrawingModel::GetPixelSize()
 {
+  float vppr = m_Parent->GetSizeReporter()->GetViewportPixelRatio();
   Vector3f x =
-    m_Parent->MapWindowToSlice(Vector2f(1.0f)) -
+    m_Parent->MapWindowToSlice(Vector2f(vppr)) -
     m_Parent->MapWindowToSlice(Vector2f(0.0f));
 
   return Vector2f(x[0],x[1]);
@@ -196,7 +199,7 @@ PolygonDrawingModel
       ProcessMouseMoveEvent(x, y);
 
       // Check if a point should be added here
-      if(m_FreehandFittingRate == 0)
+      if(this->GetFreehandFittingRate() == 0)
         {
         m_Vertices.push_back(Vertex(x,y,false,false));
         }
@@ -207,7 +210,7 @@ PolygonDrawingModel
         double dx = (v.x-x) / pxsize[0];
         double dy = (v.y-y) / pxsize[1];
         double d = dx*dx+dy*dy;
-        if(d >= m_FreehandFittingRate * m_FreehandFittingRate)
+        if(d >= this->GetFreehandFittingRate() * this->GetFreehandFittingRate())
           m_Vertices.push_back(Vertex(x,y,false,true));
         }
       }
@@ -489,7 +492,7 @@ PolygonDrawingModel
 ::ProcessFreehandCurve()
 {
   // Special case: no fitting
-  if(m_FreehandFittingRate == 0.0)
+  if(this->GetFreehandFittingRate() == 0.0)
     {
     for(VertexIterator it = m_DragVertices.begin();
       it != m_DragVertices.end(); ++it)
@@ -538,7 +541,7 @@ PolygonDrawingModel
     }
 
   // Compute the number of control points
-  size_t nctl = (size_t)ceil(len / m_FreehandFittingRate);
+  size_t nctl = (size_t)ceil(len / this->GetFreehandFittingRate());
   if(nctl < 3)
     nctl = 3;
 
diff --git a/GUI/Model/PolygonDrawingModel.h b/GUI/Model/PolygonDrawingModel.h
index 612bd55..18498ca 100644
--- a/GUI/Model/PolygonDrawingModel.h
+++ b/GUI/Model/PolygonDrawingModel.h
@@ -2,6 +2,7 @@
 #define POLYGONDRAWINGMODEL_H
 
 #include "AbstractModel.h"
+#include "PropertyModel.h"
 #include <SNAPCommon.h>
 #include <IRISException.h>
 
@@ -96,8 +97,7 @@ public:
   irisGetMacro(CachedPolygon,bool)
 
   /** Set the accuracy of freehand curve fitting */
-  irisGetMacro(FreehandFittingRate, double)
-  irisSetMacro(FreehandFittingRate, double)
+  irisRangedPropertyAccessMacro(FreehandFittingRate, double)
 
   /** Access to the vertices */
   irisGetMacro(Vertices, const VertexList &)
@@ -127,6 +127,10 @@ public:
 
   bool ProcessReleaseEvent(float x, float y);
 
+  /**
+   * Return the size of a screen logical pixel (as opposed to a physical
+   * pixel on the retina screen) in slice coordinate units
+   */
   Vector2f GetPixelSize();
 
   bool CheckState(PolygonDrawingUIState state);
@@ -179,7 +183,8 @@ protected:
 
   void SetState(PolygonState state);
 
-  double m_FreehandFittingRate;
+  // Freehand fitting rate
+  SmartPtr<ConcreteRangedDoubleProperty> m_FreehandFittingRateModel;
 
   // Type definition for the slice used for polygon rendering
   typedef itk::Image<unsigned char,2> PolygonSliceType;
diff --git a/GUI/Model/PolygonSettingsModel.cxx b/GUI/Model/PolygonSettingsModel.cxx
new file mode 100644
index 0000000..e43eb38
--- /dev/null
+++ b/GUI/Model/PolygonSettingsModel.cxx
@@ -0,0 +1,82 @@
+#include "PolygonSettingsModel.h"
+#include "GlobalUIModel.h"
+#include "PolygonDrawingModel.h"
+#include "NumericPropertyToggleAdaptor.h"
+
+void PolygonSettingsModel::SetParentModel(GlobalUIModel *model)
+{
+  m_ParentModel = model;
+
+  m_FreehandSegmentLengthModel->RebroadcastFromSourceProperty(
+        m_ParentModel->GetPolygonDrawingModel(0)->GetFreehandFittingRateModel());
+
+  m_FreehandIsPiecewiseModel->RebroadcastFromSourceProperty(
+        m_ParentModel->GetPolygonDrawingModel(0)->GetFreehandFittingRateModel());
+
+}
+
+PolygonSettingsModel::PolygonSettingsModel()
+{
+  m_ParentModel = NULL;
+
+  m_FreehandSegmentLengthModel = wrapGetterSetterPairAsProperty(
+        this,
+        &Self::GetFreehandSegmentLengthValueAndRange,
+        &Self::SetFreehandSegmentLengthValue);
+
+  m_FreehandIsPiecewiseModel = wrapGetterSetterPairAsProperty(
+        this,
+        &Self::GetFreehandIsPiecewiseValue,
+        &Self::SetFreehandIsPiecewiseValue);
+}
+
+bool PolygonSettingsModel::GetFreehandIsPiecewiseValue(bool &value)
+{
+  if(!m_ParentModel)
+    return false;
+
+  int rate = (int) m_ParentModel->GetPolygonDrawingModel(0)->GetFreehandFittingRate();
+  value = (rate != 0);
+
+  return true;
+}
+
+void PolygonSettingsModel::SetFreehandIsPiecewiseValue(bool value)
+{
+  int rate = (int) m_ParentModel->GetPolygonDrawingModel(0)->GetFreehandFittingRate();
+  if(value)
+    {
+    for(int i = 0; i < 3; i++)
+      m_ParentModel->GetPolygonDrawingModel(i)->SetFreehandFittingRate(m_LastFreehandRate);
+    }
+  else
+    {
+    m_LastFreehandRate = rate;
+    for(int i = 0; i < 3; i++)
+      m_ParentModel->GetPolygonDrawingModel(i)->SetFreehandFittingRate(0.0);
+    }
+}
+
+bool PolygonSettingsModel
+::GetFreehandSegmentLengthValueAndRange(int &value, NumericValueRange<int> *range)
+{
+  if(!m_ParentModel)
+    return false;
+
+  value = (int) m_ParentModel->GetPolygonDrawingModel(0)->GetFreehandFittingRate();
+  if(value == 0)
+    value = m_LastFreehandRate;
+
+  if(range)
+    range->Set(1, 20, 1);
+
+  return true;
+}
+
+void PolygonSettingsModel::SetFreehandSegmentLengthValue(int value)
+{
+  for(int i = 0; i < 3; i++)
+    m_ParentModel->GetPolygonDrawingModel(i)->SetFreehandFittingRate(value);
+}
+
+
diff --git a/GUI/Model/PolygonSettingsModel.h b/GUI/Model/PolygonSettingsModel.h
new file mode 100644
index 0000000..ac12414
--- /dev/null
+++ b/GUI/Model/PolygonSettingsModel.h
@@ -0,0 +1,41 @@
+#ifndef POLYGONSETTINGSMODEL_H
+#define POLYGONSETTINGSMODEL_H
+
+#include "PropertyModel.h"
+
+class GlobalUIModel;
+
+class PolygonSettingsModel : public AbstractModel
+{
+public:
+  irisITKObjectMacro(PolygonSettingsModel, AbstractModel)
+
+  irisGetMacro(ParentModel, GlobalUIModel *)
+
+  void SetParentModel(GlobalUIModel *model);
+
+  irisSimplePropertyAccessMacro(FreehandIsPiecewise, bool)
+  irisRangedPropertyAccessMacro(FreehandSegmentLength, int)
+
+protected:
+
+  PolygonSettingsModel();
+  virtual ~PolygonSettingsModel() {}
+
+  GlobalUIModel *m_ParentModel;
+
+  SmartPtr<AbstractSimpleBooleanProperty> m_FreehandIsPiecewiseModel;
+  bool GetFreehandIsPiecewiseValue(bool &value);
+  void SetFreehandIsPiecewiseValue(bool value);
+
+  SmartPtr<AbstractRangedIntProperty> m_FreehandSegmentLengthModel;
+  bool GetFreehandSegmentLengthValueAndRange(int &value, NumericValueRange<int> *range);
+  void SetFreehandSegmentLengthValue(int value);
+
+private:
+
+  int m_LastFreehandRate;
+
+};
+
+#endif // POLYGONSETTINGSMODEL_H
diff --git a/GUI/Model/SnakeWizardModel.cxx b/GUI/Model/SnakeWizardModel.cxx
index 865d28e..cd9d60a 100644
--- a/GUI/Model/SnakeWizardModel.cxx
+++ b/GUI/Model/SnakeWizardModel.cxx
@@ -15,6 +15,7 @@
 #include "RFClassificationEngine.h"
 #include "RandomForestClassifier.h"
 #include "RandomForestClassifyImageFilter.h"
+#include "NumericPropertyToggleAdaptor.h"
 
 SnakeWizardModel::SnakeWizardModel()
 {
@@ -159,17 +160,49 @@ SnakeWizardModel::SnakeWizardModel()
         GMMModifiedEvent(),
         GMMModifiedEvent());
 
-  m_ForegroundClassColorLabelModel = wrapGetterSetterPairAsProperty(
+  m_ForestSizeModel = wrapGetterSetterPairAsProperty(
         this,
-        &Self::GetForegroundClassColorLabelValueAndRange,
-        &Self::SetForegroundClassColorLabelValue,
+        &Self::GetForestSizeValueAndRange,
+        &Self::SetForestSizeValue,
         RFClassifierModifiedEvent(),
         RFClassifierModifiedEvent());
 
-  m_ForestSizeModel = wrapGetterSetterPairAsProperty(
+  m_TreeDepthModel = wrapGetterSetterPairAsProperty(
         this,
-        &Self::GetForestSizeValueAndRange,
-        &Self::SetForestSizeValue,
+        &Self::GetTreeDepthValueAndRange,
+        &Self::SetTreeDepthValue,
+        RFClassifierModifiedEvent(),
+        RFClassifierModifiedEvent());
+
+  m_ClassifierPatchRadiusModel = wrapGetterSetterPairAsProperty(
+        this,
+        &Self::GetClassifierPatchRadiusValueAndRange,
+        &Self::SetClassifierPatchRadiusValue,
+        RFClassifierModifiedEvent(),
+        RFClassifierModifiedEvent());
+
+  m_ClassifierUsePatchModel =
+      NewNumericPropertyToggleAdaptor(m_ClassifierPatchRadiusModel.GetPointer(), 0, 2);
+
+  m_ClassifierUseCoordinatesModel = wrapGetterSetterPairAsProperty(
+        this,
+        &Self::GetClassifierUseCoordinatesValue,
+        &Self::SetClassifierUseCoordinatesValue,
+        RFClassifierModifiedEvent(),
+        RFClassifierModifiedEvent());
+
+  m_ClassifierBiasModel = wrapGetterSetterPairAsProperty(
+        this,
+        &Self::GetClassifierBiasValueAndRange,
+        &Self::SetClassifierBiasValue,
+        RFClassifierModifiedEvent(),
+        RFClassifierModifiedEvent());
+
+  // Set up the more complex model governing classifier weights
+  m_ClassifierLabelForegroundModel = wrapGetterSetterPairAsProperty(
+        this,
+        &Self::GetClassifierLabelForegroundValueAndRange,
+        &Self::SetClassifierLabelForegroundValue,
         RFClassifierModifiedEvent(),
         RFClassifierModifiedEvent());
 
@@ -222,7 +255,7 @@ void SnakeWizardModel::SetParentModel(GlobalUIModel *model)
 
   // Changes to the snake mode are cast as model update events
   Rebroadcast(m_GlobalState->GetSnakeTypeModel(),
-              ValueChangedEvent(), ModelUpdateEvent());
+              ValueChangedEvent(), ModelUpdateEvent());  
 
   // We also need to rebroadcast these events as state change events
   Rebroadcast(this, ThresholdSettingsUpdateEvent(), StateMachineChangeEvent());
@@ -238,6 +271,10 @@ void SnakeWizardModel::SetParentModel(GlobalUIModel *model)
 
   m_RedTransparentSpeedModeModel->Rebroadcast(
         m_Driver, WrapperChangeEvent(), ValueChangedEvent());
+
+  m_ClassifierLabelForegroundModel->Rebroadcast(
+        m_Driver->GetColorLabelTable(), SegmentationLabelChangeEvent(),
+        DomainChangedEvent());
 }
 
 
@@ -256,6 +293,8 @@ bool SnakeWizardModel::CheckState(SnakeWizardModel::UIState state)
       return ts && ts->IsUpperThresholdEnabled();
     case UIF_EDGEPROCESSING_ENABLED:
       return AreEdgePreprocessingModelsActive();
+    case UIF_CLASSIFIER_TRAINED:
+      return IsClassifierTrained();
     case UIF_CAN_GENERATE_SPEED:
       return CanGenerateSpeedVolume();
     case UIF_SPEED_AVAILABLE:
@@ -336,6 +375,7 @@ void SnakeWizardModel::UpdateClusterPlottedComponentModel()
   this->m_ClusterPlottedComponentModel->SetDomain(cd);
 }
 
+/*
 bool SnakeWizardModel::GetForegroundClassColorLabelValueAndRange(
     LabelType &value, SnakeWizardModel::ForegroundClassDomain *range)
 {
@@ -379,6 +419,7 @@ void SnakeWizardModel::SetForegroundClassColorLabelValue(LabelType value)
   TagRFPreprocessingFilterModified();
 
 }
+*/
 
 bool SnakeWizardModel::GetForestSizeValueAndRange(int &value, NumericValueRange<int> *range)
 {
@@ -400,8 +441,195 @@ void SnakeWizardModel::SetForestSizeValue(int value)
   assert(rfe);
 
   rfe->SetForestSize(value);
+
+  InvokeEvent(RFClassifierModifiedEvent());
+}
+
+bool SnakeWizardModel::GetTreeDepthValueAndRange(int &value, NumericValueRange<int> *range)
+{
+  // Must have a classification engine
+  RFClassificationEngine *rfe = m_Driver->GetClassificationEngine();
+  if(!rfe)
+    return false;
+
+  value = rfe->GetTreeDepth();
+  if(range)
+    range->Set(10, 100, 5);
+
+  return true;
+}
+
+void SnakeWizardModel::SetTreeDepthValue(int value)
+{
+  RFClassificationEngine *rfe = m_Driver->GetClassificationEngine();
+  assert(rfe);
+
+  rfe->SetTreeDepth(value);
+
+  InvokeEvent(RFClassifierModifiedEvent());
 }
 
+bool SnakeWizardModel::GetClassifierPatchRadiusValueAndRange(int &value, NumericValueRange<int> *range)
+{
+  // Must have a classification engine
+  RFClassificationEngine *rfe = m_Driver->GetClassificationEngine();
+  if(!rfe)
+    return false;
+
+  // Get the value
+  RFClassificationEngine::RadiusType radius = rfe->GetPatchRadius();
+  value = (int) radius[0];
+
+  if(range)
+    range->Set(0, 4, 1);
+
+  return true;
+}
+
+void SnakeWizardModel::SetClassifierPatchRadiusValue(int value)
+{
+  RFClassificationEngine *rfe = m_Driver->GetClassificationEngine();
+  assert(rfe);
+  assert(value >= 0);
+
+  RFClassificationEngine::RadiusType radius;
+  radius.Fill((unsigned int) value);
+  rfe->SetPatchRadius(radius);
+
+  InvokeEvent(RFClassifierModifiedEvent());
+}
+
+bool SnakeWizardModel::GetClassifierBiasValueAndRange(double &value, NumericValueRange<double> *range)
+{
+  // Must have a classification engine
+  RFClassificationEngine *rfe = m_Driver->GetClassificationEngine();
+  if(!rfe)
+    return false;
+
+  // Must have a classifier
+  RandomForestClassifier *rfc = rfe->GetClassifier();
+  if(!rfc)
+    return false;
+
+  // The classifier must be valid (2 or more classes)
+  if(!rfc->IsValidClassifier())
+    return false;
+
+  value = rfc->GetBiasParameter();
+  if(range)
+    range->Set(0.0, 1.0, 0.01);
+
+  return true;
+}
+
+void SnakeWizardModel::SetClassifierBiasValue(double value)
+{
+  RFClassificationEngine *rfe = m_Driver->GetClassificationEngine();
+  assert(rfe);
+
+  RandomForestClassifier *rfc = rfe->GetClassifier();
+  assert(rfc);
+
+  rfc->SetBiasParameter(value);
+
+  InvokeEvent(RFClassifierModifiedEvent());
+
+  // TODO: this is a hack!
+  TagRFPreprocessingFilterModified();
+}
+
+bool SnakeWizardModel::GetClassifierUseCoordinatesValue(bool &value)
+{
+  // Must have a classification engine
+  RFClassificationEngine *rfe = m_Driver->GetClassificationEngine();
+  if(!rfe)
+    return false;
+
+  value = rfe->GetUseCoordinateFeatures();
+  return true;
+}
+
+void SnakeWizardModel::SetClassifierUseCoordinatesValue(bool value)
+{
+  RFClassificationEngine *rfe = m_Driver->GetClassificationEngine();
+  assert(rfe);
+  rfe->SetUseCoordinateFeatures(value);
+  InvokeEvent(RFClassifierModifiedEvent());
+}
+
+bool SnakeWizardModel
+::GetClassifierLabelForegroundValueAndRange(
+    ClassifierLabelForegroundMap &value, ClassifierLabelForegroundMapDomain *range)
+{
+  // Get the classification engine
+  RFClassificationEngine *rfengine = m_Driver->GetClassificationEngine();
+  if(!rfengine || !rfengine->GetClassifier()->IsValidClassifier())
+    return false;
+
+  // Clear the output map
+  value.clear();
+  if(range)
+    range->clear();
+
+  // Add all of the labels
+  RandomForestClassifier *rfc = rfengine->GetClassifier();
+  const RandomForestClassifier::WeightArray &wa = rfc->GetClassWeights();
+  for(size_t i = 0; i < wa.size(); i++)
+    {
+    RandomForestClassifier::MappingType::const_iterator itl = rfc->GetClassToLabelMapping().find(i);
+    if(itl != rfc->GetClassToLabelMapping().end())
+      {
+      LabelType label = itl->second;
+      value[label] = wa[i] > 0.0;
+      if(range)
+        (*range)[label] = m_Driver->GetColorLabelTable()->GetColorLabel(label);
+      }
+    }
+
+  return true;
+}
+
+void SnakeWizardModel
+::SetClassifierLabelForegroundValue(
+    ClassifierLabelForegroundMap value)
+{
+  // Get the classification engine
+  RFClassificationEngine *rfengine = m_Driver->GetClassificationEngine();
+  assert(rfengine && rfengine->GetClassifier()->IsValidClassifier());
+
+  // Check if anything was actually modified - to avoid loops
+  bool changed = false;
+
+  // Update the weight of each class
+  RandomForestClassifier *rfc = rfengine->GetClassifier();
+  for(RandomForestClassifier::MappingType::const_iterator it = rfc->GetClassToLabelMapping().begin();
+      it != rfc->GetClassToLabelMapping().end(); ++it)
+    {
+    double old_weight = rfc->GetClassWeights()[it->first];
+    double new_weight = old_weight;
+
+    ClassifierLabelForegroundMap::const_iterator it2 = value.find(it->second);
+    if(it2 != value.end())
+      new_weight = it2->second ? 1.0 : -1.0;
+
+    if(old_weight != new_weight)
+      {
+      rfc->SetClassWeight(it->first, new_weight);
+      changed = true;
+      }
+    }
+
+  if(changed)
+    {
+    // Fire the event
+    InvokeEvent(RFClassifierModifiedEvent());
+
+    // TODO: this is a hack!
+    TagRFPreprocessingFilterModified();
+    }
+}
+
+
 void SnakeWizardModel::OnBubbleModeEnter()
 {
   // When entering bubble mode, we should not use the overlay display of the
@@ -941,7 +1169,7 @@ void SnakeWizardModel::CompletePreprocessing()
   // to match the foreground class - otherwise it's confusing to the user
   if(m_Driver->GetPreprocessingMode() == PREPROCESS_RF)
     m_Parent->GetGlobalState()->SetDrawingColorLabel(
-          this->GetForegroundClassColorLabel());
+          this->GetClassiferFirstForegroundLabel());
 
   // Disconnect preview pipeline
   m_Driver->EnterPreprocessingMode(PREPROCESS_NONE);
@@ -1221,8 +1449,8 @@ void SnakeWizardModel::OnEvolutionPageFinish()
   // Update IRIS with SNAP images
   m_Driver->UpdateIRISWithSnapImageData(NULL);
 
-  // Set an undo point
-  m_Driver->StoreUndoPoint("Automatic Segmentation");
+  // Set an undo point in IRIS, not SNAP!
+  m_Driver->GetIRISImageData()->StoreUndoPoint("Automatic Segmentation");
 
   // Return to IRIS mode
   m_Driver->SetCurrentImageDataToIRIS();
@@ -1539,6 +1767,18 @@ SnakeWizardModel::GetLayerAndIndexForNthComponent(int n)
   return m_ComponentInfo[n];
 }
 
+
+
+LabelType SnakeWizardModel::GetClassiferFirstForegroundLabel()
+{
+  ClassifierLabelForegroundMap fbtable = this->GetClassifierLabelForeground();
+  for(ClassifierLabelForegroundMap::iterator it = fbtable.begin(); it != fbtable.end(); ++it)
+    if(it->second)
+      return it->first;
+
+  return 0;
+}
+
 void SnakeWizardModel::TrainClassifier()
 {
   // Get the classification engine
@@ -1547,21 +1787,8 @@ void SnakeWizardModel::TrainClassifier()
   // Perform the classification
   rfengine->TrainClassifier();
 
-  // Get the current foreground label
-  LabelType curr_foreground;
-  bool fg_valid =
-      m_ForegroundClassColorLabelModel->GetValueAndDomain(curr_foreground, NULL);
-
-  // Populate the available labels for the foreground label
-  m_ActiveClasses.clear();
-  const RandomForestClassifier::MappingType &mapping =
-      rfengine->GetClassifier()->GetClassToLabelMapping();
-  for(RandomForestClassifier::MappingType::const_iterator it = mapping.begin();
-      it != mapping.end(); ++it)
-    {
-    m_ActiveClasses[it->second] =
-        m_Driver->GetColorLabelTable()->GetColorLabel(it->second);
-    }
+  // Create a list of utilized labels
+  RandomForestClassifier *rfc = rfengine->GetClassifier();
 
   // Fire the appropriate event
   InvokeEvent(RFClassifierModifiedEvent());
@@ -1570,6 +1797,13 @@ void SnakeWizardModel::TrainClassifier()
   TagRFPreprocessingFilterModified();
 }
 
+bool SnakeWizardModel::IsClassifierTrained()
+{
+  // Get the classification engine
+  RFClassificationEngine *rfengine = m_Driver->GetClassificationEngine();
+  return rfengine && rfengine->GetClassifier()->IsValidClassifier();
+}
+
 void SnakeWizardModel::ClearSegmentation()
 {
   m_Driver->ResetSNAPSegmentationImage();
diff --git a/GUI/Model/SnakeWizardModel.h b/GUI/Model/SnakeWizardModel.h
index 077af80..95f383f 100644
--- a/GUI/Model/SnakeWizardModel.h
+++ b/GUI/Model/SnakeWizardModel.h
@@ -59,6 +59,7 @@ public:
     UIF_LOWER_THRESHOLD_ENABLED,
     UIF_UPPER_THRESHOLD_ENABLED,
     UIF_EDGEPROCESSING_ENABLED,
+    UIF_CLASSIFIER_TRAINED,
     UIF_CAN_GENERATE_SPEED,
     UIF_SPEED_AVAILABLE,              // Has speed volume been computed?
     UIF_PREPROCESSING_ACTIVE,         // Is the preprocessing dialog open?
@@ -254,16 +255,47 @@ public:
    * SUPERVISED CLASSIFICATION SUPPORT (RANDOM FORESTS)
    * =================================================================== */
 
-  /** Model controlling the class/label used for the foreground probability */
-  typedef STLMapWrapperItemSetDomain<LabelType, ColorLabel> ForegroundClassDomain;
-  irisGenericPropertyAccessMacro(ForegroundClassColorLabel, LabelType, ForegroundClassDomain)
+  /** A data structure representing label foreground/background state */
+  typedef std::map<LabelType, bool> ClassifierLabelForegroundMap;
+
+  /** A data structure representing the domain of classification labels */
+  typedef SimpleNonAtomicItemSetDomain<LabelType, ColorLabel> ClassifierLabelForegroundMapDomain;
+
+  /** A model around this data structure */
+  typedef AbstractPropertyModel<ClassifierLabelForegroundMap, ClassifierLabelForegroundMapDomain>
+    AbstractClassifierLabelForegroundModel;
+
+  /** Access the model encapsulating the label weights for classification */
+  irisGenericPropertyAccessMacro(ClassifierLabelForeground,
+                                 ClassifierLabelForegroundMap, ClassifierLabelForegroundMapDomain)
+
+  /** Get the first foreground label */
+  LabelType GetClassiferFirstForegroundLabel();
 
   /** Model for the forest size */
   irisRangedPropertyAccessMacro(ForestSize, int)
 
+  /** Model for the forest size */
+  irisRangedPropertyAccessMacro(TreeDepth, int)
+
+  /** Model for whether patch contextual features are used */
+  irisSimplePropertyAccessMacro(ClassifierUsePatch, bool)
+
+  /** Model for the patch radius */
+  irisRangedPropertyAccessMacro(ClassifierPatchRadius, int)
+
+  /** Bias for the classifier */
+  irisRangedPropertyAccessMacro(ClassifierBias, double)
+
+  /** Whether coordinates are used as contextual features */
+  irisSimplePropertyAccessMacro(ClassifierUseCoordinates, bool)
+
   /** Train the random forest classifier when the user hits the 'train' button */
   void TrainClassifier();
 
+  /** Whether the classifier is trained and available for use */
+  bool IsClassifierTrained();
+
   /** Clear the classification examples (i.e., clear the classification) */
   void ClearSegmentation();
 
@@ -407,13 +439,6 @@ protected:
    * SUPERVISED CLASSIFICATION SUPPORT (Random Forest)
    * =================================================================== */
 
-  // A mapping of currently defined classes to color label descriptors
-  std::map<LabelType, ColorLabel> m_ActiveClasses;
-
-  // Model for the foreground color label
-  typedef AbstractPropertyModel<LabelType, ForegroundClassDomain>
-    AbstractForegroundClassPropertyModel;
-
   // A list of suggested labels, from which the user can choose one to draw
   // These labels are the N most recently used labels
   std::map<LabelType, ColorLabel> m_ClassifyQuickLabels;
@@ -421,17 +446,36 @@ protected:
   // The size of the suggested label list (static)
   static unsigned int m_ClassifyQuickLabelsCount;
 
-  // Model for the suggested labels from which the user can choose one to draw
-
-
-  SmartPtr<AbstractForegroundClassPropertyModel> m_ForegroundClassColorLabelModel;
-  bool GetForegroundClassColorLabelValueAndRange(LabelType &value, ForegroundClassDomain *range);
-  void SetForegroundClassColorLabelValue(LabelType value);
+  // A list of color labels used in classification
+  std::map<LabelType, ColorLabel> m_ClassifyUsedLabels;
 
   SmartPtr<AbstractRangedIntProperty> m_ForestSizeModel;
   bool GetForestSizeValueAndRange(int &value, NumericValueRange<int> *range);
   void SetForestSizeValue(int value);
 
+  SmartPtr<AbstractRangedIntProperty> m_TreeDepthModel;
+  bool GetTreeDepthValueAndRange(int &value, NumericValueRange<int> *range);
+  void SetTreeDepthValue(int value);
+
+  SmartPtr<AbstractSimpleBooleanProperty> m_ClassifierUsePatchModel;
+  SmartPtr<AbstractRangedIntProperty> m_ClassifierPatchRadiusModel;
+  bool GetClassifierPatchRadiusValueAndRange(int &value, NumericValueRange<int> *range);
+  void SetClassifierPatchRadiusValue(int value);
+
+  SmartPtr<AbstractRangedDoubleProperty> m_ClassifierBiasModel;
+  bool GetClassifierBiasValueAndRange(double &value, NumericValueRange<double> *range);
+  void SetClassifierBiasValue(double value);
+
+  SmartPtr<AbstractSimpleBooleanProperty> m_ClassifierUseCoordinatesModel;
+  bool GetClassifierUseCoordinatesValue(bool &value);
+  void SetClassifierUseCoordinatesValue(bool value);
+
+  SmartPtr<AbstractClassifierLabelForegroundModel> m_ClassifierLabelForegroundModel;
+  bool GetClassifierLabelForegroundValueAndRange(ClassifierLabelForegroundMap &value,
+                                              ClassifierLabelForegroundMapDomain *range);
+  void SetClassifierLabelForegroundValue(ClassifierLabelForegroundMap value);
+
+
   // TODO: this should be handled through the ITK modified mechanism
   void TagRFPreprocessingFilterModified();
 
diff --git a/GUI/Model/SynchronizationModel.cxx b/GUI/Model/SynchronizationModel.cxx
index d8a12e8..fa80a1a 100644
--- a/GUI/Model/SynchronizationModel.cxx
+++ b/GUI/Model/SynchronizationModel.cxx
@@ -193,7 +193,8 @@ void SynchronizationModel::ReadIPCState()
 
       if(m_SyncZoomModel->GetValue()
          && gsm->IsSliceInitialized()
-         && gsm->GetViewZoom() != message.zoom_level[dir])
+         && gsm->GetViewZoom() != message.zoom_level[dir]
+         && static_cast<float>(message.zoom_level[dir]) > 0.0f)
         {
           gsm->SetViewZoom(message.zoom_level[dir]);
         }
diff --git a/GUI/Model/UIReporterDelegates.h b/GUI/Model/UIReporterDelegates.h
index 53451e3..4843d7f 100644
--- a/GUI/Model/UIReporterDelegates.h
+++ b/GUI/Model/UIReporterDelegates.h
@@ -72,6 +72,16 @@ public:
 };
 
 /**
+ This delegate is used to generate an OpenGL texture for icons. Icons
+ are identified by a string.
+ */
+class TextureGenerationDelegate
+{
+public:
+  virtual int GenerateTexture(const char *imageName);
+};
+
+/**
  This delegate is used to obtain system-specific information
  */
 class SystemInfoDelegate
diff --git a/GUI/Model/UIState.h b/GUI/Model/UIState.h
index 3024486..5b69d1c 100644
--- a/GUI/Model/UIState.h
+++ b/GUI/Model/UIState.h
@@ -16,7 +16,8 @@ enum UIState {
   UIF_UNSAVED_CHANGES,
   UIF_MESH_SAVEABLE,
   UIF_SNAKE_MODE,
-  UIF_LEVEL_SET_ACTIVE
+  UIF_LEVEL_SET_ACTIVE,
+  UIF_MULTIPLE_BASE_LAYERS       // i.e., more than one non-sticky layer
 };
 
 #endif // UISTATE_H
diff --git a/GUI/Qt/Components/AnnotationToolPanel.cxx b/GUI/Qt/Components/AnnotationToolPanel.cxx
new file mode 100644
index 0000000..09f6b54
--- /dev/null
+++ b/GUI/Qt/Components/AnnotationToolPanel.cxx
@@ -0,0 +1,83 @@
+#include "AnnotationToolPanel.h"
+#include "ui_AnnotationToolPanel.h"
+
+#include "QtAbstractButtonCoupling.h"
+#include "QtCheckableWidgetGroupCoupling.h"
+#include "QtSliderCoupling.h"
+#include "GlobalState.h"
+#include "GlobalUIModel.h"
+#include "QFileInfo"
+#include "IRISApplication.h"
+
+AnnotationToolPanel::AnnotationToolPanel(QWidget *parent) :
+  QWidget(parent),
+  ui(new Ui::AnnotationToolPanel)
+{
+  ui->setupUi(this);
+}
+
+AnnotationToolPanel::~AnnotationToolPanel()
+{
+  delete ui;
+}
+
+void AnnotationToolPanel::SetModel(GlobalUIModel *model)
+{
+  m_Model = model;
+
+  std::map<AnnotationMode, QAbstractButton *> mode_mapping;
+  mode_mapping[ANNOTATION_RULER] = ui->btnRuler;
+  mode_mapping[ANNOTATION_LANDMARK] = ui->btnText;
+  mode_mapping[ANNOTATION_SELECT] = ui->btnSelect;
+  makeCheckableWidgetGroupCoupling(ui->grpMode, mode_mapping,
+                                   m_Model->GetGlobalState()->GetAnnotationModeModel());
+
+  makeCoupling(ui->inColor, m_Model->GetGlobalState()->GetAnnotationColorModel());
+  makeCoupling(ui->inOpacity, m_Model->GetGlobalState()->GetAnnotationAlphaModel());
+  makeCoupling((QAbstractButton *) ui->btnVisible, m_Model->GetGlobalState()->GetAnnotationVisibilityModel());
+}
+
+void AnnotationToolPanel::on_btnOpen_clicked()
+{
+  // Load annotations
+  QString file = ShowSimpleOpenDialogWithHistory(
+                   this, m_Model, "Annotations", "Open Annotation File",
+                   "Annotation File", "ITK-SNAP Annotation Files (*.annot)");
+
+  if(!file.isNull())
+    {
+    QString file_abs = QFileInfo(file).absoluteFilePath();
+    try
+      {
+      m_Model->GetDriver()->LoadAnnotations(to_utf8(file_abs).c_str());
+      }
+    catch(std::exception &exc)
+      {
+      ReportNonLethalException(this, exc, "Error Opening Annotation File",
+                               QString("Failed to open annotation file %1").arg(file_abs));
+      }
+    }
+}
+
+void AnnotationToolPanel::on_btnSave_clicked()
+{
+  // Save annotations
+  QString file = ShowSimpleSaveDialogWithHistory(
+                   this, m_Model, "Annotations", "Open Annotation File",
+                   "Annotation File", "ITK-SNAP Annotation Files (*.annot)", false);
+
+  if(!file.isNull())
+    {
+    QString file_abs = QFileInfo(file).absoluteFilePath();
+    try
+      {
+      m_Model->GetDriver()->SaveAnnotations(to_utf8(file_abs).c_str());
+      }
+    catch(std::exception &exc)
+      {
+      ReportNonLethalException(this, exc, "Error Saving Annotation File",
+                               QString("Failed to save annotation file %1").arg(file_abs));
+      }
+    }
+
+}
diff --git a/GUI/Qt/Components/AnnotationToolPanel.h b/GUI/Qt/Components/AnnotationToolPanel.h
new file mode 100644
index 0000000..e70805b
--- /dev/null
+++ b/GUI/Qt/Components/AnnotationToolPanel.h
@@ -0,0 +1,31 @@
+#ifndef ANNOTATIONTOOLPANEL_H
+#define ANNOTATIONTOOLPANEL_H
+
+#include <QWidget>
+class GlobalUIModel;
+
+namespace Ui {
+class AnnotationToolPanel;
+}
+
+class AnnotationToolPanel : public QWidget
+{
+  Q_OBJECT
+
+public:
+  explicit AnnotationToolPanel(QWidget *parent = 0);
+  ~AnnotationToolPanel();
+
+  void SetModel(GlobalUIModel *model);
+
+private slots:
+  void on_btnOpen_clicked();
+
+  void on_btnSave_clicked();
+
+private:
+  Ui::AnnotationToolPanel *ui;
+  GlobalUIModel *m_Model;
+};
+
+#endif // ANNOTATIONTOOLPANEL_H
diff --git a/GUI/Qt/Components/AnnotationToolPanel.ui b/GUI/Qt/Components/AnnotationToolPanel.ui
new file mode 100644
index 0000000..8c4a189
--- /dev/null
+++ b/GUI/Qt/Components/AnnotationToolPanel.ui
@@ -0,0 +1,425 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AnnotationToolPanel</class>
+ <widget class="QWidget" name="AnnotationToolPanel">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>185</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <property name="styleSheet">
+   <string notr="true">QLabel {
+  font-size: 12px;
+}
+
+QToolButton {
+  font-size: 10px;
+}
+</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <property name="spacing">
+    <number>4</number>
+   </property>
+   <property name="leftMargin">
+    <number>0</number>
+   </property>
+   <property name="topMargin">
+    <number>0</number>
+   </property>
+   <property name="rightMargin">
+    <number>0</number>
+   </property>
+   <property name="bottomMargin">
+    <number>0</number>
+   </property>
+   <item>
+    <widget class="QLabel" name="label">
+     <property name="text">
+      <string>Annotation mode:</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QWidget" name="grpMode" native="true">
+     <layout class="QVBoxLayout" name="verticalLayout_2">
+      <property name="spacing">
+       <number>4</number>
+      </property>
+      <property name="topMargin">
+       <number>4</number>
+      </property>
+      <property name="rightMargin">
+       <number>0</number>
+      </property>
+      <property name="bottomMargin">
+       <number>0</number>
+      </property>
+      <item>
+       <widget class="QToolButton" name="btnRuler">
+        <property name="minimumSize">
+         <size>
+          <width>150</width>
+          <height>0</height>
+         </size>
+        </property>
+        <property name="toolTip">
+         <string><html><head/><body><p><span style=" font-weight:600;">Line and Ruler Mode</span></p><p>Use this mode to measure distances between points and angles between line segments. Click with the left mouse button to begin drawing a line. Click again to place the second point of the line. Right-click to complete the line.</p><p>The length of the line and the angle between the line and other lines drawn on the sa [...]
+        </property>
+        <property name="text">
+         <string>Line and Ruler Mode</string>
+        </property>
+        <property name="icon">
+         <iconset>
+          <normaloff>:/root/icons8_ruler_16.png</normaloff>:/root/icons8_ruler_16.png</iconset>
+        </property>
+        <property name="checkable">
+         <bool>true</bool>
+        </property>
+        <property name="checked">
+         <bool>true</bool>
+        </property>
+        <property name="autoExclusive">
+         <bool>true</bool>
+        </property>
+        <property name="toolButtonStyle">
+         <enum>Qt::ToolButtonTextBesideIcon</enum>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QToolButton" name="btnText">
+        <property name="minimumSize">
+         <size>
+          <width>150</width>
+          <height>0</height>
+         </size>
+        </property>
+        <property name="toolTip">
+         <string><html><head/><body><p><span style=" font-weight:600;">Text Annotation Mode</span></p><p>Use this mode to place text annotations in the 3D image. Annotations are anchored to a single voxel location. Along with line annotations, they can be saved and shared with colleagues.</p></body></html></string>
+        </property>
+        <property name="text">
+         <string>Text Annotation Mode</string>
+        </property>
+        <property name="icon">
+         <iconset>
+          <normaloff>:/root/icons8_generic_text_16.png</normaloff>:/root/icons8_generic_text_16.png</iconset>
+        </property>
+        <property name="checkable">
+         <bool>true</bool>
+        </property>
+        <property name="checked">
+         <bool>false</bool>
+        </property>
+        <property name="autoExclusive">
+         <bool>true</bool>
+        </property>
+        <property name="toolButtonStyle">
+         <enum>Qt::ToolButtonTextBesideIcon</enum>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QToolButton" name="btnSelect">
+        <property name="minimumSize">
+         <size>
+          <width>150</width>
+          <height>0</height>
+         </size>
+        </property>
+        <property name="toolTip">
+         <string><html><head/><body><p><span style=" font-weight:600;">Selection Mode</span></p><p>Use this mode to select previously created annotations. Once selected, annotations can be moved or deleted. Shift-click to select multiple annotations.</p></body></html></string>
+        </property>
+        <property name="text">
+         <string>Selection Mode</string>
+        </property>
+        <property name="icon">
+         <iconset>
+          <normaloff>:/root/icons8_cursor_16.png</normaloff>:/root/icons8_cursor_16.png</iconset>
+        </property>
+        <property name="checkable">
+         <bool>true</bool>
+        </property>
+        <property name="autoExclusive">
+         <bool>true</bool>
+        </property>
+        <property name="toolButtonStyle">
+         <enum>Qt::ToolButtonTextBesideIcon</enum>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <spacer name="verticalSpacer">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeType">
+      <enum>QSizePolicy::Fixed</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>20</width>
+       <height>5</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item>
+    <widget class="QLabel" name="label_3">
+     <property name="text">
+      <string>Annotation properties:</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QWidget" name="grpMode_2" native="true">
+     <property name="styleSheet">
+      <string notr="true">QLabel {
+font-size:12px;
+}</string>
+     </property>
+     <layout class="QFormLayout" name="formLayout_2">
+      <property name="labelAlignment">
+       <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+      </property>
+      <property name="horizontalSpacing">
+       <number>4</number>
+      </property>
+      <property name="verticalSpacing">
+       <number>4</number>
+      </property>
+      <property name="topMargin">
+       <number>4</number>
+      </property>
+      <property name="rightMargin">
+       <number>0</number>
+      </property>
+      <property name="bottomMargin">
+       <number>0</number>
+      </property>
+      <item row="0" column="0">
+       <widget class="QLabel" name="label_2">
+        <property name="text">
+         <string>Color:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="1">
+       <widget class="QColorButtonWidget" name="inColor" native="true">
+        <property name="minimumSize">
+         <size>
+          <width>10</width>
+          <height>10</height>
+         </size>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <spacer name="verticalSpacer_3">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeType">
+      <enum>QSizePolicy::Fixed</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>20</width>
+       <height>10</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item>
+    <widget class="QLabel" name="label_4">
+     <property name="text">
+      <string>Overall annotation opacity:</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QWidget" name="grpMode_3" native="true">
+     <property name="styleSheet">
+      <string notr="true">QLabel {
+font-size:12px;
+}</string>
+     </property>
+     <layout class="QHBoxLayout" name="horizontalLayout_2">
+      <property name="spacing">
+       <number>4</number>
+      </property>
+      <property name="leftMargin">
+       <number>12</number>
+      </property>
+      <property name="topMargin">
+       <number>0</number>
+      </property>
+      <property name="rightMargin">
+       <number>4</number>
+      </property>
+      <property name="bottomMargin">
+       <number>0</number>
+      </property>
+      <item>
+       <widget class="QDoubleSlider" name="inOpacity">
+        <property name="toolTip">
+         <string><html><head/><body><p>Adjust the opacity of all annotations</p></body></html></string>
+        </property>
+        <property name="maximum">
+         <number>100</number>
+        </property>
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="tickPosition">
+         <enum>QSlider::NoTicks</enum>
+        </property>
+        <property name="tickInterval">
+         <number>25</number>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QToolButton" name="btnVisible">
+        <property name="maximumSize">
+         <size>
+          <width>20</width>
+          <height>20</height>
+         </size>
+        </property>
+        <property name="toolTip">
+         <string>Toggle the visibility of all annotations</string>
+        </property>
+        <property name="text">
+         <string>...</string>
+        </property>
+        <property name="icon">
+         <iconset>
+          <normaloff>:/root/icons8_invisible_12.png</normaloff>
+          <normalon>:/root/icons8_visible_12.png</normalon>:/root/icons8_invisible_12.png</iconset>
+        </property>
+        <property name="iconSize">
+         <size>
+          <width>12</width>
+          <height>12</height>
+         </size>
+        </property>
+        <property name="checkable">
+         <bool>true</bool>
+        </property>
+        <property name="checked">
+         <bool>true</bool>
+        </property>
+        <property name="autoRaise">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <spacer name="verticalSpacer_2">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>20</width>
+       <height>40</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item>
+    <widget class="QWidget" name="widget" native="true">
+     <layout class="QHBoxLayout" name="horizontalLayout">
+      <property name="spacing">
+       <number>6</number>
+      </property>
+      <property name="leftMargin">
+       <number>4</number>
+      </property>
+      <property name="topMargin">
+       <number>4</number>
+      </property>
+      <property name="rightMargin">
+       <number>4</number>
+      </property>
+      <property name="bottomMargin">
+       <number>4</number>
+      </property>
+      <item>
+       <spacer name="horizontalSpacer">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>110</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <widget class="QToolButton" name="btnOpen">
+        <property name="toolTip">
+         <string><html><head/><body><p>Load annotations from file</p></body></html></string>
+        </property>
+        <property name="text">
+         <string>...</string>
+        </property>
+        <property name="icon">
+         <iconset>
+          <normaloff>:/root/open_22.png</normaloff>:/root/open_22.png</iconset>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QToolButton" name="btnSave">
+        <property name="toolTip">
+         <string><html><head/><body><p>Save annotations to file</p></body></html></string>
+        </property>
+        <property name="text">
+         <string>...</string>
+        </property>
+        <property name="icon">
+         <iconset>
+          <normaloff>:/root/save_22.png</normaloff>:/root/save_22.png</iconset>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>QDoubleSlider</class>
+   <extends>QSlider</extends>
+   <header>QDoubleSlider.h</header>
+  </customwidget>
+  <customwidget>
+   <class>QColorButtonWidget</class>
+   <extends>QWidget</extends>
+   <header location="global">QColorButtonWidget.h</header>
+   <container>1</container>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/GUI/Qt/Components/CursorInspector.cxx b/GUI/Qt/Components/CursorInspector.cxx
index 35a1a78..e0ef253 100644
--- a/GUI/Qt/Components/CursorInspector.cxx
+++ b/GUI/Qt/Components/CursorInspector.cxx
@@ -25,6 +25,9 @@
 #include <QtTableWidgetCoupling.h>
 #include <QtWidgetArrayCoupling.h>
 
+#include <QStandardItemModel>
+#include <QPixmapCache>
+
 /**
   This class provide the coupling properties for coupling the table of
   voxel intensities to QTableWidget
@@ -47,8 +50,8 @@ public:
                        const LayerCurrentVoxelInfo &desc, int col)
   {
     return (col == 0)
-        ? QIcon()
-        : CreateColorBoxIcon(16, 16, desc.Color);
+        ? QIcon(":/root/icons8_pin_16.png")
+        : CreateColorBoxIcon(12, 12, desc.Color);
   }
 
   static QVariant GetIconSignature(ValueType value,
@@ -83,18 +86,35 @@ CursorInspector::CursorInspector(QWidget *parent) :
 {
   ui->setupUi(this);
 
+  // Create an empty standard item model
+  m_CurrentVoxelItemModel = new QStandardItemModel(this);
+  m_CurrentVoxelItemModel->setColumnCount(2);
+  m_CurrentVoxelItemModel->setRowCount(1);
+
+  // Set the header labels
+  QStringList header;
+  header << "Layer" << "Intensity";
+  m_CurrentVoxelItemModel->setHorizontalHeaderLabels(header);
+
+  ui->tableVoxelUnderCursor->setModel(m_CurrentVoxelItemModel);
   ui->tableVoxelUnderCursor->setAlternatingRowColors(true);
   ui->tableVoxelUnderCursor->setFixedWidth(160);
   ui->tableVoxelUnderCursor->setFixedHeight(120);
   ui->tableVoxelUnderCursor->setContextMenuPolicy(Qt::CustomContextMenu);
 
-  m_ContextMenu = new QMenu(ui->tableVoxelUnderCursor);
-  m_ContextMenu->addAction(ui->actionAutoContrast);
+#if QT_VERSION >= 0x050000
+  ui->tableVoxelUnderCursor->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Interactive);
+  ui->tableVoxelUnderCursor->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch);
+#else
+  ui->tableVoxelUnderCursor->horizontalHeader()->setResizeMode(0, QHeaderView::Interactive);
+  ui->tableVoxelUnderCursor->horizontalHeader()->setResizeMode(1, QHeaderView::Stretch);
+#endif
+  ui->tableVoxelUnderCursor->setColumnWidth(0, 92);
+  // ui->tableVoxelUnderCursor->setColumnWidth(1, 68);
 
   // Hook up the context menu
   connect(ui->tableVoxelUnderCursor, SIGNAL(customContextMenuRequested(QPoint)),
           SLOT(onContextMenuRequested(QPoint)));
-
 }
 
 CursorInspector::~CursorInspector()
@@ -116,9 +136,8 @@ void CursorInspector::SetModel(CursorInspectionModel *model)
   makeArrayCoupling(ui->inCursorX, ui->inCursorY, ui->inCursorZ,
                     m_Model->GetCursorPositionModel());
 
-  makeMultiRowCoupling(ui->tableVoxelUnderCursor,
-                       m_Model->GetVoxelAtCursorModel(),
-                       LayerCurrentVoxelInfoTableWidgetRowTraits());
+  connectITK(m_Model->GetVoxelAtCursorModel(), DomainChangedEvent());
+  connectITK(m_Model->GetVoxelAtCursorModel(), DomainDescriptionChangedEvent());
 }
 
 #include "MainImageWindow.h"
@@ -147,17 +166,128 @@ void CursorInspector::onContextMenuRequested(QPoint pos)
     }
 }
 
-void CursorInspector::on_actionAutoContrast_triggered()
+void CursorInspector::UpdateVoxelTableRow(int i, const LayerCurrentVoxelInfo &vi)
 {
-  LayerIterator it =
-      m_Model->GetParent()->GetLoadedLayersSelectionModel()->GetNthLayer(m_PopupRow);
+  // Get the two items to update
+  QStandardItem *item_layer = m_CurrentVoxelItemModel->item(i, 0);
+  QStandardItem *item_intensity = m_CurrentVoxelItemModel->item(i, 1);
+
+  item_layer->setText(from_utf8(vi.LayerName));
+  item_intensity->setText(from_utf8(vi.IntensityValue));
+  item_intensity->setToolTip(from_utf8(vi.IntensityValue));
+
+  // item_layer->setForeground(QBrush(QColor(Qt::darkGray)));
+  // item_intensity->setForeground(QBrush(QColor(Qt::darkGray)));
+
+  QString tooltip_annot;
+
+  // By default the color of the items is black
+  item_layer->setForeground(QBrush(QColor(Qt::black)));
+  item_intensity->setForeground(QBrush(QColor(Qt::black)));
+  item_layer->setIcon(QIcon());
+
+  if(vi.isSelectedGroundLayer)
+    {
+    // item_layer->setIcon(QIcon(":/root/icons8_star_8.png"));
+    QFont font = item_layer->font(); font.setBold(true); font.setItalic(false);
+    item_layer->setFont(font);
+    item_layer->setToolTip(from_utf8(vi.LayerName));
+    }
+  else if(vi.isSticky)
+    {
+    // item_layer->setIcon(QIcon(":/root/icons8_pin_10.png"));
+    QFont font = item_layer->font(); font.setBold(false); font.setItalic(true);
+    item_layer->setFont(font);
+    item_layer->setToolTip(QString("<p>%1</p><p>%2</p>").arg(
+                             from_utf8(vi.LayerName)).arg(
+                             "This layer is rendered as an overlay on top of other layers."));
+    }
+  else
+    {
+    QFont font = item_layer->font(); font.setBold(false); font.setItalic(false);
+    item_layer->setFont(font);
+    item_layer->setToolTip(from_utf8(vi.LayerName));
+    }
+
+  // Set the tooltip
+  item_layer->setToolTip(
+        QString("<p>%1</p><p>%2</p>").arg(from_utf8(vi.LayerName)).arg(tooltip_annot));
 
-  if(it.GetLayer()->GetDisplayMapping()->GetIntensityCurve())
+  // Set the color icon
+  QColor stored_color = qvariant_cast<QColor>(item_intensity->data(Qt::UserRole));
+  QColor new_color = QColor(vi.Color[0], vi.Color[1], vi.Color[2]);
+  if(new_color != stored_color)
     {
-    // Select the currently highlighted layer
-    m_Model->GetParent()->GetIntensityCurveModel()->SetLayer(it.GetLayer());
+    item_intensity->setIcon(CreateColorBoxIcon(12, 12, vi.Color));
+    item_intensity->setData(new_color, Qt::UserRole);
+    }
+}
+
+void CursorInspector::RebuildVoxelTable()
+{
+  // Initialize the model
+  m_CurrentVoxelItemModel->removeRows(0, m_CurrentVoxelItemModel->rowCount());
 
-    // Auto-adjust intensity in the selected layer
-    m_Model->GetParent()->GetIntensityCurveModel()->OnAutoFitWindow();
+  // Get the domain from which we are building this model
+  int dummy;
+  CurrentVoxelInfoItemSetDomain domain;
+  if(m_Model->GetVoxelAtCursorModel()->GetValueAndDomain(dummy, &domain))
+    {
+    // Add the rows
+    for(LayerIterator it = domain.begin(); it != domain.end(); ++it)
+      {
+      QList<QStandardItem *> items;
+      items.push_back(new QStandardItem());
+      items.push_back(new QStandardItem());
+      m_CurrentVoxelItemModel->appendRow(items);
+      this->UpdateVoxelTableRow(m_CurrentVoxelItemModel->rowCount()-1, domain.GetDescription(it));
+      }
     }
 }
+
+void CursorInspector::UpdateVoxelTable()
+{
+  // Get the domain from which we are building this model
+  int dummy;
+  CurrentVoxelInfoItemSetDomain domain;
+  if(m_Model->GetVoxelAtCursorModel()->GetValueAndDomain(dummy, &domain))
+    {
+    // Update the rows
+    int row = 0;
+    for(LayerIterator it = domain.begin(); it != domain.end(); ++it, ++row)
+      {
+      this->UpdateVoxelTableRow(row, domain.GetDescription(it));
+      }
+    }
+}
+
+void CursorInspector::onModelUpdate(const EventBucket &bucket)
+{
+  m_Model->Update();
+
+  if(bucket.HasEvent(DomainChangedEvent(), m_Model->GetVoxelAtCursorModel()))
+    {
+    this->RebuildVoxelTable();
+    }
+  else if(bucket.HasEvent(DomainDescriptionChangedEvent(), m_Model->GetVoxelAtCursorModel()))
+    {
+    this->UpdateVoxelTable();
+    }
+}
+
+void CursorInspector::on_tableVoxelUnderCursor_clicked(const QModelIndex &index)
+{
+  // When the user clicks on an item, that item will become the visible one
+  int item_row = index.row();
+  if(item_row >= 0)
+    {
+    // Find the corresponding layer
+    LayerIterator it =
+        m_Model->GetParent()->GetLoadedLayersSelectionModel()->GetNthLayer(item_row);
+
+    if(!it.GetLayer()->IsSticky())
+      m_Model->GetParent()->GetDriver()->GetGlobalState()->SetSelectedLayerId(
+            it.GetLayer()->GetUniqueId());
+    }
+
+}
diff --git a/GUI/Qt/Components/CursorInspector.h b/GUI/Qt/Components/CursorInspector.h
index 09b6dfa..590a719 100644
--- a/GUI/Qt/Components/CursorInspector.h
+++ b/GUI/Qt/Components/CursorInspector.h
@@ -3,10 +3,11 @@
 
 #include "SNAPComponent.h"
 
-
-class QMenu;
 class CursorInspectionModel;
-class QtScriptTest1;
+class QTableWidgetItem;
+class QStandardItemModel;
+class QModelIndex;
+struct LayerCurrentVoxelInfo;
 
 namespace Ui {
     class CursorInspector;
@@ -29,17 +30,22 @@ public slots:
 
 protected:
 
+  void RebuildVoxelTable();
+  void UpdateVoxelTable();
 
+  void UpdateVoxelTableRow(int i, const LayerCurrentVoxelInfo &vi);
 private slots:
-  void on_actionAutoContrast_triggered();
+
+  void onModelUpdate(const EventBucket &bucket);
+
+  void on_tableVoxelUnderCursor_clicked(const QModelIndex &index);
 
 private:
   Ui::CursorInspector *ui;
-  friend class QtScriptTest1;
-
 
   CursorInspectionModel *m_Model;
-  QMenu *m_ContextMenu;
+
+  QStandardItemModel *m_CurrentVoxelItemModel;
 
   int m_PopupRow;
 };
diff --git a/GUI/Qt/Components/CursorInspector.ui b/GUI/Qt/Components/CursorInspector.ui
index 612f1dd..992676f 100644
--- a/GUI/Qt/Components/CursorInspector.ui
+++ b/GUI/Qt/Components/CursorInspector.ui
@@ -6,7 +6,7 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>179</width>
+    <width>256</width>
     <height>527</height>
    </rect>
   </property>
@@ -21,10 +21,29 @@ font-size: 12px;
 QSpinBox {
 font-size: 11px;
 }
-</string>
+
+QLineEdit {
+font-size: 11px;
+}
+
+QComboBox {
+font-size: 11px;
+}</string>
   </property>
   <layout class="QVBoxLayout" name="verticalLayout">
-   <property name="margin">
+   <property name="spacing">
+    <number>2</number>
+   </property>
+   <property name="leftMargin">
+    <number>0</number>
+   </property>
+   <property name="topMargin">
+    <number>0</number>
+   </property>
+   <property name="rightMargin">
+    <number>0</number>
+   </property>
+   <property name="bottomMargin">
     <number>0</number>
    </property>
    <item>
@@ -32,27 +51,22 @@ font-size: 11px;
      <property name="font">
       <font>
        <pointsize>-1</pointsize>
-       <weight>75</weight>
-       <bold>true</bold>
       </font>
      </property>
      <property name="styleSheet">
-      <string notr="true">font-weight:bold;</string>
+      <string notr="true"/>
      </property>
      <property name="text">
-      <string>Cursor position</string>
+      <string>Cursor position (x,y,z):</string>
      </property>
     </widget>
    </item>
    <item>
-    <layout class="QGridLayout" name="gridLayout">
-     <property name="horizontalSpacing">
-      <number>6</number>
-     </property>
-     <property name="verticalSpacing">
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <property name="spacing">
       <number>4</number>
      </property>
-     <item row="1" column="0">
+     <item>
       <widget class="QSpinBox" name="inCursorX">
        <property name="sizePolicy">
         <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
@@ -66,12 +80,15 @@ font-size: 11px;
          <height>16777215</height>
         </size>
        </property>
+       <property name="toolTip">
+        <string><html><head/><body><p><span style=" font-weight:600;">Cursor X coordinate</span></p><p>The X coordinate of the 3D cursor, in the image coordinate system (corresponds to columns of voxels). The first column has index 1 (one-based indexing).</p></body></html></string>
+       </property>
        <property name="buttonSymbols">
         <enum>QAbstractSpinBox::NoButtons</enum>
        </property>
       </widget>
      </item>
-     <item row="1" column="1">
+     <item>
       <widget class="QSpinBox" name="inCursorY">
        <property name="sizePolicy">
         <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
@@ -91,12 +108,15 @@ font-size: 11px;
          <height>16777215</height>
         </size>
        </property>
+       <property name="toolTip">
+        <string><html><head/><body><p><span style=" font-weight:600;">Cursor Y coordinate</span></p><p>The Y coordinate of the 3D cursor, in the image coordinate system (corresponds to rows of voxels). The first row has index 1 (one-based indexing).</p></body></html></string>
+       </property>
        <property name="buttonSymbols">
         <enum>QAbstractSpinBox::NoButtons</enum>
        </property>
       </widget>
      </item>
-     <item row="1" column="2">
+     <item>
       <widget class="QSpinBox" name="inCursorZ">
        <property name="sizePolicy">
         <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
@@ -110,80 +130,75 @@ font-size: 11px;
          <height>16777215</height>
         </size>
        </property>
+       <property name="toolTip">
+        <string><html><head/><body><p><span style=" font-weight:600;">Cursor Z coordinate</span></p><p>The Z coordinate of the 3D cursor, in the image coordinate system (corresponds to slices of voxels). The first slice has index 1 (one-based indexing).</p></body></html></string>
+       </property>
        <property name="buttonSymbols">
         <enum>QAbstractSpinBox::NoButtons</enum>
        </property>
       </widget>
      </item>
-     <item row="0" column="0">
-      <widget class="QLabel" name="label_2">
-       <property name="text">
-        <string>x:</string>
-       </property>
-      </widget>
-     </item>
-     <item row="0" column="1">
-      <widget class="QLabel" name="label_3">
-       <property name="text">
-        <string>y:</string>
-       </property>
-      </widget>
-     </item>
-     <item row="0" column="2">
-      <widget class="QLabel" name="label_4">
-       <property name="text">
-        <string>z:</string>
-       </property>
-      </widget>
-     </item>
     </layout>
    </item>
    <item>
-    <widget class="Line" name="line">
-     <property name="frameShadow">
-      <enum>QFrame::Plain</enum>
-     </property>
+    <spacer name="verticalSpacer_2">
      <property name="orientation">
-      <enum>Qt::Horizontal</enum>
+      <enum>Qt::Vertical</enum>
      </property>
-    </widget>
+     <property name="sizeType">
+      <enum>QSizePolicy::Fixed</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>20</width>
+       <height>6</height>
+      </size>
+     </property>
+    </spacer>
    </item>
    <item>
     <widget class="QLabel" name="label_5">
      <property name="font">
       <font>
        <pointsize>-1</pointsize>
-       <weight>75</weight>
-       <bold>true</bold>
       </font>
      </property>
      <property name="styleSheet">
-      <string notr="true">font-weight:bold;</string>
+      <string notr="true"/>
      </property>
      <property name="text">
-      <string>Intensity under cursor</string>
+      <string>Intensity under cursor:</string>
      </property>
     </widget>
    </item>
    <item>
-    <widget class="QTableWidget" name="tableVoxelUnderCursor">
-     <property name="minimumSize">
-      <size>
-       <width>162</width>
-       <height>0</height>
-      </size>
+    <spacer name="verticalSpacer_3">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeType">
+      <enum>QSizePolicy::Fixed</enum>
      </property>
-     <property name="maximumSize">
+     <property name="sizeHint" stdset="0">
       <size>
-       <width>185</width>
-       <height>120</height>
+       <width>20</width>
+       <height>6</height>
       </size>
      </property>
-     <property name="contextMenuPolicy">
-      <enum>Qt::CustomContextMenu</enum>
-     </property>
+    </spacer>
+   </item>
+   <item>
+    <widget class="QTableView" name="tableVoxelUnderCursor">
      <property name="styleSheet">
-      <string notr="true">font-size:10px;</string>
+      <string notr="true">QTableView
+{
+  font-size:10px;
+}
+
+QTableView:!active
+{
+  selection-background-color: rgb(162, 204, 255);
+}</string>
      </property>
      <property name="editTriggers">
       <set>QAbstractItemView::NoEditTriggers</set>
@@ -197,14 +212,20 @@ font-size: 11px;
      <property name="selectionBehavior">
       <enum>QAbstractItemView::SelectRows</enum>
      </property>
-     <attribute name="horizontalHeaderCascadingSectionResizes">
+     <property name="iconSize">
+      <size>
+       <width>12</width>
+       <height>12</height>
+      </size>
+     </property>
+     <property name="textElideMode">
+      <enum>Qt::ElideRight</enum>
+     </property>
+     <attribute name="horizontalHeaderHighlightSections">
       <bool>false</bool>
      </attribute>
-     <attribute name="horizontalHeaderDefaultSectionSize">
-      <number>75</number>
-     </attribute>
-     <attribute name="horizontalHeaderStretchLastSection">
-      <bool>true</bool>
+     <attribute name="horizontalHeaderMinimumSectionSize">
+      <number>48</number>
      </attribute>
      <attribute name="verticalHeaderVisible">
       <bool>false</bool>
@@ -212,26 +233,9 @@ font-size: 11px;
      <attribute name="verticalHeaderDefaultSectionSize">
       <number>16</number>
      </attribute>
-     <column>
-      <property name="text">
-       <string>Layer</string>
-      </property>
-     </column>
-     <column>
-      <property name="text">
-       <string>Intensity</string>
-      </property>
-     </column>
-    </widget>
-   </item>
-   <item>
-    <widget class="Line" name="line_3">
-     <property name="frameShadow">
-      <enum>QFrame::Plain</enum>
-     </property>
-     <property name="orientation">
-      <enum>Qt::Horizontal</enum>
-     </property>
+     <attribute name="verticalHeaderMinimumSectionSize">
+      <number>16</number>
+     </attribute>
     </widget>
    </item>
    <item>
@@ -239,74 +243,50 @@ font-size: 11px;
      <property name="font">
       <font>
        <pointsize>-1</pointsize>
-       <weight>75</weight>
-       <bold>true</bold>
       </font>
      </property>
      <property name="styleSheet">
-      <string notr="true">font-weight:bold;</string>
+      <string notr="true"/>
      </property>
      <property name="text">
-      <string>Label under cursor</string>
+      <string>Label under cursor:</string>
      </property>
     </widget>
    </item>
    <item>
-    <layout class="QGridLayout" name="gridLayout_2">
+    <layout class="QHBoxLayout" name="horizontalLayout_2">
      <property name="spacing">
-      <number>6</number>
+      <number>4</number>
      </property>
-     <item row="1" column="1">
-      <widget class="QLineEdit" name="outLabelText">
-       <property name="readOnly">
-        <bool>true</bool>
-       </property>
-      </widget>
-     </item>
-     <item row="0" column="0">
-      <widget class="QLabel" name="label_7">
-       <property name="maximumSize">
-        <size>
-         <width>16777215</width>
-         <height>16777215</height>
-        </size>
-       </property>
-       <property name="text">
-        <string>Id:</string>
-       </property>
-       <property name="alignment">
-        <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
-       </property>
-      </widget>
-     </item>
-     <item row="1" column="0">
+     <item>
       <widget class="QSpinBox" name="outLabelId">
        <property name="maximumSize">
         <size>
-         <width>60</width>
+         <width>50</width>
          <height>16777215</height>
         </size>
        </property>
+       <property name="toolTip">
+        <string><html><head/><body><p><span style=" font-weight:600;">Index of label under cursor</span></p><p>This shows the numerical value of the segmentation label under the cursor. When you save the segmentation as an image, these values are stored in the voxels of the saved image.</p></body></html></string>
+       </property>
        <property name="readOnly">
         <bool>true</bool>
        </property>
        <property name="buttonSymbols">
         <enum>QAbstractSpinBox::NoButtons</enum>
        </property>
+       <property name="maximum">
+        <number>65536</number>
+       </property>
       </widget>
      </item>
-     <item row="0" column="1">
-      <widget class="QLabel" name="label_8">
-       <property name="font">
-        <font>
-         <pointsize>-1</pointsize>
-        </font>
-       </property>
-       <property name="styleSheet">
-        <string notr="true"/>
+     <item>
+      <widget class="QLineEdit" name="outLabelText">
+       <property name="toolTip">
+        <string><html><head/><body><p><span style=" font-weight:600;">Name of label under cursor</span></p><p>This shows the name assigned to the segmentation label under the cursor. Use the label editor to modify label names.</p></body></html></string>
        </property>
-       <property name="text">
-        <string>Description:</string>
+       <property name="readOnly">
+        <bool>true</bool>
        </property>
       </widget>
      </item>
@@ -326,14 +306,6 @@ font-size: 11px;
     </spacer>
    </item>
   </layout>
-  <action name="actionAutoContrast">
-   <property name="text">
-    <string>Auto-Adjust Contrast</string>
-   </property>
-   <property name="toolTip">
-    <string>Sets the contrast of a grayscale image automatically.</string>
-   </property>
-  </action>
  </widget>
  <tabstops>
   <tabstop>inCursorX</tabstop>
diff --git a/GUI/Qt/Components/DisplayLayoutInspector.cxx b/GUI/Qt/Components/DisplayLayoutInspector.cxx
index 7a7f117..36377ec 100644
--- a/GUI/Qt/Components/DisplayLayoutInspector.cxx
+++ b/GUI/Qt/Components/DisplayLayoutInspector.cxx
@@ -2,6 +2,8 @@
 #include "ui_DisplayLayoutInspector.h"
 #include "DisplayLayoutModel.h"
 #include <QtRadioButtonCoupling.h>
+#include <QtDoubleSpinBoxCoupling.h>
+#include "GlobalUIModel.h"
 
 DisplayLayoutInspector::DisplayLayoutInspector(QWidget *parent) :
   QWidget(parent),
@@ -32,4 +34,11 @@ void DisplayLayoutInspector::SetModel(DisplayLayoutModel *model)
   // Couple the radio buttons for layer layout
   makeRadioGroupCoupling(ui->grpLayerLayout,
                          m_Model->GetSliceViewLayerLayoutModel());
+
+  // Couple the thumbnail size control
+  makeCoupling(ui->inThumbSize, m_Model->GetThumbnailRelativeSizeModel());
+
+  // Tile/thumb controls deactivated for single image
+  activateOnFlag(ui->grpLayerLayout, m_Model->GetParentModel(), UIF_MULTIPLE_BASE_LAYERS);
+  activateOnFlag(ui->grpThumbnailSize, m_Model->GetParentModel(), UIF_MULTIPLE_BASE_LAYERS);
 }
diff --git a/GUI/Qt/Components/DisplayLayoutInspector.ui b/GUI/Qt/Components/DisplayLayoutInspector.ui
index 35aa408..b232ca5 100644
--- a/GUI/Qt/Components/DisplayLayoutInspector.ui
+++ b/GUI/Qt/Components/DisplayLayoutInspector.ui
@@ -20,7 +20,19 @@ font-size: 12px;
 </string>
   </property>
   <layout class="QVBoxLayout" name="verticalLayout">
-   <property name="margin">
+   <property name="spacing">
+    <number>4</number>
+   </property>
+   <property name="leftMargin">
+    <number>0</number>
+   </property>
+   <property name="topMargin">
+    <number>0</number>
+   </property>
+   <property name="rightMargin">
+    <number>0</number>
+   </property>
+   <property name="bottomMargin">
     <number>0</number>
    </property>
    <item>
@@ -28,12 +40,10 @@ font-size: 12px;
      <property name="font">
       <font>
        <pointsize>-1</pointsize>
-       <weight>75</weight>
-       <bold>true</bold>
       </font>
      </property>
      <property name="styleSheet">
-      <string notr="true">font-weight:bold;</string>
+      <string notr="true"/>
      </property>
      <property name="text">
       <string>Display Layout:</string>
@@ -50,7 +60,7 @@ font-size: 12px;
        <enum>QLayout::SetMaximumSize</enum>
       </property>
       <property name="leftMargin">
-       <number>0</number>
+       <number>16</number>
       </property>
       <property name="topMargin">
        <number>0</number>
@@ -59,7 +69,7 @@ font-size: 12px;
        <number>0</number>
       </property>
       <property name="bottomMargin">
-       <number>12</number>
+       <number>4</number>
       </property>
       <item>
        <widget class="QToolButton" name="btnFourViews">
@@ -70,7 +80,7 @@ font-size: 12px;
          </size>
         </property>
         <property name="toolTip">
-         <string>All four views</string>
+         <string><html><head/><body><p>Show three orthogonal slice views and the 3D view.</p></body></html></string>
         </property>
         <property name="text">
          <string>...</string>
@@ -97,7 +107,7 @@ font-size: 12px;
          </size>
         </property>
         <property name="toolTip">
-         <string>Axial view</string>
+         <string>Only show the axial view.</string>
         </property>
         <property name="text">
          <string>...</string>
@@ -124,7 +134,7 @@ font-size: 12px;
          </size>
         </property>
         <property name="toolTip">
-         <string>Coronal view</string>
+         <string>Only show the coronal view.</string>
         </property>
         <property name="text">
          <string>...</string>
@@ -151,7 +161,7 @@ font-size: 12px;
          </size>
         </property>
         <property name="toolTip">
-         <string>Sagittal view</string>
+         <string>Only show the sagittal view.</string>
         </property>
         <property name="text">
          <string>...</string>
@@ -178,7 +188,7 @@ font-size: 12px;
          </size>
         </property>
         <property name="toolTip">
-         <string>3D view</string>
+         <string>Only show the 3D view.</string>
         </property>
         <property name="text">
          <string>...</string>
@@ -217,15 +227,13 @@ font-size: 12px;
      <property name="font">
       <font>
        <pointsize>-1</pointsize>
-       <weight>75</weight>
-       <bold>true</bold>
       </font>
      </property>
      <property name="styleSheet">
-      <string notr="true">font-weight:bold;</string>
+      <string notr="true"/>
      </property>
      <property name="text">
-      <string>Overlay Placement:</string>
+      <string>Multiple Image Layers:</string>
      </property>
     </widget>
    </item>
@@ -236,27 +244,39 @@ font-size: 12px;
        <pointsize>-1</pointsize>
       </font>
      </property>
-     <layout class="QHBoxLayout" name="horizontalLayout_2">
+     <layout class="QVBoxLayout" name="verticalLayout_2">
       <property name="spacing">
        <number>4</number>
       </property>
-      <property name="margin">
+      <property name="leftMargin">
+       <number>16</number>
+      </property>
+      <property name="topMargin">
+       <number>0</number>
+      </property>
+      <property name="rightMargin">
+       <number>0</number>
+      </property>
+      <property name="bottomMargin">
        <number>0</number>
       </property>
       <item>
-       <widget class="QToolButton" name="btnStack">
+       <widget class="QToolButton" name="btnTile">
         <property name="minimumSize">
          <size>
-          <width>72</width>
+          <width>140</width>
           <height>0</height>
          </size>
         </property>
+        <property name="toolTip">
+         <string><html><head/><body><p>In <span style=" font-weight:600;">tiled</span> layout, multiple image layers are shown side by side.</p></body></html></string>
+        </property>
         <property name="text">
-         <string>Stack</string>
+         <string>Tiled layout</string>
         </property>
         <property name="icon">
          <iconset resource="../Resources/SNAPResources.qrc">
-          <normaloff>:/root/layout_overlay_16.png</normaloff>:/root/layout_overlay_16.png</iconset>
+          <normaloff>:/root/layout_tile_16.png</normaloff>:/root/layout_tile_16.png</iconset>
         </property>
         <property name="checkable">
          <bool>true</bool>
@@ -270,19 +290,28 @@ font-size: 12px;
        </widget>
       </item>
       <item>
-       <widget class="QToolButton" name="btnTile">
+       <widget class="QToolButton" name="btnStack">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
         <property name="minimumSize">
          <size>
-          <width>72</width>
+          <width>140</width>
           <height>0</height>
          </size>
         </property>
+        <property name="toolTip">
+         <string><html><head/><body><p>In <span style=" font-weight:600;">thumbnail</span> layout, one image layer occupies most of the available screen space, and other loaded image layers are shown as thumbnails.</p></body></html></string>
+        </property>
         <property name="text">
-         <string>Tile</string>
+         <string>Thumbnail layout</string>
         </property>
         <property name="icon">
          <iconset resource="../Resources/SNAPResources.qrc">
-          <normaloff>:/root/layout_tile_16.png</normaloff>:/root/layout_tile_16.png</iconset>
+          <normaloff>:/root/layout_thumb_16.png</normaloff>:/root/layout_thumb_16.png</iconset>
         </property>
         <property name="checkable">
          <bool>true</bool>
@@ -295,6 +324,46 @@ font-size: 12px;
         </property>
        </widget>
       </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QLabel" name="label_3">
+     <property name="font">
+      <font>
+       <pointsize>-1</pointsize>
+      </font>
+     </property>
+     <property name="styleSheet">
+      <string notr="true"/>
+     </property>
+     <property name="text">
+      <string>Thumbnail Size:</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QWidget" name="grpThumbnailSize" native="true">
+     <layout class="QHBoxLayout" name="horizontalLayout_2">
+      <property name="leftMargin">
+       <number>16</number>
+      </property>
+      <property name="topMargin">
+       <number>0</number>
+      </property>
+      <property name="rightMargin">
+       <number>0</number>
+      </property>
+      <property name="bottomMargin">
+       <number>0</number>
+      </property>
+      <item>
+       <widget class="QDoubleSpinBox" name="inThumbSize">
+        <property name="toolTip">
+         <string><html><head/><body><p>Set the size of the thumbnails relative to window size.</p></body></html></string>
+        </property>
+       </widget>
+      </item>
       <item>
        <spacer name="horizontalSpacer_2">
         <property name="orientation">
diff --git a/GUI/Qt/Components/FileChooserPanelWithHistory.cxx b/GUI/Qt/Components/FileChooserPanelWithHistory.cxx
index f9d5189..1d1d4fc 100644
--- a/GUI/Qt/Components/FileChooserPanelWithHistory.cxx
+++ b/GUI/Qt/Components/FileChooserPanelWithHistory.cxx
@@ -107,7 +107,7 @@ void FileChooserPanelWithHistory::parseFilters(const QString &activeFormat)
     }
 
   // Update the combo box
-  ui->inFormat->setCurrentText(m_defaultFormat);
+  this->setCurrentFormatText(m_defaultFormat);
 
   // Show or hide the format panel depending on the number of formats available
   ui->panelFormat->setVisible(m_Filter.size() > 1);
@@ -525,6 +525,20 @@ QString FileChooserPanelWithHistory::guessFormat(const QString &text)
   return newFormat;
 }
 
+void FileChooserPanelWithHistory::setCurrentFormatText(const QString &format)
+{
+#if QT_VERSION >= 0x050000
+  ui->inFormat->setCurrentText(format);
+#else
+  for(int i = 0; i < ui->inFormat->count(); i++)
+    if(ui->inFormat->itemText(i) == format)
+      {
+      ui->inFormat->setCurrentIndex(i);
+      break;
+      }
+#endif
+}
+
 void FileChooserPanelWithHistory::on_inFilename_textChanged(const QString &text)
 {
   // The filename has changed. The first thing we do is to see if the filename has
@@ -534,7 +548,7 @@ void FileChooserPanelWithHistory::on_inFilename_textChanged(const QString &text)
   if(format.length())
     {
     m_defaultFormat = format;
-    ui->inFormat->setCurrentText(format);
+    this->setCurrentFormatText(format);
     emit activeFormatChanged(format);
     }
 
diff --git a/GUI/Qt/Components/FileChooserPanelWithHistory.h b/GUI/Qt/Components/FileChooserPanelWithHistory.h
index e7fb53c..f55c5ef 100644
--- a/GUI/Qt/Components/FileChooserPanelWithHistory.h
+++ b/GUI/Qt/Components/FileChooserPanelWithHistory.h
@@ -120,6 +120,7 @@ private:
   QObject *m_oracleTarget;
   const char *m_oracleSlot;
   QString guessFormat(const QString &text);
+  void setCurrentFormatText(const QString &format);
 };
 
 #endif // FILECHOOSERPANELWITHHISTORY_H
diff --git a/GUI/Qt/Components/GeneralLayerInspector.cxx b/GUI/Qt/Components/GeneralLayerInspector.cxx
index d80886a..2441910 100644
--- a/GUI/Qt/Components/GeneralLayerInspector.cxx
+++ b/GUI/Qt/Components/GeneralLayerInspector.cxx
@@ -8,8 +8,10 @@
 #include "QtSpinBoxCoupling.h"
 #include "QtSliderCoupling.h"
 #include "QtLineEditCoupling.h"
+#include "QtAbstractButtonCoupling.h"
 
 #include "QtWidgetActivator.h"
+#include "QtRadioButtonCoupling.h"
 
 Q_DECLARE_METATYPE(LayerGeneralPropertiesModel::DisplayMode)
 
@@ -33,23 +35,49 @@ void GeneralLayerInspector::SetModel(LayerGeneralPropertiesModel *model)
   makeCoupling(ui->inMode, m_Model->GetDisplayModeModel());
   makeCoupling(ui->inComponent, m_Model->GetSelectedComponentModel());
   makeCoupling(ui->inComponentSlider, m_Model->GetSelectedComponentModel());
-  makeCoupling(ui->chkAnimate, m_Model->GetAnimateModel());
+  makeCoupling((QAbstractButton *)ui->btnAnimate, m_Model->GetAnimateModel());
+
+  // Couple the pin/unpin buttons
+  std::map<bool, QAbstractButton *> button_map;
+  button_map[true] = ui->btnPin;
+  button_map[false] = ui->btnUnpin;
+  makeCheckableWidgetGroupCoupling(ui->grpOverlayChecks, button_map, m_Model->GetIsStickyModel());
 
   makeCoupling(ui->inOpacity, m_Model->GetLayerOpacityModel());
   makeCoupling(ui->inOpacityValue, m_Model->GetLayerOpacityModel());
-  makeCoupling(ui->chkVisible, m_Model->GetLayerVisibilityModel());
+  makeCoupling((QAbstractButton *)ui->btnVisible, m_Model->GetLayerVisibilityModel());
 
   makeCoupling(ui->outFilename, m_Model->GetFilenameModel());
   makeCoupling(ui->inNickname, m_Model->GetNicknameModel());
 
   activateOnFlag(ui->grpMulticomponent, m_Model,
-                 LayerGeneralPropertiesModel::UIF_MULTICOMPONENT);
+                 LayerGeneralPropertiesModel::UIF_MULTICOMPONENT,
+                 QtWidgetActivator::HideInactive);
 
-  activateOnFlag(ui->chkAnimate, m_Model,
-                 LayerGeneralPropertiesModel::UIF_CAN_SWITCH_COMPONENTS);
-  activateOnFlag(ui->inComponent, m_Model,
-                 LayerGeneralPropertiesModel::UIF_CAN_SWITCH_COMPONENTS);
-  activateOnFlag(ui->inComponentSlider, m_Model,
+  activateOnFlag(ui->grpComponent, m_Model,
                  LayerGeneralPropertiesModel::UIF_CAN_SWITCH_COMPONENTS);
 
+  activateOnFlag(ui->grpSecondary, m_Model,
+                 LayerGeneralPropertiesModel::UIF_IS_STICKINESS_EDITABLE,
+                 QtWidgetActivator::HideInactive);
+
+  activateOnFlag(ui->grpOpacity, m_Model,
+                 LayerGeneralPropertiesModel::UIF_IS_OPACITY_EDITABLE);
+  activateOnFlag(ui->lblOpacity, m_Model,
+                 LayerGeneralPropertiesModel::UIF_IS_OPACITY_EDITABLE);
+
+  activateOnFlag(ui->btnUp, m_Model,
+                 LayerGeneralPropertiesModel::UIF_MOVABLE_UP);
+  activateOnFlag(ui->btnDown, m_Model,
+                 LayerGeneralPropertiesModel::UIF_MOVABLE_DOWN);
+}
+
+void GeneralLayerInspector::on_btnUp_clicked()
+{
+  m_Model->MoveLayerUp();
+}
+
+void GeneralLayerInspector::on_btnDown_clicked()
+{
+  m_Model->MoveLayerDown();
 }
diff --git a/GUI/Qt/Components/GeneralLayerInspector.h b/GUI/Qt/Components/GeneralLayerInspector.h
index cb33e7c..fd52a3c 100644
--- a/GUI/Qt/Components/GeneralLayerInspector.h
+++ b/GUI/Qt/Components/GeneralLayerInspector.h
@@ -20,6 +20,10 @@ public:
 
   void SetModel(LayerGeneralPropertiesModel *model);
   
+private slots:
+  void on_btnUp_clicked();
+  void on_btnDown_clicked();
+
 private:
   Ui::GeneralLayerInspector *ui;
 
diff --git a/GUI/Qt/Components/GeneralLayerInspector.ui b/GUI/Qt/Components/GeneralLayerInspector.ui
index 249b771..072e4d6 100644
--- a/GUI/Qt/Components/GeneralLayerInspector.ui
+++ b/GUI/Qt/Components/GeneralLayerInspector.ui
@@ -6,8 +6,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>429</width>
-    <height>449</height>
+    <width>448</width>
+    <height>612</height>
    </rect>
   </property>
   <property name="windowTitle">
@@ -26,6 +26,9 @@
   border-radius: 4px;
   border: 1px solid rgb(130,130,130);
 }
+QGroupBox:!enabled {
+  color: rgb(108,108,108);
+}
 QGroupBox::title {
   subcontrol-origin: 	margin;
   subcontrol-position: top left;
@@ -33,7 +36,7 @@ QGroupBox::title {
   </property>
   <layout class="QVBoxLayout" name="verticalLayout_2">
    <property name="spacing">
-    <number>12</number>
+    <number>18</number>
    </property>
    <property name="leftMargin">
     <number>6</number>
@@ -49,45 +52,134 @@ QGroupBox::title {
    </property>
    <item>
     <widget class="QGroupBox" name="grpInfo">
+     <property name="enabled">
+      <bool>true</bool>
+     </property>
+     <property name="styleSheet">
+      <string notr="true">QToolButton {
+font-size:11px;
+}</string>
+     </property>
      <property name="title">
-      <string>General Information</string>
+      <string>General Image Layer Properties:</string>
      </property>
-     <layout class="QGridLayout" name="gridLayout_2">
-      <property name="margin">
+     <layout class="QGridLayout" name="gridLayout_3" rowstretch="0,0">
+      <property name="leftMargin">
+       <number>6</number>
+      </property>
+      <property name="topMargin">
+       <number>4</number>
+      </property>
+      <property name="rightMargin">
+       <number>6</number>
+      </property>
+      <property name="bottomMargin">
+       <number>4</number>
+      </property>
+      <property name="horizontalSpacing">
        <number>6</number>
       </property>
+      <property name="verticalSpacing">
+       <number>8</number>
+      </property>
       <item row="1" column="1">
        <widget class="QLineEdit" name="inNickname">
         <property name="toolTip">
-         <string>This is the name that is used when referring to the image in ITK-SNAP.</string>
+         <string><html><head/><body><p>Edit this field to assign a short nickname to this image. This information can be saved in the workspace. </p></body></html></string>
         </property>
        </widget>
       </item>
-      <item row="1" column="0">
-       <widget class="QLabel" name="label_4">
+      <item row="0" column="0">
+       <widget class="QLabel" name="label_5">
         <property name="text">
-         <string>Nickname:</string>
+         <string>Filename:</string>
         </property>
        </widget>
       </item>
       <item row="0" column="1">
        <widget class="QLineEdit" name="outFilename">
+        <property name="toolTip">
+         <string><html><head/><body><p>This is the filename from which the image was loaded. This is a read-only field.  However, you can save the image to a different file using this dialog.</p></body></html></string>
+        </property>
         <property name="readOnly">
          <bool>true</bool>
         </property>
        </widget>
       </item>
-      <item row="2" column="1">
-       <widget class="QWidget" name="widget" native="true">
-        <layout class="QHBoxLayout" name="horizontalLayout">
+      <item row="1" column="0">
+       <widget class="QLabel" name="label_6">
+        <property name="text">
+         <string>Nickname:</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="grpSecondary">
+     <property name="enabled">
+      <bool>true</bool>
+     </property>
+     <property name="styleSheet">
+      <string notr="true">QToolButton {
+font-size:11px;
+}</string>
+     </property>
+     <property name="title">
+      <string>How to Display this Image Layer:</string>
+     </property>
+     <layout class="QGridLayout" name="gridLayout_2" rowstretch="0,0,0,0" columnminimumwidth="105,0">
+      <property name="leftMargin">
+       <number>6</number>
+      </property>
+      <property name="topMargin">
+       <number>4</number>
+      </property>
+      <property name="rightMargin">
+       <number>6</number>
+      </property>
+      <property name="bottomMargin">
+       <number>4</number>
+      </property>
+      <property name="horizontalSpacing">
+       <number>6</number>
+      </property>
+      <property name="verticalSpacing">
+       <number>8</number>
+      </property>
+      <item row="1" column="1">
+       <widget class="QWidget" name="grpOpacity" native="true">
+        <property name="styleSheet">
+         <string notr="true">font-size:12pt;</string>
+        </property>
+        <layout class="QHBoxLayout" name="horizontalLayout_4">
          <property name="spacing">
-          <number>12</number>
+          <number>4</number>
+         </property>
+         <property name="leftMargin">
+          <number>0</number>
+         </property>
+         <property name="topMargin">
+          <number>0</number>
+         </property>
+         <property name="rightMargin">
+          <number>0</number>
          </property>
-         <property name="margin">
+         <property name="bottomMargin">
           <number>0</number>
          </property>
          <item>
           <widget class="QSpinBox" name="inOpacityValue">
+           <property name="minimumSize">
+            <size>
+             <width>80</width>
+             <height>0</height>
+            </size>
+           </property>
+           <property name="toolTip">
+            <string><html><head/><body><p>Adjust the opacity of the image when it is displayed as a semi-transparent overlay.</p></body></html></string>
+           </property>
            <property name="buttonSymbols">
             <enum>QAbstractSpinBox::NoButtons</enum>
            </property>
@@ -101,6 +193,9 @@ QGroupBox::title {
          </item>
          <item>
           <widget class="QSlider" name="inOpacity">
+           <property name="toolTip">
+            <string><html><head/><body><p>Adjust the opacity of the image when it is displayed as a semi-transparent overlay.</p></body></html></string>
+           </property>
            <property name="maximum">
             <number>100</number>
            </property>
@@ -108,7 +203,7 @@ QGroupBox::title {
             <enum>Qt::Horizontal</enum>
            </property>
            <property name="tickPosition">
-            <enum>QSlider::TicksBelow</enum>
+            <enum>QSlider::NoTicks</enum>
            </property>
            <property name="tickInterval">
             <number>25</number>
@@ -116,9 +211,212 @@ QGroupBox::title {
           </widget>
          </item>
          <item>
-          <widget class="QCheckBox" name="chkVisible">
+          <widget class="QToolButton" name="btnVisible">
+           <property name="maximumSize">
+            <size>
+             <width>20</width>
+             <height>20</height>
+            </size>
+           </property>
+           <property name="toolTip">
+            <string><html><head/><body><p>Toggle the visibility of the image when it is displayed as a semi-transparent overlay.</p></body></html></string>
+           </property>
            <property name="text">
-            <string>Visible</string>
+            <string>...</string>
+           </property>
+           <property name="icon">
+            <iconset resource="../Resources/SNAPResources.qrc">
+             <normaloff>:/root/icons8_invisible_12.png</normaloff>
+             <normalon>:/root/icons8_visible_12.png</normalon>:/root/icons8_invisible_12.png</iconset>
+           </property>
+           <property name="iconSize">
+            <size>
+             <width>12</width>
+             <height>12</height>
+            </size>
+           </property>
+           <property name="checkable">
+            <bool>true</bool>
+           </property>
+           <property name="checked">
+            <bool>true</bool>
+           </property>
+           <property name="autoRaise">
+            <bool>true</bool>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </widget>
+      </item>
+      <item row="0" column="1">
+       <widget class="QWidget" name="grpOverlayChecks" native="true">
+        <property name="styleSheet">
+         <string notr="true"/>
+        </property>
+        <layout class="QHBoxLayout" name="horizontalLayout_5" stretch="1,1">
+         <property name="spacing">
+          <number>6</number>
+         </property>
+         <property name="leftMargin">
+          <number>0</number>
+         </property>
+         <property name="topMargin">
+          <number>0</number>
+         </property>
+         <property name="rightMargin">
+          <number>0</number>
+         </property>
+         <property name="bottomMargin">
+          <number>0</number>
+         </property>
+         <item>
+          <widget class="QToolButton" name="btnUnpin">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="toolTip">
+            <string><html><head/><body><p><span style=" font-size:11pt;">Display this image side by side with the main image.</span></p><p><br/></p><p><span style=" font-size:11pt;">This optoin is best suited for anatomical images, e.g., when displaying T1-weighted and T2-weighted MRI scans of the same subject.</span></p></body></html></string>
+           </property>
+           <property name="text">
+            <string>Separate image</string>
+           </property>
+           <property name="icon">
+            <iconset resource="../Resources/SNAPResources.qrc">
+             <normaloff>:/root/icons8_unpin_12.png</normaloff>:/root/icons8_unpin_12.png</iconset>
+           </property>
+           <property name="iconSize">
+            <size>
+             <width>12</width>
+             <height>12</height>
+            </size>
+           </property>
+           <property name="checkable">
+            <bool>true</bool>
+           </property>
+           <property name="checked">
+            <bool>true</bool>
+           </property>
+           <property name="autoExclusive">
+            <bool>true</bool>
+           </property>
+           <property name="toolButtonStyle">
+            <enum>Qt::ToolButtonTextBesideIcon</enum>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QToolButton" name="btnPin">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="toolTip">
+            <string><html><head/><body><p><span style=" font-size:11pt;">Display this image as a semi-transparent overlay over other images.</span></p><p><br/></p><p><span style=" font-size:11pt;">This option is best for statistical maps. You can control the overall opacity of the overlay in this window, or customize the color map for partial opacity effects. </span></p></body>&l [...]
+           </property>
+           <property name="text">
+            <string>Semi-transparent overlay</string>
+           </property>
+           <property name="icon">
+            <iconset resource="../Resources/SNAPResources.qrc">
+             <normaloff>:/root/icons8_pin_12.png</normaloff>:/root/icons8_pin_12.png</iconset>
+           </property>
+           <property name="iconSize">
+            <size>
+             <width>12</width>
+             <height>12</height>
+            </size>
+           </property>
+           <property name="checkable">
+            <bool>true</bool>
+           </property>
+           <property name="autoExclusive">
+            <bool>true</bool>
+           </property>
+           <property name="toolButtonStyle">
+            <enum>Qt::ToolButtonTextBesideIcon</enum>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </widget>
+      </item>
+      <item row="3" column="1">
+       <widget class="QWidget" name="widget" native="true">
+        <layout class="QHBoxLayout" name="horizontalLayout">
+         <property name="leftMargin">
+          <number>0</number>
+         </property>
+         <property name="topMargin">
+          <number>0</number>
+         </property>
+         <property name="rightMargin">
+          <number>0</number>
+         </property>
+         <property name="bottomMargin">
+          <number>0</number>
+         </property>
+         <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="QToolButton" name="btnUp">
+           <property name="toolTip">
+            <string><html><head/><body><p><span style=" font-size:11pt;">Place this image layer earlier in the workspace. This affects the order in which the layers are layed out and rendered. The order is most important when more than one semi-transparent overlay is loaded.</span></p></body></html></string>
+           </property>
+           <property name="text">
+            <string>Move up</string>
+           </property>
+           <property name="icon">
+            <iconset resource="../Resources/SNAPResources.qrc">
+             <normaloff>:/root/icons8_up_12.png</normaloff>:/root/icons8_up_12.png</iconset>
+           </property>
+           <property name="iconSize">
+            <size>
+             <width>12</width>
+             <height>12</height>
+            </size>
+           </property>
+           <property name="toolButtonStyle">
+            <enum>Qt::ToolButtonTextBesideIcon</enum>
+           </property>
+          </widget>
+         </item>
+         <item alignment="Qt::AlignRight">
+          <widget class="QToolButton" name="btnDown">
+           <property name="toolTip">
+            <string><html><head/><body><p><span style=" font-size:11pt;">Place this image layer later in the workspace. This affects the order in which the layers are layed out and rendered. The order is most important when more than one semi-transparent overlay is loaded.</span></p></body></html></string>
+           </property>
+           <property name="text">
+            <string>Move down</string>
+           </property>
+           <property name="icon">
+            <iconset resource="../Resources/SNAPResources.qrc">
+             <normaloff>:/root/icons8_down_12.png</normaloff>:/root/icons8_down_12.png</iconset>
+           </property>
+           <property name="iconSize">
+            <size>
+             <width>12</width>
+             <height>12</height>
+            </size>
+           </property>
+           <property name="toolButtonStyle">
+            <enum>Qt::ToolButtonTextBesideIcon</enum>
            </property>
           </widget>
          </item>
@@ -126,16 +424,48 @@ QGroupBox::title {
        </widget>
       </item>
       <item row="0" column="0">
-       <widget class="QLabel" name="label_3">
+       <widget class="QLabel" name="lblOverlayMode">
         <property name="text">
-         <string>Filename:</string>
+         <string>Display as:</string>
         </property>
        </widget>
       </item>
       <item row="2" column="0">
-       <widget class="QLabel" name="label_5">
+       <spacer name="verticalSpacer_2">
+        <property name="orientation">
+         <enum>Qt::Vertical</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Fixed</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>10</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item row="3" column="0">
+       <widget class="QLabel" name="label_9">
         <property name="text">
-         <string>Opacity:</string>
+         <string>Display order:</string>
+        </property>
+        <property name="wordWrap">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="0">
+       <widget class="QLabel" name="lblOpacity">
+        <property name="styleSheet">
+         <string notr="true"/>
+        </property>
+        <property name="text">
+         <string>Overlay opacity:</string>
+        </property>
+        <property name="wordWrap">
+         <bool>true</bool>
         </property>
        </widget>
       </item>
@@ -145,46 +475,136 @@ QGroupBox::title {
    <item>
     <widget class="QGroupBox" name="grpMulticomponent">
      <property name="title">
-      <string>Displaying Multiple Components per Voxel</string>
+      <string>How to Visualize Multiple Image Components:</string>
      </property>
-     <layout class="QGridLayout" name="gridLayout">
-      <property name="margin">
+     <layout class="QGridLayout" name="gridLayout" columnminimumwidth="105,0">
+      <property name="leftMargin">
+       <number>6</number>
+      </property>
+      <property name="topMargin">
+       <number>4</number>
+      </property>
+      <property name="rightMargin">
        <number>6</number>
       </property>
+      <property name="bottomMargin">
+       <number>4</number>
+      </property>
+      <property name="horizontalSpacing">
+       <number>6</number>
+      </property>
+      <property name="verticalSpacing">
+       <number>8</number>
+      </property>
       <item row="0" column="0">
        <widget class="QLabel" name="label">
         <property name="text">
-         <string>Display Mode:</string>
+         <string>Display mode:</string>
         </property>
        </widget>
       </item>
-      <item row="0" column="1" colspan="3">
-       <widget class="QComboBox" name="inMode"/>
+      <item row="0" column="1">
+       <widget class="QComboBox" name="inMode">
+        <property name="toolTip">
+         <string><html><head/><body><p>Multi-component images have more than one value for each voxel. These values may represent measurements taken at different time points, different chromatic components, etc. ITK-SNAP offers multiple ways to visualize this multi-dimensional information. You can choose to visualize just one component, or a summary function of the components, such as magnitude, average, or maximum. In the special case of three-component images, t [...]
+        </property>
+       </widget>
       </item>
-      <item row="1" column="3" alignment="Qt::AlignRight">
-       <widget class="QCheckBox" name="chkAnimate">
-        <property name="text">
-         <string>Animate</string>
+      <item row="1" column="1">
+       <widget class="QWidget" name="grpComponent" native="true">
+        <property name="minimumSize">
+         <size>
+          <width>0</width>
+          <height>20</height>
+         </size>
         </property>
+        <property name="styleSheet">
+         <string notr="true">font-size:12pt;</string>
+        </property>
+        <layout class="QHBoxLayout" name="horizontalLayout_2">
+         <property name="spacing">
+          <number>4</number>
+         </property>
+         <property name="leftMargin">
+          <number>0</number>
+         </property>
+         <property name="topMargin">
+          <number>0</number>
+         </property>
+         <property name="rightMargin">
+          <number>0</number>
+         </property>
+         <property name="bottomMargin">
+          <number>0</number>
+         </property>
+         <item>
+          <widget class="QSpinBox" name="inComponent">
+           <property name="minimumSize">
+            <size>
+             <width>80</width>
+             <height>0</height>
+            </size>
+           </property>
+           <property name="toolTip">
+            <string><html><head/><body><p>Select the image component to visualize.</p></body></html></string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QSlider" name="inComponentSlider">
+           <property name="toolTip">
+            <string><html><head/><body><p>Select the image component to visualize.</p></body></html></string>
+           </property>
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QToolButton" name="btnAnimate">
+           <property name="maximumSize">
+            <size>
+             <width>20</width>
+             <height>20</height>
+            </size>
+           </property>
+           <property name="toolTip">
+            <string><html><head/><body><p>Toggle animation mode.</p><p>When enabled, the display will automatically loop over the image components at one-second intervals.</p></body></html></string>
+           </property>
+           <property name="text">
+            <string>...</string>
+           </property>
+           <property name="icon">
+            <iconset resource="../Resources/SNAPResources.qrc">
+             <normaloff>:/root/icons8_film_reel_12.png</normaloff>:/root/icons8_film_reel_12.png</iconset>
+           </property>
+           <property name="iconSize">
+            <size>
+             <width>12</width>
+             <height>12</height>
+            </size>
+           </property>
+           <property name="checkable">
+            <bool>true</bool>
+           </property>
+           <property name="checked">
+            <bool>true</bool>
+           </property>
+           <property name="autoRaise">
+            <bool>true</bool>
+           </property>
+          </widget>
+         </item>
+        </layout>
        </widget>
       </item>
       <item row="1" column="0">
-       <widget class="QLabel" name="label_2">
+       <widget class="QLabel" name="lblComponent">
         <property name="text">
          <string>Component:</string>
         </property>
        </widget>
       </item>
-      <item row="1" column="1">
-       <widget class="QSpinBox" name="inComponent"/>
-      </item>
-      <item row="1" column="2">
-       <widget class="QSlider" name="inComponentSlider">
-        <property name="orientation">
-         <enum>Qt::Horizontal</enum>
-        </property>
-       </widget>
-      </item>
      </layout>
     </widget>
    </item>
@@ -203,6 +623,8 @@ QGroupBox::title {
    </item>
   </layout>
  </widget>
- <resources/>
+ <resources>
+  <include location="../Resources/SNAPResources.qrc"/>
+ </resources>
  <connections/>
 </ui>
diff --git a/GUI/Qt/Components/HistoryQListModel.cxx b/GUI/Qt/Components/HistoryQListModel.cxx
index 6c6d321..1a523ae 100644
--- a/GUI/Qt/Components/HistoryQListModel.cxx
+++ b/GUI/Qt/Components/HistoryQListModel.cxx
@@ -7,48 +7,121 @@
 #include <QIcon>
 #include "SNAPQtCommon.h"
 #include "LatentITKEventNotifier.h"
+#include "itkImageFileReader.h"
+
+#include <QWaitCondition>
+#include <QThread>
+#include <QString>
+#include <SNAPQtCommon.h>
+#include <QPixmapCache>
+#include <QFileInfo>
+#include <QIcon>
+#include <QTimer>
 
 HistoryQListModel::HistoryQListModel(QObject *parent) :
-  QAbstractListModel(parent)
+  QStandardItemModel(parent)
 {
   m_Model = NULL;
+
+  QPixmap pixmap(128,128);
+  pixmap.fill(QColor(Qt::lightGray));
+  m_DummyIcon = QIcon(pixmap);
 }
 
-int HistoryQListModel::rowCount(const QModelIndex &parent) const
+void HistoryQListItem::setItem(
+    GlobalUIModel *model,
+    const QString &history_entry)
 {
-  // Display at most 12 entries in the history
-  return std::min((size_t) 12, m_CachedHistory.size());
+  // Set the name to the short name
+  QString short_name = QFileInfo(history_entry).fileName();
+  this->setText(short_name);
+
+  // Set the filename
+  this->setToolTip(history_entry);
+  this->setData(history_entry, Qt::UserRole);
+  QPixmap dummy(128, 128);
+  dummy.fill(Qt::black);
+  this->setIcon(QIcon(dummy));
+
+  // At the moment, these are hard-coded
+  this->setSizeHint(QSize(188,144));
+
+  // Deal with the icon later
+  std::string hist_str = to_utf8(history_entry);
+  std::string thumbnail =
+      model->GetDriver()->GetSystemInterface()->GetThumbnailAssociatedWithFile(hist_str.c_str());
+
+  m_IconFilename = from_utf8(thumbnail);
+
+  // TODO: for debugging change 0 to a random number
+  QTimer::singleShot(0, this, SLOT(onTimer()));
 }
 
-QVariant HistoryQListModel::data(const QModelIndex &index, int role) const
+void HistoryQListItem::onTimer()
 {
-  // Get the entry
-  std::string item = m_CachedHistory[m_CachedHistory.size() - (1 + index.row())];
-
-  // Display the appropriate item
-  if(role == Qt::DisplayRole)
+  // Construct a string from the filenane and the timestamp
+  QString key = QString("%1::%2")
+                .arg(m_IconFilename)
+                .arg(QFileInfo(m_IconFilename).lastModified().toString());
+  QPixmap *pixmap = QPixmapCache::find(key);
+  if(pixmap)
+    this->setIcon(QIcon(*pixmap));
+  else
     {
-    // Get the shorter filename
-    std::string shorty = itksys::SystemTools::GetFilenameName(item.c_str());
-    return from_utf8(shorty);
-    }
-  else if(role == Qt::DecorationRole)
-    {
-    // Need to get an icon!
-    std::string iconfile = m_Model->GetDriver()->GetSystemInterface()
-        ->GetThumbnailAssociatedWithFile(item.c_str());
-
-    // Need to load the icon
-    QIcon icon;
-    icon.addFile(iconfile.c_str());
-    return icon;
+    try
+      {
+      // Load the icon using ITK to avoid this really annoying warning
+      // from the PNG library. The only problem is that QIcon caches
+      typedef itk::RGBAPixel<unsigned char> PNGPixelType;
+      typedef itk::Image<PNGPixelType, 2> PNGSliceType;
+      typedef itk::ImageFileReader<PNGSliceType> PNGReaderType;
+      SmartPtr<PNGReaderType> reader = PNGReaderType::New();
+      reader->SetFileName(to_utf8(m_IconFilename).c_str());
+      reader->Update();
+
+      // Need to load the icon
+      SmartPtr<PNGSliceType> slice = reader->GetOutput();
+      int w = slice->GetBufferedRegion().GetSize()[0];
+      int h = slice->GetBufferedRegion().GetSize()[1];
+      QImage image(w, h, QImage::Format_ARGB32);
+      PNGPixelType *input = slice->GetBufferPointer();
+      QRgb *output = reinterpret_cast<QRgb*>(image.bits());
+      for(int i = 0; i < slice->GetPixelContainer()->Size(); i++)
+        {
+        *output++ = qRgba(input[i].GetRed(), input[i].GetGreen(), input[i].GetBlue(), input[i].GetAlpha());
+        }
+
+      QPixmap load_pixmap = QPixmap::fromImage(image);
+      this->setIcon(QIcon(load_pixmap));
+      QPixmapCache::insert(key, load_pixmap);
+      }
+    catch(itk::ExceptionObject &exc)
+      {
+      QPixmap dummy(128, 128);
+      dummy.fill(Qt::black);
+      this->setIcon(QIcon(dummy));
+      QPixmapCache::insert(key, dummy);
+      }
     }
-  else if(role == Qt::ToolTipRole || role == Qt::UserRole)
+}
+
+void HistoryQListModel::rebuildModel()
+{
+  HistoryManager::AbstractHistoryModel *hmodel =
+      m_Model->GetDriver()->GetHistoryManager()->GetGlobalHistoryModel(m_HistoryName);
+  std::vector<std::string> history = hmodel->GetValue();
+
+  this->setColumnCount(1);
+  this->setRowCount(history.size());
+
+  // We need to parse the history in reverse order (but why?)
+  for(int i = 0; i < history.size(); i++)
     {
-    return from_utf8(item.c_str());
+    // Create a standard item to hold this
+    HistoryQListItem *si = new HistoryQListItem();
+    si->setItem(m_Model, from_utf8(history[history.size() - 1 - i]));
+    this->setItem(i, 0, si);
     }
-  return QVariant();
-
 }
 
 void HistoryQListModel::Initialize(
@@ -59,23 +132,20 @@ void HistoryQListModel::Initialize(
 
   // Get the property models for the local and global histories
   HistoryManager::AbstractHistoryModel *hmodel =
-      m_Model->GetDriver()->GetHistoryManager()->GetGlobalHistoryModel(category);
+      m_Model->GetDriver()->GetHistoryManager()->GetGlobalHistoryModel(m_HistoryName);
 
-  // Listen for updates from the history model
-  LatentITKEventNotifier::connect(hmodel, ValueChangedEvent(),
-                                  this, SLOT(onModelUpdate(EventBucket)));
+  LatentITKEventNotifier::connect(
+        hmodel, ValueChangedEvent(),
+        this, SLOT(onModelUpdate(EventBucket)));
 
   // Cache the history
-  m_CachedHistory = hmodel->GetValue();
+  this->rebuildModel();
 }
 
+
 void HistoryQListModel::onModelUpdate(const EventBucket &bucket)
 {
   this->beginResetModel();
-
-  // When history changes, we update
-  m_CachedHistory =
-      m_Model->GetDriver()->GetHistoryManager()->GetGlobalHistory(m_HistoryName);
-
+  this->rebuildModel();
   this->endResetModel();
 }
diff --git a/GUI/Qt/Components/HistoryQListModel.h b/GUI/Qt/Components/HistoryQListModel.h
index c4c8e49..f1dbff2 100644
--- a/GUI/Qt/Components/HistoryQListModel.h
+++ b/GUI/Qt/Components/HistoryQListModel.h
@@ -4,42 +4,68 @@
 #include "SNAPCommon.h"
 #include <QAbstractListModel>
 #include <vector>
+#include <QDateTime>
+#include <QIcon>
+#include <QImage>
+#include <QStandardItemModel>
+#include <QStandardItem>
 
 class EventBucket;
 class GlobalUIModel;
 
+class HistoryQListItem : public QObject, public QStandardItem
+{
+  Q_OBJECT
+public:
+
+  virtual void setItem(GlobalUIModel *model, const QString &history_entry);
+
+protected slots:
+
+  void onTimer();
+
+protected:
+
+  QString m_IconFilename;
+
+};
+
+
 /**
   QT model used to display an item from the image history as an entry in
   the table of recently loaded images
   */
-class HistoryQListModel : public QAbstractListModel
+class HistoryQListModel : public QStandardItemModel
 {
   Q_OBJECT
 
 public:
   explicit HistoryQListModel(QObject *parent = 0);
 
-  virtual int rowCount(const QModelIndex &parent) const;
-  virtual QVariant data(const QModelIndex &index, int role) const;
-
   void Initialize(GlobalUIModel *, const std::string &category);
 
-signals:
-  
 public slots:
+
   void onModelUpdate(const EventBucket &bucket);
 
 protected:
 
+  void rebuildModel();
+
+  static void updateIcon(QStandardItem *item);
+
   // Need a pointer to the model
   GlobalUIModel *m_Model;
 
   // The name of the history
   std::string m_HistoryName;
 
-  // The cached value of the history - we keep it for speed
-  std::vector<std::string> m_CachedHistory;
+  // Dummy icon
+  QIcon m_DummyIcon;
 
+  // List of standard items for concurrent code
+  QList<QStandardItem *> m_ItemList;
 };
 
+
 #endif // HISTORYQLISTMODEL_H
diff --git a/GUI/Qt/Components/LabelInspector.cxx b/GUI/Qt/Components/LabelInspector.cxx
index 17e6ed2..d8c77d3 100644
--- a/GUI/Qt/Components/LabelInspector.cxx
+++ b/GUI/Qt/Components/LabelInspector.cxx
@@ -18,7 +18,7 @@ LabelInspector::LabelInspector(QWidget *parent) :
   ui->inBackLabel->setIconSize(QSize(16,16));
 
   // Connect to the action in the menubar
-  ui->btnEdit->setAction("actionLabel_Editor");
+  // ui->btnEdit->setAction("actionLabel_Editor");
 }
 
 LabelInspector::~LabelInspector()
@@ -32,10 +32,13 @@ void LabelInspector
   // Get the model
   m_Model = model;
 
+  // Attach to quick list
+  // ui->quickList->SetModel(model);
+
   // Use couplings where we can
   makeCoupling(ui->inOpacity, m_Model->GetSegmentationOpacityModel());
   makeCoupling(ui->inOpacityValue, m_Model->GetSegmentationOpacityModel());
-  makeCoupling(ui->chkVisible, m_Model->GetSegmentationVisibilityModel());
+  // makeCoupling(ui->chkVisible, m_Model->GetSegmentationVisibilityModel());
 
   // Couple the color label combo box. The actual logic for how the labels are
   // mapped to color labels is handled in QtComboBoxCoupling.h
@@ -46,9 +49,6 @@ void LabelInspector
   makeCoupling(ui->inBackLabel,
                m_Model->GetGlobalState()->GetDrawOverFilterModel());
 
-  // Couple the inversion checkbox
-  makeCoupling(ui->cbInvert,
-               m_Model->GetGlobalState()->GetPolygonInvertModel());
 }
 
 
diff --git a/GUI/Qt/Components/LabelInspector.ui b/GUI/Qt/Components/LabelInspector.ui
index a725d73..a71339b 100644
--- a/GUI/Qt/Components/LabelInspector.ui
+++ b/GUI/Qt/Components/LabelInspector.ui
@@ -6,8 +6,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>169</width>
-    <height>575</height>
+    <width>164</width>
+    <height>136</height>
    </rect>
   </property>
   <property name="sizePolicy">
@@ -26,406 +26,275 @@
    <string>Form</string>
   </property>
   <property name="styleSheet">
-   <string notr="true">*  {
-font-size: 12px;
-}
-
-QAbstractItemView::item {
-  padding:4px;
-}</string>
+   <string notr="true"/>
   </property>
   <layout class="QVBoxLayout" name="verticalLayout">
    <property name="spacing">
-    <number>-1</number>
+    <number>0</number>
+   </property>
+   <property name="leftMargin">
+    <number>0</number>
+   </property>
+   <property name="topMargin">
+    <number>0</number>
    </property>
-   <property name="margin">
+   <property name="rightMargin">
+    <number>0</number>
+   </property>
+   <property name="bottomMargin">
     <number>0</number>
    </property>
    <item>
-    <layout class="QVBoxLayout" name="verticalLayout_2">
-     <property name="spacing">
-      <number>4</number>
-     </property>
-     <item>
-      <widget class="QLabel" name="label">
-       <property name="font">
-        <font>
-         <pointsize>-1</pointsize>
-         <weight>75</weight>
-         <bold>true</bold>
-        </font>
-       </property>
-       <property name="styleSheet">
-        <string notr="true">font-weight:bold;</string>
-       </property>
-       <property name="text">
-        <string>Foreground label</string>
-       </property>
-      </widget>
-     </item>
-     <item>
-      <widget class="QComboBox" name="inForeLabel">
-       <property name="styleSheet">
-        <string notr="true">QAbstractItemView::item {
-spacing:10;
+    <widget class="QWidget" name="widget_5" native="true">
+     <property name="styleSheet">
+      <string notr="true">QLabel  {
+font-size: 12px;
+}
+
+QComboBox {
+  font-size:12px;
+  padding: 0px 0px 0px 5px;
+}
+
+QSpinBox {
+font-size: 11px;
 }</string>
-       </property>
-       <property name="editable">
-        <bool>false</bool>
-       </property>
-       <property name="insertPolicy">
-        <enum>QComboBox::InsertAtBottom</enum>
-       </property>
-      </widget>
-     </item>
-     <item>
-      <layout class="QHBoxLayout" name="horizontalLayout_3">
-       <property name="spacing">
-        <number>0</number>
-       </property>
-       <item>
-        <spacer name="horizontalSpacer">
-         <property name="orientation">
-          <enum>Qt::Horizontal</enum>
-         </property>
-         <property name="sizeType">
-          <enum>QSizePolicy::Fixed</enum>
-         </property>
-         <property name="sizeHint" stdset="0">
-          <size>
-           <width>40</width>
-           <height>20</height>
-          </size>
-         </property>
-        </spacer>
-       </item>
-       <item>
-        <widget class="QLabel" name="label_3">
-         <property name="sizePolicy">
-          <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-           <horstretch>0</horstretch>
-           <verstretch>0</verstretch>
-          </sizepolicy>
-         </property>
-         <property name="styleSheet">
-          <string notr="true">font-size:10px;</string>
-         </property>
-         <property name="text">
-          <string><html><head/><body><p>Label used by drawing <br/>and segmentation tools</p></body></html></string>
-         </property>
-         <property name="wordWrap">
-          <bool>true</bool>
-         </property>
-        </widget>
-       </item>
-      </layout>
-     </item>
-    </layout>
-   </item>
-   <item>
-    <layout class="QVBoxLayout" name="verticalLayout_3">
-     <property name="spacing">
-      <number>4</number>
      </property>
-     <item>
-      <widget class="QLabel" name="label_2">
-       <property name="font">
-        <font>
-         <pointsize>-1</pointsize>
-         <weight>75</weight>
-         <bold>true</bold>
-        </font>
-       </property>
-       <property name="styleSheet">
-        <string notr="true">font-weight:bold;</string>
-       </property>
-       <property name="text">
-        <string>Background label</string>
-       </property>
-      </widget>
-     </item>
-     <item>
-      <widget class="QComboBox" name="inBackLabel"/>
-     </item>
-     <item>
-      <layout class="QHBoxLayout" name="horizontalLayout_4">
-       <property name="spacing">
-        <number>0</number>
-       </property>
-       <item>
-        <spacer name="horizontalSpacer_2">
-         <property name="orientation">
-          <enum>Qt::Horizontal</enum>
-         </property>
-         <property name="sizeType">
-          <enum>QSizePolicy::Fixed</enum>
-         </property>
-         <property name="sizeHint" stdset="0">
-          <size>
-           <width>40</width>
-           <height>20</height>
-          </size>
-         </property>
-        </spacer>
-       </item>
-       <item>
-        <widget class="QLabel" name="label_4">
-         <property name="sizePolicy">
-          <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-           <horstretch>0</horstretch>
-           <verstretch>0</verstretch>
-          </sizepolicy>
-         </property>
-         <property name="styleSheet">
-          <string notr="true">font-size:10px;</string>
-         </property>
-         <property name="text">
-          <string><html><head/><body><p>Drawing tools only affect <br/>voxels with this label</p></body></html></string>
-         </property>
-         <property name="wordWrap">
-          <bool>true</bool>
-         </property>
-        </widget>
-       </item>
-      </layout>
-     </item>
-    </layout>
-   </item>
-   <item>
-    <widget class="QWidget" name="widget_4" native="true">
-     <layout class="QHBoxLayout" name="horizontalLayout_5">
+     <layout class="QVBoxLayout" name="verticalLayout_2">
       <property name="spacing">
        <number>0</number>
       </property>
-      <property name="margin">
+      <property name="leftMargin">
+       <number>0</number>
+      </property>
+      <property name="topMargin">
+       <number>0</number>
+      </property>
+      <property name="rightMargin">
+       <number>0</number>
+      </property>
+      <property name="bottomMargin">
        <number>0</number>
       </property>
       <item>
-       <spacer name="horizontalSpacer_4">
+       <widget class="QLabel" name="label">
+        <property name="font">
+         <font>
+          <pointsize>-1</pointsize>
+         </font>
+        </property>
+        <property name="styleSheet">
+         <string notr="true"/>
+        </property>
+        <property name="text">
+         <string>Active label:</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QComboBox" name="inForeLabel">
+        <property name="toolTip">
+         <string><html><head/><body><p><span style=" font-weight:600;">Active Segmentation Label (&lt;,&gt;)</span></p><p>Select the label used for segmentation operations, including manual and automatic tools. When segmentations are generated, they will be assigned the active segmentation label. </p></body></html></string>
+        </property>
+        <property name="styleSheet">
+         <string notr="true">QAbstractItemView::item {
+spacing:10;
+}</string>
+        </property>
+        <property name="editable">
+         <bool>false</bool>
+        </property>
+        <property name="insertPolicy">
+         <enum>QComboBox::InsertAtBottom</enum>
+        </property>
+        <item>
+         <property name="text">
+          <string>Hello</string>
+         </property>
+        </item>
+       </widget>
+      </item>
+      <item>
+       <spacer name="verticalSpacer_2">
         <property name="orientation">
-         <enum>Qt::Horizontal</enum>
+         <enum>Qt::Vertical</enum>
         </property>
         <property name="sizeType">
          <enum>QSizePolicy::Fixed</enum>
         </property>
         <property name="sizeHint" stdset="0">
          <size>
-          <width>40</width>
-          <height>20</height>
+          <width>20</width>
+          <height>6</height>
          </size>
         </property>
        </spacer>
       </item>
       <item>
-       <widget class="QCheckBox" name="cbInvert">
-        <property name="toolTip">
-         <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
-<html><head><meta name="qrichtext" content="1" /><style type="text/css">
-p, li { white-space: pre-wrap; }
-</style></head><body style=" font-family:'Helvetica'; font-size:12px; font-weight:400; font-style:normal;">
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Inverts some segmentation operations, such as polygon drawing, by applying the segmentation to the outside of the drawn region, rather than inside.</p></body></html></string>
-        </property>
-        <property name="text">
-         <string>Draw inverted</string>
-        </property>
-       </widget>
-      </item>
-     </layout>
-    </widget>
-   </item>
-   <item>
-    <widget class="Line" name="line">
-     <property name="frameShadow">
-      <enum>QFrame::Plain</enum>
-     </property>
-     <property name="lineWidth">
-      <number>1</number>
-     </property>
-     <property name="midLineWidth">
-      <number>1</number>
-     </property>
-     <property name="orientation">
-      <enum>Qt::Horizontal</enum>
-     </property>
-    </widget>
-   </item>
-   <item>
-    <widget class="QWidget" name="widget" native="true">
-     <layout class="QVBoxLayout" name="verticalLayout_4">
-      <property name="margin">
-       <number>0</number>
-      </property>
-      <item>
-       <widget class="QLabel" name="label_6">
+       <widget class="QLabel" name="label_2">
         <property name="font">
          <font>
           <pointsize>-1</pointsize>
-          <weight>75</weight>
-          <bold>true</bold>
          </font>
         </property>
         <property name="styleSheet">
-         <string notr="true">font-weight:bold;</string>
+         <string notr="true"/>
         </property>
         <property name="text">
-         <string>Label opacity</string>
+         <string>Paint over:</string>
         </property>
        </widget>
       </item>
       <item>
-       <widget class="QWidget" name="widget_2" native="true">
-        <layout class="QHBoxLayout" name="horizontalLayout_2">
-         <property name="spacing">
-          <number>4</number>
-         </property>
-         <property name="margin">
-          <number>0</number>
-         </property>
-         <item>
-          <widget class="QSlider" name="inOpacity">
-           <property name="toolTip">
-            <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
-<html><head><meta name="qrichtext" content="1" /><style type="text/css">
-p, li { white-space: pre-wrap; }
-</style></head><body style=" font-family:'Helvetica'; font-size:12px; font-weight:400; font-style:normal;">
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Set the overall opacity of segmentation labels.</p>
-<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">[A]: Make more transparent</p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">[D]: Make more opaque</p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">[S]: Toggle on/off</p></body></html></string>
-           </property>
-           <property name="minimum">
-            <number>0</number>
-           </property>
-           <property name="maximum">
-            <number>100</number>
-           </property>
-           <property name="singleStep">
-            <number>1</number>
-           </property>
-           <property name="pageStep">
-            <number>10</number>
-           </property>
-           <property name="value">
-            <number>50</number>
-           </property>
-           <property name="orientation">
-            <enum>Qt::Horizontal</enum>
-           </property>
-           <property name="tickPosition">
-            <enum>QSlider::TicksBelow</enum>
-           </property>
-           <property name="tickInterval">
-            <number>25</number>
-           </property>
-          </widget>
-         </item>
-        </layout>
+       <widget class="QComboBox" name="inBackLabel">
+        <property name="toolTip">
+         <string><html><head/><body><p><span style=" font-weight:600;">&quot;Paint Over&quot; Mask</span></p><p>Determines how segmentation operations such as drawing polygons affect voxels in the segmentation image.<br/></p><table border="0" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px;" cellspacing="2" cellpadding="0"><tr>< [...]
+        </property>
        </widget>
       </item>
       <item>
-       <widget class="QWidget" name="widget_3" native="true">
-        <layout class="QHBoxLayout" name="horizontalLayout_6">
+       <widget class="QWidget" name="widget" native="true">
+        <layout class="QVBoxLayout" name="verticalLayout_4">
          <property name="spacing">
           <number>0</number>
          </property>
-         <property name="margin">
+         <property name="leftMargin">
+          <number>0</number>
+         </property>
+         <property name="topMargin">
+          <number>0</number>
+         </property>
+         <property name="rightMargin">
+          <number>0</number>
+         </property>
+         <property name="bottomMargin">
           <number>0</number>
          </property>
          <item>
-          <widget class="QSpinBox" name="inOpacityValue">
-           <property name="buttonSymbols">
-            <enum>QAbstractSpinBox::NoButtons</enum>
-           </property>
-           <property name="suffix">
-            <string>%</string>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <spacer name="horizontalSpacer_6">
+          <spacer name="verticalSpacer_3">
            <property name="orientation">
-            <enum>Qt::Horizontal</enum>
+            <enum>Qt::Vertical</enum>
            </property>
            <property name="sizeType">
-            <enum>QSizePolicy::Expanding</enum>
+            <enum>QSizePolicy::Fixed</enum>
            </property>
            <property name="sizeHint" stdset="0">
             <size>
-             <width>5</width>
-             <height>17</height>
+             <width>20</width>
+             <height>6</height>
             </size>
            </property>
           </spacer>
          </item>
          <item>
-          <widget class="QCheckBox" name="chkVisible">
+          <widget class="QLabel" name="label_6">
+           <property name="font">
+            <font>
+             <pointsize>-1</pointsize>
+            </font>
+           </property>
+           <property name="styleSheet">
+            <string notr="true"/>
+           </property>
            <property name="text">
-            <string>Visible</string>
+            <string>Overall label opacity:</string>
            </property>
           </widget>
          </item>
+         <item>
+          <widget class="QWidget" name="widget_2" native="true">
+           <layout class="QHBoxLayout" name="horizontalLayout_2">
+            <property name="spacing">
+             <number>4</number>
+            </property>
+            <property name="leftMargin">
+             <number>0</number>
+            </property>
+            <property name="topMargin">
+             <number>0</number>
+            </property>
+            <property name="rightMargin">
+             <number>0</number>
+            </property>
+            <property name="bottomMargin">
+             <number>0</number>
+            </property>
+            <item>
+             <widget class="QSpinBox" name="inOpacityValue">
+              <property name="toolTip">
+               <string><html><head/><body><p><span style=" font-weight:600;">Label Opacity (A,S,D keys)</span></p><p>Change the overall opacity of segmentation labels.<br></p><table border="0" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px;" cellspacing="2" cellpadding="0"><tr><td style=" padding-left:5; padding-right:5; padding-t [...]
+              </property>
+              <property name="frame">
+               <bool>true</bool>
+              </property>
+              <property name="buttonSymbols">
+               <enum>QAbstractSpinBox::NoButtons</enum>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QSlider" name="inOpacity">
+              <property name="toolTip">
+               <string><html><head/><body><p><span style=" font-weight:600;">Label Opacity (A,S,D keys)</span></p><p>Change the overall opacity of segmentation labels.<br></p><table border="0" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px;" cellspacing="2" cellpadding="0"><tr><td style=" padding-left:5; padding-right:5; padding-t [...]
+              </property>
+              <property name="minimum">
+               <number>0</number>
+              </property>
+              <property name="maximum">
+               <number>100</number>
+              </property>
+              <property name="singleStep">
+               <number>1</number>
+              </property>
+              <property name="pageStep">
+               <number>10</number>
+              </property>
+              <property name="value">
+               <number>50</number>
+              </property>
+              <property name="orientation">
+               <enum>Qt::Horizontal</enum>
+              </property>
+              <property name="tickPosition">
+               <enum>QSlider::NoTicks</enum>
+              </property>
+              <property name="tickInterval">
+               <number>25</number>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </widget>
+         </item>
+         <item>
+          <widget class="QWidget" name="widget_3" native="true">
+           <layout class="QHBoxLayout" name="horizontalLayout_6">
+            <property name="spacing">
+             <number>0</number>
+            </property>
+            <property name="leftMargin">
+             <number>0</number>
+            </property>
+            <property name="topMargin">
+             <number>0</number>
+            </property>
+            <property name="rightMargin">
+             <number>0</number>
+            </property>
+            <property name="bottomMargin">
+             <number>0</number>
+            </property>
+           </layout>
+          </widget>
+         </item>
         </layout>
        </widget>
       </item>
      </layout>
     </widget>
    </item>
-   <item>
-    <widget class="Line" name="line_2">
-     <property name="frameShadow">
-      <enum>QFrame::Plain</enum>
-     </property>
-     <property name="lineWidth">
-      <number>1</number>
-     </property>
-     <property name="midLineWidth">
-      <number>1</number>
-     </property>
-     <property name="orientation">
-      <enum>Qt::Horizontal</enum>
-     </property>
-    </widget>
-   </item>
-   <item>
-    <layout class="QHBoxLayout" name="horizontalLayout">
-     <item>
-      <widget class="QActionButton" name="btnEdit">
-       <property name="sizePolicy">
-        <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-         <horstretch>0</horstretch>
-         <verstretch>0</verstretch>
-        </sizepolicy>
-       </property>
-       <property name="text">
-        <string>Label Editor...</string>
-       </property>
-      </widget>
-     </item>
-    </layout>
-   </item>
-   <item>
-    <spacer name="verticalSpacer">
-     <property name="orientation">
-      <enum>Qt::Vertical</enum>
-     </property>
-     <property name="sizeHint" stdset="0">
-      <size>
-       <width>20</width>
-       <height>40</height>
-      </size>
-     </property>
-    </spacer>
-   </item>
   </layout>
  </widget>
- <customwidgets>
-  <customwidget>
-   <class>QActionButton</class>
-   <extends>QPushButton</extends>
-   <header location="global">QActionButton.h</header>
-  </customwidget>
- </customwidgets>
  <resources/>
  <connections/>
 </ui>
diff --git a/GUI/Qt/Components/LabelSelectionButton.cxx b/GUI/Qt/Components/LabelSelectionButton.cxx
index 9eabbb2..3e0f209 100644
--- a/GUI/Qt/Components/LabelSelectionButton.cxx
+++ b/GUI/Qt/Components/LabelSelectionButton.cxx
@@ -47,6 +47,9 @@ void LabelSelectionButton::onModelUpdate(const EventBucket &bucket)
   this->UpdateAppearance();
 }
 
+#if QT_VERSION < 0x050000
+#define QRegularExpression QRegExp
+#endif
 
 void LabelSelectionButton::UpdateAppearance()
 {
@@ -55,10 +58,15 @@ void LabelSelectionButton::UpdateAppearance()
   DrawOverFilter bg = m_Model->GetGlobalState()->GetDrawOverFilter();
 
   // Draw a split button
-  this->setIcon(CreateLabelComboIcon(22, 22, fg, bg, clt));
+  this->setIcon(CreateLabelComboIcon(20, 20, fg, bg, clt));
 
   // Update the tooltip
-  this->setToolTip(CreateLabelComboTooltip(fg, bg, clt));
+  QString tooltip = this->toolTip();
+  tooltip.replace(QRegularExpression("<!--FgStart-->.*<!--FgEnd-->"),
+                  QString("<!--FgStart-->%1<!--FgEnd-->").arg(GetTitleForColorLabel(fg, clt)));
+  tooltip.replace(QRegularExpression("<!--BgStart-->.*<!--BgEnd-->"),
+                  QString("<!--BgStart-->%1<!--BgEnd-->").arg(GetTitleForDrawOverFilter(bg, clt)));
+  this->setToolTip(tooltip);
 }
 
 
@@ -129,18 +137,14 @@ LabelSelectionButtonPopupMenu::LabelSelectionButtonPopupMenu(QWidget *parent)
   : QMenu(parent)
 {
   // Add the foreground and background label selectors
-  m_SubForeground = this->addMenu("Foreground Label");
-  m_SubBackground = this->addMenu("Background Label");
+  m_SubForeground = this->addMenu("Active label:");
+  m_SubBackground = this->addMenu("Paint over:");
   this->addSeparator();
 
   // Create a QAction wrapped around the recent labels menu
   ColorLabelQuickListWidgetAction *action = new ColorLabelQuickListWidgetAction(this);
   this->m_Recent = action->GetWidget();
   this->addAction(action);
-  this->addSeparator();
-
-  // Label editor window
-  this->addAction(FindUpstreamAction(this, "actionLabel_Editor"));
 
   this->setStyleSheet("font-size: 12px;");
 
diff --git a/GUI/Qt/Components/LatentITKEventNotifier.cxx b/GUI/Qt/Components/LatentITKEventNotifier.cxx
index d31a075..fa297cc 100644
--- a/GUI/Qt/Components/LatentITKEventNotifier.cxx
+++ b/GUI/Qt/Components/LatentITKEventNotifier.cxx
@@ -98,11 +98,13 @@ LatentITKEventNotifierHelper
   if(!m_Bucket.IsEmpty())
     {
 #ifdef SNAP_DEBUG_EVENTS
+    std::string class_name = parent()->metaObject()->className();
+    std::string object_name = qPrintable(parent()->objectName());
     if(flag_snap_debug_events)
       {
       std::cout << "SEND " << m_Bucket
-                << " to " << parent()->metaObject()->className()
-                << " named '" << qPrintable(parent()->objectName())
+                << " to " << class_name
+                << " named '" << object_name
                 << "'" << std::endl << std::flush;
       }
 #endif
@@ -170,8 +172,12 @@ LatentITKEventNotifier
     c = new LatentITKEventNotifierHelper(target);
     }
 
-  // Connect to the target qobject
-  QObject::connect(c, SIGNAL(dispatchEvent(const EventBucket &)), target, slot);
+  // Connect to the target qobject.
+  // VERY IMPORTANT: this uses Qt::UniqueConnection, otherwise the slot will get
+  // called every time that an event is hooked up to the slot, making the slot be
+  // called sometimes as many as six times per event. This may have been a factor in
+  // the laggy GUI performance before
+  QObject::connect(c, SIGNAL(dispatchEvent(const EventBucket &)), target, slot, Qt::UniqueConnection);
 
   return c;
 }
diff --git a/GUI/Qt/Components/LayerInspectorRowDelegate.cxx b/GUI/Qt/Components/LayerInspectorRowDelegate.cxx
index e33c50f..4b0523b 100644
--- a/GUI/Qt/Components/LayerInspectorRowDelegate.cxx
+++ b/GUI/Qt/Components/LayerInspectorRowDelegate.cxx
@@ -8,12 +8,16 @@
 #include "QtLabelCoupling.h"
 #include "QtSliderCoupling.h"
 #include "QtActionGroupCoupling.h"
+#include "QtActionCoupling.h"
+#include "QtSliderCoupling.h"
 #include <QGraphicsOpacityEffect>
 #include <QPropertyAnimation>
 #include <QFile>
 #include <QMenu>
 #include <QContextMenuEvent>
+#include <QWidgetAction>
 #include "QtWidgetActivator.h"
+#include "QtCursorOverride.h"
 #include "GlobalUIModel.h"
 #include "ImageIODelegates.h"
 #include "ImageIOWizard.h"
@@ -26,6 +30,36 @@
 
 class QAction;
 
+
+
+OpacitySliderAction::OpacitySliderAction(QWidget *parent)
+  : QWidgetAction(parent)
+{
+}
+
+QWidget *OpacitySliderAction::createWidget(QWidget *parent)
+{
+  m_Container = new QWidget(parent);
+
+  m_Slider = new QSlider();
+  m_Slider->setOrientation(Qt::Horizontal);
+
+  QHBoxLayout *lo = new QHBoxLayout();
+  lo->setContentsMargins(27, 4, 4, 4);
+  lo->setSpacing(10);
+  lo->addWidget(new QLabel("Opacity:"));
+  lo->addWidget(m_Slider);
+  m_Container->setLayout(lo);
+
+  return m_Container;
+}
+
+
+
+
+
+
+
 QString LayerInspectorRowDelegate::m_SliderStyleSheetTemplate;
 
 LayerInspectorRowDelegate::LayerInspectorRowDelegate(QWidget *parent) :
@@ -43,6 +77,8 @@ LayerInspectorRowDelegate::LayerInspectorRowDelegate(QWidget *parent) :
   m_PopupMenu->addAction(ui->actionClose);
   m_PopupMenu->addSeparator();
   m_PopupMenu->addAction(ui->actionAutoContrast);
+  m_PopupMenu->addAction(ui->actionContrast_Inspector);
+  m_PopupMenu->addSeparator();
 
   // Add the color map menu
   m_ColorMapMenu = m_PopupMenu->addMenu("Color Map");
@@ -52,6 +88,26 @@ LayerInspectorRowDelegate::LayerInspectorRowDelegate(QWidget *parent) :
   m_DisplayModeMenu = m_PopupMenu->addMenu("Multi-Component Display");
   m_DisplayModeActionGroup = NULL;
 
+  m_PopupMenu->addSeparator();
+  m_PopupMenu->addAction(ui->actionPin_layer);
+  m_PopupMenu->addAction(ui->actionUnpin_layer);
+
+  // Create a slider for the layer opacity in the context menu
+  m_OverlayOpacitySlider = new QSlider(m_PopupMenu);
+  m_OverlayOpacitySlider->setOrientation(Qt::Horizontal);
+  m_OverlayOpacitySliderAction = new WidgetWithLabelAction(this);
+  m_OverlayOpacitySliderAction->setWidget(m_OverlayOpacitySlider);
+  m_OverlayOpacitySliderAction->setLabelText("Opacity: ");
+  m_PopupMenu->addAction(m_OverlayOpacitySliderAction);
+
+  // Create a menu listing the loaded overlays
+  m_OverlaysMenu = m_PopupMenu->addMenu("Overlays");
+
+  // Placeholder for image processing commands
+  m_PopupMenu->addSeparator();
+  QMenu *processMenu = m_PopupMenu->addMenu("Image Processing");
+  processMenu->addAction(ui->actionTextureFeatures);
+
   // set up an event filter
   ui->inLayerOpacity->installEventFilter(this);
 
@@ -68,7 +124,6 @@ LayerInspectorRowDelegate::LayerInspectorRowDelegate(QWidget *parent) :
   // Initialize the state
   m_Selected = false;
   m_Hover = false;
-  ui->stack->setCurrentWidget(ui->pageBlank);
   UpdateBackgroundPalette();
 }
 
@@ -84,41 +139,58 @@ void LayerInspectorRowDelegate::SetModel(LayerTableRowModel *model)
   makeCoupling(ui->inLayerOpacity, model->GetLayerOpacityModel());
   makeCoupling(ui->outLayerNickname, model->GetNicknameModel());
   makeCoupling(ui->outComponent, model->GetComponentNameModel());
-
-  makeCoupling((QAbstractButton *) ui->btnSticky, model->GetStickyModel());
+  makeCoupling(m_OverlayOpacitySlider, model->GetLayerOpacityModel());
   makeCoupling((QAbstractButton *) ui->btnVisible, model->GetVisibilityToggleModel());
+  makeCoupling((QAbstractButton *) ui->btnSticky, model->GetStickyModel());
+
+  const QtWidgetActivator::Options opt_hide = QtWidgetActivator::HideInactive;
+  activateOnFlag(ui->actionUnpin_layer, model, LayerTableRowModel::UIF_UNPINNABLE, opt_hide);
+  activateOnFlag(ui->actionPin_layer, model, LayerTableRowModel::UIF_PINNABLE, opt_hide);
+  activateOnAnyFlags(ui->btnSticky, model, LayerTableRowModel::UIF_UNPINNABLE, LayerTableRowModel::UIF_PINNABLE, opt_hide);
+  activateOnFlag(m_OverlayOpacitySliderAction, model, LayerTableRowModel::UIF_OPACITY_EDITABLE, opt_hide);
+  activateOnFlag(m_ColorMapMenu, model, LayerTableRowModel::UIF_COLORMAP_ADJUSTABLE, opt_hide);
+  activateOnFlag(m_DisplayModeMenu, model, LayerTableRowModel::UIF_MULTICOMPONENT, opt_hide);
+  activateOnFlag(ui->outComponent, model, LayerTableRowModel::UIF_MULTICOMPONENT, opt_hide);
+
+  // makeActionVisibilityCoupling(ui->actionUnpin_layer, model->GetStickyModel());
+  // makeActionVisibilityCoupling(ui->actionPin_layer, model->GetStickyModel(), true);
+  // makeActionVisibilityCoupling(m_OverlayOpacitySliderAction, model->GetStickyModel());
 
   // Hook up some activations
-  activateOnFlag(ui->btnVisible, model, LayerTableRowModel::UIF_OPACITY_EDITABLE);
-  activateOnFlag(ui->inLayerOpacity, model, LayerTableRowModel::UIF_OPACITY_EDITABLE);
-  activateOnFlag(ui->btnSticky, model, LayerTableRowModel::UIF_PINNABLE);
-  activateOnFlag(ui->btnMoveUp, model, LayerTableRowModel::UIF_MOVABLE_UP);
-  activateOnFlag(ui->btnMoveDown, model, LayerTableRowModel::UIF_MOVABLE_DOWN);
+  activateOnFlag(ui->btnVisible, model, LayerTableRowModel::UIF_OPACITY_EDITABLE, opt_hide);
+  activateOnFlag(ui->inLayerOpacity, model, LayerTableRowModel::UIF_OPACITY_EDITABLE, opt_hide);
+  // activateOnFlag(ui->btnMoveUp, model, LayerTableRowModel::UIF_MOVABLE_UP);
+  // activateOnFlag(ui->btnMoveDown, model, LayerTableRowModel::UIF_MOVABLE_DOWN);
   activateOnFlag(ui->actionClose, model, LayerTableRowModel::UIF_CLOSABLE);
   activateOnFlag(ui->actionAutoContrast, model, LayerTableRowModel::UIF_CONTRAST_ADJUSTABLE);
-  activateOnFlag(m_ColorMapMenu, model, LayerTableRowModel::UIF_COLORMAP_ADJUSTABLE);
-  activateOnFlag(m_DisplayModeMenu, model, LayerTableRowModel::UIF_MULTICOMPONENT);
+
 
   // Hook up the colormap and the slider's style sheet
   connectITK(m_Model->GetLayer(), WrapperChangeEvent());
   OnNicknameUpdate();
   ApplyColorMap();
 
+  // Listen to changes in all layer organization and metadata, as this affects the list
+  // of overlays shown in the context menu
+  connectITK(m_Model->GetParentModel()->GetDriver(), LayerChangeEvent());
+  connectITK(m_Model->GetParentModel()->GetDriver(), WrapperMetadataChangeEvent());
+
   // Listen to preset changes from the color map model
   connectITK(m_Model->GetParentModel()->GetColorMapModel(),
              ColorMapModel::PresetUpdateEvent());
 
+  // Listen to changes in the currently selected layer in GlobalState
+  connectITK(m_Model->GetParentModel()->GetGlobalState()->GetSelectedLayerIdModel(),
+              ValueChangedEvent());
+
   // Update the color map menu
   UpdateColorMapMenu();
 
   // Update the component menu
   UpdateComponentMenu();
 
-  // The page shown in this widget depends on whether the visibility editing
-  // is on or off
-  connectITK(m_Model->GetParentModel()->GetLayerVisibilityEditableModel(),
-             ValueChangedEvent());
-  UpdateVisibilityControls();
+  // Update the overlays
+  this->UpdateOverlaysMenu();
 }
 
 ImageWrapperBase *LayerInspectorRowDelegate::GetLayer() const
@@ -136,7 +208,7 @@ ImageWrapperBase *LayerInspectorRowDelegate::GetLayer() const
 void LayerInspectorRowDelegate::UpdateBackgroundPalette()
 {
   // Set up a pallete for the background
-  QPalette* palette = new QPalette();
+  QPalette palette;
   QLinearGradient linearGradient(QPointF(0, 0), QPointF(0, this->height()));
 
   if(m_Selected && m_Hover)
@@ -160,8 +232,9 @@ void LayerInspectorRowDelegate::UpdateBackgroundPalette()
     linearGradient.setColorAt(1, QColor(255,255,255));
     }
 
-  palette->setBrush(QPalette::Window, *(new QBrush(linearGradient)));
-  ui->frame->setPalette(*palette);
+  QBrush brush(linearGradient);
+  palette.setBrush(QPalette::Window, brush);
+  ui->frame->setPalette(palette);
 
   // Also set the font for the label
   if(ui->outLayerNickname->font().bold() != m_Selected)
@@ -179,8 +252,14 @@ void LayerInspectorRowDelegate::setSelected(bool value)
     m_Selected = value;
     emit selectionChanged(value);
 
+    // Update selection in the model
+    m_Model->SetSelected(value);
+
     // Update the look and feel
     this->UpdateBackgroundPalette();
+
+    // Update!
+    this->update();
     }
 }
 
@@ -248,18 +327,6 @@ bool LayerInspectorRowDelegate::eventFilter(QObject *, QEvent *evt)
   return false;
 }
 
-void LayerInspectorRowDelegate::UpdateVisibilityControls()
-{  
-  if(m_Model->GetParentModel()->GetLayerVisibilityEditable())
-    {
-    ui->stack->setCurrentWidget(ui->pageControls);
-    }
-  else
-    {
-    ui->stack->setCurrentWidget(ui->pageBlank);
-    }
-}
-
 void LayerInspectorRowDelegate::UpdateColorMapMenu()
 {
   // The presets are available from the color map model. We can use them
@@ -310,6 +377,10 @@ void LayerInspectorRowDelegate::UpdateColorMapMenu()
 
   // Add the action group to the menu
   m_ColorMapMenu->addActions(m_SystemPresetActionGroup->actions());
+
+  // Add the link to color map editor
+  m_ColorMapMenu->addSeparator();
+  m_ColorMapMenu->addAction(ui->actionColor_Map_Editor);
 }
 
 void LayerInspectorRowDelegate::UpdateComponentMenu()
@@ -354,6 +425,43 @@ void LayerInspectorRowDelegate::UpdateComponentMenu()
                           m_Model->GetDisplayModeModel());
 }
 
+#include "GenericImageData.h"
+#include "LayerInspectorDialog.h"
+
+void LayerInspectorRowDelegate::UpdateOverlaysMenu()
+{
+  int k = 0;
+
+  // Clear the overlays menu
+  m_OverlaysMenu->clear();
+
+  // If the current layer is sticky, disable the menu
+  if(m_Model->GetLayer() && !m_Model->GetLayer()->IsSticky())
+    {
+    // Get the current image data
+    GenericImageData *gid = m_Model->GetParentModel()->GetDriver()->GetCurrentImageData();
+
+    // Find the number of sticky layers
+    for(LayerIterator it = gid->GetLayers(OVERLAY_ROLE | SNAP_ROLE); !it.IsAtEnd(); ++it)
+      {
+      if(it.GetLayer()->IsSticky())
+        {
+        // Find the context menu for that layer
+        LayerInspectorDialog *insp = findParentWidget<LayerInspectorDialog>(this);
+        QMenu *menu = insp->GetLayerContextMenu(it.GetLayer());
+        if(menu)
+          {
+          m_OverlaysMenu->addAction(menu->menuAction());
+          k++;
+          }
+        }
+      }
+    }
+
+  // Enable overlays menu if it's not empty
+  m_OverlaysMenu->menuAction()->setVisible(k > 0);
+}
+
 
 void LayerInspectorRowDelegate::OnNicknameUpdate()
 {
@@ -365,6 +473,7 @@ void LayerInspectorRowDelegate::OnNicknameUpdate()
   ui->actionClose->setToolTip(ui->actionClose->text());
   ui->outLayerNickname->setToolTip(name);
 
+  m_PopupMenu->setTitle(name);
 }
 
 void LayerInspectorRowDelegate::onModelUpdate(const EventBucket &bucket)
@@ -373,18 +482,24 @@ void LayerInspectorRowDelegate::onModelUpdate(const EventBucket &bucket)
     {
     this->ApplyColorMap();
     }
-  if(bucket.HasEvent(WrapperMetadataChangeEvent()))
+  if(bucket.HasEvent(WrapperMetadataChangeEvent(), m_Model->GetLayer()))
     {
     this->OnNicknameUpdate();
     }
-  if(bucket.HasEvent(ValueChangedEvent()))
-    {
-    this->UpdateVisibilityControls();
-    }
   if(bucket.HasEvent(ColorMapModel::PresetUpdateEvent()))
     {
     this->UpdateColorMapMenu();
     }
+  if(bucket.HasEvent(LayerChangeEvent(), m_Model->GetParentModel()->GetDriver())
+     || bucket.HasEvent(WrapperChangeEvent(), m_Model->GetParentModel()->GetDriver()))
+    {
+    this->UpdateOverlaysMenu();
+    }
+  if(bucket.HasEvent(ValueChangedEvent(), m_Model->GetParentModel()->GetGlobalState()->GetSelectedLayerIdModel()))
+    {
+    unsigned long sid = m_Model->GetParentModel()->GetGlobalState()->GetSelectedLayerId();
+    this->setSelected(m_Model->GetLayer() && sid == m_Model->GetLayer()->GetUniqueId());
+    }
 }
 
 void LayerInspectorRowDelegate::mouseMoveEvent(QMouseEvent *)
@@ -430,6 +545,7 @@ void LayerInspectorRowDelegate::on_btnMenu_pressed()
   ui->btnMenu->setDown(false);
 }
 
+/*
 void LayerInspectorRowDelegate::on_btnMoveUp_clicked()
 {
   m_Model->MoveLayerUp();
@@ -439,6 +555,7 @@ void LayerInspectorRowDelegate::on_btnMoveDown_pressed()
 {
   m_Model->MoveLayerDown();
 }
+*/
 
 void LayerInspectorRowDelegate::on_actionSave_triggered()
 {
@@ -471,3 +588,64 @@ void LayerInspectorRowDelegate::on_actionAutoContrast_triggered()
 {
   m_Model->AutoAdjustContrast();
 }
+
+void LayerInspectorRowDelegate::on_actionTextureFeatures_triggered()
+{
+  QtCursorOverride c(Qt::WaitCursor);
+  m_Model->GenerateTextureFeatures();
+}
+
+void LayerInspectorRowDelegate::on_actionPin_layer_triggered()
+{
+  m_Model->SetSticky(true);
+}
+
+void LayerInspectorRowDelegate::on_actionUnpin_layer_triggered()
+{
+  m_Model->SetSticky(false);
+}
+
+void LayerInspectorRowDelegate::on_actionContrast_Inspector_triggered()
+{
+  emit contrastInspectorRequested();
+}
+
+
+
+WidgetWithLabelAction::WidgetWithLabelAction(QWidget *parent)
+  : QWidgetAction(parent)
+{
+  m_Container = new QWidget(parent);
+  m_Label = new QLabel();
+
+  QHBoxLayout *lo = new QHBoxLayout();
+  lo->setContentsMargins(27, 4, 4, 4);
+  lo->setSpacing(10);
+  lo->addWidget(m_Label);
+  m_Container->setLayout(lo);
+
+  this->setDefaultWidget(m_Container);
+
+  connect(this, SIGNAL(changed()), this, SLOT(onChanged()));
+}
+
+void WidgetWithLabelAction::setWidget(QWidget *widget)
+{
+  m_Container->layout()->addWidget(widget);
+}
+
+void WidgetWithLabelAction::setLabelText(const QString &text)
+{
+  m_Label->setText(text);
+}
+
+void WidgetWithLabelAction::onChanged()
+{
+  m_Container->setVisible(this->isVisible());
+  m_Container->setEnabled(this->isEnabled());
+}
+
+void LayerInspectorRowDelegate::on_actionColor_Map_Editor_triggered()
+{
+  emit colorMapInspectorRequested();
+}
diff --git a/GUI/Qt/Components/LayerInspectorRowDelegate.h b/GUI/Qt/Components/LayerInspectorRowDelegate.h
index 13070a8..b075abd 100644
--- a/GUI/Qt/Components/LayerInspectorRowDelegate.h
+++ b/GUI/Qt/Components/LayerInspectorRowDelegate.h
@@ -4,12 +4,48 @@
 #include <QWidget>
 #include <SNAPComponent.h>
 #include "SNAPCommon.h"
+#include <QWidgetAction>
 
 class LayerTableRowModel;
 class ImageWrapperBase;
 class QMenu;
 class QActionGroup;
 class QContextMenuEvent;
+class QSlider;
+class QLabel;
+
+class OpacitySliderAction : public QWidgetAction
+{
+  Q_OBJECT
+public:
+  OpacitySliderAction(QWidget *parent = 0);
+  QSlider *GetSlider() { return m_Slider; }
+  QWidget *GetContainer() { return m_Container; }
+
+protected:
+  virtual QWidget *createWidget(QWidget *parent);
+  QSlider *m_Slider;
+  QWidget *m_Container;
+};
+
+
+class WidgetWithLabelAction : public QWidgetAction
+{
+  Q_OBJECT
+public:
+  WidgetWithLabelAction(QWidget *parent = 0);
+  void setWidget(QWidget *widget);
+  virtual void setLabelText(const QString &text);
+
+protected slots:
+
+  void onChanged();
+
+protected:
+
+  QWidget *m_Container;
+  QLabel *m_Label;
+};
 
 namespace Ui {
 class LayerInspectorRowDelegate;
@@ -62,14 +98,17 @@ public slots:
 
 signals:
   void selectionChanged(bool);
+  void contrastInspectorRequested();
+  void colorMapInspectorRequested();
   
 private slots:
   void on_btnMenu_pressed();
 
+  /*
   void on_btnMoveUp_clicked();
 
   void on_btnMoveDown_pressed();
-
+  */
   void on_actionSave_triggered();
 
   void on_actionClose_triggered();
@@ -78,6 +117,16 @@ private slots:
 
   void on_actionAutoContrast_triggered();
 
+  void on_actionTextureFeatures_triggered();
+
+  void on_actionPin_layer_triggered();
+
+  void on_actionUnpin_layer_triggered();
+
+  void on_actionContrast_Inspector_triggered();
+
+  void on_actionColor_Map_Editor_triggered();
+
 private:
   Ui::LayerInspectorRowDelegate *ui;
 
@@ -95,16 +144,20 @@ private:
   QMenu *m_PopupMenu;
 
   // A submenu for the color maps
-  QMenu *m_ColorMapMenu, *m_DisplayModeMenu;
+  QMenu *m_ColorMapMenu, *m_DisplayModeMenu, *m_OverlaysMenu;
+
+  // Slider for opacity that lives in the menu
+  QSlider *m_OverlayOpacitySlider;
+  WidgetWithLabelAction *m_OverlayOpacitySliderAction;
 
   // An action group for the system presets
   QActionGroup* m_SystemPresetActionGroup, *m_DisplayModeActionGroup;
 
   void ApplyColorMap();
   void UpdateBackgroundPalette();
-  void UpdateVisibilityControls();
   void UpdateColorMapMenu();
   void UpdateComponentMenu();
+  void UpdateOverlaysMenu();
   void OnNicknameUpdate();
 };
 
diff --git a/GUI/Qt/Components/LayerInspectorRowDelegate.ui b/GUI/Qt/Components/LayerInspectorRowDelegate.ui
index 993a6bd..bf3c640 100644
--- a/GUI/Qt/Components/LayerInspectorRowDelegate.ui
+++ b/GUI/Qt/Components/LayerInspectorRowDelegate.ui
@@ -6,10 +6,16 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>163</width>
-    <height>52</height>
+    <width>200</width>
+    <height>57</height>
    </rect>
   </property>
+  <property name="maximumSize">
+   <size>
+    <width>200</width>
+    <height>16777215</height>
+   </size>
+  </property>
   <property name="windowTitle">
    <string>Form</string>
   </property>
@@ -35,7 +41,16 @@ QMenu::item
    <property name="spacing">
     <number>0</number>
    </property>
-   <property name="margin">
+   <property name="leftMargin">
+    <number>0</number>
+   </property>
+   <property name="topMargin">
+    <number>0</number>
+   </property>
+   <property name="rightMargin">
+    <number>0</number>
+   </property>
+   <property name="bottomMargin">
     <number>0</number>
    </property>
    <item>
@@ -52,119 +67,189 @@ QMenu::item
      <property name="frameShadow">
       <enum>QFrame::Raised</enum>
      </property>
-     <layout class="QVBoxLayout" name="verticalLayout" stretch="0,0">
+     <layout class="QVBoxLayout" name="verticalLayout">
       <property name="spacing">
        <number>0</number>
       </property>
-      <property name="margin">
-       <number>1</number>
+      <property name="leftMargin">
+       <number>0</number>
+      </property>
+      <property name="topMargin">
+       <number>0</number>
+      </property>
+      <property name="rightMargin">
+       <number>0</number>
+      </property>
+      <property name="bottomMargin">
+       <number>0</number>
       </property>
       <item>
-       <widget class="QLabel" name="outLayerNickname">
-        <property name="maximumSize">
-         <size>
-          <width>158</width>
-          <height>16777215</height>
-         </size>
-        </property>
-        <property name="font">
-         <font>
-          <pointsize>-1</pointsize>
-         </font>
-        </property>
-        <property name="autoFillBackground">
-         <bool>false</bool>
-        </property>
-        <property name="styleSheet">
-         <string notr="true">font-size:12px;</string>
+       <layout class="QHBoxLayout" name="horizontalLayout_4">
+        <property name="spacing">
+         <number>4</number>
         </property>
-        <property name="text">
-         <string>TextLabel</string>
+        <property name="topMargin">
+         <number>0</number>
         </property>
-       </widget>
+        <item alignment="Qt::AlignLeft">
+         <widget class="QLabel" name="outLayerNickname">
+          <property name="maximumSize">
+           <size>
+            <width>158</width>
+            <height>16777215</height>
+           </size>
+          </property>
+          <property name="font">
+           <font>
+            <pointsize>-1</pointsize>
+           </font>
+          </property>
+          <property name="autoFillBackground">
+           <bool>false</bool>
+          </property>
+          <property name="styleSheet">
+           <string notr="true">font-size:12px;</string>
+          </property>
+          <property name="text">
+           <string>TextLabel</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
       </item>
       <item>
-       <layout class="QHBoxLayout" name="horizontalLayout_4">
+       <layout class="QHBoxLayout" name="horizontalLayout_2">
         <property name="spacing">
-         <number>6</number>
+         <number>2</number>
+        </property>
+        <property name="leftMargin">
+         <number>0</number>
         </property>
         <property name="rightMargin">
          <number>0</number>
         </property>
+        <property name="bottomMargin">
+         <number>0</number>
+        </property>
+        <item>
+         <widget class="QToolButton" name="btnSticky">
+          <property name="maximumSize">
+           <size>
+            <width>20</width>
+            <height>20</height>
+           </size>
+          </property>
+          <property name="toolTip">
+           <string><html><head/><body><p>&quot;Pin&quot; or &quot;unpin&quot; the image layer. When an image layer is pinned, it is rendered as an overlay on top of other images. </p></body></html></string>
+          </property>
+          <property name="autoFillBackground">
+           <bool>false</bool>
+          </property>
+          <property name="text">
+           <string>...</string>
+          </property>
+          <property name="icon">
+           <iconset resource="../Resources/SNAPResources.qrc">
+            <normaloff>:/root/icons8_unpin_12.png</normaloff>
+            <normalon>:/root/icons8_pin_12.png</normalon>:/root/icons8_unpin_12.png</iconset>
+          </property>
+          <property name="iconSize">
+           <size>
+            <width>12</width>
+            <height>12</height>
+           </size>
+          </property>
+          <property name="checkable">
+           <bool>true</bool>
+          </property>
+          <property name="checked">
+           <bool>false</bool>
+          </property>
+          <property name="autoRaise">
+           <bool>true</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <spacer name="horizontalSpacer_2">
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="sizeType">
+           <enum>QSizePolicy::Fixed</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>6</width>
+            <height>20</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
         <item>
-         <widget class="QStackedWidget" name="stack">
+         <widget class="QToolButton" name="btnVisible">
+          <property name="maximumSize">
+           <size>
+            <width>20</width>
+            <height>20</height>
+           </size>
+          </property>
+          <property name="toolTip">
+           <string><html><head/><body><p>Toggle between making the image layer visible or invisible.</p></body></html></string>
+          </property>
           <property name="autoFillBackground">
            <bool>false</bool>
           </property>
           <property name="styleSheet">
            <string notr="true"/>
           </property>
-          <property name="currentIndex">
-           <number>1</number>
-          </property>
-          <widget class="QWidget" name="pageControls">
-           <property name="autoFillBackground">
-            <bool>false</bool>
-           </property>
-           <layout class="QHBoxLayout" name="horizontalLayout_2">
-            <property name="spacing">
-             <number>2</number>
-            </property>
-            <property name="margin">
-             <number>0</number>
-            </property>
-            <item>
-             <widget class="QToolButton" name="btnVisible">
-              <property name="maximumSize">
-               <size>
-                <width>20</width>
-                <height>20</height>
-               </size>
-              </property>
-              <property name="toolTip">
-               <string><html><head/><body><p>Toggle between making the image layer visible or invisible.</p></body></html></string>
-              </property>
-              <property name="autoFillBackground">
-               <bool>false</bool>
-              </property>
-              <property name="styleSheet">
-               <string notr="true"/>
-              </property>
-              <property name="text">
-               <string>...</string>
-              </property>
-              <property name="icon">
-               <iconset resource="../Resources/SNAPResources.qrc">
-                <normaloff>:/root/icons8_invisible_16.png</normaloff>
-                <normalon>:/root/icons8_visible_16.png</normalon>:/root/icons8_invisible_16.png</iconset>
-              </property>
-              <property name="checkable">
-               <bool>true</bool>
-              </property>
-              <property name="checked">
-               <bool>true</bool>
-              </property>
-              <property name="autoRaise">
-               <bool>true</bool>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QSlider" name="inLayerOpacity">
-              <property name="maximumSize">
-               <size>
-                <width>64</width>
-                <height>16777215</height>
-               </size>
-              </property>
-              <property name="toolTip">
-               <string><html><head/><body><p>Change the opacity of the image layer.</p></body></html></string>
-              </property>
-              <property name="autoFillBackground">
-               <bool>false</bool>
-              </property>
-              <property name="styleSheet">
-               <string notr="true">QSlider::groove:horizontal {
+          <property name="text">
+           <string>...</string>
+          </property>
+          <property name="icon">
+           <iconset resource="../Resources/SNAPResources.qrc">
+            <normaloff>:/root/icons8_invisible_12.png</normaloff>
+            <normalon>:/root/icons8_visible_12.png</normalon>:/root/icons8_invisible_12.png</iconset>
+          </property>
+          <property name="iconSize">
+           <size>
+            <width>12</width>
+            <height>12</height>
+           </size>
+          </property>
+          <property name="checkable">
+           <bool>true</bool>
+          </property>
+          <property name="checked">
+           <bool>true</bool>
+          </property>
+          <property name="autoRaise">
+           <bool>true</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QSlider" name="inLayerOpacity">
+          <property name="minimumSize">
+           <size>
+            <width>64</width>
+            <height>0</height>
+           </size>
+          </property>
+          <property name="maximumSize">
+           <size>
+            <width>64</width>
+            <height>20</height>
+           </size>
+          </property>
+          <property name="toolTip">
+           <string><html><head/><body><p>Change the opacity of the image layer.</p></body></html></string>
+          </property>
+          <property name="autoFillBackground">
+           <bool>false</bool>
+          </property>
+          <property name="styleSheet">
+           <string notr="true">QSlider::groove:horizontal {
 border: 1px solid #bbb;
 background: white;
 height: 6px;
@@ -220,167 +305,93 @@ background: #eee;
 border: 1px solid #aaa;
 border-radius: 4px;
 }</string>
-              </property>
-              <property name="sliderPosition">
-               <number>55</number>
-              </property>
-              <property name="orientation">
-               <enum>Qt::Horizontal</enum>
-              </property>
-              <property name="tickPosition">
-               <enum>QSlider::NoTicks</enum>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QToolButton" name="btnSticky">
-              <property name="maximumSize">
-               <size>
-                <width>20</width>
-                <height>20</height>
-               </size>
-              </property>
-              <property name="toolTip">
-               <string><html><head/><body><p>&quot;Pin&quot; or &quot;unpin&quot; the image layer. When an image layer is pinned, it is shown as an overlay when image layers are tiled (<img src=":/root/layout_tile_16.png"/>).</p></body></html></string>
-              </property>
-              <property name="autoFillBackground">
-               <bool>false</bool>
-              </property>
-              <property name="text">
-               <string>...</string>
-              </property>
-              <property name="icon">
-               <iconset resource="../Resources/SNAPResources.qrc">
-                <normaloff>:/root/icons8_unpin_16.png</normaloff>
-                <normalon>:/root/icons8_pin_16.png</normalon>:/root/icons8_unpin_16.png</iconset>
-              </property>
-              <property name="checkable">
-               <bool>true</bool>
-              </property>
-              <property name="checked">
-               <bool>false</bool>
-              </property>
-              <property name="autoRaise">
-               <bool>true</bool>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QToolButton" name="btnMoveUp">
-              <property name="maximumSize">
-               <size>
-                <width>20</width>
-                <height>20</height>
-               </size>
-              </property>
-              <property name="toolTip">
-               <string><html><head/><body><p>Move an image layer up in the list of image layers. This changes its position when layers are tiled (<img src=":/root/layout_tile_16.png"/>) and makes it be rendered earlier when layers are stacked (<img src=":/root/layout_overlay_16.png"/>).</p></body></html></string>
-              </property>
-              <property name="autoFillBackground">
-               <bool>false</bool>
-              </property>
-              <property name="text">
-               <string>...</string>
-              </property>
-              <property name="icon">
-               <iconset resource="../Resources/SNAPResources.qrc">
-                <normaloff>:/root/icons8_up_18.png</normaloff>:/root/icons8_up_18.png</iconset>
-              </property>
-              <property name="checked">
-               <bool>false</bool>
-              </property>
-              <property name="autoRaise">
-               <bool>true</bool>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QToolButton" name="btnMoveDown">
-              <property name="maximumSize">
-               <size>
-                <width>20</width>
-                <height>20</height>
-               </size>
-              </property>
-              <property name="toolTip">
-               <string><html><head/><body><p>Move an image layer down in the list of image layers. This changes its position when layers are tiled (<img src=":/root/layout_tile_16.png"/>) and makes it be rendered later when layers are stacked (<img src=":/root/layout_overlay_16.png"/>).</p></body></html></string>
-              </property>
-              <property name="autoFillBackground">
-               <bool>false</bool>
-              </property>
-              <property name="text">
-               <string>...</string>
-              </property>
-              <property name="icon">
-               <iconset resource="../Resources/SNAPResources.qrc">
-                <normaloff>:/root/icons8_down_18.png</normaloff>:/root/icons8_down_18.png</iconset>
-              </property>
-              <property name="checkable">
-               <bool>false</bool>
-              </property>
-              <property name="checked">
-               <bool>false</bool>
-              </property>
-              <property name="autoRaise">
-               <bool>true</bool>
-              </property>
-             </widget>
-            </item>
-           </layout>
-          </widget>
-          <widget class="QWidget" name="pageBlank">
-           <property name="autoFillBackground">
-            <bool>false</bool>
-           </property>
-           <property name="styleSheet">
-            <string notr="true"/>
-           </property>
-           <layout class="QHBoxLayout" name="horizontalLayout_3">
-            <property name="margin">
-             <number>0</number>
-            </property>
-            <item>
-             <widget class="QLabel" name="outComponent">
-              <property name="toolTip">
-               <string><html><head/><body><p>Indicates what aspect of a multi-component image layer is displayed (e.g., a particular component, magnitude of components, etc.).</p></body></html></string>
-              </property>
-              <property name="styleSheet">
-               <string notr="true">font-size:11px;
+          </property>
+          <property name="sliderPosition">
+           <number>55</number>
+          </property>
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="tickPosition">
+           <enum>QSlider::NoTicks</enum>
+          </property>
+         </widget>
+        </item>
+        <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="QLabel" name="outComponent">
+          <property name="maximumSize">
+           <size>
+            <width>16777215</width>
+            <height>20</height>
+           </size>
+          </property>
+          <property name="toolTip">
+           <string><html><head/><body><p>Indicates what aspect of a multi-component image layer is displayed (e.g., a particular component, magnitude of components, etc.).</p></body></html></string>
+          </property>
+          <property name="styleSheet">
+           <string notr="true">font-size:11px;
 color: rgb(120, 120, 120)</string>
-              </property>
-              <property name="text">
-               <string>TextLabel</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QToolButton" name="btnMenu">
-              <property name="toolTip">
-               <string><html><head/><body><p>Show a context menu of commands for this image layer.</p></body></html></string>
-              </property>
-              <property name="autoFillBackground">
-               <bool>false</bool>
-              </property>
-              <property name="text">
-               <string>...</string>
-              </property>
-              <property name="icon">
-               <iconset resource="../Resources/SNAPResources.qrc">
-                <normaloff>:/root/open_popup_16.png</normaloff>:/root/open_popup_16.png</iconset>
-              </property>
-              <property name="checkable">
-               <bool>false</bool>
-              </property>
-              <property name="checked">
-               <bool>false</bool>
-              </property>
-              <property name="autoRaise">
-               <bool>true</bool>
-              </property>
-             </widget>
-            </item>
-           </layout>
-          </widget>
+          </property>
+          <property name="text">
+           <string>TextLabel</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QToolButton" name="btnMenu">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="maximumSize">
+           <size>
+            <width>16777215</width>
+            <height>20</height>
+           </size>
+          </property>
+          <property name="toolTip">
+           <string><html><head/><body><p>Show a context menu of commands for this image layer.</p></body></html></string>
+          </property>
+          <property name="autoFillBackground">
+           <bool>false</bool>
+          </property>
+          <property name="text">
+           <string>...</string>
+          </property>
+          <property name="icon">
+           <iconset resource="../Resources/SNAPResources.qrc">
+            <normaloff>:/root/context_gray_10.png</normaloff>:/root/context_gray_10.png</iconset>
+          </property>
+          <property name="iconSize">
+           <size>
+            <width>10</width>
+            <height>10</height>
+           </size>
+          </property>
+          <property name="checkable">
+           <bool>false</bool>
+          </property>
+          <property name="checked">
+           <bool>false</bool>
+          </property>
+          <property name="autoRaise">
+           <bool>true</bool>
+          </property>
          </widget>
         </item>
        </layout>
@@ -425,6 +436,55 @@ color: rgb(120, 120, 120)</string>
     <string>Adjust contrast of the image layer automatically for optimal visualization</string>
    </property>
   </action>
+  <action name="actionTextureFeatures">
+   <property name="text">
+    <string>Generate texture features</string>
+   </property>
+   <property name="toolTip">
+    <string>Create texture features derived from this image</string>
+   </property>
+  </action>
+  <action name="actionPin_layer">
+   <property name="icon">
+    <iconset resource="../Resources/SNAPResources.qrc">
+     <normaloff>:/root/icons8_pin_16.png</normaloff>
+     <normalon>:/root/icons8_pin_16.png</normalon>:/root/icons8_pin_16.png</iconset>
+   </property>
+   <property name="text">
+    <string>Display as ovelay</string>
+   </property>
+   <property name="toolTip">
+    <string>Display the layer as a semi-transparent overlay on top of other image layers</string>
+   </property>
+  </action>
+  <action name="actionUnpin_layer">
+   <property name="icon">
+    <iconset resource="../Resources/SNAPResources.qrc">
+     <normaloff>:/root/icons8_unpin_16.png</normaloff>:/root/icons8_unpin_16.png</iconset>
+   </property>
+   <property name="text">
+    <string>Display as base layer</string>
+   </property>
+   <property name="toolTip">
+    <string>Display the layer side by side with other layers</string>
+   </property>
+  </action>
+  <action name="actionContrast_Inspector">
+   <property name="text">
+    <string>Contrast Inspector ...</string>
+   </property>
+   <property name="toolTip">
+    <string>Open the contrast inspector to adjust image contrast for this layer</string>
+   </property>
+  </action>
+  <action name="actionColor_Map_Editor">
+   <property name="text">
+    <string>Color Map Inspector ...</string>
+   </property>
+   <property name="toolTip">
+    <string>Open the color map editor for this layer</string>
+   </property>
+  </action>
  </widget>
  <resources>
   <include location="../Resources/SNAPResources.qrc"/>
diff --git a/GUI/Qt/Components/PaintbrushToolPanel.cxx b/GUI/Qt/Components/PaintbrushToolPanel.cxx
index 5a3f67c..626d56c 100644
--- a/GUI/Qt/Components/PaintbrushToolPanel.cxx
+++ b/GUI/Qt/Components/PaintbrushToolPanel.cxx
@@ -21,8 +21,26 @@ PaintbrushToolPanel::PaintbrushToolPanel(QWidget *parent) :
   ui->actionBrushDecrease->setShortcuts(
         ui->actionBrushDecrease->shortcuts() << QKeySequence('_'));
 
+  ui->actionGranularityIncrease->setShortcuts(
+        ui->actionGranularityIncrease->shortcuts() << QKeySequence(Qt::META + Qt::Key_Equal) << QKeySequence(Qt::META + Qt::Key_Plus));
+
+  ui->actionGranularityDecrease->setShortcuts(
+        ui->actionGranularityDecrease->shortcuts() << QKeySequence(Qt::META + Qt::Key_Underscore) << QKeySequence(Qt::META + Qt::Key_Minus));
+
+  ui->actionSmoothnessIncrease->setShortcuts(
+        ui->actionSmoothnessIncrease->shortcuts() << QKeySequence(Qt::ALT + Qt::Key_Equal) << QKeySequence(Qt::ALT + Qt::Key_Plus));
+
+  ui->actionSmoothnessDecrease->setShortcuts(
+        ui->actionSmoothnessDecrease->shortcuts() << QKeySequence(Qt::ALT + Qt::Key_Underscore) << QKeySequence(Qt::ALT + Qt::Key_Minus));
+
+
   addAction(ui->actionBrushIncrease);
   addAction(ui->actionBrushDecrease);
+  addAction(ui->actionGranularityDecrease);
+  addAction(ui->actionGranularityIncrease);
+  addAction(ui->actionSmoothnessDecrease);
+  addAction(ui->actionSmoothnessIncrease);
+  addAction(ui->actionBrushStyle);
 }
 
 PaintbrushToolPanel::~PaintbrushToolPanel()
@@ -56,3 +74,13 @@ void PaintbrushToolPanel::SetModel(PaintbrushSettingsModel *model)
   makeCoupling(ui->inGranularity, model->GetThresholdLevelModel());
   makeCoupling(ui->inSmoothness, model->GetSmoothingIterationsModel());
 }
+
+void PaintbrushToolPanel::on_actionBrushStyle_triggered()
+{
+  if(ui->btnSquare->isChecked())
+    ui->btnRound->setChecked(true);
+  else if(ui->btnRound->isChecked())
+    ui->btnWatershed->setChecked(true);
+  else if(ui->btnWatershed->isChecked())
+    ui->btnSquare->setChecked(true);
+}
diff --git a/GUI/Qt/Components/PaintbrushToolPanel.h b/GUI/Qt/Components/PaintbrushToolPanel.h
index 9002ee0..a26327f 100644
--- a/GUI/Qt/Components/PaintbrushToolPanel.h
+++ b/GUI/Qt/Components/PaintbrushToolPanel.h
@@ -18,7 +18,10 @@ public:
   ~PaintbrushToolPanel();
 
   void SetModel(PaintbrushSettingsModel *model);
-  
+    
+private slots:
+  void on_actionBrushStyle_triggered();
+
 private:
   Ui::PaintbrushToolPanel *ui;
   PaintbrushSettingsModel *m_Model;
diff --git a/GUI/Qt/Components/PaintbrushToolPanel.ui b/GUI/Qt/Components/PaintbrushToolPanel.ui
index 54e0fc6..d670162 100644
--- a/GUI/Qt/Components/PaintbrushToolPanel.ui
+++ b/GUI/Qt/Components/PaintbrushToolPanel.ui
@@ -13,53 +13,30 @@
   <property name="windowTitle">
    <string>Form</string>
   </property>
+  <property name="styleSheet">
+   <string notr="true">* {
+font-size:12px;
+}
+QSpinBox {
+font-size:11px;
+}</string>
+  </property>
   <layout class="QVBoxLayout" name="verticalLayout">
-   <property name="margin">
+   <property name="spacing">
+    <number>4</number>
+   </property>
+   <property name="leftMargin">
+    <number>0</number>
+   </property>
+   <property name="topMargin">
+    <number>0</number>
+   </property>
+   <property name="rightMargin">
+    <number>0</number>
+   </property>
+   <property name="bottomMargin">
     <number>0</number>
    </property>
-   <item>
-    <widget class="QLabel" name="label">
-     <property name="sizePolicy">
-      <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
-       <horstretch>0</horstretch>
-       <verstretch>0</verstretch>
-      </sizepolicy>
-     </property>
-     <property name="maximumSize">
-      <size>
-       <width>160</width>
-       <height>16777215</height>
-      </size>
-     </property>
-     <property name="font">
-      <font>
-       <pointsize>-1</pointsize>
-      </font>
-     </property>
-     <property name="styleSheet">
-      <string notr="true">* {
-font-size: 11px;
-}
-</string>
-     </property>
-     <property name="text">
-      <string>Paint with the selected label by clicking and dragging the left mouse button</string>
-     </property>
-     <property name="wordWrap">
-      <bool>true</bool>
-     </property>
-    </widget>
-   </item>
-   <item>
-    <widget class="Line" name="line_2">
-     <property name="frameShadow">
-      <enum>QFrame::Plain</enum>
-     </property>
-     <property name="orientation">
-      <enum>Qt::Horizontal</enum>
-     </property>
-    </widget>
-   </item>
    <item>
     <widget class="QLabel" name="label_2">
      <property name="text">
@@ -94,7 +71,7 @@ font-size: 11px;
          </size>
         </property>
         <property name="toolTip">
-         <string><html><head/><body><p>Rectangular brush shape</p></body></html></string>
+         <string><html><head/><body><p><span style=" font-weight:600;">Square brush shape (⌘B to cycle)</span></p></string>
         </property>
         <property name="text">
          <string>square</string>
@@ -103,6 +80,9 @@ font-size: 11px;
          <iconset resource="../Resources/SNAPResources.qrc">
           <normaloff>:/root/brush_shape_square.png</normaloff>:/root/brush_shape_square.png</iconset>
         </property>
+        <property name="shortcut">
+         <string>Ctrl+S</string>
+        </property>
         <property name="checkable">
          <bool>true</bool>
         </property>
@@ -120,7 +100,7 @@ font-size: 11px;
          </size>
         </property>
         <property name="toolTip">
-         <string><html><head/><body><p>Round brush shape</p></body></html></string>
+         <string><html><head/><body><p><span style=" font-weight:600;">Round brush shape (⌘B to cycle)</span></p></body></html></string>
         </property>
         <property name="text">
          <string>round</string>
@@ -146,7 +126,7 @@ font-size: 11px;
          </size>
         </property>
         <property name="toolTip">
-         <string><html><head/><body><p>Adaptive brush (adjusts shape to follow image boundaries)</p></body></html></string>
+         <string><html><head/><body><p><span style=" font-weight:600;">Adaptive brush (⌘B to cycle)</span></p><p>The brush adjusts itself to follow image boundaries.</p></body></html></string>
         </property>
         <property name="text">
          <string>adaptive</string>
@@ -180,6 +160,22 @@ font-size: 11px;
     </widget>
    </item>
    <item>
+    <spacer name="verticalSpacer_2">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeType">
+      <enum>QSizePolicy::Fixed</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>4</width>
+       <height>4</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item>
     <widget class="QLabel" name="label_3">
      <property name="text">
       <string>Brush Size:</string>
@@ -190,7 +186,7 @@ font-size: 11px;
     <widget class="QWidget" name="widget_2" native="true">
      <layout class="QHBoxLayout" name="horizontalLayout_2">
       <property name="spacing">
-       <number>12</number>
+       <number>6</number>
       </property>
       <property name="topMargin">
        <number>0</number>
@@ -202,10 +198,23 @@ font-size: 11px;
        <number>0</number>
       </property>
       <item>
-       <widget class="QSpinBox" name="inBrushSizeSpinbox"/>
+       <widget class="QSpinBox" name="inBrushSizeSpinbox">
+        <property name="minimumSize">
+         <size>
+          <width>48</width>
+          <height>0</height>
+         </size>
+        </property>
+        <property name="toolTip">
+         <string><html><head/><body><p>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Brush Size (+, - keys)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Adjust the radius of the paintbrush.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</p></body></html></string>
+        </property>
+       </widget>
       </item>
       <item>
        <widget class="QSlider" name="inBrushSizeSlider">
+        <property name="toolTip">
+         <string><html><head/><body><p><span style=" font-weight:600;">Brush Size (+, - keys)</span></p><p>Adjust the radius of the paintbrush.</p></body></html></string>
+        </property>
         <property name="orientation">
          <enum>Qt::Horizontal</enum>
         </property>
@@ -215,6 +224,22 @@ font-size: 11px;
     </widget>
    </item>
    <item>
+    <spacer name="verticalSpacer_3">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeType">
+      <enum>QSizePolicy::Fixed</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>4</width>
+       <height>4</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item>
     <widget class="QLabel" name="label_4">
      <property name="text">
       <string>Brush Options:</string>
@@ -223,7 +248,12 @@ font-size: 11px;
    </item>
    <item>
     <widget class="QWidget" name="widget" native="true">
-     <layout class="QVBoxLayout" name="verticalLayout_2">
+     <property name="styleSheet">
+      <string notr="true">QCheckBox {
+  padding:0px;
+}</string>
+     </property>
+     <layout class="QGridLayout" name="gridLayout">
       <property name="topMargin">
        <number>0</number>
       </property>
@@ -233,50 +263,90 @@ font-size: 11px;
       <property name="bottomMargin">
        <number>0</number>
       </property>
-      <item>
+      <property name="horizontalSpacing">
+       <number>0</number>
+      </property>
+      <property name="verticalSpacing">
+       <number>8</number>
+      </property>
+      <item row="0" column="0">
        <widget class="QCheckBox" name="chkVolumetric">
         <property name="toolTip">
-         <string><html><head/><body><p>When checked, the brush is applied in all three dimensions: a rectangular brush creates a cube in the segmentation, and a round brush creates a sphere.</p></body></html></string>
+         <string><html><head/><body><p><span style=" font-weight:600;">Toggle 3D brush mode (⇧⌘B, V)</span></p><p>When checked, the brush is applied in all three dimensions: a rectangular brush creates a cube in the segmentation, and a round brush creates a sphere.</p></body></html></string>
         </property>
         <property name="text">
-         <string>Volumetric</string>
+         <string>3D</string>
+        </property>
+        <property name="shortcut">
+         <string>Ctrl+Shift+B, V</string>
         </property>
        </widget>
       </item>
-      <item>
+      <item row="0" column="1">
        <widget class="QCheckBox" name="chkIsotropic">
         <property name="toolTip">
-         <string><html><head/><body><p>This option is relevant for images with anisotropic voxels (voxels with different x,y and z dimensions). When checked, the physical dimensions of the brush are kept as close to equal as possible. When not checked, the brush size is K x K voxels, regardless of the dimensions of the voxel.</p></body></html></string>
+         <string><html><head/><body><p><span style=" font-weight:600;">Toggle isotropic brush mode (⇧⌘B, I)</span></p><p>This option is relevant for images with anisotropic voxels (voxels with different x,y and z dimensions). When checked, the physical dimensions of the brush are kept as close to equal as possible. When not checked, the brush size is K x K voxels, regardless of the dimensions of the voxel.</p></body>&l [...]
         </property>
         <property name="text">
          <string>Isotropic</string>
         </property>
+        <property name="shortcut">
+         <string>Ctrl+Shift+B, I</string>
+        </property>
        </widget>
       </item>
-      <item>
+      <item row="3" column="0" colspan="2">
        <widget class="QCheckBox" name="chkChase">
         <property name="toolTip">
-         <string><html><head/><body><p>When checked, at the end of each paintbrush stroke, the position of the 3D image cursor is reset to the endpoint of the stroke.</p></body></html></string>
+         <string><html><head/><body><p><span style=" font-weight:600;">Toggle cursor chasing mode (⇧⌘B, C)</span></p><p>When checked, at the end of each paintbrush stroke, the position of the 3D image cursor is reset to the endpoint of the stroke.</p></body></html></string>
         </property>
         <property name="text">
          <string>Cursor chases brush</string>
         </property>
+        <property name="shortcut">
+         <string>Ctrl+Shift+B, C</string>
+        </property>
        </widget>
       </item>
      </layout>
     </widget>
    </item>
    <item>
+    <spacer name="verticalSpacer_4">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeType">
+      <enum>QSizePolicy::Fixed</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>4</width>
+       <height>4</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item>
     <widget class="QWidget" name="grpAdaptive" native="true">
      <layout class="QVBoxLayout" name="verticalLayout_3">
-      <property name="margin">
+      <property name="spacing">
+       <number>4</number>
+      </property>
+      <property name="leftMargin">
+       <number>0</number>
+      </property>
+      <property name="topMargin">
+       <number>0</number>
+      </property>
+      <property name="rightMargin">
+       <number>0</number>
+      </property>
+      <property name="bottomMargin">
        <number>0</number>
       </property>
       <item>
-       <widget class="Line" name="line_3">
-        <property name="frameShadow">
-         <enum>QFrame::Plain</enum>
-        </property>
+       <widget class="Line" name="line">
         <property name="orientation">
          <enum>Qt::Horizontal</enum>
         </property>
@@ -323,7 +393,7 @@ font-size: 11px;
          <item row="0" column="1">
           <widget class="QDoubleSpinBox" name="inGranularity">
            <property name="toolTip">
-            <string><html><head/><body><p>Lower values of this parameter lead to oversegmentation, while higher values lead to undersegmentation. </p></body></html></string>
+            <string><html><head/><body><p><span style=" font-weight:600;">Adaptive brush granularity (^+,^-)</span></p><p>Lower values of this parameter lead to oversegmentation, while higher values lead to undersegmentation.</p></body></html></string>
            </property>
           </widget>
          </item>
@@ -340,7 +410,7 @@ font-size: 11px;
          <item row="1" column="1">
           <widget class="QDoubleSpinBox" name="inSmoothness">
            <property name="toolTip">
-            <string><html><head/><body><p>Larger values of this parameter produce smoother segments.</p></body></html></string>
+            <string><html><head/><body><p><span style=" font-weight:600;">Adaptive brush smoothness (⌥+,⌥-)</span></p><p>Larger values of this parameter produce smoother segments.</p></body></html></string>
            </property>
           </widget>
          </item>
@@ -380,6 +450,40 @@ font-size: 11px;
     <string>-</string>
    </property>
   </action>
+  <action name="actionGranularityIncrease">
+   <property name="text">
+    <string>GranularityIncrease</string>
+   </property>
+  </action>
+  <action name="actionGranularityDecrease">
+   <property name="text">
+    <string>GranularityDecrease</string>
+   </property>
+   <property name="toolTip">
+    <string>GranularityDecrease</string>
+   </property>
+  </action>
+  <action name="actionSmoothnessIncrease">
+   <property name="text">
+    <string>SmoothnessIncrease</string>
+   </property>
+   <property name="shortcut">
+    <string>Alt+Tab</string>
+   </property>
+  </action>
+  <action name="actionSmoothnessDecrease">
+   <property name="text">
+    <string>SmoothnessDecrease</string>
+   </property>
+  </action>
+  <action name="actionBrushStyle">
+   <property name="text">
+    <string>BrushStyle</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+B</string>
+   </property>
+  </action>
  </widget>
  <resources>
   <include location="../Resources/SNAPResources.qrc"/>
@@ -417,5 +521,69 @@ font-size: 11px;
     </hint>
    </hints>
   </connection>
+  <connection>
+   <sender>actionGranularityIncrease</sender>
+   <signal>triggered()</signal>
+   <receiver>inGranularity</receiver>
+   <slot>stepUp()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>-1</x>
+     <y>-1</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>138</x>
+     <y>214</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>actionGranularityDecrease</sender>
+   <signal>triggered()</signal>
+   <receiver>inGranularity</receiver>
+   <slot>stepDown()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>-1</x>
+     <y>-1</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>138</x>
+     <y>214</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>actionSmoothnessIncrease</sender>
+   <signal>triggered()</signal>
+   <receiver>inSmoothness</receiver>
+   <slot>stepUp()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>-1</x>
+     <y>-1</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>138</x>
+     <y>241</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>actionSmoothnessDecrease</sender>
+   <signal>triggered()</signal>
+   <receiver>inSmoothness</receiver>
+   <slot>stepDown()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>-1</x>
+     <y>-1</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>138</x>
+     <y>241</y>
+    </hint>
+   </hints>
+  </connection>
  </connections>
 </ui>
diff --git a/GUI/Qt/Components/PolygonToolPanel.cxx b/GUI/Qt/Components/PolygonToolPanel.cxx
new file mode 100644
index 0000000..e04ad42
--- /dev/null
+++ b/GUI/Qt/Components/PolygonToolPanel.cxx
@@ -0,0 +1,51 @@
+#include "PolygonToolPanel.h"
+#include "ui_PolygonToolPanel.h"
+#include "GlobalUIModel.h"
+
+#include "QtCheckBoxCoupling.h"
+#include "QtSpinBoxCoupling.h"
+#include "QtSliderCoupling.h"
+#include "QtRadioButtonCoupling.h"
+
+#include "GlobalState.h"
+#include "PolygonSettingsModel.h"
+#include "QtWidgetActivator.h"
+
+PolygonToolPanel::PolygonToolPanel(QWidget *parent) :
+  QWidget(parent),
+  ui(new Ui::PolygonToolPanel)
+{
+  ui->setupUi(this);
+}
+
+PolygonToolPanel::~PolygonToolPanel()
+{
+  delete ui;
+}
+
+void PolygonToolPanel::SetModel(GlobalUIModel *model)
+{
+  m_Model = model;
+
+  // Couple the inversion checkbox
+  makeCoupling(ui->chkInvertPolygon,
+               m_Model->GetGlobalState()->GetPolygonInvertModel());
+
+  // Couple the freehand drawing mode
+  makeCoupling(ui->inSegmentLength,
+               m_Model->GetPolygonSettingsModel()->GetFreehandSegmentLengthModel());
+  makeCoupling(ui->inSegmentLengthSlider,
+               m_Model->GetPolygonSettingsModel()->GetFreehandSegmentLengthModel());
+
+  // Couple the radio buttons
+  std::map<bool, QAbstractButton *> radioMap;
+  radioMap[false] = ui->btnSmooth;
+  radioMap[true] = ui->btnPiecewiseLinear;
+  makeRadioGroupCoupling(ui->grpCurveStyle, radioMap,
+                         m_Model->GetPolygonSettingsModel()->GetFreehandIsPiecewiseModel());
+
+  // Toggle the appearance of the piecewise block
+  makeWidgetVisibilityCoupling(ui->grpSegmentLength,
+                               m_Model->GetPolygonSettingsModel()->GetFreehandIsPiecewiseModel());
+
+}
diff --git a/GUI/Qt/Components/PolygonToolPanel.h b/GUI/Qt/Components/PolygonToolPanel.h
new file mode 100644
index 0000000..b715329
--- /dev/null
+++ b/GUI/Qt/Components/PolygonToolPanel.h
@@ -0,0 +1,27 @@
+#ifndef POLYGONTOOLPANEL_H
+#define POLYGONTOOLPANEL_H
+
+#include <QWidget>
+
+namespace Ui {
+  class PolygonToolPanel;
+}
+
+class GlobalUIModel;
+
+class PolygonToolPanel : public QWidget
+{
+  Q_OBJECT
+
+public:
+  explicit PolygonToolPanel(QWidget *parent = 0);
+  ~PolygonToolPanel();
+
+  void SetModel(GlobalUIModel *model);
+
+private:
+  Ui::PolygonToolPanel *ui;
+  GlobalUIModel *m_Model;
+};
+
+#endif // POLYGONTOOLPANEL_H
diff --git a/GUI/Qt/Components/PolygonToolPanel.ui b/GUI/Qt/Components/PolygonToolPanel.ui
new file mode 100644
index 0000000..812e4a7
--- /dev/null
+++ b/GUI/Qt/Components/PolygonToolPanel.ui
@@ -0,0 +1,207 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>PolygonToolPanel</class>
+ <widget class="QWidget" name="PolygonToolPanel">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>174</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <property name="styleSheet">
+   <string notr="true">QWidget {
+font-size:12px;
+}
+
+</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout_3">
+   <property name="spacing">
+    <number>4</number>
+   </property>
+   <property name="leftMargin">
+    <number>0</number>
+   </property>
+   <property name="topMargin">
+    <number>0</number>
+   </property>
+   <property name="rightMargin">
+    <number>0</number>
+   </property>
+   <property name="bottomMargin">
+    <number>0</number>
+   </property>
+   <item>
+    <widget class="QLabel" name="label_4">
+     <property name="text">
+      <string>Freehand drawing style:</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QWidget" name="grpCurveStyle" native="true">
+     <property name="styleSheet">
+      <string notr="true">QRadioButton {
+  padding: 0px;
+}</string>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout">
+      <property name="spacing">
+       <number>4</number>
+      </property>
+      <property name="leftMargin">
+       <number>20</number>
+      </property>
+      <property name="topMargin">
+       <number>0</number>
+      </property>
+      <property name="rightMargin">
+       <number>0</number>
+      </property>
+      <property name="bottomMargin">
+       <number>0</number>
+      </property>
+      <item>
+       <widget class="QRadioButton" name="btnSmooth">
+        <property name="text">
+         <string>Smooth curve</string>
+        </property>
+        <property name="checked">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QRadioButton" name="btnPiecewiseLinear">
+        <property name="text">
+         <string>Polygon</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QWidget" name="grpSegmentLength" native="true">
+     <layout class="QVBoxLayout" name="verticalLayout_2">
+      <property name="spacing">
+       <number>0</number>
+      </property>
+      <property name="leftMargin">
+       <number>40</number>
+      </property>
+      <property name="topMargin">
+       <number>0</number>
+      </property>
+      <property name="rightMargin">
+       <number>0</number>
+      </property>
+      <property name="bottomMargin">
+       <number>0</number>
+      </property>
+      <item>
+       <widget class="QLabel" name="label_2">
+        <property name="text">
+         <string>Segment length:</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <layout class="QHBoxLayout" name="horizontalLayout">
+        <property name="spacing">
+         <number>6</number>
+        </property>
+        <property name="topMargin">
+         <number>0</number>
+        </property>
+        <item>
+         <widget class="QSpinBox" name="inSegmentLength">
+          <property name="buttonSymbols">
+           <enum>QAbstractSpinBox::NoButtons</enum>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QSlider" name="inSegmentLengthSlider">
+          <property name="toolTip">
+           <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'Helvetica'; font-size:12px; font-weight:400; font-style:normal;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Set the overall opacity of segmentation labels.</p>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">[A]: Make more transparent</p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">[D]: Make more opaque</p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">[S]: Toggle on/off</p></body></html></string>
+          </property>
+          <property name="minimum">
+           <number>0</number>
+          </property>
+          <property name="maximum">
+           <number>100</number>
+          </property>
+          <property name="singleStep">
+           <number>1</number>
+          </property>
+          <property name="pageStep">
+           <number>10</number>
+          </property>
+          <property name="value">
+           <number>50</number>
+          </property>
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="tickPosition">
+           <enum>QSlider::NoTicks</enum>
+          </property>
+          <property name="tickInterval">
+           <number>25</number>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="Line" name="line">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="chkInvertPolygon">
+     <property name="toolTip">
+      <string><html><head/><body><p>When enabled, polygon drawing operations are inverted, i.e., the outside of the polygon is filled with the active label.</p></body></html></string>
+     </property>
+     <property name="text">
+      <string>Invert polygon</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <spacer name="verticalSpacer">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>20</width>
+       <height>40</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/GUI/Qt/Components/QtHideOnDeactivateContainer.cxx b/GUI/Qt/Components/QtHideOnDeactivateContainer.cxx
new file mode 100644
index 0000000..9370cea
--- /dev/null
+++ b/GUI/Qt/Components/QtHideOnDeactivateContainer.cxx
@@ -0,0 +1,24 @@
+#include "QtHideOnDeactivateContainer.h"
+#include <QEvent>
+
+QtHideOnDeactivateContainer::QtHideOnDeactivateContainer(QWidget *parent)
+    : QWidget(parent)
+{
+
+}
+
+QtHideOnDeactivateContainer::~QtHideOnDeactivateContainer()
+{
+
+}
+
+void QtHideOnDeactivateContainer::changeEvent(QEvent *event)
+{
+  QWidget::changeEvent(event);
+  if(event->type() == QEvent::EnabledChange)
+    {
+    this->setVisible(this->isEnabled());
+    }
+}
+
+
diff --git a/GUI/Qt/Components/QtHideOnDeactivateContainer.h b/GUI/Qt/Components/QtHideOnDeactivateContainer.h
new file mode 100644
index 0000000..0e9f9de
--- /dev/null
+++ b/GUI/Qt/Components/QtHideOnDeactivateContainer.h
@@ -0,0 +1,16 @@
+#ifndef QTHIDEONDEACTIVATECONTAINER_H
+#define QTHIDEONDEACTIVATECONTAINER_H
+
+#include <QWidget>
+
+class QtHideOnDeactivateContainer : public QWidget
+{
+  Q_OBJECT
+public:
+  QtHideOnDeactivateContainer(QWidget *parent);
+  ~QtHideOnDeactivateContainer();
+
+  virtual void changeEvent(QEvent *event);
+};
+
+#endif // QTHIDEONDEACTIVATECONTAINER_H
diff --git a/GUI/Qt/Components/QtRendererPlatformSupport.cxx b/GUI/Qt/Components/QtRendererPlatformSupport.cxx
index 87c82e3..10094c6 100644
--- a/GUI/Qt/Components/QtRendererPlatformSupport.cxx
+++ b/GUI/Qt/Components/QtRendererPlatformSupport.cxx
@@ -8,7 +8,7 @@
 #include <iostream>
 
 QRect
-QtRendererPlatformSupport::WorldRectangleToPixelRectangle(const QRect &world)
+QtRendererPlatformSupport::WorldRectangleToPixelRectangle(double wx, double wy, double ww, double wh)
 {
   // Viewport and such
   vnl_vector<int> viewport(4);
@@ -20,11 +20,11 @@ QtRendererPlatformSupport::WorldRectangleToPixelRectangle(const QRect &world)
   glGetDoublev(GL_MODELVIEW_MATRIX, model_view.data_block());
 
   vnl_vector<double> xw1(4), xs1, xw2(4), xs2;
-  xw1[0] = world.x(); xw1[1] = world.y();
+  xw1[0] = wx; xw1[1] = wy;
   xw1[2] = 0.0; xw1[3] = 1.0;
   xs1 = projection.transpose() * (model_view.transpose() * xw1);
 
-  xw2[0] = world.x() + world.width(); xw2[1] = world.y() + world.height();
+  xw2[0] = wx + ww; xw2[1] = wy + wh;
   xw2[2] = 0.0; xw2[3] = 1.0;
   xs2 = projection.transpose() * (model_view.transpose() * xw2);
 
@@ -45,14 +45,13 @@ QtRendererPlatformSupport::WorldRectangleToPixelRectangle(const QRect &world)
 
 void QtRendererPlatformSupport
 ::RenderTextInOpenGL(const char *text,
-                     int x, int y, int w, int h,
+                     double x, double y, double w, double h,
                      FontInfo font,
                      int align_horiz, int align_vert,
-                     const Vector3d &rgbf)
+                     const Vector3d &rgbf, double alpha)
 {
   // Map the coordinates to screen coordinates
-  QRect rWorld(QPoint(x, y), QSize(w, h));
-  QRect rScreen = this->WorldRectangleToPixelRectangle(rWorld);
+  QRect rScreen = this->WorldRectangleToPixelRectangle(x, y, w, h);
 
   // Create a pixmap to render the text
   QImage canvas(rScreen.width(), rScreen.height(), QImage::Format_ARGB32);
@@ -63,6 +62,7 @@ void QtRendererPlatformSupport
 
   QColor pen_color;
   pen_color.setRgbF(rgbf[0], rgbf[1], rgbf[2], 1.0);
+  pen_color.setAlphaF(alpha);
   painter.setPen(pen_color);
 
   int ah = Qt::AlignHCenter, av = Qt::AlignVCenter;
@@ -94,13 +94,19 @@ void QtRendererPlatformSupport
   qfont.setBold(font.bold);
   painter.setFont(qfont);
 
+  // painter.fillRect(QRectF(0,0,rScreen.width(),rScreen.height()), QColor(64,64,64,64));
   painter.drawText(QRectF(0,0,rScreen.width(),rScreen.height()), ah | av, QString::fromUtf8(text));
 
   QImage gl = QGLWidget::convertToGLFormat(canvas);
 
   glPushAttrib(GL_COLOR_BUFFER_BIT);
   glEnable(GL_BLEND);
-  glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+  if(alpha <= 0.9)
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  else
+    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
   glRasterPos2i(x,y);
   glDrawPixels(rScreen.width(),rScreen.height(), GL_RGBA, GL_UNSIGNED_BYTE, gl.bits());
   glPopAttrib();
@@ -126,3 +132,30 @@ QtRendererPlatformSupport
   QFontMetrics fm(qfont);
   return fm.width(QString::fromUtf8(text));
 }
+
+
+
+#if QT_VERSION >= 0x050000
+#include <QOpenGLTexture>
+
+void QtRendererPlatformSupport::LoadTexture(const char *url, GLuint &texture_id, Vector2ui &tex_size)
+{
+  // Get the icon corresponding to the URL
+  QImage myimage(QString(":/root/%1.png").arg(url));
+
+  // Create an opengl texture object
+  QOpenGLTexture *texture = new QOpenGLTexture(myimage);
+  texture_id = texture->textureId();
+
+  // Set the texture size
+  tex_size[0] = texture->width();
+  tex_size[1] = texture->height();
+}
+#else
+void QtRendererPlatformSupport::LoadTexture(const char *url, GLuint &texture_id, Vector2ui &tex_size)
+{
+  // Seems like this is not even used anywhere
+}
+
+#endif
+
diff --git a/GUI/Qt/Components/QtRendererPlatformSupport.h b/GUI/Qt/Components/QtRendererPlatformSupport.h
index a4c23f1..4c56f96 100644
--- a/GUI/Qt/Components/QtRendererPlatformSupport.h
+++ b/GUI/Qt/Components/QtRendererPlatformSupport.h
@@ -9,15 +9,17 @@ class QtRendererPlatformSupport : public AbstractRendererPlatformSupport
 public:
   virtual void RenderTextInOpenGL(
       const char *text,
-      int x, int y, int w, int h,
+      double x, double y, double w, double h,
       FontInfo font,
       int align_horiz, int align_vert,
-      const Vector3d &rgbf);
+      const Vector3d &rgbf, double alpha = 1.0);
 
   virtual int MeasureTextWidth(const char *text, FontInfo font);
 
+  virtual void LoadTexture(const char *url, GLuint &texture_id, Vector2ui &tex_size);
+
 protected:
-  QRect WorldRectangleToPixelRectangle(const QRect &world);
+  QRect WorldRectangleToPixelRectangle(double wx, double wy, double ww, double wh);
 };
 
 #endif // QTRENDERERPLATFORMSUPPORT_H
diff --git a/GUI/Qt/Components/QtReporterDelegates.cxx b/GUI/Qt/Components/QtReporterDelegates.cxx
index 53869c4..11cf94a 100644
--- a/GUI/Qt/Components/QtReporterDelegates.cxx
+++ b/GUI/Qt/Components/QtReporterDelegates.cxx
@@ -6,7 +6,6 @@
 
 #include <QPainter>
 #include <QPixmap>
-#include <QWindow>
 
 #include <QImage>
 #include "itkImage.h"
@@ -50,18 +49,50 @@ bool QtViewportReporter::CanReportSize()
   return m_ClientWidget != NULL;
 }
 
+#if QT_VERSION >= 0x050000
+
+Vector2ui QtViewportReporter::GetViewportSize()
+{
+  // For retina displays, this method reports size in actual pixels, not abstract pixels
+  return Vector2ui(m_ClientWidget->width() * m_ClientWidget->devicePixelRatio(),
+                   m_ClientWidget->height() * m_ClientWidget->devicePixelRatio());
+}
+
+float QtViewportReporter::GetViewportPixelRatio()
+{
+  return m_ClientWidget->devicePixelRatio();
+}
+
+#include <QStandardPaths>
+std::string QtSystemInfoDelegate::GetApplicationPermanentDataLocation()
+{
+  return to_utf8(QStandardPaths::writableLocation(QStandardPaths::DataLocation));
+}
+
+
+#else
+
 Vector2ui QtViewportReporter::GetViewportSize()
 {
   // For retina displays, this method reports size in actual pixels, not abstract pixels
-  return Vector2ui(m_ClientWidget->width() * m_ClientWidget->windowHandle()->devicePixelRatio(),
-                   m_ClientWidget->height() * m_ClientWidget->windowHandle()->devicePixelRatio());
+  return Vector2ui(m_ClientWidget->width(), m_ClientWidget->height());
 }
 
 float QtViewportReporter::GetViewportPixelRatio()
 {
-  return m_ClientWidget->windowHandle()->devicePixelRatio();
+  return 1.0f;
+}
+
+#include <QDesktopServices>
+std::string QtSystemInfoDelegate::GetApplicationPermanentDataLocation()
+{
+  return to_utf8(QDesktopServices::storageLocation(QDesktopServices::DataLocation));
+
 }
 
+
+#endif
+
 Vector2ui QtViewportReporter::GetLogicalViewportSize()
 {
   return Vector2ui(m_ClientWidget->width(), m_ClientWidget->height());
@@ -112,12 +143,6 @@ std::string QtSystemInfoDelegate::GetApplicationFile()
   return to_utf8(QCoreApplication::applicationFilePath());
 }
 
-#include <QStandardPaths>
-std::string QtSystemInfoDelegate::GetApplicationPermanentDataLocation()
-{
-  return to_utf8(QStandardPaths::writableLocation(QStandardPaths::DataLocation));
-}
-
 void QtSystemInfoDelegate
 ::LoadResourceAsImage2D(std::string tag, GrayscaleImage *image)
 {
diff --git a/GUI/Qt/Components/QtWidgetActivator.cxx b/GUI/Qt/Components/QtWidgetActivator.cxx
index db6cabe..8229e56 100644
--- a/GUI/Qt/Components/QtWidgetActivator.cxx
+++ b/GUI/Qt/Components/QtWidgetActivator.cxx
@@ -33,30 +33,32 @@
 #include "SNAPUIFlag.h"
 
 QtWidgetActivator
-::QtWidgetActivator(QObject *parent, BooleanCondition *cond)
+::QtWidgetActivator(QObject *parent, BooleanCondition *cond, Options options)
   : QObject(parent)
 {
   // Register to listen to the state change events
   m_TargetWidget = dynamic_cast<QWidget *>(parent);
   m_TargetAction = dynamic_cast<QAction *>(parent);
   m_Condition = cond;
+  m_Options = options;
 
   // Give it a name
   setObjectName(QString("Activator:%1").arg(parent->objectName()));
 
   // React to events after control returns to the main UI loop
   LatentITKEventNotifier::connect(
-        cond, StateMachineChangeEvent(), this, SLOT(OnStateChange()));
+        cond, StateMachineChangeEvent(), this, SLOT(OnStateChange(const EventBucket &)));
 
   // Update the state of the widget
-  this->OnStateChange();
+  EventBucket dummy;
+  this->OnStateChange(dummy);
 }
 
 QtWidgetActivator::~QtWidgetActivator()
 {
 }
 
-void QtWidgetActivator::OnStateChange()
+void QtWidgetActivator::OnStateChange(const EventBucket &)
 {
   // Update the state of the widget based on the condition
   bool active = (*m_Condition)();
@@ -64,12 +66,20 @@ void QtWidgetActivator::OnStateChange()
     {
     bool status = m_TargetWidget->isEnabledTo(m_TargetWidget->parentWidget());
     if(status != active)
+      {
       m_TargetWidget->setEnabled(active);
+      if(m_Options & HideInactive)
+        m_TargetWidget->setVisible(active);
+      }
     }
   else if(m_TargetAction)
     {
     bool status = m_TargetAction->isEnabled();
     if(status != active)
+      {
       m_TargetAction->setEnabled(active);
+      if(m_Options & HideInactive)
+        m_TargetAction->setVisible(active);
+      }
     }
 }
diff --git a/GUI/Qt/Components/QtWidgetActivator.h b/GUI/Qt/Components/QtWidgetActivator.h
index 88ce457..e1110a8 100644
--- a/GUI/Qt/Components/QtWidgetActivator.h
+++ b/GUI/Qt/Components/QtWidgetActivator.h
@@ -33,11 +33,20 @@
 
 class BooleanCondition;
 class QAction;
+class EventBucket;
 
 class QtWidgetActivator : public QObject
 {
   Q_OBJECT
 public:
+
+  enum Option {
+    NoOptions = 0x0,
+    HideInactive = 0x1
+  };
+
+  Q_DECLARE_FLAGS(Options, Option)
+
   /**
     Creates an activator with widget parent and boolean condition. The
     condition will be deleted when this object is destroyed. The parent
@@ -45,57 +54,64 @@ public:
 
     The widget can be a QWidget or a QAction. Otherwise, this will do nothing
    */
-  explicit QtWidgetActivator(QObject *parent, BooleanCondition *cond);
+  explicit QtWidgetActivator(QObject *parent, BooleanCondition *cond, Options options = NoOptions);
   ~QtWidgetActivator();
 
 public slots:
 
-  void OnStateChange();
+  void OnStateChange(const EventBucket &);
 
 private:
   QWidget *m_TargetWidget;
   QAction *m_TargetAction;
   SmartPtr<BooleanCondition> m_Condition;
+  Options m_Options;
 };
 
+Q_DECLARE_OPERATORS_FOR_FLAGS(QtWidgetActivator::Options)
+
 template<class TModel, class TStateEnum>
-void activateOnFlag(QObject *w, TModel *m, TStateEnum flag)
+void activateOnFlag(QObject *w, TModel *m, TStateEnum flag,
+                    QtWidgetActivator::Options options = QtWidgetActivator::NoOptions)
 {
   typedef SNAPUIFlag<TModel, TStateEnum> FlagType;
   SmartPtr<FlagType> f = FlagType::New(m, flag);
-  new QtWidgetActivator(w, f);
+  new QtWidgetActivator(w, f, options);
 }
 
 template<class TModel, class TStateEnum>
-void activateOnNotFlag(QObject *w, TModel *m, TStateEnum flag)
+void activateOnNotFlag(QObject *w, TModel *m, TStateEnum flag,
+                       QtWidgetActivator::Options options = QtWidgetActivator::NoOptions)
 {
   typedef SNAPUIFlag<TModel, TStateEnum> FlagType;
   SmartPtr<FlagType> f = FlagType::New(m, flag);
   SmartPtr<NotCondition> nf = NotCondition::New(f);
-  new QtWidgetActivator(w, nf);
+  new QtWidgetActivator(w, nf, options);
 }
 
 
 template<class TModel, class TStateEnum>
 void activateOnAllFlags(QObject *w, TModel *m,
-                        TStateEnum flag1, TStateEnum flag2)
+                        TStateEnum flag1, TStateEnum flag2,
+                        QtWidgetActivator::Options options = QtWidgetActivator::NoOptions)
 {
   typedef SNAPUIFlag<TModel, TStateEnum> FlagType;
   SmartPtr<FlagType> f1 = FlagType::New(m, flag1);
   SmartPtr<FlagType> f2 = FlagType::New(m, flag2);
   SmartPtr<AndCondition> f = AndCondition::New(f1, f2);
-  new QtWidgetActivator(w, f);
+  new QtWidgetActivator(w, f, options);
 }
 
 template<class TModel, class TStateEnum>
 void activateOnAnyFlags(QObject *w, TModel *m,
-                        TStateEnum flag1, TStateEnum flag2)
+                        TStateEnum flag1, TStateEnum flag2,
+                        QtWidgetActivator::Options options = QtWidgetActivator::NoOptions)
 {
   typedef SNAPUIFlag<TModel, TStateEnum> FlagType;
   SmartPtr<FlagType> f1 = FlagType::New(m, flag1);
   SmartPtr<FlagType> f2 = FlagType::New(m, flag2);
   SmartPtr<OrCondition> f = OrCondition::New(f1, f2);
-  new QtWidgetActivator(w, f);
+  new QtWidgetActivator(w, f, options);
 }
 
 
diff --git a/GUI/Qt/Components/RecentHistoryItemsView.cxx b/GUI/Qt/Components/RecentHistoryItemsView.cxx
index c282d68..85a5ae3 100644
--- a/GUI/Qt/Components/RecentHistoryItemsView.cxx
+++ b/GUI/Qt/Components/RecentHistoryItemsView.cxx
@@ -25,6 +25,11 @@ public:
       {
       painter->setOpacity(0.8);
       }
+    else
+      {
+      painter->setBackground(QBrush(Qt::black));
+      }
+
     QItemDelegate::paint(painter, option, index);
   }
 };
@@ -38,6 +43,7 @@ RecentHistoryItemsView::RecentHistoryItemsView(QWidget *parent) :
   // Delegate for history
   HistoryListItemDelegate *del = new HistoryListItemDelegate(ui->listRecent);
   ui->listRecent->setItemDelegate(del);
+  ui->listRecent->setUniformItemSizes(true);
 
   // Set up the popup for the recent list
   m_RecentListPopup = new QMenu(this);
diff --git a/GUI/Qt/Components/SNAPComponent.h b/GUI/Qt/Components/SNAPComponent.h
index a905caf..0fc9346 100644
--- a/GUI/Qt/Components/SNAPComponent.h
+++ b/GUI/Qt/Components/SNAPComponent.h
@@ -41,6 +41,10 @@ protected:
 
   void disconnectITK(itk::Object *src, unsigned long tag);
 
+#if QT_VERSION < 0x050000
+  float devicePixelRatio() const { return 1.0f; }
+#endif
+
 };
 
 #endif // SNAPCOMPONENT_H
diff --git a/GUI/Qt/Components/SNAPQtCommon.cxx b/GUI/Qt/Components/SNAPQtCommon.cxx
index 6c403fc..43a5315 100644
--- a/GUI/Qt/Components/SNAPQtCommon.cxx
+++ b/GUI/Qt/Components/SNAPQtCommon.cxx
@@ -250,11 +250,18 @@ QIcon CreateLabelComboIcon(int w, int h, LabelType fg, DrawOverFilter bg, ColorL
 
 QString CreateLabelComboTooltip(LabelType fg, DrawOverFilter bg, ColorLabelTable *clt)
 {
+  /*
   return QString(
         "<html><head/><body>"
         "<p>Foreground label:<br><span style=\" font-weight:600;\">%1</span></p>"
         "<p>Background label:<br><span style=\" font-weight:600;\">%2</span></p>"
         "</body></html>").
+      arg(GetTitleForColorLabel(fg, clt)).arg(GetTitleForDrawOverFilter(bg, clt)); */
+
+  return QString(
+        "<html><body>"
+        "Set active label to <span style=\" font-weight:600;\">%1</span> "
+        " and the paint over mask to <span style=\" font-weight:600;\">%2</span>.").
       arg(GetTitleForColorLabel(fg, clt)).arg(GetTitleForDrawOverFilter(bg, clt));
 }
 
@@ -506,7 +513,6 @@ bool SaveWorkspace(QWidget *parent, GlobalUIModel *model, bool interactive, QWid
 #include <QMap>
 #include <QDir>
 #include <GenericImageData.h>
-#include <QStandardPaths>
 
 QMap<QString, QDir> g_CategoryToLastPathMap;
 
@@ -523,11 +529,49 @@ QString GetFileDialogPath(GlobalUIModel *model, const char *HistoryName)
     return QFileInfo(fn).absolutePath();
     }
 
-  // Use home directory
-  return QStandardPaths::standardLocations(QStandardPaths::HomeLocation).first();
+  // Use the initial directory
+  if(model->GetGlobalState()->GetInitialDirectory().length())
+    {
+    // This directory should alrady be verified readable when assigned in main.cxx
+    QDir dir(from_utf8(model->GetGlobalState()->GetInitialDirectory()));
+    return dir.absolutePath();
+    }
+
+  // Last resort : use home directory
+  return QDir::homePath();
 }
 
 void UpdateFileDialogPathForCategory(const char *HistoryName, QString dir)
 {
   g_CategoryToLastPathMap[HistoryName] = QDir(dir);
 }
+
+void TranslateStringTooltipKeyModifiers(QString &tooltip)
+{
+  tooltip.replace(QChar(0x21e7),"Shift+");
+  tooltip.replace(QChar(0x2318),"Ctrl+");
+  tooltip.replace(QChar(0x2325),"Alt+");
+  tooltip.replace("⌃","Ctrl+");
+  tooltip.replace(QChar(0x238b),"Esc");
+}
+
+void TranslateChildTooltipKeyModifiers(QWidget *parent)
+{
+  // Get all the child widgets
+  QList<QWidget *> child_widgets = parent->findChildren<QWidget *>();
+  foreach(QWidget *child, child_widgets)
+    {
+    QString tooltip = child->toolTip();
+    TranslateStringTooltipKeyModifiers(tooltip);
+    child->setToolTip(tooltip);
+    }
+
+  // Get all the child actions
+  QList<QAction *> child_actions = parent->findChildren<QAction *>();
+  foreach(QAction *child, child_actions)
+    {
+    QString tooltip = child->toolTip();
+    TranslateStringTooltipKeyModifiers(tooltip);
+    child->setToolTip(tooltip);
+    }
+}
diff --git a/GUI/Qt/Components/SNAPQtCommon.h b/GUI/Qt/Components/SNAPQtCommon.h
index 314e9b1..0b1b3f6 100644
--- a/GUI/Qt/Components/SNAPQtCommon.h
+++ b/GUI/Qt/Components/SNAPQtCommon.h
@@ -151,5 +151,8 @@ inline QString from_utf8(const std::string &input)
   return QString::fromUtf8(input.c_str());
 }
 
+/** Method translates the tooltips in all child widgets from MACOS to windows/linux format */
+void TranslateChildTooltipKeyModifiers(QWidget *parent);
+
 
 #endif // SNAPQTCOMMON_H
diff --git a/GUI/Qt/Components/SliceViewPanel.cxx b/GUI/Qt/Components/SliceViewPanel.cxx
index 6170d2e..96631fa 100644
--- a/GUI/Qt/Components/SliceViewPanel.cxx
+++ b/GUI/Qt/Components/SliceViewPanel.cxx
@@ -14,17 +14,22 @@
 #include "SnakeROIModel.h"
 #include "SliceWindowCoordinator.h"
 #include "PolygonDrawingModel.h"
+#include "AnnotationModel.h"
+#include "AnnotationRenderer.h"
 #include "QtWidgetActivator.h"
 #include "SnakeModeRenderer.h"
 #include "SnakeWizardModel.h"
 #include "DisplayLayoutModel.h"
 #include "PaintbrushModel.h"
 #include "SliceWindowDecorationRenderer.h"
+#include "LayerInspectorDialog.h"
 #include "MainImageWindow.h"
 #include "SNAPQtCommon.h"
 #include "QtScrollbarCoupling.h"
+#include "QtSliderCoupling.h"
 #include <QCursor>
 #include <QBitmap>
+#include <QToolButton>
 
 #include <QStackedLayout>
 #include <QMenu>
@@ -74,6 +79,13 @@ SliceViewPanel::SliceViewPanel(QWidget *parent) :
   ui->btnSplitNodes->setDefaultAction(ui->actionSplitSelected);
   ui->btnUndoLast->setDefaultAction(ui->actionUndo);
 
+  ui->btnAnnotationAcceptLine->setDefaultAction(ui->actionAnnotationAcceptLine);
+  ui->btnAnnotationClearLine->setDefaultAction(ui->actionAnnotationClearLine);
+  ui->btnAnnotationSelectAll->setDefaultAction(ui->actionAnnotationSelectAll);
+  ui->btnAnnotationDeleteSelected->setDefaultAction(ui->actionAnnotationDelete);
+  ui->btnAnnotationNext->setDefaultAction(ui->actionAnnotationNext);
+  ui->btnAnnotationPrevious->setDefaultAction(ui->actionAnnotationPrevious);
+
   this->addAction(ui->actionZoom_In);
   this->addAction(ui->actionZoom_Out);
 
@@ -116,6 +128,8 @@ SliceViewPanel::SliceViewPanel(QWidget *parent) :
   loPages->addWidget(ui->pagePolygonDraw);
   loPages->addWidget(ui->pagePolygonEdit);
   loPages->addWidget(ui->pagePolygonInactive);
+  loPages->addWidget(ui->pageAnnotateLineActive);
+  loPages->addWidget(ui->pageAnnotateSelect);
   delete ui->toolbar->layout();
   ui->toolbar->setLayout(loPages);
 
@@ -129,6 +143,17 @@ SliceViewPanel::SliceViewPanel(QWidget *parent) :
   QBitmap bmBitmap(":/root/crosshair_cursor_bitmap.png");
   QBitmap bmMask(":/root/crosshair_cursor_mask.png");
   m_DrawingCrosshairCursor = new QCursor(bmBitmap, bmMask, 7, 7);
+
+  // Configure the context tool button
+  m_ContextToolButton = new QToolButton(ui->sliceView);
+  m_ContextToolButton->setIcon(QIcon(":/root/context_gray_10.png"));
+  m_ContextToolButton->setVisible(false);
+  m_ContextToolButton->setAutoRaise(true);
+  m_ContextToolButton->setIconSize(QSize(10,10));
+  m_ContextToolButton->setMinimumSize(QSize(16,16));
+  m_ContextToolButton->setMaximumSize(QSize(16,16));
+  m_ContextToolButton->setPopupMode(QToolButton::InstantPopup);
+  m_ContextToolButton->setStyleSheet("QToolButton::menu-indicator { image: none; }");
 }
 
 SliceViewPanel::~SliceViewPanel()
@@ -162,6 +187,9 @@ void SliceViewPanel::Initialize(GlobalUIModel *model, unsigned int index)
   ui->imPolygon->SetModel(m_GlobalUI->GetPolygonDrawingModel(index));
   ui->imSnakeROI->SetModel(m_GlobalUI->GetSnakeROIModel(index));
   ui->imPaintbrush->SetModel(m_GlobalUI->GetPaintbrushModel(index));
+  ui->imAnnotation->SetModel(m_GlobalUI->GetAnnotationModel(index));
+
+  // ui->labelQuickList->SetModel(m_GlobalUI);
 
   // Initialize the 'orphan' renderers (without a custom widget)
   GenericSliceRenderer *parentRenderer =
@@ -181,9 +209,9 @@ void SliceViewPanel::Initialize(GlobalUIModel *model, unsigned int index)
   // Listen to toolbar change events
   connectITK(m_GlobalUI, ToolbarModeChangeEvent());
 
-  // Listen to polygon state change events
-  connectITK(m_GlobalUI->GetPolygonDrawingModel(index),
-             StateMachineChangeEvent());
+  // Listen to polygon and annotation model state change events
+  connectITK(m_GlobalUI->GetPolygonDrawingModel(index), StateMachineChangeEvent());
+  connectITK(m_GlobalUI->GetAnnotationModel(index), StateMachineChangeEvent());
 
   // Listen to the Snake ROI model too
   connectITK(m_GlobalUI->GetSnakeROIModel(index),
@@ -193,15 +221,22 @@ void SliceViewPanel::Initialize(GlobalUIModel *model, unsigned int index)
   connectITK(m_GlobalUI->GetPaintbrushModel(index),
              PaintbrushModel::PaintbrushMovedEvent());
 
+  // Listen to annotation changes
+  connectITK(m_GlobalUI->GetAnnotationModel(index), ModelUpdateEvent());
+
   // Listen to all (?) events from the snake wizard as well
   connectITK(m_GlobalUI->GetSnakeWizardModel(), IRISEvent());
 
   // Widget coupling
-  makeCoupling(ui->inSlicePosition, m_SliceModel->GetSliceIndexModel());
+  makeCoupling(ui->inSlicePosition, m_SliceModel->GetSliceIndexModel());  
 
   // Activation
   activateOnFlag(this, m_GlobalUI, UIF_BASEIMG_LOADED);
 
+  // Activation for the tile/thumb controls
+  activateOnFlag(ui->btnToggleLayout, m_GlobalUI, UIF_MULTIPLE_BASE_LAYERS,
+                 QtWidgetActivator::HideInactive);
+
   // Set up activation for polygon buttons
   PolygonDrawingModel *pm = m_GlobalUI->GetPolygonDrawingModel(index);
 
@@ -215,6 +250,12 @@ void SliceViewPanel::Initialize(GlobalUIModel *model, unsigned int index)
   activateOnAllFlags(ui->actionUndo, pm, UIF_DRAWING, UIF_HAVEPOLYGON);
   activateOnAllFlags(ui->actionClearPolygon, pm, UIF_EDITING, UIF_HAVEPOLYGON);
 
+  // Set up activation from the annotation model
+  AnnotationModel *am = m_GlobalUI->GetAnnotationModel(index);
+
+  activateOnFlag(ui->actionAnnotationAcceptLine, am, AnnotationModel::UIF_LINE_MODE_DRAWING);
+  activateOnFlag(ui->actionAnnotationClearLine, am, AnnotationModel::UIF_LINE_MODE_DRAWING);
+
   // Update the expand view button
   this->UpdateExpandViewButton();
 
@@ -225,6 +266,13 @@ void SliceViewPanel::Initialize(GlobalUIModel *model, unsigned int index)
 
   // Arrange the rendering overlays and widgets based on current mode
   this->OnToolbarModeChange();
+
+  // Listen for hover changes to move and activate widgets
+  connectITK(m_SliceModel->GetHoveredImageLayerIdModel(), ValueChangedEvent(),
+             SLOT(OnHoveredLayerChange(const EventBucket &)));
+
+  connectITK(m_SliceModel->GetHoveredImageIsThumbnailModel(), ValueChangedEvent(),
+             SLOT(OnHoveredLayerChange(const EventBucket &)));
 }
 
 void SliceViewPanel::onModelUpdate(const EventBucket &eb)
@@ -333,6 +381,7 @@ void SliceViewPanel::OnToolbarModeChange()
   ovTiled.clear();
   ovTiled.push_back(m_SnakeModeRenderer);
   ovTiled.push_back(ui->imCrosshairs->GetRenderer());
+  ovTiled.push_back(ui->imAnnotation->GetRenderer());
   ovTiled.push_back(ui->imPolygon->GetRenderer());
 
   ovGlobal.clear();
@@ -348,6 +397,8 @@ void SliceViewPanel::OnToolbarModeChange()
       ovTiled.push_back(ui->imPaintbrush->GetRenderer());
       break;
     case ANNOTATION_MODE:
+      ConfigureEventChain(ui->imAnnotation);
+      ovTiled.push_back(ui->imAnnotation->GetRenderer());
       break;
     case ROI_MODE:
       ConfigureEventChain(ui->imSnakeROI);
@@ -376,8 +427,20 @@ void SliceViewPanel::OnToolbarModeChange()
         loPages->setCurrentWidget(ui->pagePolygonInactive); break;
       }
     }
+  else if(m_GlobalUI->GetGlobalState()->GetToolbarMode() == ANNOTATION_MODE)
+    {
+    AnnotationModel *am = m_GlobalUI->GetAnnotationModel(m_Index);
+    if(am->GetFlagDrawingLine())
+      loPages->setCurrentWidget(ui->pageAnnotateLineActive);
+    else if(am->GetAnnotationMode() == ANNOTATION_SELECT)
+      loPages->setCurrentWidget(ui->pageAnnotateSelect);
+    else
+      loPages->setCurrentWidget(ui->pageDefault);
+    }
   else
+    {
     loPages->setCurrentWidget(ui->pageDefault);
+    }
 }
 
 void SliceViewPanel::on_btnZoomToFit_clicked()
@@ -459,13 +522,11 @@ void SliceViewPanel::UpdateExpandViewButton()
   LayerLayout ll = dlm->GetSliceViewLayerLayoutModel()->GetValue();
   if(ll == LAYOUT_TILED)
     {
-    ui->btnToggleLayout->setIcon(QIcon(":/root/layout_overlay_16.png"));
-    ui->btnToggleLayout->setToolTip("Render image overlays on top of each other");
+    ui->btnToggleLayout->setIcon(QIcon(":/root/layout_thumb_16.png"));
     }
   else if(ll == LAYOUT_STACKED)
     {
     ui->btnToggleLayout->setIcon(QIcon(":/root/layout_tile_16.png"));
-    ui->btnToggleLayout->setToolTip("Tile image overlays side by side");
     }
 }
 
@@ -478,16 +539,7 @@ void SliceViewPanel::on_btnScreenshot_clicked()
 
 void SliceViewPanel::on_btnToggleLayout_clicked()
 {
-  DisplayLayoutModel *dlm = m_GlobalUI->GetDisplayLayoutModel();
-  LayerLayout ll = dlm->GetSliceViewLayerLayoutModel()->GetValue();
-  if(ll == LAYOUT_TILED)
-    {
-    dlm->GetSliceViewLayerLayoutModel()->SetValue(LAYOUT_STACKED);
-    }
-  else
-    {
-    dlm->GetSliceViewLayerLayoutModel()->SetValue(LAYOUT_TILED);
-    }
+  m_GlobalUI->GetDisplayLayoutModel()->ToggleSliceViewLayerLayout();
 }
 
 void SliceViewPanel::on_actionZoom_In_triggered()
@@ -501,3 +553,73 @@ void SliceViewPanel::on_actionZoom_Out_triggered()
   // Zoom out
   m_GlobalUI->GetSliceCoordinator()->ZoomInOrOutInOneWindow(m_Index, 1.0 / 1.1);
 }
+
+void SliceViewPanel::OnHoveredLayerChange(const EventBucket &eb)
+{
+  // Determine the position where to draw the button
+  const SliceViewportLayout::SubViewport *vp = m_SliceModel->GetHoveredViewport();
+  if(vp)
+    {
+    // Set up the location of the button
+    int vppr = m_SliceModel->GetSizeReporter()->GetViewportPixelRatio();
+    int x = (vp->pos[0] + vp->size[0]) / vppr - m_ContextToolButton->width();
+    int y = (ui->sliceView->height() - 1) - (vp->pos[1] + vp->size[1]) / vppr;
+    m_ContextToolButton->setVisible(true);
+    m_ContextToolButton->move(x, y);
+
+    // Set up the context menu on the button
+    MainImageWindow *winmain = findParentWidget<MainImageWindow>(this);
+    LayerInspectorDialog *inspector = winmain->GetLayerInspector();
+
+    // Get the corresponding context menu
+    QMenu *menu = inspector->GetLayerContextMenu(
+                    m_SliceModel->GetDriver()->GetCurrentImageData()->FindLayer(
+                      m_SliceModel->GetHoveredImageLayerId(), false, ALL_ROLES));
+
+    // Show the menu
+    m_ContextToolButton->setMenu(menu);
+    m_ContextToolButton->setDown(false);
+    }
+  else
+    {
+    m_ContextToolButton->setVisible(false);
+    m_ContextToolButton->setMenu(NULL);
+    m_ContextToolButton->setDown(false);
+    }
+}
+
+
+
+
+
+
+
+void SliceViewPanel::on_actionAnnotationAcceptLine_triggered()
+{
+  m_GlobalUI->GetAnnotationModel(m_Index)->AcceptLine();
+}
+
+void SliceViewPanel::on_actionAnnotationClearLine_triggered()
+{
+  m_GlobalUI->GetAnnotationModel(m_Index)->CancelLine();
+}
+
+void SliceViewPanel::on_actionAnnotationSelectAll_triggered()
+{
+  m_GlobalUI->GetAnnotationModel(m_Index)->SelectAllOnSlice();
+}
+
+void SliceViewPanel::on_actionAnnotationDelete_triggered()
+{
+  m_GlobalUI->GetAnnotationModel(m_Index)->DeleteSelectedOnSlice();
+}
+
+void SliceViewPanel::on_actionAnnotationNext_triggered()
+{
+  m_GlobalUI->GetAnnotationModel(m_Index)->GoToNextAnnotation();
+}
+
+void SliceViewPanel::on_actionAnnotationPrevious_triggered()
+{
+  m_GlobalUI->GetAnnotationModel(m_Index)->GoToPreviousAnnotation();
+}
diff --git a/GUI/Qt/Components/SliceViewPanel.h b/GUI/Qt/Components/SliceViewPanel.h
index 6034d45..9fa3ade 100644
--- a/GUI/Qt/Components/SliceViewPanel.h
+++ b/GUI/Qt/Components/SliceViewPanel.h
@@ -11,11 +11,14 @@ class SnakeModeRenderer;
 class SliceWindowDecorationRenderer;
 class GenericSliceModel;
 class QCursor;
+class QToolButton;
 
 namespace Ui {
     class SliceViewPanel;
 }
 
+
+
 class SliceViewPanel : public SNAPComponent
 {
   Q_OBJECT
@@ -57,6 +60,20 @@ private slots:
 
   void on_actionZoom_Out_triggered();
 
+  void OnHoveredLayerChange(const EventBucket &eb);
+
+  void on_actionAnnotationAcceptLine_triggered();
+
+  void on_actionAnnotationClearLine_triggered();
+
+  void on_actionAnnotationSelectAll_triggered();
+
+  void on_actionAnnotationDelete_triggered();
+
+  void on_actionAnnotationNext_triggered();
+
+  void on_actionAnnotationPrevious_triggered();
+
 private:
   Ui::SliceViewPanel *ui;
 
@@ -75,12 +92,14 @@ private:
   // Custom cursor for drawing operations
   QCursor *m_DrawingCrosshairCursor;
 
+  // Context menu tool button
+  QToolButton *m_ContextToolButton;
+
   // Some renderers don't require a separate widget (no user interaction)
   // and so they are owned by this panel.
   SmartPtr<SnakeModeRenderer> m_SnakeModeRenderer;
   SmartPtr<SliceWindowDecorationRenderer> m_DecorationRenderer;
 
-
   // Index of the panel
   unsigned int m_Index;
 
diff --git a/GUI/Qt/Components/SliceViewPanel.ui b/GUI/Qt/Components/SliceViewPanel.ui
index c9bcc4d..17c338b 100644
--- a/GUI/Qt/Components/SliceViewPanel.ui
+++ b/GUI/Qt/Components/SliceViewPanel.ui
@@ -19,7 +19,16 @@ font-size:11px;
 }</string>
   </property>
   <layout class="QGridLayout" name="gridLayout">
-   <property name="margin">
+   <property name="leftMargin">
+    <number>0</number>
+   </property>
+   <property name="topMargin">
+    <number>0</number>
+   </property>
+   <property name="rightMargin">
+    <number>0</number>
+   </property>
+   <property name="bottomMargin">
     <number>0</number>
    </property>
    <property name="spacing">
@@ -31,7 +40,16 @@ font-size:11px;
       <property name="spacing">
        <number>2</number>
       </property>
-      <property name="margin">
+      <property name="leftMargin">
+       <number>0</number>
+      </property>
+      <property name="topMargin">
+       <number>0</number>
+      </property>
+      <property name="rightMargin">
+       <number>0</number>
+      </property>
+      <property name="bottomMargin">
        <number>0</number>
       </property>
       <item>
@@ -63,13 +81,16 @@ font-size:11px;
           <height>20</height>
          </size>
         </property>
+        <property name="toolTip">
+         <string><html><head/><body><p>Toggle between thumbnail and tiled layouts.</p><p>In <span style=" font-weight:600;">thumbnail</span> layout, one image layer occupies most of the available screen space, and other loaded image layers are shown as thumbnails. In <span style=" font-weight:600;">tiled</span> layout, multiple image layers are shown side by side. </p></body></html></string>
+        </property>
         <property name="text">
          <string>...</string>
         </property>
         <property name="icon">
          <iconset resource="../Resources/SNAPResources.qrc">
-          <normaloff>:/root/layout_overlay_16.png</normaloff>
-          <normalon>:/root/layout_tile_16.png</normalon>:/root/layout_overlay_16.png</iconset>
+          <normaloff>:/root/layout_thumb_16.png</normaloff>
+          <normalon>:/root/layout_tile_16.png</normalon>:/root/layout_thumb_16.png</iconset>
         </property>
         <property name="checkable">
          <bool>false</bool>
@@ -91,15 +112,20 @@ font-size:11px;
          </size>
         </property>
         <property name="toolTip">
-         <string>Save a screenshot</string>
+         <string><html><head/><body><p><span style=" font-size:11pt;">Save a screenshot of the current slice view.</span></p></body></html></string>
         </property>
         <property name="text">
          <string>...</string>
         </property>
         <property name="icon">
-         <iconset>
-          <normalon>:/root/screencapture2.gif</normalon>
-         </iconset>
+         <iconset resource="../Resources/SNAPResources.qrc">
+          <normaloff>:/root/icons8_slr_camera_12.png</normaloff>:/root/icons8_slr_camera_12.png</iconset>
+        </property>
+        <property name="iconSize">
+         <size>
+          <width>12</width>
+          <height>12</height>
+         </size>
         </property>
         <property name="autoRaise">
          <bool>true</bool>
@@ -111,6 +137,9 @@ font-size:11px;
         <property name="enabled">
          <bool>true</bool>
         </property>
+        <property name="toolTip">
+         <string>Slice selection</string>
+        </property>
         <property name="orientation">
          <enum>Qt::Vertical</enum>
         </property>
@@ -140,7 +169,16 @@ font-size:11px;
       <item>
        <widget class="QWidget" name="toolbar" native="true">
         <layout class="QVBoxLayout" name="verticalLayout">
-         <property name="margin">
+         <property name="leftMargin">
+          <number>0</number>
+         </property>
+         <property name="topMargin">
+          <number>0</number>
+         </property>
+         <property name="rightMargin">
+          <number>0</number>
+         </property>
+         <property name="bottomMargin">
           <number>0</number>
          </property>
          <item>
@@ -467,6 +505,222 @@ p, li { white-space: pre-wrap; }
           </widget>
          </item>
          <item>
+          <widget class="QWidget" name="pageAnnotateLineActive" native="true">
+           <layout class="QHBoxLayout" name="horizontalLayout_7">
+            <property name="spacing">
+             <number>4</number>
+            </property>
+            <property name="topMargin">
+             <number>0</number>
+            </property>
+            <property name="bottomMargin">
+             <number>0</number>
+            </property>
+            <item>
+             <spacer name="horizontalSpacer_5">
+              <property name="orientation">
+               <enum>Qt::Horizontal</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>313</width>
+                <height>17</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+            <item>
+             <widget class="QToolButton" name="btnAnnotationAcceptLine">
+              <property name="minimumSize">
+               <size>
+                <width>64</width>
+                <height>0</height>
+               </size>
+              </property>
+              <property name="maximumSize">
+               <size>
+                <width>16777215</width>
+                <height>20</height>
+               </size>
+              </property>
+              <property name="font">
+               <font>
+                <pointsize>-1</pointsize>
+               </font>
+              </property>
+              <property name="toolTip">
+               <string/>
+              </property>
+              <property name="text">
+               <string>accept</string>
+              </property>
+              <property name="toolButtonStyle">
+               <enum>Qt::ToolButtonTextOnly</enum>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QToolButton" name="btnAnnotationClearLine">
+              <property name="maximumSize">
+               <size>
+                <width>16777215</width>
+                <height>20</height>
+               </size>
+              </property>
+              <property name="font">
+               <font>
+                <pointsize>-1</pointsize>
+               </font>
+              </property>
+              <property name="text">
+               <string>clear</string>
+              </property>
+              <property name="toolButtonStyle">
+               <enum>Qt::ToolButtonTextOnly</enum>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </widget>
+         </item>
+         <item>
+          <widget class="QWidget" name="pageAnnotateSelect" native="true">
+           <layout class="QHBoxLayout" name="horizontalLayout_8">
+            <property name="spacing">
+             <number>4</number>
+            </property>
+            <property name="topMargin">
+             <number>0</number>
+            </property>
+            <property name="bottomMargin">
+             <number>0</number>
+            </property>
+            <item>
+             <spacer name="horizontalSpacer_6">
+              <property name="orientation">
+               <enum>Qt::Horizontal</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>313</width>
+                <height>17</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+            <item>
+             <widget class="QToolButton" name="btnAnnotationPrevious">
+              <property name="maximumSize">
+               <size>
+                <width>16777215</width>
+                <height>20</height>
+               </size>
+              </property>
+              <property name="font">
+               <font>
+                <pointsize>-1</pointsize>
+               </font>
+              </property>
+              <property name="text">
+               <string>previous</string>
+              </property>
+              <property name="toolButtonStyle">
+               <enum>Qt::ToolButtonTextOnly</enum>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QToolButton" name="btnAnnotationNext">
+              <property name="maximumSize">
+               <size>
+                <width>16777215</width>
+                <height>20</height>
+               </size>
+              </property>
+              <property name="font">
+               <font>
+                <pointsize>-1</pointsize>
+               </font>
+              </property>
+              <property name="text">
+               <string>next</string>
+              </property>
+              <property name="toolButtonStyle">
+               <enum>Qt::ToolButtonTextOnly</enum>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <spacer name="horizontalSpacer_7">
+              <property name="orientation">
+               <enum>Qt::Horizontal</enum>
+              </property>
+              <property name="sizeType">
+               <enum>QSizePolicy::Fixed</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>10</width>
+                <height>20</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+            <item>
+             <widget class="QToolButton" name="btnAnnotationSelectAll">
+              <property name="maximumSize">
+               <size>
+                <width>16777215</width>
+                <height>20</height>
+               </size>
+              </property>
+              <property name="font">
+               <font>
+                <pointsize>-1</pointsize>
+               </font>
+              </property>
+              <property name="text">
+               <string>select all</string>
+              </property>
+              <property name="toolButtonStyle">
+               <enum>Qt::ToolButtonTextOnly</enum>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QToolButton" name="btnAnnotationDeleteSelected">
+              <property name="minimumSize">
+               <size>
+                <width>64</width>
+                <height>0</height>
+               </size>
+              </property>
+              <property name="maximumSize">
+               <size>
+                <width>16777215</width>
+                <height>20</height>
+               </size>
+              </property>
+              <property name="font">
+               <font>
+                <pointsize>-1</pointsize>
+               </font>
+              </property>
+              <property name="toolTip">
+               <string/>
+              </property>
+              <property name="text">
+               <string>delete</string>
+              </property>
+              <property name="toolButtonStyle">
+               <enum>Qt::ToolButtonTextOnly</enum>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </widget>
+         </item>
+         <item>
           <widget class="QWidget" name="pagePolygonInactive" native="true">
            <layout class="QHBoxLayout" name="horizontalLayout_5">
             <property name="spacing">
@@ -505,14 +759,10 @@ p, li { white-space: pre-wrap; }
                </font>
               </property>
               <property name="toolTip">
-               <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
-<html><head><meta name="qrichtext" content="1" /><style type="text/css">
-p, li { white-space: pre-wrap; }
-</style></head><body style=" font-family:'Helvetica'; font-size:11px; font-weight:400; font-style:normal;">
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Pastes the last polygon that you have accepted in this slice view. You can then move the vertices in the pasted polygon to fit image data. This can be more efficient than drawing a new polygon when performing segmentation across multiple slices.</p></body></html></string>
+               <string><html><head/><body><p><span style=" font-family:'Helvetica'; font-size:11px;">Pastes the last polygon that you have accepted in this slice view. You can then move the vertices in the pasted polygon to fit image data. This can be more efficient than drawing a new polygon when performing segmentation across multiple slices.</span></p></body></html></string>
               </property>
               <property name="text">
-               <string>paste last polygon</string>
+               <string>paste</string>
               </property>
               <property name="toolButtonStyle">
                <enum>Qt::ToolButtonTextOnly</enum>
@@ -585,6 +835,9 @@ p, li { white-space: pre-wrap; }
       <item>
        <widget class="PaintbrushInteractionMode" name="imPaintbrush" native="true"/>
       </item>
+      <item>
+       <widget class="AnnotationInteractionMode" name="imAnnotation" native="true"/>
+      </item>
      </layout>
     </widget>
    </item>
@@ -781,6 +1034,108 @@ p, li { white-space: pre-wrap; }
     <enum>Qt::WidgetWithChildrenShortcut</enum>
    </property>
   </action>
+  <action name="actionAnnotationAcceptLine">
+   <property name="icon">
+    <iconset resource="../Resources/SNAPResources.qrc">
+     <normaloff>:/root/popup_ok_16.png</normaloff>:/root/popup_ok_16.png</iconset>
+   </property>
+   <property name="text">
+    <string>Accept Polygon</string>
+   </property>
+   <property name="iconText">
+    <string>accept</string>
+   </property>
+   <property name="toolTip">
+    <string><html><head/><body><p>Add the current line measurement to the annotation.</p></body></html></string>
+   </property>
+   <property name="shortcut">
+    <string>Return</string>
+   </property>
+  </action>
+  <action name="actionAnnotationClearLine">
+   <property name="icon">
+    <iconset resource="../Resources/SNAPResources.qrc">
+     <normaloff>:/root/popup_clear_16.png</normaloff>:/root/popup_clear_16.png</iconset>
+   </property>
+   <property name="text">
+    <string>Clear measurement</string>
+   </property>
+   <property name="iconText">
+    <string>clear</string>
+   </property>
+   <property name="toolTip">
+    <string><html><head/><body><p>Cancels the current measurement</p></body></html></string>
+   </property>
+   <property name="shortcut">
+    <string>Esc</string>
+   </property>
+  </action>
+  <action name="actionAnnotationSelectAll">
+   <property name="icon">
+    <iconset resource="../Resources/SNAPResources.qrc">
+     <normaloff>:/root/icons8_cursor_16.png</normaloff>:/root/icons8_cursor_16.png</iconset>
+   </property>
+   <property name="text">
+    <string>Select all annotations</string>
+   </property>
+   <property name="iconText">
+    <string>select all</string>
+   </property>
+   <property name="toolTip">
+    <string>Select all annotations on the current slice</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+A</string>
+   </property>
+  </action>
+  <action name="actionAnnotationDelete">
+   <property name="icon">
+    <iconset resource="../Resources/SNAPResources.qrc">
+     <normaloff>:/root/delete_22.png</normaloff>:/root/delete_22.png</iconset>
+   </property>
+   <property name="text">
+    <string>Delete selected annotations</string>
+   </property>
+   <property name="iconText">
+    <string>delete</string>
+   </property>
+   <property name="toolTip">
+    <string>Delete selected annotations on this slice</string>
+   </property>
+   <property name="shortcut">
+    <string>Backspace</string>
+   </property>
+  </action>
+  <action name="actionAnnotationNext">
+   <property name="icon">
+    <iconset resource="../Resources/SNAPResources.qrc">
+     <normaloff>:/root/arrow_down_16.png</normaloff>:/root/arrow_down_16.png</iconset>
+   </property>
+   <property name="text">
+    <string>Next annotation</string>
+   </property>
+   <property name="iconText">
+    <string>next</string>
+   </property>
+   <property name="toolTip">
+    <string><html><head/><body><p>Select the next annotation. Use this to cycle through the annotations in this slice view in forward order.</p></body></html></string>
+   </property>
+  </action>
+  <action name="actionAnnotationPrevious">
+   <property name="icon">
+    <iconset resource="../Resources/SNAPResources.qrc">
+     <normaloff>:/root/arrow_up_16.png</normaloff>:/root/arrow_up_16.png</iconset>
+   </property>
+   <property name="text">
+    <string>Previous annotation</string>
+   </property>
+   <property name="iconText">
+    <string>previous</string>
+   </property>
+   <property name="toolTip">
+    <string><html><head/><body><p>Select the previous annotation. Use this to cycle through the annotations in this slice view in reverse order.</p></body></html></string>
+   </property>
+  </action>
  </widget>
  <customwidgets>
   <customwidget>
@@ -830,6 +1185,12 @@ p, li { white-space: pre-wrap; }
    <header>PaintbrushInteractionMode.h</header>
    <container>1</container>
   </customwidget>
+  <customwidget>
+   <class>AnnotationInteractionMode</class>
+   <extends>QWidget</extends>
+   <header>AnnotationInteractionMode.h</header>
+   <container>1</container>
+  </customwidget>
  </customwidgets>
  <resources>
   <include location="../Resources/SNAPResources.qrc"/>
diff --git a/GUI/Qt/Components/SnakeToolROIPanel.cxx b/GUI/Qt/Components/SnakeToolROIPanel.cxx
index 1b62b25..af5856e 100644
--- a/GUI/Qt/Components/SnakeToolROIPanel.cxx
+++ b/GUI/Qt/Components/SnakeToolROIPanel.cxx
@@ -4,6 +4,7 @@
 #include <SNAPQtCommon.h>
 #include <QtSpinBoxCoupling.h>
 #include <QtWidgetArrayCoupling.h>
+#include <QtCheckBoxCoupling.h>
 #include <GlobalUIModel.h>
 #include <SnakeROIModel.h>
 #include <MainImageWindow.h>
@@ -41,6 +42,9 @@ void SnakeToolROIPanel::SetModel(GlobalUIModel *model)
   makeArrayCoupling(
         ui->inSizeX, ui->inSizeY, ui->inSizeZ,
         model->GetSnakeROISizeModel());
+
+  // Hook up the segmentation seeding option
+  makeCoupling(ui->chkCarryLabels, model->GetSnakeROISeedWithCurrentSegmentationModel());
 }
 
 void SnakeToolROIPanel::on_btnResetROI_clicked()
diff --git a/GUI/Qt/Components/SnakeToolROIPanel.ui b/GUI/Qt/Components/SnakeToolROIPanel.ui
index c618710..b5d16ed 100644
--- a/GUI/Qt/Components/SnakeToolROIPanel.ui
+++ b/GUI/Qt/Components/SnakeToolROIPanel.ui
@@ -6,7 +6,7 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>215</width>
+    <width>172</width>
     <height>439</height>
    </rect>
   </property>
@@ -24,85 +24,54 @@ font-size: 11px;
 </string>
   </property>
   <layout class="QVBoxLayout" name="verticalLayout">
-   <property name="margin">
+   <property name="spacing">
+    <number>6</number>
+   </property>
+   <property name="leftMargin">
+    <number>0</number>
+   </property>
+   <property name="topMargin">
+    <number>0</number>
+   </property>
+   <property name="rightMargin">
+    <number>0</number>
+   </property>
+   <property name="bottomMargin">
     <number>0</number>
    </property>
    <item>
-    <widget class="QLabel" name="label">
-     <property name="sizePolicy">
-      <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
-       <horstretch>0</horstretch>
-       <verstretch>0</verstretch>
-      </sizepolicy>
-     </property>
-     <property name="maximumSize">
-      <size>
-       <width>160</width>
-       <height>16777215</height>
-      </size>
-     </property>
-     <property name="font">
-      <font>
-       <pointsize>-1</pointsize>
-      </font>
-     </property>
-     <property name="styleSheet">
-      <string notr="true">* {
-font-size: 11px;
-}
-</string>
-     </property>
-     <property name="text">
-      <string>This tool selects the region of interest (ROI) for automatic segmentation.</string>
-     </property>
-     <property name="wordWrap">
-      <bool>true</bool>
-     </property>
-    </widget>
-   </item>
-   <item>
-    <widget class="Line" name="line_2">
-     <property name="frameShadow">
-      <enum>QFrame::Plain</enum>
-     </property>
-     <property name="orientation">
-      <enum>Qt::Horizontal</enum>
-     </property>
-    </widget>
-   </item>
-   <item>
-    <widget class="QLabel" name="label_4">
+    <widget class="QLabel" name="label_5">
      <property name="font">
       <font>
        <pointsize>-1</pointsize>
       </font>
      </property>
      <property name="text">
-      <string>ROI Dimensions</string>
+      <string>ROI for auto-segmentation:</string>
      </property>
     </widget>
    </item>
    <item>
     <widget class="QWidget" name="widget_6" native="true">
      <layout class="QGridLayout" name="gridLayout_3">
-      <property name="margin">
+      <property name="leftMargin">
+       <number>12</number>
+      </property>
+      <property name="topMargin">
        <number>0</number>
       </property>
-      <property name="spacing">
-       <number>4</number>
+      <property name="rightMargin">
+       <number>0</number>
+      </property>
+      <property name="bottomMargin">
+       <number>0</number>
+      </property>
+      <property name="horizontalSpacing">
+       <number>3</number>
+      </property>
+      <property name="verticalSpacing">
+       <number>2</number>
       </property>
-      <item row="0" column="0" rowspan="2" colspan="3">
-       <widget class="QLabel" name="label_3">
-        <property name="font">
-         <font>
-          <pointsize>-1</pointsize>
-         </font>
-        </property>
-        <property name="text">
-         <string>Corner position (x,y,z):</string>
-        </property>
-       </widget>
-      </item>
       <item row="2" column="0">
        <widget class="QSpinBox" name="inIndexX">
         <property name="maximumSize">
@@ -111,6 +80,9 @@ font-size: 11px;
           <height>16777215</height>
          </size>
         </property>
+        <property name="toolTip">
+         <string><html><head/><body><p>The position of the 3D region of interest (ROI) for automatic segmentation.</p></body></html></string>
+        </property>
         <property name="buttonSymbols">
          <enum>QAbstractSpinBox::NoButtons</enum>
         </property>
@@ -124,11 +96,26 @@ font-size: 11px;
           <height>16777215</height>
          </size>
         </property>
+        <property name="toolTip">
+         <string><html><head/><body><p>The position of the 3D region of interest (ROI) for automatic segmentation.</p></body></html></string>
+        </property>
         <property name="buttonSymbols">
          <enum>QAbstractSpinBox::NoButtons</enum>
         </property>
        </widget>
       </item>
+      <item row="0" column="0" rowspan="2" colspan="3">
+       <widget class="QLabel" name="label_3">
+        <property name="font">
+         <font>
+          <pointsize>-1</pointsize>
+         </font>
+        </property>
+        <property name="text">
+         <string>Position (x,y,z):</string>
+        </property>
+       </widget>
+      </item>
       <item row="2" column="2">
        <widget class="QSpinBox" name="inIndexZ">
         <property name="maximumSize">
@@ -137,6 +124,9 @@ font-size: 11px;
           <height>16777215</height>
          </size>
         </property>
+        <property name="toolTip">
+         <string><html><head/><body><p>The position of the 3D region of interest (ROI) for automatic segmentation.</p></body></html></string>
+        </property>
         <property name="buttonSymbols">
          <enum>QAbstractSpinBox::NoButtons</enum>
         </property>
@@ -148,11 +138,20 @@ font-size: 11px;
    <item>
     <widget class="QWidget" name="widget_7" native="true">
      <layout class="QGridLayout" name="gridLayout_4">
-      <property name="margin">
+      <property name="leftMargin">
+       <number>12</number>
+      </property>
+      <property name="topMargin">
+       <number>0</number>
+      </property>
+      <property name="rightMargin">
+       <number>0</number>
+      </property>
+      <property name="bottomMargin">
        <number>0</number>
       </property>
       <property name="spacing">
-       <number>4</number>
+       <number>2</number>
       </property>
       <item row="0" column="0" rowspan="2" colspan="3">
        <widget class="QLabel" name="label_2">
@@ -174,6 +173,9 @@ font-size: 11px;
           <height>16777215</height>
          </size>
         </property>
+        <property name="toolTip">
+         <string><html><head/><body><p>The size of the 3D region of interest (ROI) for automatic segmentation.</p></body></html></string>
+        </property>
         <property name="buttonSymbols">
          <enum>QAbstractSpinBox::NoButtons</enum>
         </property>
@@ -187,6 +189,9 @@ font-size: 11px;
           <height>16777215</height>
          </size>
         </property>
+        <property name="toolTip">
+         <string><html><head/><body><p>The size of the 3D region of interest (ROI) for automatic segmentation.</p></body></html></string>
+        </property>
         <property name="buttonSymbols">
          <enum>QAbstractSpinBox::NoButtons</enum>
         </property>
@@ -200,6 +205,9 @@ font-size: 11px;
           <height>16777215</height>
          </size>
         </property>
+        <property name="toolTip">
+         <string><html><head/><body><p>The size of the 3D region of interest (ROI) for automatic segmentation.</p></body></html></string>
+        </property>
         <property name="buttonSymbols">
          <enum>QAbstractSpinBox::NoButtons</enum>
         </property>
@@ -214,7 +222,16 @@ font-size: 11px;
       <property name="spacing">
        <number>0</number>
       </property>
-      <property name="margin">
+      <property name="leftMargin">
+       <number>0</number>
+      </property>
+      <property name="topMargin">
+       <number>0</number>
+      </property>
+      <property name="rightMargin">
+       <number>0</number>
+      </property>
+      <property name="bottomMargin">
        <number>0</number>
       </property>
       <item>
@@ -236,6 +253,9 @@ font-size: 11px;
           <pointsize>-1</pointsize>
          </font>
         </property>
+        <property name="toolTip">
+         <string><html><head/><body><p>Reset the region of interest to be the whole image.</p></body></html></string>
+        </property>
         <property name="text">
          <string>Reset ROI</string>
         </property>
@@ -246,9 +266,6 @@ font-size: 11px;
    </item>
    <item>
     <widget class="Line" name="line">
-     <property name="frameShadow">
-      <enum>QFrame::Plain</enum>
-     </property>
      <property name="orientation">
       <enum>Qt::Horizontal</enum>
      </property>
@@ -256,30 +273,40 @@ font-size: 11px;
    </item>
    <item>
     <widget class="QWidget" name="widget" native="true">
-     <layout class="QHBoxLayout" name="horizontalLayout">
-      <property name="margin">
+     <property name="styleSheet">
+      <string notr="true">font-size:12px;</string>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout_2">
+      <property name="leftMargin">
+       <number>12</number>
+      </property>
+      <property name="topMargin">
+       <number>0</number>
+      </property>
+      <property name="rightMargin">
+       <number>0</number>
+      </property>
+      <property name="bottomMargin">
        <number>0</number>
       </property>
       <item>
-       <spacer name="horizontalSpacer">
-        <property name="orientation">
-         <enum>Qt::Horizontal</enum>
+       <widget class="QCheckBox" name="chkResample">
+        <property name="toolTip">
+         <string><html><head/><body><p><span style=" font-size:12pt;">When checked, you will have an option to change the resolution of the region of interest (i.e., subsample or supersample) before running automatic segmentation.</span></p></body></html></string>
         </property>
-        <property name="sizeHint" stdset="0">
-         <size>
-          <width>10</width>
-          <height>20</height>
-         </size>
+        <property name="text">
+         <string>Resample ROI</string>
         </property>
-       </spacer>
+       </widget>
       </item>
       <item>
-       <widget class="QCheckBox" name="chkResample">
+       <widget class="QCheckBox" name="chkCarryLabels">
         <property name="toolTip">
-         <string>When this option is selected, you will have an option to change the resolution of the region of interest (i.e., subsample or supersample) before running automatic segmentation.</string>
+         <string><html><head/><body><p>When checked, the existing segmentation will be carried over to the automatic segmentation mode and used to initialize the active contour. When unchecked, the active contour will be initialized with bubbles.</p></body></html></string>
         </property>
         <property name="text">
-         <string>Resample ROI</string>
+         <string>Initialize with current
+segmentation</string>
         </property>
        </widget>
       </item>
@@ -287,12 +314,41 @@ font-size: 11px;
     </widget>
    </item>
    <item>
+    <widget class="Line" name="line_3">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <spacer name="verticalSpacer_2">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>20</width>
+       <height>1</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item>
     <widget class="QWidget" name="widget_2" native="true">
      <layout class="QHBoxLayout" name="horizontalLayout_2">
       <property name="spacing">
        <number>0</number>
       </property>
-      <property name="margin">
+      <property name="leftMargin">
+       <number>0</number>
+      </property>
+      <property name="topMargin">
+       <number>0</number>
+      </property>
+      <property name="rightMargin">
+       <number>0</number>
+      </property>
+      <property name="bottomMargin">
        <number>0</number>
       </property>
       <item>
@@ -314,6 +370,9 @@ font-size: 11px;
           <pointsize>-1</pointsize>
          </font>
         </property>
+        <property name="toolTip">
+         <string><html><head/><body><p>Press this button to start semi-automatic segmentation</p></body></html></string>
+        </property>
         <property name="text">
          <string>Segment 3D</string>
         </property>
@@ -330,7 +389,7 @@ font-size: 11px;
      <property name="sizeHint" stdset="0">
       <size>
        <width>20</width>
-       <height>40</height>
+       <height>1</height>
       </size>
      </property>
     </spacer>
diff --git a/GUI/Qt/Components/SnakeWizardPanel.cxx b/GUI/Qt/Components/SnakeWizardPanel.cxx
index 51ecfef..ec18e5f 100644
--- a/GUI/Qt/Components/SnakeWizardPanel.cxx
+++ b/GUI/Qt/Components/SnakeWizardPanel.cxx
@@ -145,7 +145,7 @@ void BubbleItemModel::onBubbleValuesUpdate()
 
 
 SnakeWizardPanel::SnakeWizardPanel(QWidget *parent) :
-    QWidget(parent),
+    SNAPComponent(parent),
     ui(new Ui::SnakeWizardPanel)
 {
   ui->setupUi(this);
@@ -170,6 +170,11 @@ SnakeWizardPanel::SnakeWizardPanel(QWidget *parent) :
 
   this->addAction(ui->actionIncreaseBubbleRadius);
   this->addAction(ui->actionDecreaseBubbleRadius);
+
+  // Create model for the classification foreground list view
+  QStandardItemModel *classify_fg_model = new QStandardItemModel(this);
+  classify_fg_model->setColumnCount(1);
+  ui->lstClassifyForeground->setModel(classify_fg_model);
 }
 
 SnakeWizardPanel::~SnakeWizardPanel()
@@ -221,9 +226,22 @@ void SnakeWizardPanel::SetModel(GlobalUIModel *model)
   makeCoupling(ui->inClusterCount, m_Model->GetNumberOfClustersModel());
   makeCoupling(ui->inClusterActive, m_Model->GetForegroundClusterModel());
 
-  // Couple the classification controls
-  makeCoupling(ui->inClassifyForeground, m_Model->GetForegroundClassColorLabelModel());
-  makeCoupling(ui->inClassifyTrees, m_Model->GetForestSizeModel());
+  // Set up activation on classification controls
+  activateOnFlag(ui->lstClassifyForeground, m_Model, SnakeWizardModel::UIF_CLASSIFIER_TRAINED);
+
+  // Make the coupling for foreground label list (some complicated template magic here)
+  typedef DefaultWidgetValueTraits<
+      SnakeWizardModel::ClassifierLabelForegroundMap,
+      QAbstractItemView> ClassifyForegroundValueTraits;
+
+  typedef QStandardItemModelWidgetDomainTraits<
+      SnakeWizardModel::ClassifierLabelForegroundMapDomain,
+      SingleColumnColorLabelToQSIMCouplingRowTraits> ClassifyForegroundDomainTraits;
+
+  makeCoupling((QAbstractItemView *) ui->lstClassifyForeground,
+               m_Model->GetClassifierLabelForegroundModel(),
+               ClassifyForegroundValueTraits(),
+               ClassifyForegroundDomainTraits());
 
   // Couple the edge preprocessing controls
   makeCoupling(ui->inEdgeScale, m_Model->GetEdgePreprocessingSigmaModel());
@@ -440,6 +458,7 @@ void SnakeWizardPanel::on_btnClassifyTrain_clicked()
 {
   try
   {
+    QtCursorOverride cursy(Qt::WaitCursor);
     m_Model->TrainClassifier();
   }
   catch (IRISException &exc)
@@ -469,7 +488,84 @@ void SnakeWizardPanel::onClassifyQuickLabelSelection()
   m_Model->GetParent()->GetGlobalState()->SetToolbarMode(PAINTBRUSH_MODE);
 }
 
+/*
+void SnakeWizardPanel::UpdateClassifierForegroundTable()
+{
+  m_IsClassifierForegroundTableChanging = true;
+
+  ui->lstClassifyForeground->clear();
+  if(m_Model->IsClassifierTrained())
+    {
+    SnakeWizardModel::ClassifierFBTable fbtab;
+    m_Model->GetClassifierForegroundBackgroundTable(fbtab);
+
+    if(m_ClassifierForegroundTableCached == fbtab)
+      return;
+    else
+      m_ClassifierForegroundTableCached = fbtab;
+
+    for(SnakeWizardModel::ClassifierFBTable::iterator it = fbtab.begin();
+        it != fbtab.end(); ++it)
+      {
+      QListWidgetItem *item = new QListWidgetItem(ui->lstClassifyForeground);
+      item->setText(from_utf8(it->second.title));
+      item->setIcon(CreateColorBoxIcon(16, 16,
+                                       QColor(255 * it->second.color[0],
+                                              255 * it->second.color[1],
+                                              255 * it->second.color[2])));
+      item->setData(Qt::UserRole, it->first);
+      item->setSelected(it->second.weight > 0.0);
+      }
+    }
+  else
+    {
+    m_ClassifierForegroundTableCached.clear();
+    }
+
+  m_IsClassifierForegroundTableChanging = false;
+}
+
+void SnakeWizardPanel::on_lstClassifyForeground_itemSelectionChanged()
+{
+  if(m_IsClassifierForegroundTableChanging)
+    return;
+
+  if(m_Model->IsClassifierTrained())
+    {
+    SnakeWizardModel::ClassifierFBTable fbtab;
+    for(int i = 0; i < ui->lstClassifyForeground->count(); i++)
+      {
+      QListWidgetItem *item = ui->lstClassifyForeground->item(i);
+      LabelType label = item->data(Qt::UserRole).value<LabelType>();
+      bool is_selected = item->isSelected();
+      fbtab[label].weight = is_selected ? 1.0 : -1.0;
+      }
+    m_Model->SetClassifierForegroundBackgroundTable(fbtab);
+    }
+}
+
+
+void SnakeWizardPanel::onModelUpdate(const EventBucket &bucket)
+{
+  if(bucket.HasEvent(SnakeWizardModel::RFClassifierModifiedEvent())
+     || bucket.HasEvent(SegmentationLabelChangeEvent()))
+    {
+    this->UpdateClassifierForegroundTable();
+    }
+}
+*/
+
 void SnakeWizardPanel::on_btnEdgeDetail_clicked()
 {
   m_SpeedDialog->ShowDialog();
 }
+
+void SnakeWizardPanel::on_btnClassifyDetail_clicked()
+{
+  m_SpeedDialog->ShowDialog();
+}
+
+
+
+
+
diff --git a/GUI/Qt/Components/SnakeWizardPanel.h b/GUI/Qt/Components/SnakeWizardPanel.h
index 731b8d6..c0acd09 100644
--- a/GUI/Qt/Components/SnakeWizardPanel.h
+++ b/GUI/Qt/Components/SnakeWizardPanel.h
@@ -3,6 +3,9 @@
 
 #include <QWidget>
 #include <QAbstractItemModel>
+#include <QStandardItemModel>
+#include <SNAPComponent.h>
+#include <SnakeWizardModel.h>
 
 namespace Ui {
 class SnakeWizardPanel;
@@ -10,11 +13,13 @@ class SnakeWizardPanel;
 
 class SpeedImageDialog;
 class GlobalUIModel;
-class SnakeWizardModel;
 class QTimer;
 class SnakeParameterDialog;
 class QToolBar;
 
+/**
+ * A Qt Model that handles bubble selection
+ */
 class BubbleItemModel : public QAbstractTableModel
 {
   Q_OBJECT
@@ -43,9 +48,7 @@ private:
   SnakeWizardModel *m_Model;
 };
 
-
-
-class SnakeWizardPanel : public QWidget
+class SnakeWizardPanel : public SNAPComponent
 {
   Q_OBJECT
 
@@ -119,6 +122,8 @@ private slots:
 
   void on_btnEdgeDetail_clicked();
 
+  void on_btnClassifyDetail_clicked();
+
 private:
 
   SpeedImageDialog *m_SpeedDialog;
diff --git a/GUI/Qt/Components/SnakeWizardPanel.ui b/GUI/Qt/Components/SnakeWizardPanel.ui
index 030a8b0..26a00b7 100644
--- a/GUI/Qt/Components/SnakeWizardPanel.ui
+++ b/GUI/Qt/Components/SnakeWizardPanel.ui
@@ -6,8 +6,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>177</width>
-    <height>680</height>
+    <width>191</width>
+    <height>654</height>
    </rect>
   </property>
   <property name="sizePolicy">
@@ -18,7 +18,7 @@
   </property>
   <property name="maximumSize">
    <size>
-    <width>177</width>
+    <width>191</width>
     <height>16777215</height>
    </size>
   </property>
@@ -29,28 +29,39 @@
    <string notr="true">* {
 font-size: 12px;
 }
+QSpinBox {
+font-size: 11px;
+}
 QGroupBox {
   background-origin: content;
   margin-top: 15px;
   font-weight: bold;
   font-size: 12px;
-  font-family: helvetica;
   color: rgb(30,30,160);
-  background-color: rgb(237,237,237);
+  background-color: rgb(222,222,222);
   padding: 5px;
-  border-radius: 4px;
-  border: 1px solid rgb(130,130,130);
+  border-radius: 2px;
+  border: 1px solid rgb(168,168,168);
 }
 QGroupBox::title {
   subcontrol-origin: 	margin;
   subcontrol-position: top left;
 }
 
+QToolButton::checked {
+  background-color:rgb(210, 210, 210);
+}
+
+QToolButton::pressed {
+  background-color:rgb(210, 210, 210);
+}
+
+
 </string>
   </property>
   <layout class="QVBoxLayout" name="verticalLayout_3">
    <property name="spacing">
-    <number>8</number>
+    <number>12</number>
    </property>
    <property name="leftMargin">
     <number>5</number>
@@ -73,7 +84,7 @@ QGroupBox::title {
       </size>
      </property>
      <property name="title">
-      <string>Current Stage</string>
+      <string>Current Stage:</string>
      </property>
      <layout class="QVBoxLayout" name="verticalLayout">
       <property name="leftMargin">
@@ -128,9 +139,9 @@ QGroupBox::title {
              <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
 <html><head><meta name="qrichtext" content="1" /><style type="text/css">
 p, li { white-space: pre-wrap; }
-</style></head><body style=" font-family:'Lucida Grande'; font-size:10px; font-weight:400; font-style:normal;">
-<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12px;">Step 1/3</span></p>
-<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12px; font-weight:600;">Preprocessing</span></p></body></html></string>
+</style></head><body style=" font-family:'.Helvetica Neue DeskInterface'; font-size:10px; font-weight:400; font-style:normal;">
+<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande'; font-size:12px;">Step 1/3</span></p>
+<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande'; font-size:12px; font-weight:600;">Presegmentation</span></p></body></html></string>
             </property>
             <property name="wordWrap">
              <bool>true</bool>
@@ -240,7 +251,7 @@ p, li { white-space: pre-wrap; }
        <number>0</number>
       </property>
       <property name="topMargin">
-       <number>0</number>
+       <number>6</number>
       </property>
       <property name="rightMargin">
        <number>0</number>
@@ -297,10 +308,10 @@ p, li { white-space: pre-wrap; }
              <item>
               <widget class="QLabel" name="label_2">
                <property name="text">
-                <string>Presegmentation mode</string>
+                <string>Presegmentation mode:</string>
                </property>
                <property name="wordWrap">
-                <bool>false</bool>
+                <bool>true</bool>
                </property>
               </widget>
              </item>
@@ -315,10 +326,10 @@ p, li { white-space: pre-wrap; }
               <verstretch>0</verstretch>
              </sizepolicy>
             </property>
-            <property name="maximumSize">
+            <property name="minimumSize">
              <size>
-              <width>16777215</width>
-              <height>16777215</height>
+              <width>150</width>
+              <height>0</height>
              </size>
             </property>
             <item>
@@ -328,12 +339,12 @@ p, li { white-space: pre-wrap; }
             </item>
             <item>
              <property name="text">
-              <string>Clustering</string>
+              <string>Classification</string>
              </property>
             </item>
             <item>
              <property name="text">
-              <string>Supervised Classification</string>
+              <string>Clustering</string>
              </property>
             </item>
             <item>
@@ -361,8 +372,14 @@ p, li { white-space: pre-wrap; }
           </item>
           <item>
            <widget class="Line" name="line">
+            <property name="styleSheet">
+             <string notr="true">border-top:  1px solid rgb(164, 164, 164);
+border-bottom: 1px solid rgb(164,164, 164);
+border-left: 0px;
+border-right: 0px;</string>
+            </property>
             <property name="frameShadow">
-             <enum>QFrame::Plain</enum>
+             <enum>QFrame::Sunken</enum>
             </property>
             <property name="orientation">
              <enum>Qt::Horizontal</enum>
@@ -403,6 +420,9 @@ p, li { white-space: pre-wrap; }
               <property name="leftMargin">
                <number>0</number>
               </property>
+              <property name="topMargin">
+               <number>0</number>
+              </property>
               <property name="rightMargin">
                <number>0</number>
               </property>
@@ -414,6 +434,9 @@ p, li { white-space: pre-wrap; }
                 <property name="orientation">
                  <enum>Qt::Vertical</enum>
                 </property>
+                <property name="sizeType">
+                 <enum>QSizePolicy::Fixed</enum>
+                </property>
                 <property name="sizeHint" stdset="0">
                  <size>
                   <width>20</width>
@@ -627,6 +650,9 @@ p, li { white-space: pre-wrap; }
                 <property name="orientation">
                  <enum>Qt::Vertical</enum>
                 </property>
+                <property name="sizeType">
+                 <enum>QSizePolicy::Fixed</enum>
+                </property>
                 <property name="sizeHint" stdset="0">
                  <size>
                   <width>20</width>
@@ -663,7 +689,7 @@ p, li { white-space: pre-wrap; }
                <number>0</number>
               </property>
               <property name="topMargin">
-               <number>12</number>
+               <number>0</number>
               </property>
               <property name="rightMargin">
                <number>0</number>
@@ -880,14 +906,20 @@ p, li { white-space: pre-wrap; }
              </layout>
             </widget>
             <widget class="QWidget" name="pgClassify">
-             <layout class="QGridLayout" name="gridLayout_5">
+             <layout class="QGridLayout" name="gridLayout_5" columnstretch="0">
               <property name="leftMargin">
                <number>0</number>
               </property>
+              <property name="topMargin">
+               <number>0</number>
+              </property>
               <property name="rightMargin">
                <number>0</number>
               </property>
-              <item row="13" column="0">
+              <property name="verticalSpacing">
+               <number>2</number>
+              </property>
+              <item row="17" column="0">
                <widget class="QWidget" name="widget_8" native="true">
                 <layout class="QHBoxLayout" name="horizontalLayout_7">
                  <property name="leftMargin">
@@ -902,30 +934,10 @@ p, li { white-space: pre-wrap; }
                  <property name="bottomMargin">
                   <number>0</number>
                  </property>
-                 <item>
-                  <widget class="QLabel" name="label_24">
-                   <property name="text">
-                    <string>Random forest size:</string>
-                   </property>
-                   <property name="wordWrap">
-                    <bool>true</bool>
-                   </property>
-                  </widget>
-                 </item>
-                 <item>
-                  <widget class="QSpinBox" name="inClassifyTrees">
-                   <property name="toolTip">
-                    <string><html><head/><body><p>This parameter controls the number of trees in the random forest algorithm. Using a larger number of trees will make classification slower, but can improve accuracy.</p></body></html></string>
-                   </property>
-                   <property name="maximum">
-                    <number>1000</number>
-                   </property>
-                  </widget>
-                 </item>
                 </layout>
                </widget>
               </item>
-              <item row="2" column="0">
+              <item row="2" column="0" alignment="Qt::AlignHCenter">
                <widget class="ColorLabelQuickListWidget" name="boxLabelQuickList" native="true">
                 <property name="minimumSize">
                  <size>
@@ -935,24 +947,52 @@ p, li { white-space: pre-wrap; }
                 </property>
                </widget>
               </item>
-              <item row="10" column="0">
-               <widget class="QLabel" name="label_9">
+              <item row="18" column="0" alignment="Qt::AlignHCenter">
+               <widget class="QPushButton" name="btnClassifyDetail">
+                <property name="minimumSize">
+                 <size>
+                  <width>120</width>
+                  <height>0</height>
+                 </size>
+                </property>
+                <property name="maximumSize">
+                 <size>
+                  <width>120</width>
+                  <height>16777215</height>
+                 </size>
+                </property>
+                <property name="toolTip">
+                 <string><html><head/><body><p><span style=" font-size:12pt;">Display additional classification parameters</span></p></body></html></string>
+                </property>
                 <property name="text">
-                 <string>Foreground class:</string>
+                 <string>More ...</string>
                 </property>
                </widget>
               </item>
-              <item row="1" column="0">
-               <widget class="QLabel" name="label_12">
-                <property name="text">
-                 <string><html><head/><body><p>Use the paintbrush or polygon tools to mark examples of two or more tissue classes.</p></body></html></string>
+              <item row="15" column="0">
+               <spacer name="verticalSpacer_17">
+                <property name="orientation">
+                 <enum>Qt::Vertical</enum>
                 </property>
-                <property name="wordWrap">
-                 <bool>true</bool>
+                <property name="sizeType">
+                 <enum>QSizePolicy::Fixed</enum>
+                </property>
+                <property name="sizeHint" stdset="0">
+                 <size>
+                  <width>20</width>
+                  <height>10</height>
+                 </size>
+                </property>
+               </spacer>
+              </item>
+              <item row="13" column="0">
+               <widget class="QLabel" name="label_9">
+                <property name="text">
+                 <string>Foreground class(es):</string>
                 </property>
                </widget>
               </item>
-              <item row="5" column="0" alignment="Qt::AlignHCenter">
+              <item row="4" column="0" alignment="Qt::AlignHCenter">
                <widget class="QPushButton" name="btnClassifyClearExamples">
                 <property name="sizePolicy">
                  <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
@@ -962,13 +1002,13 @@ p, li { white-space: pre-wrap; }
                 </property>
                 <property name="minimumSize">
                  <size>
-                  <width>120</width>
+                  <width>140</width>
                   <height>0</height>
                  </size>
                 </property>
                 <property name="maximumSize">
                  <size>
-                  <width>120</width>
+                  <width>140</width>
                   <height>16777215</height>
                  </size>
                 </property>
@@ -980,7 +1020,7 @@ p, li { white-space: pre-wrap; }
                 </property>
                </widget>
               </item>
-              <item row="9" column="0">
+              <item row="12" column="0">
                <spacer name="verticalSpacer_6">
                 <property name="orientation">
                  <enum>Qt::Vertical</enum>
@@ -996,13 +1036,65 @@ p, li { white-space: pre-wrap; }
                 </property>
                </spacer>
               </item>
-              <item row="12" column="0">
-               <spacer name="verticalSpacer_16">
+              <item row="1" column="0">
+               <widget class="QLabel" name="label_12">
+                <property name="sizePolicy">
+                 <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+                  <horstretch>0</horstretch>
+                  <verstretch>0</verstretch>
+                 </sizepolicy>
+                </property>
+                <property name="minimumSize">
+                 <size>
+                  <width>0</width>
+                  <height>68</height>
+                 </size>
+                </property>
+                <property name="styleSheet">
+                 <string notr="true">font-size:10px;
+color: rgb(64, 64, 64)</string>
+                </property>
+                <property name="text">
+                 <string><html><head/><body><p>Provide examples of two or more tissue classes by selecting the labels below and drawing on the image using the paintbrush tool.</p></body></html></string>
+                </property>
+                <property name="wordWrap">
+                 <bool>true</bool>
+                </property>
+               </widget>
+              </item>
+              <item row="6" column="0">
+               <widget class="QLabel" name="label_25">
+                <property name="sizePolicy">
+                 <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+                  <horstretch>0</horstretch>
+                  <verstretch>0</verstretch>
+                 </sizepolicy>
+                </property>
+                <property name="minimumSize">
+                 <size>
+                  <width>0</width>
+                  <height>56</height>
+                 </size>
+                </property>
+                <property name="styleSheet">
+                 <string notr="true">font-size:10px;
+color: rgb(64, 64, 64)</string>
+                </property>
+                <property name="text">
+                 <string><html><head/><body><p>Next, train the classifier and select the tissue class that you wish to use for segmentation.</p></body></html></string>
+                </property>
+                <property name="wordWrap">
+                 <bool>true</bool>
+                </property>
+               </widget>
+              </item>
+              <item row="5" column="0">
+               <spacer name="verticalSpacer_14">
                 <property name="orientation">
                  <enum>Qt::Vertical</enum>
                 </property>
                 <property name="sizeType">
-                 <enum>QSizePolicy::Expanding</enum>
+                 <enum>QSizePolicy::Fixed</enum>
                 </property>
                 <property name="sizeHint" stdset="0">
                  <size>
@@ -1012,56 +1104,98 @@ p, li { white-space: pre-wrap; }
                 </property>
                </spacer>
               </item>
-              <item row="11" column="0">
-               <widget class="QComboBox" name="inClassifyForeground">
-                <property name="toolTip">
-                 <string><html><head/><body><p>Select the tissue class that you would like to perform segmentation on. The rest of the tissue classes you defined will be considered background.</p></body></html></string>
+              <item row="3" column="0">
+               <spacer name="verticalSpacer_18">
+                <property name="orientation">
+                 <enum>Qt::Vertical</enum>
                 </property>
-               </widget>
+                <property name="sizeType">
+                 <enum>QSizePolicy::Fixed</enum>
+                </property>
+                <property name="sizeHint" stdset="0">
+                 <size>
+                  <width>20</width>
+                  <height>4</height>
+                 </size>
+                </property>
+               </spacer>
               </item>
-              <item row="4" column="0" alignment="Qt::AlignHCenter">
+              <item row="16" column="0">
+               <spacer name="verticalSpacer_16">
+                <property name="orientation">
+                 <enum>Qt::Vertical</enum>
+                </property>
+                <property name="sizeType">
+                 <enum>QSizePolicy::Expanding</enum>
+                </property>
+                <property name="sizeHint" stdset="0">
+                 <size>
+                  <width>20</width>
+                  <height>10</height>
+                 </size>
+                </property>
+               </spacer>
+              </item>
+              <item row="7" column="0" alignment="Qt::AlignHCenter">
                <widget class="QPushButton" name="btnClassifyTrain">
                 <property name="sizePolicy">
-                 <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+                 <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
                   <horstretch>0</horstretch>
                   <verstretch>0</verstretch>
                  </sizepolicy>
                 </property>
                 <property name="minimumSize">
                  <size>
-                  <width>120</width>
+                  <width>140</width>
                   <height>0</height>
                  </size>
                 </property>
                 <property name="maximumSize">
                  <size>
-                  <width>120</width>
+                  <width>140</width>
                   <height>16777215</height>
                  </size>
                 </property>
+                <property name="font">
+                 <font>
+                  <pointsize>-1</pointsize>
+                 </font>
+                </property>
                 <property name="toolTip">
-                 <string><html><head/><body><p>This button trains the random forest classifier. The classifier assigns a probability value to each voxel of belonging to the 'foreground' class vs. belonging to all other classes. You must train a classifier before proceeding to the text step.</p></body></html></string>
+                 <string><html><head/><body><p>This button trains the random forest classifier. The classifier assigns a probability value to each voxel of belonging to the 'foreground' class vs. belonging to all other classes. You must train a classifier before proceeding to the next step.</p></body></html></string>
                 </property>
                 <property name="text">
                  <string>Train Classifier</string>
                 </property>
                </widget>
               </item>
-              <item row="3" column="0">
-               <spacer name="verticalSpacer_14">
-                <property name="orientation">
-                 <enum>Qt::Vertical</enum>
-                </property>
-                <property name="sizeType">
-                 <enum>QSizePolicy::Fixed</enum>
-                </property>
-                <property name="sizeHint" stdset="0">
+              <item row="14" column="0" alignment="Qt::AlignHCenter">
+               <widget class="QListView" name="lstClassifyForeground">
+                <property name="maximumSize">
                  <size>
-                  <width>20</width>
-                  <height>10</height>
+                  <width>165</width>
+                  <height>16777215</height>
                  </size>
                 </property>
-               </spacer>
+                <property name="toolTip">
+                 <string><html><head/><body><p>Designate one or more classes as the &quot;foreground&quot; class(es). These are the classes that you want to apply segmentation to. The speed image is computed as the sum of probabilities of all the foreground classes, minus the sum of probabilities of the background classes.</p></body></html></string>
+                </property>
+                <property name="styleSheet">
+                 <string notr="true">QListView:!active
+{
+  selection-background-color: rgb(162, 204, 255);
+}</string>
+                </property>
+                <property name="editTriggers">
+                 <set>QAbstractItemView::NoEditTriggers</set>
+                </property>
+                <property name="selectionMode">
+                 <enum>QAbstractItemView::ExtendedSelection</enum>
+                </property>
+                <property name="selectionBehavior">
+                 <enum>QAbstractItemView::SelectRows</enum>
+                </property>
+               </widget>
               </item>
              </layout>
             </widget>
@@ -1070,6 +1204,9 @@ p, li { white-space: pre-wrap; }
               <property name="leftMargin">
                <number>0</number>
               </property>
+              <property name="topMargin">
+               <number>0</number>
+              </property>
               <property name="rightMargin">
                <number>0</number>
               </property>
@@ -1128,6 +1265,9 @@ competition</string>
               </item>
               <item row="0" column="0" colspan="2">
                <widget class="QLabel" name="label_21">
+                <property name="styleSheet">
+                 <string notr="true"/>
+                </property>
                 <property name="text">
                  <string>Use this mode to perform segmentation using a speed image  computed outside of ITK-SNAP.</string>
                 </property>
@@ -1176,6 +1316,9 @@ competition</string>
               <property name="leftMargin">
                <number>0</number>
               </property>
+              <property name="topMargin">
+               <number>0</number>
+              </property>
               <property name="rightMargin">
                <number>0</number>
               </property>
@@ -1236,9 +1379,15 @@ competition</string>
            </widget>
           </item>
           <item>
-           <widget class="Line" name="line_6">
+           <widget class="Line" name="line_2">
+            <property name="styleSheet">
+             <string notr="true">border-top:  1px solid rgb(164, 164, 164);
+border-bottom: 1px solid rgb(164,164, 164);
+border-left: 0px;
+border-right: 0px;</string>
+            </property>
             <property name="frameShadow">
-             <enum>QFrame::Plain</enum>
+             <enum>QFrame::Sunken</enum>
             </property>
             <property name="orientation">
              <enum>Qt::Horizontal</enum>
@@ -1347,7 +1496,7 @@ competition</string>
           <item>
            <widget class="QLabel" name="label_6">
             <property name="text">
-             <string>A. Place bubbles in the image to intialize the contour</string>
+             <string>Place bubbles in the image to intialize the contour</string>
             </property>
             <property name="wordWrap">
              <bool>true</bool>
@@ -1418,7 +1567,7 @@ competition</string>
             </property>
            </widget>
           </item>
-          <item>
+          <item alignment="Qt::AlignHCenter">
            <widget class="QTableView" name="tableBubbleList">
             <property name="sizePolicy">
              <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
@@ -1428,7 +1577,7 @@ competition</string>
             </property>
             <property name="maximumSize">
              <size>
-              <width>155</width>
+              <width>165</width>
               <height>120</height>
              </size>
             </property>
@@ -1508,8 +1657,8 @@ competition</string>
              <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
 <html><head><meta name="qrichtext" content="1" /><style type="text/css">
 p, li { white-space: pre-wrap; }
-</style></head><body style=" font-family:'Lucida Grande'; font-size:12px; font-weight:400; font-style:normal;">
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:13px;">C. Press 'Next&quot; to proceed to the next step.</span></p></body></html></string>
+</style></head><body style=" font-family:'.Lucida Grande UI'; font-size:12px; font-weight:400; font-style:normal;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande'; font-size:13px;">Press 'Next&quot; to proceed to the next step.</span></p></body></html></string>
             </property>
             <property name="wordWrap">
              <bool>true</bool>
@@ -1652,11 +1801,7 @@ p, li { white-space: pre-wrap; }
                 </size>
                </property>
                <property name="text">
-                <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
-<html><head><meta name="qrichtext" content="1" /><style type="text/css">
-p, li { white-space: pre-wrap; }
-</style></head><body style=" font-family:'Lucida Grande'; font-size:12px; font-weight:400; font-style:normal;">
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:13px;">A. Configure the parameters of the contour evolution differential equation</span></p></body></html></string>
+                <string>Configure the parameters of the contour evolution differential equation</string>
                </property>
                <property name="wordWrap">
                 <bool>true</bool>
@@ -1700,7 +1845,7 @@ p, li { white-space: pre-wrap; }
           <item>
            <widget class="Line" name="line_5">
             <property name="frameShadow">
-             <enum>QFrame::Plain</enum>
+             <enum>QFrame::Sunken</enum>
             </property>
             <property name="orientation">
              <enum>Qt::Horizontal</enum>
@@ -1728,11 +1873,7 @@ p, li { white-space: pre-wrap; }
              <item>
               <widget class="QLabel" name="label_14">
                <property name="text">
-                <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
-<html><head><meta name="qrichtext" content="1" /><style type="text/css">
-p, li { white-space: pre-wrap; }
-</style></head><body style=" font-family:'Lucida Grande'; font-size:12px; font-weight:400; font-style:normal;">
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:13px;">B. Execute and control the evolution</span></p></body></html></string>
+                <string>Execute and control the evolution</string>
                </property>
                <property name="wordWrap">
                 <bool>true</bool>
@@ -1775,6 +1916,9 @@ p, li { white-space: pre-wrap; }
              </item>
              <item>
               <widget class="QToolButton" name="btnRewind">
+               <property name="toolTip">
+                <string>Restart evolution</string>
+               </property>
                <property name="text">
                 <string>...</string>
                </property>
@@ -1793,6 +1937,9 @@ p, li { white-space: pre-wrap; }
              </item>
              <item>
               <widget class="QToolButton" name="btnPlay">
+               <property name="toolTip">
+                <string>Run/pause active contour evolution</string>
+               </property>
                <property name="text">
                 <string>...</string>
                </property>
@@ -1817,6 +1964,9 @@ p, li { white-space: pre-wrap; }
              </item>
              <item>
               <widget class="QToolButton" name="btnSingleStep">
+               <property name="toolTip">
+                <string>Perform a single evolution iteration</string>
+               </property>
                <property name="text">
                 <string>...</string>
                </property>
@@ -1907,7 +2057,11 @@ p, li { white-space: pre-wrap; }
               </widget>
              </item>
              <item row="1" column="0">
-              <widget class="QSpinBox" name="inStepSize"/>
+              <widget class="QSpinBox" name="inStepSize">
+               <property name="toolTip">
+                <string>Number of evolution steps per iteration.</string>
+               </property>
+              </widget>
              </item>
             </layout>
            </widget>
@@ -1915,7 +2069,7 @@ p, li { white-space: pre-wrap; }
           <item>
            <widget class="Line" name="line_4">
             <property name="frameShadow">
-             <enum>QFrame::Plain</enum>
+             <enum>QFrame::Sunken</enum>
             </property>
             <property name="orientation">
              <enum>Qt::Horizontal</enum>
@@ -1925,11 +2079,7 @@ p, li { white-space: pre-wrap; }
           <item>
            <widget class="QLabel" name="label_17">
             <property name="text">
-             <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
-<html><head><meta name="qrichtext" content="1" /><style type="text/css">
-p, li { white-space: pre-wrap; }
-</style></head><body style=" font-family:'Lucida Grande'; font-size:12px; font-weight:400; font-style:normal;">
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:13px;">C. Press 'Finish&quot; to accept the result.</span></p></body></html></string>
+             <string>Press 'Finish' to accept the result</string>
             </property>
             <property name="wordWrap">
              <bool>true</bool>
@@ -1968,6 +2118,9 @@ p, li { white-space: pre-wrap; }
                  <height>16777215</height>
                 </size>
                </property>
+               <property name="toolTip">
+                <string>Return to bubble placement</string>
+               </property>
                <property name="text">
                 <string>Back</string>
                </property>
@@ -1987,6 +2140,9 @@ p, li { white-space: pre-wrap; }
                  <height>16777215</height>
                 </size>
                </property>
+               <property name="toolTip">
+                <string>Accept segmentation and return to the main ITK-SNAP window</string>
+               </property>
                <property name="text">
                 <string>Finish</string>
                </property>
@@ -2058,6 +2214,11 @@ p, li { white-space: pre-wrap; }
  </widget>
  <customwidgets>
   <customwidget>
+   <class>QDoubleSlider</class>
+   <extends>QSlider</extends>
+   <header location="global">QDoubleSlider.h</header>
+  </customwidget>
+  <customwidget>
    <class>QDoubleSliderWithEditor</class>
    <extends>QSlider</extends>
    <header location="global">QDoubleSliderWithEditor.h</header>
@@ -2068,11 +2229,6 @@ p, li { white-space: pre-wrap; }
    <header>ColorLabelQuickListWidget.h</header>
    <container>1</container>
   </customwidget>
-  <customwidget>
-   <class>QDoubleSlider</class>
-   <extends>QSlider</extends>
-   <header location="global">QDoubleSlider.h</header>
-  </customwidget>
  </customwidgets>
  <resources>
   <include location="../Resources/SNAPResources.qrc"/>
diff --git a/GUI/Qt/Components/SynchronizationInspector.cxx b/GUI/Qt/Components/SynchronizationInspector.cxx
index 7d52e82..402d04e 100644
--- a/GUI/Qt/Components/SynchronizationInspector.cxx
+++ b/GUI/Qt/Components/SynchronizationInspector.cxx
@@ -33,9 +33,4 @@ void SynchronizationInspector::SetModel(SynchronizationModel *model)
   // The checkboxes should be deactivated when the sync model is off
   makeBooleanNamedPropertyCoupling(ui->panelProperties, "enabled",
                                    model->GetSyncEnabledModel());
-
-  // The checkboxes should be deactivated when the sync model is off
-  makeBooleanNamedPropertyCoupling(ui->inChannel, "enabled",
-                                   model->GetSyncEnabledModel());
-
 }
diff --git a/GUI/Qt/Components/SynchronizationInspector.ui b/GUI/Qt/Components/SynchronizationInspector.ui
index 69d36ed..c4bb0a2 100644
--- a/GUI/Qt/Components/SynchronizationInspector.ui
+++ b/GUI/Qt/Components/SynchronizationInspector.ui
@@ -7,7 +7,7 @@
     <x>0</x>
     <y>0</y>
     <width>162</width>
-    <height>300</height>
+    <height>349</height>
    </rect>
   </property>
   <property name="windowTitle">
@@ -17,16 +17,33 @@
    <string notr="true">*  {
 font-size: 12px;
 }
+
+QSpinBox { font-size: 11px; }
 </string>
   </property>
   <layout class="QVBoxLayout" name="verticalLayout">
-   <property name="margin">
+   <property name="spacing">
+    <number>4</number>
+   </property>
+   <property name="leftMargin">
+    <number>0</number>
+   </property>
+   <property name="topMargin">
+    <number>0</number>
+   </property>
+   <property name="rightMargin">
+    <number>0</number>
+   </property>
+   <property name="bottomMargin">
     <number>0</number>
    </property>
    <item>
     <widget class="QCheckBox" name="chkSync">
+     <property name="toolTip">
+      <string><html><head/><body><p><span style=" font-weight:600;">Toggle synchronization</span></p><p><br/></p><p>When enabled, this ITK-SNAP window will synchronize cursor position and other view properties with other ITK-SNAP windows open on the same machine. This is useful for yoking the cursor across two medical images.</p></body></html></string>
+     </property>
      <property name="styleSheet">
-      <string notr="true">font-weight:bold;</string>
+      <string notr="true"/>
      </property>
      <property name="text">
       <string>Synchronization</string>
@@ -41,6 +58,9 @@ font-size: 12px;
      <property name="leftMargin">
       <number>20</number>
      </property>
+     <property name="bottomMargin">
+      <number>5</number>
+     </property>
      <item>
       <widget class="QLabel" name="label">
        <property name="font">
@@ -69,19 +89,6 @@ ITK-SNAP windows</string>
     </layout>
    </item>
    <item>
-    <widget class="Line" name="line_2">
-     <property name="frameShadow">
-      <enum>QFrame::Plain</enum>
-     </property>
-     <property name="midLineWidth">
-      <number>1</number>
-     </property>
-     <property name="orientation">
-      <enum>Qt::Horizontal</enum>
-     </property>
-    </widget>
-   </item>
-   <item>
     <widget class="QLabel" name="label_3">
      <property name="text">
       <string>Properties to sync:</string>
@@ -94,9 +101,14 @@ ITK-SNAP windows</string>
       <bool>true</bool>
      </property>
      <property name="styleSheet">
-      <string notr="true"/>
+      <string notr="true">QCheckBox {
+  padding:0px;
+}</string>
      </property>
      <layout class="QVBoxLayout" name="verticalLayout_2">
+      <property name="spacing">
+       <number>6</number>
+      </property>
       <property name="leftMargin">
        <number>20</number>
       </property>
@@ -111,6 +123,9 @@ ITK-SNAP windows</string>
       </property>
       <item>
        <widget class="QCheckBox" name="chkCursor">
+        <property name="toolTip">
+         <string><html><head/><body><p>Sync the position of the 3D cursor between ITK-SNAP windows</p></body></html></string>
+        </property>
         <property name="text">
          <string>Cursor position</string>
         </property>
@@ -118,6 +133,9 @@ ITK-SNAP windows</string>
       </item>
       <item>
        <widget class="QCheckBox" name="chkZoom">
+        <property name="toolTip">
+         <string><html><head/><body><p>Sync the zoom level between ITK-SNAP windows. <span style=" font-style:italic;">Linked zoom must be enabled in the zoom inspector.</span></p></body></html></string>
+        </property>
         <property name="text">
          <string>Zoom level</string>
         </property>
@@ -125,6 +143,9 @@ ITK-SNAP windows</string>
       </item>
       <item>
        <widget class="QCheckBox" name="chkPan">
+        <property name="toolTip">
+         <string><html><head/><body><p>Sync the panning position betweenITK-SNAP windows. <span style=" font-style:italic;">Linked zoom must be enabled in the zoom inspector.</span></p></body></html></string>
+        </property>
         <property name="text">
          <string>Pan</string>
         </property>
@@ -132,28 +153,31 @@ ITK-SNAP windows</string>
       </item>
       <item>
        <widget class="QCheckBox" name="chkCamera">
+        <property name="toolTip">
+         <string><html><head/><body><p>Sync the 3D view camera position between ITK-SNAP windows.</p></body></html></string>
+        </property>
         <property name="text">
          <string>3D viewpoint</string>
         </property>
        </widget>
       </item>
+      <item>
+       <spacer name="verticalSpacer_2">
+        <property name="orientation">
+         <enum>Qt::Vertical</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>2</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
      </layout>
     </widget>
    </item>
    <item>
-    <widget class="Line" name="line_3">
-     <property name="frameShadow">
-      <enum>QFrame::Plain</enum>
-     </property>
-     <property name="midLineWidth">
-      <number>1</number>
-     </property>
-     <property name="orientation">
-      <enum>Qt::Horizontal</enum>
-     </property>
-    </widget>
-   </item>
-   <item>
     <widget class="QWidget" name="panelChannel" native="true">
      <layout class="QHBoxLayout" name="horizontalLayout_2">
       <property name="spacing">
@@ -171,32 +195,9 @@ ITK-SNAP windows</string>
       <property name="bottomMargin">
        <number>0</number>
       </property>
-      <item>
-       <widget class="QLabel" name="label_2">
-        <property name="text">
-         <string>Channel:</string>
-        </property>
-       </widget>
-      </item>
-      <item>
-       <widget class="QSpinBox" name="inChannel"/>
-      </item>
      </layout>
     </widget>
    </item>
-   <item>
-    <spacer name="verticalSpacer">
-     <property name="orientation">
-      <enum>Qt::Vertical</enum>
-     </property>
-     <property name="sizeHint" stdset="0">
-      <size>
-       <width>20</width>
-       <height>40</height>
-      </size>
-     </property>
-    </spacer>
-   </item>
   </layout>
  </widget>
  <resources/>
diff --git a/GUI/Qt/Components/ZoomInspector.ui b/GUI/Qt/Components/ZoomInspector.ui
index 5ff23b3..204b228 100644
--- a/GUI/Qt/Components/ZoomInspector.ui
+++ b/GUI/Qt/Components/ZoomInspector.ui
@@ -23,10 +23,25 @@
    <string notr="true">*  {
 font-size: 12px;
 }
+QSpinBox {
+font-size: 11px;
+}
 </string>
   </property>
   <layout class="QVBoxLayout" name="verticalLayout">
-   <property name="margin">
+   <property name="spacing">
+    <number>4</number>
+   </property>
+   <property name="leftMargin">
+    <number>0</number>
+   </property>
+   <property name="topMargin">
+    <number>0</number>
+   </property>
+   <property name="rightMargin">
+    <number>0</number>
+   </property>
+   <property name="bottomMargin">
     <number>0</number>
    </property>
    <item>
@@ -34,50 +49,20 @@ font-size: 12px;
      <property name="font">
       <font>
        <pointsize>-1</pointsize>
-       <weight>75</weight>
-       <bold>true</bold>
       </font>
      </property>
      <property name="focusPolicy">
       <enum>Qt::TabFocus</enum>
      </property>
+     <property name="toolTip">
+      <string><html><head/><body><p><span style=" font-weight:600;">Linked Zoom</span></p><p>When enabled, the zoom level in all three orthogonal slice views is kept equal. </p></body></html></string>
+     </property>
      <property name="text">
       <string>Linked zoom</string>
      </property>
     </widget>
    </item>
    <item>
-    <layout class="QHBoxLayout" name="horizontalLayout">
-     <property name="spacing">
-      <number>0</number>
-     </property>
-     <property name="leftMargin">
-      <number>20</number>
-     </property>
-     <item>
-      <widget class="QLabel" name="label">
-       <property name="font">
-        <font>
-         <pointsize>-1</pointsize>
-        </font>
-       </property>
-       <property name="styleSheet">
-        <string notr="true">font-size:10px;</string>
-       </property>
-       <property name="text">
-        <string>Maintains a common zoom factor in all slice views.</string>
-       </property>
-       <property name="alignment">
-        <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
-       </property>
-       <property name="wordWrap">
-        <bool>true</bool>
-       </property>
-      </widget>
-     </item>
-    </layout>
-   </item>
-   <item>
     <spacer name="verticalSpacer_2">
      <property name="orientation">
       <enum>Qt::Vertical</enum>
@@ -88,51 +73,16 @@ font-size: 12px;
      <property name="sizeHint" stdset="0">
       <size>
        <width>20</width>
-       <height>10</height>
+       <height>5</height>
       </size>
      </property>
     </spacer>
    </item>
    <item>
-    <widget class="QLabel" name="label_4">
-     <property name="enabled">
-      <bool>true</bool>
-     </property>
-     <property name="text">
-      <string>Common zoom factor:</string>
-     </property>
-     <property name="margin">
-      <number>0</number>
-     </property>
-     <property name="indent">
-      <number>0</number>
-     </property>
-     <property name="buddy">
-      <cstring>inZoom</cstring>
-     </property>
-    </widget>
-   </item>
-   <item>
     <layout class="QGridLayout" name="gridLayout">
      <property name="spacing">
       <number>4</number>
      </property>
-     <item row="0" column="0">
-      <spacer name="horizontalSpacer_2">
-       <property name="orientation">
-        <enum>Qt::Horizontal</enum>
-       </property>
-       <property name="sizeType">
-        <enum>QSizePolicy::Fixed</enum>
-       </property>
-       <property name="sizeHint" stdset="0">
-        <size>
-         <width>40</width>
-         <height>20</height>
-        </size>
-       </property>
-      </spacer>
-     </item>
      <item row="0" column="1" colspan="3">
       <widget class="QDoubleSpinBox" name="inZoom">
        <property name="sizePolicy">
@@ -143,7 +93,7 @@ font-size: 12px;
        </property>
        <property name="minimumSize">
         <size>
-         <width>120</width>
+         <width>60</width>
          <height>0</height>
         </size>
        </property>
@@ -152,6 +102,9 @@ font-size: 12px;
          <pointsize>-1</pointsize>
         </font>
        </property>
+       <property name="toolTip">
+        <string><html><head/><body><p><span style=" font-weight:600;">Zoom level for slice views</span></p><p>Set the zoom level in the three orthogonal slice views. Zoom level is expressed in units of screen pixels per physical mm. For example zoom level of 2 means that there are 2 screen pixels for every mm in the scanner coordinate system. </p></body></html></string>
+       </property>
        <property name="keyboardTracking">
         <bool>false</bool>
        </property>
@@ -159,14 +112,55 @@ font-size: 12px;
         <string/>
        </property>
        <property name="suffix">
-        <string> px/mm</string>
+        <string/>
        </property>
        <property name="decimals">
         <number>3</number>
        </property>
       </widget>
      </item>
-     <item row="1" column="1" colspan="3">
+     <item row="0" column="0">
+      <widget class="QLabel" name="label_4">
+       <property name="enabled">
+        <bool>true</bool>
+       </property>
+       <property name="text">
+        <string>Zoom:</string>
+       </property>
+       <property name="margin">
+        <number>0</number>
+       </property>
+       <property name="indent">
+        <number>0</number>
+       </property>
+       <property name="buddy">
+        <cstring>inZoom</cstring>
+       </property>
+      </widget>
+     </item>
+     <item row="0" column="4">
+      <widget class="QLabel" name="label_5">
+       <property name="enabled">
+        <bool>true</bool>
+       </property>
+       <property name="styleSheet">
+        <string notr="true">font-size:9pt;</string>
+       </property>
+       <property name="text">
+        <string> px/mm</string>
+       </property>
+       <property name="margin">
+        <number>0</number>
+       </property>
+       <property name="indent">
+        <number>0</number>
+       </property>
+       <property name="buddy">
+        <cstring>inZoom</cstring>
+       </property>
+      </widget>
+     </item>
+     <item row="1" column="1" colspan="4">
       <layout class="QHBoxLayout" name="horizontalLayout_2">
        <property name="spacing">
         <number>4</number>
@@ -191,6 +185,9 @@ font-size: 12px;
            <height>24</height>
           </size>
          </property>
+         <property name="toolTip">
+          <string><html><head/><body><p><span style=" font-weight:600;">Set zoom to 1:1</span></p><p>Set zoom level such that one screen pixel maps onto one image voxel. <span style=" font-style:italic;">When image voxels have different dimensions, the smallest of the three side lengths of the voxel is used.</span></p></body></html></string>
+         </property>
          <property name="styleSheet">
           <string notr="true"/>
          </property>
@@ -225,6 +222,9 @@ font-size: 12px;
            <height>0</height>
           </size>
          </property>
+         <property name="toolTip">
+          <string><html><head/><body><p><span style=" font-weight:600;">Set zoom to 2:1</span></p><p>Set zoom level such that two screen pixels map onto one image voxel. <span style=" font-style:italic;">When image voxels have different dimensions, the smallest of the three side lengths of the voxel is used.</span></p></body></html></string>
+         </property>
          <property name="text">
           <string>2x</string>
          </property>
@@ -244,6 +244,9 @@ font-size: 12px;
            <height>24</height>
           </size>
          </property>
+         <property name="toolTip">
+          <string><html><head/><body><p><span style=" font-weight:600;">Set zoom to 4:1</span></p><p>Set zoom level such that four screen pixels map onto one image voxel. <span style=" font-style:italic;">When image voxels have different dimensions, the smallest of the three side lengths of the voxel is used.</span></p></body></html></string>
+         </property>
          <property name="text">
           <string>4x</string>
          </property>
@@ -280,34 +283,39 @@ font-size: 12px;
       <property name="spacing">
        <number>2</number>
       </property>
-      <property name="margin">
+      <property name="leftMargin">
+       <number>0</number>
+      </property>
+      <property name="topMargin">
+       <number>0</number>
+      </property>
+      <property name="rightMargin">
+       <number>0</number>
+      </property>
+      <property name="bottomMargin">
        <number>0</number>
       </property>
      </layout>
     </widget>
    </item>
    <item>
-    <widget class="Line" name="line">
-     <property name="frameShadow">
-      <enum>QFrame::Plain</enum>
-     </property>
-     <property name="lineWidth">
-      <number>1</number>
-     </property>
-     <property name="midLineWidth">
-      <number>1</number>
-     </property>
-     <property name="orientation">
-      <enum>Qt::Horizontal</enum>
-     </property>
-    </widget>
-   </item>
-   <item>
-    <layout class="QVBoxLayout" name="verticalLayout_3"/>
-   </item>
-   <item>
     <widget class="QWidget" name="widget_2" native="true">
      <layout class="QVBoxLayout" name="verticalLayout_5">
+      <property name="spacing">
+       <number>8</number>
+      </property>
+      <property name="leftMargin">
+       <number>4</number>
+      </property>
+      <property name="topMargin">
+       <number>4</number>
+      </property>
+      <property name="rightMargin">
+       <number>4</number>
+      </property>
+      <property name="bottomMargin">
+       <number>4</number>
+      </property>
       <item>
        <widget class="QActionButton" name="btnResetViews">
         <property name="sizePolicy">
@@ -327,6 +335,9 @@ font-size: 12px;
           <pointsize>-1</pointsize>
          </font>
         </property>
+        <property name="toolTip">
+         <string><html><head/><body><p>Set the zoom level so that the image fully fits into the available screen space.</p></body></html></string>
+        </property>
         <property name="text">
          <string>Zoom to fit</string>
         </property>
@@ -345,6 +356,9 @@ font-size: 12px;
           <pointsize>-1</pointsize>
          </font>
         </property>
+        <property name="toolTip">
+         <string><html><head/><body><p>Pan so that the 3D cursor is positioned at the center of the orthogonal slice views</p></body></html></string>
+        </property>
         <property name="text">
          <string>Center on cursor</string>
         </property>
diff --git a/GUI/Qt/Coupling/QtAbstractItemViewCoupling.h b/GUI/Qt/Coupling/QtAbstractItemViewCoupling.h
index 1789c5d..1633474 100644
--- a/GUI/Qt/Coupling/QtAbstractItemViewCoupling.h
+++ b/GUI/Qt/Coupling/QtAbstractItemViewCoupling.h
@@ -24,7 +24,14 @@
 
 
 
-
+/**
+ * The default value traits for QAbstractItemView use the currentRow in the item view
+ * to represent a value. Each row is assigned a value of class TAtomic, and the value
+ * of the current row is considered to be the value of the widget.
+ *
+ * in other words, the model holds an item of type TAtomic and the widget selects a
+ * corresponding row in the widget
+ */
 template <class TAtomic>
 class DefaultWidgetValueTraits<TAtomic, QAbstractItemView>
     : public WidgetValueTraitsBase<TAtomic, QAbstractItemView *>
@@ -82,6 +89,79 @@ public:
 };
 
 
+/**
+ * An alternative value traits for QAbstractItemView uses the selection of all rows in
+ * the view to represent a value. Thus value here is map from an atomic type to boolean,
+ * where the boolean stores the selection state.
+ *
+ * Under this coupling, the model stores a list of on/off items, and the user can use
+ * multiple selection to modify this list.
+ */
+template<class TItemIndex>
+class DefaultWidgetValueTraits< std::map<TItemIndex, bool>, QAbstractItemView>
+    : public WidgetValueTraitsBase<std::map<TItemIndex, bool>, QAbstractItemView *>
+{
+public:
+  typedef std::map<TItemIndex, bool> AtomicType;
+
+  const char *GetSignal()
+  {
+    return SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &));
+  }
+
+  virtual QObject *GetSignalEmitter(QObject *w)
+  {
+    QAbstractItemView *view = dynamic_cast<QAbstractItemView *>(w);
+    return view ? view->selectionModel() : NULL;
+  }
+
+  void ScanValuesRecursive(QAbstractItemView *w, QModelIndex parent, AtomicType &result)
+  {
+    for(int i = 0; i < w->model()->rowCount(parent); i++)
+      {
+      QModelIndex index = w->model()->index(i, 0, parent);
+      TItemIndex val = w->model()->data(index, Qt::UserRole).value<TItemIndex>();
+      result[val] = w->selectionModel()->isSelected(index);
+      ScanValuesRecursive(w, index, result);
+      }
+  }
+
+  void SetValuesRecursive(QAbstractItemView *w, QModelIndex parent, const AtomicType &mapping)
+  {
+    for(int i = 0; i < w->model()->rowCount(parent); i++)
+      {
+      QModelIndex index = w->model()->index(i, 0, parent);
+      TItemIndex val = w->model()->data(index, Qt::UserRole).value<TItemIndex>();
+      typename AtomicType::const_iterator it = mapping.find(val);
+      if(it != mapping.end())
+        w->selectionModel()->select(index, it->second ? QItemSelectionModel::Select
+                                                      : QItemSelectionModel::Deselect);
+
+      SetValuesRecursive(w, index, mapping);
+      }
+  }
+
+  AtomicType GetValue(QAbstractItemView *w)
+  {
+    AtomicType value_map;
+    ScanValuesRecursive(w, QModelIndex(), value_map);
+    return value_map;
+  }
+
+  void SetValue(QAbstractItemView *w, const AtomicType &value)
+  {
+    // Find the item in the model
+    SetValuesRecursive(w, QModelIndex(), value);
+  }
+
+  void SetValueToNull(QAbstractItemView *w)
+  {
+    if(w->selectionModel())
+      w->selectionModel()->clear();
+  }
+};
+
+
 template <class TItemDomain, class TRowTraits>
 class QStandardItemModelWidgetDomainTraits :
     public WidgetDomainTraitsBase<TItemDomain, QAbstractItemView *>
diff --git a/GUI/Qt/Coupling/QtSliderCoupling.h b/GUI/Qt/Coupling/QtSliderCoupling.h
index 5b909db..8d0bec8 100644
--- a/GUI/Qt/Coupling/QtSliderCoupling.h
+++ b/GUI/Qt/Coupling/QtSliderCoupling.h
@@ -50,6 +50,11 @@ public:
   {
     w->setValue(static_cast<int>(value));
   }
+
+  virtual void SetValueToNull(QSlider *w)
+  {
+    w->setValue(w->minimum());
+  }
 };
 
 template <class TAtomic>
diff --git a/GUI/Qt/Coupling/QtWidgetCoupling.h b/GUI/Qt/Coupling/QtWidgetCoupling.h
index 5e855b9..3516dca 100644
--- a/GUI/Qt/Coupling/QtWidgetCoupling.h
+++ b/GUI/Qt/Coupling/QtWidgetCoupling.h
@@ -291,20 +291,27 @@ class WidgetBooleanNamedPropertyTraits
     : public WidgetValueTraitsBase<TAtomic, QObject *>
 {
 public:
-  WidgetBooleanNamedPropertyTraits(const char *propertyName)
-    : m_Property(propertyName) {}
+  WidgetBooleanNamedPropertyTraits(const char *propertyName, bool reverse)
+    : m_Property(propertyName), m_Reverse(reverse) {}
 
   virtual TAtomic GetValue(QObject *w)
   {
-    return qvariant_cast<TAtomic>(w->property(m_Property.c_str()));
+    if(m_Reverse)
+      return !qvariant_cast<TAtomic>(w->property(m_Property.c_str()));
+    else
+      return qvariant_cast<TAtomic>(w->property(m_Property.c_str()));
   }
   virtual void SetValue(QObject *w, const TAtomic &value)
   {
-    w->setProperty(m_Property.c_str(), value);
+    if(m_Reverse)
+      w->setProperty(m_Property.c_str(), !value);
+    else
+      w->setProperty(m_Property.c_str(), value);
   }
 
 protected:
   std::string m_Property;
+  bool m_Reverse;
 };
 
 
@@ -693,13 +700,13 @@ void makeMultiRowCoupling(TWidget *w,
 template <class TModel>
 void makeBooleanNamedPropertyCoupling(
     QObject *w, const char *propertyName,
-    TModel *model,
+    TModel *model, bool reverse = false,
     QtCouplingOptions opts = QtCouplingOptions())
 {
   // Create the traits for the property
   typedef typename TModel::ValueType ValueType;
   typedef WidgetBooleanNamedPropertyTraits<ValueType> TraitsType;
-  TraitsType traits(propertyName);
+  TraitsType traits(propertyName, reverse);
 
   // Call the main coupling method
   makeCoupling<TModel, QObject, TraitsType>(w, model, traits, opts);
@@ -710,10 +717,22 @@ void makeBooleanNamedPropertyCoupling(
  */
 template <class TModel>
 void makeWidgetVisibilityCoupling(
-    QWidget *w, TModel *model,
+    QWidget *w, TModel *model, bool reverse = false,
+    QtCouplingOptions opts = QtCouplingOptions())
+{
+  makeBooleanNamedPropertyCoupling(w, "visible", model, reverse, opts);
+}
+
+
+/**
+ * Couple the visibility of a widget to a boolean or integer-valued model
+ */
+template <class TModel>
+void makeActionVisibilityCoupling(
+    QAction *w, TModel *model, bool reverse = false,
     QtCouplingOptions opts = QtCouplingOptions())
 {
-  makeBooleanNamedPropertyCoupling(w, "visible", model, opts);
+  makeBooleanNamedPropertyCoupling(w, "visible", model, reverse, opts);
 }
 
 #endif // QTWIDGETCOUPLING_H
diff --git a/GUI/Qt/Resources/SNAPResources.qrc b/GUI/Qt/Resources/SNAPResources.qrc
index f11067a..f52d78c 100644
--- a/GUI/Qt/Resources/SNAPResources.qrc
+++ b/GUI/Qt/Resources/SNAPResources.qrc
@@ -106,10 +106,67 @@
         <file>open_22.png</file>
         <file>crosshair_cursor_bitmap.png</file>
         <file>crosshair_cursor_mask.png</file>
+        <file>icons8_undo-48.png</file>
+        <file>icons8_redo-48.png</file>
+        <file>icons8_refresh-48.png</file>
+        <file>icons8_pin-48.png</file>
+        <file>icons8_star-48.png</file>
+        <file>icons8_pin_12.png</file>
+        <file>icons8_star_12.png</file>
+        <file>icons8_pin_10.png</file>
+        <file>icons8_star_8.png</file>
+        <file>icons8_whitepin_16.png</file>
+        <file>context_gray_48.png</file>
+        <file>context_gray_16.png</file>
+        <file>context_gray_12.png</file>
+        <file>context_gray_12 at 2x.png</file>
+        <file>context_gray_10 at 2x.png</file>
+        <file>context_gray_10.png</file>
+        <file>icons8_pin_12 at 2x.png</file>
+        <file>icons8_unpin_12.png</file>
+        <file>icons8_unpin_12 at 2x.png</file>
+        <file>icons8_up_12 at x2.png</file>
+        <file>icons8_up_12.png</file>
+        <file>icons8_down_12 at x2.png</file>
+        <file>icons8_down_12.png</file>
+        <file>icons8_visible_12 at 2x.png</file>
+        <file>icons8_visible_12.png</file>
+        <file>icons8_invisible_12 at 2x.png</file>
+        <file>icons8_invisible_12.png</file>
+        <file>icons8_film_reel_12.png</file>
+        <file>icons8_film_reel_12 at 2x.png</file>
+        <file>layout_thumb_16.png</file>
+        <file>icons8_slr_camera_16 at 2x.png</file>
+        <file>icons8_slr_camera_16.png</file>
+        <file>icons8_slr_camera_12 at 2x.png</file>
+        <file>icons8_slr_camera_12.png</file>
+        <file>icons8_cursor_16 at 2x.png</file>
+        <file>icons8_cursor_16.png</file>
+        <file>icons8_ruler_16.png</file>
+        <file>icons8_ruler_16 at 2x.png</file>
+        <file>annotation_28.png</file>
+        <file>menu-arrow_8.png</file>
+        <file>menu-arrow_8 at 2x.png</file>
+        <file>icons8_generic_text_16.png</file>
+        <file>icons8_generic_text_16 at 2x.png</file>
+        <file>icons8_mouse_scrolling_16.png</file>
+        <file>icons8_mouse_scrolling_16 at 2x.png</file>
+        <file>icons8_mouse_right_click_16 at 2x.png</file>
+        <file>icons8_mouse_right_click_16.png</file>
+        <file>icons8_mouse_left_click_16 at 2x.png</file>
+        <file>icons8_mouse_left_click_16.png</file>
+        <file>icons8_palette_16 at 2x.png</file>
+        <file>icons8_palette_16.png</file>
+        <file>icons8_layers_16 at 2x.png</file>
+        <file>icons8_layers_16.png</file>
     </qresource>
     <qresource prefix="/snapres">
         <file>snapres/EdgeForcesExample.png</file>
         <file>snapres/RegionForcesExample.png</file>
         <file>snapres/SnakeParameterPreviewCurve.txt</file>
     </qresource>
+    <qresource prefix="/html">
+        <file alias="ModeTipTemplate">html/tooltips/ModeTipTemplate.html</file>
+        <file alias="TipTableRow">html/tooltips/TipTableRow.html</file>
+    </qresource>
 </RCC>
diff --git a/GUI/Qt/Resources/SNAPResources_Linux.qrc b/GUI/Qt/Resources/SNAPResources_Linux.qrc
new file mode 100644
index 0000000..807350d
--- /dev/null
+++ b/GUI/Qt/Resources/SNAPResources_Linux.qrc
@@ -0,0 +1,2 @@
+<RCC/>
+
diff --git a/GUI/Qt/Resources/SNAPResources_MacOS.qrc b/GUI/Qt/Resources/SNAPResources_MacOS.qrc
new file mode 100644
index 0000000..807350d
--- /dev/null
+++ b/GUI/Qt/Resources/SNAPResources_MacOS.qrc
@@ -0,0 +1,2 @@
+<RCC/>
+
diff --git a/GUI/Qt/Resources/SNAPResources_Windows.qrc b/GUI/Qt/Resources/SNAPResources_Windows.qrc
new file mode 100644
index 0000000..807350d
--- /dev/null
+++ b/GUI/Qt/Resources/SNAPResources_Windows.qrc
@@ -0,0 +1,2 @@
+<RCC/>
+
diff --git a/GUI/Qt/Resources/annotation_28.png b/GUI/Qt/Resources/annotation_28.png
new file mode 100644
index 0000000..98b00cd
Binary files /dev/null and b/GUI/Qt/Resources/annotation_28.png differ
diff --git a/GUI/Qt/Resources/context_gray_10.png b/GUI/Qt/Resources/context_gray_10.png
new file mode 100644
index 0000000..358285a
Binary files /dev/null and b/GUI/Qt/Resources/context_gray_10.png differ
diff --git a/GUI/Qt/Resources/context_gray_10 at 2x.png b/GUI/Qt/Resources/context_gray_10 at 2x.png
new file mode 100644
index 0000000..f2ac8b0
Binary files /dev/null and b/GUI/Qt/Resources/context_gray_10 at 2x.png differ
diff --git a/GUI/Qt/Resources/context_gray_12.png b/GUI/Qt/Resources/context_gray_12.png
new file mode 100644
index 0000000..bae0a49
Binary files /dev/null and b/GUI/Qt/Resources/context_gray_12.png differ
diff --git a/GUI/Qt/Resources/context_gray_12 at 2x.png b/GUI/Qt/Resources/context_gray_12 at 2x.png
new file mode 100644
index 0000000..3881cbd
Binary files /dev/null and b/GUI/Qt/Resources/context_gray_12 at 2x.png differ
diff --git a/GUI/Qt/Resources/context_gray_16.png b/GUI/Qt/Resources/context_gray_16.png
new file mode 100644
index 0000000..0aba006
Binary files /dev/null and b/GUI/Qt/Resources/context_gray_16.png differ
diff --git a/GUI/Qt/Resources/context_gray_48.png b/GUI/Qt/Resources/context_gray_48.png
new file mode 100644
index 0000000..4ac1fda
Binary files /dev/null and b/GUI/Qt/Resources/context_gray_48.png differ
diff --git a/GUI/Qt/Resources/html/tooltips/ModeTipTemplate.html b/GUI/Qt/Resources/html/tooltips/ModeTipTemplate.html
new file mode 100644
index 0000000..f07a543
--- /dev/null
+++ b/GUI/Qt/Resources/html/tooltips/ModeTipTemplate.html
@@ -0,0 +1,38 @@
+<html><head/>
+<body>
+<style>
+td.mod {
+  padding-left:5; padding-right:1; padding-top:0; padding-bottom:0;
+}
+td.left_click {
+  text-align:right;
+  padding-left:0; padding-right:6; padding-top:0; padding-bottom:0;
+}
+td.right_click {
+  text-align:right;
+  padding-left:0; padding-right:5; padding-top:0; padding-bottom:0;
+}
+td.scrolling {
+  text-align:right;
+  padding-left:0; padding-right:5; padding-top:0; padding-bottom:0;
+}
+td.rcol {
+  text-align:left;
+  padding-left:5; padding-right:5; padding-top:0; padding-bottom:0;
+}
+</style>
+<p><span style=" font-weight:600;">%1</span></p>
+<p>%2<br/></p>
+
+<table border="0" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px;" cellspacing="2" cellpadding="0">
+<!--
+<tr valign="middle">
+    <td rowspan="2"><u>Mouse Action</u></td>
+    <td></td>
+    <td class="rcol"><u>Operation</u></td>
+</tr>
+-->
+%3
+</table>
+</body>
+</html>
diff --git a/GUI/Qt/Resources/html/tooltips/TipTableRow.html b/GUI/Qt/Resources/html/tooltips/TipTableRow.html
new file mode 100644
index 0000000..83a6caf
--- /dev/null
+++ b/GUI/Qt/Resources/html/tooltips/TipTableRow.html
@@ -0,0 +1,6 @@
+<!-- Template for a row in the tooltip table of mouse commands -->
+<tr valign="middle">
+    <td class="mod" align="right">%3</td>
+    <td class="%1" align="right"><p><img src=":/root/icons8_mouse_%1_16.png"/></p></td>
+    <td class="rcol"><p>%2</p></td>
+</tr>
diff --git a/GUI/Qt/Resources/icons8_cursor_16.png b/GUI/Qt/Resources/icons8_cursor_16.png
new file mode 100644
index 0000000..dfc743b
Binary files /dev/null and b/GUI/Qt/Resources/icons8_cursor_16.png differ
diff --git a/GUI/Qt/Resources/icons8_cursor_16 at 2x.png b/GUI/Qt/Resources/icons8_cursor_16 at 2x.png
new file mode 100644
index 0000000..402af90
Binary files /dev/null and b/GUI/Qt/Resources/icons8_cursor_16 at 2x.png differ
diff --git a/GUI/Qt/Resources/icons8_down_12.png b/GUI/Qt/Resources/icons8_down_12.png
new file mode 100644
index 0000000..69219cf
Binary files /dev/null and b/GUI/Qt/Resources/icons8_down_12.png differ
diff --git a/GUI/Qt/Resources/icons8_down_12 at x2.png b/GUI/Qt/Resources/icons8_down_12 at x2.png
new file mode 100644
index 0000000..5d4079d
Binary files /dev/null and b/GUI/Qt/Resources/icons8_down_12 at x2.png differ
diff --git a/GUI/Qt/Resources/icons8_film_reel_12.png b/GUI/Qt/Resources/icons8_film_reel_12.png
new file mode 100644
index 0000000..243c2e2
Binary files /dev/null and b/GUI/Qt/Resources/icons8_film_reel_12.png differ
diff --git a/GUI/Qt/Resources/icons8_film_reel_12 at 2x.png b/GUI/Qt/Resources/icons8_film_reel_12 at 2x.png
new file mode 100644
index 0000000..af827c5
Binary files /dev/null and b/GUI/Qt/Resources/icons8_film_reel_12 at 2x.png differ
diff --git a/GUI/Qt/Resources/icons8_generic_text_16.png b/GUI/Qt/Resources/icons8_generic_text_16.png
new file mode 100644
index 0000000..457dec6
Binary files /dev/null and b/GUI/Qt/Resources/icons8_generic_text_16.png differ
diff --git a/GUI/Qt/Resources/icons8_generic_text_16 at 2x.png b/GUI/Qt/Resources/icons8_generic_text_16 at 2x.png
new file mode 100644
index 0000000..e963da4
Binary files /dev/null and b/GUI/Qt/Resources/icons8_generic_text_16 at 2x.png differ
diff --git a/GUI/Qt/Resources/icons8_invisible_12.png b/GUI/Qt/Resources/icons8_invisible_12.png
new file mode 100644
index 0000000..16362a1
Binary files /dev/null and b/GUI/Qt/Resources/icons8_invisible_12.png differ
diff --git a/GUI/Qt/Resources/icons8_invisible_12 at 2x.png b/GUI/Qt/Resources/icons8_invisible_12 at 2x.png
new file mode 100644
index 0000000..ff80e64
Binary files /dev/null and b/GUI/Qt/Resources/icons8_invisible_12 at 2x.png differ
diff --git a/GUI/Qt/Resources/icons8_layers_16.png b/GUI/Qt/Resources/icons8_layers_16.png
new file mode 100644
index 0000000..c1040c3
Binary files /dev/null and b/GUI/Qt/Resources/icons8_layers_16.png differ
diff --git a/GUI/Qt/Resources/icons8_layers_16 at 2x.png b/GUI/Qt/Resources/icons8_layers_16 at 2x.png
new file mode 100644
index 0000000..f9ccfc3
Binary files /dev/null and b/GUI/Qt/Resources/icons8_layers_16 at 2x.png differ
diff --git a/GUI/Qt/Resources/icons8_mouse_left_click_16.png b/GUI/Qt/Resources/icons8_mouse_left_click_16.png
new file mode 100644
index 0000000..b09bc17
Binary files /dev/null and b/GUI/Qt/Resources/icons8_mouse_left_click_16.png differ
diff --git a/GUI/Qt/Resources/icons8_mouse_left_click_16 at 2x.png b/GUI/Qt/Resources/icons8_mouse_left_click_16 at 2x.png
new file mode 100644
index 0000000..7b39cf2
Binary files /dev/null and b/GUI/Qt/Resources/icons8_mouse_left_click_16 at 2x.png differ
diff --git a/GUI/Qt/Resources/icons8_mouse_right_click_16.png b/GUI/Qt/Resources/icons8_mouse_right_click_16.png
new file mode 100644
index 0000000..10d72fc
Binary files /dev/null and b/GUI/Qt/Resources/icons8_mouse_right_click_16.png differ
diff --git a/GUI/Qt/Resources/icons8_mouse_right_click_16 at 2x.png b/GUI/Qt/Resources/icons8_mouse_right_click_16 at 2x.png
new file mode 100644
index 0000000..c6675bf
Binary files /dev/null and b/GUI/Qt/Resources/icons8_mouse_right_click_16 at 2x.png differ
diff --git a/GUI/Qt/Resources/icons8_mouse_scrolling_16.png b/GUI/Qt/Resources/icons8_mouse_scrolling_16.png
new file mode 100644
index 0000000..af39e8f
Binary files /dev/null and b/GUI/Qt/Resources/icons8_mouse_scrolling_16.png differ
diff --git a/GUI/Qt/Resources/icons8_mouse_scrolling_16 at 2x.png b/GUI/Qt/Resources/icons8_mouse_scrolling_16 at 2x.png
new file mode 100644
index 0000000..acd6bb2
Binary files /dev/null and b/GUI/Qt/Resources/icons8_mouse_scrolling_16 at 2x.png differ
diff --git a/GUI/Qt/Resources/icons8_palette_16.png b/GUI/Qt/Resources/icons8_palette_16.png
new file mode 100644
index 0000000..b4ab838
Binary files /dev/null and b/GUI/Qt/Resources/icons8_palette_16.png differ
diff --git a/GUI/Qt/Resources/icons8_palette_16 at 2x.png b/GUI/Qt/Resources/icons8_palette_16 at 2x.png
new file mode 100644
index 0000000..cf4e49f
Binary files /dev/null and b/GUI/Qt/Resources/icons8_palette_16 at 2x.png differ
diff --git a/GUI/Qt/Resources/icons8_pin-48.png b/GUI/Qt/Resources/icons8_pin-48.png
new file mode 100755
index 0000000..100616e
Binary files /dev/null and b/GUI/Qt/Resources/icons8_pin-48.png differ
diff --git a/GUI/Qt/Resources/icons8_pin_10.png b/GUI/Qt/Resources/icons8_pin_10.png
new file mode 100644
index 0000000..582e860
Binary files /dev/null and b/GUI/Qt/Resources/icons8_pin_10.png differ
diff --git a/GUI/Qt/Resources/icons8_pin_12.png b/GUI/Qt/Resources/icons8_pin_12.png
new file mode 100644
index 0000000..15a749f
Binary files /dev/null and b/GUI/Qt/Resources/icons8_pin_12.png differ
diff --git a/GUI/Qt/Resources/icons8_pin_12 at 2x.png b/GUI/Qt/Resources/icons8_pin_12 at 2x.png
new file mode 100644
index 0000000..b2ff892
Binary files /dev/null and b/GUI/Qt/Resources/icons8_pin_12 at 2x.png differ
diff --git a/GUI/Qt/Resources/icons8_redo-48.png b/GUI/Qt/Resources/icons8_redo-48.png
new file mode 100755
index 0000000..9f0878b
Binary files /dev/null and b/GUI/Qt/Resources/icons8_redo-48.png differ
diff --git a/GUI/Qt/Resources/icons8_refresh-48.png b/GUI/Qt/Resources/icons8_refresh-48.png
new file mode 100755
index 0000000..e73deee
Binary files /dev/null and b/GUI/Qt/Resources/icons8_refresh-48.png differ
diff --git a/GUI/Qt/Resources/icons8_ruler_16.png b/GUI/Qt/Resources/icons8_ruler_16.png
new file mode 100644
index 0000000..e1ba7a6
Binary files /dev/null and b/GUI/Qt/Resources/icons8_ruler_16.png differ
diff --git a/GUI/Qt/Resources/icons8_ruler_16 at 2x.png b/GUI/Qt/Resources/icons8_ruler_16 at 2x.png
new file mode 100644
index 0000000..6353cda
Binary files /dev/null and b/GUI/Qt/Resources/icons8_ruler_16 at 2x.png differ
diff --git a/GUI/Qt/Resources/icons8_slr_camera_12.png b/GUI/Qt/Resources/icons8_slr_camera_12.png
new file mode 100644
index 0000000..5cc5b73
Binary files /dev/null and b/GUI/Qt/Resources/icons8_slr_camera_12.png differ
diff --git a/GUI/Qt/Resources/icons8_slr_camera_12 at 2x.png b/GUI/Qt/Resources/icons8_slr_camera_12 at 2x.png
new file mode 100644
index 0000000..2522b6c
Binary files /dev/null and b/GUI/Qt/Resources/icons8_slr_camera_12 at 2x.png differ
diff --git a/GUI/Qt/Resources/icons8_slr_camera_16.png b/GUI/Qt/Resources/icons8_slr_camera_16.png
new file mode 100644
index 0000000..86ae193
Binary files /dev/null and b/GUI/Qt/Resources/icons8_slr_camera_16.png differ
diff --git a/GUI/Qt/Resources/icons8_slr_camera_16 at 2x.png b/GUI/Qt/Resources/icons8_slr_camera_16 at 2x.png
new file mode 100644
index 0000000..214a9ca
Binary files /dev/null and b/GUI/Qt/Resources/icons8_slr_camera_16 at 2x.png differ
diff --git a/GUI/Qt/Resources/icons8_star-48.png b/GUI/Qt/Resources/icons8_star-48.png
new file mode 100755
index 0000000..1fb42f5
Binary files /dev/null and b/GUI/Qt/Resources/icons8_star-48.png differ
diff --git a/GUI/Qt/Resources/icons8_star_12.png b/GUI/Qt/Resources/icons8_star_12.png
new file mode 100644
index 0000000..b73eb6c
Binary files /dev/null and b/GUI/Qt/Resources/icons8_star_12.png differ
diff --git a/GUI/Qt/Resources/icons8_star_8.png b/GUI/Qt/Resources/icons8_star_8.png
new file mode 100644
index 0000000..f8bdbdb
Binary files /dev/null and b/GUI/Qt/Resources/icons8_star_8.png differ
diff --git a/GUI/Qt/Resources/icons8_undo-48.png b/GUI/Qt/Resources/icons8_undo-48.png
new file mode 100755
index 0000000..de27149
Binary files /dev/null and b/GUI/Qt/Resources/icons8_undo-48.png differ
diff --git a/GUI/Qt/Resources/icons8_unpin_12.png b/GUI/Qt/Resources/icons8_unpin_12.png
new file mode 100644
index 0000000..18d25cb
Binary files /dev/null and b/GUI/Qt/Resources/icons8_unpin_12.png differ
diff --git a/GUI/Qt/Resources/icons8_unpin_12 at 2x.png b/GUI/Qt/Resources/icons8_unpin_12 at 2x.png
new file mode 100644
index 0000000..8f16cd2
Binary files /dev/null and b/GUI/Qt/Resources/icons8_unpin_12 at 2x.png differ
diff --git a/GUI/Qt/Resources/icons8_up_12.png b/GUI/Qt/Resources/icons8_up_12.png
new file mode 100644
index 0000000..9fb6ee1
Binary files /dev/null and b/GUI/Qt/Resources/icons8_up_12.png differ
diff --git a/GUI/Qt/Resources/icons8_up_12 at x2.png b/GUI/Qt/Resources/icons8_up_12 at x2.png
new file mode 100644
index 0000000..d079733
Binary files /dev/null and b/GUI/Qt/Resources/icons8_up_12 at x2.png differ
diff --git a/GUI/Qt/Resources/icons8_visible_12.png b/GUI/Qt/Resources/icons8_visible_12.png
new file mode 100644
index 0000000..7731469
Binary files /dev/null and b/GUI/Qt/Resources/icons8_visible_12.png differ
diff --git a/GUI/Qt/Resources/icons8_visible_12 at 2x.png b/GUI/Qt/Resources/icons8_visible_12 at 2x.png
new file mode 100644
index 0000000..8257e54
Binary files /dev/null and b/GUI/Qt/Resources/icons8_visible_12 at 2x.png differ
diff --git a/GUI/Qt/Resources/icons8_whitepin_16.png b/GUI/Qt/Resources/icons8_whitepin_16.png
new file mode 100644
index 0000000..1355b21
Binary files /dev/null and b/GUI/Qt/Resources/icons8_whitepin_16.png differ
diff --git a/GUI/Qt/Resources/layout_thumb_16.png b/GUI/Qt/Resources/layout_thumb_16.png
new file mode 100644
index 0000000..4a79823
Binary files /dev/null and b/GUI/Qt/Resources/layout_thumb_16.png differ
diff --git a/GUI/Qt/Resources/menu-arrow_8.png b/GUI/Qt/Resources/menu-arrow_8.png
new file mode 100644
index 0000000..01750f6
Binary files /dev/null and b/GUI/Qt/Resources/menu-arrow_8.png differ
diff --git a/GUI/Qt/Resources/menu-arrow_8 at 2x.png b/GUI/Qt/Resources/menu-arrow_8 at 2x.png
new file mode 100644
index 0000000..84b32d0
Binary files /dev/null and b/GUI/Qt/Resources/menu-arrow_8 at 2x.png differ
diff --git a/GUI/Qt/Resources/source/annotation_28.graffle b/GUI/Qt/Resources/source/annotation_28.graffle
new file mode 100644
index 0000000..d9285bd
Binary files /dev/null and b/GUI/Qt/Resources/source/annotation_28.graffle differ
diff --git a/GUI/Qt/View/AnnotationInteractionMode.cxx b/GUI/Qt/View/AnnotationInteractionMode.cxx
new file mode 100644
index 0000000..987662c
--- /dev/null
+++ b/GUI/Qt/View/AnnotationInteractionMode.cxx
@@ -0,0 +1,137 @@
+#include "AnnotationInteractionMode.h"
+#include "AnnotationRenderer.h"
+#include "AnnotationModel.h"
+#include "GenericSliceView.h"
+#include "SliceViewPanel.h"
+
+AnnotationInteractionMode::AnnotationInteractionMode(GenericSliceView *parent)
+  : SliceWindowInteractionDelegateWidget(parent)
+{
+  m_Renderer = AnnotationRenderer::New();
+  m_Renderer->SetParentRenderer(
+        static_cast<GenericSliceRenderer *>(parent->GetRenderer()));
+  m_Model = NULL;
+
+  m_ParentPanel = dynamic_cast<SliceViewPanel *>(m_ParentView->parent());
+}
+
+AnnotationInteractionMode::~AnnotationInteractionMode()
+{
+
+}
+
+void AnnotationInteractionMode::SetModel(AnnotationModel *model)
+{
+  m_Model = model;
+  m_Renderer->SetModel(model);
+  SetParentModel(model->GetParent());
+
+  connectITK(m_Model, StateMachineChangeEvent());
+  connectITK(m_Model, ModelUpdateEvent());
+}
+
+#include <QInputDialog>
+#include "SNAPQtCommon.h"
+
+void AnnotationInteractionMode::mousePressEvent(QMouseEvent *ev)
+{
+  ev->ignore();
+  if(ev->button() == Qt::LeftButton)
+    {
+    if(m_Model->ProcessPushEvent(m_XSlice, ev->modifiers() == Qt::ShiftModifier))
+      ev->accept();
+
+    if(m_Model->IsMovingSelection())
+      m_ParentPanel->setCursor(Qt::ClosedHandCursor);
+    }
+}
+
+void AnnotationInteractionMode::mouseMoveEvent(QMouseEvent *ev)
+{
+  ev->ignore();
+
+  // Nothing is pressed
+  if(this->isHovering())
+    {
+    if(m_Model->ProcessMoveEvent(m_XSlice, false, false))
+      ev->accept();
+
+    if(m_Model->GetAnnotationMode() == ANNOTATION_SELECT && m_Model->IsHoveringOverAnnotation(m_XSlice))
+      {
+      m_ParentPanel->setCursor(Qt::OpenHandCursor);
+      }
+    else
+      {
+      m_ParentPanel->setCursor(Qt::ArrowCursor);
+      }
+    }
+
+  // Left press was accepted
+  else if(this->isDragging())
+    {
+    if(m_Model->ProcessMoveEvent(m_XSlice, ev->modifiers() == Qt::ShiftModifier, true))
+      ev->accept();
+    }
+}
+
+#include <QTimer>
+
+void AnnotationInteractionMode::mouseReleaseEvent(QMouseEvent *ev)
+{
+  SliceViewPanel *panel = dynamic_cast<SliceViewPanel *>(m_ParentView->parent());
+  ev->ignore();
+
+  if(ev->button() == Qt::LeftButton)
+    {
+    if(m_Model->ProcessReleaseEvent(m_XSlice, ev->modifiers() == Qt::ShiftModifier))
+      {
+      ev->accept();
+
+      // If the user is done drawing the text annotation arrow
+      if(m_Model->GetAnnotationMode() == ANNOTATION_LANDMARK && m_Model->GetFlagDrawingLine() == false)
+        QTimer::singleShot(1, this, SLOT(onTextInputRequested()));
+
+      else if(m_Model->GetAnnotationMode() == ANNOTATION_RULER && m_Model->GetFlagDrawingLine() == false)
+        m_Model->AcceptLine();
+      }
+
+    // Handle cursor changes
+    if(m_Model->GetAnnotationMode() == ANNOTATION_SELECT)
+      {
+      if(m_Model->IsHoveringOverAnnotation(m_XSlice))
+        {
+        panel->setCursor(Qt::OpenHandCursor);
+        }
+      else
+        {
+        panel->setCursor(Qt::ArrowCursor);
+        }
+      }
+    }
+}
+
+void AnnotationInteractionMode::onAcceptAction()
+{
+  m_Model->AcceptLine();
+}
+
+void AnnotationInteractionMode::onModelUpdate(const EventBucket &bucket)
+{
+  this->update();
+}
+
+void AnnotationInteractionMode::onTextInputRequested()
+{
+  // Special handling in text annotation mode
+  bool ok;
+  QString text = QInputDialog::getText(this, "Text Annotation", "Enter annotation text:", QLineEdit::Normal,
+                                       QString(), &ok);
+  if(ok && text.length())
+    {
+    m_Model->SetCurrentAnnotationText(to_utf8(text));
+    m_Model->AcceptLine();
+    }
+}
+
+
+
diff --git a/GUI/Qt/View/AnnotationInteractionMode.h b/GUI/Qt/View/AnnotationInteractionMode.h
new file mode 100644
index 0000000..65cac08
--- /dev/null
+++ b/GUI/Qt/View/AnnotationInteractionMode.h
@@ -0,0 +1,45 @@
+#ifndef ANNOTATIONINTERACTIONMODE_H
+#define ANNOTATIONINTERACTIONMODE_H
+
+#include <SliceWindowInteractionDelegateWidget.h>
+#include <SNAPCommon.h>
+
+class GenericSliceModel;
+class GenericSliceView;
+class AnnotationModel;
+class AnnotationRenderer;
+class SliceViewPanel;
+
+class AnnotationInteractionMode : public SliceWindowInteractionDelegateWidget
+{
+  Q_OBJECT
+
+public:
+  explicit AnnotationInteractionMode(GenericSliceView *parent = 0);
+  ~AnnotationInteractionMode();
+
+  irisGetMacro(Model, AnnotationModel *)
+  void SetModel(AnnotationModel *model);
+
+  irisGetMacro(Renderer, AnnotationRenderer *)
+
+  void mousePressEvent(QMouseEvent *ev);
+  void mouseMoveEvent(QMouseEvent *ev);
+  void mouseReleaseEvent(QMouseEvent *ev);
+
+public slots:
+
+  void onAcceptAction();
+
+  void onModelUpdate(const EventBucket &bucket);
+
+  void onTextInputRequested();
+
+protected:
+
+  AnnotationModel *m_Model;
+  SmartPtr<AnnotationRenderer> m_Renderer;
+  SliceViewPanel *m_ParentPanel;
+};
+
+#endif // ANNOTATIONINTERACTIONMODE_H
diff --git a/GUI/Qt/View/CrosshairsInteractionMode.cxx b/GUI/Qt/View/CrosshairsInteractionMode.cxx
index 62af551..f1e30b2 100644
--- a/GUI/Qt/View/CrosshairsInteractionMode.cxx
+++ b/GUI/Qt/View/CrosshairsInteractionMode.cxx
@@ -39,7 +39,7 @@ CrosshairsInteractionMode::CrosshairsInteractionMode(GenericSliceView *parent) :
   // Create the renderer
   m_Renderer = CrosshairsRenderer::New();
   m_Renderer->SetParentRenderer(
-        static_cast<GenericSliceRenderer *>(parent->GetRenderer()));
+          static_cast<GenericSliceRenderer *>(parent->GetRenderer()));
 
 
   m_WheelEventTarget = NULL;
@@ -47,6 +47,7 @@ CrosshairsInteractionMode::CrosshairsInteractionMode(GenericSliceView *parent) :
 
   SetMouseButtonBehaviorToCrosshairsMode();
   setAttribute(Qt::WA_AcceptTouchEvents, true);
+
 }
 
 CrosshairsInteractionMode::~CrosshairsInteractionMode()
@@ -70,6 +71,23 @@ void CrosshairsInteractionMode
   m_BtnPan = Qt::LeftButton;
 }
 
+Qt::MouseButton
+CrosshairsInteractionMode
+::GetButtonForEvent(QMouseEvent *ev)
+{
+  if(ev->button() == Qt::RightButton)
+    return Qt::RightButton;
+  if(ev->button() == Qt::MidButton)
+    return Qt::MidButton;
+  else if(ev->button() == Qt::LeftButton && ev->modifiers() == Qt::ControlModifier)
+    return Qt::RightButton;
+  else if(ev->button() == Qt::LeftButton && ev->modifiers() == Qt::AltModifier)
+    return Qt::MidButton;
+  else if(ev->button() == Qt::LeftButton)
+    return Qt::LeftButton;
+  else return Qt::NoButton;
+}
+
 void CrosshairsInteractionMode
 ::SetModel(OrthogonalSliceCursorNavigationModel *model)
 {
@@ -80,21 +98,32 @@ void CrosshairsInteractionMode
 
 void CrosshairsInteractionMode::mousePressEvent(QMouseEvent *ev)
 {
-  // Use model to envoke event
-  if(ev->button() == m_BtnCursor)
-    {
-    m_Model->UpdateCursor(Vector2f(m_XSpace[0], m_XSpace[1]));
-    }
-  else if(ev->button() == m_BtnZoom)
-    {
-    m_Model->BeginZoom();
-    }
-  else if(ev->button() == m_BtnPan)
+  // Get the button after emulation
+  Qt::MouseButton btn = this->GetButtonForEvent(ev);
+
+  // We have to be careful to check that the event landed in the
+  // region corresponding to an image view and not to a thumbnail
+  if(this->IsMouseOverFullLayer())
     {
-    m_Model->BeginPan();
+    // Use model to envoke event
+    if(btn == m_BtnCursor)
+      {
+      m_Model->UpdateCursor(Vector2f(m_XSpace[0], m_XSpace[1]));
+      }
+    else if(btn == m_BtnZoom)
+      {
+      m_Model->BeginZoom();
+      }
+    else if(btn == m_BtnPan)
+      {
+      m_Model->BeginPan();
+      }
+
+    // Eat this event
+    ev->accept();
     }
-  // Eat this event
-  ev->accept();
+
+  m_LastPressEmulatedButton = btn;
 }
 
 void CrosshairsInteractionMode::mouseMoveEvent(QMouseEvent *ev)
@@ -103,16 +132,16 @@ void CrosshairsInteractionMode::mouseMoveEvent(QMouseEvent *ev)
     {
     Vector3d dx = m_XSpace - m_LastPressXSpace;
 
-    if(m_LastPressButton == m_BtnCursor)
+    if(m_LastPressEmulatedButton == m_BtnCursor)
       {
       m_Model->UpdateCursor(Vector2f(m_XSpace[0], m_XSpace[1]));
       }
-    else if(m_LastPressButton == m_BtnZoom)
+    else if(m_LastPressEmulatedButton == m_BtnZoom)
       {
       double scaleFactor = pow(1.02, dx(1));
       m_Model->ProcessZoomGesture(scaleFactor);
       }
-    else if(m_LastPressButton == m_BtnPan)
+    else if(m_LastPressEmulatedButton == m_BtnPan)
       {
       m_Model->ProcessPanGesture(Vector2f(dx(0), dx(1)));
       }
@@ -129,21 +158,31 @@ void CrosshairsInteractionMode::mouseMoveEvent(QMouseEvent *ev)
 
 void CrosshairsInteractionMode::mouseReleaseEvent(QMouseEvent *ev)
 {
+  // Get the button after emulation
+  Qt::MouseButton btn = this->GetButtonForEvent(ev);
 
-  if(ev->button() == m_BtnCursor)
-    {
-    m_Model->UpdateCursor(Vector2f(m_XSpace[0], m_XSpace[1]));
-    }
-  else if(ev->button() == m_BtnZoom)
+  if(isDragging())
     {
-    m_Model->EndZoom();
+      if(btn == m_BtnCursor)
+      {
+      m_Model->UpdateCursor(Vector2f(m_XSpace[0], m_XSpace[1]));
+      }
+    else if(btn == m_BtnZoom)
+      {
+      m_Model->EndZoom();
+      }
+    else if(btn == m_BtnPan)
+      {
+      m_Model->EndPan();
+      }
+
+    // Eat this event
+    ev->accept();
     }
-  else if(ev->button() == m_BtnPan)
+  else
     {
-    m_Model->EndPan();
+    ev->ignore();
     }
-  // Eat this event
-  ev->accept();
 }
 
 bool CrosshairsInteractionMode::gestureEvent(QGestureEvent *ev)
@@ -256,7 +295,52 @@ void CrosshairsInteractionMode::wheelEvent(QWheelEvent *event)
   int scrollLines = QApplication::wheelScrollLines();
   QApplication::setWheelScrollLines(1);
 
-  if(m_WheelEventTarget)
+  // Special case - when the user uses shift, we scroll in time, not in Z!
+  if(event->modifiers() == Qt::ShiftModifier)
+    {
+    bool isThumb;
+    ImageWrapperBase *layer =
+        m_Model->GetParent()->GetContextLayerAtPosition(
+          event->pos().x(),
+          m_Model->GetParent()->GetSizeReporter()->GetLogicalViewportSize()[1] - event->pos().y(),
+        isThumb);
+
+    if(layer && layer->GetNumberOfComponents() > 1)
+      {
+      AbstractMultiChannelDisplayMappingPolicy *dpolicy =
+          static_cast<AbstractMultiChannelDisplayMappingPolicy *>(layer->GetDisplayMapping());
+
+      // Get the current display mode
+      MultiChannelDisplayMode mode = dpolicy->GetDisplayMode();
+
+      // Mode must be single component
+      if(!mode.UseRGB && mode.SelectedScalarRep == SCALAR_REP_COMPONENT)
+        {
+        static double delta_accum = 0.0;
+
+#if QT_VERSION >= 0x050000
+        delta_accum += event->angleDelta().x() + event->angleDelta().y();
+#else
+        delta_accum += event->delta();
+#endif
+
+        if(delta_accum <= -120.0 || delta_accum >= 120.0)
+          {
+          mode.SelectedComponent += (int) (delta_accum / 120.0);
+          delta_accum = 0.0;
+          }
+
+        if(mode.SelectedComponent < 0)
+          mode.SelectedComponent = 0;
+        else if(mode.SelectedComponent >= layer->GetNumberOfComponents())
+          mode.SelectedComponent = layer->GetNumberOfComponents()-1;
+        dpolicy->SetDisplayMode(mode);
+        }
+      event->accept();
+      }
+    }
+
+  else if(m_WheelEventTarget)
     {
     QWheelEvent evnew(
           event->pos(), event->globalPos(), event->delta(),
diff --git a/GUI/Qt/View/CrosshairsInteractionMode.h b/GUI/Qt/View/CrosshairsInteractionMode.h
index 7be68bf..1d6eb54 100644
--- a/GUI/Qt/View/CrosshairsInteractionMode.h
+++ b/GUI/Qt/View/CrosshairsInteractionMode.h
@@ -80,6 +80,10 @@ protected:
 
   // Widget to which wheel events are forwarded
   QWidget *m_WheelEventTarget;
+
+  // Internal used to emulate right/middle button
+  Qt::MouseButton GetButtonForEvent(QMouseEvent *ev);
+  Qt::MouseButton m_LastPressEmulatedButton;
 };
 
 #endif // CROSSHAIRSINTERACTIONMODE_H
diff --git a/GUI/Qt/View/GenericSliceView.cxx b/GUI/Qt/View/GenericSliceView.cxx
index 34646c0..eb57acf 100644
--- a/GUI/Qt/View/GenericSliceView.cxx
+++ b/GUI/Qt/View/GenericSliceView.cxx
@@ -27,6 +27,13 @@
 #include "GenericSliceView.h"
 #include "CrosshairsInteractionMode.h"
 #include "LatentITKEventNotifier.h"
+#include <MainImageWindow.h>
+#include <LayerInspectorDialog.h>
+#include <GenericImageData.h>
+#include <QMenu>
+#include <SNAPQtCommon.h>
+#include <GlobalUIModel.h>
+#include <LayerSelectionModel.h>
 #include "QtReporterDelegates.h"
 
 GenericSliceView::GenericSliceView(QWidget *parent) :
diff --git a/GUI/Qt/View/PaintbrushInteractionMode.cxx b/GUI/Qt/View/PaintbrushInteractionMode.cxx
index da67fb0..425aaf4 100644
--- a/GUI/Qt/View/PaintbrushInteractionMode.cxx
+++ b/GUI/Qt/View/PaintbrushInteractionMode.cxx
@@ -33,7 +33,7 @@ void PaintbrushInteractionMode::mousePressEvent(QMouseEvent *ev)
   bool isright = (ev->button() == Qt::RightButton);
   if(isleft || isright)
     {
-    if(m_Model->ProcessPushEvent(to_float(m_XSlice),isright))
+    if(m_Model->ProcessPushEvent(to_float(m_XSlice),this->m_LastPressLayoutCell, isright))
       ev->accept();
     }
 }
@@ -42,7 +42,7 @@ void PaintbrushInteractionMode::mouseMoveEvent(QMouseEvent *ev)
 {
   ev->ignore();
 
-  if(isDragging())
+  if(this->isDragging())
     {
     if(m_Model->ProcessDragEvent(
          to_float(m_XSlice), to_float(m_LastPressXSlice),
@@ -51,7 +51,7 @@ void PaintbrushInteractionMode::mouseMoveEvent(QMouseEvent *ev)
       ev->accept();
       }
     }
-  else
+  else if(this->isHovering())
     {
     if(m_Model->ProcessMouseMoveEvent(to_float(m_XSlice)))
       ev->accept();
diff --git a/GUI/Qt/View/PolygonDrawingInteractionMode.cxx b/GUI/Qt/View/PolygonDrawingInteractionMode.cxx
index 201f368..906eea0 100644
--- a/GUI/Qt/View/PolygonDrawingInteractionMode.cxx
+++ b/GUI/Qt/View/PolygonDrawingInteractionMode.cxx
@@ -81,14 +81,12 @@ void PolygonDrawingInteractionMode::mousePressEvent(QMouseEvent *ev)
 void PolygonDrawingInteractionMode::mouseMoveEvent(QMouseEvent *ev)
 {
   ev->ignore();
-  if(m_LeftDown)
+  if(this->m_LeftStatus == PRESS_ACCEPTED)
     {
     if(m_Model->ProcessDragEvent(m_XSlice(0), m_XSlice(1)))
-      {
       ev->accept();
-      }
     }
-  else if (!isDragging())
+  else if (this->isHovering())
     {
     if(m_Model->ProcessMouseMoveEvent(m_XSlice(0), m_XSlice(1)))
       {
diff --git a/GUI/Qt/View/QtAbstractOpenGLBox.cxx b/GUI/Qt/View/QtAbstractOpenGLBox.cxx
index 730cd59..7bdc867 100644
--- a/GUI/Qt/View/QtAbstractOpenGLBox.cxx
+++ b/GUI/Qt/View/QtAbstractOpenGLBox.cxx
@@ -27,7 +27,6 @@
 #include "QtAbstractOpenGLBox.h"
 #include <QMouseEvent>
 #include <QStackedLayout>
-#include <QWindow>
 #include <QtInteractionDelegateWidget.h>
 #include "LatentITKEventNotifier.h"
 #include "SNAPOpenGL.h"
@@ -40,10 +39,13 @@
 #include "GLToPNG.h"
 
 QtAbstractOpenGLBox::QtAbstractOpenGLBox(QWidget *parent) :
-    QGLWidget(parent)
+    QOpenGLWidget(parent)
 {
   m_NeedResizeOnNextRepaint = false;
   m_GrabFocusOnEntry = false;
+
+  this->setAttribute(Qt::WA_OpaquePaintEvent);
+  this->setAttribute(Qt::WA_NoSystemBackground);
 }
 
 void QtAbstractOpenGLBox::AttachSingleDelegate(QtInteractionDelegateWidget *delegate)
@@ -79,13 +81,13 @@ void QtAbstractOpenGLBox::paintGL()
   GetRenderer()->Update();
 
   // Get width and height in pixels
-  int wp = (int) this->size().width() * this->windowHandle()->devicePixelRatio();
-  int hp = (int) this->size().height() * this->windowHandle()->devicePixelRatio();
+  int wp = (int) this->size().width() * this->devicePixelRatio();
+  int hp = (int) this->size().height() * this->devicePixelRatio();
 
   // Qt bug workaround
   if(m_NeedResizeOnNextRepaint)
     {
-    GetRenderer()->resizeGL(wp, hp);
+    GetRenderer()->resizeGL(wp, hp, this->devicePixelRatio());
     m_NeedResizeOnNextRepaint = false;
     }
 
@@ -112,8 +114,11 @@ void QtAbstractOpenGLBox::paintGL()
 
 void QtAbstractOpenGLBox::resizeGL(int w, int h)
 {
+  int wp = (int) this->size().width() * this->devicePixelRatio();
+  int hp = (int) this->size().height() * this->devicePixelRatio();
+
   GetRenderer()->Update();
-  GetRenderer()->resizeGL(w, h);
+  GetRenderer()->resizeGL(wp, hp, this->devicePixelRatio());
 }
 
 void QtAbstractOpenGLBox::initializeGL()
@@ -122,6 +127,7 @@ void QtAbstractOpenGLBox::initializeGL()
   GetRenderer()->initializeGL();
 }
 
+/*
 void QtAbstractOpenGLBox::resizeEvent(QResizeEvent *)
 {
   // This is a workaround for a Qt bug. It didn't take long to find bugs
@@ -133,7 +139,7 @@ void QtAbstractOpenGLBox::resizeEvent(QResizeEvent *)
   for(int i = 0; i < kids.size(); i++)
     kids.at(i)->setGeometry(this->geometry());
 }
-
+*/
 
 void QtAbstractOpenGLBox::enterEvent(QEvent *)
 {
diff --git a/GUI/Qt/View/QtAbstractOpenGLBox.h b/GUI/Qt/View/QtAbstractOpenGLBox.h
index 223ba5a..696f901 100644
--- a/GUI/Qt/View/QtAbstractOpenGLBox.h
+++ b/GUI/Qt/View/QtAbstractOpenGLBox.h
@@ -27,9 +27,9 @@
 #ifndef QTABSTRACTOPENGLBOX_H
 #define QTABSTRACTOPENGLBOX_H
 
-#include <QGLWidget>
 #include <SNAPCommon.h>
 #include <SNAPEvents.h>
+#include <QtGlobal>
 
 class QMouseEvent;
 class EventBucket;
@@ -38,7 +38,15 @@ class AbstractRenderer;
 
 namespace itk { class Object; }
 
-class QtAbstractOpenGLBox : public QGLWidget
+// Qt 4 compatibility
+#if QT_VERSION >= 0x050000
+  #include <QOpenGLWidget>
+#else
+  #include <QGLWidget>
+  #define QOpenGLWidget QGLWidget
+#endif
+
+class QtAbstractOpenGLBox : public QOpenGLWidget
 {
   Q_OBJECT
 
@@ -83,7 +91,7 @@ protected:
   virtual void initializeGL();
 
   // Resize event
-  virtual void resizeEvent(QResizeEvent *);
+  // virtual void resizeEvent(QResizeEvent *);
   virtual void enterEvent(QEvent *);
   virtual void leaveEvent(QEvent *);
 
@@ -96,6 +104,11 @@ protected:
   // Whether a screenshot has been requested (non-empty string)
   QString m_ScreenshotRequest;
 
+#if QT_VERSION < 0x050000
+  float devicePixelRatio() const { return 1.0f; }
+#endif
+
+
 signals:
 
 public slots:
diff --git a/GUI/Qt/View/QtInteractionDelegateWidget.cxx b/GUI/Qt/View/QtInteractionDelegateWidget.cxx
index 588f5c3..4c4d5f7 100644
--- a/GUI/Qt/View/QtInteractionDelegateWidget.cxx
+++ b/GUI/Qt/View/QtInteractionDelegateWidget.cxx
@@ -34,9 +34,10 @@
 QtInteractionDelegateWidget::QtInteractionDelegateWidget(QWidget *parent) :
   SNAPComponent(parent)
 {
-  m_LeftDown = false;
-  m_MiddleDown = false;
-  m_RightDown = false;
+  m_LeftStatus = NOT_PRESSED;
+  m_RightStatus = NOT_PRESSED;
+  m_MiddleStatus = NOT_PRESSED;
+
   m_Filtering = false;
 
   // The widget is hidden
@@ -45,6 +46,8 @@ QtInteractionDelegateWidget::QtInteractionDelegateWidget(QWidget *parent) :
 
 bool QtInteractionDelegateWidget::event(QEvent *ev)
 {
+  bool result;
+
   // If the event was sent to the widget itself, ignore it. The delegate
   // only should receive events through the sender
   if(!m_Filtering)
@@ -55,8 +58,14 @@ bool QtInteractionDelegateWidget::event(QEvent *ev)
 
   // Deal with gesture events
   if(ev->type() == QEvent::Gesture)
-    return gestureEvent(static_cast<QGestureEvent*>(ev));
-  else return QWidget::event(ev);
+    result = gestureEvent(static_cast<QGestureEvent*>(ev));
+  else
+    result = QWidget::event(ev);
+
+  // Set the dragging information
+  postprocessEvent(ev);
+
+  return result;
 }
 
 QtAbstractOpenGLBox * QtInteractionDelegateWidget::GetParentGLWidget() const
@@ -95,33 +104,43 @@ void QtInteractionDelegateWidget::preprocessEvent(QEvent *ev)
     // Compute the spatial location of the event
     QMouseEvent *emouse = static_cast<QMouseEvent *>(ev);
     m_XSpace = this->GetEventWorldCoordinates(emouse, true);
+    }
+}
 
-    // If a mouse press, back up this info for drag tracking
-    if(ev->type() == QEvent::MouseButtonPress)
+void QtInteractionDelegateWidget::postprocessEvent(QEvent *ev)
+{
+  QMouseEvent *emouse = static_cast<QMouseEvent *>(ev);
+
+  if(ev->type() == QEvent::MouseButtonPress)
+    {
+    ButtonStatus status = PRESS_IGNORED;
+    if(ev->isAccepted())
       {
       m_LastPressPos = emouse->pos();
       m_LastPressGlobalPos = emouse->globalPos();
       m_LastPressButton = emouse->button();
       m_LastPressXSpace = m_XSpace;
-
-      // Store what buttons are up or down
-      if(emouse->button() == Qt::LeftButton)
-        m_LeftDown = true;
-      if(emouse->button() == Qt::RightButton)
-        m_RightDown = true;
-      if(emouse->button() == Qt::MiddleButton)
-        m_MiddleDown = true;
-      }
-    else if(ev->type() == QEvent::MouseButtonRelease)
-      {
-      // Store what buttons are up or down
-      if(emouse->button() == Qt::LeftButton)
-        m_LeftDown = false;
-      if(emouse->button() == Qt::RightButton)
-        m_RightDown = false;
-      if(emouse->button() == Qt::MiddleButton)
-        m_MiddleDown = false;
+      status = PRESS_ACCEPTED;
       }
+
+    // Store what buttons are up or down
+    if(emouse->button() == Qt::LeftButton)
+      m_LeftStatus = status;
+    if(emouse->button() == Qt::RightButton)
+      m_RightStatus = status;
+    if(emouse->button() == Qt::MiddleButton)
+      m_MiddleStatus = status;
+    }
+
+  else if (ev->type() == QEvent::MouseButtonRelease)
+    {
+    // Store what buttons are up or down
+    if(emouse->button() == Qt::LeftButton)
+      m_LeftStatus = NOT_PRESSED;
+    if(emouse->button() == Qt::RightButton)
+      m_RightStatus = NOT_PRESSED;
+    if(emouse->button() == Qt::MiddleButton)
+      m_MiddleStatus = NOT_PRESSED;
     }
 }
 
@@ -145,8 +164,8 @@ QtInteractionDelegateWidget
   int ly = (flipY) ? parent->height() - 1 - ev->y() : ev->y();
 
   // Scale to actual pixels for the unproject call
-  double px = lx * parent->window()->devicePixelRatio();
-  double py = ly * parent->window()->devicePixelRatio();
+  double px = lx * this->devicePixelRatio();
+  double py = ly * this->devicePixelRatio();
 
   // Unproject to get the coordinate of the event
   Vector3d xProjection;
@@ -156,6 +175,22 @@ QtInteractionDelegateWidget
   return xProjection;
 }
 
+bool QtInteractionDelegateWidget::isDragging()
+{
+  return
+      m_LeftStatus == PRESS_ACCEPTED ||
+      m_RightStatus == PRESS_ACCEPTED ||
+      m_MiddleStatus == PRESS_ACCEPTED;
+}
+
+bool QtInteractionDelegateWidget::isHovering()
+{
+  return
+      m_LeftStatus == NOT_PRESSED &&
+      m_RightStatus == NOT_PRESSED &&
+      m_MiddleStatus == NOT_PRESSED;
+}
+
 double QtInteractionDelegateWidget::GetNumberOfPixelsMoved(QMouseEvent *ev)
 {
   QPoint delta = ev->pos() - m_LastPressPos;
diff --git a/GUI/Qt/View/QtInteractionDelegateWidget.h b/GUI/Qt/View/QtInteractionDelegateWidget.h
index 0123b10..89085d0 100644
--- a/GUI/Qt/View/QtInteractionDelegateWidget.h
+++ b/GUI/Qt/View/QtInteractionDelegateWidget.h
@@ -59,6 +59,8 @@ protected:
   // but should call QtInteractionDelegateWidget::preprocessEvent in there.
   virtual void preprocessEvent(QEvent *);
 
+  virtual void postprocessEvent(QEvent *);
+
   // Get the world coordinates of the Qt event. The default implementation uses
   // the current GL viewport, projection and model matrices of the parent GL
   // widget.
@@ -68,8 +70,16 @@ protected:
   virtual bool gestureEvent(QGestureEvent *ev)
     { return false; }
 
-  virtual bool isDragging()
-    { return m_LeftDown || m_RightDown || m_MiddleDown; }
+  /**
+   * Returns true when at least one mouse button is down and the corresponding
+   * press event was accepted by the widget
+   */
+  virtual bool isDragging();
+
+  /**
+   * Returns true if none of the mouse buttons are pressed.
+   */
+  virtual bool isHovering();
 
   // Return the number of pixels moved since last press
   double GetNumberOfPixelsMoved(QMouseEvent *ev);
@@ -84,13 +94,18 @@ protected:
   // Spatial coordinates of the last press event, current event
   Vector3d m_LastPressXSpace, m_XSpace;
 
+  // Status for a mouse button
+  enum ButtonStatus {
+    NOT_PRESSED = 0,      // The button is not pressed
+    PRESS_ACCEPTED,       // The button is pressed and press was accepted (dragging)
+    PRESS_IGNORED         // The button is pressed and press was ignored
+  };
+
   // Whether we are between a press and a release for a particular button
-  bool m_LeftDown, m_RightDown, m_MiddleDown;
+  ButtonStatus m_LeftStatus, m_RightStatus, m_MiddleStatus;
 
   // Whether we are currently filtering an event from another widget
   bool m_Filtering;
-
-
 };
 
 #endif // QTINTERACTIONDELEGATEWIDGET_H
diff --git a/GUI/Qt/View/QtVTKInteractionDelegateWidget.cxx b/GUI/Qt/View/QtVTKInteractionDelegateWidget.cxx
index a70b7a7..19f23ef 100644
--- a/GUI/Qt/View/QtVTKInteractionDelegateWidget.cxx
+++ b/GUI/Qt/View/QtVTKInteractionDelegateWidget.cxx
@@ -2,7 +2,6 @@
 #include "vtkRenderWindowInteractor.h"
 #include "QtAbstractOpenGLBox.h"
 #include <QApplication>
-#include <QWindow>
 
 QtVTKInteractionDelegateWidget::QtVTKInteractionDelegateWidget(QWidget *parent) :
     QtInteractionDelegateWidget(parent)
@@ -14,8 +13,8 @@ void QtVTKInteractionDelegateWidget::SetVTKEventState(QMouseEvent *ev)
   Qt::KeyboardModifiers km = QApplication::keyboardModifiers();
 
   // Account for Retina displays
-  int x = ev->pos().x() * this->windowHandle()->devicePixelRatio();
-  int y = ev->pos().y() * this->windowHandle()->devicePixelRatio();
+  int x = ev->pos().x() * this->devicePixelRatio();
+  int y = ev->pos().y() * this->devicePixelRatio();
 
   m_VTKInteractor->SetEventInformationFlipY(
         x, y, 
diff --git a/GUI/Qt/View/QtVTKRenderWindowBox.cxx b/GUI/Qt/View/QtVTKRenderWindowBox.cxx
index b5d792a..2306616 100644
--- a/GUI/Qt/View/QtVTKRenderWindowBox.cxx
+++ b/GUI/Qt/View/QtVTKRenderWindowBox.cxx
@@ -3,6 +3,14 @@
 #include "QtVTKInteractionDelegateWidget.h"
 #include "vtkRenderWindow.h"
 #include "vtkCommand.h"
+#include "QtReporterDelegates.h"
+
+#if QT_VERSION >= 0x050000
+  #include <QOpenGLContext>
+#else
+  #include <QGLContext>
+  #define QOpenGLContext QGLContext
+#endif
 
 QtVTKRenderWindowBox::QtVTKRenderWindowBox(QWidget *parent) :
   QtSimpleOpenGLBox(parent)
@@ -19,6 +27,8 @@ void QtVTKRenderWindowBox::SetRenderer(AbstractRenderer *renderer)
     {
     // Hook up the interaction delegate
     m_InteractionDelegate->SetVTKInteractor(renvtk->GetRenderWindowInteractor());
+
+    // Create a size reporter
     }
 
   // Hook up context-related events (is this needed?)
@@ -34,6 +44,7 @@ void QtVTKRenderWindowBox::SetRenderer(AbstractRenderer *renderer)
   QtSimpleOpenGLBox::SetRenderer(renderer);
 }
 
+
 void
 QtVTKRenderWindowBox
 ::RendererCallback(
@@ -46,7 +57,7 @@ QtVTKRenderWindowBox
   else if(event == vtkCommand::WindowIsCurrentEvent)
     {
     bool *result = static_cast<bool *>(data);
-    *result = QGLContext::currentContext() == this->context();
+    *result = QOpenGLContext::currentContext() == this->context();
     }
 }
 
diff --git a/GUI/Qt/View/SliceWindowInteractionDelegateWidget.cxx b/GUI/Qt/View/SliceWindowInteractionDelegateWidget.cxx
index 21df2fa..d971e34 100644
--- a/GUI/Qt/View/SliceWindowInteractionDelegateWidget.cxx
+++ b/GUI/Qt/View/SliceWindowInteractionDelegateWidget.cxx
@@ -26,22 +26,53 @@ void SliceWindowInteractionDelegateWidget::preprocessEvent(QEvent *ev)
   if(ev->type() == QEvent::MouseButtonPress ||
      ev->type() == QEvent::MouseButtonRelease ||
      ev->type() == QEvent::MouseMove ||
-     ev->type() == QEvent::MouseButtonDblClick)
+     ev->type() == QEvent::MouseButtonDblClick ||
+     ev->type() == QEvent::ContextMenu)
     {
     // Compute the spatial location of the event
     m_XSlice = to_double(m_ParentModel->MapWindowToSlice(
                            to_float(Vector2d(m_XSpace.extract(2)))));
 
-    // If a mouse press, back up this info for drag tracking
-    if(ev->type() == QEvent::MouseButtonPress)
-      {
-      m_LastPressXSlice = m_XSlice;
-      }
+    // Determine whether the mouse is over a layer, and if so what layer it is, and
+    // whether the layer is shown as a thumbnail or not
+    QPoint pos;
+    if(dynamic_cast<QMouseEvent *>(ev))
+      pos = dynamic_cast<QMouseEvent *>(ev)->pos();
+    else if(dynamic_cast<QContextMenuEvent *>(ev))
+      pos = dynamic_cast<QContextMenuEvent *>(ev)->pos();
+
+    Vector2i x(pos.x(),
+               m_ParentModel->GetSizeReporter()->GetLogicalViewportSize()[1] - pos.y());
+
+    // The hovered over layer is stored in m_HoverOverLayer
+    m_HoverOverLayer =
+        m_ParentModel->GetContextLayerAtPosition(x[0], x[1], m_HoverOverLayerIsThumbnail);
+    }
+}
+
+void SliceWindowInteractionDelegateWidget::postprocessEvent(QEvent *ev)
+{
+  QtInteractionDelegateWidget::postprocessEvent(ev);
+  if(ev->type() == QEvent::MouseButtonPress && ev->isAccepted())
+    {
+    m_LastPressXSlice = m_XSlice;
     }
+  m_HoverOverLayer = NULL;
 }
 
+bool SliceWindowInteractionDelegateWidget::IsMouseOverLayerThumbnail()
+{
+  return m_HoverOverLayer != NULL && m_HoverOverLayerIsThumbnail;
+}
+
+bool SliceWindowInteractionDelegateWidget::IsMouseOverFullLayer()
+{
+  return m_HoverOverLayer != NULL && !m_HoverOverLayerIsThumbnail;
+}
+
+
+
 #include <QDebug>
-#include <QWindow>
 
 Vector3d
 SliceWindowInteractionDelegateWidget
@@ -52,9 +83,9 @@ SliceWindowInteractionDelegateWidget
   parent->makeCurrent();
 
   // Get the x,y coordinates of the event in actual pixels (retina)
-  int xpix = (int) ev->x() * parent->windowHandle()->devicePixelRatio();
-  int ypix = (int) ev->y() * parent->windowHandle()->devicePixelRatio();
-  int hpix = (int) parent->height() * parent->windowHandle()->devicePixelRatio();
+  int xpix = (int) ev->x() * this->devicePixelRatio();
+  int ypix = (int) ev->y() * this->devicePixelRatio();
+  int hpix = (int) parent->height() * this->devicePixelRatio();
   int x = xpix;
   int y = (flipY) ? hpix - 1 - ypix : ypix;
 
@@ -91,7 +122,8 @@ SliceWindowInteractionDelegateWidget
 
   // Convert the event coordinates into the model view coordinates
   double modelMatrix[16], projMatrix[16];
-  GLint viewport[] = { icol * sz[0], (nrows - 1 - irow) * sz[1], sz[0], sz[1] };
+  // GLint viewport[] = { icol * sz[0], (nrows - 1 - irow) * sz[1], sz[0], sz[1] };
+  GLint viewport[] = { 0, 0, ncols * sz[0], nrows * sz[1] };
   glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
   glGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
 
@@ -101,5 +133,10 @@ SliceWindowInteractionDelegateWidget
                modelMatrix,projMatrix,viewport,
                &xProjection[0], &xProjection[1], &xProjection[2]);
 
+  // Get the within-cell coordinates by subtracting the corner of the cell
+  xProjection[0] -= icol * m_ParentModel->GetSize()[0];
+  xProjection[1] -= flipY
+                    ? ((nrows - 1) - irow) * m_ParentModel->GetSize()[1]
+                    : irow * m_ParentModel->GetSize()[1];
   return xProjection;
 }
diff --git a/GUI/Qt/View/SliceWindowInteractionDelegateWidget.h b/GUI/Qt/View/SliceWindowInteractionDelegateWidget.h
index 55887ae..f3eb392 100644
--- a/GUI/Qt/View/SliceWindowInteractionDelegateWidget.h
+++ b/GUI/Qt/View/SliceWindowInteractionDelegateWidget.h
@@ -4,6 +4,7 @@
 #include <QtInteractionDelegateWidget.h>
 
 class GenericSliceView;
+class ImageWrapperBase;
 
 class SliceWindowInteractionDelegateWidget : public QtInteractionDelegateWidget
 {
@@ -26,6 +27,12 @@ protected:
   // The cell in which the last press was generated
   Vector2ui m_LastPressLayoutCell;
 
+  // Whether the current position of the mouse corresponds to a layer
+  ImageWrapperBase *m_HoverOverLayer;
+
+  // Whether the layer that is hovered over is displayed as a thumbnail
+  bool m_HoverOverLayerIsThumbnail;
+
   // Parent model
   GenericSliceModel *m_ParentModel;
 
@@ -33,7 +40,10 @@ protected:
   GenericSliceView *m_ParentView;
 
   void preprocessEvent(QEvent *ev);
+  void postprocessEvent(QEvent *ev);
 
+  bool IsMouseOverLayerThumbnail();
+  bool IsMouseOverFullLayer();
 };
 
 #endif // SLICEWINDOWINTERACTIONDELEGATEWIDGET_H
diff --git a/GUI/Qt/View/SnakeROIInteractionMode.cxx b/GUI/Qt/View/SnakeROIInteractionMode.cxx
index b669477..12e83c4 100644
--- a/GUI/Qt/View/SnakeROIInteractionMode.cxx
+++ b/GUI/Qt/View/SnakeROIInteractionMode.cxx
@@ -34,30 +34,35 @@ void SnakeROIInteractionMode::mousePressEvent(QMouseEvent *ev)
 void SnakeROIInteractionMode::mouseMoveEvent(QMouseEvent *ev)
 {
   ev->ignore();
-  if(m_LeftDown)
+  if(this->m_LeftStatus == PRESS_ACCEPTED)
     {
     if(m_Model->ProcessDragEvent(
          m_XSlice[0], m_XSlice[1],
          m_LastPressXSlice[0], m_LastPressXSlice[1], false))
-      {
       ev->accept();
-      }
     }
-  else if(!isDragging())
+  else if(this->isHovering())
     {
     if(m_Model->ProcessMoveEvent(m_XSlice[0], m_XSlice[1]))
-      {
       ev->accept();
-      }
     }
 }
 
 void SnakeROIInteractionMode::mouseReleaseEvent(QMouseEvent *ev)
 {
-  if(m_Model->ProcessDragEvent(
-       m_XSlice[0], m_XSlice[1],
-       m_LastPressXSlice[0], m_LastPressXSlice[1], true))
-    ev->accept();
+  ev->ignore();
+  if(this->m_LeftStatus == PRESS_ACCEPTED)
+    {
+    if(m_Model->ProcessDragEvent(
+         m_XSlice[0], m_XSlice[1],
+         m_LastPressXSlice[0], m_LastPressXSlice[1], true))
+      ev->accept();
+    }
+  else if(this->isHovering())
+    {
+    if(m_Model->ProcessMoveEvent(m_XSlice[0], m_XSlice[1]))
+      ev->accept();
+    }
 }
 
 #include <SliceViewPanel.h>
diff --git a/GUI/Qt/View/ThumbnailInteractionMode.cxx b/GUI/Qt/View/ThumbnailInteractionMode.cxx
index 21e493e..eabcb10 100644
--- a/GUI/Qt/View/ThumbnailInteractionMode.cxx
+++ b/GUI/Qt/View/ThumbnailInteractionMode.cxx
@@ -26,12 +26,24 @@
 
 #include "OrthogonalSliceCursorNavigationModel.h"
 #include "ThumbnailInteractionMode.h"
+#include "GenericSliceModel.h"
+#include "IRISApplication.h"
+#include "GlobalState.h"
 #include <QMouseEvent>
+#include <MainImageWindow.h>
+#include <LayerInspectorDialog.h>
+#include <GenericImageData.h>
+#include <QMenu>
+#include <SNAPQtCommon.h>
+#include "GenericSliceView.h"
+#include "SliceViewPanel.h"
+
 
 ThumbnailInteractionMode::ThumbnailInteractionMode(GenericSliceView *parent) :
     SliceWindowInteractionDelegateWidget(parent)
 {
-
+  connect(this, SIGNAL(customContextMenuRequested(QPoint)),
+          this, SLOT(onContextMenuRequested(QPoint)));
 }
 
 void ThumbnailInteractionMode
@@ -40,43 +52,66 @@ void ThumbnailInteractionMode
   m_Model = model;
   m_PanFlag = false;
   this->SetParentModel(model->GetParent());
+
+  connectITK(m_Model->GetParent()->GetDriver()->GetGlobalState()->GetSelectedLayerIdModel(),
+             ValueChangedEvent());
 }
 
 
 void ThumbnailInteractionMode::mousePressEvent(QMouseEvent *ev)
 {
+  // Position of the press in real screen pixels (not logical)
+  float vppr = m_ParentModel->GetSizeReporter()->GetViewportPixelRatio();
+  Vector2ui vpsize = m_ParentModel->GetSizeReporter()->GetViewportSize();
+
   // Press position in screen pixels
-  Vector2i x(ev->pos().x(), this->height() - ev->pos().y());
+  Vector2i x((int)(ev->pos().x() * vppr),
+             (int)(vpsize[1] - ev->pos().y() * vppr));
 
   // Only react to left mouse button presses
-  if(ev->button() == Qt::LeftButton && m_Model->CheckThumbnail(x))
+  if(ev->button() == Qt::LeftButton && m_Model->CheckZoomThumbnail(x))
     {
     m_PanFlag = true;
     m_Model->BeginPan();
     ev->accept();
     }
+
+  // Check for layer thumbnail hit.
+  else if(this->IsMouseOverLayerThumbnail() && ev->button() == Qt::LeftButton)
+    {
+    if(!this->m_HoverOverLayer->IsSticky())
+      m_Model->GetParent()->GetDriver()->GetGlobalState()->SetSelectedLayerId(
+            this->m_HoverOverLayer->GetUniqueId());
+    ev->accept();
+    }
 }
 
 void ThumbnailInteractionMode::mouseMoveEvent(QMouseEvent *ev)
 {
-  // Press position in screen pixels
-  Vector2i x(ev->pos().x(), this->height() - ev->pos().y());
+  // If we are hovering over an image, it nice to indicate that to the user by
+  // highlighting the image.
+  if(this->m_HoverOverLayer != NULL)
+    {
+    m_Model->GetParent()->SetHoveredImageLayerId(this->m_HoverOverLayer->GetUniqueId());
+    m_Model->GetParent()->SetHoveredImageIsThumbnail(this->m_HoverOverLayerIsThumbnail);
+    }
+  else
+    {
+    m_Model->GetParent()->SetHoveredImageLayerId(-1ul);
+    m_Model->GetParent()->SetHoveredImageIsThumbnail(false);
+    }
 
   ev->ignore();
   if(m_PanFlag)
     {
-    Vector2i dx(ev->pos().x() - m_LastPressPos.x(),
-                - (ev->pos().y() - m_LastPressPos.y()));
+    // The event reports coordinates in logical pixels, but the thumbnail is defined
+    // in physical units. So we need to deal with vppr
+    float vppr = m_ParentModel->GetSizeReporter()->GetViewportPixelRatio();
+    Vector2i dx((int) vppr * (ev->pos().x() - m_LastPressPos.x()),
+                (int) vppr * (- (ev->pos().y() - m_LastPressPos.y())));
     m_Model->ProcessThumbnailPanGesture(-dx);
     ev->accept();
     }
-  else if(!isDragging() && m_Model->CheckThumbnail(x))
-    {
-    // When the view is responding to hover events, we want to consume
-    // mouse hovering that occurs over the thumbnail. Otherwise the user
-    // would not see the effect of the hovering
-    ev->accept();
-    }
 }
 
 void ThumbnailInteractionMode::mouseReleaseEvent(QMouseEvent *ev)
@@ -87,4 +122,58 @@ void ThumbnailInteractionMode::mouseReleaseEvent(QMouseEvent *ev)
   m_PanFlag = false;
 }
 
+void ThumbnailInteractionMode::contextMenuEvent(QContextMenuEvent *ev)
+{
+  if(this->IsMouseOverLayerThumbnail())
+    {
+    emit customContextMenuRequested(ev->pos());
+    ev->accept();
+    }
+}
+
+void ThumbnailInteractionMode::onContextMenuRequested(const QPoint &pt)
+{
+  if(this->IsMouseOverLayerThumbnail())
+    {
+    // Instead of creating a separate context menu here, we use a context menu
+    // from the corresponding row in the LayerInspector.
+    MainImageWindow *winmain = findParentWidget<MainImageWindow>(this);
+    LayerInspectorDialog *inspector = winmain->GetLayerInspector();
+
+    // Get the menu
+    QMenu *menu = inspector->GetLayerContextMenu(this->m_HoverOverLayer);
+
+    // Show the menu
+    if(menu)
+      menu->popup(QCursor::pos());
+    }
+}
+
+void ThumbnailInteractionMode::onModelUpdate(const EventBucket &bucket)
+{
+  if(bucket.HasEvent(ValueChangedEvent(),
+                     m_Model->GetParent()->GetDriver()->GetGlobalState()->GetSelectedLayerIdModel()))
+    {
+    m_Model->GetParent()->SetHoveredImageLayerId(-1ul);
+    m_Model->GetParent()->SetHoveredImageIsThumbnail(false);
+    }
+}
+
+void ThumbnailInteractionMode::enterEvent(QEvent *)
+{
+  // TODO: this is hideous!
+  SliceViewPanel *panel = dynamic_cast<SliceViewPanel *>(m_ParentView->parent());
+  panel->SetMouseMotionTracking(true);
+}
+
+void ThumbnailInteractionMode::leaveEvent(QEvent *)
+{
+  SliceViewPanel *panel = dynamic_cast<SliceViewPanel *>(m_ParentView->parent());
+  panel->SetMouseMotionTracking(false);
+
+  m_Model->GetParent()->SetHoveredImageLayerId(-1ul);
+  m_Model->GetParent()->SetHoveredImageIsThumbnail(false);
+}
+
+
 
diff --git a/GUI/Qt/View/ThumbnailInteractionMode.h b/GUI/Qt/View/ThumbnailInteractionMode.h
index ee298cf..f2ecb61 100644
--- a/GUI/Qt/View/ThumbnailInteractionMode.h
+++ b/GUI/Qt/View/ThumbnailInteractionMode.h
@@ -43,6 +43,14 @@ public:
   void mousePressEvent(QMouseEvent *ev);
   void mouseMoveEvent(QMouseEvent *);
   void mouseReleaseEvent(QMouseEvent *);
+  void contextMenuEvent(QContextMenuEvent *ev);
+  void enterEvent(QEvent *);
+  void leaveEvent(QEvent *);
+
+public slots:
+
+  void onContextMenuRequested(const QPoint &pt);
+  virtual void onModelUpdate(const EventBucket &bucket);
 
 private:
 
diff --git a/GUI/Qt/Windows/AboutDialog.ui b/GUI/Qt/Windows/AboutDialog.ui
index cc49381..72adb9b 100644
--- a/GUI/Qt/Windows/AboutDialog.ui
+++ b/GUI/Qt/Windows/AboutDialog.ui
@@ -14,6 +14,22 @@
    <string>About ITK-SNAP</string>
   </property>
   <layout class="QGridLayout" name="gridLayout" rowstretch="0,1,0" columnstretch="0,1">
+   <item row="0" column="1">
+    <widget class="SplashPanel" name="widget" native="true"/>
+   </item>
+   <item row="2" column="0" colspan="2">
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Close</set>
+     </property>
+     <property name="centerButtons">
+      <bool>false</bool>
+     </property>
+    </widget>
+   </item>
    <item row="1" column="0" colspan="2">
     <widget class="QTabWidget" name="tabWidget">
      <property name="styleSheet">
@@ -45,17 +61,17 @@
           <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
 <html><head><meta name="qrichtext" content="1" /><style type="text/css">
 p, li { white-space: pre-wrap; }
-</style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;">
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; text-decoration: underline;">ITK-SNAP 3.x Team (2011 - Present)</span></p>
-<p style=" margin-top:6px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Paul A. Yushkevich (University of Pennsylvania) - PI and Lead Developer <br />Guido Gerig (University of Utah) - Co-PI <br />Octavian Soldea (University of Pennsylvania) - Developer <br />Yang Gao (University of Utah) - Developer <br />Supported by the U.S. National Institute of Biomedical Imaging and BioEngineering through grant  [...]
-<p style=" margin-top:14px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; text-decoration: underline;">ITK-SNAP 2.x Team (2004 - 2012)</span></p>
-<p style=" margin-top:6px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Paul A. Yushkevich (University of Pennsylvania) - Lead Developer <br />Hui Zhang (University of Pennsylvania) - Developer <br />Casey Goodlett (University of Utah) - Contributor <br />Timothy Burke - Contributor <br />Nicholas Tustison - Contributor <br />Supported by the U.S. National Institute of Biomedical Imaging and Bio [...]
-<p style=" margin-top:14px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; text-decoration: underline;">SNAP/ITK Integration (2003-2004)</span></p>
-<p style=" margin-top:6px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Paul A. Yushkevich (University of Pennsylvania) - Technical Director <br />Daniel S. Fritsch - Contract PI <br />Guido Gerig (University of Utah) - Scientific Director <br />Stephen R. Aylward (Kitware) - Consultant <br />Supported by the U.S. National Library of Medicine through PO 467-MZ-202446-1 </p>
-<p style=" margin-top:14px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; text-decoration: underline;">Original SNAP/IRIS Team (199x - 2003)</span></p>
-<p style=" margin-top:6px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Guido Gerig (University of Utah) - Scientific Director <br />Silvio Turello, Joachim Schlegel, Gabor Szekely (ETH Zurich) - Original AVS Module <br />Chris Wynn, Arun Neelamkavil, David Gregg, Eric Larsen, Sanjay Sthapit (UNC Chapel Hill) - IRIS 1999 Project <br />Sean Ho, Ashraf Farrag, Amy Henderson, Robin Munesato, Ming Yu (UNC Chape [...]
-<p style=" margin-top:14px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; text-decoration: underline;">Special Thanks</span></p>
-<p style=" margin-top:6px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Terry S. Yoo (NLM) <br />Zohara Cohen (NIBIB) <br />Luis Ibanez (Kitware) <br />Joshua Cates (University of Utah) <br />James C. Gee (University of Pennsylvania) <br />All who generously contribute to ITK, VTK, FLTK, and SNAP </p></body></html></string>
+</style></head><body style=" font-family:'.Helvetica Neue DeskInterface'; font-size:13pt; font-weight:400; font-style:normal;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande'; font-weight:600; text-decoration: underline;">ITK-SNAP 3.x Team (2011 - Present)</span></p>
+<p style=" margin-top:6px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande';">Paul A. Yushkevich (University of Pennsylvania) - PI and Lead Developer <br />Guido Gerig (University of Utah) - Co-PI <br />Octavian Soldea (University of Pennsylvania) - Developer <br />Yang Gao (University of Utah) - Developer <br />Supported by the U.S. National Insti [...]
+<p style=" margin-top:14px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande'; font-weight:600; text-decoration: underline;">ITK-SNAP 2.x Team (2004 - 2012)</span></p>
+<p style=" margin-top:6px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande';">Paul A. Yushkevich (University of Pennsylvania) - Lead Developer <br />Hui Zhang (University of Pennsylvania) - Developer <br />Casey Goodlett (University of Utah) - Contributor <br />Timothy Burke - Contributor <br />Nicholas Tustison - Contributor <br />Supported  [...]
+<p style=" margin-top:14px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande'; font-weight:600; text-decoration: underline;">SNAP/ITK Integration (2003-2004)</span></p>
+<p style=" margin-top:6px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande';">Paul A. Yushkevich (University of Pennsylvania) - Technical Director <br />Daniel S. Fritsch - Contract PI <br />Guido Gerig (University of Utah) - Scientific Director <br />Stephen R. Aylward (Kitware) - Consultant <br />Supported by the U.S. National Library of Medicine [...]
+<p style=" margin-top:14px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande'; font-weight:600; text-decoration: underline;">Original SNAP/IRIS Team (199x - 2003)</span></p>
+<p style=" margin-top:6px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande';">Guido Gerig (University of Utah) - Scientific Director <br />Silvio Turello, Joachim Schlegel, Gabor Szekely (ETH Zurich) - Original AVS Module <br />Chris Wynn, Arun Neelamkavil, David Gregg, Eric Larsen, Sanjay Sthapit (UNC Chapel Hill) - IRIS 1999 Project <br />Sean Ho, Ashr [...]
+<p style=" margin-top:14px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande'; font-weight:600; text-decoration: underline;">Special Thanks</span></p>
+<p style=" margin-top:6px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande';">Terry S. Yoo (NLM) <br />Zohara Cohen (NIBIB) <br />Luis Ibanez (Kitware) <br />Joshua Cates (University of Utah) <br />James C. Gee (University of Pennsylvania) <br />All who generously contribute to ITK, VTK, FLTK, and SNAP </span></p></body>< [...]
          </property>
         </widget>
        </item>
@@ -83,6 +99,42 @@ p, li { white-space: pre-wrap; }
        </item>
       </layout>
      </widget>
+     <widget class="QWidget" name="tab_5">
+      <attribute name="title">
+       <string>Algorithms</string>
+      </attribute>
+      <layout class="QVBoxLayout" name="verticalLayout_5">
+       <property name="leftMargin">
+        <number>8</number>
+       </property>
+       <property name="topMargin">
+        <number>4</number>
+       </property>
+       <property name="rightMargin">
+        <number>8</number>
+       </property>
+       <property name="bottomMargin">
+        <number>8</number>
+       </property>
+       <item>
+        <widget class="QTextBrowser" name="ouAlgorithms">
+         <property name="html">
+          <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'.Helvetica Neue DeskInterface'; font-size:13pt; font-weight:400; font-style:normal;">
+<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; text-decoration: underline;">Active Contour Segmentation</span></p>
+<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Caselles, V., Kimmel, R., and Sapiro, G. (1997). Geodesic active contours. <span style=" font-style:italic;">International journal of computer vision, 22(1), 61-79.</span></li>
+<li style=" font-style:italic;" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial,sans-serif'; font-size:13px; font-style:normal; color:#222222; background-color:#ffffff;">Zhu, S. C., &amp; Yuille, A. (1996). Region competition: Unifying snakes, region growing, and Bayes/MDL for multiband image segmentation. </span><span style="  [...]
+<li style=" font-family:'Arial,sans-serif'; font-size:13px; color:#222222; background-color:#ffffff;" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:13px;">Sethian, J. A. (1999). </span><span style=" font-size:13px; font-style:italic;">Level set methods and fast marching methods: evolving interfaces in computational geometry, fluid [...]
+<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; text-decoration: underline;">Random Forest Classification</span></p>
+<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial,sans-serif'; font-size:13px; color:#222222; background-color:#ffffff;">Breiman, L. (2001). Random forests. </span><span style=" font-family:'Arial,sans-serif'; font-size [...]
+<li style=" font-family:'Arial,sans-serif'; font-size:13px; color:#222222; background-color:#ffffff;" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:13px; background-color:#f8f8f8;">Criminisi, A., &amp; Shotton, J. (2013). </span><span style=" font-size:13px; font-style:italic; background-color:#f8f8f8;">Decision forests for co [...]
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </widget>
      <widget class="QWidget" name="tab_3">
       <attribute name="title">
        <string>Components</string>
@@ -106,12 +158,12 @@ p, li { white-space: pre-wrap; }
           <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
 <html><head><meta name="qrichtext" content="1" /><style type="text/css">
 p, li { white-space: pre-wrap; }
-</style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;">
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; text-decoration: underline;">Toolbar Icons</span></p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">ITK-SNAP uses icons from the following free collections under the Creative Commons Attribution License:</p>
-<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">OpenIcon: <a href="http://openiconlibrary.sourceforge.net/"><span style=" text-decoration: underline; color:#0000ff;">http://openiconlibrary.sourceforge.net/</span></a> </p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">VisualPharm: <a href="http://icons8.com"><span style=" text-decoration: underline; color:#0000ff;">http://icons8.com</span></a></p></body></html></string>
+</style></head><body style=" font-family:'.Helvetica Neue DeskInterface'; font-size:13pt; font-weight:400; font-style:normal;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande'; font-weight:600; text-decoration: underline;">Toolbar Icons</span></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande';">ITK-SNAP uses icons from the following free collections under the Creative Commons Attribution License:</span></p>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Lucida Grande';"><br /></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande';">OpenIcon: </span><a href="http://openiconlibrary.sourceforge.net/"><span style=" font-family:'Lucida Grande'; text-decoration: underline; color:#0000ff;">http://openiconlibrary.sourceforge.net/</span></a><span style=" font-family:'Lucida G [...]
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande';">VisualPharm: </span><a href="http://icons8.com"><span style=" font-family:'Lucida Grande'; text-decoration: underline; color:#0000ff;">http://icons8.com</span></a></p></body></html></string>
          </property>
          <property name="openExternalLinks">
           <bool>true</bool>
@@ -159,9 +211,6 @@ p, li { white-space: pre-wrap; }
      </widget>
     </widget>
    </item>
-   <item row="0" column="1">
-    <widget class="SplashPanel" name="widget" native="true"/>
-   </item>
    <item row="0" column="0">
     <widget class="QLabel" name="label">
      <property name="text">
@@ -172,19 +221,6 @@ p, li { white-space: pre-wrap; }
      </property>
     </widget>
    </item>
-   <item row="2" column="0" colspan="2">
-    <widget class="QDialogButtonBox" name="buttonBox">
-     <property name="orientation">
-      <enum>Qt::Horizontal</enum>
-     </property>
-     <property name="standardButtons">
-      <set>QDialogButtonBox::Close</set>
-     </property>
-     <property name="centerButtons">
-      <bool>false</bool>
-     </property>
-    </widget>
-   </item>
   </layout>
  </widget>
  <customwidgets>
diff --git a/GUI/Qt/Windows/DropActionDialog.ui b/GUI/Qt/Windows/DropActionDialog.ui
index 80b97e5..04cb8a6 100644
--- a/GUI/Qt/Windows/DropActionDialog.ui
+++ b/GUI/Qt/Windows/DropActionDialog.ui
@@ -86,13 +86,16 @@
           <height>16777215</height>
          </size>
         </property>
+        <property name="toolTip">
+         <string>This will close all images currently open in this ITK-SNAP window and load the new image as the main image.</string>
+        </property>
         <property name="text">
          <string>Load as Main Image</string>
         </property>
        </widget>
       </item>
       <item>
-       <widget class="QPushButton" name="btnLoadSegmentation">
+       <widget class="QPushButton" name="btnLoadOverlay">
         <property name="minimumSize">
          <size>
           <width>192</width>
@@ -105,13 +108,16 @@
           <height>16777215</height>
          </size>
         </property>
+        <property name="toolTip">
+         <string>This will load the dropped image alongside the images currently open in this ITK-SNAP window </string>
+        </property>
         <property name="text">
-         <string>Load as Segmentation</string>
+         <string>Load as Additional Image</string>
         </property>
        </widget>
       </item>
       <item>
-       <widget class="QPushButton" name="btnLoadOverlay">
+       <widget class="QPushButton" name="btnLoadSegmentation">
         <property name="minimumSize">
          <size>
           <width>192</width>
@@ -124,8 +130,11 @@
           <height>16777215</height>
          </size>
         </property>
+        <property name="toolTip">
+         <string>This will replace the current segmentation image with the dropped image.</string>
+        </property>
         <property name="text">
-         <string>Load as Overlay</string>
+         <string>Load as Segmentation</string>
         </property>
        </widget>
       </item>
@@ -168,6 +177,9 @@
           <height>16777215</height>
          </size>
         </property>
+        <property name="toolTip">
+         <string>This will open a new ITK-SNAP window and open the dropped image as the main image</string>
+        </property>
         <property name="text">
          <string>Open in New ITK-SNAP</string>
         </property>
diff --git a/GUI/Qt/Windows/ImageIOWizard.cxx b/GUI/Qt/Windows/ImageIOWizard.cxx
index 5a2f609..58ec8b2 100644
--- a/GUI/Qt/Windows/ImageIOWizard.cxx
+++ b/GUI/Qt/Windows/ImageIOWizard.cxx
@@ -19,15 +19,25 @@
 #include <QHeaderView>
 #include <QGridLayout>
 #include <QSpinBox>
+#include <QFrame>
+
 
 #include <QtCursorOverride.h>
 
+#include <QtComboBoxCoupling.h>
+#include <QtWidgetCoupling.h>
+#include "QtVTKRenderWindowBox.h"
+
 #include "IRISException.h"
 #include "ImageIOWizardModel.h"
 #include "MetaDataAccess.h"
 #include "SNAPQtCommon.h"
 #include "FileChooserPanelWithHistory.h"
 
+#include "ImageIOWizard/RegistrationPage.h"
+#include "ImageIOWizard/OverlayRolePage.h"
+
+
 namespace imageiowiz {
 
 const QString AbstractPage::m_HtmlTemplate =
@@ -77,6 +87,35 @@ AbstractPage::WarningMessage(const IRISWarningList &wl)
     }
 }
 
+bool AbstractPage::PerformIO()
+{
+  // Get the selected format
+  QString format = this->field("Format").toString();
+  QString filename = this->field("Filename").toString();
+
+  ImageIOWizardModel::FileFormat fmt = m_Model->GetFileFormatByName(to_utf8(format));
+
+  try
+    {
+    QtCursorOverride curse(Qt::WaitCursor);
+    m_Model->SetSelectedFormat(fmt);
+    if(m_Model->IsLoadMode())
+      {
+      m_Model->LoadImage(to_utf8(filename));
+      }
+    else
+      {
+      m_Model->SaveImage(to_utf8(filename));
+      }
+    }
+  catch(IRISException &exc)
+    {
+    return ErrorMessage(exc);
+    }
+
+  return true;
+}
+
 bool
 AbstractPage::ErrorMessage(const char *subject, const char *detail)
 {
@@ -244,43 +283,7 @@ bool SelectFilePage::validatePage()
     }
 
   // Save or load the image
-  try
-    {
-    QtCursorOverride curse(Qt::WaitCursor);
-    m_Model->SetSelectedFormat(fmt);
-    if(m_Model->IsLoadMode())
-      {
-      m_Model->LoadImage(to_utf8(m_FilePanel->absoluteFilename()));
-      }
-    else
-      {
-      m_Model->SaveImage(to_utf8(m_FilePanel->absoluteFilename()));
-      }
-    }
-  catch(IRISException &exc)
-    {
-    return ErrorMessage(exc);
-    }
-
-  return true;
-}
-
-int SelectFilePage::nextId() const
-{
-  if(m_Model->IsSaveMode())
-    return -1;
-
-  // Get the selected format
-  QString format = m_FilePanel->activeFormat();
-  ImageIOWizardModel::FileFormat fmt = m_Model->GetFileFormatByName(to_utf8(format));
-
-  // Depending on the format, return the next page
-  if(fmt == GuidedNativeImageIO::FORMAT_RAW)
-    return ImageIOWizard::Page_Raw;
-  else if(fmt == GuidedNativeImageIO::FORMAT_DICOM_DIR)
-    return ImageIOWizard::Page_DICOM;
-  else
-    return ImageIOWizard::Page_Summary;
+  return this->PerformIO();
 }
 
 void SelectFilePage::onFilenameChanged(QString absoluteFilename)
@@ -511,10 +514,6 @@ bool DICOMPage::validatePage()
   return true;
 }
 
-int DICOMPage::nextId() const
-{
-  return ImageIOWizard::Page_Summary;
-}
 
 bool DICOMPage::isComplete() const
 {
@@ -675,11 +674,6 @@ void RawPage::initializePage()
   m_InEndian->setCurrentIndex(ien);
 }
 
-int RawPage::nextId() const
-{
-  return ImageIOWizard::Page_Summary;
-}
-
 bool RawPage::validatePage()
 {
   // Clear error state
@@ -720,6 +714,15 @@ bool RawPage::validatePage()
 }
 
 
+
+
+
+
+
+
+
+
+
 } // namespace
 
 using namespace imageiowiz;
@@ -730,11 +733,20 @@ ImageIOWizard::ImageIOWizard(QWidget *parent) :
   // Give ourselves a name
   this->setObjectName("wizImageIO");
 
+  // Set consistent style on all systems
+  this->setWizardStyle(QWizard::ClassicStyle);
+
+  // Use parent widget's attributes
+  if(parent)
+    this->setAttribute(Qt::WA_PaintOnScreen, parent->testAttribute(Qt::WA_PaintOnScreen));
+
   // Add pages to the wizard
   setPage(Page_File, new SelectFilePage(this));
   setPage(Page_Summary, new SummaryPage(this));
   setPage(Page_DICOM, new DICOMPage(this));
   setPage(Page_Raw, new RawPage(this));
+  setPage(Page_Coreg, new RegistrationPage(this));
+  setPage(Page_OverlayRole, new OverlayRolePage(this));
 
 }
 
@@ -755,4 +767,66 @@ void ImageIOWizard::SetModel(ImageIOWizardModel *model)
     this->setWindowTitle("Save Image - ITK-SNAP");
 }
 
+int ImageIOWizard::nextId() const
+{
+  // Determine the sequence of pages based on current state
+  std::list<int> pages;
+
+  // Always start with the file page
+  pages.push_back(Page_File);
+
+  // All other pages only occur in load mode
+  if(m_Model->IsLoadMode())
+    {
+    // DICOM or RAW page?
+    ImageIOWizardModel::FileFormat fmt =
+        m_Model->GetFileFormatByName(to_utf8(this->field("Format").toString()));
+
+    if(fmt == GuidedNativeImageIO::FORMAT_RAW)
+      pages.push_back(Page_Raw);
+    else if(fmt == GuidedNativeImageIO::FORMAT_DICOM_DIR)
+      pages.push_back(Page_DICOM);
+
+    // Overlay display page?
+    if(m_Model->IsOverlay())
+      pages.push_back(Page_OverlayRole);
+
+    // Registration page
+    if(m_Model->GetUseRegistration())
+      pages.push_back(Page_Coreg);
+
+    // Summary page
+    pages.push_back(Page_Summary);
+    pages.push_back(-1);
+    }
+  else
+    {
+    pages.push_back(-1);
+    }
+
+  // Find the page
+  for(std::list<int>::const_iterator it = pages.begin(); it != pages.end(); ++it)
+    {
+    if(*it == this->currentId())
+      {
+      ++it;
+      return *it;
+      }
+    }
+
+  return -1;
+}
+
+int ImageIOWizard::nextPageAfterLoad()
+{
+  if(m_Model->GetUseRegistration())
+    return ImageIOWizard::Page_Coreg;
+  else if(m_Model->IsOverlay() && m_Model->IsLoadMode())
+    return ImageIOWizard::Page_OverlayRole;
+  else
+    return ImageIOWizard::Page_Summary;
+
+
+}
+
 
diff --git a/GUI/Qt/Windows/ImageIOWizard.h b/GUI/Qt/Windows/ImageIOWizard.h
index c0c63f1..4e4fda1 100644
--- a/GUI/Qt/Windows/ImageIOWizard.h
+++ b/GUI/Qt/Windows/ImageIOWizard.h
@@ -2,8 +2,9 @@
 #define IMAGEIOWIZARD_H
 
 #include <QDebug>
-
 #include <QWizard>
+#include <QThread>
+
 #include "SNAPCommon.h"
 #include "ImageIOWizardModel.h"
 
@@ -19,6 +20,8 @@ class QTreeWidgetItem;
 class QTableWidget;
 class QSpinBox;
 class FileChooserPanelWithHistory;
+class OptimizationProgressRenderer;
+class QtVTKRenderWindowBox;
 
 // Helper classes in their own namespace, so I can use simple class names
 namespace imageiowiz
@@ -53,6 +56,9 @@ protected:
   void WarningMessage(const IRISWarningList &wl);
   ImageIOWizardModel *m_Model;
 
+  // Perform the actual save or load
+  bool PerformIO();
+
   // A qlabel for displaying error/warning messages. The children are
   // responsible for placing this control on their layouts
   QLabel *m_OutMessage;
@@ -67,7 +73,6 @@ class SelectFilePage : public AbstractPage
 public:
   explicit SelectFilePage(QWidget *parent = 0);
 
-  int nextId() const;
   void initializePage();
   bool validatePage();
   // bool isComplete() const;
@@ -89,7 +94,6 @@ class SummaryPage : public AbstractPage
 public:
   explicit SummaryPage(QWidget *parent = 0);
 
-  int nextId() const { return -1; }
   void initializePage();
 
   bool validatePage();
@@ -112,7 +116,6 @@ class DICOMPage : public AbstractPage
 public:
 
   explicit DICOMPage(QWidget *parent = 0);
-  int nextId() const;
   void initializePage();
   bool validatePage();
 
@@ -129,7 +132,6 @@ class RawPage : public AbstractPage
 public:
 
   explicit RawPage(QWidget *parent = 0);
-  int nextId() const;
   void initializePage();
   bool validatePage();
   virtual bool isComplete() const;
@@ -144,6 +146,8 @@ private:
   unsigned long m_FileSize;
 };
 
+
+
 } // end namespace
 
 
@@ -158,12 +162,18 @@ class ImageIOWizard : public QWizard
 
 public:
 
-  enum { Page_File, Page_Raw, Page_DICOM, Page_Summary };
+  enum { Page_File, Page_Raw, Page_DICOM, Page_Coreg, Page_OverlayRole, Page_Summary };
 
   explicit ImageIOWizard(QWidget *parent = 0);
 
   void SetModel(ImageIOWizardModel *model);
 
+  virtual int nextId() const;
+
+  /** Helper function to get the next page that should be opened after the image has
+      been loaded */
+  int nextPageAfterLoad();
+
 signals:
 
 public slots:
diff --git a/GUI/Qt/Windows/ImageIOWizard/OverlayRolePage.cxx b/GUI/Qt/Windows/ImageIOWizard/OverlayRolePage.cxx
new file mode 100644
index 0000000..9c0744b
--- /dev/null
+++ b/GUI/Qt/Windows/ImageIOWizard/OverlayRolePage.cxx
@@ -0,0 +1,56 @@
+#include "OverlayRolePage.h"
+#include "ui_OverlayRolePage.h"
+#include "QtWidgetCoupling.h"
+#include "QtRadioButtonCoupling.h"
+#include "QtComboBoxCoupling.h"
+#include "SNAPQtCommon.h"
+#include "GlobalUIModel.h"
+#include "ColorMapModel.h"
+
+namespace imageiowiz {
+
+OverlayRolePage::OverlayRolePage(QWidget *parent) :
+  AbstractPage(parent),
+  ui(new Ui::OverlayRolePage)
+{
+  ui->setupUi(this);
+}
+
+OverlayRolePage::~OverlayRolePage()
+{
+  delete ui;
+}
+
+
+void OverlayRolePage::initializePage()
+{
+  this->setTitle("How should the image be displayed?");
+
+  // Couple the radio buttons
+  std::map<bool, QAbstractButton *> radioMap;
+  radioMap[true] = ui->btnOverlay;
+  radioMap[false] = ui->btnSeparate;
+  makeRadioGroupCoupling(ui->wgtMain, radioMap, this->m_Model->GetStickyOverlayModel());
+
+  // Couple the color map selector
+  PopulateColorMapPresetCombo(ui->inOverlayColorMap,
+                              this->m_Model->GetParent()->GetColorMapModel());
+
+  makeCoupling(ui->inOverlayColorMap, this->m_Model->GetStickyOverlayColorMapModel());
+
+  // Apply the settings?
+
+}
+
+bool OverlayRolePage::validatePage()
+{
+  return true;
+}
+
+bool OverlayRolePage::isComplete() const
+{
+  return true;
+}
+
+
+}
diff --git a/GUI/Qt/Windows/ImageIOWizard/OverlayRolePage.h b/GUI/Qt/Windows/ImageIOWizard/OverlayRolePage.h
new file mode 100644
index 0000000..4763476
--- /dev/null
+++ b/GUI/Qt/Windows/ImageIOWizard/OverlayRolePage.h
@@ -0,0 +1,31 @@
+#ifndef OVERLAYROLEPAGE_H
+#define OVERLAYROLEPAGE_H
+
+#include <QWidget>
+#include "ImageIOWizard.h"
+
+namespace Ui {
+class OverlayRolePage;
+}
+
+namespace imageiowiz {
+
+class OverlayRolePage : public AbstractPage
+{
+  Q_OBJECT
+
+public:
+  explicit OverlayRolePage(QWidget *parent = 0);
+  ~OverlayRolePage();
+
+  void initializePage();
+  bool validatePage();
+  virtual bool isComplete() const;
+
+private:
+  Ui::OverlayRolePage *ui;
+};
+
+}
+
+#endif // OVERLAYROLEPAGE_H
diff --git a/GUI/Qt/Windows/ImageIOWizard/OverlayRolePage.ui b/GUI/Qt/Windows/ImageIOWizard/OverlayRolePage.ui
new file mode 100644
index 0000000..eb8d663
--- /dev/null
+++ b/GUI/Qt/Windows/ImageIOWizard/OverlayRolePage.ui
@@ -0,0 +1,222 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>OverlayRolePage</class>
+ <widget class="QWidget" name="OverlayRolePage">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>437</width>
+    <height>289</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <property name="styleSheet">
+   <string notr="true"/>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout_4">
+   <item>
+    <widget class="QWidget" name="wgtMain" native="true">
+     <layout class="QVBoxLayout" name="verticalLayout_3">
+      <property name="leftMargin">
+       <number>0</number>
+      </property>
+      <property name="topMargin">
+       <number>0</number>
+      </property>
+      <property name="rightMargin">
+       <number>0</number>
+      </property>
+      <property name="bottomMargin">
+       <number>0</number>
+      </property>
+      <item>
+       <widget class="QRadioButton" name="btnSeparate">
+        <property name="text">
+         <string>As a separate image (shown beside other images)</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QWidget" name="widget_2" native="true">
+        <layout class="QVBoxLayout" name="verticalLayout">
+         <property name="leftMargin">
+          <number>20</number>
+         </property>
+         <property name="topMargin">
+          <number>0</number>
+         </property>
+         <property name="rightMargin">
+          <number>0</number>
+         </property>
+         <property name="bottomMargin">
+          <number>0</number>
+         </property>
+         <item>
+          <widget class="QLabel" name="label_2">
+           <property name="styleSheet">
+            <string notr="true">font-size:10px;
+color:rgb(96, 96, 96);</string>
+           </property>
+           <property name="text">
+            <string>Best setting for viewing multiple anatomical images of the same subject</string>
+           </property>
+           <property name="wordWrap">
+            <bool>true</bool>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </widget>
+      </item>
+      <item>
+       <spacer name="verticalSpacer_2">
+        <property name="orientation">
+         <enum>Qt::Vertical</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Fixed</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>5</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <widget class="QRadioButton" name="btnOverlay">
+        <property name="text">
+         <string>As a semi-transparent overlay (shown on top of other images)</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QWidget" name="widget_3" native="true">
+        <layout class="QVBoxLayout" name="verticalLayout_5">
+         <property name="leftMargin">
+          <number>20</number>
+         </property>
+         <property name="topMargin">
+          <number>0</number>
+         </property>
+         <property name="rightMargin">
+          <number>0</number>
+         </property>
+         <property name="bottomMargin">
+          <number>0</number>
+         </property>
+         <item>
+          <widget class="QLabel" name="label_3">
+           <property name="styleSheet">
+            <string notr="true">font-size:10px;
+color:rgb(96, 96, 96);</string>
+           </property>
+           <property name="text">
+            <string>Best setting for viewing derived data such as statistical maps</string>
+           </property>
+           <property name="wordWrap">
+            <bool>true</bool>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QWidget" name="widget_5" native="true">
+           <layout class="QHBoxLayout" name="horizontalLayout">
+            <property name="leftMargin">
+             <number>40</number>
+            </property>
+            <item alignment="Qt::AlignLeft">
+             <widget class="QLabel" name="label_4">
+              <property name="text">
+               <string>Overlay color map:</string>
+              </property>
+             </widget>
+            </item>
+            <item alignment="Qt::AlignLeft">
+             <widget class="QComboBox" name="inOverlayColorMap">
+              <property name="maximumSize">
+               <size>
+                <width>200</width>
+                <height>16777215</height>
+               </size>
+              </property>
+             </widget>
+            </item>
+            <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>
+           </layout>
+          </widget>
+         </item>
+        </layout>
+       </widget>
+      </item>
+      <item>
+       <spacer name="verticalSpacer_3">
+        <property name="orientation">
+         <enum>Qt::Vertical</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Fixed</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>5</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <spacer name="verticalSpacer">
+        <property name="orientation">
+         <enum>Qt::Vertical</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>15</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <widget class="QWidget" name="widget_4" native="true">
+        <layout class="QVBoxLayout" name="verticalLayout_2">
+         <property name="leftMargin">
+          <number>20</number>
+         </property>
+         <property name="topMargin">
+          <number>0</number>
+         </property>
+         <property name="rightMargin">
+          <number>0</number>
+         </property>
+         <property name="bottomMargin">
+          <number>0</number>
+         </property>
+        </layout>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/GUI/Qt/Windows/ImageIOWizard/RegistrationPage.cxx b/GUI/Qt/Windows/ImageIOWizard/RegistrationPage.cxx
new file mode 100644
index 0000000..5d4acc9
--- /dev/null
+++ b/GUI/Qt/Windows/ImageIOWizard/RegistrationPage.cxx
@@ -0,0 +1,92 @@
+#include "ImageIOWizard/RegistrationPage.h"
+#include "ui_RegistrationPage.h"
+#include "SNAPQtCommon.h"
+#include <QtWidgetCoupling.h>
+#include <QtComboBoxCoupling.h>
+
+Q_DECLARE_METATYPE(ImageIOWizardModel::RegistrationMode)
+Q_DECLARE_METATYPE(ImageIOWizardModel::RegistrationMetric)
+Q_DECLARE_METATYPE(ImageIOWizardModel::RegistrationInit)
+
+
+namespace imageiowiz {
+
+void RegistrationWorkerThread::Initialize(ImageIOWizardModel *model)
+{
+  // Connect the model
+  m_Model = model;
+
+  // Respond to events from the model
+  AddListener<RegistrationWorkerThread>(
+        m_Model, ImageIOWizardModel::RegistrationProgressEvent(),
+        this, &RegistrationWorkerThread::OnProgressEvent);
+}
+
+void RegistrationWorkerThread::run()
+{
+  // This method executes the run registration code
+  m_Model->PerformRegistration();
+}
+
+void RegistrationWorkerThread::OnProgressEvent()
+{
+  emit registrationProgress();
+}
+
+
+RegistrationPage::RegistrationPage(QWidget *parent) :
+  AbstractPage(parent),
+  ui(new Ui::RegistrationPage)
+{
+  ui->setupUi(this);
+}
+
+RegistrationPage::~RegistrationPage()
+{
+  delete ui;
+}
+
+void RegistrationPage::on_btnRun_clicked()
+{
+  RegistrationWorkerThread *workerThread = new RegistrationWorkerThread();
+  workerThread->Initialize(m_Model);
+  connect(workerThread, SIGNAL(registrationProgress()), this, SLOT(onRegistrationProgress()));
+  connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater()));
+  workerThread->start();
+}
+
+int RegistrationPage::nextId() const
+{
+  return ImageIOWizard::Page_Summary;
+}
+
+void RegistrationPage::initializePage()
+{
+  this->setTitle("Image Registration");
+
+  // Connect widgets to the model
+  makeCoupling(ui->inRegistrationMode, this->m_Model->GetRegistrationModeModel());
+  makeCoupling(ui->inSimilarityMetric, this->m_Model->GetRegistrationMetricModel());
+  makeCoupling(ui->inInitialAlignment, this->m_Model->GetRegistrationInitModel());
+
+  // Get the progress renderer and attach it to the widget
+  ui->progressBox->SetRenderer(this->m_Model->GetRegistrationProgressRenderer());
+}
+
+bool RegistrationPage::validatePage()
+{
+  return true;
+}
+
+bool RegistrationPage::isComplete() const
+{
+  return true;
+}
+
+void RegistrationPage::onRegistrationProgress()
+{
+  this->m_Model->UpdateImageTransformFromRegistration();
+  this->setTitle(QString("Metric %1").arg(m_Model->GetRegistrationObjective()));
+}
+
+}
diff --git a/GUI/Qt/Windows/ImageIOWizard/RegistrationPage.h b/GUI/Qt/Windows/ImageIOWizard/RegistrationPage.h
new file mode 100644
index 0000000..dec237e
--- /dev/null
+++ b/GUI/Qt/Windows/ImageIOWizard/RegistrationPage.h
@@ -0,0 +1,58 @@
+#ifndef REGISTRATIONPAGE_H
+#define REGISTRATIONPAGE_H
+
+#include <QWidget>
+#include "ImageIOWizard.h"
+
+namespace Ui {
+  class RegistrationPage;
+}
+
+namespace imageiowiz {
+
+class RegistrationWorkerThread : public QThread
+{
+  Q_OBJECT
+
+public:
+
+  void Initialize(ImageIOWizardModel *model);
+  void run();
+  void OnProgressEvent();
+
+signals:
+
+  void registrationProgress();
+
+private:
+
+  ImageIOWizardModel *m_Model;
+};
+
+class RegistrationPage : public AbstractPage
+{
+  Q_OBJECT
+
+public:
+  explicit RegistrationPage(QWidget *parent = 0);
+  ~RegistrationPage();
+
+  int nextId() const;
+  void initializePage();
+  bool validatePage();
+  virtual bool isComplete() const;
+
+public slots:
+
+  void onRegistrationProgress();
+
+private slots:
+  void on_btnRun_clicked();
+
+private:
+  Ui::RegistrationPage *ui;
+};
+
+} // end namespace
+
+#endif // REGISTRATIONPAGE_H
diff --git a/GUI/Qt/Windows/ImageIOWizard/RegistrationPage.ui b/GUI/Qt/Windows/ImageIOWizard/RegistrationPage.ui
new file mode 100644
index 0000000..745c605
--- /dev/null
+++ b/GUI/Qt/Windows/ImageIOWizard/RegistrationPage.ui
@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>RegistrationPage</class>
+ <widget class="QWidget" name="RegistrationPage">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>404</width>
+    <height>339</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="4" column="0" colspan="2">
+    <widget class="QWidget" name="widget" native="true">
+     <layout class="QHBoxLayout" name="horizontalLayout">
+      <property name="leftMargin">
+       <number>0</number>
+      </property>
+      <property name="topMargin">
+       <number>0</number>
+      </property>
+      <property name="rightMargin">
+       <number>0</number>
+      </property>
+      <property name="bottomMargin">
+       <number>0</number>
+      </property>
+      <item>
+       <spacer name="horizontalSpacer">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>282</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <widget class="QToolButton" name="btnStop">
+        <property name="text">
+         <string>Stop</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QToolButton" name="btnRun">
+        <property name="text">
+         <string>Run</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item row="5" column="0" colspan="2">
+    <widget class="QFrame" name="frame">
+     <property name="frameShape">
+      <enum>QFrame::StyledPanel</enum>
+     </property>
+     <property name="frameShadow">
+      <enum>QFrame::Raised</enum>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout">
+      <property name="leftMargin">
+       <number>0</number>
+      </property>
+      <property name="topMargin">
+       <number>0</number>
+      </property>
+      <property name="rightMargin">
+       <number>0</number>
+      </property>
+      <property name="bottomMargin">
+       <number>0</number>
+      </property>
+      <item>
+       <widget class="QtVTKRenderWindowBox" name="progressBox" native="true">
+        <property name="minimumSize">
+         <size>
+          <width>0</width>
+          <height>120</height>
+         </size>
+        </property>
+        <property name="styleSheet">
+         <string notr="true">background-color:white;</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item row="2" column="1">
+    <widget class="QComboBox" name="inSimilarityMetric"/>
+   </item>
+   <item row="2" column="0">
+    <widget class="QLabel" name="label_3">
+     <property name="text">
+      <string>Similarity metric:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="1">
+    <widget class="QComboBox" name="inRegistrationMode"/>
+   </item>
+   <item row="1" column="1">
+    <widget class="QComboBox" name="inInitialAlignment"/>
+   </item>
+   <item row="1" column="0">
+    <widget class="QLabel" name="label_2">
+     <property name="text">
+      <string>Initial alignment:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="0">
+    <widget class="QLabel" name="label">
+     <property name="text">
+      <string>Registration mode:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="1">
+    <spacer name="verticalSpacer">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>20</width>
+       <height>40</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>QtVTKRenderWindowBox</class>
+   <extends>QWidget</extends>
+   <header location="global">QtVTKRenderWindowBox.h</header>
+   <container>1</container>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/GUI/Qt/Windows/LabelEditorDialog.cxx b/GUI/Qt/Windows/LabelEditorDialog.cxx
index fa9d0a9..0377745 100644
--- a/GUI/Qt/Windows/LabelEditorDialog.cxx
+++ b/GUI/Qt/Windows/LabelEditorDialog.cxx
@@ -39,9 +39,12 @@ LabelEditorDialog::LabelEditorDialog(QWidget *parent) :
   menu->addSeparator();
   menu->addAction(ui->actionResetLabels);
 
+  QStandardItemModel *simodel = new QStandardItemModel(this);
+  simodel->setColumnCount(2);
+
   // Set up a filter model for the label list view
   m_LabelListFilterModel = new QSortFilterProxyModel(this);
-  m_LabelListFilterModel->setSourceModel(new QStandardItemModel(this));
+  m_LabelListFilterModel->setSourceModel(simodel);
   m_LabelListFilterModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
   m_LabelListFilterModel->setFilterKeyColumn(-1);
   ui->lvLabels->setModel(m_LabelListFilterModel);
@@ -104,6 +107,15 @@ void LabelEditorDialog::SetModel(LabelEditorModel *model)
                  LabelEditorModel::UIF_EDITABLE_LABEL_SELECTED);
   activateOnFlag(ui->btnDelete, m_Model,
                  LabelEditorModel::UIF_EDITABLE_LABEL_SELECTED);
+
+  // Set resizing behavior
+#if QT_VERSION >= 0x050000
+  ui->lvLabels->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
+  ui->lvLabels->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch);
+#else
+  ui->lvLabels->horizontalHeader()->setResizeMode(0, QHeaderView::ResizeToContents);
+  ui->lvLabels->horizontalHeader()->setResizeMode(1, QHeaderView::Stretch);
+#endif
 }
 
 void LabelEditorDialog::on_btnClose_clicked()
diff --git a/GUI/Qt/Windows/LabelEditorDialog.ui b/GUI/Qt/Windows/LabelEditorDialog.ui
index 14712dd..3d4ece2 100644
--- a/GUI/Qt/Windows/LabelEditorDialog.ui
+++ b/GUI/Qt/Windows/LabelEditorDialog.ui
@@ -629,19 +629,22 @@ QGroupBox::title {
      </property>
      <layout class="QVBoxLayout" name="verticalLayout">
       <property name="leftMargin">
-       <number>6</number>
+       <number>4</number>
       </property>
       <property name="topMargin">
-       <number>6</number>
+       <number>4</number>
       </property>
       <property name="rightMargin">
-       <number>6</number>
+       <number>3</number>
       </property>
       <property name="bottomMargin">
-       <number>6</number>
+       <number>4</number>
       </property>
       <item>
        <widget class="QTableView" name="lvLabels">
+        <property name="styleSheet">
+         <string notr="true">font-size:12px;</string>
+        </property>
         <property name="editTriggers">
          <set>QAbstractItemView::NoEditTriggers</set>
         </property>
@@ -658,7 +661,7 @@ QGroupBox::title {
          <bool>false</bool>
         </attribute>
         <attribute name="horizontalHeaderDefaultSectionSize">
-         <number>50</number>
+         <number>60</number>
         </attribute>
         <attribute name="horizontalHeaderStretchLastSection">
          <bool>true</bool>
diff --git a/GUI/Qt/Windows/LayerInspectorDialog.cxx b/GUI/Qt/Windows/LayerInspectorDialog.cxx
index b135b54..5338cf0 100644
--- a/GUI/Qt/Windows/LayerInspectorDialog.cxx
+++ b/GUI/Qt/Windows/LayerInspectorDialog.cxx
@@ -49,7 +49,6 @@ LayerInspectorDialog::LayerInspectorDialog(QWidget *parent) :
 
   tb->addAction(ui->actionOpenLayer);
   tb->addWidget(m_SaveSelectedButton);
-  tb->addAction(ui->actionEditVisibility);
   tb->addAction(ui->actionLayoutToggle);
 
   // Set up the action button
@@ -107,14 +106,10 @@ void LayerInspectorDialog::SetModel(GlobalUIModel *model)
         this, SLOT(onModelUpdate(const EventBucket &)));
 
 
-  // The button turning on and off the visibility/reorder/pinning controls
-  // on the layer rows is tied to a model in GenericUIModel
-  makeCoupling(
-        ui->actionEditVisibility,
-        model->GetLayerVisibilityEditableModel());
-
   // Set up the activation on the open layer button
   activateOnFlag(ui->actionOpenLayer, m_Model, UIF_IRIS_WITH_BASEIMG_LOADED);
+
+  activateOnFlag(ui->actionLayoutToggle, m_Model, UIF_MULTIPLE_BASE_LAYERS);
 }
 
 void LayerInspectorDialog::SetPageToContrastAdjustment()
@@ -199,7 +194,7 @@ void LayerInspectorDialog::BuildLayerWidgetHierarchy()
   if(mapRoleNames.size() == 0)
     {
     mapRoleNames[MAIN_ROLE] = "Main Image";
-    mapRoleNames[OVERLAY_ROLE] = "Overlays";
+    mapRoleNames[OVERLAY_ROLE] = "Additional Images";
     mapRoleNames[SNAP_ROLE] = "Snake Mode Layers";
     }
 
@@ -278,6 +273,8 @@ void LayerInspectorDialog::BuildLayerWidgetHierarchy()
 
     // Listen to select signals from widget
     connect(w, SIGNAL(selectionChanged(bool)), this, SLOT(layerSelected(bool)));
+    connect(w, SIGNAL(contrastInspectorRequested()), this, SLOT(onContrastInspectorRequested()));
+    connect(w, SIGNAL(colorMapInspectorRequested()), this, SLOT(onColorMapInspectorRequested()));
 
     // Select the layer if it was previously selected or nothing was previously
     // selected and the layer is the main layer
@@ -347,6 +344,8 @@ void LayerInspectorDialog::layerSelected(bool flag)
 
     // Switch the current layer in all the right-pane models
     LayerInspectorRowDelegate *wsel = (LayerInspectorRowDelegate *) this->sender();
+    if(!wsel->selected())
+      wsel->setSelected(true);
     this->SetActiveLayer(wsel->GetLayer());
 
     // Put this layer's actions on the menu
@@ -354,6 +353,30 @@ void LayerInspectorDialog::layerSelected(bool flag)
     }
 }
 
+void LayerInspectorDialog::onContrastInspectorRequested()
+{
+  // Make sure the layer is selected
+  this->layerSelected(true);
+  ui->tabWidget->setCurrentWidget(ui->cmpContrast);
+
+  // Make sure to show the dialog
+  this->show();
+  this->activateWindow();
+  this->raise();
+}
+
+void LayerInspectorDialog::onColorMapInspectorRequested()
+{
+  // Make sure the layer is selected
+  this->layerSelected(true);
+  ui->tabWidget->setCurrentWidget(ui->cmpColorMap);
+
+  // Make sure to show the dialog
+  this->show();
+  this->activateWindow();
+  this->raise();
+}
+
 void LayerInspectorDialog::SetActiveLayer(ImageWrapperBase *layer)
 {
   // For our purposes, uninitialized layers are just the same as null layers,
@@ -379,13 +402,11 @@ LayerInspectorDialog::UpdateLayerLayoutAction()
 
   if(ll == LAYOUT_TILED)
     {
-    ui->actionLayoutToggle->setIcon(QIcon(":/root/layout_overlay_16.png"));
-    ui->actionLayoutToggle->setToolTip("Render image overlays on top of each other");
+    ui->actionLayoutToggle->setIcon(QIcon(":/root/layout_thumb_16.png"));
     }
   else if(ll == LAYOUT_STACKED)
     {
     ui->actionLayoutToggle->setIcon(QIcon(":/root/layout_tile_16.png"));
-    ui->actionLayoutToggle->setToolTip("Tile image overlays side by side");
     }
 }
 
diff --git a/GUI/Qt/Windows/LayerInspectorDialog.h b/GUI/Qt/Windows/LayerInspectorDialog.h
index 2276b25..bdbfe19 100644
--- a/GUI/Qt/Windows/LayerInspectorDialog.h
+++ b/GUI/Qt/Windows/LayerInspectorDialog.h
@@ -49,6 +49,9 @@ public slots:
 
   void layerSelected(bool);
 
+  void onContrastInspectorRequested();
+  void onColorMapInspectorRequested();
+
   void advanceTab();
 
 signals:
diff --git a/GUI/Qt/Windows/LayerInspectorDialog.ui b/GUI/Qt/Windows/LayerInspectorDialog.ui
index f7fb6d8..8b05765 100644
--- a/GUI/Qt/Windows/LayerInspectorDialog.ui
+++ b/GUI/Qt/Windows/LayerInspectorDialog.ui
@@ -33,7 +33,7 @@
     <widget class="QWidget" name="widget" native="true">
      <property name="minimumSize">
       <size>
-       <width>162</width>
+       <width>180</width>
        <height>0</height>
       </size>
      </property>
@@ -84,7 +84,7 @@
           <rect>
            <x>0</x>
            <y>0</y>
-           <width>150</width>
+           <width>168</width>
            <height>409</height>
           </rect>
          </property>
@@ -154,7 +154,7 @@
       </sizepolicy>
      </property>
      <property name="currentIndex">
-      <number>1</number>
+      <number>0</number>
      </property>
      <widget class="GeneralLayerInspector" name="cmpComponent">
       <attribute name="title">
@@ -208,22 +208,6 @@
     <string>Save As...</string>
    </property>
   </action>
-  <action name="actionEditVisibility">
-   <property name="checkable">
-    <bool>true</bool>
-   </property>
-   <property name="icon">
-    <iconset resource="../Resources/SNAPResources.qrc">
-     <normaloff>:/root/layer_invisible_16.png</normaloff>
-     <normalon>:/root/layer_visible_16.png</normalon>:/root/layer_invisible_16.png</iconset>
-   </property>
-   <property name="text">
-    <string>Edit Visibility</string>
-   </property>
-   <property name="toolTip">
-    <string>Press this button to display layer visibility and opacity controls in the list of layers</string>
-   </property>
-  </action>
   <action name="actionLayoutToggle">
    <property name="icon">
     <iconset resource="../Resources/SNAPResources.qrc">
@@ -233,7 +217,7 @@
     <string>Layout Toggle</string>
    </property>
    <property name="toolTip">
-    <string>Toggle layout between tiled and stacked</string>
+    <string><html><head/><body><p>Toggle between thumbnail and tiled layouts.</p><p>In <span style=" font-weight:600;">thumbnail</span> layout, one image layer occupies most of the available screen space, and other loaded image layers are shown as thumbnails. In <span style=" font-weight:600;">tiled</span> layout, multiple image layers are shown side by side. </p></body></html></string>
    </property>
   </action>
   <action name="actionOpenLayer">
diff --git a/GUI/Qt/Windows/MainControlPanel.cxx b/GUI/Qt/Windows/MainControlPanel.cxx
index 8985846..0139301 100644
--- a/GUI/Qt/Windows/MainControlPanel.cxx
+++ b/GUI/Qt/Windows/MainControlPanel.cxx
@@ -11,51 +11,47 @@
 #include <QtActionGroupCoupling.h>
 #include <QActionGroup>
 #include <QMenu>
-
-/*
- * A style sheet for making blue buttons with a drop down. For now we are
- * not going to use these, but may need them if more tools are added to
- * the main toolbox
-
-    QToolButton {
-    border-image: url(:/root/fltkbutton.png) repeat;
-    border-top-width: 8px;
-    border-bottom-width: 8px;
-    border-left-width: 3px;
-    border-right-width: 3px;
-    background-origin: content;
-    padding-top: -8px;
-    padding-bottom: -8px;
-    padding-left: -7px;
-    padding-right: 1px;
-    width:33px;
-    height:28px;
-    }
-
-    QToolButton[popupMode="0"]
-    {
-    width:28px;
-    padding-left: -2px;
-    padding-right: -2px;
-
-    }
-
-    QToolButton:pressed, QToolButton:checked {
-      border-image: url(:/root/fltkbutton_pressed.png) repeat;
-    }
-
-    QToolButton::menu-button {
-    border:0px;
-    margin:0px;
-    padding-top: 17px;
-    padding-right: 2px;
-    }
-
-    QToolButton::menu-arrow {
-    image: url(:/root/menu-arrow.png);
-    }
-
-    */
+#include <QToolButton>
+
+// A style sheet for making blue buttons with a drop down. For now we are
+// not going to use these, but may need them if more tools are added to
+// the main toolbox
+static const char *ss_toolbutton_dropdown =
+    "QToolButton {"
+    "border-top-width: 8px;"
+    "border-bottom-width: 8px;"
+    "border-left-width: 3px;"
+    "border-right-width: 3px;"
+    "background-origin: content;"
+    "padding-top: -8px;"
+    "padding-bottom: -8px;"
+    "padding-left: -7px;"
+    "padding-right: 1px;"
+    "width:33px;"
+    "height:28px;"
+    "}"
+    ""
+    "QToolButton[popupMode=\"0\"]"
+    "{"
+    "width:28px;"
+    "padding-left: -2px;"
+    "padding-right: -2px;"
+    "}"
+    ""
+    "QToolButton:pressed, QToolButton:checked {"
+    "  border-image: url(:/root/fltkbutton_pressed.png) repeat;"
+    "}"
+    ""
+    "QToolButton::menu-button {"
+    "border:0px;"
+    "margin:0px;"
+    "padding-top: 17px;"
+    "padding-right: 2px;"
+    "}"
+    ""
+    "QToolButton::menu-arrow {"
+    "image: url(:/root/menu-arrow.png);"
+    "}";
 
 /*
  * Some commented out code for setting up a dropdown menu of actions
@@ -82,7 +78,6 @@
 
  */
 
-#include <QToolBar>
 #include <QWhatsThis>
 
 MainControlPanel::MainControlPanel(MainImageWindow *parent) :
@@ -93,33 +88,97 @@ MainControlPanel::MainControlPanel(MainImageWindow *parent) :
 
   m_Model = NULL;
 
-  // The mode toolbar
-  QToolBar *toolbar = new QToolBar(this);
-  ui->panelToolbarMode->layout()->addWidget(toolbar);  
-  toolbar->addActions(parent->GetMainToolActionGroup()->actions());
+  // Connect tool buttons to actions
+  ui->btnCrosshair->setDefaultAction(FindUpstreamAction(this, "actionCrosshair"));
+  ui->btnZoom->setDefaultAction(FindUpstreamAction(this, "actionZoomPan"));
+  ui->btnPolygon->setDefaultAction(FindUpstreamAction(this, "actionPolygon"));
+  ui->btnPaintbrush->setDefaultAction(FindUpstreamAction(this, "actionPaintbrush"));
+  ui->btnAnnotation->setDefaultAction(FindUpstreamAction(this, "actionAnnotation"));
+  ui->btnSnake->setDefaultAction(FindUpstreamAction(this, "actionSnake"));
+
+  /*
+  // Configure the toolbar's simple buttons
+  toolbar->addAction(FindUpstreamAction(this, "actionCrosshair"));
+  toolbar->addAction(FindUpstreamAction(this, "actionZoomPan"));
+
+  // QWidget *spacer1 = new QWidget();
+  // spacer1->setMinimumWidth(2);
+  // toolbar->addWidget(spacer1);
+
+  // Create a drop down button for choosing between polygon and annotation modes
+  m_DrawingDropdownButton = new QToolButton(this);
+  QMenu *tbDrawingMenu = new QMenu();
+  tbDrawingMenu->addAction(FindUpstreamAction(this, "actionPolygon"));
+  tbDrawingMenu->addAction(FindUpstreamAction(this, "actionPaintbrush"));
+  tbDrawingMenu->addAction(FindUpstreamAction(this, "actionAnnotation"));
+  m_DrawingDropdownButton->setMenu(tbDrawingMenu);
+  m_DrawingDropdownButton->setDefaultAction(FindUpstreamAction(this, "actionPolygon"));
+  m_DrawingDropdownButton->setPopupMode(QToolButton::MenuButtonPopup);
+  // m_DrawingDropdownButton->setMinimumWidth(28);
+  // m_DrawingDropdownButton->setMaximumWidth(38);
+  // m_DrawingDropdownButton->setStyleSheet("padding-right:12px;");
 
+  connect(tbDrawingMenu, SIGNAL(triggered(QAction*)), this, SLOT(onDrawingButtonAction(QAction *)));
+
+  toolbar->addWidget(m_DrawingDropdownButton);
+
+  // QWidget *spacer2 = new QWidget();
+  // spacer2->setMinimumWidth(2);
+  // toolbar->addWidget(spacer2);
+
+
+
+  toolbar->addAction(FindUpstreamAction(this, "actionSnake"));
+
+  // toolbar->addActions(parent->GetMainToolActionGroup()->actions());
+
+  */
+
+
+/*
   // The action toolbar
   QToolBar *toolCmd = new QToolBar(this);
+  toolCmd->setIconSize(QSize(20,20));
   ui->panelToolbarAction->layout()->addWidget(toolCmd);
+  */
+
+  // Hide the buttons that show up and disappear
+  ui->btnPaintbrushInspector->setVisible(false);
+  ui->btnPolygonInspector->setVisible(false);
+  ui->btnSnakeInspector->setVisible(false);
+  ui->btnAnnotateInspector->setVisible(false);
+
 
   // Label selection button
-  m_LabelSelectionButton = new LabelSelectionButton(this);
+  /*m_LabelSelectionButton = new LabelSelectionButton(this);
 
   toolCmd->addAction(FindUpstreamAction(this, "actionUndo"));
   toolCmd->addAction(FindUpstreamAction(this, "actionRedo"));
   toolCmd->addWidget(m_LabelSelectionButton);
-  toolCmd->addAction(FindUpstreamAction(this, "actionLayerInspector"));
+  toolCmd->addAction(FindUpstreamAction(this, "actionLayerInspector")); */
+
+  ui->btnUndo->setDefaultAction(FindUpstreamAction(this, "actionUndo"));
+  ui->btnRedo->setDefaultAction(FindUpstreamAction(this, "actionRedo"));
+  ui->btnLayerInspector->setDefaultAction(FindUpstreamAction(this, "actionLayerInspector"));
+  ui->btnLabelEditor->setDefaultAction(FindUpstreamAction(this, "actionLabel_Editor"));
 
   // Add a shortcut for the button
-  m_LabelSelectionButton->setShortcut(QKeySequence("l"));
+  ui->btnLabelSelector->setShortcut(QKeySequence("l"));
 
   // Set up the label popup
   m_LabelSelectionPopup = new LabelSelectionPopup(this);
 
   // Set up the 3D toolbar
-  QToolBar *tool3D = new QToolBar(this);
-  ui->panelToolbarMode3D->layout()->addWidget(tool3D);
-  tool3D->addActions(parent->Get3DToolActionGroup()->actions());
+  ui->btnCross3D->setDefaultAction(FindUpstreamAction(this, "action3DCrosshair"));
+  ui->btnRotate3D->setDefaultAction(FindUpstreamAction(this, "action3DTrackball"));
+  ui->btnScalpel->setDefaultAction(FindUpstreamAction(this, "action3DScalpel"));
+  ui->btnSpray->setDefaultAction(FindUpstreamAction(this, "action3DSpray"));
+
+
+
+  //QToolBar *tool3D = new QToolBar(this);
+  //ui->panelToolbarMode3D->layout()->addWidget(tool3D);
+  //tool3D->addActions(parent->Get3DToolActionGroup()->actions());
 }
 
 void MainControlPanel::SetModel(GlobalUIModel *model)
@@ -127,15 +186,18 @@ void MainControlPanel::SetModel(GlobalUIModel *model)
   m_Model = model;
   ui->pageCursorInspector->SetModel(m_Model->GetCursorInspectionModel());
   ui->pageZoomInspector->SetModel(m_Model);
-  ui->pageLabelInspector->SetModel(m_Model);
   ui->pageDisplayInspector->SetModel(m_Model->GetDisplayLayoutModel());
   ui->pageSyncInspector->SetModel(m_Model->GetSynchronizationModel());
   ui->pagePaintbrushTool->SetModel(m_Model->GetPaintbrushSettingsModel());
   ui->pageSnakeTool->SetModel(m_Model);
+  ui->pagePolygonTool->SetModel(m_Model);
+  ui->pageAnnotationTool->SetModel(m_Model);
 
-  m_LabelSelectionButton->SetModel(model);
+  ui->btnLabelSelector->SetModel(model);
   m_LabelSelectionPopup->SetModel(model);
 
+  ui->labelInspector->SetModel(m_Model);
+
   // Set up state machine
   activateOnFlag(this, m_Model, UIF_BASEIMG_LOADED);
 
@@ -150,29 +212,34 @@ void MainControlPanel::onModelUpdate(const EventBucket &bucket)
   static QToolButton *mode_inspector_btn[] = {
     ui->btnCursorInspector,
     ui->btnZoomInspector,
-    ui->btnLabelInspector,
-    ui->btnToolInspector,
-    ui->btnToolInspector,
-    ui->btnToolInspector };
-
-  static QWidget *mode_tool_pages[] = {
-    ui->pageBlank,
-    ui->pageBlank,
-    ui->pageBlank,
-    ui->pagePaintbrushTool,
-    ui->pageSnakeTool,
-    ui->pageBlank};
+    ui->btnPolygonInspector,
+    ui->btnPaintbrushInspector,
+    ui->btnSnakeInspector,
+    ui->btnAnnotateInspector
+  };
+
 
   // Respond to changes in toolbar mode
   GlobalState *gs = m_Model->GetGlobalState();
   if(bucket.HasEvent(ValueChangedEvent(), gs->GetToolbarModeModel()))
     {
-    int mode = (int) gs->GetToolbarMode();
+    // Update the list of displayed buttons
+    ToolbarModeType mode = gs->GetToolbarMode();
+    ui->btnPaintbrushInspector->setVisible(mode == PAINTBRUSH_MODE);
+    ui->btnPolygonInspector->setVisible(mode == POLYGON_DRAWING_MODE);
+    ui->btnSnakeInspector->setVisible(mode == ROI_MODE);
+    ui->btnAnnotateInspector->setVisible(mode == ANNOTATION_MODE);
+
+    // Click the button corresponding to the mode
     mode_inspector_btn[mode]->click();
-    ui->stackToolPage->setCurrentWidget(mode_tool_pages[mode]);
     }
 }
 
+void MainControlPanel::onDrawingButtonAction(QAction *action)
+{
+  m_DrawingDropdownButton->setDefaultAction(action);
+}
+
 
 MainControlPanel::~MainControlPanel()
 {
@@ -198,15 +265,6 @@ void MainControlPanel::on_btnZoomInspector_clicked(bool checked)
     }
 }
 
-void MainControlPanel::on_btnLabelInspector_clicked(bool checked)
-{
-  if(checked)
-    {
-    ui->stack->setCurrentWidget(ui->pageLabelInspector);
-    ui->grpInspector->setTitle("Label Inspector");
-    }
-}
-
 void MainControlPanel::on_btnDisplayInspector_clicked(bool checked)
 {
   if(checked)
@@ -225,14 +283,45 @@ void MainControlPanel::on_btnSyncInspector_clicked(bool checked)
     }
 }
 
-void MainControlPanel::on_btnToolInspector_clicked(bool checked)
+
+
+
+void MainControlPanel::on_btnPolygonInspector_clicked(bool checked)
 {
   if(checked)
     {
-    ui->stack->setCurrentWidget(ui->pageToolInspector);
-    ui->grpInspector->setTitle("Active Tool Inspector");
+    ui->stack->setCurrentWidget(ui->pagePolygonTool);
+    ui->grpInspector->setTitle("Polygon Inspector");
     }
+
 }
 
+void MainControlPanel::on_btnPaintbrushInspector_clicked(bool checked)
+{
+  if(checked)
+    {
+    ui->stack->setCurrentWidget(ui->pagePaintbrushTool);
+    ui->grpInspector->setTitle("Paintbrush Inspector");
+    }
+
+}
+
+void MainControlPanel::on_btnSnakeInspector_clicked(bool checked)
+{
+  if(checked)
+    {
+    ui->stack->setCurrentWidget(ui->pageSnakeTool);
+    ui->grpInspector->setTitle("Snake Inspector");
+    }
+
+}
 
 
+void MainControlPanel::on_btnAnnotateInspector_clicked(bool checked)
+{
+  if(checked)
+    {
+    ui->stack->setCurrentWidget(ui->pageAnnotationTool);
+    ui->grpInspector->setTitle("Annotation Inspector");
+    }
+}
diff --git a/GUI/Qt/Windows/MainControlPanel.h b/GUI/Qt/Windows/MainControlPanel.h
index 635c51d..e57408b 100644
--- a/GUI/Qt/Windows/MainControlPanel.h
+++ b/GUI/Qt/Windows/MainControlPanel.h
@@ -12,6 +12,7 @@ class MainControlPanel;
 
 class GlobalUIModel;
 class MainImageWindow;
+class QToolButton;
 
 class MainControlPanel : public SNAPComponent
 {
@@ -27,20 +28,26 @@ protected slots:
 
   virtual void onModelUpdate(const EventBucket &bucket);
 
+  void onDrawingButtonAction(QAction *);
+
 private slots:
 
   void on_btnCursorInspector_clicked(bool checked);
 
   void on_btnZoomInspector_clicked(bool checked);
 
-  void on_btnLabelInspector_clicked(bool checked);
-
   void on_btnDisplayInspector_clicked(bool checked);
 
   void on_btnSyncInspector_clicked(bool checked);
 
-  void on_btnToolInspector_clicked(bool checked);
 
+  void on_btnPolygonInspector_clicked(bool checked);
+
+  void on_btnPaintbrushInspector_clicked(bool checked);
+
+  void on_btnSnakeInspector_clicked(bool checked);
+
+  void on_btnAnnotateInspector_clicked(bool checked);
 
 private:
   Ui::MainControlPanel *ui;
@@ -48,6 +55,8 @@ private:
 
   LabelSelectionButton *m_LabelSelectionButton;
   LabelSelectionPopup *m_LabelSelectionPopup;
+
+  QToolButton *m_DrawingDropdownButton;
 };
 
 #endif // MAINCONTROLPANEL_H
diff --git a/GUI/Qt/Windows/MainControlPanel.ui b/GUI/Qt/Windows/MainControlPanel.ui
index 7db5f42..f4d455e 100644
--- a/GUI/Qt/Windows/MainControlPanel.ui
+++ b/GUI/Qt/Windows/MainControlPanel.ui
@@ -7,7 +7,7 @@
     <x>0</x>
     <y>0</y>
     <width>184</width>
-    <height>588</height>
+    <height>715</height>
    </rect>
   </property>
   <property name="minimumSize">
@@ -32,391 +32,993 @@
   font-weight: bold;
   font-size: 12px;
   color: rgb(30,30,160);
-  background-color: rgb(237,237,237);
+  background-color: rgb(222,222,222);
   padding: 5px;
-  border-radius: 4px;
-  border: 1px solid rgb(130,130,130);
+  border-radius: 2px;
+  border: 1px solid rgb(168,168,168);
 }
 QGroupBox::title {
   subcontrol-origin: 	margin;
   subcontrol-position: top left;
-}</string>
+}
+
+QToolButton::checked {
+  background-color:rgb(210, 210, 210);
+}
+
+QToolButton::pressed {
+  background-color:rgb(210, 210, 210);
+}
+</string>
   </property>
-  <layout class="QVBoxLayout" name="verticalLayout">
+  <layout class="QVBoxLayout" name="verticalLayout" stretch="0">
    <property name="spacing">
-    <number>8</number>
+    <number>0</number>
    </property>
-   <property name="margin">
+   <property name="leftMargin">
+    <number>5</number>
+   </property>
+   <property name="topMargin">
+    <number>5</number>
+   </property>
+   <property name="rightMargin">
+    <number>5</number>
+   </property>
+   <property name="bottomMargin">
     <number>5</number>
    </property>
    <item>
-    <widget class="QGroupBox" name="grpToolbox">
+    <widget class="QWidget" name="widgetMain" native="true">
      <property name="styleSheet">
-      <string notr="true">
-
-QToolBar {
-	padding: 0px;
-}</string>
+      <string notr="true"/>
      </property>
-     <property name="title">
-      <string>Main Toolbar</string>
-     </property>
-     <layout class="QVBoxLayout" name="verticalLayout_4">
+     <layout class="QVBoxLayout" name="verticalLayout_15">
       <property name="spacing">
-       <number>2</number>
+       <number>12</number>
       </property>
-      <property name="margin">
+      <property name="leftMargin">
        <number>0</number>
       </property>
-      <item>
-       <widget class="QWidget" name="panelToolbarMode" native="true">
-        <property name="styleSheet">
-         <string notr="true">QToolButton {
-	width: 22px;
-	height: 22px;
-	icon-size: 22px;
-	padding: 1px;
-}</string>
-        </property>
-        <layout class="QVBoxLayout" name="verticalLayout_5">
-         <property name="margin">
-          <number>0</number>
-         </property>
-        </layout>
-       </widget>
-      </item>
-      <item>
-       <widget class="Line" name="line">
-        <property name="orientation">
-         <enum>Qt::Horizontal</enum>
-        </property>
-       </widget>
-      </item>
-      <item>
-       <widget class="QWidget" name="panelToolbarAction" native="true">
-        <property name="styleSheet">
-         <string notr="true">QToolButton {
-	width: 16px;
-	height: 16px;
-	icon-size: 16px;
-	padding: 1px;
-}</string>
-        </property>
-        <layout class="QHBoxLayout" name="horizontalLayout">
-         <property name="margin">
-          <number>0</number>
-         </property>
-        </layout>
-       </widget>
-      </item>
-     </layout>
-    </widget>
-   </item>
-   <item>
-    <widget class="QGroupBox" name="grpInspector">
-     <property name="sizePolicy">
-      <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-       <horstretch>0</horstretch>
-       <verstretch>1</verstretch>
-      </sizepolicy>
-     </property>
-     <property name="title">
-      <string>Cursor Inspector</string>
-     </property>
-     <layout class="QVBoxLayout" name="verticalLayout_2">
-      <property name="spacing">
-       <number>5</number>
+      <property name="topMargin">
+       <number>0</number>
+      </property>
+      <property name="rightMargin">
+       <number>0</number>
       </property>
-      <property name="margin">
+      <property name="bottomMargin">
        <number>0</number>
       </property>
       <item>
-       <widget class="QWidget" name="widget" native="true">
+       <widget class="QGroupBox" name="grpToolbox">
         <property name="styleSheet">
-         <string notr="true">QToolButton {
-  icon-size: 22px;
-  min-width: 1ex;
-  border-top: 1px solid rgb(108, 108, 108);
-  border-bottom: 1px solid rgb(108, 108, 108);
-  border-left: 1px;
-  border-right: 1px;
-  background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(255, 255, 255, 255), stop:0.0394089 rgba(245, 245, 245, 255), stop:0.487685 rgba(226, 226, 226, 255), stop:0.502463 rgba(215, 215, 215, 255), stop:1 rgba(245, 245, 245, 255));
-  width: 25px;
-  height: 25px;
+         <string notr="true">/* *** STYLE WITH 28x28 buttons, dropdown menu option *** */
+
+/*
+QToolBar {
+	padding: 0px;
 }
-QToolButton:hover, QToolButton:checked {
-  background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(255, 255, 255, 255), stop:0.0394089 rgba(214, 228, 245, 255), stop:0.487685 rgba(193, 205, 221, 255), stop:0.502463 rgba(182, 193, 207, 255), stop:1 rgba(215, 228, 245, 255));
-  padding:0px;
-  
+
+QToolButton { 
+    border: 1px solid rgba(255, 255, 255, 0);
+    border-radius: 3px;
+    padding: 0px;
+    margin: 0px;
+    height: 26px;
+    width: 26px;
+    icon-size: 28px;
 }
-</string>
+
+QToolButton:hover { 
+    border-color: #8f8f91;
+    background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
+                                      stop: 0 #f6f7fa, stop: 1 #dadbde);
+}
+
+QToolButton[popupMode="1"] { 
+  padding-right: 6px; 
+}
+
+QToolButton:checked {
+    border-color: #8f8f91;
+    background-color: #bbbbbb;
+}
+
+QToolButton::menu-button {
+    border: 1px solid rgba(255, 255, 255, 0);
+    border-top-right-radius: 3px;
+    border-bottom-right-radius: 3px;
+    width: 10px;
+}
+
+QToolButton::menu-button:hover {
+    border-top-color: #8f8f91;
+    border-bottom-color: #8f8f91;
+    border-right-color: #8f8f91;
+}
+
+QToolButton::menu-button:checked {
+    border-top-color: #8f8f91;
+    border-bottom-color: #8f8f91;
+    border-right-color: #8f8f91;
+}
+
+QToolButton::menu-button:pressed {
+    border-top-color: #8f8f91;
+    border-bottom-color: #8f8f91;
+    border-right-color: #8f8f91;
+}
+
+QToolButton::menu-arrow {
+image: url(:/root/menu-arrow_8.png);
+top:11px;
+}
+
+QToolButton::menu-arrow:open {
+    top: 12px; left: 0px; 
+}
+*/
+
+QToolButton { 
+    border: 1px solid rgba(255, 255, 255, 0);
+    border-radius: 3px;
+    padding: 0px;
+    margin: 0px;
+    height: 22px;
+    width: 22px;
+    icon-size: 24px;
+}
+
+QToolButton:hover { 
+    border-color: #8f8f91;
+    background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
+                                      stop: 0 #f6f7fa, stop: 1 #dadbde);
+}
+
+QToolButton:checked {
+    border-color: #8f8f91;
+    background-color: #bbbbbb;
+}</string>
+        </property>
+        <property name="title">
+         <string>Main Toolbar</string>
         </property>
-        <layout class="QHBoxLayout" name="horizontalLayout_2">
+        <layout class="QVBoxLayout" name="verticalLayout_4">
          <property name="spacing">
+          <number>2</number>
+         </property>
+         <property name="leftMargin">
+          <number>0</number>
+         </property>
+         <property name="topMargin">
           <number>0</number>
          </property>
-         <property name="margin">
+         <property name="rightMargin">
+          <number>0</number>
+         </property>
+         <property name="bottomMargin">
           <number>0</number>
          </property>
          <item>
-          <widget class="QToolButton" name="btnCursorInspector">
-           <property name="minimumSize">
-            <size>
-             <width>25</width>
-             <height>30</height>
-            </size>
-           </property>
-           <property name="toolTip">
-            <string><html><head/><body><p><span style=" font-weight:600;">Cursor Inspector</span></p><p>Examine the voxel under the cursor and enter exact 3D cursor location.</p></body></html></string>
-           </property>
+          <widget class="QWidget" name="panelToolbarMode" native="true">
            <property name="styleSheet">
-            <string notr="true"/>
-           </property>
-           <property name="text">
-            <string>...</string>
-           </property>
-           <property name="icon">
-            <iconset resource="../Resources/SNAPResources.qrc">
-             <normaloff>:/root/crosshair.gif</normaloff>:/root/crosshair.gif</iconset>
-           </property>
-           <property name="checkable">
-            <bool>true</bool>
-           </property>
-           <property name="checked">
-            <bool>true</bool>
-           </property>
-           <property name="autoExclusive">
-            <bool>true</bool>
+            <string notr="true">QQQ_QToolButton {
+	width: 22px;
+	height: 22px;
+	icon-size: 22px;
+	padding: 1px;
+}</string>
            </property>
+           <layout class="QHBoxLayout" name="horizontalLayout_4">
+            <property name="spacing">
+             <number>0</number>
+            </property>
+            <property name="leftMargin">
+             <number>0</number>
+            </property>
+            <property name="topMargin">
+             <number>0</number>
+            </property>
+            <property name="rightMargin">
+             <number>0</number>
+            </property>
+            <property name="bottomMargin">
+             <number>0</number>
+            </property>
+            <item>
+             <widget class="QToolButton" name="btnCrosshair">
+              <property name="text">
+               <string>...</string>
+              </property>
+              <property name="icon">
+               <iconset>
+                <normaloff>:/root/crosshair.gif</normaloff>:/root/crosshair.gif</iconset>
+              </property>
+              <property name="checkable">
+               <bool>true</bool>
+              </property>
+              <property name="checked">
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QToolButton" name="btnZoom">
+              <property name="text">
+               <string>...</string>
+              </property>
+              <property name="icon">
+               <iconset>
+                <normaloff>:/root/zoom.gif</normaloff>:/root/zoom.gif</iconset>
+              </property>
+              <property name="checkable">
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QToolButton" name="btnPolygon">
+              <property name="text">
+               <string>...</string>
+              </property>
+              <property name="icon">
+               <iconset>
+                <normaloff>:/root/poly.gif</normaloff>:/root/poly.gif</iconset>
+              </property>
+              <property name="checkable">
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QToolButton" name="btnPaintbrush">
+              <property name="text">
+               <string>...</string>
+              </property>
+              <property name="icon">
+               <iconset>
+                <normaloff>:/root/paintbrush.gif</normaloff>:/root/paintbrush.gif</iconset>
+              </property>
+              <property name="checkable">
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QToolButton" name="btnSnake">
+              <property name="text">
+               <string>...</string>
+              </property>
+              <property name="icon">
+               <iconset>
+                <normaloff>:/root/snake.gif</normaloff>:/root/snake.gif</iconset>
+              </property>
+              <property name="checkable">
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QToolButton" name="btnAnnotation">
+              <property name="text">
+               <string>...</string>
+              </property>
+              <property name="icon">
+               <iconset>
+                <normaloff>:/root/annotation_28.png</normaloff>:/root/annotation_28.png</iconset>
+              </property>
+              <property name="checkable">
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
+           </layout>
           </widget>
          </item>
          <item>
-          <widget class="QToolButton" name="btnZoomInspector">
-           <property name="minimumSize">
-            <size>
-             <width>25</width>
-             <height>30</height>
-            </size>
-           </property>
-           <property name="toolTip">
-            <string><html><head/><body><p><span style=" font-weight:600;">Zoom Inspector</span></p><p>Control zoom factor in all slice views. </p></body></html></string>
-           </property>
+          <widget class="QWidget" name="panelToolbarMode_3" native="true">
            <property name="styleSheet">
-            <string notr="true"/>
-           </property>
-           <property name="text">
-            <string>...</string>
-           </property>
-           <property name="icon">
-            <iconset resource="../Resources/SNAPResources.qrc">
-             <normaloff>:/root/zoom.gif</normaloff>:/root/zoom.gif</iconset>
-           </property>
-           <property name="checkable">
-            <bool>true</bool>
-           </property>
-           <property name="autoExclusive">
-            <bool>true</bool>
+            <string notr="true">QQQ_QToolButton {
+	width: 22px;
+	height: 22px;
+	icon-size: 22px;
+	padding: 1px;
+}</string>
            </property>
+           <layout class="QHBoxLayout" name="horizontalLayout_7">
+            <property name="spacing">
+             <number>2</number>
+            </property>
+            <property name="leftMargin">
+             <number>0</number>
+            </property>
+            <property name="topMargin">
+             <number>0</number>
+            </property>
+            <property name="rightMargin">
+             <number>0</number>
+            </property>
+            <property name="bottomMargin">
+             <number>0</number>
+            </property>
+           </layout>
           </widget>
          </item>
          <item>
-          <widget class="QToolButton" name="btnLabelInspector">
-           <property name="minimumSize">
-            <size>
-             <width>25</width>
-             <height>27</height>
-            </size>
-           </property>
-           <property name="toolTip">
-            <string><html><head/><body><p><span style=" font-weight:600;">Label Inspector</span></p><p>Select the foreground and background labels for segmentation tasks. </p></body></html></string>
-           </property>
-           <property name="styleSheet">
-            <string notr="true"/>
-           </property>
-           <property name="text">
-            <string>...</string>
-           </property>
-           <property name="icon">
-            <iconset resource="../Resources/SNAPResources.qrc">
-             <normaloff>:/root/paintbrush.gif</normaloff>:/root/paintbrush.gif</iconset>
-           </property>
-           <property name="checkable">
-            <bool>true</bool>
-           </property>
-           <property name="autoExclusive">
-            <bool>true</bool>
+          <widget class="Line" name="line">
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
            </property>
           </widget>
          </item>
          <item>
-          <widget class="QToolButton" name="btnDisplayInspector">
-           <property name="minimumSize">
-            <size>
-             <width>25</width>
-             <height>27</height>
-            </size>
-           </property>
-           <property name="toolTip">
-            <string><html><head/><body><p><span style=" font-weight:600;">Display Layout Inspector</span></p><p>Control which slice views are shown in the main ITK-SNAP window and how multiple image layers are rendered. </p></body></html></string>
-           </property>
+          <widget class="QWidget" name="panelToolbarAction" native="true">
            <property name="styleSheet">
-            <string notr="true"/>
-           </property>
-           <property name="text">
-            <string>...</string>
-           </property>
-           <property name="icon">
-            <iconset resource="../Resources/SNAPResources.qrc">
-             <normaloff>:/root/dl_toolbox.png</normaloff>:/root/dl_toolbox.png</iconset>
-           </property>
-           <property name="checkable">
-            <bool>true</bool>
-           </property>
-           <property name="autoExclusive">
-            <bool>true</bool>
+            <string notr="true">QToolButton {
+	width: 16px;
+	height: 16px;
+	icon-size: 16px;
+	padding: 1px;
+}
+
+QToolButton::menu-indicator {
+  image:none;
+}
+
+QToolButton::menu-arrow {
+  image:none;
+}
+</string>
            </property>
+           <layout class="QHBoxLayout" name="horizontalLayout">
+            <property name="spacing">
+             <number>2</number>
+            </property>
+            <property name="leftMargin">
+             <number>0</number>
+            </property>
+            <property name="topMargin">
+             <number>0</number>
+            </property>
+            <property name="rightMargin">
+             <number>0</number>
+            </property>
+            <property name="bottomMargin">
+             <number>0</number>
+            </property>
+            <item>
+             <widget class="QToolButton" name="btnUndo">
+              <property name="text">
+               <string>...</string>
+              </property>
+              <property name="icon">
+               <iconset>
+                <normaloff>:/root/icons8_undo-48.png</normaloff>:/root/icons8_undo-48.png</iconset>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QToolButton" name="btnRedo">
+              <property name="text">
+               <string>...</string>
+              </property>
+              <property name="icon">
+               <iconset>
+                <normaloff>:/root/icons8_redo-48.png</normaloff>:/root/icons8_redo-48.png</iconset>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <spacer name="horizontalSpacer_2">
+              <property name="orientation">
+               <enum>Qt::Horizontal</enum>
+              </property>
+              <property name="sizeType">
+               <enum>QSizePolicy::Fixed</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>8</width>
+                <height>20</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+            <item>
+             <widget class="QToolButton" name="btnLayerInspector">
+              <property name="text">
+               <string>...</string>
+              </property>
+              <property name="icon">
+               <iconset>
+                <normaloff>:/root/layer_Inspector_16.png</normaloff>:/root/layer_Inspector_16.png</iconset>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <spacer name="horizontalSpacer_9">
+              <property name="orientation">
+               <enum>Qt::Horizontal</enum>
+              </property>
+              <property name="sizeType">
+               <enum>QSizePolicy::Fixed</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>8</width>
+                <height>20</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+            <item>
+             <widget class="LabelSelectionButton" name="btnLabelSelector">
+              <property name="toolTip">
+               <string><html><head/><body><p><span style=" font-weight:600;">Quick Label Picker</span><br/></p><table border="0" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px;" cellspacing="0" cellpadding="2"><tr><td><p>Active label:</p></td><td><p><span style=" font-weight:600;"><!--FgStart--&g [...]
+              </property>
+              <property name="styleSheet">
+               <string notr="true"/>
+              </property>
+              <property name="text">
+               <string>...</string>
+              </property>
+              <property name="icon">
+               <iconset>
+                <normaloff>:/root/layer_Inspector_16.png</normaloff>:/root/layer_Inspector_16.png</iconset>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QToolButton" name="btnLabelEditor">
+              <property name="text">
+               <string>...</string>
+              </property>
+              <property name="icon">
+               <iconset>
+                <normaloff>:/root/layer_Inspector_16.png</normaloff>:/root/layer_Inspector_16.png</iconset>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <spacer name="horizontalSpacer_8">
+              <property name="orientation">
+               <enum>Qt::Horizontal</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>40</width>
+                <height>20</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+           </layout>
           </widget>
          </item>
+        </layout>
+       </widget>
+      </item>
+      <item>
+       <widget class="QGroupBox" name="grpInspector">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+          <horstretch>0</horstretch>
+          <verstretch>1</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="styleSheet">
+         <string notr="true"/>
+        </property>
+        <property name="title">
+         <string>Cursor Inspector</string>
+        </property>
+        <layout class="QVBoxLayout" name="verticalLayout_2">
+         <property name="spacing">
+          <number>5</number>
+         </property>
+         <property name="leftMargin">
+          <number>0</number>
+         </property>
+         <property name="topMargin">
+          <number>0</number>
+         </property>
+         <property name="rightMargin">
+          <number>0</number>
+         </property>
+         <property name="bottomMargin">
+          <number>0</number>
+         </property>
          <item>
-          <widget class="QToolButton" name="btnSyncInspector">
-           <property name="minimumSize">
-            <size>
-             <width>25</width>
-             <height>27</height>
-            </size>
-           </property>
-           <property name="toolTip">
-            <string><html><head/><body><p><span style=" font-weight:600;">Synchronization Inspector</span></p><p>Adjust synchronization of cursor, zoom and pan across multiple ITK-SNAP sessions running on one computer.</p></body></html></string>
-           </property>
+          <widget class="QWidget" name="widget" native="true">
            <property name="styleSheet">
-            <string notr="true"/>
-           </property>
-           <property name="text">
-            <string>...</string>
-           </property>
-           <property name="icon">
-            <iconset resource="../Resources/SNAPResources.qrc">
-             <normaloff>:/root/network-wireless.png</normaloff>:/root/network-wireless.png</iconset>
-           </property>
-           <property name="checkable">
-            <bool>true</bool>
-           </property>
-           <property name="autoExclusive">
-            <bool>true</bool>
+            <string notr="true">QToolButton {
+  icon-size: 22px;
+  min-width: 1ex;
+  border-top: 1px solid rgb(192, 192, 192);
+  border-bottom: 1px solid rgb(192, 192, 192);
+  border-left: 1px;
+  border-right: 1px;
+  background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(255, 255, 255, 255), stop:0.0394089 rgba(235, 235, 235, 255), stop:0.487685 rgba(216, 216, 216, 255), stop:0.502463 rgba(205, 205, 205, 255), stop:1 rgba(235, 235, 235, 255));
+  width: 25px;
+  height: 25px;
+}
+QToolButton:hover, QToolButton:checked {
+  background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(255, 255, 255, 255), stop:0.0394089 rgba(214, 228, 245, 255), stop:0.487685 rgba(193, 205, 221, 255), stop:0.502463 rgba(182, 193, 207, 255), stop:1 rgba(215, 228, 245, 255));
+  padding:0px;
+}
+QWidget#widget {
+  background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(255, 255, 255, 255), stop:0.0394089 rgba(235, 235, 235, 255), stop:0.487685 rgba(216, 216, 216, 255), stop:0.502463 rgba(205, 205, 205, 255), stop:1 rgba(235, 235, 235, 255));
+  border-top: 1px solid rgb(192, 192, 192);
+  border-bottom: 1px solid rgb(192, 192, 192);
+}
+</string>
            </property>
+           <layout class="QHBoxLayout" name="horizontalLayout_2">
+            <property name="spacing">
+             <number>0</number>
+            </property>
+            <property name="leftMargin">
+             <number>0</number>
+            </property>
+            <property name="topMargin">
+             <number>0</number>
+            </property>
+            <property name="rightMargin">
+             <number>0</number>
+            </property>
+            <property name="bottomMargin">
+             <number>0</number>
+            </property>
+            <item>
+             <widget class="QToolButton" name="btnCursorInspector">
+              <property name="minimumSize">
+               <size>
+                <width>25</width>
+                <height>30</height>
+               </size>
+              </property>
+              <property name="toolTip">
+               <string><html><head/><body><p><span style=" font-weight:600;">Cursor Inspector</span></p><p>Examine the voxel under the cursor and enter exact 3D cursor location.</p></body></html></string>
+              </property>
+              <property name="styleSheet">
+               <string notr="true"/>
+              </property>
+              <property name="text">
+               <string>...</string>
+              </property>
+              <property name="icon">
+               <iconset>
+                <normaloff>:/root/crosshair.gif</normaloff>:/root/crosshair.gif</iconset>
+              </property>
+              <property name="checkable">
+               <bool>true</bool>
+              </property>
+              <property name="checked">
+               <bool>true</bool>
+              </property>
+              <property name="autoExclusive">
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QToolButton" name="btnZoomInspector">
+              <property name="minimumSize">
+               <size>
+                <width>25</width>
+                <height>30</height>
+               </size>
+              </property>
+              <property name="toolTip">
+               <string><html><head/><body><p><span style=" font-weight:600;">Zoom Inspector</span></p><p>Control zoom factor in all slice views. </p></body></html></string>
+              </property>
+              <property name="styleSheet">
+               <string notr="true"/>
+              </property>
+              <property name="text">
+               <string>...</string>
+              </property>
+              <property name="icon">
+               <iconset>
+                <normaloff>:/root/zoom.gif</normaloff>:/root/zoom.gif</iconset>
+              </property>
+              <property name="checkable">
+               <bool>true</bool>
+              </property>
+              <property name="autoExclusive">
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QToolButton" name="btnDisplayInspector">
+              <property name="minimumSize">
+               <size>
+                <width>25</width>
+                <height>27</height>
+               </size>
+              </property>
+              <property name="toolTip">
+               <string><html><head/><body><p><span style=" font-weight:600;">Display Layout Inspector</span></p><p>Control which slice views are shown in the main ITK-SNAP window and how multiple image layers are rendered. </p></body></html></string>
+              </property>
+              <property name="styleSheet">
+               <string notr="true"/>
+              </property>
+              <property name="text">
+               <string>...</string>
+              </property>
+              <property name="icon">
+               <iconset>
+                <normaloff>:/root/dl_toolbox.png</normaloff>:/root/dl_toolbox.png</iconset>
+              </property>
+              <property name="checkable">
+               <bool>true</bool>
+              </property>
+              <property name="autoExclusive">
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QToolButton" name="btnSyncInspector">
+              <property name="minimumSize">
+               <size>
+                <width>25</width>
+                <height>27</height>
+               </size>
+              </property>
+              <property name="toolTip">
+               <string><html><head/><body><p><span style=" font-weight:600;">Synchronization Inspector</span></p><p>Adjust synchronization of cursor, zoom and pan across multiple ITK-SNAP sessions running on one computer.</p></body></html></string>
+              </property>
+              <property name="styleSheet">
+               <string notr="true"/>
+              </property>
+              <property name="text">
+               <string>...</string>
+              </property>
+              <property name="icon">
+               <iconset>
+                <normaloff>:/root/network-wireless.png</normaloff>:/root/network-wireless.png</iconset>
+              </property>
+              <property name="checkable">
+               <bool>true</bool>
+              </property>
+              <property name="autoExclusive">
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QToolButton" name="btnPolygonInspector">
+              <property name="minimumSize">
+               <size>
+                <width>25</width>
+                <height>27</height>
+               </size>
+              </property>
+              <property name="toolTip">
+               <string><html><head/><body><p><span style=" font-weight:600;">Polygon Tool Inspector</span></p><p>Adjust settings associated with the polygon tool.</p></body></html></string>
+              </property>
+              <property name="styleSheet">
+               <string notr="true"/>
+              </property>
+              <property name="text">
+               <string>...</string>
+              </property>
+              <property name="icon">
+               <iconset>
+                <normaloff>:/root/poly.gif</normaloff>:/root/poly.gif</iconset>
+              </property>
+              <property name="checkable">
+               <bool>true</bool>
+              </property>
+              <property name="autoExclusive">
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QToolButton" name="btnPaintbrushInspector">
+              <property name="minimumSize">
+               <size>
+                <width>25</width>
+                <height>27</height>
+               </size>
+              </property>
+              <property name="toolTip">
+               <string><html><head/><body><p><span style=" font-weight:600;">Paintbrush Tool Inspector</span></p><p>Adjust settings associated with the paintbrush tool.</p></body></html></string>
+              </property>
+              <property name="styleSheet">
+               <string notr="true"/>
+              </property>
+              <property name="text">
+               <string>...</string>
+              </property>
+              <property name="icon">
+               <iconset>
+                <normaloff>:/root/paintbrush.gif</normaloff>:/root/paintbrush.gif</iconset>
+              </property>
+              <property name="checkable">
+               <bool>true</bool>
+              </property>
+              <property name="autoExclusive">
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QToolButton" name="btnSnakeInspector">
+              <property name="minimumSize">
+               <size>
+                <width>25</width>
+                <height>27</height>
+               </size>
+              </property>
+              <property name="toolTip">
+               <string><html><head/><body><p><span style=" font-weight:600;">Snake Tool Inspector</span></p><p>Adjust settings associated with the automatic segmentation (snake) tool.</p></body></html></string>
+              </property>
+              <property name="styleSheet">
+               <string notr="true"/>
+              </property>
+              <property name="text">
+               <string>...</string>
+              </property>
+              <property name="icon">
+               <iconset>
+                <normaloff>:/root/snake.gif</normaloff>:/root/snake.gif</iconset>
+              </property>
+              <property name="checkable">
+               <bool>true</bool>
+              </property>
+              <property name="autoExclusive">
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QToolButton" name="btnAnnotateInspector">
+              <property name="minimumSize">
+               <size>
+                <width>25</width>
+                <height>27</height>
+               </size>
+              </property>
+              <property name="toolTip">
+               <string><html><head/><body><p><span style=" font-weight:600;">Annotation Tool Inspector</span></p><p>Adjust settings associated with the annotation tool.</p></body></html></string>
+              </property>
+              <property name="styleSheet">
+               <string notr="true"/>
+              </property>
+              <property name="text">
+               <string>...</string>
+              </property>
+              <property name="icon">
+               <iconset>
+                <normaloff>:/root/annotation_28.png</normaloff>:/root/annotation_28.png</iconset>
+              </property>
+              <property name="checkable">
+               <bool>true</bool>
+              </property>
+              <property name="autoExclusive">
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <spacer name="horizontalSpacer">
+              <property name="orientation">
+               <enum>Qt::Horizontal</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>5</width>
+                <height>20</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+           </layout>
           </widget>
          </item>
          <item>
-          <widget class="QToolButton" name="btnToolInspector">
-           <property name="minimumSize">
-            <size>
-             <width>25</width>
-             <height>27</height>
-            </size>
-           </property>
-           <property name="toolTip">
-            <string><html><head/><body><p><span style=" font-weight:600;">Active Tool Inspector</span></p><p>Adjust parameters and settings specific to the currently selected tool in the main toolbar.</p></body></html></string>
-           </property>
-           <property name="styleSheet">
-            <string notr="true"/>
-           </property>
-           <property name="text">
-            <string>...</string>
-           </property>
-           <property name="icon">
-            <iconset resource="../Resources/SNAPResources.qrc">
-             <normaloff>:/root/tools.png</normaloff>:/root/tools.png</iconset>
-           </property>
-           <property name="checkable">
-            <bool>true</bool>
-           </property>
-           <property name="autoExclusive">
-            <bool>true</bool>
+          <widget class="QStackedWidget" name="stack">
+           <property name="currentIndex">
+            <number>0</number>
            </property>
+           <widget class="CursorInspector" name="pageCursorInspector"/>
+           <widget class="ZoomInspector" name="pageZoomInspector"/>
+           <widget class="DisplayLayoutInspector" name="pageDisplayInspector">
+            <property name="toolTip">
+             <string/>
+            </property>
+           </widget>
+           <widget class="SynchronizationInspector" name="pageSyncInspector">
+            <property name="toolTip">
+             <string/>
+            </property>
+           </widget>
+           <widget class="SnakeToolROIPanel" name="pageSnakeTool"/>
+           <widget class="PaintbrushToolPanel" name="pagePaintbrushTool"/>
+           <widget class="PolygonToolPanel" name="pagePolygonTool"/>
+           <widget class="AnnotationToolPanel" name="pageAnnotationTool"/>
+           <widget class="QWidget" name="pageBlank"/>
           </widget>
          </item>
         </layout>
        </widget>
       </item>
       <item>
-       <widget class="QStackedWidget" name="stack">
-        <property name="currentIndex">
-         <number>0</number>
-        </property>
-        <widget class="CursorInspector" name="pageCursorInspector"/>
-        <widget class="ZoomInspector" name="pageZoomInspector"/>
-        <widget class="LabelInspector" name="pageLabelInspector"/>
-        <widget class="DisplayLayoutInspector" name="pageDisplayInspector">
-         <property name="toolTip">
-          <string/>
-         </property>
-        </widget>
-        <widget class="SynchronizationInspector" name="pageSyncInspector">
-         <property name="toolTip">
-          <string/>
-         </property>
-        </widget>
-        <widget class="QWidget" name="pageToolInspector">
-         <property name="toolTip">
-          <string/>
-         </property>
-         <layout class="QVBoxLayout" name="verticalLayout_3">
-          <property name="spacing">
-           <number>0</number>
-          </property>
-          <property name="margin">
-           <number>0</number>
-          </property>
-          <item>
-           <widget class="QStackedWidget" name="stackToolPage">
-            <property name="currentIndex">
-             <number>1</number>
-            </property>
-            <widget class="SnakeToolROIPanel" name="pageSnakeTool"/>
-            <widget class="PaintbrushToolPanel" name="pagePaintbrushTool"/>
-            <widget class="QWidget" name="pageBlank"/>
-           </widget>
-          </item>
-         </layout>
-        </widget>
-       </widget>
-      </item>
-     </layout>
-    </widget>
-   </item>
-   <item>
-    <widget class="QGroupBox" name="grpToolbox3D">
-     <property name="styleSheet">
-      <string notr="true">
+       <widget class="QGroupBox" name="grpToolbox3D_2">
+        <property name="styleSheet">
+         <string notr="true">
 
 QToolBar {
 	padding: 0px;
 }</string>
-     </property>
-     <property name="title">
-      <string>3D Toolbar</string>
-     </property>
-     <layout class="QVBoxLayout" name="verticalLayout_6">
-      <property name="spacing">
-       <number>2</number>
-      </property>
-      <property name="margin">
-       <number>0</number>
-      </property>
-      <item>
-       <widget class="QWidget" name="panelToolbarMode3D" native="true">
-        <property name="styleSheet">
-         <string notr="true">QToolButton {
+        </property>
+        <property name="title">
+         <string>Segmentation Labels</string>
+        </property>
+        <layout class="QHBoxLayout" name="horizontalLayout_3">
+         <property name="spacing">
+          <number>2</number>
+         </property>
+         <property name="leftMargin">
+          <number>0</number>
+         </property>
+         <property name="topMargin">
+          <number>0</number>
+         </property>
+         <property name="rightMargin">
+          <number>0</number>
+         </property>
+         <property name="bottomMargin">
+          <number>0</number>
+         </property>
+         <item>
+          <widget class="LabelInspector" name="labelInspector" native="true">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="styleSheet">
+            <string notr="true">QToolButton {
 	width: 22px;
 	height: 22px;
 	icon-size: 22px;
 	padding: 1px;
 }</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </widget>
+      </item>
+      <item>
+       <widget class="QGroupBox" name="grpToolbox3D">
+        <property name="styleSheet">
+         <string notr="true">QToolButton { 
+    border: 1px solid rgba(255, 255, 255, 0);
+    border-radius: 3px;
+    padding: 0px;
+    margin: 0px;
+    height: 22px;
+    width: 22px;
+    icon-size: 24px;
+}
+
+QToolButton:hover { 
+    border-color: #8f8f91;
+    background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
+                                      stop: 0 #f6f7fa, stop: 1 #dadbde);
+}
+
+QToolButton:checked {
+    border-color: #8f8f91;
+    background-color: #bbbbbb;
+}</string>
+        </property>
+        <property name="title">
+         <string>3D Toolbar</string>
         </property>
-        <layout class="QVBoxLayout" name="verticalLayout_7">
-         <property name="margin">
+        <layout class="QVBoxLayout" name="verticalLayout_6">
+         <property name="spacing">
+          <number>2</number>
+         </property>
+         <property name="leftMargin">
           <number>0</number>
          </property>
+         <property name="topMargin">
+          <number>0</number>
+         </property>
+         <property name="rightMargin">
+          <number>0</number>
+         </property>
+         <property name="bottomMargin">
+          <number>0</number>
+         </property>
+         <item>
+          <widget class="QWidget" name="panelToolbarMode3D" native="true">
+           <property name="styleSheet">
+            <string notr="true"/>
+           </property>
+           <layout class="QHBoxLayout" name="horizontalLayout_8">
+            <property name="spacing">
+             <number>0</number>
+            </property>
+            <property name="leftMargin">
+             <number>0</number>
+            </property>
+            <property name="topMargin">
+             <number>0</number>
+            </property>
+            <property name="rightMargin">
+             <number>0</number>
+            </property>
+            <property name="bottomMargin">
+             <number>0</number>
+            </property>
+            <item>
+             <widget class="QToolButton" name="btnRotate3D">
+              <property name="text">
+               <string>...</string>
+              </property>
+              <property name="icon">
+               <iconset>
+                <normaloff>:/root/rotate3d.gif</normaloff>:/root/rotate3d.gif</iconset>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QToolButton" name="btnCross3D">
+              <property name="text">
+               <string>...</string>
+              </property>
+              <property name="icon">
+               <iconset>
+                <normaloff>:/root/crosshair3D.gif</normaloff>:/root/crosshair3D.gif</iconset>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QToolButton" name="btnSpray">
+              <property name="text">
+               <string>...</string>
+              </property>
+              <property name="icon">
+               <iconset>
+                <normaloff>:/root/spray.gif</normaloff>:/root/spray.gif</iconset>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QToolButton" name="btnScalpel">
+              <property name="text">
+               <string>...</string>
+              </property>
+              <property name="icon">
+               <iconset>
+                <normaloff>:/root/scalpel.gif</normaloff>:/root/scalpel.gif</iconset>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <spacer name="horizontalSpacer_3">
+              <property name="orientation">
+               <enum>Qt::Horizontal</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>40</width>
+                <height>20</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+           </layout>
+          </widget>
+         </item>
         </layout>
        </widget>
       </item>
@@ -468,9 +1070,24 @@ QToolBar {
    <header>SynchronizationInspector.h</header>
    <container>1</container>
   </customwidget>
+  <customwidget>
+   <class>PolygonToolPanel</class>
+   <extends>QWidget</extends>
+   <header>PolygonToolPanel.h</header>
+   <container>1</container>
+  </customwidget>
+  <customwidget>
+   <class>AnnotationToolPanel</class>
+   <extends>QWidget</extends>
+   <header>AnnotationToolPanel.h</header>
+   <container>1</container>
+  </customwidget>
+  <customwidget>
+   <class>LabelSelectionButton</class>
+   <extends>QToolButton</extends>
+   <header>LabelSelectionButton.h</header>
+  </customwidget>
  </customwidgets>
- <resources>
-  <include location="../Resources/SNAPResources.qrc"/>
- </resources>
+ <resources/>
  <connections/>
 </ui>
diff --git a/GUI/Qt/Windows/MainImageWindow.cxx b/GUI/Qt/Windows/MainImageWindow.cxx
index ba7c907..267efdf 100644
--- a/GUI/Qt/Windows/MainImageWindow.cxx
+++ b/GUI/Qt/Windows/MainImageWindow.cxx
@@ -86,9 +86,84 @@
 #include <QDesktopServices>
 #include <SNAPQtCommon.h>
 #include <QMimeData>
-
+#include <QDesktopWidget>
 #include <QShortcut>
 
+#include <QTextStream>
+
+QString read_tooltip_qt(const QString &filename)
+{
+  QFile file(filename);
+  file.open(QFile::ReadOnly);
+  QTextStream ts(&file);
+  QString result = ts.readAll();
+  file.close();;
+
+  return result;
+}
+
+class ModeTooltipBuilder
+{
+public:
+  ModeTooltipBuilder(QString title, QString descr)
+  {
+    m_Title = title;
+    m_Descr = descr;
+
+    // Read the HTML templates
+    if(m_RowTemplate.isEmpty())
+      {
+      m_RowTemplate = ReadResource(":/html/TipTableRow");
+      m_MainTemplate = ReadResource(":/html/ModeTipTemplate");
+      }
+  }
+
+  enum Action { LMB, RMB, SCROLL };
+
+  void addMouseAction(Action action, QString descr, QString modifier = "")
+  {
+    QString row = m_RowTemplate;
+    QString atext;
+    switch(action)
+      {
+      case ModeTooltipBuilder::LMB:
+        atext = "left_click"; break;
+      case ModeTooltipBuilder::RMB:
+        atext = "right_click"; break;
+      case ModeTooltipBuilder::SCROLL:
+        atext = "scrolling"; break;
+      }
+
+    QString fullrow = row.arg(atext).arg(descr).arg(modifier);
+    m_Rows.append(fullrow);
+  }
+
+  QString makeTooltip()
+  {
+    QString tooltip = m_MainTemplate;
+    return tooltip.arg(m_Title, m_Descr, m_Rows);
+  }
+
+private:
+
+  QString ReadResource(QString tag)
+  {
+    QFile file(tag);
+    file.open(QFile::ReadOnly);
+    QTextStream ts(&file);
+    QString result = ts.readAll();
+    file.close();
+    return result;
+  }
+
+
+  QString m_Title, m_Descr, m_Rows;
+  static QString m_RowTemplate, m_MainTemplate;
+};
+
+QString ModeTooltipBuilder::m_MainTemplate;
+QString ModeTooltipBuilder::m_RowTemplate;
+
 
 MainImageWindow::MainImageWindow(QWidget *parent) :
     QMainWindow(parent),
@@ -104,6 +179,7 @@ MainImageWindow::MainImageWindow(QWidget *parent) :
   ui->actionPolygon->setActionGroup(grpToolbarMain);
   ui->actionPaintbrush->setActionGroup(grpToolbarMain);
   ui->actionSnake->setActionGroup(grpToolbarMain);
+  ui->actionAnnotation->setActionGroup(grpToolbarMain);
 
   QActionGroup *grpToolbar3D = new QActionGroup(this);
   ui->action3DTrackball->setActionGroup(grpToolbar3D);
@@ -142,6 +218,7 @@ MainImageWindow::MainImageWindow(QWidget *parent) :
         QDockWidget::DockWidgetFloatable |
         QDockWidget::DockWidgetMovable);
   m_DockLeft->setWindowTitle("ITK-SNAP Toolbox");
+  // m_DockLeft->setTitleBarWidget(new QWidget());
   this->addDockWidget(Qt::LeftDockWidgetArea, m_DockLeft);
 
   m_ControlPanel = new MainControlPanel(this);
@@ -223,6 +300,11 @@ MainImageWindow::MainImageWindow(QWidget *parent) :
   connect(ui->actionRecent_3, SIGNAL(triggered()), SLOT(LoadRecentActionTriggered()));
   connect(ui->actionRecent_4, SIGNAL(triggered()), SLOT(LoadRecentActionTriggered()));
   connect(ui->actionRecent_5, SIGNAL(triggered()), SLOT(LoadRecentActionTriggered()));
+  connect(ui->actionRecentOverlay_1, SIGNAL(triggered()), SLOT(LoadRecentOverlayActionTriggered()));
+  connect(ui->actionRecentOverlay_2, SIGNAL(triggered()), SLOT(LoadRecentOverlayActionTriggered()));
+  connect(ui->actionRecentOverlay_3, SIGNAL(triggered()), SLOT(LoadRecentOverlayActionTriggered()));
+  connect(ui->actionRecentOverlay_4, SIGNAL(triggered()), SLOT(LoadRecentOverlayActionTriggered()));
+  connect(ui->actionRecentOverlay_5, SIGNAL(triggered()), SLOT(LoadRecentOverlayActionTriggered()));
   connect(ui->actionRecentWorkspace1, SIGNAL(triggered()), SLOT(LoadRecentProjectActionTriggered()));
   connect(ui->actionRecentWorkspace2, SIGNAL(triggered()), SLOT(LoadRecentProjectActionTriggered()));
   connect(ui->actionRecentWorkspace3, SIGNAL(triggered()), SLOT(LoadRecentProjectActionTriggered()));
@@ -252,6 +334,78 @@ MainImageWindow::MainImageWindow(QWidget *parent) :
   this->HookupSecondaryShortcutToAction(QKeySequence(","), ui->actionForegroundLabelPrev);
   this->HookupSecondaryShortcutToAction(QKeySequence("."), ui->actionForegroundLabelNext);
   this->HookupShortcutToAction(QKeySequence("C"), ui->actionCenter_on_Cursor);
+
+  this->HookupShortcutToAction(QKeySequence("\\"), ui->actionToggleLayerLayout);
+  this->HookupShortcutToAction(QKeySequence("["), ui->actionActivatePreviousLayer);
+  this->HookupShortcutToAction(QKeySequence("]"), ui->actionActivateNextLayer);
+
+  // Common modifiers
+  const QString mod_option(QChar(0x2325));
+  const QString mod_shift(QChar(0x21e7));
+
+  // Generate tooltips for the complex actions
+  ModeTooltipBuilder ttCrosshair("Crosshair Mode (1)",
+                                 "Used to position the 3D cursor in the three orthogonal image slices.");
+  ttCrosshair.addMouseAction(ModeTooltipBuilder::LMB, "<b>Place and move the 3D cursor</b>");
+  ttCrosshair.addMouseAction(ModeTooltipBuilder::RMB, "Zoom in and out (hold & drag)");
+  ttCrosshair.addMouseAction(ModeTooltipBuilder::LMB, "Pan (hold & drag)",mod_option);
+  ttCrosshair.addMouseAction(ModeTooltipBuilder::SCROLL, "Go to next/previous image slice");
+  ttCrosshair.addMouseAction(ModeTooltipBuilder::SCROLL, "Go to next/previous image component",mod_shift);
+  ui->actionCrosshair->setToolTip(ttCrosshair.makeTooltip());
+
+  ModeTooltipBuilder ttZoom("Zoom/Pan Mode (2)",
+                            "Used to zoom into the image and to pan around when zoomed in.");
+  ttZoom.addMouseAction(ModeTooltipBuilder::LMB, "<b>Pan (hold & drag)</b>");
+  ttZoom.addMouseAction(ModeTooltipBuilder::RMB, "<b>Zoom in and out (hold & drag)</b>");
+  ttZoom.addMouseAction(ModeTooltipBuilder::LMB, "Place and move the 3D cursor", mod_option);
+  ttZoom.addMouseAction(ModeTooltipBuilder::SCROLL, "Scroll through image slices");
+  ttZoom.addMouseAction(ModeTooltipBuilder::SCROLL, "Scroll through image components",mod_shift);
+  ui->actionZoomPan->setToolTip(ttZoom.makeTooltip());
+
+  ModeTooltipBuilder ttPolygon("Polygon Mode (3)",
+                               "Used to perform manual segmentation by drawing and filling polygons in the three orthogonal image slices.");
+  ttPolygon.addMouseAction(ModeTooltipBuilder::LMB, "<b>Add points to the polygon and edit the completed polygon</b>");
+  ttPolygon.addMouseAction(ModeTooltipBuilder::RMB, "Zoom in and out (hold & drag)");
+  ttPolygon.addMouseAction(ModeTooltipBuilder::LMB, "Place and move the 3D cursor",mod_option);
+  ttPolygon.addMouseAction(ModeTooltipBuilder::SCROLL, "Scroll through image slices");
+  ttPolygon.addMouseAction(ModeTooltipBuilder::SCROLL, "Scroll through image components",mod_shift);
+  ui->actionPolygon->setToolTip(ttPolygon.makeTooltip());
+
+  ModeTooltipBuilder ttPaintbrush("Paintbrush Mode (4)",
+                               "Used to perform manual segmentation by drawing with a paintbrush-like tool. "
+                               "Different brush shapes are available, including an adaptive brush that adjusts itself to the image data.");
+  ttPaintbrush.addMouseAction(ModeTooltipBuilder::LMB, "<b>Paint with the active label</b>");
+  ttPaintbrush.addMouseAction(ModeTooltipBuilder::RMB, "<b>Erase voxels painted with the active label</b>");
+  ttPaintbrush.addMouseAction(ModeTooltipBuilder::LMB, "Place and move the 3D cursor",mod_option);
+  ttPaintbrush.addMouseAction(ModeTooltipBuilder::SCROLL, "Scroll through image slices");
+  ttPaintbrush.addMouseAction(ModeTooltipBuilder::SCROLL, "Scroll through image components",mod_shift);
+  ui->actionPaintbrush->setToolTip(ttPaintbrush.makeTooltip());
+
+  ModeTooltipBuilder ttSnake("Active Contour (aka \"Snake\") Segmentation Mode (5)",
+                             "Used to select the region of interest for semi-automatic active contour "
+                             "segmentation and start the semi-automatic segmentation wizard.");
+  ttSnake.addMouseAction(ModeTooltipBuilder::LMB, "<b>Adjust the boundaries of the region of interest</b>");
+  ttSnake.addMouseAction(ModeTooltipBuilder::RMB, "Zoom in and out (hold & drag)");
+  ttSnake.addMouseAction(ModeTooltipBuilder::LMB, "Place and move the 3D cursor",mod_option);
+  ttSnake.addMouseAction(ModeTooltipBuilder::SCROLL, "Scroll through image slices");
+  ttSnake.addMouseAction(ModeTooltipBuilder::SCROLL, "Scroll through image components",mod_shift);
+  ui->actionSnake->setToolTip(ttSnake.makeTooltip());
+
+  ModeTooltipBuilder ttRuler("Image Annotation Mode (6)",
+                             "Used to draw annotations (lines, text) on image slices and to measure "
+                             "distances and angles between points in a slice.");
+  ttRuler.addMouseAction(ModeTooltipBuilder::LMB, "<b>Draw and edit annotations</b>");
+  ttRuler.addMouseAction(ModeTooltipBuilder::RMB, "Zoom in and out (hold & drag)");
+  ttRuler.addMouseAction(ModeTooltipBuilder::LMB, "Place and move the 3D cursor",mod_option);
+  ttRuler.addMouseAction(ModeTooltipBuilder::SCROLL, "Scroll through image slices");
+  ttRuler.addMouseAction(ModeTooltipBuilder::SCROLL, "Scroll through image components",mod_shift);
+  ui->actionAnnotation->setToolTip(ttRuler.makeTooltip());
+
+  // Translate the tooltips in all the widgets. This changes the apple symbols that are currently
+  // hard coded in the tooltips into their Windows/Linux equivalents
+#ifndef __APPLE__
+  TranslateChildTooltipKeyModifiers(this);
+#endif
 }
 
 
@@ -264,7 +418,7 @@ MainImageWindow::~MainImageWindow()
 void MainImageWindow::HookupShortcutToAction(const QKeySequence &ks, QAction *action)
 {
   // The bug/feature of single-key shortcuts not working is only in MacOS
-#ifdef __APPLE__
+#if QT_VERSION >= 0x050000 && defined __APPLE__
   QShortcut *short_S = new QShortcut(ks, this);
   connect(short_S, SIGNAL(activated()), action, SLOT(trigger()));
 #endif
@@ -306,11 +460,11 @@ void MainImageWindow::Initialize(GlobalUIModel *model)
   // menu. TODO: a more direct way would be to listen to changes to the
   // history, but that requires making history an event-firing object
   LatentITKEventNotifier::connect(model->GetDriver(), LayerChangeEvent(),
-                                  this, SLOT(onModelUpdate(const EventBucket&)));
+                                  this, SLOT(onModelUpdate(EventBucket)));
 
   // Also listen to changes in the image filenames
   LatentITKEventNotifier::connect(model->GetDriver(), WrapperMetadataChangeEvent(),
-                                  this, SLOT(onModelUpdate(const EventBucket&)));
+                                  this, SLOT(onModelUpdate(EventBucket)));
 
   // Hook up the recent lists
   ui->panelRecentImages->Initialize(m_Model, "MainImage");
@@ -332,6 +486,21 @@ void MainImageWindow::Initialize(GlobalUIModel *model)
         model->GetGlobalState()->GetProjectFilenameModel(), ValueChangedEvent(),
         this, SLOT(onModelUpdate(EventBucket)));
 
+  // Listen to changes in the display layout to adjust the dimensions of the main
+  // window in response.
+  LatentITKEventNotifier::connect(
+        model->GetDisplayLayoutModel(), DisplayLayoutModel::DisplayLayoutChangeEvent(),
+        this, SLOT(onModelUpdate(EventBucket)));
+
+  LatentITKEventNotifier::connect(
+        model->GetDisplayLayoutModel(), DisplayLayoutModel::LayerLayoutChangeEvent(),
+        this, SLOT(onModelUpdate(EventBucket)));
+
+  // Watch for changes in the selected layer
+  LatentITKEventNotifier::connect(
+        model->GetDriver()->GetGlobalState()->GetSelectedLayerIdModel(),
+        ValueChangedEvent(), this, SLOT(onModelUpdate(EventBucket)));
+
   // Couple the visibility of each view panel to the correponding property
   // model in DisplayLayoutModel
   DisplayLayoutModel *layoutModel = m_Model->GetDisplayLayoutModel();
@@ -341,13 +510,6 @@ void MainImageWindow::Initialize(GlobalUIModel *model)
                                  layoutModel->GetViewPanelVisibilityModel(i));
     }
 
-  // Populate the recent file menu
-  this->UpdateRecentMenu();
-  this->UpdateRecentProjectsMenu();
-
-  // Update which page is shown
-  this->UpdateMainLayout();
-
   // Set up activations - File menu
   activateOnFlag(ui->actionOpenMain, m_Model, UIF_IRIS_MODE);
   activateOnFlag(ui->menuRecent_Images, m_Model, UIF_IRIS_MODE);
@@ -366,6 +528,10 @@ void MainImageWindow::Initialize(GlobalUIModel *model)
   activateOnFlag(ui->actionBackgroundLabelNext, m_Model, UIF_BASEIMG_LOADED);
   activateOnFlag(ui->actionBackgroundLabelPrev, m_Model, UIF_BASEIMG_LOADED);
 
+  activateOnFlag(ui->actionToggleLayerLayout, m_Model, UIF_MULTIPLE_BASE_LAYERS);
+  activateOnFlag(ui->actionActivateNextLayer, m_Model, UIF_MULTIPLE_BASE_LAYERS);
+  activateOnFlag(ui->actionActivatePreviousLayer, m_Model, UIF_MULTIPLE_BASE_LAYERS);
+
   // Add actions that are not on the menu
   activateOnFlag(ui->actionZoomToFitInAllViews, m_Model, UIF_BASEIMG_LOADED);
   activateOnFlag(ui->actionCenter_on_Cursor, m_Model, UIF_BASEIMG_LOADED);
@@ -387,9 +553,11 @@ void MainImageWindow::Initialize(GlobalUIModel *model)
 
   // Overlay action activations
   activateOnFlag(ui->actionAdd_Overlay, m_Model, UIF_IRIS_WITH_BASEIMG_LOADED);
-  activateOnAllFlags(ui->actionUnload_Last_Overlay, m_Model, UIF_IRIS_WITH_BASEIMG_LOADED, UIF_OVERLAY_LOADED);
+  // activateOnAllFlags(ui->actionUnload_Last_Overlay, m_Model, UIF_IRIS_WITH_BASEIMG_LOADED, UIF_OVERLAY_LOADED);
   activateOnAllFlags(ui->actionUnload_All_Overlays, m_Model, UIF_IRIS_WITH_BASEIMG_LOADED, UIF_OVERLAY_LOADED);
-  activateOnFlag(ui->menuOverlayAppearance, m_Model, UIF_OVERLAY_LOADED);
+  activateOnFlag(ui->actionOverlayVisibilityToggleAll, m_Model, UIF_OVERLAY_LOADED);
+  activateOnFlag(ui->actionOverlayVisibilityDecreaseAll, m_Model, UIF_OVERLAY_LOADED);
+  activateOnFlag(ui->actionOverlayVisibilityIncreaseAll, m_Model, UIF_OVERLAY_LOADED);
 
   // Workspace menu
   activateOnFlag(ui->actionOpenWorkspace, m_Model, UIF_IRIS_MODE);
@@ -402,6 +570,7 @@ void MainImageWindow::Initialize(GlobalUIModel *model)
   activateOnFlag(ui->actionPolygon, m_Model, UIF_BASEIMG_LOADED);
   activateOnFlag(ui->actionSnake, m_Model, UIF_IRIS_WITH_BASEIMG_LOADED);
   activateOnFlag(ui->actionPaintbrush, m_Model, UIF_BASEIMG_LOADED);
+  activateOnFlag(ui->actionAnnotation, m_Model, UIF_BASEIMG_LOADED);
 
   activateOnFlag(ui->action3DCrosshair, m_Model, UIF_BASEIMG_LOADED);
   activateOnFlag(ui->action3DTrackball, m_Model, UIF_BASEIMG_LOADED);
@@ -441,6 +610,8 @@ void MainImageWindow::ShowFirstTime()
   this->UpdateRecentMenu();
   this->UpdateRecentProjectsMenu();
   this->UpdateWindowTitle();
+  this->UpdateLayerLayoutActions();
+  this->UpdateSelectedLayerActions();
 
   // Show the window
   this->show();
@@ -455,16 +626,19 @@ void MainImageWindow::onModelUpdate(const EventBucket &b)
     // Delaying the relayout of the main window seems to reduce the amount of
     // flashing that occurs when loading images.
     // TODO: figure out if we can avoid flashing altogether
-    QTimer::singleShot(200, this, SLOT(UpdateMainLayout()));
+    // QTimer::singleShot(200, this, SLOT(UpdateMainLayout()));
+    this->UpdateMainLayout();
     }
 
   if(b.HasEvent(LayerChangeEvent()) || b.HasEvent(WrapperMetadataChangeEvent()))
     {
     // Update the window title
     this->UpdateWindowTitle();
+    this->UpdateSelectedLayerActions();
     }
 
-  if(b.HasEvent(ValueChangedEvent(), m_Model->GetHistoryModel("MainImage")))
+  if(b.HasEvent(LayerChangeEvent()) ||
+     b.HasEvent(ValueChangedEvent(), m_Model->GetHistoryModel("MainImage")))
     {
     this->UpdateRecentMenu();
     }
@@ -478,10 +652,29 @@ void MainImageWindow::onModelUpdate(const EventBucket &b)
     {
     this->UpdateProjectMenuItems();
     }
+
+  if(b.HasEvent(DisplayLayoutModel::DisplayLayoutChangeEvent()))
+    {
+    this->UpdateCanvasDimensions();
+    }
+
+  if(b.HasEvent(DisplayLayoutModel::LayerLayoutChangeEvent()))
+    {
+    this->UpdateLayerLayoutActions();
+    }
+
+  if(b.HasEvent(ValueChangedEvent(),
+                m_Model->GetDriver()->GetGlobalState()->GetSelectedLayerIdModel()))
+    {
+    this->UpdateSelectedLayerActions();
+    }
 }
 
 void MainImageWindow::UpdateMainLayout()
 {
+  // Update the image dimensions
+  this->UpdateCanvasDimensions();
+
   // Choose what page to show depending on if an image has been loaded
   if(m_Model->GetDriver()->IsMainImageLoaded())
     {
@@ -505,6 +698,100 @@ void MainImageWindow::UpdateMainLayout()
 }
 
 
+void MainImageWindow::UpdateCanvasDimensions()
+{
+  // We should not do this in fullscreen mode
+  Qt::WindowStates ws = this->windowState();
+  if(ws.testFlag(Qt::WindowFullScreen))
+    {
+    return;
+    }
+
+  // Get the current desktop dimensions
+  QRect desktop = QApplication::desktop()->availableGeometry(this);
+
+  // The desired window aspect ratio
+  double windowAR = 1.0;
+
+  // Get the current aspect ratio
+  if(m_Model->GetDriver()->IsMainImageLoaded())
+    {
+    if(m_Model->GetDisplayLayoutModel()->GetSliceViewLayerLayoutModel()->GetValue() == LAYOUT_TILED)
+      {
+      Vector2ui tiling =
+          m_Model->GetDisplayLayoutModel()->GetSliceViewLayerTilingModel()->GetValue();
+
+      // Compute the tiling aspect ratio
+      double tilingAR = tiling(1) * 1.0 / tiling(0);
+
+      // The tiling aspect ratio should not be mapped directly to the screen aspect ratio -
+      // this creates configurations that are too wide. Instead, we will use a scaling factor
+      windowAR = (tilingAR - 1.0) * 0.6 + 1.0;
+      }
+    else if(m_Model->GetDisplayLayoutModel()->GetNumberOfGroundLevelLayers() > 1)
+      {
+      windowAR = 1.0 / 0.88;
+      }
+    }
+
+  // Adjust the width of the screen to achieve desired aspect ratio
+  int cw_width = static_cast<int>(windowAR * ui->centralwidget->height());
+  int mw_width = this->width() + (cw_width - ui->centralwidget->width());
+
+  // Adjust the width to be within the desktop dimensions
+  mw_width = std::min(desktop.width(), mw_width);
+
+  // Deterimine the left point
+  int left = std::max(0, this->pos().x() + this->width() / 2 - mw_width / 2);
+
+  // Adjust the left point if necessary
+  if(left + mw_width > desktop.right())
+    left = std::max(0, desktop.right() - mw_width);
+
+  // Now we want to position the window nicely.
+  this->resize(QSize(mw_width, this->height()));
+  this->move(left, this->pos().y());
+}
+
+
+void MainImageWindow::UpdateLayerLayoutActions()
+{
+  DisplayLayoutModel *dlm = m_Model->GetDisplayLayoutModel();
+  LayerLayout ll = dlm->GetSliceViewLayerLayoutModel()->GetValue();
+  if(ll == LAYOUT_TILED)
+    {
+    ui->actionToggleLayerLayout->setIcon(QIcon(":/root/layout_thumb_16.png"));
+    ui->actionToggleLayerLayout->setText("Enter Thumbnail Layout");
+    }
+  else if(ll == LAYOUT_STACKED)
+    {
+    ui->actionToggleLayerLayout->setIcon(QIcon(":/root/layout_tile_16.png"));
+    ui->actionToggleLayerLayout->setText("Enter Tiled Layout");
+    }
+}
+
+void MainImageWindow::UpdateSelectedLayerActions()
+{
+  // Find the selected layer
+  ImageWrapperBase *layer =
+      m_Model->GetDriver()->GetCurrentImageData()->FindLayer(
+        m_Model->GetGlobalState()->GetSelectedLayerId(), false);
+
+  if(layer)
+    {
+    ui->actionUnload_Last_Overlay->setVisible(true);
+    ui->actionUnload_Last_Overlay->setEnabled(true);
+    ui->actionUnload_Last_Overlay->setText(
+          QString("Close image \"%1\"").arg(from_utf8(layer->GetNickname())));
+    }
+  else
+    {
+    ui->actionUnload_Last_Overlay->setVisible(false);
+    ui->actionUnload_Last_Overlay->setEnabled(false);
+    ui->actionUnload_Last_Overlay->setText("Close selected image");
+    }
+}
+
 void MainImageWindow::UpdateRecentMenu()
 {
   // Menus to populate
@@ -532,6 +819,33 @@ void MainImageWindow::UpdateRecentMenu()
       menus[i]->setEnabled(false);
       }
     }
+
+  // Do the same for the overlay menus
+  QAction *omenus[] = {
+    ui->actionRecentOverlay_1,
+    ui->actionRecentOverlay_2,
+    ui->actionRecentOverlay_3,
+    ui->actionRecentOverlay_4,
+    ui->actionRecentOverlay_5};
+
+  // List of filenames - from local history
+  recent = m_Model->GetRecentHistoryItems("AnatomicImage", 5, false);
+
+  // Toggle the state of each menu item
+  for(int i = 0; i < 5; i++)
+    {
+    if(i < recent.size())
+      {
+      omenus[i]->setText(from_utf8(recent[i]));
+      omenus[i]->setEnabled(true);
+      }
+    else
+      {
+      omenus[i]->setText("Not available");
+      omenus[i]->setEnabled(false);
+      }
+    }
+
 }
 
 void MainImageWindow::UpdateRecentProjectsMenu()
@@ -568,32 +882,49 @@ void MainImageWindow::UpdateRecentProjectsMenu()
 void MainImageWindow::UpdateWindowTitle()
 {
   GenericImageData *gid = m_Model->GetDriver()->GetIRISImageData();
-  QString mainfile, segfile;
+  QString mainfile, segfile, projfile;
   if(gid && gid->IsMainLoaded())
     {
     mainfile = QFileInfo(from_utf8(gid->GetMain()->GetFileName())).fileName();
     segfile = QFileInfo(from_utf8(gid->GetSegmentation()->GetFileName())).fileName();
     }
 
-  if(mainfile.length())
+  // If a project is loaded, we display the project title
+  if(m_Model->GetGlobalState()->GetProjectFilename().length())
+    projfile = QFileInfo(from_utf8(m_Model->GetGlobalState()->GetProjectFilename())).fileName();
+
+  // Set up the window title
+  if(projfile.length())
     {
-    if(segfile.length())
-      {
-      this->setWindowTitle(QString("%1 - %2 - ITK-SNAP").arg(mainfile).arg(segfile));
-      ui->actionSaveSegmentation->setText(QString("Save \"%1\"").arg(segfile));
-      ui->actionSaveSegmentationAs->setText(QString("Save \"%1\" as...").arg(segfile));
-      ui->actionSaveSegmentationAs->setVisible(true);
-      }
-    else
-      {
-      this->setWindowTitle(QString("%1 - New Segmentation - ITK-SNAP").arg(mainfile));
-      ui->actionSaveSegmentation->setText(QString("Save Segmentation Image ..."));
-      ui->actionSaveSegmentationAs->setVisible(false);
-      }
+    this->setWindowTitle(QString("%1 - ITK-SNAP").arg(projfile));
+    }
+  else if(mainfile.length() && segfile.length())
+    {
+    this->setWindowTitle(QString("%1 - %2 - ITK-SNAP").arg(mainfile).arg(segfile));
+    }
+  else if(mainfile.length())
+    {
+    this->setWindowTitle(QString("%1 - New Segmentation - ITK-SNAP").arg(mainfile));
     }
   else
     {
     this->setWindowTitle("ITK-SNAP");
+    }
+
+  // Set up the save segmentation menu items
+  if(segfile.length())
+    {
+    ui->actionSaveSegmentation->setText(QString("Save \"%1\"").arg(segfile));
+    ui->actionSaveSegmentationAs->setText(QString("Save \"%1\" as...").arg(segfile));
+    ui->actionSaveSegmentationAs->setVisible(true);
+    }
+  else if(mainfile.length())
+    {
+    ui->actionSaveSegmentation->setText(QString("Save Segmentation Image ..."));
+    ui->actionSaveSegmentationAs->setVisible(false);
+    }
+  else
+    {
     ui->actionSaveSegmentation->setText(QString("Save"));
     ui->actionSaveSegmentationAs->setText(QString("Save as..."));
     }
@@ -793,9 +1124,79 @@ void MainImageWindow::LoadDroppedFile(QString file)
     }
 }
 
+#ifdef __APPLE__
+#include <CoreFoundation/CFError.h>
+#include <CoreFoundation/CFURL.h>
+#endif
+
 void MainImageWindow::dropEvent(QDropEvent *event)
 {
-  QString file = event->mimeData()->urls().first().toLocalFile();
+  QUrl url = event->mimeData()->urls().first();
+
+#if defined(__APPLE__) && QT_VERSION >= 0x050000
+  // TODO: this is a Yosemite bug fix - bug https://bugreports.qt.io/browse/QTBUG-40449
+  // Check if this is still necessary in future Qt versions (discovered in Qt 5.4)
+  if (url.toString().startsWith("file:///.file/id="))
+    {
+    CFURLRef cfurl = url.toCFURL();
+    CFErrorRef error = 0;
+    CFURLRef absurl = CFURLCreateFilePathURL(kCFAllocatorDefault, cfurl, &error);
+    url = QUrl::fromCFURL(absurl);
+    CFRelease(cfurl);
+    CFRelease(absurl);
+    }
+
+#elif defined(__APPLE__) && QT_VERSION < 0x050000
+
+  QString localFileQString = url.toLocalFile();
+  // [pzion 20150805] Work around
+  // https://bugreports.qt.io/browse/QTBUG-40449
+  if ( localFileQString.startsWith("/.file/id=") )
+    {
+    CFStringRef relCFStringRef =
+        CFStringCreateWithCString(
+          kCFAllocatorDefault,
+          localFileQString.toUtf8().constData(),
+          kCFStringEncodingUTF8
+          );
+    CFURLRef relCFURL =
+        CFURLCreateWithFileSystemPath(
+          kCFAllocatorDefault,
+          relCFStringRef,
+          kCFURLPOSIXPathStyle,
+          false // isDirectory
+          );
+    CFErrorRef error = 0;
+    CFURLRef absCFURL =
+        CFURLCreateFilePathURL(
+          kCFAllocatorDefault,
+          relCFURL,
+          &error
+          );
+    if ( !error )
+      {
+      static const CFIndex maxAbsPathCStrBufLen = 4096;
+      char absPathCStr[maxAbsPathCStrBufLen];
+      if ( CFURLGetFileSystemRepresentation(
+             absCFURL,
+             true, // resolveAgainstBase
+             reinterpret_cast<UInt8 *>( &absPathCStr[0] ),
+             maxAbsPathCStrBufLen
+             ) )
+        {
+        localFileQString = QString( absPathCStr );
+        }
+      }
+    CFRelease( absCFURL );
+    CFRelease( relCFURL );
+    CFRelease( relCFStringRef );
+
+    url = QUrl::fromLocalFile(localFileQString);
+    }
+
+#endif
+
+  QString file = url.toLocalFile();
   LoadDroppedFile(file);
   event->acceptProposedAction();
 }
@@ -835,6 +1236,7 @@ void MainImageWindow::LoadMainImage(const QString &file)
     {
     ReportNonLethalException(this, exc, "Image IO Error",
                              QString("Failed to load image %1").arg(file));
+
     }
 }
 
@@ -846,6 +1248,29 @@ void MainImageWindow::LoadRecentActionTriggered()
   LoadMainImage(file);
 }
 
+void MainImageWindow::LoadRecentOverlayActionTriggered()
+{
+  // Get the filename that wants to be loaded
+  QAction *action = qobject_cast<QAction *>(sender());
+  QString file = action->text();
+
+  // Try loading the image
+  try
+    {
+    // Change cursor for this operation
+    QtCursorOverride c(Qt::WaitCursor);
+    IRISWarningList warnings;
+    SmartPtr<LoadOverlayImageDelegate> del = LoadOverlayImageDelegate::New();
+    del->Initialize(m_Model->GetDriver());
+    m_Model->GetDriver()->LoadImageViaDelegate(file.toUtf8().constData(), del, warnings);
+    }
+  catch(exception &exc)
+    {
+    ReportNonLethalException(this, exc, "Image IO Error",
+                             QString("Failed to load overlay image %1").arg(file));
+    }
+}
+
 void MainImageWindow::LoadProject(const QString &file)
 {
   // Try loading the image
@@ -889,13 +1314,8 @@ void MainImageWindow::onSnakeWizardFinished()
   // Make the dock containing the wizard visible
   m_DockRight->setVisible(false);
 
-  // TODO: this way of handling the size of the main window after the right
-  // dock is hidden is rudimentary. I should learn how to use sizePolicy and
-  // sizeHint fields more effectively.
-
-  // Return to previous size
-  this->layout()->activate();
-  resize(m_SizeWithoutRightDock.width(), m_SizeWithoutRightDock.height());
+  // Auto-adjust the canvas size
+  this->UpdateCanvasDimensions();
 }
 
 void MainImageWindow::on_actionUnload_All_triggered()
@@ -991,7 +1411,22 @@ void MainImageWindow::on_actionAdd_Overlay_triggered()
   delegate->Initialize(m_Model->GetDriver());
   SmartPtr<ImageIOWizardModel> model = ImageIOWizardModel::New();
   model->InitializeForLoad(m_Model, delegate,
-                           "AnatomicImage", "Overlay Image");
+                           "AnatomicImage", "Additional Image");
+
+  // Execute the IO wizard
+  ImageIOWizard wiz(this);
+  wiz.SetModel(model);
+  wiz.exec();
+}
+
+
+void MainImageWindow::on_actionCoregister_Overlay_triggered()
+{
+  SmartPtr<LoadCoregisteredOverlayImageDelegate> delegate = LoadCoregisteredOverlayImageDelegate::New();
+  delegate->Initialize(m_Model->GetDriver());
+  SmartPtr<ImageIOWizardModel> model = ImageIOWizardModel::New();
+  model->InitializeForLoad(m_Model, delegate,
+                           "AnatomicImage", "Coregistered Overlay Image");
 
   // Execute the IO wizard
   ImageIOWizard wiz(this);
@@ -999,6 +1434,7 @@ void MainImageWindow::on_actionAdd_Overlay_triggered()
   wiz.exec();
 }
 
+
 void MainImageWindow::ExportScreenshot(int panelIndex)
 {
   // Generate a filename for the screenshot
@@ -1100,7 +1536,7 @@ void MainImageWindow::ExportScreenshotSeries(AnatomicalDirection direction)
 
     // Repaint the GL window and save screenshot
     target->SaveScreenshot(filename);
-    target->updateGL();
+    target->update();
     // QCoreApplication::processEvents();
 
     // Go to the next slice
@@ -1204,6 +1640,9 @@ bool MainImageWindow::SaveSegmentation(bool interactive)
 
 void MainImageWindow::RaiseDialog(QDialog *dialog)
 {
+  // propagate the attributes.
+  dialog->setAttribute(Qt::WA_PaintOnScreen, this->testAttribute(Qt::WA_PaintOnScreen));
+
   dialog->show();
   dialog->activateWindow();
   dialog->raise();
@@ -1601,8 +2040,10 @@ void MainImageWindow::on_actionDocumentation_Home_triggered()
 
 void MainImageWindow::on_actionNew_ITK_SNAP_Window_triggered()
 {
-  // Launch a new SNAP
+  // Launch a new SNAP in the relevant directory
   std::list<std::string> args;
+  args.push_back("--cwd");
+  args.push_back(to_utf8(GetFileDialogPath(m_Model, "MainImage")));
   m_Model->GetSystemInterface()->LaunchChildSNAPSimple(args);
 }
 
@@ -1623,12 +2064,43 @@ void MainImageWindow::changeEvent(QEvent *)
 
 void MainImageWindow::on_actionUnload_Last_Overlay_triggered()
 {
-  // What is the last overlay?
-  ImageWrapperBase *last = m_Model->GetDriver()->GetIRISImageData()->GetLastOverlay();
+  // Get the selected ID
+  unsigned long id_selected = m_Model->GetDriver()->GetGlobalState()->GetSelectedLayerId();
 
-  if(SaveModifiedLayersDialog::PromptForUnsavedChanges(m_Model, OVERLAY_ROLE))
+  // Find the actual layer
+  ImageWrapperBase *layer = m_Model->GetDriver()->GetCurrentImageData()->FindLayer(id_selected, false);
+
+  // Is this layer an overlay or a main image
+  if(layer && layer == m_Model->GetDriver()->GetCurrentImageData()->GetMain())
     {
-    m_Model->GetDriver()->UnloadOverlay(last);
+    // Prompt for unsaved changes
+    if(SaveModifiedLayersDialog::PromptForUnsavedChanges(m_Model))
+      {
+      // Unload the main image
+      m_Model->GetDriver()->UnloadMainImage();
+      }
     }
+  else
+    {
+    if(SaveModifiedLayersDialog::PromptForUnsavedChanges(m_Model, OVERLAY_ROLE))
+      {
+      m_Model->GetDriver()->UnloadOverlay(layer);
+      }
+    }
+}
+
+
+void MainImageWindow::on_actionToggleLayerLayout_triggered()
+{
+  m_Model->GetDisplayLayoutModel()->ToggleSliceViewLayerLayout();
+}
+
+void MainImageWindow::on_actionActivateNextLayer_triggered()
+{
+  m_Model->GetDisplayLayoutModel()->ActivateNextLayerInTiledMode();
+}
 
+void MainImageWindow::on_actionActivatePreviousLayer_triggered()
+{
+  m_Model->GetDisplayLayoutModel()->ActivatePrevLayerInTiledMode();
 }
diff --git a/GUI/Qt/Windows/MainImageWindow.h b/GUI/Qt/Windows/MainImageWindow.h
index c43953b..df7fa76 100644
--- a/GUI/Qt/Windows/MainImageWindow.h
+++ b/GUI/Qt/Windows/MainImageWindow.h
@@ -121,6 +121,7 @@ public:
 public slots:
 
   void LoadRecentActionTriggered();
+  void LoadRecentOverlayActionTriggered();
   void LoadRecentProjectActionTriggered();
 
   void AdjustMarginsForDocks();
@@ -216,6 +217,8 @@ private slots:
 
   void UpdateMainLayout();
 
+  void UpdateCanvasDimensions();
+
   // Load image without interaction (used for recent/drop action).
   void LoadMainImage(const QString &file);
 
@@ -268,6 +271,14 @@ private slots:
 
   void on_actionUnload_All_Overlays_triggered();
 
+  void on_actionCoregister_Overlay_triggered();
+
+  void on_actionToggleLayerLayout_triggered();
+
+  void on_actionActivateNextLayer_triggered();
+
+  void on_actionActivatePreviousLayer_triggered();
+
 protected:
 
   // bool eventFilter(QObject *obj, QEvent *event);
@@ -281,7 +292,8 @@ private:
   void UpdateWindowTitle();
   void UpdateProjectMenuItems();
   void UpdateRecentProjectsMenu();
-
+  void UpdateLayerLayoutActions();
+  void UpdateSelectedLayerActions();
 
   // Save the segmentation (interactively or not). Return true if save was
   // successful
diff --git a/GUI/Qt/Windows/MainImageWindow.ui b/GUI/Qt/Windows/MainImageWindow.ui
index 546556c..aaa3c5e 100644
--- a/GUI/Qt/Windows/MainImageWindow.ui
+++ b/GUI/Qt/Windows/MainImageWindow.ui
@@ -13,6 +13,9 @@
   <property name="windowTitle">
    <string>MainWindow</string>
   </property>
+  <property name="styleSheet">
+   <string notr="true"/>
+  </property>
   <widget class="QWidget" name="centralwidget">
    <layout class="QVBoxLayout" name="verticalLayout">
     <property name="spacing">
@@ -33,18 +36,18 @@
     <item>
      <widget class="QStackedWidget" name="stackMain">
       <property name="currentIndex">
-       <number>0</number>
+       <number>1</number>
       </property>
       <widget class="QWidget" name="pageMain">
        <layout class="QGridLayout" name="gridLayout_2">
         <property name="leftMargin">
-         <number>4</number>
+         <number>0</number>
         </property>
         <property name="topMargin">
          <number>4</number>
         </property>
         <property name="rightMargin">
-         <number>4</number>
+         <number>0</number>
         </property>
         <property name="bottomMargin">
          <number>4</number>
@@ -103,7 +106,7 @@ QTabWidget::tab-bar {
 QTabBar:tab {
 	border:none;
 	margin-left: 20px;
-	margin-top: 12px;
+	margin-top: 6px;
 	padding-left: 5px;
 	padding-right: 5px;
 	min-width: 132px;
@@ -133,11 +136,14 @@ QTabBar:tab:hover {
             <property name="leftMargin">
              <number>12</number>
             </property>
+            <property name="topMargin">
+             <number>6</number>
+            </property>
             <property name="rightMargin">
              <number>12</number>
             </property>
             <property name="bottomMargin">
-             <number>12</number>
+             <number>4</number>
             </property>
             <item>
              <widget class="QFrame" name="frame">
@@ -183,7 +189,7 @@ QTextBrowser {
                   <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
 <html><head><meta name="qrichtext" content="1" /><style type="text/css">
 p, li { white-space: pre-wrap; }
-</style></head><body style=" font-family:'.Lucida Grande UI'; font-size:13pt; font-weight:400; font-style:normal;">
+</style></head><body style=" font-family:'.Helvetica Neue DeskInterface'; font-size:13pt; font-weight:400; font-style:normal;">
 <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Lucida Grande';"><br /></p>
 <ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Lucida Grande';" style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Learn about the <a href="http://www.itksnap.org/pmwiki/pmwiki.php?n=Documentation.NewFeaturesVersion30"><span style=" text-decoration: underline; color:#0000ff;& [...]
 <li style=" font-family:'Lucida Grande';" style=" margin-top:0px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Read a <a href="http://www.itksnap.org/pmwiki/pmwiki.php?n=Documentation.UpgradingTo30"><span style=" text-decoration: underline; color:#0000ff;">quick transition guide</span></a> for Version 2 users</li>
@@ -238,14 +244,20 @@ color:rgb(103, 103, 103);
             <string>Recent Images</string>
            </attribute>
            <layout class="QVBoxLayout" name="verticalLayout_3">
+            <property name="spacing">
+             <number>4</number>
+            </property>
             <property name="leftMargin">
              <number>12</number>
             </property>
+            <property name="topMargin">
+             <number>6</number>
+            </property>
             <property name="rightMargin">
              <number>12</number>
             </property>
             <property name="bottomMargin">
-             <number>12</number>
+             <number>4</number>
             </property>
             <item>
              <widget class="RecentHistoryItemsView" name="panelRecentImages" native="true"/>
@@ -257,14 +269,20 @@ color:rgb(103, 103, 103);
             <string>Recent Workspaces</string>
            </attribute>
            <layout class="QVBoxLayout" name="verticalLayout_5">
+            <property name="spacing">
+             <number>4</number>
+            </property>
             <property name="leftMargin">
              <number>12</number>
             </property>
+            <property name="topMargin">
+             <number>6</number>
+            </property>
             <property name="rightMargin">
              <number>12</number>
             </property>
             <property name="bottomMargin">
-             <number>12</number>
+             <number>4</number>
             </property>
             <item>
              <widget class="RecentHistoryItemsView" name="panelRecentWorkspaces" native="true"/>
@@ -276,6 +294,12 @@ color:rgb(103, 103, 103);
         <item>
          <widget class="QWidget" name="widget" native="true">
           <layout class="QHBoxLayout" name="horizontalLayout">
+           <property name="topMargin">
+            <number>4</number>
+           </property>
+           <property name="bottomMargin">
+            <number>6</number>
+           </property>
            <item>
             <spacer name="horizontalSpacer">
              <property name="orientation">
@@ -327,7 +351,7 @@ color:rgb(103, 103, 103);
     </property>
     <widget class="QMenu" name="menuRecent_Images">
      <property name="title">
-      <string>Recent Images</string>
+      <string>Recent Main Images</string>
      </property>
      <addaction name="actionRecent_1"/>
      <addaction name="actionRecent_2"/>
@@ -335,6 +359,16 @@ color:rgb(103, 103, 103);
      <addaction name="actionRecent_4"/>
      <addaction name="actionRecent_5"/>
     </widget>
+    <widget class="QMenu" name="menuRecent_Overlays">
+     <property name="title">
+      <string>Recent Added Images</string>
+     </property>
+     <addaction name="actionRecentOverlay_1"/>
+     <addaction name="actionRecentOverlay_2"/>
+     <addaction name="actionRecentOverlay_3"/>
+     <addaction name="actionRecentOverlay_4"/>
+     <addaction name="actionRecentOverlay_5"/>
+    </widget>
     <widget class="QMenu" name="menuSave_Image">
      <property name="title">
       <string>Save Image</string>
@@ -380,9 +414,14 @@ color:rgb(103, 103, 103);
     <addaction name="actionOpenMain"/>
     <addaction name="menuRecent_Images"/>
     <addaction name="separator"/>
+    <addaction name="actionAdd_Overlay"/>
+    <addaction name="menuRecent_Overlays"/>
+    <addaction name="separator"/>
     <addaction name="menuSave_Image"/>
+    <addaction name="separator"/>
     <addaction name="menuExport"/>
     <addaction name="separator"/>
+    <addaction name="actionUnload_Last_Overlay"/>
     <addaction name="actionUnload_All"/>
     <addaction name="separator"/>
     <addaction name="actionNew_ITK_SNAP_Window"/>
@@ -414,30 +453,12 @@ color:rgb(103, 103, 103);
     <addaction name="actionLoadLabels"/>
     <addaction name="actionSaveLabels"/>
     <addaction name="separator"/>
+    <addaction name="actionLabel_Editor"/>
+    <addaction name="separator"/>
     <addaction name="actionVolumesAndStatistics"/>
     <addaction name="separator"/>
     <addaction name="menuAppearance"/>
    </widget>
-   <widget class="QMenu" name="menuOverlay">
-    <property name="title">
-     <string>Overlay</string>
-    </property>
-    <widget class="QMenu" name="menuOverlayAppearance">
-     <property name="title">
-      <string>Appearance</string>
-     </property>
-     <addaction name="actionOverlayVisibilityToggleAll"/>
-     <addaction name="separator"/>
-     <addaction name="actionOverlayVisibilityIncreaseAll"/>
-     <addaction name="actionOverlayVisibilityDecreaseAll"/>
-    </widget>
-    <addaction name="actionAdd_Overlay"/>
-    <addaction name="separator"/>
-    <addaction name="actionUnload_Last_Overlay"/>
-    <addaction name="actionUnload_All_Overlays"/>
-    <addaction name="separator"/>
-    <addaction name="menuOverlayAppearance"/>
-   </widget>
    <widget class="QMenu" name="menuTools">
     <property name="title">
      <string>Tools</string>
@@ -451,6 +472,7 @@ color:rgb(103, 103, 103);
      <addaction name="actionPolygon"/>
      <addaction name="actionPaintbrush"/>
      <addaction name="actionSnake"/>
+     <addaction name="actionAnnotation"/>
     </widget>
     <widget class="QMenu" name="menuActive_3D_Tool">
      <property name="title">
@@ -470,6 +492,7 @@ color:rgb(103, 103, 103);
      <addaction name="actionAutoContrastGlobal"/>
      <addaction name="actionResetContrastGlobal"/>
     </widget>
+    <addaction name="separator"/>
     <addaction name="actionLayerInspector"/>
     <addaction name="separator"/>
     <addaction name="menuContrast"/>
@@ -479,8 +502,6 @@ color:rgb(103, 103, 103);
     <addaction name="menuActive_Main_Tool"/>
     <addaction name="menuActive_3D_Tool"/>
     <addaction name="separator"/>
-    <addaction name="actionLabel_Editor"/>
-    <addaction name="separator"/>
     <addaction name="actionReorient_Image"/>
     <addaction name="separator"/>
     <addaction name="actionPreferences"/>
@@ -524,6 +545,19 @@ color:rgb(103, 103, 103);
      <addaction name="separator"/>
      <addaction name="actionCenter_on_Cursor"/>
     </widget>
+    <widget class="QMenu" name="menuLayers">
+     <property name="title">
+      <string>Layers</string>
+     </property>
+     <addaction name="actionToggleLayerLayout"/>
+     <addaction name="separator"/>
+     <addaction name="actionActivateNextLayer"/>
+     <addaction name="actionActivatePreviousLayer"/>
+     <addaction name="separator"/>
+     <addaction name="actionOverlayVisibilityToggleAll"/>
+     <addaction name="actionOverlayVisibilityIncreaseAll"/>
+     <addaction name="actionOverlayVisibilityDecreaseAll"/>
+    </widget>
     <addaction name="actionUndo"/>
     <addaction name="actionRedo"/>
     <addaction name="separator"/>
@@ -533,6 +567,8 @@ color:rgb(103, 103, 103);
     <addaction name="menuSlice_Annotations"/>
     <addaction name="separator"/>
     <addaction name="menuZoom"/>
+    <addaction name="separator"/>
+    <addaction name="menuLayers"/>
    </widget>
    <widget class="QMenu" name="menuHelp">
     <property name="title">
@@ -567,14 +603,13 @@ color:rgb(103, 103, 103);
    <addaction name="menuFile"/>
    <addaction name="menuEdit"/>
    <addaction name="menuSegmentation"/>
-   <addaction name="menuOverlay"/>
    <addaction name="menuProject"/>
    <addaction name="menuTools"/>
    <addaction name="menuHelp"/>
   </widget>
   <action name="actionOpenMain">
    <property name="text">
-    <string>Open Image ...</string>
+    <string>Open Main Image ...</string>
    </property>
    <property name="toolTip">
     <string>Open the main anatomy image that you wish to display or segment</string>
@@ -697,10 +732,10 @@ color:rgb(103, 103, 103);
   </action>
   <action name="actionUnload_All">
    <property name="text">
-    <string>Unload All Images</string>
+    <string>Close All Images</string>
    </property>
    <property name="shortcut">
-    <string>Ctrl+U</string>
+    <string>Ctrl+Shift+W</string>
    </property>
   </action>
   <action name="actionClear">
@@ -710,10 +745,10 @@ color:rgb(103, 103, 103);
   </action>
   <action name="actionAdd_Overlay">
    <property name="text">
-    <string>Add Overlay ...</string>
+    <string>Add Another Image ...</string>
    </property>
    <property name="toolTip">
-    <string>Load an image to overlay over the images currently loaded into SNAP</string>
+    <string><html><head/><body><p>Load an image to display alongside the main image. The dimensions of this image must match those of the main image. </p></body></html></string>
    </property>
    <property name="shortcut">
     <string>Ctrl+Shift+G</string>
@@ -728,9 +763,16 @@ color:rgb(103, 103, 103);
    </property>
   </action>
   <action name="actionLabel_Editor">
+   <property name="icon">
+    <iconset resource="../Resources/SNAPResources.qrc">
+     <normaloff>:/root/icons8_palette_16.png</normaloff>:/root/icons8_palette_16.png</iconset>
+   </property>
    <property name="text">
     <string>Label Editor ...</string>
    </property>
+   <property name="toolTip">
+    <string><html><head/><body><p><span style=" font-weight:600;">Label Editor (⌘L)</span></p><p>Opens the label editor, where you can edit segmentation labels.</p></body></html></string>
+   </property>
    <property name="shortcut">
     <string>Ctrl+L</string>
    </property>
@@ -765,11 +807,14 @@ color:rgb(103, 103, 103);
   <action name="actionUndo">
    <property name="icon">
     <iconset resource="../Resources/SNAPResources.qrc">
-     <normaloff>:/root/undo_22.png</normaloff>:/root/undo_22.png</iconset>
+     <normaloff>:/root/icons8_undo-48.png</normaloff>:/root/icons8_undo-48.png</iconset>
    </property>
    <property name="text">
     <string>Undo</string>
    </property>
+   <property name="toolTip">
+    <string><html><head/><body><p><span style=" font-weight:600;">Undo (⌘Z)</span></p><p>Undo the last modification to the segmentation image.</p></body></html></string>
+   </property>
    <property name="shortcut">
     <string>Ctrl+Z</string>
    </property>
@@ -777,11 +822,14 @@ color:rgb(103, 103, 103);
   <action name="actionRedo">
    <property name="icon">
     <iconset resource="../Resources/SNAPResources.qrc">
-     <normaloff>:/root/redo_22.png</normaloff>:/root/redo_22.png</iconset>
+     <normaloff>:/root/icons8_redo-48.png</normaloff>:/root/icons8_redo-48.png</iconset>
    </property>
    <property name="text">
     <string>Redo</string>
    </property>
+   <property name="toolTip">
+    <string><html><head/><body><p><span style=" font-weight:600;">Redo (⇧⌘Z)</span></p><p>Redo the last modification to the segmentation image.</p></body></html></string>
+   </property>
    <property name="shortcut">
     <string>Ctrl+Shift+Z</string>
    </property>
@@ -894,15 +942,18 @@ color:rgb(103, 103, 103);
   </action>
   <action name="actionUnload_Last_Overlay">
    <property name="text">
-    <string>Remove Last Overlay</string>
+    <string>Close Image XXX</string>
    </property>
    <property name="toolTip">
-    <string>Remove the last overlay that was loaded from the workspace</string>
+    <string><html><head/><body><p>Unload the last image layer</p></body></html></string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+W</string>
    </property>
   </action>
   <action name="actionUnload_All_Overlays">
    <property name="text">
-    <string>Remove All Overlays</string>
+    <string>Unload all additional image layers</string>
    </property>
    <property name="toolTip">
     <string>Remove all overlays from the current workspace. Only the main image will remain open.</string>
@@ -911,11 +962,14 @@ color:rgb(103, 103, 103);
   <action name="actionLayerInspector">
    <property name="icon">
     <iconset resource="../Resources/SNAPResources.qrc">
-     <normaloff>:/root/layer_Inspector_16.png</normaloff>:/root/layer_Inspector_16.png</iconset>
+     <normaloff>:/root/icons8_layers_16.png</normaloff>:/root/icons8_layers_16.png</iconset>
    </property>
    <property name="text">
     <string>Layer Inspector...</string>
    </property>
+   <property name="toolTip">
+    <string><html><head/><body><p><span style=" font-weight:600;">Layer Inspector (⌘I)</span></p><p>Opens the layer inspector window, which lists loaded image layers and can be used used to adjust their display properties.</p></body></html></string>
+   </property>
    <property name="shortcut">
     <string>Ctrl+I</string>
    </property>
@@ -935,7 +989,7 @@ color:rgb(103, 103, 103);
     <string>Crosshair Tool</string>
    </property>
    <property name="toolTip">
-    <string><html><head/><body><p><span style=" font-weight:600;">Crosshair Mode</span></p><p>Click and drag the left mouse button to move the 3D cursor in the image. Use the right mouse button to zoom, and the middle mouse button to pan.</p></body></html></string>
+    <string>Crosshair Tool</string>
    </property>
    <property name="shortcut">
     <string>1</string>
@@ -953,7 +1007,7 @@ color:rgb(103, 103, 103);
     <string>Zoom/Pan Mode</string>
    </property>
    <property name="toolTip">
-    <string><html><head/><body><p><span style=" font-weight:600;">Zoom/Pan Mode</span></p><p>Click and drag the left mouse button to pan the slice views. Use the right mouse button to zoom in and out.</p></body></html></string>
+    <string><html><head/><body><p><span style=" font-weight:600;">Zoom/Pan Mode (2)</span></p><p>Use the mouse to zoom in and out of the image, and to pan around when the image is zoomed in. <br/></p><table border="0" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px;" cellspacing="2" cellpadding="0"><tr><td style=" padding-left:5; p [...]
    </property>
    <property name="shortcut">
     <string>2</string>
@@ -971,7 +1025,7 @@ color:rgb(103, 103, 103);
     <string>Polygon Drawing Mode</string>
    </property>
    <property name="toolTip">
-    <string><html><head/><body><p><span style=" font-weight:600;">Polygon Mode</span></p><p>Primary tool for manual segmentation. Use the mouse to draw polygons on the 2D slice views, then edit the polygons and fill them with segmentation labels.</p></body></html></string>
+    <string><html><head/><body><p><span style=" font-weight:600;">Polygon Drawing Mode (3)</span></p><p>Used to perform manual segmentation by drawing and filling polygons in the three orthogonal image slices. <br/></p><table border="0" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px;" cellspacing="2" cellpadding="0"><tr><td style=&quot [...]
    </property>
    <property name="shortcut">
     <string>3</string>
@@ -989,7 +1043,7 @@ color:rgb(103, 103, 103);
     <string>Paintbrush Mode</string>
    </property>
    <property name="toolTip">
-    <string><html><head/><body><p><span style=" font-weight:600;">Paintbrush Mode</span></p><p>A tool for manual editing of segmentations. Hold the left mouse button and drag the mouse to draw with the currently selected label using one of the available brush shapes. Use the right mouse button to draw wuth the background label.</p></body></html></string>
+    <string><html><head/><body><p><span style=" font-weight:600;">Paintbrush Mode (4)</span></p><p>Used to perform manual segmentation by drawing with a paintbrush-like tool. Different brush shapes are available, including an adaptive brush that adjusts itself to the image data. <br/></p><table border="0" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px;" cellspacing=& [...]
    </property>
    <property name="shortcut">
     <string>4</string>
@@ -1007,7 +1061,7 @@ color:rgb(103, 103, 103);
     <string>Active Contour Segmentation Mode</string>
    </property>
    <property name="toolTip">
-    <string><html><head/><body><p><span style=" font-weight:600;">Active Contour Segmentation (Snake) Mode</span></p><p>Select a region of interest (ROI) for automatic segmentation. Use the mouse to move the boundaries of the ROI, then click the &quot;Segment 3D&quot; button to begin automatic segmentation.</p></body></html></string>
+    <string><html><head/><body><p><span style=" font-weight:600;">Active Contour (aka &quot;Snake&quot;) Segmentation Mode (5)</span></p><p>Used to select the region of interest for semi-automatic active contour segmentation and start the semi-automatic segmentation wizard.<br/></p><table border="0" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px;" cellspacing [...]
    </property>
    <property name="shortcut">
     <string>5</string>
@@ -1033,7 +1087,7 @@ color:rgb(103, 103, 103);
     <string>3D Trackball Tool</string>
    </property>
    <property name="toolTip">
-    <string><html><head/><body><p><span style=" font-weight:600;">3D Trackball Mode</span></p><p>Click and drag the left mouse button to rotate the 3D scene. Use the right mouse button to zoom, and the middle mouse button to pan the 3D scene.</p></body></html></string>
+    <string><html><head/><body><p><span style=" font-weight:600;">3D Trackball Mode</span></p><p>Used to manipulate the viewpoint in the 3D window. <br/></p><table border="0" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px;" cellspacing="2" cellpadding="0"><tr><td style=" padding-left:5; padding-right:5; padding-top:0; padding-bott [...]
    </property>
   </action>
   <action name="action3DCrosshair">
@@ -1048,7 +1102,7 @@ color:rgb(103, 103, 103);
     <string>3D Crosshair Tool</string>
    </property>
    <property name="toolTip">
-    <string><html><head/><body><p><span style=" font-weight:600;">3D Crosshair Mode</span></p><p>Click the left button over a segmentation surface in the 3D window to position the 3D cursor at that position.</p></body></html></string>
+    <string><html><head/><body><p><span style=" font-weight:600;">3D Crosshair Mode</span></p><p>Used to place the linked 3D cursor on one of the surfaces rendered in the 3D window. <br/></p><table border="0" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px;" cellspacing="2" cellpadding="0"><tr><td style=" padding-left:5; padding-ri [...]
    </property>
   </action>
   <action name="action3DScalpel">
@@ -1063,7 +1117,7 @@ color:rgb(103, 103, 103);
     <string>3D Scalpel Tool</string>
    </property>
    <property name="toolTip">
-    <string><html><head/><body><p><span style=" font-weight:600;">3D Scalpel Mode</span></p><p>Left-click on two points in the 3D window to define a cutplane. Then click 'Accept' to relabel the segmentation on one side of the cutplane.</p></body></html></string>
+    <string><html><head/><body><p><span style=" font-weight:600;">Scalpel Mode</span></p><p>Used to relabel parts of the 3D scene with a cutplane. Voxels on one side of the cutplane will be assigned the current foreground label. <br/></p><table border="0" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px;" cellspacing="2" cellpadding="0"><tr&gt [...]
    </property>
   </action>
   <action name="action3DSpray">
@@ -1078,12 +1132,15 @@ color:rgb(103, 103, 103);
     <string>3D Spray Paint Tool</string>
    </property>
    <property name="toolTip">
-    <string><html><head/><body><p><span style=" font-weight:600;">Spray Paint Mode</span></p><p>Click and hold the left mouse button to relabel voxels on the boundaries of segmented objects.</p></body></html></string>
+    <string><html><head/><body><p><span style=" font-weight:600;">Spray Paint Mode</span></p><p>Used to add voxels to the surfaces of existing segmentations. <br/></p><table border="0" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px;" cellspacing="2" cellpadding="0"><tr><td style=" padding-left:5; padding-right:5; padding-top:0; pa [...]
    </property>
   </action>
   <action name="actionOverlayVisibilityToggleAll">
    <property name="text">
-    <string>Toggle Visibility (All)</string>
+    <string>Toggle Overlay Visibility</string>
+   </property>
+   <property name="iconText">
+    <string>Toggle Visibility of Sticky Layers</string>
    </property>
    <property name="toolTip">
     <string>Toggle Visibility (All)</string>
@@ -1094,7 +1151,7 @@ color:rgb(103, 103, 103);
   </action>
   <action name="actionOverlayVisibilityIncreaseAll">
    <property name="text">
-    <string>Increase Opacity (All)</string>
+    <string>Increase Overlay Opacity</string>
    </property>
    <property name="shortcut">
     <string>E</string>
@@ -1102,7 +1159,7 @@ color:rgb(103, 103, 103);
   </action>
   <action name="actionOverlayVisibilityDecreaseAll">
    <property name="text">
-    <string>Decrease Opacity (All)</string>
+    <string>Decrease Overlay Opacity</string>
    </property>
    <property name="shortcut">
     <string>Q</string>
@@ -1330,6 +1387,84 @@ color:rgb(103, 103, 103);
     <string>New ITK-SNAP Window</string>
    </property>
   </action>
+  <action name="actionCoregister_Overlay">
+   <property name="text">
+    <string>Coregister Overlay ...</string>
+   </property>
+   <property name="toolTip">
+    <string>Co-register an image with the main image currently loaded into ITK-SNAP</string>
+   </property>
+  </action>
+  <action name="actionRecentOverlay_1">
+   <property name="text">
+    <string>Recent 1</string>
+   </property>
+  </action>
+  <action name="actionRecentOverlay_2">
+   <property name="text">
+    <string>Recent 2</string>
+   </property>
+  </action>
+  <action name="actionRecentOverlay_3">
+   <property name="text">
+    <string>Recent 3</string>
+   </property>
+  </action>
+  <action name="actionRecentOverlay_4">
+   <property name="text">
+    <string>Recent 4</string>
+   </property>
+  </action>
+  <action name="actionRecentOverlay_5">
+   <property name="text">
+    <string>Recent 5</string>
+   </property>
+  </action>
+  <action name="actionAnnotation">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="icon">
+    <iconset resource="../Resources/SNAPResources.qrc">
+     <normaloff>:/root/annotation_28.png</normaloff>:/root/annotation_28.png</iconset>
+   </property>
+   <property name="text">
+    <string>Annotation Tool</string>
+   </property>
+   <property name="toolTip">
+    <string><html><head/><body><p><span style=" font-weight:600;">Annotation Mode (6)</span></p><p>Used to draw annotations (lines, text) on image slices and to measure distance and angles between points in a slice. <br/></p><table border="0" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px;" cellspacing="2" cellpadding="0"><tr><td style [...]
+   </property>
+   <property name="shortcut">
+    <string>6</string>
+   </property>
+  </action>
+  <action name="actionToggleLayerLayout">
+   <property name="text">
+    <string>Thumbnail Layout</string>
+   </property>
+   <property name="toolTip">
+    <string><html><head/><body><p>Toggle between thumbnail and tiled layouts.</p><p>In <span style=" font-weight:600;">thumbnail</span> layout, one image layer occupies most of the available screen space, and other loaded image layers are shown as thumbnails. In <span style=" font-weight:600;">tiled</span> layout, multiple image layers are shown side by side. </p></body></html></string>
+   </property>
+   <property name="shortcut">
+    <string>\</string>
+   </property>
+  </action>
+  <action name="actionActivateNextLayer">
+   <property name="text">
+    <string>Activate Next Layer</string>
+   </property>
+   <property name="shortcut">
+    <string>]</string>
+   </property>
+  </action>
+  <action name="actionActivatePreviousLayer">
+   <property name="text">
+    <string>Activate Previous Layer</string>
+   </property>
+   <property name="shortcut">
+    <string>[</string>
+   </property>
+  </action>
  </widget>
  <customwidgets>
   <customwidget>
diff --git a/GUI/Qt/Windows/MeshExportWizard/MeshExportWizard.cxx b/GUI/Qt/Windows/MeshExportWizard/MeshExportWizard.cxx
index ab91ef5..8c2cb8e 100644
--- a/GUI/Qt/Windows/MeshExportWizard/MeshExportWizard.cxx
+++ b/GUI/Qt/Windows/MeshExportWizard/MeshExportWizard.cxx
@@ -5,7 +5,11 @@ MeshExportWizard::MeshExportWizard(QWidget *parent) :
   QWizard(parent),
   ui(new Ui::MeshExportWizard)
 {
+  // Use parent's double buffering attributes
+  this->setAttribute(Qt::WA_PaintOnScreen, parent->testAttribute(Qt::WA_PaintOnScreen));
+
   ui->setupUi(this);
+  this->setWizardStyle(QWizard::ClassicStyle);
 }
 
 MeshExportWizard::~MeshExportWizard()
diff --git a/GUI/Qt/Windows/PreferencesDialog.cxx b/GUI/Qt/Windows/PreferencesDialog.cxx
index c72f902..4f94ce3 100644
--- a/GUI/Qt/Windows/PreferencesDialog.cxx
+++ b/GUI/Qt/Windows/PreferencesDialog.cxx
@@ -37,7 +37,7 @@ PreferencesDialog::PreferencesDialog(QWidget *parent) :
 
   // Set up layoyt options
   ui->inOverlayLayout->clear();
-  ui->inOverlayLayout->addItem(QIcon(":/root/layout_overlay_16.png"),
+  ui->inOverlayLayout->addItem(QIcon(":/root/layout_thumb_16.png"),
                                "Stack", QVariant::fromValue(LAYOUT_STACKED));
   ui->inOverlayLayout->addItem(QIcon(":/root/layout_tile_16.png"),
                                "Tile", QVariant::fromValue(LAYOUT_TILED));
@@ -121,6 +121,9 @@ void PreferencesDialog::SetModel(GlobalPreferencesModel *model)
   // Couple the interpolation mode (the domain is not provided by the model)
   makeCoupling(ui->inInterpolationMode, gds->GetGreyInterpolationModeModel());
 
+  // Couple the layer layout model
+  makeCoupling(ui->inOverlayLayout, gds->GetLayerLayoutModel());
+
   // Couple the color map preset selection.
   UpdateColorMapPresets();
   makeCoupling(ui->inDefaultColorMap, dbs->GetOverlayColorMapPresetModel());
diff --git a/GUI/Qt/Windows/PreferencesDialog.ui b/GUI/Qt/Windows/PreferencesDialog.ui
index 1a9f424..bdcc537 100644
--- a/GUI/Qt/Windows/PreferencesDialog.ui
+++ b/GUI/Qt/Windows/PreferencesDialog.ui
@@ -27,7 +27,7 @@
    <item row="1" column="1">
     <widget class="QStackedWidget" name="stack">
      <property name="currentIndex">
-      <number>0</number>
+      <number>1</number>
      </property>
      <widget class="QWidget" name="pageGeneral">
       <layout class="QVBoxLayout" name="verticalLayout">
@@ -234,14 +234,14 @@
               <item row="2" column="0">
                <widget class="QLabel" name="label_8">
                 <property name="text">
-                 <string>Default layout for overlays:</string>
+                 <string>Default layout for multiple images:</string>
                 </property>
                </widget>
               </item>
               <item row="1" column="0">
                <widget class="QLabel" name="label_10">
                 <property name="text">
-                 <string>Default colormap for overays:</string>
+                 <string>Default color map for overlayed images:</string>
                 </property>
                </widget>
               </item>
@@ -1397,7 +1397,7 @@ font-weight:bold;</string>
   <customwidget>
    <class>QColorButtonWidget</class>
    <extends>QWidget</extends>
-   <header>QColorButtonWidget.h</header>
+   <header location="global">QColorButtonWidget.h</header>
    <container>1</container>
   </customwidget>
  </customwidgets>
diff --git a/GUI/Qt/Windows/SaveModifiedLayersDialog.cxx b/GUI/Qt/Windows/SaveModifiedLayersDialog.cxx
index ba2ad1d..53000f0 100644
--- a/GUI/Qt/Windows/SaveModifiedLayersDialog.cxx
+++ b/GUI/Qt/Windows/SaveModifiedLayersDialog.cxx
@@ -42,9 +42,15 @@ SaveModifiedLayersDialog::SaveModifiedLayersDialog(QWidget *parent) :
   this->setObjectName("dlgSaveModified");
 
   // Resize the table to contents
+#if QT_VERSION >= 0x050000
   ui->tableLayers->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
   ui->tableLayers->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
-}
+#else
+  ui->tableLayers->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents);
+  ui->tableLayers->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
+#endif
+
+ }
 
 SaveModifiedLayersDialog::~SaveModifiedLayersDialog()
 {
diff --git a/GUI/Qt/Windows/SimpleFileDialogWithHistory.cxx b/GUI/Qt/Windows/SimpleFileDialogWithHistory.cxx
index df5918d..b6bee0f 100644
--- a/GUI/Qt/Windows/SimpleFileDialogWithHistory.cxx
+++ b/GUI/Qt/Windows/SimpleFileDialogWithHistory.cxx
@@ -8,6 +8,9 @@ SimpleFileDialogWithHistory::SimpleFileDialogWithHistory(QWidget *parent) :
   QDialog(parent),
   ui(new Ui::SimpleFileDialogWithHistory)
 {
+  // Use parent's double buffering attributes
+  this->setAttribute(Qt::WA_PaintOnScreen, parent->testAttribute(Qt::WA_PaintOnScreen));
+
   // Set an object name for scripting
   this->setObjectName("dlgSimpleFile");
 
diff --git a/GUI/Qt/Windows/SpeedImageDialog.cxx b/GUI/Qt/Windows/SpeedImageDialog.cxx
index c7cce33..8e392ec 100644
--- a/GUI/Qt/Windows/SpeedImageDialog.cxx
+++ b/GUI/Qt/Windows/SpeedImageDialog.cxx
@@ -24,6 +24,10 @@
 #include "GMMRenderer.h"
 #include "QtDoubleSliderWithEditorCoupling.h"
 #include "QtPagedWidgetCoupling.h"
+#include "ImageIODelegates.h"
+#include "ImageIOWizard.h"
+#include "ImageIOWizardModel.h"
+#include "GenericImageData.h"
 
 Q_DECLARE_METATYPE(SnakeWizardModel::LayerScalarRepIndex)
 
@@ -96,6 +100,19 @@ void SpeedImageDialog::SetModel(SnakeWizardModel *model)
   makeCoupling(ui->inNumSamples, model->GetNumberOfGMMSamplesModel());
   makeCoupling(ui->inClusterXComponent, model->GetClusterPlottedComponentModel());
 
+  // Couple the classification widgets
+  makeCoupling(ui->inClassifierTreeNumber, m_Model->GetForestSizeModel());
+  makeCoupling(ui->inClassifierTreeDepth, m_Model->GetTreeDepthModel());
+  makeCoupling(ui->inClassifyBias, m_Model->GetClassifierBiasModel());
+
+  activateOnFlag(ui->inClassifyBias, m_Model, SnakeWizardModel::UIF_CLASSIFIER_TRAINED);
+
+
+  makeCoupling(ui->inClassifyUsePatch, m_Model->GetClassifierUsePatchModel());
+  makeCoupling(ui->inClassifierPatchSize, m_Model->GetClassifierPatchRadiusModel());
+  makeCoupling(ui->inClassifyUseCoordinates, m_Model->GetClassifierUseCoordinatesModel());
+
+
   // Couple the tab pages to the current mode
   std::map<PreprocessingMode, QWidget *> preproc_page_map;
   preproc_page_map[PREPROCESS_THRESHOLD] = ui->tabThreshold;
@@ -152,7 +169,26 @@ void SpeedImageDialog::on_btnIterateTen_clicked()
 }
 
 
-void SpeedImageDialog::on_btnTrain_clicked()
+void SpeedImageDialog::on_btnClassifyLoad_clicked()
+{
+  // Create a model for IO
+  SmartPtr<LoadSegmentationImageDelegate> delegate = LoadSegmentationImageDelegate::New();
+  delegate->Initialize(m_Model->GetParent()->GetDriver());
+
+  SmartPtr<ImageIOWizardModel> model = ImageIOWizardModel::New();
+  model->InitializeForLoad(m_Model->GetParent(), delegate, "ClassifierSamples", "Classifier Samples Image");
+
+  // Execute the IO wizard
+  ImageIOWizard wiz(this);
+  wiz.SetModel(model);
+  wiz.exec();
+
+}
+
+void SpeedImageDialog::on_btnClassifySave_clicked()
 {
-  m_Model->TrainClassifier();
+  SaveImageLayer(
+        m_Model->GetParent(),
+        m_Model->GetParent()->GetDriver()->GetCurrentImageData()->GetSegmentation(),
+        LABEL_ROLE, true, this);
 }
diff --git a/GUI/Qt/Windows/SpeedImageDialog.h b/GUI/Qt/Windows/SpeedImageDialog.h
index 334e557..c298d39 100644
--- a/GUI/Qt/Windows/SpeedImageDialog.h
+++ b/GUI/Qt/Windows/SpeedImageDialog.h
@@ -46,7 +46,9 @@ private slots:
 
   void on_btnIterateTen_clicked();
 
-  void on_btnTrain_clicked();
+  void on_btnClassifyLoad_clicked();
+
+  void on_btnClassifySave_clicked();
 
 private:
   Ui::SpeedImageDialog *ui;
diff --git a/GUI/Qt/Windows/SpeedImageDialog.ui b/GUI/Qt/Windows/SpeedImageDialog.ui
index 40cbea5..4afc907 100644
--- a/GUI/Qt/Windows/SpeedImageDialog.ui
+++ b/GUI/Qt/Windows/SpeedImageDialog.ui
@@ -6,8 +6,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>500</width>
-    <height>543</height>
+    <width>512</width>
+    <height>560</height>
    </rect>
   </property>
   <property name="windowTitle">
@@ -16,13 +16,33 @@
   <property name="styleSheet">
    <string notr="true">* {
 font-size: 12px;
+}
+
+QGroupBox {
+  background-origin: content;
+  margin-top: 15px;
+  font-weight: bold;
+  font-size: 12px;
+  font-family: helvetica;
+  color: rgb(30,30,160);
+  background-color: rgb(237,237,237);
+  padding: 5px;
+  border-radius: 4px;
+  border: 1px solid rgb(130,130,130);
+}
+QGroupBox:!enabled {
+  color: rgb(108,108,108);
+}
+QGroupBox::title {
+  subcontrol-origin: 	margin;
+  subcontrol-position: top left;
 }</string>
   </property>
   <layout class="QVBoxLayout" name="verticalLayout">
    <item>
     <widget class="QTabWidget" name="tabMode">
      <property name="currentIndex">
-      <number>2</number>
+      <number>1</number>
      </property>
      <widget class="QWidget" name="tabThreshold">
       <attribute name="title">
@@ -454,6 +474,397 @@ font-size: 12px;
        </item>
       </layout>
      </widget>
+     <widget class="QWidget" name="tabClassify">
+      <attribute name="title">
+       <string>Classification</string>
+      </attribute>
+      <layout class="QVBoxLayout" name="verticalLayout_9">
+       <property name="spacing">
+        <number>16</number>
+       </property>
+       <item>
+        <widget class="QGroupBox" name="groupBox">
+         <property name="title">
+          <string>Additional features:</string>
+         </property>
+         <layout class="QVBoxLayout" name="verticalLayout_6">
+          <property name="spacing">
+           <number>0</number>
+          </property>
+          <property name="leftMargin">
+           <number>0</number>
+          </property>
+          <property name="topMargin">
+           <number>0</number>
+          </property>
+          <property name="rightMargin">
+           <number>0</number>
+          </property>
+          <property name="bottomMargin">
+           <number>0</number>
+          </property>
+          <item>
+           <widget class="QWidget" name="widget_10" native="true">
+            <layout class="QGridLayout" name="gridLayout_3">
+             <property name="leftMargin">
+              <number>0</number>
+             </property>
+             <property name="topMargin">
+              <number>4</number>
+             </property>
+             <property name="rightMargin">
+              <number>0</number>
+             </property>
+             <property name="bottomMargin">
+              <number>4</number>
+             </property>
+             <item row="2" column="3">
+              <widget class="QSpinBox" name="inClassifierPatchSize">
+               <property name="minimumSize">
+                <size>
+                 <width>100</width>
+                 <height>0</height>
+                </size>
+               </property>
+               <property name="toolTip">
+                <string><html><head/><body><p>The radius of the neighborhood used to produce additional features. When set to 1, the neighborhood size is 3x3x3 voxels. When set to 2, the neighborhood is 5x5x5 voxels, and so on.</p></body></html></string>
+               </property>
+              </widget>
+             </item>
+             <item row="2" column="2">
+              <widget class="QLabel" name="label_26">
+               <property name="text">
+                <string>Neighborhood size:</string>
+               </property>
+              </widget>
+             </item>
+             <item row="1" column="0">
+              <spacer name="horizontalSpacer_4">
+               <property name="orientation">
+                <enum>Qt::Horizontal</enum>
+               </property>
+               <property name="sizeType">
+                <enum>QSizePolicy::Fixed</enum>
+               </property>
+               <property name="sizeHint" stdset="0">
+                <size>
+                 <width>50</width>
+                 <height>20</height>
+                </size>
+               </property>
+              </spacer>
+             </item>
+             <item row="2" column="4">
+              <spacer name="horizontalSpacer_7">
+               <property name="orientation">
+                <enum>Qt::Horizontal</enum>
+               </property>
+               <property name="sizeType">
+                <enum>QSizePolicy::Expanding</enum>
+               </property>
+               <property name="sizeHint" stdset="0">
+                <size>
+                 <width>5</width>
+                 <height>20</height>
+                </size>
+               </property>
+              </spacer>
+             </item>
+             <item row="2" column="1">
+              <spacer name="horizontalSpacer_8">
+               <property name="orientation">
+                <enum>Qt::Horizontal</enum>
+               </property>
+               <property name="sizeType">
+                <enum>QSizePolicy::Fixed</enum>
+               </property>
+               <property name="sizeHint" stdset="0">
+                <size>
+                 <width>50</width>
+                 <height>20</height>
+                </size>
+               </property>
+              </spacer>
+             </item>
+             <item row="0" column="0" colspan="5">
+              <widget class="QCheckBox" name="inClassifyUsePatch">
+               <property name="text">
+                <string>Inculde the intensities of the voxels' neighbors as features</string>
+               </property>
+              </widget>
+             </item>
+             <item row="1" column="1" colspan="4">
+              <widget class="QLabel" name="label_21">
+               <property name="styleSheet">
+                <string notr="true">font-size:10px;
+color: rgb(64, 64, 64);</string>
+               </property>
+               <property name="text">
+                <string>Can help you segment images with rich texture or complex patterns, but classification will be much slower</string>
+               </property>
+               <property name="alignment">
+                <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+               </property>
+               <property name="wordWrap">
+                <bool>true</bool>
+               </property>
+              </widget>
+             </item>
+             <item row="3" column="0" colspan="5">
+              <widget class="QCheckBox" name="inClassifyUseCoordinates">
+               <property name="text">
+                <string>Inculde the voxels' coordinates as features</string>
+               </property>
+              </widget>
+             </item>
+             <item row="4" column="1" colspan="4">
+              <widget class="QLabel" name="label_22">
+               <property name="styleSheet">
+                <string notr="true">font-size:10px;
+color: rgb(64, 64, 64);</string>
+               </property>
+               <property name="text">
+                <string>Allows you to provide geometrical hints to the segmentation, for example avoiding leaking into a certain region</string>
+               </property>
+               <property name="alignment">
+                <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+               </property>
+               <property name="wordWrap">
+                <bool>true</bool>
+               </property>
+              </widget>
+             </item>
+            </layout>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item>
+        <widget class="QGroupBox" name="groupBox_2">
+         <property name="title">
+          <string>Random forest classifier settings:</string>
+         </property>
+         <layout class="QVBoxLayout" name="verticalLayout_7">
+          <property name="spacing">
+           <number>0</number>
+          </property>
+          <property name="leftMargin">
+           <number>0</number>
+          </property>
+          <property name="topMargin">
+           <number>0</number>
+          </property>
+          <property name="rightMargin">
+           <number>0</number>
+          </property>
+          <property name="bottomMargin">
+           <number>0</number>
+          </property>
+          <item>
+           <widget class="QWidget" name="widget_9" native="true">
+            <layout class="QGridLayout" name="gridLayout_6">
+             <property name="leftMargin">
+              <number>0</number>
+             </property>
+             <property name="topMargin">
+              <number>4</number>
+             </property>
+             <property name="rightMargin">
+              <number>0</number>
+             </property>
+             <property name="bottomMargin">
+              <number>4</number>
+             </property>
+             <item row="2" column="2" alignment="Qt::AlignVCenter">
+              <widget class="QLabel" name="label_25">
+               <property name="minimumSize">
+                <size>
+                 <width>190</width>
+                 <height>26</height>
+                </size>
+               </property>
+               <property name="maximumSize">
+                <size>
+                 <width>190</width>
+                 <height>26</height>
+                </size>
+               </property>
+               <property name="styleSheet">
+                <string notr="true">font-size:10px;
+color: rgb(64, 64, 64);</string>
+               </property>
+               <property name="text">
+                <string>Boost the contribution of the foreground class to the speed image</string>
+               </property>
+               <property name="alignment">
+                <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+               </property>
+               <property name="wordWrap">
+                <bool>true</bool>
+               </property>
+              </widget>
+             </item>
+             <item row="0" column="0" alignment="Qt::AlignRight">
+              <widget class="QLabel" name="label_18">
+               <property name="text">
+                <string>Number of trees:</string>
+               </property>
+              </widget>
+             </item>
+             <item row="2" column="1">
+              <widget class="QDoubleSliderWithEditor" name="inClassifyBias">
+               <property name="orientation">
+                <enum>Qt::Horizontal</enum>
+               </property>
+              </widget>
+             </item>
+             <item row="1" column="1">
+              <widget class="QSpinBox" name="inClassifierTreeDepth">
+               <property name="minimumSize">
+                <size>
+                 <width>100</width>
+                 <height>0</height>
+                </size>
+               </property>
+              </widget>
+             </item>
+             <item row="0" column="2">
+              <widget class="QLabel" name="label_23">
+               <property name="minimumSize">
+                <size>
+                 <width>190</width>
+                 <height>26</height>
+                </size>
+               </property>
+               <property name="maximumSize">
+                <size>
+                 <width>190</width>
+                 <height>26</height>
+                </size>
+               </property>
+               <property name="styleSheet">
+                <string notr="true">font-size:10px;
+color: rgb(64, 64, 64);</string>
+               </property>
+               <property name="text">
+                <string>More trees produce more accurate classification at the cost of more time.</string>
+               </property>
+               <property name="alignment">
+                <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+               </property>
+               <property name="wordWrap">
+                <bool>true</bool>
+               </property>
+              </widget>
+             </item>
+             <item row="0" column="1">
+              <widget class="QSpinBox" name="inClassifierTreeNumber">
+               <property name="minimumSize">
+                <size>
+                 <width>100</width>
+                 <height>0</height>
+                </size>
+               </property>
+              </widget>
+             </item>
+             <item row="2" column="0" alignment="Qt::AlignRight">
+              <widget class="QLabel" name="label_24">
+               <property name="text">
+                <string>Classifier bias:</string>
+               </property>
+              </widget>
+             </item>
+             <item row="1" column="0" alignment="Qt::AlignRight">
+              <widget class="QLabel" name="label_19">
+               <property name="text">
+                <string>Tree depth:</string>
+               </property>
+              </widget>
+             </item>
+             <item row="1" column="2">
+              <widget class="QLabel" name="label_20">
+               <property name="minimumSize">
+                <size>
+                 <width>190</width>
+                 <height>26</height>
+                </size>
+               </property>
+               <property name="maximumSize">
+                <size>
+                 <width>190</width>
+                 <height>26</height>
+                </size>
+               </property>
+               <property name="styleSheet">
+                <string notr="true">font-size:10px;
+color: rgb(64, 64, 64);</string>
+               </property>
+               <property name="text">
+                <string>Increase when there are many features and complex patterns to be learned</string>
+               </property>
+               <property name="alignment">
+                <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+               </property>
+               <property name="wordWrap">
+                <bool>true</bool>
+               </property>
+              </widget>
+             </item>
+            </layout>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item>
+        <spacer name="verticalSpacer_16">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>40</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item>
+        <widget class="QWidget" name="widget_11" native="true">
+         <layout class="QHBoxLayout" name="horizontalLayout_4">
+          <item>
+           <spacer name="horizontalSpacer_11">
+            <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="btnClassifyLoad">
+            <property name="text">
+             <string>Load samples ...</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="btnClassifySave">
+            <property name="text">
+             <string>Save samples ...</string>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+      </layout>
+     </widget>
      <widget class="QWidget" name="tabCluster">
       <attribute name="title">
        <string>Clustering</string>
@@ -876,59 +1287,6 @@ font-size: 12px;
        </item>
       </layout>
      </widget>
-     <widget class="QWidget" name="tabClassify">
-      <attribute name="title">
-       <string>Classification</string>
-      </attribute>
-      <layout class="QVBoxLayout" name="verticalLayout_9">
-       <item>
-        <widget class="QLabel" name="label_18">
-         <property name="text">
-          <string>Table of tissue classes:</string>
-         </property>
-        </widget>
-       </item>
-       <item>
-        <widget class="QTableView" name="tableClasses"/>
-       </item>
-       <item>
-        <widget class="QWidget" name="widget_9" native="true">
-         <layout class="QHBoxLayout" name="horizontalLayout_4">
-          <item>
-           <spacer name="horizontalSpacer_4">
-            <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="btnTrain">
-            <property name="text">
-             <string>Train</string>
-            </property>
-           </widget>
-          </item>
-         </layout>
-        </widget>
-       </item>
-       <item>
-        <widget class="QLabel" name="label_19">
-         <property name="text">
-          <string><html><head/><body><p>To use supervised classification, define two or more classes. For each class, use the paintbrush tool to provide examples of that class in the image.</p></body></html></string>
-         </property>
-         <property name="wordWrap">
-          <bool>true</bool>
-         </property>
-        </widget>
-       </item>
-      </layout>
-     </widget>
      <widget class="QWidget" name="tabEdgeAttraction">
       <attribute name="title">
        <string>Edge Attraction</string>
@@ -1231,11 +1589,6 @@ font-size: 12px;
  </widget>
  <customwidgets>
   <customwidget>
-   <class>QDoubleSliderWithEditor</class>
-   <extends>QSlider</extends>
-   <header location="global">QDoubleSliderWithEditor.h</header>
-  </customwidget>
-  <customwidget>
    <class>QDoubleSlider</class>
    <extends>QSlider</extends>
    <header location="global">QDoubleSlider.h</header>
@@ -1247,6 +1600,11 @@ font-size: 12px;
    <container>1</container>
   </customwidget>
   <customwidget>
+   <class>QDoubleSliderWithEditor</class>
+   <extends>QSlider</extends>
+   <header location="global">QDoubleSliderWithEditor.h</header>
+  </customwidget>
+  <customwidget>
    <class>QtVTKRenderWindowBox</class>
    <extends>QWidget</extends>
    <header location="global">QtVTKRenderWindowBox.h</header>
diff --git a/GUI/Qt/Windows/SplashPanel.ui b/GUI/Qt/Windows/SplashPanel.ui
index c8578e4..3cc6672 100644
--- a/GUI/Qt/Windows/SplashPanel.ui
+++ b/GUI/Qt/Windows/SplashPanel.ui
@@ -107,7 +107,7 @@ Jan 12, 2013</string>
 color:rgb(109, 109, 109);</string>
      </property>
      <property name="text">
-      <string>Copyright (C) 1998-2014
+      <string>Copyright (C) 1998-2015
 Paul A. Yushkevich 
 Guido Gerig</string>
      </property>
diff --git a/GUI/Qt/main.cxx b/GUI/Qt/main.cxx
index c667d3c..6e09756 100644
--- a/GUI/Qt/main.cxx
+++ b/GUI/Qt/main.cxx
@@ -90,6 +90,12 @@ public:
     {
     this->setApplicationName("ITK-SNAP");
     this->setOrganizationName("itksnap.org");
+
+#if QT_VERSION >= 0x050000
+    // Allow @x2 pixmaps for icons for retina displays
+    this->setAttribute(Qt::AA_UseHighDpiPixmaps, true);
+#endif
+
     m_MainWindow = NULL;
 
     // Store the command-line arguments
@@ -160,22 +166,23 @@ private:
 bool flag_snap_debug_events = false;
 #endif
 
-void usage()
+void usage(const char *progname)
 {
   // Print usage info and exit
   cout << "ITK-SnAP Command Line Usage:" << endl;
-  cout << "   snap [options] [main_image]" << endl;
+  cout << "   " << progname << " [options] [main_image]" << endl;
   cout << "Image Options:" << endl;
-  cout << "   -g FILE              : Load the greyscale image from FILE" << endl;
+  cout << "   -g FILE              : Load the main image from FILE" << endl;
   cout << "   -s FILE              : Load the segmentation image from FILE" << endl;
   cout << "   -l FILE              : Load label descriptions from FILE" << endl;
-  cout << "   -o FILE              : Load overlay image from FILE" << endl;
-  cout << "                        :   (-o option can be repeated multiple times)" << endl;
+  cout << "   -o FILE [FILE+]      : Load additional images from FILE" << endl;
+  cout << "                        :   (multiple files may be provided)" << endl;
   cout << "   -w FILE              : Load workspace from FILE" << endl;
   cout << "                        :   (-w cannot be mixed with -g,-s,-l,-o options)" << endl;
   cout << "Additional Options:" << endl;
   cout << "   -z FACTOR            : Specify initial zoom in screen pixels/mm" << endl;
-  cout << "Debugging/Testing Options" << endl;
+  cout << "   --cwd PATH           : Start with PATH as the initial directory" << endl;
+  cout << "Debugging/Testing Options:" << endl;
 #ifdef SNAP_DEBUG_EVENTS
   cout << "   --debug-events       : Dump information regarding UI events" << endl;
 #endif // SNAP_DEBUG_EVENTS
@@ -183,6 +190,12 @@ void usage()
   cout << "   --test TESTID        : Execute a test. " << endl;
   cout << "   --testdir DIR        : Set the root directory for tests. " << endl;
   cout << "   --testacc factor     : Adjust the interval between test commands by factor (e.g., 0.5). " << endl;
+  cout << "Platform-Specific Options:" << endl;
+#if QT_VERSION < 0x050000
+#ifdef Q_WS_X11
+  cout << "   --x11-db             : Enable widget double buffering on X11. By default it is off." << endl;
+#endif
+#endif
 }
 
 void setupParser(CommandLineArgumentParser &parser)
@@ -209,15 +222,55 @@ public:
   // Whether the application is being launched from the console
   bool flagConsole;
 
+  // Whether widgets are double-buffered
+  bool flagX11DoubleBuffer;
+
   // Test-related stuff
   std::string xTestId;
   std::string fnTestDir;
   double xTestAccel;
 
+  // Current working directory
+  std::string cwd;
+
+  // GUI related
+  std::string style;
+
   CommandLineRequest()
-    : flagDebugEvents(false), flagNoFork(false), flagConsole(false), xZoomFactor(0.0) {}
+    : flagDebugEvents(false), flagNoFork(false), flagConsole(false), xZoomFactor(0.0),
+      flagX11DoubleBuffer(false)
+    {
+#if QT_VERSION >= 0x050000
+    style = "fusion";
+#else
+    style = "plastique";
+#endif
+    }
+};
+
+
+/*
+ * Define customizations to the Plastique style to make it appear more like Fusion
+ */
+#if QT_VERSION < 0x050000
+#include <QProxyStyle>
+
+class FusionProxy : public QProxyStyle
+{
+public:
+
+  virtual void polish(QPalette &palette)
+  {
+    QColor fusion_gray(232, 232, 232);
+    palette = QPalette(fusion_gray);
+  }
+
+protected:
 };
 
+#endif
+
+
 /**
  This function decodes filenames in "SHORT" DOS format. It does nothing
  on non-Windows platforms
@@ -293,11 +346,19 @@ int parse(int argc, char *argv[], CommandLineRequest &argdata)
   parser.AddOption("--testdir", 1);
   parser.AddOption("--testacc", 1);
 
+  // Current working directory
+  parser.AddOption("--cwd", 1);
+
   // This dummy option is actually used internally. It's a work-around for
   // a buggy behavior on MacOS, when execvp actually causes a file
   // open event to be fired, which causes the drop dialog to open
   parser.AddOption("--dummy", 1);
 
+  // Some qt stuff
+  parser.AddOption("--style", 1);
+
+  parser.AddOption("--x11-db",0);
+
   // Obtain the result
   CommandLineArgumentParseResult parseResult;
 
@@ -314,7 +375,7 @@ int parse(int argc, char *argv[], CommandLineRequest &argdata)
   // Need help?
   if(parseResult.IsOptionPresent("--help"))
     {
-    usage();
+    usage(argv[0]);
     return 1;
     }
 
@@ -329,6 +390,10 @@ int parse(int argc, char *argv[], CommandLineRequest &argdata)
 #endif
     }
 
+  // Initial directory
+  if(parseResult.IsOptionPresent("--cwd"))
+    argdata.cwd = parseResult.GetOptionParameter("--cwd");
+
   // Check if a workspace is being loaded
   if(parseResult.IsOptionPresent("--workspace"))
     {
@@ -447,10 +512,21 @@ int parse(int argc, char *argv[], CommandLineRequest &argdata)
 
     }
 
+  // GUI stuff
+  if(parseResult.IsOptionPresent("--style"))
+    argdata.style = parseResult.GetOptionParameter("--style");
+
+  // Enable double buffering on X11
+  if(parseResult.IsOptionPresent("x11-db"))
+    argdata.flagX11DoubleBuffer = true;
+
   return 0;
 }
 
 
+
+#include <QDir>
+
 int main(int argc, char *argv[])
 {  
   // Test object, which only is allocated if tests are requested. The
@@ -494,8 +570,19 @@ int main(int argc, char *argv[])
   Q_INIT_RESOURCE(SNAPResources);
   Q_INIT_RESOURCE(TestingScripts);
 
+  // Force use of native OpenGL, since all of our functions and VTK use native
+  // and cannot use ANGLE
+  // TODO: we haven't proven that this actually helps with anything so hold off..
+  // app.setAttribute(Qt::AA_UseDesktopOpenGL);
+
   // Set the application style
-  app.setStyle(QStyleFactory::create("fusion"));
+  app.setStyle(QStyleFactory::create(argdata.style.c_str()));
+  if(argdata.style != "fusion")
+    {
+    QPalette fpal(QColor(232,232,232));
+    fpal.setColor(QPalette::Normal, QPalette::Highlight, QColor(70, 136, 228));
+    app.setPalette(fpal);
+    }
 
   // Before we can create any of the framework classes, we need to get some
   // platform-specific functionality to the SystemInterface
@@ -508,6 +595,35 @@ int main(int argc, char *argv[])
     SmartPtr<GlobalUIModel> gui = GlobalUIModel::New();
     IRISApplication *driver = gui->GetDriver();
 
+    // Set the initial directory. The fallthough is to set to the user's home
+    // directory
+    QString init_dir = QDir::homePath();
+    QString app_dir = QApplication::applicationDirPath();
+
+    // Also get the directory one up from the application dir (this is because
+    // on windows "run in" defaults to one up dir)
+    QDir app_up_qdir(app_dir); app_up_qdir.cdUp();
+    QString app_up_dir = app_up_qdir.path();
+
+    // If the user provides a flag for the current directory, try using it but
+    // only if this is a valid directory
+    if(argdata.cwd.size())
+      {
+      QDir dir(from_utf8(argdata.cwd));
+      if(dir.exists() && dir.isReadable())
+        {
+        init_dir = dir.absolutePath();
+        }
+      }
+    else if(QDir::currentPath().length() > 1 &&
+            QDir::currentPath() != app_dir &&
+            QDir::currentPath() != app_up_dir)
+      {
+      init_dir = QDir::currentPath();
+      }
+
+    gui->GetGlobalState()->SetInitialDirectory(to_utf8(init_dir));
+
     // Load the user preferences
     gui->LoadUserPreferences();
 
@@ -515,6 +631,16 @@ int main(int argc, char *argv[])
     MainImageWindow *mainwin = new MainImageWindow();
     mainwin->Initialize(gui);
 
+    // Disable double buffering in X11 to avoid flickering issues. The documentation
+    // says this only happens on X11. For the time being, we are only implementing this
+    // for Qt4 and X11
+#if QT_VERSION < 0x050000
+#ifdef Q_WS_X11
+    if(!argdata.flagX11DoubleBuffer)
+      mainwin->setAttribute(Qt::WA_PaintOnScreen);
+#endif
+#endif
+
     // Start parsing options
     IRISWarningList warnings;
 
diff --git a/GUI/Renderer/AbstractRenderer.h b/GUI/Renderer/AbstractRenderer.h
index cf75f5a..2636c82 100644
--- a/GUI/Renderer/AbstractRenderer.h
+++ b/GUI/Renderer/AbstractRenderer.h
@@ -2,6 +2,7 @@
 #define ABSTRACTRENDERER_H
 
 #include "AbstractModel.h"
+#include "SNAPOpenGL.h"
 
 /**
  * @brief The RendererPlatformSupport class
@@ -26,12 +27,14 @@ public:
 
   virtual void RenderTextInOpenGL(
       const char *text,
-      int x, int y, int w, int h,
+      double x, double y, double w, double h,
       FontInfo font,
       int align_horiz, int align_vert,
-      const Vector3d &rgbf) = 0;
+      const Vector3d &rgbf, double alpha = 1.0) = 0;
 
   virtual int MeasureTextWidth(const char *text, FontInfo font) = 0;
+
+  virtual void LoadTexture(const char *url, GLuint &texture_id, Vector2ui &tex_size) = 0;
 };
 
 
@@ -44,7 +47,7 @@ class AbstractRenderer : public AbstractModel
 public:
 
   virtual void initializeGL() {}
-  virtual void resizeGL(int w, int h) {}
+  virtual void resizeGL(int w, int h, int device_pixel_ratio) {}
   virtual void paintGL() = 0;
 
   static void SetPlatformSupport(AbstractRendererPlatformSupport *support)
diff --git a/GUI/Renderer/AbstractVTKRenderer.cxx b/GUI/Renderer/AbstractVTKRenderer.cxx
index b74bbce..69fb3b9 100644
--- a/GUI/Renderer/AbstractVTKRenderer.cxx
+++ b/GUI/Renderer/AbstractVTKRenderer.cxx
@@ -46,6 +46,9 @@ AbstractVTKRenderer::AbstractVTKRenderer()
   m_Interactor = vtkSmartPointer<QtRenderWindowInteractor>::New();
   m_Interactor->SetRenderWindow(m_RenderWindow);
   m_Interactor->SetInteractorStyle(NULL);
+
+  // Set the pixel ratio
+  m_DevicePixelRatio = 1;
 }
 
 void AbstractVTKRenderer::paintGL()
@@ -119,9 +122,16 @@ void AbstractVTKRenderer::SyncronizeCamera(Self *reference)
                          vtkCommand::ModifiedEvent, ModelUpdateEvent());
 }
 
-void AbstractVTKRenderer::resizeGL(int w, int h)
+void AbstractVTKRenderer::resizeGL(int w, int h, int device_pixel_ratio)
 {
   // Pass the size to VTK
   m_RenderWindow->SetSize(w, h);
   m_Interactor->UpdateSize(w, h);
+
+  if(m_DevicePixelRatio != device_pixel_ratio)
+    {
+    int old_ratio = m_DevicePixelRatio;
+    m_DevicePixelRatio = device_pixel_ratio;
+    this->OnDevicePixelRatioChange(old_ratio, device_pixel_ratio);
+    }
 }
diff --git a/GUI/Renderer/AbstractVTKRenderer.h b/GUI/Renderer/AbstractVTKRenderer.h
index 3369ef2..eaf80f1 100644
--- a/GUI/Renderer/AbstractVTKRenderer.h
+++ b/GUI/Renderer/AbstractVTKRenderer.h
@@ -3,6 +3,7 @@
 
 #include "AbstractRenderer.h"
 #include <vtkSmartPointer.h>
+#include "UIReporterDelegates.h"
 
 class vtkRenderer;
 class vtkRenderWindow;
@@ -30,7 +31,7 @@ public:
   };
 
   virtual void paintGL();
-  virtual void resizeGL(int w, int h);
+  virtual void resizeGL(int w, int h, int device_pixel_ratio);
   virtual void initializeGL();
 
   vtkRenderWindow *GetRenderWindow();
@@ -55,9 +56,17 @@ protected:
   // The interactor
   vtkSmartPointer<vtkRenderWindowInteractor> m_Interactor;
 
+  // The device pixel ratio (1 for regular screens, 2 for retina)
+  // This is updated in resizeGL
+  int m_DevicePixelRatio;
+
   // Background color
   Vector3d m_BackgroundColor;
 
+  // Virtual method called when the device pixel ratio changes, allowing
+  // the child classes to update some properties (e.g., font size)
+  virtual void OnDevicePixelRatioChange(int old_ratio, int new_ratio) {}
+
   AbstractVTKRenderer();
   virtual ~AbstractVTKRenderer() {}
 };
diff --git a/GUI/Renderer/AbstractVTKSceneRenderer.cxx b/GUI/Renderer/AbstractVTKSceneRenderer.cxx
index 3b39ab3..7607a53 100644
--- a/GUI/Renderer/AbstractVTKSceneRenderer.cxx
+++ b/GUI/Renderer/AbstractVTKSceneRenderer.cxx
@@ -3,6 +3,8 @@
 #include <vtkGenericOpenGLRenderWindow.h>
 #include <vtkRenderer.h>
 #include <vtkContextView.h>
+#include <vtkChart.h>
+#include <vtkTextProperty.h>
 
 AbstractVTKSceneRenderer::AbstractVTKSceneRenderer()
   : AbstractVTKRenderer()
@@ -19,6 +21,31 @@ AbstractVTKSceneRenderer::AbstractVTKSceneRenderer()
   m_BackgroundColor.fill(0.0);
 }
 
+#include <vtkPlot.h>
+#include <vtkPen.h>
+#include <vtkAxis.h>
+void AbstractVTKSceneRenderer::UpdateChartDevicePixelRatio(
+    vtkChart *chart, int old_ratio, int new_ratio)
+{
+  // Axis titles
+  const int axis_arr[] = {vtkAxis::LEFT, vtkAxis::RIGHT, vtkAxis::BOTTOM, vtkAxis::TOP};
+  for(int i = 0; i < 4; i++)
+    {
+    if(chart->GetAxis(axis_arr[i]))
+      {
+      vtkTextProperty *propl = chart->GetAxis(axis_arr[i])->GetLabelProperties();
+      propl->SetFontSize(new_ratio * propl->GetFontSize() / old_ratio);
+
+      vtkTextProperty *propt = chart->GetAxis(axis_arr[i])->GetTitleProperties();
+      propt->SetFontSize(new_ratio * propt->GetFontSize() / old_ratio);
+      }
+    }
+
+  // Main chart title
+  vtkTextProperty *prop = chart->GetTitleProperties();
+  prop->SetFontSize(new_ratio * prop->GetFontSize() / old_ratio);
+}
+
 void AbstractVTKSceneRenderer::paintGL()
 {
   // Set renderer background
diff --git a/GUI/Renderer/AbstractVTKSceneRenderer.h b/GUI/Renderer/AbstractVTKSceneRenderer.h
index 6501659..e09a95d 100644
--- a/GUI/Renderer/AbstractVTKSceneRenderer.h
+++ b/GUI/Renderer/AbstractVTKSceneRenderer.h
@@ -8,6 +8,7 @@ class vtkRenderer;
 class vtkRenderWindow;
 class vtkGenericOpenGLRenderWindow;
 class vtkContextView;
+class vtkChart;
 
 /**
   This class provides support for rendering a VTK scene in OpenGL. It sets
@@ -44,6 +45,10 @@ protected:
 
   AbstractVTKSceneRenderer();
   virtual ~AbstractVTKSceneRenderer() {}
+
+  // Helper method for updating device pixel ratio (i.e. retina mode)
+  // for VTK charts
+  virtual void UpdateChartDevicePixelRatio(vtkChart *chart, int old_ratio, int new_ratio);
 };
 
 #endif // ABSTRACTVTKSCENERENDERER_H
diff --git a/GUI/Renderer/AnnotationRenderer.cxx b/GUI/Renderer/AnnotationRenderer.cxx
new file mode 100644
index 0000000..c7179e0
--- /dev/null
+++ b/GUI/Renderer/AnnotationRenderer.cxx
@@ -0,0 +1,322 @@
+#include "AnnotationRenderer.h"
+#include "SNAPAppearanceSettings.h"
+#include "GlobalUIModel.h"
+#include "AnnotationModel.h"
+#include "GlobalState.h"
+#include "IRISApplication.h"
+#include "SNAPAppearanceSettings.h"
+#include "ImageAnnotationData.h"
+#include <iomanip>
+
+void AnnotationRenderer::DrawLineLength(const Vector3f &xSlice1,
+                                        const Vector3f &xSlice2,
+                                        const Vector3d &color,
+                                        double alpha)
+{
+  // Compute the length of the drawing line
+  double length = m_Model->GetLineLength(xSlice1, xSlice2);
+
+  // Get the retina pixel ratio
+  int vppr = m_ParentRenderer->GetModel()->GetSizeReporter()->GetViewportPixelRatio();
+
+  // Shared settings for text drawing
+  Vector3f text_offset_slice =
+      m_Model->GetParent()->MapWindowOffsetToSliceOffset(
+        Vector2f(5.f, 5.f) * (float) vppr);
+
+  Vector3f text_width_slice =
+      m_Model->GetParent()->MapWindowOffsetToSliceOffset(
+        Vector2f(96.f, 12.f) * (float) vppr);
+
+  // TODO: support other units
+  std::ostringstream oss_length;
+  oss_length << std::setprecision(4) << length << " " << "mm";
+
+  // Set up the rendering properties
+  AbstractRendererPlatformSupport::FontInfo font_info =
+        { AbstractRendererPlatformSupport::TYPEWRITER,
+          12 * vppr,
+          false };
+
+  Vector3f curr_center = (xSlice1 + xSlice2) * 0.5f;
+
+  // Draw the length text
+  m_PlatformSupport->RenderTextInOpenGL(
+        oss_length.str().c_str(),
+        curr_center[0] + text_offset_slice[0], curr_center[1] + text_offset_slice[1],
+        text_width_slice[0], text_width_slice[1],
+        font_info,
+        AbstractRendererPlatformSupport::LEFT, AbstractRendererPlatformSupport::TOP,
+        color, alpha);
+}
+
+void AnnotationRenderer::paintGL()
+{
+  assert(m_Model);
+
+  // Not in thumbnail mode
+  if(m_ParentRenderer->IsDrawingZoomThumbnail() || m_ParentRenderer->IsDrawingLayerThumbnail())
+    return;
+
+  // Get appearance settings
+  SNAPAppearanceSettings *as =
+      m_Model->GetParent()->GetParentUI()->GetAppearanceSettings();
+
+  // Get the opacity of the annotations, and stop if it is zero
+  double alpha =
+      m_Model->GetParent()->GetParentUI()->GetGlobalState()->GetAnnotationAlpha();
+  if(alpha == 0)
+    return;
+
+  // Get the color for the annotations
+  Vector3d ann_color
+      = m_Model->GetParent()->GetDriver()->GetGlobalState()->GetAnnotationColor();
+
+  // Get the retina pixel ratio
+  int vppr = m_ParentRenderer->GetModel()->GetSizeReporter()->GetViewportPixelRatio();
+
+  // Shared settings for text drawing
+  Vector3f text_offset_slice =
+      m_Model->GetParent()->MapWindowOffsetToSliceOffset(
+        Vector2f(5.f, 5.f) * (float) vppr);
+
+  Vector3f text_width_slice =
+      m_Model->GetParent()->MapWindowOffsetToSliceOffset(
+        Vector2f(96.f, 12.f) * (float) vppr);
+
+  // Get the list of annotations
+  const ImageAnnotationData *adata = m_Model->GetAnnotations();
+
+  // Push the line state
+  glPushAttrib(GL_LINE_BIT | GL_COLOR_BUFFER_BIT);
+
+  // set line and point drawing parameters
+  glPointSize(3 * vppr);
+  glLineWidth(1.0 * vppr);
+  glEnable(GL_LINE_SMOOTH);
+  glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
+  glEnable(GL_BLEND);
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+  // Draw current line - the current line can either be a ruler or an annotation arrow
+  if(m_Model->GetFlagDrawingLine())
+    {
+    const AnnotationModel::LineSegment &curr_line = m_Model->GetCurrentLine();
+
+    // Use the polygon drawing settings
+    const OpenGLAppearanceElement *elt =
+        as->GetUIElement(SNAPAppearanceSettings::POLY_DRAW_MAIN);
+
+    // Draw the line and the endpoints
+
+    // Draw the current line
+    glColor4d(ann_color[0], ann_color[1], ann_color[2],alpha);
+    glBegin(GL_POINTS);
+    glVertex2d(curr_line.first[0], curr_line.first[1]);
+
+    // Midpoint only drawn in ruler mode
+    if(m_Model->GetAnnotationMode() == ANNOTATION_RULER)
+      {
+      glVertex2d(0.5 * (curr_line.first[0] + curr_line.second[0]),
+                 0.5 * (curr_line.first[1] + curr_line.second[1]));
+      }
+
+    glVertex2d(curr_line.second[0], curr_line.second[1]);
+    glEnd();
+
+    // Draw the line itself
+    glPushAttrib(GL_LINE_BIT | GL_COLOR_BUFFER_BIT);
+    glEnable(GL_LINE_STIPPLE);
+    glLineStipple(1, 0x9999);
+    glBegin(GL_LINES);
+    glVertex2d(curr_line.first[0], curr_line.first[1]);
+    glVertex2d(curr_line.second[0], curr_line.second[1]);
+    glEnd();
+    glPopAttrib();
+
+    // Decoration drawn only in ruler mode
+    if(m_Model->GetAnnotationMode() == ANNOTATION_RULER)
+      {
+      // Draw the current line length
+      DrawLineLength(curr_line.first, curr_line.second, ann_color, alpha);
+      }
+    } // Current line valid
+
+  // Draw each annotation
+  for(ImageAnnotationData::AnnotationConstIterator it = adata->GetAnnotations().begin();
+      it != adata->GetAnnotations().end(); ++it)
+    {
+    if(m_Model->IsAnnotationVisible(*it))
+      {
+      // Draw all the line segments
+      annot::LineSegmentAnnotation *lsa =
+          dynamic_cast<annot::LineSegmentAnnotation *>(it->GetPointer());
+      if(lsa)
+        {
+        // Draw the line
+        Vector3f p1 = m_Model->GetParent()->MapImageToSlice(lsa->GetSegment().first);
+        Vector3f p2 = m_Model->GetParent()->MapImageToSlice(lsa->GetSegment().second);
+
+        glColor4d(lsa->GetColor()[0], lsa->GetColor()[1], lsa->GetColor()[2], alpha);
+
+        glBegin(GL_POINTS);
+        glVertex2d((p1[0] + p2[0]) * 0.5, (p1[1] + p2[1]) * 0.5);
+        glEnd();
+
+        glBegin(GL_LINES);
+        glVertex2d(p1[0], p1[1]);
+        glVertex2d(p2[0], p2[1]);
+        glEnd();
+
+        if(lsa->GetSelected())
+          {
+          this->DrawSelectionHandle(p1);
+          this->DrawSelectionHandle(p2);
+          }
+
+        // Draw length or angle
+        if(m_Model->IsDrawingRuler())
+          {
+          // Draw angle:
+          // Compute the dot product and no need for the third components that are zeros
+          double angle = m_Model->GetAngleWithCurrentLine(lsa);
+          std::ostringstream oss_angle;
+          oss_angle << std::setprecision(3) << angle << "°";
+
+          Vector3f line_center = m_Model->GetAnnotationCenter(lsa);
+
+          // Set up the rendering properties
+          AbstractRendererPlatformSupport::FontInfo font_info =
+                { AbstractRendererPlatformSupport::TYPEWRITER,
+                  12 * vppr,
+                  false };
+
+          // Draw the angle text
+          m_PlatformSupport->RenderTextInOpenGL(
+                oss_angle.str().c_str(),
+                line_center[0] + text_offset_slice[0], line_center[1] + text_offset_slice[1],
+              text_width_slice[0], text_width_slice[1],
+              font_info,
+              AbstractRendererPlatformSupport::LEFT, AbstractRendererPlatformSupport::TOP,
+              lsa->GetColor(), alpha);
+          }
+        else
+          {
+          this->DrawLineLength(p1, p2, lsa->GetColor(),alpha);
+          }
+        }
+
+      annot::LandmarkAnnotation *lma =
+          dynamic_cast<annot::LandmarkAnnotation *>(it->GetPointer());
+      if(lma)
+        {
+        // Get the head and tail coordinate in slice units
+        Vector3f xHeadSlice, xTailSlice;
+        m_Model->GetLandmarkArrowPoints(lma->GetLandmark(), xHeadSlice, xTailSlice);
+
+        std::string text = lma->GetLandmark().Text;
+
+        glColor4d(lma->GetColor()[0], lma->GetColor()[1], lma->GetColor()[2], alpha);
+
+        glBegin(GL_LINES);
+        glVertex2d(xHeadSlice[0], xHeadSlice[1]);
+        glVertex2d(xTailSlice[0], xTailSlice[1]);
+        glEnd();
+
+        if(lma->GetSelected())
+          {
+          this->DrawSelectionHandle(xHeadSlice);
+          this->DrawSelectionHandle(xTailSlice);
+          }
+
+        // Font properties
+        AbstractRendererPlatformSupport::FontInfo fi;
+        fi.type = AbstractRendererPlatformSupport::SANS;
+        fi.pixel_size = 12 * vppr;
+        fi.bold = false;
+
+        // Text box size in screen pixels
+        Vector2f xTextSizeWin;
+        xTextSizeWin[0] = this->m_PlatformSupport->MeasureTextWidth(text.c_str(), fi);
+        xTextSizeWin[1] = fi.pixel_size * vppr;
+
+        // Text box size in slice coordinate units
+        Vector3f xTextSizeSlice = m_Model->GetParent()->MapWindowOffsetToSliceOffset(xTextSizeWin);
+
+        // How to position the text
+        double xbox, ybox;
+        int align_horiz, align_vert;
+        if(fabs(lma->GetLandmark().Offset[0]) >= fabs(lma->GetLandmark().Offset[1]))
+          {
+          align_vert = AbstractRendererPlatformSupport::VCENTER;
+          ybox = xTailSlice[1] - xTextSizeSlice[1] / 2;
+          if(lma->GetLandmark().Offset[0] >= 0)
+            {
+            align_horiz = AbstractRendererPlatformSupport::LEFT;
+            xbox = xTailSlice[0];
+            }
+          else
+            {
+            align_horiz = AbstractRendererPlatformSupport::RIGHT;
+            xbox = xTailSlice[0] - xTextSizeSlice[0];
+            }
+          }
+        else
+          {
+          align_horiz = AbstractRendererPlatformSupport::HCENTER;
+          xbox = xTailSlice[0] - xTextSizeSlice[0] / 2;
+          if(lma->GetLandmark().Offset[1] >= 0)
+            {
+            align_vert = AbstractRendererPlatformSupport::BOTTOM;
+            ybox = xTailSlice[1];
+            }
+          else
+            {
+            align_vert = AbstractRendererPlatformSupport::TOP;
+            ybox = xTailSlice[1] - xTextSizeSlice[1];
+            }
+          }
+
+        // Draw the text at the right location
+        this->m_PlatformSupport->RenderTextInOpenGL(text.c_str(),
+                                                    xbox, ybox,
+                                                    xTextSizeSlice[0], xTextSizeSlice[1], fi,
+                                                    align_horiz, align_vert,
+                                                    lma->GetColor(), alpha);
+        }
+
+      }
+    }
+
+  glPopAttrib();
+}
+
+void AnnotationRenderer::DrawSelectionHandle(const Vector3f &xSlice)
+{
+  // Determine the width of the line
+  float radius = 4 * m_Model->GetParent()->GetSizeReporter()->GetViewportPixelRatio();
+  Vector3f offset = m_Model->GetParent()->MapWindowOffsetToSliceOffset(Vector2f(radius, radius));
+
+  glColor4d(1, 1, 1, 0.5);
+  glBegin(GL_QUADS);
+  glVertex2d(xSlice[0] + offset[0], xSlice[1] + offset[1]);
+  glVertex2d(xSlice[0] + offset[0], xSlice[1] - offset[1]);
+  glVertex2d(xSlice[0] - offset[0], xSlice[1] - offset[1]);
+  glVertex2d(xSlice[0] - offset[0], xSlice[1] + offset[1]);
+  glEnd();
+
+  glColor3d(0, 0, 0);
+  glBegin(GL_LINE_LOOP);
+  glVertex2d(xSlice[0] + offset[0], xSlice[1] + offset[1]);
+  glVertex2d(xSlice[0] + offset[0], xSlice[1] - offset[1]);
+  glVertex2d(xSlice[0] - offset[0], xSlice[1] - offset[1]);
+  glVertex2d(xSlice[0] - offset[0], xSlice[1] + offset[1]);
+  glEnd();
+}
+
+AnnotationRenderer::AnnotationRenderer()
+{
+  m_Model = NULL;
+}
+
+
diff --git a/GUI/Renderer/AnnotationRenderer.h b/GUI/Renderer/AnnotationRenderer.h
new file mode 100644
index 0000000..f306cab
--- /dev/null
+++ b/GUI/Renderer/AnnotationRenderer.h
@@ -0,0 +1,33 @@
+#ifndef ANNOTATIONRENDERER_H
+#define ANNOTATIONRENDERER_H
+
+#include "SNAPCommon.h"
+#include "GenericSliceRenderer.h"
+
+
+class AnnotationModel;
+
+class AnnotationRenderer : public SliceRendererDelegate
+{
+public:
+
+  irisITKObjectMacro(AnnotationRenderer, SliceRendererDelegate)
+
+  virtual void paintGL();
+
+  irisGetMacro(Model, AnnotationModel *)
+  irisSetMacro(Model, AnnotationModel *)
+
+protected:
+
+  AnnotationRenderer();
+  virtual ~AnnotationRenderer() {}
+
+  AnnotationModel *m_Model;
+  void DrawLineLength(const Vector3f &xSlice1, const Vector3f &xSlice2,
+                      const Vector3d &color, double alpha);
+
+  void DrawSelectionHandle(const Vector3f &xSlice);
+};
+
+#endif // ANNOTATIONRENDERER_H
diff --git a/GUI/Renderer/ColorMapRenderer.cxx b/GUI/Renderer/ColorMapRenderer.cxx
index 0f8e8ba..ccfbe56 100644
--- a/GUI/Renderer/ColorMapRenderer.cxx
+++ b/GUI/Renderer/ColorMapRenderer.cxx
@@ -197,7 +197,7 @@ void ColorMapRenderer::paintGL()
 
 }
 
-void ColorMapRenderer::resizeGL(int w, int h)
+void ColorMapRenderer::resizeGL(int w, int h, int device_pixel_ratio)
 {
   // Instead of using the w/h passed in here, which are in physical pixel units,
   // we will use 'logical' pixel units on Retina-type displays. This makes the
@@ -210,7 +210,7 @@ void ColorMapRenderer::resizeGL(int w, int h)
   // Set up the basic projection with a small margin
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
-  gluOrtho2D(-0.1,1.1,-0.1,1.1);
+  irisOrtho2D(-0.1,1.1,-0.1,1.1);
   glViewport(0,0,vpl[0],vpl[1]);
 
   // Establish the model view matrix
diff --git a/GUI/Renderer/ColorMapRenderer.h b/GUI/Renderer/ColorMapRenderer.h
index a8970df..f4a139b 100644
--- a/GUI/Renderer/ColorMapRenderer.h
+++ b/GUI/Renderer/ColorMapRenderer.h
@@ -13,7 +13,7 @@ public:
 
   void SetModel(ColorMapModel *model);
 
-  void resizeGL(int w, int h);
+  void resizeGL(int w, int h, int device_pixel_ratio);
   void paintGL();
 
 protected:
diff --git a/GUI/Renderer/CrosshairsRenderer.cxx b/GUI/Renderer/CrosshairsRenderer.cxx
index d504980..f6d18c9 100644
--- a/GUI/Renderer/CrosshairsRenderer.cxx
+++ b/GUI/Renderer/CrosshairsRenderer.cxx
@@ -48,7 +48,7 @@ void CrosshairsRenderer::paintGL()
 
   // Get the line color, thickness and dash spacing for the crosshairs
   OpenGLAppearanceElement *elt =
-    this->GetParentRenderer()->IsThumbnailDrawing()
+    this->GetParentRenderer()->IsDrawingZoomThumbnail()
     ? as->GetUIElement(SNAPAppearanceSettings::CROSSHAIRS_THUMB)
     : as->GetUIElement(SNAPAppearanceSettings::CROSSHAIRS);
 
diff --git a/GUI/Renderer/EdgePreprocessingSettingsRenderer.cxx b/GUI/Renderer/EdgePreprocessingSettingsRenderer.cxx
index 80c6c5a..613a284 100644
--- a/GUI/Renderer/EdgePreprocessingSettingsRenderer.cxx
+++ b/GUI/Renderer/EdgePreprocessingSettingsRenderer.cxx
@@ -55,6 +55,11 @@ EdgePreprocessingSettingsRenderer::EdgePreprocessingSettingsRenderer()
 
 }
 
+void EdgePreprocessingSettingsRenderer::OnDevicePixelRatioChange(int old_ratio, int new_ratio)
+{
+  this->UpdateChartDevicePixelRatio(m_Chart, old_ratio, new_ratio);
+}
+
 void EdgePreprocessingSettingsRenderer::SetModel(SnakeWizardModel *model)
 {
   this->m_Model = model;
diff --git a/GUI/Renderer/EdgePreprocessingSettingsRenderer.h b/GUI/Renderer/EdgePreprocessingSettingsRenderer.h
index 0bbf5c9..b40e288 100644
--- a/GUI/Renderer/EdgePreprocessingSettingsRenderer.h
+++ b/GUI/Renderer/EdgePreprocessingSettingsRenderer.h
@@ -39,6 +39,8 @@ protected:
   vtkSmartPointer<vtkTable> m_PlotTable;
   vtkSmartPointer<vtkPlot> m_Plot;
   vtkSmartPointer<vtkFloatArray> m_DataX, m_DataY;
+
+  virtual void OnDevicePixelRatioChange(int old_ratio, int new_ratio);
 };
 
 #endif // EDGEPREPROCESSINGSETTINGSRENDERER_H
diff --git a/GUI/Renderer/GMMRenderer.cxx b/GUI/Renderer/GMMRenderer.cxx
index 47c9255..7700027 100644
--- a/GUI/Renderer/GMMRenderer.cxx
+++ b/GUI/Renderer/GMMRenderer.cxx
@@ -175,3 +175,8 @@ void GMMRenderer::UpdatePlotValues()
       }
     }
 }
+
+void GMMRenderer::OnDevicePixelRatioChange(int old_ratio, int new_ratio)
+{
+  this->UpdateChartDevicePixelRatio(m_Chart, old_ratio, new_ratio);
+}
diff --git a/GUI/Renderer/GMMRenderer.h b/GUI/Renderer/GMMRenderer.h
index 0670cbc..1d2f9be 100644
--- a/GUI/Renderer/GMMRenderer.h
+++ b/GUI/Renderer/GMMRenderer.h
@@ -41,6 +41,8 @@ protected:
   LayerHistogramPlotAssembly *m_HistogramAssembly;
 
   static unsigned int NUM_POINTS;
+
+  void OnDevicePixelRatioChange(int old_ratio, int new_ratio);
 };
 
 #endif // GMMRENDERER_H
diff --git a/GUI/Renderer/GenericSliceRenderer.cxx b/GUI/Renderer/GenericSliceRenderer.cxx
index fb5baff..609b015 100644
--- a/GUI/Renderer/GenericSliceRenderer.cxx
+++ b/GUI/Renderer/GenericSliceRenderer.cxx
@@ -42,7 +42,8 @@
 GenericSliceRenderer
 ::GenericSliceRenderer()
 {
-  this->m_ThumbnailDrawing = false;
+  this->m_DrawingZoomThumbnail = false;
+  this->m_DrawingLayerThumbnail = false;
 }
 
 void
@@ -86,6 +87,13 @@ GenericSliceRenderer::SetModel(GenericSliceModel *model)
   PaintbrushSettingsModel *psm = m_Model->GetParentUI()->GetPaintbrushSettingsModel();
   Rebroadcast(psm->GetBrushSizeModel(), ValueChangedEvent(), AppearanceUpdateEvent());
 
+  // Which layer is currently selected
+  Rebroadcast(m_Model->GetParentUI()->GetDriver()->GetGlobalState()->GetSelectedLayerIdModel(),
+              ValueChangedEvent(), AppearanceUpdateEvent());
+
+  Rebroadcast(m_Model->GetHoveredImageLayerIdModel(), ValueChangedEvent(), AppearanceUpdateEvent());
+  Rebroadcast(m_Model->GetHoveredImageIsThumbnailModel(), ValueChangedEvent(), AppearanceUpdateEvent());
+
 }
 
 void GenericSliceRenderer::OnUpdate()
@@ -110,15 +118,8 @@ void
 GenericSliceRenderer
 ::paintGL()
 {
-  // Number of divisions
-  DisplayLayoutModel *dlm = m_Model->GetParentUI()->GetDisplayLayoutModel();
-  Vector2ui layout = dlm->GetSliceViewLayerTilingModel()->GetValue();
-  int nrows = (int) layout[0];
-  int ncols = (int) layout[1];
-
-  // Get the dimensions of the cells
-  unsigned int cell_w = m_Model->GetSize()[0];
-  unsigned int cell_h = m_Model->GetSize()[1];
+  // Get the current image data
+  GenericImageData *id = m_Model->GetDriver()->GetCurrentImageData();
 
   // Get the appearance settings pointer since we use it a lot
   SNAPAppearanceSettings *as =
@@ -128,90 +129,190 @@ GenericSliceRenderer
   Vector3d clrBack = as->GetUIElement(
       SNAPAppearanceSettings::BACKGROUND_2D)->GetNormalColor();
 
+  // Get the overall viewport
+  Vector2ui vp_full = m_Model->GetSizeReporter()->GetViewportSize();
+  int vppr = m_Model->GetSizeReporter()->GetViewportPixelRatio();
+
   // Set up lighting attributes
   glPushAttrib(GL_LIGHTING_BIT | GL_DEPTH_BUFFER_BIT |
-               GL_PIXEL_MODE_BIT | GL_TEXTURE_BIT );
+               GL_PIXEL_MODE_BIT | GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT);
 
   glDisable(GL_LIGHTING);
 
   glClearColor(clrBack[0], clrBack[1], clrBack[2], 1.0);
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
+  // Set up the viewports for individual 'cells' in the display. Each cell constitutes one
+  // image with its various overlays.
+
   // Slice should be initialized before display
   if (m_Model->IsSliceInitialized())
     {
-    // Draw each cell in the nrows by ncols table of images. Usually, there
-    // will only be one column, but the new SNAP supports side-by-side drawing
-    // of layers for when there are overlays
-    for(int irow = 0; irow < nrows; irow++)
-      for(int icol = 0; icol < ncols; icol++)
+    // Draw each viewport in turn. For now, the number of z-layers is hard-coded at 2
+    for(int k = 0; k < m_Model->GetViewportLayout().vpList.size(); k++)
+      {
+      const SliceViewportLayout::SubViewport &vp = m_Model->GetViewportLayout().vpList[k];
+
+      // Set up the viewport for the current cell
+      glViewport(vp.pos[0], vp.pos[1], vp.size[0], vp.size[1]);
+
+      // Set up the projection
+      glMatrixMode(GL_PROJECTION);
+      glPushMatrix();
+      glLoadIdentity();
+      irisOrtho2D(0.0, vp.size[0], 0.0, vp.size[1]);
+
+      // Establish the model view matrix
+      glMatrixMode(GL_MODELVIEW);
+      glPushMatrix();
+      glLoadIdentity();
+      glPushMatrix();
+
+      // First set of transforms
+      glTranslated(0.5 * vp.size[0], 0.5 * vp.size[1], 0.0);
+
+      // Zoom by display zoom. The amount of zoom depends on whether we are in thumbnail
+      // mode or in regular mode
+      double zoom = m_Model->GetViewZoom();
+      if(vp.isThumbnail)
         {
-        // Set up the viewport for the current cell
-        glViewport(icol * cell_w, (nrows - 1 - irow) * cell_h,
-                   cell_w, cell_h);
+        double scale_x = vp.size[0] * 1.0 / m_Model->GetCanvasSize()[0];
+        double scale_y = vp.size[1] * 1.0 / m_Model->GetCanvasSize()[1];
+        zoom *= std::max(scale_x, scale_y);
+        }
 
-        // Set up the projection
-        glMatrixMode(GL_PROJECTION);
-        glLoadIdentity();
-        gluOrtho2D(0.0, cell_w, 0.0, cell_h);
+      // Apply the correct scaling
+      glScalef(zoom, zoom, 1.0);
 
-        // Establish the model view matrix
-        glMatrixMode(GL_MODELVIEW);
-        glLoadIdentity();
+      // Panning
+      glTranslated(-m_Model->GetViewPosition()[0], -m_Model->GetViewPosition()[1], 0.0);
 
-        // Scale to account for multiple rows and columns
-        // glScaled(1.0 / ncols, 1.0 / nrows, 1.0);
+      // Convert from voxel space to physical units
+      glScalef(m_Model->GetSliceSpacing()[0], m_Model->GetSliceSpacing()[1], 1.0);
 
-        // Prepare for overlay drawing.  The model view is set up to correspond
-        // to pixel coordinates of the slice
-        glPushMatrix();
+      // Draw the main layers for this row/column combination
+      ImageWrapperBase *layer = id->FindLayer(vp.layer_id, false);
+      if(layer && this->DrawImageLayers(layer, !vp.isThumbnail))
+        {
+        // Set the thumbnail flag
+        m_DrawingLayerThumbnail = vp.isThumbnail;
 
-        // First set of transforms
-        glTranslated(0.5 * cell_w, 0.5 * cell_h, 0.0);
+        // We don't want to draw segmentation over the speed image and other
+        // SNAP-mode layers.
+        this->DrawSegmentationTexture();
 
-        // Zoom by display zoom
-        glScalef(m_Model->GetViewZoom(), m_Model->GetViewZoom(), 1.0);
+        // Draw the overlays
+        if(as->GetOverallVisibility())
+          {
+          // Draw all the overlays added to this object
+          this->DrawTiledOverlays();
+          }
 
-        // Panning
-        glTranslated(-m_Model->GetViewPosition()[0],
-                     -m_Model->GetViewPosition()[1],
-                     0.0);
+        glPopMatrix();
 
-        // Convert from voxel space to physical units
-        glScalef(m_Model->GetSliceSpacing()[0],
-                 m_Model->GetSliceSpacing()[1],
-                 1.0);
+        // Determine if the current layer is hovered over by the mouse
+        bool is_hover = layer->GetUniqueId() == m_Model->GetHoveredImageLayerId();
+        bool is_thumb = vp.isThumbnail;
+        bool is_selected = layer->GetUniqueId() == m_Model->GetDriver()->GetGlobalState()->GetSelectedLayerId();
 
-        // Draw the main layers for this row/column combination
-        if(this->DrawImageLayers(nrows, ncols, irow, icol))
+        // Draw decoration around layer thumbnail. This is done when the thumbnail is hovered over
+        // or currently selected
+        if(is_thumb && (is_hover || is_selected))
           {
-          // We don't want to draw segmentation over the speed image and other
-          // SNAP-mode layers.
-          this->DrawSegmentationTexture();
+          // If the layer has positive z, draw a line
+          glPushAttrib(GL_LINE_BIT | GL_COLOR_BUFFER_BIT);
 
-          // Draw the overlays
-          if(as->GetOverallVisibility())
+          // The element used for highlighting thumbnails
+          SmartPtr<OpenGLAppearanceElement> elt = OpenGLAppearanceElement::New();
+          elt->SetNormalColor(Vector3d(0.6, 0.54, 0.46));
+          elt->SetActiveColor(Vector3d(1.0, 0.9, 0.1));
+          elt->SetLineThickness(1.5 * vppr);
+          elt->SetVisible(true);
+          elt->SetAlphaBlending(false);
+
+          elt->ApplyLineSettings();
+
+          // Determine the colors
+          if(is_selected && is_hover)
+            {
+            Vector3d clr = elt->GetActiveColor();
+            clr += 0.4;
+            clr = clr.clamp(Vector3d(0.0), Vector3d(1.0));
+            glColor3dv(clr.data_block());
+            }
+          else if(is_selected)
             {
-            // Draw all the overlays added to this object
-            this->DrawTiledOverlays();
+            glColor3dv(elt->GetActiveColor().data_block());
+            }
+          else if(is_hover)
+            {
+            glColor3dv(elt->GetNormalColor().data_block());
+            }
 
+          glBegin(GL_LINE_LOOP);
+          glVertex2i(0,0);
+          glVertex2i(0,vp.size[1]);
+          glVertex2i(vp.size[0], vp.size[1]);
+          glVertex2i(vp.size[0], 0);
+          glEnd();
+
+          glPopAttrib();
+          }
+
+        // Draw context menu indicator for the layer being hovered
+        /*
+         * // NOTE - this is now being done in the Qt code instead
+        if(is_hover && is_thumb == m_Model->GetHoveredImageIsThumbnail())
+          {
+          // Load the texture for the icon
+          static GLuint icon_texture_id = -1u;
+          static Vector2ui icon_size;
+          int vpratio = m_Model->GetSizeReporter()->GetViewportPixelRatio();
+          if(icon_texture_id == -1u)
+            {
+            m_PlatformSupport->LoadTexture("context_gray_12", icon_texture_id, icon_size);
             }
+
+          // Draw the icon in the corner of the view
+          glPushAttrib(GL_COLOR_BUFFER_BIT | GL_TEXTURE_BIT);
+          glEnable(GL_TEXTURE_2D);
+          glEnable(GL_BLEND);
+          glBindTexture(GL_TEXTURE_2D, icon_texture_id);
+          glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+          glColor3d(1.0, 1.0, 1.0);
+          glBegin(GL_QUADS);
+          int margin = 4 * vpratio;
+          int x0 = vp.size[0] - margin - icon_size[0], x1 = vp.size[0] - margin;
+          int y1 = vp.size[1] - margin - icon_size[1], y0 = vp.size[1] - margin;
+          glTexCoord2d(0.0, 0.0); glVertex2i(x0,y0);
+          glTexCoord2d(0.0, 1.0); glVertex2i(x0,y1);
+          glTexCoord2d(1.0, 1.0); glVertex2i(x1,y1);
+          glTexCoord2d(1.0, 0.0); glVertex2i(x1,y0);
+          glEnd();
+
+          glPopAttrib();
           }
+          */
+
 
-        // Clean up the GL state
+        glPopMatrix();
+        glMatrixMode(GL_PROJECTION);
         glPopMatrix();
         }
+      }
 
-    // Set the viewport and projection to original dimensions
-    Vector2ui vp = m_Model->GetSizeReporter()->GetViewportSize();
+    // No longer drawing thumbnails
+    m_DrawingLayerThumbnail = false;
 
-    glViewport(0, 0, vp[0], vp[1]);
+    // Set the viewport and projection to original dimensions
+    glViewport(0, 0, vp_full[0], vp_full[1]);
 
     // Set up the projection
     glMatrixMode(GL_PROJECTION);
     glPushMatrix();
     glLoadIdentity();
-    gluOrtho2D(0.0, vp[0], 0.0, vp[1]);
+    irisOrtho2D(0.0, vp_full[0], 0.0, vp_full[1]);
 
     // Establish the model view matrix
     glMatrixMode(GL_MODELVIEW);
@@ -233,7 +334,6 @@ GenericSliceRenderer
 
     glMatrixMode(GL_MODELVIEW);
     glPopMatrix();
-
     }
 
   // Draw the various decorations
@@ -245,12 +345,12 @@ GenericSliceRenderer
 
 void
 GenericSliceRenderer
-::resizeGL(int w, int h)
+::resizeGL(int w, int h, int device_pixel_ratio)
 {
   // Set up projection matrix
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
-  gluOrtho2D(0.0,w,0.0,h);
+  irisOrtho2D(0.0,w,0.0,h);
   glViewport(0,0,w,h);
 
   // Establish the model view matrix
@@ -258,34 +358,37 @@ GenericSliceRenderer
   glLoadIdentity();
 }
 
-bool GenericSliceRenderer::DrawImageLayers(int nrows, int ncols, int irow, int icol)
+bool GenericSliceRenderer::DrawImageLayers(ImageWrapperBase *base_layer, bool drawStickies)
 {
   // Get the image data
   GenericImageData *id = m_Model->GetImageData();
 
   // If drawing the thumbnail, only draw the main layer
-  if(m_ThumbnailDrawing)
+  if(m_DrawingZoomThumbnail)
     {
-    DrawTextureForLayer(id->GetMain(), false);
+    DrawTextureForLayer(base_layer, false);
     return true;
     }
 
   // Is the display partitioned into rows and columns?
-  if(nrows == 1 && ncols == 1)
+  if(!this->IsTiledMode())
     {
-    // Draw all the layers that are visible except segmentation, which is handled
-    // separately (last)
-    for(LayerIterator it(id); !it.IsAtEnd(); ++it)
+    // Draw the base layer without transparency
+    DrawTextureForLayer(base_layer, false);
+
+    // Now draw all the sticky layers on top
+    if(drawStickies)
       {
-      ImageWrapperBase *layer = it.GetLayer();
-      if(it.GetRole() == MAIN_ROLE)
-        {
-        DrawTextureForLayer(layer, false);
-        }
-      else if(it.GetRole() != LABEL_ROLE
-              && layer->IsDrawable() && layer->GetAlpha() > 0)
+        for(LayerIterator it(id); !it.IsAtEnd(); ++it)
         {
-        DrawTextureForLayer(it.GetLayer(), true);
+        ImageWrapperBase *layer = it.GetLayer();
+        if(it.GetRole() != LABEL_ROLE
+           && layer->IsDrawable()
+           && layer->IsSticky()
+           && layer->GetAlpha() > 0)
+          {
+          DrawTextureForLayer(layer, true);
+          }
         }
       }
 
@@ -293,56 +396,37 @@ bool GenericSliceRenderer::DrawImageLayers(int nrows, int ncols, int irow, int i
     }
   else
     {
-    // Geth the n-th layer
-    ImageWrapperBase *layer = GetLayerForNthTile(irow, icol);
-
-    // Check if the layer is in drawable condition. If not, draw nothing.
-    if(!layer)
-      return false;
-
     // Draw the particular layer
-    DrawTextureForLayer(layer, false);
+    DrawTextureForLayer(base_layer, false);
 
     // Now draw all the non-sticky layers
-    for(LayerIterator itov(id); !itov.IsAtEnd(); ++itov)
+    if(drawStickies)
       {
-      if(itov.GetRole() != MAIN_ROLE
-         && itov.GetLayer()->IsSticky()
-         && itov.GetLayer()->IsDrawable()
-         && itov.GetLayer()->GetAlpha() > 0)
+      for(LayerIterator itov(id); !itov.IsAtEnd(); ++itov)
         {
-        DrawTextureForLayer(itov.GetLayer(), true);
+        if(itov.GetRole() != MAIN_ROLE
+           && itov.GetLayer()->IsSticky()
+           && itov.GetLayer()->IsDrawable()
+           && itov.GetLayer()->GetAlpha() > 0)
+          {
+          DrawTextureForLayer(itov.GetLayer(), true);
+          }
         }
       }
 
     return true;
-    }
+  }
 }
 
-
-ImageWrapperBase *GenericSliceRenderer::GetLayerForNthTile(int row, int col)
+bool GenericSliceRenderer::IsTiledMode() const
 {
-  // Number of divisions
   DisplayLayoutModel *dlm = m_Model->GetParentUI()->GetDisplayLayoutModel();
   Vector2ui layout = dlm->GetSliceViewLayerTilingModel()->GetValue();
-  int ncols = (int) layout[1];
+  return layout[0] > 1 || layout[1] > 1;
+}
 
-  // How many layers to go until we get to the one we want to paint?
-  int togo = row * ncols + col;
 
-  // Skip all layers until we get to the sticky layer we want to paint
-  for(LayerIterator it(m_Model->GetImageData()); !it.IsAtEnd(); ++it)
-    {
-    if(it.GetRole() == MAIN_ROLE || !it.GetLayer()->IsSticky())
-      {
-      if(togo == 0)
-        return it.GetLayer()->IsDrawable() ? it.GetLayer() : NULL;
-      togo--;
-      }
-    }
 
-  return NULL;
-}
 
 
 
@@ -356,7 +440,7 @@ void GenericSliceRenderer::DrawMainTexture()
     DrawTextureForLayer(id->GetMain(), false);
 
   // Draw each of the overlays
-  if (!m_ThumbnailDrawing)
+  if (!m_DrawingZoomThumbnail)
     {
     for(LayerIterator it(id, OVERLAY_ROLE); !it.IsAtEnd(); ++it)
       DrawTextureForLayer(it.GetLayer(), true);
@@ -392,7 +476,7 @@ void GenericSliceRenderer::DrawTextureForLayer(
       }
     else
       {
-      Vector3d clrBackground = m_ThumbnailDrawing
+      Vector3d clrBackground = m_DrawingZoomThumbnail
         ? as->GetUIElement(SNAPAppearanceSettings::ZOOM_THUMBNAIL)->GetNormalColor()
         : Vector3d(1.0);
       tex->Draw(clrBackground);
@@ -404,11 +488,11 @@ void GenericSliceRenderer::DrawTextureForLayer(
 void GenericSliceRenderer::DrawSegmentationTexture()
   {
   GenericImageData *id = m_Model->GetImageData();
+  double alpha = m_Model->GetParentUI()->GetDriver()->GetGlobalState()->GetSegmentationAlpha();
 
-  if (id->IsSegmentationLoaded())
+  if (id->IsSegmentationLoaded() && alpha > 0)
     {
     Texture *texture = m_Texture[id->GetSegmentation()];
-    double alpha = m_Model->GetParentUI()->GetDriver()->GetGlobalState()->GetSegmentationAlpha();
     texture->DrawTransparent(alpha);
     }
   }
@@ -425,16 +509,11 @@ void GenericSliceRenderer::DrawThumbnail()
 
   // Tell model to figure out the thumbnail size
   m_Model->ComputeThumbnailProperties();
-  Vector2i tPos = m_Model->GetThumbnailPosition();
+  Vector2i tPos = m_Model->GetZoomThumbnailPosition();
   double tZoom = m_Model->GetThumbnailZoom();
 
-  // Current display layout
-  DisplayLayoutModel *dlm = m_Model->GetParentUI()->GetDisplayLayoutModel();
-  Vector2ui layout = dlm->GetSliceViewLayerTilingModel()->GetValue();
-  unsigned int rows = layout[0], cols = layout[1];
-
   // Indicate the fact that we are currently drawing in thumbnail mode
-  m_ThumbnailDrawing = true;
+  m_DrawingZoomThumbnail = true;
 
   // Set up the GL matrices
   glPushMatrix();
@@ -472,8 +551,8 @@ void GenericSliceRenderer::DrawThumbnail()
   glTranslated(m_Model->GetViewPosition()[0],
                m_Model->GetViewPosition()[1],
                0.0);
-  w = m_Model->GetSize()[0] * 0.5 / m_Model->GetViewZoom();
-  h = m_Model->GetSize()[1] * 0.5 / m_Model->GetViewZoom();
+  w = m_Model->GetCanvasSize()[0] * 0.5 / m_Model->GetViewZoom();
+  h = m_Model->GetCanvasSize()[1] * 0.5 / m_Model->GetViewZoom();
 
   glColor3dv(elt->GetActiveColor().data_block());
   glBegin(GL_LINE_LOOP);
@@ -486,7 +565,7 @@ void GenericSliceRenderer::DrawThumbnail()
   glPopMatrix();
 
   // Indicate the fact that we are not drawing in thumbnail mode
-  m_ThumbnailDrawing = false;
+  m_DrawingZoomThumbnail = false;
   }
 
 GenericSliceRenderer::Texture *
diff --git a/GUI/Renderer/GenericSliceRenderer.h b/GUI/Renderer/GenericSliceRenderer.h
index 3eb6ae6..f1db6db 100644
--- a/GUI/Renderer/GenericSliceRenderer.h
+++ b/GUI/Renderer/GenericSliceRenderer.h
@@ -66,11 +66,16 @@ public:
   void SetModel(GenericSliceModel *model);
 
   void initializeGL();
-  void resizeGL(int w, int h);
-  void paintGL();
+  virtual void resizeGL(int w, int h, int device_pixel_ratio);
+  virtual void paintGL();
 
   irisGetMacro(Model, GenericSliceModel *)
-  irisIsMacro(ThumbnailDrawing)
+
+  /** This flag is on while the zoom thumbnail is being painted */
+  irisIsMacro(DrawingZoomThumbnail)
+
+  /** This flag is on while the layer thumbnail is being painted */
+  irisIsMacro(DrawingLayerThumbnail)
 
   typedef std::list<SliceRendererDelegate *> RendererDelegateList;
 
@@ -91,12 +96,10 @@ public:
   // This method can be used by the renderer delegates to draw a texture
   void DrawTextureForLayer(ImageWrapperBase *layer, bool use_transparency);
 
-  // Get the layer that is drawn in the given tile
-  ImageWrapperBase *GetLayerForNthTile(int row, int col);
-
   // A callback for when the model is reinitialized
   // void OnModelReinitialize();
 
+
 protected:
 
   GenericSliceRenderer();
@@ -114,12 +117,14 @@ protected:
   // Draw the image and overlays either on top of each other or separately
   // in individual cells. Returns true if a layer was drawn, false if not,
   // i.e., the cell is outside of the range of available layers
-  bool DrawImageLayers(int nrows, int ncols, int irow, int icol);
+  bool DrawImageLayers(ImageWrapperBase *base_layer, bool drawStickes);
+
+  bool IsTiledMode() const;
 
   GenericSliceModel *m_Model;
 
   // Whether rendering to thumbnail or not
-  bool m_ThumbnailDrawing;
+  bool m_DrawingZoomThumbnail, m_DrawingLayerThumbnail;
 
   // A dynamic association between various image layers and texture objects
   typedef OpenGLSliceTexture<ImageWrapperBase::DisplayPixelType> Texture;
diff --git a/GUI/Renderer/IntensityCurveVTKRenderer.cxx b/GUI/Renderer/IntensityCurveVTKRenderer.cxx
index 71c2273..6df2d63 100644
--- a/GUI/Renderer/IntensityCurveVTKRenderer.cxx
+++ b/GUI/Renderer/IntensityCurveVTKRenderer.cxx
@@ -22,6 +22,8 @@
 #include "vtkRenderWindowInteractor.h"
 #include "vtkContextMouseEvent.h"
 #include "vtkChartLegend.h"
+#include <vtkTextProperty.h>
+
 
 #include "IntensityCurveModel.h"
 #include "IntensityCurveInterface.h"
@@ -415,8 +417,7 @@ IntensityCurveVTKRenderer::IntensityCurveVTKRenderer()
   m_CurvePlot->GetYAxis()->SetMinimumLimit(-0.1);
   m_CurvePlot->GetYAxis()->SetMinimum(-0.1);
   m_CurvePlot->GetYAxis()->SetMaximumLimit(1.1);
-  m_CurvePlot->GetYAxis()->SetMaximum(1.1);
-
+  m_CurvePlot->GetYAxis()->SetMaximum(1.1);  
   m_CurvePlot->GetXAxis()->SetTitle("Image Intensity");
   m_CurvePlot->GetYAxis()->SetTitle("Index into Color Map");
   m_CurvePlot->GetXAxis()->SetBehavior(vtkAxis::FIXED);
@@ -576,3 +577,8 @@ IntensityCurveVTKRenderer
   m_Model->GetMovingControlIdModel()->SetValue(
         m_Controls->GetCurrentPoint() + 1);
 }
+
+void IntensityCurveVTKRenderer::OnDevicePixelRatioChange(int old_ratio, int new_ratio)
+{
+  this->UpdateChartDevicePixelRatio(m_Chart, old_ratio, new_ratio);
+}
diff --git a/GUI/Renderer/IntensityCurveVTKRenderer.h b/GUI/Renderer/IntensityCurveVTKRenderer.h
index 94b10db..f0a5f96 100644
--- a/GUI/Renderer/IntensityCurveVTKRenderer.h
+++ b/GUI/Renderer/IntensityCurveVTKRenderer.h
@@ -58,6 +58,8 @@ protected:
 
   void OnCurrentControlPointChangedInScene(vtkObject *, unsigned long, void *);
 
+  virtual void OnDevicePixelRatioChange(int old_ratio, int new_ratio);
+
 };
 
 #endif // INTENSITYCURVEVTKRENDERER_H
diff --git a/GUI/Renderer/OptimizationProgressRenderer.cxx b/GUI/Renderer/OptimizationProgressRenderer.cxx
new file mode 100644
index 0000000..d0100b3
--- /dev/null
+++ b/GUI/Renderer/OptimizationProgressRenderer.cxx
@@ -0,0 +1,96 @@
+#include "OptimizationProgressRenderer.h"
+
+#include "ImageIOWizardModel.h"
+
+#include <vtkChartXY.h>
+#include <vtkPlot.h>
+#include <vtkPlotBar.h>
+#include <vtkFloatArray.h>
+#include <vtkTable.h>
+#include <vtkContextView.h>
+#include <vtkContextScene.h>
+#include <vtkAxis.h>
+#include <vtkContextMouseEvent.h>
+#include "vtkGenericOpenGLRenderWindow.h"
+
+
+OptimizationProgressRenderer::OptimizationProgressRenderer()
+{
+  m_Model = NULL;
+
+  // Set up the scene for rendering
+  m_Chart = vtkSmartPointer<vtkChartXY>::New();
+  m_Chart->SetActionToButton(vtkChartXY::PAN, vtkContextMouseEvent::LEFT_BUTTON);
+  m_Chart->SetActionToButton(vtkChartXY::ZOOM, vtkContextMouseEvent::RIGHT_BUTTON);
+
+  // Add the chart to the renderer
+  m_ContextView->GetScene()->AddItem(m_Chart);
+
+  // Set up the data
+  m_DataX = vtkSmartPointer<vtkFloatArray>::New();
+  m_DataX->SetName("Optimization Iteration");
+  m_DataY = vtkSmartPointer<vtkFloatArray>::New();
+  m_DataY->SetName("Metric Value");
+
+  // Set up the table
+  m_PlotTable = vtkSmartPointer<vtkTable>::New();
+  m_PlotTable->AddColumn(m_DataX);
+  m_PlotTable->AddColumn(m_DataY);
+  m_PlotTable->SetNumberOfRows(0);
+
+  // Set up the plot
+  m_Plot = m_Chart->AddPlot(vtkChart::LINE);
+  m_Plot->SetInputData(m_PlotTable, 0, 1);
+  m_Plot->SetColor(1, 0, 0);
+  m_Plot->SetWidth(2.0);
+  m_Plot->GetYAxis()->SetBehavior(vtkAxis::FIXED);
+  m_Plot->GetYAxis()->SetMinimum(-0.05);
+  m_Plot->GetYAxis()->SetMaximum(1.05);
+  m_Plot->GetXAxis()->SetTitle("Optimization iteration");
+  m_Plot->GetXAxis()->SetBehavior(vtkAxis::FIXED);
+  m_Plot->GetYAxis()->SetTitle("Metric value");
+
+  // Set the background to white
+  m_BackgroundColor.fill(1.0);
+
+  // Customize the render window
+  this->m_RenderWindow->SetMultiSamples(0);
+  this->m_RenderWindow->SetLineSmoothing(1);
+  this->m_RenderWindow->SetPolygonSmoothing(1);
+}
+
+void OptimizationProgressRenderer::SetModel(ImageIOWizardModel *model)
+{
+  m_Model = model;
+
+  // Rebroadcast the relevant events from the model in order for the
+  // widget that uses this renderer to cause an update
+  Rebroadcast(model, ImageIOWizardModel::RegistrationProgressEvent(), ModelUpdateEvent());
+
+  // Reset value range
+
+}
+
+void OptimizationProgressRenderer::OnUpdate()
+{
+  int x = m_DataX->GetNumberOfTuples()+1;
+  double y = m_Model->GetRegistrationObjective();
+
+  m_DataX->InsertNextValue(x);
+  m_DataY->InsertNextValue(y);
+  m_PlotTable->Modified();
+
+  m_Plot->GetXAxis()->SetRange(0.0, ((x + 5) / 40 + 1) * 40.0);
+
+
+  if (x == 1 || y <= m_MinValue)
+    {
+    m_MinValue = (((int) floor(y * 10)) - 1) * 0.1;
+    }
+  if (x == 1 || y >= m_MaxValue)
+    {
+    m_MaxValue = (((int) ceil(y * 10)) + 1) * 0.1;
+    }
+
+  m_Plot->GetYAxis()->SetRange(m_MinValue, m_MaxValue);
+}
diff --git a/GUI/Renderer/OptimizationProgressRenderer.h b/GUI/Renderer/OptimizationProgressRenderer.h
new file mode 100644
index 0000000..e33769d
--- /dev/null
+++ b/GUI/Renderer/OptimizationProgressRenderer.h
@@ -0,0 +1,46 @@
+#ifndef OPTIMIZATIONPROGRESSRENDERER_H
+#define OPTIMIZATIONPROGRESSRENDERER_H
+
+#include "AbstractVTKSceneRenderer.h"
+#include "vtkSmartPointer.h"
+
+class vtkActor;
+class vtkPropAssembly;
+class vtkChartXY;
+class vtkFloatArray;
+class vtkPlot;
+class vtkTable;
+
+class ImageIOWizardModel;
+
+class OptimizationProgressRenderer : public AbstractVTKSceneRenderer
+{
+public:
+
+  irisITKObjectMacro(OptimizationProgressRenderer, AbstractVTKSceneRenderer)
+
+  void SetModel(ImageIOWizardModel *model);
+
+  void OnUpdate();
+
+  void UpdatePlotValues();
+
+protected:
+
+  OptimizationProgressRenderer();
+
+  virtual ~OptimizationProgressRenderer() {}
+
+  ImageIOWizardModel *m_Model;
+
+  // Rendering stuff
+  vtkSmartPointer<vtkChartXY> m_Chart;
+  vtkSmartPointer<vtkTable> m_PlotTable;
+  vtkSmartPointer<vtkPlot> m_Plot;
+  vtkSmartPointer<vtkFloatArray> m_DataX, m_DataY;
+
+  // Range of values
+  double m_MinValue, m_MaxValue;
+};
+
+#endif // OPTIMIZATIONPROGRESSRENDERER_H
diff --git a/GUI/Renderer/PolygonDrawingRenderer.cxx b/GUI/Renderer/PolygonDrawingRenderer.cxx
index 9cf65da..ec79734 100644
--- a/GUI/Renderer/PolygonDrawingRenderer.cxx
+++ b/GUI/Renderer/PolygonDrawingRenderer.cxx
@@ -32,7 +32,7 @@ PolygonDrawingRenderer
 ::paintGL()
 {
   assert(m_Model);
-  if(m_ParentRenderer->IsThumbnailDrawing())
+  if(m_ParentRenderer->IsDrawingZoomThumbnail() || m_ParentRenderer->IsDrawingLayerThumbnail())
     return;
 
   PolygonDrawingModel::PolygonState state = m_Model->GetState();
@@ -68,7 +68,8 @@ PolygonDrawingRenderer
   glPushAttrib(GL_LINE_BIT | GL_COLOR_BUFFER_BIT);
 
   // Set line and point drawing parameters
-  glPointSize(4);
+  float vppr = m_ParentRenderer->GetModel()->GetSizeReporter()->GetViewportPixelRatio();
+  glPointSize(3 * vppr);
 
   // Draw the line segments
   const PolygonDrawingModel::VertexList &vx = m_Model->GetVertices();
diff --git a/GUI/Renderer/PolygonScanConvert.cxx b/GUI/Renderer/PolygonScanConvert.cxx
index f8b5e4c..461bfb4 100644
--- a/GUI/Renderer/PolygonScanConvert.cxx
+++ b/GUI/Renderer/PolygonScanConvert.cxx
@@ -119,7 +119,7 @@ PolygonScanConvertBase
       glMatrixMode(GL_PROJECTION);
       glPushMatrix();
       glLoadIdentity();
-      gluOrtho2D(xTile, xTile + wTile, yTile, yTile + hTile);
+      irisOrtho2D(xTile, xTile + wTile, yTile, yTile + hTile);
 
       // Set the model view matrix
       glMatrixMode(GL_MODELVIEW);
diff --git a/GUI/Renderer/SliceWindowDecorationRenderer.cxx b/GUI/Renderer/SliceWindowDecorationRenderer.cxx
index b10ef75..f972251 100644
--- a/GUI/Renderer/SliceWindowDecorationRenderer.cxx
+++ b/GUI/Renderer/SliceWindowDecorationRenderer.cxx
@@ -61,7 +61,9 @@ void SliceWindowDecorationRenderer::DrawOrientationLabels()
     }
 
   double vppr = parentModel->GetSizeReporter()->GetViewportPixelRatio();
-  Vector2ui vp = parentModel->GetSizeReporter()->GetLogicalViewportSize();
+
+  Vector2ui vp_pos, vp_size;
+  parentModel->GetNonThumbnailViewport(vp_pos, vp_size);
 
   glPushAttrib(GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT | GL_DEPTH_BUFFER_BIT);
   glPushMatrix();
@@ -74,7 +76,7 @@ void SliceWindowDecorationRenderer::DrawOrientationLabels()
   // Get the various sizes and offsets
   int offset = 4 + elt->GetFontSize();
   int margin = elt->GetFontSize() / 3;
-  int w = vp[0], h = vp[1];
+  int w = vp_size[0] / vppr, h = vp_size[1] / vppr;
 
   // Create the font info
   AbstractRendererPlatformSupport::FontInfo font_info =
@@ -97,6 +99,33 @@ void SliceWindowDecorationRenderer::DrawOrientationLabels()
   glPopAttrib();
 }
 
+std::string SliceWindowDecorationRenderer::GetDisplayText(ImageWrapperBase *layer)
+{
+  std::string nickname = layer->GetNickname();
+  if(layer->GetNumberOfComponents() > 1)
+    {
+    AbstractMultiChannelDisplayMappingPolicy *policy =
+        static_cast<AbstractMultiChannelDisplayMappingPolicy *>(layer->GetDisplayMapping());
+    MultiChannelDisplayMode mode = policy->GetDisplayMode();
+    if(mode.UseRGB)
+      nickname += " [RGB]";
+    else if(mode.SelectedScalarRep == SCALAR_REP_MAGNITUDE)
+      nickname += " [Mag]";
+    else if(mode.SelectedScalarRep == SCALAR_REP_MAX)
+      nickname += " [Max]";
+    else if(mode.SelectedScalarRep == SCALAR_REP_AVERAGE)
+      nickname += " [Avg]";
+    else
+      {
+      std::ostringstream oss;
+      oss << " [" << mode.SelectedComponent + 1 << "/" << layer->GetNumberOfComponents() <<  "]";
+      nickname += oss.str();
+      }
+    }
+
+  return nickname;
+}
+
 void SliceWindowDecorationRenderer::DrawNicknames()
 {
   // Draw the nicknames
@@ -106,9 +135,6 @@ void SliceWindowDecorationRenderer::DrawNicknames()
   int nrows = (int) layout[0];
   int ncols = (int) layout[1];
 
-  if(nrows * ncols == 1)
-    return;
-
   // Get the properties for the labels
   SNAPAppearanceSettings *as =
       parentModel->GetParentUI()->GetAppearanceSettings();
@@ -117,11 +143,17 @@ void SliceWindowDecorationRenderer::DrawNicknames()
       as->GetUIElement(SNAPAppearanceSettings::RULER);
 
   // Leave if the labels are disabled
-  if(!elt->GetVisible()) return;
+  if(!elt->GetVisible())
+    return;
+
+  // Leave if there is trivial information to show
+  // ### if(dlm->GetNumberOfGroundLevelLayers() < 2) return;
 
   // Viewport properties (retina-related)
   double vppr = parentModel->GetSizeReporter()->GetViewportPixelRatio();
-  Vector2ui vp = parentModel->GetSizeReporter()->GetLogicalViewportSize();
+
+  Vector2ui vp_pos, vp_size;
+  parentModel->GetNonThumbnailViewport(vp_pos, vp_size);
 
   // Apply the label properties
   glPushAttrib(GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT | GL_DEPTH_BUFFER_BIT);
@@ -133,7 +165,20 @@ void SliceWindowDecorationRenderer::DrawNicknames()
   glColor4d( elt->GetNormalColor()[0], elt->GetNormalColor()[1], elt->GetNormalColor()[2], 1.0 );
 
   // Get the viewport size
-  int w = vp[0] / ncols, h = vp[1] / nrows;
+  int w = vp_size[0] / (vppr * ncols), h = vp_size[1] / (vppr * nrows);
+
+  // For non-tiled mode, set the offset to equal that of the anatomical markers
+  const OpenGLAppearanceElement *elt_marker = as->GetUIElement(SNAPAppearanceSettings::RULER);
+  int left_margin = elt_marker->GetFontSize() / 3;
+  int right_margin = left_margin + 2 + elt_marker->GetFontSize() / 2;
+
+  // Set the maximum allowed width. For tiled layout, this is the size of the tile,
+  // for stacked, it is the half-width of the tile, to leave space for the anatomic
+  // marker
+  int max_allowed_width = (ncols == 1)
+                          ? (int) (0.5 * w - left_margin - right_margin)
+                          : (int) (0.92 * w);
+
 
   AbstractRendererPlatformSupport::FontInfo font_info =
         { AbstractRendererPlatformSupport::SANS, elt->GetFontSize() * vppr, false };
@@ -146,12 +191,13 @@ void SliceWindowDecorationRenderer::DrawNicknames()
       {
       // Define the ROI for this label
       ImageWrapperBase *layer =
-          this->GetParentRenderer()->GetLayerForNthTile(i, j);
+          parentModel->GetLayerForNthTile(i, j);
 
       if(layer)
         {
+        std::string nick_text = this->GetDisplayText(layer);
         int fw = this->m_PlatformSupport->MeasureTextWidth(
-              layer->GetNickname().c_str(), font_info);
+              nick_text.c_str(), font_info) / vppr;
         if(fw > maxwidth)
           maxwidth = fw;
         }
@@ -159,9 +205,9 @@ void SliceWindowDecorationRenderer::DrawNicknames()
     }
 
   // Adjust the font size
-  if(maxwidth > 0.92 * w)
+  if(maxwidth > max_allowed_width)
     {
-    font_info.pixel_size = (int) (font_info.pixel_size * w * 0.92 / maxwidth);
+    font_info.pixel_size = (int) (font_info.pixel_size * max_allowed_width / maxwidth);
     }
 
   // Draw each nickname
@@ -171,15 +217,30 @@ void SliceWindowDecorationRenderer::DrawNicknames()
       {
       // Define the ROI for this label
       ImageWrapperBase *layer =
-          this->GetParentRenderer()->GetLayerForNthTile(i, j);
+          parentModel->GetLayerForNthTile(i, j);
       if(layer)
         {
-        this->m_PlatformSupport->RenderTextInOpenGL(
-              layer->GetNickname().c_str(),
-              w * j, h * (nrows - i) - 20, w, 15, font_info,
-              AbstractRendererPlatformSupport::HCENTER,
-              AbstractRendererPlatformSupport::TOP,
-              elt->GetNormalColor());
+        std::string nick_text = this->GetDisplayText(layer);
+
+        // If there is only one column, we render the text on the left
+        if(ncols == 1)
+          {
+          this->m_PlatformSupport->RenderTextInOpenGL(
+                nick_text.c_str(),
+                left_margin, h * (nrows - i) - 18, w, 15, font_info,
+                AbstractRendererPlatformSupport::LEFT,
+                AbstractRendererPlatformSupport::TOP,
+                elt->GetNormalColor());
+          }
+        else
+          {
+          this->m_PlatformSupport->RenderTextInOpenGL(
+                nick_text.c_str(),
+                w * j, h * (nrows - i) - 20, w, 15, font_info,
+                AbstractRendererPlatformSupport::HCENTER,
+                AbstractRendererPlatformSupport::TOP,
+                elt->GetNormalColor());
+          }
         }
       }
     }
@@ -204,7 +265,13 @@ void SliceWindowDecorationRenderer::DrawRulers()
 
   // Get the viewport properties (retina-capable)
   float vppr = parentModel->GetSizeReporter()->GetViewportPixelRatio();
-  Vector2ui vp = parentModel->GetSizeReporter()->GetLogicalViewportSize();
+
+  // Get the dimensions of the non-thumbnail area where the decorations go
+  Vector2ui vp_pos, vp_size;
+  parentModel->GetNonThumbnailViewport(vp_pos, vp_size);
+
+  // Convert into logical pixel units
+  Vector2f vp = to_float(vp_size) / vppr;
 
   glPushAttrib(GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT | GL_DEPTH_BUFFER_BIT);
   glPushMatrix();
@@ -219,7 +286,7 @@ void SliceWindowDecorationRenderer::DrawRulers()
   double maxw = 0.5 * vp[0] - 20.0;
   maxw = maxw < 5 ? 5 : maxw;
 
-  double zoom = parentModel->GetViewZoom();
+  double zoom = parentModel->GetViewZoom() / vppr;
   double scale = 1.0;
   while(zoom * scale > maxw) scale /= 10.0;
   while(zoom * scale < 0.1 * maxw) scale *= 10.0;
diff --git a/GUI/Renderer/SliceWindowDecorationRenderer.h b/GUI/Renderer/SliceWindowDecorationRenderer.h
index ffd0768..7d6f540 100644
--- a/GUI/Renderer/SliceWindowDecorationRenderer.h
+++ b/GUI/Renderer/SliceWindowDecorationRenderer.h
@@ -25,6 +25,7 @@ protected:
 
   SliceWindowDecorationRenderer();
   virtual ~SliceWindowDecorationRenderer();
+  std::string GetDisplayText(ImageWrapperBase *layer);
 };
 
 #endif // SLICEWINDOWDECORATIONRENDERER_H
diff --git a/GUI/Renderer/SnakeModeRenderer.cxx b/GUI/Renderer/SnakeModeRenderer.cxx
index 0c230e4..5264f55 100644
--- a/GUI/Renderer/SnakeModeRenderer.cxx
+++ b/GUI/Renderer/SnakeModeRenderer.cxx
@@ -18,7 +18,8 @@ void SnakeModeRenderer::paintGL()
   IRISApplication *app = m_Model->GetParent()->GetDriver();
 
   if(app->IsSnakeModeActive()
-     && !this->GetParentRenderer()->IsThumbnailDrawing())
+     && !this->GetParentRenderer()->IsDrawingZoomThumbnail()
+     && !this->GetParentRenderer()->IsDrawingLayerThumbnail())
     {
     // Bubbles are drawn only when on the bubbles page
     if(m_Model->CheckState(SnakeWizardModel::UIF_BUBBLE_MODE))
diff --git a/GUI/Renderer/SnakeParameterPreviewRenderer.cxx b/GUI/Renderer/SnakeParameterPreviewRenderer.cxx
index e8a7d62..0a7b597 100644
--- a/GUI/Renderer/SnakeParameterPreviewRenderer.cxx
+++ b/GUI/Renderer/SnakeParameterPreviewRenderer.cxx
@@ -20,12 +20,12 @@ void SnakeParameterPreviewRenderer::initializeGL()
 {
 }
 
-void SnakeParameterPreviewRenderer::resizeGL(int w, int h)
+void SnakeParameterPreviewRenderer::resizeGL(int w, int h, int device_pixel_ratio)
 {
   // The window will have coordinates (0,0) to (1,1)
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
-  gluOrtho2D(0.0,1.0,0.0,1.0);
+  irisOrtho2D(0.0,1.0,0.0,1.0);
   glViewport(0,0,w,h);
 
   // Establish the model view matrix
diff --git a/GUI/Renderer/SnakeParameterPreviewRenderer.h b/GUI/Renderer/SnakeParameterPreviewRenderer.h
index 8eb1467..037d4be 100644
--- a/GUI/Renderer/SnakeParameterPreviewRenderer.h
+++ b/GUI/Renderer/SnakeParameterPreviewRenderer.h
@@ -30,7 +30,7 @@ public:
   virtual void paintGL();
 
   virtual void initializeGL();
-  virtual void resizeGL(int w, int h);
+  virtual void resizeGL(int w, int h, int device_pixel_ratio);
 
 protected:
 
diff --git a/GUI/Renderer/SnakeROIRenderer.cxx b/GUI/Renderer/SnakeROIRenderer.cxx
index 65eb745..dae8a29 100644
--- a/GUI/Renderer/SnakeROIRenderer.cxx
+++ b/GUI/Renderer/SnakeROIRenderer.cxx
@@ -21,7 +21,7 @@ void SnakeROIRenderer::paintGL()
 
   // Check the current state
   assert(m_Model);
-  if(m_ParentRenderer->IsThumbnailDrawing())
+  if(m_ParentRenderer->IsDrawingZoomThumbnail())
     return;
 
   // The region of interest should be in effect
diff --git a/GUI/Renderer/ThresholdSettingsRenderer.cxx b/GUI/Renderer/ThresholdSettingsRenderer.cxx
index 7ddcd6b..ba6e1e1 100644
--- a/GUI/Renderer/ThresholdSettingsRenderer.cxx
+++ b/GUI/Renderer/ThresholdSettingsRenderer.cxx
@@ -113,3 +113,10 @@ void ThresholdSettingsRenderer::OnUpdate()
 
 }
 
+void ThresholdSettingsRenderer::OnDevicePixelRatioChange(int old_ratio, int new_ratio)
+{
+  this->UpdateChartDevicePixelRatio(m_Chart, old_ratio, new_ratio);
+}
+
+
+
diff --git a/GUI/Renderer/ThresholdSettingsRenderer.h b/GUI/Renderer/ThresholdSettingsRenderer.h
index ca7dc53..7a4dd24 100644
--- a/GUI/Renderer/ThresholdSettingsRenderer.h
+++ b/GUI/Renderer/ThresholdSettingsRenderer.h
@@ -42,6 +42,8 @@ protected:
 
   // Histogram rendering
   LayerHistogramPlotAssembly *m_HistogramAssembly;
+
+  void OnDevicePixelRatioChange(int old_ratio, int new_ratio);
 };
 
 #endif // THRESHOLDSETTINGSRENDERER_H
diff --git a/Logic/Common/ColorMap.cxx b/Logic/Common/ColorMap.cxx
index 0e68edd..c3d8af0 100644
--- a/Logic/Common/ColorMap.cxx
+++ b/Logic/Common/ColorMap.cxx
@@ -75,6 +75,21 @@ ColorMap::CMPoint
   m_RGBA[0][3] = 0;  m_RGBA[1][3] = 0;
   }
 
+
+// Continuous point with linear alpha
+ColorMap::CMPoint
+::CMPoint(double j, EltType r, EltType g, EltType b)
+{
+  m_Index = j;
+  m_Type = (j == 0.0 || j == 1.0) ? DISCONTINUOUS : CONTINUOUS;
+  EltType a = (EltType)(j * 255);
+
+  m_RGBA[0][0] = r;  m_RGBA[1][0] = r;
+  m_RGBA[0][1] = g;  m_RGBA[1][1] = g;
+  m_RGBA[0][2] = b;  m_RGBA[1][2] = b;
+  m_RGBA[0][3] = a;  m_RGBA[1][3] = a;
+}
+
 // Continuous point
 ColorMap::CMPoint
 ::CMPoint(double j, EltType r, EltType g, EltType b, EltType a)
@@ -316,22 +331,22 @@ ColorMap
   {
     case COLORMAP_GREY:
       m_CMPoints.push_back( CMPoint(0.0, 0x00, 0x00, 0x00, 0x00, 0xff) );
-      m_CMPoints.push_back( CMPoint(1.0, 0xff, 0xff, 0xff, 0xff, 0x00) );
+      m_CMPoints.push_back( CMPoint(1.0, 0xff, 0xff, 0xff, 0xff, 0xff) );
       break;
 
     case COLORMAP_RED:
       m_CMPoints.push_back( CMPoint(0.0, 0x00, 0x00, 0x00, 0x00, 0xff) );
-      m_CMPoints.push_back( CMPoint(1.0, 0xff, 0x00, 0x00, 0xff, 0x00) );
+      m_CMPoints.push_back( CMPoint(1.0, 0xff, 0x00, 0x00, 0xff, 0xff) );
       break;
 
     case COLORMAP_GREEN:
       m_CMPoints.push_back( CMPoint(0.0, 0x00, 0x00, 0x00, 0x00, 0xff) );
-      m_CMPoints.push_back( CMPoint(1.0, 0x00, 0xff, 0x00, 0xff, 0x00) );
+      m_CMPoints.push_back( CMPoint(1.0, 0x00, 0xff, 0x00, 0xff, 0xff) );
       break;
 
     case COLORMAP_BLUE:
       m_CMPoints.push_back( CMPoint(0.0, 0x00, 0x00, 0x00, 0x00, 0xff) );
-      m_CMPoints.push_back( CMPoint(1.0, 0x00, 0x00, 0xff, 0xff, 0x00) );
+      m_CMPoints.push_back( CMPoint(1.0, 0x00, 0x00, 0xff, 0xff, 0xff) );
       break;
 
     case COLORMAP_HOT:
@@ -340,38 +355,38 @@ ColorMap
       m_CMPoints.push_back( CMPoint(22.0 / 63.0, 0xd8, 0x00, 0x00, 0xff) );
       m_CMPoints.push_back( CMPoint(28.0 / 63.0, 0xff, 0x3a, 0x00, 0xff) );
       m_CMPoints.push_back( CMPoint(48.0 / 63.0, 0xff, 0xff, 0x00, 0xff) );
-      m_CMPoints.push_back( CMPoint(1.0        , 0xff, 0xff, 0xff, 0xff, 0x00) );
+      m_CMPoints.push_back( CMPoint(1.0        , 0xff, 0xff, 0xff, 0xff, 0xff) );
       break;
 
     case COLORMAP_COOL:
       m_CMPoints.push_back( CMPoint(0.0, 0xff, 0x00, 0xff, 0x00, 0xff) );
-      m_CMPoints.push_back( CMPoint(1.0, 0x00, 0xff, 0xff, 0xff, 0x00) );
+      m_CMPoints.push_back( CMPoint(1.0, 0x00, 0xff, 0xff, 0xff, 0xff) );
       break;
 
     case COLORMAP_SPRING:
       m_CMPoints.push_back( CMPoint(0.0, 0xff, 0x00, 0xff, 0x00, 0xff) );
-      m_CMPoints.push_back( CMPoint(1.0, 0xff, 0xff, 0x00, 0xff, 0x00) );
+      m_CMPoints.push_back( CMPoint(1.0, 0xff, 0xff, 0x00, 0xff, 0xff) );
       break;
 
     case COLORMAP_SUMMER:
       m_CMPoints.push_back( CMPoint(0.0, 0x00, 0x80, 0x66, 0x00, 0xff) );
-      m_CMPoints.push_back( CMPoint(1.0, 0xff, 0xff, 0x66, 0xff, 0x00) );
+      m_CMPoints.push_back( CMPoint(1.0, 0xff, 0xff, 0x66, 0xff, 0xff) );
       break;
 
     case COLORMAP_AUTUMN:
       m_CMPoints.push_back( CMPoint(0.0, 0xff, 0x00, 0x00, 0x00, 0xff) );
-      m_CMPoints.push_back( CMPoint(1.0, 0xff, 0xff, 0x00, 0xff, 0x00) );
+      m_CMPoints.push_back( CMPoint(1.0, 0xff, 0xff, 0x00, 0xff, 0xff) );
       break;
 
     case COLORMAP_WINTER:
       m_CMPoints.push_back( CMPoint(0.0, 0x00, 0x00, 0xff, 0x00, 0xff) );
-      m_CMPoints.push_back( CMPoint(1.0, 0x00, 0xff, 0x80, 0xff, 0x00) );
+      m_CMPoints.push_back( CMPoint(1.0, 0x00, 0xff, 0x80, 0xff, 0xff) );
       break;
 
     case COLORMAP_COPPER:
       m_CMPoints.push_back( CMPoint(0.0,    0x00, 0x00, 0xff, 0x00, 0xff) );
       m_CMPoints.push_back( CMPoint(0.8334, 0xff, 0xaa, 0x6a, 0xff) );
-      m_CMPoints.push_back( CMPoint(1.0,    0xff, 0xcc, 0x80, 0xff, 0x00) );
+      m_CMPoints.push_back( CMPoint(1.0,    0xff, 0xcc, 0x80, 0xff, 0xff) );
       break;
 
     case COLORMAP_HSV:
@@ -381,7 +396,7 @@ ColorMap
       m_CMPoints.push_back( CMPoint(0.5000, 0x00, 0xff, 0xff, 0xff) );
       m_CMPoints.push_back( CMPoint(0.6667, 0x00, 0x00, 0xff, 0xff) );
       m_CMPoints.push_back( CMPoint(0.8334, 0xff, 0x00, 0xff, 0xff) );
-      m_CMPoints.push_back( CMPoint(1.0,    0xff, 0x00, 0x00, 0xff, 0x00) );
+      m_CMPoints.push_back( CMPoint(1.0,    0xff, 0x00, 0x00, 0xff, 0xff) );
       break;
 
     case COLORMAP_JET:
@@ -390,19 +405,19 @@ ColorMap
       m_CMPoints.push_back( CMPoint(0.36  , 0x00, 0xff, 0xff, 0xff) );
       m_CMPoints.push_back( CMPoint(0.6   , 0xff, 0xff, 0x00, 0xff) );
       m_CMPoints.push_back( CMPoint(0.9   , 0xff, 0x00, 0x00, 0xff) );
-      m_CMPoints.push_back( CMPoint(1.0,    0x80, 0x00, 0x00, 0xff, 0x00) );
+      m_CMPoints.push_back( CMPoint(1.0,    0x80, 0x00, 0x00, 0xff, 0xff) );
       break;
 
     case COLORMAP_BWR:
       m_CMPoints.push_back( CMPoint(0.0,    0x00, 0x00, 0xff, 0x00, 0xff) ); 
       m_CMPoints.push_back( CMPoint(0.5,    0xff, 0xff, 0xff, 0xff) ); 
-      m_CMPoints.push_back( CMPoint(1.0,    0xff, 0x00, 0x00, 0xff, 0x00) );
+      m_CMPoints.push_back( CMPoint(1.0,    0xff, 0x00, 0x00, 0xff, 0xff) );
       break;
 
     case COLORMAP_RWB:
       m_CMPoints.push_back( CMPoint(0.0,    0xff, 0x00, 0x00, 0x00, 0xff) ); 
       m_CMPoints.push_back( CMPoint(0.5,    0xff, 0xff, 0xff, 0xff) ); 
-      m_CMPoints.push_back( CMPoint(1.0,    0x00, 0x00, 0xff, 0xff, 0x00) );
+      m_CMPoints.push_back( CMPoint(1.0,    0x00, 0x00, 0xff, 0xff, 0xff) );
       break;
 
     case COLORMAP_SPEED:
diff --git a/Logic/Common/ColorMap.h b/Logic/Common/ColorMap.h
index 376fb9f..75c422d 100644
--- a/Logic/Common/ColorMap.h
+++ b/Logic/Common/ColorMap.h
@@ -94,6 +94,11 @@ public:
 
     CMPoint();
 
+    // Default way to construct color map points starting with SNAP 3.4
+    // Alpha equals the position in the color map, i.e., linear alpha across
+    // the color map. Points are discontinuous if index is 0/1
+    CMPoint(double, EltType r, EltType g, EltType b);
+
     // Continuous point
     CMPoint(double, EltType r, EltType g, EltType b, EltType a);
 
diff --git a/Logic/Common/SNAPAppearanceSettings.cxx b/Logic/Common/SNAPAppearanceSettings.cxx
index c51cc98..531253e 100644
--- a/Logic/Common/SNAPAppearanceSettings.cxx
+++ b/Logic/Common/SNAPAppearanceSettings.cxx
@@ -286,6 +286,11 @@ GlobalDisplaySettings::GlobalDisplaySettings()
   emap_layout.AddPair(LAYOUT_CAS,"CAS");
   emap_layout.AddPair(LAYOUT_CSA,"CSA");
 
+  // This is needed to read display layout modes
+  RegistryEnumMap<LayerLayout> emap_layer_layout;
+  emap_layer_layout.AddPair(LAYOUT_STACKED, "Stacked");
+  emap_layer_layout.AddPair(LAYOUT_TILED, "Tiled");
+
   // Set the common flags
   m_FlagDisplayZoomThumbnailModel =
       NewSimpleProperty("FlagDisplayZoomThumbnail", true);
@@ -308,6 +313,9 @@ GlobalDisplaySettings::GlobalDisplaySettings()
   m_FlagLayoutPatientRightShownLeftModel =
       NewSimpleProperty("FlagLayoutPatientRightShownLeft", true);
 
+  m_LayerLayoutModel =
+      NewSimpleEnumProperty("LayerLayout", LAYOUT_STACKED, emap_layer_layout);
+
 }
 
 void GlobalDisplaySettings
diff --git a/Logic/Common/SNAPAppearanceSettings.h b/Logic/Common/SNAPAppearanceSettings.h
index cce12e3..0299766 100644
--- a/Logic/Common/SNAPAppearanceSettings.h
+++ b/Logic/Common/SNAPAppearanceSettings.h
@@ -44,6 +44,7 @@
 #include "Registry.h"
 #include <string>
 #include "AbstractPropertyContainerModel.h"
+#include "GlobalState.h"
 
 
 /**
@@ -122,6 +123,7 @@ public:
   irisSimplePropertyAccessMacro(FlagLayoutPatientAnteriorShownLeft, bool)
   irisSimplePropertyAccessMacro(FlagLayoutPatientRightShownLeft, bool)
   irisSimplePropertyAccessMacro(SliceLayout, UISliceLayout)
+  irisSimplePropertyAccessMacro(LayerLayout, LayerLayout)
 
   /**
    * This method uses SliceLayout, FlagLayoutPatientAnteriorShownLeft and
@@ -147,6 +149,9 @@ protected:
   typedef ConcretePropertyModel<UISliceLayout, TrivialDomain> ConcreteSliceLayoutModel;
   SmartPtr<ConcreteSliceLayoutModel> m_SliceLayoutModel;
 
+  typedef ConcretePropertyModel<LayerLayout> ConcreteLayerLayoutModel;
+  SmartPtr<ConcreteLayerLayoutModel> m_LayerLayoutModel;
+
   GlobalDisplaySettings();
 };
 
diff --git a/Logic/Common/SNAPRegistryIO.cxx b/Logic/Common/SNAPRegistryIO.cxx
index b73d971..36eb4d0 100644
--- a/Logic/Common/SNAPRegistryIO.cxx
+++ b/Logic/Common/SNAPRegistryIO.cxx
@@ -174,6 +174,7 @@ SNAPRegistryIO
     sub["Size"] << in.GetROI().GetSize(d);
     }
   folder["InterpolationMethod"].PutEnum(m_EnumMapROI,in.GetInterpolationMethod());
+  folder["SeedWithCurrentSegmentation"] << in.IsSeedWithCurrentSegmentation();
 }
 
 RegistryEnumMap<CoverageModeType> &SNAPRegistryIO::GetEnumMapCoverage()
@@ -240,6 +241,9 @@ SNAPRegistryIO
         to_unsigned_int(
           folder["ResampleDimensions"][to_int(Vector3ui(outRegion.GetSize()))]));
 
+  // Read carry over properties
+  out.SetSeedWithCurrentSegmentation(folder["SeedWithCurrentSegmentation"][false]);
+
   return out;
 }  
 
diff --git a/Logic/Common/SNAPSegmentationROISettings.cxx b/Logic/Common/SNAPSegmentationROISettings.cxx
index a24075c..e5aa783 100644
--- a/Logic/Common/SNAPSegmentationROISettings.cxx
+++ b/Logic/Common/SNAPSegmentationROISettings.cxx
@@ -56,7 +56,8 @@ bool SNAPSegmentationROISettings
   return
       m_ROI == other.m_ROI &&
       m_ResampleDimensions == other.m_ResampleDimensions &&
-      m_InterpolationMethod == other.m_InterpolationMethod;
+      m_InterpolationMethod == other.m_InterpolationMethod &&
+      m_SeedWithCurrentSegmentation == other.m_SeedWithCurrentSegmentation;
 }
 
 bool SNAPSegmentationROISettings
diff --git a/Logic/Common/SNAPSegmentationROISettings.h b/Logic/Common/SNAPSegmentationROISettings.h
index 9a62f3f..70ef913 100644
--- a/Logic/Common/SNAPSegmentationROISettings.h
+++ b/Logic/Common/SNAPSegmentationROISettings.h
@@ -54,6 +54,7 @@ public:
   SNAPSegmentationROISettings()
     {
     m_InterpolationMethod = NEAREST_NEIGHBOR;
+    m_SeedWithCurrentSegmentation = false;
     }
 
   virtual ~SNAPSegmentationROISettings() {}
@@ -79,6 +80,12 @@ public:
   // Set the interpolation method used
   irisGetMacro(InterpolationMethod,InterpolationMethod)
 
+  // Check whether the current segmentation is used to seed level set
+  irisIsMacro(SeedWithCurrentSegmentation)
+
+  // Set whether the current segmentation is used to seed level set
+  irisSetMacro(SeedWithCurrentSegmentation, bool)
+
   bool operator == (const SNAPSegmentationROISettings &other) const;
   bool operator != (const SNAPSegmentationROISettings &other) const;
 
@@ -92,6 +99,9 @@ private:
   
   // The interpolation method used
   InterpolationMethod m_InterpolationMethod;
+
+  // Whether the current segmentation is used to seed level set
+  bool m_SeedWithCurrentSegmentation;
 };
 
 
diff --git a/Logic/Framework/GenericImageData.cxx b/Logic/Framework/GenericImageData.cxx
index 6d4202a..c6ccdc7 100644
--- a/Logic/Framework/GenericImageData.cxx
+++ b/Logic/Framework/GenericImageData.cxx
@@ -53,6 +53,7 @@
 #include "Rebroadcaster.h"
 #include "LayerIterator.h"
 #include "GuidedNativeImageIO.h"
+#include "ImageAnnotationData.h"
 
 // System includes
 #include <fstream>
@@ -76,6 +77,7 @@ GenericImageData
 
 GenericImageData
 ::GenericImageData()
+  : m_UndoManager(4,200000)
 {
   // Make main image wrapper point to grey wrapper initially
   m_MainImageWrapper = NULL;
@@ -86,6 +88,9 @@ GenericImageData
   // Add to the relevant lists
   m_Wrappers[MAIN_ROLE].push_back(m_MainImageWrapper);
   m_Wrappers[LABEL_ROLE].push_back(m_LabelWrapper.GetPointer());
+
+  // Create empty annotations
+  m_Annotations = ImageAnnotationData::New();
 }
 
 GenericImageData
@@ -129,13 +134,25 @@ GenericImageData
   m_MainImageWrapper->SetAlpha(255);
 }
 
+#include "itkIdentityTransform.h"
 
 SmartPtr<ImageWrapperBase>
-GenericImageData::CreateAnatomicWrapper(GuidedNativeImageIO *io)
+GenericImageData::CreateAnatomicWrapper(GuidedNativeImageIO *io, bool sameSpaceAsMainWrapper)
 {
   // The output wrapper
   SmartPtr<ImageWrapperBase> out_wrapper;
 
+  // Determine the reference image and transform
+  ImageBaseType *refSpace = NULL;
+  typedef itk::IdentityTransform<double, 3> TransformType;
+  SmartPtr<TransformType> transform = NULL;
+
+  if(!sameSpaceAsMainWrapper)
+    {
+    refSpace = this->GetMain()->GetImageBase();
+    transform = TransformType::New();
+    }
+
   // Split depending on whether the image is scalar or vector
   if(io->GetNumberOfComponentsInNativeImage() > 1)
     {
@@ -155,7 +172,7 @@ GenericImageData::CreateAnatomicWrapper(GuidedNativeImageIO *io)
 
     // Set properties
     wrapper->SetDisplayGeometry(m_DisplayGeometry);
-    wrapper->SetImage(image);
+    wrapper->SetImage(image, refSpace, transform);
     wrapper->SetNativeMapping(mapper);
     out_wrapper = wrapper.GetPointer();
     }
@@ -178,7 +195,7 @@ GenericImageData::CreateAnatomicWrapper(GuidedNativeImageIO *io)
 
     // Set properties
     wrapper->SetDisplayGeometry(m_DisplayGeometry);
-    wrapper->SetImage(image);
+    wrapper->SetImage(image, refSpace, transform);
     wrapper->SetNativeMapping(mapper);
     out_wrapper = wrapper.GetPointer();
     }
@@ -191,7 +208,7 @@ void GenericImageData::SetMainImage(GuidedNativeImageIO *io)
 {
   // Create the wrapper from the Native IO (the wrapper will either be a scalar
   // or a vector-valued image, depending on the number of components)
-  SmartPtr<ImageWrapperBase> wrapper = this->CreateAnatomicWrapper(io);
+  SmartPtr<ImageWrapperBase> wrapper = this->CreateAnatomicWrapper(io, true);
 
   // Assign this wrapper to the main image
   this->SetMainImageInternal(wrapper);
@@ -208,6 +225,10 @@ GenericImageData
 
   m_LabelWrapper->GetDisplayMapping()->SetLabelColorTable(m_Parent->GetColorLabelTable());
   SetSingleImageWrapper(LABEL_ROLE, m_LabelWrapper.GetPointer());
+
+  // Reset the undo manager
+  m_UndoManager.Clear();
+  m_UndoManager.SetCumulativeDelta(NULL);
 }
 
 void
@@ -224,6 +245,9 @@ GenericImageData
   // Reset the label wrapper
   RemoveSingleImageWrapper(LABEL_ROLE);
   m_LabelWrapper = NULL;
+
+  // Clear the annotations
+  m_Annotations->Reset();
 }
 
 void
@@ -232,7 +256,7 @@ GenericImageData
 {
   // Create the wrapper from the Native IO (the wrapper will either be a scalar
   // or a vector-valued image, depending on the number of components)
-  SmartPtr<ImageWrapperBase> wrapper = this->CreateAnatomicWrapper(io);
+  SmartPtr<ImageWrapperBase> wrapper = this->CreateAnatomicWrapper(io, true);
 
   // Assign this wrapper to the main image
   this->AddOverlayInternal(wrapper);
@@ -240,20 +264,33 @@ GenericImageData
 
 void
 GenericImageData
-::AddOverlayInternal(ImageWrapperBase *overlay)
+::AddCoregOverlay(GuidedNativeImageIO *io)
+{
+  // Create the wrapper from the Native IO (the wrapper will either be a scalar
+  // or a vector-valued image, depending on the number of components)
+  SmartPtr<ImageWrapperBase> wrapper = this->CreateAnatomicWrapper(io, false);
+
+  // Assign this wrapper to the main image
+  this->AddOverlayInternal(wrapper, false);
+}
+
+void
+GenericImageData
+::AddOverlayInternal(ImageWrapperBase *overlay, bool checkSpace)
 {
   // Check that the image matches the size of the main image
-  if(m_MainImageWrapper->GetBufferedRegion() != overlay->GetBufferedRegion())
+  if(checkSpace && m_MainImageWrapper->GetBufferedRegion() != overlay->GetBufferedRegion())
     {
     throw IRISException("Main and overlay data sizes are different");
     }
 
   // Pass the image to a Grey image wrapper
   overlay->SetAlpha(0.5);
-  overlay->SetDefaultNickname("Overlay Image");
+  overlay->SetDefaultNickname("Additional Image");
 
   // Sync up spacing between the main and overlay image
-  overlay->CopyImageCoordinateTransform(m_MainImageWrapper);
+  if(checkSpace)
+    overlay->CopyImageCoordinateTransform(m_MainImageWrapper);
 
   // Add to the overlay wrapper list
   PushBackImageWrapper(OVERLAY_ROLE, overlay);
@@ -306,6 +343,25 @@ GenericImageData
 
   // Sync up spacing between the main and label image
   m_LabelWrapper->CopyImageCoordinateTransform(m_MainImageWrapper);
+
+  // Reset the undo manager
+  m_UndoManager.Clear();
+  m_UndoManager.SetCumulativeDelta(this->CompressLabelImage());
+}
+
+GenericImageData::UndoManagerType::Delta *
+GenericImageData
+::CompressLabelImage()
+{
+  UndoManagerType::Delta *new_cumulative = new UndoManagerType::Delta();
+  LabelImageType *seg = this->GetSegmentation()->GetImage();
+  LabelType *buffer = seg->GetBufferPointer();
+  LabelType *buffer_end = buffer + seg->GetPixelContainer()->Size();
+  while (buffer < buffer_end)
+    new_cumulative->Encode(*buffer++);
+
+  new_cumulative->FinishEncoding();
+  return new_cumulative;
 }
 
 bool
@@ -359,6 +415,176 @@ const ImageCoordinateGeometry &GenericImageData::GetImageGeometry() const
   return m_MainImageWrapper->GetImageGeometry();
 }
 
+GenericImageData::UndoManagerType::Delta *
+GenericImageData::GetCumulativeUndoDelta()
+{
+  return m_UndoManager.GetCumulativeDelta();
+}
+
+void GenericImageData::StoreUndoPoint(const char *text)
+{
+  // Set the current state as the undo point. We store the difference between
+  // the last 'undo' image and the current segmentation image, and then copy
+  // the current segmentation image into the undo image
+  LabelImageWrapper *seg = this->GetSegmentation();
+  UndoManagerType::Delta *new_cumulative = new UndoManagerType::Delta();
+
+  LabelType *dseg = seg->GetVoxelPointer();
+  size_t n = seg->GetNumberOfVoxels();
+
+  // Create the Undo delta object
+  UndoManagerType::Delta *delta = new UndoManagerType::Delta();
+
+  // Get the old cumulative delta
+  UndoManagerType::Delta *old_cumulative = m_UndoManager.GetCumulativeDelta();
+
+  // Run over the old cumulative data
+  if(old_cumulative)
+    {
+    for(size_t i = 0; i < old_cumulative->GetNumberOfRLEs(); i++)
+      {
+      size_t rle_len = old_cumulative->GetRLELength(i);
+      LabelType rle_val = old_cumulative->GetRLEValue(i);
+
+      for(size_t j = 0; j < rle_len; j++)
+        {
+        delta->Encode(*dseg - rle_val);
+        new_cumulative->Encode(*dseg);
+        dseg++;
+        }
+      }
+
+    // Important last step!
+    delta->FinishEncoding();
+    new_cumulative->FinishEncoding();
+    }
+  else
+    {
+    LabelType *dseg_end = dseg + n;
+    for(; dseg < dseg_end; ++dseg)
+      {
+      // TODO: add code to duplicate
+      delta->Encode(*dseg);
+      }
+
+    delta->FinishEncoding();
+    *new_cumulative = *delta;
+    }
+
+  // Add the delta object
+  m_UndoManager.AppendDelta(delta);
+  m_UndoManager.SetCumulativeDelta(new_cumulative);
+}
+
+void GenericImageData::ClearUndoPoints()
+{
+  m_UndoManager.Clear();
+}
+
+bool
+GenericImageData
+::IsUndoPossible()
+{
+  return m_UndoManager.IsUndoPossible();
+}
+
+void
+GenericImageData
+::Undo()
+{
+  // In order to undo, we must take the 'current' delta and apply
+  // it to the image
+  UndoManagerType::Delta *delta = m_UndoManager.GetDeltaForUndo();
+  UndoManagerType::Delta *cumulative = new UndoManagerType::Delta();
+
+  LabelImageWrapper *imSeg = this->GetSegmentation();
+  LabelType *dseg = imSeg->GetVoxelPointer();
+
+  // Applying the delta means adding
+  for(size_t i = 0; i < delta->GetNumberOfRLEs(); i++)
+    {
+    size_t n = delta->GetRLELength(i);
+    LabelType d = delta->GetRLEValue(i);
+    if(d == 0)
+      {
+      for(size_t j = 0; j < n; j++)
+        {
+        cumulative->Encode(*dseg);
+        ++dseg;
+        }
+      }
+    else
+      {
+      for(size_t j = 0; j < n; j++)
+        {
+        *dseg -= d;
+        cumulative->Encode(*dseg);
+        ++dseg;
+        }
+      }
+    }
+
+  cumulative->FinishEncoding();
+  m_UndoManager.SetCumulativeDelta(cumulative);
+
+  // Set modified flags
+  imSeg->GetImage()->Modified();
+  InvokeEvent(SegmentationChangeEvent());
+}
+
+bool
+GenericImageData
+::IsRedoPossible()
+{
+  return m_UndoManager.IsRedoPossible();
+}
+
+void
+GenericImageData
+::Redo()
+{
+  // In order to undo, we must take the 'current' delta and apply
+  // it to the image
+  UndoManagerType::Delta *delta = m_UndoManager.GetDeltaForRedo();
+  LabelImageWrapper *imSeg = this->GetSegmentation();
+  LabelType *dseg = imSeg->GetVoxelPointer();
+
+  UndoManagerType::Delta *cumulative = new UndoManagerType::Delta();
+
+  // Applying the delta means adding
+  for(size_t i = 0; i < delta->GetNumberOfRLEs(); i++)
+    {
+    size_t n = delta->GetRLELength(i);
+    LabelType d = delta->GetRLEValue(i);
+    if(d == 0)
+      {
+      for(size_t j = 0; j < n; j++)
+        {
+        cumulative->Encode(*dseg);
+        ++dseg;
+        }
+      }
+    else
+      {
+      for(size_t j = 0; j < n; j++)
+        {
+        *dseg += d;
+        cumulative->Encode(*dseg);
+        ++dseg;
+        }
+      }
+    }
+
+  cumulative->FinishEncoding();
+  m_UndoManager.SetCumulativeDelta(cumulative);
+
+  // Set modified flags
+  imSeg->GetImage()->Modified();
+  InvokeEvent(SegmentationChangeEvent());
+}
+
+
+
 GenericImageData::RegionType
 GenericImageData
 ::GetImageRegion() const
@@ -487,3 +713,9 @@ void GenericImageData::RemoveSingleImageWrapper(LayerRole role)
 
 
 
+
+
+void GenericImageData::AddOverlay(ImageWrapperBase *new_layer)
+{
+  this->AddOverlayInternal(new_layer, true);
+}
diff --git a/Logic/Framework/GenericImageData.h b/Logic/Framework/GenericImageData.h
index 736e203..6a4b3d1 100644
--- a/Logic/Framework/GenericImageData.h
+++ b/Logic/Framework/GenericImageData.h
@@ -51,12 +51,14 @@
 #include "ImageCoordinateGeometry.h"
 #include <string>
 #include "LayerIterator.h"
+#include "UndoDataManager.h"
 
 class IRISApplication;
 class GenericImageData;
 class LayerIterator;
 class Registry;
 class GuidedNativeImageIO;
+class ImageAnnotationData;
 
 /**
  * \class GenericImageData
@@ -87,13 +89,16 @@ public:
   typedef AnatomicImageWrapper::ImageType                   AnatomicImageType;
   typedef LabelImageWrapper::ImageType                         LabelImageType;
 
-
   // Support for lists of wrappers
   typedef SmartPtr<ImageWrapperBase> WrapperPointer;
   typedef std::vector<WrapperPointer> WrapperList;
   typedef WrapperList::iterator WrapperIterator;
   typedef WrapperList::const_iterator WrapperConstIterator;
 
+  // Segmentation undo support
+  typedef UndoDataManager<LabelType> UndoManagerType;
+
+
   /**
    * Set the parent driver
    */
@@ -219,11 +224,18 @@ public:
 
   /** Handle overlays */
   virtual void AddOverlay(GuidedNativeImageIO *io);
+  virtual void AddOverlay(ImageWrapperBase *new_layer);
   virtual void UnloadOverlays();
   virtual void UnloadOverlayLast();
   virtual void UnloadOverlay(ImageWrapperBase *overlay);
 
   /**
+   * Add an overlay that is obtained from the image referenced by *io by applying
+   * a spatial transformation.
+   */
+  void AddCoregOverlay(GuidedNativeImageIO *io);
+
+  /**
    * Change the ordering of the layers within a particular role (for now just
    * overlays are supported in the GUI) by moving the specified layer up or
    * down one spot. The sign of the direction determines whether the layer is
@@ -270,6 +282,34 @@ public:
   /** Get the image coordinate geometry */
   const ImageCoordinateGeometry &GetImageGeometry() const;
 
+  /** Get the list of annotations created by the user */
+  irisGetMacro(Annotations, ImageAnnotationData *)
+
+  /** TODO: in 3.6 this will be unnecessary */
+  UndoManagerType::Delta *GetCumulativeUndoDelta();
+
+  /** Store an undo point */
+  void StoreUndoPoint(const char *text);
+
+  /** Clear all undo points */
+  void ClearUndoPoints();
+
+  /** Check whether undo is possible */
+  bool IsUndoPossible();
+
+  /** Check whether undo is possible */
+  bool IsRedoPossible();
+
+  /** Undo (revert to last stored undo point) */
+  void Undo();
+
+  /** Redo (undo the undo) */
+  void Redo();
+
+  irisGetMacro(UndoManager, const UndoManagerType &);
+
+
+
 protected:
 
   GenericImageData();
@@ -293,10 +333,10 @@ protected:
   // Equal to m_Wrappers[SEGMENTATION].first()
   SmartPtr<LabelImageWrapper> m_LabelWrapper;
 
-  // A list of linked wrappers, whose cursor position and image geometry
-  // are updated concurrently
-  // WrapperList m_MainWrappers;
-  // WrapperList m_OverlayWrappers;
+  // Undo data manager, stores 'deltas', i.e., differences between states of the segmentation
+  // image. These deltas are compressed, allowing us to store a bunch of
+  // undo steps with little cost in performance or memory
+  UndoManagerType m_UndoManager;
 
   // Parent object
   IRISApplication *m_Parent;
@@ -304,15 +344,18 @@ protected:
   // The display to anatomy transformation, which is stored by this object
   IRISDisplayGeometry m_DisplayGeometry;
 
+  // Image annotations - these are distinct from segmentations
+  SmartPtr<ImageAnnotationData> m_Annotations;
+
   friend class SNAPImageData;
   friend class LayerIterator;
 
   // Create a wrapper (vector or scalar) from native format stored in the IO
-  SmartPtr<ImageWrapperBase> CreateAnatomicWrapper(GuidedNativeImageIO *io);
+  SmartPtr<ImageWrapperBase> CreateAnatomicWrapper(GuidedNativeImageIO *io, bool sameSpaceAsMainWrapper);
 
   // Update the main image
   virtual void SetMainImageInternal(ImageWrapperBase *wrapper);
-  virtual void AddOverlayInternal(ImageWrapperBase *wrapper);
+  virtual void AddOverlayInternal(ImageWrapperBase *wrapper, bool checkSpace = true);
 
   // Append an image wrapper to a role
   void PushBackImageWrapper(LayerRole role, ImageWrapperBase *wrapper);
@@ -323,6 +366,8 @@ protected:
   void SetSingleImageWrapper(LayerRole, ImageWrapperBase *wrapper);
   void RemoveSingleImageWrapper(LayerRole);
 
+  // Used in the undo/redo process: RLE compresses current image
+  UndoManagerType::Delta *CompressLabelImage();
 };
 
 #endif
diff --git a/Logic/Framework/GlobalState.cxx b/Logic/Framework/GlobalState.cxx
index 638c7e4..f02e92e 100644
--- a/Logic/Framework/GlobalState.cxx
+++ b/Logic/Framework/GlobalState.cxx
@@ -37,6 +37,7 @@
 #include "IRISApplication.h"
 #include "MeshOptions.h"
 #include "DefaultBehaviorSettings.h"
+#include "NumericPropertyToggleAdaptor.h"
 
 GlobalState
 ::GlobalState()
@@ -94,8 +95,6 @@ GlobalState
   m_PaintbrushSettings.watershed.level = 0.2;
   m_PaintbrushSettings.watershed.smooth_iterations = 15;
 
-  // Set annotation defaults
-  m_AnnotationSettings.shownOnAllSlices = false;
 
   m_PolygonDrawingContextMenuModel = NewSimpleConcreteProperty(false);
 
@@ -119,11 +118,23 @@ GlobalState
   // Project stuff
   m_ProjectFilenameModel = NewSimpleConcreteProperty(std::string());
 
+  m_InitialDirectoryModel = NewSimpleConcreteProperty(std::string());
+
   // Initialize the properties
   m_ToolbarModeModel = NewSimpleConcreteProperty(CROSSHAIRS_MODE);
   m_ToolbarMode3DModel = NewSimpleConcreteProperty(TRACKBALL_MODE);
 
   m_SliceViewLayerLayoutModel = NewSimpleConcreteProperty(LAYOUT_STACKED);
+
+  m_SelectedLayerIdModel = NewSimpleConcreteProperty(0ul);
+
+  // Set annotation defaults
+  m_AnnotationSettings.shownOnAllSlices = false;
+  m_AnnotationModeModel = NewSimpleConcreteProperty(ANNOTATION_RULER);
+
+  m_AnnotationColorModel = NewSimpleConcreteProperty(Vector3d(1, 0, 0));
+  m_AnnotationAlphaModel = NewRangedConcreteProperty(1.0, 0.0, 1.0, 0.01);
+  m_AnnotationVisibilityModel = NewNumericPropertyToggleAdaptor(m_AnnotationAlphaModel.GetPointer(), 0.0, 1.0);
 }
 
 void GlobalState::SetDriver(IRISApplication *parent)
diff --git a/Logic/Framework/GlobalState.h b/Logic/Framework/GlobalState.h
index e4381b7..2bdb292 100644
--- a/Logic/Framework/GlobalState.h
+++ b/Logic/Framework/GlobalState.h
@@ -76,9 +76,9 @@ enum PreprocessingMode
 {
   PREPROCESS_NONE = 0,
   PREPROCESS_THRESHOLD,
-  PREPROCESS_EDGE,
+  PREPROCESS_RF,
   PREPROCESS_GMM,
-  PREPROCESS_RF
+  PREPROCESS_EDGE
 };
 
 enum ConstraintsType 
@@ -122,6 +122,13 @@ enum ToolbarMode3DType
   SCALPEL_MODE
 };
 
+enum AnnotationMode
+{
+  ANNOTATION_RULER = 0,
+  ANNOTATION_SELECT,
+  ANNOTATION_LANDMARK
+};
+
 /** Layout of overlays in a slice view */
 enum LayerLayout {
   LAYOUT_STACKED = 0, LAYOUT_TILED
@@ -363,6 +370,15 @@ public:
   /** Set/Get the layout of multiple layers in slice views */
   irisSimplePropertyAccessMacro(SliceViewLayerLayout, LayerLayout)
 
+  /** Set/Get selected layer id */
+  irisSimplePropertyAccessMacro(SelectedLayerId, unsigned long)
+
+  /**
+   * Initial directory where to open file/save dialogs. This MUST be set when
+   * SNAP is first started!
+   */
+  irisSimplePropertyAccessMacro(InitialDirectory, std::string)
+
   // ----------------------- Project support ------------------------------
 
   /**
@@ -373,6 +389,20 @@ public:
 
   // --------------------- End Project support ----------------------------
 
+  /**
+   * Annotation mode
+   */
+  irisSimplePropertyAccessMacro(AnnotationMode, AnnotationMode)
+
+  /**
+   * Color for Annotations
+   */
+  irisSimplePropertyAccessMacro(AnnotationColor, Vector3d)
+
+  /** Opacity of the annotations */
+  irisRangedPropertyAccessMacro(AnnotationAlpha, double)
+  irisSimplePropertyAccessMacro(AnnotationVisibility, bool)
+
 protected:
 
   GlobalState();
@@ -485,14 +515,26 @@ private:
   // Paintbrush settings
   PaintbrushSettings m_PaintbrushSettings;
 
-  // Annotation settings
-  AnnotationSettings m_AnnotationSettings;
+  // Initial path for opening images
+  SmartPtr<ConcreteSimpleStringProperty> m_InitialDirectoryModel;
 
   IRISApplication *m_Driver;
 
+  // ------------------- Selected Image ID ---------------------------------
+  SmartPtr<ConcreteSimpleULongProperty> m_SelectedLayerIdModel;
+
   // ------------------- Project Related -----------------------------------
   SmartPtr<ConcreteSimpleStringProperty> m_ProjectFilenameModel;
 
+  // ------------------- Annotation Mode -----------------------------------
+  AnnotationSettings m_AnnotationSettings;
+
+  typedef ConcretePropertyModel<AnnotationMode> ConcreteAnnotationModeModel;
+  SmartPtr<ConcreteAnnotationModeModel> m_AnnotationModeModel;
+
+  SmartPtr<ConcreteSimpleDoubleVec3Property> m_AnnotationColorModel;
+  SmartPtr<ConcreteRangedDoubleProperty> m_AnnotationAlphaModel;
+  SmartPtr<AbstractSimpleBooleanProperty> m_AnnotationVisibilityModel;
 };
 
 #endif // __GlobalState_h_
diff --git a/Logic/Framework/IRISApplication.cxx b/Logic/Framework/IRISApplication.cxx
index 16e0eda..64a3450 100644
--- a/Logic/Framework/IRISApplication.cxx
+++ b/Logic/Framework/IRISApplication.cxx
@@ -85,6 +85,8 @@
 #include "RFClassificationEngine.h"
 #include "RandomForestClassifyImageFilter.h"
 #include "LabelUseHistory.h"
+#include "ImageAnnotationData.h"
+
 
 
 #include <stdio.h>
@@ -93,7 +95,6 @@
 
 IRISApplication
 ::IRISApplication() 
-: m_UndoManager(4,200000)
 {
   // Create a new system interface
   m_SystemInterface = new SystemInterface();
@@ -209,7 +210,7 @@ IRISApplication
   unsigned int nCopied = 0;
   while(!itLabel.IsAtEnd())
     {
-    if(itLabel.Value() != passThroughLabel)
+    if(itLabel.Value() != passThroughLabel || !roi.IsSeedWithCurrentSegmentation())
       itLabel.Value() = (LabelType) 0;
     else
       nCopied++;
@@ -306,12 +307,17 @@ void IRISApplication::UnloadOverlay(ImageWrapperBase *ovl)
   SaveMetaDataAssociatedWithLayer(ovl, OVERLAY_ROLE);
 
   // Unload this overlay
+  unsigned long ovl_id = ovl->GetUniqueId();
   m_IRISImageData->UnloadOverlay(ovl);
 
   // for overlay, we don't want to change the cursor location
   // just force the IRISSlicer to update
   m_IRISImageData->SetCrosshairs(m_GlobalState->GetCrosshairsPosition());
 
+  // Check if the selected layer needs to be updated (default to main)
+  if(m_GlobalState->GetSelectedLayerId() == ovl_id)
+    m_GlobalState->SetSelectedLayerId(m_IRISImageData->GetMain()->GetUniqueId());
+
   // Fire event
   InvokeEvent(LayerChangeEvent());
 }
@@ -328,6 +334,9 @@ void IRISApplication::UnloadAllOverlays()
   // just force the IRISSlicer to update
   m_IRISImageData->SetCrosshairs(m_GlobalState->GetCrosshairsPosition());
 
+  // The selected layer should revert to main
+  m_GlobalState->SetSelectedLayerId(m_IRISImageData->GetMain()->GetUniqueId());
+
   // Fire event
   InvokeEvent(LayerChangeEvent());
 
@@ -350,10 +359,6 @@ IRISApplication
   // Reset the segmentation image
   this->m_IRISImageData->ResetSegmentationImage();
 
-  // Clear the undo buffer
-  m_UndoManager.Clear();
-  m_UndoManager.SetCumulativeDelta(NULL);
-
   // Fire the appropriate event
   InvokeEvent(LayerChangeEvent());
   InvokeEvent(SegmentationChangeEvent());
@@ -375,6 +380,39 @@ IRISApplication
 
 void
 IRISApplication
+::UpdateSNAPSegmentationImage(GuidedNativeImageIO *io)
+{
+  // This has to happen in 'pure' SNAP mode
+  assert(IsSnakeModeActive());
+
+  // Cast the image to label type
+  CastNativeImage<LabelImageType> caster;
+  LabelImageType::Pointer imgLabel = caster(io);
+
+  // The header of the label image is made to match that of the grey image
+  imgLabel->SetOrigin(m_CurrentImageData->GetMain()->GetImageBase()->GetOrigin());
+  imgLabel->SetSpacing(m_CurrentImageData->GetMain()->GetImageBase()->GetSpacing());
+  imgLabel->SetDirection(m_CurrentImageData->GetMain()->GetImageBase()->GetDirection());
+
+  // Update the iris data
+  m_CurrentImageData->SetSegmentationImage(imgLabel);
+
+  // Update filenames
+  m_CurrentImageData->GetSegmentation()->SetFileName(io->GetFileNameOfNativeImage());
+
+  // Set the loaded labels as valid
+  LabelImageType *seg = m_CurrentImageData->GetSegmentation()->GetImage();
+  LabelType *buffer = seg->GetBufferPointer();
+  LabelType *buffer_end = buffer + seg->GetPixelContainer()->Size();
+  while (buffer < buffer_end)
+    m_ColorLabelTable->SetColorLabelValid(*buffer++, true);
+
+  // Let the GUI know that segmentation changed
+  InvokeEvent(SegmentationChangeEvent());
+}
+
+void
+IRISApplication
 ::UpdateIRISSegmentationImage(GuidedNativeImageIO *io)
 {
   // This has to happen in 'pure' IRIS mode
@@ -399,24 +437,11 @@ IRISApplication
   m_SystemInterface->GetHistoryManager()->UpdateHistory(
         "LabelImage", io->GetFileNameOfNativeImage(), true);
 
-
-  // Reset the UNDO manager
-  m_UndoManager.Clear();
-
-  // Store the current segmentation image as the cumulative delta in the undo
-  // manager.
-  UndoManagerType::Delta *new_cumulative = new UndoManagerType::Delta();
-  LabelImageType *seg = m_IRISImageData->GetSegmentation()->GetImage();
-  LabelType *buffer = seg->GetBufferPointer();
-  LabelType *buffer_end = buffer + seg->GetPixelContainer()->Size();
-  while (buffer < buffer_end)
-    new_cumulative->Encode(*buffer++);
-
-  new_cumulative->FinishEncoding();
-  m_UndoManager.SetCumulativeDelta(new_cumulative);
-
   // Now we can use the RLE encoding of the segmentation to quickly determine
   // which labels are valid
+  // TODO: this will become unnecessary when we move to compressed segmentations!
+  GenericImageData::UndoManagerType::Delta *new_cumulative =
+      m_IRISImageData->GetCumulativeUndoDelta();
   for(size_t j = 0; j < new_cumulative->GetNumberOfRLEs(); j++)
     {
     LabelType label = new_cumulative->GetRLEValue(j);
@@ -490,9 +515,6 @@ IRISApplication
     double zSlice,
     const std::string &undoTitle)
 {
-  // Only in IRIS mode
-  assert(!IsSnakeModeActive());
-
   // Get the segmentation image
   LabelImageType *seg = m_CurrentImageData->GetSegmentation()->GetImage();
 
@@ -711,57 +733,8 @@ void
 IRISApplication
 ::StoreUndoPoint(const char *text)
 {
-  // Set the current state as the undo point. We store the difference between
-  // the last 'undo' image and the current segmentation image, and then copy
-  // the current segmentation image into the undo image
-  LabelImageWrapper *seg = m_IRISImageData->GetSegmentation();
-  UndoManagerType::Delta *new_cumulative = new UndoManagerType::Delta();
-
-  LabelType *dseg = seg->GetVoxelPointer();
-  size_t n = seg->GetNumberOfVoxels();
-
-  // Create the Undo delta object
-  UndoManagerType::Delta *delta = new UndoManagerType::Delta();
-
-  // Get the old cumulative delta
-  UndoManagerType::Delta *old_cumulative = m_UndoManager.GetCumulativeDelta();
-
-  // Run over the old cumulative data
-  if(old_cumulative)
-    {
-    for(size_t i = 0; i < old_cumulative->GetNumberOfRLEs(); i++)
-      {
-      size_t rle_len = old_cumulative->GetRLELength(i);
-      LabelType rle_val = old_cumulative->GetRLEValue(i);
-
-      for(size_t j = 0; j < rle_len; j++)
-        {
-        delta->Encode(*dseg - rle_val);
-        new_cumulative->Encode(*dseg);
-        dseg++;
-        }
-      }
-
-    // Important last step!
-    delta->FinishEncoding();
-    new_cumulative->FinishEncoding();
-    }
-  else
-    {
-    LabelType *dseg_end = dseg + n;
-    for(; dseg < dseg_end; ++dseg)
-      {
-      // TODO: add code to duplicate
-      delta->Encode(*dseg);
-      }
-
-    delta->FinishEncoding();
-    *new_cumulative = *delta;
-    }
-
-  // Add the delta object
-  m_UndoManager.AppendDelta(delta);
-  m_UndoManager.SetCumulativeDelta(new_cumulative);
+  // Delegate to the image data
+  m_CurrentImageData->StoreUndoPoint(text);
 
   // TODO: I am not sure this is the best place for this code. I think it's a
   // good idea to migrate all of the code that deals with updating the
@@ -780,14 +753,15 @@ void
 IRISApplication
 ::ClearUndoPoints()
 {
-  m_UndoManager.Clear();
+  m_IRISImageData->ClearUndoPoints();
+  m_SNAPImageData->ClearUndoPoints();
 }
 
 bool
 IRISApplication
 ::IsUndoPossible()
 {
-  return m_UndoManager.IsUndoPossible();
+  return m_CurrentImageData->IsUndoPossible();
 }
 
 /*
@@ -836,43 +810,7 @@ void
 IRISApplication
 ::Undo()
 {
-  // In order to undo, we must take the 'current' delta and apply
-  // it to the image
-  UndoManagerType::Delta *delta = m_UndoManager.GetDeltaForUndo();
-  UndoManagerType::Delta *cumulative = new UndoManagerType::Delta();
-
-  LabelImageWrapper *imSeg = m_IRISImageData->GetSegmentation();
-  LabelType *dseg = imSeg->GetVoxelPointer();
-
-  // Applying the delta means adding
-  for(size_t i = 0; i < delta->GetNumberOfRLEs(); i++)
-    {
-    size_t n = delta->GetRLELength(i);
-    LabelType d = delta->GetRLEValue(i);
-    if(d == 0)
-      {
-      for(size_t j = 0; j < n; j++)
-        {
-        cumulative->Encode(*dseg);
-        ++dseg;
-        }
-      }
-    else
-      {
-      for(size_t j = 0; j < n; j++)
-        {
-        *dseg -= d;
-        cumulative->Encode(*dseg);
-        ++dseg;
-        }
-      }
-    }
-
-  cumulative->FinishEncoding();
-  m_UndoManager.SetCumulativeDelta(cumulative);
-
-  // Set modified flags
-  imSeg->GetImage()->Modified();
+  m_CurrentImageData->Undo();
   InvokeEvent(SegmentationChangeEvent());
 }
 
@@ -880,91 +818,14 @@ bool
 IRISApplication
 ::IsRedoPossible()
 {
-  return m_UndoManager.IsRedoPossible();
+  return m_CurrentImageData->IsRedoPossible();
 }
 
-/*
 void
 IRISApplication
 ::Redo()
 {
-  // In order to undo, we must take the 'current' delta and apply
-  // it to the image
-  UndoManagerType::Delta *delta = m_UndoManager.GetDeltaForRedo();
-
-  LabelImageWrapper *imUndo = m_IRISImageData->GetUndoImage();
-  LabelImageWrapper *imSeg = m_IRISImageData->GetSegmentation();
-  LabelType *dundo = imUndo->GetVoxelPointer();
-  LabelType *dseg = imSeg->GetVoxelPointer();
-
-  // Applying the delta means adding 
-  for(size_t i = 0; i < delta->GetNumberOfRLEs(); i++)
-    {
-    size_t n = delta->GetRLELength(i);
-    LabelType d = delta->GetRLEValue(i);
-    if(d == 0)
-      {
-      dundo += n;
-      dseg += n;
-      }
-    else
-      {
-      for(size_t j = 0; j < n; j++)
-        {
-        *dundo += d;
-        *dseg = *dundo;
-        ++dundo; ++dseg;
-        }
-      }
-    }
-
-  // Set modified flags
-  imSeg->GetImage()->Modified();
-  InvokeEvent(SegmentationChangeEvent());
-}
-*/
-
-void
-IRISApplication
-::Redo()
-{
-  // In order to undo, we must take the 'current' delta and apply
-  // it to the image
-  UndoManagerType::Delta *delta = m_UndoManager.GetDeltaForRedo();
-  LabelImageWrapper *imSeg = m_IRISImageData->GetSegmentation();
-  LabelType *dseg = imSeg->GetVoxelPointer();
-
-  UndoManagerType::Delta *cumulative = new UndoManagerType::Delta();
-
-  // Applying the delta means adding
-  for(size_t i = 0; i < delta->GetNumberOfRLEs(); i++)
-    {
-    size_t n = delta->GetRLELength(i);
-    LabelType d = delta->GetRLEValue(i);
-    if(d == 0)
-      {
-      for(size_t j = 0; j < n; j++)
-        {
-        cumulative->Encode(*dseg);
-        ++dseg;
-        }
-      }
-    else
-      {
-      for(size_t j = 0; j < n; j++)
-        {
-        *dseg += d;
-        cumulative->Encode(*dseg);
-        ++dseg;
-        }
-      }
-    }
-
-  cumulative->FinishEncoding();
-  m_UndoManager.SetCumulativeDelta(cumulative);
-
-  // Set modified flags
-  imSeg->GetImage()->Modified();
+  m_CurrentImageData->Redo();
   InvokeEvent(SegmentationChangeEvent());
 }
 
@@ -1016,6 +877,9 @@ IRISApplication
     m_CurrentImageData = m_IRISImageData;
     TransferCursor(m_SNAPImageData, m_IRISImageData);
     InvokeEvent(MainImageDimensionsChangeEvent());
+
+    // Set the selected layer ID to the main image
+    m_GlobalState->SetSelectedLayerId(m_IRISImageData->GetMain()->GetUniqueId());
     }
 }
 
@@ -1038,6 +902,9 @@ void IRISApplication
     // Upon entering this mode, we need reset the active tools
     m_GlobalState->SetToolbarMode(CROSSHAIRS_MODE);
     m_GlobalState->SetToolbarMode3D(TRACKBALL_MODE);
+
+    // Set the selected layer ID to the main image
+    m_GlobalState->SetSelectedLayerId(m_SNAPImageData->GetMain()->GetUniqueId());
     }
 }
 
@@ -1519,6 +1386,90 @@ IRISApplication
 
   // Add the image as the current grayscale overlay
   m_IRISImageData->AddOverlay(io);
+  ImageWrapperBase *layer = m_IRISImageData->GetLastOverlay();
+
+  // Set the filename of the overlay
+  // TODO: this is cumbersome, could we just initialize the wrapper from the
+  // GuidedNativeImageIO without passing all this junk around?
+  layer->SetFileName(io->GetFileNameOfNativeImage());
+
+  // Add the overlay to the history
+  m_HistoryManager->UpdateHistory("AnatomicImage", io->GetFileNameOfNativeImage(), true);
+
+  // for overlay, we don't want to change the cursor location
+  // just force the IRISSlicer to update
+  m_IRISImageData->SetCrosshairs(m_GlobalState->GetCrosshairsPosition());
+
+  // Apply the default color map for overlays
+  std::string deflt_preset =
+      m_GlobalState->GetDefaultBehaviorSettings()->GetOverlayColorMapPreset();
+  m_ColorMapPresetManager->SetToPreset(layer->GetDisplayMapping()->GetColorMap(),
+                                       deflt_preset);
+
+  // Initialize the layer-specific segmentation parameters
+  CreateSegmentationSettings(layer, OVERLAY_ROLE);
+
+  // Read and apply the project-level settings associated with the main image
+  LoadMetaDataAssociatedWithLayer(layer, OVERLAY_ROLE, metadata);
+
+  // If the default is to auto-contrast, perform the contrast adjustment
+  // operation on the image
+  if(m_GlobalState->GetDefaultBehaviorSettings()->GetAutoContrast())
+    AutoContrastLayerOnLoad(layer);
+
+  // Set the selected layer ID to be the new overlay
+  m_GlobalState->SetSelectedLayerId(layer->GetUniqueId());
+
+  // Fire event
+  InvokeEvent(LayerChangeEvent());
+}
+
+void
+IRISApplication
+::AddDerivedOverlayImage(ImageWrapperBase *overlay)
+{
+  assert(this->IsMainImageLoaded());
+  ImageWrapperBase *layer = m_CurrentImageData->GetLastOverlay();
+
+  // Add the image as the current grayscale overlay
+  m_CurrentImageData->AddOverlay(overlay);
+
+  // for overlay, we don't want to change the cursor location
+  // just force the IRISSlicer to update
+  m_CurrentImageData->SetCrosshairs(m_GlobalState->GetCrosshairsPosition());
+
+  // Apply the default color map for overlays
+  std::string deflt_preset =
+      m_GlobalState->GetDefaultBehaviorSettings()->GetOverlayColorMapPreset();
+  m_ColorMapPresetManager->SetToPreset(layer->GetDisplayMapping()->GetColorMap(),
+                                       deflt_preset);
+
+  // Initialize the layer-specific segmentation parameters
+  CreateSegmentationSettings(layer, OVERLAY_ROLE);
+
+  // If the default is to auto-contrast, perform the contrast adjustment
+  // operation on the image
+  if(m_GlobalState->GetDefaultBehaviorSettings()->GetAutoContrast())
+    AutoContrastLayerOnLoad(layer);
+
+  // Set the selected layer ID to be the new overlay
+  m_GlobalState->SetSelectedLayerId(layer->GetUniqueId());
+
+  // Fire event
+  InvokeEvent(LayerChangeEvent());
+}
+
+// TODO: this code is 99% same as above - fix it!
+void
+IRISApplication
+::AddIRISCoregOverlayImage(GuidedNativeImageIO *io, Registry *metadata)
+{
+  assert(!IsSnakeModeActive());
+  assert(m_IRISImageData->IsMainLoaded());
+  assert(io->IsNativeImageLoaded());
+
+  // Add the image as the current grayscale overlay
+  m_IRISImageData->AddCoregOverlay(io);
 
   // Set the filename of the overlay
   // TODO: this is cumbersome, could we just initialize the wrapper from the
@@ -1595,25 +1546,6 @@ IRISApplication
     }
 }
 
-/*
- *   // Get the size of the image as a vector of uint
-  Vector3ui size = io->GetNativeImage()->GetBufferedRegion().GetSize();
-
-  // Compute the new image geometry for the IRIS data
-  ImageCoordinateGeometry icg(
-        io->GetNativeImage()->GetDirection().GetVnlMatrix(),
-        m_DisplayToAnatomyRAI, size);
-
-  // Rescale the image to desired number of bits
-  RescaleNativeImageToIntegralType<AnatomyImageType> rescaler;
-  AnatomyImageType::Pointer imgMain = rescaler(io);
-  LinearInternalToNativeIntensityMapping mapper(rescaler.GetNativeScale(), rescaler.GetNativeShift());
-
-  // Set the image as the current main anatomy image/
-  m_IRISImageData->SetMainImage(imgMain, icg, mapper);
-
-*/
-
 void
 IRISApplication
 ::UpdateIRISMainImage(GuidedNativeImageIO *io, Registry *metadata)
@@ -1624,14 +1556,17 @@ IRISApplication
   // Load the image into the current image data object
   m_IRISImageData->SetMainImage(io);
 
+  // Get a pointer to the resulting wrapper
+  ImageWrapperBase *layer = m_IRISImageData->GetMain();
+
   // Set the filename and nickname of the image wrapper
-  m_IRISImageData->GetMain()->SetFileName(io->GetFileNameOfNativeImage());
+  layer->SetFileName(io->GetFileNameOfNativeImage());
 
   // Update the preprocessing settings to defaults.
   m_EdgePreprocessingSettings->InitializeToDefaults();
 
   // Initialize the layer-specific segmentation parameters
-  CreateSegmentationSettings(m_IRISImageData->GetMain(), MAIN_ROLE);
+  CreateSegmentationSettings(layer, MAIN_ROLE);
 
   // Update the system's history list
   m_HistoryManager->UpdateHistory("MainImage", io->GetFileNameOfNativeImage(), false);
@@ -1641,41 +1576,40 @@ IRISApplication
   m_GlobalState->SetSegmentationROI(io->GetNativeImage()->GetBufferedRegion());
 
   // Read and apply the project-level settings associated with the main image
-  LoadMetaDataAssociatedWithLayer(
-        m_IRISImageData->GetMain(), MAIN_ROLE, metadata);
+  LoadMetaDataAssociatedWithLayer(layer, MAIN_ROLE, metadata);
+
+  // The main image may not be sticky, but in old versions of SNAP that was
+  // allowed, so we force override
+  if(layer->IsSticky())
+    layer->SetSticky(false);
 
   // Fire the dimensions change event
   InvokeEvent(MainImageDimensionsChangeEvent());
 
   // Update the crosshairs position to the center of the image
-  Vector3ui cursor = m_IRISImageData->GetMain()->GetSize();
-  cursor /= 2;
-  this->SetCursorPosition(cursor);
+  this->SetCursorPosition(layer->GetSize() / 2u);
 
   // This line forces the cursor to be propagated to the image even if the
   // crosshairs positions did not change from their previous values
-  this->GetIRISImageData()->SetCrosshairs(cursor);
+  this->GetIRISImageData()->SetCrosshairs(layer->GetSize() / 2u);
 
   // If the default is to auto-contrast, perform the contrast adjustment
   // operation on the image
   if(m_GlobalState->GetDefaultBehaviorSettings()->GetAutoContrast())
-    {
-    AutoContrastLayerOnLoad(m_IRISImageData->GetMain());
-    }
+    AutoContrastLayerOnLoad(layer);
 
   // Save the thumbnail for the current image. This ensures that a thumbnail
   // is created even if the application crashes or is killed.
-  m_CurrentImageData->GetMain()->WriteThumbnail(
+  layer->WriteThumbnail(
         m_SystemInterface->GetThumbnailAssociatedWithFile(
           io->GetFileNameOfNativeImage().c_str()).c_str(), 128);
 
-  // Reset the UNDO manager
-  m_UndoManager.Clear();
-  m_UndoManager.SetCumulativeDelta(NULL);
-
   // We also want to reset the label history at this point, as these are
   // very different labels
   m_LabelUseHistory->Reset();
+
+  // Make the main image 'selected'
+  m_GlobalState->SetSelectedLayerId(layer->GetUniqueId());
 }
 
 void IRISApplication::LoadMetaDataAssociatedWithLayer(
@@ -1888,19 +1822,25 @@ IRISApplication::CreateSaveDelegateForLayer(ImageWrapperBase *layer, LayerRole r
   if(role == MAIN_ROLE)
     {
     history = "AnatomicImage";
-    category = "Main Image";
+    category = "Image";
     }
 
   else if(role == LABEL_ROLE)
     {
     history = "LabelImage";
     category = "Segmentation Image";
+
+    if(this->IsSnakeModeActive() && this->GetPreprocessingMode() == PREPROCESS_RF)
+      {
+      history = "ClassifierSamples";
+      category = "Classifier Samples Image";
+      }
     }
 
   else if(role == OVERLAY_ROLE)
     {
     history = "AnatomicImage";
-    category = "Overlay Image";
+    category = "Image";
     }
 
   else if(role == SNAP_ROLE)
@@ -1921,6 +1861,7 @@ IRISApplication::CreateSaveDelegateForLayer(ImageWrapperBase *layer, LayerRole r
   // Create delegate
   SmartPtr<DefaultSaveImageDelegate> delegate = DefaultSaveImageDelegate::New();
   delegate->Initialize(this, layer, history);
+  delegate->SetCategory(category);
 
   // Return the delegate
   return delegate.GetPointer();
@@ -1971,6 +1912,10 @@ void IRISApplication::SaveProjectToRegistry(Registry &preg, const std::string pr
     // Save the metadata associated with the layer
     SaveMetaDataAssociatedWithLayer(layer, it.GetRole(), &folder);
     }
+
+  // Save the annotations in the workspace
+  Registry &ann_folder = preg.Folder("Annotations");
+  this->m_IRISImageData->GetAnnotations()->SaveAnnotations(ann_folder);
 }
 
 void IRISApplication::SaveProject(const std::string &proj_file)
@@ -2071,7 +2016,9 @@ void IRISApplication::OpenProject(
 
     // Check if the main has been loaded
     if(role == MAIN_ROLE)
-      main_loaded = true;
+      {
+      main_loaded = true;      
+      }
     }
 
   // If main has not been loaded, throw an exception
@@ -2085,6 +2032,13 @@ void IRISApplication::OpenProject(
   m_SystemInterface->GetHistoryManager()->
       UpdateHistory("Project", proj_file_full, false);
 
+  // Load the annotations
+  if(preg.HasFolder("Annotations"))
+    {
+    Registry &ann_folder = preg.Folder("Annotations");
+    m_IRISImageData->GetAnnotations()->LoadAnnotations(ann_folder);
+    }
+
   // Simulate saving the project into a registy that will be cached. This
   // allows us to check later whether the project state has changed.
   SaveProjectToRegistry(m_LastSavedProjectState, proj_file_full);
@@ -2118,6 +2072,25 @@ bool IRISApplication::IsProjectFile(const char *filename)
 }
 
 
+void IRISApplication::SaveAnnotations(const char *filename)
+{
+  Registry reg;
+  m_CurrentImageData->GetAnnotations()->SaveAnnotations(reg);
+  reg.WriteToXMLFile(filename);
+
+  m_SystemInterface->GetHistoryManager()->UpdateHistory("Annotations", filename, true);
+}
+
+void IRISApplication::LoadAnnotations(const char *filename)
+{
+  Registry reg;
+  reg.ReadFromXMLFile(filename);
+  m_CurrentImageData->GetAnnotations()->LoadAnnotations(reg);
+
+  m_SystemInterface->GetHistoryManager()->UpdateHistory("Annotations", filename, true);
+}
+
+
 
 
 void IRISApplication::Quit()
@@ -2371,7 +2344,8 @@ void IRISApplication::EnterRandomForestPreprocessingMode()
   bool can_use_saved_classifier =
       (m_LastUsedRFClassifier &&
        m_LastUsedRFClassifierComponents ==
-       m_ClassificationEngine->GetNumberOfComponents());
+       m_ClassificationEngine->GetNumberOfComponents() &&
+       m_LastUsedRFClassifier->IsValidClassifier());
 
   if(can_use_saved_classifier)
     {
@@ -2397,6 +2371,10 @@ void IRISApplication::EnterRandomForestPreprocessingMode()
   m_RandomForestPreviewWrapper->AttachInputs(m_SNAPImageData);
   m_RandomForestPreviewWrapper->AttachOutputWrapper(m_SNAPImageData->GetSpeed());
   m_RandomForestPreviewWrapper->SetParameters(m_ClassificationEngine->GetClassifier());
+
+  // Switch segmentation to examples
+  m_SNAPImageData->SwitchLabelImageToExamples();
+  InvokeEvent(SegmentationChangeEvent());
 }
 
 #include "RandomForestClassifier.h"
@@ -2420,6 +2398,10 @@ void IRISApplication::LeaveRandomForestPreprocessingMode()
 
   // Clear the classification engine
   m_ClassificationEngine = NULL;
+
+  // Switch segmentation to examples
+  m_SNAPImageData->SwitchLabelImageToMainSegmentation();
+  InvokeEvent(SegmentationChangeEvent());
 }
 
 void IRISApplication::EnterPreprocessingMode(PreprocessingMode mode)
diff --git a/Logic/Framework/IRISApplication.h b/Logic/Framework/IRISApplication.h
index 313dbcc..a7b7a54 100644
--- a/Logic/Framework/IRISApplication.h
+++ b/Logic/Framework/IRISApplication.h
@@ -70,7 +70,7 @@ class GaussianMixtureModel;
 class RandomForestClassifier;
 struct IRISDisplayGeometry;
 class LabelUseHistory;
-
+class ImageAnnotationData;
 
 template <class TTraits> class PresetManager;
 class ColorMapPresetTraits;
@@ -125,7 +125,6 @@ public:
   typedef itk::Image<LabelType,3> LabelImageType;
   typedef itk::Image<short ,3> SpeedImageType;
   typedef itk::Command CommandType;
-  typedef UndoDataManager<LabelType> UndoManagerType;
 
   // A drawing performed on a slice
   typedef itk::Image<unsigned char, 2> SliceBinaryImageType;
@@ -220,6 +219,19 @@ public:
   void AddIRISOverlayImage(GuidedNativeImageIO *nativeIO, Registry *metadata = NULL);
 
   /**
+   * Add an overlay image that resides in its native space, but is transformed into
+   * the space of the main image using a set of transformation parameters (e.g., rigid
+   * transform)
+   */
+  void AddIRISCoregOverlayImage(GuidedNativeImageIO *io, Registry *metadata);
+
+  /**
+   * Add a 'derived' overlay, i.e., an overlay generated using image processing from one
+   * of the existing image layers
+   */
+  void AddDerivedOverlayImage(ImageWrapperBase *overlay);
+
+  /**
    * Remove a specific overlay
    */
   void UnloadOverlay(ImageWrapperBase *ovl);
@@ -253,6 +265,16 @@ public:
    */
   void UpdateIRISSegmentationImage(GuidedNativeImageIO *io);
 
+  /**
+   * Update the SNAP image data with an external segmentation image (e.g.,
+   * loaded from a file).
+   *
+   * TODO: this should probably change when we allow multiple concurrent segmentation
+   * images to be used in SNAP mode.
+   */
+  void UpdateSNAPSegmentationImage(GuidedNativeImageIO *io);
+
+
   /** 
    * Clear the IRIS segmentation image
    */
@@ -501,9 +523,7 @@ public:
   /** Redo (undo the undo) */
   void Redo();
 
-  irisGetMacro(UndoManager, const UndoManagerType &);
-
-  /** 
+  /**
    * Reorient the main image (and all overlays) 
    */
   void ReorientImage(vnl_matrix_fixed<double, 3, 3> inDirection);
@@ -577,6 +597,17 @@ public:
 
   // --------------------- End project support ----------------------------
 
+  // --------------------- Annotation support ----------------------------
+
+  /**
+   * Read annotations from file
+   */
+  void LoadAnnotations(const char *filename);
+
+  /**
+   * Save annotations to file
+   */
+  void SaveAnnotations(const char *filename);
 
 protected:
 
@@ -610,13 +641,6 @@ protected:
   // Coordinate mapping between display space and anatomical space
   IRISDisplayGeometry m_DisplayGeometry;
 
-  // Undo data manager. Perhaps this should really be in IRISImageData, but
-  // there is a lot of stuff here that is ambiguous in this way. The manager
-  // stores 'deltas', i.e., differences between states of the segmentation
-  // image. These deltas are compressed, allowing us to store a bunch of 
-  // undo steps with little cost in performance or memory
-  UndoManagerType m_UndoManager;
-
   // Settings for the speed preprocessing. Still not sure this is the best
   // place to put this stuff!
   SmartPtr<EdgePreprocessingSettings> m_EdgePreprocessingSettings;
@@ -712,6 +736,8 @@ protected:
 
   // Auto-adjust contrast of a layer on load
   void AutoContrastLayerOnLoad(ImageWrapperBase *layer);
+
+
 };
 
 #endif // __IRISApplication_h_
diff --git a/Logic/Framework/ImageAnnotationData.cxx b/Logic/Framework/ImageAnnotationData.cxx
new file mode 100644
index 0000000..f4456f0
--- /dev/null
+++ b/Logic/Framework/ImageAnnotationData.cxx
@@ -0,0 +1,196 @@
+#include "ImageAnnotationData.h"
+#include "Registry.h"
+#include "IRISException.h"
+
+namespace annot
+{
+
+bool AbstractAnnotation::IsVisible(int plane, int slice) const
+{
+  // Check if the plane makes this annotation invisible
+  if(!m_VisibleInAllPlanes && plane != m_Plane)
+    return false;
+
+  // Check if the slice makes this annotation invisible
+  if(!m_VisibleInAllSlices && slice != this->GetSliceIndex(plane))
+    return false;
+
+  return true;
+}
+
+bool AbstractAnnotation::IsVisible(int plane) const
+{
+  // Check if the plane makes this annotation invisible
+  if(!m_VisibleInAllPlanes && plane != m_Plane)
+    return false;
+
+  return true;
+}
+
+void AbstractAnnotation::Save(Registry &folder)
+{
+  folder["Selected"] << m_Selected;
+  folder["VisibleInAllSlices"] << m_VisibleInAllSlices;
+  folder["VisibleInAllPlanes"] << m_VisibleInAllPlanes;
+  folder["Plane"] << m_Plane;
+  folder["Color"] << m_Color;
+}
+
+void AbstractAnnotation::Load(Registry &folder)
+{
+  m_Selected = folder["Selected"][false];
+  m_VisibleInAllSlices = folder["VisibleInAllSlices"][false];
+  m_VisibleInAllPlanes = folder["VisibleInAllPlanes"][false];
+  m_Plane = folder["Plane"][0];
+  m_Color = folder["Color"][Vector3d(1.0, 0.0, 0.0)];
+}
+
+int LineSegmentAnnotation::GetSliceIndex(int plane) const
+{
+  // Just return the coordinate of the first point. It should be the same
+  // as the coordinate of the second point
+  assert(plane == m_Plane);
+  assert(m_Segment.first[plane] == m_Segment.second[plane]);
+
+  return (int) (m_Segment.first[plane]);
+}
+
+Vector3f LineSegmentAnnotation::GetAnchorPoint(int plane) const
+{
+  // Use the midpoint
+  return (m_Segment.first + m_Segment.second) * 0.5f;
+}
+
+void LineSegmentAnnotation::Save(Registry &folder)
+{
+  Superclass::Save(folder);
+  folder["Type"] << "LineSegmentAnnotation";
+  folder["Point1"] << to_double(m_Segment.first);
+  folder["Point2"] << to_double(m_Segment.second);
+}
+
+void LineSegmentAnnotation::Load(Registry &folder)
+{
+  Superclass::Load(folder);
+  m_Segment.first = to_float(folder["Point1"][Vector3d(0.0)]);
+  m_Segment.second = to_float(folder["Point2"][Vector3d(0.0)]);
+  if(m_Segment.first[this->m_Plane] != m_Segment.second[this->m_Plane])
+    throw IRISException("Invalid line segment annotation detected in file.");
+}
+
+void LineSegmentAnnotation::MoveBy(const Vector3f &offset)
+{
+  m_Segment.first += offset;
+  m_Segment.second += offset;
+}
+
+int LandmarkAnnotation::GetSliceIndex(int plane) const
+{
+  // Just return the coordinate of the first point. It should be the same
+  // as the coordinate of the second point
+  return (int) (m_Landmark.Pos[plane]);
+}
+
+Vector3f LandmarkAnnotation::GetAnchorPoint(int plane) const
+{
+  return m_Landmark.Pos;
+}
+
+void LandmarkAnnotation::MoveBy(const Vector3f &offset)
+{
+  m_Landmark.Pos += offset;
+}
+
+void LandmarkAnnotation::Save(Registry &folder)
+{
+  Superclass::Save(folder);
+  folder["Type"] << "LandmarkAnnotation";
+  folder["Pos"] << to_double(m_Landmark.Pos);
+  folder["Offset"] << to_double(m_Landmark.Offset);
+  folder["Text"] << m_Landmark.Text;
+}
+
+void LandmarkAnnotation::Load(Registry &folder)
+{
+  Superclass::Load(folder);
+  m_Landmark.Pos = to_float(folder["Pos"][Vector3d(0.0)]);
+  m_Landmark.Offset = to_float(folder["Offset"][Vector2d(0.0)]);
+  m_Landmark.Text = folder["Text"]["??? Landmark"];
+}
+
+
+}
+
+void ImageAnnotationData::AddAnnotation(ImageAnnotationData::AbstractAnnotation *annot)
+{
+  SmartPtr<AbstractAnnotation> myannot = annot;
+  m_Annotations.push_back(myannot);
+}
+
+void ImageAnnotationData::Reset()
+{
+  m_Annotations.clear();
+}
+
+void ImageAnnotationData::SaveAnnotations(Registry &reg)
+{
+  // Store the current format of the annotations
+  reg["Format"] << "ITK-SNAP Annotation File";
+
+  // Format date specifies the date this format was developed. If in the future
+  // the format changes in drastic ways, this allows the future code to recover.
+  reg["FormatDate"] << "20150624";
+
+  // Save the array of annotations
+  reg["Annotations.ArraySize"] << m_Annotations.size();
+  int i = 0;
+  for(AnnotationConstIterator it = m_Annotations.begin(); it != m_Annotations.end(); it++, i++)
+    {
+    AbstractAnnotation *ann = *it;
+    Registry &folder = reg.Folder(reg.Key("Annotations.Element[%d]", i));
+    ann->Save(folder);
+    }
+}
+
+
+void ImageAnnotationData::LoadAnnotations(Registry &reg)
+{
+  // Read the format
+  std::string format = reg["Format"][""];
+  std::string format_date = reg["FormatDate"][""];
+  if(format != "ITK-SNAP Annotation File" || format_date.length() != 8)
+    throw IRISException("Annotation file is not in the correct format.");
+
+  // Clear the annotations
+  m_Annotations.clear();
+
+  // Read the list of annotations
+  int n_annot = reg["Annotations.ArraySize"][0];
+  for(int i = 0; i < n_annot; i++)
+    {
+    Registry &folder = reg.Folder(reg.Key("Annotations.Element[%d]", i));
+
+    // Factory code
+    std::string type = folder["Type"][""];
+    AnnotationPtr ann;
+    if(type == "LineSegmentAnnotation")
+      {
+      SmartPtr<annot::LineSegmentAnnotation> line_ann =  annot::LineSegmentAnnotation::New();
+      ann = line_ann.GetPointer();
+      }
+    else if(type == "LandmarkAnnotation")
+      {
+      SmartPtr<annot::LandmarkAnnotation> lm_ann =  annot::LandmarkAnnotation::New();
+      ann = lm_ann.GetPointer();
+      }
+
+    // Read the annotation
+    if(ann)
+      {
+      ann->Load(folder);
+      m_Annotations.push_back(ann);
+      }
+    }
+}
+
+
diff --git a/Logic/Framework/ImageAnnotationData.h b/Logic/Framework/ImageAnnotationData.h
new file mode 100644
index 0000000..d06aa07
--- /dev/null
+++ b/Logic/Framework/ImageAnnotationData.h
@@ -0,0 +1,181 @@
+#ifndef IMAGEANNOTATIONDATA_H
+#define IMAGEANNOTATIONDATA_H
+
+#include "SNAPCommon.h"
+#include <utility>
+#include <string>
+#include <list>
+#include "itkDataObject.h"
+#include "itkObjectFactory.h"
+
+class Registry;
+
+namespace annot
+{
+
+typedef Vector3f Point;
+
+/**
+ * @brief Slices where the annotation is displayed
+ */
+enum VisSlice {
+  SINGLE_SLICE = 0, ALL_SLICES
+};
+
+/**
+ * @brief Parent class for annotations
+ */
+class AbstractAnnotation : public itk::DataObject
+{
+public:
+  irisITKAbstractObjectMacro(AbstractAnnotation, itk::DataObject)
+
+  /** Whether this annotation is currently selected */
+  irisGetSetMacro(Selected, bool)
+
+  /** Whether this annotation is visible in all slices or just its own slice */
+  irisGetSetMacro(VisibleInAllSlices, bool)
+
+  /** Whether this annotation is visible in all ortho planes or just its own plane */
+  irisGetSetMacro(VisibleInAllPlanes, bool)
+
+  /** The image dimension to which this annotation belongs, or -1 if it's non-planar */
+  irisGetSetMacro(Plane, int)
+
+  /** Get the color of the annotation */
+  irisGetSetMacro(Color, const Vector3d &)
+
+  /** Test whether the annotation is visible in the current plane and given slice */
+  bool IsVisible(int plane, int slice) const;
+
+  /** Test whether the annotation is visible in the current plane in some slice */
+  bool IsVisible(int plane) const;
+
+  /** Get the slice this annotation belongs to for a particular plane */
+  virtual int GetSliceIndex(int plane) const = 0;
+
+  /** Get the anchor point for the annotation in a given plane - used for sorting */
+  virtual Vector3f GetAnchorPoint(int plane) const = 0;
+
+  /** Move the annotation by given amount in physical space */
+  virtual void MoveBy(const Vector3f &offset) = 0;
+
+  /** Save the annotation data to registry */
+  virtual void Save(Registry &folder);
+
+  /** Load from the registry */
+  virtual void Load(Registry &folder);
+
+protected:
+
+  AbstractAnnotation() {}
+  ~AbstractAnnotation() {}
+
+  bool m_Selected;
+  bool m_VisibleInAllSlices;
+  bool m_VisibleInAllPlanes;
+
+  Vector3d m_Color;
+
+  int m_Plane;
+};
+
+/** A simple line segment */
+typedef std::pair<Vector3f,Vector3f>           LineSegment;
+
+class LineSegmentAnnotation : public AbstractAnnotation
+{
+public:
+  irisITKObjectMacro(LineSegmentAnnotation, AbstractAnnotation)
+
+  typedef LineSegment                   ObjectType;
+
+  irisGetSetMacro(Segment, const LineSegment &)
+
+  virtual void Save(Registry &folder);
+  virtual void Load(Registry &folder);
+
+  virtual void MoveBy(const Vector3f &offset);
+
+protected:
+
+  virtual int GetSliceIndex(int plane) const;
+
+  virtual Vector3f GetAnchorPoint(int plane) const;
+
+  LineSegment m_Segment;
+};
+
+/**
+ * @brief Text with location
+ */
+struct Landmark
+{
+  std::string Text;
+  Vector3f Pos;
+  Vector2f Offset;
+};
+
+class LandmarkAnnotation : public AbstractAnnotation
+{
+public:
+  irisITKObjectMacro(LandmarkAnnotation, AbstractAnnotation)
+
+  typedef Landmark                   ObjectType;
+
+  irisGetSetMacro(Landmark, const Landmark &)
+
+
+protected:
+
+  virtual int GetSliceIndex(int plane) const;
+  virtual Vector3f GetAnchorPoint(int plane) const;
+
+  virtual void MoveBy(const Vector3f &offset);
+
+  virtual void Save(Registry &folder);
+  virtual void Load(Registry &folder);
+
+  Landmark m_Landmark;
+};
+
+}
+
+
+/**
+ * This class describes a collection of image annotations
+ *
+ * Image annotations are defined in voxel coordinate space. This helps keep the
+ * annotations in place when header information changes. It also makes the internal
+ * logic simpler.
+ */
+class ImageAnnotationData : public itk::DataObject
+{
+public:
+  typedef annot::AbstractAnnotation AbstractAnnotation;
+  typedef SmartPtr<AbstractAnnotation> AnnotationPtr;
+  typedef std::list<AnnotationPtr> AnnotationList;
+  typedef AnnotationList::iterator AnnotationIterator;
+  typedef AnnotationList::const_iterator AnnotationConstIterator;
+
+  irisITKObjectMacro(ImageAnnotationData, itk::DataObject)
+
+  irisGetMacro(Annotations, const AnnotationList &)
+
+  AnnotationList &GetAnnotations() { return m_Annotations; }
+
+  void AddAnnotation(AbstractAnnotation *annot);
+
+  void Reset();
+
+  void SaveAnnotations(Registry &reg);
+  void LoadAnnotations(Registry &reg);
+
+protected:
+  ImageAnnotationData() {}
+  ~ImageAnnotationData() {}
+
+  AnnotationList m_Annotations;
+};
+
+#endif // IMAGEANNOTATIONDATA_H
diff --git a/Logic/Framework/ImageIODelegates.cxx b/Logic/Framework/ImageIODelegates.cxx
index 6d3f29b..1d7d34a 100644
--- a/Logic/Framework/ImageIODelegates.cxx
+++ b/Logic/Framework/ImageIODelegates.cxx
@@ -3,6 +3,7 @@
 #include "IRISApplication.h"
 #include "GenericImageData.h"
 #include "HistoryManager.h"
+#include "IRISImageData.h"
 
 
 /* =============================
@@ -39,12 +40,13 @@ LoadMainImageDelegate
   m_Driver->UnloadMainImage();
 }
 
-void
-LoadMainImageDelegate
-::UpdateApplicationWithImage(GuidedNativeImageIO *io)
+ImageWrapperBase *LoadMainImageDelegate::UpdateApplicationWithImage(GuidedNativeImageIO *io)
 {
   // Update the IRIS driver
   m_Driver->UpdateIRISMainImage(io, this->GetMetaDataRegistry());
+
+  // Return the main image
+  return m_Driver->GetIRISImageData()->GetMain();
 }
 
 
@@ -60,12 +62,13 @@ LoadOverlayImageDelegate
   // on an undo in a wizard?
 }
 
-void
-LoadOverlayImageDelegate
-::UpdateApplicationWithImage(GuidedNativeImageIO *io)
+ImageWrapperBase *LoadOverlayImageDelegate::UpdateApplicationWithImage(GuidedNativeImageIO *io)
 {
+  // Load the overlay
   m_Driver->AddIRISOverlayImage(io, this->GetMetaDataRegistry());
 
+  // Return it
+  return m_Driver->GetIRISImageData()->GetLastOverlay();
 }
 
 
@@ -89,11 +92,37 @@ LoadOverlayImageDelegate
                         "does not match the size of the main image "
                         "(%d x %d x %d). Images must have the same dimensions.",
                         szSeg[0], szSeg[1], szSeg[2],
-                        szMain[0], szMain[1], szMain[2]);
+        szMain[0], szMain[1], szMain[2]);
     }
 }
 
 
+
+/* =============================
+   Co-Registered Overlay Image
+   ============================= */
+
+void
+LoadCoregisteredOverlayImageDelegate
+::UnloadCurrentImage()
+{
+}
+
+ImageWrapperBase *LoadCoregisteredOverlayImageDelegate::UpdateApplicationWithImage(GuidedNativeImageIO *io)
+{
+  m_Driver->AddIRISCoregOverlayImage(io, this->GetMetaDataRegistry());
+  return m_Driver->GetIRISImageData()->GetLastOverlay();
+}
+
+
+void
+LoadCoregisteredOverlayImageDelegate
+::ValidateHeader(GuidedNativeImageIO *io, IRISWarningList &wl)
+{
+  // Do the parent's check
+  LoadAnatomicImageDelegate::ValidateHeader(io, wl);
+}
+
 /* =============================
    SEGMENTATION Image
    ============================= */
@@ -188,11 +217,14 @@ LoadSegmentationImageDelegate
     }
 }
 
-void
-LoadSegmentationImageDelegate
-::UpdateApplicationWithImage(GuidedNativeImageIO *io)
+ImageWrapperBase *LoadSegmentationImageDelegate::UpdateApplicationWithImage(GuidedNativeImageIO *io)
 {
-  m_Driver->UpdateIRISSegmentationImage(io);
+  if(m_Driver->IsSnakeModeActive())
+    m_Driver->UpdateSNAPSegmentationImage(io);
+  else
+    m_Driver->UpdateIRISSegmentationImage(io);
+
+  return m_Driver->GetCurrentImageData()->GetSegmentation();
 }
 
 void
diff --git a/Logic/Framework/ImageIODelegates.h b/Logic/Framework/ImageIODelegates.h
index 211e984..bdbc53a 100644
--- a/Logic/Framework/ImageIODelegates.h
+++ b/Logic/Framework/ImageIODelegates.h
@@ -42,7 +42,15 @@ public:
   virtual void ValidateHeader(GuidedNativeImageIO *io, IRISWarningList &wl) {}
   virtual void ValidateImage(GuidedNativeImageIO *io, IRISWarningList &wl) {}
   virtual void UnloadCurrentImage() = 0;
-  virtual void UpdateApplicationWithImage(GuidedNativeImageIO *io) = 0;
+
+  /**
+   * Update the application with the image contained in the Guided IO object and
+   * return a pointer to the loaded image layer
+   */
+  virtual ImageWrapperBase *UpdateApplicationWithImage(GuidedNativeImageIO *io) = 0;
+
+  virtual bool GetUseRegistration() const { return false; }
+  virtual bool IsOverlay() const { return false; }
 
 protected:
   AbstractLoadImageDelegate() : m_MetaDataRegistry(NULL) {}
@@ -74,7 +82,7 @@ public:
   irisITKObjectMacro(LoadMainImageDelegate, LoadAnatomicImageDelegate)
 
   void UnloadCurrentImage();
-  void UpdateApplicationWithImage(GuidedNativeImageIO *io);
+  ImageWrapperBase * UpdateApplicationWithImage(GuidedNativeImageIO *io);
 
 protected:
   LoadMainImageDelegate() {}
@@ -89,14 +97,37 @@ public:
   irisITKObjectMacro(LoadOverlayImageDelegate, LoadAnatomicImageDelegate)
 
   void UnloadCurrentImage();
-  void UpdateApplicationWithImage(GuidedNativeImageIO *io);
+  ImageWrapperBase * UpdateApplicationWithImage(GuidedNativeImageIO *io);
   void ValidateHeader(GuidedNativeImageIO *io, IRISWarningList &wl);
+  virtual bool IsOverlay() const { return true; }
 
 protected:
-  LoadOverlayImageDelegate() {}
+  LoadOverlayImageDelegate() { }
   virtual ~LoadOverlayImageDelegate() {}
 };
 
+
+class LoadCoregisteredOverlayImageDelegate : public LoadAnatomicImageDelegate
+{
+public:
+
+  irisITKObjectMacro(LoadCoregisteredOverlayImageDelegate, LoadAnatomicImageDelegate)
+
+  void UnloadCurrentImage();
+  ImageWrapperBase * UpdateApplicationWithImage(GuidedNativeImageIO *io);
+  void ValidateHeader(GuidedNativeImageIO *io, IRISWarningList &wl);
+
+  virtual bool GetUseRegistration() const { return true; }
+  virtual bool IsOverlay() const { return true; }
+
+
+protected:
+  LoadCoregisteredOverlayImageDelegate() { }
+  virtual ~LoadCoregisteredOverlayImageDelegate() {}
+};
+
+
+
 class LoadSegmentationImageDelegate : public AbstractLoadImageDelegate
 {
 public:
@@ -106,7 +137,7 @@ public:
   virtual void ValidateHeader(GuidedNativeImageIO *io, IRISWarningList &wl);
   virtual void ValidateImage(GuidedNativeImageIO *io, IRISWarningList &wl);
   void UnloadCurrentImage();
-  void UpdateApplicationWithImage(GuidedNativeImageIO *io);
+  ImageWrapperBase * UpdateApplicationWithImage(GuidedNativeImageIO *io);
 
 protected:
   LoadSegmentationImageDelegate() {}
@@ -138,12 +169,18 @@ public:
    */
   bool IsSaveSuccessful() { return m_SaveSuccessful; }
 
+  /**
+   * A user-readable category
+   */
+  irisGetSetMacro(Category, std::string)
+
 protected:
   AbstractSaveImageDelegate() {}
   virtual ~AbstractSaveImageDelegate() {}
 
   IRISApplication *m_Driver;
   bool m_SaveSuccessful;
+  std::string m_Category;
 };
 
 class DefaultSaveImageDelegate : public AbstractSaveImageDelegate
diff --git a/Logic/Framework/LayerIterator.cxx b/Logic/Framework/LayerIterator.cxx
index 2f87d81..cd0fcbf 100644
--- a/Logic/Framework/LayerIterator.cxx
+++ b/Logic/Framework/LayerIterator.cxx
@@ -67,6 +67,15 @@ LayerIterator& LayerIterator
   return *this;
 }
 
+LayerIterator &LayerIterator::Find(unsigned long layer_id)
+{
+  // Just a linear search - we won't have so many wrappers!
+  MoveToBegin();
+  while(!this->IsAtEnd() && this->GetLayer() && this->GetLayer()->GetUniqueId() != layer_id)
+    ++(*this);
+  return *this;
+}
+
 void LayerIterator::MoveToNextTrialPosition()
 {
   // If we are at the end of storage, that's it
diff --git a/Logic/Framework/LayerIterator.h b/Logic/Framework/LayerIterator.h
index 1524e8e..fd37007 100644
--- a/Logic/Framework/LayerIterator.h
+++ b/Logic/Framework/LayerIterator.h
@@ -30,6 +30,8 @@ public:
   // Move to a specific layer, or end if the layer is not found
   LayerIterator &Find(ImageWrapperBase *value);
 
+  LayerIterator &Find(unsigned long layer_id);
+
   LayerIterator & operator++();
 
   LayerIterator & operator+=(int k);
diff --git a/Logic/Framework/SNAPImageData.cxx b/Logic/Framework/SNAPImageData.cxx
index 7db1c1a..e8f6453 100644
--- a/Logic/Framework/SNAPImageData.cxx
+++ b/Logic/Framework/SNAPImageData.cxx
@@ -76,6 +76,8 @@ SNAPImageData
 
   // Create the mutex lock
   m_LevelSetPipelineMutexLock = itk::FastMutexLock::New();
+
+  m_CompressedAlternateLabelImage = NULL;
 }
 
 
@@ -84,6 +86,9 @@ SNAPImageData
 {
   if(m_LevelSetDriver)
     delete m_LevelSetDriver;
+
+  if(m_CompressedAlternateLabelImage)
+    delete m_CompressedAlternateLabelImage;
 }
 
 void 
@@ -509,6 +514,54 @@ SNAPImageData
   return m_LevelSetDriver->GetLevelSetFunction();
 }
 
+void SNAPImageData::SwapLabelImageWithCompressedAlternative()
+{
+  // Create a compressed version of the current segmentation
+  CompressedLabelImageType *save = new CompressedLabelImageType();
+  LabelImageWrapper *liw = this->GetSegmentation();
+  for(LabelImageWrapper::ConstIterator iter(liw->GetImage(), liw->GetBufferedRegion());
+      !iter.IsAtEnd(); ++iter)
+    {
+    save->Encode(iter.Value());
+    }
+  save->FinishEncoding();
+
+  // Clear the undo manager
+  this->m_UndoManager.Clear();
+  this->m_UndoManager.SetCumulativeDelta(m_CompressedAlternateLabelImage);
+
+  // Decompress the currently saved alternative
+  if(m_CompressedAlternateLabelImage)
+    {
+    LabelImageWrapper::Iterator it_write(liw->GetImage(), liw->GetBufferedRegion());
+    for(size_t i = 0; i < m_CompressedAlternateLabelImage->GetNumberOfRLEs(); ++i)
+      {
+      LabelType value = m_CompressedAlternateLabelImage->GetRLEValue(i);
+      for(size_t j = 0; j < m_CompressedAlternateLabelImage->GetRLELength(i); ++j, ++it_write)
+        it_write.Value() = value;
+      }
+    }
+  else
+    {
+    liw->GetImage()->FillBuffer(0);
+    }
+
+  liw->GetImage()->Modified();
+  m_CompressedAlternateLabelImage = save;
+}
+
+void SNAPImageData::SwitchLabelImageToExamples()
+{
+  this->SwapLabelImageWithCompressedAlternative();
+  m_LabelImageInExampleMode = true;
+}
+
+void SNAPImageData::SwitchLabelImageToMainSegmentation()
+{
+  this->SwapLabelImageWithCompressedAlternative();
+  m_LabelImageInExampleMode = false;
+}
+
 void
 SNAPImageData
 ::InitializeToROI(GenericImageData *source,
@@ -541,6 +594,16 @@ SNAPImageData
     // Copy metadata
     this->CopyLayerMetadata(this->GetLastOverlay(), lit.GetLayer());
     }
+
+  // Destroy the alternate image if there is none or if the ROI settings have changed
+  if(m_CompressedAlternateLabelImage && m_ROISettings != roi)
+    {
+    delete m_CompressedAlternateLabelImage;
+    m_CompressedAlternateLabelImage = NULL;
+    }
+
+  // Cache the ROI settings
+  m_ROISettings = roi;
 }
 
 void SNAPImageData::CopyLayerMetadata(
diff --git a/Logic/Framework/SNAPImageData.h b/Logic/Framework/SNAPImageData.h
index b1ea91b..290fda1 100644
--- a/Logic/Framework/SNAPImageData.h
+++ b/Logic/Framework/SNAPImageData.h
@@ -51,6 +51,7 @@
 
 #include "SNAPLevelSetFunction.h"
 #include "itkImageAdaptor.h"
+#include "UndoDataManager.h"
 
 namespace itk {
   class Command;
@@ -211,6 +212,14 @@ public:
    */
   irisGetMacro(LevelSetPipelineMutexLock, itk::FastMutexLock *)
 
+  /** ====================================================================== */
+
+  /* SUPPORT FOR EXAMPLES */
+  void SwitchLabelImageToExamples();
+  void SwitchLabelImageToMainSegmentation();
+
+  /** Is the label image currently switched to example (squiggles) mode? */
+  irisIsMacro(LabelImageInExampleMode)
   
 protected:
 
@@ -284,6 +293,19 @@ protected:
   // SNAPImageData provides a mutex lock that prevents multiple threads from
   // causing the level set pipeline to update at once.
   SmartPtr<itk::FastMutexLock> m_LevelSetPipelineMutexLock;
+
+  // Are we in example mode
+  bool m_LabelImageInExampleMode;
+
+  // Compressed data for the example/main segmentation image
+  typedef UndoDataManager<LabelType>::Delta CompressedLabelImageType;
+  CompressedLabelImageType *m_CompressedAlternateLabelImage;
+
+  // Current ROI settings
+  SNAPSegmentationROISettings m_ROISettings;
+
+
+  void SwapLabelImageWithCompressedAlternative();
 };
 
 
diff --git a/Logic/Framework/UndoDataManager.h b/Logic/Framework/UndoDataManager.h
index 8652e8f..5b3a21d 100644
--- a/Logic/Framework/UndoDataManager.h
+++ b/Logic/Framework/UndoDataManager.h
@@ -32,6 +32,9 @@
   PURPOSE.  See the above copyright notices for more information. 
 
 =========================================================================*/
+#ifndef __UndoDataManager_h_
+#define __UndoDataManager_h_
+
 #include <vector>
 #include <list>
 
@@ -154,3 +157,5 @@ private:
 
   Delta *m_CumulativeDelta;
 };
+
+#endif // __UndoDataManager_h_
diff --git a/Logic/ImageWrapper/DisplayMappingPolicy.cxx b/Logic/ImageWrapper/DisplayMappingPolicy.cxx
index fed5a4e..4761a9c 100644
--- a/Logic/ImageWrapper/DisplayMappingPolicy.cxx
+++ b/Logic/ImageWrapper/DisplayMappingPolicy.cxx
@@ -582,6 +582,11 @@ int MultiChannelDisplayMode::GetHashValue() const
   return SelectedComponent;
 }
 
+bool MultiChannelDisplayMode::IsSingleComponent()
+{
+  return !UseRGB && (SelectedScalarRep == SCALAR_REP_COMPONENT);
+}
+
 bool operator < (const MultiChannelDisplayMode &a, const MultiChannelDisplayMode &b)
 {
   return a.GetHashValue() < b.GetHashValue();
diff --git a/Logic/ImageWrapper/DisplayMappingPolicy.h b/Logic/ImageWrapper/DisplayMappingPolicy.h
index 6e5c43d..0a96a58 100644
--- a/Logic/ImageWrapper/DisplayMappingPolicy.h
+++ b/Logic/ImageWrapper/DisplayMappingPolicy.h
@@ -363,6 +363,12 @@ struct MultiChannelDisplayMode
   /** Get a hash value for this struct - for ordering purposes */
   int GetHashValue() const;
 
+  /**
+   * Whether the mode is a single-component mode: i.e., non-RGB and the
+   * ScalarRepresentation is single component
+   */
+  bool IsSingleComponent();
+
   /** Comparison operators */
   bool operator == (const MultiChannelDisplayMode &mode) const
     { return GetHashValue() == mode.GetHashValue(); }
diff --git a/Logic/ImageWrapper/GuidedNativeImageIO.cxx b/Logic/ImageWrapper/GuidedNativeImageIO.cxx
index 5ff5af7..4da55a9 100755
--- a/Logic/ImageWrapper/GuidedNativeImageIO.cxx
+++ b/Logic/ImageWrapper/GuidedNativeImageIO.cxx
@@ -930,7 +930,9 @@ RescaleNativeImageToIntegralType<TOutputImage>
   typedef itk::VectorImage<TNative, 3> InputImageType;
   typedef itk::ImageRegionConstIterator<InputImageType> InputIterator;
   SmartPtr<InputImageType> input = dynamic_cast<InputImageType *>(native);
+
   assert(input);
+  assert(input->GetPixelContainer()->Size() > 0);
 
   // Get the number of components in the native image
   size_t ncomp = input->GetNumberOfComponentsPerPixel();
@@ -945,24 +947,28 @@ RescaleNativeImageToIntegralType<TOutputImage>
   // Only bother with computing the scale and shift if the types are different
   if(typeid(OutputComponentType) != typeid(TNative))
     {
-    // We must compute the range of the input data
-    double imin = itk::NumericTraits<double>::max();
-    double imax = -itk::NumericTraits<double>::max();
+    // We must compute the range of the input data    
     OutputComponentType omax = itk::NumericTraits<OutputComponentType>::max();
     OutputComponentType omin = itk::NumericTraits<OutputComponentType>::min();
 
+    // Scan over all the image components. Avoid using iterators here because of
+    // unnecessary overhead for vector images.
+    TNative *ib_begin = input->GetBufferPointer();
+    TNative *ib_end = ib_begin + input->GetPixelContainer()->Size();
+
+    TNative imin_nat = *ib_begin, imax_nat = *ib_begin;
+
     // Iterate over all the components in the input image
-    for(InputIterator it(input, input->GetBufferedRegion()); !it.IsAtEnd(); ++it)
+    for(TNative *buffer = ib_begin + 1; buffer < ib_end; ++buffer)
       {
-      typename InputImageType::PixelType pix = it.Get();
-      for(int i = 0; i < ncomp; i++)
-        {
-        double val = static_cast<double>(pix[i]);
-        if(val < imin) imin = val;
-        if(val > imax) imax = val;
-        }
+      TNative val = *buffer;
+      if(val < imin_nat) imin_nat = val;
+      if(val > imax_nat) imax_nat = val;
       }
 
+    // Cast the values to double
+    double imin = static_cast<double>(imin_nat), imax = static_cast<double>(imax_nat);
+
     // Now we have to be careful, depending on the type of the input voxel
     // For float and double, we map the input range into the output range
     if(!itk::NumericTraits<TNative>::is_integer)
@@ -974,16 +980,13 @@ RescaleNativeImageToIntegralType<TOutputImage>
         {
         isint = true;
 
-        for(InputIterator it(input, input->GetBufferedRegion()); !it.IsAtEnd(); ++it)
+        // Another pass through the image? Why is this necessary?
+        for(TNative *buffer = ib_begin; buffer < ib_end; ++buffer)
           {
-          typename InputImageType::PixelType pix = it.Get();
-          for(int i = 0; i < ncomp; i++)
-            {
-            TNative vin = pix[i];
-            TNative vcmp = static_cast<TNative>(static_cast<OutputComponentType>(vin + 0.5));
-            if(vin != vcmp)
-              { isint = false; break; }
-            }
+          TNative vin = *buffer;
+          TNative vcmp = static_cast<TNative>(static_cast<OutputComponentType>(vin + 0.5));
+          if(vin != vcmp)
+            { isint = false; break; }
           }
         }
 
@@ -1003,8 +1006,21 @@ RescaleNativeImageToIntegralType<TOutputImage>
       else
         {
         // Compute the scaling factor to map image into output range
-        scale = (1.0 * omax - 1.0 * omin) / (imax - imin);
-        shift = omin / scale - imin;
+
+        // Does the input range include zero?
+        if(imin <= 0 && imax >= 0)
+          {
+          // If so, there will be no shift, allowing zero to map to zero
+          scale = std::min((double) omax, -1.0 * (double) omin) * 1.0 / std::max(imax, -imin);
+          shift = 0.0;
+          }
+
+        else
+          {
+          // Zero is not in the range, so just use the complete range
+          scale = (1.0 * omax - 1.0 * omin) / (imax - imin);
+          shift = omin / scale - imin;
+          }
         }
       }
 
diff --git a/Logic/ImageWrapper/ImageWrapper.cxx b/Logic/ImageWrapper/ImageWrapper.cxx
index 3e1f97d..cf88d0b 100644
--- a/Logic/ImageWrapper/ImageWrapper.cxx
+++ b/Logic/ImageWrapper/ImageWrapper.cxx
@@ -68,6 +68,7 @@
 #include "UnaryValueToValueFilter.h"
 #include "ScalarImageHistogram.h"
 #include "GuidedNativeImageIO.h"
+#include "itkTransform.h"
 
 
 #include <vnl/vnl_inverse.h>
@@ -426,7 +427,7 @@ ImageWrapper<TTraits,TBase>
 {
   // Update the direction matrix in the image
   typename ImageType::DirectionType matrix(direction);
-  m_Image->SetDirection(matrix);
+  m_ReferenceSpace->SetDirection(matrix);
 
   // Update the NIFTI/RAS transform
   this->UpdateNiftiTransforms();
@@ -517,7 +518,7 @@ ImageWrapper<TTraits,TBase>
   for(size_t d = 0; d < 3; d++) xIndex[d] = iVoxel[d];
 
   itk::Point<double, 3> xPoint;
-  m_ImageBase->TransformIndexToPhysicalPoint(xIndex, xPoint);
+  m_ReferenceSpace->TransformIndexToPhysicalPoint(xIndex, xPoint);
 
   Vector3d xOut;
   for(unsigned int q = 0; q < 3; q++) xOut[q] = xPoint[q];
@@ -577,27 +578,61 @@ ImageWrapper<TTraits,TBase>
 template<class TTraits, class TBase>
 void 
 ImageWrapper<TTraits,TBase>
-::UpdateImagePointer(ImageType *newImage)
+::UpdateImagePointer(ImageType *newImage, ImageBaseType *referenceSpace, ITKTransformType *transform)
 {
+  // If there is no reference space, we assume that the reference space is the same as the image
+  referenceSpace = referenceSpace ? referenceSpace : newImage;
+
   // Check if the image size or image direction matrix has changed
   bool hasSizeChanged = true, hasDirectionChanged = true;
-  if(m_Image && m_Image != newImage)
+  if(m_ReferenceSpace && m_ReferenceSpace != referenceSpace)
     {
-    hasSizeChanged = newImage->GetLargestPossibleRegion().GetSize()
-        != m_Image->GetLargestPossibleRegion().GetSize();
+    hasSizeChanged = referenceSpace->GetLargestPossibleRegion().GetSize()
+        != m_ReferenceSpace->GetLargestPossibleRegion().GetSize();
 
-    hasDirectionChanged = newImage->GetDirection()
-        != m_Image->GetDirection();
+    hasDirectionChanged = referenceSpace->GetDirection()
+        != m_ReferenceSpace->GetDirection();
     }
 
-  // Change the input of the slicers 
-  m_Slicer[0]->SetInput(newImage);
-  m_Slicer[1]->SetInput(newImage);
-  m_Slicer[2]->SetInput(newImage);
+  // Set the input of the slicers, depending on whether the image is subject to transformation
+  if(transform == NULL)
+    {
+    // Slicers take their input directly from the new image
+    for(int i = 0; i < 3; i++)
+      {
+      m_Slicer[i]->SetInput(newImage);
+      m_Slicer[i]->SetPreviewInput(NULL);
+      m_Slicer[i]->SetBypassMainInput(false);
+      }
+    }
+  else
+    {
+    // Create a dummy image to serve as the nominal input to the slicers
+    // We purposely do not allocate this dummy image!
+    SmartPtr<ImageType> dummy = ImageType::New();
+    dummy->CopyInformation(referenceSpace);
+    dummy->SetLargestPossibleRegion(referenceSpace->GetBufferedRegion());
+
+    // Each slicer is attached to a preview filter
+    for(int i = 0; i < 3; i++)
+      {
+      // Set the input to the dummy image
+      m_Slicer[i]->SetInput(dummy);
+
+      // Create an itk reslicing filter
+      m_ResampleFilter[i] = ResampleFilter::New();
+      m_ResampleFilter[i]->SetInput(newImage);
+      m_ResampleFilter[i]->SetTransform(transform);
+      m_ResampleFilter[i]->SetOutputParametersFromImage(referenceSpace);
+      m_Slicer[i]->SetPreviewInput(m_ResampleFilter[i]->GetOutput());
+      m_Slicer[i]->SetBypassMainInput(true);
+      }
+    }
 
   // Update the image
+  this->m_ReferenceSpace = referenceSpace;
   this->m_ImageBase = newImage;
-  m_Image = newImage;
+  this->m_Image = newImage;
 
   // Mark the image as Modified to enforce correct sequence of
   // operations with MinMaxCalc
@@ -629,13 +664,14 @@ ImageWrapper<TTraits,TBase>
 template<class TTraits, class TBase>
 void 
 ImageWrapper<TTraits,TBase>
-::InitializeToWrapper(const ImageWrapperBase *source, ImageType *image) 
+::InitializeToWrapper(const ImageWrapperBase *source,
+                      ImageType *image, ImageBaseType *refSpace, ITKTransformType *tran)
 {
   // Update the display geometry from the source wrapper
   m_DisplayGeometry = source->GetDisplayGeometry();
 
   // Call the common update method
-  UpdateImagePointer(image);
+  UpdateImagePointer(image, refSpace, tran);
 
   // Update the slice index
   SetSliceIndex(source->GetSliceIndex());
@@ -679,6 +715,29 @@ ImageWrapper<TTraits,TBase>
 
 
 template<class TTraits, class TBase>
+void
+ImageWrapper<TTraits,TBase>
+::SetImage(ImagePointer newImage, ImageBaseType *refSpace, ITKTransformType *transform)
+{
+  UpdateImagePointer(newImage, refSpace, transform);
+}
+
+template<class TTraits, class TBase>
+void
+ImageWrapper<TTraits,TBase>
+::SetITKTransform(ImageBaseType *refSpace, ITKTransformType *transform)
+{
+  // TODO: this is a hack, to get around the display slices not updating...
+  Vector3ui index = this->GetSliceIndex();
+  UpdateImagePointer(m_Image, refSpace, transform);
+  this->SetSliceIndex(Vector3ui(0u));
+  this->SetSliceIndex(index);
+  this->InvokeEvent(WrapperDisplayMappingChangeEvent());
+}
+
+
+
+template<class TTraits, class TBase>
 void 
 ImageWrapper<TTraits,TBase>
 ::Reset() 
@@ -801,13 +860,13 @@ ImageWrapper<TTraits,TBase>
   // This method must be called whenever one of these parameters changes.
 
   // Create an image coordinate geometry based on the current state
-  if(m_Image)
+  if(m_ReferenceSpace)
     {
     // Set the geometry based on the current image characteristics
     m_ImageGeometry.SetGeometry(
-          m_Image->GetDirection().GetVnlMatrix(),
+          m_ReferenceSpace->GetDirection().GetVnlMatrix(),
           m_DisplayGeometry,
-          m_Image->GetLargestPossibleRegion().GetSize());
+          m_ReferenceSpace->GetLargestPossibleRegion().GetSize());
 
     // Update the geometry for each slice
     for(unsigned int iSlice = 0;iSlice < 3;iSlice ++)
@@ -860,13 +919,13 @@ void
 ImageWrapper<TTraits,TBase>
 ::UpdateNiftiTransforms()
 {
-  assert(m_Image);
+  assert(m_ReferenceSpace);
 
   // Update the NIFTI/RAS transform
   m_NiftiSform = ImageWrapperBase::ConstructNiftiSform(
-    m_Image->GetDirection().GetVnlMatrix(),
-    m_Image->GetOrigin().GetVnlVector(),
-    m_Image->GetSpacing().GetVnlVector());
+    m_ReferenceSpace->GetDirection().GetVnlMatrix(),
+    m_ReferenceSpace->GetOrigin().GetVnlVector(),
+    m_ReferenceSpace->GetSpacing().GetVnlVector());
 
   // Compute the inverse transform
   m_NiftiInvSform = vnl_inverse(m_NiftiSform);
@@ -1015,7 +1074,8 @@ ImageWrapper<TTraits, TBase>
 ::SetFileName(const std::string &name)
 {
   m_FileName = name;
-  m_FileNameShort = itksys::SystemTools::GetFilenameName(name);
+  m_FileNameShort = itksys::SystemTools::GetFilenameWithoutExtension(
+        itksys::SystemTools::GetFilenameName(name));
   this->InvokeEvent(WrapperMetadataChangeEvent());
 }
 
diff --git a/Logic/ImageWrapper/ImageWrapper.h b/Logic/ImageWrapper/ImageWrapper.h
index 2437c2c..94e6286 100644
--- a/Logic/ImageWrapper/ImageWrapper.h
+++ b/Logic/ImageWrapper/ImageWrapper.h
@@ -52,6 +52,11 @@ class SNAPSegmentationROISettings;
 namespace itk {
   template <unsigned int VDimension> class ImageBase;
   template <class TImage> class ImageSource;
+  template <typename TScalar, unsigned int V1, unsigned int V2> class Transform;
+  template<typename TInputImage,
+           typename TOutputImage,
+           typename TInterpolatorPrecisionType,
+           typename TTransformPrecisionType> class ResampleImageFilter;
 }
 
 #include <itkImageSource.h>
@@ -128,6 +133,10 @@ public:
   typedef itk::SimpleDataObjectDecorator<ComponentType>    ComponentTypeObject;
   typedef itk::SimpleDataObjectDecorator<double>                  DoubleObject;
 
+  // ITK's coordinate transform (rigid, affine, etc)
+  typedef typename Superclass::ITKTransformType               ITKTransformType;
+
+
   /**
    * Get the parent wrapper for this wrapper. For 'normal' wrappers, this method
    * returns NULL, indicating that the wrapper is a top-level wrapper. For derived
@@ -152,7 +161,7 @@ public:
    * source wrapper, otherwise, it's equivalent to SetImage()
    */ 
   virtual void InitializeToWrapper(
-    const ImageWrapperBase *source, ImageType *image);
+    const ImageWrapperBase *source, ImageType *image, ImageBaseType *refSpace, ITKTransformType *tran);
 
   /**
     Get a unique id for this wrapper. All wrappers ever created have
@@ -343,6 +352,18 @@ public:
   virtual void SetImage(ImagePointer newImage);
 
   /**
+   * Set the wrapper to hold an image that is in a coordinate space that is
+   * different from the program's main reference space
+   */
+  virtual void SetImage(ImagePointer newImage, ImageBaseType *refSpace, ITKTransformType *transform);
+
+  /**
+   * Update the transform between the coordinate space of this image and the program's
+   * main reference space
+   */
+  virtual void SetITKTransform(ImageBaseType *referenceSpace, ITKTransformType *transform);
+
+  /**
    * Extract a region of interest from the image wrapper, as a new wrapper of
    * the same type
    */
@@ -526,6 +547,9 @@ protected:
   /** The wrapped image */
   SmartPtr<ImageBaseType> m_ImageBase;
 
+  /** The reference space - this is the space into which the image is sliced */
+  SmartPtr<ImageBaseType> m_ReferenceSpace;
+
   /** The current cursor position (slice index) in image dimensions */
   Vector3ui m_SliceIndex;
 
@@ -585,11 +609,18 @@ protected:
   typedef std::map<std::string, SmartPtr<itk::Object> > UserDataMapType;
   UserDataMapType m_UserDataMap;
 
+
   /**
    * Handle a change in the image pointer (i.e., a load operation on the image or 
-   * an initialization operation)
+   * an initialization operation). This function can take two optional parameters:
+   * the reference space and a transform. If these parameters are not NULL, then the
+   * wrapper represents a spatially transformed image. The slicers in the wrapper will
+   * slice not along the orthogonal directions in the image, but along directions in
+   * the reference space.
    */
-  virtual void UpdateImagePointer(ImageType *);
+  virtual void UpdateImagePointer(ImageType *image,
+                                  ImageBaseType *refSpace = NULL,
+                                  ITKTransformType *tran = NULL);
 
   /**
    * Update the image geometry (combining the information in the image and the
@@ -609,6 +640,9 @@ protected:
   /** Parent wrapper */
   ImageWrapperBase *m_ParentWrapper;
 
+
+  typedef itk::ResampleImageFilter<ImageType, ImageType, double, double> ResampleFilter;
+  SmartPtr<ResampleFilter> m_ResampleFilter[3];
 };
 
 #endif // __ImageWrapper_h_
diff --git a/Logic/ImageWrapper/ImageWrapperBase.h b/Logic/ImageWrapper/ImageWrapperBase.h
index e5284fe..b045ded 100644
--- a/Logic/ImageWrapper/ImageWrapperBase.h
+++ b/Logic/ImageWrapper/ImageWrapperBase.h
@@ -11,6 +11,8 @@ namespace itk {
   template <unsigned int VDim> class ImageBase;
   template <class TPixel, unsigned int VDim> class Image;
   template <class TPixel> class RGBAPixel;
+  template <class TOutputImage> class ImageSource;
+  template <class TScalar, unsigned int V1, unsigned int V2> class Transform;
 
   namespace Statistics {
     class DenseFrequencyContainer;
@@ -48,7 +50,7 @@ enum ScalarRepresentation
 
 
 /**
- \class ImageWrapper
+ \class ImageWrapperBase
  \brief Abstract parent class for all image wrappers
 
  This class is at the head of the ImageWrapper hierarchy. In fact, there are
@@ -65,15 +67,18 @@ class ImageWrapperBase : public itk::Object
 public:
 
   // Definition for the display slice type
-  typedef itk::RGBAPixel<unsigned char> DisplayPixelType;
-  typedef itk::Image<DisplayPixelType,2> DisplaySliceType;
-  typedef SmartPtr<DisplaySliceType> DisplaySlicePointer;
+  typedef itk::RGBAPixel<unsigned char>                       DisplayPixelType;
+  typedef itk::Image<DisplayPixelType,2>                      DisplaySliceType;
+  typedef SmartPtr<DisplaySliceType>                       DisplaySlicePointer;
 
   // Image base
   typedef itk::ImageBase<3> ImageBaseType;
 
   // Transform matrices
-  typedef vnl_matrix_fixed<double, 4, 4> TransformType;
+  typedef vnl_matrix_fixed<double, 4, 4>                         TransformType;
+
+  // ITK's coordinate transform (rigid, affine, etc)
+  typedef itk::Transform<double, 3, 3>                        ITKTransformType;
 
   /**
    * The image wrapper fires a WrapperMetadataChangeEvent when properties
@@ -389,6 +394,13 @@ public:
    */
   virtual itk::Object* GetUserData(const std::string &role) const = 0;
 
+  //
+
+  /**
+   * Set an ITK transform between this image and a reference image.
+   */
+  virtual void SetITKTransform(ImageBaseType *referenceSpace, ITKTransformType *transform) = 0;
+
 protected:
 
 };
@@ -400,6 +412,8 @@ public:
   // A common image format to which the contents of the scalar image wrapper
   // may be cast for downstream processing
   typedef itk::Image<GreyType, 3>                      CommonFormatImageType;
+  typedef itk::Image<float, 3>                                FloatImageType;
+  typedef itk::ImageSource<FloatImageType>                  FloatImageSource;
 
   /**
    * An enum of export channel types. Export channels are used to present the
@@ -466,6 +480,25 @@ public:
       ExportChannel channel = WHOLE_IMAGE) = 0;
 
   /**
+    Cast the internally stored image to a floating point image. The returned
+    image is connected to the internally stored image by a mini-pipeline that
+    may include a cast filter or a scale/shift filter, depending on the internal
+    format of the image and the internal-to-native intensity mapping. This mini
+    pipeline is not memory managed by the wrapper, and as soon as the returned
+    image smartpointer goes out of scope, the mini-pipeline is deallocated.
+
+    The method is intended for use with external pipelines that don't know what
+    the internal data representation is for the image. There is a cost with using
+    this method in terms of memory, so the recommended use is in conjunction with
+    streaming filters, so that the cast mini-pipeline does not allocate the whole
+    floating point image all at once.
+
+    The mini-pipeline should not be kept around in memory after it's used. This would
+    result in unnecessary duplication of memory.
+    */
+  virtual SmartPtr<FloatImageSource> CreateCastToFloatPipeline() const = 0;
+
+  /**
    * Get the intensity curve used to map raw intensities to color map inputs.
    * The intensity curve is only used by some wrappers (anatomic, speed) and
    * so this method may return NULL for some layers.
diff --git a/Logic/ImageWrapper/NativeIntensityMappingPolicy.h b/Logic/ImageWrapper/NativeIntensityMappingPolicy.h
index 784fd0f..084bc22 100644
--- a/Logic/ImageWrapper/NativeIntensityMappingPolicy.h
+++ b/Logic/ImageWrapper/NativeIntensityMappingPolicy.h
@@ -22,6 +22,8 @@ public:
 class LinearInternalToNativeIntensityMapping : public AbstractNativeIntensityMapping
 {
 public:
+  typedef LinearInternalToNativeIntensityMapping Self;
+
   double operator() (double g) const
     { return MapInternalToNative(g); }
 
@@ -40,6 +42,9 @@ public:
   LinearInternalToNativeIntensityMapping() : scale(1.0), shift(0.0) {}
   LinearInternalToNativeIntensityMapping(double a, double b) : scale(a), shift(b) {}
 
+  bool operator != (const Self &other) const
+    { return scale != other.scale || shift != other.shift; }
+
 protected:
   double scale;
   double shift;
@@ -49,6 +54,9 @@ class SpeedImageInternalToNativeIntensityMapping
     : public LinearInternalToNativeIntensityMapping
 {
 public:
+
+  typedef SpeedImageInternalToNativeIntensityMapping Self;
+
   SpeedImageInternalToNativeIntensityMapping()
   {
     // Map the range of short to -1 : 1
@@ -56,11 +64,17 @@ public:
     this->scale = 2.0 / ((int) smax - (int) smin);
     this->shift = 0.0;
   }
+
+  bool operator != (const Self &other) const { return false; }
+
 };
 
 class IdentityInternalToNativeIntensityMapping : public AbstractNativeIntensityMapping
 {
 public:
+
+  typedef IdentityInternalToNativeIntensityMapping Self;
+
   double operator() (double g) const
     { return g; }
 
@@ -76,6 +90,7 @@ public:
   virtual double GetScale() const { return 1; }
   virtual double GetShift() const { return 0; }
 
+  bool operator != (const Self &other) const { return false; }
 };
 
 
diff --git a/Logic/ImageWrapper/ScalarImageWrapper.cxx b/Logic/ImageWrapper/ScalarImageWrapper.cxx
index 8c7d814..6ac44ff 100644
--- a/Logic/ImageWrapper/ScalarImageWrapper.cxx
+++ b/Logic/ImageWrapper/ScalarImageWrapper.cxx
@@ -33,8 +33,8 @@
 #include "SNAPSegmentationROISettings.h"
 #include "itkCommand.h"
 #include "itkMinimumMaximumImageFilter.h"
-#include "itkGradientMagnitudeImageFilter.h"
 #include "itkVectorImageToImageAdaptor.h"
+#include "itkCastImageFilter.h"
 #include "IRISException.h"
 #include "VectorImageWrapper.h"
 #include "ScalarImageHistogram.h"
@@ -51,19 +51,6 @@ ScalarImageWrapper<TTraits,TBase>
   m_MinMaxFilter = MinMaxFilter::New();
   m_HistogramFilter = HistogramFilterType::New();
 
-  m_GradientMagnitudeFilter = GradMagFilter::New();
-  m_GradientMagnitudeFilter->ReleaseDataFlagOn();
-
-  // TODO: This filter is a huge waste of memory because it computes the
-  // gradient of the image just to obtain a maximum value. Not only that,
-  // the filter is applied to the common representation (float) image, so
-  // it requires another intermediate volume. The right thing to do would
-  // be to implement a filter that computes the maximum possible gradient
-  // magnitude of the image using a streaming implementation, and without
-  // having to cast to float.
-  m_GradientMagnitudeMaximumFilter = GradMagMaxFilter::New();
-  m_GradientMagnitudeMaximumFilter->SetInput(m_GradientMagnitudeFilter->GetOutput());
-
   // Set up VTK export pipeline
   this->SetupVTKImportExport();
 }
@@ -104,10 +91,10 @@ ScalarImageWrapper<TTraits,TBase>
 template<class TTraits, class TBase>
 void 
 ScalarImageWrapper<TTraits,TBase>
-::UpdateImagePointer(ImageType *newImage) 
+::UpdateImagePointer(ImageType *newImage, ImageBaseType *referenceSpace, ITKTransformType *transform)
 {
   // Call the parent
-  Superclass::UpdateImagePointer(newImage);
+  Superclass::UpdateImagePointer(newImage, referenceSpace, transform);
 
   // Update the max-min pipeline once we have one setup
   m_MinMaxFilter->SetInput(newImage);
@@ -123,12 +110,7 @@ ScalarImageWrapper<TTraits,TBase>
   // Update the common representation policy
   m_CommonRepresentationPolicy.UpdateInputImage(newImage);
 
-  // Also update the grad max range pipeline
-  CommonFormatImageType *imgCommon =
-      m_CommonRepresentationPolicy.GetOutput(ScalarImageWrapperBase::WHOLE_IMAGE);
-
-  m_GradientMagnitudeFilter->SetInput(imgCommon);
-
+  // Update the VTK export pipeline
   m_VTKExporter->SetInput(newImage);
 }
 
@@ -179,8 +161,13 @@ double
 ScalarImageWrapper<TTraits,TBase>
 ::GetImageGradientMagnitudeUpperLimit()
 {
-  m_GradientMagnitudeMaximumFilter->Update();
-  return m_GradientMagnitudeMaximumFilter->GetMaximum();
+  // Paul - 12/1/2014: I have modified this code to not compute the gradient magnitude
+  // on the whole image, but instead, to compute just the difference between the max and
+  // min values. I think this is much more efficient, and this removes some problems with
+  // wrappers that wrap around ImageAdapter objects.
+  //
+  // I hope this does not cause too much trouble...
+  return m_MinMaxFilter->GetMaximum() - m_MinMaxFilter->GetMinimum();
 }
 
 template<class TTraits, class TBase>
@@ -194,6 +181,24 @@ ScalarImageWrapper<TTraits,TBase>
 
 
 template<class TTraits, class TBase>
+SmartPtr<typename ScalarImageWrapper<TTraits, TBase>::FloatImageSource>
+ScalarImageWrapper<TTraits, TBase>::CreateCastToFloatPipeline() const
+{
+  // The kind of mini-pipeline that is created here depends on whether the
+  // internal image is a floating point image or not, and whether the native
+  // to intensity mapping is identity or not. We use template specialization to
+  // select the right behavior
+  typedef itk::UnaryFunctorImageFilter<ImageType, FloatImageType, NativeIntensityMapping> FilterType;
+  SmartPtr<FilterType> filter = FilterType::New();
+  filter->SetInput(this->m_Image);
+  filter->SetFunctor(this->m_NativeMapping);
+
+  SmartPtr<FloatImageSource> output = filter.GetPointer();
+  return output;
+}
+
+
+template<class TTraits, class TBase>
 double 
 ScalarImageWrapper<TTraits,TBase>
 ::GetImageScaleFactor()
@@ -245,9 +250,18 @@ ScalarImageWrapper<TTraits,TBase>
   Vector3ui idxDisp =
       this->GetImageToDisplayTransform(0).TransformVoxelIndex(this->GetSliceIndex());
 
+  DisplaySliceType *slice = this->GetDisplaySlice(0);
+  ImageType *source = this->m_Slicer[0]->GetPreviewInput();
+
+  itk::ImageRegion<3> rgnSource;
+  if(source)
+    {
+    rgnSource = source->GetBufferedRegion();
+    }
+
   // Get the RGB value
   typename DisplaySliceType::IndexType idx2D = {{idxDisp[0], idxDisp[1]}};
-  out_appearance = this->GetDisplaySlice(0)->GetPixel(idx2D);
+  out_appearance = slice->GetPixel(idx2D);
 
   // Get the numerical value
   PixelType val_raw = this->GetSlicer(0)->GetOutput()->GetPixel(idx2D);
diff --git a/Logic/ImageWrapper/ScalarImageWrapper.h b/Logic/ImageWrapper/ScalarImageWrapper.h
index 944a434..cebe3b5 100644
--- a/Logic/ImageWrapper/ScalarImageWrapper.h
+++ b/Logic/ImageWrapper/ScalarImageWrapper.h
@@ -42,8 +42,8 @@
 template<class TIn> class ThreadedHistogramImageFilter;
 namespace itk {
   template<class TIn> class MinimumMaximumImageFilter;
-  template<class TIn, class TOut> class GradientMagnitudeImageFilter;
   template<class TInputImage> class VTKImageExport;
+  template<class TOut> class ImageSource;
 }
 
 class vtkImageImport;
@@ -72,11 +72,16 @@ public:
 
 
   // Image Types
+  typedef typename Superclass::ImageBaseType                     ImageBaseType;
   typedef typename Superclass::ImageType                             ImageType;
   typedef typename Superclass::ImagePointer                       ImagePointer;
   typedef typename Superclass::PixelType                             PixelType;
   typedef typename Superclass::CommonFormatImageType     CommonFormatImageType;
 
+  // Floating point image type
+  typedef itk::Image<float, 3>                                  FloatImageType;
+  typedef itk::ImageSource<FloatImageType>                    FloatImageSource;
+
   // Slice image type
   typedef typename Superclass::SliceType                             SliceType;
   typedef typename Superclass::SlicePointer                       SlicePointer;
@@ -107,6 +112,8 @@ public:
 
   typedef typename Superclass::NativeIntensityMapping   NativeIntensityMapping;
 
+  typedef typename Superclass::ITKTransformType               ITKTransformType;
+
 
   virtual bool IsScalar() const { return true; }
 
@@ -210,6 +217,20 @@ public:
     */
   double GetImageGradientMagnitudeUpperLimitNative();
 
+
+  /**
+    This method creates an ITK mini-pipeline that can be used to cast the internal
+    image to a floating point image. The ownership of the mini-pipeline is passed
+    to the caller of this method. This method should be used with caution, since
+    there is potential to create duplicates of the internally stored image without
+    need. The best practice is to use this method with filters that only access a
+    portion of the casted image at a time, such as streaming filters.
+
+    When you call Update() on the returned mini-pipeline, the data will be cast to
+    floating point, and if necessary, converted to the native intensity range.
+    */
+  SmartPtr<FloatImageSource> CreateCastToFloatPipeline() const;
+
   /**
    * Get an image cast to a common representation.
    * @see ScalarImageWrapperBase::GetCommonFormatImage()
@@ -260,17 +281,6 @@ protected:
   typedef typename TTraits::CommonRepresentationPolicy CommonRepresentationPolicy;
   CommonRepresentationPolicy m_CommonRepresentationPolicy;
 
-  /**
-    A mini-pipeline to compute the maximum value of the gradient of
-    the input image on demand.
-    */
-  typedef itk::Image<float ,3> FloatImageType;
-  typedef itk::GradientMagnitudeImageFilter<CommonFormatImageType, FloatImageType> GradMagFilter;
-  typedef itk::MinimumMaximumImageFilter<FloatImageType> GradMagMaxFilter;
-
-  SmartPtr<GradMagFilter> m_GradientMagnitudeFilter;
-  SmartPtr<GradMagMaxFilter> m_GradientMagnitudeMaximumFilter;
-
   /** The intensity scaling factor */
   double m_ImageScaleFactor;
   
@@ -284,7 +294,9 @@ protected:
    * Handle a change in the image pointer (i.e., a load operation on the image or 
    * an initialization operation)
    */
-  virtual void UpdateImagePointer(ImageType *);
+  virtual void UpdateImagePointer(ImageType *image,
+                                  ImageBaseType *refSpace = NULL,
+                                  ITKTransformType *tran = NULL);
 
 
   typedef itk::VTKImageExport<ImageType> VTKExporter;
diff --git a/Logic/ImageWrapper/VectorImageWrapper.cxx b/Logic/ImageWrapper/VectorImageWrapper.cxx
index 40ec44b..90a4c61 100644
--- a/Logic/ImageWrapper/VectorImageWrapper.cxx
+++ b/Logic/ImageWrapper/VectorImageWrapper.cxx
@@ -195,7 +195,7 @@ template <class TTraits, class TBase>
 template <class TFunctor>
 SmartPtr<ScalarImageWrapperBase>
 VectorImageWrapper<TTraits,TBase>
-::CreateDerivedWrapper(ImageType *image)
+::CreateDerivedWrapper(ImageType *image, ImageBaseType *refSpace, ITKTransformType *transform)
 {
   typedef VectorDerivedQuantityImageWrapperTraits<TFunctor> WrapperTraits;
   typedef typename WrapperTraits::WrapperType DerivedWrapper;
@@ -205,7 +205,7 @@ VectorImageWrapper<TTraits,TBase>
   adaptor->SetImage(image);
 
   SmartPtr<DerivedWrapper> wrapper = DerivedWrapper::New();
-  wrapper->InitializeToWrapper(this, adaptor);
+  wrapper->InitializeToWrapper(this, adaptor, refSpace, transform);
 
   // Assign a parent wrapper to the derived wrapper
   wrapper->SetParentWrapper(this);
@@ -222,7 +222,7 @@ VectorImageWrapper<TTraits,TBase>
 template <class TTraits, class TBase>
 void
 VectorImageWrapper<TTraits,TBase>
-::UpdateImagePointer(ImageType *newImage)
+::UpdateImagePointer(ImageType *newImage, ImageBaseType *referenceSpace, ITKTransformType *transform)
 {
   // Create the component wrappers before calling the parent's method.
   int nc = newImage->GetNumberOfComponentsPerPixel();
@@ -241,7 +241,7 @@ VectorImageWrapper<TTraits,TBase>
 
     // Create a wrapper for this image and assign the component image
     SmartPtr<ComponentWrapperType> cw = ComponentWrapperType::New();
-    cw->InitializeToWrapper(this, comp);
+    cw->InitializeToWrapper(this, comp, referenceSpace, transform);
 
     // Assign a parent wrapper to the derived wrapper
     cw->SetParentWrapper(this);
@@ -255,13 +255,13 @@ VectorImageWrapper<TTraits,TBase>
     }
 
   m_ScalarReps[std::make_pair(SCALAR_REP_MAGNITUDE, 0)]
-      = this->template CreateDerivedWrapper<MagnitudeFunctor>(newImage);
+      = this->template CreateDerivedWrapper<MagnitudeFunctor>(newImage, referenceSpace, transform);
 
   m_ScalarReps[std::make_pair(SCALAR_REP_MAX, 0)]
-      = this->template CreateDerivedWrapper<MaxFunctor>(newImage);
+      = this->template CreateDerivedWrapper<MaxFunctor>(newImage, referenceSpace, transform);
 
   m_ScalarReps[std::make_pair(SCALAR_REP_AVERAGE, 0)]
-      = this->template CreateDerivedWrapper<MeanFunctor>(newImage);
+      = this->template CreateDerivedWrapper<MeanFunctor>(newImage, referenceSpace, transform);
 
   // Create a flat representation of the image
   m_FlatImage = FlatImageType::New();
@@ -309,7 +309,7 @@ VectorImageWrapper<TTraits,TBase>
   ColorMap *cm = cref->GetDisplayMapping()->GetColorMap(); */
 
   // Call the parent's method = this will initialize the display mapping
-  Superclass::UpdateImagePointer(newImage);
+  Superclass::UpdateImagePointer(newImage, referenceSpace, transform);
 
 }
 
diff --git a/Logic/ImageWrapper/VectorImageWrapper.h b/Logic/ImageWrapper/VectorImageWrapper.h
index 8599eaa..f940da6 100644
--- a/Logic/ImageWrapper/VectorImageWrapper.h
+++ b/Logic/ImageWrapper/VectorImageWrapper.h
@@ -52,6 +52,7 @@ public:
   itkNewMacro(Self)
 
   // Image Types
+  typedef typename Superclass::ImageBaseType                     ImageBaseType;
   typedef typename Superclass::ImageType                             ImageType;
   typedef typename Superclass::ImagePointer                       ImagePointer;
 
@@ -83,6 +84,8 @@ public:
   // Pipeline objects wrapped around values
   typedef typename Superclass::ComponentTypeObject         ComponentTypeObject;
 
+  typedef typename Superclass::ITKTransformType               ITKTransformType;
+
   virtual bool IsScalar() const { return false; }
 
   /**
@@ -233,14 +236,17 @@ protected:
    */
   VectorImageWrapper(const Self &copy) : Superclass(copy) {}
 
-  virtual void UpdateImagePointer(ImageType *newImage);
+  virtual void UpdateImagePointer(ImageType *image,
+                                  ImageBaseType *refSpace = NULL,
+                                  ITKTransformType *tran = NULL);
 
   /** Destructor */
   virtual ~VectorImageWrapper();
 
   /** Create a derived wrapper of a certain type */
   template <class TFunctor>
-  SmartPtr<ScalarImageWrapperBase> CreateDerivedWrapper(ImageType *image);
+  SmartPtr<ScalarImageWrapperBase> CreateDerivedWrapper(
+      ImageType *image, ImageBaseType *refSpace, ITKTransformType *transform);
 
   template <class TFunctor>
   void SetNativeMappingInDerivedWrapper(
diff --git a/Logic/Preprocessing/EdgePreprocessingImageFilter.h b/Logic/Preprocessing/EdgePreprocessingImageFilter.h
index e04117c..dd1a652 100644
--- a/Logic/Preprocessing/EdgePreprocessingImageFilter.h
+++ b/Logic/Preprocessing/EdgePreprocessingImageFilter.h
@@ -193,8 +193,8 @@ private:
   typedef itk::GPUDiscreteGaussianImageFilter<GPUInternalImageType,
                                               GPUInternalImageType>
                                                                  GPUBlurFilter;
-#endif
-
+#endif
+
   typedef itk::GradientMagnitudeImageFilter<InternalImageType,
                                             InternalImageType>   GradMagFilter;
 
@@ -210,8 +210,8 @@ private:
 #ifdef SNAP_USE_GPU
   SmartPtr<GPUImageSource> m_GPUImageSource;
   SmartPtr<GPUBlurFilter>  m_GPUBlurFilter;
-#endif
-
+#endif
+
 };
 
 #ifndef ITK_MANUAL_INSTANTIATION
diff --git a/Logic/Preprocessing/ImageCollectionToImageFilter.h b/Logic/Preprocessing/ImageCollectionToImageFilter.h
index 8c1dcfe..5c5c618 100644
--- a/Logic/Preprocessing/ImageCollectionToImageFilter.h
+++ b/Logic/Preprocessing/ImageCollectionToImageFilter.h
@@ -39,6 +39,8 @@
 #include <itkImageToImageFilter.h>
 
 #include <itkImageRegionIteratorWithIndex.h>
+#include <itkConstNeighborhoodIterator.h>
+
 
 /**
  * This class is derived from the itk::iterator hierarchy and used to gain
@@ -140,9 +142,15 @@ public:
   /** Add an image that must be dynamically castable to either TImage or TVectorImage */
   void AddImage(itk::DataObject *image);
 
+  /** Optional neighborhood support (used by Value(comp, offset)) */
+  void SetRadius(const SizeType &size);
+
   /** Get the number of components across the collection */
   itkGetMacro(TotalComponents, unsigned int)
 
+  /** Get the optional neighborhood size */
+  itkGetMacro(NeighborhoodSize, int)
+
   /** Standard iterator operations */
   bool IsAtEnd() const { return m_InternalIter.IsAtEnd(); }
   bool IsAtBegin() const { return m_InternalIter.IsAtBegin(); }
@@ -159,6 +167,15 @@ public:
     return *(dataPtr);
   }
 
+  /** Get a pointer to a component in the neighborhood of pointed voxel (no bounds check) */
+  InternalPixelType &NeighborValue(unsigned int comp, unsigned int nbr_idx)
+  {
+    OffsetValueType offset = m_InternalIter.GetOffset();
+    offset += m_NeighborhoodOffsetTable[nbr_idx];
+    InternalPixelType *dataPtr = m_Start[comp] + offset * m_OffsetScaling[comp];
+    return *(dataPtr);
+  }
+
 protected:
 
   // Collection of scalar images
@@ -191,6 +208,18 @@ protected:
 
   // This method initializes all the iteration mechanics
   void ComputeMechanics(ImageBaseType *image);
+
+  // Compute neighborhood offsets
+  void ComputeNeighborhoodOffsets();
+
+  // Radius for the optional neighborhood support
+  SizeType m_Radius;
+
+  // Offset table for optional neighborhood support
+  std::vector<int> m_NeighborhoodOffsetTable;
+
+  // Size of the neighborhood
+  int m_NeighborhoodSize;
 };
 
 
@@ -200,6 +229,8 @@ ImageCollectionConstRegionIteratorWithIndex<TImage, TVectorImage>
 {
   m_Region = region;
   m_TotalComponents = 0;
+  m_Radius.Fill(0);
+  m_NeighborhoodSize = 1;
 }
 
 template <class TImage, class TVectorImage>
@@ -265,6 +296,21 @@ ImageCollectionConstRegionIteratorWithIndex<TImage, TVectorImage>
             "Wrong input type to ImageCollectionConstRegionIteratorWithIndex");
       }
     }
+
+
+}
+
+template <class TImage, class TVectorImage>
+void
+ImageCollectionConstRegionIteratorWithIndex<TImage, TVectorImage>
+::SetRadius(const SizeType &radius)
+{
+  // Set the radius of the neighborhood
+  m_Radius = radius;
+
+  // Compute offsets if an image has been set
+  if(this->GetTotalComponents() > 0)
+      this->ComputeNeighborhoodOffsets();
 }
 
 template <class TImage, class TVectorImage>
@@ -276,6 +322,31 @@ ImageCollectionConstRegionIteratorWithIndex<TImage, TVectorImage>
   m_DummyImage->SetRegions(image->GetBufferedRegion());
 
   m_InternalIter = InternalIteratorType(m_DummyImage, m_Region);
+
+  this->ComputeNeighborhoodOffsets();
+}
+
+
+template <class TImage, class TVectorImage>
+void
+ImageCollectionConstRegionIteratorWithIndex<TImage, TVectorImage>
+::ComputeNeighborhoodOffsets()
+{
+  typedef itk::ConstNeighborhoodIterator<ImageType> DummyIter;
+  DummyIter diter(m_Radius, m_DummyImage, m_DummyImage->GetBufferedRegion());
+
+  // Compute offsets in memory
+  m_NeighborhoodOffsetTable.resize(diter.Size(), 0);
+  for(int i = 0; i < diter.Size(); i++)
+    {
+    OffsetType offset = diter.GetOffset(i);
+    IndexType index;
+    for(int j = 0; j < TImage::ImageDimension; j++)
+      index[j] = offset[j];
+    m_NeighborhoodOffsetTable[i] = m_DummyImage->ComputeOffset(index);
+    }
+
+  m_NeighborhoodSize = diter.Size();
 }
 
 
diff --git a/Logic/Preprocessing/PreprocessingFilterConfigTraits.h b/Logic/Preprocessing/PreprocessingFilterConfigTraits.h
index ff7f2c7..c1600f6 100644
--- a/Logic/Preprocessing/PreprocessingFilterConfigTraits.h
+++ b/Logic/Preprocessing/PreprocessingFilterConfigTraits.h
@@ -50,6 +50,8 @@ class RandomForestClassifier;
 class SmoothBinaryThresholdFilterConfigTraits {
 public:
 
+  typedef SNAPImageData                                          InputDataType;
+
   typedef ScalarImageWrapperBase::CommonFormatImageType               GreyType;
   typedef SNAPImageData::SpeedImageType                              SpeedType;
   typedef SpeedImageWrapper                                  OutputWrapperType;
@@ -77,6 +79,8 @@ public:
 class EdgePreprocessingFilterConfigTraits {
 public:
 
+  typedef SNAPImageData                                          InputDataType;
+
   typedef ScalarImageWrapperBase::CommonFormatImageType               GreyType;
   typedef SNAPImageData::SpeedImageType                              SpeedType;
   typedef SpeedImageWrapper                                  OutputWrapperType;
@@ -101,6 +105,8 @@ public:
 class GMMPreprocessingFilterConfigTraits {
 public:
 
+  typedef SNAPImageData                                          InputDataType;
+
   typedef AnatomicScalarImageWrapper::ImageType                 GreyScalarType;
   typedef AnatomicImageWrapper::ImageType                       GreyVectorType;
   typedef SNAPImageData::SpeedImageType                              SpeedType;
@@ -129,6 +135,8 @@ public:
 class RFPreprocessingFilterConfigTraits {
 public:
 
+  typedef SNAPImageData                                          InputDataType;
+
   typedef AnatomicScalarImageWrapper::ImageType                 GreyScalarType;
   typedef AnatomicImageWrapper::ImageType                       GreyVectorType;
   typedef SNAPImageData::SpeedImageType                              SpeedType;
diff --git a/Logic/Preprocessing/RandomForest/RFClassificationEngine.cxx b/Logic/Preprocessing/RandomForest/RFClassificationEngine.cxx
index 4d4d116..8754fa5 100644
--- a/Logic/Preprocessing/RandomForest/RFClassificationEngine.cxx
+++ b/Logic/Preprocessing/RandomForest/RFClassificationEngine.cxx
@@ -19,6 +19,9 @@ RFClassificationEngine::RFClassificationEngine()
   m_Sample = NULL;
   m_Classifier = RandomForestClassifier::New();
   m_ForestSize = 50;
+  m_TreeDepth = 30;
+  m_PatchRadius.Fill(0);
+  m_UseCoordinateFeatures = false;
 }
 
 RFClassificationEngine::~RFClassificationEngine()
@@ -48,6 +51,10 @@ void RFClassificationEngine:: TrainClassifier()
 {
   assert(m_DataSource && m_DataSource->IsMainLoaded());
 
+  typedef ImageCollectionConstRegionIteratorWithIndex<
+      AnatomicScalarImageWrapper::ImageType,
+      AnatomicImageWrapper::ImageType> CollectionIter;
+
   // TODO: in the future, we should only recompute the sample when we know
   // that the data has changed. However, currently, we are just going to
   // compute a new sample every time
@@ -59,21 +66,22 @@ void RFClassificationEngine:: TrainClassifier()
   // Get the segmentation image - which determines the samples
   LabelImageWrapper *wrpSeg = m_DataSource->GetSegmentation();
   LabelImageWrapper::ImagePointer imgSeg = wrpSeg->GetImage();
-  typedef itk::ImageRegionConstIterator<LabelImageWrapper::ImageType> LabelIter;
+  typedef itk::ImageRegionConstIteratorWithIndex<LabelImageWrapper::ImageType> LabelIter;
+
+  // Shrink the buffered region by radius because we can't handle BCs
+  itk::ImageRegion<3> reg = imgSeg->GetBufferedRegion();
+  reg.ShrinkByRadius(m_PatchRadius);
 
   // We need to iterate throught the label image once to determine the
   // number of samples to allocate.
   unsigned long nSamples = 0;
-  for(LabelIter lit(imgSeg, imgSeg->GetBufferedRegion()); !lit.IsAtEnd(); ++lit)
+  for(LabelIter lit(imgSeg, reg); !lit.IsAtEnd(); ++lit)
     if(lit.Value())
       nSamples++;
 
   // Create an iterator for going over all the anatomical image data
-  typedef ImageCollectionConstRegionIteratorWithIndex<
-      AnatomicScalarImageWrapper::ImageType,
-      AnatomicImageWrapper::ImageType> CollectionIter;
-
-  CollectionIter cit(imgSeg->GetBufferedRegion());
+  CollectionIter cit(reg);
+  cit.SetRadius(m_PatchRadius);
 
   // Add all the anatomical images to this iterator
   for(LayerIterator it = m_DataSource->GetLayers(MAIN_ROLE | OVERLAY_ROLE);
@@ -84,21 +92,34 @@ void RFClassificationEngine:: TrainClassifier()
 
   // Get the number of components
   int nComp = cit.GetTotalComponents();
+  int nPatch = cit.GetNeighborhoodSize();
+  int nColumns = nComp * nPatch;
+
+  // Are we using coordinate informtion
+  if(m_UseCoordinateFeatures)
+    nColumns += 3;
 
   // Create a new sample
-  m_Sample = new SampleType(nSamples, nComp);
+  m_Sample = new SampleType(nSamples, nColumns);
 
   // Now fill out the samples
   int iSample = 0;
-  for(LabelIter lit(imgSeg, imgSeg->GetBufferedRegion()); !lit.IsAtEnd(); ++lit, ++cit)
+  for(LabelIter lit(imgSeg, reg); !lit.IsAtEnd(); ++lit, ++cit)
     {
     LabelType label = lit.Value();
     if(label)
       {
       // Fill in the data
       std::vector<GreyType> &column = m_Sample->data[iSample];
+      int k = 0;
       for(int i = 0; i < nComp; i++)
-        column[i] = cit.Value(i);
+        for(int j = 0; j < nPatch; j++)
+          column[k++] = cit.NeighborValue(i,j);
+
+      // Add the coordinate features if used
+      if(m_UseCoordinateFeatures)
+        for(int d = 0; d < 3; d++)
+          column[k++] = lit.GetIndex()[d];
 
       // Fill in the label
       m_Sample->label[iSample] = label;
@@ -121,7 +142,8 @@ void RFClassificationEngine:: TrainClassifier()
 
   // Set up the classifier parameters
   TrainingParameters params;
-  params.treeDepth = 10;
+  // TODO:
+  params.treeDepth = m_TreeDepth;
   params.treeNum = m_ForestSize;
   params.candidateNodeClassifierNum = 10;
   params.candidateClassifierThresholdNum = 10;
@@ -130,18 +152,33 @@ void RFClassificationEngine:: TrainClassifier()
   params.leafEntropy = 0.05;
   params.verbose = true;
 
+  // Cap the number of training voxels at some reasonable number
+  if(m_Sample->Size() > 10000)
+    params.subSamplePercent = 100 * 10000.0 / m_Sample->Size();
+  else
+    params.subSamplePercent = 0;
+
   // Create the classification engine
   typedef RandomForestClassifier::RFAxisClassifierType RFAxisClassifierType;
   typedef Classification<GreyType, LabelType, RFAxisClassifierType> ClassificationType;
   ClassificationType classification;
 
   // Before resetting the classifier, we want to retain whatever the
-  // foreground label was.
-  bool isOldForegroundLabelValid = m_Classifier->IsValidClassifier();
-  LabelType oldForegroundLabel = 0;
+  // weighting of the classes was
+  std::map<LabelType, double> old_label_weights;
+  if(m_Classifier->IsValidClassifier())
+    {
+    // Get the class weights
+    const RandomForestClassifier::WeightArray &class_weights = m_Classifier->GetClassWeights();
 
-  if(isOldForegroundLabelValid)
-    oldForegroundLabel = m_Classifier->GetForegroundClassLabel();
+    // Convert them to label weights (since class to label mapping may change)
+    for(RandomForestClassifier::MappingType::const_iterator it =
+        m_Classifier->m_ClassToLabelMapping.begin();
+        it != m_Classifier->m_ClassToLabelMapping.end(); ++it)
+      {
+      old_label_weights[it->second] = class_weights[it->first];
+      }
+    }
 
   // Prepare the classifier
   m_Classifier->Reset();
@@ -153,20 +190,38 @@ void RFClassificationEngine:: TrainClassifier()
         m_Classifier->m_ValidLabel,
         m_Classifier->m_ClassToLabelMapping);
 
-  // Assign the foreground index to zero (default)
-  m_Classifier->m_ForegroundClass = 0;
+  // Reset the class weights to the number of classes and assign default
+  int n_classes = m_Classifier->m_ClassToLabelMapping.size(), n_fore = 0, n_back = 0;
+  m_Classifier->m_ClassWeights.resize(n_classes, -1.0);
 
-  // Now maybe re-assign the old foreground label
-  if(isOldForegroundLabelValid)
+  // Apply the old weight assignments if possible. Keep track of the number of fore and back classes
+  for(RandomForestClassifier::MappingType::iterator it =
+      m_Classifier->m_ClassToLabelMapping.begin();
+      it != m_Classifier->m_ClassToLabelMapping.end(); ++it)
     {
-    for(RandomForestClassifier::MappingType::const_iterator it =
-        m_Classifier->m_ClassToLabelMapping.begin();
-        it != m_Classifier->m_ClassToLabelMapping.end(); ++it)
+    if(old_label_weights.find(it->second) != old_label_weights.end())
       {
-      if(it->second == oldForegroundLabel)
-        m_Classifier->m_ForegroundClass = it->first;
+      m_Classifier->m_ClassWeights[it->first] = old_label_weights[it->second];
       }
+    if(m_Classifier->m_ClassWeights[it->first] < 0.0)
+      n_back++;
+    else if(m_Classifier->m_ClassWeights[it->first] > 0.0)
+      n_fore++;
+    }
+
+  // Make sure that we have at least one foreground class and at least one background class
+  if(n_classes >= 2)
+    {
+    if(n_fore == 0)
+      m_Classifier->m_ClassWeights.front() = 1.0;
+    if(n_back == 0)
+      m_Classifier->m_ClassWeights.back() = -1.0;
     }
+
+  // Store the patch radius in the classifier - this remains fixed until
+  // training is repeated
+  m_Classifier->m_PatchRadius = m_PatchRadius;
+  m_Classifier->m_UseCoordinateFeatures = m_UseCoordinateFeatures;
 }
 
 void RFClassificationEngine::SetClassifier(RandomForestClassifier *rf)
diff --git a/Logic/Preprocessing/RandomForest/RFClassificationEngine.h b/Logic/Preprocessing/RandomForest/RFClassificationEngine.h
index 2ad5f4c..7e02439 100644
--- a/Logic/Preprocessing/RandomForest/RFClassificationEngine.h
+++ b/Logic/Preprocessing/RandomForest/RFClassificationEngine.h
@@ -3,6 +3,7 @@
 
 #include <itkObject.h>
 #include <itkObjectFactory.h>
+#include <itkSize.h>
 #include "SNAPCommon.h"
 #include "PropertyModel.h"
 
@@ -22,6 +23,9 @@ public:
   // Standard ITK class stuff
   irisITKObjectMacro(RFClassificationEngine, itk::Object)
 
+  // Patch radius type
+  typedef itk::Size<3> RadiusType;
+
   /** Set the data source for the classification */
   void SetDataSource(SNAPImageData *imageData);
 
@@ -35,10 +39,23 @@ public:
   void SetClassifier(RandomForestClassifier *rf);
 
   /** Access the trained classifier */
-  irisGetMacro(Classifier, RandomForestClassifier *)
+  itkGetMacro(Classifier, RandomForestClassifier *)
+
+  /** Size of the random forest (main parameter) */
+  itkGetMacro(ForestSize, int)
+  itkSetMacro(ForestSize, int)
 
   /** Size of the random forest (main parameter) */
-  irisGetSetMacro(ForestSize, int)
+  itkGetMacro(TreeDepth, int)
+  itkSetMacro(TreeDepth, int)
+
+  /** Patch radius for sampling features */
+  itkGetMacro(PatchRadius, const RadiusType &)
+  itkSetMacro(PatchRadius, RadiusType)
+
+  /** Whether coordinates of the voxels are used as features */
+  itkGetMacro(UseCoordinateFeatures, bool)
+  itkSetMacro(UseCoordinateFeatures, bool)
 
   /** Get the number of components passed to the classifier */
   int GetNumberOfComponents() const;
@@ -61,6 +78,15 @@ protected:
   // Number of trees
   int m_ForestSize;
 
+  // Number of trees
+  int m_TreeDepth;
+
+  // Patch radius
+  RadiusType m_PatchRadius;
+
+  // Are coordinates included as features
+  bool m_UseCoordinateFeatures;
+
   // Cached samples used to train the classifier
   typedef MLData<GreyType, LabelType> SampleType;
   SampleType *m_Sample;
diff --git a/Logic/Preprocessing/RandomForest/RandomForestClassifier.cxx b/Logic/Preprocessing/RandomForest/RandomForestClassifier.cxx
index 38cb7ee..89a3b83 100644
--- a/Logic/Preprocessing/RandomForest/RandomForestClassifier.cxx
+++ b/Logic/Preprocessing/RandomForest/RandomForestClassifier.cxx
@@ -8,40 +8,26 @@ void RandomForestClassifier::Reset()
 
   m_Forest = new RandomForestType(true);
   m_ClassToLabelMapping.clear();
-  m_ForegroundClass = 0;
+  m_BiasParameter = 0.5;
+  m_PatchRadius.Fill(0);
+  m_UseCoordinateFeatures = false;
+  m_ClassWeights.clear();
 }
 
-LabelType RandomForestClassifier::GetForegroundClassLabel() const
+void RandomForestClassifier::SetClassWeight(size_t class_id, double weight)
 {
-  MappingType::const_iterator it = m_ClassToLabelMapping.find(m_ForegroundClass);
-  if(it != m_ClassToLabelMapping.end())
-    return it->second;
-
-  // Default behavior - clear label
-  return 0;
-}
-
-void RandomForestClassifier::SetForegroundClassLabel(LabelType label)
-{
-  MappingType::const_iterator it = m_ClassToLabelMapping.begin();
-  for(; it != m_ClassToLabelMapping.end(); ++it)
-    {
-    if(it->second == label)
-      {
-      m_ForegroundClass = it->first;
-      return;
-      }
-    }
+  m_ClassWeights[class_id] = weight;
 }
 
 bool RandomForestClassifier::IsValidClassifier() const
 {
-  return m_ClassToLabelMapping.size() >= 2;
+  return m_ClassToLabelMapping.size() >= 2 && m_Forest->GetForestSize() > 0;
 }
 
 RandomForestClassifier::RandomForestClassifier()
 {
-  m_Forest = new RandomForestType(true);
+  m_Forest = NULL;
+  this->Reset();
 }
 
 RandomForestClassifier::~RandomForestClassifier()
diff --git a/Logic/Preprocessing/RandomForest/RandomForestClassifier.h b/Logic/Preprocessing/RandomForest/RandomForestClassifier.h
index 78ea4b1..a5c0b7f 100644
--- a/Logic/Preprocessing/RandomForest/RandomForestClassifier.h
+++ b/Logic/Preprocessing/RandomForest/RandomForestClassifier.h
@@ -3,6 +3,7 @@
 
 #include <itkDataObject.h>
 #include <itkObjectFactory.h>
+#include <itkSize.h>
 #include <SNAPCommon.h>
 #include <map>
 
@@ -25,6 +26,10 @@ public:
   typedef AxisAlignedClassifier<GreyType, LabelType> RFAxisClassifierType;
   typedef DecisionForest<RFHistogramType, RFAxisClassifierType, GreyType> RandomForestType;
   typedef std::map<size_t, LabelType> MappingType;
+  typedef itk::Size<3> SizeType;
+
+  // A list of weights for each class - used to construct speed image
+  typedef std::vector<double> WeightArray;
 
   // Reset the classifier
   void Reset();
@@ -35,14 +40,22 @@ public:
   // Get the random forest
   irisGetMacro(Forest, RandomForestType *)
 
-  // Get the foreground class
-  irisGetMacro(ForegroundClass, size_t)
+  // Get the patch radius
+  irisGetMacro(PatchRadius, const SizeType &)
+
+  /** Whether coordinates of the voxels are used as features */
+  itkGetMacro(UseCoordinateFeatures, bool)
+  itkSetMacro(UseCoordinateFeatures, bool)
 
-  // Get the label of the foreground class
-  LabelType GetForegroundClassLabel() const;
+  // Set the bias parameter (adjusts the mapping of FG probability to speed)
+  itkGetMacro(BiasParameter, double)
+  itkSetMacro(BiasParameter, double)
 
-  // Set the foreground class by label
-  void SetForegroundClassLabel(LabelType label);
+  // Get a reference to the weight array
+  irisGetMacro(ClassWeights, const WeightArray &)
+
+  // Set the weight for a class
+  void SetClassWeight(size_t class_id, double weight);
 
   // Test if the classifier is valid (has 2+ classes)
   bool IsValidClassifier() const;
@@ -61,15 +74,20 @@ protected:
   // Mapping of index to label (?)
   MappingType m_ClassToLabelMapping;
 
-  // The class that is currently active
-  size_t m_ForegroundClass;
+  // Weight of each class
+  WeightArray m_ClassWeights;
 
-  // Let the engine handle our data
-  friend class RFClassificationEngine;
+  // The patch radius
+  SizeType m_PatchRadius;
 
-  // TODO: make all that protected!
+  // Whether coordinate features are used
+  bool m_UseCoordinateFeatures;
 
+  // Bias parameter
+  double m_BiasParameter;
 
+  // Let the engine handle our data
+  friend class RFClassificationEngine;
 };
 
 #endif // RANDOMFORESTCLASSIFIER_H
diff --git a/Logic/Preprocessing/RandomForestClassifyImageFilter.txx b/Logic/Preprocessing/RandomForestClassifyImageFilter.txx
index 8a963ed..e828051 100644
--- a/Logic/Preprocessing/RandomForestClassifyImageFilter.txx
+++ b/Logic/Preprocessing/RandomForestClassifyImageFilter.txx
@@ -69,12 +69,16 @@ RandomForestClassifyImageFilter<TInputImage, TInputVectorImage, TOutputImage>
       {
       InputImageRegionType inputRegion;
       this->CallCopyOutputRegionToInputRegion( inputRegion, this->GetOutput()->GetRequestedRegion() );
+      inputRegion.PadByRadius(m_Classifier->GetPatchRadius());
+      inputRegion.Crop(input->GetLargestPossibleRegion());
       input->SetRequestedRegion(inputRegion);
       }
     else if(vecInput)
       {
       InputImageRegionType inputRegion;
       this->CallCopyOutputRegionToInputRegion( inputRegion, this->GetOutput()->GetRequestedRegion() );
+      inputRegion.PadByRadius(m_Classifier->GetPatchRadius());
+      inputRegion.Crop(vecInput->GetLargestPossibleRegion());
       vecInput->SetRequestedRegion(inputRegion);
       }
     }
@@ -97,33 +101,57 @@ RandomForestClassifyImageFilter<TInputImage, TInputVectorImage, TOutputImage>
 {
   assert(m_Classifier);
 
-  // Create an iterator for the output
   OutputImagePointer outputPtr = this->GetOutput(0);
-  typedef itk::ImageRegionIterator<TOutputImage> OutputIter;
-  OutputIter it_out(outputPtr, outputRegionForThread);
+
+  // Fill the output region with zeros
+  itk::ImageRegionIterator<OutputImageType> zit(outputPtr, outputRegionForThread);
+  for(; !zit.IsAtEnd(); ++zit)
+    zit.Set((OutputPixelType) 0);
+
+  // Adjust the output region so that we don't touch image boundaries.
+  OutputImageRegionType crop_region = outputPtr->GetLargestPossibleRegion();
+  crop_region.ShrinkByRadius(m_Classifier->GetPatchRadius());
+  OutputImageRegionType out_region = outputRegionForThread;
+  bool can_crop = out_region.Crop(crop_region);
+
+  if(!can_crop)
+    return;
+
+  // Create an iterator for the output
+  typedef itk::ImageRegionIteratorWithIndex<TOutputImage> OutputIter;
+  OutputIter it_out(outputPtr, out_region);
 
   // Create a collection iterator for the inputs
   typedef ImageCollectionConstRegionIteratorWithIndex<
       TInputImage, TInputVectorImage> CollectionIter;
 
   // Configure the input collection iterator
-  CollectionIter cit(outputRegionForThread);
+  CollectionIter cit(out_region);
   for( itk::InputDataObjectIterator it( this ); !it.IsAtEnd(); it++ )
     cit.AddImage(it.GetInput());
 
+  // TODO: This is hard-coded
+  cit.SetRadius(m_Classifier->GetPatchRadius());
+
   // Get the number of components
   int nComp = cit.GetTotalComponents();
+  int nPatch = cit.GetNeighborhoodSize();
+  int nColumns = nComp * nPatch;
+
+  // Are coordinate features used?
+  if(m_Classifier->GetUseCoordinateFeatures())
+    nColumns += 3;
 
   // Get the number of classes
   int nClass = m_Classifier->GetClassToLabelMapping().size();
 
-  // Get the current class
-  int activeClass = (int) m_Classifier->GetForegroundClass();
+  // Get the class weights (as they are assigned to foreground/background)
+  const RandomForestClassifier::WeightArray &class_weights = m_Classifier->GetClassWeights();
 
   // Create the MLdata representing each voxel (?)
   typedef Histogram<InputPixelType,LabelType> HistogramType;
   typedef MLData<InputPixelType,HistogramType *> TestingDataType;
-  TestingDataType testData(1, nComp);
+  TestingDataType testData(1, nColumns);
 
   // Get the number of trees
   int nTrees = m_Classifier->GetForest()->trees_.size();
@@ -143,28 +171,51 @@ RandomForestClassifyImageFilter<TInputImage, TInputVectorImage, TOutputImage>
   for(; !it_out.IsAtEnd(); ++it_out, ++cit)
     {
     // Assign the data to the testData vector
+    int k = 0;
     for(int i = 0; i < nComp; i++)
-      testData.data[0][i] = cit.Value(i);
+      for(int j = 0; j < nPatch; j++)
+        testData.data[0][k++] = cit.NeighborValue(i,j);
+
+    // Add the coordinate features
+    if(m_Classifier->GetUseCoordinateFeatures())
+      for(int d = 0; d < 3; d++)
+        testData.data[0][k++] = it_out.GetIndex()[d];
 
     // Perform classification on this data
     m_Classifier->GetForest()->ApplyFast(testData, testResult, vIndex, vResult);
 
-    // Add up the predictions made by each tree for each class
-    double p = 0;
+    // New code: compute output map with a bias parameter. The bias parameter q is such
+    // that p_fore = q maps to 0 speed value. For the time being we just shift the linear
+    // mapping from p_fore to speed and cap speed between -1 and 1
+
+    // First we compute p_fore - for some reason not all trees in the forest have probabilities
+    // summing up to one (some are zero), so we need to use division
+    double p_fore_total = 0, p_total = 0;
     for(int i = 0; i < testResult.Size(); i++)
       {
+      HistogramType *hist = testResult[i][0];
       for(int j = 0; j < nClass; j++)
         {
-        if(j == activeClass)
-          p += testResult[i][0]->prob_[j];
-        else
-          p -= testResult[i][0]->prob_[j];
+        double p = hist->prob_[j];
+        if(class_weights[j] > 0.0)
+          p_fore_total += p;
+        p_total += p;
         }
       }
-    p /= testResult.Size();
 
-    // Presumably, at this point p stores the (p_fore - p_back) value
-    it_out.Set((OutputPixelType)(p * 0x7fff));
+    // Set output only if the total probability is non-zero
+    if(p_total > 0)
+      {
+      double q = m_Classifier->GetBiasParameter();
+      double p_fore = p_fore_total / p_total;
+      double speed = 2 * (p_fore - q);
+      if(speed < -1.0)
+        speed = -1.0;
+      else if(speed > 1.0)
+        speed = 1.0;
+
+      it_out.Set((OutputPixelType)(speed * 0x7fff));
+      }
     }
 }
 
diff --git a/Logic/Preprocessing/SlicePreviewFilterWrapper.h b/Logic/Preprocessing/SlicePreviewFilterWrapper.h
index 0b6acf3..8538723 100644
--- a/Logic/Preprocessing/SlicePreviewFilterWrapper.h
+++ b/Logic/Preprocessing/SlicePreviewFilterWrapper.h
@@ -124,6 +124,8 @@ public:
   typedef typename FilterType::OutputImageType              OutputImageType;
   typedef typename OutputImageType::PixelType               OutputPixelType;
 
+  typedef typename TFilterConfigTraits::InputDataType         InputDataType;
+
   typedef typename TFilterConfigTraits::OutputWrapperType OutputWrapperType;
   typedef IRISSlicer<OutputImageType, itk::Image<OutputPixelType, 2> >
                                                                  SlicerType;
@@ -137,7 +139,7 @@ public:
   void SetPreviewMode(bool mode);
 
   /** Set the input image, etc */
-  void AttachInputs(SNAPImageData *sid);
+  void AttachInputs(InputDataType *sid);
 
   /** Set the output volume */
   void AttachOutputWrapper(OutputWrapperType *wrapper);
diff --git a/Logic/Preprocessing/SlicePreviewFilterWrapper.txx b/Logic/Preprocessing/SlicePreviewFilterWrapper.txx
index dfa8778..c7fe826 100644
--- a/Logic/Preprocessing/SlicePreviewFilterWrapper.txx
+++ b/Logic/Preprocessing/SlicePreviewFilterWrapper.txx
@@ -63,7 +63,7 @@ SlicePreviewFilterWrapper<TFilterConfigTraits>
 template <class TFilterConfigTraits>
 void
 SlicePreviewFilterWrapper<TFilterConfigTraits>
-::AttachInputs(SNAPImageData *sid)
+::AttachInputs(InputDataType *sid)
 {
   // Get the default scalar layer for the traits. If this is NULL, the method
   // does not expect an active layer to be specified (acts on all inputs)
diff --git a/Logic/Preprocessing/Texture/MomentTextures.cxx b/Logic/Preprocessing/Texture/MomentTextures.cxx
new file mode 100644
index 0000000..2ee8bfd
--- /dev/null
+++ b/Logic/Preprocessing/Texture/MomentTextures.cxx
@@ -0,0 +1,172 @@
+#include "MomentTextures.h"
+#include "itkImage.h"
+#include "itkVectorImage.h"
+#include "itkImageRegionIteratorWithIndex.h"
+#include "itkNeighborhoodIterator.h"
+
+#define MIN(a,b) (((a)<(b))?(a):(b))
+#define MAX(a,b) (((a)>(b))?(a):(b))
+
+const int MAX_VAL=100000;
+
+namespace bilwaj {
+
+template <class TInputImage, class TOutputImage>
+void
+MomentTextureFilter<TInputImage, TOutputImage>
+::ThreadedGenerateData(const RegionType & outputRegionForThread,
+                       itk::ThreadIdType threadId)
+{
+  // Iterator for the output region
+  typedef itk::ImageRegionIteratorWithIndex<OutputImageType> OutputIteratorType;
+  OutputIteratorType TexIt(this->GetOutput(), outputRegionForThread);
+
+  // Neighborhood iterator for the input region
+  typedef itk::ConstNeighborhoodIterator<InputImageType> NeighborhoodIterator;
+  NeighborhoodIterator InpIt(m_Radius,this->GetInput(), outputRegionForThread);
+
+  // Accumulator array
+  vnl_vector<float> accumX(m_HighestDegree);
+  OutputPixelType out_pix(m_HighestDegree);
+
+  for( TexIt.GoToBegin(); !TexIt.IsAtEnd(); ++TexIt, ++InpIt)
+    {
+    // On the first pass through the neighborhood compute the mean intensity and
+    // the intensity range in the neighborhood
+    float accum=0.0;
+    float min=0; //Store minimum voxel intensity value
+    float max=0; //Store maximum voxel intensity value
+
+    for(int j=0;j<InpIt.Size();j++)
+      {
+      InputPixelType pix = InpIt.GetPixel(j);
+      accum += pix;
+      min=MIN(min, pix);
+      max=MAX(max, pix);
+      }
+
+    float range = max-min;
+    float mean = accum / InpIt.Size();
+
+    // On the second pass, compute the moments
+    accumX.fill(0.0f);
+    for(int j=0;j<InpIt.Size();j++)
+      {
+      InputPixelType pix = InpIt.GetPixel(j);
+      float norm_val = ((pix - mean) / range), norm_val_k = norm_val;
+      accumX[0] += norm_val;
+      for(int k = 1; k < m_HighestDegree; k++)
+        {
+        norm_val_k *= norm_val;
+        accumX[k] += norm_val_k;
+        }
+      }
+
+    // Scale the moments by neighborhood size
+    accumX /= InpIt.Size();
+
+    // The first moment should just be the mean
+    accumX[0] = mean / range;
+
+    // Assign to the output voxel
+    for(int k = 0; k < m_HighestDegree; k++)
+      {
+      out_pix[k] = static_cast<OutputComponentType>(1000 * accumX[k]);
+      }
+
+    // Assign to the output voxel
+    TexIt.Set(out_pix);
+    }
+}
+
+template <class TInputImage, class TOutputImage>
+void
+MomentTextureFilter<TInputImage, TOutputImage>
+::UpdateOutputInformation()
+{
+  Superclass::UpdateOutputInformation();
+  this->GetOutput()->SetNumberOfComponentsPerPixel(m_HighestDegree);
+}
+
+template class MomentTextureFilter<itk::Image<short, 3>, itk::VectorImage<short, 3> >;
+
+/*
+//Returns the estimated moment around the mean associated of the degree(th) order
+//TO DO Ext defaults to 1; Ideally should be part of moments class
+void MomentTexture(SmartPtr<ImageType> &Inp, SmartPtr<ImageType> &MomentTexture, int degree, int Ext)
+{
+  IteratorType TexIt(MomentTexture,MomentTexture->GetBufferedRegion());
+  typedef itk::NeighborhoodIterator<ImageType> NeighborhoodIterator;
+  NeighborhoodIterator::RadiusType radius;
+  for(int i=0;i<ImageType::ImageDimension;i++)
+    {radius[i]=1;}
+  NeighborhoodIterator InpIt(radius,Inp,Inp->GetBufferedRegion());
+  TexIt.GoToBegin();
+  while(!TexIt.IsAtEnd())
+    {
+    float accum=0.0;
+    float min=0; //Store minimum voxel intensity value
+    float max=0; //Store maximum voxel intensity value
+
+    //first compute the mean
+    //TO DO use mean texture function to not recompute the mean every time
+    for(int j=0;j<InpIt.Size();j++)
+      {
+      accum=accum+InpIt.GetPixel(j);
+      min=MIN(min,InpIt.GetPixel(j));
+      max=MAX(max,InpIt.GetPixel(j));
+      }
+    float range=max-min;
+    float mean=accum/InpIt.Size();
+    double accumX=0.0;
+    for(int j=0;j<InpIt.Size();j++)
+      {
+      //Modified expression for moments to keep them range bound and manageable
+      accumX=accumX+std::pow((InpIt.GetPixel(j)-mean)/range,degree);
+      }
+    //100 is usedas a multiplier to keep images produced to be visualized
+    TexIt.Set((datatype)(1000*accumX/InpIt.Size()));
+    ++TexIt;
+    ++InpIt;
+    }
+  std::cout<<"Traversing done"<<std::endl;
+}
+*/
+
+} // namespace
+
+
+/*
+int main(int argc, char *argv[])
+{
+  ReaderType::Pointer input = ReaderType::New();
+  //Input file
+  input->SetFileName("1.nii");
+  input->Update();
+
+  ImageType::Pointer Inp=ImageType::New();
+  Inp=input->GetOutput();
+
+  ImageType::Pointer Tex = ImageType::New();;
+  Tex->CopyInformation(Inp);
+  Tex->SetRequestedRegion( Inp->GetRequestedRegion() );
+  Tex->SetBufferedRegion( Inp->GetBufferedRegion() );
+  Tex->Allocate();
+  Tex->FillBuffer(0);
+
+
+  //Second moment neighborhood radius of 3
+  MomentTexture(Inp,Tex,2,3);
+  //The function is generic and multiple runs ,ay be used to create feature vectors as desired Inp and Tex are image types
+
+
+  WriterType::Pointer output = WriterType::New();
+  //Output file
+  output->SetFileName("out.nii");
+  output->SetInput(Tex);
+  output->Update();
+
+  //std::cout<<max_val<<std::endl;
+  return EXIT_SUCCESS;
+}
+*/
diff --git a/Logic/Preprocessing/Texture/MomentTextures.h b/Logic/Preprocessing/Texture/MomentTextures.h
new file mode 100644
index 0000000..f93fe48
--- /dev/null
+++ b/Logic/Preprocessing/Texture/MomentTextures.h
@@ -0,0 +1,83 @@
+#ifndef MOMENTTEXTURES_H
+#define MOMENTTEXTURES_H
+
+#include "SNAPCommon.h"
+#include "itkImageToImageFilter.h"
+
+// Forward declarations
+namespace itk
+{
+template <class TPixel, unsigned int VDim> class Image;
+template <class TImage> class ImageRegionIteratorWithIndex;
+}
+
+namespace bilwaj {
+
+template <class TInputImage, class TOutputImage>
+class MomentTextureFilter
+    : public itk::ImageToImageFilter<TInputImage, TOutputImage>
+{
+public:
+  typedef MomentTextureFilter<TInputImage, TOutputImage> Self;
+  typedef itk::ImageToImageFilter<TInputImage, TOutputImage> Superclass;
+  typedef itk::SmartPointer<Self> Pointer;
+  typedef itk::SmartPointer<const Self> ConstPointer;
+
+  itkTypeMacro(ImageToImageFilter, ImageSource)
+
+  itkNewMacro(Self)
+
+  itkStaticConstMacro(ImageDimension, unsigned int, TInputImage::ImageDimension);
+
+  typedef TInputImage                                  InputImageType;
+  typedef typename InputImageType::RegionType          RegionType;
+  typedef typename InputImageType::SizeType            SizeType;
+  typedef typename InputImageType::PixelType           InputPixelType;
+  typedef TOutputImage                                 OutputImageType;
+  typedef typename OutputImageType::PixelType          OutputPixelType;
+  typedef typename OutputImageType::InternalPixelType  OutputComponentType;
+
+  /** Set the radius for moment computation */
+  itkSetMacro(Radius, SizeType)
+  itkGetMacro(Radius, SizeType)
+
+  /** Set the highest order of the moments */
+  itkSetMacro(HighestDegree, unsigned int)
+  itkGetMacro(HighestDegree, unsigned int)
+
+protected:
+
+  MomentTextureFilter() : m_HighestDegree(2) { m_Radius.Fill(1); }
+  ~MomentTextureFilter() {}
+
+  virtual void ThreadedGenerateData(const RegionType & outputRegionForThread,
+                                    itk::ThreadIdType threadId);
+
+  virtual void UpdateOutputInformation();
+
+  // Highest degree for which to generate the textures
+  unsigned int m_HighestDegree;
+
+  // Radius of the neighborhood for texture generation
+  SizeType m_Radius;
+
+private:
+
+  MomentTextureFilter(const Self &); //purposely not implemented
+  void operator=(const Self &);     //purposely not implemented
+
+
+
+};
+
+/*
+typedef short datatype;
+typedef itk::Image<datatype, 3> ImageType;
+
+void MomentTexture(SmartPtr<ImageType> &Inp,
+                   SmartPtr<ImageType> &MomentTexture,
+                   int degree, int Ext=1);
+*/
+}
+
+#endif // MOMENTTEXTURES_H
diff --git a/Logic/Slicing/IRISSlicer.h b/Logic/Slicing/IRISSlicer.h
index a2f59b2..d1affcf 100644
--- a/Logic/Slicing/IRISSlicer.h
+++ b/Logic/Slicing/IRISSlicer.h
@@ -124,6 +124,13 @@ public:
     */
   InputImageType *GetPreviewInput();
 
+  /**
+   * Indicate whether the main input should always be bypassed when the preview
+   * input is present. If not, the slicer will use whichever input is newer.
+   */
+  itkGetMacro(BypassMainInput, bool)
+  itkSetMacro(BypassMainInput, bool)
+
 protected:
   IRISSlicer();
   virtual ~IRISSlicer() {};
@@ -181,6 +188,9 @@ private:
 
   // Whether the pixel direction is reversed
   bool m_PixelTraverseForward;
+
+  // Whether the main input should always be bypassed
+  bool m_BypassMainInput;
   
   // The worker methods in this filter
   // void CopySliceLineForwardPixelForward(InputIteratorType, OutputImageType *);
diff --git a/Logic/Slicing/IRISSlicer.txx b/Logic/Slicing/IRISSlicer.txx
index c19dc4f..01a169d 100644
--- a/Logic/Slicing/IRISSlicer.txx
+++ b/Logic/Slicing/IRISSlicer.txx
@@ -63,6 +63,8 @@ IRISSlicer<TInputImage, TOutputImage>
 
   // Initialize to a zero slice index
   m_SliceIndex = 0;
+
+  m_BypassMainInput = false;
 }
 
 template <class TInputImage, class TOutputImage>
@@ -179,7 +181,7 @@ IRISSlicer<TInputImage, TOutputImage>
 
   if(preview)
     {
-    if(preview->GetPipelineMTime() > main->GetMTime())
+    if(m_BypassMainInput || preview->GetPipelineMTime() > main->GetMTime())
       {
       // We want the preview to be updated
       preview->SetRequestedRegion(inputRegion);
@@ -321,10 +323,9 @@ void IRISSlicer<TInputImage, TOutputImage>
   const InputImageType *preview =
       (InputImageType *) this->GetInputs()[1].GetPointer();
 
-  if(preview && preview->GetMTime() > inputPtr->GetMTime())
-    {
-    inputPtr = preview;
-    }
+  if(preview)
+    if(m_BypassMainInput || preview->GetMTime() > inputPtr->GetMTime())
+      inputPtr = preview;
   
   // Allocate (why is this necessary?)
   this->AllocateOutputs();
@@ -365,8 +366,11 @@ void IRISSlicer<TInputImage, TOutputImage>
   xStartVoxel[m_SliceDirectionImageAxis] = 
     szVol[m_SliceDirectionImageAxis] == 1 ? 0 : m_SliceIndex;
 
-  // Get the offset of the first voxel
-  size_t iStart = dot_product(stride_image, xStartVoxel);
+  // Get the offset of the first voxel. As pointed out by Roman Grothausmann, the VNL
+  // dot product causes overflow so we compute directly.
+  size_t iStart = 0;
+  for(int i = 0; i < 3; i++)
+    iStart += static_cast<long>(stride_image[i]) * static_cast<long>(xStartVoxel[i]);
 
   // Get the size of the output region (whole slice)
   typename OutputImageType::RegionType rgn = outputPtr->GetBufferedRegion();
diff --git a/ReleaseNotes.txt b/ReleaseNotes.txt
index 6515d90..782e122 100644
--- a/ReleaseNotes.txt
+++ b/ReleaseNotes.txt
@@ -1,13 +1,121 @@
 ======================================
  InsightSNAP Release Notes
- Version 3.2.0
+ Version 3.4.0
 ======================================
 
 -----------------
 1. New Features
 -----------------
 
-1.1. New in Version 3.2.0
+1.1. New in Version 3.4.0 
+----------------------------------------------
+
+This release was largely focused on improving the user experience through extensive
+changes to the GUI. We made access to the new features introduced in versions 3.0 and
+3.2 more intuitive. The loading and display of multiple images has been extensively
+reworked and improved. In addition, we made the classification mode in the semi-
+automatic segmentation workflow more powerful by providing additional image and
+geometric features that the classifier can use to learn the patterns of difference
+between the classes labeled by the use. We have been alsobusy working on new
+functionality such as image registration within SNAP, and a smaller memory footprint,
+but these will become available in the 3.6 release. The main focus of 3.4 is
+on usability.
+
+1.1.1. New functionality in this release
+
+ -  The controls for selecting segmentation labels have been brought back to the
+    main SNAP panel, where they were in versions 1 and 2. This will make the
+    interface more familiar to long-time users. 
+
+ -  The interface for loading and viewing additional image layers has been
+    extensively redesigned. When more than one anatomical image is loaded into
+    ITK-SNAP, the default behavior is to display one image at full size and the
+    rest of the images as thumbnails. Clicking the thumbnails makes them full
+    size. This new thumbnail mode is far more intuitive for working with
+    multiple images than the method of semi-transparent overlays employed in
+    previous versions. 
+
+ -  The IO dialog for opening additional images promts whether the user would
+    like the image to be shown side by side with an existing image or as a
+    semi-transparent overlay.
+
+ -  The thumbnails have a context menu button that provides fast access to
+    common image commands, such as adjusting contrast and color map.
+
+ -  The tiled display mode introduced in version 3.0 is also available as an
+    alternative to the thumbnail display.
+
+ -  The new thumbnail mode makes semi-automatic segmentation easier to work
+    with because one can switch easily between anatomical images and the
+    speed (blue and white) image during pre-segmentation, bubble placement
+    and contour evolution.
+
+ -  A new image annotation tool has been added to the main tool palette. This
+    tool can be used to measure distances on image slices, draw lines, measure
+    angles between lines, and place text annotations in specific points in the
+    3D image. Annotations can be exported and imported, allowing teams to
+    comment on medical images and segmentations. Annotations are automatically
+    saved in workspace files.
+
+ -  Command tooltips have been redesigned and now include information on the
+    shortcut key to activate each command. In addion, tooltips for the tools in
+    the main palette describe the actions of each mouse button. Many new shortcuts
+    have been added.
+
+ -  Cleaned up the behavior of mouse buttons and mouse scrolling to be more
+    consistent between modes. Added Shift-scroll action, which scrolls through
+    timepoints in a 4D image and components in a 3D multi-component image.
+
+ -  Added the ability to generate "contextual" features in the classification
+    mode in the semi-automatic segmentation workflow. Two types of contextual
+    features are provided: neighboring intensity features, and coordinate
+    features. The former allow the classifier to learn patterns of textural
+    differences between regions in the image. When used, the classifier can
+    separate regions that have identical average intensity but different texture.
+    The coordinate features allow the classifier to learn geometrical information,
+    such as the location/extent of the structure of interest relative to the
+    background structures. This can be used to segment a structure that has
+    no intensity contrast with adjacent structures, simply by giving the classifer
+    hints as to the location of the boundary on a few slices. These new features
+    are available by pressing "More..." when in classification mode.
+
+ -  Added some extra controls when working in classificaiton mode, such as
+    setting the forest size and tree depth for the random forest classifier
+    and a slider for "classifier bias", which allows you to bias the classfier
+    output more toward the foreground class or background classes.
+
+ -  Added the ability to select more than one class as the foreground class in
+    the random forest classification mode. This is powerful when the foreground
+    object has heterogeneous intensity.
+
+ -  Training examples drawn in random forest classificaiton mode are now retained
+    and can be reused to label multiple structures.
+
+
+1.1.2. Programmatic Improvements
+
+ -  Refactored the software to allow multiple images that occupy different
+    anatomical space to be loaded in the same ITK-SNAP session. This
+    functionality has not yet been enabled, and will be rolled out it 3.4 as
+    part of the new image registration functionality.
+
+ -  Updated to Qt 5.4
+
+ -  Fixed font size and other rendering issues on Retina displays. Added
+    high-resolution icons for Retina.
+
+ -  Made it possible to build ITK-SNAP against older Qt version 4.8. In some
+    Linux environments, applications based on Qt5 do not work well over remote
+    connection (ssh -X, VNC, x2go, NX) because the way Qt and X11 interface was
+    changed drastically in Qt5. The fallback to Qt4 makes it possible to run the
+    new SNAP version in cluster environments.
+
+ -  Fixed problems with loading images > 4gb
+
+ -  Restored ability to build on 64 bit Windows
+
+
+1.2. New in Version 3.2.0
 ----------------------------------------------
 
 The main new feature introduced in this release is supervised classification.
@@ -15,7 +123,7 @@ The release also is built against Qt5 (3.0 used Qt4.8), which resulted in a lot
 of changes to compilation and packaging. Quite a few bugs have been fixed and
 the release should be more stable than 3.0.
 
-1.1.1. New functionality in this release
+1.2.1. New functionality in this release
 
  -  Added a supervised classification presegmentation mode. This mode allows
     the user to compute the speed image by marking examples of two or more
@@ -46,7 +154,7 @@ the release should be more stable than 3.0.
  -  Improved volumes & statistics computation speed and display formatting
 
 
-1.1.2. Bug Fixes
+1.2.2. Bug Fixes
  
  -  Fixed a bug with small bubbles not growing in snake mode.
 
@@ -60,7 +168,7 @@ the release should be more stable than 3.0.
  -  Fixed several dozen smaller bugs
 
 
-1.1.3. Programmatic Improvements
+1.2.3. Programmatic Improvements
 
  -  Migrated to Qt5 as well as up to date versions of ITK (4.5) and VTK (6.1)
 
@@ -71,14 +179,14 @@ the release should be more stable than 3.0.
 
 
 
-1.2. New in Version 3.0.0
+1.3. New in Version 3.0.0
 ----------------------------------------------
 
 This is a major new release of ITK-SNAP. The user interface has been completely
 rewritten using the Qt platform, and new functionality for multi-modal image
 segmentation has been added.
 
-1.2.1. New functionality for multi-modality image segmentation
+1.3.1. New functionality for multi-modality image segmentation
 
  -  SNAP is no longer limited to just scalar-valued and RGB-valued images. An
     image with any number of components can be loaded into SNAP. The GUI provides
@@ -106,7 +214,7 @@ segmentation has been added.
     The user selects the desired number of clusters (i.e., tissue classes) and
     once the clusters are initialized, chooses the cluster of interest.
 
-1.2.2. New features in the Qt-based GUI
+1.3.2. New features in the Qt-based GUI
 
  -  The graphical user interface (GUI) uses Qt, a much more powerful toolkit
     than the FLTK toolkit in the previous versions. The new GUI is much richer
@@ -152,7 +260,7 @@ segmentation has been added.
     filtering labels by name, assinging foreground/background labels directly
     from the dialog.
 
-1.2.3. Improvements to 3D rendering window
+1.3.3. Improvements to 3D rendering window
 
  -  The 3D rendering window now uses the VTK toolkit for rendering. This will
     make it easier to introduce new functionality (such as volume rendering)
@@ -172,7 +280,7 @@ segmentation has been added.
  -  The scalpel tool uses VTK's 3D cutplane widget that can be rotated and moved
     after the cut has been drawn.
 
-1.2.4. Other new features
+1.3.4. Other new features
 
  -  Reduced memory footprint for large images. The previous version of SNAP
     would allocate on the order of 6 bytes for every voxel in the main image.
@@ -188,7 +296,7 @@ segmentation has been added.
     lists all the series with their dimensions and other meta-data, making it
     easier to determine which series one wishes to load.
 
-1.2.5. Programmatic improvements
+1.3.5. Programmatic improvements
 
  -  The SNAP code has been extensively refactored. There is a new "model" layer
     separating the Qt GUI from the "logic" layer. This layer is agnostic to the
@@ -200,7 +308,7 @@ segmentation has been added.
     reduces the amount of Qt-aware code.
 
 
-1.3. New in Version 2.4.0
+1.4. New in Version 2.4.0
 ----------------------------------------------
 
 This is the last planned release of the FLTK-based version of ITK-SNAP. It adds
@@ -208,14 +316,14 @@ minimal new functionality and addressed a number of bugs reported in the last
 year. The subsequent releases of ITK-SNAP will be based on the Qt platform and
 will have the 3.x version number.
 
-1.3.1. New Features and UI Improvements
+1.4.1. New Features and UI Improvements
 
  -  Ported the dependency on ITK 3.20.1 to ITK 4.2 on all operating systems:
     Mac OS X, Linux, and Windows.
 
  -  ITK-SNAP can read and write MRC images now.
 
-1.3.2. Bug Fixes and Stability Improvements
+1.4.2. Bug Fixes and Stability Improvements
 
  -  Fixed a problem with the RAI code which was not updating after reorienting.
 
@@ -242,14 +350,14 @@ will have the 3.x version number.
 
 ======================================
 
-1.4. New in Version 2.2.0
+1.5. New in Version 2.2.0
 ----------------------------------------------
 
 This is largely a maintenance release, with a few usability enhancements based
 on user feedback. The main change programmatically is 64 bit support on Linux,
 MacOS and Windows.
 
-1.4.1. New Features and UI Improvements
+1.5.1. New Features and UI Improvements
 
  -  64 bit versions of the software are available for Linux, Windows and Mac.
     These versions are now built nightly and will be distributed on
@@ -312,7 +420,7 @@ MacOS and Windows.
 
  -  Ability to save segmentation mesh in active contour mode
 
-1.4.2. Bug Fixes and Stability Improvements
+1.5.2. Bug Fixes and Stability Improvements
 
  -  Fixed a problem with certain operations being very slow because of the way
     the progress bars were displayed. Preprocessing, mesh rendering and mesh
@@ -330,10 +438,10 @@ MacOS and Windows.
 
  -  Fixed problem with bubbles not being spherical for certain image orientations
 
-1.5. New in Version 2.0
+1.6. New in Version 2.0
 ----------------------------------------------
 
-1.5.1. New Features and UI Improvements
+1.6.1. New Features and UI Improvements
 
  -  Support for multiple image layers. Users can now load gray and RGB images
     as overlays on top of the main image layer. For example, one can display a
@@ -404,7 +512,7 @@ MacOS and Windows.
     modes, crosshair motion is accessible through MMB as well.
 
 
-1.5.2. Bug Fixes
+1.6.2. Bug Fixes
 
  -  Fixed an issue with SNAP reading certain types of image twice from disc. This should
     speed up the reading of floating point images, for example.
@@ -424,16 +532,16 @@ MacOS and Windows.
 
  -  Please see the bug tracker on itksnap.org for the full listing of bug fixes.
 
-1.5.3. Website Changes
+1.6.3. Website Changes
 
  -  The itksnap.org website has been Wikified. Content can now be edited on the fly.
 
 
 
-1.6. New in Version 1.8
+1.7. New in Version 1.8
 ----------------------------------------------
 
-1.6.1. New Features and UI Improvements
+1.7.1. New Features and UI Improvements
 
  -  Support for reading floating point images of arbitrary range. SNAP still
     represents gray images internally as signed short, but now it can load a
@@ -561,7 +669,7 @@ MacOS and Windows.
  -  Documented existing keyboard shortcuts and added some new ones. Available
     shortcuts can be listed by selecting Help->Shortcuts.
 
-1.6.2. Programmatic/Distribution Changes
+1.7.2. Programmatic/Distribution Changes
 
  -  SNAP is now built against ITK 3.8, offering several improvements, especially
     in how image orientation is handled.
@@ -574,23 +682,23 @@ MacOS and Windows.
     Some people complained about the latter. We can also make .rpm and .deb
     packages although these won't be posted for public download yet.
 
-1.6.3. Bug Fixes
+1.7.3. Bug Fixes
 
  -  Level set fix for ITK 3.8 fixes automatic segmentation's weird behavior
 
-1.7. New in Version 1.6.0.1
+1.8. New in Version 1.6.0.1
 ---------------------------
 
-1.7.1. Bug Fixes
+1.8.1. Bug Fixes
 
  -  Major bug in release 1.6.0 involving disabled cursor movement in snake
     segmentation mode has been resolved.
 
 
-1.8. New in Version 1.6.0
+1.9. New in Version 1.6.0
 -------------------------
 
-1.8.1. New Features and UI Improvements
+1.9.1. New Features and UI Improvements
 
  -  You can now save a sequence of all axial, coronal or sagittal slices with
     overlays as PNG files (File->Save->Screenshot Series).
@@ -639,11 +747,11 @@ MacOS and Windows.
 
  -  Shortened/simplified some of the menu items
 
-1.8.2. Bug Fixes
+1.9.2. Bug Fixes
 
  -  Various bugs have been fixed :)
 
-1.8.3. Distribution Changes
+1.9.3. Distribution Changes
 
  -  SNAP website fully migrated to sourceforge.net
 
@@ -653,10 +761,10 @@ MacOS and Windows.
  -  Linux binaries will be available starting with 1.6.0
 
 
-1.9. New in Version 1.4.1
+1.10. New in Version 1.4.1
 -------------------------
 
-1.9.1. New Features and UI Improvements
+1.10.1. New Features and UI Improvements
 
  -  Added paintbrush tool to the main toolbar. Paintbrush can be used to quickly
     touch up segmentations. Left mouse button paints with selected label, right
@@ -675,7 +783,7 @@ MacOS and Windows.
     different segmentation from the same viewpoint. Press 's' in the 3D window
     to save the camera state and 'r' to restore it.
 
-1.9.2. Bug Fixes
+1.10.2. Bug Fixes
 
  -  MAJOR: fixed bug that was causing crashes on Win32 during polygon drawing
     (thanks to Jeff Tsao for this bug fix!)
@@ -693,7 +801,7 @@ MacOS and Windows.
  -  Fixed crash when changing bubble radius and then going back to
     preprocessing mode
 
-1.9.3. Distribution Changes
+1.10.3. Distribution Changes
 
  -  Interim SNAP releases are now hosted on SourceForge. ITK repository will only
     be used to host major releases (like 1.6). This allows us to check stuff in
@@ -705,10 +813,10 @@ MacOS and Windows.
     own and the download size is reduced
 
 
-1.10. New in Version 1.4
+1.11. New in Version 1.4
 -----------------------
 
-1.10.1. New Features and User Interface Improvements
+1.11.1. New Features and User Interface Improvements
 
  -  New and improved label editor. You can easily switch between labels while in
     the editor and the interface for adding new labels is more intuitive. You
@@ -747,7 +855,7 @@ MacOS and Windows.
 
  -  The tutorial has been updated to reflect the new features.
 
-1.10.2. Bug Fixes.
+1.11.2. Bug Fixes.
 
  -  SNAP should crash a lot less than before
 
@@ -763,12 +871,12 @@ MacOS and Windows.
 
  -  Lots of other small bugs have been fixed!
 
-1.10.3. Programmatic Enhancements
+1.11.3. Programmatic Enhancements
 
  -  SNAP and IRIS now share the sameset of OpenGL windows. This should prevent
     crashes on some platforms.
 
-1.10.4. Other
+1.11.4. Other
 
  -  SNAP available as a universal (Intel/PPC) binary for MacOS at itksnap.org
 
@@ -816,10 +924,10 @@ MacOS and Windows.
     advection term.
 
 
-3. Known Issues
+2. Known Issues
 -----------------
 
- -  Some advanced features (annotation mode, label editor advanced tools) have
+ -  Some advanced features (label editor advanced tools, window shrinking) have
     not yet been ported to Qt. They will be ported in future versions, and
     expanded in the process. There is a plan to integrate SNAP and C3D which
     will provide much richer image processing support for images and segmentations.
@@ -827,7 +935,3 @@ MacOS and Windows.
  -  The cutplane in the scalpel tool is too big when the camera is zoomed in and
     it needs a flip button. Also with dark labels you can't see the handle.
 
-4. Wish List
------------------
- -  The ability to perform 2D level set segmentation in each slice view.
-
diff --git a/Testing/GUI/Qt/SNAPTestQt.cxx b/Testing/GUI/Qt/SNAPTestQt.cxx
index 3adcec2..3875227 100644
--- a/Testing/GUI/Qt/SNAPTestQt.cxx
+++ b/Testing/GUI/Qt/SNAPTestQt.cxx
@@ -5,15 +5,30 @@
 #include <QLineEdit>
 #include <QFile>
 #include <QTextStream>
-#include <QQmlEngine>
 #include <QDebug>
 #include <QPushButton>
 #include <QTimer>
 #include <QThread>
 #include <QRegExp>
 #include <QApplication>
+#include <QAbstractItemView>
+#include <QComboBox>
+#include <QMouseEvent>
+#include <QApplication>
+#include <QKeySequence>
+
+
+
 #include "SNAPQtCommon.h"
 
+#if QT_VERSION >= 0x050000
+  #include <QJSEngine>
+#else
+  #include <QScriptEngine>
+  #define QJSEngine QScriptEngine
+  #define QJSValue QScriptValue
+#endif
+
 using namespace std;
 
 SNAPTestQt::SNAPTestQt(MainImageWindow *win,
@@ -63,7 +78,9 @@ SNAPTestQt::LaunchTest(std::string test)
 
   // Create and run the thread
   TestWorker *worker = new TestWorker(this, from_utf8(test), m_ScriptEngine, m_Acceleration);
-  connect(worker, &TestWorker::finished, worker, &QObject::deleteLater);
+
+  connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
+
   worker->start();
 }
 
@@ -81,7 +98,6 @@ QWidget *SNAPTestQt::findWidget(QString widgetName)
   return NULL;
 }
 
-#include <QAbstractItemView>
 
 QVariant SNAPTestQt::tableItemText(QObject *table, int row, int col)
 {
@@ -95,7 +111,6 @@ QVariant SNAPTestQt::tableItemText(QObject *table, int row, int col)
   return QVariant();
 }
 
-#include <QComboBox>
 
 QModelIndex SNAPTestQt::findItem(QObject *container, QVariant text)
 {
@@ -205,6 +220,16 @@ void SNAPTestQt::validateValue(QVariant v1, QVariant v2)
 
 }
 
+void SNAPTestQt::sleep(int milli_sec)
+{
+  // Scale requested sleep time by acceleration factor
+  int ms_actual = (int)(milli_sec / m_Acceleration);
+
+  // Sleep
+  qDebug() << "sleeping for " << ms_actual << "ms.";
+  TestWorker::sleep_ms(ms_actual);
+}
+
 void SNAPTestQt::validateFloatValue(double v1, double v2, double precision)
 {
   // Validation involves checking if the values are equal. If not,
@@ -230,8 +255,6 @@ void SNAPTestQt::testFailed(QString reason)
   ::exit(REGRESSION_TEST_FAILURE);
 }
 
-#include <QMouseEvent>
-#include <QApplication>
 
 void SNAPTestQt::postMouseEvent(QObject *object, double rel_x, double rel_y, QString eventType, QString button)
 {
@@ -268,7 +291,6 @@ void SNAPTestQt::postMouseEvent(QObject *object, double rel_x, double rel_y, QSt
     }
 }
 
-#include <QKeySequence>
 void SNAPTestQt::postKeyEvent(QObject *object, QString key)
 {
   QWidget *widget = dynamic_cast<QWidget *>(object);
@@ -310,101 +332,6 @@ TestWorker::TestWorker(QObject *parent, QString script, QJSEngine *engine, doubl
   m_Acceleration = accel_factor > 0.0 ? accel_factor : 1.0;
 }
 
-
-
-void TestWorker::processDirective(QString line)
-{
-  // If the line is a command, process the command
-  QRegExp rxSleep("//---\\s+sleep\\s+(\\d+)");
-  QRegExp rxSource("//---\\s+source\\s+(\\w+)");
-
-  if(rxSleep.indexIn(line) >= 0)
-    {
-    // Sleeping
-    int ms = rxSleep.cap(1).toInt() * m_Acceleration;
-    qDebug() << QString("Sleeping for %1 ms").arg(ms);
-    msleep(ms);
-    }
-
-  else if(rxSource.indexIn(line) >= 0)
-    {
-    // Sleeping
-    QString file = rxSource.cap(1);
-    this->runScript(file);
-    }
-
-  else
-    {
-    // Unknown directive
-    qDebug() << "Unknown directive" << line;
-    }
-}
-
-void TestWorker::executeScriptlet(QString scriptlet)
-{
-  QJSValue rc = m_Engine->evaluate(scriptlet);
-  if(rc.isError())
-    {
-    qWarning() << "JavaScript exception:" << rc.toString();
-    ::exit(SNAPTestQt::REGRESSION_TEST_FAILURE);
-    }
-}
-
-
-void TestWorker::runScript(QString script_url)
-{
-  // The test may be a path to an actual file
-  if(!QFileInfo(script_url).isReadable())
-    script_url = QString(":/scripts/Scripts/test_%1.js").arg(script_url);
-
-  // Report which test we are accessing
-  qDebug() << "Running test " << script_url;
-
-  // Find the script file corresponding to the test
-  QFile file(script_url);
-  if(!file.open(QIODevice::ReadOnly))
-    {
-    qWarning() << QString("Unable to read test script %1").arg(script_url);
-    ::exit(SNAPTestQt::NO_SUCH_TEST);
-    }
-
-  // Read the script
-  QTextStream stream(&file);
-
-  // Break the script into pieces that should be sent to the processor
-  QString scriptlet;
-  while(true)
-    {
-    // Read a line of the script
-    QString line = stream.readLine();
-
-    // Is the line an interpreter command or a script line?
-    if(line.isNull() || line.startsWith("//---"))
-      {
-      // The current scriptlet has ended. Time to execute!
-      this->executeScriptlet(scriptlet);
-
-      // Reset the scriptlet
-      scriptlet = QString();
-
-      // If the line is null (eof) break
-      if(line.isNull())
-        break;
-
-      // Otherwise, it's a directive
-      this->processDirective(line);
-      }
-    else
-      {
-      // Append the line to the current scriptlent
-      scriptlet.append(line);
-      scriptlet.append('\n');
-      }
-    }
-
-  // That's it - the script is finished
-}
-
 void TestWorker::run()
 {
   // Add ourselves to the engine
@@ -415,27 +342,24 @@ void TestWorker::run()
   qDebug() << "CTEST_FULL_OUTPUT";
 
   // Run the top-level script
-  // runScript(m_MainScript);
   source(m_MainScript);
 
   // Once the test has completed, we can exit the application
   ::exit(SNAPTestQt::SUCCESS);
 }
 
+void TestWorker::sleep_ms(unsigned int msec)
+{
+  QThread::msleep(msec);
+}
+
 void TestWorker::wait(unsigned int msec)
 {
   msleep(msec);
 }
 
-void TestWorker::source(QString script_url)
+void TestWorker::readScript(QString script_url, QString &script)
 {
-  // The test may be a path to an actual file
-  if(!QFileInfo(script_url).isReadable())
-    script_url = QString(":/scripts/Scripts/test_%1.js").arg(script_url);
-
-  // Report which test we are accessing
-  qDebug() << "Running test " << script_url;
-
   // Find the script file corresponding to the test
   QFile file(script_url);
   if(!file.open(QIODevice::ReadOnly))
@@ -446,7 +370,6 @@ void TestWorker::source(QString script_url)
 
   // Read the script
   QTextStream stream(&file);
-  QString script;
 
   // Read the script line by line, making substitutions
   while(!stream.atEnd())
@@ -454,15 +377,28 @@ void TestWorker::source(QString script_url)
     QString line = stream.readLine();
     QRegExp rxSleep("^\\s*$");
     QRegExp rxComment("//===\\s+(\\w+.*)");
+    // QRegExp rxInclude("include.*\\((\\w+.*)\\)");
+    QRegExp rxInclude("include.*\"(\\w+.*)\".*");
 
     if(rxSleep.indexIn(line) >= 0)
       {
-      line = QString("thread.wait(500)");
+      line = QString("engine.sleep(500)");
       }
     else if(rxComment.indexIn(line) >= 0)
       {
       line = QString("engine.print(\"%1\")").arg(rxComment.cap(1));
       }
+    else if(rxInclude.indexIn(line) >= 0)
+      {
+      QString child_url = rxInclude.cap(1);
+      if(!QFileInfo(child_url).isReadable())
+        child_url = QString(":/scripts/Scripts/test_%1.js").arg(child_url);
+
+      qDebug() << "Including : " << child_url;
+
+      this->readScript(child_url, script);
+      line = "";
+      }
 
     script += line;
     script += "\n";
@@ -470,6 +406,19 @@ void TestWorker::source(QString script_url)
 
   // Close the file
   file.close();
+}
+
+void TestWorker::source(QString script_url)
+{
+  // The test may be a path to an actual file
+  if(!QFileInfo(script_url).isReadable())
+    script_url = QString(":/scripts/Scripts/test_%1.js").arg(script_url);
+
+  // Report which test we are accessing
+  qDebug() << "Running test: " << script_url;
+
+  QString script;
+  this->readScript(script_url, script);
 
   // Execute it
   QJSValue rc = m_Engine->evaluate(script);
diff --git a/Testing/GUI/Qt/SNAPTestQt.h b/Testing/GUI/Qt/SNAPTestQt.h
index 424cea7..98ab9e1 100644
--- a/Testing/GUI/Qt/SNAPTestQt.h
+++ b/Testing/GUI/Qt/SNAPTestQt.h
@@ -7,6 +7,7 @@
 #include <QStringList>
 #include <QThread>
 #include <QVariant>
+#include <QModelIndex>
 
 class MainImageWindow;
 class GlobalUIModel;
@@ -15,6 +16,14 @@ class QQmlEngine;
 class QTimer;
 class QStringList;
 
+#if QT_VERSION >= 0x050000
+  class QJSEngine;
+#else
+  class QScriptEngine;
+  #define QJSEngine QScriptEngine
+#endif
+
+
 
 class TestWorker : public QThread
 {
@@ -24,6 +33,7 @@ public:
   TestWorker(QObject *parent, QString script, QJSEngine *engine, double accel_factor);
 
   void run();
+  static void sleep_ms(unsigned int msec);
 
 public slots:
 
@@ -37,9 +47,7 @@ protected:
   // Acceleration factor
   double m_Acceleration;
 
-  void runScript(QString script_url);
-  void executeScriptlet(QString scriptlet);
-  void processDirective(QString line);
+  void readScript(QString script_url, QString &script);
 };
 
 class SNAPTestQt : public QObject
@@ -94,6 +102,9 @@ public slots:
   void postMouseEvent(QObject *widget, double rel_x, double rel_y, QString eventType, QString button);
 
   void postKeyEvent(QObject *object, QString key);
+
+  void sleep(int milli_sec);
+
 protected:
 
   ReturnCode ListTests();
diff --git a/Testing/GUI/Qt/Scripts/test_Library.js b/Testing/GUI/Qt/Scripts/test_Library.js
index 2805dd9..c4efa7d 100644
--- a/Testing/GUI/Qt/Scripts/test_Library.js
+++ b/Testing/GUI/Qt/Scripts/test_Library.js
@@ -4,7 +4,7 @@ function setCursor(x, y, z)
   engine.findChild(mainwin, "inCursorX").value = x;
   engine.findChild(mainwin, "inCursorY").value = y;
   engine.findChild(mainwin, "inCursorZ").value = z;
-  thread.wait(200);
+  engine.sleep(200);
 }
 
 function openMainImage(name)
@@ -18,11 +18,11 @@ function openMainImage(name)
 
   //=== Pressing the 'next' button
   engine.findChild(dialog, "qt_wizard_commit").click();
-  thread.wait(1000);
+  engine.sleep(1000);
 
   //=== Pressing the 'finish' button
   engine.findChild(dialog, "qt_wizard_finish").click();
-  thread.wait(1000);
+  engine.sleep(1000);
 }
 
 function openWorkspace(name)
@@ -36,7 +36,7 @@ function openWorkspace(name)
 
   //=== Accepting text
   dialog.accept();
-  thread.wait(1000);
+  engine.sleep(1000);
 }
 
 function enterSnakeMode(pos_x, pos_y, pos_z, size_x, size_y, size_z)
@@ -56,7 +56,7 @@ function enterSnakeMode(pos_x, pos_y, pos_z, size_x, size_y, size_z)
 
   //=== Pushing the Segment3D button
   engine.findChild(roipanel,"btnAuto").click();
-  thread.wait(1000);
+  engine.sleep(1000);
 }
 
 function enterSnakeModeFullROI()
@@ -71,7 +71,7 @@ function enterSnakeModeFullROI()
 
   //=== Pushing the Segment3D button
   engine.findChild(roipanel,"btnAuto").click();
-  thread.wait(1000);
+  engine.sleep(1000);
 }
 
 function readVoxelIntensity(layer_row)
diff --git a/Testing/GUI/Qt/Scripts/test_ProbeIntensity.js b/Testing/GUI/Qt/Scripts/test_ProbeIntensity.js
index 562f09b..eb12555 100644
--- a/Testing/GUI/Qt/Scripts/test_ProbeIntensity.js
+++ b/Testing/GUI/Qt/Scripts/test_ProbeIntensity.js
@@ -1,7 +1,7 @@
 // This script positions the cursor and checks image intensity
 
 // Call the open image script
-thread.source("Library")
+include("Library");
 
 // Open the test image
 openMainImage("MRIcrop-orig.gipl.gz");
diff --git a/Testing/GUI/Qt/Scripts/test_RandomForest.js b/Testing/GUI/Qt/Scripts/test_RandomForest.js
index c16d4e1..bfc5b26 100644
--- a/Testing/GUI/Qt/Scripts/test_RandomForest.js
+++ b/Testing/GUI/Qt/Scripts/test_RandomForest.js
@@ -1,5 +1,5 @@
 // Read the function library
-thread.source("Library");
+include("Library");
 
 // Open the test workspace
 openWorkspace("tensor.itksnap");
@@ -46,7 +46,7 @@ engine.findChild(snakepanel,"btnClassifyClearExamples").click();
 
 //=== Go to bubble mode
 engine.findChild(snakepanel,"btnNextPreproc").click();
-thread.wait(1000);
+engine.sleep(1000);
 
 //=== Go back to the first seed 
 setCursor(20,8,13);
@@ -62,7 +62,7 @@ engine.findChild(snakepanel,"inBubbleRadius").value = 4;
 
 //=== Go to snake mode
 engine.findChild(snakepanel,"btnBubbleNext").click();
-thread.wait(1000);
+engine.sleep(1000);
 
 //=== Set step size
 engine.findChild(snakepanel,"inStepSize").value = 10;
@@ -76,7 +76,7 @@ for(var i = 0; i < 10; i++)
 
 //=== Finish snake mode
 engine.findChild(snakepanel,"btnEvolutionNext").click()
-thread.wait(1000)
+engine.sleep(1000)
 
 //=== Open volumes and statistics
 engine.findChild(mainwin,"actionVolumesAndStatistics").trigger();
diff --git a/Testing/GUI/Qt/Scripts/test_RegionCompetition.js b/Testing/GUI/Qt/Scripts/test_RegionCompetition.js
index 4bf967a..9cfa72a 100644
--- a/Testing/GUI/Qt/Scripts/test_RegionCompetition.js
+++ b/Testing/GUI/Qt/Scripts/test_RegionCompetition.js
@@ -1,5 +1,5 @@
 // Read the function library
-thread.source("Library");
+include("Library");
 
 // Open the test image
 openMainImage("MRIcrop-orig.gipl.gz");
@@ -23,14 +23,14 @@ engine.validateFloatValue(readVoxelIntensity(1), -0.2263, 0.0001)
 
 //=== Go to bubble mode
 engine.findChild(snakepanel,"btnNextPreproc").click();
-thread.wait(1000);
+engine.sleep(1000);
 
 //=== Add a bubble
 engine.findChild(snakepanel,"btnAddBubble").click();
 
 //=== Go to snake mode
 engine.findChild(snakepanel,"btnBubbleNext").click();
-thread.wait(1000);
+engine.sleep(1000);
 
 //=== Validating level set image
 engine.validateValue(readVoxelIntensity(2), -4);
diff --git a/Testing/GUI/Qt/Scripts/test_Workspace.js b/Testing/GUI/Qt/Scripts/test_Workspace.js
index c5465ac..3e4dfc6 100644
--- a/Testing/GUI/Qt/Scripts/test_Workspace.js
+++ b/Testing/GUI/Qt/Scripts/test_Workspace.js
@@ -1,5 +1,5 @@
 // Read the function library
-thread.source("Library");
+include("Library");
 
 // Open the test workspace
 openWorkspace("tensor.itksnap");
@@ -21,7 +21,7 @@ engine.findChild(layerdialog, "tabWidget").setCurrentWidget(cmpcolormap);
 
 //=== Select the color map preset we want
 var inpreset = engine.findChild(cmpcolormap, "inPreset");
-inpreset.setCurrentText("Summer");
+inpreset.setCurrentIndex(8);
 
 //=== Close the inspector dialog
 layerdialog.close();
diff --git a/Utilities/MacOS/BundleResources/dsstore.bin b/Utilities/MacOS/BundleResources/dsstore.bin
index 851861d..2e14b80 100644
Binary files a/Utilities/MacOS/BundleResources/dsstore.bin and b/Utilities/MacOS/BundleResources/dsstore.bin differ

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/itksnap.git



More information about the debian-med-commit mailing list