1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * clock.cpp: Clock management
6 * Moonlight List (moonlight-list@lists.ximian.com)
8 * Copyright 2007 Novell, Inc. (http://www.novell.com)
10 * See the LICENSE file included with the distribution for details.
22 #include "timemanager.h"
24 #include "uielement.h"
26 #include "deployment.h"
33 SetObjectType (Type::TIMELINE
);
37 timeline_status
= TIMELINE_STATUS_OK
;
41 Timeline::~Timeline ()
46 Timeline::AllocateClock ()
48 clock
= new Clock (this);
50 AttachCompletedHandler ();
64 RepeatBehavior
*repeat
= GetRepeatBehavior ();
65 Duration
*duration
= GetDuration ();
67 if (duration
->HasTimeSpan () && duration
->GetTimeSpan () == 0 &&
68 (GetFillBehavior () == FillBehaviorStop
|| (repeat
->HasCount () && repeat
->GetCount () > 1.0)))
69 timeline_status
= TIMELINE_STATUS_DETACHED
;
71 // FIXME This should prolly be changed to a more generic if BeginTime > Duration
72 // Need to investigate, though SL checking seems to be very selective
73 if (duration
->HasTimeSpan () && duration
->GetTimeSpan () == 0 &&
74 this->GetBeginTime () > 0)
81 Timeline::SetRepeatBehavior (RepeatBehavior behavior
)
83 SetValue (Timeline::RepeatBehaviorProperty
, Value(behavior
));
87 Timeline::GetRepeatBehavior ()
89 return GetValue (Timeline::RepeatBehaviorProperty
)->AsRepeatBehavior();
93 Timeline::SetDuration (Duration duration
)
95 SetValue (Timeline::DurationProperty
, Value(duration
));
99 Timeline::GetDuration ()
101 return GetValue (Timeline::DurationProperty
)->AsDuration();
105 Timeline::GetNaturalDuration (Clock
*clock
)
107 Duration
* d
= GetDuration ();
108 if (*d
== Duration::Automatic
) {
109 // printf ("automatic duration, we need to calculate it\n");
110 Duration cd
= GetNaturalDurationCore (clock
);
111 // if (cd.HasTimeSpan ())
112 // printf (" + duration (%lld timespan)\n", cd.GetTimeSpan ());
113 // else if (cd == Duration::Automatic)
114 // printf (" + automatic\n");
115 // else if (cd == Duration::Forever)
116 // printf (" + forever\n");
125 Timeline::GetNaturalDurationCore (Clock
*clock
)
127 return Duration::Automatic
;
131 Timeline::GetBeginTime ()
133 Value
*v
= GetValue (Timeline::BeginTimeProperty
);
134 return v
== NULL
? 0LL : v
->AsTimeSpan();
138 Timeline::AttachCompletedHandler ()
140 clock
->AddHandler (Clock::CompletedEvent
, clock_completed
, this);
144 Timeline::DetachCompletedHandler ()
146 clock
->RemoveHandler (Clock::CompletedEvent
, clock_completed
, this);
150 Timeline::clock_completed (EventObject
*sender
, EventArgs
*calldata
, gpointer closure
)
152 Timeline
*timeline
= (Timeline
*) closure
;
153 timeline
->OnClockCompleted ();
157 Timeline::OnClockCompleted ()
159 Emit (Timeline::CompletedEvent
);
163 Timeline::TeardownClock ()
166 DetachCompletedHandler ();
168 ClockGroup
*group
= c
->GetParentClock();
170 group
->RemoveChild (c
);
178 TimelineGroup::TimelineGroup ()
180 SetObjectType (Type::TIMELINEGROUP
);
183 TimelineGroup::~TimelineGroup ()
188 TimelineGroup::AllocateClock ()
190 clock
= new ClockGroup (this);
191 TimelineCollection
*collection
= GetChildren ();
193 for (int i
= 0; i
< collection
->GetCount (); i
++)
194 ((ClockGroup
*)clock
)->AddChild (collection
->GetValueAt (i
)->AsTimeline ()->AllocateClock ());
196 AttachCompletedHandler ();
200 // Validate this TimelineGroup by validating all of it's children
202 TimelineGroup::Validate ()
204 TimelineCollection
*collection
= GetChildren ();
207 for (int i
= 0; i
< collection
->GetCount (); i
++) {
208 timeline
= collection
->GetValueAt (i
)->AsTimeline ();
209 if (!timeline
->Validate ())
213 return Timeline::Validate ();
217 TimelineGroup::AddChild (Timeline
*child
)
219 TimelineCollection
*children
= GetChildren ();
220 children
->Add (child
);
224 TimelineGroup::RemoveChild (Timeline
*child
)
226 TimelineCollection
*children
= GetChildren ();
228 children
->Remove (child
);
232 TimelineGroup::OnCollectionChanged (Collection
*col
, CollectionChangedEventArgs
*args
)
234 if (col
== GetChildren()) {
235 if (args
->GetChangedAction() == CollectionChangedActionAdd
||
236 args
->GetChangedAction() == CollectionChangedActionReplace
) {
237 Timeline
*timeline
= args
->GetNewItem()->AsTimeline ();
239 timeline
->SetHadParent (true);
245 TimelineCollection::TimelineCollection ()
247 SetObjectType (Type::TIMELINE_COLLECTION
);
250 TimelineCollection::~TimelineCollection ()
254 ParallelTimeline::ParallelTimeline ()
256 SetObjectType (Type::PARALLELTIMELINE
);
259 ParallelTimeline::~ParallelTimeline ()
264 ParallelTimeline::GetNaturalDurationCore (Clock
*clock
)
266 TimelineCollection
*collection
= GetChildren ();
267 Duration d
= Duration::Automatic
;
268 TimeSpan duration_span
= 0;
271 if (collection
->GetCount () == 0)
272 return Duration::FromSeconds (0);
274 for (int i
= 0; i
< collection
->GetCount (); i
++) {
275 timeline
= collection
->GetValueAt (i
)->AsTimeline ();
277 Duration duration
= timeline
->GetNaturalDuration (clock
);
278 if (duration
.IsAutomatic())
281 if (duration
.IsForever())
282 return Duration::Forever
;
284 TimeSpan span
= duration
.GetTimeSpan ();
286 RepeatBehavior
*repeat
= timeline
->GetRepeatBehavior ();
287 if (repeat
->IsForever())
288 return Duration::Forever
;
290 if (repeat
->HasCount ())
291 span
= (TimeSpan
) (span
* repeat
->GetCount ());
293 if (timeline
->GetAutoReverse ())
296 // If we have duration-base repeat behavior,
297 // clamp/up our span to that.
298 if (repeat
->HasDuration ())
299 span
= repeat
->GetDuration ();
302 span
= (TimeSpan
)(span
/ timeline
->GetSpeedRatio());
304 span
+= timeline
->GetBeginTime ();
306 if (duration_span
<= span
) {
307 duration_span
= span
;
308 d
= Duration (duration_span
);
315 TimelineMarker::TimelineMarker ()
317 SetObjectType (Type::TIMELINEMARKER
);
320 TimelineMarker::~TimelineMarker ()
324 DispatcherTimer::DispatcherTimer ()
326 SetObjectType (Type::DISPATCHERTIMER
);
334 DispatcherTimer::Start ()
339 Surface
*surface
= Deployment::GetCurrent ()->GetSurface ();
343 clock
->BeginOnTick ();
344 clock
->SetRootParentTime (surface
->GetTimeManager()->GetCurrentTime());
347 char *name
= g_strdup_printf ("DispatcherTimer (%p)", this);
348 clock
->SetValue (DependencyObject::NameProperty
, name
);
351 surface
->GetTimeManager()->AddClock (clock
);
353 clock
->BeginOnTick ();
358 DispatcherTimer::Stop ()
366 DispatcherTimer::Restart ()
371 TimeSpan time
= clock
->GetParentClock()->GetCurrentTime();
372 clock
->SetRootParentTime (time
);
377 DispatcherTimer::OnClockCompleted ()
380 Emit (DispatcherTimer::TickEvent
);
382 /* if the timer wasn't stopped on started on
383 the tick event, restart it. Unlike Start,
384 which makes it go on the next tick, Restart
385 includes the time spent on the tick.
387 if (!IsStopped () && !IsStarted ())
392 DispatcherTimer::GetNaturalDurationCore (Clock
*clock
)
394 return Duration::FromSeconds (0);
398 DispatcherTimer::TeardownClock ()
402 Timeline::TeardownClock ();