using System; using MatterHackers.Agg; using MatterHackers.Agg.UI; using MatterHackers.VectorMath; namespace MatterHackers.MatterControl { public class EditableNumberDisplay : FlowLayoutWidget { protected GuiWidget clickableValueContainer; protected MHNumberEdit numberInputField; protected TextWidget valueDisplay; public string DisplayFormat { get; set; } = "{0}"; public event EventHandler ValueChanged; public Color TextColor { get => valueDisplay.TextColor; set => valueDisplay.TextColor = value; } Color _borderColor = Color.White; private ThemeConfig theme; public override Color BorderColor { get { return _borderColor; } set { _borderColor = value; clickableValueContainer.BorderColor = new Color(BorderColor, 140); } } public EditableNumberDisplay(double startingValue, string largestPossibleValue, ThemeConfig theme) : this(startingValue, largestPossibleValue, theme.TextColor, theme) { } public EditableNumberDisplay(double startingValue, string largestPossibleValue, Color textColor, ThemeConfig theme) : base(FlowDirection.LeftToRight) { this.Margin = new BorderDouble(3, 0); this.VAnchor = VAnchor.Center; this.theme = theme; clickableValueContainer = new GuiWidget() { VAnchor = VAnchor.Stretch, Cursor = Cursors.Hand, Border = 1, BorderColor = BorderColor, }; clickableValueContainer.MouseEnterBounds += (sender, e) => { clickableValueContainer.BorderColor = new Color(BorderColor, 255); }; clickableValueContainer.MouseLeaveBounds += (sender, e) => { clickableValueContainer.BorderColor = new Color(BorderColor, 140); }; valueDisplay = new TextWidget(largestPossibleValue, pointSize: 12) { TextColor = textColor, VAnchor = VAnchor.Center, HAnchor = HAnchor.Left, Margin = new BorderDouble(6), }; clickableValueContainer.Click += editField_Click; clickableValueContainer.AddChild(valueDisplay); clickableValueContainer.SetBoundsToEncloseChildren(); numberInputField = new MHNumberEdit(0, theme, pixelWidth: 40, allowDecimals: true) { VAnchor = VAnchor.Center, Margin = new BorderDouble(left: 6), Visible = false }; // This is a hack to make sure the control is tall enough. // TODO: This hack needs a unit test and then pass and then remove this line. this.MinimumSize = new Vector2(0, numberInputField.Height); numberInputField.ActuallNumberEdit.EnterPressed += (s, e) => UpdateDisplayString(); numberInputField.ContainsFocusChanged += (s1, e1) => { if (!numberInputField.ContainsFocus) { UpdateDisplayString(); } }; numberInputField.KeyDown += (sender, e) => { if (e.KeyCode == Keys.Escape) { clickableValueContainer.Visible = true; numberInputField.Visible = false; } }; this.AddChild(clickableValueContainer); this.AddChild(numberInputField); Value = startingValue + 1; Value = startingValue; BorderColor = TextColor; } private void editField_Click(object sender, EventArgs mouseEvent) { clickableValueContainer.Visible = false; numberInputField.Visible = true; // This is trying to get all the numbers to the left of the decimal. We could do a better // job of finding the number. 6546431321654 string displayString = valueDisplay.Text.Split('.')[0]; if (displayString != null && displayString != "") { double displayStringAsValue; double.TryParse(displayString, out displayStringAsValue); numberInputField.ActuallNumberEdit.Value = displayStringAsValue; } numberInputField.ActuallNumberEdit.InternalNumberEdit.Focus(); numberInputField.ActuallNumberEdit.InternalNumberEdit.SelectAll(); } private void UpdateDisplayString(bool callValueChanged = true) { clickableValueContainer.Visible = true; numberInputField.Visible = false; valueDisplay.Text = string.Format(DisplayFormat, numberInputField.Value); if (callValueChanged) { ValueChanged?.Invoke(this, null); } } public double ValueDirect { set { double sameError = .00001; if (value < numberInputField.Value - sameError || value > numberInputField.Value + sameError) { numberInputField.Value = value; UpdateDisplayString(false); } } } public double Value { get { return numberInputField.ActuallNumberEdit.Value; } set { double sameError = .00001; if (value < numberInputField.Value - sameError || value > numberInputField.Value + sameError) { numberInputField.Value = value; UpdateDisplayString(); } } } } }