Skip to content

Design Manager: Enhance Layout and Styling Systems for Modern, Fluid UI Development #9

@Toikron

Description

@Toikron

DesignManager (design_manager.h) is a comprehensive UI design tool built upon ImGui, offering powerful features like layers, advanced shape rendering (corners, borders, shadows, blur, gradients, glass), parenting hierarchies, Shape Keys for responsiveness, a sophisticated animation engine (ButtonAnimation, ChainAnimation), and code generation capabilities.

Despite its strengths, creating complex, responsive, and fluid user interfaces comparable to those built with modern web frameworks (e.g., React with CSS Flexbox/Grid) presents challenges. The current reliance on absolute positioning and manual adjustments often leads to what can be described as a "mathematics explosion" and repetitive style management, hindering rapid development and maintainability.

This issue outlines the core areas for improvement required to bridge this gap, aiming to enhance DesignManager's capabilities while preserving its existing powerful features. The primary focus is on fundamentally improving the Layout System and the Styling System to align better with modern UI development paradigms.

Areas for Improvement & Proposed Paths:

1. Layout System:

  • Current State:
    • Layout primarily relies on absolute positioning defined by ShapeItem::position and ShapeItem::size.
    • The ShapeKey mechanism provides adaptability based on window size, but it's rule-based and requires manual configuration for specific size transitions. It doesn't inherently handle the relative positioning of sibling elements.
    • Parenting (SetParent) establishes a transform hierarchy, but lacks an intrinsic mechanism for automatic content flow or dynamic arrangement of children within a container (analogous to CSS Flexbox or Grid).
    • Common layout scenarios like arranging items horizontally/vertically with spacing, wrapping content, distributing space, or centering groups require extensive manual calculations or complex ShapeKey setups.
  • Shortcomings:
    • Absence of an automatic, fluid, and constraint-based layout engine.
    • Significant manual effort ("math explosion") is needed for achieving responsive and adaptive layouts beyond simple ShapeKey rules.
    • Poor scalability for complex UIs where elements need to reflow dynamically.
  • Proposed Path (High Priority):
    • Introduce Container Elements:
      • Define new specialized ShapeItem types (e.g., FlexContainer, GridContainer, StackPanel) OR add layout modes/properties to the existing ShapeItem.
      • These containers will be responsible for measuring and arranging their child ShapeItems.
    • Implement Layout Properties: Equip container elements with properties to control child arrangement:
      • direction: Row, Column (for Flex/Stack)
      • justifyContent: Start, Center, End, SpaceBetween, SpaceAround, SpaceEvenly (distribution along the main axis)
      • alignItems: Start, Center, End, Stretch, Baseline (alignment along the cross axis)
      • gap: Spacing between child elements (pixels or potentially relative units).
      • wrap: NoWrap, Wrap, WrapReverse (for Flex)
      • (Grid-specific properties like templateColumns, templateRows could be added later if a Grid container is implemented)
    • Develop a Two-Pass Layout Engine (Measure/Arrange):
      • Measure Pass: Each container recursively asks its children how much space they desire (based on their content, fixed size, or constraints). The container then determines its own desired size based on its children and layout rules. This pass calculates the "intrinsic" or "desired" size.
      • Arrange Pass: Given the actual space allocated to the container (by its parent or the window), the container recursively positions and sizes its children according to its layout properties (direction, justifyContent, alignItems, gap, etc.) and the children's measured sizes/flexibility factors.
    • Implement Flexibility (Grow/Shrink): Allow child elements within layout containers to define flexibility factors:
      • growFactor: How much extra space the element should take up if the container has available space along the main axis.
      • shrinkFactor: How much the element should shrink if there isn't enough space in the container along the main axis.
      • basis (Optional): An initial size basis before flexing.

2. Styling System:

  • Current State:
    • Style attributes (fillColor, borderColor, cornerRadius, shadowColor, etc.) are defined directly as members of the ShapeItem struct.
    • Basic state styling exists via hoverColor and clickedColor.
    • Advanced styles like gradients and glass effects are handled through specific properties.
  • Shortcomings:
    • No mechanism for defining reusable styles or themes (like CSS classes). Applying consistent styling across multiple elements requires redundant property setting.
    • Lack of a standardized way to handle other common UI states (e.g., disabled, focused).
    • Difficult to perform global theme changes.
  • Proposed Path (Medium Priority):
    • Define a StyleData Struct/Class: Create a dedicated structure to encapsulate all visual styling attributes (colors, fonts, borders, shadows, gradients, potentially padding/margin if integrated with the layout system).
    • Implement a Central Style Repository (StyleSheet): Use a mechanism like std::map<std::string, StyleData> to define named, reusable styles.
    • Reference Styles from ShapeItem: Modify ShapeItem to hold references (e.g., std::string styleName or StyleID) to styles defined in the central repository, rather than holding all style properties directly. Allow overriding specific properties locally.
    • Introduce State-Based Styles: Enhance StyleData or the referencing mechanism to support variations for different states (normal, hover, active, disabled, focused). The DesignManager rendering logic should automatically query the appropriate style variant based on the element's current state (using ImGui::IsItemHovered(), ImGui::IsItemActive(), potentially adding a disabled flag to ShapeItem).
    • Consider Style Inheritance (Optional): Implement a simple inheritance model where child elements inherit style properties from their parent unless explicitly overridden.

3. Animation & Layout Integration:

  • Current State: The sophisticated animation engine (ButtonAnimation, ChainAnimation) primarily targets direct transform properties (position, size, rotation).
  • Shortcomings: Cannot fluidly animate layout-related properties (e.g., a FlexContainer's gap, an element's width percentage, a sidebar's overall width managed by the layout system). This prevents smooth transitions like the collapsing sidebar seen in the React example.
  • Proposed Path (Post-Layout System):
    • Extend the animation engine (UpdateShapeTransforms_Unified, UpdateChainAnimations) to allow targeting and interpolating layout-specific properties defined in the new Layout System (e.g., width, height (could be fixed, percentage, or 'auto'), growFactor, gap, potentially container-specific properties).
    • Ensure the Layout Engine re-runs its Measure and Arrange passes whenever animated layout properties change, allowing the UI to reflow smoothly during the animation.

4. Code Structure & Organization:

  • Current State: All code resides within a single, large header file (design_manager.h).
  • Shortcomings: Can lead to longer compile times, reduced maintainability, and potential namespace pollution as the system grows.
  • Proposed Path (Ongoing/Lower Priority):
    • Modularize: Refactor the code into logical modules (e.g., Core, Rendering, Layout, Animation, Styling, UI_Editor) with separate header (.h) and implementation (.cpp) files.
    • Namespace Usage: Enforce consistent use of the DesignManager namespace for all related structures, functions, and enums to prevent naming conflicts.

5. Component Model Refinement (Optional/Lower Priority):

  • Current State: ShapeItem serves as a monolithic entity handling rendering, styling, basic layout, animation, and behavior.
  • Shortcomings: Can make the ShapeItem struct overly complex and potentially violate the Single Responsibility Principle.
  • Proposed Path: Consider introducing more specialized component types, perhaps inheriting from a base UIElement or using ShapeItem via composition. Examples: TextLabel, ImageElement, Panel, ButtonBase, FlexContainer. This could improve code clarity and organization but requires significant refactoring. Evaluate if the benefits outweigh the costs after addressing layout and styling.

Proposed Roadmap (Prioritized):

  1. [Layout System] Design and implement the core layout container(s) (e.g., Flexbox-like) and the Measure/Arrange pass logic.
  2. [Styling System] Design and implement the StyleData structure and the central StyleSheet repository mechanism. Modify ShapeItem to use style references. Implement state-based styling application.
  3. [Animation/Layout Integration] Update the animation engine to target and interpolate layout properties. Integrate with the layout engine for smooth reflows.
  4. [Code Structure] Gradually refactor the codebase into separate modules and improve namespace consistency.
  5. [Component Model] Evaluate the need for and potentially implement more specialized component types.

Conclusion:

DesignManager provides a remarkable foundation for visual UI design within the ImGui ecosystem. Addressing the core Layout and Styling systems as outlined above will be crucial in elevating its capabilities to match the flexibility and developer experience offered by modern UI frameworks. These enhancements will significantly reduce the need for manual calculations, streamline the design workflow, and enable the creation of more complex, adaptive, and visually polished user interfaces.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions