Previously the cache was divided only by layer, with entries keyed on a
string built from the text and style. Now the style has its own tier in
the cache, i.e. layers > styles > text > info.
This introduces some complexity, since the nested for loops are ugly,
but at the same time we avoid having to create the cache-key strings.
More importantly it solves the problem of uniqueness that exists when we
try to join strings that may contain arbitrary text. It also allows a
further optimization in the canvas plugin, which can now set text style
and color just once per distinct style, instead of with every string.
This lets users 'namespace' text more naturally, i.e. placing x-axis
labels in a different container from y-axis labels, providing more
flexibility when it comes to styling and interactivity.
Internally the text cache now has a second tier: layers > text > info.
The getTextInfo method previously added new text to the top-level
container when measuring it. Now it adds the text to the text layer,
just as it will be when rendered, so that parent-child CSS rules can
resolve correctly.
This also avoids having to safe a reference to the top-level container,
since it wasn't used anywhere else.
Every cache element now contains the actual text element instead of just
its HTML, plus a flag indicating whether it is visible. The addText and
removeText methods control the state of this flag, and the render method
uses it to manage elements within the text container. So where we
previously used drawText to actually render text, now we add each string
once, then let the render method take care of drawing them as necessary.
This dramatically improves performance by eliminating the need to clear
and re-populate HTML text on every drawing cycle. Since the elements
are now static between add/remove calls, this also allows users to add
interactivity, as they could in 0.7. Finally, it eliminates the need
for a separate 'hot' cache.
I also removed the unnecessary 'dimensions' object; it's easier and
faster to store the width and height at the top level of the info
object.
This significantly improves performance, since we already create the
elements when measuring them, and that effort is now no longer wasted.
We must take care to detach, rather than remove, when clearing the text
layer, so we can add the elements back later if necessary.
This resolves#534 by handling the case where data is a string, whether
it is provided alone or as a pair. We can also eliminate the old and
unnecessary check for undefined values.
The canvasWidth, canvasHeight, legendWidth and legendHeight variables
existed only to share data between the setupPie and draw functions. Now
that setupPie has been folded into draw, they're no longer necessary.
This code is only used to prepare the plot for drawing; inlining it is
cleaner and will allow us to get rid of some plugin-global variables
that existed only to give setupPie a way to share data with the draw
function.
The redraw flag starts out as true, then is immediately set to false on
draw. If labels are enabled, drawPie calls drawLabels, which calls
drawLabel for each label. Any label that can't fit sets redraw back to
true, so the whole process can repeat.
This isn't the most obvious mechanism, and forces one to remember to do
things like setting redraw back to true after drawing, so the plot can
redraw itself on resize or when setting new data.
Instead we now have drawPie return true when it drew successfully, and
false otherwise, which the same happening in drawLabels and drawLabel.
Instead of checking the flag, we now just check the return value.
This has the added benefit of slightly improving performance in the case
where several redraws are necessary, since it now short-circuits out of
the draw loop as soon as one label fails to fit.
In plugins we should never add hooks conditionally; the condition should
remain within individual hooks, so the plugin can be toggled at any
time.
Ideally we should also 'inline' the hook functions, since they're used
nowhere else. But since that would involve a lot of code changes, we'll
put it off until the broader cleanup effort scheduled for 0.9.0.