> For the complete documentation index, see [llms.txt](https://tanishisherewith.gitbook.io/dynamic-hud/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://tanishisherewith.gitbook.io/dynamic-hud/contextmenu/contextmenu-class.md).

# ContextMenu class

## ContextMenu

The `ContextMenu` class manages right-click menus for widgets in **DynamicHUD**. It stores menu options, menu state, and the skin-backed rendering logic used to display them.

### Key Properties

* **properties**: `ContextMenuProperties` used for styling, layout, and skin behavior.
* **options**: List of `Option<?>` instances shown in the menu.
* **screenFactory**: `ContextMenuScreenFactory` used by skins that open in a separate screen.
* **x, y**: Menu position.
* **scale**: Animation scale used while the menu opens and closes.

### Key Methods

* **addOption(Option\<?> option)**: Adds a menu option.
* **render(DrawContext, int, int, int, int)**: Renders the menu using the active skin.
* **open()**, **close()**, **toggleDisplay()**: Controls menu visibility.
* **createSubMenu(int, int, ContextMenuProperties)**: Creates nested menus for `SubMenuOption`.
* **mouseClicked(double, double, int)**: Handles menu and option interaction.

### LayoutEngine

From `4.0.0`, `ContextMenu` uses a `LayoutEngine` to position and size options. For the full node model and strategy API, see [LayoutEngine](/dynamic-hud/skin-system/layoutengine.md).

The layout engine controls:

* horizontal padding
* vertical padding
* spacing between items
* minimum menu width
* the active layout strategy

The default strategy is `VerticalFlowStrategy`. It places visible options in a single vertical column and expands the menu width to fit the longest option.

#### Key methods

* **applyLayout(ContextMenu\<?> menu)**: Runs the active strategy on the menu.
* **layoutOption(Option\<?> option, int x, int y, int targetWidth)**: Positions one option, applies width and height, and returns the next Y position.
* **setActiveStrategy(LayoutStrategy)**: Replaces the current layout strategy.
* **setHorizontalPadding(int)**, **setVerticalPadding(int)**, **setItemSpacing(int)**, **setMinWidth(int)**: Adjust layout spacing and sizing.

#### Notes

* Built-in skins use the default vertical flow layout.
* The active skin still decides which options are visible.
* The layout engine works with the option dimensions already provided by the skin renderer.

### Usage

Create the menu in your widget, then implement [ContextMenuProvider](/dynamic-hud/contextmenu/contextmenuprovider.md) and register it with [ContextMenuManager](/dynamic-hud/contextmenu/contextmenumanager.md).

Use [ContextMenuProperties](/dynamic-hud/contextmenu/contextmenuproperties.md) to define the skin and visual behavior.

Example:

```java
public class MyWidget extends Widget implements ContextMenuProvider {
    private ContextMenu<?> menu;
    private boolean enabled = true;
    private String alignment = "Left";
    private final List<String> alignments = Arrays.asList("Left", "Center", "Right");
    
    public MyWidget(...) {
        super(...);
        createMenu();
        ContextMenuManager.getInstance().registerProvider(this);
    }

    public void createMenu() {
        ContextMenuProperties properties = ContextMenuProperties.builder().build();
        menu = new ContextMenu<>(getX(), getY(), properties);

        menu.addOption(new BooleanOption("Enabled",
                () -> this.enabled, value -> this.enabled = value)
                .description("Turns this feature on or off")
        );

        menu.addOption(new CycleOption<>("Alignment",
                () -> this.alignment, value -> this.alignment = value, alignments)
                .description("Cycles between the available alignments")
        );
    }

    @Override
    public ContextMenu<?> getContextMenu() {
        return menu;
    }

    @Override
    public boolean mouseClicked(double mouseX, double mouseY, int button) {
        menu.toggleDisplay(widgetBox, mouseX, mouseY, button);
        return super.mouseClicked(mouseX, mouseY, button);
    }

    @Override
    public void onClose() {
        super.onClose();
        menu.close();
    }
}
```

{% hint style="warning" %}

* Ensure `properties` is valid before creating the menu.
* Register your provider, or the menu will not render through `ContextMenuManager`.
* Open the menu with `toggleDisplay(widgetBox, mouseX, mouseY, button)` or `menu.open()`, otherwise it will never show up.
  {% endhint %}
