SharedResourcePointer to LookAndFeel


#1

Does anyone have any pointers (budum dum tshhhh) for getting a custom LookAndFeel to work when instantiating individual components in the Projucer?

Jules said in another thread...

...use something like a SharedResourcePointer which creates your custom look, and then make your individual components reference that. Then when the projucer uses a component which uses this shared object, it'll get created and used.

...but despite my best attempts I've failed to get it to work.

I tried creating a container class with my custom LookAndFeel object as a member, then creating a SharedResourcePointer to the container class and setting the default LAF in my components via the SharedResourcePointer. It works when running the whole application, but not when running individual components in the Projucer as intended. The reasoning behind having a container class was to point all my application's components there, and in the container class handle runtime switching between variations of my LAF.

Any idea whether when Jules wrote "which creates your custom look", he might have meant either a) which points to a customised LookAndFeel objector b) which points to a home-rolled class (one which does not inherit from Juce's LAF classes) to implement the drawing of your components?

Many thanks in advance for any guidance / suggestions!


JIT and LookAndFeel
#2
struct MySharedLnF
{
    MySharedLnF() { ....initialisation etc... }

    MyCustomLookAndFeel lf;
};

struct MyComponent
{
    MyComponent()
    {
        setLookAndFeel (&sharedLookAndFeel.lf);
    }

    SharedResourcePointer<MySharedLnF> sharedLookAndFeel;
};

#3

I’ve run into a circular dependancy problem related to @jules’ suggestion above.

/** ==============================================================================
    MyComponent.h
    =========================================================================== */

#include "LookAndFeel.h" //** <<< ??? <<< */

struct MyComponent : public Component
{
    MyComponent()
    {
        setLookAndFeel (&sharedLookAndFeel->laf);
    }

    struct LookAndFeelMethods
        {
            virtual ~LookAndFeelMethods() {}
            virtual void drawMyComponentBackground (Graphics&, MyComponent&) = 0;
            virtual void drawMyComponentForeground (Graphics&, MyComponent&) = 0;
        };
 
private:
    SharedResourcePointer<SharedLookAndFeel> sharedLookAndFeel;
};
/** ==============================================================================
    LookAndFeel.h
    =========================================================================== */

#include "MyComponent.h" //** <<< ??? <<< */

struct LookAndFeel_Custom  : public LookAndFeel_V3,
                             public MyComponent::LookAndFeelMethods
{
    LookAndFeel_Custom() {}
    void drawMyComponentBackground (Graphics&, MyComponent&) override;
    void drawMyComponentForeground (Graphics&, MyComponent&) override;
};

struct SharedLookAndFeel
{
    LookAndFeel_Custom laf;
};

Any input on how I can avoid the circular #include gladly appreciated!


#4

Forward Class Declaration might help you out here, .e.g instead of
#include "MyComponent.h"
write
class MyComponent;

It’s one way to get round circular dependencies. Works as long as you only need to reference the class type, not any of its methods or members.


#5

Many thanks for the input @adamski, but on this occasion, my LookAndFeel class wants to inherit from MyComponent::LookAndFeelMethods - it’s not just the MyComponent& arguments in the LookAndFeel methods.

Anyone have a cunning solution to this?


#6

You can include the headers in the cpp instead of including one header in the next header.
As long as the needed include is placed before the header depending on the other one, it should work.


SharedResourcePointer<>*
#7

Whenever I run into forward declaration problems, mostly because of trying to forward declare an inner class, I end up using a pointer to the base class as member variable in the header and cast it to the actual class in the cpp file (If you use static_cast, you get away without runtime performance penalties).