fpspreadsheet: Improved worksheet grid row height and col width calculation taking care of rich text formatted cells.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4207 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2015-07-09 21:35:50 +00:00
parent 4e44185df4
commit a5e3c273a6
2 changed files with 140 additions and 20 deletions

View File

@ -891,16 +891,26 @@ end;
procedure TsCustomWorksheetGrid.AutoAdjustColumn(ACol: Integer);
var
gRow: Integer; // row in grid coordinates
r: Cardinal;
lastRow: Cardinal;
w, maxw: Integer;
txt: String;
cell: PCell;
begin
if Worksheet = nil then
exit;
lastRow := Worksheet.GetLastOccupiedRowIndex;
maxw := -1;
for cell in Worksheet.Cells.GetColEnumerator(GetWorkSheetCol(ACol)) do
begin
gRow := GetGridRow(cell^.Row);
txt := GetCellText(ACol, gRow);
if txt = '' then
Continue;
w := RichTextWidth(Canvas, Workbook, Rect(0, 0, MaxInt, MaxInt), txt,
Worksheet.ReadCellFontIndex(cell), cell^.RichTextParams,
Worksheet.ReadTextRotation(cell), false);
if w > maxw then maxw := w;
end;
{
for r := 0 to lastRow do
begin
gRow := GetGridRow(r);
@ -909,6 +919,7 @@ begin
w := Canvas.TextWidth(txt);
if (txt <> '') and (w > maxw) then maxw := w;
end;
}
if maxw > -1 then
maxw := maxw + 2*constCellPadding
else
@ -2635,11 +2646,11 @@ var
lCell: PCell;
s: String;
wrapped: Boolean;
txtR: TRect;
cellR: TRect;
flags: Cardinal;
r1,c1,r2,c2: Cardinal;
fmt: PsCellFormat;
fntIndex: Integer;
txtRot: TsTextRotation;
begin
Result := 0;
if ShowHeaders and ((ACol = 0) or (ARow = 0)) then
@ -2650,6 +2661,7 @@ begin
lCell := Worksheet.FindCell(ARow-FHeaderCount, ACol-FHeaderCount);
if lCell <> nil then
begin
cellR := CellRect(ACol, ARow);
if Worksheet.IsMerged(lCell) then
begin
Worksheet.FindMergedRange(lCell, r1, c1, r2, c2);
@ -2658,12 +2670,38 @@ begin
// determination since only the height of the first row of the block
// (containing the merge base cell) would change which is very confusing.
exit;
cellR := CellRect(c1+FHeaderCount, ARow);
cellR.Right := CellRect(c2+FHeaderCount, ARow).Right;
end;
InflateRect(cellR, -constCellPadding, -constCellPadding);
s := GetCellText(ACol, ARow);
if s = '' then
exit;
DoPrepareCanvas(ACol, ARow, []);
fmt := Workbook.GetPointerToCellFormat(lCell^.FormatIndex);
if (uffFont in fmt^.UsedFormattingFields) then
fntIndex := fmt^.FontIndex else fntIndex := DEFAULT_FONTINDEX;
if (uffTextRotation in fmt^.UsedFormattingFields) then
txtRot := fmt^.TextRotation else txtRot := trHorizontal;
wrapped := (uffWordWrap in fmt^.UsedFormattingFields);
case txtRot of
trHorizontal: ;
rt90DegreeClockwiseRotation,
rt90DegreeCounterClockwiseRotation:
cellR := Rect(0, 0, MaxInt, MaxInt);
rtStacked:
cellR := Rect(0, 0, MaxInt, MaxInt);
end;
Result := RichTextHeight(Canvas, Workbook, cellR, s, fntIndex,
lCell^.RichTextParams, txtRot, wrapped)
+ 2 * constCellPadding;
(*
wrapped := (uffWordWrap in fmt^.UsedFormattingFields)
or (fmt^.TextRotation = rtStacked);
// *** multi-line text ***
@ -2700,6 +2738,7 @@ begin
then
Result := Canvas.TextWidth(s) + 2*constCellPadding;
end;
*)
end;
end;
@ -2760,8 +2799,7 @@ end;
function TsCustomWorksheetGrid.GetCellText(ACol, ARow: Integer): String;
var
cell: PCell;
r, c, i: Integer;
s: String;
r, c: Integer;
begin
Result := '';

View File

@ -21,9 +21,18 @@ procedure DrawRichText(ACanvas: TCanvas; AWorkbook: TsWorkbook; const ARect: TRe
AWordwrap: Boolean; AHorAlignment: TsHorAlignment; AVertAlignment: TsVertAlignment;
ARotation: TsTextRotation);
function RichTextWidth(ACanvas: TCanvas; AWorkbook: TsWorkbook; AMaxRect: TRect;
const AText: String; AFontIndex: Integer; ARichTextParams: TsRichTextParams;
ATextRotation: TsTextRotation; AWordWrap: Boolean): Integer;
function RichTextHeight(ACanvas: TCanvas; AWorkbook: TsWorkbook; AMaxRect: TRect;
const AText: String; AFontIndex: Integer; ARichTextParams: TsRichTextParams;
ATextRotation: TsTextRotation; AWordWrap: Boolean): Integer;
{
function RichTextWidth(ACanvas: TCanvas; AWorkbook: TsWorkbook; const AText: String;
AFontIndex: Integer; ARichTextParams: TsRichTextParams): Integer;
}
implementation
@ -163,10 +172,11 @@ begin
end;
end;
procedure DrawRichText(ACanvas: TCanvas; AWorkbook: TsWorkbook; const ARect: TRect;
const AText: String; AFontIndex: Integer; ARichTextParams: TsRichTextParams;
AWordwrap: Boolean; AHorAlignment: TsHorAlignment; AVertAlignment: TsVertAlignment;
ARotation: TsTextRotation);
procedure InternalDrawRichText(ACanvas: TCanvas; AWorkbook: TsWorkbook;
const ARect: TRect; const AText: String; AFontIndex: Integer;
ARichTextParams: TsRichTextParams; AWordwrap: Boolean;
AHorAlignment: TsHorAlignment; AVertAlignment: TsVertAlignment;
ARotation: TsTextRotation; var Width,Height: Integer; AMeasureOnly: Boolean);
type
TLineInfo = record
pStart, pEnd: PChar;
@ -183,7 +193,7 @@ var
iRtp: Integer;
lineInfo: TLineInfo;
lineInfos: Array of TLineInfo = nil;
totalHeight, stackPeriod: Integer;
totalHeight, linelen, stackPeriod: Integer;
procedure InitFont(P: PChar; out rtState: TRtState;
PendingRtpIndex: Integer; out AHeight: Integer);
@ -426,6 +436,7 @@ begin
else
iRtp := -1;
totalHeight := 0;
linelen := 0;
Convert_sFont_to_Font(AWorkbook.GetFont(AFontIndex), ACanvas.Font);
if ARotation = rtStacked then
@ -444,6 +455,7 @@ begin
NextRtpIndex := iRtp;
ScanLine(pEnd, NumSpaces, NextRtpIndex, Width, Height);
totalHeight := totalHeight + Height;
linelen := Max(linelen, Width);
iRtp := NextRtpIndex;
p := pEnd;
case p^ of
@ -457,6 +469,14 @@ begin
end;
until p^ = #0;
Width := linelen;
if ARotation = rtStacked then
Height := Length(lineinfos) * stackperiod
else
Height := totalHeight;
if AMeasureOnly then
exit;
// Draw lines
// 1/ get starting point of line
case ARotation of
@ -540,12 +560,59 @@ begin
end;
end;
function RichTextWidth(ACanvas: TCanvas; AWorkbook: TsWorkbook; const AText: String;
AFontIndex: Integer; ARichTextParams: TsRichTextParams): Integer;
procedure DrawRichText(ACanvas: TCanvas; AWorkbook: TsWorkbook; const ARect: TRect;
const AText: String; AFontIndex: Integer; ARichTextParams: TsRichTextParams;
AWordwrap: Boolean; AHorAlignment: TsHorAlignment; AVertAlignment: TsVertAlignment;
ARotation: TsTextRotation);
var
w,h: Integer;
begin
InternalDrawRichText(ACanvas, AWorkbook, ARect, AText, AFontIndex,
ARichTextParams, AWordWrap, AHorAlignment, AVertAlignment, ARotation,
w, h, false);
end;
function RichTextWidth(ACanvas: TCanvas; AWorkbook: TsWorkbook; AMaxRect: TRect;
const AText: String; AFontIndex: Integer; ARichTextParams: TsRichTextParams;
ATextRotation: TsTextRotation; AWordWrap: Boolean): Integer;
var
h, w: Integer;
begin
InternalDrawRichText(ACanvas, AWorkbook, AMaxRect, AText, AFontIndex,
ARichTextParams, AWordWrap, haLeft, vaTop, ATextRotation,
w, h, true);
case ATextRotation of
trHorizontal, rtStacked:
Result := w;
rt90DegreeClockwiseRotation, rt90DegreeCounterClockwiseRotation:
Result := h;
end;
end;
function RichTextHeight(ACanvas: TCanvas; AWorkbook: TsWorkbook; AMaxRect: TRect;
const AText: String; AFontIndex: Integer; ARichTextParams: TsRichTextParams;
ATextRotation: TsTextRotation; AWordWrap: Boolean): Integer;
var
h, w: Integer;
begin
InternalDrawRichText(ACanvas, AWorkbook, AMaxRect, AText, AFontIndex,
ARichTextParams, AWordWrap, haLeft, vaTop, ATextRotation,
w, h, true);
case ATextRotation of
trHorizontal, rtStacked:
Result := h;
rt90DegreeClockwiseRotation, rt90DegreeCounterClockwiseRotation:
Result := w;
end;
end;
(*
function GetRichTextExtent(ACanvas: TCanvas; AWorkbook: TsWorkbook;
const AText: String; AFontIndex: Integer; ARichTextParams: TsRichTextParams;
ATextRotation: TsTextRotation): TSize;
var
s: String;
p: Integer;
w, n: Integer;
len, height: Integer;
rtp, next_rtp: TsRichTextParam;
fnt, fnt0: TsFont;
begin
@ -557,9 +624,24 @@ begin
if Length(ARichTextParams) = 0 then
begin
Result := ACanvas.TextWidth(AText);
if fnt0.Position <> fpNormal then
Result := Round(Result * SUBSCRIPT_SUPERSCRIPT_FACTOR);
Result := ACanvas.TextExtent(AText);
if ATextRotation = trHorizontal then
exit;
len := Result.cx;
height := Result.cy;
case ATextRotation of
rt90DegreeClockwiseRotation,
rt90DegreeCounterClockwiseRotation:
begin
Result.CX := height;
Result.CY := len;
end;
rtStacked:
begin
Result.CX := ACanvas.TextWidth('M');
Restul.CY := UTF8Length(AText) * height;
end;
end;
exit;
end;
@ -602,5 +684,5 @@ begin
inc(p);
end;
end;
*)
end.