What is the proper JUCE way to specify different styles for different versions of the same Component?

So, as we all know, the proper way to change styles for all Components is to subclass LookAndFeel and change the appropriate methods for a specific Component type. But what if I only want to change some of them?

For example, what if I want to have a specific type of Label that is used for page titles. When it’s used in that context I want the font to be bold and to be a bit bigger. What is the proper way to specify those styles for only the page title version of label?

You could write some builder functions to create a Component with the predefined styles. For example:

void buildHeadingsLabel(juce::Label& label)
{
    label.setFont(juce::Font(25.f, juce::Font::bold));
    label.setColour(textColourId, juce::Colours::blue);
    label.setJustification(juce::Justification::centred);
}

// ...
juce::Label myLabel;
buildHeadingsLabel(myLabel);
2 Likes

I don’t know that there is a “proper” way to do that, but you can always add a member variable and accessors to get/set, say, an enumerated value in your component that tells what style to use, set it from your editor when creating the components, and then query that style in your LookAndFeel function(s) when that component is being used.

1 Like

The colours are looked up through the hierarchy. First it is checked, if you set a colour directly on the component, then it fetches the colour from the lookAndFeel.
It is absolutely common to have multiple lookAndFeels, even of the same type. That way they can have different colour settings.

The LookAndFeels are also looked up from each parent until the root is hit.

I found the whole complex too cumbersome and wrote a system, where the component DOM inherits CSS like properties. Have a look at PluginGuiMagic or this thread:

I havent tested this but it might work. Create a globalLookAndFeel that styles your app in whatever default way you want. You could set your labels to whatever default label style you want your labels to have in this look and feel. Then you could subclass this global look and feel (maybe call it SpecialLabel) but only override the label functions and make it special for this type of label.

Then whenever you have a label that needs to be special, you set its look and feel to be the special label look and feel.

1 Like

In general if you want something simple like a text non-editable label or button with a specific style, I’d say the proper way to do it is to ignore LookAndFeel completely. Just create a super simple label component and override paint, and/or do the same with Button.

It can get a bit maze like with LookAndFeel…

3 Likes

I would agree, keep it simple.

Just adding: don’t inherit Label but just Component. You don’t need to keep all Label functionality just to display a text.

For a Button I am hesitant with that advice, since with all the mouseDown, mouseDrag etc. handling you can easily miss some edge cases, so in this case I would go the route by inheriting LookAndFeel.

1 Like

You just inherit from Button and override paintButton and clicked() for the action and job is done :slight_smile: All the setup is done by Button and no LookAndFeel stuff in sight.

A button in about 8 lines of code might look a bit like…

class TriggerButton: public Button
{
public:
 TriggerButton(Processor & processor): Button({}), processor(processor) {}
 void paintButton(Graphics & g, bool mouseOver, bool) { 
    g.setColour(mouseOver ? Colours::white : Colours::pink); 
    g.drawText("trigger", getLocalBounds(), Justiication::centred); 
 }
 void clicked() override { processor.triggerSounds(); }; 
 Processor & processor;
};

Thanks so much. I’ve ended up making my own Component. Works really well, and feels much cleaner.

1 Like

you can also let a new class inherit from your custom look and feel and only change the detail that should be a little different in that look and feel instead of rewriting everything or copying a lot of code fragments