I am having more success with building plugins with plots, but I still have some questions. Here is a screen shot of a generic plot, which is implemented as a component class. My question is: how can I get my y axis label to display vertically, i.e., rotated -90 degrees?
My suggestion would be a label component for your “y axis label” as subcomponent of your ‘plot component’.
That subcomponent can be rotated with a simple call “Label.setTransform();”
Hope that helps
Sounds like a plan! I’ll give it a shot. Thanks!
It may be personal preference but in my opinion this is a bad idea from the perspective of a user. It’s just harder to read.
You could also use addTransform() when drawing the text in the paint routine for the component. That’s what I did.
If you use Graphics::addTransform()
it’s probably a good idea to save the state first and restore it after (unless it’s the very last thing you draw) otherwise everything after will be rotated:
auto midX = static_cast<float>(getWidth()) * 0.5f;
auto midY = static_cast<float>(getHeight()) * 0.5f;
g.saveState();
g.addTransform(AffineTransform::rotation(-MathConstants<float>::halfPi, midX, midY))
g.drawText("y axis label", getLocalBounds(), Justification::centredTop);
g.restoreState();
(Not tested)
Thanks for all of the recommendations. I’ll see if I can make them work for me. The comment from Achder had some interesting consequences for me. I decided to search Google to see if there is a “proper” way to label the vertical (y) axis of a graph. I came across an article in Forbes that recommended both a vertical and horizontal format, with a preference for the vertical. But the interesting part is that the author of the article is a person I worked with at Bell Laboratories in the 1970s and have not seen since. She is a statistician who, in retirement, has established herself as a consultant in the area of presenting data. Nice coincidence that I should land on her web site while researching a JUCE problem!
That’s a solution I used in the past as well. Just want to add the RAII save state for Graphics:
{
Graphics::ScopedSaveState state (g);
g.addTransform (AffineTransform::rotation (-MathConstants<float>::halfPi,
getWidth() * 0.5f,
getHeight() * 0.5f));
g.drawText("y axis label", getLocalBounds(), Justification::centredTop);
}
and you don’t need the explicit cast, if you are multiplying with a float.
I got the results I wanted using the Label approach. I used (child) Label components for both axis labels. I applied a rotation transform to the y axis label. Here’s my resize() code from my Plot component:
xAxisLabel.setText(xLabel, dontSendNotification);
yAxisLabel.setText(yLabel, dontSendNotification);
xAxisLabel.setJustificationType(Justification::centred);
yAxisLabel.setJustificationType(Justification::centred);
yAxisLabel.setTransform(AffineTransform::rotation(-MathConstants<float>::halfPi, 0.5 * getHeight(), 0.5 * getWidth()));
xAxisLabel.setBounds(0, 0.9 * getHeight(), getWidth(), 0.1 * getHeight());
yAxisLabel.setBounds(0, 0, getWidth(), 0.1 * getWidth());
Although I invoked the setText method in the Plot constructor, it did not display until I re-invoked it in the resize() method. I’m confused by this, but it seems to work.
Here is an alternative way I just stumbled upon;
drawMultiLineText(). Just set a width about half of font size, works like a charm, except I can’t seem to get it to make a new line if there is a ‘space’ character!
g.setFont (fontSize);
g.drawMultiLineText ("Vertical", x , fontSize, fontSize / 2, Justification::centred);
This woked for me :
I’ve overrided the drawLabel(…) from LookAndFell_V2 :
void MyLookAndFeel::drawLabel(Graphics& g, Label& label)
{
g.fillAll(label.findColour(Label::backgroundColourId));
if (!label.isBeingEdited())
{
auto alpha = label.isEnabled() ? 1.0f : 0.5f;
const Font font(getLabelFont(label));
g.setColour(label.findColour(Label::textColourId).withMultipliedAlpha(alpha));
g.setFont(font);
auto textArea = getLabelBorderSize(label).subtractedFrom(label.getLocalBounds());
// === MY_CODE ==== //
if (label.getComponentID() == "vertical") {
Graphics::ScopedSaveState state(g);
auto t = AffineTransform::rotation(-MathConstants<float>::halfPi,
textArea.toFloat().getCentreX(),
textArea.toFloat().getCentreY());
auto newTextArea = textArea.toFloat().transformedBy(t);
g.addTransform(t);
g.drawText(label.getText(), newTextArea, Justification::centredLeft);
}
else {
g.drawFittedText(label.getText(), textArea, label.getJustificationType(),
jmax(1, (int)((float)textArea.getHeight() / font.getHeight())),
label.getMinimumHorizontalScale());
}
// ====== /MY_CODE ========//
g.setColour(label.findColour(Label::outlineColourId).withMultipliedAlpha(alpha));
}
else if (label.isEnabled())
{
g.setColour(label.findColour(Label::outlineColourId));
}
g.drawRect(label.getLocalBounds());
}
So i setted the component name to “vertical” to decide when a label should be vertical and then apply a transform either to the graphic context and the textArea !