/// <summary> /// Write a class that implements the IDynamicAnimatedVisualSource interface. /// </summary> void WriteIDynamicAnimatedVisualSource(CodeBuilder builder, CodeGenInfo info) { var nodes = info.LoadedImageSurfaceNodes.ToArray(); builder.WriteLine("namespace AnimatedVisuals"); builder.OpenScope(); builder.WriteLine($"sealed class {info.ClassName} : IDynamicAnimatedVisualSource, INotifyPropertyChanged"); builder.OpenScope(); // Declare variables. builder.WriteLine($"{_stringifier.Const(_stringifier.Int32TypeName)} c_loadedImageSurfaceCount = {nodes.Distinct().Count()};"); builder.WriteLine($"{_stringifier.Int32TypeName} _loadCompleteEventCount;"); builder.WriteLine("bool _isAnimatedVisualSourceDynamic = true;"); builder.WriteLine("bool _isTryCreateAnimatedVisualCalled;"); builder.WriteLine("bool _isImageLoadingStarted;"); builder.WriteLine("EventRegistrationTokenTable<TypedEventHandler<IDynamicAnimatedVisualSource, object>> _animatedVisualInvalidatedEventTokenTable;"); // Declare the variables to hold the surfaces. foreach (var n in nodes) { builder.WriteLine($"{_stringifier.ReferenceTypeName(n.TypeName)} {n.FieldName};"); } builder.WriteLine(); // Implement the INotifyPropertyChanged.PropertyChanged event. builder.WriteSummaryComment("This implementation of the INotifyPropertyChanged.PropertyChanged event is specific to C# and does not work on WinRT."); builder.WriteLine("public event PropertyChangedEventHandler PropertyChanged;"); builder.WriteLine(); // Implement the AnimatedVisualInvalidated event. WriteAnimatedVisualInvalidatedEvent(builder); // Define properties. builder.WriteSummaryComment("If this property is set to true, <see cref=\"TryCreateAnimatedVisual\"/> will return null until all images have loaded. When all images have loaded, <see cref=\"TryCreateAnimatedVisual\"/> will return the AnimatedVisual. To use, set it when declaring the AnimatedVisualSource. Once <see cref=\"TryCreateAnimatedVisual\"/> is called, changes made to this property will be ignored. Default value is true."); builder.WriteLine("public bool IsAnimatedVisualSourceDynamic"); builder.OpenScope(); builder.WriteLine("get { return _isAnimatedVisualSourceDynamic; }"); builder.WriteLine("set"); builder.OpenScope(); builder.WriteLine("if (!_isTryCreateAnimatedVisualCalled && _isAnimatedVisualSourceDynamic != value)"); builder.OpenScope(); builder.WriteLine("_isAnimatedVisualSourceDynamic = value;"); builder.WriteLine("NotifyPropertyChanged(nameof(IsAnimatedVisualSourceDynamic));"); builder.CloseScope(); builder.CloseScope(); builder.CloseScope(); builder.WriteLine(); builder.WriteSummaryComment("Returns true if all images have loaded. To see if the images succeeded to load, see <see cref=\"ImageSuccessfulLoadingProgress\"/>."); builder.WriteLine("public bool IsImageLoadingCompleted { get; private set; }"); builder.WriteLine(); builder.WriteSummaryComment("Represents the progress of the image loading. Returns value between 0 and 1. 0 means none of the images finished loading. 1 means all images finished loading."); builder.WriteLine("public double ImageSuccessfulLoadingProgress { get; private set; }"); builder.WriteLine(); // Generate the method that creates an instance of the animated visual. builder.WriteLine("public IAnimatedVisual TryCreateAnimatedVisual(Compositor compositor, out object diagnostics)"); builder.OpenScope(); builder.WriteLine("_isTryCreateAnimatedVisualCalled = true;"); builder.WriteLine(); builder.WriteLine("diagnostics = null;"); builder.WriteLine("if (!IsRuntimeCompatible())"); builder.OpenScope(); builder.WriteLine("return null;"); builder.CloseScope(); builder.WriteLine(); builder.WriteLine("EnsureImageLoadingStarted();"); builder.WriteLine(); builder.WriteLine("if (_isAnimatedVisualSourceDynamic && _loadCompleteEventCount != c_loadedImageSurfaceCount)"); builder.OpenScope(); builder.WriteLine("return null;"); builder.CloseScope(); builder.WriteLine("return"); builder.Indent(); WriteAnimatedVisualCall(builder, info); builder.UnIndent(); builder.CloseScope(); builder.WriteLine(); // Generate the method that load all the LoadedImageSurfaces. WriteEnsureImageLoadingStarted(builder, info); // Generate the method that handle the LoadCompleted event of the LoadedImageSurface objects. WriteHandleLoadCompleted(builder); // Generate the method that raise the PropertyChanged event. builder.WriteLine("void NotifyPropertyChanged(string name)"); builder.OpenScope(); builder.WriteLine("PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));"); builder.CloseScope(); builder.WriteLine(); // Generate the method that get or create the EventRegistrationTokenTable. builder.WriteLine("EventRegistrationTokenTable<TypedEventHandler<IDynamicAnimatedVisualSource, object>> GetAnimatedVisualInvalidatedEventRegistrationTokenTable()"); builder.OpenScope(); builder.WriteLine("return EventRegistrationTokenTable<TypedEventHandler<IDynamicAnimatedVisualSource, object>>.GetOrCreateEventRegistrationTokenTable(ref _animatedVisualInvalidatedEventTokenTable);"); builder.CloseScope(); builder.WriteLine(); }