284 lines
No EOL
6.9 KiB
Markdown
284 lines
No EOL
6.9 KiB
Markdown
# 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: lowercase with underscores (e.g., `grid_layout.hpp`)
|
|
|
|
#### Classes and Types
|
|
|
|
- Class names: PascalCase (e.g., `Button`, `GridLayout`)
|
|
- Type aliases/typedefs: PascalCase (e.g., `using WidgetPtr = std::shared_ptr<View>`)
|
|
- Enum names: PascalCase
|
|
- Enum values: PascalCase (e.g., `enum class Alignment { TopLeft, Center, BottomRight }`)
|
|
|
|
#### Functions and Variables
|
|
|
|
- Function names: camelCase (e.g., `getPosition()`, `setVisible()`)
|
|
- Variable names: camelCase (e.g., `buttonText`, `isVisible`)
|
|
- Member variables: prefix with `m_` (e.g., `m_position`, `m_size`)
|
|
- Static variables: prefix with `s_` (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 <cigui/config.h>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <SFML/Graphics/Drawable.hpp>
|
|
#include <cigui/utils/rect.hpp>
|
|
|
|
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<MouseEvent> 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<typename T>
|
|
class Container {
|
|
// ...
|
|
};
|
|
|
|
// Include the implementation
|
|
#include <cigui/widgets/container.inl>
|
|
|
|
// In .inl file
|
|
template<typename T>
|
|
Container<T>::Container() {
|
|
// ...
|
|
}
|
|
|
|
// In .cpp file for explicit instantiation
|
|
template class Container<int>;
|
|
template class Container<std::string>;
|
|
```
|
|
|
|
### 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 <cigui.hpp>
|
|
|
|
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())
|
|
)
|
|
}
|
|
}
|
|
``` |