# Espaciado (Gap)

> Cómo espaciar componentes sin Spacer — usando Gap, ingap/outgap y fracciones de layout.

Source: https://crossfly.dev/es/docs/ui/widgets/spacing — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# Espaciado (Gap)

> ⚠️ **`Spacer` fue eliminado** en la modernización 2026. Ya no hay un widget de espaciado. Para separar componentes usa, en orden de preferencia: **fracciones de layout** (`LAY_AUTO`/`LAY_FILL`/fracción), **`ingap`/`outgap`** de los componentes, o el valor `Gap` directamente.

`Gap` representa valores de espaciado (izquierda, arriba, derecha, abajo) con escala opcional. Se usa en toda la UI como **padding** (`ingap`), **margin** (`outgap`), y como espaciado interno de layouts. Un `Gap` puede ser:

- **píxeles fijos** — `Gap.ofPixels(...)`
- **relativo a la fuente** — `Gap.ofFont(...)` (escala con `font.scaledHeight()`, ideal para responsividad)
- **relativo a la pantalla** — `Gap.ofScreen(...)` (porcentaje de las dimensiones de la pantalla)

> 🟢 · **Paquete:** `dev.crossfly.ui` · **Extiende:** `Component` · **Relacionado:** `ComponentStyle.ingap`/`outgap`, layouts

## Cuándo usar
- Definir el padding interno de un componente (`ingap`) o el margen externo (`outgap`).
- Pasar espaciado a un layout (ej.: gaps entre celdas).
- Sustituir el antiguo `Spacer` por espacio proporcional.

## Cuándo NO usar
- Para "empujar" un componente y absorber el sobrante → usa una fila `LAY_FILL` en el `VerticalLayout`/`HorizontalLayout` (ver [`layouts/`](/docs/ui)), no un `Gap` fijo.

## Ejemplo completo (copiar, pegar y ejecutar)
```java
package com.exemplo;

import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.style.*;   // Styles, ButtonRole, State

/** Pantalla principal ejecutable. Apunta el launcher (classname) y corre: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      // Encabezado con altura natural
      add(LAY_AUTO, new Label("Cabeçalho"));

      // Botón alejado de los vecinos vía outgap (margen relativo a la fuente)
      Button b = new Button("Enviar").style(
         Styles.theme().button(ButtonRole.PRIMARY, State.NORMAL)
            .pressable()
            .outgap(Gap.ofFont(0.5f)));   // 0.5 × altura de la fuente en todos los lados
      add(LAY_AUTO, b);

      // Pie empujado hacia abajo: la fila LAY_FILL absorbe el sobrante vertical
      add(LAY_FILL, new Label("(espaço que sobra)"));
      add(LAY_AUTO, new Label("Rodapé"));
   }
}
```

> Los fragmentos siguientes muestran **solo el núcleo** (lo que va dentro de `onShow()`). Para ejecutar, colócalos en el esqueleto `MainWindow` de arriba.

### 1. Fracciones de layout (preferido)
```java
VerticalLayout col = new VerticalLayout();
col.add(LAY_AUTO, cabecalho);   // altura natural
col.add(LAY_FILL, conteudo);    // absorbe el sobrante (empuja el pie hacia abajo)
col.add(LAY_AUTO, rodape);
```

### 2. `ingap` / `outgap` en el estilo
```java
// Margen externo (aleja este componente de los vecinos) vía outgap relativo a la fuente
Button b = new Button("Enviar").style(
   Styles.theme().button(ButtonRole.PRIMARY, State.NORMAL)
      .pressable()
      .outgap(Gap.ofFont(0.5f)));   // 0.5 × altura de la fuente en todos los lados
container.add(LAY_AUTO, b);
```

### 3. `Gap` como padding interno
```java
Label card = new Label("Conteúdo do cartão").style(
   Styles.theme().label(LabelRole.BODY)
      .ingap(Gap.ofFont(1f, 0.5f, 1f, 0.5f)));  // L,T,R,B en unidades de fuente
container.add(LAY_AUTO, card);
```

## Fábricas (`Gap`)
| Fábrica | Escala | Uso |
|---|---|---|
| `Gap.ofPixels(float all)` / `ofPixels(l, t, r, b)` | píxeles fijos | valores absolutos |
| `Gap.ofFont(float all)` / `ofFont(l, t, r, b)` | × altura de la fuente por defecto | **responsivo** (recomendado) |
| `Gap.ofFont(Font, l, t, r, b)` | × altura de la fuente indicada | rebaseado a una fuente específica |
| `Gap.ofScreen(float all)` / `ofScreen(l, t, r, b)` | % de las dimensiones de la pantalla | espaciado proporcional a la pantalla |
| `Gap.none()` / `Gap.ZERO` | cero | sin espaciado |

## Propiedades y métodos
| Método | Tipo | Qué hace |
|---|---|---|
| `left()` / `top()` / `right()` / `bottom()` | `int` | valor resuelto en píxeles (ya aplica la escala) |
| `width()` / `height()` | `int` | suma horizontal (`left+right`) / vertical (`top+bottom`) en píxeles |
| `withFont(Font)` | `Gap` | rebasa los factores a otra fuente (si es font-relative) |
| `isFontRelative()` / `font()` | `boolean` / `Font` | consulta la base de escala |

## Buenas prácticas
- Para el "espacio que sobra", usa **una sola** fila `LAY_FILL` en el layout, no varios gaps.
- Reaprovecha `Gap.ZERO` para poner a cero el padding sin asignar objetos.

## Errores comunes
- **Buscar la clase `Spacer`:** ya no existe. Usa fracciones de layout / `Gap` / `ingap`/`outgap`.
- **Usar `Gap.ofPixels` para todo:** en pantallas de densidades diferentes el espaciado queda inconsistente; prefiere `ofFont`/`ofScreen`.
- **Intentar centrar con dos gaps fijos:** usa la alineación del layout o `LAY_FILL` a ambos lados.

## Ver también
- Guía del área: [`ui/`](/docs/ui) · Recetas: [`cookbook/`](/docs/cookbook)
- Concepto (constraints, responsividad): [`concepts/`](/docs/concepts)
- Componentes relacionados: [`Label`](/docs/ui/widgets/label) · [`Button`](/docs/ui/widgets/button)
