For example, I have a custom ListBox implementation that I want to have rounded corners. It’s easy enough to draw the background of this component with rounded borders, but there’s no way I can find to make the child ListBox cells and accompanying scrollbar obey this roundness as well. Ideally I’m looking for something like Graphics::reduceClipRegion(juce::Path) but for an entire component and its children to obey. i.e. Component::reduceClipRegion
I find this to be a common problem with Juce and am often able to hack something like this by manually clipping a component’s paint routine and any children that might lie in the perceived clip region. But that’s not an option here given that all of the cells are a moving target.
I’m very interested in this issue. I thought about it a while ago and I was wondering if you could use a “cover” component for this,which is transparent except for the corners?
I’ve done this before as well and it will work fine in cases that have a solid or simple background. My particular case also has a drop shadow (another thing Juce Graphics has issues with) behind my component which makes this solution kind of impossible. It also just feels unfortunate to have to hack a solution like this just to implement something as common as rounded corners.
But unfortunately it’s not something I can use so we just opted to get rid of the rounded corners until such time that juce can accommodate something like that.
I’d like to bump this as it doesn’t seem it would an extremely heavy lift and would add a lot of functionality to JUCE for rounded corners which is a large use case where the OS design is going on. (They now round the corner on all windows on Mac OS)
similar to setPaintingIsUnclipped() – maybe we could have a:
We could traverse the parent components and check for the first one which has painting clipped for children, we could just set the clip region to the parent – of course like painting is unclipped you wouldn’t want to use fillAll etc – but then we could have rounded parent components with children? Would make for a much easier case when dealing with rounded corners!
With the way things are going maybe we should just be able to set the corner radius on components at this point
Has anyone found a good method for doing this? I am facing exactly the same situation: a parent with rounded corners that dynamically draws children within its bounds.
static void setAsCornerOwner(juce::Component& c, float roundness)
{
c.getProperties().set("corner_owner",true);
c.getProperties().set("roundness",roundness);
}
//
juce::Component myCornerOwner;
setAsCornerOwner(myCornerOwner,10);
static juce::Path getClip(juce::Component* c)
{
juce::Path clip;
juce::Component* corner_candidate = c;
bool found = false;
while(corner_candidate )
{
if(corner_candidate ->getPropertries().contains("corner_owner"))
{
found = true;
break;
}
corner_candidate = corner_candidate .getParentComponent();
}
if(found)
{
clip.addRoundedRectangle(corner_candidate.getLocalBounds()...
clip.addTransform(// move the clip according to the requester's position, sorry, can't come up with it just like that
}
return clip;
}
(your paint method)
void paint(juce::Graphics& g)
{
g.clipRegion(getClip(this)...
}
it looks rough and it’s surely untested, but I believe this is the approach I would use, well, maybe get the clip at resize instead of repaint, but that’s basically it
Ok, I’ve made an implementation of this, I’m not sure it covers all cases but it works as far as I could test it.
Based on @nfect’s answer and implemented in the simplest, most intuitive way I could think of.
Then, add a member variable to any component classes you want to be “clippable”
std::unique_ptr<juce::Path> clipPath;
Next, the path variable should be updated both in resized() and parentHierarchyChanged() - to cover Viewport usage scenarios and such… (and maybe also in moved())