コード例 #1
0
		public override void Process(Configuration config)
		{
			var tables = GetTables(config);

			// create a resource resolver that will scan all plugins
			// TODO: we should only scan plugins that are tied to the specified PersistentStore, but there is currently no way to know this
			IResourceResolver resolver = new ResourceResolver(
				CollectionUtils.Map(Platform.PluginManager.Plugins, (PluginInfo pi) => pi.Assembly).ToArray());

			// find all dbi resources
			var rx = new Regex("dbi.xml$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
			var dbiFiles = resolver.FindResources(rx);

			foreach (var dbiFile in dbiFiles)
			{
				using (var stream = resolver.OpenResource(dbiFile))
				{
					var xmlDoc = new XmlDocument();
					xmlDoc.Load(stream);
					var indexElements = xmlDoc.SelectNodes("indexes/index");
					if (indexElements == null)
						continue;

					foreach (XmlElement indexElement in indexElements)
					{
						ProcessIndex(indexElement, tables);
					}
				}
			}

		}
コード例 #2
0
ファイル: TableView.cs プロジェクト: nhannd/Xian
		public TableView()
        {
			SuppressSelectionChangedEvent = false;
			InitializeComponent();

            // if we allow the framework to generate columns, there seems to be a bug with 
            // setting the minimum column width > 100 pixels
            // therefore, turn off the auto-generate and create the columns ourselves
            _dataGridView.AutoGenerateColumns = false;

            _rowHeight = this.DataGridView.RowTemplate.Height;
            this.DataGridView.RowPrePaint += SetCustomBackground;
            this.DataGridView.RowPostPaint += DisplayCellSubRows;
            this.DataGridView.RowPostPaint += OutlineCell;
            this.DataGridView.RowPostPaint += SetLinkColor;

			// System.Component.DesignMode does not work in control constructors
			if (LicenseManager.UsageMode != LicenseUsageMode.Designtime)
			{
				// Use a DelayedEventPublisher to make fixes for bugs 386 and 8032 a little clearer.  Previously used a Timer directly
				// to delay the events
				_delayedSelectionChangedPublisher = new DelayedEventPublisher((sender, args) => NotifySelectionChanged(), 50);
			}

			try
			{
				var resolver = new ResourceResolver(typeof (TableView), false);
				using (var s = resolver.OpenResource("checkmark.png"))
				{
					_checkmarkBitmap = new Bitmap(s);
				}
			}
			catch (Exception) {}
        }
コード例 #3
0
ファイル: SettingsTestBase.cs プロジェクト: nhannd/Xian
		public static void TestConfigResourceToFile(string fileName)
		{
			ResourceResolver resolver = new ResourceResolver(typeof(SettingsMigrationTests).Assembly);
			using (Stream resourceStream = resolver.OpenResource("TestPreviousConfiguration.config"))
			{
				StreamToFile(resourceStream, fileName);
				resourceStream.Close();
			}
		}
コード例 #4
0
ファイル: AlertNotificationForm.cs プロジェクト: nhannd/Xian
        public AlertNotificationForm(DesktopForm owner, string title)
        {
            InitializeComponent();

			this.Text = title;
        	this.Owner = owner;

            _maxOpacity = 1.0;
            _minOpacity = 0.3;

        	var resolver = new ResourceResolver(typeof (AlertNotificationForm).Assembly);
			using (var s = resolver.OpenResource("close.bmp"))
			{
				_closeButtonBitmap = new Bitmap(s);
			}

			owner.Move += OwnerFormMoved;
        	owner.Resize += OwnerFormResized;
        }
コード例 #5
0
		private EnumerationInfo ReadSoftEnum(Type enumValueClass, Table table)
		{
			// look for an embedded resource that matches the enum class
			string res = string.Format("{0}.enum.xml", enumValueClass.FullName);
			IResourceResolver resolver = new ResourceResolver(enumValueClass.Assembly);
			try
			{
				using (Stream xmlStream = resolver.OpenResource(res))
				{
					XmlDocument xmlDoc = new XmlDocument();
					xmlDoc.Load(xmlStream);
					int displayOrder = 1;

					return new EnumerationInfo(enumValueClass.FullName, table.Name, false,
						CollectionUtils.Map<XmlElement, EnumerationMemberInfo>(xmlDoc.GetElementsByTagName("enum-value"),
							delegate(XmlElement enumValueElement)
							{
								XmlElement valueNode = CollectionUtils.FirstElement<XmlElement>(enumValueElement.GetElementsByTagName("value"));
								XmlElement descNode = CollectionUtils.FirstElement<XmlElement>(enumValueElement.GetElementsByTagName("description"));

								return new EnumerationMemberInfo(
									enumValueElement.GetAttribute("code"),
									valueNode != null ? valueNode.InnerText : null,
									descNode != null ? descNode.InnerText : null,
									displayOrder++,
									false);
							}));
				}
			}
			catch (Exception)
			{
				// no embedded resource found - no values defined
				return new EnumerationInfo(enumValueClass.FullName, table.Name, false, new List<EnumerationMemberInfo>());
			}
		}
コード例 #6
0
ファイル: AnnotationLayoutStore.cs プロジェクト: nhannd/Xian
		private void Initialize(bool reloadSettings)
		{
			lock (_syncLock)
			{
				if (Document != null && !reloadSettings)
					return;

				AnnotationLayoutStoreSettings.Default.Reload();
				if (Document != null)
					return;

				try
				{
					XmlDocument document = new XmlDocument();
					ResourceResolver resolver = new ResourceResolver(this.GetType().Assembly);
					using (Stream stream = resolver.OpenResource("AnnotationLayoutStoreDefaults.xml"))
					{
						document.Load(stream);
						Document = document;
					}
				}
				catch (Exception e)
				{
					Platform.Log(LogLevel.Debug, e);
					Clear();
				}
			}
		}
コード例 #7
0
		/// <summary>
		/// Translates the default value for a settings class given the raw value.
		/// </summary>
		/// <remarks>
		/// If the specified raw value is the name of an embedded resource (embedded in the same
		/// assembly as the specified settings class), the contents of the resource are returned.
		/// Otherwise, the raw value is simply returned.
		/// </remarks>
		public static string TranslateDefaultValue(Type settingsClass, string rawValue)
		{
			// short circuit if nothing translatable
			if (string.IsNullOrEmpty(rawValue))
				return rawValue;

			// does the raw value look like it could be an embedded resource?
			if (Regex.IsMatch(rawValue, @"^([\w]+\.)+\w+$"))
			{
				try
				{
					// try to open the resource
					IResourceResolver resolver = new ResourceResolver(settingsClass.Assembly);
					using (var resourceStream = resolver.OpenResource(rawValue))
					{
						var r = new StreamReader(resourceStream);
						return r.ReadToEnd();
					}
				}
				catch (MissingManifestResourceException)
				{
					// guess it was not an embedded resource, so return the raw value
					return rawValue;
				}
			}
			return rawValue;
		}
コード例 #8
0
		public void Test()
		{
			DicomFilteredAnnotationLayoutStore.Instance.Clear();

			IList<DicomFilteredAnnotationLayout> layouts = DicomFilteredAnnotationLayoutStore.Instance.FilteredLayouts;
			Assert.AreEqual(0, layouts.Count);

			DicomFilteredAnnotationLayoutStore.Instance.Update(CreateLayout("testLayout1", "Dicom.MR", "MR"));
			layouts = DicomFilteredAnnotationLayoutStore.Instance.FilteredLayouts;
			Assert.AreEqual(1, layouts.Count);

			layouts = new List<DicomFilteredAnnotationLayout>();
			layouts.Clear();
			layouts.Add(CreateLayout("testLayout1", "Dicom.MR", "MR"));
			layouts.Add(CreateLayout("testLayout2", "Dicom.MG", "MG"));
			layouts.Add(CreateLayout("testLayout3", "Dicom.CT", "CT"));
			layouts.Add(CreateLayout("testLayout4", "Dicom.PT", "PT"));

			DicomFilteredAnnotationLayoutStore.Instance.Update(layouts);

			layouts = DicomFilteredAnnotationLayoutStore.Instance.FilteredLayouts;
			Assert.AreEqual(4, layouts.Count);

			ResourceResolver resolver = new ResourceResolver(this.GetType().Assembly);
			using (Stream stream = resolver.OpenResource("DicomFilteredAnnotationLayoutStoreDefaults.xml"))
			{
				StreamReader reader = new StreamReader(stream);
				DicomFilteredAnnotationLayoutStoreSettings.Default.FilteredLayoutSettingsXml = reader.ReadToEnd();
			}

			layouts = DicomFilteredAnnotationLayoutStore.Instance.FilteredLayouts;
			Assert.AreEqual(_countLayoutsInDicomFilteredLayoutStoreXml, layouts.Count);

			DicomFilteredAnnotationLayout layout = DicomFilteredAnnotationLayoutStore.Instance.GetFilteredLayout("Dicom.Filtered.MR");
			layout = CopyLayout(layout, "Dicom.Filtered.RT");
			layout.Filters[0] = new KeyValuePair<string,string>("Modality", "RT");

			DicomFilteredAnnotationLayoutStore.Instance.Update(layout);
			layouts = DicomFilteredAnnotationLayoutStore.Instance.FilteredLayouts;
			Assert.AreEqual(_countLayoutsInDicomFilteredLayoutStoreXml + 1, layouts.Count);

			layout = DicomFilteredAnnotationLayoutStore.Instance.GetFilteredLayout("Dicom.Filtered.RT");
			Assert.IsNotNull(layout);

			DicomFilteredAnnotationLayoutStore.Instance.RemoveFilteredLayout("Dicom.Filtered.RT");
			layouts = DicomFilteredAnnotationLayoutStore.Instance.FilteredLayouts;
			Assert.AreEqual(_countLayoutsInDicomFilteredLayoutStoreXml, layouts.Count);

			layout = DicomFilteredAnnotationLayoutStore.Instance.GetFilteredLayout("Dicom.Filtered.RT");
			Assert.IsNull(layout);

			layout = DicomFilteredAnnotationLayoutStore.Instance.GetFilteredLayout("Dicom.Filtered.MR");
			Assert.IsNotNull(layout);

			layouts = new List<DicomFilteredAnnotationLayout>();
			layouts.Clear();
			layouts.Add(CreateLayout("Dicom.Filtered.RT", "Dicom.RT", "RT"));
			layouts.Add(CreateLayout("Dicom.Filtered.SC", "Dicom.SC", "SC"));
			layouts.Add(CreateLayout("Dicom.Filtered.US", "Dicom.US", "US"));
			layouts.Add(CreateLayout("Dicom.Filtered.ES", "Dicom.ES", "ES"));

			DicomFilteredAnnotationLayoutStore.Instance.Update(layouts);

			layouts = DicomFilteredAnnotationLayoutStore.Instance.FilteredLayouts;
			Assert.AreEqual(_countLayoutsInDicomFilteredLayoutStoreXml + 4, layouts.Count);

			DicomFilteredAnnotationLayoutStore.Instance.RemoveFilteredLayout("Dicom.Filtered.RT");
			layouts = DicomFilteredAnnotationLayoutStore.Instance.FilteredLayouts;
			Assert.AreEqual(_countLayoutsInDicomFilteredLayoutStoreXml + 3, layouts.Count);

			DicomFilteredAnnotationLayoutStore.Instance.RemoveFilteredLayout("Dicom.Filtered.SC");
			layouts = DicomFilteredAnnotationLayoutStore.Instance.FilteredLayouts;
			Assert.AreEqual(_countLayoutsInDicomFilteredLayoutStoreXml + 2, layouts.Count);

			layout = DicomFilteredAnnotationLayoutStore.Instance.GetFilteredLayout("Dicom.Filtered.AllMatch");
			Assert.IsNotNull(layout);
			Assert.AreEqual(0, layout.Filters.Count);

			layout = DicomFilteredAnnotationLayoutStore.Instance.GetFilteredLayout("Dicom.Filtered.MR");
			Assert.AreEqual(1, layout.Filters.Count);
		}
コード例 #9
0
		/// <summary>
		/// Gets the icon for the <see cref="ApplicationTheme"/>.
		/// </summary>
		/// <returns>A new <see cref="Stream"/> for the icon.</returns>
		/// <seealso cref="Icon"/>
		public Stream GetIcon()
		{
			if (string.IsNullOrEmpty(_providers[0].Icon))
				return null;

			var resourceResolver = new ResourceResolver(_providers[0].GetType(), false);
			return resourceResolver.OpenResource(_providers[0].Icon);
		}
コード例 #10
0
		private static PaletteColorLut CreateFromColorPaletteSopInstanceXml(string resourceName)
		{
			try
			{
				var resourceResolver = new ResourceResolver(Assembly.GetExecutingAssembly());
				using (var xmlStream = resourceResolver.OpenResource(resourceName))
				{
					var xmlDocument = new XmlDocument();
					xmlDocument.Load(xmlStream);
					var docRootNode = CollectionUtils.FirstElement(xmlDocument.GetElementsByTagName("ClearCanvasColorPaletteDefinition")) as XmlElement;
					if (docRootNode != null)
					{
						var instanceNode = CollectionUtils.FirstElement(docRootNode.GetElementsByTagName("Instance")) as XmlElement;
						if (instanceNode != null)
						{
							var instanceXml = new InstanceXml(instanceNode, null);
							return Create(instanceXml.Collection);
						}
					}
				}
			}
			catch (Exception ex)
			{
				Platform.Log(LogLevel.Debug, ex, "Failed to load embedded standard color palette SOP from resource {0}", resourceName);
			}
			return null;
		}
コード例 #11
0
		public void Test()
		{
			List<IAnnotationItem> annotationItems = new List<IAnnotationItem>();

			AnnotationLayoutStore.Instance.Clear();

			IList<StoredAnnotationLayout> layouts = AnnotationLayoutStore.Instance.GetLayouts(annotationItems);
			Assert.AreEqual(0, layouts.Count);

			AnnotationLayoutStore.Instance.Update(this.CreateLayout("testLayout1"));
			layouts = AnnotationLayoutStore.Instance.GetLayouts(annotationItems);
			Assert.AreEqual(1, layouts.Count);

			layouts = new List<StoredAnnotationLayout>();
			layouts.Clear();
			layouts.Add(CreateLayout("testLayout1"));
			layouts.Add(CreateLayout("testLayout2"));
			layouts.Add(CreateLayout("testLayout3"));
			layouts.Add(CreateLayout("testLayout4"));

			AnnotationLayoutStore.Instance.Update(layouts);

			layouts = AnnotationLayoutStore.Instance.GetLayouts(annotationItems);
			Assert.AreEqual(4, layouts.Count);

			ResourceResolver resolver = new ResourceResolver(this.GetType().Assembly);
			using (Stream stream = resolver.OpenResource("AnnotationLayoutStoreDefaults.xml"))
			{
				AnnotationLayoutStoreSettings.Default.LayoutSettingsXml = new XmlDocument();
				AnnotationLayoutStoreSettings.Default.LayoutSettingsXml.Load(stream);
			}

			layouts = AnnotationLayoutStore.Instance.GetLayouts(annotationItems);
			int xmlLayoutCount = layouts.Count;

			StoredAnnotationLayout layout = AnnotationLayoutStore.Instance.GetLayout("Dicom.OT", annotationItems);
			layout = CopyLayout(layout, "Dicom.OT.Copied");

			AnnotationLayoutStore.Instance.Update(layout);
			layouts = AnnotationLayoutStore.Instance.GetLayouts(annotationItems);
			Assert.AreEqual(xmlLayoutCount + 1, layouts.Count);

			layout = AnnotationLayoutStore.Instance.GetLayout("Dicom.OT.Copied", annotationItems);
			Assert.IsNotNull(layout);
			
			AnnotationLayoutStore.Instance.RemoveLayout("Dicom.OT.Copied");
			layouts = AnnotationLayoutStore.Instance.GetLayouts(annotationItems);
			Assert.AreEqual(xmlLayoutCount, layouts.Count);

			layout = AnnotationLayoutStore.Instance.GetLayout("Dicom.OT.Copied", annotationItems);
			Assert.IsNull(layout);

			layout = AnnotationLayoutStore.Instance.GetLayout("Dicom.OT", annotationItems);
			Assert.IsNotNull(layout);

			layouts = new List<StoredAnnotationLayout>(); 
			layouts.Clear();
			layouts.Add(CreateLayout("testLayout1"));
			layouts.Add(CreateLayout("testLayout2"));
			layouts.Add(CreateLayout("testLayout3"));
			layouts.Add(CreateLayout("testLayout4"));

			AnnotationLayoutStore.Instance.Update(layouts);

			layouts = AnnotationLayoutStore.Instance.GetLayouts(annotationItems);
			Assert.AreEqual(xmlLayoutCount + 4, layouts.Count);

			AnnotationLayoutStore.Instance.RemoveLayout("testLayout1");
			layouts = AnnotationLayoutStore.Instance.GetLayouts(annotationItems);
			Assert.AreEqual(xmlLayoutCount + 3, layouts.Count);

			AnnotationLayoutStore.Instance.RemoveLayout("testLayout2");
			layouts = AnnotationLayoutStore.Instance.GetLayouts(annotationItems);
			Assert.AreEqual(xmlLayoutCount + 2, layouts.Count);

			layout = AnnotationLayoutStore.Instance.GetLayout("Dicom.OT", annotationItems);
			Assert.IsNotNull(layout);

			layout = AnnotationLayoutStore.Instance.GetLayout("testLayout3", annotationItems); 
			Assert.AreEqual(1, layout.AnnotationBoxGroups.Count);

			layout = AnnotationLayoutStore.Instance.GetLayout("Dicom.OT", annotationItems);
			layout = CopyLayout(layout, "testLayout3");
			AnnotationLayoutStore.Instance.Update(layout);
			layout = AnnotationLayoutStore.Instance.GetLayout("testLayout3", annotationItems);
			Assert.AreEqual(5, layout.AnnotationBoxGroups.Count);
		}
コード例 #12
0
ファイル: SplashScreen.cs プロジェクト: nhannd/Xian
		private void AddAssemblyIconToImage(Assembly pluginAssembly)
		{
			object[] pluginAttributes = pluginAssembly.GetCustomAttributes(typeof(PluginAttribute), false);

			foreach (PluginAttribute pluginAttribute in pluginAttributes)
			{
				if (!string.IsNullOrEmpty(pluginAttribute.Icon))
				{
					try
					{
						IResourceResolver resolver = new ResourceResolver(pluginAssembly);
						Bitmap icon = new Bitmap(resolver.OpenResource(pluginAttribute.Icon));

						// Burn the icon into the background image
						Graphics g = Graphics.FromImage(this.BackgroundImage);

						int positionX = _nextIconPositionX;
						int positionY = _nextIconPositionY;

						g.DrawImage(icon, positionX, positionY, IconWidth, IconHeight);

						// Burn the icon's name and version into the background image
						string pluginName = pluginAttribute.Name;
						string pluginVersion = string.Empty;
						try
						{
							FileVersionInfo versionInfo = FileVersionInfo.GetVersionInfo(pluginAssembly.Location);
							pluginVersion = versionInfo.ProductVersion;
						}
						catch
						{
						}

						Font font = new Font("Tahoma", 10F, GraphicsUnit.Pixel);
						Brush brush = new SolidBrush(Color.FromArgb(50, 50, 50));

						StringFormat format = new StringFormat();
						format.Alignment = StringAlignment.Center;

						Rectangle layoutRect = new Rectangle(positionX - IconPaddingX / 2, positionY + IconHeight, IconWidth + IconPaddingX, IconTextHeight);

						g.DrawString(pluginName + "\n" + pluginVersion, font, brush, layoutRect, format);

						font.Dispose();
						brush.Dispose();

						g.Dispose();

						// Advance to the next icon position within the plugin rectangle
						_nextIconPositionX += (IconWidth + IconPaddingX);
						if (_nextIconPositionX + IconWidth + IconPaddingX / 2 > _pluginIconsRectangle.Right)
						{
							_nextIconPositionX = _pluginIconsRectangle.Left + IconPaddingX / 2;
							_nextIconPositionY += IconPaddingY + IconHeight + IconTextHeight;
						}

						this.Invalidate();
					}
					catch
					{
					}
				}
			}
		}
コード例 #13
0
		// [Test]
		internal void ExportDefaultLayoutConfigurationData()
		{
			// this method exports the default layout in EnterpriseServer format

			var configBodyData = new StringBuilder();
			using (var configBodyDataWriter = new StringWriter(configBodyData))
			{
				var configBody = new XmlDocument();
				{
					var sbValue = new StringBuilder();
					using (var writer = new StringWriter(sbValue))
					{
						var resourceResolver = new ResourceResolver(typeof (AnnotationLayoutStoreTests).Assembly);
						var defaultLayout = new XmlDocument();
						defaultLayout.Load(resourceResolver.OpenResource("AnnotationLayoutStoreDefaults.xml"));
						defaultLayout.Save(writer);
					}

					var cdata = configBody.CreateCDataSection(sbValue.ToString());

					var value = configBody.CreateElement("value");
					value.AppendChild(cdata);

					var setting = configBody.CreateElement("setting");
					setting.SetAttribute("name", "LayoutSettingsXml");
					setting.AppendChild(value);

					var settings = configBody.CreateElement("settings");
					settings.AppendChild(setting);

					configBody.AppendChild(settings);
				}
				configBody.Save(configBodyDataWriter);
			}

			var configDocument = new XmlDocument();

			var nameElement = configDocument.CreateElement("Name");
			nameElement.InnerText = typeof (AnnotationLayoutStoreSettings).FullName ?? string.Empty;

			var versionElement = configDocument.CreateElement("Version");
			versionElement.InnerText = string.Format("{0:00000}.{1:00000}", ProductInformation.Version.Major, ProductInformation.Version.Minor);

			var bodyElement = configDocument.CreateElement("Body");
			bodyElement.InnerText = configBodyData.ToString();

			var configItem = configDocument.CreateElement("item");
			configItem.AppendChild(nameElement);
			configItem.AppendChild(versionElement);
			configItem.AppendChild(bodyElement);

			var rootConfigurations = configDocument.CreateElement("Configurations");
			rootConfigurations.SetAttribute("type", "array");
			rootConfigurations.AppendChild(configItem);

			configDocument.AppendChild(rootConfigurations);
			configDocument.Save(string.Format("{0}.xml", typeof (AnnotationLayoutStoreSettings).FullName));
		}
コード例 #14
0
		public void TestDefaultLayout()
		{
			var resourceResolver = new ResourceResolver(typeof (AnnotationLayoutStoreTests).Assembly);

			var xmlDocument = new XmlDocument();
			xmlDocument.Load(resourceResolver.OpenResource("AnnotationLayoutStoreDefaults.xml"));

			var layouts = xmlDocument.SelectNodes("/annotation-configuration/annotation-layouts/annotation-layout");
			Assert.IsNotNull(layouts, "/annotation-configuration/annotation-layouts/annotation-layout");

			foreach (var layout in layouts.OfType<XmlElement>())
			{
				var layoutId = layout.GetAttribute("id");
				Assert.IsNotEmpty(layoutId, "/annotation-configuration/annotation-layouts/annotation-layout/@id");

				var groups = layout.SelectNodes("annotation-box-groups/annotation-box-group");
				Assert.IsNotNull(groups, "[{0}]: annotation-box-groups/annotation-box-group", layoutId);

				foreach (var group in groups.OfType<XmlElement>())
				{
					var groupId = group.GetAttribute("id");
					Assert.IsNotEmpty(groupId, "[{0}]: annotation-box-groups/annotation-box-group/@id", layoutId);

					var boxes = group.SelectNodes("annotation-boxes/annotation-box");
					Assert.IsNotNull(boxes, "[{0}/{1}]: annotation-boxes/annotation-box", layoutId, groupId);

					var rectangles = new List<RectangleF>();
					foreach (var box in boxes.OfType<XmlElement>())
					{
						var rectangleString = box.GetAttribute("normalized-rectangle");
						Assert.IsNotEmpty(rectangleString, "[{0}/{1}]: annotation-boxes/annotation-box/@normalized-rectangle", layoutId, groupId);

						var rectangleStringParts = rectangleString.Split('\\');
						Assert.IsTrue(rectangleStringParts.Length == 4, "[{0}/{1}]: '{2}' does not have 4 elements", layoutId, groupId, rectangleString);

						var rectangleComponents = rectangleStringParts.Select(s => AssertParseOrFail(s, "[{0}/{1}]: '{2}' failed to parse as 4 valid values between 0 and 1", layoutId, groupId, rectangleString)).ToArray();

						Assert.IsTrue(rectangleComponents.All(d => d >= 0 && d <= 1), "[{0}/{1}]: '{2}' failed to parse as 4 valid values between 0 and 1", layoutId, groupId, rectangleString);

						var rectangle = RectangleF.FromLTRB(rectangleComponents[0], rectangleComponents[1], rectangleComponents[2], rectangleComponents[3]);

						Assert.IsTrue(rectangle.Width > 0 && rectangle.Height > 0, "[{0}/{1}]: '{2}' should define a rectangle with positive width and height", layoutId, groupId, rectangleString);

						rectangles.Add(rectangle);
					}

					// skip overlap tests for all directional marker groups
					if (groupId == "DirectionalMarkers") continue;

					rectangles.Sort((x, y) => x.Top.CompareTo(y.Top));
					for (var n = 1; n < rectangles.Count; ++n)
					{
						Assert.IsTrue(rectangles[n].Top >= rectangles[n - 1].Bottom, "[{0}/{1}]: Found a vertically overlapping rectangle", layoutId, groupId);
					}
				}
			}
		}