/[cits3200i]/branches/playback-branch-rvvs89/UWAPlugins/PlaybackPlugin/Source/PlaybackControl.cs


UCC Code Repository

Diff of /branches/playback-branch-rvvs89/UWAPlugins/PlaybackPlugin/Source/PlaybackControl.cs

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 60 by rvvs89, Wed Sep 22 15:08:13 2010 UTC revision 61 by rvvs89, Thu Sep 30 03:03:02 2010 UTC
# Line 2  Line 2 
2  using System;  using System;
3  using System.Collections.Generic;  using System.Collections.Generic;
4  using System.ComponentModel;  using System.ComponentModel;
 using System.Drawing;  
5  using System.Data;  using System.Data;
6    using System.Drawing;
7  using System.Text;  using System.Text;
8  using System.Timers;  using System.Timers;
9  using System.Windows.Forms;  using System.Windows.Forms;
# Line 20  namespace PlaybackPlugin.Source Line 20  namespace PlaybackPlugin.Source
20          private PlaybackState state = PlaybackState.Disabled;          private PlaybackState state = PlaybackState.Disabled;
21          private IActivity activity = null;          private IActivity activity = null;
22          private System.Timers.Timer timer;          private System.Timers.Timer timer;
23            private DateTime startTime;
24            private DateTime endTime;
25            private DateTime currentTime;
26            private Nullable<DateTime> initialSelection = null;
27            private IRouteControl control;
28            private IRouteControlItem item;
29            private IGPSRoute route;
30            private EventHandler selectedItemsChangedHandler;
31            private IList<IRouteControlSelection> oldSelection;
32            private const double MOVE_SELECTION_THRESHOLD = 2000.0;
33            private const double PLAYBACKBAR_TICK_GRANULARITY = 100;
34            private const double REWIND_FACTOR = -5.0;
35            private const double FASTFORWARD_FACTOR = 5.0;
36            private const double STEP_SIZE = 1.0;
37    
38          public PlaybackControl()          public PlaybackControl()
39          {          {
40              InitializeComponent();              InitializeComponent();
41                if (PlaybackAnimationRouteControlLayer.Instances.Count == 0)
42                {
43                    // HACK: make designer work properly
44                    return;
45                }
46                CheckRouteValidity();
47                MarkSelectedRegion();
48              UpdateUI();              UpdateUI();
49              timer = new System.Timers.Timer(5000.0);              selectedItemsChangedHandler = new EventHandler(control_SelectedItemsChanged);
50                control.SelectedItemsChanged += selectedItemsChangedHandler;
51                timer = new System.Timers.Timer();
52                timer.Interval = 100.0;
53              timer.Elapsed += new ElapsedEventHandler(PlaybackTick);              timer.Elapsed += new ElapsedEventHandler(PlaybackTick);
54              timer.SynchronizingObject = this;              timer.SynchronizingObject = this;
55          }          }
56            
         public PlaybackControl(IActivity activity) : this()  
         {  
             this.activity = activity;  
         }  
   
57          public IActivity Activity          public IActivity Activity
58          {          {
59              get { return activity; }              get { return activity; }
60              set {              set {
61                  activity = value;                  activity = value;
62                  if (activity != null)                  State = activity == null ? PlaybackState.Disabled : PlaybackState.Stopped;
                 {  
                     State = PlaybackState.Stopped;  
                 }  
63              }              }
64          }          }
65    
# Line 58  namespace PlaybackPlugin.Source Line 74  namespace PlaybackPlugin.Source
74              }              }
75          }          }
76    
77            private DateTime CurrentTime
78            {
79                get { return currentTime; }
80                set
81                {
82                    currentTime = value;
83                    currentTime = DateTimeMax(currentTime, startTime);
84                    currentTime = DateTimeMin(currentTime, endTime);
85                    UpdateUI();
86                }
87            }
88    
89            public new void Dispose()
90            {
91                State = PlaybackState.Disabled;
92                control.SelectedItemsChanged -= selectedItemsChangedHandler;
93                control.SelectedItems = oldSelection;
94                timer.Stop();
95                timer.Dispose();
96                PlaybackAnimationRouteControlLayer.Instances[0].StartMarker.Visible = false;
97                PlaybackAnimationRouteControlLayer.Instances[0].EndMarker.Visible = false;
98                PlaybackAnimationRouteControlLayer.Instances[0].UpdateMarkers();
99                base.Dispose();
100            }
101    
102          private void UpdateUI()          private void UpdateUI()
103          {          {
104                TimeSpan length = endTime - startTime;
105                TimeSpan progress = currentTime - startTime;
106              rewindButton.Enabled = State != PlaybackState.Disabled && State != PlaybackState.Stopped;              rewindButton.Enabled = State != PlaybackState.Disabled && State != PlaybackState.Stopped;
107              fastForwardButton.Enabled = State != PlaybackState.Disabled && State != PlaybackState.Stopped;              fastForwardButton.Enabled = State != PlaybackState.Disabled && State != PlaybackState.Stopped;
108              playButton.Enabled = State != PlaybackState.Disabled;              playButton.Enabled = State != PlaybackState.Disabled;
# Line 69  namespace PlaybackPlugin.Source Line 112  namespace PlaybackPlugin.Source
112              speedSpinner.Enabled = State != PlaybackState.Disabled;              speedSpinner.Enabled = State != PlaybackState.Disabled;
113              statusStrip.Enabled = State != PlaybackState.Disabled;              statusStrip.Enabled = State != PlaybackState.Disabled;
114              playbackBar.Enabled = State != PlaybackState.Disabled;              playbackBar.Enabled = State != PlaybackState.Disabled;
115                playbackBar.Maximum = (int) (length.TotalMilliseconds / PLAYBACKBAR_TICK_GRANULARITY);
116                int ticks = Math.Min(playbackBar.Maximum, 10);
117                playbackBar.TickFrequency = playbackBar.Maximum / ticks;
118                playbackBar.Value = (int) (progress.TotalMilliseconds / PLAYBACKBAR_TICK_GRANULARITY);
119              statusLabel.Enabled = State != PlaybackState.Disabled;              statusLabel.Enabled = State != PlaybackState.Disabled;
120                statusLabel.Text = String.Format("{0}:{1:00}:{2:00} / {3}:{4:00}:{5:00}", progress.Hours, progress.Minutes, progress.Seconds, length.Hours, length.Minutes, length.Seconds);
121                control.SelectedItems = new List<IRouteControlSelection> { new PlaybackRouteControlSelection(item, currentTime) };
122                if (followButton.Checked)
123                {
124                    control.MapControl.Center = route.GetInterpolatedValue(currentTime).Value;
125                }
126            }
127    
128            private void CheckRouteValidity()
129            {
130                // TODO: Verify that the current route is one that can be played back (ie has valid time data)
131                // TODO: notify user that playback is impossible if the route does not have time data and throw exception
132                control = PlaybackAnimationRouteControlLayer.Instances[0].Control;
133                oldSelection = control.SelectedItems;
134            }
135    
136            private static DateTime DateTimeMin(DateTime a, DateTime b)
137            {
138                return a < b ? a : b;
139            }
140    
141            private static DateTime DateTimeMax(DateTime a, DateTime b)
142            {
143                return a > b ? a : b;
144            }
145    
146            private static int RouteIndexFromDistance(IGPSRoute route, double distance)
147            {
148                // FIXME: add out parameter to output the remaining distance to improve accuracy
149                IEnumerator<ITimeValueEntry<IGPSPoint>> i = route.GetEnumerator();
150                int index = 0;
151                double count = 0.0;
152                i.MoveNext();
153                IGPSPoint prev = i.Current.Value;
154                while (i.MoveNext())
155                {
156                    IGPSPoint cur = i.Current.Value;
157                    count += prev.DistanceMetersToPoint(cur);
158                    if (count < distance)
159                    {
160                        index++;
161                        prev = cur;
162                    }
163                    else
164                    {
165                        return index;
166                    }
167                }
168                return index;
169            }
170    
171            private static DateTime RouteTimeFromDistance(IGPSRoute route, double distance)
172            {
173                int index = RouteIndexFromDistance(route, distance);
174                return route.StartTime.AddSeconds(route[index].ElapsedSeconds);
175            }
176    
177            private void CalculateSelectedRegion(out DateTime start, out DateTime end)
178            {
179                // FIXME: account for multiple ranges within one selection
180                start = DateTime.MaxValue;
181                end = DateTime.MinValue;
182                for (int k = 0; k < control.SelectedItems.Count; k++)
183                {
184                    IRouteControlSelection selection = control.SelectedItems[k];
185                    if (selection == null || !selection.Item.DisplayRoute || selection.Item.Item == null)
186                    {
187                        return;
188                    }
189                    if (selection.DistanceMetersRanges != null && selection.DistanceMetersRanges.Count >= 1)
190                    {
191                        start = DateTimeMin(start, RouteTimeFromDistance(route, selection.DistanceMetersRanges[0].Lower));
192                        end = DateTimeMax(end, RouteTimeFromDistance(route, selection.DistanceMetersRanges[0].Upper));
193                    }
194                    else if (selection.TimeRanges != null && selection.TimeRanges.Count >= 1)
195                    {
196                        start = DateTimeMin(start, selection.TimeRanges[0].Lower);
197                        end = DateTimeMax(start, selection.TimeRanges[0].Upper);
198                    }
199                }
200                if (start == DateTime.MaxValue)
201                {
202                    start = DateTime.MinValue;
203                }
204                if (end == DateTime.MinValue)
205                {
206                    end = DateTime.MaxValue;
207                }
208            }
209    
210            private void MarkSelectedRegion()
211            {
212                item = control.Items[0];
213                route = item.Item.GPSRoute;
214                IList<IRouteControlSelection> selection = PlaybackAnimationRouteControlLayer.Instances[0].Control.SelectedItems;
215                CalculateSelectedRegion(out startTime, out endTime);
216                if (endTime == startTime)
217                {
218                    initialSelection = startTime;
219                    startTime = DateTime.MinValue;
220                    endTime = DateTime.MaxValue;
221                }
222                else
223                {
224                    initialSelection = null;
225                }
226                startTime = DateTimeMax(startTime, route.StartTime);
227                if (startTime > route.StartTime)
228                {
229                    MapMarker startMarker = PlaybackAnimationRouteControlLayer.Instances[0].StartMarker;
230                    startMarker.Location = route.GetInterpolatedValue(startTime).Value;
231                    startMarker.Visible = true;
232                }
233                endTime = DateTimeMin(endTime, route.StartTime.AddSeconds(route.TotalElapsedSeconds));
234                if (endTime < route.StartTime.AddSeconds(route.TotalElapsedSeconds))
235                {
236                    MapMarker endMarker = PlaybackAnimationRouteControlLayer.Instances[0].EndMarker;
237                    endMarker.Location = route.GetInterpolatedValue(endTime).Value;
238                    endMarker.Visible = true;
239                }
240                PlaybackAnimationRouteControlLayer.Instances[0].UpdateMarkers();
241                CurrentTime = initialSelection == null ? startTime : initialSelection.Value;
242          }          }
243    
244          public enum PlaybackState          public enum PlaybackState
# Line 84  namespace PlaybackPlugin.Source Line 253  namespace PlaybackPlugin.Source
253    
254          private void playButton_Click(object sender, EventArgs e)          private void playButton_Click(object sender, EventArgs e)
255          {          {
256                if (State == PlaybackState.Stopped && CurrentTime >= endTime)
257                {
258                    CurrentTime = startTime;
259                }
260              State = State == PlaybackState.Playing || State == PlaybackState.FastForwarding || State == PlaybackState.Rewinding ? PlaybackState.Paused : PlaybackState.Playing;              State = State == PlaybackState.Playing || State == PlaybackState.FastForwarding || State == PlaybackState.Rewinding ? PlaybackState.Paused : PlaybackState.Playing;
261          }          }
262    
263          private void fastForwardButton_Click(object sender, EventArgs e)          private void fastForwardButton_Click(object sender, EventArgs e)
264          {          {
265              // TODO              if (State == PlaybackState.Paused)
266                {
267                    CurrentTime = CurrentTime.AddSeconds(STEP_SIZE);
268                }
269                else
270                {
271                    // TODO: implement fast-forward
272                }
273          }          }
274    
275          private void rewindButton_Click(object sender, EventArgs e)          private void rewindButton_Click(object sender, EventArgs e)
276          {          {
277              // TODO              if (State == PlaybackState.Paused)
278          }              {
279                    CurrentTime = CurrentTime.AddSeconds(-STEP_SIZE);
280          private void loopButton_CheckedChanged(object sender, EventArgs e)              }
281          {              else
282              // TODO              {
283          }                  // TODO: implement rewind
284                }
         private void speedSpinner_ValueChanged(object sender, EventArgs e)  
         {  
             // TODO  
285          }          }
286    
287          private void playbackBar_Scroll(object sender, EventArgs e)          private void playbackBar_Scroll(object sender, EventArgs e)
288          {          {
289              // TODO              CurrentTime = startTime.AddMilliseconds(playbackBar.Value * PLAYBACKBAR_TICK_GRANULARITY);
290          }          }
291    
292          private static int RouteIndexFromDistance(IEnumerator<ITimeValueEntry<IGPSPoint>> route, double distance)          private void PlaybackTick(object source, ElapsedEventArgs args)
293          {          {
294              int index = 0;              CurrentTime = CurrentTime.AddMilliseconds((double) speedSpinner.Value * timer.Interval);
295              double count = 0.0;              if (CurrentTime >= endTime)
             IGPSPoint prev = route.Current.Value;  
             while(route.MoveNext())  
296              {              {
297                  IGPSPoint cur = route.Current.Value;                  if (loopButton.Checked)
                 count += prev.DistanceMetersToPoint(cur);  
                 if(count < distance)  
298                  {                  {
299                      index++;                      CurrentTime = startTime;
300                                          prev = cur;                  }
301                  } else {                  else
302                      return index;                  {
303                                  }                      State = PlaybackState.Stopped;
304                    }
305              }              }
             return -1;  
306          }          }
307    
308          private void PlaybackTick(object source, ElapsedEventArgs args)          private void control_SelectedItemsChanged(object sender, EventArgs e)
309          {          {
310              //IRouteControlSelection selection = CollectionUtils.GetSingleItemOfType<IRouteControlSelection>(PlaybackAnimationRouteControlLayer.Instance.Control.SelectedItems);              // FIXME: account for multiple ranges within one selection
311              IRouteControlSelection selection = CollectionUtils.GetFirstItemOfType<IRouteControlSelection>(PlaybackAnimationRouteControlLayer.Selection);              DateTime selectedTime = DateTime.MinValue;
312              if (selection == null)              for (int k = 0; k < control.SelectedItems.Count; k++)
313                {
314                    IRouteControlSelection selection = control.SelectedItems[k];
315                    if (selection == null || !selection.Item.DisplayRoute || selection.Item.Item == null)
316                    {
317                        return;
318                    }
319                    if (selection.DistanceMetersRanges != null && selection.DistanceMetersRanges.Count >= 1)
320                    {
321                        selectedTime = RouteTimeFromDistance(route, selection.DistanceMetersRanges[0].Lower);
322                    }
323                    else if (selection.TimeRanges != null && selection.TimeRanges.Count >= 1)
324                    {
325                        selectedTime = selection.TimeRanges[0].Lower;
326                    }
327                    if (selectedTime != DateTime.MinValue)
328                    {
329                        break;
330                    }
331                }
332                if (selectedTime == DateTime.MinValue)
333              {              {
334                  // TODO                  return;
335              }              }
336              else              TimeSpan diff = currentTime < selectedTime ? selectedTime - currentTime : currentTime - selectedTime;
337                if (diff.TotalMilliseconds > MOVE_SELECTION_THRESHOLD)
338              {              {
339                  IList<IValueRange<DateTime>> ranges = selection.TimeRanges;                  CurrentTime = selectedTime;
                 IGPSRoute item = selection.Item.Item.GPSRoute;  
                 IList<IValueRange<double>> distanceRanges = selection.DistanceMetersRanges;  
                 /*DateTime upper = range.Upper;  
                 DateTime lower = range.Lower;*/  
                 Console.WriteLine("Test");  
340              }              }
341          }          }
342      }      }

Legend:
Removed from v.60  
changed lines
  Added in v.61

Managed by UCC Webmasters ViewVC Help
Powered by ViewVC 1.1.26