using System; using System.Collections.Generic; using System.Linq; namespace FastReport.AdvMatrix { internal static class HeaderDataExt { // Returns the first item of a group. For simple type items: // - returns an item in the first parent group // - if there is no parent group, or useThisGroup parameter is true, returns the first item of a group in the same level internal static HeaderData GetFirstItem(this HeaderData item, bool useIneractiveSort, bool useThisGroup) { if (item.Parent == null) return null; if (item.Value == null) { HeaderData parentGroup = GetFirstItem(item.Parent, useIneractiveSort, useThisGroup); if (parentGroup == null || useThisGroup) { // return the first item of a group in the same level foreach (HeaderDataList dl in item.Parent.Items) { if (dl.Descriptor.IsGroup) return dl.GetSortedList(useIneractiveSort).FirstOrDefault(); } } else { // return an item in the parent group foreach (HeaderDataList dl in parentGroup.Items) { if (dl.Descriptor == item.Descriptor) return dl[0]; } } return null; } return item.ParentDataList.GetSortedList(useIneractiveSort).FirstOrDefault(); } // The same as above but with the last item internal static HeaderData GetLastItem(this HeaderData item, bool useIneractiveSort, bool useThisGroup) { if (item.Parent == null) return null; if (item.Value == null) { HeaderData parentGroup = GetLastItem(item.Parent, useIneractiveSort, useThisGroup); if (parentGroup == null || useThisGroup) { foreach (HeaderDataList dl in item.Parent.Items) { if (dl.Descriptor.IsGroup) return dl.GetSortedList(useIneractiveSort).LastOrDefault(); } } else { foreach (HeaderDataList dl in parentGroup.Items) { if (dl.Descriptor == item.Descriptor) return dl[0]; } } return null; } return item.ParentDataList.GetSortedList(useIneractiveSort).LastOrDefault(); } // The same as above but with the previous item internal static HeaderData GetPreviousItem(this HeaderData item, bool useIneractiveSort, bool useThisGroup) { if (item.Parent == null) return null; if (item.Value == null) { HeaderData parentGroup = GetPreviousItem(item.Parent, useIneractiveSort, useThisGroup); if (parentGroup == null || useThisGroup) { foreach (HeaderDataList dl in item.Parent.Items) { if (dl.Descriptor.IsGroup) { List l = dl.GetSortedList(useIneractiveSort); if (l.Count > 1) return l[l.Count - 2]; return null; } } } else { foreach (HeaderDataList dl in parentGroup.Items) { if (dl.Descriptor == item.Descriptor) return dl[0]; } } return null; } List list = item.ParentDataList.GetSortedList(useIneractiveSort); int index = list.IndexOf(item); if (index != -1) { if (index == 0) return null; return list[index - 1]; } return null; } // The same as above but with the next item internal static HeaderData GetNextItem(this HeaderData item, bool useIneractiveSort, bool useThisGroup) { if (item.Parent == null) return null; if (item.Value == null) { HeaderData parentGroup = GetNextItem(item.Parent, useIneractiveSort, useThisGroup); if (parentGroup == null || useThisGroup) { foreach (HeaderDataList dl in item.Parent.Items) { if (dl.Descriptor.IsGroup) { List l = dl.GetSortedList(useIneractiveSort); if (l.Count > 1) return l[1]; return null; } } } else { foreach (HeaderDataList dl in parentGroup.Items) { if (dl.Descriptor == item.Descriptor) return dl[0]; } } return null; } List list = item.ParentDataList.GetSortedList(useIneractiveSort); int index = list.IndexOf(item); if (index != -1) { if (index == list.Count - 1) return null; return list[index + 1]; } return null; } // The same as above but with the specific item internal static HeaderData GetSpecificItem(this HeaderData item, object value) { if (item.Parent == null) return null; if (item.Value == null) { foreach (HeaderDataList dl in item.Parent.Items) { if (dl.Descriptor.IsGroup) { HeaderData d = GetSpecificItem(dl[0], value); if (d != null) return d; } } } else { foreach (HeaderData d in item.ParentDataList) { if (d.Value.Equals(value)) return d; } } return null; } internal static HeaderDataList GetGroup(this HeaderData item) { HeaderData item1 = item; // trying to find a parent group while (item1 != null && item1.Value == null) item1 = item1.Parent; if (item1 != null) return item1.ParentDataList; // trying to find a group on the same level item1 = item.Parent; while (item1 != null) { foreach (HeaderDataList dl in item1.Items) { if (dl.Descriptor.IsGroup) return dl; } item1 = item1.Parent; } return null; } internal static HeaderData FindByIndex(this HeaderData item, int index) { if (item.Index == index) return item; // do not use root enumerator here, avoid additional sorting which may lead to SO foreach (HeaderDataList dl in item.Items) { foreach (HeaderData d in dl) { HeaderData result = FindByIndex(d, index); if (result != null) return result; } } return null; } internal static void ToggleVisible(this HeaderData item, int index, bool collapseAll, bool expandAll) { item = item.FindByIndex(index); if (item == null) return; MatrixCollapseButton btn = item.Descriptor.TemplateCell.GetCollapseButton(); if (btn == null) return; Action func = (root, visible, skip) => { if (root == null) return; foreach (HeaderDataList dl in root.Items) { foreach (HeaderData d in dl) { if (d == item && skip) continue; foreach (HeaderDataList dl1 in btn.GetLinkedItems(d)) { dl1.Visible = visible; } } } }; if (collapseAll) { func(item.Parent, false, false); return; } if (expandAll) { func(item.Parent, true, false); return; } if (btn.Exclusive) { func(item.Parent, false, true); } foreach (HeaderDataList dl in btn.GetLinkedItems(item)) { dl.Visible = !dl.Visible; } } } }