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");
}
}
}