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 (%" G_GINT64_FORMAT " 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
);
335 DispatcherTimer::Start ()
340 Surface
*surface
= Deployment::GetCurrent ()->GetSurface ();
344 clock
->BeginOnTick ();
345 clock
->SetRootParentTime (surface
->GetTimeManager()->GetCurrentTime());
348 char *name
= g_strdup_printf ("DispatcherTimer (%p)", this);
349 clock
->SetValue (DependencyObject::NameProperty
, name
);
352 surface
->GetTimeManager()->AddClock (clock
);
354 clock
->BeginOnTick ();
359 DispatcherTimer::Stop ()
366 Timeline::TeardownClock ();
370 DispatcherTimer::Restart ()
375 TimeSpan time
= clock
->GetParentClock()->GetCurrentTime();
376 clock
->SetRootParentTime (time
);
381 DispatcherTimer::OnClockCompleted ()
385 Emit (DispatcherTimer::TickEvent
);
388 /* if the timer wasn't stopped or started on
389 the tick event, restart it. Unlike Start,
390 which makes it go on the next tick, Restart
391 includes the time spent on the tick.
393 if the timer was stopped but not started
394 on the tick event, we don't need to keep
395 the clock around anymore.
397 if (!stopped
&& !started
)
399 else if (stopped
&& !started
)
400 Timeline::TeardownClock ();
404 DispatcherTimer::GetNaturalDurationCore (Clock
*clock
)
406 return Duration::FromSeconds (0);
410 DispatcherTimer::TeardownClock ()
414 Timeline::TeardownClock ();