跳转至

Graphics_Complete_Examples.md

Source code

/**
 * @page Graphics_Complete_Examples Graphics Framework - Complete Code Examples
 *
 * @tableofcontents
 *
 * Comprehensive code examples demonstrating all graphics subsystem features,
 * organized by functional area: device setup, drawing operations, text widgets,
 * and complex UI compositions.
 *
 * ---
 *
 * @section PART_1 PART 1: Graphics Device Foundation
 *
 * @subsection GEx1_BasicGraphicsDevice Basic Graphics Device Setup
 *
 * The simplest example showing graphics device initialization:
 *
 * @code
 * #include "graphic_device.h"
 * #include "oled_graphic_device.h"
 * #include "oled.h"
 *
 * void example_basic_graphics_setup(void) {
 *     // Initialize OLED display
 *     CFBD_OLED oled;
 *     CFBD_OLED_IICInitsParams iic_params = {
 *         .device_address = SSD1309_DRIVER_ADDRESS,
 *         .i2c_handle = get_i2c_interface(),
 *     };
 *
 *     CFBD_GetOLEDHandle(&oled, CFBD_OLEDDriverType_IIC, &iic_params, CFBD_TRUE);
 *     oled.ops->open(&oled);
 *
 *     // Create graphics device and bind to OLED
 *     CFBD_GraphicDevice graphics;
 *     CFBDGraphic_BindOLEDAsDevice(&graphics, &oled);
 *     graphics.ops->open(&graphics);
 *
 *     // Graphics device is now ready to use
 * }
 * @endcode
 *
 * @subsection GEx2_ImmediateDrawing Immediate Drawing Mode
 *
 * Drawing with immediate updates after each operation:
 *
 * @code
 * void example_immediate_drawing(CFBD_GraphicDevice* graphics) {
 *     // Enable immediate draw mode
 *     CFBDGraphic_DeviceSetIfRequestUpdateAtOnce(graphics, CFBD_TRUE);
 *
 *     // Clear display (immediate update)
 *     graphics->ops->clear(graphics);
 *
 *     // Each pixel is visible immediately
 *     for (uint16_t x = 0; x < 128; x += 2) {
 *         graphics->ops->setPixel(graphics, x, 32);
 *         // Display updates automatically
 *     }
 * }
 * @endcode
 *
 * @subsection GEx3_DeferredDrawing Deferred Drawing Mode
 *
 * Batch drawing operations for better performance:
 *
 * @code
 * void example_deferred_drawing(CFBD_GraphicDevice* graphics) {
 *     // Enable deferred mode (batch operations)
 *     CFBDGraphic_DeviceSetIfRequestUpdateAtOnce(graphics, CFBD_FALSE);
 *
 *     // Clear display (buffered)
 *     graphics->ops->clear(graphics);
 *
 *     // Draw multiple pixels without updating display
 *     for (uint16_t y = 0; y < 64; y += 4) {
 *         for (uint16_t x = 0; x < 128; x += 4) {
 *             graphics->ops->setPixel(graphics, x, y);
 *         }
 *     }
 *
 *     // Update display once with all changes
 *     graphics->ops->update(graphics);
 * }
 * @endcode
 *
 * @subsection GEx4_AreaOperations Area-Based Drawing
 *
 * Efficient rectangular area operations:
 *
 * @code
 * void example_area_operations(CFBD_GraphicDevice* graphics) {
 *     uint8_t bitmap[32] = {0};  // 16x16 pixel bitmap
 *
 *     // Draw bitmap to area
 *     graphics->ops->setArea(graphics, 56, 24, 16, 16, bitmap);
 *
 *     // Update only affected area
 *     graphics->ops->update_area(graphics, 56, 24, 16, 16);
 * }
 * @endcode
 *
 * @subsection GEx5_QueryDeviceProperties Query Device Properties
 *
 * Getting display capabilities:
 *
 * @code
 * void example_query_device(CFBD_GraphicDevice* graphics) {
 *     uint16_t width = 0, height = 0;
 *     CFBD_bool is_rgb = CFBD_FALSE;
 *
 *     // Query display dimensions
 *     graphics->ops->self_consult(graphics, "width", NULL, &width);
 *     graphics->ops->self_consult(graphics, "height", NULL, &height);
 *
 *     // Query color capability
 *     graphics->ops->self_consult(graphics, "rgb", NULL, &is_rgb);
 *
 *     printf("Display: %u x %u %s\n",
 *            width, height,
 *            is_rgb ? "RGB" : "Monochrome");
 * }
 * @endcode
 *
 * @subsection GEx6_ModeToggling Dynamic Mode Switching
 *
 * Switching between immediate and deferred modes:
 *
 * @code
 * void example_mode_switching(CFBD_GraphicDevice* graphics) {
 *     // Check current mode
 *     if (CFBDGraphic_DeviceRequestUpdateAtOnce(graphics)) {
 *         printf("Currently in immediate mode\n");
 *     } else {
 *         printf("Currently in deferred mode\n");
 *     }
 *
 *     // Switch to deferred mode
 *     CFBDGraphic_DeviceSetIfRequestUpdateAtOnce(graphics, CFBD_FALSE);
 *
 *     // Perform batch operations
 *     for (int i = 0; i < 100; i++) {
 *         graphics->ops->setPixel(graphics, i, 32);
 *     }
 *     graphics->ops->update(graphics);
 *
 *     // Switch back to immediate
 *     CFBDGraphic_DeviceSetIfRequestUpdateAtOnce(graphics, CFBD_TRUE);
 * }
 * @endcode
 *
 * @subsection GEx7_ClearImmediately Clear Display Utility
 *
 * Using the clear immediate convenience function:
 *
 * @code
 * void example_clear_immediate(CFBD_GraphicDevice* graphics) {
 *     // Clear entire display with single operation
 *     CFBDGraphic_DeviceClearImmediate(graphics);
 *
 *     // Equivalent to:
 *     // graphics->ops->clear(graphics);
 *     // graphics->ops->update(graphics);
 * }
 * @endcode
 *
 * ---
 *
 * @section PART_2 PART 2: Animation and Rendering
 *
 * @subsection GEx8_AnimatedFrames Animated Frame Rendering
 *
 * Smooth animation with frame-based timing:
 *
 * @code
 * void example_animated_frames(CFBD_GraphicDevice* graphics) {
 *     CFBD_BaseAnimation anim;
 *     CFBD_InitBaseAnimation(&anim);
 *     anim.anim_frames = 16;
 *     anim.anim_frame_delay_ms = 50;
 *
 *     // Disable immediate mode for batch updates
 *     CFBDGraphic_DeviceSetIfRequestUpdateAtOnce(graphics, CFBD_FALSE);
 *
 *     for (uint8_t frame = 0; frame < anim.anim_frames; frame++) {
 *         graphics->ops->clear(graphics);
 *
 *         // Draw frame-dependent content
 *         uint16_t y = 16 + (frame * 3);  // Animate Y position
 *         graphics->ops->setPixel(graphics, 64, y);
 *
 *         graphics->ops->update(graphics);
 *
 *         if (anim.anim_frame_delay_ms > 0) {
 *             HAL_Delay(anim.anim_frame_delay_ms);
 *         }
 *     }
 * }
 * @endcode
 *
 * @subsection GEx9_CompleteAnimation Complete Animated Scene
 *
 * Full example combining multiple concepts:
 *
 * @code
 * #include "graphic_device.h"
 * #include "oled_graphic_device.h"
 * #include "oled.h"
 * #include "widget/animation/animation.h"
 * #include "widget/base_support/common/helpers.h"
 *
 * void example_complete_animation(void) {
 *     // Initialize OLED
 *     CFBD_OLED oled;
 *     CFBD_OLED_IICInitsParams iic_params = {
 *         .device_address = SSD1309_DRIVER_ADDRESS,
 *         .i2c_handle = get_i2c_interface(),
 *     };
 *     CFBD_GetOLEDHandle(&oled, CFBD_OLEDDriverType_IIC, &iic_params, CFBD_TRUE);
 *     oled.ops->open(&oled);
 *
 *     // Create graphics device
 *     CFBD_GraphicDevice graphics;
 *     CFBDGraphic_BindOLEDAsDevice(&graphics, &oled);
 *     graphics.ops->open(&graphics);
 *     CFBDGraphic_DeviceSetIfRequestUpdateAtOnce(&graphics, CFBD_FALSE);
 *
 *     // Setup animation
 *     CFBD_BaseAnimation anim;
 *     CFBD_InitBaseAnimation(&anim);
 *     anim.anim_frames = 8;
 *     anim.anim_frame_delay_ms = 50;
 *
 *     // Animate bouncing ball
 *     for (uint8_t frame = 0; frame < anim.anim_frames; frame++) {
 *         graphics.ops->clear(&graphics);
 *
 *         // Calculate position
 *         int16_t x = 64 + 30 * (frame % 4) - 45;
 *         int16_t y = 32 + (frame * 2);
 *
 *         // Clamp to display bounds
 *         x = clamp_i32(x, 0, 127);
 *         y = clamp_i32(y, 0, 63);
 *
 *         // Draw ball
 *         graphics.ops->setPixel(&graphics, x, y);
 *         graphics.ops->update(&graphics);
 *
 *         HAL_Delay(anim.anim_frame_delay_ms);
 *     }
 *
 *     // Cleanup
 *     graphics.ops->close(&graphics);
 *     oled.ops->close(&oled);
 * }
 * @endcode
 *
 * @subsection GEx10_UtilityFunctions Using Utility Functions
 *
 * Applying helper utilities in graphics code:
 *
 * @code
 * #include "widget/base_support/common/helpers.h"
 *
 * void example_utility_functions(CFBD_GraphicDevice* graphics) {
 *     int width = 128, height = 64;
 *
 *     // Clamp coordinate to valid range
 *     int user_x = get_user_input();
 *     int x = clamp_i32(user_x, 0, width - 1);
 *
 *     // Find center
 *     int center_x = MAX(0, width / 2);
 *     int center_y = MIN(64, height / 2);
 *
 *     // Draw centered point
 *     graphics->ops->setPixel(graphics, center_x, center_y);
 *     graphics->ops->update(graphics);
 * }
 * @endcode
 *
 * @subsection GEx11_ResourceConfiguration Resource Configuration
 *
 * Configuring graphics resources:
 *
 * @code
 * // In your project, before including graphics headers:
 *
 * // Option 1: Keep all defaults
 * #include "graphic/resource/config.h"
 *
 * // Option 2: Disable all, then enable selectively
 * #define _USE_NO_DEFAULT_SOURCES
 * #include "graphic/resource/config.h"
 *
 * // Option 3: Disable specific resources
 * #define DISABLE_ASCII_6X8_SOURCES
 * #include "graphic/resource/config.h"
 * // Now only 8x16 font is available
 * @endcode
 *
 * ---
 *
 * @section PART_3 PART 3: Text Widget Examples
 *
 * @subsection TEx1_BasicText Basic Text Rendering
 *
 * Simple text display on graphics device:
 *
 * @code
 * void example_basic_text(CFBD_GraphicDevice* dev) {
 *     CFBDGraphic_Text text;
 *     CFBDGraphic_Point pos = {0, 0};
 *     CFBDGraphicSize area = {128, 16};
 *     CFBDGraphic_InitText(&text, pos, area, ASCII_8x16);
 *
 *     CFBDGraphic_SetText(&text, "Hello!");
 *     CFBDGraphic_DrawText(dev, &text, CCGraphic_AsciiTextItem_AppendContinously);
 *
 *     dev->ops->update(dev);
 * }
 * @endcode
 *
 * @subsection TEx2_MultipleTexts Multiple Text Elements
 *
 * Rendering multiple independent text widgets:
 *
 * @code
 * void example_multiple_texts(CFBD_GraphicDevice* dev) {
 *     CFBDGraphic_Text title, status;
 *
 *     // Title at top
 *     CFBDGraphic_Point title_pos = {0, 0};
 *     CFBDGraphicSize title_area = {128, 16};
 *     CFBDGraphic_InitText(&title, title_pos, title_area, ASCII_8x16);
 *     CFBDGraphic_SetText(&title, "Game Status");
 *     CFBDGraphic_DrawText(dev, &title, CCGraphic_AsciiTextItem_AppendContinously);
 *
 *     // Status at bottom
 *     CFBDGraphic_Point status_pos = {0, 50};
 *     CFBDGraphicSize status_area = {128, 14};
 *     CFBDGraphic_InitText(&status, status_pos, status_area, ASCII_6x8);
 *     CFBDGraphic_SetText(&status, "Running... 60FPS");
 *     CFBDGraphic_DrawText(dev, &status, CCGraphic_AsciiTextItem_AppendContinously);
 *
 *     dev->ops->update(dev);
 * }
 * @endcode
 *
 * @subsection TEx3_MultilineText Multiline Text with Breaks
 *
 * Multiple lines with explicit line breaks:
 *
 * @code
 * void example_multiline_text(CFBD_GraphicDevice* dev) {
 *     CFBDGraphic_Text text;
 *     CFBDGraphic_Point pos = {0, 0};
 *     CFBDGraphicSize area = {128, 64};
 *     CFBDGraphic_InitText(&text, pos, area, ASCII_8x16);
 *
 *     // First line
 *     CFBDGraphic_SetText(&text, "Line 1");
 *     CFBDGraphic_DrawText(dev, &text, CCGraphic_AsciiTextItem_AppendContinously);
 *
 *     // Second line
 *     CFBDGraphic_SetText(&text, "Line 2");
 *     CFBDGraphic_DrawText(dev, &text, CCGraphic_AsciiTextItem_AppendNextLine);
 *
 *     // Third line
 *     CFBDGraphic_SetText(&text, "Line 3");
 *     CFBDGraphic_DrawText(dev, &text, CCGraphic_AsciiTextItem_AppendNextLine);
 *
 *     dev->ops->update(dev);
 * }
 * @endcode
 *
 * @subsection TEx4_ContinuousText Continuous Text with Auto-Wrap
 *
 * Text that wraps automatically:
 *
 * @code
 * void example_continuous_text(CFBD_GraphicDevice* dev) {
 *     CFBDGraphic_Text text;
 *     CFBDGraphic_Point pos = {0, 0};
 *     CFBDGraphicSize area = {128, 64};
 *     CFBDGraphic_InitText(&text, pos, area, ASCII_6x8);
 *
 *     // Long text automatically wraps
 *     CFBDGraphic_SetText(&text, "This is a long text that will wrap");
 *     CFBDGraphic_DrawText(dev, &text, CCGraphic_AsciiTextItem_AppendContinously);
 *
 *     dev->ops->update(dev);
 * }
 * @endcode
 *
 * @subsection TEx5_DynamicText Dynamic Text with sprintf
 *
 * Formatted text with variables:
 *
 * @code
 * void example_dynamic_text(CFBD_GraphicDevice* dev, int score, int lives) {
 *     CFBDGraphic_Text text;
 *     CFBDGraphic_Point pos = {0, 55};
 *     CFBDGraphicSize area = {128, 8};
 *     CFBDGraphic_InitText(&text, pos, area, ASCII_6x8);
 *
 *     char buffer[32];
 *     sprintf(buffer, "Score:%d Lives:%d", score, lives);
 *     CFBDGraphic_SetText(&text, buffer);
 *     CFBDGraphic_DrawText(dev, &text, CCGraphic_AsciiTextItem_AppendContinously);
 *
 *     dev->ops->update(dev);
 * }
 * @endcode
 *
 * @subsection TEx6_FontSelection Font Selection with Config
 *
 * Conditional font usage based on compile-time configuration:
 *
 * @code
 * void example_font_selection(CFBD_GraphicDevice* dev) {
 *     CFBDGraphic_Text text;
 *     CFBDGraphic_Point pos = {0, 0};
 *     CFBDGraphicSize area = {128, 20};
 *
 * #if ENABLE_ASCII_8x16_SOURCES
 *     CFBDGraphic_InitText(&text, pos, area, ASCII_8x16);
 *     CFBDGraphic_SetText(&text, "Large Text");
 * #elif ENABLE_ASCII_6x8_SOURCES
 *     CFBDGraphic_InitText(&text, pos, area, ASCII_6x8);
 *     CFBDGraphic_SetText(&text, "Small Text");
 * #else
 *     printf("No ASCII fonts available\n");
 *     return;
 * #endif
 *
 *     CFBDGraphic_DrawText(dev, &text, CCGraphic_AsciiTextItem_AppendContinously);
 *     dev->ops->update(dev);
 * }
 * @endcode
 *
 * @subsection TEx7_TextMetrics Querying Text Metrics
 *
 * Get text size without rendering:
 *
 * @code
 * void example_text_metrics(CFBD_GraphicDevice* dev) {
 *     CFBDGraphic_Text text;
 *     CFBDGraphic_Point pos = {0, 0};
 *     CFBDGraphicSize area = {128, 64};
 *     CFBDGraphic_InitText(&text, pos, area, ASCII_8x16);
 *
 *     // Query text size
 *     CFBDGraphicSize font_size = __fetch_font_size(ASCII_8x16);
 *     printf("Font size: %u x %u pixels\n", font_size.width, font_size.height);
 *
 *     // Query next position without drawing
 *     CFBDGraphic_SetText(&text, "Sample");
 *     CFBDGraphic_Point end_pos = CFBDGraphic_DrawText(
 *         dev, &text,
 *         CCGraphic_AsciiTextItem_RequestOldPoint
 *     );
 *     printf("Text would end at (%u, %u)\n", end_pos.x, end_pos.y);
 * }
 * @endcode
 *
 * @subsection TEx8_TextRepositioning Repositioning Text
 *
 * Dynamic repositioning of text elements:
 *
 * @code
 * void example_reposition_text(CFBD_GraphicDevice* dev) {
 *     CFBDGraphic_Text text;
 *     CFBDGraphic_Point pos = {0, 0};
 *     CFBDGraphicSize area = {128, 32};
 *     CFBDGraphic_InitText(&text, pos, area, ASCII_8x16);
 *
 *     CFBDGraphic_SetText(&text, "Hello");
 *
 *     // Draw at original position
 *     CFBDGraphic_DrawText(dev, &text, CCGraphic_AsciiTextItem_AppendContinously);
 *     dev->ops->update(dev);
 *     HAL_Delay(500);
 *
 *     // Move to new position
 *     CFBDGraphic_Point new_pos = {30, 25};
 *     CFBDGraphic_SetTextTLPointPoint(&text, &new_pos);
 *
 *     dev->ops->clear(dev);
 *     CFBDGraphic_DrawText(dev, &text, CCGraphic_AsciiTextItem_AppendContinously);
 *     dev->ops->update(dev);
 * }
 * @endcode
 *
 * @subsection TEx9_CenteredText Centered Text
 *
 * Centering text horizontally:
 *
 * @code
 * void example_centered_text(CFBD_GraphicDevice* dev, const char* text_str) {
 *     CFBDGraphicSize font_size = __fetch_font_size(ASCII_8x16);
 *
 *     // Calculate text width
 *     size_t text_len = strlen(text_str);
 *     int text_width = text_len * (font_size.width + CFBDGraphic_TEXT_PADDING_WIDTH);
 *
 *     // Center horizontally (128 pixel display)
 *     int center_x = (128 - text_width) / 2;
 *     CFBDGraphic_Point pos = {center_x, 25};
 *
 *     CFBDGraphic_Text text;
 *     CFBDGraphicSize area = {text_width + 5, 16};
 *     CFBDGraphic_InitText(&text, pos, area, ASCII_8x16);
 *     CFBDGraphic_SetText(&text, (char*)text_str);
 *     CFBDGraphic_DrawText(dev, &text, CCGraphic_AsciiTextItem_AppendContinously);
 *
 *     dev->ops->update(dev);
 * }
 * @endcode
 *
 * @subsection TEx10_ScrollingText Scrolling Text Effect
 *
 * Horizontal text scrolling:
 *
 * @code
 * void example_scrolling_text(CFBD_GraphicDevice* dev) {
 *     const char* text_str = "Scrolling Text Example";
 *     CFBDGraphicSize font_size = __fetch_font_size(ASCII_8x16);
 *     int text_width = strlen(text_str) * (font_size.width + 1);
 *
 *     // Scroll from right to left
 *     for (int x = 128; x > -text_width; x -= 2) {
 *         CFBDGraphic_Text text;
 *         CFBDGraphic_Point pos = {x, 25};
 *         CFBDGraphicSize area = {text_width + 5, 16};
 *         CFBDGraphic_InitText(&text, pos, area, ASCII_8x16);
 *         CFBDGraphic_SetText(&text, (char*)text_str);
 *
 *         dev->ops->clear(dev);
 *         CFBDGraphic_DrawText(dev, &text, CCGraphic_AsciiTextItem_AppendContinously);
 *         dev->ops->update(dev);
 *
 *         HAL_Delay(50);
 *     }
 * }
 * @endcode
 *
 * ---
 *
 * @section PART_4 PART 4: Graphics Widget Examples (Image, Menu, Progress Bar)
 *
 * @subsection WEx1_BasicImage Basic Image Drawing
 *
 * Simple bitmap rendering:
 *
 * @code
 * void example_draw_bitmap(CFBD_GraphicDevice* dev) {
 *     uint8_t heart_bitmap[64] = {
 *         0x00, 0x00, 0x00, 0x00,
 *         0x66, 0x99, 0x99, 0x66,
 *         0xFF, 0xFF, 0xFF, 0xFF,
 *         0xFF, 0xFF, 0xFF, 0xFF,
 *         // ... (16x16 bitmap)
 *     };
 *
 *     CCGraphic_Image heart;
 *     CFBDGraphic_Point pos = {56, 24};
 *     CFBDGraphicSize size = {16, 16};
 *     CFBDGraphic_InitImage(&heart, &pos, &size, heart_bitmap);
 *
 *     dev->ops->clear(dev);
 *     CFBDGraphic_DrawImage(dev, &heart);
 *     dev->ops->update(dev);
 * }
 * @endcode
 *
 * @subsection WEx2_AnimatedImage Animated Image Transitions
 *
 * Multiple images with frame-based animation:
 *
 * @code
 * void example_animated_image(CFBD_GraphicDevice* dev) {
 *     CCGraphic_Image frames[4];
 *     uint8_t frame_data[4][64] = {...};  // 4 animation frames
 *     CFBDGraphic_Point pos = {48, 24};
 *     CFBDGraphicSize size = {32, 16};
 *
 *     // Initialize all frames
 *     for (int i = 0; i < 4; i++) {
 *         CFBDGraphic_InitImage(&frames[i], &pos, &size, frame_data[i]);
 *     }
 *
 *     // Animate through frames
 *     CFBD_BaseAnimation anim = {4, 100};  // 4 frames, 100ms each
 *     for (uint8_t frame = 0; frame < anim.anim_frames; frame++) {
 *         dev->ops->clear(dev);
 *         CFBDGraphic_DrawImage(dev, &frames[frame % 4]);
 *         dev->ops->update(dev);
 *         HAL_Delay(anim.anim_frame_delay_ms);
 *     }
 * }
 * @endcode
 *
 * @subsection WEx3_SimpleMenu Basic Menu
 *
 * Minimal menu with 3 items:
 *
 * @code
 * void on_item_selected(void* ctx) {
 *     printf("Item selected!\n");
 * }
 *
 * void example_simple_menu(CFBD_GraphicDevice* dev) {
 *     // Allocate item array
 *     CFBD_MenuItem items[3];
 *     CFBD_MenuItemGroup item_group = {items, 3, 0};
 *
 *     // Initialize menu
 *     CFBD_Menu menu;
 *     CFBD_InitMenu(&menu, dev, &item_group, 128);
 *
 *     // Add items
 *     CFBD_MenuItemCallbackPack cb = {on_item_selected, NULL};
 *     menu.operations->add_item(&menu, "Start", ASCII_8x16, &cb);
 *     menu.operations->add_item(&menu, "Options", ASCII_8x16, NULL);
 *     menu.operations->add_item(&menu, "Exit", ASCII_8x16, NULL);
 *
 *     // Draw menu
 *     menu.operations->immediate_draw(&menu);
 * }
 * @endcode
 *
 * @subsection WEx4_MenuNavigation Interactive Menu Navigation
 *
 * Simulated keyboard input and menu selection:
 *
 * @code
 * void example_menu_navigation(CFBD_GraphicDevice* dev) {
 *     // Setup menu (from previous example)
 *     CFBD_MenuItem items[5];
 *     CFBD_MenuItemGroup item_group = {items, 5, 0};
 *     CFBD_Menu menu;
 *     CFBD_InitMenu(&menu, dev, &item_group, 128);
 *
 *     for (int i = 0; i < 5; i++) {
 *         char label[16];
 *         sprintf(label, "Item %d", i + 1);
 *         menu.operations->add_item(&menu, label, ASCII_6x8, NULL);
 *     }
 *
 *     // Simulate navigation
 *     menu.operations->immediate_draw(&menu);
 *
 *     // Down arrow - move to next item
 *     OLED_Menu_SelectNext(&menu);
 *     menu.operations->immediate_draw(&menu);
 *     HAL_Delay(300);
 *
 *     // Down arrow again
 *     OLED_Menu_SelectNext(&menu);
 *     menu.operations->immediate_draw(&menu);
 *     HAL_Delay(300);
 *
 *     // Up arrow - move to previous
 *     OLED_Menu_SelectPrev(&menu);
 *     menu.operations->immediate_draw(&menu);
 *     HAL_Delay(300);
 *
 *     // Enter - activate current item
 *     menu.operations->activate_current(&menu);
 * }
 * @endcode
 *
 * @subsection WEx5_MenuWithIndicator Menu with Custom Indicator
 *
 * Menu with styled selection indicator:
 *
 * @code
 * void example_menu_with_indicator(CFBD_GraphicDevice* dev) {
 *     CFBD_MenuItem items[4];
 *     CFBD_MenuItemGroup item_group = {items, 4, 0};
 *     CFBD_Menu menu;
 *     CFBD_InitMenu(&menu, dev, &item_group, 120);
 *
 *     // Configure indicator
 *     CFBD_MenuIndicator indicator;
 *     CFBD_InitDefaultMenuIndicator(&indicator);
 *     indicator.width = 6;      // 6-pixel wide indicator
 *     indicator.x = 2;          // 2 pixels from left edge
 *     menu.operations->set_indicator_property(&menu, &indicator);
 *
 *     // Add items with callbacks
 *     CFBD_MenuItemCallbackPack cb1 = {on_item_selected, (void*)1};
 *     CFBD_MenuItemCallbackPack cb2 = {on_item_selected, (void*)2};
 *     menu.operations->add_item(&menu, "Play", ASCII_8x16, &cb1);
 *     menu.operations->add_item(&menu, "Settings", ASCII_8x16, &cb2);
 *     menu.operations->add_item(&menu, "About", ASCII_8x16, NULL);
 *     menu.operations->add_item(&menu, "Exit", ASCII_8x16, NULL);
 *
 *     // Draw
 *     menu.operations->immediate_draw(&menu);
 * }
 * @endcode
 *
 * @subsection WEx6_MenuWithAnimation Menu with Transitions
 *
 * Menu with animated selection changes:
 *
 * @code
 * void example_animated_menu(CFBD_GraphicDevice* dev) {
 *     CFBD_MenuItem items[3];
 *     CFBD_MenuItemGroup item_group = {items, 3, 0};
 *     CFBD_Menu menu;
 *     CFBD_InitMenu(&menu, dev, &item_group, 128);
 *
 *     menu.operations->add_item(&menu, "One", ASCII_8x16, NULL);
 *     menu.operations->add_item(&menu, "Two", ASCII_8x16, NULL);
 *     menu.operations->add_item(&menu, "Three", ASCII_8x16, NULL);
 *
 *     // Enable animation
 *     CFBD_BaseAnimation anim = {6, 40};  // 6 frames, 40ms per frame
 *     menu.operations->set_animation(&menu, &anim);
 *
 *     // Navigate with visual feedback
 *     for (int i = 0; i < 3; i++) {
 *         OLED_Menu_SelectNext(&menu);
 *         for (int f = 0; f < anim.anim_frames; f++) {
 *             menu.operations->immediate_draw(&menu);
 *             HAL_Delay(anim.anim_frame_delay_ms);
 *         }
 *     }
 * }
 * @endcode
 *
 * @subsection WEx7_BasicProgressBar Simple Progress Bar
 *
 * Basic progress bar with fill animation:
 *
 * @code
 * void example_progress_bar(CFBD_GraphicDevice* dev) {
 *     CFBD_ProgressBar progress;
 *     CFBDGraphic_Point pos = {10, 32};
 *     CFBDGraphicSize size = {108, 8};
 *     CFBD_ProgressBar_Init(&progress, dev, &pos, &size, 0, 100);
 *
 *     // Draw at different values
 *     for (int val = 0; val <= 100; val += 10) {
 *         dev->ops->clear(dev);
 *         progress.ops->set_value(&progress, val);
 *         progress.ops->immediate_draw(&progress);
 *         dev->ops->update(dev);
 *         HAL_Delay(100);
 *     }
 * }
 * @endcode
 *
 * @subsection WEx8_ProgressBarWithBorder Progress Bar with Border
 *
 * Styled progress bar with border and padding:
 *
 * @code
 * void example_styled_progress(CFBD_GraphicDevice* dev) {
 *     CFBD_ProgressBar progress;
 *     CFBDGraphic_Point pos = {10, 32};
 *     CFBDGraphicSize size = {108, 10};
 *     CFBD_ProgressBar_Init(&progress, dev, &pos, &size, 0, 100);
 *
 *     // Enable border and padding
 *     uint8_t border = 1;
 *     progress.ops->set_property(&progress, "border", &border);
 *     uint8_t padding = 1;
 *     progress.ops->set_property(&progress, "padding", &padding);
 *
 *     // Animate from 0 to 100
 *     for (int val = 0; val <= 100; val += 5) {
 *         dev->ops->clear(dev);
 *         progress.ops->set_value(&progress, val);
 *         progress.ops->immediate_draw(&progress);
 *         dev->ops->update(dev);
 *         HAL_Delay(50);
 *     }
 * }
 * @endcode
 *
 * @subsection WEx9_ProgressWithAnimation Progress Bar with Transitions
 *
 * Progress bar with frame-based animation:
 *
 * @code
 * void example_animated_progress(CFBD_GraphicDevice* dev) {
 *     CFBD_ProgressBar progress;
 *     CFBDGraphic_Point pos = {10, 32};
 *     CFBDGraphicSize size = {108, 8};
 *     CFBD_ProgressBar_Init(&progress, dev, &pos, &size, 0, 100);
 *
 *     // Configure animation
 *     CFBD_BaseAnimation anim = {4, 50};  // 4-frame, 50ms transitions
 *     progress.ops->set_property(&progress, "animation", &anim);
 *
 *     // Smooth progress animation
 *     for (int target = 10; target <= 100; target += 10) {
 *         for (int frame = 0; frame < anim.anim_frames; frame++) {
 *             int current = (progress.value * (anim.anim_frames - frame) +
 *                           target * frame) / anim.anim_frames;
 *             dev->ops->clear(dev);
 *             progress.ops->set_value(&progress, current);
 *             progress.ops->immediate_draw(&progress);
 *             dev->ops->update(dev);
 *             HAL_Delay(anim.anim_frame_delay_ms);
 *         }
 *     }
 * }
 * @endcode
 *
 * ---
 *
 * @section PART_5 PART 5: Complex UI Compositions
 *
 * @subsection TEx11_MenuText Menu with Text Items
 *
 * Text-based menu display:
 *
 * @code
 * void example_menu_text(CFBD_GraphicDevice* dev) {
 *     CFBDGraphic_Text menu;
 *     CFBDGraphic_Point pos = {10, 10};
 *     CFBDGraphicSize area = {108, 54};
 *     CFBDGraphic_InitText(&menu, pos, area, ASCII_8x16);
 *
 *     dev->ops->clear(dev);
 *
 *     // Title
 *     CFBDGraphic_SetText(&menu, "MENU");
 *     CFBDGraphic_DrawText(dev, &menu, CCGraphic_AsciiTextItem_AppendContinously);
 *
 *     // Menu items
 *     const char* items[] = {"Start", "Settings", "Exit"};
 *     for (int i = 0; i < 3; i++) {
 *         char item_text[16];
 *         sprintf(item_text, "%d. %s", i + 1, items[i]);
 *         CFBDGraphic_SetText(&menu, item_text);
 *         CFBDGraphic_DrawText(dev, &menu, CCGraphic_AsciiTextItem_AppendNextLine);
 *     }
 *
 *     dev->ops->update(dev);
 * }
 * @endcode
 *
 * @subsection TEx12_CompleteUI Complete UI with Mixed Text
 *
 * Complex interface combining multiple text elements:
 *
 * @code
 * void example_complete_ui(CFBD_GraphicDevice* dev, int score, int level) {
 *     CFBDGraphic_Text title, body, footer;
 *
 *     // Title
 *     CFBDGraphic_Point title_pos = {0, 0};
 *     CFBDGraphicSize title_size = {128, 16};
 *     CFBDGraphic_InitText(&title, title_pos, title_size, ASCII_8x16);
 *     CFBDGraphic_SetText(&title, "Game Screen");
 *     CFBDGraphic_DrawText(dev, &title, CCGraphic_AsciiTextItem_AppendContinously);
 *
 *     // Body text
 *     CFBDGraphic_Point body_pos = {0, 20};
 *     CFBDGraphicSize body_size = {128, 36};
 *     CFBDGraphic_InitText(&body, body_pos, body_size, ASCII_6x8);
 *     CFBDGraphic_SetText(&body, "Level in progress...");
 *     CFBDGraphic_DrawText(dev, &body, CCGraphic_AsciiTextItem_AppendContinously);
 *
 *     // Footer with stats
 *     CFBDGraphic_Point footer_pos = {0, 55};
 *     CFBDGraphicSize footer_size = {128, 8};
 *     CFBDGraphic_InitText(&footer, footer_pos, footer_size, ASCII_6x8);
 *     char footer_text[32];
 *     sprintf(footer_text, "Score:%d Level:%d", score, level);
 *     CFBDGraphic_SetText(&footer, footer_text);
 *     CFBDGraphic_DrawText(dev, &footer, CCGraphic_AsciiTextItem_AppendContinously);
 *
 *     dev->ops->update(dev);
 * }
 * @endcode
 *
 * @subsection WEx10_MultipleWidgets Multiple Widgets Together
 *
 * Complex UI with image, menu, and progress bar:
 *
 * @code
 * // Global state
 * typedef enum {
 *     SCREEN_MENU,
 *     SCREEN_LOADING,
 *     SCREEN_GAME
 * } ScreenState;
 *
 * void example_multi_widget_ui(CFBD_GraphicDevice* dev) {
 *     ScreenState screen = SCREEN_MENU;
 *
 *     // Setup menu
 *     CFBD_MenuItem items[3];
 *     CFBD_MenuItemGroup item_group = {items, 3, 0};
 *     CFBD_Menu menu;
 *     CFBD_InitMenu(&menu, dev, &item_group, 128);
 *     menu.operations->add_item(&menu, "Start Game", ASCII_8x16, NULL);
 *     menu.operations->add_item(&menu, "Settings", ASCII_8x16, NULL);
 *     menu.operations->add_item(&menu, "Exit", ASCII_8x16, NULL);
 *
 *     // Setup progress bar for loading screen
 *     CFBD_ProgressBar progress;
 *     CFBDGraphic_Point prog_pos = {10, 50};
 *     CFBDGraphicSize prog_sz = {108, 8};
 *     CFBD_ProgressBar_Init(&progress, dev, &prog_pos, &prog_sz, 0, 100);
 *     uint8_t border = 1;
 *     progress.ops->set_property(&progress, "border", &border);
 *
 *     // Setup image for loading screen
 *     uint8_t logo_bitmap[128] = {...};  // 32x32 logo
 *     CCGraphic_Image logo;
 *     CFBDGraphic_Point logo_pos = {48, 8};
 *     CFBDGraphicSize logo_sz = {32, 32};
 *     CFBDGraphic_InitImage(&logo, &logo_pos, &logo_sz, logo_bitmap);
 *
 *     while (1) {
 *         switch (screen) {
 *         case SCREEN_MENU:
 *             dev->ops->clear(dev);
 *             menu.operations->immediate_draw(&menu);
 *             // Handle input to change screen
 *             break;
 *
 *         case SCREEN_LOADING:
 *             CFBDGraphic_DrawImage(dev, &logo);
 *             for (int i = 0; i <= 100; i += 10) {
 *                 progress.ops->set_value(&progress, i);
 *                 progress.ops->immediate_draw(&progress);
 *                 dev->ops->update(dev);
 *                 HAL_Delay(100);
 *             }
 *             screen = SCREEN_GAME;
 *             break;
 *         }
 *     }
 * }
 * @endcode
 *
 * @subsection WEx11_WidgetBatching Batch Drawing for Performance
 *
 * Multiple widgets with deferred updates:
 *
 * @code
 * void example_batch_widgets(CFBD_GraphicDevice* dev) {
 *     // Enable deferred mode
 *     CFBDGraphic_DeviceSetIfRequestUpdateAtOnce(dev, CFBD_FALSE);
 *
 *     // Setup widgets
 *     CCGraphic_Image bg;
 *     CFBDGraphic_InitImage(&bg, &(CFBDGraphic_Point){0, 0},
 *                          &(CFBDGraphicSize){128, 64}, background_data);
 *
 *     CFBD_MenuItem items[2];
 *     CFBD_MenuItemGroup item_group = {items, 2, 0};
 *     CFBD_Menu menu;
 *     CFBD_InitMenu(&menu, dev, &item_group, 128);
 *     menu.operations->add_item(&menu, "Option 1", ASCII_6x8, NULL);
 *     menu.operations->add_item(&menu, "Option 2", ASCII_6x8, NULL);
 *
 *     CFBD_ProgressBar progress;
 *     CFBDGraphic_Point p = {20, 55};
 *     CFBDGraphicSize s = {88, 6};
 *     CFBD_ProgressBar_Init(&progress, dev, &p, &s, 0, 100);
 *
 *     // Draw all widgets, update only once
 *     dev->ops->clear(dev);
 *     CFBDGraphic_DrawImage(dev, &bg);
 *     menu.operations->immediate_draw(&menu);
 *     progress.ops->set_value(&progress, 75);
 *     progress.ops->immediate_draw(&progress);
 *     dev->ops->update(dev);  // Single update for all widgets
 * }
 * @endcode
 *
 * ---
 *
 * @see @ref Graphics_UserGuide - Detailed graphics framework guide
 * @see @ref Widget_UserGuide - Complete widget guide
 * @see @ref Text_UserGuide - Complete text guide
 * @see CFBD_GraphicDevice - Device structure
 * @see CFBD_Menu - Menu structure
 * @see CFBD_ProgressBar - Progress bar structure
 * @see CCGraphic_Image - Image structure
 * @see CFBDGraphic_Text - Text structure
 * @see CFBD_BaseAnimation - Animation structure
 */

Updated on 2026-02-03 at 13:21:55 +0000