Avoiding instanceofs with GUI composites

I have a stack of custom Row widgets. Each of them is a label with some editComponent (often a JTextComponent). Rows are aware of their previous and next siblings (if a Row has no such sibling the corresponding field stores a null reference). The stack of Rows is wrapped in a custom Form object. Some Rows contain Forms which, in turn, contain other Rows. In other words, some Rows are composites. Now, the app requirements include transferring focus between Rows on arrow key events. For example, if I press Up, the row that is above the focused one should gain focus instead. While "up" and "down" are fluid concepts with dynamic layouts, that aspect could be ignored. The problem is I want to write it cleanly, without instanceof expressions. That means, the row that cedes its focus to, for example, the next row should have no knowledge of whether it's a "leaf" or a "composite" Row. A "leaf" row should simply focus its edit component, it's simple. But how should a "composite" Row process its focus gain? It could theoretically memoize its last focused nested row, then focus it. However, a "composite" row may have never been in focus before, so it doesn't appear to be the right approach. I could check the X coordinate of the previous focus owner. Unfortunately, I'm not sure how to get a previous focus owner: KeyboardFocusManager only has getFocusOwner(). But even if I find a way, checking the physical coordinates on a screen doesn't feel that much better than instanceof checks. To make it more concrete, how does Composite row, once it gets a requestFocus() call, know which of its two Leaf rows it should focus? The previous focus owner could be "above" as well as "below" it. (I omitted the Form component) So how do I square it all? Are there cases when you just can't avoid instanceof expressions, and you should just bite the bullet and put it (beside equals())?

Feb 10, 2025 - 13:32
 0
Avoiding instanceofs with GUI composites

I have a stack of custom Row widgets. Each of them is a label with some editComponent (often a JTextComponent). Rows are aware of their previous and next siblings (if a Row has no such sibling the corresponding field stores a null reference). The stack of Rows is wrapped in a custom Form object.

Some Rows contain Forms which, in turn, contain other Rows. In other words, some Rows are composites.

Now, the app requirements include transferring focus between Rows on arrow key events. For example, if I press Up, the row that is above the focused one should gain focus instead. While "up" and "down" are fluid concepts with dynamic layouts, that aspect could be ignored.

The problem is I want to write it cleanly, without instanceof expressions. That means, the row that cedes its focus to, for example, the next row should have no knowledge of whether it's a "leaf" or a "composite" Row.

A "leaf" row should simply focus its edit component, it's simple. But how should a "composite" Row process its focus gain? It could theoretically memoize its last focused nested row, then focus it. However, a "composite" row may have never been in focus before, so it doesn't appear to be the right approach. I could check the X coordinate of the previous focus owner. Unfortunately, I'm not sure how to get a previous focus owner: KeyboardFocusManager only has getFocusOwner(). But even if I find a way, checking the physical coordinates on a screen doesn't feel that much better than instanceof checks.

To make it more concrete, how does Composite row, once it gets a requestFocus() call, know which of its two Leaf rows it should focus? The previous focus owner could be "above" as well as "below" it.

enter image description here (I omitted the Form component)

So how do I square it all? Are there cases when you just can't avoid instanceof expressions, and you should just bite the bullet and put it (beside equals())?