// ================================================================================ Inspector
        public override void OnInspectorGui()
        {
            BGEditorUtility.Assign(ref whiteTexture, () => BGEditorUtility.Texture1X1(Color.white));

            components = Curve.GetComponents <BGCc>();
            var length = components.Length;

            tree.Refresh(components);

            if (tree.InitException != null)
            {
                EditorGUILayout.HelpBox("There was an error initializing editors for component's Tree View: " + tree.InitException.Message +
                                        "\r\n\r\nYou still can use default Unity's editors for components below.", MessageType.Error);
                return;
            }


            var hasError   = HasError;
            var hasWarning = HasWarning;

            BGEditorUtility.HorizontalBox(() =>
            {
                EditorGUILayout.LabelField("Components: " + length + " (" + (hasError ? "Error" : "Ok") + ")");

                GUILayout.FlexibleSpace();

                // turn on/off handles
                var handlesOff = BGCurveSettingsForEditor.CcInspectorHandlesOff;
                if (BGEditorUtility.ButtonWithIcon(
                        handlesOff
                        ? BGBinaryResources.BGHandlesOff123
                        : BGBinaryResources.BGHandlesOn123,
                        "Turn on/off handles settings in Inspector"))
                {
                    BGCurveSettingsForEditor.CcInspectorHandlesOff = !BGCurveSettingsForEditor.CcInspectorHandlesOff;
                }
                EditorGUILayout.Separator();

                // turn on/off colored tree
                if (BGEditorUtility.ButtonWithIcon(customEditorsOn ? BGBinaryResources.BGOn123: BGBinaryResources.BGOff123, "Use custom UI for components (colored tree) and hide standard unity editors for components"))
                {
                    customEditorsOn = !customEditorsOn;
                    tree.Refresh(null, true);
                }
                EditorGUILayout.Separator();

                if (length > 0)
                {
                    // collapse/expand
                    if (BGEditorUtility.ButtonWithIcon(BGBinaryResources.BGCollapseAll123, "Collapse all components"))
                    {
                        tree.ExpandCollapseAll(true);
                    }
                    EditorGUILayout.Separator();
                    if (BGEditorUtility.ButtonWithIcon(BGBinaryResources.BGExpandAll123, "Expand all components"))
                    {
                        tree.ExpandCollapseAll(false);
                    }
                    EditorGUILayout.Separator();


                    // delete all Ccs
                    if (BGEditorUtility.ButtonWithIcon(BGBinaryResources.BGDelete123, "Delete all components") &&
                        BGEditorUtility.Confirm("Delete", "Are you sure you want to delete " + length + " component(s)?", "Delete"))
                    {
                        tree.Delete();
                    }
                    EditorGUILayout.Separator();
                }

                //add new Cc
                if (BGEditorUtility.ButtonWithIcon(BGBinaryResources.BGAdd123, "Add new component"))
                {
                    BGCcAddWindow.Open(Curve, type => AddComponent(Curve, type));
                }
            });


            if (length > 0)
            {
                // warnings/errors
                if (hasWarning || hasError)
                {
                    for (var i = 0; i < components.Length; i++)
                    {
                        var component = components[i];

                        var name = (component.Descriptor != null ? component.Descriptor.Name + " " : "") + component.CcName;

                        var error = component.Error;
                        if (!string.IsNullOrEmpty(error))
                        {
                            BGEditorUtility.HelpBox("Component error [" + name + "]: " + error, MessageType.Error);
                        }

                        var warning = component.Warning;
                        if (!string.IsNullOrEmpty(warning))
                        {
                            BGEditorUtility.HelpBox("Component warning [" + name + "]: " + warning, MessageType.Warning);
                        }
                    }
                }
                else
                {
                    BGEditorUtility.HelpBox("No warnings or errors", MessageType.Info);
                }

                // tree GUI
                tree.OnInspectorGui();
            }
            else
            {
                EditorGUILayout.HelpBox(
                    "Hit the Plus icon to add a component"
                    + "\r\n"
                    + "\r\n"
                    + "Components allows to add functionality without any scripting."
                    , MessageType.Info);
            }


            if (hasError ^ HasError || hasWarning ^ HasWarning)
            {
                EditorApplication.RepaintHierarchyWindow();
            }
        }
                private void HeaderUi(int level, bool hasError)
                {
                    var color = MyTree.GetColor(level, Collapsed, () => new Color(0, 0, 0, 0));

                    BGEditorUtility.SwapGuiBackgroundColor(color, () =>
                    {
                        BGEditorUtility.Horizontal(headerBoxStyle, () =>
                        {
                            BGEditorUtility.Indent(1, () =>
                            {
                                var content = new GUIContent(descriptor == null ? Cc.GetType().Name : descriptor.Name + " (" + BGEditorUtility.Trim(Cc.CcName, 10) + ")",
                                                             descriptor == null ? null : descriptor.Description);
                                var width = headerFoldoutStyle.CalcSize(content).x + 16;

                                BGEditorUtility.SwapLabelWidth((int)width, () =>
                                {
                                    //foldout (we dont use layout version cause it does not support clickin on labels)
                                    Collapsed = EditorGUI.Foldout(
                                        GUILayoutUtility.GetRect(width, 16f),
                                        Collapsed,
                                        content,
                                        true,
                                        Cc.enabled ? headerFoldoutStyle : headerFoldoutStyleDisabled);
                                });
                            });

                            GUILayout.FlexibleSpace();

                            // status(error or Ok)
                            EditorGUI.LabelField(GUILayoutUtility.GetRect(70, 16, EditorStyles.label), hasError ? "Error" : "Ok.", hasError ? errorStyle : okStyle);


                            //help url
                            if (!String.IsNullOrEmpty(Cc.HelpURL))
                            {
                                if (BGEditorUtility.ButtonWithIcon(BGBinaryResources.BGHelp123, "Open help in the browser"))
                                {
                                    Application.OpenURL(Cc.HelpURL);
                                }
                                EditorGUILayout.Separator();
                            }

                            //change visibility
                            if (BGEditorUtility.ButtonWithIcon(Cc.Hidden ? BGBinaryResources.BGHiddenOn123 : BGBinaryResources.BGHiddenOff123, "Hide/Show properties"))
                            {
                                Cc.Hidden = !Cc.Hidden;
                            }
                            EditorGUILayout.Separator();

                            //change name
                            if (BGEditorUtility.ButtonWithIcon(BGBinaryResources.BGCcEditName123, "Change the name"))
                            {
                                BGCcChangeNameWindow.Open(Cc);
                            }
                            EditorGUILayout.Separator();

                            //add a child
                            if (BGEditorUtility.ButtonWithIcon(BGBinaryResources.BGAdd123, "Add a component, which is dependant on this component"))
                            {
                                BGCcAddWindow.Open(MyTree.Curve, type =>
                                {
                                    //cache some data
                                    var gameObject    = Cc.Curve.gameObject;
                                    var oldComponents = gameObject.GetComponents <BGCc>();
                                    var currentCcType = Cc.GetType();

                                    //add
                                    var addedCc = AddComponent(MyTree.Curve, type);
                                    if (addedCc == null)
                                    {
                                        return;
                                    }

                                    //we need to process all the way up to the Cc and link Ccs to right (newly created) parents
                                    var parentClass    = addedCc.GetParentClass();
                                    var recursionLimit = 16;
                                    var cc             = addedCc;
                                    while (parentClass != null && recursionLimit-- > 0)
                                    {
                                        if (currentCcType == parentClass)
                                        {
                                            //we reached the current Cc
                                            cc.SetParent(Cc);
                                            break;
                                        }

                                        //going up
                                        var possibleParents = gameObject.GetComponents(parentClass);
                                        var parent          = possibleParents.Where(possibleParent => !oldComponents.Contains(possibleParent)).Cast <BGCc>().FirstOrDefault();

                                        if (parent == null)
                                        {
                                            break;
                                        }

                                        cc.SetParent(parent);
                                        cc          = parent;
                                        parentClass = cc.GetParentClass();
                                    }
                                }, Cc.GetType());
                            }
                            EditorGUILayout.Separator();


                            //enable/disable
                            if (BGEditorUtility.ButtonWithIcon(Cc.enabled ? BGBinaryResources.BGTickYes123 : BGBinaryResources.BGTickNo123, "Enable/disable a component"))
                            {
                                Enable(!Cc.enabled);
                            }
                            EditorGUILayout.Separator();

                            //delete
                            if (!BGEditorUtility.ButtonWithIcon(BGBinaryResources.BGDelete123, "Remove this component"))
                            {
                                return;
                            }


                            //remove
                            Delete();

                            EditorUtility.SetDirty(MyTree.Curve.gameObject);

                            //not sure how to make proper exit
                            throw new BGEditorUtility.ExitException();
                        });
                    });
                }
                private void HeaderUi(int level, bool hasError)
                {
                    var color = MyTree.GetColor(level, Collapsed, () => new Color(0, 0, 0, 0));

                    BGEditorUtility.SwapGuiBackgroundColor(color, () =>
                    {
                        BGEditorUtility.Horizontal(headerBoxStyle, () =>
                        {
                            BGEditorUtility.Indent(1, () =>
                            {
                                var content = new GUIContent(descriptor == null ? Cc.GetType().Name : descriptor.Name + " (" + BGEditorUtility.Trim(Cc.CcName, 10) + ")",
                                                             descriptor == null ? null : descriptor.Description);
                                var width = headerFoldoutStyle.CalcSize(content).x + 16;

                                BGEditorUtility.SwapLabelWidth((int)width, () =>
                                {
                                    //foldout (we dont use layout version cause it does not support clickin on labels)
                                    Collapsed = EditorGUI.Foldout(
                                        GUILayoutUtility.GetRect(width, 16f),
                                        Collapsed,
                                        content,
                                        true,
                                        Cc.enabled ? headerFoldoutStyle : headerFoldoutStyleDisabled);
                                });
                            });

                            GUILayout.FlexibleSpace();

                            // status(error or Ok)
                            EditorGUI.LabelField(GUILayoutUtility.GetRect(70, 16, EditorStyles.label), hasError ? "Error" : "Ok.", hasError ? errorStyle : okStyle);


                            //help url
                            if (!String.IsNullOrEmpty(Cc.HelpURL))
                            {
                                if (BGEditorUtility.ButtonWithIcon(helpTexture, "Open help in the browser"))
                                {
                                    Application.OpenURL(Cc.HelpURL);
                                }
                                EditorGUILayout.Separator();
                            }

                            //change name
                            if (BGEditorUtility.ButtonWithIcon(changeNameTexture, "Change the name"))
                            {
                                BGCcChangeNameWindow.Open(Cc);
                            }
                            EditorGUILayout.Separator();

                            //add child
                            if (BGEditorUtility.ButtonWithIcon(addTexture, "Add a component, which is dependant on this component"))
                            {
                                BGCcAddWindow.Open(MyTree.Curve, type =>
                                {
                                    var bgCc = AddComponent(MyTree.Curve, type);
                                    bgCc.SetParent(Cc);
                                }, Cc.GetType());
                            }
                            EditorGUILayout.Separator();


                            //enable/disable
                            if (BGEditorUtility.ButtonWithIcon(Cc.enabled ? enabledTexture : disabledTexture, "Enable/disable a component"))
                            {
                                Enable(!Cc.enabled);
                            }
                            EditorGUILayout.Separator();

                            //delete
                            if (!BGEditorUtility.ButtonWithIcon(deleteTexture, "Remove this component"))
                            {
                                return;
                            }


                            //remove
                            Delete();

                            EditorUtility.SetDirty(MyTree.Curve.gameObject);

                            //not sure how to make proper exit
                            throw new ExitException();
                        });
                    });
                }