Skip to content

Pie Chart Widget - Complete Documentation

Overview

A versatile pie chart widget similar to Embedded Wizard's implementation, supporting both traditional pie charts and donut charts with extensive customization options.

Features

Pie & Donut - Full pie or donut chart (with inner radius)
Multiple Styles - Solid, Gradient, Outlined, 3D effect
Flexible Labels - Inside, Outside, or Separate legend
Value Display - Percentage, Absolute, or Both
Slice Explosion - Highlight slices by pulling them out
Interactive Mode - Clickable slices with selection
Custom Colors - Per-slice color customization
Start Angle - Create half-pies or gauge-style charts
Memory Efficient - Minimal RAM usage (~20 bytes per slice)

API Reference

Creation

mgui_widget_t* gui_pie_chart_create(
    mgui_widget_t* parent,
    int16_t x, int16_t y,
    int16_t width, int16_t height,
    uint8_t num_slices
);

Parameters: - num_slices - Number of slices (max 16)

Data Functions

// Set single slice value
void gui_pie_chart_set_value(mgui_widget_t* obj, uint8_t slice_index, int16_t value);

// Set multiple values at once
void gui_pie_chart_set_values(mgui_widget_t* obj, const int16_t* values, uint8_t count);

Appearance Functions

// Set slice color
void gui_pie_chart_set_slice_color(mgui_widget_t* obj, uint8_t slice_index, mgui_color_t color);

// Set slice label
void gui_pie_chart_set_slice_label(mgui_widget_t* obj, uint8_t slice_index, const char* label);

// Set chart style
void gui_pie_chart_set_style(mgui_widget_t* obj, gui_pie_chart_style_t style);

Chart Styles: - PIE_CHART_STYLE_SOLID - Solid filled slices - PIE_CHART_STYLE_GRADIENT - Gradient filled slices - PIE_CHART_STYLE_OUTLINED - Only borders, no fill - PIE_CHART_STYLE_3D - 3D effect with shadow

Geometry Functions

// Set pie radius
void gui_pie_chart_set_radius(mgui_widget_t* obj, uint16_t radius);

// Set inner radius (creates donut chart)
void gui_pie_chart_set_inner_radius(mgui_widget_t* obj, uint16_t inner_radius);

// Set start angle (0 = right/east, 90 = bottom, etc.)
void gui_pie_chart_set_start_angle(mgui_widget_t* obj, int16_t angle);

Slice Explosion

// Explode/separate a slice from the pie
void gui_pie_chart_explode_slice(mgui_widget_t* obj, uint8_t slice_index, 
                                 bool explode, uint8_t distance);

Display Options

// Set label display mode
void gui_pie_chart_set_label_mode(mgui_widget_t* obj, gui_pie_chart_label_mode_t mode);

// Set value display mode
void gui_pie_chart_set_value_mode(mgui_widget_t* obj, gui_pie_chart_value_mode_t mode);

Label Modes: - PIE_CHART_LABEL_NONE - No labels - PIE_CHART_LABEL_INSIDE - Labels inside slices - PIE_CHART_LABEL_OUTSIDE - Labels outside with connecting lines - PIE_CHART_LABEL_LEGEND - Separate legend box

Value Display Modes: - PIE_CHART_VALUE_NONE - No values shown - PIE_CHART_VALUE_PERCENTAGE - Show percentages (e.g., "25%") - PIE_CHART_VALUE_ABSOLUTE - Show absolute values (e.g., "250") - PIE_CHART_VALUE_BOTH - Show both (e.g., "250 (25%)")

Interaction Functions

// Enable/disable slice selection
void gui_pie_chart_set_interactive(mgui_widget_t* obj, bool interactive);

// Get selected slice index (-1 if none)
int8_t gui_pie_chart_get_selected(mgui_widget_t* obj);

Usage Examples

Example 1: Simple Pie Chart

// Create pie chart
mgui_widget_t* chart = gui_pie_chart_create(
    screen, 20, 20, 300, 300, 5  // 5 slices
);

// Set market share data
const int16_t market_data[] = {35, 25, 20, 15, 5};
gui_pie_chart_set_values(chart, market_data, 5);

// Set colors
gui_pie_chart_set_slice_color(chart, 0, MGUI_COLOR_BLUE);
gui_pie_chart_set_slice_color(chart, 1, MGUI_COLOR_GREEN);
gui_pie_chart_set_slice_color(chart, 2, MGUI_COLOR_ORANGE);
gui_pie_chart_set_slice_color(chart, 3, MGUI_COLOR_RED);
gui_pie_chart_set_slice_color(chart, 4, MGUI_COLOR_GRAY);

// Add labels
gui_pie_chart_set_slice_label(chart, 0, "Company A");
gui_pie_chart_set_slice_label(chart, 1, "Company B");
// ... etc

// Configure display
gui_pie_chart_set_style(chart, PIE_CHART_STYLE_SOLID);
gui_pie_chart_set_label_mode(chart, PIE_CHART_LABEL_OUTSIDE);
gui_pie_chart_set_value_mode(chart, PIE_CHART_VALUE_PERCENTAGE);

Example 2: Donut Chart

// Create chart
mgui_widget_t* chart = gui_pie_chart_create(
    screen, 350, 20, 300, 300, 6
);

// Set data
gui_pie_chart_set_value(chart, 0, 30);
gui_pie_chart_set_value(chart, 1, 20);
gui_pie_chart_set_value(chart, 2, 15);
gui_pie_chart_set_value(chart, 3, 15);
gui_pie_chart_set_value(chart, 4, 10);
gui_pie_chart_set_value(chart, 5, 10);

// Configure as DONUT (key difference!)
gui_pie_chart_set_radius(chart, 120);
gui_pie_chart_set_inner_radius(chart, 60);  // Creates hole

gui_pie_chart_set_style(chart, PIE_CHART_STYLE_GRADIENT);
gui_pie_chart_set_label_mode(chart, PIE_CHART_LABEL_INSIDE);

Example 3: Interactive Pie with Explosion

// Callback for slice clicks
void slice_clicked(mgui_widget_t* obj, mgui_event_t event) {
    int8_t selected = gui_pie_chart_get_selected(obj);
    DEBUG_PRINT("Slice %d selected", selected);
}

// Create chart
mgui_widget_t* chart = gui_pie_chart_create(
    screen, 20, 350, 250, 250, 4
);

// Set data...
gui_pie_chart_set_values(chart, quarterly_sales, 4);

// Enable interaction
gui_pie_chart_set_interactive(chart, true);
gui_widget_set_click_handler(chart, slice_clicked);

// Clicking a slice will automatically explode it!

Example 4: Pie Chart with Legend

mgui_widget_t* chart = gui_pie_chart_create(
    screen, 300, 350, 280, 250, 7
);

// Set data for 7 days
const int16_t activity[] = {8, 9, 7, 10, 9, 5, 6};
gui_pie_chart_set_values(chart, activity, 7);

// Add labels
const char* days[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
for (int i = 0; i < 7; i++) {
    gui_pie_chart_set_slice_label(chart, i, days[i]);
}

// Show legend (displays outside the pie)
gui_pie_chart_set_label_mode(chart, PIE_CHART_LABEL_LEGEND);
gui_pie_chart_set_value_mode(chart, PIE_CHART_VALUE_PERCENTAGE);

Example 5: Exploded Pie (Highlight Largest)

mgui_widget_t* chart = gui_pie_chart_create(
    screen, 400, 50, 250, 250, 5
);

// Data with one dominant value
const int16_t data[] = {10, 15, 45, 20, 10};
gui_pie_chart_set_values(chart, data, 5);

// Explode the largest slice (index 2)
gui_pie_chart_explode_slice(chart, 2, true, 20);  // Pull out by 20px

gui_pie_chart_set_style(chart, PIE_CHART_STYLE_3D);

Example 6: Half Pie / Gauge Style

mgui_widget_t* chart = gui_pie_chart_create(
    screen, 650, 450, 200, 150, 5
);

// Start from left (creates semi-circle)
gui_pie_chart_set_start_angle(chart, 180);

// Equal segments for gauge
for (int i = 0; i < 5; i++) {
    gui_pie_chart_set_value(chart, i, 20);
}

// Color gradient (green to red)
gui_pie_chart_set_slice_color(chart, 0, MGUI_COLOR_GREEN);
gui_pie_chart_set_slice_color(chart, 1, MGUI_COLOR_YELLOW);
gui_pie_chart_set_slice_color(chart, 2, MGUI_COLOR_ORANGE);
gui_pie_chart_set_slice_color(chart, 3, MGUI_COLOR_ORANGE);
gui_pie_chart_set_slice_color(chart, 4, MGUI_COLOR_RED);

// Make it a gauge (donut)
gui_pie_chart_set_radius(chart, 90);
gui_pie_chart_set_inner_radius(chart, 60);

Example 7: Real-Time Sensor Distribution

mgui_widget_t* sensor_pie = NULL;

void init_sensor_pie(mgui_widget_t* parent) {
    sensor_pie = gui_pie_chart_create(
        parent, 650, 250, 200, 200, 4
    );

    gui_pie_chart_set_style(sensor_pie, PIE_CHART_STYLE_GRADIENT);
    gui_pie_chart_set_label_mode(sensor_pie, PIE_CHART_LABEL_INSIDE);
}

// Update periodically
void update_sensors(int16_t temp, int16_t humid, int16_t press, int16_t light) {
    gui_pie_chart_set_value(sensor_pie, 0, temp);
    gui_pie_chart_set_value(sensor_pie, 1, humid);
    gui_pie_chart_set_value(sensor_pie, 2, press);
    gui_pie_chart_set_value(sensor_pie, 3, light);
}

Example 8: Minimal Pie (MCU-Friendly)

// Minimal configuration for low-end MCUs
mgui_widget_t* chart = gui_pie_chart_create(
    screen, 20, 20, 150, 150, 3  // Just 3 slices
);

gui_pie_chart_set_value(chart, 0, 50);
gui_pie_chart_set_value(chart, 1, 30);
gui_pie_chart_set_value(chart, 2, 20);

// Minimal styling (saves RAM and CPU)
gui_pie_chart_set_slice_color(chart, 0, MGUI_COLOR_BLUE);
gui_pie_chart_set_slice_color(chart, 1, MGUI_COLOR_GREEN);
gui_pie_chart_set_slice_color(chart, 2, MGUI_COLOR_RED);

gui_pie_chart_set_style(chart, PIE_CHART_STYLE_SOLID);
gui_pie_chart_set_label_mode(chart, PIE_CHART_LABEL_NONE);
gui_pie_chart_set_value_mode(chart, PIE_CHART_VALUE_NONE);
gui_pie_chart_set_radius(chart, 60);

More example

// pie_chart_examples.c - Comprehensive Pie Chart Examples

#include "gui_widget.h"

// ============================================================================
// Example 1: Basic Pie Chart (Market Share)
// ============================================================================
void example_market_share_pie(mgui_widget_t* parent) {
    // Create pie chart
    mgui_widget_t* chart = gui_pie_chart_create(
        parent,
        20, 20,              // Position
        300, 300,            // Size
        5                    // 5 slices
    );

    // Set market share data
    const int16_t market_data[] = {35, 25, 20, 15, 5};
    gui_pie_chart_set_values(chart, market_data, 5);

    // Set colors and labels
    const char* companies[] = {"Company A", "Company B", "Company C", "Company D", "Others"};
    const mgui_color_t colors[] = {
        MGUI_COLOR_BLUE,
        MGUI_COLOR_GREEN,
        MGUI_COLOR_ORANGE,
        MGUI_COLOR_RED,
        MGUI_COLOR_GRAY
    };

    for (int i = 0; i < 5; i++) {
        gui_pie_chart_set_slice_color(chart, i, colors[i]);
        gui_pie_chart_set_slice_label(chart, i, companies[i]);
    }

    // Configure appearance
    gui_pie_chart_set_style(chart, PIE_CHART_STYLE_SOLID);
    gui_pie_chart_set_label_mode(chart, PIE_CHART_LABEL_OUTSIDE);
    gui_pie_chart_set_value_mode(chart, PIE_CHART_VALUE_PERCENTAGE);

    DEBUG_PRINT("Market share pie chart created");
}

// ============================================================================
// Example 2: Donut Chart (Budget Breakdown)
// ============================================================================
void example_budget_donut(mgui_widget_t* parent) {
    // Create donut chart (pie with inner radius)
    mgui_widget_t* chart = gui_pie_chart_create(
        parent,
        350, 20,             // Position
        300, 300,            // Size
        6                    // 6 categories
    );

    // Set budget data
    gui_pie_chart_set_value(chart, 0, 30);  // Housing
    gui_pie_chart_set_value(chart, 1, 20);  // Food
    gui_pie_chart_set_value(chart, 2, 15);  // Transportation
    gui_pie_chart_set_value(chart, 3, 15);  // Utilities
    gui_pie_chart_set_value(chart, 4, 10);  // Entertainment
    gui_pie_chart_set_value(chart, 5, 10);  // Savings

    // Set labels and colors
    gui_pie_chart_set_slice_label(chart, 0, "Housing");
    gui_pie_chart_set_slice_color(chart, 0, MGUI_COLOR_RED);

    gui_pie_chart_set_slice_label(chart, 1, "Food");
    gui_pie_chart_set_slice_color(chart, 1, MGUI_COLOR_ORANGE);

    gui_pie_chart_set_slice_label(chart, 2, "Transport");
    gui_pie_chart_set_slice_color(chart, 2, MGUI_COLOR_YELLOW);

    gui_pie_chart_set_slice_label(chart, 3, "Utilities");
    gui_pie_chart_set_slice_color(chart, 3, MGUI_COLOR_GREEN);

    gui_pie_chart_set_slice_label(chart, 4, "Entertainment");
    gui_pie_chart_set_slice_color(chart, 4, MGUI_COLOR_BLUE);

    gui_pie_chart_set_slice_label(chart, 5, "Savings");
    gui_pie_chart_set_slice_color(chart, 5, MGUI_COLOR_CYAN);

    // Configure as donut (set inner radius)
    gui_pie_chart_set_radius(chart, 120);
    gui_pie_chart_set_inner_radius(chart, 60);  // Creates donut hole

    gui_pie_chart_set_style(chart, PIE_CHART_STYLE_GRADIENT);
    gui_pie_chart_set_label_mode(chart, PIE_CHART_LABEL_INSIDE);
    gui_pie_chart_set_value_mode(chart, PIE_CHART_VALUE_PERCENTAGE);

    DEBUG_PRINT("Budget donut chart created");
}

// ============================================================================
// Example 3: Interactive Pie Chart with Explosion
// ============================================================================
mgui_widget_t* interactive_pie = NULL;

void pie_slice_clicked(mgui_widget_t* obj, mgui_event_t event) {
    if (event & MGUI_EVENT_CLICKED) {
        int8_t selected = gui_pie_chart_get_selected(obj);
        if (selected >= 0) {
            DEBUG_PRINT("Slice %d clicked!", selected);
            // Show details, update info panel, etc.
        }
    }
}

void example_interactive_pie(mgui_widget_t* parent) {
    interactive_pie = gui_pie_chart_create(
        parent,
        20, 350,             // Position
        250, 250,            // Size
        4                    // 4 quarters
    );

    // Quarterly sales data
    const int16_t quarterly_sales[] = {120, 145, 132, 178};
    gui_pie_chart_set_values(interactive_pie, quarterly_sales, 4);

    // Set colors
    const mgui_color_t quarter_colors[] = {
        MGUI_COLOR_RED,
        MGUI_COLOR_ORANGE,
        MGUI_COLOR_YELLOW,
        MGUI_COLOR_GREEN
    };

    for (int i = 0; i < 4; i++) {
        char label[8];
        snprintf(label, sizeof(label), "Q%d", i + 1);
        gui_pie_chart_set_slice_label(interactive_pie, i, label);
        gui_pie_chart_set_slice_color(interactive_pie, i, quarter_colors[i]);
    }

    // Enable interaction
    gui_pie_chart_set_interactive(interactive_pie, true);
    gui_widget_set_click_handler(interactive_pie, pie_slice_clicked);

    // Configure
    gui_pie_chart_set_style(interactive_pie, PIE_CHART_STYLE_3D);
    gui_pie_chart_set_label_mode(interactive_pie, PIE_CHART_LABEL_OUTSIDE);
    gui_pie_chart_set_value_mode(interactive_pie, PIE_CHART_VALUE_BOTH);

    DEBUG_PRINT("Interactive pie chart created - click on slices!");
}

// ============================================================================
// Example 4: Pie Chart with Legend
// ============================================================================
void example_pie_with_legend(mgui_widget_t* parent) {
    mgui_widget_t* chart = gui_pie_chart_create(
        parent,
        300, 350,            // Position
        280, 250,            // Size (leave room for legend)
        7                    // 7 days
    );

    // Weekly activity data
    const char* days[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
    const int16_t activity[] = {8, 9, 7, 10, 9, 5, 6};
    const mgui_color_t day_colors[] = {
        MGUI_COLOR_RED,
        MGUI_COLOR_ORANGE,
        MGUI_COLOR_YELLOW,
        MGUI_COLOR_GREEN,
        MGUI_COLOR_CYAN,
        MGUI_COLOR_BLUE,
        MGUI_COLOR_PURPLE
    };

    gui_pie_chart_set_values(chart, activity, 7);

    for (int i = 0; i < 7; i++) {
        gui_pie_chart_set_slice_label(chart, i, days[i]);
        gui_pie_chart_set_slice_color(chart, i, day_colors[i]);
    }

    // Show legend instead of labels on pie
    gui_pie_chart_set_label_mode(chart, PIE_CHART_LABEL_LEGEND);
    gui_pie_chart_set_value_mode(chart, PIE_CHART_VALUE_PERCENTAGE);
    gui_pie_chart_set_style(chart, PIE_CHART_STYLE_SOLID);

    DEBUG_PRINT("Pie chart with legend created");
}

// ============================================================================
// Example 5: Simple 3-Slice Pie (Yes/No/Maybe)
// ============================================================================
void example_simple_survey_pie(mgui_widget_t* parent) {
    mgui_widget_t* chart = gui_pie_chart_create(
        parent,
        650, 20,
        200, 200,
        3                    // 3 slices
    );

    // Survey results
    gui_pie_chart_set_value(chart, 0, 45);  // Yes
    gui_pie_chart_set_value(chart, 1, 30);  // No
    gui_pie_chart_set_value(chart, 2, 25);  // Maybe

    gui_pie_chart_set_slice_label(chart, 0, "Yes");
    gui_pie_chart_set_slice_color(chart, 0, MGUI_COLOR_GREEN);

    gui_pie_chart_set_slice_label(chart, 1, "No");
    gui_pie_chart_set_slice_color(chart, 1, MGUI_COLOR_RED);

    gui_pie_chart_set_slice_label(chart, 2, "Maybe");
    gui_pie_chart_set_slice_color(chart, 2, MGUI_COLOR_YELLOW);

    // Simple style
    gui_pie_chart_set_style(chart, PIE_CHART_STYLE_SOLID);
    gui_pie_chart_set_label_mode(chart, PIE_CHART_LABEL_INSIDE);
    gui_pie_chart_set_value_mode(chart, PIE_CHART_VALUE_PERCENTAGE);
    gui_pie_chart_set_radius(chart, 80);

    DEBUG_PRINT("Simple survey pie chart created");
}

// ============================================================================
// Example 6: Real-Time Data Pie (Sensor Distribution)
// ============================================================================
mgui_widget_t* sensor_pie = NULL;

void example_sensor_distribution(mgui_widget_t* parent) {
    sensor_pie = gui_pie_chart_create(
        parent,
        650, 250,
        200, 200,
        4                    // 4 sensor types
    );

    // Initial sensor readings
    gui_pie_chart_set_value(sensor_pie, 0, 25);  // Temperature
    gui_pie_chart_set_value(sensor_pie, 1, 30);  // Humidity
    gui_pie_chart_set_value(sensor_pie, 2, 20);  // Pressure
    gui_pie_chart_set_value(sensor_pie, 3, 25);  // Light

    gui_pie_chart_set_slice_label(sensor_pie, 0, "Temp");
    gui_pie_chart_set_slice_color(sensor_pie, 0, MGUI_COLOR_RED);

    gui_pie_chart_set_slice_label(sensor_pie, 1, "Humid");
    gui_pie_chart_set_slice_color(sensor_pie, 1, MGUI_COLOR_BLUE);

    gui_pie_chart_set_slice_label(sensor_pie, 2, "Press");
    gui_pie_chart_set_slice_color(sensor_pie, 2, MGUI_COLOR_YELLOW);

    gui_pie_chart_set_slice_label(sensor_pie, 3, "Light");
    gui_pie_chart_set_slice_color(sensor_pie, 3, MGUI_COLOR_GREEN);

    gui_pie_chart_set_style(sensor_pie, PIE_CHART_STYLE_GRADIENT);
    gui_pie_chart_set_label_mode(sensor_pie, PIE_CHART_LABEL_INSIDE);
    gui_pie_chart_set_value_mode(sensor_pie, PIE_CHART_VALUE_ABSOLUTE);

    DEBUG_PRINT("Sensor distribution pie created");
}

// Update sensor readings
void update_sensor_data(int16_t temp, int16_t humid, int16_t press, int16_t light) {
    if (!sensor_pie) return;

    gui_pie_chart_set_value(sensor_pie, 0, temp);
    gui_pie_chart_set_value(sensor_pie, 1, humid);
    gui_pie_chart_set_value(sensor_pie, 2, press);
    gui_pie_chart_set_value(sensor_pie, 3, light);
}

// ============================================================================
// Example 7: Minimal Pie Chart (MCU-Friendly)
// ============================================================================
void example_minimal_pie(mgui_widget_t* parent) {
    // Minimal configuration for low-end MCUs
    mgui_widget_t* chart = gui_pie_chart_create(
        parent,
        20, 20,
        150, 150,
        3                    // Just 3 slices
    );

    // Simple data
    gui_pie_chart_set_value(chart, 0, 50);
    gui_pie_chart_set_value(chart, 1, 30);
    gui_pie_chart_set_value(chart, 2, 20);

    // Minimal styling (saves RAM and CPU)
    gui_pie_chart_set_slice_color(chart, 0, MGUI_COLOR_BLUE);
    gui_pie_chart_set_slice_color(chart, 1, MGUI_COLOR_GREEN);
    gui_pie_chart_set_slice_color(chart, 2, MGUI_COLOR_RED);

    gui_pie_chart_set_style(chart, PIE_CHART_STYLE_SOLID);
    gui_pie_chart_set_label_mode(chart, PIE_CHART_LABEL_NONE);
    gui_pie_chart_set_value_mode(chart, PIE_CHART_VALUE_NONE);
    gui_pie_chart_set_radius(chart, 60);

    DEBUG_PRINT("Minimal pie chart created (MCU-friendly)");
}

// ============================================================================
// Example 8: Exploded Pie Chart (Highlight Largest)
// ============================================================================
void example_exploded_pie(mgui_widget_t* parent) {
    mgui_widget_t* chart = gui_pie_chart_create(
        parent,
        400, 50,
        250, 250,
        5
    );

    // Data with one dominant value
    const int16_t data[] = {10, 15, 45, 20, 10};
    gui_pie_chart_set_values(chart, data, 5);

    // Colors
    const mgui_color_t colors[] = {
        MGUI_COLOR_LIGHT_GRAY,
        MGUI_COLOR_GRAY,
        MGUI_COLOR_BLUE,      // Largest - will be exploded
        MGUI_COLOR_DARK_GRAY,
        MGUI_COLOR_LIGHT_GRAY
    };

    for (int i = 0; i < 5; i++) {
        gui_pie_chart_set_slice_color(chart, i, colors[i]);
    }

    // Explode the largest slice (index 2)
    gui_pie_chart_explode_slice(chart, 2, true, 20);

    gui_pie_chart_set_style(chart, PIE_CHART_STYLE_3D);
    gui_pie_chart_set_label_mode(chart, PIE_CHART_LABEL_OUTSIDE);
    gui_pie_chart_set_value_mode(chart, PIE_CHART_VALUE_PERCENTAGE);

    DEBUG_PRINT("Exploded pie chart created (largest slice highlighted)");
}

// ============================================================================
// Example 9: Half Pie / Gauge Style
// ============================================================================
void example_gauge_pie(mgui_widget_t* parent) {
    mgui_widget_t* chart = gui_pie_chart_create(
        parent,
        650, 450,
        200, 150,            // Wider than tall
        5
    );

    // Create semi-circle (gauge-like)
    gui_pie_chart_set_start_angle(chart, 180);  // Start from left

    // Data for gauge sections
    gui_pie_chart_set_value(chart, 0, 20);  // Low
    gui_pie_chart_set_value(chart, 1, 20);  // Med-Low
    gui_pie_chart_set_value(chart, 2, 20);  // Medium
    gui_pie_chart_set_value(chart, 3, 20);  // Med-High
    gui_pie_chart_set_value(chart, 4, 20);  // High

    // Color gradient from green to red
    gui_pie_chart_set_slice_color(chart, 0, MGUI_COLOR_GREEN);
    gui_pie_chart_set_slice_color(chart, 1, MGUI_COLOR_YELLOW);
    gui_pie_chart_set_slice_color(chart, 2, MGUI_COLOR_ORANGE);
    gui_pie_chart_set_slice_color(chart, 3, (mgui_color_t){.value = 0xFF8000});  // Orange-red
    gui_pie_chart_set_slice_color(chart, 4, MGUI_COLOR_RED);

    // Make it a gauge (donut with inner radius)
    gui_pie_chart_set_radius(chart, 90);
    gui_pie_chart_set_inner_radius(chart, 60);

    gui_pie_chart_set_style(chart, PIE_CHART_STYLE_GRADIENT);
    gui_pie_chart_set_label_mode(chart, PIE_CHART_LABEL_NONE);
    gui_pie_chart_set_value_mode(chart, PIE_CHART_VALUE_NONE);

    DEBUG_PRINT("Gauge-style half pie created");
}

// ============================================================================
// Example 10: Comparison Pies (Side by Side)
// ============================================================================
void example_comparison_pies(mgui_widget_t* parent) {
    // First pie - Last Year
    mgui_widget_t* last_year = gui_pie_chart_create(
        parent, 50, 450, 150, 150, 4
    );

    const int16_t ly_data[] = {30, 25, 25, 20};
    gui_pie_chart_set_values(last_year, ly_data, 4);

    // Second pie - This Year
    mgui_widget_t* this_year = gui_pie_chart_create(
        parent, 220, 450, 150, 150, 4
    );

    const int16_t ty_data[] = {35, 30, 20, 15};
    gui_pie_chart_set_values(this_year, ty_data, 4);

    // Same colors for both
    const mgui_color_t colors[] = {
        MGUI_COLOR_BLUE,
        MGUI_COLOR_GREEN,
        MGUI_COLOR_ORANGE,
        MGUI_COLOR_RED
    };

    for (int i = 0; i < 4; i++) {
        gui_pie_chart_set_slice_color(last_year, i, colors[i]);
        gui_pie_chart_set_slice_color(this_year, i, colors[i]);
    }

    // Configure both
    gui_pie_chart_set_style(last_year, PIE_CHART_STYLE_SOLID);
    gui_pie_chart_set_style(this_year, PIE_CHART_STYLE_SOLID);
    gui_pie_chart_set_label_mode(last_year, PIE_CHART_LABEL_INSIDE);
    gui_pie_chart_set_label_mode(this_year, PIE_CHART_LABEL_INSIDE);
    gui_pie_chart_set_value_mode(last_year, PIE_CHART_VALUE_PERCENTAGE);
    gui_pie_chart_set_value_mode(this_year, PIE_CHART_VALUE_PERCENTAGE);

    DEBUG_PRINT("Comparison pies created (side by side)");
}

// ============================================================================
// Memory Usage Information
// ============================================================================
void pie_chart_memory_info(void) {
    DEBUG_PRINT("Pie Chart Memory Usage:");
    DEBUG_PRINT("  3 slices:  ~180 bytes");
    DEBUG_PRINT("  5 slices:  ~260 bytes");
    DEBUG_PRINT("  8 slices:  ~380 bytes");
    DEBUG_PRINT("  16 slices: ~710 bytes (max)");
    DEBUG_PRINT("");
    DEBUG_PRINT("Per slice: ~20 bytes (value, color, label, flags, explode)");
    DEBUG_PRINT("Base struct: ~80 bytes");
}

// ============================================================================
// Performance Tips
// ============================================================================
void pie_chart_performance_tips(void) {
    DEBUG_PRINT("Pie Chart Performance Tips:");
    DEBUG_PRINT("");
    DEBUG_PRINT("For STM32F1/ATmega (low-end):");
    DEBUG_PRINT("  - Use 3-5 slices maximum");
    DEBUG_PRINT("  - Use SOLID style (fastest)");
    DEBUG_PRINT("  - Disable labels (LABEL_NONE)");
    DEBUG_PRINT("  - Disable values (VALUE_NONE)");
    DEBUG_PRINT("  - Smaller radius (<80px)");
    DEBUG_PRINT("");
    DEBUG_PRINT("For STM32F4/ESP32 (mid-range):");
    DEBUG_PRINT("  - Use up to 8 slices");
    DEBUG_PRINT("  - GRADIENT and 3D styles OK");
    DEBUG_PRINT("  - Labels and values OK");
    DEBUG_PRINT("  - Interactive mode OK");
    DEBUG_PRINT("");
    DEBUG_PRINT("For STM32H7 (high-end):");
    DEBUG_PRINT("  - Use up to 16 slices");
    DEBUG_PRINT("  - All features enabled");
    DEBUG_PRINT("  - Multiple pies simultaneously");
    DEBUG_PRINT("  - Smooth animations");
}

Memory Usage

Number of Slices RAM Usage Notes
3 slices ~180 bytes Minimal
5 slices ~260 bytes Typical
8 slices ~380 bytes Good balance
16 slices ~710 bytes Maximum

Per Slice: ~20 bytes (value, color, label pointer, explode flags)

Additional Memory: - Extended struct: ~80 bytes - Angle cache: 2 bytes per slice - Labels: strlen + 1 bytes each (optional)

Performance Considerations

For Low-End MCUs (STM32F1, ATmega):

✅ Use 3-5 slices maximum
✅ Use PIE_CHART_STYLE_SOLID (fastest)
✅ Disable labels (LABEL_NONE)
✅ Disable values (VALUE_NONE)
✅ Smaller radius (<80px)
✅ Avoid explosion/interaction

For Mid-Range MCUs (STM32F4, ESP32):

✅ Use up to 8 slices
✅ Gradient and 3D styles OK
✅ Labels and values OK
✅ Interactive mode OK
✅ Donut charts OK

For High-End MCUs (STM32H7):

✅ Use up to 16 slices
✅ All features enabled
✅ Multiple charts simultaneously
✅ Smooth animations

Chart Types

Traditional Pie Chart

// Full circle, no inner radius
gui_pie_chart_set_inner_radius(chart, 0);

Donut Chart

// Circle with hole in center
gui_pie_chart_set_radius(chart, 120);
gui_pie_chart_set_inner_radius(chart, 60);

Half Pie / Semi-Circle

// Start from different angle to show half
gui_pie_chart_set_start_angle(chart, 180);  // Left
// or
gui_pie_chart_set_start_angle(chart, 270);  // Top

Gauge Style

// Combine half-pie with donut
gui_pie_chart_set_start_angle(chart, 180);
gui_pie_chart_set_inner_radius(chart, 60);

Comparison with Other Widgets

Feature Pie Chart Bar Chart Progress Bar
Data type Proportional Absolute/Relative Single value
Multiple values ✅ Yes ✅ Yes ❌ No
Visual style Circular Linear Linear
Space efficient ✅ Good ⚠️ Moderate ✅ Good
Easy to read ⚠️ <5 slices ✅ Yes ✅ Yes
Interaction ✅ Yes ✅ Yes ❌ No
Memory ~20B/slice ~18B/bar ~30B total

Common Use Cases

Business & Analytics

  • Market share distribution
  • Budget breakdown
  • Sales by category
  • Revenue by product
  • Resource allocation

Embedded Systems

  • Sensor distribution
  • Battery composition
  • Memory usage breakdown
  • Network traffic distribution
  • Task time allocation

Surveys & Polls

  • Yes/No/Maybe results
  • Rating distributions
  • Choice selections
  • Preference analysis

System Monitoring

  • Disk space usage
  • CPU core utilization
  • Memory allocation
  • Process distribution

Best Practices

DO:

✅ Use for proportional data (parts of a whole)
✅ Limit to 5-8 slices for readability
✅ Use different colors for each slice
✅ Start largest slice at 12 o'clock (top)
✅ Explode important slices to highlight them
✅ Use donut charts for better label space

DON'T:

❌ Use for comparing absolute values (use bar chart)
❌ Use >10 slices (unreadable)
❌ Use similar colors for adjacent slices
❌ Forget to set slice colors (all will be same)
❌ Explode all slices (defeats the purpose)
❌ Use 3D style on low-end MCUs (slow)

Troubleshooting

Q: Slices don't show
A: Check that all values are > 0 and colors are set

Q: Pie is too small
A: Increase radius with gui_pie_chart_set_radius()

Q: Labels overlap
A: Use LABEL_LEGEND mode or reduce number of slices

Q: Slow performance
A: Use SOLID style, disable labels/values, reduce slice count

Q: High RAM usage
A: Each slice uses ~20 bytes; reduce count or don't use labels

Q: Explosion doesn't work
A: Must call gui_pie_chart_explode_slice() with distance > 0

Future Enhancements

Potential features for future versions: - [ ] Animation on value change - [ ] Rotation animation - [ ] Multiple data series (nested pies) - [ ] Custom slice patterns - [ ] Export to image - [ ] Touch gestures - [ ] Smooth gradient colors - [ ] Shadow effects

Integration Checklist

  • [ ] Add MGUI_WIDGET_PIE_CHART to widget types enum
  • [ ] Add extended struct to gui_types.h
  • [ ] Add widget data to mgui_widget_t union
  • [ ] Include gui_widget_pie_chart.c in build
  • [ ] Add gui_draw_pie_chart() to gui_draw.c
  • [ ] Add case MGUI_WIDGET_PIE_CHART: in switch statements
  • [ ] Include fast_sin() and fast_cos() functions
  • [ ] Define MGUI_WIDGET_ENABLE_PIE_CHART in config
  • [ ] Test with examples

Mathematical Notes

Angle Calculation

Slice angle = (slice_value / total_value) × 360°

Percentage Calculation

Percentage = (slice_value / total_value) × 100%

Point on Circle

x = center_x + radius × cos(angle)
y = center_y + radius × sin(angle)

Explosion Offset

offset_x = explode_distance × cos(mid_angle)
offset_y = explode_distance × sin(mid_angle)

Conclusion

The Pie Chart widget provides an intuitive way to visualize proportional data in embedded GUIs. With support for both traditional pie charts and donut charts, multiple styling options, and interactive features, it's suitable for everything from simple dashboards to complex analytics displays.

Memory efficient design makes it practical even on low-end MCUs, while the full feature set enables sophisticated visualizations on more capable hardware. The slice explosion feature is particularly useful for highlighting important data points or creating engaging interactive experiences.

Perfect for displaying market share, budget breakdowns, survey results, or any data where the relationship between parts and the whole is important.