How to let TextEditor display units (prefix or suffix)

Hey guys,

on my plugin’s UI I have a few TextEditor components which would like to display their units, for example “ms” for milliseconds and so on. I know I can just place a label next to the TextEditor, but I am hoping for something more fancy.

I couldn’t find anything out of the box. Has anyone implemented this before and has some ideas for me on how to get started?

Ideally I would like to display the prefix or suffix only when out of keyboard focus, and for it to disappear as soon as keyboard focus is gained (to prevent the user having to type around it).

Any suggestions other than completely reimplementing paint()?

1 Like

Override the mouseDown() event, and each time the user clicks the editor just update the text so that it no longer displays the post/prefix. Then override the texteditorfocuslost() method so that each time the focus is lost you update the texteditor’s contents by adding back the post/prefix. Oh wait, this may actually give focus back to the editor! I couldn’t say for sure.

Hey thanks for the reply. I tried your idea overriding the focusGained() and focusLost() methods. Didn’t want to rely on mouseDown() in case the keyboard focus was gained by tabbing into the TextEditor.

void CMyTextEditor::focusGained(FocusChangeType cause)
{
	if (m_suffix.isNotEmpty())
	{
		// Remove the suffix characters
		String newText = getText().upToLastOccurrenceOf(m_suffix, false, false);
		setText(newText, false /* do not notify listeners */);
	}

	TextEditor::focusGained(cause);
}

void CMyTextEditor::focusLost(FocusChangeType cause)
{
	if (m_suffix.isNotEmpty())
	{
		String newText = getText() + m_suffix;
		setText(newText, true /* notify listeners */);
	}

	TextEditor::focusLost(cause);
}

To ensure that focus highlighting worked I had to call the base implementation of TextEditor::focusGained() from within my reimplementation. So far so good.

However, it was in focusLost() where I ran into issues. If I add the call to the base TextEditor::focusLost(), the text gets overwritten to the original text (i.e. without the suffix). Not sure why :frowning:

If I don’t call the base implementation, then my plugin (which inherits from TextEditor::Listener) does NOT get signaled even if I set the second parameter of setText() to true. This means that although the TextEditor shows the new value, the plugin still has the old value internally.

In general this approach felt too fishy and I decided against it. Instead I tried to just draw the units on top of the TextEditor:

void CMyTextEditor::paint(Graphics &g)
{
	// First let base implementation paint the component.
	TextEditor::paint(g);

	// If a suffix has been defined (string not empty), paint it 
	// so long as the TextEditor does NOT have keyboard focus
	if (!hasKeyboardFocus(true) && m_suffix.isNotEmpty())
	{
		// Calculate the position of the suffix so it is placed right next to the text.
		Rectangle<float> textArea = ... 

		g.setColour(Colours::black);
		g.drawText(m_suffix, textArea, Justification::centred);
	}
}	

In general I am happy with this solution. In my particular application I know how many characters will be allowed on each one of the TextEditors and also how many characters my suffixes have, so it works well. I can imagine though, that the positioning of the suffix would be a bit tricky if I didn’t (i.e. for a generic solution).

Cool. Glad you got something worked out in the end.