mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-13 21:02:55 +02:00
TAChart: Add wordwrapping feature to axis title.
git-svn-id: trunk@64799 -
This commit is contained in:
parent
970b6b43d6
commit
2d5c00038e
@ -116,11 +116,14 @@ type
|
||||
FRange: TChartRange;
|
||||
FTitle: TChartAxisTitle;
|
||||
FTransformations: TChartAxisTransformations;
|
||||
FWrappedTitle: String;
|
||||
FZPosition: TChartDistance;
|
||||
|
||||
function GetMarks: TChartAxisMarks; inline;
|
||||
function GetRealTitle: String;
|
||||
function GetValue(AIndex: Integer): TChartValueText; inline;
|
||||
function GetValueCount: Integer; inline;
|
||||
function IsWordwrappedTitle: Boolean;
|
||||
function PositionIsStored: Boolean;
|
||||
procedure SetAtDataOnly(AValue: Boolean);
|
||||
procedure SetAxisPen(AValue: TChartAxisPen);
|
||||
@ -139,6 +142,7 @@ type
|
||||
procedure SetTitle(AValue: TChartAxisTitle);
|
||||
procedure SetTransformations(AValue: TChartAxisTransformations);
|
||||
procedure SetZPosition(AValue: TChartDistance);
|
||||
procedure WordwrapTitle(ADrawer: IChartDrawer; AClipRect: TRect);
|
||||
|
||||
protected
|
||||
function GetDisplayName: String; override;
|
||||
@ -160,8 +164,8 @@ type
|
||||
function IsFlipped: Boolean; override;
|
||||
function IsPointInside(const APoint: TPoint): Boolean;
|
||||
function IsVertical: Boolean; inline;
|
||||
procedure Measure(
|
||||
const AExtent: TDoubleRect; var AMeasureData: TChartAxisGroup);
|
||||
procedure Measure(const AExtent: TDoubleRect; const AClipRect: TRect;
|
||||
var AMeasureData: TChartAxisGroup);
|
||||
function MeasureLabelSize(ADrawer: IChartDrawer): Integer;
|
||||
function PositionToCoord(const ARect: TRect): Integer;
|
||||
procedure PrepareHelper(
|
||||
@ -235,8 +239,8 @@ type
|
||||
procedure Draw(ACurrentZ: Integer; var AIndex: Integer);
|
||||
function GetAxisByAlign(AAlign: TChartAxisAlignment): TChartAxis;
|
||||
function GetEnumerator: TChartAxisEnumerator;
|
||||
function Measure(
|
||||
const AExtent: TDoubleRect; ADepth: Integer): TChartAxisMargins;
|
||||
function Measure(const AExtent: TDoubleRect; const AClipRect: TRect;
|
||||
ADepth: Integer): TChartAxisMargins;
|
||||
procedure Prepare(ARect: TRect);
|
||||
procedure PrepareGroups;
|
||||
procedure SetAxisByAlign(AAlign: TChartAxisAlignment; AValue: TChartAxis);
|
||||
@ -276,7 +280,8 @@ type
|
||||
implementation
|
||||
|
||||
uses
|
||||
LResources, Math, PropEdits, TAChartStrConsts, TAGeometry, TAMath;
|
||||
LResources, Math, PropEdits,
|
||||
TAChartStrConsts, TAGeometry, TAMath;
|
||||
|
||||
var
|
||||
VIdentityTransform: TChartAxisTransformations;
|
||||
@ -636,7 +641,7 @@ begin
|
||||
end;
|
||||
TPointBoolArr(p)[IsVertical] := FTitlePos;
|
||||
p += FHelper.FZOffset;
|
||||
Title.DrawLabel(FHelper.FDrawer, p, p, Title.Caption, FTitlePolygon);
|
||||
Title.DrawLabel(FHelper.FDrawer, p, p, GetRealTitle, FTitlePolygon);
|
||||
end;
|
||||
|
||||
function TChartAxis.GetAlignment: TChartAxisAlignment;
|
||||
@ -665,6 +670,14 @@ begin
|
||||
Result := TChartAxisMarks(inherited Marks);
|
||||
end{%H-}; // to silence the compiler warning of impossible inherited inside inline proc
|
||||
|
||||
function TChartAxis.GetRealTitle: String;
|
||||
begin
|
||||
if Title.Visible and IsWordwrappedTitle then
|
||||
Result := FWrappedTitle
|
||||
else
|
||||
Result := Title.Caption;
|
||||
end;
|
||||
|
||||
procedure TChartAxis.GetMarkValues;
|
||||
var
|
||||
i: Integer;
|
||||
@ -763,6 +776,13 @@ begin
|
||||
Result := Alignment in [calLeft, calRight];
|
||||
end;
|
||||
|
||||
function TChartAxis.IsWordwrappedTitle: Boolean;
|
||||
begin
|
||||
Result := Title.Wordwrap and (
|
||||
((FAlignment in [calLeft, calRight]) and (abs(Title.LabelFont.Orientation) = 900)) or
|
||||
((FAlignment in [calTop, calBottom]) and (Title.LabelFont.Orientation = 0)) );
|
||||
end;
|
||||
|
||||
function TChartAxis.MakeValuesInRangeParams(
|
||||
AMin, AMax: Double): TValuesInRangeParams;
|
||||
begin
|
||||
@ -779,7 +799,7 @@ begin
|
||||
end;
|
||||
|
||||
procedure TChartAxis.Measure(
|
||||
const AExtent: TDoubleRect; var AMeasureData: TChartAxisGroup);
|
||||
const AExtent: TDoubleRect; const AClipRect: TRect; var AMeasureData: TChartAxisGroup);
|
||||
var
|
||||
v: Boolean;
|
||||
d: IChartDrawer;
|
||||
@ -788,7 +808,7 @@ var
|
||||
begin
|
||||
if not Title.Visible or (Title.Caption = '') then exit(0);
|
||||
// Workaround for issue #19780, fix after upgrade to FPC 2.6.
|
||||
with Title.MeasureLabel(d, Title.Caption) do
|
||||
with Title.MeasureLabel(d, GetRealTitle) do
|
||||
Result := IfThen(v, cx, cy);
|
||||
if Title.DistanceToCenter then
|
||||
Result := Result div 2;
|
||||
@ -856,11 +876,16 @@ begin
|
||||
maxi := i;
|
||||
end;
|
||||
end;
|
||||
|
||||
if Title.Visible and IsWordwrappedTitle then
|
||||
WordwrapTitle(d, AClipRect);
|
||||
|
||||
with AMeasureData do begin
|
||||
FSize := Max(sz, FSize);
|
||||
FTitleSize := Max(TitleSize, FTitleSize);
|
||||
FMargin := Max(Margin, FMargin);
|
||||
end;
|
||||
|
||||
if minc < MaxInt then begin
|
||||
UpdateFirstLast(minc, mini, rmin, rmax);
|
||||
UpdateFirstLast(maxc, maxi, rmin, rmax);
|
||||
@ -1139,6 +1164,24 @@ begin
|
||||
end;
|
||||
}
|
||||
|
||||
procedure TChartAxis.WordwrapTitle(ADrawer: IChartDrawer; AClipRect: TRect);
|
||||
var
|
||||
w: Integer;
|
||||
begin
|
||||
if Alignment in [calLeft, calRight] then
|
||||
w := AClipRect.Height
|
||||
else if Alignment in [calBottom, calTop] then
|
||||
w := AClipRect.Width
|
||||
else
|
||||
begin
|
||||
FWrappedTitle := Title.Caption;
|
||||
exit;
|
||||
end;
|
||||
ADrawer.Font := Title.LabelFont;
|
||||
FWrappedTitle := TADrawUtils.WordWrap(Title.Caption, ADrawer, w, Title.TextFormat);
|
||||
end;
|
||||
|
||||
|
||||
{ TChartAxisList }
|
||||
|
||||
function TChartAxisList.Add: TChartAxis; inline;
|
||||
@ -1210,8 +1253,8 @@ begin
|
||||
AList.Sort(ACompare);
|
||||
end;
|
||||
|
||||
function TChartAxisList.Measure(
|
||||
const AExtent: TDoubleRect; ADepth: Integer): TChartAxisMargins;
|
||||
function TChartAxisList.Measure(const AExtent: TDoubleRect;
|
||||
const AClipRect: TRect; ADepth: Integer): TChartAxisMargins;
|
||||
var
|
||||
g: ^TChartAxisGroup;
|
||||
|
||||
@ -1239,14 +1282,14 @@ begin
|
||||
for j := 0 to g^.FCount - 1 do begin
|
||||
axis := TChartAxis(FGroupOrder[ai]);
|
||||
try
|
||||
axis.Measure(AExtent, g^);
|
||||
axis.Measure(AExtent, AClipRect, g^);
|
||||
except
|
||||
axis.Visible := false;
|
||||
raise;
|
||||
end;
|
||||
ai += 1;
|
||||
end;
|
||||
// Axises of the same group should have the same Alignment, Position and ZPosition.
|
||||
// Axes of the same group should have the same Alignment, Position and ZPosition.
|
||||
if axis.IsDefaultPosition then
|
||||
Result[axis.Alignment] += Max(0,
|
||||
g^.FSize + g^.FTitleSize + g^.FMargin +
|
||||
|
@ -41,11 +41,13 @@ type
|
||||
strict private
|
||||
FCaption: String;
|
||||
FPositionOnMarks: Boolean;
|
||||
FWordwrap: Boolean;
|
||||
|
||||
function GetFont: TFont;
|
||||
procedure SetCaption(AValue: String);
|
||||
procedure SetFont(AValue: TFont);
|
||||
procedure SetPositionOnMarks(AValue: Boolean);
|
||||
procedure SetWordwrap(AValue: Boolean);
|
||||
public
|
||||
constructor Create(AOwner: TCustomChart);
|
||||
|
||||
@ -60,6 +62,7 @@ type
|
||||
read FPositionOnMarks write SetPositionOnMarks default false;
|
||||
property TextFormat;
|
||||
property Visible default false;
|
||||
property Wordwrap: Boolean read FWordwrap write SetWordwrap default false;
|
||||
end;
|
||||
|
||||
ICoordTransformer = interface
|
||||
@ -603,6 +606,14 @@ begin
|
||||
StyleChanged(Self);
|
||||
end;
|
||||
|
||||
procedure TChartAxisTitle.SetWordwrap(AValue: Boolean);
|
||||
begin
|
||||
if FWordwrap = AValue then exit;
|
||||
FWordwrap := AValue;
|
||||
StyleChanged(Self);
|
||||
end;
|
||||
|
||||
|
||||
{ TCustomChartAxisMarks }
|
||||
|
||||
constructor TCustomChartAxisMarks.Create(AOwner: TCustomChart);
|
||||
|
@ -15,7 +15,7 @@ unit TADrawUtils;
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, FPCanvas, FPImage, Types, TAChartUtils;
|
||||
SysUtils, Classes, FPCanvas, FPImage, Types, TAChartUtils;
|
||||
|
||||
type
|
||||
// Same types as in Graphics unit, but without dependency.
|
||||
@ -191,10 +191,14 @@ type
|
||||
function FPColorToChartColor(AFPColor: TFPColor): TChartColor;
|
||||
function ColorDef(AColor, ADefaultColor: TChartColor): TChartColor; inline;
|
||||
|
||||
function Wordwrap(const AText: String; ADrawer: IChartDrawer;
|
||||
AMaxWidth: Integer; ATextFormat: TChartTextFormat): String;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
Math, fasthtmlparser, htmlutil, TAGeometry, TAHtml;
|
||||
StrUtils, Math, fasthtmlparser, htmlutil, TAGeometry, TAHtml;
|
||||
|
||||
const
|
||||
LINE_INTERVAL = 2;
|
||||
@ -798,5 +802,65 @@ begin
|
||||
Result := TChartTextOut.Create(Self);
|
||||
end;
|
||||
|
||||
// Inserts LineEndings into the provided string AText such that its width
|
||||
// does not exceed the given width.
|
||||
function WordWrap(const AText: String; ADrawer: IChartDrawer;
|
||||
AMaxWidth: Integer; ATextFormat: TChartTextFormat): string;
|
||||
var
|
||||
L: TStrings;
|
||||
sa: TStringArray;
|
||||
line, testline: String;
|
||||
s: String;
|
||||
w, ws, wspace: Integer;
|
||||
i: Integer;
|
||||
begin
|
||||
Result := '';
|
||||
|
||||
if ATextFormat = tfNormal then
|
||||
begin
|
||||
wspace := ADrawer.TextExtent(' ').X;
|
||||
L := TStringList.Create;
|
||||
try
|
||||
L.Text := AText;
|
||||
for i := 0 to L.Count-1 do
|
||||
begin
|
||||
sa := SplitString(L[i], ' ');
|
||||
line := '';
|
||||
w := 0;
|
||||
for s in sa do
|
||||
begin
|
||||
ws := ADrawer.TextExtent(s).X;
|
||||
if w + wspace + ws <= AMaxWidth then
|
||||
begin
|
||||
line := IfThen(line='', s, line + ' ' + s);
|
||||
w := w + wspace + ws;
|
||||
end else
|
||||
begin
|
||||
if line = '' then
|
||||
begin
|
||||
Result := IfThen(Result='', s, Result + LineEnding + s);
|
||||
line := '';
|
||||
w := 0;
|
||||
end else
|
||||
begin
|
||||
Result := IfThen(Result='', line, Result + LineEnding + line);
|
||||
line := s;
|
||||
w := ws;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
if line <> '' then
|
||||
Result := IfThen(Result='', line, Result + LineEnding + line);
|
||||
if i <> L.Count-1 then
|
||||
Result := Result + LineEnding;
|
||||
end;
|
||||
finally
|
||||
L.Free;
|
||||
end;
|
||||
end else
|
||||
// ToDo: Implement wordwrap for html format
|
||||
Result := AText;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
|
@ -1521,7 +1521,7 @@ begin
|
||||
CalculateTransformationCoeffs(scSeriesMargins, scChartMargins, scMinDataSpace);
|
||||
cr := FClipRect;
|
||||
for tries := 1 to 10 do begin
|
||||
axisMargin := AxisList.Measure(CurrentExtent, scDepth);
|
||||
axisMargin := AxisList.Measure(CurrentExtent, FClipRect, scDepth);
|
||||
axisMargin[calLeft] := Max(axisMargin[calLeft], scDepth);
|
||||
axisMargin[calBottom] := Max(axisMargin[calBottom], scDepth);
|
||||
FClipRect := cr;
|
||||
|
Loading…
Reference in New Issue
Block a user