<commit_before>﻿namespace RNUIExamples.Showcase
{
    using System;
    using System.Drawing;
    using RAGENativeUI;
    using RAGENativeUI.Elements;
    using Rage;

    using static Util;

    internal sealed class Menus : UIMenu
    {
        public Menus() : base(Plugin.MenuTitle, "MENUS")
        {
            Plugin.Pool.Add(this);

            CreateMenuItems();
        }

        private void CreateMenuItems()
        {
            UIMenuItem visualOptionsBindItem = new UIMenuItem("Visual Options", $"Demonstrates the visual options of the ~b~{nameof(UIMenu)}~s~ class.");
            UIMenuItem checkboxBindItem = new UIMenuItem("Checkbox", $"Demonstrates the ~b~{nameof(UIMenuCheckboxItem)}~s~ class.");
            UIMenuItem scrollerBindItem = new UIMenuItem("Scroller", $"Demonstrates the ~b~{nameof(UIMenuListScrollerItem<int>)}~s~ and ~b~{nameof(UIMenuNumericScrollerItem<int>)}~s~ classes.");

            UIMenu visualOptionsMenu = new UIMenu(Title, Subtitle + ": VISUAL OPTIONS");
            UIMenu checkboxMenu = new UIMenu(Title, Subtitle + ": CHECKBOX");
            UIMenu scrollerMenu = new UIMenu(Title, Subtitle + ": SCROLLER");

            Plugin.Pool.Add(visualOptionsMenu, checkboxMenu, scrollerMenu);

            AddItems(visualOptionsBindItem, checkboxBindItem, scrollerBindItem);

            BindMenuToItem(visualOptionsMenu, visualOptionsBindItem);
            BindMenuToItem(checkboxMenu, checkboxBindItem);
            BindMenuToItem(scrollerMenu, scrollerBindItem);

            // visual options
            {
                static void ApplyToEachMenu(Action<UIMenu> f)
                {
                    foreach (UIMenu m in Plugin.Pool)
                    {
                        f(m);
                    }
                }

                var width = new UIMenuNumericScrollerItem<float>(nameof(Width), $"Modifies the ~b~{nameof(UIMenu)}.{nameof(Width)}~s~ property.", 0.0f, 1.0f, 0.001f);
                width.Formatter = v => v.ToString("0.000");
                width.Value = Width;
                width.IndexChanged += (s, o, n) => ApplyToEachMenu(m => m.Width = width.Value);

                var offsetX = new UIMenuNumericScrollerItem<int>("Offset X", $"Modifies the X-coord of the ~b~{nameof(UIMenu)}.{nameof(Offset)}~s~ property.", -1000, 1000, 1);
                offsetX.Value = Offset.X;
                offsetX.IndexChanged += (s, o, n) => ApplyToEachMenu(m => m.Offset = new Point(offsetX.Value, m.Offset.Y));

                var offsetY = new UIMenuNumericScrollerItem<int>("Offset Y", $"Modifies the Y-coord of the ~b~{nameof(UIMenu)}.{nameof(Offset)}~s~ property.", -1000, 1000, 1);
                offsetY.Value = Offset.Y;
                offsetY.IndexChanged += (s, o, n) => ApplyToEachMenu(m => m.Offset = new Point(m.Offset.X, offsetY.Value));

                const string BannerTypeText = "Banner Type (Current)", BannerTypeUnsetText = "Banner Type";
                var bannerType = new UIMenuListScrollerItem<string>(BannerTypeText, "", new[] { "No Banner", "Sprite", "Color", "Custom Texture"});
                int currBannerType = bannerType.Index = 1;
                bannerType.IndexChanged += (s, o, n) => bannerType.Text = n == currBannerType ? BannerTypeText : BannerTypeUnsetText;
                bannerType.Activated += (m, s) =>
                {
                    currBannerType = bannerType.Index;
                    bannerType.Text = BannerTypeText;
                    ApplyToEachMenu(currBannerType switch
                    {
                        0 => m => m.RemoveBanner(),
                        1 => m => m.SetBannerType(new Sprite("commonmenu", "interaction_bgd", Point.Empty, Size.Empty)),
                        2 => m => m.SetBannerType(new ResRectangle(Point.Empty, Size.Empty, HudColor.Red.GetColor())),
                        3 => m => m.SetBannerType(Game.CreateTextureFromFile("cursor_32_2.png")),
                        _ => throw new InvalidOperationException("Invalid banner type")
                    });
                };
                
                var title = NewTextEditingItem(nameof(Title), $"Select to modify the ~b~{nameof(UIMenu)}.{nameof(Title)}~s~ property.",
                                               () => Title,
                                               s => ApplyToEachMenu(m => m.Title = s));

                var titleColor = NewColorsItem("Title Color", $"Modifies the color of the ~b~{nameof(UIMenu)}.{nameof(TitleStyle)}~s~ property.");
                titleColor.IndexChanged += (s, o, n) =>
                {
                    Color c = titleColor.SelectedItem.GetColor();
                    ApplyToEachMenu(m => m.TitleStyle = m.TitleStyle.With(color: c));
                };

                var subtitleColor = NewColorsItem("Subtitle Color", $"Modifies the color of the ~b~{nameof(UIMenu)}.{nameof(SubtitleStyle)}~s~ property.");
                subtitleColor.IndexChanged += (s, o, n) =>
                {
                    Color c = subtitleColor.SelectedItem.GetColor();
                    ApplyToEachMenu(m => m.SubtitleStyle = m.SubtitleStyle.With(color: c));
                };

                var descriptionOverride = NewTextEditingItem("Description Override", $"Select to modify the ~b~{nameof(UIMenu)}.{nameof(DescriptionOverride)}~s~ property.",
                                               () => DescriptionOverride ?? string.Empty,
                                               s => ApplyToEachMenu(m => m.DescriptionOverride = s.Length == 0 ? null : s));

                var descriptionColor = NewColorsItem("Description Color", $"Modifies the color of the ~b~{nameof(UIMenu)}.{nameof(DescriptionStyle)}~s~ property.");
                descriptionColor.IndexChanged += (s, o, n) =>
                {
                    Color c = descriptionColor.SelectedItem.GetColor();
                    ApplyToEachMenu(m => m.DescriptionStyle = m.DescriptionStyle.With(color: c));
                };

                var descriptionSeparatorColor = NewColorsItem("Description Separator", $"Modifies the ~b~{nameof(UIMenu)}.{nameof(DescriptionSeparatorColor)}~s~ property.");
                descriptionSeparatorColor.SelectedItem = HudColor.Black;
                descriptionSeparatorColor.IndexChanged += (s, o, n) =>
                {
                    Color c = descriptionSeparatorColor.SelectedItem.GetColor();
                    ApplyToEachMenu(m => m.DescriptionSeparatorColor = c);
                };

                var counterOverride = NewTextEditingItem("Counter Override", $"Select to modify the ~b~{nameof(UIMenu)}.{nameof(CounterOverride)}~s~ property.",
                                               () => CounterOverride ?? string.Empty,
                                               s => ApplyToEachMenu(m => m.CounterOverride = s.Length == 0 ? null : s));

                var counterColor = NewColorsItem("Counter Color", $"Modifies the color of the ~b~{nameof(UIMenu)}.{nameof(CounterStyle)}~s~ property.");
                counterColor.IndexChanged += (s, o, n) =>
                {
                    Color c = counterColor.SelectedItem.GetColor();
                    ApplyToEachMenu(m => m.CounterStyle = m.CounterStyle.With(color: c));
                };

                var scaleWithSafezone = new UIMenuCheckboxItem("Scale with Safe-Zone", ScaleWithSafezone, $"Modifies the ~b~{nameof(UIMenu)}.{nameof(ScaleWithSafezone)}~s~ property.");
                scaleWithSafezone.Checked = ScaleWithSafezone;
                scaleWithSafezone.CheckboxEvent += (s, v) => ApplyToEachMenu(m => m.ScaleWithSafezone = v);

                visualOptionsMenu.AddItems(width, offsetX, offsetY, bannerType, title, titleColor, subtitleColor,
                                           descriptionOverride, descriptionColor, descriptionSeparatorColor,
                                           counterOverride, counterColor, scaleWithSafezone);
            }

            // checkbox
            {
                checkboxMenu.AddItems(
                    new UIMenuCheckboxItem("#1", false, "Unchecked."),
                    new UIMenuCheckboxItem("#2", true, "Checked."),
                    new UIMenuCheckboxItem("#3", false, "Unchecked and disabled.") { Enabled = false },
                    new UIMenuCheckboxItem("#4", true, "Checked and disabled.") { Enabled = false },
                    new UIMenuCheckboxItem("#5", false, "With right badge.") { RightBadge = UIMenuItem.BadgeStyle.Armour },
                    new UIMenuCheckboxItem("#6", true, "With right badge.") { RightBadge = UIMenuItem.BadgeStyle.Armour },
                    new UIMenuCheckboxItem("#7", false, "With left badge.") { LeftBadge = UIMenuItem.BadgeStyle.Armour },
                    new UIMenuCheckboxItem("#8", true, "With left badge.") { LeftBadge = UIMenuItem.BadgeStyle.Armour },
                    new UIMenuCheckboxItem("#9", false, "With both badges.") { RightBadge = UIMenuItem.BadgeStyle.Armour, LeftBadge = UIMenuItem.BadgeStyle.Armour },
                    new UIMenuCheckboxItem("#10", true, "With both badges.") { RightBadge = UIMenuItem.BadgeStyle.Armour, LeftBadge = UIMenuItem.BadgeStyle.Armour },
                    new UIMenuCheckboxItem("#11", false, "With both badges and disabled.") { Enabled = false, RightBadge = UIMenuItem.BadgeStyle.Armour, LeftBadge = UIMenuItem.BadgeStyle.Armour },
                    new UIMenuCheckboxItem("#12", true, "With both badges and disabled.") { Enabled = false, RightBadge = UIMenuItem.BadgeStyle.Armour, LeftBadge = UIMenuItem.BadgeStyle.Armour },
                    new UIMenuCheckboxItem("#13", false, "With custom background color.") { BackColor = Color.FromArgb(140, HudColor.RedDark.GetColor()), HighlightedBackColor = Color.FromArgb(230, HudColor.TechRed.GetColor()) },
                    new UIMenuCheckboxItem("#14", true, "With custom background color.") { BackColor = Color.FromArgb(140, HudColor.RedDark.GetColor()), HighlightedBackColor = Color.FromArgb(230, HudColor.TechRed.GetColor()) },
                    new UIMenuCheckboxItem("#14", false, "With custom badge.") { RightBadgeInfo = new UIMenuItem.BadgeInfo("commonmenu", "mp_alerttriangle", HudColor.Red.GetColor()) },
                    new UIMenuCheckboxItem("#15", true, "With custom badge.") { RightBadgeInfo = new UIMenuItem.BadgeInfo("commonmenu", "mp_alerttriangle", HudColor.Red.GetColor()) }
                );
            }

            // scroller
            {
                string[] values = new[] { "Hello", "World", "Foo", "Bar" };
                scrollerMenu.AddItems(
                    new UIMenuListScrollerItem<string>("List #1", "List scroller.", values),
                    new UIMenuListScrollerItem<string>("List #2", "List scroller disabled.", values) { Enabled = false },
                    new UIMenuListScrollerItem<string>("List #3", "List scroller disabled with scrolling enabled.", values) { Enabled = false, ScrollingEnabledWhenDisabled = true },<commit_msg>(#61) Add checkbox examples: cross style and tri-state checkbox<commit_after>﻿namespace RNUIExamples.Showcase
{
    using System;
    using System.Drawing;
    using RAGENativeUI;
    using RAGENativeUI.Elements;
    using Rage;

    using static Util;

    internal sealed class Menus : UIMenu
    {
        public Menus() : base(Plugin.MenuTitle, "MENUS")
        {
            Plugin.Pool.Add(this);

            CreateMenuItems();
        }

        private void CreateMenuItems()
        {
            UIMenuItem visualOptionsBindItem = new UIMenuItem("Visual Options", $"Demonstrates the visual options of the ~b~{nameof(UIMenu)}~s~ class.");
            UIMenuItem checkboxBindItem = new UIMenuItem("Checkbox", $"Demonstrates the ~b~{nameof(UIMenuCheckboxItem)}~s~ class.");
            UIMenuItem scrollerBindItem = new UIMenuItem("Scroller", $"Demonstrates the ~b~{nameof(UIMenuListScrollerItem<int>)}~s~ and ~b~{nameof(UIMenuNumericScrollerItem<int>)}~s~ classes.");

            UIMenu visualOptionsMenu = new UIMenu(Title, Subtitle + ": VISUAL OPTIONS");
            UIMenu checkboxMenu = new UIMenu(Title, Subtitle + ": CHECKBOX");
            UIMenu scrollerMenu = new UIMenu(Title, Subtitle + ": SCROLLER");

            Plugin.Pool.Add(visualOptionsMenu, checkboxMenu, scrollerMenu);

            AddItems(visualOptionsBindItem, checkboxBindItem, scrollerBindItem);

            BindMenuToItem(visualOptionsMenu, visualOptionsBindItem);
            BindMenuToItem(checkboxMenu, checkboxBindItem);
            BindMenuToItem(scrollerMenu, scrollerBindItem);

            // visual options
            {
                static void ApplyToEachMenu(Action<UIMenu> f)
                {
                    foreach (UIMenu m in Plugin.Pool)
                    {
                        f(m);
                    }
                }

                var width = new UIMenuNumericScrollerItem<float>(nameof(Width), $"Modifies the ~b~{nameof(UIMenu)}.{nameof(Width)}~s~ property.", 0.0f, 1.0f, 0.001f);
                width.Formatter = v => v.ToString("0.000");
                width.Value = Width;
                width.IndexChanged += (s, o, n) => ApplyToEachMenu(m => m.Width = width.Value);

                var offsetX = new UIMenuNumericScrollerItem<int>("Offset X", $"Modifies the X-coord of the ~b~{nameof(UIMenu)}.{nameof(Offset)}~s~ property.", -1000, 1000, 1);
                offsetX.Value = Offset.X;
                offsetX.IndexChanged += (s, o, n) => ApplyToEachMenu(m => m.Offset = new Point(offsetX.Value, m.Offset.Y));

                var offsetY = new UIMenuNumericScrollerItem<int>("Offset Y", $"Modifies the Y-coord of the ~b~{nameof(UIMenu)}.{nameof(Offset)}~s~ property.", -1000, 1000, 1);
                offsetY.Value = Offset.Y;
                offsetY.IndexChanged += (s, o, n) => ApplyToEachMenu(m => m.Offset = new Point(m.Offset.X, offsetY.Value));

                const string BannerTypeText = "Banner Type (Current)", BannerTypeUnsetText = "Banner Type";
                var bannerType = new UIMenuListScrollerItem<string>(BannerTypeText, "", new[] { "No Banner", "Sprite", "Color", "Custom Texture"});
                int currBannerType = bannerType.Index = 1;
                bannerType.IndexChanged += (s, o, n) => bannerType.Text = n == currBannerType ? BannerTypeText : BannerTypeUnsetText;
                bannerType.Activated += (m, s) =>
                {
                    currBannerType = bannerType.Index;
                    bannerType.Text = BannerTypeText;
                    ApplyToEachMenu(currBannerType switch
                    {
                        0 => m => m.RemoveBanner(),
                        1 => m => m.SetBannerType(new Sprite("commonmenu", "interaction_bgd", Point.Empty, Size.Empty)),
                        2 => m => m.SetBannerType(new ResRectangle(Point.Empty, Size.Empty, HudColor.Red.GetColor())),
                        3 => m => m.SetBannerType(Game.CreateTextureFromFile("cursor_32_2.png")),
                        _ => throw new InvalidOperationException("Invalid banner type")
                    });
                };
                
                var title = NewTextEditingItem(nameof(Title), $"Select to modify the ~b~{nameof(UIMenu)}.{nameof(Title)}~s~ property.",
                                               () => Title,
                                               s => ApplyToEachMenu(m => m.Title = s));

                var titleColor = NewColorsItem("Title Color", $"Modifies the color of the ~b~{nameof(UIMenu)}.{nameof(TitleStyle)}~s~ property.");
                titleColor.IndexChanged += (s, o, n) =>
                {
                    Color c = titleColor.SelectedItem.GetColor();
                    ApplyToEachMenu(m => m.TitleStyle = m.TitleStyle.With(color: c));
                };

                var subtitleColor = NewColorsItem("Subtitle Color", $"Modifies the color of the ~b~{nameof(UIMenu)}.{nameof(SubtitleStyle)}~s~ property.");
                subtitleColor.IndexChanged += (s, o, n) =>
                {
                    Color c = subtitleColor.SelectedItem.GetColor();
                    ApplyToEachMenu(m => m.SubtitleStyle = m.SubtitleStyle.With(color: c));
                };

                var descriptionOverride = NewTextEditingItem("Description Override", $"Select to modify the ~b~{nameof(UIMenu)}.{nameof(DescriptionOverride)}~s~ property.",
                                               () => DescriptionOverride ?? string.Empty,
                                               s => ApplyToEachMenu(m => m.DescriptionOverride = s.Length == 0 ? null : s));

                var descriptionColor = NewColorsItem("Description Color", $"Modifies the color of the ~b~{nameof(UIMenu)}.{nameof(DescriptionStyle)}~s~ property.");
                descriptionColor.IndexChanged += (s, o, n) =>
                {
                    Color c = descriptionColor.SelectedItem.GetColor();
                    ApplyToEachMenu(m => m.DescriptionStyle = m.DescriptionStyle.With(color: c));
                };

                var descriptionSeparatorColor = NewColorsItem("Description Separator", $"Modifies the ~b~{nameof(UIMenu)}.{nameof(DescriptionSeparatorColor)}~s~ property.");
                descriptionSeparatorColor.SelectedItem = HudColor.Black;
                descriptionSeparatorColor.IndexChanged += (s, o, n) =>
                {
                    Color c = descriptionSeparatorColor.SelectedItem.GetColor();
                    ApplyToEachMenu(m => m.DescriptionSeparatorColor = c);
                };

                var counterOverride = NewTextEditingItem("Counter Override", $"Select to modify the ~b~{nameof(UIMenu)}.{nameof(CounterOverride)}~s~ property.",
                                               () => CounterOverride ?? string.Empty,
                                               s => ApplyToEachMenu(m => m.CounterOverride = s.Length == 0 ? null : s));

                var counterColor = NewColorsItem("Counter Color", $"Modifies the color of the ~b~{nameof(UIMenu)}.{nameof(CounterStyle)}~s~ property.");
                counterColor.IndexChanged += (s, o, n) =>
                {
                    Color c = counterColor.SelectedItem.GetColor();
                    ApplyToEachMenu(m => m.CounterStyle = m.CounterStyle.With(color: c));
                };

                var scaleWithSafezone = new UIMenuCheckboxItem("Scale with Safe-Zone", ScaleWithSafezone, $"Modifies the ~b~{nameof(UIMenu)}.{nameof(ScaleWithSafezone)}~s~ property.");
                scaleWithSafezone.Checked = ScaleWithSafezone;
                scaleWithSafezone.CheckboxEvent += (s, v) => ApplyToEachMenu(m => m.ScaleWithSafezone = v);

                visualOptionsMenu.AddItems(width, offsetX, offsetY, bannerType, title, titleColor, subtitleColor,
                                           descriptionOverride, descriptionColor, descriptionSeparatorColor,
                                           counterOverride, counterColor, scaleWithSafezone);
            }

            // checkbox
            {
                checkboxMenu.AddItems(
                    new UIMenuCheckboxItem("#1", false, "Unchecked."),
                    new UIMenuCheckboxItem("#2", true, "Checked."),
                    new UIMenuCheckboxItem("#3", false, "Unchecked and disabled.") { Enabled = false },
                    new UIMenuCheckboxItem("#4", true, "Checked and disabled.") { Enabled = false },
                    new UIMenuCheckboxItem("#5", false, "With right badge.") { RightBadge = UIMenuItem.BadgeStyle.Armour },
                    new UIMenuCheckboxItem("#6", true, "With right badge.") { RightBadge = UIMenuItem.BadgeStyle.Armour },
                    new UIMenuCheckboxItem("#7", false, "With left badge.") { LeftBadge = UIMenuItem.BadgeStyle.Armour },
                    new UIMenuCheckboxItem("#8", true, "With left badge.") { LeftBadge = UIMenuItem.BadgeStyle.Armour },
                    new UIMenuCheckboxItem("#9", false, "With both badges.") { RightBadge = UIMenuItem.BadgeStyle.Armour, LeftBadge = UIMenuItem.BadgeStyle.Armour },
                    new UIMenuCheckboxItem("#10", true, "With both badges.") { RightBadge = UIMenuItem.BadgeStyle.Armour, LeftBadge = UIMenuItem.BadgeStyle.Armour },
                    new UIMenuCheckboxItem("#11", false, "With both badges and disabled.") { Enabled = false, RightBadge = UIMenuItem.BadgeStyle.Armour, LeftBadge = UIMenuItem.BadgeStyle.Armour },
                    new UIMenuCheckboxItem("#12", true, "With both badges and disabled.") { Enabled = false, RightBadge = UIMenuItem.BadgeStyle.Armour, LeftBadge = UIMenuItem.BadgeStyle.Armour },
                    new UIMenuCheckboxItem("#13", false, "With custom background color.") { BackColor = Color.FromArgb(140, HudColor.RedDark.GetColor()), HighlightedBackColor = Color.FromArgb(230, HudColor.TechRed.GetColor()) },
                    new UIMenuCheckboxItem("#14", true, "With custom background color.") { BackColor = Color.FromArgb(140, HudColor.RedDark.GetColor()), HighlightedBackColor = Color.FromArgb(230, HudColor.TechRed.GetColor()) },
                    new UIMenuCheckboxItem("#14", false, "With custom badge.") { RightBadgeInfo = new UIMenuItem.BadgeInfo("commonmenu", "mp_alerttriangle", HudColor.Red.GetColor()) },
                    new UIMenuCheckboxItem("#15", true, "With custom badge.") { RightBadgeInfo = new UIMenuItem.BadgeInfo("commonmenu", "mp_alerttriangle", HudColor.Red.GetColor()) },
                    new UIMenuCheckboxItem("#16", true, "With cross instead of tick.") { Style = UIMenuCheckboxStyle.Cross },
                    CreateTriStateCheckbox("#17", "Checkbox with three states: unchecked, checked with tick and checked with cross.")
                );

                static UIMenuCheckboxItem CreateTriStateCheckbox(string name, string description)
                {
                    var cb = new UIMenuCheckboxItem(name, false, description);

                    cb.Activated += (s, i) =>
                    {
                        if (cb.Checked)
                        {
                            if (cb.Style == UIMenuCheckboxStyle.Tick)
                            {
                                cb.Style = UIMenuCheckboxStyle.Cross;
                                cb.Checked = !cb.Checked; // make the item checked
                            }
                            else
                            {
                                cb.Style = UIMenuCheckboxStyle.Tick;
                            }
                        }
                    };

                    return cb;
                }
            }

            // scroller
            {
                string[] values = new[] { "Hello", "World", "Foo", "Bar" };
                scrollerMenu.AddItems(
                    new UIMenuListScrollerItem<string>("List #1", "List scroller.", values),
                    new UIMenuListScrollerItem<string>("List #2", "List scroller disabled.", values) { Enabled = false },
                    new UIMenuListScrollerItem<string>("List #3", "List scroller disabled with scrolling enabled.", values) { Enabled = false, ScrollingEnabledWhenDisabled = true },
{'fraction_non_alphanumeric': 0.11970557851239669, 'fraction_numerical': 0.006973140495867769, 'mean_word_length': 2.057375970522437, 'pattern_counts': {'":': 6, '<': 23, '<?xml version=': 0, '>': 102, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 32, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4311407', 'n_tokens_mistral': 6584, 'n_tokens_neox': 6195, 'n_words': 1320}