using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using TradeIdeas.Extensions; using TradeIdeas.TIProData; namespace TIProDevExtension.ValueEditor { public partial class ConstantEditor : Form { /// /// True means we always return a ConstantDataNode factory containing /// the selected constant. False means we return the constant as is. /// public bool WrapInDataNodeFactory { get { return wrapInConstantDataNocdeCheckBox.Checked; } set { wrapInConstantDataNocdeCheckBox.Checked = value; UpdateState(); } } /// /// True means the user can change WrapInDataNodeFactory with the /// check box. /// public bool UserControlsWrap { get { return wrapInConstantDataNocdeCheckBox.Enabled; } set { wrapInConstantDataNocdeCheckBox.Enabled = value; } } public bool UserControlsType { get { return nullRadioButton.Enabled; } set { nullRadioButton.Enabled = value; integerRadioButton.Enabled = value; doubleRadioButton.Enabled = value; stringRadioButton.Enabled = value; colorRadioButton.Enabled = value; selectColorButton.Enabled = value || colorRadioButton.Checked; } } /// /// This value is not defined if the user hits cancel. It might be null, or the /// last valid value a user entered, or anything else. /// public Object Result { get; private set; } /// /// I'm not sure if this is required. I copied this design from some WPF code. /// private bool _initialized; public ConstantEditor() { InitializeComponent(); _initialized = true; UpdateState(); } public ConstantEditor(Int64 initialValue) : this() { Result = initialValue; integerRadioButton.Checked = true; valueTextBox.Text = initialValue.ToString(); } public ConstantEditor(double initalValue) : this() { Result = initalValue; doubleRadioButton.Checked = true; valueTextBox.Text = initalValue.ToString(); } public ConstantEditor(string initialValue) : this() { System.Diagnostics.Debug.Assert(null != initialValue); Result = initialValue; stringRadioButton.Checked = true; valueTextBox.Text = initialValue; } /// /// Load a color into the display, so someone can hit OK to accept it. /// Note that the original value / broadcastValue might be a color or a /// ConstantDataNode containing a color. We don't know what to expect /// at this time because no one has had a chance to set the check boxes. /// /// /// Load this into the samples on this window. /// public ConstantEditor(Color initialValue) : this() { Result = initialValue; colorRadioButton.Checked = true; WriteColor(initialValue); } /// /// Pretty much any change the user makes to the GUI. Radio buttons, check boxes, /// text box... /// /// /// private void GuiChanged(object sender, EventArgs e) { UpdateState(); } /// /// Update various outputs based on the current state of the inputs. Like drawing /// a sample of the selected color, or disabling the update button if there's a problem. /// private void UpdateState() { if (!_initialized) return; object newValue = null; bool valueIsValid = false; sampleLabel.ForeColor = SystemColors.ControlText; sampleLabel.BackColor = SystemColors.Control; sampleLabel.Text = ""; secondSampleLabel.ForeColor = SystemColors.ControlText; secondSampleLabel.BackColor = SystemColors.Control; secondSampleLabel.Text = ""; if (nullRadioButton.Checked) { newValue = null; valueIsValid = true; } else if (integerRadioButton.Checked) { Int64 asInt; valueIsValid = Int64.TryParse(valueTextBox.Text, out asInt); if (valueIsValid) { sampleLabel.Text = asInt.ToString(); secondSampleLabel.Text = asInt.ToString("N0"); newValue = asInt; } else sampleLabel.Text = "Invalid"; } else if (doubleRadioButton.Checked) { double asDouble; valueIsValid = double.TryParse(valueTextBox.Text, out asDouble); if (valueIsValid) { sampleLabel.Text = asDouble.ToString("g"); secondSampleLabel.Text = asDouble.ToString("e"); newValue = asDouble; } else sampleLabel.Text = "Invalid"; } else if (stringRadioButton.Checked) { valueIsValid = true; newValue = valueTextBox.Text; sampleLabel.Text = valueTextBox.Text; } else if (colorRadioButton.Checked) { Color? newColor = RequestedColor(); if (newColor.HasValue) { valueIsValid = true; newValue = newColor; sampleLabel.Text = "Foreground $123%"; sampleLabel.ForeColor = newColor.Value; sampleLabel.BackColor = GradientInfo.AltColor(newColor.Value); secondSampleLabel.Text = "Background {[/?]}"; secondSampleLabel.ForeColor = sampleLabel.BackColor; secondSampleLabel.BackColor = newColor.Value; } } else throw new Exception(); if (valueIsValid) { if (wrapInConstantDataNocdeCheckBox.Checked) newValue = ConstantDataNode.GetFactory(newValue); Result = newValue; } // In some places we disable the OK button if nothing has changed. In this form // we aren't keeping track of the original value. okButton.Enabled = valueIsValid; } /// /// Try to interpret the value in the text box as a color. /// /// private Color? RequestedColor() { if (valueTextBox.Text == "") // It seems strange that I have to make a special case for this. The code below // will return most bad inputs into a null. But it would turn "" into black for // some reason. return null; try { return (Color)new ColorConverter().ConvertFromInvariantString(valueTextBox.Text); } catch { return null; } } /// /// Burnt Orange. /// Use this as the initial value in the color editor, unless the user has already /// selected a color. /// //public static readonly Color DEFAULT_COLOR = Color.FromArgb(0xFFCF5300); // Burnt orange. public static readonly Color DEFAULT_COLOR = Color.FromArgb(0xCF, 0x53, 0x00); // Burnt orange. private void selectColorButton_Click(object sender, EventArgs e) { using (ColorDialog dialog = new ColorDialog()) { Color? previousColor = RequestedColor(); if (previousColor.HasValue) dialog.Color = previousColor.Value; else dialog.Color = DEFAULT_COLOR; dialog.FullOpen = true; if (dialog.ShowDialog() == DialogResult.OK) { WriteColor(dialog.Color); colorRadioButton.Checked = true; } } } /// /// This is the complement to RequestedColor(). This takes a color and converts /// it to a string and puts that string in the text box. The output is in a format /// acceptable to RequestedColor(). /// /// private void WriteColor(Color color) { if (color.IsNamedColor) valueTextBox.Text = color.Name; else // newColor.Name would give us a series of 8 hex digits. The first two would // be the alpha, which is always ff coming from this dialog box. If you add // a # to the front, you can read the result back in. I'm doing it myself to // avoid the alpha. valueTextBox.Text = '#' + color.R.ToString("X2") + color.G.ToString("X2") + color.B.ToString("X2"); } } }