Delphi 10.1, VCL, with embedded Teechart.
I've an Area Series with a Mark moved by code to a custom position. When the Mark title content is changed, the Yellow background is not adjusted (Auto Sized) to the new Mark content. I've a work around for that, but it has flickers and it is not elegant. I'm looking for an idea how to do it better.
In details: I put three buttons on the chart, one to move the Mark location, the 2nd button to add a second content line to Mark title. The 3rd button is my work around to get a proper size. The Series Creation:
procedure TForm2.FormCreate(Sender: TObject);
begin
Chart1.View3D := false;
Chart1.Axes.Bottom.SetMinMax(0,5);
with Chart1.AddSeries(tAreaSeries) as tAreaSeries do
begin
AddXY(1, 10); // Two points AreaSeries
AddXY(4, 10);
Marks[1].Visible := false; // Hide the other Mark, the default is true
Marks.Visible := true; // Global Visibility for all Markers
Chart1[0].Marks[0].Text.Text := 'First-line';
end;
end;
Pressing Move Mark button code:
procedure TForm2.btnMoveMarkClick(Sender: TObject);
begin
Chart1[0].Marks.Positions[0].Custom := true;
Chart1[0].Marks.Positions[0].Offset(point(50,70));
// Chart1[0].Marks.Positions[0].LeftTop := point(150,200); // It is moving the Mark but not drawing the line to Series point
Chart1.Repaint; // It doesn't work without this Repaint
end;
Will generate the following screen: Now, pressing the 2nd button to change Mark Title content as follow:
procedure TForm2.btnChangeMarkContentClick(Sender: TObject);
begin
Chart1[0].Marks[0].Text.Text := 'First-line'+#13+'Second-line';
end;
As you can see, the Yellow background size was not changed:
My brut-force work around is to delete the custom position, this will resize the Mark, then reposition the Mark again as follow:
procedure TForm2.btnResizeMarkClick(Sender: TObject);
var
LastPoint: tpoint;
begin
LastPoint := Chart1[0].Marks.Positions[0].LeftTop;
Chart1[0].Marks.Positions.Automatic(0);
Chart1.Repaint;
Chart1[0].Marks.Positions[0].Custom := true;
Chart1.Repaint;
// Chart1[0].Marks[0].MoveTo(LastPoint); // It doesn't work - Why?
Chart1[0].Marks.Positions[0].LeftTop := LastPoint; // Better to use Offset
Chart1.Repaint;
end;
It is doing the job, but with flicker due to Mark movement, as follow:
Thanks for any hint how to resize the Mark without delete its custom position which cause the flicker. Reron
Yeray solved the main problem. In addition, the Arrows should be adjusted too as follow:
type
tCustomTextShapeAccess = class(tCustomTextShape); // Yeray: tCustomTextShapeAccess class to get access to the protected CalcBounds method
const
tcaTopLeft = 0;
tcaArrowTo = 1;
procedure TeeChart_ResizeCustomMark(aChart: tChart; aSeriesInx, aMarkInx, aAnchor: integer);
// Resize Custom Mark area shape. It is required after Title text modification
// aAnchor: tcaTopLeft(0), tcaArrowTo(1); Choose which point to keep
var
aSeries: tChartSeries;
aMark : tMarksItem;
aMarkPosision: tSeriesMarkPosition;
begin
// Assignments for more readable code
aSeries := aChart[aSeriesInx];
aMark := aChart[aSeriesInx].Marks[aMarkInx];
aMarkPosision := aSeries.Marks.Positions[aMarkInx];
// Bounds Calculation of the new Mark. Yeray solution.
tCustomTextShapeAccess(aMark).CalcBounds(aChart); // Yeray: tCustomTextShapeAccess class to get access to the protected CalcBounds method
aMarkPosision.Height := aMark.Height;
aMarkPosision.Width := aMark.Width;
// Set Mark position based on aAnchor
case aAnchor of
tcaTopLeft: // Keep LeftTop point. Set new ArrowTo point.
begin
aMarkPosision.ArrowTo.X := aMarkPosision.LeftTop.X + (aMarkPosision.Width div 2);
if aSeries.CalcYPos(aMarkInx) > aMarkPosision.ArrowTo.Y then // Mark above Series point
aMarkPosision.ArrowTo.Y := aMarkPosision.LeftTop.Y + aMarkPosision.Height
else
aMarkPosision.ArrowTo.Y := aMarkPosision.LeftTop.Y;
end;
else // Set ArrowTo point. Set a New LeftTop point.
begin
aMarkPosision.LeftTop.X := aMarkPosision.ArrowTo.X - (aMarkPosision.Width div 2);
if aSeries.CalcYPos(aMarkInx) > aMarkPosision.ArrowTo.Y then // Mark above Series point
aMarkPosision.LeftTop.Y := aMarkPosision.ArrowTo.Y - (aMarkPosision.Height -1)
else // Mark below Series point
aMarkPosision.ArrowTo.Y := aMarkPosision.LeftTop.Y;
end;
end; // case
aChart.Repaint;
end;