# cigui ## CIGUI Style Guide This document outlines the coding standards and best practices for the CIGUI library. Following these guidelines ensures consistency across the project and makes the codebase more maintainable. ### General Principles - **Clarity over cleverness**: Write code that's easy to understand, not code that's clever. - **Consistency**: Follow established patterns within the codebase. - **Documentation**: Document public APIs thoroughly. - **Testability**: Write code that can be easily tested. ### Naming Conventions #### Files - Header files: `.hpp` for C++ headers, `.h` for C-compatible headers - Implementation files: `.cpp` - Template implementation files: `.inl` - File names: PascalCase (e.g., `GridLayout.hpp`) #### Classes and Types - Class names: PascalCase (e.g., `Button`, `GridLayout`) - Type aliases/typedefs: lowercase (e.g., `using view_ptr = std::shared_ptr`) - Enum names: PascalCase - Enum values: PascalCase/UPPERCASE (e.g., `enum class Alignment { TopLeft, Center, BottomRight }` or `enum class Direction { LEFT, UP, RIGHT, DOWN }`) #### Functions and Variables - API function names: camelCase (e.g., `getPosition()`, `setVisible()`) - Internal function names: lowercase (e.g. `render_view()`, `get_visibility()`) - Variable names: camelCase (e.g., `buttonText`, `isVisible`) - Member variables: prefix with `m_` + UpperCamelCase (e.g., `m_Position`, `m_Size`) - Static variables: prefix with `s_` + UpperCamelCase (e.g., `s_DefaultFont`) - Constants and macros: ALL_CAPS with underscores (e.g., `MAX_WIDGETS`, `CIGUI_API`) ### Code Structure #### Namespaces - All library code should be inside the `cig` namespace - Avoid deeply nested namespaces - Do not use `using namespace` in headers ```cpp // Good namespace cig { class Button : public View { // ... }; } // Bad using namespace sf; // Don't do this in headers ``` #### Headers - Always use include guards with project-specific prefix - Order includes as follows: 1. Related header 2. C++ standard library headers 3. Third-party library headers (SFML) 4. CIGUI headers - Forward declare classes when possible to reduce dependencies ```cpp // Example of a good header structure #pragma once #include #include #include #include #include namespace cig { class View; // Forward declaration class CIGUI_API Container { // Implementation }; } // namespace cig ``` #### Classes - Separate public, protected, and private sections - Order within sections: 1. Constructors/Destructors 2. Public methods 3. Event callbacks 4. Static methods 5. Member variables ```cpp class Button : public View { public: // Constructors/Destructors Button(); explicit Button(const std::string& text); ~Button() override; // Methods void setText(const std::string& text); const std::string& getText() const; // Event dispatcher EventDispatcher onClicked; protected: // Protected methods void updateAppearance(); private: // Private methods void initializeGraphics(); // Member variables std::string m_text; sf::RectangleShape m_background; bool m_isHovered; }; ``` ### Templates - Template implementation should be in `.inl` files - Use explicit instantiation for common types in DLLs - Document template parameters ```cpp // In .hpp file template class Container { // ... }; // Include the implementation #include // In .inl file template Container::Container() { // ... } // In .cpp file for explicit instantiation template class Container; template class Container; ``` ### C++ Features - **C++ Standard**: Use C++20 features where appropriate - **Smart Pointers**: Use `std::unique_ptr` for exclusive ownership, `std::shared_ptr` for shared ownership - **Auto**: Use `auto` when the type is obvious or when using iterators - **Range-based for loops**: Prefer over traditional for loops - **Lambdas**: Use for short callbacks and event handlers - **Move Semantics**: Support move operations where appropriate ### Comments and Documentation - Use Doxygen-style comments for public APIs - Comment complex algorithms and non-obvious code - Avoid redundant comments that just repeat the code ```cpp /** * @brief Creates a button with the specified label text * * @param text The text to display on the button * @param size The size of the button (default: 100x30) */ Button(const std::string& text, const sf::Vector2f& size = {100.f, 30.f}); ``` ### Error Handling - Use exceptions for exceptional cases only - Validate input parameters and handle edge cases - Document error conditions in function comments ### Memory Management - Prefer automatic memory management with smart pointers - Explicitly define ownership models in documentation - Design with RAII principles (Resource Acquisition Is Initialization) ### DLL/Shared Library Considerations - Use `CIGUI_API` macro for all classes and non-inline functions - Use `CIGUI_TEMPLATE_API` for template classes - Handle template instantiation properly (see Templates section) ### SFML Integration - Wrap SFML types when extending functionality - Use SFML conventions for graphics-related code - Don't expose SFML implementation details in public APIs when avoidable ### Testing - Write unit tests for core functionality - Test edge cases and error conditions - Create interactive examples for UI components ### Formatting - Indentation: 4 spaces (no tabs) - Line length: 100 characters maximum - Braces: Open brace on same line, close brace on new line - Space after keywords (if, for, while) - No space after function names - Place * and & with the type, not the variable name ```cpp // Good formatting example if (condition) { doSomething(); } else { doSomethingElse(); } void setPosition(const sf::Vector2f& position) { m_position = position; } ``` ### Best Practices - Prefer composition over inheritance - Design interfaces that are hard to use incorrectly - Follow the Rule of Five/Zero for class design - Make data members private and provide accessors when needed - Consider performance implications in UI code (avoid work in draw methods) --- This style guide is a living document and may evolve as the project grows. When in doubt, maintain consistency with the existing codebase. --- ## Goal ```cpp #include struct ContentView : public cig::View { void body() { cig::VStack( cig::SystemIcon("globe.fill"), cig::Text("Welcome to Cigui") ) } } struct SettingsView : public cig::View { void body() { cig::Tabbed( cig::Tab( ).tag("Tab 1"), cig::Tab( cig::VStack( cig::Text("Other Tab") ) ) ); } } struct MainApp : public cig::App { void body() { cig::WindowGroup()( cig::ViewWindow(new ContentView()), cig::SettingsWindow(new SettingsView()) ) } } ```