/// <summary> /// Method to create a DataTable to be visualized /// </summary> /// <param name="list"></param> /// <param name="history">history as breadcrumbs to jump back. root objects don't need one</param> /// <returns></returns> private DataTable CreateDataTableFromList(String title, System.Collections.IList list, List <HistoryElement> history = null) { if (list.Count == 0) { return(null); } var dataTable = new DataTable(); // root object? init history if (history == null) { history = new List <HistoryElement>(); } bool addBackButton = history != null && history.Count > 0; // fake-headers-row: List <DataCellObject> header = new List <DataCellObject>(); dataTable.rows.Add(header); for (int rowNr = 0; rowNr < list.Count; rowNr++) { var rowObject = list[rowNr]; // try to convert this object if there is an converter registered(e.g. UID) rowObject = devui.DataBrowserConvertObject(rowObject); List <DataCellObject> rowDataList = new List <DataCellObject>(); Action <object, List <DataCellObject> > traverseObj = null; traverseObj = (rowObj, rowData) => { DataBrowser.Traverse(rowObj, (varName, varObj, type, meta) => { Debug.Log(varName + " : " + varObj); if (rowNr == 0) { // define the columns in the first row var headerElement = new ColumnDefinition() { width = meta == null ? 100.0f : meta.width, colName = (meta == null || meta.visualName == null) ? varName : meta.visualName }; dataTable.columnDef.Add(headerElement); // --------fake headers------------ header.Add(new DataCellObject() { value = headerElement.colName, cellType = DataCellObject.CellType.Header, callback = (st) => { Debug.Log("Pressed the header:" + headerElement.colName); } }); // -------------------------------- } // traverse another list and add the whole data in one DataCellObject /*if (meta!=null && meta.type == DataBrowser.UIDBInclude.Type.subdata) { * if (type == MemoryBrowser.ElementType.listType) { * var subList = (IList)varObj; * List<List<DataCellObject>> subdata = new List<List<DataCellObject>>(); * for (int i = 0; i < subList.Count; i++) { * var subListElem = subList[i]; * List<DataCellObject> subRowData = new List<DataCellObject>(); * traverseObj(subListElem, subRowData); * subdata.Add(subRowData); * } * var rowElem = new DataCellObject() { * cellType = DataCellObject.CellType.Subdata, * value = subdata * }; * rowData.Add(rowElem); * } * } * else */ if (varObj == null || MemoryBrowser.IsSimple(varObj.GetType()) || varObj is Vector2 || varObj is Vector3) { // SIMPLE TYPE-HANDLING (int,string,enums,bool,...) var rowElem = new DataCellObject() { value = varObj, callback = (newVal) => { if (newVal == null) { // selection of readonly-cell return; } // try to set the value of this field/property bool successful = DataBrowser.SetValue(rowObj, varName, newVal); Debug.Log("Setting var " + varName + " to new Value:" + newVal + " [" + (successful ? "success" : "fail") + "]"); } }; var onlyread = varObj == null || (meta != null && meta.type == DataBrowser.UIDBInclude.Type.onlyread); if (onlyread) { rowElem.cellType = DataCellObject.CellType.Output; } else { if (varObj is Enum) { rowElem.cellType = DataCellObject.CellType.Dropdown; rowElem.dropdownValues = new List <string>(Enum.GetNames(varObj.GetType())); rowElem.value = (int)varObj; } else if (varObj.GetType() == typeof(bool)) { rowElem.cellType = DataCellObject.CellType.Dropdown; rowElem.dropdownValues = new List <string> { "false", "true" }; rowElem.value = ((bool)varObj) ? 1 : 0; } else { rowElem.cellType = DataCellObject.CellType.EditableOutput; } } rowData.Add(rowElem); } else { // NOT SIMPLE TYPES ( Object-Instances, List, Dict...) if (type == MemoryBrowser.ElementType.objectType || type == MemoryBrowser.ElementType.dictType) { // REFERENCE - LINK : OBJECT string cellTitle = (meta != null && meta.type == DataBrowser.UIDBInclude.Type.subdata) ? "( " + (varObj.ToString()) + " )" : "LINK"; var rowElem = new DataCellObject() { value = cellTitle, callback = (newVal) => { var objList = new ArrayList() { varObj }; Debug.Log("Go to REF:" + varObj.ToString()); history.Add(new HistoryElement() { historyTitle = title, objectList = list }); _eventService.Publish(new Service.DevUIService.Events.NewDataTable() { // since this is a single object and the DataBrowser is meant for lists, wrap the object in a list objectList = objList, history = history, tableTitle = varName + ":" + varObj.GetType().Name }); return; }, cellType = DataCellObject.CellType.Button }; rowData.Add(rowElem); } else if (type == MemoryBrowser.ElementType.listType) { // REFERENCE-LINK: LIST var theList = (IList)varObj; string cellTitle = (meta != null && meta.type == DataBrowser.UIDBInclude.Type.subdata) ? "( " + (OutputListAsStrings(theList)) + " )" : "List[" + theList.Count + "]"; var rowElem = new DataCellObject() { value = cellTitle, callback = (newVal) => { Debug.Log("Cannot go into empty lists"); if (theList.Count == 0) { // return; } history.Add(new HistoryElement() { historyTitle = title, objectList = list }); _eventService.Publish(new Service.DevUIService.Events.NewDataTable() { // since this is a single object and the DataBrowser is meant for lists, wrap the object in a list objectList = (IList)varObj, history = history, tableTitle = varName + ":" + varObj.GetType().Name }); return; }, cellType = DataCellObject.CellType.Button }; rowData.Add(rowElem); } } }); }; traverseObj(rowObject, rowDataList); Func <int, List <DataCellObject> > CreateEmptyLine = (amount) => { var result = new List <DataCellObject>(amount); for (int i = 0; i < amount; i++) { result.Add(new DataCellObject() { cellType = DataCellObject.CellType.Empty }); } return(result); }; dataTable.rows.Add(rowDataList); } return(dataTable); }
private MemoryBrowser Create(DevUIView resultView, object viewObject, bool autoupdate = false, Action <object, object> onValueChanged = null) { DevUIButton compButton = new DevUIButton(viewObject.GetType().ToString(), () => { }); resultView.AddElement(compButton); MemoryBrowser mB = new MemoryBrowser(viewObject); Dictionary <string, DevUIKeyValue> dict = new Dictionary <string, DevUIKeyValue>(); foreach (string key in mB.rxCurrentSnapShot.Keys) { object obj = mB.rxCurrentSnapShot[key]; if (obj == null || MemoryBrowser.IsSimple(obj.GetType()) || obj is Vector3 || obj is Vector2 || obj is Vector4) { DevUIKeyValue uiKV = new DevUIKeyValue(key, obj == null ? "null" : obj.ToString()); uiKV.OnValueChangeRequested = (newVal) => { mB.SetValue(key, newVal); if (onValueChanged != null) { onValueChanged(key, newVal); } }; resultView.AddElement(uiKV); dict[key] = uiKV; } else if (obj is IDevUIVisible) { DevUIKeyValue uiKV = new DevUIKeyValue(key, obj == null ? "null" : "'" + obj.ToString() + "'"); resultView.AddElement(uiKV); // TODO: Detect changes in custom-type } else if (obj is IList && ((IList)obj).Count > 0) { IList thelist = (IList)obj; object firstElement = thelist[0]; if (firstElement is IDevUIVisible) { resultView.AddElement(new DevUIButton(key + "(List)", null)); for (int i = 0; i < thelist.Count; i++) { object listObj = thelist[i]; DevUIKeyValue uiKV = new DevUIKeyValue(key, i + "| " + listObj == null ? "null" : "'" + listObj.ToString() + "'"); resultView.AddElement(uiKV); // TODO: detect list changes } } } } if (autoupdate && dict.Count > 0) { mB.rxCurrentSnapShot .ObserveReplace() .Subscribe(evt => { if (evt.OldValue == evt.NewValue) { return; } string key = evt.Key; if (dict.ContainsKey(key)) { DevUIKeyValue uiKV = dict[key]; uiKV.Value = evt.NewValue.ToString(); } }) .AddTo(resultView.disposables); // when the view is disposed, also dispose this subscription } else { // TODO: no button if we cannot show any values? resultView.RemoveElement(compButton); } // Poll the data at a this interval for every component // TODO: Make this more efficient: only the view that is in focus!? timeService.CreateGlobalTimer(1.0f, () => { mB.UpdateCurrentSnapshot(); logging.Info("UPDATED SNAPSHOT"); }, 0); return(mB); }