discontinuedPackage jet_cad_floor_plan has been discontinued and replaced by jet_cad_2d_plan.

handBack method

void handBack()

Hands the focus back to the node that had it before the panel fields -- the canvas.

One UnfocusDisposition.previouslyFocusedChild focuses the scope's most recent focused child other than this node. After Width then Height, or a Selection panel field then the page scale, that child is the earlier panel field, still in the scope's focus history (fix/post-07 F3). So the walk goes on while it lands on a panel field, in either panel: each step drops that field from the history, until the most recent child is not a panel field, or the history is empty and the scope itself takes the focus. Every step removes a node, and seen bounds the walk by the number of panel fields anyway.

A canvas click requests the focus itself, and the walk leaves that request alone: if it came first, the canvas is the scope's most recent child and the walk stops at it at once; if not, it lands after the walk. A plain unfocus() would not do: it clears the scope's history and takes the focus to the scope itself, even from that click, and with the focus on the route's scope no key reaches the shell's shortcuts.

The walk starts from the node that has the focus, which is not always this one. Enter comes from the focused field, but onTapOutside is armed from the field's focus at its last build: within one frame it can fire for a field that has since lost the focus -- tap Width, then tap the scale, then click the Page title before a frame (fix/post-07 F2F3b m1). Walking from this node there would find it unfocused, go on from the scale, step back to Width, and stop on Width, which seen already holds. From the focused node the walk passes both. And when the focused node is not a panel field, there is nothing to hand back.

Implementation

void handBack() {
  final seen = <FocusNode>{};
  FocusNode? node = hasFocus ? this : FocusManager.instance.primaryFocus;
  while (node is PanelFieldFocusNode && seen.add(node)) {
    node.unfocus(disposition: UnfocusDisposition.previouslyFocusedChild);
    node = node.enclosingScope?.focusedChild;
  }
}