aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.UI/ViewModels/ItemCollectionViewModel.cs
blob: 82feedbd70590937963e3c072097e1286c589d5c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
using MediaBrowser.Model.DTO;
using System;
using System.Threading;
using System.Windows;

namespace MediaBrowser.UI.ViewModels
{
    /// <summary>
    /// Represents a view model that contains multiple items.
    /// This should be used if you want to display a button or list item that holds more than one item, 
    /// and cycle through them periodically.
    /// </summary>
    public class ItemCollectionViewModel : BaseViewModel, IDisposable
    {
        private int RotationPeriodMs { get; set; }

        public ItemCollectionViewModel(int rotationPeriodMs = 10000, int rotationDevaiationMs = 2000)
            : base()
        {
            if (rotationDevaiationMs > 0)
            {
                rotationPeriodMs += new Random(Guid.NewGuid().GetHashCode()).Next(0 - rotationDevaiationMs, rotationDevaiationMs);
            }

            RotationPeriodMs = rotationPeriodMs;
        }

        /// <summary>
        /// Gets the timer that updates the current item
        /// </summary>
        private Timer CurrentItemTimer { get; set; }

        private string _name;
        /// <summary>
        /// Gets or sets the name of the collection
        /// </summary>
        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;
                OnPropertyChanged("Name");
            }
        }

        private DtoBaseItem[] _items;
        /// <summary>
        /// Gets or sets the list of items
        /// </summary>
        public DtoBaseItem[] Items
        {
            get { return _items; }
            set
            {
                _items = value ?? new DtoBaseItem[] { };
                OnPropertyChanged("Items");
                CurrentItemIndex = Items.Length == 0 ? -1 : 0;

                ReloadTimer();
            }
        }

        private int _currentItemIndex;
        /// <summary>
        /// Gets or sets the index of the current item
        /// </summary>
        public int CurrentItemIndex
        {
            get { return _currentItemIndex; }
            set
            {
                _currentItemIndex = value;
                OnPropertyChanged("CurrentItemIndex");
                OnPropertyChanged("CurrentItem");
                OnPropertyChanged("NextItem");
            }
        }

        /// <summary>
        /// Gets the current item
        /// </summary>
        public DtoBaseItem CurrentItem
        {
            get { return CurrentItemIndex == -1 ? null : Items[CurrentItemIndex]; }
        }

        /// <summary>
        /// Gets the next item
        /// </summary>
        public DtoBaseItem NextItem
        {
            get
            {
                if (CurrentItem == null || CurrentItemIndex == -1)
                {
                    return null;
                }
                var index = CurrentItemIndex + 1;

                if (index >= Items.Length)
                {
                    index = 0;
                }

                return Items[index];
            }
        }

        /// <summary>
        /// Disposes the timer
        /// </summary>
        private void DisposeTimer()
        {
            if (CurrentItemTimer != null)
            {
                CurrentItemTimer.Dispose();
            }
        }

        /// <summary>
        /// Reloads the timer
        /// </summary>
        private void ReloadTimer()
        {
            DisposeTimer();

            // Don't bother unless there's at least two items
            if (Items.Length > 1)
            {
                CurrentItemTimer = new Timer(state => Application.Current.Dispatcher.InvokeAsync(IncrementCurrentItemIndex), null, RotationPeriodMs, RotationPeriodMs);
            }
        }

        /// <summary>
        /// Increments current item index, or resets it back to zero if we're at the end of the list
        /// </summary>
        private void IncrementCurrentItemIndex()
        {
            var newIndex = CurrentItemIndex + 1;

            if (newIndex >= Items.Length)
            {
                newIndex = 0;
            }

            CurrentItemIndex = newIndex;
        }

        /// <summary>
        /// Disposes the collection
        /// </summary>
        public void Dispose()
        {
            DisposeTimer();
        }
    }
}