<commit_before>﻿// Copyright (c) 2007-2018 ppy Pty Ltd <<EMAIL>>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using OpenTK;
using OpenTK.Graphics;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Extensions.TypeExtensions;

namespace osu.Framework.Graphics.Visualisation
{
    internal class PropertyDisplay : VisibilityContainer
    {
        private readonly FillFlowContainer flow;

        private const float width = 600;

        protected override Container<Drawable> Content => flow;

        public PropertyDisplay()
        {
            Width = width;
            RelativeSizeAxes = Axes.Y;

            AddInternal(new ScrollContainer
            {
                Padding = new MarginPadding(10),
                RelativeSizeAxes = Axes.Both,
                ScrollbarOverlapsContent = false,
                Child = flow = new FillFlowContainer
                {
                    RelativeSizeAxes = Axes.X,
                    AutoSizeAxes = Axes.Y,
                    Direction = FillDirection.Vertical
                }
            });
        }

        public void UpdateFrom(Drawable source)
        {
            Clear();

            if (source == null)
                return;

            Type type = source.GetType();

            var properties = (IEnumerable<MemberInfo>)type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
                                                          // Only properties which we can read
                                                          .Where(p => p.CanRead);

            var fields = (IEnumerable<MemberInfo>)type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
                                                      // Exclude the backing fields of properties
                                                      .Where(f => f.GetCustomAttribute<CompilerGeneratedAttribute>() == null);

            // Upper, then lower-case
            var allMembers = properties.Concat(fields).OrderBy(m => (int)m.Name[0]).ThenBy(m => m.Name);

            AddRange(allMembers.Select(member => new PropertyItem(member, source)));
        }

        protected override void PopIn()
        {
            this.ResizeWidthTo(width, 500, Easing.OutQuint);
        }

        protected override void PopOut()
        {
            this.ResizeWidthTo(0, 500, Easing.OutQuint);
        }

        private class PropertyItem : Container
        {
            private readonly SpriteText valueText;
            private readonly Box changeMarker;
            private readonly Func<object> getValue;

            public PropertyItem(MemberInfo info, IDrawable d)
            {
                Type type;<commit_msg>Retrieve all inherited members for property display<commit_after>﻿// Copyright (c) 2007-2018 ppy Pty Ltd <<EMAIL>>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using OpenTK;
using OpenTK.Graphics;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Extensions.TypeExtensions;

namespace osu.Framework.Graphics.Visualisation
{
    internal class PropertyDisplay : VisibilityContainer
    {
        private readonly FillFlowContainer flow;

        private const float width = 600;

        protected override Container<Drawable> Content => flow;

        public PropertyDisplay()
        {
            Width = width;
            RelativeSizeAxes = Axes.Y;

            AddInternal(new ScrollContainer
            {
                Padding = new MarginPadding(10),
                RelativeSizeAxes = Axes.Both,
                ScrollbarOverlapsContent = false,
                Child = flow = new FillFlowContainer
                {
                    RelativeSizeAxes = Axes.X,
                    AutoSizeAxes = Axes.Y,
                    Direction = FillDirection.Vertical
                }
            });
        }

        public void UpdateFrom(Drawable source)
        {
            Clear();

            if (source == null)
                return;

            var allMembers = new List<MemberInfo>();

            Type type = source.GetType();
            while (type != null && type != typeof(object))
            {
                type.GetMembers(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly)
                    .Where(m => m is FieldInfo || m is PropertyInfo pi && pi.GetMethod != null)
                    .ForEach(m => allMembers.Add(m));

                type = type.BaseType;
            }

            // Order by upper then lower-case, and exclude auto-generated backing fields of properties
            AddRange(allMembers.OrderBy(m => m.Name[0]).ThenBy(m => m.Name)
                               .Where(m => m.GetCustomAttribute<CompilerGeneratedAttribute>() == null)
                               .Select(m => new PropertyItem(m, source)));
        }

        protected override void PopIn()
        {
            this.ResizeWidthTo(width, 500, Easing.OutQuint);
        }

        protected override void PopOut()
        {
            this.ResizeWidthTo(0, 500, Easing.OutQuint);
        }

        private class PropertyItem : Container
        {
            private readonly SpriteText valueText;
            private readonly Box changeMarker;
            private readonly Func<object> getValue;

            public PropertyItem(MemberInfo info, IDrawable d)
            {
                Type type;
{'fraction_non_alphanumeric': 0.08275174476570289, 'fraction_numerical': 0.006979062811565304, 'mean_word_length': 1.7969330855018588, 'pattern_counts': {'":': 0, '<': 16, '<?xml version=': 0, '>': 29, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6033399', 'n_tokens_mistral': 1537, 'n_tokens_neox': 1417, 'n_words': 355}