When creating a set of colors that work well together you often want to change the saturation and luminosity levels on all of the colors at once. There are some amazing color tools out there, but up to now I've not found any that lets me do this en-masse adjustment.
So I thought I'd try and create a utility tool in Visio that lets you do this.
An HSL utility
When creating this tool I had two goals:
- to be able to adjust and view the saturation and luminosity values of multiple shapes in one action
- and, to be able to copy a list of those color values as a list to the clipboard
The first requirement can be easily met by standard ShapeSheet logic, but the second requires some code.
Bearing in mind that not everyone will be able to run macro code, I've created two files: a template (.vstx) without code and an accompanying stencil (.vssm) where the code lives.
The stencil file is digitally signed from visualsignals ltd and if any changes made to the stencil this will invalidate the signature.
HSL
If you're not familiar with it, HSL is an alternative color model to the more common RGB. RGB can be thought of as a cubic arrangement, with each dimension representing a range for each component. HSL, on the other hand, represents colors in a cylindrical model, which means that each component (hue, saturation and luminosity) can set as a single value.
SharkD, CC BY-SA 3.0, via Wikimedia Commons
You can read more about HSL on Wikipedia.
The solution
The solution has two masters:
-
a
Color
circle shape for each color instance -
and a
Container
shape to visualualize the Hue and Saturation components + a slider to control the Luminosity of all colors on the page
When dropping Color
instances onto the page the resulting HSL values are determined by each shape's vertical (Saturation) and horizontal (Hue) position.
As these are standard Visio shapes you can drag select, Ctrl+Click and Ctrl+A as you like and then move the selection on the page.
Each of the shapes reference a page level Shape Data cell to retrieve their Luminosity value and this can be set by either directly editing the Shape Data window or by dragging the yellow control handle on the Container shape, which is visible when the shape is selected.
Show color values
On page right-click you can choose whether to display color values which, if turned on, will display the RGB, HSL and HEX values.
Instance luminosity
Although you control the global luminosity via the page, as described above, you might also want to add an offset to individual shapes and you can do this via a Shape Data row named Luminosity Offset
. This defaults to 0 but can take a negative or positive integer and the shape will add this to the global value in order to arrive at its own calculated result.
If Show color values is true then the offset will be displayed along side the other information.
Color Values Shape Report
The file contains a report definition that will report all colors in RGB, HSL and HEX formats, which you can run from Review / Shape Reports.
It's really there for those who are not able to run the macros version and as an alternative to the Copy color values (see below).
Macro enhancements
The code version of the document includes a few additional features:
Reset all luminosity offsets
If you've applied local luminosity offsets to a number of Color
shapes and want to reset them then you can do this via the Reset all local luminosity offsets page right-click menu item.
Copy Color values to clipboard
You can right-click on the page and select "Copy RGB values". This harvests the RGB string cell from each Color shape, concatenates this into a list and then copies the resulting string to the clipboard. So, for example, if you had three colors on the page you'd find something like this in the clipboard:
RGB(238,168,111)|RGB(113,236,122)|RGB(112,190,237)
You're free to change the parameters of the corresponding CALLTHIS function in the page ShapeSheet, where the last three arguments are: the target cell name, the color delimiter (pipe in the above example) and a boolean that determines whether to retrieve the local formula (with local component separator) or universal which will always be a comma.
On the Color
shape you'll find string cells cells:
User.RGBStr
User.HSLStr
User.HEXStr
Save Colors
Another right-click feature on the page is the ability to save the current set of Color
shapes to the document, which you can then 'reload' at a later date.
Individual named Palettes are stored in the Document's ShapeSheet and so are saved with the document.
Colors are stored in the palette as RGB values and then translated back to HSL when they're dropped back onto the page.
There are a number of options for converting from RGB to HSL and back again. I looked at a number of options for doing this:
- Converting sRGB Colors to HSL - W3C
- HSL to RGB color conversion - Stack Overflow
- RGB to HSL conversion - Stack Overflow
In the end I went for the Win32 api which has a ColorRGBToHSL function, which does very nicely.
Drop and Delete Palettes
Now that you're storing palettes you need some way to manage them and so there is an further menu item named 'Manage palettes...'.
This surfaces a form which allows you to select one or more palettes and either drop all of the colors in each palette or, delete the selected palettes.
Note - If the luminosity level on the page has changed since the colors were stored a corresponding offset will be applied on drop.
Override Ctrl+A
This utility is specialized enough that I decided to catch the select all (Ctrl+A) event. Most of the time I just want to select the Color
shapes and not the Container
shape. However as I needed the Container
to be selectable, in order to move the luminosity slider, I couldn't just lock that layer. Instead the event is caught and quickly deselects the Container
resulting in a Colors only selection.
Final notes
New pages - in Visio if your master shapes reference any page User or Shape Data cells then these cells are created on new pages if they don't already exist. That's not the case for Actions cells (which give you context menu functionality. One route around this would be listen for the page added event and then create the rows in code, however this won't work if you're using the non-macro template only. The alternative is to use the Duplicate
command on the page tab context menu and this will bring across all of the cells that you need.