### Basic Setup with DrawnUI in C# and XAML
Source: https://github.com/taublast/drawnui/blob/main/aidocs/00-master-index.md
Demonstrates the basic setup for DrawnUI by configuring the MauiProgram and initializing the Canvas control in XAML. This pattern is essential for getting started with DrawnUI applications.
```csharp
// MauiProgram.cs
builder.UseDrawnUi(new() { MobileIsFullscreen = true });
```
```xml
```
--------------------------------
### Advanced Fluent API Patterns for SkiaButton
Source: https://github.com/taublast/drawnui/blob/main/aidocs/03-skiabutton-interactive-controls.md
Demonstrates advanced fluent API patterns for configuring SkiaButton, including event handling, styling, and layout integration. This example shows how to chain methods for a more readable and concise button setup.
```csharp
```csharp
// Real-world example from AppoMobi.Mobile project
SkiaButton actionButton;
var layout = new SkiaLayout()
{
Type = LayoutType.Column,
Spacing = 16,
Children = new List
{
new SkiaButton("Save Changes")
{
BackgroundColor = Colors.Blue,
TextColor = Colors.White,
CornerRadius = 8
}
.Assign(out actionButton)
.OnTapped(async btn =>
{
btn.IsEnabled = false;
btn.Text = "Saving...";
try
{
await SaveChangesAsync();
btn.Text = "Saved!";
await Task.Delay(1000);
btn.Text = "Save Changes";
}
finally
{
btn.IsEnabled = true;
}
})
.WithCache(SkiaCacheType.Operations)
.Height(44)
.CenterX(),
new SkiaButton("Cancel")
.OnTapped(btn => Navigation.PopAsync())
.Adapt(btn =>
{
if (HasUnsavedChanges)
{
btn.BackgroundColor = Colors.Orange;
btn.Text = "Discard Changes";
}
})
}
}
.Initialize(layout =>
{
// Access assigned variables after construction
actionButton.CommandTapped = new Command(() =>
{
// Alternative command binding
});
});
```
```
--------------------------------
### Fluent Method Examples (C#)
Source: https://github.com/taublast/drawnui/blob/main/docs/articles/first-app-code.md
This section provides examples of key fluent methods used in the project, including `.Assign()`, `.OnTapped()`, and `.ObserveProperties()`. It also shows how to use constructor parameters for setting text content, promoting cleaner and more readable code.
```csharp
new SkiaButton("Click Me!").Assign(out btnClickMe)
```
```csharp
button.OnTapped(async me => {
// Handle tap with direct access to the control
})
```
```csharp
label.ObserveProperties(() => btnClickMe,
[nameof(SkiaButton.Text)],
me => { /* Update logic */ })
```
```csharp
new SkiaLabel("Text content") // Direct text in constructor
new SkiaButton("Button text") // Cleaner than setting Text property
```
--------------------------------
### AI Agent Quick Start with SkiaCamera
Source: https://github.com/taublast/drawnui/blob/main/src/Maui/Addons/DrawnUi.Maui.Camera/README.md
Provides a quick start guide for AI agents integrating with SkiaCamera, demonstrating setup, dual-channel processing, and manual camera selection.
```csharp
// 1. Setup dual-channel camera
var camera = new SkiaCamera
{
Facing = CameraPosition.Default,
PhotoQuality = CaptureQuality.Medium,
IsOn = true
};
// 2. CHANNEL 1: Live preview processing for AI/ML
camera.NewPreviewSet += (s, source) => {
// Real-time AI processing on preview frames
Task.Run(() => ProcessFrameForAI(source.Image));
};
// 3. CHANNEL 2: Captured photo processing
camera.CaptureSuccess += (s, captured) => {
// High-quality processing on captured photo
ProcessCapturedPhoto(captured.Image, captured.Metadata);
};
// 4. Manual camera selection
var cameras = await camera.GetAvailableCamerasAsync();
camera.Facing = CameraPosition.Manual;
camera.CameraIndex = 2; // Select third camera
// 5. Take photo (triggers Channel 2 processing)
await camera.TakePicture();
```
--------------------------------
### Use DrawnUiBasePage for Keyboard Support (XAML)
Source: https://github.com/taublast/drawnui/blob/main/docs/_site/articles/getting-started.html
This XAML example shows how to use DrawnUiBasePage, which provides built-in keyboard support, for integrating the DrawnUi Canvas. It configures rendering mode and gesture handling.
```xml
```
--------------------------------
### Initialization and Observation Methods
Source: https://github.com/taublast/drawnui/blob/main/docs/_site/api/DrawnUi.Draw.LottieRefreshIndicator.html
Methods for initializing UI elements and observing property changes.
```APIDOC
## Initialize
### Description
Initializes a UI element with a configuration action.
### Method
`Initialize(T element, Action configure)`
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
None
### Request Example
None
### Response
#### Success Response (200)
Returns the initialized element.
#### Response Example
None
## ObserveBindingContextOn
### Description
Observes changes to the binding context of a target element, triggering an action with source and property name.
### Method
`ObserveBindingContextOn(T element, TTarget target, Action action, bool observeChild }}=
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
None
### Request Example
None
### Response
#### Success Response (200)
Returns the element with binding context observation set up.
#### Response Example
None
## ObserveBindingContext
### Description
Observes changes to the binding context of a target element, triggering an action with source and property name.
### Method
`ObserveBindingContext(T element, Action action, bool observeChild }}=
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
None
### Request Example
None
### Response
#### Success Response (200)
Returns the element with binding context observation set up.
#### Response Example
None
## ObserveOn
### Description
Observes a specific property on a parent element and triggers an action when it changes, optionally observing child properties.
### Method
`ObserveOn(T element, TParent parent, Func targetProperty, string targetPropertyName, Action action, string[] childPropertyNames)`
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
None
### Request Example
None
### Response
#### Success Response (200)
Returns the element with the specified property observation set up.
#### Response Example
None
## ObservePropertiesOn
### Description
Observes multiple properties on a parent element and triggers an action when any of them change.
### Method
`ObservePropertiesOn(T element, TParent parent, Func targetProperty, string targetPropertyName, IEnumerable propertyNames, Action action)`
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
None
### Request Example
None
### Response
#### Success Response (200)
Returns the element with multiple property observations set up.
#### Response Example
None
## ObserveProperties
### Description
Observes multiple properties on a source object and triggers an action when any of them change.
### Method
`ObserveProperties(T element, Func sourceProperty, IEnumerable propertyNames, Action action)`
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
None
### Request Example
None
### Response
#### Success Response (200)
Returns the element with multiple property observations set up.
#### Response Example
None
## ObserveProperties (Source Object)
### Description
Observes multiple properties on a source object and triggers an action when any of them change.
### Method
`ObserveProperties(T element, TSource source, IEnumerable propertyNames, Action action)`
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
None
### Request Example
None
### Response
#### Success Response (200)
Returns the element with multiple property observations set up.
#### Response Example
None
## ObservePropertyOn
### Description
Observes a specific property on a parent element and triggers an action when it changes.
### Method
`ObservePropertyOn(T element, TParent parent, Func targetProperty, string targetPropertyName, string propertyName, Action action)`
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
None
### Request Example
None
### Response
#### Success Response (200)
Returns the element with the specified property observation set up.
#### Response Example
None
## ObserveProperty
### Description
Observes a specific property on a source object and triggers an action when it changes.
### Method
`ObserveProperty(T element, Func sourceProperty, string propertyName, Action action)`
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
None
### Request Example
None
### Response
#### Success Response (200)
Returns the element with the specified property observation set up.
#### Response Example
None
## ObserveProperty (Source Object)
### Description
Observes a specific property on a source object and triggers an action when it changes.
### Method
`ObserveProperty(T element, TSource source, string propertyName, Action action)`
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
None
### Request Example
None
### Response
#### Success Response (200)
Returns the element with the specified property observation set up.
#### Response Example
None
## ObserveSelf
### Description
Observes changes to the element itself and triggers an action with the element and property name.
### Method
`ObserveSelf(T element, Action action)`
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
None
### Request Example
None
### Response
#### Success Response (200)
Returns the element with self-observation set up.
#### Response Example
None
## Observe
### Description
Observes changes to properties on a source object, triggering an action with the element and property names.
### Method
`Observe(T element, Func sourceProperty, Action action, string[] propertyNames)`
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
None
### Request Example
None
### Response
#### Success Response (200)
Returns the element with property observation set up.
#### Response Example
None
## Observe (Action with Element)
### Description
Observes changes to properties on a source object, triggering an action with only the element.
### Method
`Observe(T element, Func sourceProperty, Action action, string[] propertyNames)`
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
None
### Request Example
None
### Response
#### Success Response (200)
Returns the element with property observation set up.
#### Response Example
None
## Observe (Source Object)
### Description
Observes changes to properties on a source object, triggering an action with the element and property names.
### Method
`Observe(T element, TSource source, Action action, string[] propertyNames)`
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
None
### Request Example
None
### Response
#### Success Response (200)
Returns the element with property observation set up.
#### Response Example
None
```
--------------------------------
### Display an SVG Icon using DrawnUi Canvas
Source: https://github.com/taublast/drawnui/blob/main/docs/_site/articles/getting-started.html
Provides a simple example of embedding an SVG icon within a DrawnUi `Canvas` control. It demonstrates the use of `SkiaSvg` with properties like `Source`, `LockRatio`, `TintColor`, and `WidthRequest` for sizing and appearance.
```xaml
```
--------------------------------
### SkiaImage C# Examples
Source: https://context7.com/taublast/drawnui/llms.txt
Provides C# examples for SkiaImage, including programmatic creation with source, loading options, and event handling for success and error. It also demonstrates a custom `BannerImage` class inheriting from SkiaImage to implement a fade-in animation on successful image load.
```csharp
// Programmatic image with loading events
var urlImage = new SkiaImage
{
Source = "https://example.com/image.jpg",
LoadSourceOnFirstDraw = true,
Aspect = TransformAspect.AspectCover,
WidthRequest = 200,
HeightRequest = 200,
UseCache = SkiaCacheType.Image
};
urlImage.Success += (s, e) => Console.WriteLine("Image loaded successfully!");
urlImage.Error += (s, e) => Console.WriteLine("Failed to load image");
// Custom fade-in animation on load
public class BannerImage : SkiaImage
{
public override void OnSuccess(string source)
{
base.OnSuccess(source);
this.Opacity = 0.01;
_ = this.FadeToAsync(1, 300, Easing.SinIn);
}
}
```
--------------------------------
### Configure .NET MAUI Project for DrawnUI
Source: https://github.com/taublast/drawnui/blob/main/docs/_site/articles/getting-started.html
Specifies the minimum supported OS versions for various platforms and includes necessary MAUI and DrawnUI NuGet packages. This setup ensures compatibility and access to DrawnUI features within your .NET MAUI application.
```xml
15.0
15.2
21.0
10.0.19041.0
10.0.19041.0
```
--------------------------------
### Create New MAUI Project - Bash
Source: https://github.com/taublast/drawnui/blob/main/docs/articles/interactive-cards.md
This snippet demonstrates how to create a new MAUI project named 'InteractiveCardsTutorial' and navigate into its directory using the .NET CLI.
```bash
dotnet new maui -n InteractiveCardsTutorial
cd InteractiveCardsTutorial
```
--------------------------------
### SkiaButton C# Fluent API Example
Source: https://context7.com/taublast/drawnui/llms.txt
Shows how to create and configure a SkiaButton programmatically using a fluent API in C#. This example includes setting text, appearance, handling tap events with asynchronous operations, and chaining method calls for layout.
```csharp
// Fluent API for programmatic button creation
SkiaButton actionButton;
var button = new SkiaButton("Save Changes")
{
BackgroundColor = Colors.Blue,
TextColor = Colors.White,
CornerRadius = 8
}
.Assign(out actionButton)
.OnTapped(async btn =>
{
btn.IsEnabled = false;
btn.Text = "Saving...";
try
{
await SaveChangesAsync();
btn.Text = "Saved!";
await Task.Delay(1000);
btn.Text = "Save Changes";
}
finally
{
btn.IsEnabled = true;
}
})
.Height(44)
.CenterX();
```
--------------------------------
### Create Linear Gradient Programmatically in C#
Source: https://github.com/taublast/drawnui/blob/main/docs/_site/articles/advanced/gradients.html
This C# code example demonstrates how to create a `SkiaGradient` object programmatically. It sets the gradient type, start and end colors, and start and end points, and then applies it to a control's `FillGradient` property.
```C#
var gradient = new SkiaGradient
{
Type = SkiaGradientType.Linear,
StartColor = Colors.Red,
EndColor = Colors.Yellow,
StartPoint = new Point(0, 0),
EndPoint = new Point(1, 1)
};
control.FillGradient = gradient;
```
--------------------------------
### Observe Multiple Properties in Real-world Example
Source: https://github.com/taublast/drawnui/blob/main/docs/_site/articles/fluent-extensions.html
A comprehensive example demonstrating the observation of multiple properties on a SkiaButton and updating a SkiaRichLabel based on those changes. It includes observing the button's Text and IsPressed properties to reflect its state in a separate label.
```csharp
SkiaButton btnClickMe;
```
--------------------------------
### Configure DrawnUI Startup Settings in C#
Source: https://github.com/taublast/drawnui/blob/main/docs/articles/startup-settings.md
Demonstrates how to initialize DrawnUI with custom startup settings in a MAUI application. This includes setting desktop window dimensions, providing a custom logger, enabling desktop keyboard handling, and configuring mobile fullscreen behavior. The Startup delegate allows for post-initialization actions.
```csharp
using DrawnUi.Draw;
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp()
.UseDrawnUi(new DrawnUiStartupSettings
{
// Desktop window sizing (desktop platforms)
DesktopWindow = new()
{
Width = 375,
Height = 800,
IsFixedSize = false
},
// Provide an ILogger used by Super.Log
Logger = LoggerFactory.Create(b =>
{
b.AddConsole();
b.SetMinimumLevel(LogLevel.Information);
}).CreateLogger("DrawnUi"),
// Optional features
UseDesktopKeyboard = true,
MobileIsFullscreen = false,
// Optional post-initialization hook
Startup = services =>
{
// Run custom code once DrawnUI is initialized
}
});
```
--------------------------------
### Complete Shell Application Example (C# Code-Behind)
Source: https://github.com/taublast/drawnui/blob/main/docs/articles/controls/shell.md
Provides the C# code-behind for the MainShell XAML file, initializing the SkiaShell, registering navigation routes for different pages, and handling tab button taps to navigate between them. It also implements the OnBackButtonPressed method to allow the shell to manage the back navigation.
```csharp
public partial class MainShell : DrawnUiBasePage
{
public SkiaShell Shell { get; private set; }
public MainShell()
{
InitializeComponent();
// Initialize shell
Shell = new SkiaShell();
Shell.Initialize(MainCanvas);
// Register routes
Shell.RegisterRoute("home", typeof(HomePage));
Shell.RegisterRoute("profile", typeof(ProfilePage));
Shell.RegisterRoute("settings", typeof(SettingsPage));
Shell.RegisterRoute("details", typeof(DetailsPage));
// Navigate to initial route
Shell.GoToAsync("home");
}
private void OnHomeTabTapped(object sender, EventArgs e)
{
Shell.GoToAsync("home");
}
private void OnProfileTabTapped(object sender, EventArgs e)
{
Shell.GoToAsync("profile");
}
private void OnSettingsTabTapped(object sender, EventArgs e)
{
Shell.GoToAsync("settings");
}
protected override bool OnBackButtonPressed()
{
// Let shell handle back button
return Shell.GoBack(true);
}
}
```
--------------------------------
### Observe Single Property Change in Real-world Example
Source: https://github.com/taublast/drawnui/blob/main/docs/_site/articles/fluent-extensions.html
A practical example of using ObserveProperty within a SkiaRichLabel to update its Text property whenever the Text property of the parent (this) changes. This is useful for dynamic UI updates based on internal state.
```csharp
new SkiaRichLabel()
{
Text = this.Text,
UseCache = SkiaCacheType.Operations,
HorizontalTextAlignment = DrawTextAlignment.Center,
VerticalOptions = LayoutOptions.Center,
FontSize = 16,
FontAttributes = FontAttributes.Bold,
TextColor = Colors.White,
}
.ObserveProperty(this, nameof(Text), me =>
{
me.Text = this.Text;
})
```
--------------------------------
### Get All Elements Including Self and Parents
Source: https://github.com/taublast/drawnui/blob/main/docs/_site/api/DrawnUi.Controls.ScrollPickerLabelLayout.html
Collects all elements in the visual tree starting from a VisualElement, including itself and all its ancestors. Useful for context-aware operations.
```csharp
public static IEnumerable GetAllWithMyselfParents(VisualElement element)
```
--------------------------------
### Install and Build Documentation with NPM
Source: https://github.com/taublast/drawnui/blob/main/docs/_site/README.html
Installs the docfx-flavored-markdown NPM package and builds the documentation. This is an alternative method for environments where .NET is not available.
```bash
npm install -g @tsgkadot/docfx-flavored-markdown
dfm build
```
--------------------------------
### Prepend Buffered Data to Output File
Source: https://github.com/taublast/drawnui/blob/main/ARCHITECTURE_DIAGRAM.md
This process describes how buffered frames (e.g., 5 seconds of pre-recorded video) are prepended to a newly started recording. It involves extracting buffered data, initializing a file encoder, and then writing the buffered frames followed by the live-recorded frames to the output file. The total time for writing to the output file is less than 10ms.
```C#
public class RecordingManager
{
private Queue _preRecordingBuffer = new Queue();
private bool _isPreRecording = true;
private bool _isRecordingVideo = false;
private Encoder _fileEncoder;
public void StartRecording()
{
_isPreRecording = false;
_isRecordingVideo = true;
// Step 1: Extract Buffered Data
byte[] bufferedData = ExtractBufferedData();
// Step 2: Initialize File Encoder
_fileEncoder = new Encoder();
_fileEncoder.Initialize(new EncoderSettings { Bitrate = 8000000, Resolution = new Resolution(1920, 1080) });
// Step 3: Write to Output File
// 1. Write buffered frames first (prepend)
WriteBufferedFrames(bufferedData);
// 2. Then write live recorded frames (handled by encoder during recording)
// ... live recording logic ...
}
private byte[] ExtractBufferedData()
{
// Simulate extracting data from the pre-recording buffer
// In a real scenario, this would aggregate data from _preRecordingBuffer
long totalSize = 0;
foreach (var frame in _preRecordingBuffer)
{
totalSize += frame.Data.Length;
}
byte[] combinedData = new byte[totalSize];
int offset = 0;
foreach (var frame in _preRecordingBuffer)
{
Buffer.BlockCopy(frame.Data, 0, combinedData, offset, frame.Data.Length);
offset += frame.Data.Length;
}
_preRecordingBuffer.Clear();
return combinedData;
}
private void WriteBufferedFrames(byte[] data)
{
// Simulate writing the extracted buffered data to the file encoder
// This would involve passing the data to the encoder's write function
// _fileEncoder.Write(data);
Console.WriteLine($"Prepended {data.Length} bytes of buffered data.");
}
// Placeholder for Encoder class and related types
public class Encoder
{
public void Initialize(EncoderSettings settings) { Console.WriteLine("Encoder Initialized."); }
public void Write(byte[] data) { Console.WriteLine("Writing data to file."); }
}
public class EncoderSettings { public int Bitrate { get; set; } public Resolution Resolution { get; set; } }
public struct Resolution { public int Width { get; } public int Height { get; } public Resolution(int width, int height) { Width = width; Height = height; } }
}
```
--------------------------------
### Get Spring Animation Initial Velocity in C#
Source: https://github.com/taublast/drawnui/blob/main/docs/_site/api/DrawnUi.Draw.SpringTimingParameters.html
Retrieves the initial velocity of the spring animation. This value determines how fast the spring starts its movement.
```csharp
public float InitialVelocity { get; }
```
--------------------------------
### SkiaSlider Range Example (XML)
Source: https://github.com/taublast/drawnui/blob/main/docs/controls/range-controls.md
Illustrates how to configure a SkiaSlider for range selection by enabling the 'EnableRange' property and setting both 'Start' and 'End' values.
```xml
```
--------------------------------
### Build and Serve Documentation with DocFX
Source: https://github.com/taublast/drawnui/blob/main/docs/_site/README.html
Commands to navigate to the docs folder and build the documentation using DocFX. After building, 'docfx serve _site' can be used to preview the generated documentation locally.
```bash
cd docs
docfx build
docfx serve _site
```
--------------------------------
### Calculate Video Buffer Size (C#)
Source: https://github.com/taublast/drawnui/blob/main/src/Maui/Addons/DrawnUi.Maui.Camera/PreRecordingTech.md
Provides the formula and an example for calculating the video buffer size based on expected bytes per second, duration, and a safety margin. It also shows the initialization of two byte arrays (_bufferA and _bufferB) for video buffering and a CircularAudioBuffer for audio samples. This calculation is crucial for managing memory efficiently during recording.
```csharp
// Video buffer formula:
// bufferSize = expectedBytesPerSecond × duration × safetyMargin
// Example for 1080p @ 30fps:
// - H.264 bitrate: ~15 Mbps = 1.875 MB/s
// - 5 seconds: 1.875 × 5 = 9.375 MB
// - Safety margin: 1.44x (for IDR frame spikes)
// - Total: 13.5 MB per buffer
const int bufferSize = (int)(11.25 * 1024 * 1024 * 1.2); // ~13.5 MB
_bufferA = new byte[bufferSize];
_bufferB = new byte[bufferSize];
// Audio buffer:
// - Circular mode with PreRecordDuration
_audioBuffer = new CircularAudioBuffer(PreRecordDuration);
```
--------------------------------
### Get All Elements Including Parents in C#
Source: https://github.com/taublast/drawnui/blob/main/docs/_site/api/DrawnUi.Draw.ContentLayout.html
Fetches all elements in the visual tree, starting from the specified element and including its parents. This is helpful for context-aware operations.
```csharp
public static IEnumerable GetAllWithMyselfParents(VisualElement element)
{
// Implementation details...
var parents = new List();
parents.Add(element);
return parents;
}
```
--------------------------------
### Get All Elements Including Parents
Source: https://github.com/taublast/drawnui/blob/main/docs/_site/api/DrawnUi.Controls.SkiaShell.PopupWrapper.html
Fetches all elements in the visual tree, starting from a VisualElement and including all its ancestors up to the root. This can be used for traversal or applying properties recursively.
```csharp
StaticResourcesExtensions.GetAllWithMyselfParents(VisualElement)
```
--------------------------------
### Initialize DrawnUI in MauiProgram.cs
Source: https://github.com/taublast/drawnui/blob/main/docs/_site/articles/interactive-cards.html
This C# code snippet shows how to configure the DrawnUI library within the `MauiProgram.cs` file. It enables desktop keyboard support and sets custom dimensions for the desktop window. Dependencies include the DrawnUi NuGet package.
```csharp
using DrawnUi.Infrastructure;
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp()
.UseDrawnUi(new DrawnUiStartupSettings
{
UseDesktopKeyboard = true,
DesktopWindow = new()
{
Width = 400,
Height = 700
}
})
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "FontText");
fonts.AddFont("OpenSans-Semibold.ttf", "FontSemibold");
});
return builder.Build();
}
}
```
--------------------------------
### Get All Parents Including Self with StaticResourcesExtensions
Source: https://github.com/taublast/drawnui/blob/main/docs/_site/api/DrawnUi.Draw.SkiaHoverMask.html
Retrieves a collection of all parent elements, including the element itself, starting from a VisualElement. Useful for traversing the visual tree upwards.
```csharp
public static IEnumerable GetAllWithMyselfParents(this VisualElement element)
{
// Implementation details omitted for brevity
return Enumerable.Empty();
}
```
--------------------------------
### Metal Resource Management: Shared Device and Command Queue (C#)
Source: https://github.com/taublast/drawnui/blob/main/src/Maui/Addons/DrawnUi.Maui.Camera/PreRecordingTech.md
Explains the best practice of creating and reusing Metal device and command queue resources for the lifetime of the application. This static approach within AppleVideoToolboxEncoder minimizes overhead by avoiding repeated creation and disposal of these core Metal objects.
```csharp
// In AppleVideoToolboxEncoder - STATIC shared resources
private static IMTLDevice _sharedMetalDevice;
private static IMTLCommandQueue _sharedCommandQueue;
private static GCHandle _sharedQueuePin;
private static readonly object _sharedMetalLock = new();
private void EnsureMetalContext()
{
lock (_sharedMetalLock)
{
if (_sharedMetalDevice == null)
{
_sharedMetalDevice = MTLDevice.SystemDefault;
if (_sharedMetalDevice != null)
{
_sharedCommandQueue = _sharedMetalDevice.CreateCommandQueue();
_sharedQueuePin = GCHandle.Alloc(_sharedCommandQueue, GCHandleType.Pinned);
}
}
}
// Per-instance GRContext using shared device/queue
if (_encodingContext == null && _sharedMetalDevice != null)
{
var backend = new GRMtlBackendContext
{
Device = _sharedMetalDevice,
Queue = _sharedCommandQueue
};
_encodingContext = GRContext.CreateMetal(backend);
_metalCache = new CVMetalTextureCache(_sharedMetalDevice);
}
}
// NOTE: _sharedMetalDevice, _sharedCommandQueue, _sharedQueuePin are NEVER disposed
// They are reused across all encoder instances for the app lifetime
```
--------------------------------
### Professional Shader Camera Setup (C#)
Source: https://github.com/taublast/drawnui/blob/main/src/Maui/Addons/DrawnUi.Maui.Camera/README.md
Shows how to initialize and configure a CameraWithEffects instance for advanced shader-based camera effects. It enables constant updates for smooth effects, utilizes GPU caching, applies a custom shader, and turns the camera on.
```csharp
var camera = new CameraWithEffects
{
Facing = CameraPosition.Default,
ConstantUpdate = true, // For smooth shader effects
UseCache = SkiaCacheType.GPU
};
// Apply professional look
camera.SetCustomShader("Shaders/Camera/action.sksl");
camera.IsOn = true;
```
--------------------------------
### AnimatedFramesRenderer DefaultFrame Property
Source: https://github.com/taublast/drawnui/blob/main/docs/_site/api/DrawnUi.Controls.AnimatedFramesRenderer.html
Gets or sets the default frame to display when the animation starts or resets. A value of -1 indicates the last frame. This property is bound to the DefaultFrameProperty.
```csharp
public int DefaultFrame { get; set; }
```
--------------------------------
### SkiaButton XML Examples
Source: https://context7.com/taublast/drawnui/llms.txt
Demonstrates various ways to use SkiaButton in XML, including platform-styled buttons, custom styling with visual states, buttons with icons, and buttons with complex custom content layouts.
```xml
```
--------------------------------
### Text Change Event Handling for Entry Controls
Source: https://github.com/taublast/drawnui/blob/main/docs/_site/articles/fluent-extensions.html
Provides examples of handling text changes for SkiaMauiEntry, SkiaMauiEditor, and SkiaLabel using the OnTextChanged event.
```csharp
new SkiaMauiEntry()
.OnTextChanged((entry, text) =>
{
// Handle text changes
Console.WriteLine($"Text changed to: {text}");
});
new SkiaMauiEditor()
.OnTextChanged((editor, text) =>
{
// Handle editor text changes
});
new SkiaLabel()
.OnTextChanged((label, text) =>
{
// Handle label text changes via PropertyChanged
});
```
--------------------------------
### Setup SkiaViewSwitcher Transition Animation
Source: https://github.com/taublast/drawnui/blob/main/docs/_site/api/DrawnUi.Controls.SkiaViewSwitcher.html
Configures and prepares the animation for transitioning between two views. It takes the transition type and the previous and new visible views as parameters. This method is asynchronous and returns a Task.
```csharp
protected virtual Task SetupTransitionAnimation(DoubleViewTransitionType doubleViewTransitionType, SkiaControl previousVisibleView, SkiaControl newVisibleView)
{
// Implementation details for setting up transition animation
return Task.CompletedTask;
}
```
--------------------------------
### StaticResourcesExtensions: Get All Parents Including Self
Source: https://github.com/taublast/drawnui/blob/main/docs/_site/api/DrawnUi.Draw.SkiaProgress.html
Collects all visual elements in the hierarchy starting from the given visual element up to the root. This includes the element itself. Part of the DrawnUi.Draw.StaticResourcesExtensions class.
```csharp
public static IEnumerable GetAllWithMyselfParents(this VisualElement element)
{
// Implementation to traverse and collect parents
yield return element;
}
```
--------------------------------
### Building and Running a DrawnUI App
Source: https://github.com/taublast/drawnui/blob/main/docs/_site/articles/first-app.html
Command-line instructions for building and running a DrawnUI application using the .NET CLI. These commands are standard for .NET projects and initiate the application's execution.
```bash
dotnet build
dotnet run
```
--------------------------------
### Get All Parents Including Self (C#)
Source: https://github.com/taublast/drawnui/blob/main/docs/_site/api/DrawnUi.Draw.VirtualScroll.html
Retrieves a collection of all visual elements in the hierarchy, starting from the given element and including all its ancestors up to the root. This is useful for traversing the visual tree.
```csharp
public static IEnumerable GetAllWithMyselfParents(this VisualElement element)
{
// Implementation details for getting all parents
yield break;
}
```
--------------------------------
### DrawnUiBasePage XAML Structure
Source: https://github.com/taublast/drawnui/blob/main/docs/articles/getting-started.md
Defines a basic DrawnUi page structure using DrawnUiBasePage, including a Canvas with SkiaLayout, SkiaLabel, and SkiaButton. It demonstrates how to set rendering modes, gestures, and layout options.
```xml
```
--------------------------------
### Trim Audio Samples by Timestamp (C#)
Source: https://github.com/taublast/drawnui/blob/main/src/Maui/Addons/DrawnUi.Maui.Camera/PreRecordingTech.md
Demonstrates how to trim audio samples to match the video duration when the audio capture starts before video encoding. It calculates the target start timestamp in nanoseconds and filters the audio samples to include only those within the video's duration. This ensures synchronized audio and video output.
```csharp
var targetStartNs = lastSampleTimestamp - (long)(videoDurationMs * 1_000_000);
allAudioSamples = allAudioSamples.Where(s => s.TimestampNs >= targetStartNs).ToArray();
```
--------------------------------
### SkiaShell - SetupRoot
Source: https://github.com/taublast/drawnui/blob/main/docs/_site/api/DrawnUi.Controls.SkiaShell.html
Sets up the main root layout control within the SkiaShell.
```APIDOC
## SetupRoot
### Description
Sets up the main root layout control within the SkiaShell.
### Method
`protected virtual void`
### Endpoint
N/A (Internal method)
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
- **shellLayout** (ISkiaControl) - The root layout control to set up.
### Request Example
```json
{
"shellLayout": ""
}
```
### Response
#### Success Response (200)
None
#### Response Example
None
```
--------------------------------
### StaticResourcesExtensions: Get All Parents Including Self
Source: https://github.com/taublast/drawnui/blob/main/docs/_site/api/DrawnUi.Draw.SkiaLayout.html
Returns a collection of all visual elements in the hierarchy, starting from the given visual element and including all its ancestors. Useful for traversing the visual tree.
```csharp
public static IEnumerable GetAllWithMyselfParents(this VisualElement element)
{
// Implementation to get all parents including the element itself
return Enumerable.Empty();
}
```
--------------------------------
### SkiaControl Rendering and Gradient Setup
Source: https://github.com/taublast/drawnui/blob/main/docs/_site/api/DrawnUi.Controls.SkiaLottie.html
Details methods for setting up gradients, creating shadows, and updating platform-specific shadow rendering.
```APIDOC
## SkiaControl Rendering and Gradient Setup
### Description
This section describes methods related to advanced rendering features, including configuring gradients, generating shadows, and managing platform-specific shadow implementations.
### Methods
- **SetupGradient(SKPaint paint, SkiaGradient gradient, SKRect rect)**: Configures a gradient for a given paint object and rectangle.
- **CreateShadow(SkiaShadow shadow, float alpha)**: Creates a shadow effect with specified parameters.
- **UpdatePlatformShadow()**: Updates the shadow rendering based on platform-specific requirements.
- **PlatformShadow**: Property related to the platform's shadow implementation.
- **HasPlatformClip()**: Checks if the platform has a clipping mechanism.
- **GetDensity()**: Retrieves the screen density.
```
--------------------------------
### SkiaViewSwitcher XAML Basic Usage
Source: https://github.com/taublast/drawnui/blob/main/docs/_site/articles/controls/shell.html
Illustrates the basic XAML setup for a SkiaViewSwitcher. This example focuses on defining transition types and durations, with views intended to be added programmatically.
```xaml
```
--------------------------------
### Add DrawnUi Namespace to XAML
Source: https://github.com/taublast/drawnui/blob/main/docs/_site/articles/getting-started.html
Declares the DrawnUi XML namespace in a .NET MAUI XAML file. This allows you to use DrawnUI controls and elements directly within your XAML markup.
```xml
```
--------------------------------
### Gradient and Shadow Setup
Source: https://github.com/taublast/drawnui/blob/main/docs/_site/api/DrawnUi.Controls.GridLayout.html
Methods for setting up gradients and creating shadows for the SkiaControl.
```APIDOC
## SkiaControl Gradient and Shadow Setup
### Description
Provides methods to configure gradients and shadows for rendering effects within the SkiaControl.
### Methods
- **SetupGradient(SKPaint paint, SkiaGradient gradient, SKRect bounds)**
- **Description**: Configures the provided SKPaint object to use the specified gradient for rendering within the given bounds.
- **Method**: POST
- **Endpoint**: N/A (Method call)
- **Parameters**:
- **paint** (SKPaint) - Required - The paint object to configure.
- **gradient** (SkiaGradient) - Required - The gradient definition.
- **bounds** (SKRect) - Required - The rectangular area for the gradient.
- **CreateShadow(SkiaShadow shadow, float opacity)**
- **Description**: Creates shadow information based on the provided shadow definition and opacity.
- **Method**: POST
- **Endpoint**: N/A (Method call)
- **Parameters**:
- **shadow** (SkiaShadow) - Required - The definition of the shadow.
- **opacity** (float) - Required - The opacity of the shadow.
- **UpdatePlatformShadow()**
- **Description**: Updates the platform-specific shadow rendering.
- **Method**: POST
- **Endpoint**: N/A (Method call)
- **PlatformShadow**
- **Description**: Gets or sets the platform-specific shadow properties.
- **Method**: GET/SET
- **Endpoint**: N/A (Property access)
### Response
#### Success Response (200)
- **Result** (Void or Shadow Object) - Description depends on the method or property accessed.
#### Response Example
```json
{
"example": "Shadow updated."
}
```
```
--------------------------------
### Gradient and Shadow Setup
Source: https://github.com/taublast/drawnui/blob/main/docs/_site/api/DrawnUi.Draw.SkiaHotspotZoom.html
Methods for setting up gradients and shadows for Skia rendering.
```APIDOC
## SkiaControl Gradient and Shadow Methods
### Description
Methods for configuring gradients and shadows within the Skia rendering context.
### Methods
- **SetupGradient(SKPaint, SkiaGradient, SKRect)**: Configures a gradient for a given SKPaint object.
- **CreateShadow(SkiaShadow, float)**: Creates a shadow effect.
- **UpdatePlatformShadow()**: Updates the platform-specific shadow.
```
--------------------------------
### Get All Ancestors Including Self (C#)
Source: https://github.com/taublast/drawnui/blob/main/docs/_site/api/DrawnUi.Draw.SkiaFrame.html
Retrieves a collection of all visual elements in the hierarchy, starting from the given element and including all its ancestors up to the root. This is useful for traversal and analysis of the visual tree.
```csharp
public static IEnumerable GetAllWithMyselfParents(this VisualElement element)
{
// Implementation details for getting all parents including self
return Enumerable.Empty();
}
```
--------------------------------
### SkiaGif Playback Control
Source: https://github.com/taublast/drawnui/blob/main/docs/_site/articles/controls/animations.html
Provides C# code examples for controlling the playback of a SkiaGif animation. This includes starting, stopping, seeking to a specific frame, and retrieving the total number of frames.
```csharp
// Start the animation
myGif.Start();
// Stop at current frame
myGif.Stop();
// Jump to specific frame
myGif.Seek(5);
// Get total frames
int total = myGif.Animation?.TotalFrames ?? 0;
```
--------------------------------
### C# AVFoundation Muxing Pre-recorded and Live Audio/Video
Source: https://github.com/taublast/drawnui/blob/main/src/Maui/Addons/DrawnUi.Maui.Camera/PreRecordingTech.md
Illustrates the process of combining pre-recorded and live video and audio segments into a single composition using AVFoundation in C#. It details inserting tracks into an AVMutableComposition and exporting the final asset, utilizing the passthrough mode for efficiency.
```csharp
using var composition = new AVMutableComposition();
var videoTrack = composition.AddMutableTrack(AVMediaTypes.Video, 0);
// Insert pre-recording VIDEO at time 0
videoTrack.InsertTimeRange(preRecVideoRange, preRecVideoTrack, CMTime.Zero, out error);
// Insert live recording VIDEO after pre-recording
videoTrack.InsertTimeRange(liveVideoRange, liveRecVideoTrack, preRecAsset.Duration, out error);
// Add pre-rec AUDIO at time 0
if (preRecAudioFilePath exists)
{
using var preRecAudioAsset = AVAsset.FromUrl(preRecAudioFilePath);
var audioTrack = composition.AddMutableTrack(AVMediaTypes.Audio, 0);
audioTrack.InsertTimeRange(preRecAudioRange, preRecAudioTracks[0], CMTime.Zero, out error);
}
// Add live AUDIO starting after pre-rec video duration
if (liveAudioFilePath exists)
{
using var liveAudioAsset = AVAsset.FromUrl(liveAudioFilePath);
// Get or create audio track
var audioTrack = composition.TracksWithMediaType(AVMediaTypes.Audio)[0];
audioTrack.InsertTimeRange(liveAudioRange, liveAudioTracks[0], preRecVideoDuration, out error);
}
// Export with Passthrough (fast!)
using var exporter = new AVAssetExportSession(composition, AVAssetExportSessionPreset.Passthrough);
await exporter.ExportTaskAsync();
```
--------------------------------
### Install DocFX .NET Global Tool
Source: https://github.com/taublast/drawnui/blob/main/docs/_site/README.html
Installs DocFX as a .NET global tool, which is the recommended method for building documentation locally. This tool is essential for processing and generating the documentation files.
```bash
dotnet tool install -g docfx
```
--------------------------------
### Get DrawingContext Argument in C#
Source: https://github.com/taublast/drawnui/blob/main/docs/_site/api/DrawnUi.Draw.DrawingContext.html
Retrieves an optional argument from the DrawingContext using a string key. Returns null if the key is not found. Example usage demonstrates checking for a scale argument.
```csharp
public object? GetArgument(string key)
// Example:
// if (ctx.GetArgument(ContextArguments.Scale.ToString()) is float zoomedScale) {}
```