ComboBoxes aren't effected by AffineTransform of parent?


#1

I’m working on a way to have my plugin UI scale and seeing as though Desktop::getInstance().setGlobalScaleFactor doesn’t really work for plugins (unless I’m wrong), I’ve resorted to a container component that has an AffineTransform applied to it and all other components are attached to the container. That works well for everything except ComboBoxes. And actually, the ComboBox looks fine in place until the dropdown list is displayed from a mouse click. It looks like dropdown list portion is not affected by the AffineTransform and displays at the original scale.

Am I missing something?


#2

By default, the dropdown menus are separate native windows and therefore not a child of the container. However, you can override this either for a single menu popup:

menu.showMenu (PopupMenu::Options().withParentComponent (myContainer))

or you can globally override this in your l&f

Component* MyLookAndFeel::getParentComponentForMenuOptions (const PopupMenu::Options& options) override
{
    if (options.getParentComponent() == nullptr && options.getTargetComponent() != nullptr)
                 return options.getTargetComponent()->getTopLevelComponent(); // <- assuming this component has the affine transform

    return LookAndFeel_V2::getParentComponentForMenuOptions (options);
}

The downside of this solution is that your popup menu will never be larger than the top-level component.


#3

Thanks for the reply. I now understand that the popup menu is a separate component of the ComboBox and actually a separate window. I’ll try the L&F method, but I’ll have to dig around my hierarchy to find the correct component. Seems kinda ugly.

Shouldn’t the ComboBox just have a option to just obey it’s parent’s transformation or not rather than having to dig around with L&F?


#4

I’m back at this one nagging issue with my plugin’s scaling…everything scales very easily because everything obeys my container’s AffineTransform. Everything except PopupMenus and the ComboxBox’s popupMenu.

@fabian, it would be so much simpler and straightforward if there was a way to give PopupMenu (and ComboBox) an AffineTransform. Everything else seems like a bad hack.

Thoughts?


#5

Hmmm ok let me have another look…


#6

OK this should be fixed with this commit on develop.

Does this work for you?


#7

Thank you for addressing this.

A couple of things:

This works with a ComboBox that’s a child of a transformed parent, but when displaying a PopupMenu that’s near the bottom of the screen, it draws below the bottom…meaning, it doesn’t know it’s off the screen.

Also, when using PopupMenu::showAt(&myComponent…), it works properly, but not when using PopupMenu::showMenu(options) with options.withParentComponent.


#8

Are you confusing parentComponent with targetComponent? When using parentComponent, your popup menu will not be a top-level window, but a child component of parentComponent. As it is a child component, the popup should have already transformed with it’s parent transform (even before my change). Obviously, the popup will only be limited to it’s parent window.

When parentComponent is null, the popup menu will be it’s own top-level window. The commit I pushed yesterday, will now transform the bounds of this window (and the contents) with the transform of the targetComponent. So, in summary, parentComponent should be null and targetComponent should point to the component which initiated the menu.


#9

Sorry, I wasn’t very clear.

One of my uses is for a right-click menu for some global things that the user could trigger anywhere in my plugin window. So, I don’t really have a targetComponent as such and want the menu to display at the mousePosition, but transformed by my container component which has the scale factor.

So, I can’t use show() or showAt() and when I use showMenu(), it ignores targetScreenArea and attaches to the side of the targetComponent, which in my case is the container component with the scale factor, but the position is incorrect. I can’t seem to get position and scale to work together…it’s either or.