void RemoveTweetItemControl(TweetsPanelItem tic, TweetsPanelLayoutMode mode, Storyboard sb) { tweetControls.Remove(tic); switch (mode) { case TweetsPanelLayoutMode.AddNew: case TweetsPanelLayoutMode.Left: case TweetsPanelLayoutMode.Relayout: // 右に押し出す { DoubleAnimation da = new DoubleAnimation() { To = (double)tic.GetValue(Canvas.LeftProperty) + ActualWidth, Duration = moveDuration, EasingFunction = moveEasing, }; da.Completed += (sender, e) => { Children.Remove(tic); recycleTweetControls.Add(tic); }; Storyboard.SetTarget(da, tic); Storyboard.SetTargetProperty(da, canvasLeftPropertyPath); sb.Children.Add(da); } break; case TweetsPanelLayoutMode.Right: { DoubleAnimation da = new DoubleAnimation() { To = (double)tic.GetValue(Canvas.LeftProperty) - ActualWidth, Duration = moveDuration, EasingFunction = moveEasing, }; da.Completed += (sender, e) => { Children.Remove(tic); recycleTweetControls.Add(tic); }; Storyboard.SetTarget(da, tic); Storyboard.SetTargetProperty(da, canvasLeftPropertyPath); sb.Children.Add(da); } break; default: // すぐ消す Children.Remove(tic); recycleTweetControls.Add(tic); break; } }
/// <summary> /// ツイートをレイアウトする /// </summary> public void LayoutTweets(TweetsPanelLayoutMode mode) { Panel container = (Panel)Parent; Debug.WriteLine("cursor: {0}/{1}", TopItemIndex, Tweets.Count); const int sideMargin = 6; int tweetMargin = TweetMargin; double width = container.ActualWidth - (sideMargin * 2); double height = container.ActualHeight; double columnWidth = Math.Floor( width / Columns); double tweetWidth = columnWidth - tweetMargin; double x = sideMargin; double y = 0; int column = 0; TimeSpan newItemDelay = moveDuration.TimeSpan; Duration newItemDuration = moveDuration; Storyboard sb = new Storyboard(); var newItems = new List<TweetsPanelItem>(); switch (mode) { case TweetsPanelLayoutMode.Right: TopItemIndex = Math.Min(TopItemIndex + tweetControls.Count, Tweets.Count - 1); break; case TweetsPanelLayoutMode.Left: { for (; TopItemIndex >= 0; TopItemIndex--) { var tweet = Tweets[TopItemIndex]; var tic = tweetControls.FirstOrDefault(c => c.Tweet == tweet); bool newItem = false; if (tic == null) { newItem = true; tic = AddTweetItemControl(); tic.Tweet = tweet; tic.SetValue(Canvas.WidthProperty, tweetWidth); tic.UpdateLayout(); newItems.Add(tic); Debug.WriteLine("newItems.Add {0} {1}", TopItemIndex, tweet.Text); } y += tic.ActualHeight + tweetMargin; if (y > height) { y = 0; column++; if (column >= Columns) { if (newItem) { RemoveTweetItemControl(tic, TweetsPanelLayoutMode.None, sb); Debug.WriteLine("newItems.Remove {0} {1}", TopItemIndex, tweet.Text); newItems.Remove(tic); } TopItemIndex++; break; } } } if (TopItemIndex < 0) TopItemIndex = 0; column = 0; y = 0; } break; } bool outside = false; int index = -1; foreach (var tweet in Tweets) { index++; //if (index > 0) break; // テスト用 var tic = tweetControls.FirstOrDefault(c => c.Tweet == tweet); if (tic != null) { if (outside || index < TopItemIndex) { RemoveTweetItemControl(tic, mode, sb); continue; } } if (index < TopItemIndex) { continue; } bool newItem = false; if (tic == null) { if (outside) { continue; } newItem = true; tic = AddTweetItemControl(); tic.Tweet = tweet; } // 高さ決定 if (tic.Width != tweetWidth) { tic.SetValue(Canvas.WidthProperty, tweetWidth); } tic.UpdateLayout(); tic.UpdateTime(); // 表示位置決定 if (y + tic.ActualHeight > height) { y = 0; x += columnWidth; column++; if (column >= Columns) { outside = true; RemoveTweetItemControl(tic, newItem ? TweetsPanelLayoutMode.None : mode, sb); continue; } } if (mode == TweetsPanelLayoutMode.None) { tic.SetValue(Canvas.LeftProperty, x); tic.SetValue(Canvas.TopProperty, y); } else { DoubleAnimation daLeft = new DoubleAnimation() { Duration = moveDuration, To = x, EasingFunction = moveEasing, }; DoubleAnimation daTop = new DoubleAnimation() { Duration = moveDuration, To = y, EasingFunction = moveEasing, }; // 新アイテムの扱い if (newItem) { switch (mode) { case TweetsPanelLayoutMode.AddNew: // 左から入ってくる daLeft.BeginTime = newItemDelay; daTop.BeginTime = newItemDelay; daLeft.Duration = newItemDuration; daTop.Duration = newItemDuration; tic.SetValue(Canvas.LeftProperty, -columnWidth); tic.SetValue(Canvas.TopProperty, y); break; case TweetsPanelLayoutMode.Relayout: // 右から入ってくる case TweetsPanelLayoutMode.Right: tic.SetValue(Canvas.LeftProperty, width+x); tic.SetValue(Canvas.TopProperty, y); break; case TweetsPanelLayoutMode.Left: break; } } else if (mode == TweetsPanelLayoutMode.Left && newItems.Remove(tic)) { // 左から入ってくる Debug.WriteLine("使った: {0} {1}", TopItemIndex, tweet.Text); tic.SetValue(Canvas.LeftProperty, x - width); tic.SetValue(Canvas.TopProperty, y); } sb.Children.Add(daLeft); sb.Children.Add(daTop); Storyboard.SetTarget(daLeft, tic); Storyboard.SetTarget(daTop, tic); Storyboard.SetTargetProperty(daLeft, canvasLeftPropertyPath); Storyboard.SetTargetProperty(daTop, canvasTopPropertyPath); } y += (int)tic.ActualHeight + tweetMargin; } foreach (var t in newItems) { Debug.WriteLine("残った!!: {0}", t.Tweet.Text); } Width = Math.Max(x + columnWidth, container.ActualWidth); container.UpdateLayout(); sb.Begin(); }