You've already forked lazarus-ccr
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:
@ -891,16 +891,26 @@ end;
|
|||||||
procedure TsCustomWorksheetGrid.AutoAdjustColumn(ACol: Integer);
|
procedure TsCustomWorksheetGrid.AutoAdjustColumn(ACol: Integer);
|
||||||
var
|
var
|
||||||
gRow: Integer; // row in grid coordinates
|
gRow: Integer; // row in grid coordinates
|
||||||
r: Cardinal;
|
|
||||||
lastRow: Cardinal;
|
|
||||||
w, maxw: Integer;
|
w, maxw: Integer;
|
||||||
txt: String;
|
txt: String;
|
||||||
|
cell: PCell;
|
||||||
begin
|
begin
|
||||||
if Worksheet = nil then
|
if Worksheet = nil then
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
lastRow := Worksheet.GetLastOccupiedRowIndex;
|
|
||||||
maxw := -1;
|
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
|
for r := 0 to lastRow do
|
||||||
begin
|
begin
|
||||||
gRow := GetGridRow(r);
|
gRow := GetGridRow(r);
|
||||||
@ -909,6 +919,7 @@ begin
|
|||||||
w := Canvas.TextWidth(txt);
|
w := Canvas.TextWidth(txt);
|
||||||
if (txt <> '') and (w > maxw) then maxw := w;
|
if (txt <> '') and (w > maxw) then maxw := w;
|
||||||
end;
|
end;
|
||||||
|
}
|
||||||
if maxw > -1 then
|
if maxw > -1 then
|
||||||
maxw := maxw + 2*constCellPadding
|
maxw := maxw + 2*constCellPadding
|
||||||
else
|
else
|
||||||
@ -2635,11 +2646,11 @@ var
|
|||||||
lCell: PCell;
|
lCell: PCell;
|
||||||
s: String;
|
s: String;
|
||||||
wrapped: Boolean;
|
wrapped: Boolean;
|
||||||
txtR: TRect;
|
|
||||||
cellR: TRect;
|
cellR: TRect;
|
||||||
flags: Cardinal;
|
|
||||||
r1,c1,r2,c2: Cardinal;
|
r1,c1,r2,c2: Cardinal;
|
||||||
fmt: PsCellFormat;
|
fmt: PsCellFormat;
|
||||||
|
fntIndex: Integer;
|
||||||
|
txtRot: TsTextRotation;
|
||||||
begin
|
begin
|
||||||
Result := 0;
|
Result := 0;
|
||||||
if ShowHeaders and ((ACol = 0) or (ARow = 0)) then
|
if ShowHeaders and ((ACol = 0) or (ARow = 0)) then
|
||||||
@ -2650,6 +2661,7 @@ begin
|
|||||||
lCell := Worksheet.FindCell(ARow-FHeaderCount, ACol-FHeaderCount);
|
lCell := Worksheet.FindCell(ARow-FHeaderCount, ACol-FHeaderCount);
|
||||||
if lCell <> nil then
|
if lCell <> nil then
|
||||||
begin
|
begin
|
||||||
|
cellR := CellRect(ACol, ARow);
|
||||||
if Worksheet.IsMerged(lCell) then
|
if Worksheet.IsMerged(lCell) then
|
||||||
begin
|
begin
|
||||||
Worksheet.FindMergedRange(lCell, r1, c1, r2, c2);
|
Worksheet.FindMergedRange(lCell, r1, c1, r2, c2);
|
||||||
@ -2658,12 +2670,38 @@ begin
|
|||||||
// determination since only the height of the first row of the block
|
// determination since only the height of the first row of the block
|
||||||
// (containing the merge base cell) would change which is very confusing.
|
// (containing the merge base cell) would change which is very confusing.
|
||||||
exit;
|
exit;
|
||||||
|
cellR := CellRect(c1+FHeaderCount, ARow);
|
||||||
|
cellR.Right := CellRect(c2+FHeaderCount, ARow).Right;
|
||||||
end;
|
end;
|
||||||
|
InflateRect(cellR, -constCellPadding, -constCellPadding);
|
||||||
|
|
||||||
s := GetCellText(ACol, ARow);
|
s := GetCellText(ACol, ARow);
|
||||||
if s = '' then
|
if s = '' then
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
DoPrepareCanvas(ACol, ARow, []);
|
DoPrepareCanvas(ACol, ARow, []);
|
||||||
|
|
||||||
fmt := Workbook.GetPointerToCellFormat(lCell^.FormatIndex);
|
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)
|
wrapped := (uffWordWrap in fmt^.UsedFormattingFields)
|
||||||
or (fmt^.TextRotation = rtStacked);
|
or (fmt^.TextRotation = rtStacked);
|
||||||
// *** multi-line text ***
|
// *** multi-line text ***
|
||||||
@ -2700,6 +2738,7 @@ begin
|
|||||||
then
|
then
|
||||||
Result := Canvas.TextWidth(s) + 2*constCellPadding;
|
Result := Canvas.TextWidth(s) + 2*constCellPadding;
|
||||||
end;
|
end;
|
||||||
|
*)
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -2760,8 +2799,7 @@ end;
|
|||||||
function TsCustomWorksheetGrid.GetCellText(ACol, ARow: Integer): String;
|
function TsCustomWorksheetGrid.GetCellText(ACol, ARow: Integer): String;
|
||||||
var
|
var
|
||||||
cell: PCell;
|
cell: PCell;
|
||||||
r, c, i: Integer;
|
r, c: Integer;
|
||||||
s: String;
|
|
||||||
begin
|
begin
|
||||||
Result := '';
|
Result := '';
|
||||||
|
|
||||||
|
@ -21,9 +21,18 @@ procedure DrawRichText(ACanvas: TCanvas; AWorkbook: TsWorkbook; const ARect: TRe
|
|||||||
AWordwrap: Boolean; AHorAlignment: TsHorAlignment; AVertAlignment: TsVertAlignment;
|
AWordwrap: Boolean; AHorAlignment: TsHorAlignment; AVertAlignment: TsVertAlignment;
|
||||||
ARotation: TsTextRotation);
|
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;
|
function RichTextWidth(ACanvas: TCanvas; AWorkbook: TsWorkbook; const AText: String;
|
||||||
AFontIndex: Integer; ARichTextParams: TsRichTextParams): Integer;
|
AFontIndex: Integer; ARichTextParams: TsRichTextParams): Integer;
|
||||||
|
}
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
@ -163,10 +172,11 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure DrawRichText(ACanvas: TCanvas; AWorkbook: TsWorkbook; const ARect: TRect;
|
procedure InternalDrawRichText(ACanvas: TCanvas; AWorkbook: TsWorkbook;
|
||||||
const AText: String; AFontIndex: Integer; ARichTextParams: TsRichTextParams;
|
const ARect: TRect; const AText: String; AFontIndex: Integer;
|
||||||
AWordwrap: Boolean; AHorAlignment: TsHorAlignment; AVertAlignment: TsVertAlignment;
|
ARichTextParams: TsRichTextParams; AWordwrap: Boolean;
|
||||||
ARotation: TsTextRotation);
|
AHorAlignment: TsHorAlignment; AVertAlignment: TsVertAlignment;
|
||||||
|
ARotation: TsTextRotation; var Width,Height: Integer; AMeasureOnly: Boolean);
|
||||||
type
|
type
|
||||||
TLineInfo = record
|
TLineInfo = record
|
||||||
pStart, pEnd: PChar;
|
pStart, pEnd: PChar;
|
||||||
@ -183,7 +193,7 @@ var
|
|||||||
iRtp: Integer;
|
iRtp: Integer;
|
||||||
lineInfo: TLineInfo;
|
lineInfo: TLineInfo;
|
||||||
lineInfos: Array of TLineInfo = nil;
|
lineInfos: Array of TLineInfo = nil;
|
||||||
totalHeight, stackPeriod: Integer;
|
totalHeight, linelen, stackPeriod: Integer;
|
||||||
|
|
||||||
procedure InitFont(P: PChar; out rtState: TRtState;
|
procedure InitFont(P: PChar; out rtState: TRtState;
|
||||||
PendingRtpIndex: Integer; out AHeight: Integer);
|
PendingRtpIndex: Integer; out AHeight: Integer);
|
||||||
@ -426,6 +436,7 @@ begin
|
|||||||
else
|
else
|
||||||
iRtp := -1;
|
iRtp := -1;
|
||||||
totalHeight := 0;
|
totalHeight := 0;
|
||||||
|
linelen := 0;
|
||||||
|
|
||||||
Convert_sFont_to_Font(AWorkbook.GetFont(AFontIndex), ACanvas.Font);
|
Convert_sFont_to_Font(AWorkbook.GetFont(AFontIndex), ACanvas.Font);
|
||||||
if ARotation = rtStacked then
|
if ARotation = rtStacked then
|
||||||
@ -444,6 +455,7 @@ begin
|
|||||||
NextRtpIndex := iRtp;
|
NextRtpIndex := iRtp;
|
||||||
ScanLine(pEnd, NumSpaces, NextRtpIndex, Width, Height);
|
ScanLine(pEnd, NumSpaces, NextRtpIndex, Width, Height);
|
||||||
totalHeight := totalHeight + Height;
|
totalHeight := totalHeight + Height;
|
||||||
|
linelen := Max(linelen, Width);
|
||||||
iRtp := NextRtpIndex;
|
iRtp := NextRtpIndex;
|
||||||
p := pEnd;
|
p := pEnd;
|
||||||
case p^ of
|
case p^ of
|
||||||
@ -457,6 +469,14 @@ begin
|
|||||||
end;
|
end;
|
||||||
until p^ = #0;
|
until p^ = #0;
|
||||||
|
|
||||||
|
Width := linelen;
|
||||||
|
if ARotation = rtStacked then
|
||||||
|
Height := Length(lineinfos) * stackperiod
|
||||||
|
else
|
||||||
|
Height := totalHeight;
|
||||||
|
if AMeasureOnly then
|
||||||
|
exit;
|
||||||
|
|
||||||
// Draw lines
|
// Draw lines
|
||||||
// 1/ get starting point of line
|
// 1/ get starting point of line
|
||||||
case ARotation of
|
case ARotation of
|
||||||
@ -540,12 +560,59 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function RichTextWidth(ACanvas: TCanvas; AWorkbook: TsWorkbook; const AText: String;
|
procedure DrawRichText(ACanvas: TCanvas; AWorkbook: TsWorkbook; const ARect: TRect;
|
||||||
AFontIndex: Integer; ARichTextParams: TsRichTextParams): Integer;
|
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
|
var
|
||||||
s: String;
|
s: String;
|
||||||
p: Integer;
|
p: Integer;
|
||||||
w, n: Integer;
|
len, height: Integer;
|
||||||
rtp, next_rtp: TsRichTextParam;
|
rtp, next_rtp: TsRichTextParam;
|
||||||
fnt, fnt0: TsFont;
|
fnt, fnt0: TsFont;
|
||||||
begin
|
begin
|
||||||
@ -557,9 +624,24 @@ begin
|
|||||||
|
|
||||||
if Length(ARichTextParams) = 0 then
|
if Length(ARichTextParams) = 0 then
|
||||||
begin
|
begin
|
||||||
Result := ACanvas.TextWidth(AText);
|
Result := ACanvas.TextExtent(AText);
|
||||||
if fnt0.Position <> fpNormal then
|
if ATextRotation = trHorizontal then
|
||||||
Result := Round(Result * SUBSCRIPT_SUPERSCRIPT_FACTOR);
|
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;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -602,5 +684,5 @@ begin
|
|||||||
inc(p);
|
inc(p);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
*)
|
||||||
end.
|
end.
|
||||||
|
Reference in New Issue
Block a user