committed by
GitHub
22 changed files with 650 additions and 379 deletions
@ -0,0 +1,251 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
using Android.Views; |
||||
|
|
||||
|
using Avalonia.Android.Platform.SkiaPlatform; |
||||
|
using Avalonia.Collections.Pooled; |
||||
|
using Avalonia.Input; |
||||
|
using Avalonia.Input.Raw; |
||||
|
|
||||
|
#nullable enable |
||||
|
|
||||
|
namespace Avalonia.Android.Platform.Specific.Helpers |
||||
|
{ |
||||
|
internal class AndroidMotionEventsHelper : IDisposable |
||||
|
{ |
||||
|
private static readonly PooledList<RawPointerPoint> s_intermediatePointsPooledList = new(ClearMode.Never); |
||||
|
private static readonly float s_radiansToDegree = (float)(180f * Math.PI); |
||||
|
private readonly TouchDevice _touchDevice; |
||||
|
private readonly MouseDevice _mouseDevice; |
||||
|
private readonly PenDevice _penDevice; |
||||
|
private readonly TopLevelImpl _view; |
||||
|
private bool _disposed; |
||||
|
|
||||
|
public AndroidMotionEventsHelper(TopLevelImpl view) |
||||
|
{ |
||||
|
_touchDevice = new TouchDevice(); |
||||
|
_penDevice = new PenDevice(); |
||||
|
_mouseDevice = new MouseDevice(); |
||||
|
_view = view; |
||||
|
} |
||||
|
|
||||
|
public bool? DispatchMotionEvent(MotionEvent e, out bool callBase) |
||||
|
{ |
||||
|
callBase = true; |
||||
|
if (_disposed) |
||||
|
{ |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
var eventTime = (ulong)DateTime.Now.Millisecond; |
||||
|
var inputRoot = _view.InputRoot; |
||||
|
var actionMasked = e.ActionMasked; |
||||
|
var modifiers = GetModifiers(e.MetaState, e.ButtonState); |
||||
|
|
||||
|
if (actionMasked == MotionEventActions.Move) |
||||
|
{ |
||||
|
for (int index = 0; index < e.PointerCount; index++) |
||||
|
{ |
||||
|
var toolType = e.GetToolType(index); |
||||
|
var device = GetDevice(toolType); |
||||
|
var eventType = toolType == MotionEventToolType.Finger ? RawPointerEventType.TouchUpdate : RawPointerEventType.Move; |
||||
|
var point = CreatePoint(e, index); |
||||
|
modifiers |= GetToolModifiers(toolType); |
||||
|
|
||||
|
// ButtonState reports only mouse buttons, but not touch or stylus pointer.
|
||||
|
if (toolType != MotionEventToolType.Mouse) |
||||
|
{ |
||||
|
modifiers |= RawInputModifiers.LeftMouseButton; |
||||
|
} |
||||
|
|
||||
|
var args = new RawTouchEventArgs(device, eventTime, inputRoot, eventType, point, modifiers, e.GetPointerId(index)) |
||||
|
{ |
||||
|
IntermediatePoints = new Lazy<IReadOnlyList<RawPointerPoint>?>(() => |
||||
|
{ |
||||
|
var site = e.HistorySize; |
||||
|
s_intermediatePointsPooledList.Clear(); |
||||
|
s_intermediatePointsPooledList.Capacity = site; |
||||
|
|
||||
|
for (int pos = 0; pos < site; pos++) |
||||
|
{ |
||||
|
s_intermediatePointsPooledList.Add(CreateHistoricalPoint(e, index, pos)); |
||||
|
} |
||||
|
|
||||
|
return s_intermediatePointsPooledList; |
||||
|
}) |
||||
|
}; |
||||
|
_view.Input(args); |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
var index = e.ActionIndex; |
||||
|
var toolType = e.GetToolType(index); |
||||
|
var device = GetDevice(toolType); |
||||
|
modifiers |= GetToolModifiers(toolType); |
||||
|
var point = CreatePoint(e, index); |
||||
|
|
||||
|
if (actionMasked == MotionEventActions.Scroll && toolType == MotionEventToolType.Mouse) |
||||
|
{ |
||||
|
var delta = new Vector(e.GetAxisValue(Axis.Hscroll), e.GetAxisValue(Axis.Vscroll)); |
||||
|
var args = new RawMouseWheelEventArgs(device, eventTime, inputRoot, point.Position, delta, RawInputModifiers.None); |
||||
|
_view.Input(args); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
var eventType = GetActionType(e, actionMasked, toolType); |
||||
|
if (eventType >= 0) |
||||
|
{ |
||||
|
var args = new RawTouchEventArgs(device, eventTime, inputRoot, eventType, point, modifiers, e.GetPointerId(index)); |
||||
|
_view.Input(args); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
private static RawInputModifiers GetModifiers(MetaKeyStates metaState, MotionEventButtonState buttonState) |
||||
|
{ |
||||
|
var modifiers = RawInputModifiers.None; |
||||
|
if (metaState.HasAnyFlag(MetaKeyStates.ShiftOn)) |
||||
|
{ |
||||
|
modifiers |= RawInputModifiers.Shift; |
||||
|
} |
||||
|
if (metaState.HasAnyFlag(MetaKeyStates.CtrlOn)) |
||||
|
{ |
||||
|
modifiers |= RawInputModifiers.Control; |
||||
|
} |
||||
|
if (metaState.HasAnyFlag(MetaKeyStates.AltOn)) |
||||
|
{ |
||||
|
modifiers |= RawInputModifiers.Alt; |
||||
|
} |
||||
|
if (metaState.HasAnyFlag(MetaKeyStates.MetaOn)) |
||||
|
{ |
||||
|
modifiers |= RawInputModifiers.Meta; |
||||
|
} |
||||
|
if (buttonState.HasAnyFlag(MotionEventButtonState.Primary)) |
||||
|
{ |
||||
|
modifiers |= RawInputModifiers.LeftMouseButton; |
||||
|
} |
||||
|
if (buttonState.HasAnyFlag(MotionEventButtonState.Secondary)) |
||||
|
{ |
||||
|
modifiers |= RawInputModifiers.RightMouseButton; |
||||
|
} |
||||
|
if (buttonState.HasAnyFlag(MotionEventButtonState.Tertiary)) |
||||
|
{ |
||||
|
modifiers |= RawInputModifiers.MiddleMouseButton; |
||||
|
} |
||||
|
if (buttonState.HasAnyFlag(MotionEventButtonState.Back)) |
||||
|
{ |
||||
|
modifiers |= RawInputModifiers.XButton1MouseButton; |
||||
|
} |
||||
|
if (buttonState.HasAnyFlag(MotionEventButtonState.Forward)) |
||||
|
{ |
||||
|
modifiers |= RawInputModifiers.XButton2MouseButton; |
||||
|
} |
||||
|
if (buttonState.HasAnyFlag(MotionEventButtonState.StylusPrimary)) |
||||
|
{ |
||||
|
modifiers |= RawInputModifiers.PenBarrelButton; |
||||
|
} |
||||
|
return modifiers; |
||||
|
} |
||||
|
|
||||
|
#pragma warning disable CA1416 // Validate platform compatibility
|
||||
|
private static RawPointerEventType GetActionType(MotionEvent e, MotionEventActions actionMasked, MotionEventToolType toolType) |
||||
|
{ |
||||
|
var isTouch = toolType == MotionEventToolType.Finger; |
||||
|
var isMouse = toolType == MotionEventToolType.Mouse; |
||||
|
switch (actionMasked) |
||||
|
{ |
||||
|
// DOWN
|
||||
|
case MotionEventActions.Down when !isMouse: |
||||
|
case MotionEventActions.PointerDown when !isMouse: |
||||
|
return isTouch ? RawPointerEventType.TouchBegin : RawPointerEventType.LeftButtonDown; |
||||
|
case MotionEventActions.ButtonPress: |
||||
|
return e.ActionButton switch |
||||
|
{ |
||||
|
MotionEventButtonState.Back => RawPointerEventType.XButton1Down, |
||||
|
MotionEventButtonState.Forward => RawPointerEventType.XButton2Down, |
||||
|
MotionEventButtonState.Primary => RawPointerEventType.LeftButtonDown, |
||||
|
MotionEventButtonState.Secondary => RawPointerEventType.RightButtonDown, |
||||
|
MotionEventButtonState.StylusPrimary => RawPointerEventType.LeftButtonDown, |
||||
|
MotionEventButtonState.StylusSecondary => RawPointerEventType.RightButtonDown, |
||||
|
MotionEventButtonState.Tertiary => RawPointerEventType.MiddleButtonDown, |
||||
|
_ => RawPointerEventType.LeftButtonDown |
||||
|
}; |
||||
|
// UP
|
||||
|
case MotionEventActions.Up when !isMouse: |
||||
|
case MotionEventActions.PointerUp when !isMouse: |
||||
|
return isTouch ? RawPointerEventType.TouchEnd : RawPointerEventType.LeftButtonUp; |
||||
|
case MotionEventActions.ButtonRelease: |
||||
|
return e.ActionButton switch |
||||
|
{ |
||||
|
MotionEventButtonState.Back => RawPointerEventType.XButton1Up, |
||||
|
MotionEventButtonState.Forward => RawPointerEventType.XButton2Up, |
||||
|
MotionEventButtonState.Primary => RawPointerEventType.LeftButtonUp, |
||||
|
MotionEventButtonState.Secondary => RawPointerEventType.RightButtonUp, |
||||
|
MotionEventButtonState.StylusPrimary => RawPointerEventType.LeftButtonUp, |
||||
|
MotionEventButtonState.StylusSecondary => RawPointerEventType.RightButtonUp, |
||||
|
MotionEventButtonState.Tertiary => RawPointerEventType.MiddleButtonUp, |
||||
|
_ => RawPointerEventType.LeftButtonUp |
||||
|
}; |
||||
|
// MOVE
|
||||
|
case MotionEventActions.Outside: |
||||
|
case MotionEventActions.HoverMove: |
||||
|
case MotionEventActions.Move: |
||||
|
return isTouch ? RawPointerEventType.TouchUpdate : RawPointerEventType.Move; |
||||
|
// CANCEL
|
||||
|
case MotionEventActions.Cancel: |
||||
|
return isTouch ? RawPointerEventType.TouchCancel : RawPointerEventType.LeaveWindow; |
||||
|
default: |
||||
|
return (RawPointerEventType)(-1); |
||||
|
} |
||||
|
} |
||||
|
#pragma warning restore CA1416 // Validate platform compatibility
|
||||
|
|
||||
|
private IPointerDevice GetDevice(MotionEventToolType type) |
||||
|
{ |
||||
|
return type switch |
||||
|
{ |
||||
|
MotionEventToolType.Mouse => _mouseDevice, |
||||
|
MotionEventToolType.Stylus => _penDevice, |
||||
|
MotionEventToolType.Eraser => _penDevice, |
||||
|
MotionEventToolType.Finger => _touchDevice, |
||||
|
_ => _touchDevice |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
private RawPointerPoint CreatePoint(MotionEvent e, int index) |
||||
|
{ |
||||
|
return new RawPointerPoint |
||||
|
{ |
||||
|
Position = new Point(e.GetX(index), e.GetY(index)) / _view.RenderScaling, |
||||
|
Pressure = Math.Min(e.GetPressure(index), 1), // android pressure can depend on the device, can be mixed up with "GetSize", may be larger than 1.0f on some devices
|
||||
|
Twist = e.GetOrientation(index) * s_radiansToDegree |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
private RawPointerPoint CreateHistoricalPoint(MotionEvent e, int index, int pos) |
||||
|
{ |
||||
|
return new RawPointerPoint |
||||
|
{ |
||||
|
Position = new Point(e.GetHistoricalX(index, pos), e.GetHistoricalY(index, pos)) / _view.RenderScaling, |
||||
|
Pressure = Math.Min(e.GetHistoricalPressure(index, pos), 1), |
||||
|
Twist = e.GetHistoricalOrientation(index, pos) * s_radiansToDegree |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
private static RawInputModifiers GetToolModifiers(MotionEventToolType toolType) |
||||
|
{ |
||||
|
// Android "Eraser" indicates Inverted pen OR actual Eraser. So we have to go both here.
|
||||
|
return toolType == MotionEventToolType.Eraser ? RawInputModifiers.PenInverted | RawInputModifiers.PenEraser : RawInputModifiers.None; |
||||
|
} |
||||
|
|
||||
|
public void Dispose() |
||||
|
{ |
||||
|
_disposed = true; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,85 +0,0 @@ |
|||||
using System; |
|
||||
using Android.Views; |
|
||||
using Avalonia.Input; |
|
||||
using Avalonia.Input.Raw; |
|
||||
using Avalonia.Platform; |
|
||||
|
|
||||
namespace Avalonia.Android.Platform.Specific.Helpers |
|
||||
{ |
|
||||
public class AndroidTouchEventsHelper<TView> : IDisposable where TView : ITopLevelImpl, IAndroidView |
|
||||
{ |
|
||||
private TView _view; |
|
||||
public bool HandleEvents { get; set; } |
|
||||
|
|
||||
public AndroidTouchEventsHelper(TView view, Func<IInputRoot> getInputRoot, Func<MotionEvent, int, Point> getPointfunc) |
|
||||
{ |
|
||||
this._view = view; |
|
||||
HandleEvents = true; |
|
||||
_getPointFunc = getPointfunc; |
|
||||
_getInputRoot = getInputRoot; |
|
||||
} |
|
||||
|
|
||||
private TouchDevice _touchDevice = new TouchDevice(); |
|
||||
private Func<MotionEvent, int, Point> _getPointFunc; |
|
||||
private Func<IInputRoot> _getInputRoot; |
|
||||
|
|
||||
public bool? DispatchTouchEvent(MotionEvent e, out bool callBase) |
|
||||
{ |
|
||||
if (!HandleEvents) |
|
||||
{ |
|
||||
callBase = true; |
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
var eventTime = DateTime.Now; |
|
||||
|
|
||||
//Basic touch support
|
|
||||
var pointerEventType = e.Action switch |
|
||||
{ |
|
||||
MotionEventActions.Down => RawPointerEventType.TouchBegin, |
|
||||
MotionEventActions.Up => RawPointerEventType.TouchEnd, |
|
||||
MotionEventActions.Cancel => RawPointerEventType.TouchCancel, |
|
||||
_ => RawPointerEventType.TouchUpdate |
|
||||
}; |
|
||||
|
|
||||
if (e.Action.HasFlag(MotionEventActions.PointerDown)) |
|
||||
{ |
|
||||
pointerEventType = RawPointerEventType.TouchBegin; |
|
||||
} |
|
||||
|
|
||||
if (e.Action.HasFlag(MotionEventActions.PointerUp)) |
|
||||
{ |
|
||||
pointerEventType = RawPointerEventType.TouchEnd; |
|
||||
} |
|
||||
|
|
||||
for (int i = 0; i < e.PointerCount; i++) |
|
||||
{ |
|
||||
//if point is in view otherwise it's possible avalonia not to find the proper window to dispatch the event
|
|
||||
var point = _getPointFunc(e, i); |
|
||||
|
|
||||
double x = _view.View.GetX(); |
|
||||
double y = _view.View.GetY(); |
|
||||
double r = x + _view.View.Width; |
|
||||
double b = y + _view.View.Height; |
|
||||
|
|
||||
if (x <= point.X && r >= point.X && y <= point.Y && b >= point.Y) |
|
||||
{ |
|
||||
var inputRoot = _getInputRoot(); |
|
||||
|
|
||||
var mouseEvent = new RawTouchEventArgs(_touchDevice, (uint)eventTime.Ticks, inputRoot, |
|
||||
i == e.ActionIndex ? pointerEventType : RawPointerEventType.TouchUpdate, point, RawInputModifiers.None, e.GetPointerId(i)); |
|
||||
_view.Input(mouseEvent); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
callBase = true; |
|
||||
//if return false events for move and up are not received!!!
|
|
||||
return e.Action != MotionEventActions.Up; |
|
||||
} |
|
||||
|
|
||||
public void Dispose() |
|
||||
{ |
|
||||
HandleEvents = false; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,94 @@ |
|||||
|
using System.IO; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using Generator; |
||||
|
using Microsoft.CodeAnalysis; |
||||
|
using Microsoft.CodeAnalysis.CSharp; |
||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax; |
||||
|
|
||||
|
namespace DevGenerators; |
||||
|
|
||||
|
[Generator(LanguageNames.CSharp)] |
||||
|
public class EnumMemberDictionaryGenerator : IIncrementalGenerator |
||||
|
{ |
||||
|
const string DictionaryAttributeFullName = "global::Avalonia.SourceGenerator.GenerateEnumValueDictionaryAttribute"; |
||||
|
const string ListAttributeFullName = "global::Avalonia.SourceGenerator.GenerateEnumValueListAttribute"; |
||||
|
|
||||
|
public void Initialize(IncrementalGeneratorInitializationContext context) |
||||
|
{ |
||||
|
var allMethodsWithAttributes = context.SyntaxProvider |
||||
|
.CreateSyntaxProvider( |
||||
|
static (s, _) => s is MethodDeclarationSyntax |
||||
|
{ |
||||
|
AttributeLists.Count: > 0, |
||||
|
} md && md.Modifiers.Any(m=>m.IsKind(SyntaxKind.PartialKeyword)), |
||||
|
static (context, _) => |
||||
|
(IMethodSymbol)context.SemanticModel.GetDeclaredSymbol(context.Node)!); |
||||
|
|
||||
|
var all = allMethodsWithAttributes |
||||
|
.Where(s => |
||||
|
s.HasAttributeWithFullyQualifiedName(DictionaryAttributeFullName) |
||||
|
|| s.HasAttributeWithFullyQualifiedName(ListAttributeFullName) |
||||
|
).Collect(); |
||||
|
context.RegisterSourceOutput(all, static (context, methods) => |
||||
|
{ |
||||
|
foreach (var typeGroup in methods.GroupBy(f => f.ContainingType)) |
||||
|
{ |
||||
|
var classBuilder = new StringBuilder(); |
||||
|
if (typeGroup.Key.ContainingNamespace != null) |
||||
|
classBuilder |
||||
|
.AppendLine("using System;") |
||||
|
.Append("namespace ") |
||||
|
.Append(typeGroup.Key.ContainingNamespace) |
||||
|
.AppendLine(";"); |
||||
|
classBuilder |
||||
|
.Append("partial class ") |
||||
|
.AppendLine(typeGroup.Key.Name) |
||||
|
.AppendLine("{"); |
||||
|
|
||||
|
foreach (var method in typeGroup) |
||||
|
{ |
||||
|
var namedReturn = method.ReturnType as INamedTypeSymbol; |
||||
|
var arrayReturn = method.ReturnType as IArrayTypeSymbol; |
||||
|
|
||||
|
if ((namedReturn != null && namedReturn.Arity > 0) || arrayReturn != null) |
||||
|
{ |
||||
|
ITypeSymbol enumType = namedReturn != null |
||||
|
? namedReturn.TypeArguments.Last() |
||||
|
: arrayReturn!.ElementType; |
||||
|
|
||||
|
var isDic = method.HasAttributeWithFullyQualifiedName(DictionaryAttributeFullName); |
||||
|
|
||||
|
classBuilder |
||||
|
.Pad(1) |
||||
|
.Append("private static partial " + method.ReturnType + " " + method.Name + "()") |
||||
|
.AppendLine().Pad(4).Append(" => new ").Append(method.ReturnType).AppendLine("{"); |
||||
|
foreach (var member in enumType.GetMembers()) |
||||
|
{ |
||||
|
if (member.Name == ".ctor") |
||||
|
continue; |
||||
|
|
||||
|
if (isDic) |
||||
|
classBuilder.Pad(2) |
||||
|
.Append("{\"") |
||||
|
.Append(member.Name) |
||||
|
.Append("\", ") |
||||
|
.Append(member.ToString()) |
||||
|
.AppendLine("},"); |
||||
|
else |
||||
|
classBuilder.Pad(2).Append(member.ToString()).AppendLine(","); |
||||
|
} |
||||
|
|
||||
|
classBuilder.Pad(1).AppendLine("};"); |
||||
|
} |
||||
|
} |
||||
|
classBuilder.AppendLine("}"); |
||||
|
|
||||
|
context.AddSource(typeGroup.Key.GetFullyQualifiedName().Replace(":", ""), classBuilder.ToString()); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,73 @@ |
|||||
|
using System.IO; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using Generator; |
||||
|
using Microsoft.CodeAnalysis; |
||||
|
using Microsoft.CodeAnalysis.CSharp; |
||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax; |
||||
|
|
||||
|
namespace DevGenerators; |
||||
|
|
||||
|
[Generator(LanguageNames.CSharp)] |
||||
|
public class X11AtomsGenerator : IIncrementalGenerator |
||||
|
{ |
||||
|
public void Initialize(IncrementalGeneratorInitializationContext context) |
||||
|
{ |
||||
|
var x11AtomsClasses = context.SyntaxProvider |
||||
|
.CreateSyntaxProvider( |
||||
|
static (s, _) => s is ClassDeclarationSyntax |
||||
|
{ |
||||
|
Identifier.Text: "X11Atoms" |
||||
|
}, |
||||
|
static (context, _) => |
||||
|
(INamedTypeSymbol)context.SemanticModel.GetDeclaredSymbol(context.Node)!); |
||||
|
|
||||
|
var all = x11AtomsClasses.Collect(); |
||||
|
context.RegisterSourceOutput(all, static (context, classes) => |
||||
|
{ |
||||
|
foreach (var cl in classes) |
||||
|
{ |
||||
|
var classBuilder = new StringBuilder(); |
||||
|
if (cl.ContainingNamespace != null) |
||||
|
classBuilder |
||||
|
.AppendLine("using System;") |
||||
|
.AppendLine("using static Avalonia.X11.XLib;") |
||||
|
.Append("namespace ") |
||||
|
.Append(cl.ContainingNamespace) |
||||
|
.AppendLine(";"); |
||||
|
classBuilder |
||||
|
.Append("partial class ") |
||||
|
.AppendLine(cl.Name) |
||||
|
.AppendLine("{"); |
||||
|
|
||||
|
var fields = cl.GetMembers().OfType<IFieldSymbol>() |
||||
|
.Where(f => f.Type.Name == "IntPtr" |
||||
|
&& f.DeclaredAccessibility == Accessibility.Public).ToList(); |
||||
|
|
||||
|
classBuilder.Pad(1).AppendLine("private void PopulateAtoms(IntPtr display)").Pad(1).AppendLine("{"); |
||||
|
classBuilder.Pad(2).Append("var atoms = new IntPtr[").Append(fields.Count).AppendLine("];"); |
||||
|
classBuilder.Pad(2).Append("var atomNames = new string[").Append(fields.Count).AppendLine("] {"); |
||||
|
|
||||
|
|
||||
|
for (int c = 0; c < fields.Count; c++) |
||||
|
classBuilder.Pad(3).Append("\"").Append(fields[c].Name).AppendLine("\","); |
||||
|
classBuilder.Pad(2).AppendLine("};"); |
||||
|
|
||||
|
classBuilder.Pad(2).AppendLine("XInternAtoms(display, atomNames, atomNames.Length, true, atoms);"); |
||||
|
|
||||
|
for (int c = 0; c < fields.Count; c++) |
||||
|
classBuilder.Pad(2).Append("InitAtom(ref ").Append(fields[c].Name).Append(", \"") |
||||
|
.Append(fields[c].Name).Append("\", atoms[").Append(c).AppendLine("]);"); |
||||
|
|
||||
|
|
||||
|
classBuilder.Pad(1).AppendLine("}"); |
||||
|
classBuilder.AppendLine("}"); |
||||
|
|
||||
|
context.AddSource(cl.GetFullyQualifiedName().Replace(":", ""), classBuilder.ToString()); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
||||
Loading…
Reference in new issue