Vertical Text in Component

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 :slight_smile:

3 Likes

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.

2 Likes

You could also use addTransform() when drawing the text in the paint routine for the component. That’s what I did.

2 Likes

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)

3 Likes

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!

2 Likes

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.

1 Like

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 !