private void RefreshHeaderLabels()
        {
            if (BusyPopulatingColumns)
            {
                return;
            }

            if (dataGridViewX1.Columns.Count == 0)
            {
                return;
            }

            int fullWidth = dataGridViewX1.RowHeadersVisible ? dataGridViewX1.RowHeadersWidth : 0;

            foreach (DataGridViewColumn col in dataGridViewX1.Columns)
            {
                if (!col.Frozen)
                {
                    fullWidth += col.Width;
                }
            }
            int horzOffset           = Convert.ToInt32(dataGridViewX1.HorizontalScrollingOffsetValue * fullWidth);
            int headerRowHeight      = dataGridViewX1.ColumnHeadersHeight;
            int realColumnIndex      = 0;
            int widthPrevCols        = dataGridViewX1.RowHeadersVisible ? dataGridViewX1.RowHeadersWidth : 0;
            int visibleGridWidth     = dataGridViewX1.Width;
            int widthOfFrozenColumns = 0;

            if (dataGridViewX1.VerticalScrollbarVisible)
            {
                visibleGridWidth -= dataGridViewX1.VerticalScrollbarWidth;
            }

            if (ShowDeleteColumn && dataGridViewX1.Columns.Count > 0)
            {
                widthPrevCols   = dataGridViewX1.Columns[0].Width;
                realColumnIndex = 1;
            }
            for (int i = 0; i < Columns.Count; i++)
            {
                int colWidth = dataGridViewX1.Columns[realColumnIndex].Width;

                //if (Columns[i].IsNullable)
                //    colWidth += dataGridViewX1.Columns[realColumnIndex + 1].Width;

                Rectangle rectColumn1 = new Rectangle();

                if ((!FrozenColumnIndex.HasValue || FrozenColumnIndex.Value < i + 1) &&
                    (widthPrevCols + colWidth < horzOffset ||
                     widthPrevCols >= horzOffset + visibleGridWidth))
                {
                    widthPrevCols += colWidth;

                    // This column is not in the current view window
                    //if (Columns[i].IsNullable)
                    //    realColumnIndex += 2;
                    //else
                    realColumnIndex += 1;

                    Labels[i].Visible = false;
                    continue;
                }
                if (FrozenColumnIndex.HasValue && i + 1 <= FrozenColumnIndex.Value)
                {
                    // Column is fully displayed
                    rectColumn1 = new Rectangle(widthPrevCols + horzOffset, 0, colWidth, headerRowHeight);

                    if (i + 1 == FrozenColumnIndex.Value)
                    {
                        widthOfFrozenColumns += widthPrevCols + colWidth;                        // +2;
                        //widthPrevCols = 0;
                        //    //horzOffset = widthPrevCols + horzOffset + colWidth;
                        //    widthPrevCols = widthPrevCols + horzOffset;
                    }
                }
                else
                {
                    if (widthPrevCols < widthOfFrozenColumns + horzOffset)
                    {
                        colWidth         -= widthOfFrozenColumns + horzOffset - widthPrevCols;    // -4;
                        rectColumn1.X     = widthOfFrozenColumns + horzOffset;
                        widthPrevCols     = widthOfFrozenColumns + horzOffset;                    // +2;
                        rectColumn1.Width = colWidth;
                    }
                    else if (widthPrevCols + colWidth > horzOffset + visibleGridWidth)
                    {
                        colWidth          = horzOffset + visibleGridWidth - widthPrevCols;
                        rectColumn1.X     = widthPrevCols;
                        rectColumn1.Width = colWidth;
                    }
                    else
                    {
                        rectColumn1 = new Rectangle(widthPrevCols, 0, colWidth, headerRowHeight);
                    }
                }
                rectColumn1.Height = headerRowHeight / 2;
                rectColumn1.X     += 2;
                rectColumn1.Y      = 1;
                rectColumn1.Width -= 4;

                widthPrevCols += colWidth;
                //realColumnIndex += Columns[i].IsNullable ? 2 : 1;
                realColumnIndex += 1;

                if (rectColumn1.Width <= 0)
                {
                    Labels[i].Visible = false;
                    continue;
                }
                Labels[i].Size    = rectColumn1.Size;
                Labels[i].Top     = dataGridViewX1.Top + rectColumn1.Height;
                Labels[i].Left    = rectColumn1.Left - horzOffset + dataGridViewX1.Left;
                Labels[i].Visible = true;
                Labels[i].Refresh();
            }

            #region Categories
            for (int catCounter = CategoryLabels.Count - 1; catCounter >= 0; catCounter--)
            {
                LabelX catLabel = CategoryLabels[catCounter];
                int    left     = -1;
                int    width    = 0;
                bool   found    = false;

                for (int i = 0; i < Columns.Count; i++)
                {
                    if (Columns[i].CategoryName == catLabel.Text)
                    {
                        found = true;

                        if (left < 0)
                        {
                            left = Labels[i].Left;
                        }

                        if (Labels[i].Width > 0)
                        {
                            width = Labels[i].Right - left;
                        }
                    }
                    else if (found)
                    {
                        break;
                    }
                }
                catLabel.Left = left;

                if (left > 0)
                {
                    width += 2;
                }

                catLabel.Width   = width;
                catLabel.Top     = dataGridViewX1.Top;
                catLabel.Height  = headerRowHeight / 2;
                catLabel.Visible = true;
                catLabel.BringToFront();
                catLabel.Refresh();
            }
            #endregion
        }
        private void Populate()
        {
            foreach (LabelX label in Labels)
                panelEx1.Controls.Remove(label);

            foreach (ComboBoxEx combo in ComboBoxes)
                panelEx1.Controls.Remove(combo);

            Labels.Clear();
            ComboBoxes.Clear();
            textBoxComponentName.Text = "";

            //labelComponentName.Text = string.Format("{0} fields", ComponentSpecification.Name);
            labelComponentName.Text = "Component fields";

            if (Entity == null)
            {
                pictureComponent.Visible = false;
                labelComponentName.Visible = false;
                pictureEntity.Visible = false;
                //labelColumns.Visible = false;
                labelColumns.Left = Gap;
                labelColumns.Text = "Select entity:";
                comboBoxExEntities.Left = labelColumns.Right + Gap;
                comboBoxExEntities.Visible = true;
                comboBoxExEntities.DisplayMember = "Name";
                comboBoxExEntities.Items.Clear();
                comboBoxExEntities.Items.AddRange(ComponentSpecification.EntitySet.Entities.ToArray());
                comboBoxExEntities.Top = Gap;// pictureBox1.Bottom + Gap;// labelColumns.Top;
                labelColumns.Top = comboBoxExEntities.Top;
                textBoxComponentName.Text = "";
                textBoxComponentName.Visible = false;
                labelComponentNameInput.Visible = false;
                int newWidth = comboBoxExEntities.Right + Gap;

                if (this.Width != newWidth)
                    this.Left = this.Left - (this.Width - newWidth);

                this.Width = newWidth;
            }
            else
            {
                textBoxComponentName.Visible = true;
                labelComponentNameInput.Visible = true;
                pictureComponent.Visible = true;
                labelComponentName.Visible = true;
                pictureEntity.Visible = true;
                labelColumns.Top = pictureEntity.Top;
                labelColumns.Visible = true;
                comboBoxExEntities.Visible = false;
                labelColumns.Text = "Mapped columns";

                //if (string.IsNullOrEmpty(textBoxComponentName.Text))
                //    textBoxComponentName.Text = "Not set";
            }
            if (ComponentSpecification != null)
            {
                comboBoxComponents.Visible = false;
                labelSelect.Visible = false;
                textBoxComponentName.Top = Gap;
                labelComponentNameInput.Top = Gap;

                ArchAngel.Providers.EntityModel.Model.EntityLayer.Component component = ComponentSpecification.GetImplementationFor(Entity);

                if (component != null)
                    textBoxComponentName.Text = component.Name;
            }
            else
            {
                comboBoxComponents.DisplayMember = "Name";

                foreach (var comp in Entity.EntitySet.ComponentSpecifications)
                    comboBoxComponents.Items.Add(comp);

                //if (comboBoxComponents.Items.Count > 0)
                //    comboBoxComponents.SelectedIndex = 0;

                comboBoxComponents.Top = Gap;
                labelSelect.Top = Gap;
                textBoxComponentName.Top = comboBoxComponents.Bottom + Gap * 3;
                labelComponentNameInput.Top = textBoxComponentName.Top;
            }

            int top = labelComponentName.Bottom + Gap * 2;

            if (Entity != null)
            {
                if (ComponentSpecification != null)
                {
                    foreach (var prop in ComponentSpecification.Properties)
                        Labels.Add(new LabelX() { Text = string.Format("{0}  [{1}]", prop.Name, prop.Type) });

                    ArchAngel.Providers.EntityModel.Model.EntityLayer.Component component = ComponentSpecification.GetImplementationFor(Entity);
                    int numTables = Entity.MappedTables().Count();

                    if (component != null)
                    {
                        foreach (var prop in component.Properties)
                        {
                            List<Column> columns = GetColumnsOfType(Entity, prop.RepresentedProperty.Type);
                            ComboBoxEx combo = new ComboBoxEx();
                            combo.Width = 200;

                            foreach (Column column in columns)
                            {
                                if (numTables > 1)
                                    combo.Items.Add(string.Format("{0}.{1}  [{2}]", column.Parent.Name, column.Name, column.OriginalDataType));
                                else
                                    combo.Items.Add(string.Format("{0}  [{1}]", column.Name, column.OriginalDataType));
                            }
                            combo.DropDownStyle = ComboBoxStyle.DropDownList;
                            IColumn col = prop.MappedColumn();

                            if (col != null)
                            {
                                if (numTables > 1)
                                    combo.SelectedItem = string.Format("{0}.{1}  [{2}]", col.Parent.Name, col.Name, col.OriginalDataType);
                                else
                                    combo.SelectedItem = string.Format("{0}  [{1}]", col.Name, col.OriginalDataType);
                            }
                            ComboBoxes.Add(combo);
                        }
                    }
                    else
                    {
                        // Get the properties of the component specification
                        foreach (var prop in ComponentSpecification.Properties)
                        {
                            List<Column> columns = GetColumnsOfType(Entity, prop.Type);
                            ComboBoxEx combo = new ComboBoxEx();
                            combo.Width = 200;

                            foreach (Column column in columns)
                            {
                                if (numTables > 1)
                                    combo.Items.Add(string.Format("{0}.{1}  [{2}]", column.Parent.Name, column.Name, column.OriginalDataType));
                                else
                                    combo.Items.Add(string.Format("{0}  [{1}]", column.Name, column.OriginalDataType));
                            }
                            combo.DropDownStyle = ComboBoxStyle.DropDownList;
                            ComboBoxes.Add(combo);
                        }
                    }
                }

                int maxLeftColumnWidth = Math.Max(GetWidestLabel(Labels), Gap + pictureComponent.Width + labelComponentName.Width);
                int maxRightColumnWidth = Math.Max(GetWidestComboBox(ComboBoxes), pictureEntity.Width + labelColumns.Width + Gap);
                Graphics labelGraphics = null;

                if (ComponentSpecification != null)
                {
                    for (int i = 0; i < ComponentSpecification.Properties.Count; i++)
                    {
                        LabelX label = Labels[i];
                        panelEx1.Controls.Add(label);
                        //label.BackColor = Color.Transparent;
                        //label.ForeColor = Color.White;
                        if (labelGraphics == null)
                            labelGraphics = Graphics.FromHwnd(label.Handle);

                        SizeF size = Graphics.FromHwnd(label.Handle).MeasureString(label.Text, label.Font);
                        label.Height = Convert.ToInt32(size.Height) + 1;
                        label.Width = Convert.ToInt32(size.Width) + 1;
                        label.Top = top;
                        label.Left = Math.Max(Gap, Gap + maxLeftColumnWidth - label.Width);
                        label.BringToFront();

                        if (Entity != null)
                        {
                            ComboBoxEx comboBox = ComboBoxes[i];
                            panelEx1.Controls.Add(comboBox);
                            comboBox.Top = top;
                            comboBox.Left = Gap * 10 + maxLeftColumnWidth + 60;
                            comboBox.Width = maxRightColumnWidth;
                            comboBox.BringToFront();

                            label.Top = top + comboBox.Height / 2 - label.Height / 2;
                            top += comboBox.Height + 2;
                        }
                        else
                            top += label.Height + 2;
                    }
                }

                pictureComponent.Left = Gap;
                labelComponentName.Left = pictureComponent.Right;
                pictureEntity.Left = Gap * 10 + maxLeftColumnWidth + 60;
                labelColumns.Left = pictureEntity.Right;
                comboBoxExEntities.Left = pictureEntity.Right;
                comboBoxExEntities.Top = labelColumns.Top;
                int newWidth = Gap * 10 + maxLeftColumnWidth + 60 + maxRightColumnWidth + Gap * 3;

                if (this.Width != newWidth)
                    this.Left = this.Left - (this.Width - newWidth);

                this.Width = newWidth;
            }
            this.Height = top + Gap * 15 + buttonOk.Height;
        }
        /// <summary>
        /// This should only be called when populating the Grid for the first time,
        /// or when the number of columns changes.
        /// </summary>
        private void ResetLabelCache()
        {
            foreach (LabelX label in Labels)
            {
                this.Controls.Remove(label);
            }

            foreach (LabelX label in CategoryLabels)
            {
                this.Controls.Remove(label);
            }

            Labels.Clear();
            CategoryLabels.Clear();

            if (Columns.Count > 0)
            {
                LabelX catLabel = new LabelX();
                catLabel.BackColor                              = Color.Transparent;
                catLabel.Text                                   = Columns[0].CategoryName;
                catLabel.TextAlignment                          = StringAlignment.Center;
                catLabel.BackgroundStyle.BackColor              = Columns[0].CategoryBackColor;   // Color.FromArgb(82, 128, 208);
                catLabel.BackgroundStyle.BackColor2             = Columns[0].CategoryBackColor2;  // Color.Navy;
                catLabel.ForeColor                              = Columns[0].CategoryForeColor;
                catLabel.BackgroundStyle.BackColorGradientAngle = 90;
                //catLabel.ForeColor = Color.White;
                catLabel.Visible = false;

                this.Controls.Add(catLabel);
                CategoryLabels.Add(catLabel);
                catLabel.BringToFront();
            }
            for (int i = 0; i < Columns.Count; i++)
            {
                LabelX label = new LabelX();
                label.BackColor                              = Color.Transparent;
                label.Text                                   = Columns[i].Text;
                label.TextAlignment                          = StringAlignment.Center;
                label.BackgroundStyle.BackColor              = Color.FromArgb(100, 100, 100);
                label.BackgroundStyle.BackColor2             = Color.FromArgb(8, 8, 8);
                label.BackgroundStyle.BackColorGradientAngle = 90;
                label.ForeColor                              = Color.White;
                label.Visible                                = false;

                if (Columns[i].IsLink)
                {
                    label.MouseEnter += new EventHandler(label_MouseEnter);
                    label.MouseLeave += new EventHandler(label_MouseLeave);
                }
                label.MouseClick += new MouseEventHandler(label_MouseClick);
                label.Tag         = i.ToString();

                this.Controls.Add(label);
                Labels.Add(label);
                label.BringToFront();

                if (Columns[i].CategoryName != CategoryLabels[CategoryLabels.Count - 1].Text)
                {
                    LabelX catLabel = new LabelX();
                    catLabel.BackColor                              = Color.Transparent;
                    catLabel.Text                                   = Columns[i].CategoryName;
                    catLabel.TextAlignment                          = StringAlignment.Center;
                    catLabel.BackgroundStyle.BackColor              = Columns[i].CategoryBackColor;
                    catLabel.BackgroundStyle.BackColor2             = Columns[i].CategoryBackColor2;
                    catLabel.BackgroundStyle.BackColorGradientAngle = 90;
                    catLabel.ForeColor                              = Columns[i].CategoryForeColor;
                    catLabel.Visible                                = false;

                    this.Controls.Add(catLabel);
                    CategoryLabels.Add(catLabel);
                    catLabel.BringToFront();
                }
            }
        }