1192 lines
33 KiB
C++
1192 lines
33 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/graph/GraphElements.hpp
|
|
*
|
|
* Declares the various graph element classes. Instances of these classes can be added to a graph.
|
|
*/
|
|
#ifndef TOUCHGFX_GRAPHELEMENTS_HPP
|
|
#define TOUCHGFX_GRAPHELEMENTS_HPP
|
|
|
|
#include <touchgfx/hal/Types.hpp>
|
|
#include <touchgfx/widgets/canvas/CWRUtil.hpp>
|
|
#include <touchgfx/widgets/canvas/Canvas.hpp>
|
|
#include <touchgfx/widgets/canvas/CanvasWidget.hpp>
|
|
#include <touchgfx/widgets/graph/AbstractDataGraph.hpp>
|
|
|
|
namespace touchgfx
|
|
{
|
|
/**
|
|
* An abstract graph element. Declares a couple of useful functions to help subclasses which use
|
|
* CWR (Canvas Widget Renderer).
|
|
*/
|
|
class AbstractGraphElement : public CanvasWidget
|
|
{
|
|
public:
|
|
/** Default constructor. */
|
|
AbstractGraphElement()
|
|
: CanvasWidget()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Invalidate the point at the given index. This allows a graph element to only invalidate
|
|
* the minimum rectangle required for the given index. The Graph will call this function
|
|
* before and after changing a point to ensure that both the old and the new area are
|
|
* redrawn (invalidated).
|
|
*
|
|
* @param index Zero-based index of the point.
|
|
*/
|
|
virtual void invalidateGraphPointAt(int16_t index) = 0;
|
|
|
|
protected:
|
|
/**
|
|
* Gets a pointer to the the graph containing the GraphElement.
|
|
*
|
|
* @return A pointer to the graph.
|
|
*/
|
|
FORCE_INLINE_FUNCTION AbstractDataGraph* getGraph() const
|
|
{
|
|
return parent ? (AbstractDataGraph*)(parent->getParent()) : (AbstractDataGraph*)0;
|
|
}
|
|
|
|
/**
|
|
* Gets graph screen x for x value.
|
|
*
|
|
* @param graph The graph.
|
|
* @param x The x value.
|
|
*
|
|
* @return The graph screen x for value.
|
|
*/
|
|
FORCE_INLINE_FUNCTION CWRUtil::Q5 valueToScreenXQ5(const AbstractDataGraph* graph, int x) const
|
|
{
|
|
return graph->valueToScreenXQ5(x);
|
|
}
|
|
|
|
/**
|
|
* Gets graph screen y for y value.
|
|
*
|
|
* @param graph The graph.
|
|
* @param y The y value.
|
|
*
|
|
* @return The graph screen y for value.
|
|
*/
|
|
FORCE_INLINE_FUNCTION CWRUtil::Q5 valueToScreenYQ5(const AbstractDataGraph* graph, int y) const
|
|
{
|
|
return graph->valueToScreenYQ5(y);
|
|
}
|
|
|
|
/**
|
|
* Gets screen x coordinate for a specific data point added to the graph.
|
|
*
|
|
* @param graph The graph.
|
|
* @param index The index of the element to get the x coordinate for.
|
|
*
|
|
* @return The screen x coordinate for the specific data point.
|
|
*/
|
|
FORCE_INLINE_FUNCTION CWRUtil::Q5 indexToScreenXQ5(const AbstractDataGraph* graph, int16_t index) const
|
|
{
|
|
return graph->indexToScreenXQ5(index);
|
|
}
|
|
|
|
/**
|
|
* Gets screen y coordinate for a specific data point added to the graph.
|
|
*
|
|
* @param graph The graph.
|
|
* @param index The index of the element to get the y coordinate for.
|
|
*
|
|
* @return The screen x coordinate for the specific data point.
|
|
*/
|
|
FORCE_INLINE_FUNCTION CWRUtil::Q5 indexToScreenYQ5(const AbstractDataGraph* graph, int16_t index) const
|
|
{
|
|
return graph->indexToScreenYQ5(index);
|
|
}
|
|
|
|
/**
|
|
* Gets graph element range for screen x coordinate range.
|
|
*
|
|
* @param graph The graph.
|
|
* @param xMin The low X.
|
|
* @param xMax The high X.
|
|
* @param [out] indexMin The low index.
|
|
* @param [out] indexMax The high index.
|
|
*
|
|
* @return True if it succeeds, false if it fails.
|
|
*/
|
|
FORCE_INLINE_FUNCTION bool xScreenRangeToIndexRange(const AbstractDataGraph* graph, int16_t xMin, int16_t xMax, int16_t& indexMin, int16_t& indexMax) const
|
|
{
|
|
return graph->xScreenRangeToIndexRange(xMin, xMax, indexMin, indexMax);
|
|
}
|
|
|
|
/**
|
|
* Find the screen rectangle containing the Q5 screen rectangle by rounding the coordinates
|
|
* up/down.
|
|
*
|
|
* @param screenXminQ5 The minimum screen x coordinate (in Q5).
|
|
* @param screenYminQ5 The maximum screen y coordinate (in Q5).
|
|
* @param screenXmaxQ5 The minimum screen x coordinate (in Q5).
|
|
* @param screenYmaxQ5 The maximum screen y coordinate (in Q5).
|
|
*
|
|
* @return A Rect containing the Q5 rectangle.
|
|
*/
|
|
Rect rectFromQ5Coordinates(CWRUtil::Q5 screenXminQ5, CWRUtil::Q5 screenYminQ5, CWRUtil::Q5 screenXmaxQ5, CWRUtil::Q5 screenYmaxQ5) const;
|
|
|
|
/**
|
|
* Find the screen rectangle around a given point with the specified diameter.
|
|
*
|
|
* @param xQ5 The screen x coordinate (in Q5).
|
|
* @param yQ5 The screen y coordinate (in Q5).
|
|
* @param diameterQ5 The diameter (in Q5).
|
|
*
|
|
* @return A Rect containing the point (and diameter).
|
|
*/
|
|
Rect rectAround(CWRUtil::Q5 xQ5, CWRUtil::Q5 yQ5, CWRUtil::Q5 diameterQ5) const;
|
|
|
|
/**
|
|
* Round the given CWRUtil::Q5 to the nearest integer and return it as a CWRUtil::Q5 instead
|
|
* of an integer.
|
|
*
|
|
* @param q5 The CWRUtil::Q5 value to round.
|
|
*
|
|
* @return The nearest integer as a CWRUtil::Q5 value.
|
|
*/
|
|
FORCE_INLINE_FUNCTION CWRUtil::Q5 roundQ5(CWRUtil::Q5 q5) const
|
|
{
|
|
return CWRUtil::toQ5(q5.round());
|
|
}
|
|
|
|
/**
|
|
* Converts the value to the proper X scale of the graph.
|
|
*
|
|
* @param graph The graph.
|
|
* @param value The value.
|
|
* @param scale The scale.
|
|
*
|
|
* @return The given data converted to a graph scale x coordinate.
|
|
*/
|
|
FORCE_INLINE_FUNCTION int convertToGraphScaleX(const AbstractDataGraph* graph, int value, int scale) const
|
|
{
|
|
return AbstractDataGraph::convertToNewScale(value, scale, graph->getScaleX());
|
|
}
|
|
|
|
/**
|
|
* Converts the value to the proper Y scale of the graph.
|
|
*
|
|
* @param graph The graph.
|
|
* @param value The value.
|
|
* @param scale The scale.
|
|
*
|
|
* @return The given data converted to a graph scale y coordinate.
|
|
*/
|
|
FORCE_INLINE_FUNCTION int convertToGraphScaleY(const AbstractDataGraph* graph, int value, int scale) const
|
|
{
|
|
return AbstractDataGraph::convertToNewScale(value, scale, graph->getScaleY());
|
|
}
|
|
|
|
/**
|
|
* @copydoc AbstractDataGraph::indexToXAxis
|
|
*
|
|
* @param graph The graph.
|
|
*
|
|
* @return The x axis value.
|
|
*/
|
|
FORCE_INLINE_FUNCTION int getIndexToXAxis(const AbstractDataGraph* graph, const int valueScaled, const int labelScaled) const
|
|
{
|
|
return graph->indexToXAxis(valueScaled, labelScaled);
|
|
}
|
|
|
|
/**
|
|
* Query if the center of a given data point index is visible inside the graph area.
|
|
*
|
|
* @param graph The graph.
|
|
* @param index The data point index.
|
|
*
|
|
* @return True if center invisible, false if not.
|
|
*/
|
|
bool isCenterInvisible(const AbstractDataGraph* graph, int16_t index) const;
|
|
};
|
|
|
|
/**
|
|
* An abstract graph element. Declares a couple of useful functions to help subclasses which do
|
|
* not use CWR (Canvas Widget Renderer).
|
|
*/
|
|
class AbstractGraphElementNoCWR : public AbstractGraphElement
|
|
{
|
|
public:
|
|
AbstractGraphElementNoCWR()
|
|
: color(0)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Sets the color of the graph element.
|
|
*
|
|
* @param newColor The new color.
|
|
*
|
|
* @see getColor
|
|
*/
|
|
virtual void setColor(colortype newColor)
|
|
{
|
|
color = newColor;
|
|
}
|
|
|
|
/**
|
|
* Gets the color of the graph element.
|
|
*
|
|
* @return The color.
|
|
*
|
|
* @see setColor
|
|
*/
|
|
virtual colortype getColor() const
|
|
{
|
|
return color;
|
|
}
|
|
|
|
virtual bool drawCanvasWidget(const Rect&) const
|
|
{
|
|
return true;
|
|
}
|
|
|
|
protected:
|
|
colortype color; ///< The currently assigned color
|
|
|
|
/**
|
|
* Normalize rectangle by changing a rectangle with negative width or height to a rectangle
|
|
* with positive width or height at the correct position.
|
|
*
|
|
* @param [in,out] r The rectangle.
|
|
*/
|
|
void normalizeRect(Rect& r) const;
|
|
|
|
private:
|
|
virtual void setPainter(AbstractPainter& /*painter*/)
|
|
{
|
|
}
|
|
};
|
|
|
|
/**
|
|
* GraphElementGridBase is a helper class used to implement classed to draw grid lines in the
|
|
* graph.
|
|
*/
|
|
class GraphElementGridBase : public AbstractGraphElementNoCWR
|
|
{
|
|
public:
|
|
/** Default constructor. */
|
|
GraphElementGridBase()
|
|
: dataScale(1), gridInterval(10), lineWidth(1), majorGrid(0)
|
|
{
|
|
}
|
|
|
|
virtual void draw(const Rect& invalidatedArea) const;
|
|
|
|
/**
|
|
* Sets a scaling factor to be multiplied on the grid interval. Any already set grid interval
|
|
* will be updated to the new correctly scaled value. To avoid this, use setIntervalScaled()
|
|
* after setting scale.
|
|
*
|
|
* @param scale The scaling factor.
|
|
*
|
|
* @see getScale
|
|
*/
|
|
FORCE_INLINE_FUNCTION void setScale(int scale)
|
|
{
|
|
assert(scale != 0);
|
|
gridInterval = AbstractDataGraph::convertToNewScale(gridInterval, dataScale, scale);
|
|
dataScale = scale;
|
|
}
|
|
|
|
/**
|
|
* Gets the scaling factor set using setScale.
|
|
*
|
|
* @return The scaling factor.
|
|
*
|
|
* @see setScale
|
|
*/
|
|
FORCE_INLINE_FUNCTION int getScale() const
|
|
{
|
|
return dataScale;
|
|
}
|
|
|
|
/**
|
|
* Sets the interval between each grid line.
|
|
*
|
|
* @param interval The interval between each grid line.
|
|
*
|
|
* @see getIntervalAsInt, getIntervalAsFloat, setMajorGrid
|
|
*
|
|
* @note If interval is 0 only the axis is shown.
|
|
*/
|
|
FORCE_INLINE_FUNCTION void setInterval(int interval)
|
|
{
|
|
setIntervalScaled(abs(interval) * dataScale);
|
|
}
|
|
|
|
/** @copydoc setInterval(int) */
|
|
FORCE_INLINE_FUNCTION void setInterval(float interval)
|
|
{
|
|
setIntervalScaled(AbstractDataGraph::float2scaled(abs(interval), dataScale));
|
|
}
|
|
|
|
/**
|
|
* @copydoc setInterval(int)
|
|
*
|
|
* @note The interval set here must already be scaled.
|
|
*/
|
|
FORCE_INLINE_FUNCTION void setIntervalScaled(int interval)
|
|
{
|
|
gridInterval = abs(interval);
|
|
}
|
|
|
|
/**
|
|
* Gets the interval between each grid line.
|
|
*
|
|
* @return The interval between each grid line.
|
|
*
|
|
* @see setInterval
|
|
*/
|
|
FORCE_INLINE_FUNCTION int getIntervalAsInt() const
|
|
{
|
|
return AbstractDataGraph::scaled2int(getIntervalScaled(), dataScale);
|
|
}
|
|
|
|
/** @copydoc getIntervalAsInt() */
|
|
FORCE_INLINE_FUNCTION float getIntervalAsFloat() const
|
|
{
|
|
return AbstractDataGraph::scaled2float(getIntervalScaled(), dataScale);
|
|
}
|
|
|
|
/**
|
|
* @copydoc getIntervalAsInt()
|
|
*
|
|
* @note The interval returned here is left unscaled.
|
|
*/
|
|
FORCE_INLINE_FUNCTION int getIntervalScaled() const
|
|
{
|
|
return gridInterval;
|
|
}
|
|
|
|
/**
|
|
* Sets "major" grid that will be responsible for drawing major grid lines. If a grid line
|
|
* would be drawn at the same position as the major grid line, the grid line will not be
|
|
* drawn.
|
|
*
|
|
* @param major Reference to a major grid line object.
|
|
*/
|
|
FORCE_INLINE_FUNCTION void setMajorGrid(const GraphElementGridBase& major)
|
|
{
|
|
majorGrid = &major;
|
|
}
|
|
|
|
/**
|
|
* Sets line width of the grid lines.
|
|
*
|
|
* @param width The width of the grid lines.
|
|
*
|
|
* @see getLineWidth
|
|
*/
|
|
FORCE_INLINE_FUNCTION void setLineWidth(uint8_t width)
|
|
{
|
|
lineWidth = width;
|
|
}
|
|
|
|
/**
|
|
* Gets line width.
|
|
*
|
|
* @return The line width.
|
|
*
|
|
* @see setLineWidth
|
|
*/
|
|
FORCE_INLINE_FUNCTION uint8_t getLineWidth() const
|
|
{
|
|
return lineWidth;
|
|
}
|
|
|
|
virtual void invalidateGraphPointAt(int16_t)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Gets correctly scaled minor interval, as the minor grid may have a scale that differs the
|
|
* scale of the graph and this grid line.
|
|
*
|
|
* @param graph The graph.
|
|
*
|
|
* @return The correctly scaled minor interval.
|
|
*/
|
|
virtual int getCorrectlyScaledGridInterval(const AbstractDataGraph* graph) const = 0;
|
|
|
|
/**
|
|
* Gets correctly scaled major interval, as the major grid may have a scale that differs the
|
|
* scale of the graph and this grid line.
|
|
*
|
|
* @param graph The graph.
|
|
*
|
|
* @return The correctly scaled major interval.
|
|
*/
|
|
virtual int getCorrectlyScaledMajorInterval(const AbstractDataGraph* graph) const
|
|
{
|
|
return majorGrid == 0 ? 0 : majorGrid->getCorrectlyScaledGridInterval(graph);
|
|
}
|
|
|
|
protected:
|
|
int dataScale; ///< The scaling factor
|
|
int gridInterval; ///< The grid line interval.
|
|
uint8_t lineWidth; ///< Width of the line.
|
|
const GraphElementGridBase* majorGrid; ///< A pointer to a major grid, if any
|
|
|
|
/**
|
|
* Draw vertical line using LCD::fillRect and handles negative dimensions properly.
|
|
*
|
|
* @param invalidatedArea The invalidated area to intersect the line with.
|
|
* @param start The start coordinate (offset from edge).
|
|
* @param length The length of the line.
|
|
* @param pos The start coordinate (distance in span).
|
|
* @param width The width of the line.
|
|
* @param a The alpha of the line.
|
|
*/
|
|
virtual void drawLine(const Rect& invalidatedArea, int16_t start, int16_t length, int16_t pos, int16_t width, uint8_t a) const;
|
|
|
|
/**
|
|
* Return the enclosing area for the grid lines. Vertical lines are allowed to go a bit to
|
|
* the left and right, but not above or below. Vice versa for horizontal gridlines.
|
|
*
|
|
* @param graph The graph.
|
|
*
|
|
* @return A Rect which the grid lines should be inside.
|
|
*/
|
|
virtual Rect enclosingArea(const AbstractDataGraph* graph) const = 0;
|
|
|
|
/**
|
|
* Return the specific rectangle for line.
|
|
*
|
|
* @param start The start (distance from the border).
|
|
* @param length The length (length of the line).
|
|
* @param pos The position (horizonal offset for vertical lines, vertical offset for
|
|
* horizontal lines).
|
|
* @param width The (line) width.
|
|
*
|
|
* @return A Rect.
|
|
*/
|
|
virtual Rect lineRect(int16_t start, int16_t length, int16_t pos, int16_t width) const = 0;
|
|
|
|
/**
|
|
* Gets graph range minimum x/y scaled.
|
|
*
|
|
* @param graph The graph.
|
|
*
|
|
* @return The graph range minimum scaled.
|
|
*/
|
|
virtual int getGraphRangeMinScaled(const AbstractDataGraph* graph) const = 0;
|
|
|
|
/**
|
|
* Gets graph range maximum x/y scaled.
|
|
*
|
|
* @param graph The graph.
|
|
*
|
|
* @return The graph range maximum scaled.
|
|
*/
|
|
virtual int getGraphRangeMaxScaled(const AbstractDataGraph* graph) const = 0;
|
|
|
|
/**
|
|
* Gets graph area start (distance from the border).
|
|
*
|
|
* @param graph The graph.
|
|
*
|
|
* @return The graph area start (distance from the border).
|
|
*/
|
|
virtual int getGraphAreaStart(const AbstractDataGraph* graph) const = 0;
|
|
|
|
/**
|
|
* Gets graph area length (distance from border to border).
|
|
*
|
|
* @param graph The graph.
|
|
*
|
|
* @return The graph area length (distance from border to border.
|
|
*/
|
|
virtual int getGraphAreaLength(const AbstractDataGraph* graph) const = 0;
|
|
|
|
/**
|
|
* Gets graph area start position. Horizontal offset of first vertical line or vertical
|
|
* offset of first horizontal line.
|
|
*
|
|
* @param graph The graph.
|
|
*
|
|
* @return The graph area start position. Horizontal offset of first vertical line or
|
|
* vertical offset og first horizontal line.
|
|
*/
|
|
virtual int getGraphAreaStartPos(const AbstractDataGraph* graph) const = 0;
|
|
|
|
/**
|
|
* Gets graph area end position. Horizontal offset of last vertical line or vertical offset
|
|
* of last horizontal line.
|
|
*
|
|
* @param graph The graph.
|
|
*
|
|
* @return The graph area end position. Horizontal offset of last vertical line or vertical
|
|
* offset of last horizontal line.
|
|
*/
|
|
virtual int getGraphAreaEndPos(const AbstractDataGraph* graph) const = 0;
|
|
|
|
/**
|
|
* The graph value to the correct screen coordinate in Q5.
|
|
*
|
|
* @param graph The graph.
|
|
* @param value The value.
|
|
*
|
|
* @return The graph value to the correct screen coordinate in Q5.
|
|
*/
|
|
virtual CWRUtil::Q5 valueToScreenQ5(const AbstractDataGraph* graph, int value) const = 0;
|
|
};
|
|
|
|
/**
|
|
* GraphElementGridX draws vertical lines at selected intervals along the x axis. By combining
|
|
* two GraphElementGridX instances, it is possible to have minor and major grid lines.
|
|
*
|
|
* @note The grid lines are drawn using LCD::fillRect for higher performance.
|
|
*/
|
|
class GraphElementGridX : public GraphElementGridBase
|
|
{
|
|
public:
|
|
virtual int getCorrectlyScaledGridInterval(const AbstractDataGraph* graph) const
|
|
{
|
|
return convertToGraphScaleX(graph, gridInterval, dataScale);
|
|
}
|
|
|
|
protected:
|
|
virtual Rect enclosingArea(const AbstractDataGraph* graph) const
|
|
{
|
|
return Rect(0, graph->getGraphAreaPaddingTop(), graph->getGraphAreaWidthIncludingPadding(), graph->getGraphAreaHeight());
|
|
}
|
|
|
|
virtual Rect lineRect(int16_t start, int16_t length, int16_t pos, int16_t width) const
|
|
{
|
|
return Rect(pos, start, width, length);
|
|
}
|
|
|
|
virtual int getGraphRangeMinScaled(const AbstractDataGraph* graph) const
|
|
{
|
|
return graph->getGraphRangeXMinScaled();
|
|
}
|
|
|
|
virtual int getGraphRangeMaxScaled(const AbstractDataGraph* graph) const
|
|
{
|
|
return graph->getGraphRangeXMaxScaled();
|
|
}
|
|
|
|
virtual int getGraphAreaStart(const AbstractDataGraph* graph) const
|
|
{
|
|
return graph->getGraphAreaPaddingTop();
|
|
}
|
|
|
|
virtual int getGraphAreaLength(const AbstractDataGraph* graph) const
|
|
{
|
|
return graph->getGraphAreaHeight();
|
|
}
|
|
|
|
virtual int getGraphAreaStartPos(const AbstractDataGraph* graph) const
|
|
{
|
|
return graph->getGraphAreaPaddingLeft();
|
|
}
|
|
|
|
virtual int getGraphAreaEndPos(const AbstractDataGraph* graph) const
|
|
{
|
|
return graph->getGraphAreaWidth();
|
|
}
|
|
|
|
virtual CWRUtil::Q5 valueToScreenQ5(const AbstractDataGraph* graph, int value) const
|
|
{
|
|
return valueToScreenXQ5(graph, value);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* GraphElementGridY draws horizontal lines at selected intervals along the y axis. By combining
|
|
* two GraphElementGridY instances, it is possible to have minor and major grid lines.
|
|
*
|
|
* @note The grid lines are drawn using LCD::fillRect for higher performance.
|
|
*/
|
|
class GraphElementGridY : public GraphElementGridBase
|
|
{
|
|
public:
|
|
virtual int getCorrectlyScaledGridInterval(const AbstractDataGraph* graph) const
|
|
{
|
|
return convertToGraphScaleY(graph, gridInterval, dataScale);
|
|
}
|
|
|
|
protected:
|
|
virtual Rect enclosingArea(const AbstractDataGraph* graph) const
|
|
{
|
|
return Rect(graph->getGraphAreaPaddingLeft(), 0, graph->getGraphAreaWidth(), graph->getGraphAreaHeightIncludingPadding());
|
|
}
|
|
|
|
virtual Rect lineRect(int16_t start, int16_t length, int16_t pos, int16_t width) const
|
|
{
|
|
return Rect(start, pos, length, width);
|
|
}
|
|
|
|
virtual int getGraphRangeMinScaled(const AbstractDataGraph* graph) const
|
|
{
|
|
return graph->getGraphRangeYMinScaled();
|
|
}
|
|
|
|
virtual int getGraphRangeMaxScaled(const AbstractDataGraph* graph) const
|
|
{
|
|
return graph->getGraphRangeYMaxScaled();
|
|
}
|
|
|
|
virtual int getGraphAreaStart(const AbstractDataGraph* graph) const
|
|
{
|
|
return graph->getGraphAreaPaddingLeft();
|
|
}
|
|
|
|
virtual int getGraphAreaLength(const AbstractDataGraph* graph) const
|
|
{
|
|
return graph->getGraphAreaWidth();
|
|
}
|
|
|
|
virtual int getGraphAreaStartPos(const AbstractDataGraph* graph) const
|
|
{
|
|
return graph->getGraphAreaPaddingTop();
|
|
}
|
|
|
|
virtual int getGraphAreaEndPos(const AbstractDataGraph* graph) const
|
|
{
|
|
return graph->getGraphAreaHeight();
|
|
}
|
|
|
|
virtual CWRUtil::Q5 valueToScreenQ5(const AbstractDataGraph* graph, int value) const
|
|
{
|
|
return valueToScreenYQ5(graph, value);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* GraphElementArea will fill the area below the line connecting the data points in the graph.
|
|
*
|
|
* @note The Area is drawn using Canvas Widget Renderer which is slower but produces much nicer
|
|
* graphics.
|
|
*/
|
|
class GraphElementArea : public AbstractGraphElement
|
|
{
|
|
public:
|
|
GraphElementArea()
|
|
: dataScale(1), yBaseline(0)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Sets a scaling factor to be multiplied on the baseline. Any already set baseline will be
|
|
* updated to the new correctly scaled value. To avoid this, use setBaselineScaled()
|
|
* after setting scale.
|
|
*
|
|
* @param scale The scaling factor.
|
|
*
|
|
* @see getScale
|
|
*/
|
|
FORCE_INLINE_FUNCTION void setScale(int scale)
|
|
{
|
|
assert(scale != 0);
|
|
yBaseline = AbstractDataGraph::convertToNewScale(yBaseline, dataScale, scale);
|
|
dataScale = scale;
|
|
}
|
|
|
|
/**
|
|
* Gets the scaling factor set using setScale.
|
|
*
|
|
* @return The scaling factor.
|
|
*
|
|
* @see setScale
|
|
*/
|
|
FORCE_INLINE_FUNCTION int getScale() const
|
|
{
|
|
return dataScale;
|
|
}
|
|
|
|
/**
|
|
* Sets the base of the area drawn. Normally, the base is 0 which means that the area is
|
|
* drawn below positive y values and above negative y values. Setting the base to a very
|
|
* high number will cause the area above the graph to be drawn. Setting the base to a very
|
|
* low number will cause the area below the graph to be drawn (even for negative numbers,
|
|
* which are higher than the base value).
|
|
*
|
|
* @param baseline The baseline value.
|
|
*
|
|
* @see getBaselineAsInt, getBaselineAsFloat
|
|
*/
|
|
FORCE_INLINE_FUNCTION void setBaseline(int baseline)
|
|
{
|
|
setBaselineScaled(baseline * dataScale);
|
|
}
|
|
|
|
/** @copydoc setBaseline(int) */
|
|
FORCE_INLINE_FUNCTION void setBaseline(float baseline)
|
|
{
|
|
setBaselineScaled(AbstractDataGraph::float2scaled(baseline, dataScale));
|
|
}
|
|
|
|
/**
|
|
* @copydoc setBaseline(int)
|
|
*
|
|
* @note The baseline set here must already be scaled.
|
|
*/
|
|
FORCE_INLINE_FUNCTION void setBaselineScaled(int baseline)
|
|
{
|
|
yBaseline = baseline;
|
|
}
|
|
|
|
/**
|
|
* Gets the base previously set using setBase.
|
|
*
|
|
* @return The base value.
|
|
*
|
|
* @see setBaseline
|
|
*/
|
|
FORCE_INLINE_FUNCTION int getBaselineAsInt() const
|
|
{
|
|
return AbstractDataGraph::scaled2int(getBaselineScaled(), dataScale);
|
|
}
|
|
|
|
/** @copydoc getBaselineAsInt() */
|
|
FORCE_INLINE_FUNCTION float getBaselineAsFloat() const
|
|
{
|
|
return AbstractDataGraph::scaled2float(getBaselineScaled(), dataScale);
|
|
}
|
|
|
|
/**
|
|
* @copydoc getBaselineAsInt()
|
|
*
|
|
* @note The baseline returned here is left unscaled.
|
|
*/
|
|
FORCE_INLINE_FUNCTION int getBaselineScaled() const
|
|
{
|
|
return yBaseline;
|
|
}
|
|
|
|
virtual bool drawCanvasWidget(const Rect& invalidatedArea) const;
|
|
|
|
virtual void invalidateGraphPointAt(int16_t index);
|
|
|
|
protected:
|
|
int dataScale; ///< The scaling factor
|
|
int yBaseline; ///< The base value.
|
|
};
|
|
|
|
/**
|
|
* GraphElementLine will draw a line with a given thickness through the data points in the graph.
|
|
*
|
|
* @note The Line is drawn using Canvas Widget Renderer which is slower but produces much nicer
|
|
* graphics.
|
|
*/
|
|
class GraphElementLine : public AbstractGraphElement
|
|
{
|
|
public:
|
|
GraphElementLine()
|
|
: lineWidth(2)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Sets line width.
|
|
*
|
|
* @param width The width.
|
|
*
|
|
* @see getLineWidth
|
|
*/
|
|
FORCE_INLINE_FUNCTION void setLineWidth(uint8_t width)
|
|
{
|
|
lineWidth = width;
|
|
}
|
|
|
|
/**
|
|
* Gets line width.
|
|
*
|
|
* @return The line width.
|
|
*
|
|
* @see setLineWidth
|
|
*/
|
|
FORCE_INLINE_FUNCTION uint8_t getLineWidth() const
|
|
{
|
|
return lineWidth;
|
|
}
|
|
|
|
virtual bool drawCanvasWidget(const Rect& invalidatedArea) const;
|
|
|
|
virtual void invalidateGraphPointAt(int16_t index);
|
|
|
|
protected:
|
|
uint8_t lineWidth; ///< Width of the line
|
|
|
|
/**
|
|
* Draw a line between all indexes in the given range. This is used where there is a gap in
|
|
* the graph and the line has to be drawn as two separate lines.
|
|
*
|
|
* @param [in] canvas The canvas.
|
|
* @param graph The graph.
|
|
* @param indexMin The minimum index.
|
|
* @param indexMax The maximum index.
|
|
*/
|
|
void drawIndexRange(Canvas& canvas, const AbstractDataGraph* graph, int16_t indexMin, int16_t indexMax) const;
|
|
};
|
|
|
|
/**
|
|
* The GraphElementVerticalGapLine is used to draw a vertical line where the gap in the graph
|
|
* is. This only makes sense to add to a GraphWrapAndOverwrite (or GraphWrapAndOverwriteData).
|
|
*
|
|
* @note The vertical line is drawn using LCD::fillRect for higher performance.
|
|
*/
|
|
class GraphElementVerticalGapLine : public AbstractGraphElementNoCWR
|
|
{
|
|
public:
|
|
/**
|
|
* Sets the width of the gap line in pixels. If the gap line is set to 0 the gap line will
|
|
* extend to the next point in the graph.
|
|
*
|
|
* @param width The width.
|
|
*
|
|
* @see getGapLineWidth
|
|
*/
|
|
FORCE_INLINE_FUNCTION void setGapLineWidth(uint16_t width)
|
|
{
|
|
lineWidth = width;
|
|
}
|
|
|
|
/**
|
|
* Gets the width of the gap line as set using setGapLineWidth().
|
|
*
|
|
* @return The gap line width.
|
|
*/
|
|
FORCE_INLINE_FUNCTION uint16_t getGapLineWidth() const
|
|
{
|
|
return lineWidth;
|
|
}
|
|
|
|
virtual void draw(const Rect& invalidatedArea) const;
|
|
|
|
virtual void invalidateGraphPointAt(int16_t index);
|
|
|
|
protected:
|
|
uint16_t lineWidth; ///< Width of the line
|
|
|
|
private:
|
|
void invalidateIndex(const AbstractDataGraph* graph, int16_t index) const;
|
|
};
|
|
|
|
/**
|
|
* The GraphElementHistogram is used to draw blocks from the x axis to the data point in the
|
|
* graph. If more graphs are placed on top of each other, the histogram can be moved slightly to
|
|
* the left/right.
|
|
*
|
|
* @note Historgram boxes are drawn using LCD::fillRect for higher performance.
|
|
*/
|
|
class GraphElementHistogram : public AbstractGraphElementNoCWR
|
|
{
|
|
public:
|
|
GraphElementHistogram()
|
|
: dataScale(1), yBaseline(0), barWidth(2), barOffset(0)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Sets a scaling factor to be multiplied on the baseline. Any already set baseline will be
|
|
* updated to the new correctly scaled value. To avoid this, use setBaselineScaled()
|
|
* after setting scale.
|
|
*
|
|
* @param scale The scaling factor.
|
|
*
|
|
* @see getScale
|
|
*/
|
|
FORCE_INLINE_FUNCTION void setScale(int scale)
|
|
{
|
|
assert(scale != 0);
|
|
yBaseline = AbstractDataGraph::convertToNewScale(yBaseline, dataScale, scale);
|
|
dataScale = scale;
|
|
}
|
|
|
|
/**
|
|
* Gets the scaling factor set using setScale.
|
|
*
|
|
* @return The scaling factor.
|
|
*
|
|
* @see setScale
|
|
*/
|
|
FORCE_INLINE_FUNCTION int getScale() const
|
|
{
|
|
return dataScale;
|
|
}
|
|
|
|
/**
|
|
* Sets the base of the area drawn. Normally, the base is 0 which means that the area is
|
|
* drawn below positive y values and above negative y values. Setting the base to a very
|
|
* high number will cause the area above the graph to be drawn. Setting the base to a very
|
|
* low number will cause the area below the graph to be drawn (even for negative numbers,
|
|
* which are higher than the base value).
|
|
*
|
|
* @param baseline The base value.
|
|
*
|
|
* @see getBaselineAsInt, getBaselineAsFloat
|
|
*/
|
|
FORCE_INLINE_FUNCTION void setBaseline(int baseline)
|
|
{
|
|
setBaselineScaled(baseline * dataScale);
|
|
}
|
|
|
|
/** @copydoc setBaseline(int) */
|
|
FORCE_INLINE_FUNCTION void setBaseline(float baseline)
|
|
{
|
|
setBaselineScaled(AbstractDataGraph::float2scaled(baseline, dataScale));
|
|
}
|
|
|
|
/**
|
|
* @copydoc setBaseline(int)
|
|
*
|
|
* @note The baseline set here must already be scaled.
|
|
*/
|
|
FORCE_INLINE_FUNCTION void setBaselineScaled(int baseline)
|
|
{
|
|
yBaseline = baseline;
|
|
}
|
|
|
|
/**
|
|
* Gets the base previously set using setBaseline.
|
|
*
|
|
* @return The base value.
|
|
*
|
|
* @see setBaseline
|
|
*/
|
|
FORCE_INLINE_FUNCTION int getBaselineAsInt() const
|
|
{
|
|
return AbstractDataGraph::scaled2int(getBaselineScaled(), dataScale);
|
|
}
|
|
|
|
/** @copydoc getBaselineAsInt() */
|
|
FORCE_INLINE_FUNCTION float getBaselineAsFloat() const
|
|
{
|
|
return AbstractDataGraph::scaled2float(getBaselineScaled(), dataScale);
|
|
}
|
|
|
|
/**
|
|
* @copydoc getBaselineAsInt()
|
|
*
|
|
* @note The baseline returned here is left unscaled.
|
|
*/
|
|
FORCE_INLINE_FUNCTION int getBaselineScaled() const
|
|
{
|
|
return yBaseline;
|
|
}
|
|
|
|
/**
|
|
* Sets bar width of each histogram column in pixels.
|
|
*
|
|
* @param width The width.
|
|
*
|
|
* @see getBarWidth
|
|
*/
|
|
FORCE_INLINE_FUNCTION void setBarWidth(uint16_t width)
|
|
{
|
|
barWidth = width;
|
|
}
|
|
|
|
/**
|
|
* Gets bar width of the histogram columns.
|
|
*
|
|
* @return The bar width.
|
|
*
|
|
* @see setBarWidth
|
|
*/
|
|
FORCE_INLINE_FUNCTION uint16_t getBarWidth() const
|
|
{
|
|
return barWidth;
|
|
}
|
|
|
|
/**
|
|
* Sets bar offset (horizontally) in pixels. This can be used when there are two different histogram
|
|
* graphs on top of each other to prevent one histogram from covering the other.
|
|
*
|
|
* @param offset The offset.
|
|
*
|
|
* @see getBarOffset
|
|
*/
|
|
FORCE_INLINE_FUNCTION void setBarOffset(int16_t offset)
|
|
{
|
|
barOffset = offset;
|
|
}
|
|
|
|
/**
|
|
* Gets bar offset (horizontally). Bar offset can be used when there are two different
|
|
* histogram graphs on top of each other to prevent one histogram from covering the other.
|
|
*
|
|
* @return The bar offset.
|
|
*
|
|
* @see setBarOffset
|
|
*/
|
|
FORCE_INLINE_FUNCTION int16_t getBarOffset() const
|
|
{
|
|
return barOffset;
|
|
}
|
|
|
|
virtual void draw(const Rect& invalidatedArea) const;
|
|
|
|
virtual void invalidateGraphPointAt(int16_t index);
|
|
|
|
protected:
|
|
int dataScale; ///< The scaling factor
|
|
int yBaseline; ///< The baseline
|
|
uint16_t barWidth; ///< Width of each bar
|
|
int16_t barOffset; ///< The horizontal bar offset
|
|
};
|
|
|
|
/**
|
|
* GraphElementBoxes will draw square box for every data point in graph.
|
|
*
|
|
* @note The boxes are drawn using LCD::fillRect for higher performance. This also means that
|
|
* boxes with an odd width will not align properly if combined with a GraphElementLine or
|
|
* any other GraphElement that uses Canvas Widget Renderer. Use an even number for box width
|
|
* in these cases.
|
|
*/
|
|
class GraphElementBoxes : public AbstractGraphElementNoCWR
|
|
{
|
|
public:
|
|
GraphElementBoxes()
|
|
: boxWidth(2)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Sets box width.
|
|
*
|
|
* @param width The width.
|
|
*
|
|
* @see getBoxWidth
|
|
*/
|
|
FORCE_INLINE_FUNCTION void setBoxWidth(uint16_t width)
|
|
{
|
|
boxWidth = width;
|
|
}
|
|
|
|
/**
|
|
* Gets box width.
|
|
*
|
|
* @return The box width.
|
|
*
|
|
* @see setBoxWidth
|
|
*/
|
|
FORCE_INLINE_FUNCTION uint16_t getBoxWidth() const
|
|
{
|
|
return boxWidth;
|
|
}
|
|
|
|
virtual void draw(const Rect& invalidatedArea) const;
|
|
|
|
virtual void invalidateGraphPointAt(int16_t index);
|
|
|
|
protected:
|
|
uint16_t boxWidth; ///< Width of the box
|
|
};
|
|
|
|
/**
|
|
* GraphElementDots will draw a circular dot for every data point in graph.
|
|
*
|
|
* @note The Dots are drawn using Canvas Widget Renderer which is slower but produces much nicer
|
|
* graphics.
|
|
*/
|
|
class GraphElementDots : public AbstractGraphElement
|
|
{
|
|
public:
|
|
GraphElementDots()
|
|
: dotWidth(2)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Sets dot width.
|
|
*
|
|
* @param width The width.
|
|
*
|
|
* @see getDotWidth
|
|
*/
|
|
FORCE_INLINE_FUNCTION void setDotWidth(uint8_t width)
|
|
{
|
|
dotWidth = width;
|
|
}
|
|
|
|
/**
|
|
* Gets dot width.
|
|
*
|
|
* @return The dot width.
|
|
*
|
|
* @see setDotWidth
|
|
*/
|
|
FORCE_INLINE_FUNCTION uint8_t getDotWidth() const
|
|
{
|
|
return dotWidth;
|
|
}
|
|
|
|
virtual bool drawCanvasWidget(const Rect& invalidatedArea) const;
|
|
|
|
virtual void invalidateGraphPointAt(int16_t index);
|
|
|
|
protected:
|
|
uint8_t dotWidth; ///< Width of the dot
|
|
};
|
|
|
|
/**
|
|
* GraphElementDiamonds will draw a diamond (a square with the corners up/down/left/right) for
|
|
* every data point in graph.
|
|
*
|
|
* @note The Diamonds are drawn using Canvas Widget Renderer which is slower but produces much
|
|
* nicer graphics.
|
|
*/
|
|
class GraphElementDiamonds : public AbstractGraphElement
|
|
{
|
|
public:
|
|
GraphElementDiamonds()
|
|
: diamondWidth(2)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Sets diamond width.
|
|
*
|
|
* @param width The width.
|
|
*
|
|
* @see getDiamondWidth
|
|
*/
|
|
FORCE_INLINE_FUNCTION void setDiamondWidth(uint8_t width)
|
|
{
|
|
diamondWidth = width;
|
|
}
|
|
|
|
/**
|
|
* Gets diamond width.
|
|
*
|
|
* @return The diamond width.
|
|
*
|
|
* @see setDiamondWidth
|
|
*/
|
|
FORCE_INLINE_FUNCTION uint8_t getDiamondWidth() const
|
|
{
|
|
return diamondWidth;
|
|
}
|
|
|
|
virtual bool drawCanvasWidget(const Rect& invalidatedArea) const;
|
|
|
|
virtual void invalidateGraphPointAt(int16_t index);
|
|
|
|
protected:
|
|
uint8_t diamondWidth; ///< Width of the diamond
|
|
};
|
|
|
|
} // namespace touchgfx
|
|
|
|
#endif // TOUCHGFX_GRAPHELEMENTS_HPP
|