>

2018年12月26日水曜日

コード

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Globalization;
using System.Windows.Media.Imaging;
using System.Windows.Media;
using System.Windows.Shapes;

namespace Phistory
{
    class IndexCanvas:Canvas
    {
        private static readonly DateTimeFormatInfo dtfi = new DateTimeFormatInfo();

        /// 
        /// 現在画面に表示されている目盛りを検索するためのDictionary
        /// 
        private Dictionary Up2NowIndexLabelDictionary { get; set; }
        private Dictionary Up2NowIndexRectangleDictionary { get; set; }
        
        private BitmapImage line = new BitmapImage(new Uri("images/line.bmp", UriKind.Relative));

        public IndexCanvas()
        {
            Up2NowIndexLabelDictionary = new Dictionary();
            CultureResources.ResourceProvider.DataChanged += OnResourceProviderDataChanged;
        }
        
        public void Render(long time, long scale)
        {
            // 表示開始タイマー刻み数(100ナノ秒単位)
            long begin = time;
            // 表示終了タイマー刻み数(100ナノ秒単位)
            long end = time + (long)(ActualWidth * scale);

            //目盛りの更新処理
            Dictionary nextIndexLabelDictionary = new Dictionary();
            Dictionary nextIndexRectangleDictionary = new Dictionary();
            List indicesToBeAdded = new List();
            foreach (Index index in GetIndices(begin, end, scale))
            {
                if (!Up2NowIndexLabelDictionary.ContainsKey(index))//今回表示すべき目盛りでこれまでも表示されていなかった目盛りに対する処理
                {
                    indicesToBeAdded.Add(index);
                }
                else//前回から表示されている目盛りに対する処理
                {
                    double x = (index.Time - time) / scale;
                    SetLeft(Up2NowIndexRectangleDictionary[index], x);
                    SetLeft(Up2NowIndexLabelDictionary[index], x);
                    nextIndexRectangleDictionary.Add(index, Up2NowIndexRectangleDictionary[index]);
                    nextIndexLabelDictionary.Add(index, Up2NowIndexLabelDictionary[index]);
                }
            }
            foreach (Index index in indicesToBeAdded)
            {
                double x = (index.Time - time) / scale;

                Rectangle lineRect = new Rectangle();
                lineRect.Width = 1;
                lineRect.Height = 24;
                SolidColorBrush brush = new SolidColorBrush(Util.GetForegroundColor());
                lineRect.Fill = brush;
                SetLeft(lineRect, x);
                SetBottom(lineRect, 0);
                Children.Add(lineRect);
                nextIndexRectangleDictionary.Add(index, lineRect);

                Label label = new Label();
                label.Content = index.Text;
                label.FontSize = 20;
                label.Foreground = new SolidColorBrush(Util.GetForegroundColor());
                SetLeft(label, x);
                Children.Add(label);
                nextIndexLabelDictionary.Add(index, label);
            }

            List indicesToBeRemoved = new List();
            foreach (Index index in Up2NowIndexLabelDictionary.Keys)
            {
                if (!nextIndexLabelDictionary.ContainsKey(index))//これまで表示されてきた目盛りで今回表示しない目盛りに対する処理
                {
                    indicesToBeRemoved.Add(index);
                }
            }
            foreach (Index index in indicesToBeRemoved)
            {
                Children.Remove(Up2NowIndexLabelDictionary[index]);
                Children.Remove(Up2NowIndexRectangleDictionary[index]);
            }

            Up2NowIndexRectangleDictionary = nextIndexRectangleDictionary;
            Up2NowIndexLabelDictionary = nextIndexLabelDictionary;
        }

        private void OnResourceProviderDataChanged(object sender, EventArgs args)
        {
            foreach (Index index in Up2NowIndexRectangleDictionary.Keys)
            {
                Rectangle lineRect = Up2NowIndexRectangleDictionary[index];
                if (Children.Contains(lineRect))
                {
                    Children.Remove(lineRect);
                }
            }
            foreach (Index index in Up2NowIndexLabelDictionary.Keys)
            {
                Label label = Up2NowIndexLabelDictionary[index];
                if (Children.Contains(label))
                {
                    Children.Remove(label);
                }
            }
            Up2NowIndexRectangleDictionary.Clear();
            Up2NowIndexLabelDictionary.Clear();
        }

        /// 
        /// 現在の表示範囲属性で画面に表示する目盛り情報を取得します。
        /// 
        /// 
        private List GetIndices(long begin, long end, long scale)
        {
            List retIndices = new List();

            string format;
            long interval = 0;//目盛りの間隔

            if (scale < 25920000000)
            {
                if (scale < 2000000)// 40s/200px
                {
                    format = "HH:mm:ss";

                    if (scale < 500000)// 10s/200px
                    {
                        interval = 50000000; // 5s
                    }
                    else if (scale < 2000000)
                    { // 40s/200px
                        interval = 200000000; // 20s
                    }
                }
                else if (scale < 360000000)
                { // 2h/200px
                    format = "HH:mm";

                    if (scale < 6000000)
                    { // 2m/200px
                        interval = 600000000;  // 60s
                    }
                    else if (scale < 30000000)
                    { // 10m/200px
                        interval = 3000000000; // 5m
                    }
                    else if (scale < 120000000)
                    { // 
                        interval = 12000000000;
                    }
                    else if (scale < 360000000)
                    {
                        interval = 36000000000;
                    }

                }
                else if (scale < 2160000000)
                {
                    format = "dd HH:mm";
                    interval = 216000000000;
                }
                else
                {
                    format = Util.GetMonthDateString();
                    if (scale < 8640000000)
                    {
                        interval = 864000000000;
                    }
                    else
                    {
                        interval = 2592000000000;
                    }
                }


                for (int i = 0; i < (int)((end - begin) / interval) + 2; i++)
                {
                    DateTime date = new DateTime(begin - begin % interval + i * interval);
                    Index indexElement = new Index(date.Ticks, date.ToString(format));

                    retIndices.Add(indexElement);
                }
            }
            else if (scale < 60480000000)//1week/100px
            {
                format = Util.GetMonthDateString();
                interval = 864000000000;

                for (int i = 0; i < (int)((end - begin) / interval) + 2; i++)
                {
                    DateTime date = new DateTime(begin - begin % interval + i * interval);

                    if (date.DayOfWeek == DayOfWeek.Sunday)
                    {
                        Index indexElement = new Index(date.Ticks, date.ToString(format));

                        retIndices.Add(indexElement);
                    }

                }
            }
            else if (scale < 725760000000)
            {
                format = Util.GetYearMonthString();

                DateTime date = new DateTime(begin);
                date = date.AddDays(-date.Day + 1);
                date = date.AddHours(-date.Hour);
                date = date.AddMinutes(-date.Minute);
                date = date.AddSeconds(-date.Second);
                date = date.AddMilliseconds(-date.Millisecond);
                while (date.Ticks < end)
                {

                    Index indexElement = new Index(date.Ticks, date.ToString(format));

                    if (scale < 241920000000)
                    {
                        retIndices.Add(indexElement);
                    }
                    else
                    {
                        if ((date.Month - 1) % 3 == 0)
                        {
                            retIndices.Add(indexElement);
                        }
                    }

                    date = date.AddMonths(1);
                }
            }
            else
            {
                format = "yyyy";
                DateTime date = new DateTime(begin);
                date = date.AddMonths(-date.Month + 1);
                date = date.AddDays(-date.Day + 1);
                date = date.AddHours(-date.Hour);
                date = date.AddMinutes(-date.Minute);
                date = date.AddSeconds(-date.Second);
                date = date.AddMilliseconds(-date.Millisecond);
                while (date.Ticks < end)
                {
                    Index indexElement = new Index(date.Ticks, date.ToString(format));

                    if (scale < 3153600000000)
                    {
                        retIndices.Add(indexElement);
                    }
                    else
                    {
                        if (date.Year % 5 == 0)
                        {
                            retIndices.Add(indexElement);
                        }
                    }

                    date = date.AddYears(1);
                }
            }

            return retIndices;
        }
    }
}