public void Initialize(Sheet sheet) { Sheet = sheet; filteredRows = Sheet.Rows; Int32 index; /* 기본 컬럼 추가 */ columnViewModels.Clear(); index = 0; foreach (Column column in sheet.Columns) { columnViewModels.Add(new ColumnViewModel(mainPageViewModel) { Column = column, Index = index }); index++; } // 컬럼 타입 추측 foreach (ColumnViewModel columnViewModel in columnViewModels) { index = columnViewModel.Index; columnViewModel.Type = columnViewModel.Column.Type; columnViewModel.CategoricalType = columnViewModel.Column.CategoricalType; columnViewModel.Unit = columnViewModel.Column.Unit; columnViewModel.ContainString = CheckStringValue(sheet.Rows.Select(r => r.Cells[index].RawContent)); if (columnViewModel.Type == ColumnType.Categorical) { List <String> uniqueValues = new List <String>(); foreach (Row row in sheet.Rows) { String value = row.Cells[index].RawContent; if (!uniqueValues.Contains(value)) { uniqueValues.Add(value); } } if (columnViewModel.Column.CategoircalOrder != null) // 이미 지정된 순서가 있으면 { List <String> order = columnViewModel.Column.CategoircalOrder; uniqueValues = uniqueValues.OrderBy(u => order.IndexOf(u)).ToList(); } else { // uniqueValues의 순서 정해야 함. if (columnViewModel.ContainString) { uniqueValues = uniqueValues.OrderBy(u => u).ToList(); } else { uniqueValues = uniqueValues.OrderBy(u => Double.Parse(u)).ToList(); } } // 카테고리 추가 후 List <Category> categories = uniqueValues.Select(u => new Category() { Value = u, ColumnViewModel = columnViewModel }).ToList(); Int32 categoryIndex = 0; foreach (Category category in categories) { category.Order = categoryIndex; category.Color = Category10.Colors[categoryIndex % Category10.Colors.Count]; categoryIndex++; } columnViewModel.Categories = categories; // 원래 cateogorical의 content는 string이 들어있을 텐데 이를 Category로 바꾼다. 즉 content는 Category 아니면 Double임 혹은 데이트타임일수도 foreach (Row row in sheet.Rows) { String value = row.Cells[index].RawContent; row.Cells[index].Content = categories.Where(c => c.Value == value).First(); } } else if (columnViewModel.Type == ColumnType.Numerical) { foreach (Row row in sheet.Rows) { String value = row.Cells[index].RawContent; row.Cells[index].Content = Double.Parse(row.Cells[index].RawContent); } } } // 추측한 컬럼 타입에 대해 순서 정함 (카테고리컬을 먼저 보여줌) // 그냥 그대로 보여주는것으로 변경 index = 0; foreach (ColumnViewModel columnViewModel in columnViewModels /*.Where(c => c.Type != ColumnType.Categorical)*/) { columnViewModel.Order = index++; } /* 기본 row 추가 */ allRowViewModels.Clear(); index = 0; foreach (Row row in sheet.Rows) { RowViewModel rowViewModel = new RowViewModel(mainPageViewModel) { Index = index, Row = row }; Int32 index2 = 0; foreach (Cell cell in row.Cells) { cell.ColumnViewModel = columnViewModels[index2++]; rowViewModel.Cells.Add(cell); } allRowViewModels.Add(rowViewModel); index++; } MeasureColumnWidth(); UpdateColumnX(); SheetWidth = columnViewModels.Select(c => c.Width).Sum() + Const.RowHeaderWidth; SheetHeight = allRowViewModels.Count * Const.RowHeight; }
private AnimationScenario PlayExpandAnimation(ViewStatus viewStatus, ColumnViewModel columnViewModel) { AnimationHint hint = null;// stashedViewStatus.AnimationHint; IEnumerable <RowViewModel> previousRowViewModels = (stashedViewStatus.TableViewState == TableViewState.AllRow) ? SheetViewModel.AllRowViewModels : stashedViewStatus.GroupedRowViewModels; IEnumerable <RowViewModel> currentRowViewModels = viewStatus.IsAllRowViewModelVisible ? SheetViewModel.AllRowViewModels : viewStatus.GroupedRowViewModels; Double beforeX = hint.ColumnViewModelPosition[columnViewModel]; Double afterX = columnViewModel.X; Int32 index = 0; Storyboard storyboard = new Storyboard(); Double horizontalAnimationDuration = 0; Canvas canvas = view.TableView.AnimatingRowCanvas; canvas.Children.Clear(); RowViewModel rootGroupedRowViewModel = stashedViewStatus.GroupedRowViewModels[0]; Int32 rootIndex = 0; IEnumerable <Row> rows = rootGroupedRowViewModel.Rows; IEnumerable <RowViewModel> expandingRowViewModels = currentRowViewModels .Where(rvm => (rvm.Row == null ? rows.Intersect(rvm.Rows).Count() > 0 : rows.Contains(rvm.Row)) && rvm.Y < mainPageViewModel.Bounds.Height) .OrderBy(rvm => rvm.Y) .Take(50); if (expandingRowViewModels.Count() < 5) { index = 0; foreach (GroupedRows groupedRows in stashedViewStatus.GroupedRows) { IEnumerable <RowViewModel> candidate = currentRowViewModels .Where(rvm => (rvm.Row == null ? groupedRows.Rows.Intersect(rvm.Rows).Count() > 0 : groupedRows.Rows.Contains(rvm.Row)) && rvm.Y < mainPageViewModel.Bounds.Height) .OrderBy(rvm => rvm.Y) .Take(50); if (candidate.Count() >= 5) { rootGroupedRowViewModel = stashedViewStatus.GroupedRowViewModels[index]; rows = groupedRows.Rows; expandingRowViewModels = candidate; rootIndex = index; break; } index++; } } viewStatus.ColorRowViewModels(allRowViewModels, viewStatus.GroupedRowViewModels, viewStatus.GroupedRows); if (viewStatus.IsAllRowViewModelVisible) { // root { AnimatingRowViewModel arvm = new AnimatingRowViewModel() { RowViewModel = rootGroupedRowViewModel, X = beforeX, ColumnViewModel = columnViewModel }; AnimatingRowPresenter arp = new AnimatingRowPresenter() { AnimatingRowViewModel = arvm }; arp.Opacity = 1; arp.Update(); canvas.Children.Add(arp); Canvas.SetTop(arp, rootGroupedRowViewModel.StashedY); arp.CellPresenter.Foreground = new SolidColorBrush(rootGroupedRowViewModel.Color); storyboard.Children.Add(Util.Animator.Generate(arp, "Opacity", 0, UnitAnimationDuration, DelayBeforeAnimation)); } index = 0; foreach (RowViewModel rvm in expandingRowViewModels) { AnimatingRowViewModel arvm = new AnimatingRowViewModel() { RowViewModel = rvm, X = beforeX, ColumnViewModel = columnViewModel }; AnimatingRowPresenter arp = new AnimatingRowPresenter() { AnimatingRowViewModel = arvm }; arp.Opacity = 0; arp.Update(); canvas.Children.Add(arp); Canvas.SetTop(arp, rootGroupedRowViewModel.StashedY); arp.CellPresenter.Foreground = new SolidColorBrush(rootGroupedRowViewModel.Color); storyboard.Children.Add(Util.Animator.Generate(arp, "(Canvas.Top)", rvm.Y, UnitAnimationDuration, DelayBeforeAnimation)); storyboard.Children.Add(Util.Animator.Generate(arp, "Opacity", 1, UnitAnimationDuration, DelayBeforeAnimation)); storyboard.Children.Add( Util.Animator.GenerateColorAnimation(arp.CellPresenter, "(TextBlock.Foreground).(SolidColorBrush.Color)", rvm.Color, UnitAnimationDuration, DelayBeforeAnimation) ); if (beforeX != afterX) { storyboard.Children.Add(Util.Animator.Generate(arp.CellPresenter, "(Canvas.Left)", afterX, UnitAnimationDuration, DelayBeforeAnimation + UnitAnimationDuration)); horizontalAnimationDuration = UnitAnimationDuration; } index++; } } else // grouped row visible { } stashedViewStatus = null; return(new AnimationScenario() { TotalAnimationDuration = DelayBeforeAnimation + UnitAnimationDuration + horizontalAnimationDuration, TableHeaderUpdateTime = DelayBeforeAnimation + UnitAnimationDuration, AnimationStoryboard = storyboard }); }
/// <summary> /// Animation은 viewStatus에 새로운 컬럼이 추가되거나 해제될 때 마지막에 보이던 TableView와 현재 보일 TableView를 잇는데 사용된다. /// prevTableView와 currentTableView를 부드럽게 잇는 테이블 애니메이션이 가능한 경우와 불가능한 경우는 아래와 같다 /// /// 가능한 경우: /// allRows -> groupedRows: 항상 가능 /// groupedRows -> allRows: 항상 가능 /// groupedRows-> selectedRows: 항상 가능 /// selectedRows -> groupedRows: 항상 가능 /// groupedRows -> groupedRows: N -> CN 인 경우는 불가능함 /// /// 불가능한 경우: /// allRows -> allRows: 이런 상황이 일어나는 경우가 없음 /// selectedRows -> selectedRows: 셀렉션이 추가되거나 제거되는 경우인데 이건 현재 애니메이션을 지원하지 않음 /// allRows -> selectedRows: 스캐터플롯에서 셀렉션을 추가하는 경우가 있을 수 있는데 현재 애니메이션 지원하지 않음 /// selectedRows -> allRows: 스캐터플롯에서 셀렉션이 제거되는 경우가 있을 수 있는데 현재 애니메이션 지원하지 않음 /// </summary> /// <param name="viewStatus"></param> /// <returns></returns> private AnimationScenario CreateTableAnimation(ViewStatus viewStatus) { if (!Settings.Instance.AnimationEnabled) { return(AnimationScenario.None); } if (stashedViewStatus == null) { return(AnimationScenario.None); } //AnimationHint hint = stashedViewStatus.AnimationHint; Canvas canvas = view.TableView.AnimatingRowCanvas; canvas.Children.Clear(); TableViewState previousState = stashedViewStatus.TableViewState, currentState = viewStatus.TableViewState; switch (previousState) { case TableViewState.AllRow: switch (currentState) { case TableViewState.AllRow: return(AnimationScenario.None); case TableViewState.GroupedRow: // 처음 그룹바이가 일어나는 경우 return(PlayCollapseAnimation(SheetViewModel.AllRowViewModels, viewStatus.GroupedRowViewModels, viewStatus.FirstColumn)); //, viewStatus); case TableViewState.SelectedRow: return(AnimationScenario.None); } break; case TableViewState.GroupedRow: switch (currentState) { case TableViewState.AllRow: // 그룹바이가 풀리는 경우 (C -> Empty, CN -> CNN 등) return(PlayExpandAnimation(stashedViewStatus.GroupedRowViewModels, SheetViewModel.AllRowViewModels, stashedViewStatus.CategoricalCount > 0 ? stashedViewStatus.LastCategorical : stashedViewStatus.FirstNumerical)); //, viewStatus); case TableViewState.GroupedRow: // TODO break; case TableViewState.SelectedRow: IEnumerable <Row> selectedOnScreenRows = SheetViewModel.AllRowViewModels.Where(arvm => SelectedRows.Contains(arvm.Row) && arvm.Y < mainPageViewModel.Bounds.Height).Select(arvm => arvm.Row); RowViewModel selectedRowViewModel = stashedViewStatus.GroupedRowViewModels .OrderByDescending(rvm => rvm.Rows.Intersect(selectedOnScreenRows).Count()) .First(); return(PlayExpandAnimation(new List <RowViewModel>() { selectedRowViewModel }, SheetViewModel.AllRowViewModels, stashedViewStatus.CategoricalCount > 0 ? stashedViewStatus.LastCategorical : stashedViewStatus.FirstNumerical)); //, viewStatus); } break; case TableViewState.SelectedRow: switch (currentState) { case TableViewState.AllRow: return(AnimationScenario.None); case TableViewState.GroupedRow: IEnumerable <Row> unselectedOnScreenRows = SheetViewModel.AllRowViewModels.Where( arvm => stashedViewStatus.SelectedRows.Contains(arvm.Row) && arvm.StashedY < mainPageViewModel.Bounds.Height ).Select(arvm => arvm.Row); RowViewModel collapsingRowViewModel = viewStatus.GroupedRowViewModels.OrderByDescending(rvm => rvm.Rows.Intersect(unselectedOnScreenRows).Count()).First(); return(PlayCollapseAnimation(AllRowViewModels, new List <RowViewModel>() { collapsingRowViewModel }, stashedViewStatus.CategoricalCount > 0 ? viewStatus.LastCategorical : viewStatus.FirstNumerical)); //, viewStatus); case TableViewState.SelectedRow: return(AnimationScenario.None); } break; } return(AnimationScenario.None); }
private AnimationScenario PlayCollapseAnimation(List <RowViewModel> previousRowViewModels, List <RowViewModel> currentRowViewModels, ColumnViewModel columnViewModel) { Double beforeX = columnViewModel.StashedX; Double afterX = columnViewModel.X; Storyboard storyboard = new Storyboard(); Canvas canvas = view.TableView.AnimatingRowCanvas; RowViewModel rootRowViewModel = currentRowViewModels[0]; IEnumerable <Row> rows = rootRowViewModel.Rows; IEnumerable <RowViewModel> collapsingRowViewModels = previousRowViewModels .Where(rvm => (rvm.Row == null ? rows.Intersect(rvm.Rows).Count() > 0 : rows.Contains(rvm.Row)) && rvm.Y < mainPageViewModel.Bounds.Height) .OrderBy(rvm => rvm.Y) .Take(50); if (collapsingRowViewModels.Count() < 5) { foreach (RowViewModel groupedRowViewModel in currentRowViewModels) { IEnumerable <RowViewModel> candidate = previousRowViewModels .Where(rvm => (rvm.Row == null ? groupedRowViewModel.Rows.Intersect(rvm.Rows).Count() > 0 : groupedRowViewModel.Rows.Contains(rvm.Row)) && rvm.Y < mainPageViewModel.Bounds.Height) .OrderBy(rvm => rvm.Y) .Take(50); if (candidate.Count() >= 5) { rows = groupedRowViewModel.Rows; collapsingRowViewModels = candidate; rootRowViewModel = groupedRowViewModel; break; } } } Double colorChangingAnimationDuration = 0; Double horizontalAnimationDuration = 0; if (collapsingRowViewModels.Any(rvm => rvm.StashedColor != rootRowViewModel.Color)) { colorChangingAnimationDuration = UnitAnimationDuration; } if (beforeX != afterX) { horizontalAnimationDuration = UnitAnimationDuration; } // root { AnimatingRowViewModel arvm = new AnimatingRowViewModel() { RowViewModel = rootRowViewModel, X = beforeX, ColumnViewModel = columnViewModel }; AnimatingRowPresenter arp = new AnimatingRowPresenter() { AnimatingRowViewModel = arvm }; arp.Opacity = 0; arp.Update(); canvas.Children.Add(arp); arp.CellPresenter.Foreground = new SolidColorBrush(rootRowViewModel.Color); Canvas.SetTop(arp, rootRowViewModel.Y); storyboard.Children.Add(Util.Animator.Generate(arp, "Opacity", 1, UnitAnimationDuration, DelayBeforeAnimation + colorChangingAnimationDuration)); if (beforeX != afterX) { storyboard.Children.Add(Util.Animator.Generate(arp.CellPresenter, "(Canvas.Left)", afterX, UnitAnimationDuration, DelayBeforeAnimation + UnitAnimationDuration + colorChangingAnimationDuration)); } } foreach (RowViewModel rvm in collapsingRowViewModels) { AnimatingRowViewModel arvm = new AnimatingRowViewModel() { RowViewModel = rvm, X = beforeX, ColumnViewModel = columnViewModel }; AnimatingRowPresenter arp = new AnimatingRowPresenter() { AnimatingRowViewModel = arvm }; arp.Opacity = 1; arp.Update(); canvas.Children.Add(arp); Canvas.SetTop(arp, rvm.StashedY); arp.CellPresenter.Foreground = new SolidColorBrush(rvm.StashedColor); if (colorChangingAnimationDuration > 0) { storyboard.Children.Add( Util.Animator.GenerateColorAnimation(arp.CellPresenter, "(TextBlock.Foreground).(SolidColorBrush.Color)", rootRowViewModel.Color, UnitAnimationDuration, DelayBeforeAnimation) ); } // 그 다음 세로로 모음 storyboard.Children.Add(Util.Animator.Generate(arp, "(Canvas.Top)", rootRowViewModel.Y, UnitAnimationDuration, DelayBeforeAnimation + colorChangingAnimationDuration)); storyboard.Children.Add(Util.Animator.Generate(arp, "Opacity", 0, UnitAnimationDuration, DelayBeforeAnimation + colorChangingAnimationDuration)); // 그 다음 가로로 이동 if (beforeX != afterX) { storyboard.Children.Add(Util.Animator.Generate(arp.CellPresenter, "(Canvas.Left)", afterX, UnitAnimationDuration, DelayBeforeAnimation + UnitAnimationDuration + colorChangingAnimationDuration)); } } stashedViewStatus = null; return(new AnimationScenario() { TotalAnimationDuration = DelayBeforeAnimation + UnitAnimationDuration + horizontalAnimationDuration + colorChangingAnimationDuration, TableHeaderUpdateTime = DelayBeforeAnimation + UnitAnimationDuration + colorChangingAnimationDuration, AnimationStoryboard = storyboard, SpotlightColumnViewModel = columnViewModel }); }
public void FilterRowsByValueAtPosition(Double x, Double y) { ColumnViewModel columnViewModel = SheetViewModel.ColumnViewModels.First(cvm => cvm.X <= x && x < cvm.X + cvm.Width); if (columnViewModel == null) { return; } RowViewModel rowViewModel = null; if (mainPageViewModel.ExplorationViewModel.ViewStatus.IsN) { return; } if (mainPageViewModel.ExplorationViewModel.ViewStatus.CategoricalCount > 0) { if (columnViewModel.Type == ColumnType.Numerical) { return; } if (mainPageViewModel.ExplorationViewModel.ViewStatus.SelectedColumnViewModels.IndexOf(columnViewModel) < 0) { return; } } if (State == TableViewState.AllRow || State == TableViewState.SelectedRow) { rowViewModel = allRowViewModels.First(rvm => rvm.Y <= y && y < rvm.Y + Const.RowHeight); } else if (State == TableViewState.GroupedRow) { rowViewModel = groupedRowViewModels.First(rvm => rvm.Y <= y && y < rvm.Y + Const.RowHeight); } if (rowViewModel == null) { return; } if (columnViewModel.Type == ColumnType.Categorical) { Category category = rowViewModel.Cells[columnViewModel.Index].Content as Category; category.IsKept = false; ColumnViewModel cvm = category.ColumnViewModel; if (cvm.Categories.All(c => c.IsKept)) { cvm.IsKept = true; } else if (cvm.Categories.All(c => !c.IsKept)) { cvm.IsKept = false; } else { cvm.IsKept = null; } mainPageViewModel.SheetViewModel.UpdateFilter(); mainPageViewModel.ReflectAll(ReflectReason.RowFiltered); } }