This page was machine-translated from Portuguese and may contain errors. The Portuguese version is canonical.
How to centralize navigation in a controller
Purpose. Scattering new X().show() and hide() across screens couples the UI to the navigation graph. A controller concentrates push/pop, gives a single point for logging/guards, and enables “close down to the root”. It merely orchestrates the real EventsProcessor stack.
APIs used
Window.show()/Window.hide()— push/pop on the stack (the controller merely delegates to them).EventsProcessor.topWindow()— static method that returns the top window (instance.windows.peek()).EventsProcessor.instance.getLastWindow()— instance method; returns the real top of the stack (ornullif empty). Use it when you need to check whether something is stacked without throwing an exception.
Names confirmed in the
EventsProcessorsource:topWindow()(static) andgetLastWindow()(instance).topWindow()doeswindows.peek()and throws if the stack is empty;getLastWindow()returnsnullin that case — prefer this one for defensive checks.
Complete example (copy, paste and run)
package com.exemplo;
import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
/** Runnable main screen: uses the Nav controller to push/pop screens. */
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 via controller
}
}
/** Stacked screen: closes via controller (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 via controller
}
}
/** Controller: thin facade over the real EventsProcessor stack. */
final class Nav
{
private Nav() {}
/** push: stacks and displays. */
public static void push(Window w)
{
w.show();
}
/** pop: closes the topmost window, if any. */
public static void pop()
{
Window top = EventsProcessor.instance.getLastWindow(); // null-safe
if (top != null)
top.hide();
}
/** window currently on top (may be null). */
public static Window current()
{
return EventsProcessor.instance.getLastWindow();
}
}
The snippet below shows only the core. To run it, place it inside the
MainWindowskeleton above.
Minimal snippet
// verified in the source: EventsProcessor.topWindow() (static) and instance.getLastWindow() (returns null if empty)
public final class Nav
{
private Nav() {}
/** push: stacks and displays. */
public static void push(Window w)
{
w.show();
}
/** pop: closes the topmost window, if any. */
public static void pop()
{
Window top = EventsProcessor.instance.getLastWindow(); // null-safe
if (top != null)
top.hide();
}
/** repeated pop until only 1 window remains (the root). */
public static void popToRoot()
{
Window top;
// while there is more than one window stacked, drop the top one
while ((top = EventsProcessor.instance.getLastWindow()) != null
&& top != EventsProcessor.topWindow()) { top.hide(); }
// (to "return to root", each hide() pops one; adjust the stopping criterion to your app)
}
/** window currently on top (may be null). */
public static Window current()
{
return EventsProcessor.instance.getLastWindow();
}
}
// usage in screens:
Nav.push(new DetalheTela());
// ...
Nav.pop();
Best practices:
- Do not reimplement the stack: the
EventsProcessoris already the source of truth. The controller is a thin facade overshow()/hide(). - Navigation guards (e.g., “are there unsaved changes?”) fit naturally here: check before
pop()and, if needed, fire a confirmationAlert. - Be careful with
topWindow()when the stack may be empty — it doespeek()and throws. For defensive code usegetLastWindow().
Go deeper
- The window stack · Navigate between screens
- Sibling recipe: Open and close a screen
Was this page helpful?Thanks for the feedback!