protected virtual void DrawImpl(Rect position, GUIContent label)
        {
            var rowHeight = GUI.skin.font.lineHeight;

            rowHeight += GUI.skin.label.margin.vertical + GUI.skin.label.padding.vertical;
            var pos = new GUILayoutPosition(position, rowHeight);

            if (Target.CurrentType == SerializedTarget.Type.SerializedProperty)
            {
                using (var scope = new EditorGUI.ChangeCheckScope())
                {
                    var foldoutPos = pos.GetSplitPos(3f, 0);
                    _foldout = EditorGUI.Foldout(foldoutPos, _foldout, label);

                    var objFieldPos = pos.GetSplitPos(3f, 1, 2);
                    var newObj      = EditorGUI.ObjectField(objFieldPos, Target.ObjectReference, typeof(TDictionary), false);
                    if (scope.changed)
                    {
                        Target.ObjectReference = newObj;
                    }
                }
                if (!_foldout || Target.ObjectReference == null)
                {
                    return;
                }
            }
            else
            {
                EditorGUI.LabelField(pos.Pos, label);
            }

            var assetInstance = Dictionary;

            if (assetInstance == null)
            {
                pos.IncrementRow();
                var labelPos = pos.Pos;
                EditorGUI.LabelField(labelPos, "Don't Found Reference...");
                return;
            }

            var SO = new SerializedObject(assetInstance);

            var(doApply, nextPos) = OnDrawElementsBefore(pos, SO, rowHeight);
            pos = nextPos;
            if (doApply)
            {
                return;
            }

            using (var indent1 = new EditorGUI.IndentLevelScope())
            {
                var indentPos = pos.Indent(true);
                DrawElements(indentPos, SO, rowHeight);
            }
        }
        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            var textTemplateEngine = GetTargetTextTemplateEngine(property);
            var keywordProp        = property.FindPropertyRelative("keyword");
            var valueProp          = property.FindPropertyRelative("value");

            int selectedKeywordIndex = textTemplateEngine.Keywords
                                       .Zip(Enumerable.Range(0, textTemplateEngine.Keywords.Count()), (_k, _i) => (_k, _i))
                                       .Where(_t => _t._k.key == keywordProp.stringValue)
                                       .Select(_t => _t._i).FirstOrDefault();

            int selectedValueIndex = 0;

            if (textTemplateEngine.Keywords.Any())
            {
                selectedValueIndex = textTemplateEngine.Keywords
                                     .ElementAt(selectedKeywordIndex)
                                     .values.FindIndex(_i => _i == valueProp.stringValue);
            }

            var pos = new GUILayoutPosition(position);

            pos.Indent(false, 0.3f);
            var  posWidth   = 6;
            var  popupWidth = 2;
            bool isUpdated  = false;

            using (var horizontalScope = new GUILayout.HorizontalScope())
            {
                EditorGUI.LabelField(pos.GetSplitPos(posWidth, 0, 1), "Key");

                var keywordList = textTemplateEngine.Keywords.Select(_k => _k.key);
                if (!keywordList.Any())
                {
                    keywordList = Enumerable.Repeat("", 1);
                }

                selectedKeywordIndex = Mathf.Clamp(selectedKeywordIndex, 0, keywordList.Count() - 1);
                var newSelectedKeywordIndex = EditorGUI.Popup(pos.GetSplitPos(posWidth, 1, popupWidth), selectedKeywordIndex, keywordList.ToArray());

                if (newSelectedKeywordIndex != selectedKeywordIndex)
                {
                    isUpdated            = true;
                    selectedKeywordIndex = newSelectedKeywordIndex;
                    selectedValueIndex   = 0;
                }

                EditorGUI.LabelField(pos.GetSplitPos(posWidth, 3, 1), "Val");
                var valueList = (selectedKeywordIndex < textTemplateEngine.Keywords.Count())
                    ? textTemplateEngine.Keywords.ElementAt(selectedKeywordIndex).values.AsEnumerable()
                    : Enumerable.Repeat("", 1);
                var newSelectedValueIndex = EditorGUI.Popup(pos.GetSplitPos(posWidth, 4, popupWidth), selectedValueIndex, valueList.ToArray());
                if (newSelectedValueIndex != selectedValueIndex)
                {
                    isUpdated          = true;
                    selectedValueIndex = newSelectedValueIndex;
                }
            }

            if (isUpdated)
            {
                var keyword = textTemplateEngine.Keywords.ElementAt(selectedKeywordIndex);
                property.FindPropertyRelative("keyword").stringValue = keyword.key;
                property.FindPropertyRelative("value").stringValue   = keyword.values[selectedValueIndex];
            }
        }