UI update 02
This commit is contained in:
@@ -0,0 +1,646 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace XCharts.Runtime
|
||||
{
|
||||
/// <summary>
|
||||
/// Tooltip component.
|
||||
/// ||提示框组件。
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
[ComponentHandler(typeof(TooltipHandler), true)]
|
||||
public class Tooltip : MainComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicator type.
|
||||
/// ||指示器类型。
|
||||
/// </summary>
|
||||
public enum Type
|
||||
{
|
||||
/// <summary>
|
||||
/// line indicator.
|
||||
/// ||直线指示器
|
||||
/// </summary>
|
||||
Line,
|
||||
/// <summary>
|
||||
/// shadow crosshair indicator.
|
||||
/// ||阴影指示器
|
||||
/// </summary>
|
||||
Shadow,
|
||||
/// <summary>
|
||||
/// no indicator displayed.
|
||||
/// ||无指示器
|
||||
/// </summary>
|
||||
None,
|
||||
/// <summary>
|
||||
/// crosshair indicator, which is actually the shortcut of enable two axisPointers of two orthometric axes.
|
||||
/// ||十字准星指示器。坐标轴显示Label和交叉线。
|
||||
/// </summary>
|
||||
Cross,
|
||||
/// <summary>
|
||||
/// Auto select indicator according to serie type.
|
||||
/// ||根据serie的类型自动选择显示指示器。
|
||||
/// </summary>
|
||||
Auto
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Trigger strategy.
|
||||
/// ||触发类型。
|
||||
/// </summary>
|
||||
public enum Trigger
|
||||
{
|
||||
/// <summary>
|
||||
/// Triggered by data item, which is mainly used for charts that don't have a category axis like scatter charts or pie charts.
|
||||
/// ||数据项图形触发,主要在散点图,饼图等无类目轴的图表中使用。
|
||||
/// </summary>
|
||||
Item,
|
||||
/// <summary>
|
||||
/// Triggered by axes, which is mainly used for charts that have category axes, like bar charts or line charts.
|
||||
/// ||坐标轴触发,主要在柱状图,折线图等会使用类目轴的图表中使用。
|
||||
/// </summary>
|
||||
Axis,
|
||||
/// <summary>
|
||||
/// Trigger nothing.
|
||||
/// ||什么都不触发。
|
||||
/// </summary>
|
||||
None,
|
||||
/// <summary>
|
||||
/// Auto select trigger according to serie type.
|
||||
/// ||根据serie的类型自动选择触发类型。
|
||||
/// </summary>
|
||||
Auto
|
||||
}
|
||||
/// <summary>
|
||||
/// the condition of trigger tooltip.
|
||||
/// ||触发条件。
|
||||
/// </summary>
|
||||
public enum TriggerOn
|
||||
{
|
||||
/// <summary>
|
||||
/// Trigger when mouse move.
|
||||
/// ||鼠标移动时触发。
|
||||
/// </summary>
|
||||
MouseMove,
|
||||
/// <summary>
|
||||
/// Trigger when mouse click.
|
||||
/// ||鼠标点击时触发。
|
||||
/// </summary>
|
||||
Click,
|
||||
}
|
||||
/// <summary>
|
||||
/// Position type.
|
||||
/// ||坐标类型。
|
||||
/// </summary>
|
||||
public enum Position
|
||||
{
|
||||
/// <summary>
|
||||
/// Auto. The mobile platform is displayed at the top, and the non-mobile platform follows the mouse position.
|
||||
/// ||自适应。移动平台靠顶部显示,非移动平台跟随鼠标位置。
|
||||
/// </summary>
|
||||
Auto,
|
||||
/// <summary>
|
||||
/// Custom. Fully customize display position (x,y).
|
||||
/// ||自定义。完全自定义显示位置(x,y)。
|
||||
/// </summary>
|
||||
Custom,
|
||||
/// <summary>
|
||||
/// Just fix the coordinate X. Y follows the mouse position.
|
||||
/// ||只固定坐标X。Y跟随鼠标位置。
|
||||
/// </summary>
|
||||
FixedX,
|
||||
/// <summary>
|
||||
/// Just fix the coordinate Y. X follows the mouse position.
|
||||
/// ||只固定坐标Y。X跟随鼠标位置。
|
||||
FixedY
|
||||
}
|
||||
|
||||
[SerializeField] private bool m_Show = true;
|
||||
[SerializeField] private Type m_Type = Type.Auto;
|
||||
[SerializeField] private Trigger m_Trigger = Trigger.Auto;
|
||||
[SerializeField][Since("v3.11.0")] private TriggerOn m_TriggerOn = TriggerOn.MouseMove;
|
||||
[SerializeField][Since("v3.3.0")] private Position m_Position = Position.Auto;
|
||||
[SerializeField] private string m_ItemFormatter;
|
||||
[SerializeField] private string m_TitleFormatter;
|
||||
[SerializeField] private string m_Marker = "●";
|
||||
[SerializeField] private float m_FixedWidth = 0;
|
||||
[SerializeField] private float m_FixedHeight = 0;
|
||||
[SerializeField] private float m_MinWidth = 0;
|
||||
[SerializeField] private float m_MinHeight = 0;
|
||||
[SerializeField] private string m_NumericFormatter = "";
|
||||
[SerializeField] private int m_PaddingLeftRight = 10;
|
||||
[SerializeField] private int m_PaddingTopBottom = 10;
|
||||
[SerializeField] private bool m_IgnoreDataShow = false;
|
||||
[SerializeField] private string m_IgnoreDataDefaultContent = "-";
|
||||
[SerializeField] private bool m_ShowContent = true;
|
||||
[SerializeField] private bool m_AlwayShowContent = false;
|
||||
[SerializeField] private Vector2 m_Offset = new Vector2(18f, -25f);
|
||||
[SerializeField] private Sprite m_BackgroundImage;
|
||||
[SerializeField] private Image.Type m_BackgroundType = Image.Type.Simple;
|
||||
[SerializeField] private Color m_BackgroundColor;
|
||||
[SerializeField] private float m_BorderWidth = 2f;
|
||||
[SerializeField] private float m_FixedX = 0f;
|
||||
[SerializeField] private float m_FixedY = 0.7f;
|
||||
[SerializeField] private float m_TitleHeight = 25f;
|
||||
[SerializeField] private float m_ItemHeight = 25f;
|
||||
[SerializeField] private Color32 m_BorderColor = new Color32(230, 230, 230, 255);
|
||||
[SerializeField][Since("v3.14.0")] private List<float> m_ColumnGapWidths = new List<float>{15};
|
||||
[SerializeField] private LineStyle m_LineStyle = new LineStyle(LineStyle.Type.None);
|
||||
[SerializeField]
|
||||
private LabelStyle m_TitleLabelStyle = new LabelStyle()
|
||||
{
|
||||
textStyle = new TextStyle() { alignment = TextAnchor.MiddleLeft }
|
||||
};
|
||||
[SerializeField]
|
||||
private List<LabelStyle> m_ContentLabelStyles = new List<LabelStyle>()
|
||||
{
|
||||
new LabelStyle() { textPadding = new TextPadding(0, 5, 0, 0), textStyle = new TextStyle() { alignment = TextAnchor.MiddleCenter } },
|
||||
new LabelStyle() { textPadding = new TextPadding(0, 20, 0, 0), textStyle = new TextStyle() { alignment = TextAnchor.MiddleLeft } },
|
||||
new LabelStyle() { textPadding = new TextPadding(0, 0, 0, 0), textStyle = new TextStyle() { alignment = TextAnchor.MiddleRight } }
|
||||
};
|
||||
|
||||
public TooltipContext context = new TooltipContext();
|
||||
public TooltipView view;
|
||||
|
||||
/// <summary>
|
||||
/// the callback of tooltip click index.
|
||||
/// ||Tooltip为Click触发时,点击的X轴索引的回调。
|
||||
/// </summary>
|
||||
public System.Action<int> onClickIndex { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether to show the tooltip component.
|
||||
/// ||是否显示提示框组件。
|
||||
/// </summary>
|
||||
public bool show
|
||||
{
|
||||
get { return m_Show; }
|
||||
set { if (PropertyUtil.SetStruct(ref m_Show, value)) { SetAllDirty(); SetActive(value); } }
|
||||
}
|
||||
/// <summary>
|
||||
/// Indicator type.
|
||||
/// ||提示框指示器类型。
|
||||
/// </summary>
|
||||
public Type type
|
||||
{
|
||||
get { return m_Type; }
|
||||
set { if (PropertyUtil.SetStruct(ref m_Type, value)) SetAllDirty(); }
|
||||
}
|
||||
/// <summary>
|
||||
/// Type of triggering.
|
||||
/// ||触发类型。
|
||||
/// </summary>
|
||||
public Trigger trigger
|
||||
{
|
||||
get { return m_Trigger; }
|
||||
set { if (PropertyUtil.SetStruct(ref m_Trigger, value)) SetAllDirty(); }
|
||||
}
|
||||
/// <summary>
|
||||
/// Condition of trigger tooltip.
|
||||
/// ||触发条件。
|
||||
/// </summary>
|
||||
public TriggerOn triggerOn
|
||||
{
|
||||
get { return m_TriggerOn; }
|
||||
set { if (PropertyUtil.SetStruct(ref m_TriggerOn, value)) SetAllDirty(); }
|
||||
}
|
||||
/// <summary>
|
||||
/// Type of position.
|
||||
/// ||显示位置类型。
|
||||
/// </summary>
|
||||
public Position position
|
||||
{
|
||||
get { return m_Position; }
|
||||
set { if (PropertyUtil.SetStruct(ref m_Position, value)) SetAllDirty(); }
|
||||
}
|
||||
/// <summary>
|
||||
/// String template formatter for tooltip title content. \n line wrapping is supported. The placeholder {i} can be set separately to indicate that title is ignored and not displayed.
|
||||
/// Template variables are {.}, {a}, {b}, {c}, {d}, {e}, {f}, and {g}. <br />
|
||||
/// {.} is the dot of the corresponding color of serie currently indicated or index 0. <br />
|
||||
/// {a} is the series name name of serie currently indicated or index 0. <br />
|
||||
/// {b} is the name of the serie data item serieData currently indicated or index 0, or the category value (such as the X-axis of a line chart). <br />
|
||||
/// {c} is the value of the serie y-dimension (dimesion is 1) currently indicated or index is 0. <br />
|
||||
/// {d} is the serie y-dimensional (dimesion 1) percentage value of the currently indicated or index 0, note without the % sign. <br />
|
||||
/// {e} is the name of the serie data item serieData currently indicated or whose index is 0. <br />
|
||||
/// {h} is the hexadecimal color value of serieData for the serie data item currently indicated or index 0. <br />
|
||||
/// {f} is the sum of data. <br />
|
||||
/// {g} indicates the total number of data. <br />
|
||||
/// {y} is category value of y axis. <br />
|
||||
/// {.1} represents a dot of the corresponding color with serie specified as index 1. <br />
|
||||
/// The 1 in {a1}, {b1}, {c1} represents serie where index is specified as 1. <br />
|
||||
/// {c1:2} represents the third data of the current indicator data item in serie with index 1 (one data item has multiple data, index 2 represents the third data). <br />
|
||||
/// {c1:2-2} represents the third data of serie third data item with index 1 (that is, the number of data items must be specified when specifying the number of data items). <br />
|
||||
/// {d1:2:f2} indicates that a format string with a single value is f2 (numericFormatter is used if no value is specified). <br />
|
||||
/// {d:0.##} indicates that the format string with a value specified alone is 0.## # (for percentages, preserving a 2-digit significant number while avoiding the "100.00%" situation with f2). <br />
|
||||
/// example: "{a}, {c}", "{a1}, {c1: f1}", "{a1}, {c1:0: f1}", "{a1}, {c1:1-1: f1}"
|
||||
/// ||提示框标题内容的字符串模版格式器。支持用 \n 换行。可以单独设置占位符{i}表示忽略不显示title。
|
||||
/// 模板变量有{.}、{a}、{b}、{c}、{d}、{e}、{f}、{g}。<br/>
|
||||
/// {.}为当前所指示或index为0的serie的对应颜色的圆点。<br/>
|
||||
/// {a}为当前所指示或index为0的serie的系列名name。<br/>
|
||||
/// {b}为当前所指示或index为0的serie的数据项serieData的name,或者类目值(如折线图的X轴)。<br/>
|
||||
/// {c}为当前所指示或index为0的serie的y维(dimesion为1)的数值。<br/>
|
||||
/// {d}为当前所指示或index为0的serie的y维(dimesion为1)百分比值,注意不带%号。<br/>
|
||||
/// {e}为当前所指示或index为0的serie的数据项serieData的name。<br/>
|
||||
/// {h}为当前所指示或index为0的serie的数据项serieData的十六进制颜色值。<br/>
|
||||
/// {f}为数据总和。<br/>
|
||||
/// {g}为数据总个数。<br/>
|
||||
/// {y}为value所对应的y轴的类目值。<br/>
|
||||
/// {.1}表示指定index为1的serie对应颜色的圆点。<br/>
|
||||
/// {a1}、{b1}、{c1}中的1表示指定index为1的serie。<br/>
|
||||
/// {c1:2}表示索引为1的serie的当前指示数据项的第3个数据(一个数据项有多个数据,index为2表示第3个数据)。<br/>
|
||||
/// {c1:2-2}表示索引为1的serie的第3个数据项的第3个数据(也就是要指定第几个数据项时必须要指定第几个数据)。<br/>
|
||||
/// {d1:2:f2}表示单独指定了数值的格式化字符串为f2(不指定时用numericFormatter)。<br/>
|
||||
/// {d:0.##} 表示单独指定了数值的格式化字符串为 0.## (用于百分比,保留2位有效数同时又能避免使用 f2 而出现的类似于"100.00%"的情况 )。<br/>
|
||||
/// 示例:"{a}:{c}"、"{a1}:{c1:f1}"、"{a1}:{c1:0:f1}"、"{a1}:{c1:1-1:f1}"
|
||||
/// </summary>
|
||||
public string titleFormatter { get { return m_TitleFormatter; } set { m_TitleFormatter = value; } }
|
||||
/// <summary>
|
||||
/// a string template formatter for a single Serie or data item content. Support for wrapping lines with \n.
|
||||
/// Template variables are {.}, {a}, {b}, {c}, {d}.<br/>
|
||||
/// {.} is the dot of the corresponding color of a Serie that is currently indicated or whose index is 0.<br/>
|
||||
/// {a} is the series name of the serie that is currently indicated or whose index is 0.<br/>
|
||||
/// {b} is the name of the data item serieData that is currently indicated or whose index is 0, or a category value (such as the X-axis of a line chart).<br/>
|
||||
/// {c} is the value of a Y-dimension (dimesion is 1) from a Serie that is currently indicated or whose index is 0.<br/>
|
||||
/// {d} is the percentage value of Y-dimensions (dimesion is 1) from serie that is currently indicated or whose index is 0, with no % sign.<br/>
|
||||
/// {e} is the name of the data item serieData that is currently indicated or whose index is 0.<br/>
|
||||
/// {f} is sum of data.<br/>
|
||||
/// {y} is category value of y axis.<br/>
|
||||
/// {.1} represents a dot from serie corresponding color that specifies index as 1.<br/>
|
||||
/// 1 in {a1}, {b1}, {c1} represents a serie that specifies an index of 1.<br/>
|
||||
/// {c1:2} represents the third data from serie's current indication data item indexed to 1 (a data item has multiple data, index 2 represents the third data).<br/>
|
||||
/// {c1:2-2} represents the third data item from serie's third data item indexed to 1 (i.e., which data item must be specified to specify).<br/>
|
||||
/// {d1:2: F2} indicates that a formatted string with a value specified separately is F2 (numericFormatter is used when numericFormatter is not specified).<br/>
|
||||
/// {d:0.##} indicates that a formatted string with a value specified separately is 0.## (used for percentage, reserved 2 valid digits while avoiding the situation similar to "100.00%" when using f2 ).<br/>
|
||||
/// Example: "{a}, {c}", "{a1}, {c1: f1}", "{a1}, {c1:0: f1}", "{a1} : {c1:1-1: f1}"<br/>
|
||||
/// ||提示框单个serie或数据项内容的字符串模版格式器。支持用 \n 换行。用|来表示多个列的分隔。
|
||||
/// 模板变量有{.}、{a}、{b}、{c}、{d}、{e}、{f}、{g}。<br/>
|
||||
/// {i}或-表示忽略当前项。
|
||||
/// {.}为当前所指示的serie或数据项的对应颜色的圆点。<br/>
|
||||
/// {a}为当前所指示的serie或数据项的系列名name。<br/>
|
||||
/// {b}为当前所指示的serie或数据项的数据项serieData的name,或者类目值(如折线图的X轴)。<br/>
|
||||
/// {c}为当前所指示的serie或数据项的y维(dimesion为1)的数值。<br/>
|
||||
/// {d}为当前所指示的serie或数据项的y维(dimesion为1)百分比值,注意不带%号。<br/>
|
||||
/// {e}为当前所指示的serie或数据项的数据项serieData的name。<br/>
|
||||
/// {f}为当前所指示的serie的默认维度的数据总和。<br/>
|
||||
/// {g}为当前所指示的serie的数据总个数。<br/>
|
||||
/// {h}为当前所指示的serie的十六进制颜色值。<br/>
|
||||
/// {y}为当前所指示的serie的y轴的类目值。<br/>
|
||||
/// {c0}表示当前数据项维度为0的数据。<br/>
|
||||
/// {c1}表示当前数据项维度为1的数据。<br/>
|
||||
/// {d3}表示维度3的数据的百分比。它的分母是默认维度(一般是1维度)数据。<br/>
|
||||
/// |表示多个列的分隔。<br/>
|
||||
/// 示例:"{i}", "{.}|{a}|{c}", "{.}|{b}|{c2:f2}", "{.}|{b}|{y}"
|
||||
/// </summary>
|
||||
public string itemFormatter { get { return m_ItemFormatter; } set { m_ItemFormatter = value; } }
|
||||
/// <summary>
|
||||
/// Standard number and date format string. Used to format a Double value or a DateTime date as a string.
|
||||
/// numericFormatter is used as an argument to either `Double.ToString ()` or `DateTime.ToString()`. <br />
|
||||
/// The number format uses the Axx format: A is a single-character format specifier that supports C currency,
|
||||
/// D decimal, E exponent, F fixed-point number, G regular, N digit, P percentage, R round trip, and X hexadecimal.
|
||||
/// xx is precision specification, from 0-99. E.g. F1, E2<br />
|
||||
/// Date format: Starts with `date`, which is used to format DateTime. Common date formats are:
|
||||
/// yyyy year, MM month, dd day, HH hour, mm minute, ss second, fff millisecond. For example: date:yyyy-MM-dd HH:mm:ss<br />
|
||||
/// Time format: Starts with `time`, which is used to format TimeSpan. Common time formats are:
|
||||
/// d day, HH hour, mm minute, ss second, fffffff fractional part.
|
||||
/// Only the version of Unity2018 or later can support formatting, and the characters inside should be escaped.
|
||||
/// For example: time:HH\:mm\:ss<br />
|
||||
/// number format reference: https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings<br/>
|
||||
/// date format reference: https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings<br/>
|
||||
/// Note: The date and time formats are only supported by 'v3.12.0' or later.<br/>
|
||||
/// ||标准数字和日期格式字符串。用于将Double数值或DateTime日期格式化显示为字符串。numericFormatter用来作为Double.ToString()或DateTime.ToString()的参数。<br/>
|
||||
/// 数字格式使用Axx的形式:A是格式说明符的单字符,支持C货币、D十进制、E指数、F定点数、G常规、N数字、P百分比、R往返、X十六进制的。xx是精度说明,从0-99。如:F1, E2<br/>
|
||||
/// 日期格式:以`date`开头,用来格式化DateTime,常见格式有:yyyy年,MM月,dd日,HH时,mm分,ss秒,fff毫秒。如:date:yyyy-MM-dd HH:mm:ss<br/>
|
||||
/// 时间格式:以`time`开头,用来格式化TimeSpan,常见格式有:d日,HH时,mm分,ss秒,fffffff小数部分。
|
||||
/// 需要Unity2018以上版本才支持格式化,并且里面的字符要转义。如:time:d\.HH\:mm\:ss<br/>
|
||||
/// 数值格式化参考:https://docs.microsoft.com/zh-cn/dotnet/standard/base-types/standard-numeric-format-strings <br/>
|
||||
/// 日期格式化参考:https://learn.microsoft.com/zh-cn/dotnet/standard/base-types/standard-date-and-time-format-strings <br/>
|
||||
/// 时间格式化参考:https://learn.microsoft.com/zh-cn/dotnet/standard/base-types/standard-timespan-format-strings <br/>
|
||||
/// 注意:date和time格式需要`v3.12.0`以上版本才支持。
|
||||
/// </summary>
|
||||
public string numericFormatter
|
||||
{
|
||||
get { return m_NumericFormatter; }
|
||||
set { if (PropertyUtil.SetClass(ref m_NumericFormatter, value)) SetComponentDirty(); }
|
||||
}
|
||||
/// <summary>
|
||||
/// the marker of serie.
|
||||
/// ||serie的符号标志。
|
||||
/// </summary>
|
||||
public string marker { get { return m_Marker; } set { m_Marker = value; } }
|
||||
/// <summary>
|
||||
/// Fixed width. Higher priority than minWidth.
|
||||
/// ||固定宽度。比 minWidth 优先。
|
||||
/// </summary>
|
||||
public float fixedWidth { get { return m_FixedWidth; } set { m_FixedWidth = value; } }
|
||||
/// <summary>
|
||||
/// Fixed height. Higher priority than minHeight.
|
||||
/// ||固定高度。比 minHeight 优先。
|
||||
/// </summary>
|
||||
public float fixedHeight { get { return m_FixedHeight; } set { m_FixedHeight = value; } }
|
||||
/// <summary>
|
||||
/// Minimum width. If fixedWidth has a value, get fixedWidth first.
|
||||
/// ||最小宽度。如若 fixedWidth 设有值,优先取 fixedWidth。
|
||||
/// </summary>
|
||||
public float minWidth { get { return m_MinWidth; } set { m_MinWidth = value; } }
|
||||
/// <summary>
|
||||
/// Minimum height. If fixedHeight has a value, take priority over fixedHeight.
|
||||
/// ||最小高度。如若 fixedHeight 设有值,优先取 fixedHeight。
|
||||
/// </summary>
|
||||
public float minHeight { get { return m_MinHeight; } set { m_MinHeight = value; } }
|
||||
/// <summary>
|
||||
/// the text padding of left and right. defaut:5.
|
||||
/// ||左右边距。
|
||||
/// </summary>
|
||||
public int paddingLeftRight { get { return m_PaddingLeftRight; } set { m_PaddingLeftRight = value; } }
|
||||
/// <summary>
|
||||
/// the text padding of top and bottom. defaut:5.
|
||||
/// ||上下边距。
|
||||
/// </summary>
|
||||
public int paddingTopBottom { get { return m_PaddingTopBottom; } set { m_PaddingTopBottom = value; } }
|
||||
/// <summary>
|
||||
/// Whether to show ignored data on tooltip.
|
||||
/// ||是否显示忽略数据在tooltip上。
|
||||
/// </summary>
|
||||
public bool ignoreDataShow { get { return m_IgnoreDataShow; } set { m_IgnoreDataShow = value; } }
|
||||
/// <summary>
|
||||
/// The default display character information for ignored data.
|
||||
/// ||被忽略数据的默认显示字符信息。如果设置为空,则表示完全不显示忽略数据。
|
||||
/// </summary>
|
||||
public string ignoreDataDefaultContent { get { return m_IgnoreDataDefaultContent; } set { m_IgnoreDataDefaultContent = value; } }
|
||||
/// <summary>
|
||||
/// The background image of tooltip.
|
||||
/// ||提示框的背景图片。
|
||||
/// </summary>
|
||||
public Sprite backgroundImage { get { return m_BackgroundImage; } set { m_BackgroundImage = value; SetComponentDirty(); } }
|
||||
/// <summary>
|
||||
/// The background type of tooltip.
|
||||
/// ||提示框的背景图片显示类型。
|
||||
/// </summary>
|
||||
public Image.Type backgroundType { get { return m_BackgroundType; } set { m_BackgroundType = value; SetComponentDirty(); } }
|
||||
/// <summary>
|
||||
/// The background color of tooltip.
|
||||
/// ||提示框的背景颜色。
|
||||
/// </summary>
|
||||
public Color backgroundColor { get { return m_BackgroundColor; } set { m_BackgroundColor = value; SetComponentDirty(); } }
|
||||
/// <summary>
|
||||
/// Whether to trigger after always display.
|
||||
/// ||是否触发后一直显示提示框浮层。
|
||||
/// </summary>
|
||||
public bool alwayShowContent { get { return m_AlwayShowContent; } set { m_AlwayShowContent = value; } }
|
||||
/// <summary>
|
||||
/// Whether to show the tooltip floating layer, whose default value is true.
|
||||
/// It should be configurated to be false, if you only need tooltip to trigger the event or show the axisPointer without content.
|
||||
/// ||是否显示提示框浮层,默认显示。只需tooltip触发事件或显示axisPointer而不需要显示内容时可配置该项为false。
|
||||
/// </summary>
|
||||
public bool showContent { get { return m_ShowContent; } set { m_ShowContent = value; } }
|
||||
/// <summary>
|
||||
/// The position offset of tooltip relative to the mouse position.
|
||||
/// ||提示框相对于鼠标位置的偏移。
|
||||
/// </summary>
|
||||
public Vector2 offset { get { return m_Offset; } set { m_Offset = value; } }
|
||||
/// <summary>
|
||||
/// the width of tooltip border.
|
||||
/// ||边框线宽。
|
||||
/// </summary>
|
||||
public float borderWidth
|
||||
{
|
||||
get { return m_BorderWidth; }
|
||||
set { if (PropertyUtil.SetStruct(ref m_BorderWidth, value)) SetVerticesDirty(); }
|
||||
}
|
||||
/// <summary>
|
||||
/// the color of tooltip border.
|
||||
/// ||边框颜色。
|
||||
/// </summary>
|
||||
public Color32 borderColor
|
||||
{
|
||||
get { return m_BorderColor; }
|
||||
set { if (PropertyUtil.SetColor(ref m_BorderColor, value)) SetVerticesDirty(); }
|
||||
}
|
||||
/// <summary>
|
||||
/// the x positionn of fixedX.
|
||||
/// ||固定X位置的坐标。
|
||||
/// </summary>
|
||||
public float fixedX
|
||||
{
|
||||
get { return m_FixedX; }
|
||||
set { if (PropertyUtil.SetStruct(ref m_FixedX, value)) SetVerticesDirty(); }
|
||||
}
|
||||
/// <summary>
|
||||
/// the y position of fixedY.
|
||||
/// ||固定Y位置的坐标。
|
||||
/// </summary>
|
||||
public float fixedY
|
||||
{
|
||||
get { return m_FixedY; }
|
||||
set { if (PropertyUtil.SetStruct(ref m_FixedY, value)) SetVerticesDirty(); }
|
||||
}
|
||||
/// <summary>
|
||||
/// height of title text.
|
||||
/// ||标题文本的高。
|
||||
/// </summary>
|
||||
public float titleHeight
|
||||
{
|
||||
get { return m_TitleHeight; }
|
||||
set { if (PropertyUtil.SetStruct(ref m_TitleHeight, value)) SetComponentDirty(); }
|
||||
}
|
||||
/// <summary>
|
||||
/// height of content text.
|
||||
/// ||数据项文本的高。
|
||||
/// </summary>
|
||||
public float itemHeight
|
||||
{
|
||||
get { return m_ItemHeight; }
|
||||
set { if (PropertyUtil.SetStruct(ref m_ItemHeight, value)) SetComponentDirty(); }
|
||||
}
|
||||
/// <summary>
|
||||
/// the column gap width of content. When there is only one column, it only represents the gap width of the second column.
|
||||
/// ||内容部分的列间距。当只有一列时,只表示第二列的间距。
|
||||
/// </summary>
|
||||
public List<float> columnGapWidths
|
||||
{
|
||||
get { return m_ColumnGapWidths; }
|
||||
set { if (value != null) { m_ColumnGapWidths = value; SetComponentDirty(); } }
|
||||
}
|
||||
/// <summary>
|
||||
/// the textstyle of title.
|
||||
/// ||标题的文本样式。
|
||||
/// </summary>
|
||||
public LabelStyle titleLabelStyle
|
||||
{
|
||||
get { return m_TitleLabelStyle; }
|
||||
set { if (value != null) { m_TitleLabelStyle = value; SetComponentDirty(); } }
|
||||
}
|
||||
/// <summary>
|
||||
/// the column text style list of content. The first represents the text style of the first column, and so on.
|
||||
/// ||内容部分的列文本样式列表。第一个表示第一列的文本样式,以此类推。
|
||||
/// </summary>
|
||||
public List<LabelStyle> contentLabelStyles
|
||||
{
|
||||
get { return m_ContentLabelStyles; }
|
||||
set { if (value != null) { m_ContentLabelStyles = value; SetComponentDirty(); } }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the line style of indicator line.
|
||||
/// ||指示线样式。
|
||||
/// </summary>
|
||||
public LineStyle lineStyle
|
||||
{
|
||||
get { return m_LineStyle; }
|
||||
set { if (value != null) m_LineStyle = value; SetComponentDirty(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 组件是否需要刷新
|
||||
/// </summary>
|
||||
public override bool componentDirty
|
||||
{
|
||||
get { return m_ComponentDirty || lineStyle.componentDirty; }
|
||||
}
|
||||
|
||||
public override void ClearComponentDirty()
|
||||
{
|
||||
base.ClearComponentDirty();
|
||||
lineStyle.ClearComponentDirty();
|
||||
}
|
||||
/// <summary>
|
||||
/// 当前提示框所指示的Serie索引(目前只对散点图有效)。
|
||||
/// </summary>
|
||||
public Dictionary<int, List<int>> runtimeSerieIndex = new Dictionary<int, List<int>>();
|
||||
/// <summary>
|
||||
/// The data index currently indicated by Tooltip.
|
||||
/// ||当前提示框所指示的数据项索引。
|
||||
/// </summary>
|
||||
public List<int> runtimeDataIndex { get { return m_RuntimeDateIndex; } internal set { m_RuntimeDateIndex = value; } }
|
||||
private List<int> m_RuntimeDateIndex = new List<int>() { -1, -1 };
|
||||
|
||||
/// <summary>
|
||||
/// Keep Tooltiop displayed at the top.
|
||||
/// ||保持Tooltiop显示在最顶上
|
||||
/// </summary>
|
||||
public void KeepTop()
|
||||
{
|
||||
gameObject.transform.SetAsLastSibling();
|
||||
}
|
||||
|
||||
public override void ClearData()
|
||||
{
|
||||
ClearValue();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除提示框指示数据
|
||||
/// </summary>
|
||||
internal void ClearValue()
|
||||
{
|
||||
for (int i = 0; i < runtimeDataIndex.Count; i++) runtimeDataIndex[i] = -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 提示框是否显示
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool IsActive()
|
||||
{
|
||||
return gameObject != null && gameObject.activeInHierarchy;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置Tooltip组件是否显示
|
||||
/// </summary>
|
||||
/// <param name="flag"></param>
|
||||
public void SetActive(bool flag)
|
||||
{
|
||||
if (gameObject && gameObject.activeInHierarchy != flag)
|
||||
{
|
||||
gameObject.SetActive(alwayShowContent ? true : flag);
|
||||
}
|
||||
SetContentActive(flag);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置文本框是否显示
|
||||
/// </summary>
|
||||
/// <param name="flag"></param>
|
||||
public void SetContentActive(bool flag)
|
||||
{
|
||||
if (view == null)
|
||||
return;
|
||||
|
||||
view.SetActive(alwayShowContent ? true : flag);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当前提示框是否选中数据项
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool IsSelected()
|
||||
{
|
||||
foreach (var index in runtimeDataIndex)
|
||||
if (index >= 0) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 指定索引的数据项是否被提示框选中
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
/// <returns></returns>
|
||||
public bool IsSelected(int index)
|
||||
{
|
||||
foreach (var temp in runtimeDataIndex)
|
||||
if (temp == index) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void ClearSerieDataIndex()
|
||||
{
|
||||
foreach (var kv in runtimeSerieIndex)
|
||||
{
|
||||
kv.Value.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void AddSerieDataIndex(int serieIndex, int dataIndex)
|
||||
{
|
||||
if (!runtimeSerieIndex.ContainsKey(serieIndex))
|
||||
{
|
||||
runtimeSerieIndex[serieIndex] = new List<int>();
|
||||
}
|
||||
runtimeSerieIndex[serieIndex].Add(dataIndex);
|
||||
}
|
||||
|
||||
public bool isAnySerieDataIndex()
|
||||
{
|
||||
foreach (var kv in runtimeSerieIndex)
|
||||
{
|
||||
if (kv.Value.Count > 0) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsTriggerItem()
|
||||
{
|
||||
return trigger == Trigger.Auto ? context.trigger == Trigger.Item : trigger == Trigger.Item;
|
||||
}
|
||||
|
||||
public bool IsTriggerAxis()
|
||||
{
|
||||
return trigger == Trigger.Auto ? context.trigger == Trigger.Axis : trigger == Trigger.Axis;
|
||||
}
|
||||
|
||||
public LabelStyle GetContentLabelStyle(int index)
|
||||
{
|
||||
if (m_ContentLabelStyles.Count == 0)
|
||||
return null;
|
||||
|
||||
if (index < 0)
|
||||
index = 0;
|
||||
else if (index > m_ContentLabelStyles.Count - 1)
|
||||
index = m_ContentLabelStyles.Count - 1;
|
||||
|
||||
return m_ContentLabelStyles[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dff3b0d6d38ee49838f054d30ab9b733
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using XUGL;
|
||||
|
||||
namespace XCharts.Runtime
|
||||
{
|
||||
public class TooltipData
|
||||
{
|
||||
public string title;
|
||||
public List<SerieParams> param = new List<SerieParams>();
|
||||
}
|
||||
|
||||
public class TooltipContext
|
||||
{
|
||||
public Vector2 pointer;
|
||||
public float width;
|
||||
public float height;
|
||||
public float angle;
|
||||
public int xAxisClickIndex = -1;
|
||||
public Tooltip.Type type;
|
||||
public Tooltip.Trigger trigger;
|
||||
public TooltipData data = new TooltipData();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7324ce36c9b2c475bb18abd6618b107c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,893 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
using XUGL;
|
||||
|
||||
namespace XCharts.Runtime
|
||||
{
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
internal sealed class TooltipHandler : MainComponentHandler<Tooltip>
|
||||
{
|
||||
private Dictionary<string, ChartLabel> m_IndicatorLabels = new Dictionary<string, ChartLabel>();
|
||||
private GameObject m_LabelRoot;
|
||||
private ISerieContainer m_PointerContainer;
|
||||
|
||||
public override void InitComponent()
|
||||
{
|
||||
InitTooltip(component);
|
||||
}
|
||||
|
||||
public override void BeforceSerieUpdate()
|
||||
{
|
||||
UpdateTooltipData(component);
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
UpdateTooltip(component);
|
||||
UpdateTooltipIndicatorLabelText(component);
|
||||
if (component.view != null)
|
||||
component.view.Update();
|
||||
}
|
||||
|
||||
public override void DrawUpper(VertexHelper vh)
|
||||
{
|
||||
DrawTooltipIndicator(vh, component);
|
||||
}
|
||||
|
||||
public override void OnPointerExit(PointerEventData eventData)
|
||||
{
|
||||
base.OnPointerExit(eventData);
|
||||
if (chart.isTriggerOnClick)
|
||||
{
|
||||
component.context.xAxisClickIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
private void InitTooltip(Tooltip tooltip)
|
||||
{
|
||||
tooltip.painter = chart.m_PainterUpper;
|
||||
tooltip.refreshComponent = delegate ()
|
||||
{
|
||||
var objName = ChartCached.GetComponentObjectName(tooltip);
|
||||
tooltip.gameObject = ChartHelper.AddObject(objName, chart.transform, chart.chartMinAnchor,
|
||||
chart.chartMaxAnchor, chart.chartPivot, chart.chartSizeDelta, -1, chart.childrenNodeNames);
|
||||
var tooltipObject = tooltip.gameObject;
|
||||
tooltipObject.transform.localPosition = Vector3.zero;
|
||||
tooltipObject.hideFlags = chart.chartHideFlags;
|
||||
var parent = tooltipObject.transform;
|
||||
ChartHelper.HideAllObject(tooltipObject.transform);
|
||||
|
||||
tooltip.view = TooltipView.CreateView(tooltip, chart.theme, parent);
|
||||
tooltip.SetActive(false);
|
||||
|
||||
m_LabelRoot = ChartHelper.AddObject("label", tooltip.gameObject.transform, chart.chartMinAnchor,
|
||||
chart.chartMaxAnchor, chart.chartPivot, chart.chartSizeDelta);
|
||||
m_LabelRoot.transform.SetSiblingIndex(0);
|
||||
ChartHelper.HideAllObject(m_LabelRoot);
|
||||
m_IndicatorLabels.Clear();
|
||||
foreach (var com in chart.components)
|
||||
{
|
||||
if (com is Axis)
|
||||
{
|
||||
var axis = com as Axis;
|
||||
var aligment = (com is AngleAxis) ? TextAnchor.MiddleCenter : axis.context.aligment;
|
||||
var labelName = ChartCached.GetComponentObjectName(axis);
|
||||
var item = ChartHelper.AddTooltipIndicatorLabel(component, labelName, m_LabelRoot.transform,
|
||||
chart.theme, aligment, axis.indicatorLabel);
|
||||
item.SetActive(false);
|
||||
m_IndicatorLabels[labelName] = item;
|
||||
}
|
||||
}
|
||||
chart.isTriggerOnClick = tooltip.triggerOn == Tooltip.TriggerOn.Click;
|
||||
};
|
||||
tooltip.refreshComponent();
|
||||
}
|
||||
|
||||
private ChartLabel GetIndicatorLabel(Axis axis)
|
||||
{
|
||||
if (m_LabelRoot == null) return null;
|
||||
var key = ChartCached.GetComponentObjectName(axis);
|
||||
if (m_IndicatorLabels.ContainsKey(key))
|
||||
{
|
||||
return m_IndicatorLabels[key];
|
||||
}
|
||||
else
|
||||
{
|
||||
var item = ChartHelper.AddTooltipIndicatorLabel(component, key, m_LabelRoot.transform,
|
||||
chart.theme, TextAnchor.MiddleCenter, axis.indicatorLabel);
|
||||
m_IndicatorLabels[key] = item;
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateTooltipData(Tooltip tooltip)
|
||||
{
|
||||
m_ShowTooltip = false;
|
||||
if (tooltip.trigger == Tooltip.Trigger.None) return;
|
||||
chart.isTriggerOnClick = tooltip.triggerOn == Tooltip.TriggerOn.Click;
|
||||
|
||||
if ((tooltip.show && chart.isPointerInChart) &&
|
||||
((tooltip.triggerOn == Tooltip.TriggerOn.Click && chart.isPointerClick) ||
|
||||
(tooltip.triggerOn == Tooltip.TriggerOn.MouseMove))
|
||||
)
|
||||
{
|
||||
for (int i = chart.series.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var serie = chart.series[i];
|
||||
if (!(serie is INeedSerieContainer))
|
||||
{
|
||||
m_ShowTooltip = true;
|
||||
m_ContainerSeries = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_ContainerSeries = ListPool<Serie>.Get();
|
||||
UpdatePointerContainerAndSeriesAndTooltip(tooltip, ref m_ContainerSeries);
|
||||
if (m_ContainerSeries.Count > 0)
|
||||
{
|
||||
m_ShowTooltip = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_ShowTooltip && tooltip.IsActive())
|
||||
{
|
||||
tooltip.ClearValue();
|
||||
tooltip.SetActive(false);
|
||||
component.context.xAxisClickIndex = -1;
|
||||
chart.pointerClickEventData = null;
|
||||
}
|
||||
}
|
||||
|
||||
private bool m_ShowTooltip;
|
||||
private List<Serie> m_ContainerSeries;
|
||||
private void UpdateTooltip(Tooltip tooltip)
|
||||
{
|
||||
if (!m_ShowTooltip)
|
||||
{
|
||||
if (m_ContainerSeries != null)
|
||||
{
|
||||
ListPool<Serie>.Release(m_ContainerSeries);
|
||||
m_ContainerSeries = null;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var anyTrigger = false;
|
||||
for (int i = chart.series.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var serie = chart.series[i];
|
||||
if (!(serie is INeedSerieContainer))
|
||||
{
|
||||
if (SetSerieTooltip(tooltip, serie))
|
||||
{
|
||||
anyTrigger = true;
|
||||
chart.RefreshTopPainter();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!anyTrigger && m_ContainerSeries == null)
|
||||
{
|
||||
m_ContainerSeries = ListPool<Serie>.Get();
|
||||
UpdatePointerContainerAndSeriesAndTooltip(tooltip, ref m_ContainerSeries);
|
||||
}
|
||||
if (m_ContainerSeries != null)
|
||||
{
|
||||
if (!SetSerieTooltip(tooltip, m_ContainerSeries))
|
||||
m_ShowTooltip = false;
|
||||
else
|
||||
anyTrigger = true;
|
||||
ListPool<Serie>.Release(m_ContainerSeries);
|
||||
m_ContainerSeries = null;
|
||||
}
|
||||
if (!m_ShowTooltip || !anyTrigger)
|
||||
{
|
||||
if (tooltip.context.type == Tooltip.Type.Cross && m_PointerContainer != null && m_PointerContainer.IsPointerEnter())
|
||||
{
|
||||
m_ShowTooltip = true;
|
||||
tooltip.SetActive(true);
|
||||
tooltip.SetContentActive(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ShowTooltip = false;
|
||||
tooltip.SetActive(false);
|
||||
chart.pointerClickEventData = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
chart.RefreshUpperPainter();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateTooltipIndicatorLabelText(Tooltip tooltip)
|
||||
{
|
||||
if (!tooltip.show) return;
|
||||
if (tooltip.context.type == Tooltip.Type.None) return;
|
||||
if (m_PointerContainer != null)
|
||||
{
|
||||
if (tooltip.context.type == Tooltip.Type.Cross)
|
||||
{
|
||||
if (m_PointerContainer is GridCoord)
|
||||
{
|
||||
var grid = m_PointerContainer as GridCoord;
|
||||
ChartHelper.HideAllObject(m_LabelRoot);
|
||||
foreach (var component in chart.components)
|
||||
{
|
||||
if (component is XAxis || component is YAxis)
|
||||
{
|
||||
var axis = component as Axis;
|
||||
if (axis.gridIndex == grid.index)
|
||||
{
|
||||
var label = GetIndicatorLabel(axis);
|
||||
SetTooltipIndicatorLabel(tooltip, axis, label);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (m_PointerContainer is PolarCoord)
|
||||
{
|
||||
var polar = m_PointerContainer as PolarCoord;
|
||||
ChartHelper.HideAllObject(m_LabelRoot);
|
||||
foreach (var component in chart.components)
|
||||
{
|
||||
if (component is AngleAxis || component is RadiusAxis)
|
||||
{
|
||||
var axis = component as Axis;
|
||||
if (axis.polarIndex == polar.index)
|
||||
{
|
||||
var label = GetIndicatorLabel(axis);
|
||||
SetTooltipIndicatorLabel(tooltip, axis, label);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetTooltipIndicatorLabel(Tooltip tooltip, Axis axis, ChartLabel label)
|
||||
{
|
||||
if (label == null) return;
|
||||
if (double.IsNaN(axis.context.pointerValue)) return;
|
||||
if (!axis.show || !axis.indicatorLabel.show)
|
||||
{
|
||||
label.SetActive(false, false);
|
||||
return;
|
||||
}
|
||||
label.SetActive(true, true);
|
||||
label.SetTextActive(true);
|
||||
label.SetPosition(axis.context.pointerLabelPosition + axis.indicatorLabel.offset);
|
||||
|
||||
if (axis.IsCategory())
|
||||
{
|
||||
var index = (int)axis.context.pointerValue;
|
||||
var dataZoom = chart.GetDataZoomOfAxis(axis);
|
||||
var category = axis.GetData(index, dataZoom);
|
||||
label.SetText(axis.indicatorLabel.GetFormatterContent(index, 0, category));
|
||||
}
|
||||
else if (axis.IsTime())
|
||||
{
|
||||
label.SetText(axis.indicatorLabel.GetFormatterDateTime(0, 0, axis.context.pointerValue, axis.context.minValue, axis.context.maxValue, !chart.useUtc));
|
||||
}
|
||||
else
|
||||
{
|
||||
label.SetText(axis.indicatorLabel.GetFormatterContent(0, 0, axis.context.pointerValue, axis.context.minValue, axis.context.maxValue, axis.IsLog()));
|
||||
}
|
||||
var textColor = axis.axisLabel.textStyle.GetColor(chart.theme.axis.textColor);
|
||||
if (ChartHelper.IsClearColor(axis.indicatorLabel.background.color))
|
||||
label.color = textColor;
|
||||
else
|
||||
label.color = axis.indicatorLabel.background.color;
|
||||
|
||||
if (ChartHelper.IsClearColor(axis.indicatorLabel.textStyle.color))
|
||||
label.SetTextColor(Color.white);
|
||||
else
|
||||
label.SetTextColor(axis.indicatorLabel.textStyle.color);
|
||||
}
|
||||
|
||||
private void UpdatePointerContainerAndSeriesAndTooltip(Tooltip tooltip, ref List<Serie> list)
|
||||
{
|
||||
list.Clear();
|
||||
m_PointerContainer = null;
|
||||
var updateTooltipTypeAndTrigger = false;
|
||||
for (int i = chart.components.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var component = chart.components[i];
|
||||
if (component is ISerieContainer)
|
||||
{
|
||||
var container = component as ISerieContainer;
|
||||
if (container.IsPointerEnter())
|
||||
{
|
||||
foreach (var serie in chart.series)
|
||||
{
|
||||
if (serie is INeedSerieContainer &&
|
||||
(serie as INeedSerieContainer).containterInstanceId == component.instanceId &&
|
||||
!serie.placeHolder)
|
||||
{
|
||||
if (!updateTooltipTypeAndTrigger)
|
||||
{
|
||||
updateTooltipTypeAndTrigger = true;
|
||||
tooltip.context.type = tooltip.type == Tooltip.Type.Auto ?
|
||||
serie.context.tooltipType : tooltip.type;
|
||||
tooltip.context.trigger = tooltip.trigger == Tooltip.Trigger.Auto ?
|
||||
serie.context.tooltipTrigger : tooltip.trigger;
|
||||
}
|
||||
var isTriggerAxis = tooltip.IsTriggerAxis();
|
||||
var inchart = true;
|
||||
if (container is GridCoord)
|
||||
{
|
||||
var xAxis = chart.GetChartComponent<XAxis>(serie.xAxisIndex);
|
||||
var yAxis = chart.GetChartComponent<YAxis>(serie.yAxisIndex);
|
||||
inchart = UpdateAxisPointerDataIndex(serie, xAxis, yAxis, container as GridCoord, isTriggerAxis);
|
||||
}
|
||||
else if (container is PolarCoord)
|
||||
{
|
||||
var m_AngleAxis = ComponentHelper.GetAngleAxis(chart.components, container.index);
|
||||
tooltip.context.angle = (float)m_AngleAxis.context.pointerValue;
|
||||
}
|
||||
if (inchart)
|
||||
{
|
||||
list.Add(serie);
|
||||
if (!isTriggerAxis)
|
||||
{
|
||||
chart.RefreshTopPainter();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
m_PointerContainer = container;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool UpdateAxisPointerDataIndex(Serie serie, XAxis xAxis, YAxis yAxis, GridCoord grid, bool isTriggerAxis)
|
||||
{
|
||||
serie.context.pointerAxisDataIndexs.Clear();
|
||||
if (xAxis == null || yAxis == null) return false;
|
||||
var flag = true;
|
||||
if (serie is Heatmap)
|
||||
{
|
||||
GetSerieDataByXYAxis(serie, xAxis, yAxis);
|
||||
}
|
||||
else if (yAxis.IsCategory() && !xAxis.IsCategory())
|
||||
{
|
||||
if (isTriggerAxis)
|
||||
{
|
||||
var index = serie.context.dataZoomStartIndex + (int)yAxis.context.pointerValue;
|
||||
if (serie.useSortData) index = yAxis.context.sortedDataIndices[index];
|
||||
serie.context.pointerEnter = true;
|
||||
serie.context.pointerAxisDataIndexs.Add(index);
|
||||
serie.context.pointerItemDataIndex = index;
|
||||
yAxis.context.axisTooltipValue = index;
|
||||
}
|
||||
}
|
||||
else if (yAxis.IsTime())
|
||||
{
|
||||
serie.context.pointerEnter = true;
|
||||
if (isTriggerAxis)
|
||||
GetSerieDataIndexByAxis(serie, yAxis, grid);
|
||||
else
|
||||
GetSerieDataIndexByItem(serie, yAxis, grid);
|
||||
}
|
||||
else if (xAxis.IsCategory())
|
||||
{
|
||||
if (isTriggerAxis)
|
||||
{
|
||||
var index = serie.context.dataZoomStartIndex + (int)xAxis.context.pointerValue;
|
||||
if (serie.useSortData) index = xAxis.context.sortedDataIndices[index];
|
||||
if (chart.isTriggerOnClick)
|
||||
{
|
||||
if (serie.insertDataToHead)
|
||||
index = index + (serie.context.totalDataIndex - serie.context.clickTotalDataIndex);
|
||||
else if (serie.context.totalDataIndex >= serie.dataCount)
|
||||
index = index - (serie.context.totalDataIndex - serie.context.clickTotalDataIndex);
|
||||
if (index < 0 || index >= serie.dataCount)
|
||||
{
|
||||
index = -1;
|
||||
flag = false;
|
||||
}
|
||||
}
|
||||
if (component.context.xAxisClickIndex != index)
|
||||
{
|
||||
component.context.xAxisClickIndex = index;
|
||||
if (component.onClickIndex != null)
|
||||
{
|
||||
component.onClickIndex(index);
|
||||
}
|
||||
}
|
||||
serie.context.pointerEnter = true;
|
||||
serie.context.pointerAxisDataIndexs.Add(index);
|
||||
serie.context.pointerItemDataIndex = index;
|
||||
xAxis.context.axisTooltipValue = index;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isTriggerAxis)
|
||||
{
|
||||
serie.context.pointerEnter = true;
|
||||
GetSerieDataIndexByAxis(serie, xAxis, grid);
|
||||
}
|
||||
else
|
||||
{
|
||||
GetSerieDataIndexByItem(serie, xAxis, grid);
|
||||
}
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
private void GetSerieDataByXYAxis(Serie serie, Axis xAxis, Axis yAxis)
|
||||
{
|
||||
var xAxisIndex = AxisHelper.GetAxisValueSplitIndex(xAxis, xAxis.context.pointerValue, false);
|
||||
var yAxisIndex = AxisHelper.GetAxisValueSplitIndex(yAxis, yAxis.context.pointerValue, false);
|
||||
serie.context.pointerItemDataIndex = -1;
|
||||
if (serie is Heatmap)
|
||||
{
|
||||
var heatmap = serie as Heatmap;
|
||||
if (heatmap.heatmapType == HeatmapType.Count)
|
||||
{
|
||||
serie.context.pointerItemDataIndex = HeatmapHandler.GetGridKey(xAxisIndex, yAxisIndex);
|
||||
return;
|
||||
}
|
||||
}
|
||||
foreach (var serieData in serie.data)
|
||||
{
|
||||
var x = AxisHelper.GetAxisValueSplitIndex(xAxis, serieData.GetData(0), true);
|
||||
var y = AxisHelper.GetAxisValueSplitIndex(yAxis, serieData.GetData(1), true);
|
||||
if (xAxisIndex == x && y == yAxisIndex)
|
||||
{
|
||||
serie.context.pointerItemDataIndex = serieData.index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void GetSerieDataIndexByAxis(Serie serie, Axis axis, GridCoord grid, int dimension = 0)
|
||||
{
|
||||
var currValue = 0d;
|
||||
var lastValue = 0d;
|
||||
var nextValue = 0d;
|
||||
var axisValue = axis.context.pointerValue;
|
||||
var isTimeAxis = axis.IsTime();
|
||||
var dataCount = serie.dataCount;
|
||||
var themeSymbolSize = chart.theme.serie.scatterSymbolSize;
|
||||
var data = serie.data;
|
||||
if (!isTimeAxis)// || serie.useSortData)
|
||||
{
|
||||
serie.context.sortedData.Clear();
|
||||
for (int i = 0; i < dataCount; i++)
|
||||
{
|
||||
var serieData = serie.data[i];
|
||||
serie.context.sortedData.Add(serieData);
|
||||
}
|
||||
serie.context.sortedData.Sort(delegate (SerieData a, SerieData b)
|
||||
{
|
||||
return a.GetData(dimension).CompareTo(b.GetData(dimension));
|
||||
});
|
||||
data = serie.context.sortedData;
|
||||
}
|
||||
serie.context.pointerAxisDataIndexs.Clear();
|
||||
for (int i = 0; i < dataCount; i++)
|
||||
{
|
||||
var serieData = data[i];
|
||||
currValue = serieData.GetData(dimension);
|
||||
if (i == 0)
|
||||
{
|
||||
if (i + 1 < dataCount)
|
||||
{
|
||||
nextValue = data[i + 1].GetData(dimension);
|
||||
if (axisValue <= currValue + (nextValue - currValue) / 2)
|
||||
{
|
||||
serie.context.pointerAxisDataIndexs.Add(serieData.index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var diff = axis.context.tickValue * 0.5f;
|
||||
if (axisValue >= currValue - diff && axisValue <= currValue + diff)
|
||||
{
|
||||
serie.context.pointerAxisDataIndexs.Add(serieData.index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (i == dataCount - 1)
|
||||
{
|
||||
if (axisValue > lastValue + (currValue - lastValue) / 2)
|
||||
{
|
||||
serie.context.pointerAxisDataIndexs.Add(serieData.index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (i + 1 < dataCount)
|
||||
{
|
||||
nextValue = data[i + 1].GetData(dimension);
|
||||
if (axisValue > (currValue - (currValue - lastValue) / 2) && axisValue <= currValue + (nextValue - currValue) / 2)
|
||||
{
|
||||
serie.context.pointerAxisDataIndexs.Add(serieData.index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
lastValue = currValue;
|
||||
}
|
||||
if (serie.context.pointerAxisDataIndexs.Count > 0)
|
||||
{
|
||||
var index = serie.context.pointerAxisDataIndexs[0];
|
||||
serie.context.pointerItemDataIndex = index;
|
||||
axis.context.axisTooltipValue = serie.GetSerieData(index).GetData(dimension);
|
||||
}
|
||||
else
|
||||
{
|
||||
serie.context.pointerItemDataIndex = -1;
|
||||
axis.context.axisTooltipValue = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void GetSerieDataIndexByItem(Serie serie, Axis axis, GridCoord grid, int dimension = 0)
|
||||
{
|
||||
if (serie.context.pointerItemDataIndex >= 0)
|
||||
{
|
||||
axis.context.axisTooltipValue = serie.GetSerieData(serie.context.pointerItemDataIndex).GetData(dimension);
|
||||
}
|
||||
else if (component.type == Tooltip.Type.Cross)
|
||||
{
|
||||
axis.context.axisTooltipValue = axis.context.pointerValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
axis.context.axisTooltipValue = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private bool SetSerieTooltip(Tooltip tooltip, Serie serie)
|
||||
{
|
||||
if (serie.context.pointerItemDataIndex < 0) return false;
|
||||
tooltip.context.type = tooltip.type == Tooltip.Type.Auto ? serie.context.tooltipType : tooltip.type;
|
||||
tooltip.context.trigger = tooltip.trigger == Tooltip.Trigger.Auto ? serie.context.tooltipTrigger : tooltip.trigger;
|
||||
if (tooltip.context.trigger == Tooltip.Trigger.None) return false;
|
||||
tooltip.context.data.param.Clear();
|
||||
tooltip.context.data.title = serie.serieName;
|
||||
tooltip.context.pointer = GetTooltipPointerPos();
|
||||
|
||||
serie.handler.UpdateTooltipSerieParams(serie.context.pointerItemDataIndex, false, null,
|
||||
tooltip.marker, tooltip.itemFormatter, tooltip.numericFormatter, tooltip.ignoreDataDefaultContent,
|
||||
ref tooltip.context.data.param,
|
||||
ref tooltip.context.data.title);
|
||||
TooltipHelper.ResetTooltipParamsByItemFormatter(tooltip, chart);
|
||||
|
||||
tooltip.SetActive(m_ShowTooltip);
|
||||
tooltip.view.Refresh();
|
||||
TooltipHelper.LimitInRect(chart, tooltip, chart.chartRect);
|
||||
return true;
|
||||
}
|
||||
|
||||
private Vector2 GetTooltipPointerPos()
|
||||
{
|
||||
if (chart.isTriggerOnClick && chart.isPointerClick)
|
||||
return chart.clickPos;
|
||||
else
|
||||
return chart.pointerPos;
|
||||
}
|
||||
|
||||
private bool SetSerieTooltip(Tooltip tooltip, List<Serie> series)
|
||||
{
|
||||
if (tooltip.context.trigger == Tooltip.Trigger.None)
|
||||
return false;
|
||||
|
||||
if (series.Count <= 0)
|
||||
return false;
|
||||
|
||||
string category = null;
|
||||
var showCategory = false;
|
||||
var isTriggerByAxis = false;
|
||||
var isTriggerByItem = tooltip.context.trigger == Tooltip.Trigger.Item;
|
||||
var dataIndex = -1;
|
||||
var timestamp = -1;
|
||||
double axisRange = 0;
|
||||
tooltip.context.data.param.Clear();
|
||||
tooltip.context.pointer = GetTooltipPointerPos();
|
||||
if (m_PointerContainer is GridCoord)
|
||||
{
|
||||
GetAxisCategory(m_PointerContainer.index, ref dataIndex, ref category, ref timestamp, ref axisRange);
|
||||
if (tooltip.context.trigger == Tooltip.Trigger.Axis)
|
||||
{
|
||||
isTriggerByAxis = true;
|
||||
if (series.Count <= 1)
|
||||
{
|
||||
showCategory = true;
|
||||
tooltip.context.data.title = series[0].serieName;
|
||||
}
|
||||
else
|
||||
{
|
||||
tooltip.context.data.title = category;
|
||||
}
|
||||
}
|
||||
else if (tooltip.context.trigger == Tooltip.Trigger.Item)
|
||||
{
|
||||
isTriggerByItem = true;
|
||||
showCategory = series.Count <= 1;
|
||||
}
|
||||
}
|
||||
|
||||
var triggerSerieCount = 0;
|
||||
for (int i = 0; i < series.Count; i++)
|
||||
{
|
||||
var serie = series[i];
|
||||
if (!serie.show) continue;
|
||||
if (isTriggerByItem && serie.context.pointerItemDataIndex < 0) continue;
|
||||
triggerSerieCount++;
|
||||
serie.context.isTriggerByAxis = isTriggerByAxis;
|
||||
if (isTriggerByAxis && dataIndex >= 0 && serie.context.pointerItemDataIndex < 0)
|
||||
serie.context.pointerItemDataIndex = dataIndex;
|
||||
if (timestamp >= 0)
|
||||
{
|
||||
showCategory = false;
|
||||
var serieData = serie.GetSerieData(serie.context.pointerItemDataIndex);
|
||||
if (serieData != null)
|
||||
{
|
||||
var value = (int)serieData.GetData(0);
|
||||
if (string.IsNullOrEmpty(tooltip.titleLabelStyle.numericFormatter))
|
||||
tooltip.context.data.title = DateTimeUtil.GetDefaultDateTimeString(value, axisRange, !chart.useUtc);
|
||||
else
|
||||
{
|
||||
var dateTime = DateTimeUtil.GetDateTime(value, !chart.useUtc);
|
||||
try
|
||||
{
|
||||
tooltip.context.data.title = dateTime.ToString(tooltip.titleLabelStyle.numericFormatter);
|
||||
}
|
||||
catch
|
||||
{
|
||||
tooltip.context.data.title = DateTimeUtil.GetDefaultDateTimeString(value, axisRange, !chart.useUtc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
serie.handler.UpdateTooltipSerieParams(dataIndex, showCategory, category,
|
||||
tooltip.marker, tooltip.itemFormatter, tooltip.numericFormatter,
|
||||
tooltip.ignoreDataDefaultContent,
|
||||
ref tooltip.context.data.param,
|
||||
ref tooltip.context.data.title);
|
||||
}
|
||||
if (triggerSerieCount <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
TooltipHelper.ResetTooltipParamsByItemFormatter(tooltip, chart);
|
||||
if (tooltip.context.data.param.Count > 0 || !string.IsNullOrEmpty(tooltip.context.data.title))
|
||||
{
|
||||
tooltip.SetActive(m_ShowTooltip);
|
||||
if (tooltip.view != null)
|
||||
tooltip.view.Refresh();
|
||||
TooltipHelper.LimitInRect(chart, tooltip, chart.chartRect);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool GetAxisCategory(int gridIndex, ref int dataIndex, ref string category, ref int timestamp, ref double axisRange)
|
||||
{
|
||||
foreach (var component in chart.components)
|
||||
{
|
||||
if (component is Axis)
|
||||
{
|
||||
var axis = component as Axis;
|
||||
if (axis.gridIndex == gridIndex)
|
||||
{
|
||||
if (axis.IsCategory())
|
||||
{
|
||||
dataIndex = double.IsNaN(axis.context.pointerValue)
|
||||
? axis.context.dataZoomStartIndex
|
||||
: (int)axis.context.axisTooltipValue;
|
||||
category = axis.GetData(dataIndex);
|
||||
return true;
|
||||
}
|
||||
else if (axis.IsTime())
|
||||
{
|
||||
timestamp = (int)axis.context.pointerValue;
|
||||
axisRange = axis.context.minMaxRange;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void DrawTooltipIndicator(VertexHelper vh, Tooltip tooltip)
|
||||
{
|
||||
if (!tooltip.show) return;
|
||||
if (tooltip.context.type == Tooltip.Type.None) return;
|
||||
if (!IsAnySerieNeedTooltip()) return;
|
||||
if (m_PointerContainer is GridCoord)
|
||||
{
|
||||
var grid = m_PointerContainer as GridCoord;
|
||||
if (!grid.context.isPointerEnter) return;
|
||||
if (IsYCategoryOfGrid(grid.index))
|
||||
DrawYAxisIndicator(vh, tooltip, grid);
|
||||
else
|
||||
DrawXAxisIndicator(vh, tooltip, grid);
|
||||
}
|
||||
else if (m_PointerContainer is PolarCoord)
|
||||
{
|
||||
DrawPolarIndicator(vh, tooltip, m_PointerContainer as PolarCoord);
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsYCategoryOfGrid(int gridIndex)
|
||||
{
|
||||
foreach (var component in chart.GetChartComponents<YAxis>())
|
||||
{
|
||||
var yAxis = component as YAxis;
|
||||
if (yAxis.gridIndex == gridIndex && !yAxis.IsCategory()) return false;
|
||||
}
|
||||
foreach (var component in chart.GetChartComponents<XAxis>())
|
||||
{
|
||||
var xAxis = component as XAxis;
|
||||
if (xAxis.gridIndex == gridIndex && xAxis.IsCategory()) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void DrawXAxisIndicator(VertexHelper vh, Tooltip tooltip, GridCoord grid)
|
||||
{
|
||||
if (!tooltip.lineStyle.show) return;
|
||||
var xAxes = chart.GetChartComponents<XAxis>();
|
||||
var lineType = tooltip.lineStyle.GetType(chart.theme.tooltip.lineType);
|
||||
var lineWidth = tooltip.lineStyle.GetWidth(chart.theme.tooltip.lineWidth);
|
||||
foreach (var component in xAxes)
|
||||
{
|
||||
var xAxis = component as XAxis;
|
||||
if (xAxis.gridIndex == grid.index)
|
||||
{
|
||||
if (double.IsInfinity(xAxis.context.pointerValue))
|
||||
continue;
|
||||
var dataZoom = chart.GetDataZoomOfAxis(xAxis);
|
||||
int dataCount = chart.series.Count > 0 ? chart.series[0].GetDataList(dataZoom).Count : 0;
|
||||
float splitWidth = AxisHelper.GetDataWidth(xAxis, grid.context.width, dataCount, dataZoom);
|
||||
switch (tooltip.context.type)
|
||||
{
|
||||
case Tooltip.Type.Cross:
|
||||
case Tooltip.Type.Line:
|
||||
float pX = grid.context.x;
|
||||
pX += xAxis.IsCategory() ?
|
||||
(float)(xAxis.context.pointerValue * splitWidth + (xAxis.boundaryGap ? splitWidth / 2 : 0)) :
|
||||
xAxis.GetDistance(xAxis.context.axisTooltipValue, grid.context.width);
|
||||
if (pX < grid.context.x)
|
||||
break;
|
||||
Vector2 sp = new Vector2(pX, grid.context.y);
|
||||
Vector2 ep = new Vector2(pX, grid.context.y + grid.context.height);
|
||||
var lineColor = TooltipHelper.GetLineColor(tooltip, chart.theme.tooltip.lineColor);
|
||||
ChartDrawer.DrawLineStyle(vh, lineType, lineWidth, sp, ep, lineColor);
|
||||
if (tooltip.context.type == Tooltip.Type.Cross)
|
||||
{
|
||||
sp = new Vector2(grid.context.x, chart.pointerPos.y);
|
||||
ep = new Vector2(grid.context.x + grid.context.width, chart.pointerPos.y);
|
||||
ChartDrawer.DrawLineStyle(vh, lineType, lineWidth, sp, ep, lineColor);
|
||||
}
|
||||
break;
|
||||
case Tooltip.Type.Shadow:
|
||||
if (xAxis.IsCategory() && !double.IsInfinity(xAxis.context.pointerValue))
|
||||
{
|
||||
float tooltipSplitWid = splitWidth < 1 ? 1 : splitWidth;
|
||||
pX = (float)(grid.context.x + splitWidth * xAxis.context.pointerValue -
|
||||
(xAxis.boundaryGap ? 0 : splitWidth / 2));
|
||||
if (pX < grid.context.x)
|
||||
break;
|
||||
float pY = grid.context.y + grid.context.height;
|
||||
Vector3 p1 = chart.ClampInGrid(grid, new Vector3(pX, grid.context.y));
|
||||
Vector3 p2 = chart.ClampInGrid(grid, new Vector3(pX, pY));
|
||||
Vector3 p3 = chart.ClampInGrid(grid, new Vector3(pX + tooltipSplitWid, pY));
|
||||
Vector3 p4 = chart.ClampInGrid(grid, new Vector3(pX + tooltipSplitWid, grid.context.y));
|
||||
var areaColor = TooltipHelper.GetLineColor(tooltip, chart.theme.tooltip.areaColor);
|
||||
UGL.DrawQuadrilateral(vh, p1, p2, p3, p4, areaColor);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsAnySerieNeedTooltip()
|
||||
{
|
||||
foreach (var serie in chart.series)
|
||||
{
|
||||
if (serie.context.pointerEnter) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private void DrawYAxisIndicator(VertexHelper vh, Tooltip tooltip, GridCoord grid)
|
||||
{
|
||||
var yAxes = chart.GetChartComponents<YAxis>();
|
||||
var lineType = tooltip.lineStyle.GetType(chart.theme.tooltip.lineType);
|
||||
var lineWidth = tooltip.lineStyle.GetWidth(chart.theme.tooltip.lineWidth);
|
||||
foreach (var component in yAxes)
|
||||
{
|
||||
var yAxis = component as YAxis;
|
||||
if (yAxis.gridIndex == grid.index)
|
||||
{
|
||||
if (double.IsInfinity(yAxis.context.pointerValue))
|
||||
continue;
|
||||
var dataZoom = chart.GetDataZoomOfAxis(yAxis);
|
||||
int dataCount = chart.series.Count > 0 ? chart.series[0].GetDataList(dataZoom).Count : 0;
|
||||
float splitWidth = AxisHelper.GetDataWidth(yAxis, grid.context.height, dataCount, dataZoom);
|
||||
switch (tooltip.context.type)
|
||||
{
|
||||
case Tooltip.Type.Cross:
|
||||
case Tooltip.Type.Line:
|
||||
float pY = (float)(grid.context.y + yAxis.context.pointerValue * splitWidth +
|
||||
(yAxis.boundaryGap ? splitWidth / 2 : 0));
|
||||
if (pY < grid.context.y)
|
||||
break;
|
||||
Vector2 sp = new Vector2(grid.context.x, pY);
|
||||
Vector2 ep = new Vector2(grid.context.x + grid.context.width, pY);
|
||||
var lineColor = TooltipHelper.GetLineColor(tooltip, chart.theme.tooltip.lineColor);
|
||||
ChartDrawer.DrawLineStyle(vh, lineType, lineWidth, sp, ep, lineColor);
|
||||
if (tooltip.context.type == Tooltip.Type.Cross)
|
||||
{
|
||||
sp = new Vector2(chart.pointerPos.x, grid.context.y);
|
||||
ep = new Vector2(chart.pointerPos.x, grid.context.y + grid.context.height);
|
||||
ChartDrawer.DrawLineStyle(vh, lineType, lineWidth, sp, ep, lineColor);
|
||||
}
|
||||
break;
|
||||
case Tooltip.Type.Shadow:
|
||||
if (yAxis.IsCategory())
|
||||
{
|
||||
float tooltipSplitWid = splitWidth < 1 ? 1 : splitWidth;
|
||||
float pX = grid.context.x + grid.context.width;
|
||||
pY = (float)(grid.context.y + splitWidth * yAxis.context.pointerValue -
|
||||
(yAxis.boundaryGap ? 0 : splitWidth / 2));
|
||||
if (pY < grid.context.y)
|
||||
break;
|
||||
Vector3 p1 = new Vector3(grid.context.x, pY);
|
||||
Vector3 p2 = new Vector3(grid.context.x, pY + tooltipSplitWid);
|
||||
Vector3 p3 = new Vector3(pX, pY + tooltipSplitWid);
|
||||
Vector3 p4 = new Vector3(pX, pY);
|
||||
UGL.DrawQuadrilateral(vh, p1, p2, p3, p4, chart.theme.tooltip.areaColor);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawPolarIndicator(VertexHelper vh, Tooltip tooltip, PolarCoord m_Polar)
|
||||
{
|
||||
if (tooltip.context.angle < 0) return;
|
||||
var theme = chart.theme;
|
||||
var m_AngleAxis = ComponentHelper.GetAngleAxis(chart.components, m_Polar.index);
|
||||
var lineColor = TooltipHelper.GetLineColor(tooltip, theme.tooltip.lineColor);
|
||||
var lineType = tooltip.lineStyle.GetType(theme.tooltip.lineType);
|
||||
var lineWidth = tooltip.lineStyle.GetWidth(theme.tooltip.lineWidth);
|
||||
var cenPos = m_Polar.context.center;
|
||||
var radius = m_Polar.context.outsideRadius;
|
||||
var tooltipAngle = m_AngleAxis.GetValueAngle(tooltip.context.angle);
|
||||
|
||||
var sp = ChartHelper.GetPos(m_Polar.context.center, m_Polar.context.insideRadius, tooltipAngle, true);
|
||||
var ep = ChartHelper.GetPos(m_Polar.context.center, m_Polar.context.outsideRadius, tooltipAngle, true);
|
||||
|
||||
switch (tooltip.context.type)
|
||||
{
|
||||
case Tooltip.Type.Cross:
|
||||
ChartDrawer.DrawLineStyle(vh, lineType, lineWidth, sp, ep, lineColor);
|
||||
var dist = Vector2.Distance(chart.pointerPos, cenPos);
|
||||
if (dist > radius) dist = radius;
|
||||
var outsideRaidus = dist + tooltip.lineStyle.GetWidth(theme.tooltip.lineWidth) * 2;
|
||||
UGL.DrawDoughnut(vh, cenPos, dist, outsideRaidus, lineColor, Color.clear);
|
||||
break;
|
||||
case Tooltip.Type.Line:
|
||||
ChartDrawer.DrawLineStyle(vh, lineType, lineWidth, sp, ep, lineColor);
|
||||
break;
|
||||
case Tooltip.Type.Shadow:
|
||||
UGL.DrawSector(vh, cenPos, radius, lineColor, tooltipAngle - 2, tooltipAngle + 2, chart.settings.cicleSmoothness);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7d25a5b5e3d6f45b8a06b94e33792087
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,156 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts.Runtime
|
||||
{
|
||||
public static class TooltipHelper
|
||||
{
|
||||
internal static void ResetTooltipParamsByItemFormatter(Tooltip tooltip, BaseChart chart)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(tooltip.titleFormatter))
|
||||
{
|
||||
if (IsIgnoreFormatter(tooltip.titleFormatter))
|
||||
{
|
||||
tooltip.context.data.title = string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
tooltip.context.data.title = tooltip.titleFormatter;
|
||||
var numericFormatter = string.IsNullOrEmpty(tooltip.titleLabelStyle.numericFormatter)
|
||||
? tooltip.numericFormatter : tooltip.titleLabelStyle.numericFormatter;
|
||||
FormatterHelper.ReplaceContent(ref tooltip.context.data.title, -1, numericFormatter, null, chart);
|
||||
}
|
||||
}
|
||||
for (int i = tooltip.context.data.param.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var param = tooltip.context.data.param[i];
|
||||
if (IsIgnoreFormatter(param.itemFormatter))
|
||||
{
|
||||
tooltip.context.data.param.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
foreach (var param in tooltip.context.data.param)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(param.itemFormatter))
|
||||
{
|
||||
param.columns.Clear();
|
||||
var content = param.itemFormatter;
|
||||
FormatterHelper.ReplaceSerieLabelContent(ref content,
|
||||
param.numericFormatter,
|
||||
param.dataCount,
|
||||
param.value,
|
||||
param.total,
|
||||
param.serieName,
|
||||
param.category,
|
||||
param.serieData.name,
|
||||
param.color,
|
||||
param.serieData,
|
||||
chart,
|
||||
param.serieIndex);
|
||||
foreach (var item in content.Split('|'))
|
||||
{
|
||||
param.columns.Add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsIgnoreFormatter(string itemFormatter)
|
||||
{
|
||||
return "-".Equals(itemFormatter) || "{i}".Equals(itemFormatter, StringComparison.CurrentCultureIgnoreCase);
|
||||
}
|
||||
|
||||
public static void LimitInRect(BaseChart chart, Tooltip tooltip, Rect chartRect)
|
||||
{
|
||||
if (tooltip.view == null)
|
||||
return;
|
||||
|
||||
var pos = tooltip.view.GetTargetPos();
|
||||
if (pos.x + tooltip.context.width > chartRect.x + chartRect.width)
|
||||
{
|
||||
pos.x = tooltip.context.pointer.x - tooltip.context.width - tooltip.offset.x;
|
||||
}
|
||||
else if (pos.x < chartRect.x)
|
||||
{
|
||||
pos.x = tooltip.context.pointer.x - tooltip.context.width + Mathf.Abs(tooltip.offset.x);
|
||||
}
|
||||
if (pos.y - tooltip.context.height < chartRect.y)
|
||||
{
|
||||
pos.y = chartRect.y + tooltip.context.height;
|
||||
}
|
||||
if (pos.y > chartRect.y + chartRect.height)
|
||||
pos.y = chartRect.y + chartRect.height;
|
||||
var screenGap = 10;
|
||||
var screenPos = chart.LocalPointToScreenPoint(pos);
|
||||
if (screenPos.x < screenGap)
|
||||
pos.x += Mathf.Abs(screenPos.x) + screenGap;
|
||||
if (screenPos.x + tooltip.context.width > Screen.width - screenGap)
|
||||
pos.x -= Mathf.Abs(screenPos.x + tooltip.context.width - Screen.width) + screenGap;
|
||||
|
||||
if (screenPos.y < tooltip.context.height + screenGap)
|
||||
pos.y += Mathf.Abs(screenPos.y - tooltip.context.height) + screenGap;
|
||||
if (screenPos.y > Screen.height - screenGap)
|
||||
pos.y -= Mathf.Abs(screenPos.y - Screen.height) + screenGap;
|
||||
|
||||
UpdateContentPos(tooltip, pos, chartRect);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新文本框位置
|
||||
/// </summary>
|
||||
/// <param name="pos"></param>
|
||||
private static void UpdateContentPos(Tooltip tooltip, Vector2 pos, Rect chartRect)
|
||||
{
|
||||
if (tooltip.view != null)
|
||||
{
|
||||
var width = chartRect.width;
|
||||
var height = chartRect.height;
|
||||
switch (tooltip.position)
|
||||
{
|
||||
case Tooltip.Position.Auto:
|
||||
#if UNITY_ANDROID || UNITY_IOS
|
||||
if (tooltip.fixedY == 0) pos.y = chartRect.x + ChartHelper.GetActualValue(0.7f, height);
|
||||
else pos.y = chartRect.y + ChartHelper.GetActualValue(tooltip.fixedY, height);
|
||||
#endif
|
||||
break;
|
||||
case Tooltip.Position.Custom:
|
||||
pos = new Vector2(chartRect.x, chartRect.y);
|
||||
pos.x += ChartHelper.GetActualValue(tooltip.fixedX, width);
|
||||
pos.y += ChartHelper.GetActualValue(tooltip.fixedY, height);
|
||||
break;
|
||||
case Tooltip.Position.FixedX:
|
||||
pos = new Vector2(chartRect.x, pos.y);
|
||||
pos.x += ChartHelper.GetActualValue(tooltip.fixedX, width);
|
||||
break;
|
||||
case Tooltip.Position.FixedY:
|
||||
pos = new Vector2(pos.x, chartRect.y);
|
||||
pos.y += ChartHelper.GetActualValue(tooltip.fixedY, height);
|
||||
break;
|
||||
}
|
||||
tooltip.view.UpdatePosition(pos);
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetItemNumericFormatter(Tooltip tooltip, Serie serie, SerieData serieData)
|
||||
{
|
||||
var itemStyle = SerieHelper.GetItemStyle(serie, serieData);
|
||||
if (!string.IsNullOrEmpty(itemStyle.numericFormatter)) return itemStyle.numericFormatter;
|
||||
else return tooltip.numericFormatter;
|
||||
}
|
||||
|
||||
public static Color32 GetLineColor(Tooltip tooltip, Color32 defaultColor)
|
||||
{
|
||||
var lineStyle = tooltip.lineStyle;
|
||||
if (!ChartHelper.IsClearColor(lineStyle.color))
|
||||
{
|
||||
return lineStyle.GetColor();
|
||||
}
|
||||
else
|
||||
{
|
||||
var color = defaultColor;
|
||||
ChartHelper.SetColorOpacity(ref color, lineStyle.opacity);
|
||||
return color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 184e190de6da6486b8b4d333a302477a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,301 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using XUGL;
|
||||
|
||||
namespace XCharts.Runtime
|
||||
{
|
||||
public class TooltipViewItem
|
||||
{
|
||||
public GameObject gameObject;
|
||||
public List<ChartLabel> columns = new List<ChartLabel>();
|
||||
}
|
||||
public class TooltipView
|
||||
{
|
||||
private static Vector2 anchorMax = new Vector2(0, 1);
|
||||
private static Vector2 anchorMin = new Vector2(0, 1);
|
||||
private static Vector2 pivot = new Vector2(0, 1);
|
||||
private static Vector2 v2_0_05 = new Vector2(0, 0.5f);
|
||||
|
||||
public Tooltip tooltip;
|
||||
public ComponentTheme theme;
|
||||
public GameObject gameObject;
|
||||
public Transform transform;
|
||||
public Image background;
|
||||
public Outline border;
|
||||
public VerticalLayoutGroup layout;
|
||||
public ChartLabel title;
|
||||
private List<TooltipViewItem> m_Items = new List<TooltipViewItem>();
|
||||
private List<float> m_ColumnMaxWidth = new List<float>();
|
||||
private bool m_Active = false;
|
||||
private Vector3 m_TargetPos;
|
||||
private Vector3 m_CurrentVelocity;
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (!m_Active)
|
||||
return;
|
||||
transform.localPosition = Vector3.SmoothDamp(transform.localPosition, m_TargetPos, ref m_CurrentVelocity, 0.08f);
|
||||
}
|
||||
|
||||
public Vector3 GetCurrentPos()
|
||||
{
|
||||
return transform.localPosition;
|
||||
}
|
||||
|
||||
public Vector3 GetTargetPos()
|
||||
{
|
||||
return m_TargetPos;
|
||||
}
|
||||
|
||||
public void UpdatePosition(Vector3 pos)
|
||||
{
|
||||
m_TargetPos = pos;
|
||||
}
|
||||
|
||||
public void SetActive(bool flag)
|
||||
{
|
||||
m_Active = flag && tooltip.showContent;
|
||||
ChartHelper.SetActive(gameObject, m_Active);
|
||||
if (!flag)
|
||||
{
|
||||
m_ColumnMaxWidth.Clear();
|
||||
foreach (var item in m_Items)
|
||||
item.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void Refresh()
|
||||
{
|
||||
if (tooltip == null) return;
|
||||
var data = tooltip.context.data;
|
||||
var ignoreColumn = string.IsNullOrEmpty(tooltip.ignoreDataDefaultContent);
|
||||
|
||||
var titleActive = !string.IsNullOrEmpty(data.title);
|
||||
ChartHelper.SetActive(title, titleActive);
|
||||
title.SetText(data.title);
|
||||
|
||||
for (int i = 0; i < data.param.Count; i++)
|
||||
{
|
||||
var item = GetItem(i);
|
||||
var param = data.param[i];
|
||||
if (param.columns.Count <= 0 || (ignoreColumn && param.ignore))
|
||||
{
|
||||
item.gameObject.SetActive(false);
|
||||
continue;
|
||||
}
|
||||
item.gameObject.SetActive(true);
|
||||
for (int j = 0; j < param.columns.Count; j++)
|
||||
{
|
||||
var column = GetItemColumn(item, j, j == 0 && IsSecondaryMark(param, param.columns[j]));
|
||||
column.SetActive(true);
|
||||
column.SetText(param.columns[j]);
|
||||
|
||||
if (j == 0)
|
||||
{
|
||||
var labelStyle = tooltip.GetContentLabelStyle(j);
|
||||
if (labelStyle != null && ChartHelper.IsClearColor(labelStyle.textStyle.color))
|
||||
column.text.SetColor(param.color);
|
||||
}
|
||||
|
||||
if (j >= m_ColumnMaxWidth.Count)
|
||||
m_ColumnMaxWidth.Add(0);
|
||||
|
||||
var columnWidth = column.text.GetPreferredWidth() + GetTooltipColumnGapWidth(tooltip, j);
|
||||
if (m_ColumnMaxWidth[j] < columnWidth)
|
||||
m_ColumnMaxWidth[j] = columnWidth;
|
||||
}
|
||||
for (int j = param.columns.Count; j < item.columns.Count; j++)
|
||||
{
|
||||
item.columns[j].SetActive(false);
|
||||
}
|
||||
}
|
||||
for (int i = data.param.Count; i < m_Items.Count; i++)
|
||||
{
|
||||
m_Items[i].gameObject.SetActive(false);
|
||||
}
|
||||
ResetSize();
|
||||
UpdatePosition(tooltip.context.pointer + tooltip.offset);
|
||||
tooltip.gameObject.transform.SetAsLastSibling();
|
||||
}
|
||||
|
||||
private static float GetTooltipColumnGapWidth(Tooltip tooltip, int index)
|
||||
{
|
||||
if (tooltip == null || tooltip.columnGapWidths.Count == 0) return 0;
|
||||
if (tooltip.columnGapWidths.Count == 1) return index == 1 ? tooltip.columnGapWidths[0] : 0;
|
||||
if (index < tooltip.columnGapWidths.Count)
|
||||
{
|
||||
return tooltip.columnGapWidths[index];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static bool IsSecondaryMark(SerieParams sp, string mark)
|
||||
{
|
||||
return sp.isSecondaryMark && mark == sp.marker;
|
||||
}
|
||||
|
||||
private void ResetSize()
|
||||
{
|
||||
var maxHig = 0f;
|
||||
var maxWid = 0f;
|
||||
if (tooltip.fixedWidth > 0)
|
||||
{
|
||||
maxWid = tooltip.fixedWidth;
|
||||
}
|
||||
else
|
||||
{
|
||||
maxWid = TotalMaxWidth();
|
||||
var titleWid = title.GetTextWidth();
|
||||
if (maxWid < titleWid)
|
||||
maxWid = titleWid;
|
||||
}
|
||||
|
||||
if (tooltip.fixedHeight > 0)
|
||||
{
|
||||
maxHig = tooltip.fixedHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!string.IsNullOrEmpty(title.text.GetText()))
|
||||
maxHig += tooltip.titleHeight;
|
||||
maxHig += tooltip.itemHeight * tooltip.context.data.param.Count;
|
||||
maxHig += tooltip.paddingTopBottom * 2;
|
||||
}
|
||||
|
||||
if (tooltip.minWidth > 0 && maxWid < tooltip.minWidth)
|
||||
maxWid = tooltip.minWidth;
|
||||
|
||||
if (tooltip.minHeight > 0 && maxHig < tooltip.minHeight)
|
||||
maxHig = tooltip.minHeight;
|
||||
|
||||
for (int i = 0; i < m_Items.Count; i++)
|
||||
{
|
||||
var item = m_Items[i];
|
||||
item.gameObject.GetComponent<RectTransform>().sizeDelta = new Vector2(maxWid, tooltip.itemHeight);
|
||||
var xPos = 0f;
|
||||
for (int j = 0; j < m_ColumnMaxWidth.Count; j++)
|
||||
{
|
||||
if (j >= item.columns.Count) break;
|
||||
var deltaX = j == m_ColumnMaxWidth.Count - 1 ? maxWid - xPos : m_ColumnMaxWidth[j];
|
||||
item.columns[j].text.SetSizeDelta(new Vector2(deltaX, tooltip.itemHeight));
|
||||
item.columns[j].SetSize(deltaX, tooltip.itemHeight);
|
||||
item.columns[j].SetRectPosition(new Vector3(xPos, 0));
|
||||
xPos += m_ColumnMaxWidth[j];
|
||||
}
|
||||
}
|
||||
tooltip.context.width = maxWid + tooltip.paddingLeftRight * 2;
|
||||
tooltip.context.height = maxHig;
|
||||
background.GetComponent<RectTransform>().sizeDelta = new Vector2(tooltip.context.width, tooltip.context.height);
|
||||
}
|
||||
|
||||
private float TotalMaxWidth()
|
||||
{
|
||||
var total = 0f;
|
||||
foreach (var max in m_ColumnMaxWidth)
|
||||
total += max;
|
||||
return total;
|
||||
}
|
||||
|
||||
private TooltipViewItem GetItem(int i)
|
||||
{
|
||||
if (i < 0) i = 0;
|
||||
if (i < m_Items.Count)
|
||||
{
|
||||
return m_Items[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
var item = CreateViewItem(i, gameObject.transform, tooltip, theme);
|
||||
m_Items.Add(item);
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
private ChartLabel GetItemColumn(TooltipViewItem item, int i, bool isSecondaryMark = false)
|
||||
{
|
||||
if (i < 0) i = 0;
|
||||
ChartLabel column;
|
||||
if (i < item.columns.Count)
|
||||
{
|
||||
column = item.columns[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
column = CreateViewItemColumn(i, item.gameObject.transform, tooltip, theme);
|
||||
item.columns.Add(column);
|
||||
}
|
||||
if (isSecondaryMark)
|
||||
{
|
||||
column.text.text.fontSize = (int)(tooltip.GetContentLabelStyle(i).textStyle.fontSize * 0.6f);
|
||||
}
|
||||
return column;
|
||||
}
|
||||
|
||||
public static TooltipView CreateView(Tooltip tooltip, ThemeStyle theme, Transform parent)
|
||||
{
|
||||
var view = new TooltipView();
|
||||
view.tooltip = tooltip;
|
||||
view.theme = theme.tooltip;
|
||||
|
||||
view.gameObject = ChartHelper.AddObject("view", parent, anchorMin, anchorMax, pivot, Vector3.zero);
|
||||
view.gameObject.transform.localPosition = Vector3.zero;
|
||||
view.transform = view.gameObject.transform;
|
||||
|
||||
view.background = ChartHelper.EnsureComponent<Image>(view.gameObject);
|
||||
view.background.sprite = tooltip.backgroundImage;
|
||||
view.background.type = tooltip.backgroundType;
|
||||
view.background.color = ChartHelper.IsClearColor(tooltip.backgroundColor) ?
|
||||
Color.white : tooltip.backgroundColor;
|
||||
|
||||
view.border = ChartHelper.EnsureComponent<Outline>(view.gameObject);
|
||||
view.border.enabled = tooltip.borderWidth > 0;
|
||||
view.border.useGraphicAlpha = false;
|
||||
view.border.effectColor = tooltip.borderColor;
|
||||
view.border.effectDistance = new Vector2(tooltip.borderWidth, -tooltip.borderWidth);
|
||||
|
||||
view.layout = ChartHelper.EnsureComponent<VerticalLayoutGroup>(view.gameObject);
|
||||
view.layout.childControlHeight = false;
|
||||
view.layout.childControlWidth = false;
|
||||
view.layout.childForceExpandHeight = false;
|
||||
view.layout.childForceExpandWidth = false;
|
||||
view.layout.padding = new RectOffset(tooltip.paddingLeftRight,
|
||||
tooltip.paddingLeftRight,
|
||||
tooltip.paddingTopBottom,
|
||||
tooltip.paddingTopBottom);
|
||||
|
||||
view.title = ChartHelper.AddChartLabel("title", view.gameObject.transform, tooltip.titleLabelStyle, theme.tooltip,
|
||||
"", Color.clear, TextAnchor.MiddleLeft);
|
||||
view.title.gameObject.SetActive(true);
|
||||
|
||||
var item = CreateViewItem(0, view.gameObject.transform, tooltip, theme.tooltip);
|
||||
view.m_Items.Add(item);
|
||||
|
||||
view.Refresh();
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
private static TooltipViewItem CreateViewItem(int i, Transform parent, Tooltip tooltip, ComponentTheme theme)
|
||||
{
|
||||
GameObject item1 = ChartHelper.AddObject("item" + i, parent, anchorMin, anchorMax, v2_0_05, Vector3.zero);
|
||||
|
||||
var item = new TooltipViewItem();
|
||||
item.gameObject = item1;
|
||||
item.columns.Add(CreateViewItemColumn(0, item1.transform, tooltip, theme));
|
||||
item.columns.Add(CreateViewItemColumn(1, item1.transform, tooltip, theme));
|
||||
item.columns.Add(CreateViewItemColumn(2, item1.transform, tooltip, theme));
|
||||
return item;
|
||||
}
|
||||
|
||||
private static ChartLabel CreateViewItemColumn(int i, Transform parent, Tooltip tooltip, ComponentTheme theme)
|
||||
{
|
||||
var labelStyle = tooltip.GetContentLabelStyle(i);
|
||||
labelStyle.textStyle.autoAlign = false;
|
||||
var label = ChartHelper.AddChartLabel("column" + i, parent, labelStyle, theme,
|
||||
"", Color.clear, TextAnchor.MiddleLeft, true);
|
||||
return label;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 20bbaf6c402824f5d8abcaf1cee57865
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user