Custom KeyboardFocusTraverser shadowed by LabelKeyboardFocusTraverser

I have a top level component, called MyFocusContainer. It has the focus container flag set to true and it overwrites createFocusTraverser() to return an instance of a custom MyCustomKeyboardFocusTraverser : public KeyboardFocusTraverser.

In this top level component, I have a bunch of subcomponents with controls (e.g. Labels) in them, like this:

- MyFocusContainer
    - SubComponentA 
        - Label
        - Knob
    - SubComponentB
        - Label
        - Label

When I edit a label and press tab, I would expect the focus to traverse the components according to the rules of my MyCustomKeyboardFocusTraverser. But that doesn’t happen. I found that MyCustomKeyboardFocusTraverser isn’t even instantiated, instead, whenever the focus is in a Label, it would not iterate upwards to the FocusContainer and create the focus traverser from there. Instead, it creates a LabelKeyboardFocusTraverser right away, which basically just calls the default implementations.

Because of this I can not apply any custom KeyboardFocusTraverser. At least not without also using a custom Label that stops LabelKeyboardFocusTraverser objects from being used instead of my own implementation. Is that supposed to behave like that?

Am I using the wrong approach? How can I implement a custom focusing order?

I just ran into this -it doesn’t seem a good default behaviour indeed. I think Label should forward focus traversing to the parent, like

struct ProxyFocusTraverser : KeyboardFocusTraverser
{
    ProxyFocusTraverser (Component* c)
        : c{ c }, traverser{ c->getParentComponent()->createFocusTraverser() } {}

    Component* getNextComponent (Component*) override
    {
        return traverser->getNextComponent (c);
    }

    Component* getPreviousComponent (Component*) override
    {
        return traverser->getPreviousComponent (c);
    }

private:
    Component* c;
    std::unique_ptr<KeyboardFocusTraverser> traverser;
};

KeyboardFocusTraverser* Label::createFocusTraverser()
{
    return new ProxyFocusTraverser (this);
}