# UI Components

This document describes the custom UI components available in the Skelly project.

## ValueStepper Component

### Overview

**ValueStepper** is a reusable UI control for stepping through discrete values with left/right arrow navigation. It provides an intuitive interface for selecting from predefined options and is particularly well-suited for game settings menus.

**Location**: `scenes/ui/components/ValueStepper.tscn` and `scenes/ui/components/ValueStepper.gd`

### Why ValueStepper Exists

Godot's built-in controls have limitations for discrete option selection:
- **OptionButton**: Dropdown popups don't work well with gamepad navigation
- **SpinBox**: Designed for numeric values, not text options
- **HSlider**: Better for continuous values, not discrete choices

ValueStepper fills this gap by providing:
- ✅ **Gamepad-friendly** discrete option selection
- ✅ **No popup complications** - values displayed inline
- ✅ **Dual input support** - mouse clicks + keyboard/gamepad
- ✅ **Clean horizontal layout** with current value always visible
- ✅ **Perfect for game settings** like language, difficulty, resolution

### Features

- **Multiple Data Sources**: Built-in support for language, resolution, difficulty
- **Custom Values**: Easy setup with custom arrays of values
- **Navigation Integration**: Built-in highlighting and input handling
- **Signal-Based**: Clean event communication with parent scenes
- **Visual Feedback**: Automatic highlighting and animations
- **Audio Support**: Integrated click sounds
- **Flexible Display**: Separate display names and internal values

### Visual Structure

```
[<] [Current Value] [>]
```

- **Left Arrow Button** (`<`): Navigate to previous value
- **Value Display**: Shows current selection (e.g., "English", "Hard", "1920×1080")
- **Right Arrow Button** (`>`): Navigate to next value

## API Reference

### Signals

```gdscript
signal value_changed(new_value: String, new_index: int)
```
Emitted when the value changes, providing both the new value string and its index.

### Properties

```gdscript
@export var data_source: String = "language"
@export var custom_format_function: String = ""
```

- **data_source**: Determines the data type ("language", "resolution", "difficulty", or "custom")
- **custom_format_function**: Reserved for future custom formatting (currently unused)

### Key Methods

#### Setup and Configuration
```gdscript
func setup_custom_values(custom_values: Array[String], custom_display_names: Array[String] = [])
```
Configure the stepper with custom values and optional display names.

#### Value Management
```gdscript
func get_current_value() -> String
func set_current_value(value: String)
func change_value(direction: int)
```
Get, set, or modify the current value programmatically.

#### Navigation Integration
```gdscript
func set_highlighted(highlighted: bool)
func handle_input_action(action: String) -> bool
func get_control_name() -> String
```
Integration methods for navigation systems and visual feedback.

## Usage Examples

### Basic Usage in Scene

1. **Add to Scene**: Instance `ValueStepper.tscn` in your scene
2. **Set Data Source**: Configure the `data_source` property
3. **Connect Signal**: Connect the `value_changed` signal

```gdscript
# In your scene script
@onready var language_stepper: ValueStepper = $LanguageStepper

func _ready():
    language_stepper.value_changed.connect(_on_language_changed)

func _on_language_changed(new_value: String, new_index: int):
    print("Language changed to: ", new_value)
```

### Built-in Data Sources

#### Language Selection
```gdscript
# Set data_source = "language" in editor or code
language_stepper.data_source = "language"
```
Automatically loads available languages from SettingsManager.

#### Resolution Selection
```gdscript
# Set data_source = "resolution"
resolution_stepper.data_source = "resolution"
```
Provides common resolution options with display names.

#### Difficulty Selection
```gdscript
# Set data_source = "difficulty"
difficulty_stepper.data_source = "difficulty"
```
Provides difficulty levels: Easy, Normal, Hard, Nightmare.

### Custom Values

```gdscript
# Setup custom theme selector
var theme_values = ["light", "dark", "blue", "green"]
var theme_names = ["Light Theme", "Dark Theme", "Blue Theme", "Green Theme"]
theme_stepper.setup_custom_values(theme_values, theme_names)
theme_stepper.data_source = "theme"  # For better logging
```

### Navigation System Integration

```gdscript
# In a navigation-enabled menu
var navigable_controls: Array[Control] = []

func _setup_navigation():
    navigable_controls.append(volume_slider)
    navigable_controls.append(language_stepper)  # Add stepper to navigation
    navigable_controls.append(back_button)

func _update_visual_selection():
    for i in range(navigable_controls.size()):
        var control = navigable_controls[i]
        if control is ValueStepper:
            control.set_highlighted(i == current_index)
        else:
            # Handle other control highlighting
            pass

func _handle_input(action: String):
    var current_control = navigable_controls[current_index]
    if current_control is ValueStepper:
        if current_control.handle_input_action(action):
            AudioManager.play_ui_click()
            return true
    return false
```

## Integration Patterns

### Settings Menu Pattern
See `scenes/ui/SettingsMenu.gd` for a complete example of integrating ValueStepper into a settings menu with full navigation support.

### Multiple Steppers Navigation
See `examples/ValueStepperExample.gd` for an example showing multiple steppers with keyboard/gamepad navigation.

## Extending ValueStepper

### Adding New Data Sources

1. **Add to `_load_data()` method**:
```gdscript
func _load_data():
    match data_source:
        "language":
            _load_language_data()
        "your_custom_type":
            _load_your_custom_data()
        # ... other cases
```

2. **Implement your loader**:
```gdscript
func _load_your_custom_data():
    values = ["value1", "value2", "value3"]
    display_names = ["Display 1", "Display 2", "Display 3"]
    current_index = 0
```

3. **Add value application logic**:
```gdscript
func _apply_value_change(new_value: String, index: int):
    match data_source:
        "your_custom_type":
            # Apply your custom logic here
            YourManager.set_custom_setting(new_value)
```

### Custom Formatting

Override `_update_display()` for custom display formatting:

```gdscript
func _update_display():
    if data_source == "your_custom_type":
        # Custom formatting logic
        value_display.text = "Custom: " + display_names[current_index]
    else:
        super._update_display()  # Call parent implementation
```

## Best Practices

### When to Use ValueStepper
- ✅ **Discrete options**: Language, difficulty, resolution, theme
- ✅ **Settings menus**: Any option with predefined choices
- ✅ **Game configuration**: Graphics quality, control schemes
- ✅ **Limited options**: 2-10 options work best

### When NOT to Use ValueStepper
- ❌ **Continuous values**: Use sliders for volume, brightness
- ❌ **Large lists**: Use ItemList or OptionButton for 20+ items
- ❌ **Text input**: Use LineEdit for user-entered text
- ❌ **Numeric input**: Use SpinBox for number entry

### Performance Considerations
- ValueStepper is lightweight and suitable for multiple instances
- Data loading happens once in `_ready()`
- Visual updates are minimal (just text changes)

### Accessibility
- Visual highlighting provides clear focus indication
- Audio feedback confirms user actions
- Keyboard and gamepad support for non-mouse users
- Consistent navigation patterns

## Common Issues and Solutions

### Stepper Not Responding to Input
- Ensure `handle_input_action()` is called from parent's `_input()`
- Check that the stepper has proper focus/highlighting
- Verify input actions are defined in project input map

### Values Not Saving
- Override `_apply_value_change()` to handle persistence
- Connect to `value_changed` signal for custom save logic
- Ensure SettingsManager or your data manager is configured

### Display Names Not Showing
- Check that `display_names` array is properly populated
- Ensure `display_names.size()` matches `values.size()`
- Verify `_update_display()` is called after data loading

## File Structure

```
scenes/ui/components/
├── ValueStepper.gd          # Main component script
└── ValueStepper.tscn        # Component scene

examples/
├── ValueStepperExample.gd   # Usage example script
└── ValueStepperExample.tscn # Example scene

docs/
└── UI_COMPONENTS.md         # This documentation
```

This component provides a solid foundation for any game's settings system and can be easily extended for project-specific needs.