<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.Linq.Expressions;
using Signum.Utilities;
using System.Web.Mvc.Html;
using Signum.Entities.Reflection;
using Signum.Entities;
using System.Globalization;
using Signum.Entities.Basics;
using System.Reflection;


namespace Signum.Web
{
    public static class ValueLineHelper
    {
        public static ValueLineConfigurator Configurator = new ValueLineConfigurator();

        private static MvcHtmlString InternalValueLine(this HtmlHelper helper, ValueLine valueLine)
        {
            if (!valueLine.Visible || (valueLine.HideIfNull && valueLine.UntypedValue == null))
                return MvcHtmlString.Empty;

            if (valueLine.PlaceholderLabels && !valueLine.ValueHtmlProps.ContainsKey("placeholder"))
                valueLine.ValueHtmlProps["placeholder"] = valueLine.LabelText;

            var value = InternalValue(helper, valueLine);

            if (valueLine.InlineCheckbox)
                return new HtmlTag("label").InnerHtml("{0} {1}".FormatHtml(value, valueLine.LabelText)).ToHtml();

            return helper.FormGroup(valueLine, valueLine.Prefix, valueLine.LabelHtml ?? valueLine.LabelText.FormatHtml(), value);
        }

        private static MvcHtmlString InternalValue(HtmlHelper helper, ValueLine valueLine)
        {
            HtmlStringBuilder sb = new HtmlStringBuilder();
            ValueLineType vltype = valueLine.ValueLineType ?? Configurator.GetDefaultValueLineType(valueLine.Type);

            using (valueLine.UnitText == null ? null : sb.SurroundLine(new HtmlTag("div").Class("input-group")))
            {
                sb.AddLine(Configurator.Helper[vltype](helper, valueLine));

                if (valueLine.UnitText.HasText())
                    sb.AddLine(helper.Span(valueLine.Compose("unit"), valueLine.UnitText, "input-group-addon"));
            }

            return sb.ToHtml();
        }

        public static MvcHtmlString EnumComboBox(this HtmlHelper helper, ValueLine valueLine)
        {
            var uType = valueLine.Type.UnNullify();
            Enum value = valueLine.UntypedValue as Enum;

            return InternalComboBox(helper, valueLine, uType, value);
        }

        public static MvcHtmlString BooleanEnumComboBox(this HtmlHelper helper, ValueLine valueLine)
        {
            var uType = valueLine.Type.UnNullify();
            if (uType != typeof(bool))
                throw new InvalidOperationException("valueLine Type is not a boolean");

            BooleanEnum? value = ToBooleanEnum((bool?)valueLine.UntypedValue);

            return InternalComboBox(helper, valueLine, typeof(BooleanEnum), value);
        }

        private static BooleanEnum? ToBooleanEnum(bool? value)
        {
            return value == null ? (BooleanEnum?)null :
                value.Value ? BooleanEnum.True :
                BooleanEnum.False;
        }

        private static MvcHtmlString InternalComboBox(HtmlHelper helper, ValueLine valueLine, Type uType, Enum value)
        {
            if (valueLine.ReadOnly)
            {
                MvcHtmlString result = MvcHtmlString.Empty;
                if (valueLine.WriteHiddenOnReadonly)
                    result = result.Concat(helper.Hidden(valueLine.Prefix, valueLine.UntypedValue.ToString()));

                string str = value == null ? null :
                    LocalizedAssembly.GetDescriptionOptions(uType).IsSet(DescriptionOptions.Members) ? value.NiceToString() : value.ToString();

                return result.Concat(helper.FormControlStatic(valueLine, null, str, valueLine.ValueHtmlProps));
            }

            StringBuilder sb = new StringBuilder();
            List<SelectListItem> items = valueLine.EnumComboItems ?? valueLine.CreateComboItems();

            if (value != null)
                items.Where(e => e.Value == value.ToString())
                    .SingleOrDefaultEx()
                    .TryDo(s => s.Selected = true);

            valueLine.ValueHtmlProps.AddCssClass("form-control");
            return helper.DropDownList(valueLine.Prefix, items, valueLine.ValueHtmlProps);
        }

        public static MvcHtmlString DateTimePicker(this HtmlHelper helper, ValueLine valueLine)
        {
            DateTime? value = (DateTime?)valueLine.UntypedValue;

            if (value.HasValue)
                value = value.Value.ToUserInterface();

            if (valueLine.ReadOnly)
            {
                MvcHtmlString result = MvcHtmlString.Empty;
                if (valueLine.WriteHiddenOnReadonly)
                    result = result.Concat(helper.Hidden(valueLine.Prefix, value.TryToString(valueLine.Format)));
                return result.Concat(helper.FormControlStatic(valueLine, null, value.TryToString(valueLine.Format), valueLine.ValueHtmlProps));
            }

            valueLine.ValueHtmlProps.AddCssClass("form-control");
            return helper.DateTimePicker(valueLine.Prefix, true, value, valueLine.Format, CultureInfo.CurrentCulture, valueLine.ValueHtmlProps);
        }

        public static MvcHtmlString TimeSpanPicker(this HtmlHelper helper, ValueLine valueLine)
        {
            TimeSpan? value = (TimeSpan?)valueLine.UntypedValue;

            if (valueLine.ReadOnly)
            {
                MvcHtmlString result = MvcHtmlString.Empty;
                if (valueLine.WriteHiddenOnReadonly)
                    result = result.Concat(helper.Hidden(valueLine.Prefix, value.TryToString(valueLine.Format)));
                return result.Concat(helper.FormControlStatic(valueLine, null, value.TryToString(valueLine.Format), valueLine.ValueHtmlProps));
            }
            
            var dateFormatAttr = valueLine.PropertyRoute.PropertyInfo.GetCustomAttribute<TimeSpanDateFormatAttribute>();
            if (dateFormatAttr != null)
                return helper.TimePicker(valueLine.Prefix, true, value, dateFormatAttr.Format, CultureInfo.CurrentCulture, valueLine.ValueHtmlProps);
            else
            {
                valueLine.ValueHtmlProps.AddCssClass("form-control");
                return helper.TextBox(valueLine.Prefix, value == null ? "" : value.Value.ToString(valueLine.Format, CultureInfo.CurrentCulture), valueLine.ValueHtmlProps);
            }
        }

        public static MvcHtmlString TextboxInLine(this HtmlHelper helper, ValueLine valueLine)
        {
            string value = (valueLine.UntypedValue as IFormattable).TryToString(valueLine.Format) ??
                           valueLine.UntypedValue.TryToString() ?? "";

            if (valueLine.ReadOnly)
            {
                MvcHtmlString result = MvcHtmlString.Empty;
                if (valueLine.WriteHiddenOnReadonly)
                    result = result.Concat(helper.Hidden(valueLine.Prefix, value));

                if (valueLine.UnitText.HasText())
                    return new HtmlTag("p").Id(valueLine.Prefix).SetInnerText(value).Class("form-control").Attrs(valueLine.ValueHtmlProps).ToHtml();
                else
                    return result.Concat(helper.FormControlStatic(valueLine, valueLine.Prefix, value, valueLine.ValueHtmlProps));
            }

            if (!valueLine.ValueHtmlProps.ContainsKey("autocomplete"))
                valueLine.ValueHtmlProps.Add("autocomplete", "off");
            else
                valueLine.ValueHtmlProps.Remove("autocomplete");

            valueLine.ValueHtmlProps["onblur"] = "this.setAttribute('value', this.value); " + valueLine.ValueHtmlProps.TryGetC("onblur");

            if (!valueLine.ValueHtmlProps.ContainsKey("type"))
                valueLine.ValueHtmlProps["type"] = "text";

            valueLine.ValueHtmlProps.AddCssClass("form-control");
            return helper.TextBox(valueLine.Prefix, value, valueLine.ValueHtmlProps);
        }

        public static MvcHtmlString NumericTextbox(this HtmlHelper helper, ValueLine valueLine)
        {
            if (!valueLine.ReadOnly)
                valueLine.ValueHtmlProps.Add("onkeydown", Reflector.IsDecimalNumber(valueLine.Type) ? 
                    "return SF.InputValidator.isDecimal(event);" : 
                    "return SF.InputValidator.isNumber(event);");

            valueLine.ValueHtmlProps.AddCssClass("numeric");
            
            return helper.TextboxInLine(valueLine);
        }

        public static MvcHtmlString ColorTextbox(this HtmlHelper helper, ValueLine valueLine)
        {
            HtmlStringBuilder sb = new HtmlStringBuilder();

            using (sb.SurroundLine(new HtmlTag("div").Class("input-group")))
            {
                valueLine.ValueHtmlProps.AddCssClass("form-control");

                ColorEntity color = (ColorEntity)valueLine.UntypedValue;

                sb.AddLine(helper.TextBox(valueLine.Prefix, color == null ? "" : color.RGBHex(), valueLine.ValueHtmlProps));

                sb.AddLine(new HtmlTag("span").Class("input-group-addon").InnerHtml(new HtmlTag("i")));
            }

            sb.AddLine(new HtmlTag("script").InnerHtml(MvcHtmlString.Create(
@" $(function(){
        $('#" + valueLine.Prefix + @"').parent().colorpicker()" + (valueLine.ReadOnly ? ".colorpicker('disable')" : null) + @";
   });")));

            return sb.ToHtml();
        }

        public static MvcHtmlString TextAreaInLine(this HtmlHelper helper, ValueLine valueLine)
        {
            if (valueLine.ReadOnly)
            {
                MvcHtmlString result = MvcHtmlString.Empty;
                if (valueLine.WriteHiddenOnReadonly)
                    result = result.Concat(helper.Hidden(valueLine.Prefix, (string)valueLine.UntypedValue));

                if (valueLine.FormControlStaticAsFormControlReadonly)
                    valueLine.ValueHtmlProps.AddCssClass("readonly-textarea");

                return result.Concat(helper.FormControlStatic(valueLine, "", (string)valueLine.UntypedValue, valueLine.ValueHtmlProps));
            }

            valueLine.ValueHtmlProps.Add("autocomplete", "off");
            valueLine.ValueHtmlProps["onblur"] = "this.innerHTML = this.value; " + valueLine.ValueHtmlProps.TryGetC("onblur");
            valueLine.ValueHtmlProps.AddCssClass("form-control");
            return helper.TextArea(valueLine.Prefix, (string)valueLine.UntypedValue, valueLine.ValueHtmlProps);
        }

        public static MvcHtmlString CheckBox(this HtmlHelper helper, ValueLine valueLine)
        {
            bool? value = (bool?)valueLine.UntypedValue;
            if (!valueLine.InlineCheckbox)
                valueLine.ValueHtmlProps.AddCssClass("form-control");
            return helper.CheckBox(valueLine.Prefix, value ?? false, !valueLine.ReadOnly, valueLine.ValueHtmlProps);
        }

        public static MvcHtmlString ValueLine(this HtmlHelper helper, ValueLine valueLine)
        {
            return helper.InternalValueLine(valueLine);
        }

        public static MvcHtmlString ValueLine<T, S>(this HtmlHelper helper, TypeContext<T> tc, Expression<Func<T, S>> property)
        {
            return helper.ValueLine(tc, property, null);<commit_msg>remove id from ReadOnly value lines in the few cases that were still there to avoid conflict with WriteHiddenOnReadonly ids<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.Linq.Expressions;
using Signum.Utilities;
using System.Web.Mvc.Html;
using Signum.Entities.Reflection;
using Signum.Entities;
using System.Globalization;
using Signum.Entities.Basics;
using System.Reflection;


namespace Signum.Web
{
    public static class ValueLineHelper
    {
        public static ValueLineConfigurator Configurator = new ValueLineConfigurator();

        private static MvcHtmlString InternalValueLine(this HtmlHelper helper, ValueLine valueLine)
        {
            if (!valueLine.Visible || (valueLine.HideIfNull && valueLine.UntypedValue == null))
                return MvcHtmlString.Empty;

            if (valueLine.PlaceholderLabels && !valueLine.ValueHtmlProps.ContainsKey("placeholder"))
                valueLine.ValueHtmlProps["placeholder"] = valueLine.LabelText;

            var value = InternalValue(helper, valueLine);

            if (valueLine.InlineCheckbox)
                return new HtmlTag("label").InnerHtml("{0} {1}".FormatHtml(value, valueLine.LabelText)).ToHtml();

            return helper.FormGroup(valueLine, valueLine.Prefix, valueLine.LabelHtml ?? valueLine.LabelText.FormatHtml(), value);
        }

        private static MvcHtmlString InternalValue(HtmlHelper helper, ValueLine valueLine)
        {
            HtmlStringBuilder sb = new HtmlStringBuilder();
            ValueLineType vltype = valueLine.ValueLineType ?? Configurator.GetDefaultValueLineType(valueLine.Type);

            using (valueLine.UnitText == null ? null : sb.SurroundLine(new HtmlTag("div").Class("input-group")))
            {
                sb.AddLine(Configurator.Helper[vltype](helper, valueLine));

                if (valueLine.UnitText.HasText())
                    sb.AddLine(helper.Span(null, valueLine.UnitText, "input-group-addon"));
            }

            return sb.ToHtml();
        }

        public static MvcHtmlString EnumComboBox(this HtmlHelper helper, ValueLine valueLine)
        {
            var uType = valueLine.Type.UnNullify();
            Enum value = valueLine.UntypedValue as Enum;

            return InternalComboBox(helper, valueLine, uType, value);
        }

        public static MvcHtmlString BooleanEnumComboBox(this HtmlHelper helper, ValueLine valueLine)
        {
            var uType = valueLine.Type.UnNullify();
            if (uType != typeof(bool))
                throw new InvalidOperationException("valueLine Type is not a boolean");

            BooleanEnum? value = ToBooleanEnum((bool?)valueLine.UntypedValue);

            return InternalComboBox(helper, valueLine, typeof(BooleanEnum), value);
        }

        private static BooleanEnum? ToBooleanEnum(bool? value)
        {
            return value == null ? (BooleanEnum?)null :
                value.Value ? BooleanEnum.True :
                BooleanEnum.False;
        }

        private static MvcHtmlString InternalComboBox(HtmlHelper helper, ValueLine valueLine, Type uType, Enum value)
        {
            if (valueLine.ReadOnly)
            {
                MvcHtmlString result = MvcHtmlString.Empty;
                if (valueLine.WriteHiddenOnReadonly)
                    result = result.Concat(helper.Hidden(valueLine.Prefix, valueLine.UntypedValue.ToString()));

                string str = value == null ? null :
                    LocalizedAssembly.GetDescriptionOptions(uType).IsSet(DescriptionOptions.Members) ? value.NiceToString() : value.ToString();

                return result.Concat(helper.FormControlStatic(valueLine, null, str, valueLine.ValueHtmlProps));
            }

            StringBuilder sb = new StringBuilder();
            List<SelectListItem> items = valueLine.EnumComboItems ?? valueLine.CreateComboItems();

            if (value != null)
                items.Where(e => e.Value == value.ToString())
                    .SingleOrDefaultEx()
                    .TryDo(s => s.Selected = true);

            valueLine.ValueHtmlProps.AddCssClass("form-control");
            return helper.DropDownList(valueLine.Prefix, items, valueLine.ValueHtmlProps);
        }

        public static MvcHtmlString DateTimePicker(this HtmlHelper helper, ValueLine valueLine)
        {
            DateTime? value = (DateTime?)valueLine.UntypedValue;

            if (value.HasValue)
                value = value.Value.ToUserInterface();

            if (valueLine.ReadOnly)
            {
                MvcHtmlString result = MvcHtmlString.Empty;
                if (valueLine.WriteHiddenOnReadonly)
                    result = result.Concat(helper.Hidden(valueLine.Prefix, value.TryToString(valueLine.Format)));
                return result.Concat(helper.FormControlStatic(valueLine, null, value.TryToString(valueLine.Format), valueLine.ValueHtmlProps));
            }

            valueLine.ValueHtmlProps.AddCssClass("form-control");
            return helper.DateTimePicker(valueLine.Prefix, true, value, valueLine.Format, CultureInfo.CurrentCulture, valueLine.ValueHtmlProps);
        }

        public static MvcHtmlString TimeSpanPicker(this HtmlHelper helper, ValueLine valueLine)
        {
            TimeSpan? value = (TimeSpan?)valueLine.UntypedValue;

            if (valueLine.ReadOnly)
            {
                MvcHtmlString result = MvcHtmlString.Empty;
                if (valueLine.WriteHiddenOnReadonly)
                    result = result.Concat(helper.Hidden(valueLine.Prefix, value.TryToString(valueLine.Format)));
                return result.Concat(helper.FormControlStatic(valueLine, null, value.TryToString(valueLine.Format), valueLine.ValueHtmlProps));
            }
            
            var dateFormatAttr = valueLine.PropertyRoute.PropertyInfo.GetCustomAttribute<TimeSpanDateFormatAttribute>();
            if (dateFormatAttr != null)
                return helper.TimePicker(valueLine.Prefix, true, value, dateFormatAttr.Format, CultureInfo.CurrentCulture, valueLine.ValueHtmlProps);
            else
            {
                valueLine.ValueHtmlProps.AddCssClass("form-control");
                return helper.TextBox(valueLine.Prefix, value == null ? "" : value.Value.ToString(valueLine.Format, CultureInfo.CurrentCulture), valueLine.ValueHtmlProps);
            }
        }

        public static MvcHtmlString TextboxInLine(this HtmlHelper helper, ValueLine valueLine)
        {
            string value = (valueLine.UntypedValue as IFormattable).TryToString(valueLine.Format) ??
                           valueLine.UntypedValue.TryToString() ?? "";

            if (valueLine.ReadOnly)
            {
                MvcHtmlString result = MvcHtmlString.Empty;
                if (valueLine.WriteHiddenOnReadonly)
                    result = result.Concat(helper.Hidden(valueLine.Prefix, value));

                if (valueLine.UnitText.HasText())
                    return result.Concat(new HtmlTag("p").SetInnerText(value).Class("form-control").Attrs(valueLine.ValueHtmlProps).ToHtml());
                else
                    return result.Concat(helper.FormControlStatic(valueLine, null, value, valueLine.ValueHtmlProps));
            }

            if (!valueLine.ValueHtmlProps.ContainsKey("autocomplete"))
                valueLine.ValueHtmlProps.Add("autocomplete", "off");
            else
                valueLine.ValueHtmlProps.Remove("autocomplete");

            valueLine.ValueHtmlProps["onblur"] = "this.setAttribute('value', this.value); " + valueLine.ValueHtmlProps.TryGetC("onblur");

            if (!valueLine.ValueHtmlProps.ContainsKey("type"))
                valueLine.ValueHtmlProps["type"] = "text";

            valueLine.ValueHtmlProps.AddCssClass("form-control");
            return helper.TextBox(valueLine.Prefix, value, valueLine.ValueHtmlProps);
        }

        public static MvcHtmlString NumericTextbox(this HtmlHelper helper, ValueLine valueLine)
        {
            if (!valueLine.ReadOnly)
                valueLine.ValueHtmlProps.Add("onkeydown", Reflector.IsDecimalNumber(valueLine.Type) ? 
                    "return SF.InputValidator.isDecimal(event);" : 
                    "return SF.InputValidator.isNumber(event);");

            valueLine.ValueHtmlProps.AddCssClass("numeric");
            
            return helper.TextboxInLine(valueLine);
        }

        public static MvcHtmlString ColorTextbox(this HtmlHelper helper, ValueLine valueLine)
        {
            HtmlStringBuilder sb = new HtmlStringBuilder();

            using (sb.SurroundLine(new HtmlTag("div").Class("input-group")))
            {
                valueLine.ValueHtmlProps.AddCssClass("form-control");

                ColorEntity color = (ColorEntity)valueLine.UntypedValue;

                sb.AddLine(helper.TextBox(valueLine.Prefix, color == null ? "" : color.RGBHex(), valueLine.ValueHtmlProps));

                sb.AddLine(new HtmlTag("span").Class("input-group-addon").InnerHtml(new HtmlTag("i")));
            }

            sb.AddLine(new HtmlTag("script").InnerHtml(MvcHtmlString.Create(
@" $(function(){
        $('#" + valueLine.Prefix + @"').parent().colorpicker()" + (valueLine.ReadOnly ? ".colorpicker('disable')" : null) + @";
   });")));

            return sb.ToHtml();
        }

        public static MvcHtmlString TextAreaInLine(this HtmlHelper helper, ValueLine valueLine)
        {
            if (valueLine.ReadOnly)
            {
                MvcHtmlString result = MvcHtmlString.Empty;
                if (valueLine.WriteHiddenOnReadonly)
                    result = result.Concat(helper.Hidden(valueLine.Prefix, (string)valueLine.UntypedValue));

                if (valueLine.FormControlStaticAsFormControlReadonly)
                    valueLine.ValueHtmlProps.AddCssClass("readonly-textarea");

                return result.Concat(helper.FormControlStatic(valueLine, null, (string)valueLine.UntypedValue, valueLine.ValueHtmlProps));
            }

            valueLine.ValueHtmlProps.Add("autocomplete", "off");
            valueLine.ValueHtmlProps["onblur"] = "this.innerHTML = this.value; " + valueLine.ValueHtmlProps.TryGetC("onblur");
            valueLine.ValueHtmlProps.AddCssClass("form-control");
            return helper.TextArea(valueLine.Prefix, (string)valueLine.UntypedValue, valueLine.ValueHtmlProps);
        }

        public static MvcHtmlString CheckBox(this HtmlHelper helper, ValueLine valueLine)
        {
            bool? value = (bool?)valueLine.UntypedValue;
            if (!valueLine.InlineCheckbox)
                valueLine.ValueHtmlProps.AddCssClass("form-control");
            return helper.CheckBox(valueLine.Prefix, value ?? false, !valueLine.ReadOnly, valueLine.ValueHtmlProps);
        }

        public static MvcHtmlString ValueLine(this HtmlHelper helper, ValueLine valueLine)
        {
            return helper.InternalValueLine(valueLine);
        }

        public static MvcHtmlString ValueLine<T, S>(this HtmlHelper helper, TypeContext<T> tc, Expression<Func<T, S>> property)
        {
            return helper.ValueLine(tc, property, null);
{'fraction_non_alphanumeric': 0.1007890161815183, 'fraction_numerical': 0.00017830874158605625, 'mean_word_length': 2.4862470862470865, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5513660', 'n_tokens_mistral': 5947, 'n_tokens_neox': 5732, 'n_words': 1025}