public override void HandleType(BSMLParser.ComponentTypeWithData componentType, BSMLParserParams parserParams)
            {
                base.HandleType(componentType, parserParams);
                var buttonCollection = componentType.component as ButtonCollection;

                buttonCollection.SetTexts(new[] { "t1", "t2", "t3" });
                buttonCollection.parserParams = parserParams;
                parserParams.AddEvent("post-parse", buttonCollection.Setup);
            }
            public override void HandleType(BSMLParser.ComponentTypeWithData componentType, BSMLParserParams parserParams)
            {
                Debug.LogError("Handler handling stuff");
                base.HandleType(componentType, parserParams);
                ButtonCollection buttonCollection = (componentType.component as ButtonCollection);

                buttonCollection.SetTexts(new [] { "t1", "t2", "t3" });
                buttonCollection.parserParams = parserParams;
                parserParams.AddEvent("post-parse", buttonCollection.Setup);
            }
Exemple #3
0
        public BSMLParserParams Parse(XmlNode parentNode, GameObject parent, object host = null)
        {
            BSMLParserParams parserParams = new BSMLParserParams();

            parserParams.host = host;
            if (host != null)
            {
                foreach (MethodInfo methodInfo in host.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
                {
                    UIAction uiaction = methodInfo.GetCustomAttributes(typeof(UIAction), true).FirstOrDefault() as UIAction;
                    if (uiaction != null)
                    {
                        parserParams.actions.Add(uiaction.id, new BSMLAction(host, methodInfo));
                    }
                }

                foreach (FieldInfo fieldInfo in host.GetType().GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
                {
                    UIValue uivalue = fieldInfo.GetCustomAttributes(typeof(UIValue), true).FirstOrDefault() as UIValue;
                    if (uivalue != null)
                    {
                        parserParams.values.Add(uivalue.id, new BSMLFieldValue(host, fieldInfo));
                    }

                    UIParams uiParams = fieldInfo.GetCustomAttributes(typeof(UIParams), true).FirstOrDefault() as UIParams;
                    if (uiParams != null)
                    {
                        fieldInfo.SetValue(host, parserParams);
                    }
                }

                foreach (PropertyInfo propertyInfo in host.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
                {
                    UIValue uivalue = propertyInfo.GetCustomAttributes(typeof(UIValue), true).FirstOrDefault() as UIValue;
                    if (uivalue != null)
                    {
                        parserParams.values.Add(uivalue.id, new BSMLPropertyValue(host, propertyInfo));
                    }
                }
            }

            foreach (XmlNode node in parentNode.ChildNodes)
            {
                HandleNode(node, parent, parserParams);
            }

            foreach (KeyValuePair <string, BSMLAction> action in parserParams.actions.Where(x => x.Key.StartsWith(SUBSCRIVE_EVENT_ACTION_PREFIX)))
            {
                parserParams.AddEvent(action.Key.Substring(1), delegate { action.Value.Invoke(); });
            }

            parserParams.EmitEvent("post-parse");

            return(parserParams);
        }
Exemple #4
0
        public override void HandleType(BSMLParser.ComponentTypeWithData componentType, BSMLParserParams parserParams)
        {
            BSMLScrollableContainer scrollView = componentType.component as BSMLScrollableContainer;

            if (componentType.data.TryGetValue("id", out string id))
            {
                parserParams.AddEvent(id + "#PageUp", scrollView.PageUpButtonPressed);
                parserParams.AddEvent(id + "#PageDown", scrollView.PageDownButtonPressed);
            }

            if (componentType.data.TryGetValue("maskOverflow", out string value))
            {
                scrollView.MaskOverflow = bool.TryParse(value, out bool bval) ? bval : true;
            }

            if (componentType.data.TryGetValue("alignBottom", out value))
            {
                scrollView.AlignBottom = bool.TryParse(value, out bool bval) ? bval : false;
            }
        }
        public override void HandleType(ComponentTypeWithData componentType, BSMLParserParams parserParams)
        {
            try
            {
                ModalView modalView      = componentType.component as ModalView;
                Transform originalParent = modalView.transform.parent;
                bool      moveToCenter   = true;
                if (componentType.data.TryGetValue("moveToCenter", out string moveToCenterString))
                {
                    moveToCenter = bool.Parse(moveToCenterString);
                }

                if (componentType.data.TryGetValue("showEvent", out string showEvent))
                {
                    parserParams.AddEvent(showEvent, delegate
                    {
                        modalView.Show(true, moveToCenter);
                    });
                }

                if (componentType.data.TryGetValue("hideEvent", out string hideEvent))
                {
                    parserParams.AddEvent(hideEvent, delegate
                    {
                        modalView.Hide(true, () => modalView.transform.SetParent(originalParent, true));
                    });
                }

                if (componentType.data.TryGetValue("clickOffCloses", out string clickOffCloses) && Parse.Bool(clickOffCloses))
                {
                    modalView._blockerClickedEvent += delegate
                    {
                        modalView.Hide(true, () => modalView.transform.SetParent(originalParent, true));
                    };
                }
            }
            catch (Exception ex)
            {
                Logger.log?.Error(ex);
            }
        }
        public override void HandleType(ComponentTypeWithData componentType, BSMLParserParams parserParams)
        {
            base.HandleType(componentType, parserParams);
            TabSelector tabSelector = (componentType.component as TabSelector);

            tabSelector.parserParams = parserParams;
            if (!componentType.data.TryGetValue("tabTag", out string tabTag))
            {
                throw new Exception("Tab Selector must have a tab-tag");
            }
            tabSelector.tabTag = tabTag;
            parserParams.AddEvent("post-parse", tabSelector.Setup);
        }
        public override void HandleType(ComponentTypeWithData componentType, BSMLParserParams parserParams)
        {
            CustomCellListTableData tableData = componentType.component as CustomCellListTableData;

            if (componentType.data.TryGetValue("selectCell", out string selectCell))
            {
                tableData.tableView.didSelectCellWithIdxEvent += delegate(TableView table, int index)
                {
                    if (!parserParams.actions.TryGetValue(selectCell, out BSMLAction action))
                    {
                        throw new Exception("select-cell action '" + componentType.data["selectCell"] + "' not found");
                    }

                    action.Invoke(table, (table.dataSource as CustomCellListTableData).data[index]);
                };
            }

            if (componentType.data.TryGetValue("listDirection", out string listDirection))
            {
                tableData.tableView.SetField <TableView, TableType>("_tableType", (TableType)Enum.Parse(typeof(TableType), listDirection));
            }

            if (componentType.data.TryGetValue("cellSize", out string cellSize))
            {
                tableData.cellSize = Parse.Float(cellSize);
            }

            if (componentType.data.TryGetValue("cellTemplate", out string cellTemplate))
            {
                tableData.cellTemplate = "<bg>" + cellTemplate + "</bg>";
            }

            if (componentType.data.TryGetValue("cellClickable", out string cellClickable))
            {
                tableData.clickableCells = Parse.Bool(cellClickable);
            }

            if (componentType.data.TryGetValue("alignCenter", out string alignCenter))
            {
                tableData.tableView.SetField <TableView, bool>("_alignToCenter", Parse.Bool(alignCenter));
            }

            if (componentType.data.TryGetValue("data", out string value))
            {
                if (!parserParams.values.TryGetValue(value, out BSMLValue contents))
                {
                    throw new Exception("value '" + value + "' not found");
                }
                tableData.data = contents.GetValue() as List <object>;
                tableData.tableView.ReloadData();
            }

            switch (tableData.tableView.tableType)
            {
            case TableType.Vertical:
                (componentType.component.gameObject.transform as RectTransform).sizeDelta = new Vector2(componentType.data.TryGetValue("listWidth", out string vListWidth) ? Parse.Float(vListWidth) : 60, tableData.cellSize * (componentType.data.TryGetValue("visibleCells", out string vVisibleCells) ? Parse.Float(vVisibleCells) : 7));
                break;

            case TableType.Horizontal:
                (componentType.component.gameObject.transform as RectTransform).sizeDelta = new Vector2(tableData.cellSize * (componentType.data.TryGetValue("visibleCells", out string hVisibleCells) ? Parse.Float(hVisibleCells) : 4), componentType.data.TryGetValue("listHeight", out string hListHeight) ? Parse.Float(hListHeight) : 40);
                break;
            }

            componentType.component.gameObject.GetComponent <LayoutElement>().preferredHeight = (componentType.component.gameObject.transform as RectTransform).sizeDelta.y;
            componentType.component.gameObject.GetComponent <LayoutElement>().preferredWidth  = (componentType.component.gameObject.transform as RectTransform).sizeDelta.x;

            tableData.tableView.gameObject.SetActive(true);
            tableData.tableView.LazyInit();

            if (componentType.data.TryGetValue("id", out string id))
            {
                ScrollView scroller = tableData.tableView.GetField <ScrollView, TableView>("_scrollView");
                parserParams.AddEvent(id + "#PageUp", scroller.PageUpButtonPressed);
                parserParams.AddEvent(id + "#PageDown", scroller.PageDownButtonPressed);
            }
        }
Exemple #8
0
        public override void HandleType(BSMLParser.ComponentTypeWithData componentType, BSMLParserParams parserParams)
        {
            var tableData = componentType.component as CustomListTableData;

            if (componentType.data.TryGetValue("selectCell", out var selectCell))
            {
                tableData.TableView.didSelectCellWithIdxEvent += delegate(TableView table, int index)
                {
                    if (!parserParams.actions.TryGetValue(selectCell, out var action))
                    {
                        throw new Exception("select-cell action '" + componentType.data["onClick"] + "' not found");
                    }

                    action.Invoke(table, index);
                };
            }

            if (componentType.data.TryGetValue("listDirection", out var listDirection))
            {
                tableData.TableView.SetField("_tableType", (TableView.TableType)Enum.Parse(typeof(TableView.TableType), listDirection));
            }

            if (componentType.data.TryGetValue("listStyle", out var listStyle))
            {
                tableData.Style = (CustomListTableData.ListStyle)Enum.Parse(typeof(CustomListTableData.ListStyle), listStyle);
            }

            if (componentType.data.TryGetValue("cellSize", out var cellSize))
            {
                tableData.cellSize = Parse.Float(cellSize);
            }

            if (componentType.data.TryGetValue("expandCell", out var expandCell))
            {
                tableData.ExpandCell = Parse.Bool(expandCell);
            }

            if (componentType.data.TryGetValue("alignCenter", out var alignCenter))
            {
                tableData.TableView.SetField("_alignToCenter", Parse.Bool(alignCenter));
            }


            if (componentType.data.TryGetValue("data", out var value))
            {
                if (!parserParams.values.TryGetValue(value, out var contents))
                {
                    throw new Exception("value '" + value + "' not found");
                }

                tableData.Data = contents.GetValue() as List <CustomListTableData.CustomCellInfo>;
                tableData.TableView.ReloadData();
            }

            switch (tableData.TableView.tableType)
            {
            case TableView.TableType.Vertical:
                (componentType.component.gameObject.transform as RectTransform).sizeDelta = new Vector2(
                    componentType.data.TryGetValue("listWidth", out var vListWidth) ? Parse.Float(vListWidth) : 60,
                    tableData.cellSize * (componentType.data.TryGetValue("visibleCells", out var vVisibleCells)
                            ? Parse.Float(vVisibleCells)
                            : 7));
                break;

            case TableView.TableType.Horizontal:
                (componentType.component.gameObject.transform as RectTransform).sizeDelta = new Vector2(
                    tableData.cellSize * (componentType.data.TryGetValue("visibleCells", out var hVisibleCells) ? Parse.Float(hVisibleCells) : 4),
                    componentType.data.TryGetValue("listHeight", out var hListHeight) ? Parse.Float(hListHeight) : 40);
                break;
            }

            componentType.component.gameObject.GetComponent <LayoutElement>().preferredHeight =
                (componentType.component.gameObject.transform as RectTransform).sizeDelta.y;
            componentType.component.gameObject.GetComponent <LayoutElement>().preferredWidth =
                (componentType.component.gameObject.transform as RectTransform).sizeDelta.x;

            tableData.TableView.gameObject.SetActive(true);
            tableData.TableView.LazyInit();

            if (componentType.data.TryGetValue("id", out var id))
            {
                var scroller = tableData.TableView.GetField <ScrollView, TableView>("_scrollView");
                parserParams.AddEvent(id + "#PageUp", scroller.PageUpButtonPressed);
                parserParams.AddEvent(id + "#PageDown", scroller.PageDownButtonPressed);
            }
        }
        public override void HandleType(ComponentTypeWithData componentType, BSMLParserParams parserParams)
        {
            CustomListTableData tableData  = componentType.component as CustomListTableData;
            ScrollView          scrollView = tableData.tableView.GetField <ScrollView, TableView>("_scrollView");

            if (componentType.data.TryGetValue("selectCell", out string selectCell))
            {
                tableData.tableView.didSelectCellWithIdxEvent += delegate(TableView table, int index)
                {
                    if (!parserParams.actions.TryGetValue(selectCell, out BSMLAction action))
                    {
                        throw new Exception("select-cell action '" + componentType.data["onClick"] + "' not found");
                    }

                    action.Invoke(table, index);
                };
            }

            bool verticalList = true;

            if (componentType.data.TryGetValue("listDirection", out string listDirection))
            {
                tableData.tableView.SetField <TableView, TableType>("_tableType", (TableType)Enum.Parse(typeof(TableType), listDirection));
                scrollViewDirectionField.SetValue(scrollView, Enum.Parse(scrollViewDirectionField.FieldType, listDirection));
                verticalList = listDirection.ToLower() != "horizontal";
            }

            if (componentType.data.TryGetValue("listStyle", out string listStyle))
            {
                tableData.Style = (ListStyle)Enum.Parse(typeof(ListStyle), listStyle);
            }

            if (componentType.data.TryGetValue("cellSize", out string cellSize))
            {
                tableData.cellSize = Parse.Float(cellSize);
            }

            if (componentType.data.TryGetValue("expandCell", out string expandCell))
            {
                tableData.expandCell = Parse.Bool(expandCell);
            }

            if (componentType.data.TryGetValue("alignCenter", out string alignCenter))
            {
                tableData.tableView.SetField <TableView, bool>("_alignToCenter", Parse.Bool(alignCenter));
            }

            if (componentType.data.TryGetValue("stickScrolling", out string stickScrolling))
            {
                if (Parse.Bool(stickScrolling))
                {
                    scrollView.SetField("_platformHelper", BeatSaberUI.PlatformHelper);
                }
            }

            // We can only show the scroll bar for vertical lists
            if (verticalList && componentType.data.TryGetValue("showScrollbar", out string showScrollbar))
            {
                if (Parse.Bool(showScrollbar))
                {
                    TextPageScrollView textScrollView = UnityEngine.Object.Instantiate(ScrollViewTag.ScrollViewTemplate, componentType.component.transform);

                    Button pageUpButton   = textScrollView.GetField <Button, ScrollView>("_pageUpButton");
                    Button pageDownButton = textScrollView.GetField <Button, ScrollView>("_pageDownButton");
                    VerticalScrollIndicator verticalScrollIndicator = textScrollView.GetField <VerticalScrollIndicator, ScrollView>("_verticalScrollIndicator");
                    RectTransform           scrollBar = verticalScrollIndicator.transform.parent as RectTransform;

                    scrollView.SetField("_pageUpButton", pageUpButton);
                    scrollView.SetField("_pageDownButton", pageDownButton);
                    scrollView.SetField("_verticalScrollIndicator", verticalScrollIndicator);
                    scrollBar.SetParent(componentType.component.transform);
                    GameObject.Destroy(textScrollView.gameObject);

                    // Need to adjust scroll bar positioning
                    scrollBar.anchorMin = new Vector2(1, 0);
                    scrollBar.anchorMax = Vector2.one;
                    scrollBar.offsetMin = Vector2.zero;
                    scrollBar.offsetMax = new Vector2(8, 0);
                }
            }

            if (componentType.data.TryGetValue("data", out string value))
            {
                if (!parserParams.values.TryGetValue(value, out BSMLValue contents))
                {
                    throw new Exception("value '" + value + "' not found");
                }


                var tableDataValue = contents.GetValue();
                if (!(tableDataValue is List <CustomCellInfo> tableDataList))
                {
                    throw new Exception($"Value '{value}' is not a List<CustomCellInfo>, which is required for custom-list");
                }

                tableData.data = tableDataList;
                tableData.tableView.ReloadData();
            }

            switch (tableData.tableView.tableType)
            {
            case TableType.Vertical:
                (componentType.component.gameObject.transform as RectTransform).sizeDelta = new Vector2(componentType.data.TryGetValue("listWidth", out string vListWidth) ? Parse.Float(vListWidth) : 60, tableData.cellSize * (componentType.data.TryGetValue("visibleCells", out string vVisibleCells) ? Parse.Float(vVisibleCells) : 7));
                break;

            case TableType.Horizontal:
                (componentType.component.gameObject.transform as RectTransform).sizeDelta = new Vector2(tableData.cellSize * (componentType.data.TryGetValue("visibleCells", out string hVisibleCells) ? Parse.Float(hVisibleCells) : 4), componentType.data.TryGetValue("listHeight", out string hListHeight) ? Parse.Float(hListHeight) : 40);
                break;
            }

            componentType.component.gameObject.GetComponent <LayoutElement>().preferredHeight = (componentType.component.gameObject.transform as RectTransform).sizeDelta.y;
            componentType.component.gameObject.GetComponent <LayoutElement>().preferredWidth  = (componentType.component.gameObject.transform as RectTransform).sizeDelta.x;

            tableData.tableView.gameObject.SetActive(true);
            tableData.tableView.LazyInit();

            if (componentType.data.TryGetValue("id", out string id))
            {
                parserParams.AddEvent(id + "#PageUp", scrollView.PageUpButtonPressed);
                parserParams.AddEvent(id + "#PageDown", scrollView.PageDownButtonPressed);
            }
        }
Exemple #10
0
        public override void HandleType(BSMLParser.ComponentTypeWithData componentType, BSMLParserParams parserParams)
        {
            var tableData = (PropListTableData)componentType.component;

            if (componentType.data.TryGetValue("selectCell", out string selectCell))
            {
                tableData.tableView.didSelectCellWithIdxEvent += delegate(TableView table, int index)
                {
                    if (!parserParams.actions.TryGetValue(selectCell, out BSMLAction action))
                    {
                        throw new Exception("select-cell action '" + componentType.data["onClick"] + "' not found");
                    }

                    action.Invoke(table, index);
                };
            }

            if (componentType.data.TryGetValue("listDirection", out string listDirection))
            {
                tableData.tableView.SetField("_tableType", (TableView.TableType)Enum.Parse(typeof(TableView.TableType), listDirection));
            }

            if (componentType.data.TryGetValue("cellSize", out string cellSize))
            {
                tableData.cellSize = Parse.Float(cellSize);
            }

            if (componentType.data.TryGetValue("alignCenter", out string alignCenter))
            {
                tableData.tableView.SetField("_alignToCenter", Parse.Bool(alignCenter));
            }


            if (componentType.data.TryGetValue("data", out string value))
            {
                if (!parserParams.values.TryGetValue(value, out BSMLValue contents))
                {
                    throw new Exception("value '" + value + "' not found");
                }
                tableData.data = contents.GetValue() as List <PropListTableData.PropertyDescriptor>;
                tableData.tableView.ReloadData();
            }

            switch (tableData.tableView.tableType)
            {
            case TableView.TableType.Vertical:
                (componentType.component.gameObject.transform as RectTransform).sizeDelta = new Vector2(componentType.data.TryGetValue("listWidth", out string vListWidth) ? Parse.Float(vListWidth) : 60, tableData.cellSize * (componentType.data.TryGetValue("visibleCells", out string vVisibleCells) ? Parse.Float(vVisibleCells) : 7));
                break;

            case TableView.TableType.Horizontal:
                (componentType.component.gameObject.transform as RectTransform).sizeDelta = new Vector2(tableData.cellSize * (componentType.data.TryGetValue("visibleCells", out string hVisibleCells) ? Parse.Float(hVisibleCells) : 4), componentType.data.TryGetValue("listHeight", out string hListHeight) ? Parse.Float(hListHeight) : 40);
                break;
            }

            componentType.component.gameObject.GetComponent <LayoutElement>().preferredHeight = (componentType.component.gameObject.transform as RectTransform).sizeDelta.y;
            componentType.component.gameObject.GetComponent <LayoutElement>().preferredWidth  = (componentType.component.gameObject.transform as RectTransform).sizeDelta.x;

            tableData.tableView.gameObject.SetActive(true);
            tableData.tableView.LazyInit();

            if (componentType.data.TryGetValue("id", out string id))
            {
                TableViewScroller scroller = tableData.tableView.GetField <TableViewScroller, TableView>("scroller");
                parserParams.AddEvent(id + "#PageUp", scroller.PageScrollUp);
                parserParams.AddEvent(id + "#PageDown", scroller.PageScrollDown);
            }
        }
Exemple #11
0
        public BSMLParserParams Parse(XmlNode parentNode, GameObject parent, object host = null)
        {
            BSMLParserParams parserParams = new BSMLParserParams();

            parserParams.host = host;
            FieldAccessOption    fieldAccessOptions    = FieldAccessOption.Auto;
            PropertyAccessOption propertyAccessOptions = PropertyAccessOption.Auto;
            MethodAccessOption   methodAccessOptions   = MethodAccessOption.Auto;
            HostOptionsAttribute hostOptions           = host?.GetType().GetCustomAttribute <HostOptionsAttribute>();

            if (hostOptions != null)
            {
                fieldAccessOptions    = hostOptions.FieldAccessOption;
                propertyAccessOptions = hostOptions.PropertyAccessOption;
                methodAccessOptions   = hostOptions.MethodAccessOption;
            }
            if (host != null)
            {
                foreach (MethodInfo methodInfo in host.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
                {
                    UIAction uiaction     = methodInfo.GetCustomAttributes(typeof(UIAction), true).FirstOrDefault() as UIAction;
                    string   methodName   = methodInfo.Name;
                    string   uiActionName = null;
                    if (uiaction != null)
                    {
                        uiActionName = uiaction.id;
                        if (parserParams.actions.TryGetValue(uiActionName, out BSMLAction existing))
                        {
                            if (existing.FromUIAction)
                            {
                                throw new InvalidOperationException($"UIAction '{uiActionName}' is already used by member '{existing.MemberName}'.");
                            }
                            existing.methodInfo   = methodInfo;
                            existing.FromUIAction = true;
                        }
                        else
                        {
                            parserParams.actions.Add(uiActionName, new BSMLAction(host, methodInfo, true));
                        }
                        if (methodAccessOptions == MethodAccessOption.AllowBoth && methodName != uiActionName)
                        {
                            if (!parserParams.actions.ContainsKey(methodName))
                            {
                                parserParams.actions.Add(methodName, new BSMLAction(host, methodInfo, false));
                            }
                        }
                    }
                    else if (methodAccessOptions != MethodAccessOption.OptIn)
                    {
                        if (!parserParams.actions.ContainsKey(methodName))
                        {
                            parserParams.actions.Add(methodName, new BSMLAction(host, methodInfo));
                        }
                    }
                }

                foreach (FieldInfo fieldInfo in host.GetType().GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
                {
                    UIValue uivalue     = fieldInfo.GetCustomAttributes(typeof(UIValue), true).FirstOrDefault() as UIValue;
                    string  fieldName   = fieldInfo.Name;
                    string  uiValueName = null;
                    if (uivalue != null)
                    {
                        uiValueName = uivalue.id;
                        if (parserParams.values.TryGetValue(uiValueName, out BSMLValue existing))
                        {
                            if (existing.FromUIValue)
                            {
                                throw new InvalidOperationException($"UIValue '{uiValueName}' is already used by member '{existing.MemberName}'.");
                            }
                            if (existing is BSMLFieldValue existingField)
                            {
                                existingField.fieldInfo   = fieldInfo;
                                existingField.FromUIValue = true;
                            }
                        }
                        else
                        {
                            parserParams.values.Add(uiValueName, new BSMLFieldValue(host, fieldInfo));
                        }
                        if (fieldAccessOptions == FieldAccessOption.AllowBoth && fieldName != uiValueName)
                        {
                            if (!parserParams.values.ContainsKey(fieldName))
                            {
                                parserParams.values.Add(fieldName, new BSMLFieldValue(host, fieldInfo, false));
                            }
                        }
                    }
                    else if (fieldAccessOptions != FieldAccessOption.OptIn)
                    {
                        if (!parserParams.values.ContainsKey(fieldName))
                        {
                            parserParams.values.Add(fieldName, new BSMLFieldValue(host, fieldInfo, false));
                        }
                    }

                    UIParams uiParams = fieldInfo.GetCustomAttributes(typeof(UIParams), true).FirstOrDefault() as UIParams;
                    if (uiParams != null)
                    {
                        fieldInfo.SetValue(host, parserParams);
                    }
                }

                foreach (PropertyInfo propertyInfo in host.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
                {
                    UIValue uivalue     = Attribute.GetCustomAttributes(propertyInfo, typeof(UIValue), true).FirstOrDefault() as UIValue;
                    string  propName    = propertyInfo.Name;
                    string  uiValueName = null;
                    if (uivalue != null)
                    {
                        uiValueName = uivalue.id;
                        if (parserParams.values.TryGetValue(uiValueName, out BSMLValue existing))
                        {
                            if (existing.FromUIValue)
                            {
                                throw new InvalidOperationException($"UIValue '{uiValueName}' is already used by member '{existing.MemberName}'.");
                            }
                            if (existing is BSMLPropertyValue existingProp)
                            {
                                existingProp.propertyInfo = propertyInfo;
                                existingProp.FromUIValue  = true;
                            }
                        }
                        else
                        {
                            parserParams.values.Add(uiValueName, new BSMLPropertyValue(host, propertyInfo));
                        }
                        if (propertyAccessOptions == PropertyAccessOption.AllowBoth && propName != uiValueName)
                        {
                            if (!parserParams.values.ContainsKey(propName))
                            {
                                parserParams.values.Add(propName, new BSMLPropertyValue(host, propertyInfo, false));
                            }
                        }
                    }
                    else if (propertyAccessOptions != PropertyAccessOption.OptIn)
                    {
                        if (!parserParams.values.ContainsKey(propName))
                        {
                            parserParams.values.Add(propName, new BSMLPropertyValue(host, propertyInfo, false));
                        }
                    }
                }
            }

            IEnumerable <ComponentTypeWithData> componentInfo = Enumerable.Empty <ComponentTypeWithData>();

            foreach (XmlNode node in parentNode.ChildNodes)
            {
                HandleNode(node, parent, parserParams, out IEnumerable <ComponentTypeWithData> components);
                componentInfo = componentInfo.Concat(components);
            }

            foreach (KeyValuePair <string, BSMLAction> action in parserParams.actions.Where(x => x.Key.StartsWith(SUBSCRIVE_EVENT_ACTION_PREFIX)))
            {
                parserParams.AddEvent(action.Key.Substring(1), delegate { action.Value.Invoke(); });
            }

            foreach (ComponentTypeWithData component in componentInfo)
            {
                component.typeHandler.HandleTypeAfterParse(component, parserParams);
            }

            parserParams.EmitEvent("post-parse");

            return(parserParams);
        }
        public override void HandleType(ComponentTypeWithData componentType, BSMLParserParams parserParams)
        {
            CustomCellListTableData tableData = componentType.component as CustomCellListTableData;

            if (componentType.data.TryGetValue("selectCell", out string selectCell))
            {
                tableData.tableView.didSelectCellWithIdxEvent += delegate(TableView table, int index)
                {
                    if (!parserParams.actions.TryGetValue(selectCell, out BSMLAction action))
                    {
                        throw new Exception("select-cell action '" + componentType.data["selectCell"] + "' not found");
                    }

                    action.Invoke(table, (table.dataSource as CustomCellListTableData).data[index]);
                };
            }

            if (componentType.data.TryGetValue("listDirection", out string listDirection))
            {
                //temp
                FieldInfo fieldInfo = typeof(TableView).GetField("_tableType", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
                fieldInfo.SetValue(tableData.tableView, (TableType)Enum.Parse(typeof(TableType), listDirection));
                //

                /*
                 * tableData.tableView.SetPrivateField("_tableType", (TableType)Enum.Parse(typeof(TableType), listDirection));
                 */
            }

            if (componentType.data.TryGetValue("cellSize", out string cellSize))
            {
                tableData.cellSize = Parse.Float(cellSize);
            }

            if (componentType.data.TryGetValue("cellTemplate", out string cellTemplate))
            {
                tableData.cellTemplate = "<bg>" + cellTemplate + "</bg>";
            }

            if (componentType.data.TryGetValue("cellClickable", out string cellClickable))
            {
                tableData.clickableCells = Parse.Bool(cellClickable);
            }

            if (componentType.data.TryGetValue("data", out string value))
            {
                if (!parserParams.values.TryGetValue(value, out BSMLValue contents))
                {
                    throw new Exception("value '" + value + "' not found");
                }
                tableData.data = contents.GetValue() as List <object>;
                tableData.tableView.ReloadData();
            }

            switch (tableData.tableView.tableType)
            {
            case TableType.Vertical:
                (componentType.component.gameObject.transform as RectTransform).sizeDelta = new Vector2(componentType.data.TryGetValue("listWidth", out string vListWidth) ? Parse.Float(vListWidth) : 60, tableData.cellSize * (componentType.data.TryGetValue("visibleCells", out string vVisibleCells) ? Parse.Float(vVisibleCells) : 7));
                tableData.tableView.contentTransform.anchorMin = new Vector2(0, 1);
                break;

            case TableType.Horizontal:
                (componentType.component.gameObject.transform as RectTransform).sizeDelta = new Vector2(tableData.cellSize * (componentType.data.TryGetValue("visibleCells", out string hVisibleCells) ? Parse.Float(hVisibleCells) : 4), componentType.data.TryGetValue("listHeight", out string hListHeight) ? Parse.Float(hListHeight) : 40);
                break;
            }

            componentType.component.gameObject.GetComponent <LayoutElement>().preferredHeight = (componentType.component.gameObject.transform as RectTransform).sizeDelta.y;
            componentType.component.gameObject.GetComponent <LayoutElement>().preferredWidth  = (componentType.component.gameObject.transform as RectTransform).sizeDelta.x;
            tableData.tableView.gameObject.SetActive(true);

            if (componentType.data.TryGetValue("id", out string id))
            {
                //temp
                FieldInfo         fieldInfo = typeof(TableView).GetField("_scroller", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
                TableViewScroller scroller  = fieldInfo.GetValue(tableData.tableView) as TableViewScroller;
                //

                /*
                 * TableViewScroller scroller = tableData.tableView.GetPrivateField<TableViewScroller>("_scroller");
                 */
                parserParams.AddEvent(id + "#PageUp", scroller.PageScrollUp);
                parserParams.AddEvent(id + "#PageDown", scroller.PageScrollDown);
            }
        }