485 lines
16 KiB
C++
485 lines
16 KiB
C++
/******************************************************************************
|
|
* Copyright (c) 2018(-2023) STMicroelectronics.
|
|
* All rights reserved.
|
|
*
|
|
* This file is part of the TouchGFX 4.21.2 distribution.
|
|
*
|
|
* This software is licensed under terms that can be found in the LICENSE file in
|
|
* the root directory of this software component.
|
|
* If no LICENSE file comes with this software, it is provided AS-IS.
|
|
*
|
|
*******************************************************************************/
|
|
|
|
/**
|
|
* @file touchgfx/widgets/TextArea.hpp
|
|
*
|
|
* Declares the touchgfx::TextArea class.
|
|
*/
|
|
#ifndef TOUCHGFX_TEXTAREA_HPP
|
|
#define TOUCHGFX_TEXTAREA_HPP
|
|
|
|
#include <touchgfx/Font.hpp>
|
|
#include <touchgfx/TextProvider.hpp>
|
|
#include <touchgfx/TypedText.hpp>
|
|
#include <touchgfx/Unicode.hpp>
|
|
#include <touchgfx/hal/Types.hpp>
|
|
#include <touchgfx/widgets/Widget.hpp>
|
|
|
|
namespace touchgfx
|
|
{
|
|
/**
|
|
* This widget is capable of showing a text area on the screen. The text must be a predefined
|
|
* TypedText in the text sheet in the assets folder. In order to display a dynamic text,
|
|
* use TextAreaWithOneWildcard or TextAreaWithTwoWildcards.
|
|
*
|
|
* @see TypedText, TextAreaWithOneWildcard, TextAreaWithTwoWildcards
|
|
*
|
|
* @note A TextArea just holds a pointer to the text displayed. The developer must ensure that
|
|
* the pointer remains valid when drawing.
|
|
*/
|
|
class TextArea : public Widget
|
|
{
|
|
public:
|
|
TextArea()
|
|
: Widget(), typedText(TYPED_TEXT_INVALID), color(0), linespace(0), alpha(255), indentation(0), rotation(TEXT_ROTATE_0), wideTextAction(WIDE_TEXT_NONE), boundingArea()
|
|
{
|
|
}
|
|
|
|
virtual void setWidth(int16_t width)
|
|
{
|
|
Widget::setWidth(width);
|
|
boundingArea = calculateBoundingArea();
|
|
}
|
|
|
|
virtual void setHeight(int16_t height)
|
|
{
|
|
Widget::setHeight(height);
|
|
boundingArea = calculateBoundingArea();
|
|
}
|
|
|
|
virtual Rect getSolidRect() const
|
|
{
|
|
return Rect();
|
|
}
|
|
|
|
/**
|
|
* Sets the color of the text. If no color is set, the default color (black) is used.
|
|
*
|
|
* @param newColor The color to use.
|
|
*/
|
|
FORCE_INLINE_FUNCTION void setColor(colortype newColor)
|
|
{
|
|
color = newColor;
|
|
}
|
|
|
|
/**
|
|
* Gets the color of the text. If no color has been set, the default color, black, is
|
|
* returned.
|
|
*
|
|
* @return The color to used for drawing the text.
|
|
*/
|
|
FORCE_INLINE_FUNCTION colortype getColor() const
|
|
{
|
|
return color;
|
|
}
|
|
|
|
/**
|
|
* @copydoc Image::setAlpha
|
|
*/
|
|
virtual void setAlpha(uint8_t newAlpha)
|
|
{
|
|
alpha = newAlpha;
|
|
}
|
|
|
|
/**
|
|
* @copydoc Image::getAlpha
|
|
*/
|
|
uint8_t getAlpha() const
|
|
{
|
|
return alpha;
|
|
}
|
|
|
|
/**
|
|
* Adjusts the TextArea y coordinate so the text will have its baseline at the specified
|
|
* value. The placements is relative to the specified TypedText so if the TypedText is
|
|
* changed, you have to set the baseline again.
|
|
*
|
|
* @param baselineY The y coordinate of the baseline of the text.
|
|
*
|
|
* @note setTypedText() must be called prior to setting the baseline.
|
|
*/
|
|
virtual void setBaselineY(int16_t baselineY)
|
|
{
|
|
setY(baselineY - getTypedText().getFont()->getBaseline());
|
|
}
|
|
|
|
/**
|
|
* Adjusts the TextArea x and y coordinates so the text will have its baseline at the
|
|
* specified y value. The placements is relative to the specified TypedText so if the
|
|
* TypedText is changed you have to set the baseline again. The specified x coordinate
|
|
* will be used as the x coordinate of the TextArea.
|
|
*
|
|
* @param x The x coordinate of the TextArea.
|
|
* @param baselineY The y coordinate of the baseline of the text.
|
|
*
|
|
* @note setTypedText() must be called prior to setting the baseline.
|
|
*/
|
|
virtual void setXBaselineY(int16_t x, int16_t baselineY)
|
|
{
|
|
setX(x);
|
|
setBaselineY(baselineY);
|
|
}
|
|
|
|
/**
|
|
* Sets the line spacing of the TextArea. Setting a larger value will increase the space
|
|
* between lines. It is possible to set a negative value to have lines (partially)
|
|
* overlap. Default line spacing, if not set, is 0.
|
|
*
|
|
* @param space The line spacing of use in the TextArea.
|
|
*
|
|
* @see getLinespacing
|
|
*/
|
|
FORCE_INLINE_FUNCTION void setLinespacing(int16_t space)
|
|
{
|
|
linespace = space;
|
|
boundingArea = calculateBoundingArea();
|
|
}
|
|
|
|
/**
|
|
* Gets the line spacing of the TextArea. If no line spacing has been set, the line
|
|
* spacing is 0.
|
|
*
|
|
* @return The line spacing.
|
|
*
|
|
* @see setLinespacing
|
|
*/
|
|
FORCE_INLINE_FUNCTION int16_t getLinespacing() const
|
|
{
|
|
return linespace;
|
|
}
|
|
|
|
/**
|
|
* Sets the indentation for the text. This can be very useful when a font is an italic
|
|
* font where letters such as "j" and "g" extend a lot to the left under the previous
|
|
* character(s). if a line starts with a "j" or "g" this letter would either have to be
|
|
* pushed to the right to be able to see all of it, e.g. using spaces (which would ruin
|
|
* a multi line text which is left aligned) - or by clipping the first letter (which
|
|
* could ruin the nice graphics). The solution is to change
|
|
* @code
|
|
* textarea.setPosition(50, 50, 100, 100);
|
|
* @endcode
|
|
* to
|
|
* @code
|
|
* textarea.setPosition(45, 50, 110, 100);
|
|
* textarea.setIndentation(5);
|
|
* @endcode
|
|
* Characters that do not extend to the left under the previous characters will be drawn
|
|
* in the same position in either case, but "j" and "g" will be aligned with other lines.
|
|
*
|
|
* The function Font::getMaxPixelsLeft() will give you the maximum number of pixels any glyph
|
|
* in the font extends to the left.
|
|
*
|
|
* @param indent The indentation from left (when left aligned text) and right (when right
|
|
* aligned text).
|
|
*
|
|
* @see Font::getMaxPixelsLeft
|
|
*/
|
|
FORCE_INLINE_FUNCTION void setIndentation(uint8_t indent)
|
|
{
|
|
indentation = indent;
|
|
boundingArea = calculateBoundingArea();
|
|
}
|
|
|
|
/**
|
|
* Gets the indentation of text inside the TextArea.
|
|
*
|
|
* @return The indentation.
|
|
*
|
|
* @see setIndentation
|
|
*/
|
|
FORCE_INLINE_FUNCTION uint8_t getIndentation()
|
|
{
|
|
return indentation;
|
|
}
|
|
|
|
/**
|
|
* Gets the alignment of text inside the TextArea.
|
|
*
|
|
* @return The alignment.
|
|
*
|
|
*/
|
|
virtual Alignment getAlignment() const;
|
|
|
|
/**
|
|
* Gets the total height needed by the text, taking number of lines and line spacing
|
|
* into consideration.
|
|
*
|
|
* @return the total height needed by the text.
|
|
*/
|
|
virtual int16_t getTextHeight() const;
|
|
|
|
/**
|
|
* Gets the width in pixels of the current associated text in the current selected
|
|
* language. In case of multi-lined text the width of the widest line is returned.
|
|
*
|
|
* @return The width in pixels of the current text.
|
|
*/
|
|
virtual uint16_t getTextWidth() const;
|
|
|
|
virtual void draw(const Rect& area) const;
|
|
|
|
/**
|
|
* Sets the TypedText of the text area. If no prior size has been set, the TextArea will
|
|
* be resized to fit the new TypedText.
|
|
*
|
|
* @param t The TypedText for this widget to display.
|
|
*
|
|
* @see resizeToCurrentText
|
|
*/
|
|
void setTypedText(const TypedText& t);
|
|
|
|
/**
|
|
* Gets the TypedText of the text area.
|
|
*
|
|
* @return The currently used TypedText.
|
|
*/
|
|
const TypedText& getTypedText() const
|
|
{
|
|
return typedText;
|
|
}
|
|
|
|
/**
|
|
* Sets rotation of the text in the TextArea. The value TEXT_ROTATE_0 is the default for
|
|
* normal text. The value TEXT_ROTATE_90 will rotate the text clockwise, thus writing
|
|
* from the top of the display and down. Similarly TEXT_ROTATE_180 and TEXT_ROTATE_270
|
|
* will each rotate the text further 90 degrees clockwise.
|
|
*
|
|
* @param textRotation The rotation of the text.
|
|
*/
|
|
FORCE_INLINE_FUNCTION void setRotation(const TextRotation textRotation)
|
|
{
|
|
rotation = textRotation;
|
|
boundingArea = calculateBoundingArea();
|
|
}
|
|
|
|
/**
|
|
* Gets rotation of the text in the TextArea.
|
|
*
|
|
* @return The rotation of the text.
|
|
*
|
|
* @see setRotation
|
|
*/
|
|
TextRotation getRotation() const
|
|
{
|
|
return rotation;
|
|
}
|
|
|
|
/**
|
|
* Sets the dimensions of the TextArea to match the width and height of the current
|
|
* associated text for the current selected language.
|
|
*
|
|
* If WordWrap is turned on for the TextArea, the height might be set to an unexpected
|
|
* value, as only manually insert line breaks in the text will be respected - use
|
|
* resizeHeightToCurrentText() to keep the width of the TextArea and therefore retain
|
|
* word wrapping.
|
|
*
|
|
* If the text is centered or right aligned, calling resizeToCurrentText() will actually
|
|
* move the text on the screen, as the x and y coordinates of the TextArea widget is not
|
|
* changed. To simply minimize the size of the TextArea but keep the TypedText in the
|
|
* same position on the screen, use resizeToCurrentTextWithAlignment(). This is also the
|
|
* case if the text is rotated, e.g. 180 degrees.
|
|
*
|
|
* @see setRotation, resizeHeightToCurrentText
|
|
*
|
|
* @note If the current text rotation is either 90 or 270 degrees, the width of the text area
|
|
* will be set to the height of the text and vice versa, as the text is rotated.
|
|
*/
|
|
void resizeToCurrentText();
|
|
|
|
/**
|
|
* Sets the dimensions of the TextArea to match the width and height of the current
|
|
* associated text for the current selected language, and for centered and right aligned
|
|
* text, the position of the TextArea widget is also updated to keep the text in the
|
|
* same position on the display. Text that is rotated is also handled properly.
|
|
*
|
|
* @see setRotation, resizeHeightToCurrentText
|
|
*
|
|
* @note If the current text rotation is either 90 or 270 degrees, the width of the text area
|
|
* will be set to the height of the text and vice versa, as the text is rotated.
|
|
*/
|
|
void resizeToCurrentTextWithAlignment();
|
|
|
|
/**
|
|
* Sets the height of the TextArea to match the height of the current associated text
|
|
* for the current selected language. This is especially useful for texts with WordWrap
|
|
* enabled.
|
|
*
|
|
* @see resizeToCurrentText, setWideTextAction, setRotation,
|
|
* resizeHeightToCurrentTextWithRotation
|
|
*
|
|
* @note If the current text rotation is either 90 or 270 degrees, the width of the text area
|
|
* will be set and not the height, as the text is rotated.
|
|
* @note If the current text is rotated, the x/y coordinate is not updated, which means that
|
|
* the text will be repositioned on the display.
|
|
*/
|
|
void resizeHeightToCurrentText();
|
|
|
|
/**
|
|
* Sets the height of the TextArea to match the height of the current associated text
|
|
* for the current selected language. This is especially useful for texts with WordWrap
|
|
* enabled.
|
|
*
|
|
* @see resizeToCurrentText, setWideTextAction, setRotation, resizeHeightToCurrentText
|
|
*
|
|
* @note If the current text rotation is either 90 or 270 degrees, the width of the text area
|
|
* will be set and not the height, as the text is rotated. Also, the x or y
|
|
* coordinates will be updated.
|
|
*/
|
|
void resizeHeightToCurrentTextWithRotation();
|
|
|
|
/**
|
|
* Defines what to do if a line of text is wider than the text area. Default action is
|
|
* ::WIDE_TEXT_NONE which means that text lines are only broken if there is a manually
|
|
* inserted newline in the text.
|
|
*
|
|
* If wrapping is enabled and the text would occupy more lines than the size of the
|
|
* TextArea, the end of the last line will get an ellipsis (often …) to signal
|
|
* that some text is missing. The character used for ellipsis is taken from the text
|
|
* spreadsheet.
|
|
*
|
|
* @param action The action to perform for wide lines of text.
|
|
*
|
|
* @see WideTextAction, getWideTextAction, resizeHeightToCurrentText
|
|
*/
|
|
FORCE_INLINE_FUNCTION void setWideTextAction(WideTextAction action)
|
|
{
|
|
wideTextAction = action;
|
|
boundingArea = calculateBoundingArea();
|
|
}
|
|
|
|
/**
|
|
* Gets wide text action previously set using setWideTextAction.
|
|
*
|
|
* @return current WideTextAction setting.
|
|
*
|
|
* @see setWideTextAction, WideTextAction
|
|
*/
|
|
WideTextAction getWideTextAction() const
|
|
{
|
|
return wideTextAction;
|
|
}
|
|
|
|
/**
|
|
* Gets the total height needed by the text. Determined by number of lines and
|
|
* linespace. The number of parameters passed after the format, must match the number of
|
|
* wildcards in the TypedText.
|
|
*
|
|
* @param format The text containing <placeholder> wildcards.
|
|
* @param ... Variable arguments providing additional information.
|
|
*
|
|
* @return the total height needed by the text.
|
|
*/
|
|
virtual int16_t calculateTextHeight(const Unicode::UnicodeChar* format, ...) const;
|
|
|
|
/**
|
|
* Gets the first wildcard used in the TypedText.
|
|
*
|
|
* @return A pointer to the first wildcard, if this text area has a wildcard, otherwise 0.
|
|
*
|
|
* @see TextAreaWithOneWildcard, TextAreaWithTwoWildcards
|
|
*/
|
|
virtual const Unicode::UnicodeChar* getWildcard1() const
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Gets the second wildcard used in the TypedText.
|
|
*
|
|
* @return A pointer to the second wildcard, if this text area has two wildcards, otherwise 0.
|
|
*
|
|
* @see TextAreaWithOneWildcard, TextAreaWithTwoWildcards
|
|
*/
|
|
virtual const Unicode::UnicodeChar* getWildcard2() const
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
virtual void invalidateContent() const;
|
|
|
|
protected:
|
|
/** Structure for the relationship between a bounding rectangle and the contained text. */
|
|
class BoundingArea
|
|
{
|
|
public:
|
|
/**
|
|
* Initializes a new instance of the BoundingArea class.
|
|
*
|
|
* @param boundingRect The bounding rectangle of this text area.
|
|
* @param containedText A pointer to the text contained in the bounding rectangle.
|
|
*/
|
|
BoundingArea(const Rect& boundingRect, const Unicode::UnicodeChar* containedText)
|
|
: rect(boundingRect), text(containedText)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Initializes a new instance of the BoundingArea class which is invalid by default.
|
|
*/
|
|
BoundingArea()
|
|
: rect(Rect(0, 0, -1, -1)), // Negative width and height means invalid rectangle
|
|
text(0)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Gets bounding rectangle.
|
|
*
|
|
* @return The bounding rectangle.
|
|
*/
|
|
Rect getRect() const
|
|
{
|
|
return rect;
|
|
}
|
|
|
|
/**
|
|
* Query if the bounding area is valid.
|
|
*
|
|
* @param currentText A pointer to the current text of this text area.
|
|
*
|
|
* @return True if valid otherwise false.
|
|
*/
|
|
bool isValid(const Unicode::UnicodeChar* currentText) const
|
|
{
|
|
return (rect.height >= 0 && rect.width >= 0 && text == currentText);
|
|
}
|
|
|
|
private:
|
|
Rect rect;
|
|
const Unicode::UnicodeChar* text;
|
|
};
|
|
|
|
/**
|
|
* Calculates the minimum bounding rectangle of this text area and correlates it
|
|
* with the containing text, to get the bounding area.
|
|
* Note: The bounding rectangle is adjusted according to alignment and rotation.
|
|
*
|
|
* @return The bounding area.
|
|
*/
|
|
virtual TextArea::BoundingArea calculateBoundingArea() const;
|
|
|
|
TypedText typedText; ///< The TypedText to display
|
|
colortype color; ///< The color to use for the text.
|
|
int16_t linespace; ///< The extra space between lines of text, measured in pixels.
|
|
uint8_t alpha; ///< The alpha to use.
|
|
uint8_t indentation; ///< The indentation of the text inside the text area.
|
|
TextRotation rotation; ///< The text rotation to use in steps of 90 degrees.
|
|
WideTextAction wideTextAction; ///< What to do if the lines of text are wider than the text area.
|
|
static const uint16_t newLine = 10; ///< NewLine value.
|
|
BoundingArea boundingArea; ///< Bounding area of this text area.
|
|
};
|
|
|
|
} // namespace touchgfx
|
|
|
|
#endif // TOUCHGFX_TEXTAREA_HPP
|