void WriteHandleLoadCompleted(CodeBuilder builder) { builder.WriteLine("void HandleLoadCompleted(LoadedImageSurface sender, LoadedImageSourceLoadCompletedEventArgs e)"); builder.OpenScope(); builder.WriteLine("_loadCompleteEventCount++;"); builder.WriteLine("sender.LoadCompleted -= HandleLoadCompleted;"); builder.WriteLine(); builder.WriteLine("if (e.Status == LoadedImageSourceLoadStatus.Success)"); builder.OpenScope(); builder.WriteLine("if (_isAnimatedVisualSourceDynamic && _loadCompleteEventCount == c_loadedImageSurfaceCount)"); builder.OpenScope(); builder.WriteLine("_animatedVisualInvalidatedEventTokenTable?.InvocationList?.Invoke(this, null);"); builder.CloseScope(); builder.WriteLine("ImageSuccessfulLoadingProgress = (double)_loadCompleteEventCount / c_loadedImageSurfaceCount;"); builder.WriteLine("NotifyPropertyChanged(nameof(ImageSuccessfulLoadingProgress));"); builder.CloseScope(); builder.WriteLine(); builder.WriteLine("if (_loadCompleteEventCount == c_loadedImageSurfaceCount)"); builder.OpenScope(); builder.WriteLine("IsImageLoadingCompleted = true;"); builder.WriteLine("NotifyPropertyChanged(nameof(IsImageLoadingCompleted));"); builder.CloseScope(); builder.CloseScope(); builder.WriteLine(); }
void WriteEnsureImageLoadingStarted(CodeBuilder builder, CodeGenInfo info) { builder.WriteLine("void EnsureImageLoadingStarted()"); builder.OpenScope(); builder.WriteLine("if (!_isImageLoadingStarted)"); builder.OpenScope(); builder.WriteLine("var eventHandler = new TypedEventHandler<LoadedImageSurface, LoadedImageSourceLoadCompletedEventArgs>(HandleLoadCompleted);"); var nodes = info.LoadedImageSurfaceNodes.ToArray(); foreach (var n in nodes) { switch (n.LoadedImageSurfaceType) { case LoadedImageSurface.LoadedImageSurfaceType.FromStream: builder.WriteLine($"{n.FieldName} = LoadedImageSurface.StartLoadFromStream({n.BytesFieldName}.AsBuffer().AsStream().AsRandomAccessStream());"); break; case LoadedImageSurface.LoadedImageSurfaceType.FromUri: builder.WriteLine($"{n.FieldName} = LoadedImageSurface.StartLoadFromUri(new Uri(\"{n.ImageUri}\"));"); break; default: throw new InvalidOperationException(); } builder.WriteLine($"{n.FieldName}.LoadCompleted += eventHandler;"); } builder.WriteLine("_isImageLoadingStarted = true;"); builder.CloseScope(); builder.CloseScope(); builder.WriteLine(); }
/// <inheritdoc/> // Called by the base class to write the end of the file (i.e. everything after the body of the Instantiator class). protected override void WriteFileEnd( CodeBuilder builder, CodeGenInfo info) { // Write the constructor for the instantiator. if (info.HasLoadedImageSurface) { builder.WriteLine($"internal AnimatedVisual(Compositor compositor,"); builder.Indent(); // Define the image surface parameters of the AnimatedVisual() constructor. builder.WriteCommaSeparatedLines(info.LoadedImageSurfaceNodes.Select(n => $"{_stringifier.ReferenceTypeName(n.TypeName)} {_stringifier.CamelCase(n.Name)}")); builder.WriteLine(")"); builder.UnIndent(); builder.OpenScope(); builder.WriteLine("_c = compositor;"); builder.WriteLine($"{info.ReusableExpressionAnimationFieldName} = compositor.CreateExpressionAnimation();"); // Initialize the private image surface variables with the input parameters of the constructor. var nodes = info.LoadedImageSurfaceNodes.ToArray(); foreach (var n in nodes) { builder.WriteLine($"{n.FieldName} = {_stringifier.CamelCase(n.Name)};"); } } else { builder.WriteLine("internal AnimatedVisual(Compositor compositor)"); builder.OpenScope(); builder.WriteLine("_c = compositor;"); builder.WriteLine($"{info.ReusableExpressionAnimationFieldName} = compositor.CreateExpressionAnimation();"); } builder.WriteLine("Root();"); builder.CloseScope(); builder.WriteLine(); // Write the IAnimatedVisual implementation. builder.WriteLine("Visual IAnimatedVisual.RootVisual => _root;"); builder.WriteLine($"TimeSpan IAnimatedVisual.Duration => TimeSpan.FromTicks({info.DurationTicksFieldName});"); builder.WriteLine($"Vector2 IAnimatedVisual.Size => {Vector2(info.CompositionDeclaredSize)};"); builder.WriteLine("void IDisposable.Dispose() => _root?.Dispose();"); // Close the scope for the instantiator class. builder.CloseScope(); // Close the scope for the class. builder.CloseScope(); // Close the scope for the namespace builder.CloseScope(); }
/// <inheritdoc/> // Called by the base class to write the start of the file (i.e. everything up to the body of the Instantiator class). protected override void WriteFileStart(CodeBuilder builder, CodeGenInfo info) { if (info.UsesCanvas) { builder.WriteLine("using Microsoft.Graphics.Canvas;"); } if (info.UsesCanvasEffects) { builder.WriteLine("using Microsoft.Graphics.Canvas.Effects;"); } if (info.UsesCanvasGeometry) { builder.WriteLine("using Microsoft.Graphics.Canvas.Geometry;"); } if (info.UsesNamespaceWindowsUIXamlMedia) { builder.WriteLine("using Windows.UI.Xaml.Media;"); } if (info.UsesStreams) { builder.WriteLine("using System.IO;"); builder.WriteLine("using System.Runtime.InteropServices.WindowsRuntime;"); } builder.WriteLine("using Microsoft.UI.Xaml.Controls;"); builder.WriteLine("using System;"); builder.WriteLine("using System.Numerics;"); builder.WriteLine("using Windows.UI;"); builder.WriteLine("using Windows.UI.Composition;"); builder.WriteLine(); builder.WriteLine("namespace AnimatedVisuals"); builder.OpenScope(); builder.WriteLine($"sealed class {info.ClassName} : IAnimatedVisualSource"); builder.OpenScope(); // 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("diagnostics = null;"); builder.WriteLine("if (!IsRuntimeCompatible())"); builder.OpenScope(); builder.WriteLine("return null;"); builder.CloseScope(); builder.WriteLine("return new AnimatedVisual(compositor);"); builder.CloseScope(); builder.WriteLine(); }
void WriteAnimatedVisualInvalidatedEvent(CodeBuilder builder) { builder.WriteLine("public event TypedEventHandler<IDynamicAnimatedVisualSource, object> AnimatedVisualInvalidated"); builder.OpenScope(); builder.WriteLine("add"); builder.OpenScope(); builder.WriteLine("return GetAnimatedVisualInvalidatedEventRegistrationTokenTable().AddEventHandler(value);"); builder.CloseScope(); builder.WriteLine("remove"); builder.OpenScope(); builder.WriteLine("GetAnimatedVisualInvalidatedEventRegistrationTokenTable().RemoveEventHandler(value);"); builder.CloseScope(); builder.CloseScope(); builder.WriteLine(); }
/// <inheritdoc/> // Called by the base class to write the end of the file (i.e. everything after the body of the Instantiator class). protected override void WriteFileEnd( CodeBuilder builder, CodeGenInfo info) { // Write the constructor for the instantiator. builder.WriteLine("internal AnimatedVisual(Compositor compositor)"); builder.OpenScope(); builder.WriteLine("_c = compositor;"); builder.WriteLine($"{info.ReusableExpressionAnimationFieldName} = compositor.CreateExpressionAnimation();"); builder.WriteLine("Root();"); builder.CloseScope(); builder.WriteLine(); // Write the IAnimatedVisual implementation. builder.WriteLine("Visual IAnimatedVisual.RootVisual => _root;"); builder.WriteLine($"TimeSpan IAnimatedVisual.Duration => TimeSpan.FromTicks({info.DurationTicksFieldName});"); builder.WriteLine($"Vector2 IAnimatedVisual.Size => {Vector2(info.CompositionDeclaredSize)};"); builder.WriteLine("void IDisposable.Dispose() => _root?.Dispose();"); // Close the scope for the instantiator class. builder.CloseScope(); // Close the scope for the class. builder.CloseScope(); // Close the scope for the namespace builder.CloseScope(); }
void WriteIsAnimatedVisualSourceDynamicGetSet(CodeBuilder builder, CodeGenInfo info) { builder.WriteLine($"bool AnimatedVisuals::{info.ClassName}::IsAnimatedVisualSourceDynamic::get()"); builder.OpenScope(); builder.WriteLine("return m_isAnimatedVisualSourceDynamic;"); builder.CloseScope(); builder.WriteLine(); builder.WriteLine($"void AnimatedVisuals::{info.ClassName}::IsAnimatedVisualSourceDynamic::set(bool isAnimatedVisualSourceDynamic)"); builder.OpenScope(); builder.WriteLine("if (!m_isTryCreateAnimatedVisualCalled && m_isAnimatedVisualSourceDynamic != isAnimatedVisualSourceDynamic)"); builder.OpenScope(); builder.WriteLine("m_isAnimatedVisualSourceDynamic = isAnimatedVisualSourceDynamic;"); builder.WriteLine("PropertyChanged(this, ref new PropertyChangedEventArgs(\"IsAnimatedVisualSourceDynamic\"));"); builder.CloseScope(); builder.CloseScope(); }
void WriteEnsureImageLoadingStarted(CodeBuilder builder, CodeGenInfo info) { builder.WriteLine($"void AnimatedVisuals::{info.ClassName}::EnsureImageLoadingStarted()"); builder.OpenScope(); builder.WriteLine("if (!m_isImageLoadingStarted)"); builder.OpenScope(); builder.WriteLine($"auto eventHandler = ref new TypedEventHandler<LoadedImageSurface^, LoadedImageSourceLoadCompletedEventArgs^>(this, &AnimatedVisuals::{info.ClassName}::HandleLoadCompleted);"); var nodes = info.LoadedImageSurfaceNodes.ToArray(); foreach (var n in nodes) { var imageMemberName = MakeFieldName(n.Name); switch (n.LoadedImageSurfaceType) { case LoadedImageSurface.LoadedImageSurfaceType.FromStream: var streamName = $"stream_{n.Name}"; var dataWriterName = $"dataWriter_{n.Name}"; builder.WriteLine($"auto {streamName} = ref new InMemoryRandomAccessStream();"); builder.WriteLine($"auto {dataWriterName} = ref new DataWriter({streamName}->GetOutputStreamAt(0));"); builder.WriteLine($"{dataWriterName}->WriteBytes({n.BytesFieldName});"); builder.WriteLine($"{dataWriterName}->StoreAsync();"); builder.WriteLine($"{dataWriterName}->FlushAsync();"); builder.WriteLine($"{streamName}->Seek(0);"); builder.WriteLine($"{imageMemberName} = Windows::UI::Xaml::Media::LoadedImageSurface::StartLoadFromStream({streamName});"); break; case LoadedImageSurface.LoadedImageSurfaceType.FromUri: builder.WriteLine($"{imageMemberName} = Windows::UI::Xaml::Media::LoadedImageSurface::StartLoadFromUri(ref new Uri(\"{n.ImageUri}\"));"); break; default: throw new InvalidOperationException(); } builder.WriteLine($"{imageMemberName}->LoadCompleted += eventHandler;"); } builder.WriteLine("m_isImageLoadingStarted = true;"); builder.CloseScope(); builder.CloseScope(); builder.WriteLine(); }
/// <summary> /// Write a class that implements the IAnimatedVisualSource interface. /// </summary> void WriteIAnimatedVisualSource(CodeBuilder builder, CodeGenInfo info) { builder.WriteLine("namespace AnimatedVisuals"); builder.OpenScope(); builder.WriteLine($"sealed class {info.ClassName} : IAnimatedVisualSource"); builder.OpenScope(); // 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("diagnostics = null;"); builder.WriteLine("if (!IsRuntimeCompatible())"); builder.OpenScope(); builder.WriteLine("return null;"); builder.CloseScope(); builder.WriteLine("return new AnimatedVisual(compositor);"); builder.CloseScope(); builder.WriteLine(); }
/// <inheritdoc/> protected override void WriteInstantiatorStart(CodeBuilder builder, CodeGenInfo info) { // Start writing the instantiator. builder.WriteLine("ref class AnimatedVisual sealed : public Microsoft::UI::Xaml::Controls::IAnimatedVisual"); builder.OpenScope(); if (info.UsesCanvasEffects || info.UsesCanvasGeometry) { // D2D factory field. builder.WriteLine("ComPtr<ID2D1Factory> _d2dFactory;"); } }
void WriteHandleLoadCompleted(CodeBuilder builder, CodeGenInfo info) { builder.WriteLine($"void AnimatedVisuals::{info.ClassName}::HandleLoadCompleted(LoadedImageSurface^ sender, LoadedImageSourceLoadCompletedEventArgs^ e)"); builder.OpenScope(); builder.WriteLine("m_loadCompleteEventCount++;"); builder.WriteLine("if (e->Status == LoadedImageSourceLoadStatus::Success)"); builder.OpenScope(); builder.WriteLine("if (m_isAnimatedVisualSourceDynamic && m_loadCompleteEventCount == c_loadedImageSurfaceCount)"); builder.OpenScope(); builder.WriteLine("RaiseAnimatedVisualInvalidatedEvent(this, nullptr);"); builder.CloseScope(); builder.WriteLine("m_imageSuccessfulLoadingProgress = (double)m_loadCompleteEventCount / c_loadedImageSurfaceCount;"); builder.WriteLine("PropertyChanged(this, ref new PropertyChangedEventArgs(\"ImageSuccessfulLoadingProgress\"));"); builder.CloseScope(); builder.WriteLine(); builder.WriteLine("if (m_loadCompleteEventCount == c_loadedImageSurfaceCount)"); builder.OpenScope(); builder.WriteLine("m_isImageLoadingCompleted = true;"); builder.WriteLine("PropertyChanged(this, ref new PropertyChangedEventArgs(\"IsImageLoadingCompleted\"));"); builder.CloseScope(); builder.CloseScope(); builder.WriteLine(); }
/// <inheritdoc/> protected override string WriteCompositeEffectFactory(CodeBuilder builder, Mgce.CompositeEffect compositeEffect) { builder.WriteLine("ComPtr<CompositeEffect> compositeEffect(new CompositeEffect());"); builder.WriteLine($"compositeEffect->SetMode({_stringifier.CanvasCompositeMode(compositeEffect.Mode)});"); foreach (var source in compositeEffect.Sources) { builder.OpenScope(); builder.WriteLine($"auto sourceParameter = ref new CompositionEffectSourceParameter({String(source.Name)});"); builder.WriteLine("compositeEffect->AddSource(reinterpret_cast<ABI::Windows::Graphics::Effects::IGraphicsEffectSource*>(sourceParameter));"); builder.CloseScope(); } return("reinterpret_cast<Windows::Graphics::Effects::IGraphicsEffect^>(compositeEffect.Get())"); }
/// <summary> /// Generate the body of the TryCreateAnimatedVisual() method for the composition that contains LoadedImageSurfaces. /// </summary> void WriteTryCreateInstantiatorWithImageLoading(CodeBuilder builder, CodeGenInfo info) { builder.WriteLine("m_isTryCreateAnimatedVisualCalled = true;"); builder.WriteLine(); builder.WriteLine("diagnostics = nullptr;"); builder.WriteLine("if (!IsRuntimeCompatible())"); builder.OpenScope(); builder.WriteLine("return nullptr;"); builder.CloseScope(); builder.WriteLine(); builder.WriteLine("EnsureImageLoadingStarted();"); builder.WriteLine(); builder.WriteLine("if (m_isAnimatedVisualSourceDynamic && m_loadCompleteEventCount != c_loadedImageSurfaceCount)"); builder.OpenScope(); builder.WriteLine("return nullptr;"); builder.CloseScope(); builder.WriteLine("return ref new AnimatedVisual(compositor,"); builder.Indent(); builder.WriteCommaSeparatedLines(info.LoadedImageSurfaceNodes.Select(n => MakeFieldName(n.Name))); builder.UnIndent(); builder.WriteLine(");"); builder.CloseScope(); builder.WriteLine(); }
/// <inheritdoc/> protected override void WriteAnimatedVisualStart( CodeBuilder builder, IAnimatedVisualInfo info) { // Start writing the instantiator. builder.WriteLine($"ref class {info.ClassName} sealed"); builder.Indent(); builder.WriteLine($": public {AnimatedVisualTypeName}"); builder.UnIndent(); builder.OpenScope(); if (info.AnimatedVisualSourceInfo.UsesCanvasEffects || info.AnimatedVisualSourceInfo.UsesCanvasGeometry) { // D2D factory field. builder.WriteLine("ComPtr<ID2D1Factory> _d2dFactory;"); } }
/// <inheritdoc/> protected override void WriteCanvasGeometryGroupFactory(CodeBuilder builder, CanvasGeometry.Group obj, string typeName, string fieldName) { builder.WriteLine($"ComPtr<ID2D1Geometry> geometries[{obj.Geometries.Length}];"); builder.OpenScope(); for (var i = 0; i < obj.Geometries.Length; i++) { var geometry = obj.Geometries[i]; builder.WriteLine($"{CallFactoryFor(geometry)}->GetGeometry(&geometries[{i}]);"); } builder.CloseScope(); builder.WriteLine($"{typeName} result;"); builder.WriteLine("ComPtr<ID2D1GeometryGroup> group;"); builder.WriteLine("FFHR(_d2dFactory->CreateGeometryGroup("); builder.Indent(); builder.WriteLine($"{FilledRegionDetermination(obj.FilledRegionDetermination)},"); builder.WriteLine("geometries[0].GetAddressOf(),"); builder.WriteLine($"{obj.Geometries.Length},"); builder.WriteLine("&group));"); builder.UnIndent(); builder.WriteLine($"result = {FieldAssignment(fieldName)}new GeoSource(group.Get());"); }
/// <inheritdoc/> protected override void WriteCanvasGeometryPathFactory(CodeBuilder builder, CanvasGeometry.Path obj, string typeName, string fieldName) { builder.WriteLine($"{typeName} result;"); builder.WriteLine($"using (var builder = new CanvasPathBuilder(null))"); builder.OpenScope(); if (obj.FilledRegionDetermination != CanvasFilledRegionDetermination.Alternate) { builder.WriteLine($"builder.SetFilledRegionDetermination({_stringifier.FilledRegionDetermination(obj.FilledRegionDetermination)});"); } foreach (var command in obj.Commands) { switch (command.Type) { case CanvasPathBuilder.CommandType.BeginFigure: builder.WriteLine($"builder.BeginFigure({Vector2(((CanvasPathBuilder.Command.BeginFigure)command).StartPoint)});"); break; case CanvasPathBuilder.CommandType.EndFigure: builder.WriteLine($"builder.EndFigure({_stringifier.CanvasFigureLoop(((CanvasPathBuilder.Command.EndFigure)command).FigureLoop)});"); break; case CanvasPathBuilder.CommandType.AddLine: builder.WriteLine($"builder.AddLine({Vector2(((CanvasPathBuilder.Command.AddLine)command).EndPoint)});"); break; case CanvasPathBuilder.CommandType.AddCubicBezier: var cb = (CanvasPathBuilder.Command.AddCubicBezier)command; builder.WriteLine($"builder.AddCubicBezier({Vector2(cb.ControlPoint1)}, {Vector2(cb.ControlPoint2)}, {Vector2(cb.EndPoint)});"); break; default: throw new InvalidOperationException(); } } builder.WriteLine($"result = {FieldAssignment(fieldName)}CanvasGeometry.CreatePath(builder);"); builder.CloseScope(); }
protected override void WriteThemePropertyImpls(CodeBuilder builder) { var propertyBindings = SourceInfo.SourceMetadata.PropertyBindings; var sourceClassQualifier = $"{S.Namespace(SourceInfo.Namespace)}::{SourceClassName}::"; if (propertyBindings.Any(pb => pb.ExposedType == PropertySetValueType.Color)) { // Write the helper for converting a color to a vector 4. builder.WriteLine($"float4 {sourceClassQualifier}ColorAsVector4(Color color)"); builder.OpenScope(); builder.WriteLine("return { static_cast<float>(color.R), static_cast<float>(color.G), static_cast<float>(color.B), static_cast<float>(color.A) };"); builder.CloseScope(); builder.WriteLine(); } builder.WriteLine($"{T.CompositionPropertySet} {sourceClassQualifier}EnsureThemeProperties({T.Compositor} compositor)"); builder.OpenScope(); builder.WriteLine($"if ({SourceInfo.ThemePropertiesFieldName} == nullptr)"); builder.OpenScope(); builder.WriteLine($"{SourceInfo.ThemePropertiesFieldName} = compositor{S.Deref}CreatePropertySet();"); // Initialize the values in the property set. foreach (var prop in propertyBindings) { WriteThemePropertyInitialization(builder, SourceInfo.ThemePropertiesFieldName, prop, prop.BindingName); } builder.CloseScope(); builder.WriteLine(); builder.WriteLine($"return {SourceInfo.ThemePropertiesFieldName};"); builder.CloseScope(); builder.WriteLine(); // The GetThemeProperties method is designed to allow setting of properties when the actual // type of the IAnimatedVisualSource is not known. It relies on a custom interface that declares // it, so if we're not generating code for a custom interface, there's no reason to generate // the method. if (IsInterfaceCustom) { builder.WriteLine($"{T.CompositionPropertySet} {sourceClassQualifier}GetThemeProperties({T.Compositor} compositor)"); builder.OpenScope(); builder.WriteLine("return EnsureThemeProperties(compositor);"); builder.CloseScope(); builder.WriteLine(); } // Write property implementations for each theme property. foreach (var prop in propertyBindings) { if (SourceInfo.GenerateDependencyObject) { // Write the dependency property accessor. builder.WriteLine($"DependencyProperty^ {sourceClassQualifier}{prop.BindingName}Property()"); builder.OpenScope(); builder.WriteLine($"return _{S.CamelCase(prop.BindingName)}Property;"); builder.CloseScope(); builder.WriteLine(); // Write the dependency property change handler. builder.WriteLine($"void {sourceClassQualifier}On{prop.BindingName}Changed(DependencyObject^ d, DependencyPropertyChangedEventArgs^ e)"); builder.OpenScope(); builder.WriteLine($"auto self = ({sourceClassQualifier}^)d;"); builder.WriteLine(); builder.WriteLine("if (self->_themeProperties != nullptr)"); builder.OpenScope(); WriteThemePropertyInitialization(builder, $"self->{SourceInfo.ThemePropertiesFieldName}", prop, "e->NewValue"); builder.CloseScope(); builder.CloseScope(); builder.WriteLine(); // Write the dependency property initializer. builder.WriteLine($"DependencyProperty^ {sourceClassQualifier}_{S.CamelCase(prop.BindingName)}Property ="); builder.Indent(); builder.WriteLine($"DependencyProperty::Register("); builder.Indent(); builder.WriteLine($"{S.String(prop.BindingName)},"); builder.WriteLine($"{TypeName(prop.ExposedType)}::typeid,"); builder.WriteLine($"{sourceClassQualifier}typeid,"); builder.WriteLine($"ref new PropertyMetadata(c_theme{prop.BindingName},"); builder.WriteLine($"ref new PropertyChangedCallback(&{sourceClassQualifier}On{prop.BindingName}Changed)));"); builder.UnIndent(); builder.UnIndent(); builder.WriteLine(); } // Write the getter. builder.WriteLine($"{TypeName(prop.ExposedType)} {sourceClassQualifier}{prop.BindingName}::get()"); builder.OpenScope(); if (SourceInfo.GenerateDependencyObject) { // Get the value from the dependency property. builder.WriteLine($"return ({TypeName(prop.ExposedType)})GetValue(_{S.CamelCase(prop.BindingName)}Property);"); } else { // Get the value from the backing field. builder.WriteLine($"return _theme{prop.BindingName};"); } builder.CloseScope(); builder.WriteLine(); // Write the setter. builder.WriteLine($"void {sourceClassQualifier}{prop.BindingName}::set({TypeName(prop.ExposedType)} value)"); builder.OpenScope(); if (SourceInfo.GenerateDependencyObject) { builder.WriteLine($"SetValue(_{S.CamelCase(prop.BindingName)}Property, value);"); } else { // This saves to the backing field, and updates the theme property // set if one has been created. builder.WriteLine($"_theme{prop.BindingName} = value;"); builder.WriteLine("if (_themeProperties != nullptr)"); builder.OpenScope(); WriteThemePropertyInitialization(builder, "_themeProperties", prop); builder.CloseScope(); } builder.CloseScope(); builder.WriteLine(); } }
protected override void WriteThemePropertyImpls(CodeBuilder builder) { var propertyBindings = SourceInfo.SourceMetadata.PropertyBindings; var sourceClassQualifier = $"{T.CompositionPropertySet} {S.Namespace(SourceInfo.Namespace)}::{SourceClassName}::"; if (propertyBindings.Any(pb => pb.ExposedType == PropertySetValueType.Color)) { // Write the helper for converting a color to a vector 4. builder.WriteLine($"float4 {sourceClassQualifier}ColorAsVector4(Color color)"); builder.OpenScope(); builder.WriteLine("return { static_cast<float>(color.R), static_cast<float>(color.G), static_cast<float>(color.B), static_cast<float>(color.A) };"); builder.CloseScope(); builder.WriteLine(); } builder.WriteLine($"{T.CompositionPropertySet} {sourceClassQualifier}EnsureThemeProperties({T.Compositor} compositor)"); builder.OpenScope(); builder.WriteLine($"if ({SourceInfo.ThemePropertiesFieldName} == nullptr)"); builder.OpenScope(); builder.WriteLine($"{SourceInfo.ThemePropertiesFieldName} = compositor{S.Deref}CreatePropertySet();"); // Initialize the values in the property set. foreach (var prop in propertyBindings) { WriteThemePropertyInitialization(builder, SourceInfo.ThemePropertiesFieldName, prop); } builder.CloseScope(); builder.WriteLine(); builder.WriteLine($"return {SourceInfo.ThemePropertiesFieldName};"); builder.CloseScope(); builder.WriteLine(); builder.WriteLine($"{T.CompositionPropertySet} {sourceClassQualifier}GetThemeProperties({T.Compositor} compositor)"); builder.OpenScope(); builder.WriteLine("return EnsureThemeProperties(compositor);"); builder.CloseScope(); builder.WriteLine(); // Write property implementations for each theme property. foreach (var prop in propertyBindings) { // Write the getter. This just reads the values out of the backing field. builder.WriteLine($"{TypeName(prop.ExposedType)} {sourceClassQualifier}{prop.BindingName}()"); builder.OpenScope(); builder.WriteLine($"return _theme{prop.BindingName};"); builder.CloseScope(); builder.WriteLine(); // Write the setter. This saves to the backing field, and updates the theme property // set if one has been created. builder.WriteLine($"void {sourceClassQualifier}{prop.BindingName}({TypeName(prop.ExposedType)} value)"); builder.OpenScope(); builder.WriteLine($"_theme{prop.BindingName} = value;"); builder.WriteLine("if (_themeProperties != nullptr)"); builder.OpenScope(); WriteThemePropertyInitialization(builder, "_themeProperties", prop); builder.CloseScope(); builder.CloseScope(); builder.WriteLine(); } }
/// <inheritdoc/> // Called by the base class to write the end of the file (i.e. everything after the body of the Instantiator class). protected override void WriteFileEnd( CodeBuilder builder, CodeGenInfo info) { if (info.UsesCanvasEffects || info.UsesCanvasGeometry) { // Utility method for D2D geometries builder.WriteLine("static IGeometrySource2D^ CanvasGeometryToIGeometrySource2D(CanvasGeometry geo)"); builder.OpenScope(); builder.WriteLine("ComPtr<ABI::Windows::Graphics::IGeometrySource2D> interop = geo.Detach();"); builder.WriteLine("return reinterpret_cast<IGeometrySource2D^>(interop.Get());"); builder.CloseScope(); builder.WriteLine(); // Utility method for fail-fasting on bad HRESULTs from d2d operations builder.WriteLine("static void FFHR(HRESULT hr)"); builder.OpenScope(); builder.WriteLine("if (hr != S_OK)"); builder.OpenScope(); builder.WriteLine("RoFailFastWithErrorContext(hr);"); builder.CloseScope(); builder.CloseScope(); builder.WriteLine(); } // Write the constructor for the instantiator. builder.UnIndent(); builder.WriteLine("public:"); builder.Indent(); builder.WriteLine("AnimatedVisual(Compositor^ compositor)"); // Initializer list. builder.Indent(); builder.WriteLine(": _c(compositor)"); // Instantiate the reusable ExpressionAnimation. builder.WriteLine($", {info.ReusableExpressionAnimationFieldName}(compositor->CreateExpressionAnimation())"); builder.UnIndent(); builder.OpenScope(); if (info.UsesCanvasEffects || info.UsesCanvasGeometry) { builder.WriteLine($"{FailFastWrapper("D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, _d2dFactory.GetAddressOf())")};"); } // Instantiate the root. This will cause the whole Visual tree to be built and animations started. builder.WriteLine("Root();"); builder.CloseScope(); // Write the destructor. This is how CX implements IClosable/IDisposable. builder.WriteLine("virtual ~AnimatedVisual() { }"); // Write the members on IAnimatedVisual. builder.WriteLine(); builder.WriteLine("property TimeSpan Duration"); builder.OpenScope(); builder.WriteLine("virtual TimeSpan get() { return { c_durationTicks }; }"); builder.CloseScope(); builder.WriteLine(); builder.WriteLine("property Visual^ RootVisual"); builder.OpenScope(); builder.WriteLine("virtual Visual^ get() { return _root; }"); builder.CloseScope(); builder.WriteLine(); builder.WriteLine("property float2 Size"); builder.OpenScope(); builder.WriteLine($"virtual float2 get() {{ return {Vector2(info.CompositionDeclaredSize)}; }}"); builder.CloseScope(); builder.WriteLine(); // Close the scope for the instantiator class. builder.UnIndent(); builder.WriteLine("};"); // Close the anonymous namespace. builder.WriteLine("} // end namespace"); builder.WriteLine(); // Generate the method that creates an instance of the composition. builder.WriteLine($"Microsoft::UI::Xaml::Controls::IAnimatedVisual^ AnimatedVisuals::{info.ClassName}::TryCreateAnimatedVisual("); builder.Indent(); builder.WriteLine("Compositor^ compositor,"); builder.WriteLine("Object^* diagnostics)"); builder.UnIndent(); builder.OpenScope(); builder.WriteLine("diagnostics = nullptr;"); builder.WriteLine("if (!IsRuntimeCompatible())"); builder.OpenScope(); builder.WriteLine("return nullptr;"); builder.CloseScope(); builder.WriteLine("return ref new AnimatedVisual(compositor);"); builder.CloseScope(); }
/// <inheritdoc/> protected override void WriteInstantiatorStart(CodeBuilder builder, CodeGenInfo info) { // Start the instantiator class. builder.WriteLine("sealed class AnimatedVisual : IAnimatedVisual"); builder.OpenScope(); }
/// <inheritdoc/> // Called by the base class to write the start of the file (i.e. everything up to the body of the Instantiator class). protected override void WriteFileStart(CodeBuilder builder) { // A sorted set to hold the namespaces that the generated code will use. The set is maintained in sorted order. var namespaces = new SortedSet <string>(); if (Info.UsesCanvas) { namespaces.Add("Microsoft.Graphics.Canvas"); } if (Info.UsesCanvasEffects) { namespaces.Add("Microsoft.Graphics.Canvas.Effects"); } if (Info.UsesCanvasGeometry) { // Windows.Graphics is needed for IGeometrySource2D. namespaces.Add("Windows.Graphics"); namespaces.Add("Microsoft.Graphics.Canvas.Geometry"); } if (Info.UsesNamespaceWindowsUIXamlMedia) { namespaces.Add("System.ComponentModel"); namespaces.Add("System.Runtime.InteropServices.WindowsRuntime"); namespaces.Add("Windows.Foundation"); namespaces.Add($"{_winUiNamespace}.Xaml.Media"); } if (Info.GenerateDependencyObject) { namespaces.Add($"{_winUiNamespace}.Xaml"); } if (Info.UsesStreams) { namespaces.Add("System.IO"); } namespaces.Add("System"); namespaces.Add("System.Numerics"); // Windows.UI is needed for Color. namespaces.Add("Windows.UI"); namespaces.Add($"{_winUiNamespace}.Composition"); // Write out each namespace using. foreach (var n in namespaces) { builder.WriteLine($"using {n};"); } builder.WriteLine(); builder.WriteLine($"namespace {Info.Namespace}"); builder.OpenScope(); // Write a description of the source as comments. builder.WritePreformattedCommentLines(GetSourceDescriptionLines()); // If the composition has LoadedImageSurface, write a class that implements the IDynamicAnimatedVisualSource interface. // Otherwise, implement the IAnimatedVisualSource interface. if (Info.LoadedImageSurfaces.Count > 0) { WriteIDynamicAnimatedVisualSource(builder); } else { WriteIAnimatedVisualSource(builder); } builder.CloseScope(); builder.WriteLine(); }
/// <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(); }