public void RefreshRowAndColumnUi() { RefreshRowUi(); float y = 0; for (int i = 0; i < data.rows.Count; ++i) { DataSheetRow rObj = contentRectangle.GetChild(i).GetComponent <DataSheetRow>(); UpdateRowData(rObj, data.rows[i], y); y += rObj.GetComponent <RectTransform>().rect.height; } }
DataSheetRow CreateRow(RowData rowData, float yPosition = float.NaN) { GameObject rowUi = Instantiate(uiPrototypes.dataSheetRow.gameObject); DataSheetRow rObj = rowUi.GetComponent <DataSheetRow>(); if (rObj == null) { throw new Exception("RowUI prefab must have " + nameof(DataSheetRow) + " component"); } rObj.rowData = rowData; if (rObj.rowData == null) { throw new Exception("something bad. where is the object that this row is for?"); } rowUi.SetActive(true); UpdateRowData(rObj, rowData, yPosition); return(rObj); }
/// <summary> /// uses a dictionary to quickly calculate UI elements for rows, and position them in the view /// </summary> public Dictionary <object, DataSheetRow> RefreshRowUi() { // map list elements to row UI Dictionary <object, DataSheetRow> srcToRowUiMap = new Dictionary <object, DataSheetRow>(); for (int i = 0; i < contentRectangle.childCount; ++i) { DataSheetRow rObj = contentRectangle.GetChild(i).GetComponent <DataSheetRow>(); if (rObj == null) { continue; } if (rObj.obj == null) { throw new Exception("found a row (" + rObj.transform.HierarchyPath() + ") without source object at index " + i); } if (srcToRowUiMap.TryGetValue(rObj.obj, out DataSheetRow uiElement)) { throw new Exception("multiple row elements for row " + i + ": " + rObj.obj); } srcToRowUiMap[rObj.obj] = rObj; } List <DataSheetRow> unused = new List <DataSheetRow>(); // check to see if any of the UI rows are not being used by the datasheet (should be removed or replaced) Dictionary <object, DataSheetRow> unusedMapping = srcToRowUiMap.Copy(); for (int i = 0; i < data.rows.Count; ++i) { RowData rd = data.rows[i]; if (unusedMapping.TryGetValue(rd.obj, out DataSheetRow found)) { unusedMapping.Remove(rd.obj); } } foreach (KeyValuePair <object, DataSheetRow> kvp in unusedMapping) { unused.Add(kvp.Value); srcToRowUiMap.Remove(kvp.Key); } Vector2 cursor = Vector2.zero; // go through all of the row elements and put the row UI elements in the correct spot for (int i = 0; i < data.rows.Count; ++i) { RowData rd = data.rows[i]; // if this row data is missing a UI element if (!srcToRowUiMap.TryGetValue(rd.obj, out DataSheetRow rObj)) { // use one of the unused elements if there is one if (unused.Count > 0) { rObj = unused[unused.Count - 1]; unused.RemoveAt(unused.Count - 1); UpdateRowData(rObj, rd, -cursor.y); } else { // create he UI element, and put it into the content rectangle rObj = CreateRow(data.rows[i], -cursor.y); } rObj.transform.SetParent(contentRectangle); srcToRowUiMap[rObj.obj] = rObj; } rObj.transform.SetSiblingIndex(i); RectTransform rect = rObj.GetComponent <RectTransform>(); //rect.anchoredPosition = cursor; //rect.localPosition = cursor; rObj.LocalPosition = cursor; cursor.y -= rect.rect.height; } if (contentRectangle.childCount > data.rows.Count || unused.Count > 0) { // remove them in reverse order, should be slightly faster for (int i = contentRectangle.childCount - 1; i >= data.rows.Count; --i) { DataSheetRow rObj = contentRectangle.GetChild(i).GetComponent <DataSheetRow>(); srcToRowUiMap.Remove(rObj.obj); unused.Add(rObj); } Show.Log("deleting extra elements: " + unused.JoinToString(", ", go => { DataSheetRow ro = go.GetComponent <DataSheetRow>(); if (ro == null) { return("<null>"); } if (ro.obj == null) { return("<null obj>"); } return(ro.obj.ToString()); })); unused.ForEach(go => { go.transform.SetParent(null); Destroy(go); }); } contentAreaSize.y = -cursor.y; contentRectangle.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, -cursor.y); return(srcToRowUiMap); }
public GameObject UpdateRowData(DataSheetRow rObj, RowData rowData, float yPosition = float.NaN) { object[] columns = rowData.columns; Vector2 rowCursor = Vector2.zero; RectTransform rect; // remove all columns from the row (probably temporarily) List <GameObject> unusedColumns = new List <GameObject>(); for (int i = 0; i < rObj.transform.childCount; ++i) { GameObject fieldUi = rObj.transform.GetChild(i).gameObject; if (fieldUi == null) { throw new Exception("a null child in the row? wat"); } unusedColumns.Add(fieldUi); } while (rObj.transform.childCount > 0) { rObj.transform.GetChild(rObj.transform.childCount - 1).SetParent(null, false); } TokenErrorLog errLog = new TokenErrorLog(); for (int c = 0; c < data.columnSettings.Count; ++c) { Udash.ColumnSetting colS = data.columnSettings[c]; GameObject fieldUi = null; string columnUiName = colS.data.columnUi.ResolveString(errLog, rowData.obj); if (columnUiName == null) { string errorMessage = "could not resolve column UI name from " + colS.data.columnUi + "\n" + errLog.GetErrorString(); Show.Log(errorMessage); columnUiName = colS.data.columnUi.ResolveString(errLog, rowData.obj); throw new Exception(errorMessage); } // check if there's a version of it from earlier for (int i = 0; i < unusedColumns.Count; ++i) { if (unusedColumns[i].name.StartsWith(columnUiName)) { fieldUi = unusedColumns[i]; unusedColumns.RemoveAt(i); break; } } // otherwise create it if (fieldUi == null) { GameObject prefab = uiPrototypes.GetElement(columnUiName); if (prefab == null) { columnUiName = colS.data.columnUi.ResolveString(errLog, rowData.obj); throw new Exception("no such prefab \"" + columnUiName + "\" in data sheet initialization script. valid values: [" + uiPrototypes.transform.JoinToString() + "]\n---\n" + colS.data.columnUi + "\n---\n" + columnSetup); } fieldUi = Instantiate(prefab); } if (colS.data.onClick.IsSyntax) { ClickableScriptedCell clickable = fieldUi.GetComponent <ClickableScriptedCell>(); UiClick.ClearOnClick(fieldUi); if (fieldUi != null) { Destroy(clickable); } clickable = fieldUi.AddComponent <ClickableScriptedCell>(); clickable.Set(rowData.obj, colS.data.onClick); clickable.debugMetaData = colS.data.onClick.StringifySmall(); if (!UiClick.AddOnButtonClickIfNotAlready(fieldUi, clickable, clickable.OnClick)) { UiClick.AddOnPanelClickIfNotAlready(fieldUi, clickable, clickable.OnClick); } } fieldUi.SetActive(true); fieldUi.transform.SetParent(rObj.transform, false); fieldUi.transform.SetSiblingIndex(c); object value = columns[c]; if (value != null) { UiText.SetText(fieldUi, value.ToString()); } else { UiText.SetText(fieldUi, ""); } rect = fieldUi.GetComponent <RectTransform>(); rect.anchoredPosition = rowCursor; float w = rect.sizeDelta.x; if (colS.data.widthOfColumn > 0) { w = colS.data.widthOfColumn; rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, w); } rowCursor.x += w * rt.localScale.x; } for (int i = 0; i < unusedColumns.Count; ++i) { Destroy(unusedColumns[i]); } unusedColumns.Clear(); rect = rObj.GetComponent <RectTransform>(); rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, rowCursor.x); rect.transform.SetParent(contentRectangle, false); if (!float.IsNaN(yPosition)) { //rect.anchoredPosition = new Vector2(0, -yPosition); //rect.localPosition = new Vector2(0, -yPosition); rObj.LocalPosition = new Vector2(0, -yPosition); } return(rObj.gameObject); }