/// <summary> /// Returns a default radiopanel. /// This panel will try to fit into the second column, /// if not it will take a new line and spread over the whole width. /// </summary> /// <param name="position">Position of the Panel.</param> /// <param name="tag">Tag for the panel, containing data about the RadioButtons.</param> /// <returns></returns> private Panel CreateRadioPanel(Position position, SingleSelectionList tag) { Panel panel = new Panel(); panel.AutoSize = false; panel.Tag = tag; panel.TabIndex = position.NextTabIndex; panel.Name = "radioPanel" + position.TabIndex.ToString(); bool takeNewLine = false; // needed to know the columnwidth when calculating the expected height List <RadioButton> items = new List <RadioButton>(tag.Items.Count); for (int i = 0; i < tag.Items.Count; i++) { RadioButton btn = new RadioButton(); btn.AutoSize = false; btn.TabIndex = position.NextTabIndex; btn.Name = "radioButton" + position.TabIndex.ToString(); btn.Text = tag.Items[i].Evaluate(); btn.CheckAlign = ContentAlignment.TopLeft; btn.Checked = (i == tag.Selected); btn.CheckedChanged += _singleSelectionListChange; btn.Tag = i; SetHelp(btn, tag.Help.Evaluate()); items.Add(btn); // see if we should take a new line (add 30 for the radiobutton and to cover too small measurements) btn.Width = (int)(btn.CreateGraphics().MeasureString(btn.Text, btn.Font).Width + 30); if (btn.Width > position.WidthColumnTwo) { takeNewLine = true; } } // we can't calculate the height before, because we don't know the available width (depends on takeNewLine) // => second loop is needed Position nPos = (Position)position.Clone(); nPos.LinePosition = 0; int width; // values depend on the new line, we can't use Position if (takeNewLine) { width = position.Width - position.Margin; } else { width = position.WidthColumnTwo; } foreach (RadioButton btn in items) { btn.Location = new Point(0, nPos.LinePosition); if (btn.Width > width) // doesn't fit in the column, we'll have to calculate the height to avoid overlapping controls { btn.MaximumSize = new Size(width, (int)((double)btn.Width / width * btn.Height + position.LineHeight - btn.Height)); btn.MinimumSize = btn.MaximumSize; btn.AutoSize = true; nPos.LinePosition += btn.MaximumSize.Height; } else { nPos.LinePosition += nPos.LineHeight; } panel.Controls.Add(btn); } panel.Size = new Size(width, nPos.LinePosition); // Locate and return the panel if (!takeNewLine) { panel.Location = new Point(position.StartColumnTwo, position.LinePosition); } else { position.LinePosition += position.ItemHeight; panel.Location = new Point(position.StartColumnOne + position.Margin, position.LinePosition); } return(panel); }
/// <summary> /// Incrementally finds the 'perfect' size of this GroupBox, increasing size /// (if returnDesiredWidth or -Height are true) reverse-logarithmically. [i.e. It /// increases based on the number of non-visible controls.] /// /// NOTE: Any function that calls this recursively should suspend layout before calling /// </summary> /// <param name="returnDesiredHeight">Indicates that Height will be variable. If true, suspend layout before calling this function.</param> /// <param name="returnDesiredWidth">Indicates that Width will be variable. If true, suspend layout before calling this function.</param> /// <param name="newDesiredSize">The desired Size of this GroupBox.</param> /// <returns></returns> private Size ToolBoxGroupBox_LayoutHelper(bool returnDesiredHeight, bool returnDesiredWidth, Size newDesiredSize) { // Documents the lastButton we were doing the layout on RadioButton lastButton = null; int leftMargin = 0; int rightMargin = this.Width - LeftRight_Padding; int hiddenControlCount = 0; // Foreach radio button, do layout foreach (Control testControl in this.Controls) { // If (at design time) we have something other than a RadioButton, report, remove, and continue... if (!(testControl.GetType().AssemblyQualifiedName == (new RadioButton()).GetType().AssemblyQualifiedName)) { MessageBox.Show(this, "Invalid Windows control added. Removing invalid control, " + testControl.ToString()); this.Controls.Remove(testControl); continue; } // Cast into our RadioButton RadioButton currentButton = (RadioButton)testControl; // Make sure our FlatStyle will look good on XP currentButton.FlatStyle = FlatStyle.System; // Set our width based on how much text we have currentButton.Width = (int)(currentButton.CreateGraphics() .MeasureString(currentButton.Text, currentButton.Font).Width + 0.5f + RadioButtonText_Padding); // Make sure we have a minimum Width if (newDesiredSize.Width < currentButton.Width) { newDesiredSize.Width = currentButton.Width; } // If this is our first iteration... if (lastButton == null) { currentButton.Location = new Point(LeftRight_Padding, Top_Padding); leftMargin = currentButton.Location.X + currentButton.Width; this.bHidingControls = false; // Make sure our Height is a bare minimum if (newDesiredSize.Height < currentButton.Height) { newDesiredSize.Height = currentButton.Height + Top_Padding + Bottom_Padding; } } // Else, we are on the second control else { int x, y; // If our y is in bounds, assign it accordingly if ((lastButton.Location.Y + lastButton.Height + currentButton.Height) < (newDesiredSize.Height - Bottom_Padding)) { y = lastButton.Location.Y + lastButton.Size.Height; } // Else, y needs to be reset to the top of the GroupBox else { y = Top_Padding; } // Assign our x based on what we got for y: // If y has been reset, assign x as the next button over if (y == Top_Padding) { x = leftMargin; } else { x = lastButton.Location.X; } currentButton.Location = new Point(x, y); // If our button X coord and width exceed our leftMargin, document it if ((currentButton.Location.X + currentButton.Width) > leftMargin) { leftMargin = currentButton.Location.X + currentButton.Width; } // If we are out of bounds, make anything we iterate through invisible if (leftMargin > newDesiredSize.Width && newDesiredSize.Width != currentButton.Width) { currentButton.Visible = false; bHidingControls = true; ++hiddenControlCount; } else { currentButton.Visible = true; bHidingControls = false; } } // Document our last button for next iteration lastButton = currentButton; } // Now that we're done processing, return what we've found // If we want to return both desired variables, do so... //if( returnDesiredHeight && returnDesiredWidth ) { if (bHidingControls) { newDesiredSize.Width += HeightWidth_Increment * hiddenControlCount; newDesiredSize.Height += HeightWidth_Increment * hiddenControlCount; // Return the size based on the value we just created for newDesiredSize return(ToolBoxGroupBox_LayoutHelper(true, true, newDesiredSize)); } else { return(newDesiredSize); } } // Else, if we only want to return Height, do so... // else if( returnDesiredHeight && !returnDesiredWidth ) // { // if( bHidingControls ) // { // newDesiredSize.Width = this.Width; // newDesiredSize.Height += HeightWidth_Increment * hiddenControlCount; // return ToolBoxGroupBox_LayoutHelper( returnDesiredHeight, returnDesiredWidth, newDesiredSize ); // } // else // return new Size( this.Width, newDesiredSize.Height ); // } // // Else, if we only want to return Width, do so... // else if( !returnDesiredHeight && returnDesiredWidth ) // { // if( bHidingControls ) // { // newDesiredSize.Width += HeightWidth_Increment * hiddenControlCount; // newDesiredSize.Height = this.Height; // return ToolBoxGroupBox_LayoutHelper( returnDesiredHeight, returnDesiredWidth, newDesiredSize ); // } // else // return new Size( newDesiredSize.Width, this.Height ); // } // // Else, set this.Size and return it... // else // { // this.Size = newDesiredSize; // return this.Size; // } }