fpspreadsheet: Fix merged cell borders in TWorksheet being drawn as defined by the merge base.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4467 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2016-01-25 13:57:19 +00:00
parent cf95cc412c
commit 4f691313d7

View File

@ -1710,14 +1710,15 @@ begin
end; end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
Draws the borders of all cells. Calls DrawCellBorder for each individual cell. Draws the borders of all cells. Calls DrawCellBorders for each individual cell.
-------------------------------------------------------------------------------} -------------------------------------------------------------------------------}
procedure TsCustomWorksheetGrid.DrawCellBorders; procedure TsCustomWorksheetGrid.DrawCellBorders;
var var
cell: PCell; cell, base: PCell;
gc, gr: Integer; gc, gr: Integer;
sr1, sc1, sr2, sc2: Cardinal; sr1, sc1, sr2, sc2: Cardinal;
rect: TRect; rect: TRect;
cellHasBorder: Boolean;
begin begin
if Worksheet = nil then if Worksheet = nil then
exit; exit;
@ -1730,20 +1731,14 @@ begin
if sc1 = UNASSIGNED_ROW_COL_INDEX then sc1 := 0; if sc1 = UNASSIGNED_ROW_COL_INDEX then sc1 := 0;
for cell in Worksheet.Cells.GetRangeEnumerator(sr1, sc1, sr2, sc2) do for cell in Worksheet.Cells.GetRangeEnumerator(sr1, sc1, sr2, sc2) do
if (uffBorder in Worksheet.ReadUsedFormatting(cell)) then
begin
gc := GetGridCol(cell^.Col);
gr := GetGridRow(cell^.Row);
rect := CellRect(gc, gr);
DrawCellBorders(gc, gr, rect, cell);
end;
{
gr := TopLeft.Y;
gc := TopLeft.X;
for cell in Worksheet.Cells do
begin begin
if (uffBorder in Worksheet.ReadUsedFormatting(cell)) then if Worksheet.IsMerged(cell) then
begin
base := Worksheet.FindMergeBase(cell);
cellHasBorder := uffBorder in Worksheet.ReadUsedFormatting(base);
end else
cellHasBorder := uffBorder in Worksheet.ReadUsedFormatting(cell);
if cellHasBorder then
begin begin
gc := GetGridCol(cell^.Col); gc := GetGridCol(cell^.Col);
gr := GetGridRow(cell^.Row); gr := GetGridRow(cell^.Row);
@ -1751,7 +1746,6 @@ begin
DrawCellBorders(gc, gr, rect, cell); DrawCellBorders(gc, gr, rect, cell);
end; end;
end; end;
}
end; end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
@ -1892,23 +1886,12 @@ var
fmt: PsCellFormat; fmt: PsCellFormat;
begin begin
if Assigned(Worksheet) then begin if Assigned(Worksheet) then begin
if IsRightToLeft then // Left border
begin if GetBorderStyle(ACol, ARow, -1, 0, ACell, bs) then
// Left border DrawBorderLine(ARect.Left-ord(not IsRightToLeft), ARect, drawVert, bs);
if GetBorderStyle(ACol, ARow, +1, 0, ACell, bs) then // Right border
DrawBorderLine(ARect.Left-1, ARect, drawVert, bs); if GetBorderStyle(ACol, ARow, +1, 0, ACell, bs) then
// Right border DrawBorderLine(ARect.Right-ord(not IsRightToLeft), ARect, drawVert, bs);
if GetBorderStyle(ACol, ARow, -1, 0, ACell, bs) then
DrawBorderLine(ARect.Right-1, ARect, drawVert, bs);
end else
begin
// Left border
if GetBorderStyle(ACol, ARow, -1, 0, ACell, bs) then
DrawBorderLine(ARect.Left-1, ARect, drawVert, bs);
// Right border
if GetBorderStyle(ACol, ARow, +1, 0, ACell, bs) then
DrawBorderLine(ARect.Right-1, ARect, drawVert, bs);
end;
// Top border // Top border
if GetBorderstyle(ACol, ARow, 0, -1, ACell, bs) then if GetBorderstyle(ACol, ARow, 0, -1, ACell, bs) then
DrawBorderLine(ARect.Top-1, ARect, drawHor, bs); DrawBorderLine(ARect.Top-1, ARect, drawHor, bs);
@ -2717,6 +2700,8 @@ end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
Returns the cell borders which are drawn around a given cell. Returns the cell borders which are drawn around a given cell.
If the cell is part of a merged block then the borders of the merge base
are applied to the location of the cell (no inner borders for merged cells).
@param ACol Grid column index of the cell @param ACol Grid column index of the cell
@param ARow Grid row index of the cell @param ARow Grid row index of the cell
@ -2725,12 +2710,33 @@ end;
function TsCustomWorksheetGrid.GetCellBorder(ACol, ARow: Integer): TsCellBorders; function TsCustomWorksheetGrid.GetCellBorder(ACol, ARow: Integer): TsCellBorders;
var var
cell: PCell; cell: PCell;
base: PCell;
r, c, r1, c1, r2, c2: Cardinal;
begin begin
Result := []; Result := [];
if Assigned(Worksheet) then if Assigned(Worksheet) then
begin begin
cell := Worksheet.FindCell(GetWorksheetRow(ARow), GetWorksheetCol(ACol)); r := GetWorksheetRow(ARow);
Result := Worksheet.ReadCellBorders(cell); c := GetWorksheetCol(ACol);
cell := Worksheet.FindCell(r, c);
if Worksheet.IsMerged(cell) then
begin
Worksheet.FindMergedRange(cell, r1, c1, r2, c2);
base := Worksheet.FindCell(r1, c1);
Result := Worksheet.ReadCellBorders(base);
if (cbNorth in Result) and (r > r1) then Exclude(Result, cbNorth);
if (cbSouth in Result) and (r < r2) then Exclude(Result, cbSouth);
if IsRightToLeft then
begin
if (cbEast in Result) and (c > c1) then Exclude(Result, cbEast);
if (cbWest in Result) and (c < c2) then Exclude(Result, cbWest);
end else
begin
if (cbWest in Result) and (c > c1) then Exclude(Result, cbWest);
if (cbEast in Result) and (c < c2) then Exclude(Result, cbEast);
end;
end else
Result := Worksheet.ReadCellBorders(cell);
end; end;
end; end;
@ -2771,6 +2777,9 @@ end;
by the parameter ABorder of a cell. The style is defined by line style and by the parameter ABorder of a cell. The style is defined by line style and
line color. line color.
If the cell belongs to a merged block then the border styles of the merge
base are returned.
@param ACol Grid column index of the cell @param ACol Grid column index of the cell
@param ARow Grid row index of the cell @param ARow Grid row index of the cell
@param ABorder Identifier of the border at which the line will be drawn @param ABorder Identifier of the border at which the line will be drawn
@ -2782,11 +2791,14 @@ function TsCustomWorksheetGrid.GetCellBorderStyle(ACol, ARow: Integer;
ABorder: TsCellBorder): TsCellBorderStyle; ABorder: TsCellBorder): TsCellBorderStyle;
var var
cell: PCell; cell: PCell;
base: PCell;
begin begin
Result := DEFAULT_BORDERSTYLES[ABorder]; Result := DEFAULT_BORDERSTYLES[ABorder];
if Assigned(Worksheet) then if Assigned(Worksheet) then
begin begin
cell := Worksheet.FindCell(GetWorksheetRow(ARow), GetWorksheetCol(ACol)); cell := Worksheet.FindCell(GetWorksheetRow(ARow), GetWorksheetCol(ACol));
if Worksheet.IsMerged(cell) then
cell := Worksheet.FindMergeBase(cell);
Result := Worksheet.ReadCellBorderStyle(cell, ABorder); Result := Worksheet.ReadCellBorderStyle(cell, ABorder);
end; end;
end; end;
@ -3183,12 +3195,12 @@ end;
function TsCustomWorksheetGrid.GetBorderStyle(ACol, ARow, ADeltaCol, ADeltaRow: Integer; function TsCustomWorksheetGrid.GetBorderStyle(ACol, ARow, ADeltaCol, ADeltaRow: Integer;
ACell: PCell; out ABorderStyle: TsCellBorderStyle): Boolean; ACell: PCell; out ABorderStyle: TsCellBorderStyle): Boolean;
var var
//cell,
neighborcell: PCell; neighborcell: PCell;
border, neighborborder: TsCellBorder; border, neighborborder: TsCellBorder;
// r, c: Cardinal; r, c: Cardinal;
begin begin
Result := true; Result := true;
if (ADeltaCol = -1) and (ADeltaRow = 0) then if (ADeltaCol = -1) and (ADeltaRow = 0) then
begin begin
border := cbWest; border := cbWest;
@ -3211,13 +3223,15 @@ begin
end else end else
raise Exception.Create('[TsCustomWorksheetGrid] Incorrect col/row for GetBorderStyle.'); raise Exception.Create('[TsCustomWorksheetGrid] Incorrect col/row for GetBorderStyle.');
// r := GetWorksheetRow(ARow); if IsRightToLeft then
// c := GetWorksheetCol(ACol); ADeltaCol := -ADeltaCol;
//cell := Worksheet.FindCell(r, c);
if (ARow - FHeaderCount + ADeltaRow < 0) or (ACol - FHeaderCount + ADeltaCol < 0) then r := GetWorksheetRow(ARow);
c := GetWorksheetCol(ACol);
if (r + ADeltaRow < 0) or (c + ADeltaCol < 0) then
neighborcell := nil neighborcell := nil
else else
neighborcell := Worksheet.FindCell(ARow - FHeaderCount + ADeltaRow, ACol - FHeaderCount + ADeltaCol); neighborcell := Worksheet.FindCell(r + ADeltaRow, c + ADeltaCol);
// Only cell has border, but neighbor has not // Only cell has border, but neighbor has not
if HasBorder(ACell, border) and not HasBorder(neighborCell, neighborBorder) then if HasBorder(ACell, border) and not HasBorder(neighborCell, neighborBorder) then
@ -3225,7 +3239,7 @@ begin
if Worksheet.InSameMergedRange(ACell, neighborcell) then if Worksheet.InSameMergedRange(ACell, neighborcell) then
result := false result := false
else else
ABorderStyle := Worksheet.ReadCellBorderStyle(ACell, border) ABorderStyle := GetCellBorderStyle(ACol, ARow, border);
end end
else else
// Only neighbor has border, cell has not // Only neighbor has border, cell has not
@ -3234,7 +3248,7 @@ begin
if Worksheet.InSameMergedRange(ACell, neighborcell) then if Worksheet.InSameMergedRange(ACell, neighborcell) then
result := false result := false
else else
ABorderStyle := Worksheet.ReadCellBorderStyle(neighborcell, neighborborder); ABorderStyle := GetCellBorderStyle(ACol+ADeltaCol, ARow+ADeltaRow, neighborborder);
end end
else else
// Both cells have shared border -> use top or left border // Both cells have shared border -> use top or left border
@ -3244,9 +3258,9 @@ begin
result := false result := false
else else
if (border in [cbNorth, cbWest]) then if (border in [cbNorth, cbWest]) then
ABorderStyle := Worksheet.ReadCellBorderStyle(neighborcell, neighborborder) ABorderStyle := GetCellBorderStyle(ACol+ADeltaCol, ARow+ADeltaRow, neighborborder)
else else
ABorderStyle := Worksheet.ReadCellBorderStyle(ACell, border); ABorderStyle := GetCellBorderStyle(ACol, ARow, border);
end else end else
Result := false; Result := false;
end; end;
@ -3327,16 +3341,34 @@ begin
end; end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
Returns true if the cell has the given border. Returns true if the cell has the given border. In case of merged cell the
borders of the merge base are checked. Inner merged cells don't have a border.
@param ACell Pointer to cell considered @param ACell Pointer to cell considered
@param ABorder Indicator for border to be checked for visibility @param ABorder Indicator for border to be checked for visibility
-------------------------------------------------------------------------------} -------------------------------------------------------------------------------}
function TsCustomWorksheetGrid.HasBorder(ACell: PCell; ABorder: TsCellBorder): Boolean; function TsCustomWorksheetGrid.HasBorder(ACell: PCell; ABorder: TsCellBorder): Boolean;
var
base: PCell;
r1, c1, r2, c2: Cardinal;
begin begin
if Worksheet = nil then if Worksheet = nil then
result := false result := false
else else
if Worksheet.IsMerged(ACell) then
begin
Worksheet.FindMergedRange(ACell, r1, c1, r2, c2);
base := Worksheet.FindCell(r1, c1);
Result := ABorder in Worksheet.ReadCellBorders(base);
case ABorder of
cbNorth : if ACell^.Row > r1 then Result := false;
cbSouth : if ACell^.Row < r2 then Result := false;
cbEast : if (IsRightToLeft and (ACell^.Col > c1)) or
(not IsRightToLeft and (ACell^.Col < c2)) then Result := false;
cbWest : if (IsRightToLeft and (ACell^.Col < c2)) or
(not IsRightToLeft and (ACell^.Col > c1)) then Result := false;
end;
end else
Result := ABorder in Worksheet.ReadCellBorders(ACell); Result := ABorder in Worksheet.ReadCellBorders(ACell);
end; end;