fpspreadsheet: Fix grid's Col/RowCount not being reduced if a sheet with less cols/rows than the current sheet is selected (http://forum.lazarus.freepascal.org/index.php/topic,35182.msg232477.html#msg232477). Introduce top/left cell indexes in worksheet to make sure that active cell remains at the row/col stored in the worksheet when changing worksheets.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@5560 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2016-12-23 17:05:14 +00:00
parent d6e3ba3a4f
commit e22ceab9c9
3 changed files with 126 additions and 36 deletions

View File

@ -84,6 +84,8 @@ type
FRows, FCols: TIndexedAVLTree; // This lists contain only rows or cols with styles different from default FRows, FCols: TIndexedAVLTree; // This lists contain only rows or cols with styles different from default
FActiveCellRow: Cardinal; FActiveCellRow: Cardinal;
FActiveCellCol: Cardinal; FActiveCellCol: Cardinal;
FTopRow: Cardinal;
FLeftCol: Cardinal;
FSelection: TsCellRangeArray; FSelection: TsCellRangeArray;
FLeftPaneWidth: Integer; FLeftPaneWidth: Integer;
FTopPaneHeight: Integer; FTopPaneHeight: Integer;
@ -477,6 +479,8 @@ type
function GetSelectionRangeIndexOfActiveCell: Integer; function GetSelectionRangeIndexOfActiveCell: Integer;
procedure SetSelection(const ASelection: TsCellRangeArray); procedure SetSelection(const ASelection: TsCellRangeArray);
procedure ScrollTo(ANewTopRow, ANewLeftCol: Cardinal);
// Comments // Comments
function FindComment(ACell: PCell): PsComment; function FindComment(ACell: PCell): PsComment;
function HasComment(ACell: PCell): Boolean; function HasComment(ACell: PCell): Boolean;
@ -582,6 +586,10 @@ type
property ActiveCellCol: Cardinal read FActiveCellCol; property ActiveCellCol: Cardinal read FActiveCellCol;
{@@ Row index of the selected cell of this worksheet } {@@ Row index of the selected cell of this worksheet }
property ActiveCellRow: Cardinal read FActiveCellRow; property ActiveCellRow: Cardinal read FActiveCellRow;
{@@ Index of the left-most visible column in the grid - used by WorksheetGrid}
property LeftCol: Cardinal read FLeftCol;
{@@ Index of the top-most visible row in the grid - used by WorksheetGrid }
property TopRow: Cardinal read FTopRow;
{@@ Number of frozen columns which do not scroll } {@@ Number of frozen columns which do not scroll }
property LeftPaneWidth: Integer read FLeftPaneWidth write FLeftPaneWidth; property LeftPaneWidth: Integer read FLeftPaneWidth write FLeftPaneWidth;
{@@ Number of frozen rows which do not scroll } {@@ Number of frozen rows which do not scroll }
@ -4225,6 +4233,17 @@ begin
FSelection[i] := ASelection[i]; FSelection[i] := ASelection[i];
end; end;
{@@ ----------------------------------------------------------------------------
Uses the passed parameters a TopRow and LeftCol. These are used by the
TsWorksheetGrid to scroll the visible grid such that the corresponding cell
is at the top/left.
-------------------------------------------------------------------------------}
procedure TsWorksheet.ScrollTo(ANewTopRow, ANewLeftCol: Cardinal);
begin
FTopRow := ANewTopRow;
FLeftCol := ANewLeftCol;
end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
Helper method to update internal caching variables Helper method to update internal caching variables
-------------------------------------------------------------------------------} -------------------------------------------------------------------------------}

View File

@ -1071,7 +1071,8 @@ begin
AWorkbook.DisableNotifications; AWorkbook.DisableNotifications;
if AWorkbook <> FWorkbook then if AWorkbook <> FWorkbook then
InternalCreateNewWorkbook(AWorkbook); InternalCreateNewWorkbook(AWorkbook) else
SetOptions(FOptions);
WorkbookOpenedHandler(self); WorkbookOpenedHandler(self);
if AWorksheetIndex = -1 then if AWorksheetIndex = -1 then
@ -1672,10 +1673,10 @@ begin
FWorksheet.OnZoom := @WorksheetZoomHandler; FWorksheet.OnZoom := @WorksheetZoomHandler;
NotifyListeners([lniWorksheet]); NotifyListeners([lniWorksheet]);
FWorksheet := AWorksheet; // !!!!! FWorksheet := AWorksheet; // !!!!!
if FWorksheet.ActiveCellRow = Cardinal(-1) then if FWorksheet.ActiveCellRow = UNASSIGNED_ROW_COL_INDEX then
r := FWorksheet.TopPaneHeight else r := FWorksheet.TopPaneHeight else
r := FWorksheet.ActiveCellRow; r := FWorksheet.ActiveCellRow;
if FWorksheet.ActiveCellCol = Cardinal(-1) then if FWorksheet.ActiveCellCol = UNASSIGNED_ROW_COL_INDEX then
c := FWorksheet.LeftPaneWidth else c := FWorksheet.LeftPaneWidth else
c := FWorksheet.ActiveCellCol; c := FWorksheet.ActiveCellCol;
SelectCell(r, c); SelectCell(r, c);

View File

@ -15,6 +15,8 @@ unit fpspreadsheetgrid;
{$mode objfpc}{$H+} {$mode objfpc}{$H+}
{$I ..\fps.inc} {$I ..\fps.inc}
{.$DEFINE GRID_DEBUG}
{ To do: { To do:
- When Lazarus 1.4 comes out remove the workaround for the RGB2HLS bug in - When Lazarus 1.4 comes out remove the workaround for the RGB2HLS bug in
FindNearestPaletteIndex. FindNearestPaletteIndex.
@ -247,6 +249,7 @@ type
procedure SetEditText(ACol, ARow: Longint; const AValue: string); override; procedure SetEditText(ACol, ARow: Longint; const AValue: string); override;
procedure Setup; procedure Setup;
procedure Sort(AColSorting: Boolean; AIndex, AIndxFrom, AIndxTo:Integer); override; procedure Sort(AColSorting: Boolean; AIndex, AIndxFrom, AIndxTo:Integer); override;
procedure TopLeftChanged; override;
function TrimToCell(ACell: PCell): String; function TrimToCell(ACell: PCell): String;
{@@ Automatically recalculate formulas whenever a cell value changes. } {@@ Automatically recalculate formulas whenever a cell value changes. }
@ -4081,45 +4084,100 @@ end;
procedure TsCustomWorksheetGrid.ListenerNotification(AChangedItems: TsNotificationItems; procedure TsCustomWorksheetGrid.ListenerNotification(AChangedItems: TsNotificationItems;
AData: Pointer = nil); AData: Pointer = nil);
var var
actgrow, actgcol: Integer;
grow, gcol: Integer; grow, gcol: Integer;
srow, scol: Cardinal; srow, scol: Cardinal;
cell: PCell; cell: PCell;
lRow: PRow; lRow: PRow;
{$IFDEF GRID_DEBUG}
procedure DebugNotification(ACaption: String);
var
s: String;
begin
WriteLn(ACaption);
s := '';
if (lniWorksheet in AChangedItems) then s := s + 'lniWorksheet, ';
if (lniCell in AChangedItems) then s := s + 'lniCell, ';
if (lniSelection in AChangedItems) then s := s + 'lniSelection, ';
if (lniAbortSelection in AChangedItems) then s := s + 'lniAbortSelection, ';
if (lniRow in AChangedItems) then s := s + 'lniRow, ';
if (lniCol in AChangedItems) then s := s + 'lniCol, ';
if (lniWorksheetZoom in AChangedItems) then s := s + 'lniWorksheetZoom, ';
if s <> '' then SetLength(s, Length(s) - 2);
WriteLn(' AChangedItems = [', s, ']');
WriteLn(' ActiveCellRow: ', Worksheet.ActiveCellRow, ' ActiveCellCol: ', Worksheet.ActiveCellCol);
WriteLn(' TopRow: ', Worksheet.TopRow, ' LeftCol: ', Worksheet.LeftCol);
WriteLn;
end;
{$ENDIF}
begin begin
Unused(AData); Unused(AData);
{$IFDEF GRID_DEBUG}
if Worksheet <> nil then
DebugNotification('BEFORE ListenerNotification WorksheetGrid "' + Worksheet.Name + '":');
{$ENDIF}
// Nothing to do for "workbook changed" because this is always combined with // Nothing to do for "workbook changed" because this is always combined with
// "worksheet changed". // "worksheet changed".
// Worksheet changed // Worksheet changed
if (lniWorksheet in AChangedItems) then if (lniWorksheet in AChangedItems) then
begin begin
if (Worksheet <> nil) then BeginUpdate; // avoid flicker...
begin try
inc(FLockSetup); if (Worksheet <> nil) then
ShowHeaders := (soShowHeaders in Worksheet.Options); begin
ShowGridLines := (soShowGridLines in Worksheet.Options); // remember indexes of top/left and active cell
if (soHasFrozenPanes in Worksheet.Options) then begin grow := GetGridRow(Worksheet.TopRow);
FrozenCols := Worksheet.LeftPaneWidth; gcol := GetGridCol(Worksheet.LeftCol);
FrozenRows := Worksheet.TopPaneHeight; actgrow := GetGridRow(Worksheet.ActiveCellRow);
end else begin actgcol := GetGridCol(Worksheet.ActiveCellCol);
FrozenCols := 0; AutoExpandToRow(grow, aeNavigation);
FrozenRows := 0; AutoExpandToCol(gcol, aeNavigation);
if (grow <> Row) or (gcol <> Col) then
MoveExtend(false, gcol, grow);
inc(FLockSetup);
// Setup grid headers and col/row count
ShowHeaders := (soShowHeaders in Worksheet.Options);
ShowGridLines := (soShowGridLines in Worksheet.Options);
if (soHasFrozenPanes in Worksheet.Options) then begin
FrozenCols := Worksheet.LeftPaneWidth;
FrozenRows := Worksheet.TopPaneHeight;
end else begin
FrozenCols := 0;
FrozenRows := 0;
end;
case Worksheet.BiDiMode of
bdDefault: ParentBiDiMode := true;
bdLTR : begin
ParentBiDiMode := false;
BiDiMode := bdLeftToRight;
end;
bdRTL : begin
ParentBiDiMode := false;
BiDiMode := bdRightToLeft;
end;
end;
dec(FLockSetup);
end; end;
case Worksheet.BiDiMode of Setup;
bdDefault: ParentBiDiMode := true; // scroll the grid for top/left to be as stored in the sheet
bdLTR : begin if (grow <> TopRow) or (gcol <> LeftCol) then
ParentBiDiMode := false; begin
BiDiMode := bdLeftToRight; TopRow := gRow;
end; LeftCol := gCol;
bdRTL : begin
ParentBiDiMode := false;
BiDiMode := bdRightToLeft;
end;
end; end;
dec(FLockSetup); // Select active cell
AutoExpandToRow(actgrow, aeNavigation);
AutoExpandToCol(actgcol, aeNavigation);
if (actgrow <> Row) or (actgcol <> Col) then
MoveExtend(false, actgcol, actgrow);
finally
EndUpdate;
end; end;
Setup;
end; end;
// Cell value or format changed // Cell value or format changed
@ -4179,6 +4237,12 @@ begin
// Worksheet zoom // Worksheet zoom
if (lniWorksheetZoom in AChangedItems) and (Worksheet <> nil) then if (lniWorksheetZoom in AChangedItems) and (Worksheet <> nil) then
AdaptToZoomFactor; // Reads value directly from Worksheet AdaptToZoomFactor; // Reads value directly from Worksheet
{$IFDEF GRID_DEBUG}
if Worksheet <> nil then
DebugNotification('AFTER ListenerNotification WorksheetGrid "' + Worksheet.Name + '":');
{$ENDIF}
end; end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
@ -4498,6 +4562,8 @@ end;
initial column widths and row heights. initial column widths and row heights.
-------------------------------------------------------------------------------} -------------------------------------------------------------------------------}
procedure TsCustomWorksheetGrid.Setup; procedure TsCustomWorksheetGrid.Setup;
var
defColCount, defRowCount: Integer;
begin begin
if csLoading in ComponentState then if csLoading in ComponentState then
exit; exit;
@ -4520,15 +4586,10 @@ begin
end; end;
end else end else
if Worksheet <> nil then begin if Worksheet <> nil then begin
if FHeaderCount = 0 then defColCount := DEFAULT_COL_COUNT;
begin defRowCount := DEFAULT_ROW_COUNT;
ColCount := Max(GetGridCol(Worksheet.GetLastColIndex), ColCount-1); ColCount := Max(GetGridCol(Worksheet.GetLastColIndex)+1, defColCount) + FHeaderCount;
RowCount := Max(GetGridRow(Worksheet.GetLastRowIndex), RowCount-1); RowCount := max(GetGridRow(Worksheet.GetLastRowIndex)+1, defRowCount) + FHeaderCount;
end else
begin
ColCount := Max(GetGridCol(Worksheet.GetLastColIndex) + 1, ColCount);
RowCount := Max(GetGridRow(Worksheet.GetLastRowIndex) + 1, RowCount);
end;
FixedCols := FFrozenCols + FHeaderCount; FixedCols := FFrozenCols + FHeaderCount;
FixedRows := FFrozenRows + FHeaderCount; FixedRows := FFrozenRows + FHeaderCount;
if ShowHeaders then begin if ShowHeaders then begin
@ -4539,7 +4600,7 @@ begin
end; end;
UpdateColWidths; UpdateColWidths;
UpdateRowHeights; UpdateRowHeights;
Invalidate; //Invalidate; // wp: really needed? Might cause flicker
end; end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
@ -4681,6 +4742,15 @@ begin
); );
end; end;
{@@ ----------------------------------------------------------------------------
Store the value of the TopLeft cell in the worksheet
-------------------------------------------------------------------------------}
procedure TsCustomWorksheetGrid.TopLeftChanged;
begin
inherited;
Worksheet.ScrollTo(GetWorkSheetRow(TopRow), GetWorksheetCol(LeftCol));
end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
Modifies the text that is show for cells which are too narrow to hold the Modifies the text that is show for cells which are too narrow to hold the
entire text. The method follows the behavior of Excel and Open/LibreOffice: entire text. The method follows the behavior of Excel and Open/LibreOffice: