3

I'm using the Juce Framework that has a setColour method like so:

g.setColour (Colour (0xff2a2620));

I instead would like to write something like more readable like:

g.setColour (Colour (lovelyBrown));, 'mapping' 0xff2a2620 to 'lovelyBrown'.

The method's prototype is:

explicit Colour (uint32 argb) noexcept; where uint32 is:

/** A platform-independent 32-bit unsigned integer type. */ typedef unsigned int uint32;

Juce has nice readable colour names already such as:

const Colour Colours::tomato (0xffff6347);, using a method to find the colour given a name:

static JUCE_API Colour findColourForName (const String& colourName, const Colour& defaultColour);

However, I don't want to modify or subclass their Colours class. I am wondering if there is a simpler way of 'mapping' 0xff2a2620 to 'lovelyBrown'?

Dave Chambers
  • 2,483
  • 2
  • 32
  • 55

3 Answers3

2

Use C++11 enums (that way your enum will be an uint32_t):

#include <cstdint>
enum class Colours : std::uint32_t {
    lovelyBrown = 0xff2a2620,
    lovelyOther = 0xff2a26FF
};
syntagma
  • 23,346
  • 16
  • 78
  • 134
  • thanks for the answer but it would have to be MyColours or similar to avoid clashing with the Juce class ‘Colours’ and I get an error `....No matching conversion for functional-style cast from 'MyColours' to 'juce::Colour'` I answered it anyway myself with a simple enum the same time as you! – Dave Chambers Sep 25 '15 at 09:53
  • Of course, the naming was just an example. It's good you've found a solution anyways. – syntagma Sep 25 '15 at 10:00
2

Just as you say Juce provides...

const Colour Colours::tomato (0xffff6347);

...you can add colours of your own:

const Colour lovelyBrown (0xff2a2620);

If you want a function to map from colour names to values at runtime, an easy and robust way is:

std::map<std::string, Colour> colourMap;
colourMap["lovelyBrown"] = lovelyBrown;
// add more here...

A slightly faster alternative is to have a contiguous array or vector of sorted colour names and use lower_bound to search. If you're not sure how to do that, you probably shouldn't... ;-P. (You'd either need to trust yourself/others to keep the list sorted in the source code, or do a runtime sort before first use, so there's a bit more risk/hassle+delocalisation respectively).


Note:

  • a problem with using enum class Colours is that when you use the contained colour names, they must be prefixed by Colours::, so there's a discrepancy with the Juce-provided colour names:
    g.setColour (Colour (tomato));  // ok for provided colours
    g.setColour (Colour (Colours::lovelyBrown));  // oops, one of yours
  • more generally, using enum or enum class makes the colours a distinct type, which has subtle consequences: e.g. you can't just stream them a la cout << lovelyBrown without writing your own operator<<, you can't invert the red component a la lovelyBrown ^ 0xFF0000 etc. - again, these things can be done for the Juce-provided colours.
Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • Thanks but as I said I don't want to edit the Juce classes since I pull from Github very often. I used a simple enum – Dave Chambers Sep 25 '15 at 09:54
  • @DaveChambers: nothing in my answer suggests editing the Juce classes... why do you mention it? – Tony Delroy Sep 25 '15 at 10:01
  • Tony, I owe you an apology. I simply added `g.setColour (Colour (Colour::lovelyBrown));` to my own file, included that file and it works like: `g.fillAll (Colour (lovelyBrown));` That's perfect and the best solution. Cheers! Dave – Dave Chambers Sep 25 '15 at 10:06
  • @DaveChambers: no worries - glad if it helped. Cheers. – Tony Delroy Sep 25 '15 at 10:15
0
enum MyColour {
lovelyBrown = 0xff2a2620,
};

This works but I ended up following Tony's advise for a cleaner (and easy!) solution. See his answer

Dave Chambers
  • 2,483
  • 2
  • 32
  • 55