Navigation:  I Want To... > Imaging >

Customize the image layout

Previous pageReturn to chapter overviewNext page

Use Case

You want to write your own image layout (hanging protocol) engine.

Relevant Architecture

Physical and Logical Workspaces
Opening a study

Relevant Types

LayoutManagerExtensionPoint
ILayoutManager
IImageViewer
IPhysicalWorkspace
ILogicalWorkspace
IImageBox
ITile
IImageSet
IDisplaySet
IPresentationImage

Sample Code

Note:  To use the following sample code, the Enabled flag must be set to True as described in the comments at the top of the class.

using System.Collections.Generic;

using ClearCanvas.Common;

using ClearCanvas.ImageViewer;

using ClearCanvas.ImageViewer.StudyManagement;

 

// ... (other using namespace statements here)

 

namespace MyPlugin.Imaging

{

   /// <remarks>

   /// You can override some or all parts of the default layout process.

   /// Only include the overrides you want, and make sure they don't call

   /// the default implementation, or some very strange things may happen!

   /// 

   /// But don't include both this class and the MyOtherLayoutManager class below!

   /// 

   /// To select the one you wish to enable, change the flag on one of them to True.

   /// i.e. [ExtensionOf(typeof (LayoutManagerExtensionPoint), Enabled = true)]

   /// </remarks>

   [ExtensionOf(typeof (LayoutManagerExtensionPoint), Enabled = false)]

   public class MyLayoutManager : LayoutManager

   {

      protected override void BuildLogicalWorkspace()

      {

         // Build your logical workspace here, 

         // i.e., add your DisplaySets and PresentationImages

      }

 

      protected override void LayoutPhysicalWorkspace()

      {

         // Build your physical workspace here, 

         // i.e., add your ImageBoxes and Tiles

      }

 

      protected override void FillPhysicalWorkspace()

      {

         // Populate your ImageBoxes with your DisplaySets here

      }

 

      protected override void SortStudies(StudyCollection studies)

      {

         // Do your own sorting of studies here

      }

 

      /// <remarks>

      /// Don't override SortStudies if you use this.

      /// </remarks>

      protected override IComparer<Study> GetStudyComparer()

      {

         // return your own IComparer<Study>

         return null;

      }

   }

 

   /// <remarks>

   /// Or you can override all of it entirely!

   /// 

   /// But don't include both this class and the MyLayoutManager class above!

   /// 

   /// To select the one you wish to enable, change the flag on one of them to True.

   /// i.e. [ExtensionOf(typeof (LayoutManagerExtensionPoint), Enabled = true)]

   /// </remarks>

   [ExtensionOf(typeof (LayoutManagerExtensionPoint), Enabled = false)]

   public class MyOtherLayoutManager : LayoutManager

   {

      public override void Layout()

      {

         // if you override this, you will need to manually call

         // BuildLogicalWorkspace, LayoutPhysicalWorkspace, etc.

         //

         // of course, you can also put all the code in here instead!

      }

   }

}

Remarks

The LayoutManagerExtensionPoint gives you a chance to determine how images are initially laid out in an ImageViewerComponent.

In the default implementation of LayoutManager, ImageSets and studies are synonymous, as are DisplaySets and series.  However, it doesn't have to be that way.  In the sample above, you can build your LogicalWorkspace in any way you like.  For example, you might want to take an MR series that has interleaved echoes and separate it into two DisplaySets (e.g. Echo 1, Echo 2, etc).  Or, if on the modality, all the images in a skeletal survey are acquired as one series, you might want to separate each image out into its own DisplaySet.  It's entirely up to you.

When creating your PhysicalWorkspace, there is also a lot of flexibility. PhysicalWorkspace provides convenience methods that allow you to create rectangular grids of ImageBoxes.  However, it doesn't have to be that way, since the arrangement of ImageBoxes is determined using normalized coordinates relative to the PhysicalWorkspace itself. Thus, non-rectangular layouts are possible.

Once you've added the relevant objects to the LogicalWorkspace and PhysicalWorkspace, you're ready to fill the ImageBoxes in the PhysicalWorkspace with the appropriate DisplaySets.

Finally, remember to call Draw() on the PhysicalWorkspace in order to render the images you've just laid out.

Deployment Notes

If you've written your own layout plugin, make sure you've either removed the default ClearCanvas.ImageViewer.Layout.Basic.dll plugin (and its corresponding view dll) from your plugins directory, or disabled the relevant extension.

Examples in Code Base

ClearCanvas.ImageViewer.Layout.Basic.LayoutManager