Saltar al contenido
CrossFly es 100% open sourceSíguenos en GitHub
CrossFlyCrossFly
Empezar

Esta página fue traducida automáticamente del portugués y puede contener errores. La versión en portugués es la canónica.

Cómo centralizar la navegación en un controller

Propósito. Esparcir new X().show() y hide() por las pantallas acopla la UI al grafo de navegación. Un controller concentra push/pop, da un punto único para logging/guardas y permite “cerrar hasta la raíz”. Solo orquesta la pila real del EventsProcessor.

APIs usadas

  • Window.show() / Window.hide() — push/pop en la pila (el controller solo les delega).
  • EventsProcessor.topWindow() — método estático que retorna la ventana de la cima (instance.windows.peek()).
  • EventsProcessor.instance.getLastWindow() — método de instancia; retorna la cima real de la pila (o null si está vacía). Úsalo cuando necesites comprobar si hay algo apilado sin lanzar excepción.

Nombres confirmados en la fuente de EventsProcessor: topWindow() (estático) y getLastWindow() (instancia). topWindow() hace windows.peek() y lanza si la pila está vacía; getLastWindow() retorna null en ese caso — prefiere este para verificaciones defensivas.

Ejemplo completo (copiar, pegar y ejecutar)

package com.exemplo;

import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;

/** Pantalla principal ejecutable: usa el controlador Nav para apilar/desapilar pantallas. */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      add(new Label("Tela raiz"));
      add(new Button("Abrir detalhe").onAction(e -> Nav.push(new OutraTela())));  // push mediante el controlador
   }
}

/** Pantalla apilada: cierra mediante el controlador (pop). */
class OutraTela extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      add(new Label("Detalhe"));
      add(new Button("Voltar").onAction(e -> Nav.pop()));  // pop mediante el controlador
   }
}

/** Controlador: fachada fina sobre la pila real del EventsProcessor. */
final class Nav
{
   private Nav() {}

   /** push: apila y muestra. */
   public static void push(Window w)
   {
      w.show();
   }

   /** pop: cierra la ventana superior, si la hay. */
   public static void pop()
   {
      Window top = EventsProcessor.instance.getLastWindow();  // null-safe
      if (top != null)
         top.hide();
   }

   /** ventana actualmente en la cima (puede ser null). */
   public static Window current()
   {
      return EventsProcessor.instance.getLastWindow();
   }
}

El fragmento de abajo muestra solo el núcleo. Para ejecutarlo, colócalo en el esqueleto MainWindow de arriba.

Fragmento mínimo

// verificado en la fuente: EventsProcessor.topWindow() (static) e instance.getLastWindow() (devuelve null si está vacía)
public final class Nav
{
   private Nav() {}

   /** push: apila y muestra. */
   public static void push(Window w)
   {
      w.show();
   }

   /** pop: cierra la ventana superior, si la hay. */
   public static void pop()
   {
      Window top = EventsProcessor.instance.getLastWindow();  // null-safe
      if (top != null)
         top.hide();
   }

   /** pop repetido hasta que quede solo 1 ventana (la raíz). */
   public static void popToRoot()
   {
      Window top;
      // mientras haya más de una ventana apilada, elimina la de la cima
      while ((top = EventsProcessor.instance.getLastWindow()) != null
             && top != EventsProcessor.topWindow()) { top.hide(); }
      // (para "volver a la raíz", cada hide() desapila una; ajusta el criterio de parada a tu app)
   }

   /** ventana actualmente en la cima (puede ser null). */
   public static Window current()
   {
      return EventsProcessor.instance.getLastWindow();
   }
}

// uso en las pantallas:
Nav.push(new DetalheTela());
// ...
Nav.pop();

Buenas prácticas:

  • No reimplementes la pila: el EventsProcessor ya es la fuente de la verdad. El controller es una fachada fina sobre show()/hide().
  • Las guardas de navegación (ej.: “¿hay cambios sin guardar?”) quedan naturales aquí: comprueba antes de pop() y, si es necesario, dispara un Alert de confirmación.
  • Cuidado con topWindow() cuando la pila puede estar vacía — hace peek() y lanza. Para código defensivo usa getLastWindow().

Profundiza

¿Te resultó útil esta página?