PDA

View Full Version : [CLOSED] chart / text at the bottom of a column too long



tMp
Jan 16, 2014, 2:56 PM
When the Text of the bottom axis is getting to long I either don't see everything or I don't see the text at all. Is there a way how I can confine this text in a box so that it just breaks when it gets too long?

example:

<%@ Page Language="C#" %>

<%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>

<!DOCTYPE html>

<script runat="server">

protected void Page_Load(object sender, EventArgs e)
{
// create sample data
System.Data.DataTable dt = new System.Data.DataTable();
Random ran = new Random();

System.Data.DataColumn dc = new System.Data.DataColumn("Name");
dc.DataType = System.Type.GetType("System.String");
dt.Columns.Add(dc);
dc = new System.Data.DataColumn("Data");
dc.DataType = System.Type.GetType("System.Int32");
dt.Columns.Add(dc);
System.Data.DataRow dr = dt.NewRow();
dr[0] = "January";
dr[1] = ran.Next(0, 100);
dt.Rows.Add(dr); dr = dt.NewRow();
dr[0] = "February";
dr[1] = ran.Next(0, 100);
dt.Rows.Add(dr); dr = dt.NewRow();
dr[0] = "March is just way too long for this";
dr[1] = ran.Next(0, 100);
dt.Rows.Add(dr);


if (!X.IsAjaxRequest)
{
Ext.Net.Panel pnl = new Ext.Net.Panel
{
Title = "Chart Test",
Layout = "FitLayout",
Width = 300,
Height = 500,
Items =
{
new Chart {
ID = "ChartTest",
Shadow = true,
Animate = true,
LegendConfig = new ChartLegend() { Position = LegendPosition.Top },
Store = {
new Store {
DataSource = dt,
AutoDataBind = true,
Model = {
new Model {
Fields = {
new ModelField { Name = "Name" },
new ModelField { Name = "Data" }
}
}
}
}
},
Axes = {
new NumericAxis { Fields = new string[] { "Data" }, Title = "Number", Minimum = 0 },
new CategoryAxis { Position = Position.Bottom, Fields = new string[] { "Name" }, Title = "Name" }
},
Series = {
new ColumnSeries { Axis = Position.Left, XField = new string[] { "Name" }, YField = new string[] { "Data" } }
}
}
}
};

this.Form.Controls.Add(pnl);
}
}

</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<ext:ResourceManager ID="ResourceManager1" runat="server" />
<div>

</div>
</form>
</body>
</html>

Daniil
Jan 17, 2014, 5:50 AM
Hi @tMp,

Maybe, something like this:

new CategoryAxis
{
Position = Position.Bottom,
Fields = new string[] { "Name" },
Title = "Name",
Label = new AxisLabel()
{
Renderer =
{
Handler = "if (value.length > 8) { value = value.substr(0, 8) + '...' }; return value;"
}
}
}

Though, there is a big disadvantage. Whenever the Chart's width changes, you will have to adjust "8" in the Label's Renderer.

Those labels are drown in the Ext.chart.axis.Axis's drawHorizontalLabels function. Maybe, you will be able to override it. Here is the original code.

Ext.chart.axis.Axis.override({
drawHorizontalLabels: function () {
var me = this,
labelConf = me.label,
floor = Math.floor,
max = Math.max,
axes = me.chart.axes,
insetPadding = me.chart.insetPadding,
gutters = me.chart.maxGutters,
position = me.position,
inflections = me.inflections,
ln = inflections.length,
labels = me.labels,
maxHeight = 0,
ratio,
bbox, point, prevLabel, prevLabelId,
adjustEnd = me.adjustEnd,
hasLeft = axes.findIndex('position', 'left') != -1,
hasRight = axes.findIndex('position', 'right') != -1,
textLabel, text,
last, x, y, i, firstLabel;

last = ln - 1;
//get a reference to the first text label dimensions
point = inflections[0];
firstLabel = me.getOrCreateLabel(0, me.label.renderer(labels[0]));
ratio = Math.floor(Math.abs(Math.sin(labelConf.rotate && (labelConf.rotate.degrees * Math.PI / 180) || 0)));

for (i = 0; i < ln; i++) {
point = inflections[i];
text = me.label.renderer(labels[i]);
textLabel = me.getOrCreateLabel(i, text);
bbox = textLabel._bbox;
maxHeight = max(maxHeight, bbox.height + me.dashSize + me.label.padding);
x = floor(point[0] - (ratio ? bbox.height : bbox.width) / 2);
if (adjustEnd && gutters.left == 0 && gutters.right == 0) {
if (i == 0 && !hasLeft) {
x = point[0];
}
else if (i == last && !hasRight) {
x = Math.min(x, point[0] - bbox.width + insetPadding);
}
}
if (position == 'top') {
y = point[1] - (me.dashSize * 2) - me.label.padding - (bbox.height / 2);
}
else {
y = point[1] + (me.dashSize * 2) + me.label.padding + (bbox.height / 2);
}

textLabel.setAttributes({
hidden: false,
x: x,
y: y
}, true);

// Skip label if there isn't available minimum space
if (i != 0 && (me.intersect(textLabel, prevLabel)
|| me.intersect(textLabel, firstLabel))) {
if (i === last && prevLabelId !== 0) {
prevLabel.hide(true);
} else {
textLabel.hide(true);
continue;
}
}

prevLabel = textLabel;
prevLabelId = i;
}

return maxHeight;
}
});

tMp
Jan 17, 2014, 9:00 AM
thank you. I didn't think of the renderer. Working perfectly for me in this case and the size never changes anyway. So for quick and dirty this is perfect. I will look into the rest, when I have so more time. It would be nice, if one could rotate the text or define like a boundry box. Perhaps as a future setting.

Best regards

Daniil
Jan 17, 2014, 11:30 AM
Ok, I am closing the thread.

If you revisit the issue in the future, please feel free to post here.