📄 flatgrids.pas
字号:
end;
procedure TFlatSparseList.Put(Index: Integer; Item: Pointer);
begin
if Index < 0 then TList.Error(SListIndexError, Index);
FList[Index] := Item;
FCount := FList.HighBound + 1
end;
{ TFlatSparseLists }
constructor TFlatSparseLists.Create(Quantum: TSPAQuantum);
begin
inherited Create;
FList := TFlatSparseList.Create(Quantum)
end;
destructor TFlatSparseLists.Destroy;
begin
if FList <> nil then begin
Clear;
FList.Destroy
end
end;
procedure TFlatSparseLists.ReadData(Reader: TReader);
var
i: Integer;
begin
with Reader do begin
i := Integer(ReadInteger);
while i > 0 do begin
InsertObject(Integer(ReadInteger), ReadString, nil);
Dec(i)
end
end
end;
procedure TFlatSparseLists.WriteData(Writer: TWriter);
var
itemCount: Integer;
function CountItem(TheIndex: Integer; TheItem: Pointer): Integer; far;
begin
Inc(itemCount);
Result := 0
end;
function StoreItem(TheIndex: Integer; TheItem: Pointer): Integer; far;
begin
with Writer do
begin
WriteInteger(TheIndex); { Item index }
WriteString(PStrItem(TheItem)^.FString);
end;
Result := 0
end;
begin
with Writer do
begin
itemCount := 0;
FList.ForAll(@CountItem);
WriteInteger(itemCount);
FList.ForAll(@StoreItem);
end
end;
procedure TFlatSparseLists.DefineProperties(Filer: TFiler);
begin
Filer.DefineProperty('List', ReadData, WriteData, True);
end;
function TFlatSparseLists.Get(Index: Integer): String;
var
p: PStrItem;
begin
p := PStrItem(FList[Index]);
if p = nil then Result := '' else Result := p^.FString
end;
function TFlatSparseLists.GetCount: Integer;
begin
Result := FList.Count
end;
function TFlatSparseLists.GetObject(Index: Integer): TObject;
var
p: PStrItem;
begin
p := PStrItem(FList[Index]);
if p = nil then Result := nil else Result := p^.FObject
end;
procedure TFlatSparseLists.Put(Index: Integer; const S: String);
var
p: PStrItem;
obj: TObject;
begin
p := PStrItem(FList[Index]);
if p = nil then obj := nil else obj := p^.FObject;
if (S = '') and (obj = nil) then { Nothing left to store }
FList[Index] := nil
else
FList[Index] := NewStrItem(S, obj);
if p <> nil then DisposeStrItem(p);
Changed
end;
procedure TFlatSparseLists.PutObject(Index: Integer; AObject: TObject);
var
p: PStrItem;
begin
p := PStrItem(FList[Index]);
if p <> nil then
p^.FObject := AObject
else if AObject <> nil then
FList[Index] := NewStrItem('',AObject);
Changed
end;
procedure TFlatSparseLists.Changed;
begin
if Assigned(FOnChange) then FOnChange(Self)
end;
procedure TFlatSparseLists.Delete(Index: Integer);
var
p: PStrItem;
begin
p := PStrItem(FList[Index]);
if p <> nil then DisposeStrItem(p);
FList.Delete(Index);
Changed
end;
procedure TFlatSparseLists.Exchange(Index1, Index2: Integer);
begin
FList.Exchange(Index1, Index2);
end;
procedure TFlatSparseLists.Insert(Index: Integer; const S: String);
begin
FList.Insert(Index, NewStrItem(S, nil));
Changed
end;
procedure TFlatSparseLists.Clear;
function ClearItem(TheIndex: Integer; TheItem: Pointer): Integer; far;
begin
DisposeStrItem(PStrItem(TheItem)); { Item guaranteed non-nil }
Result := 0
end;
begin
FList.ForAll(@ClearItem);
FList.Clear;
Changed
end;
{ TStringGridStrings }
{ AIndex < 0 is a column (for column -AIndex - 1)
AIndex > 0 is a row (for row AIndex - 1)
AIndex = 0 denotes an empty row or column }
constructor TFlatGridStrings.Create(AGrid: TFlatStringGrid; AIndex: Longint);
begin
inherited Create;
FGrid := AGrid;
FIndex := AIndex;
end;
procedure TFlatGridStrings.Assign(Source: TPersistent);
var
I, Max: Integer;
begin
if Source is TStrings then
begin
BeginUpdate;
Max := TStrings(Source).Count - 1;
if Max >= Count then Max := Count - 1;
try
for I := 0 to Max do
begin
Put(I, TStrings(Source).Strings[I]);
PutObject(I, TStrings(Source).Objects[I]);
end;
finally
EndUpdate;
end;
Exit;
end;
inherited Assign(Source);
end;
procedure TFlatGridStrings.CalcXY(Index: Integer; var X, Y: Integer);
begin
if FIndex = 0 then
begin
X := -1; Y := -1;
end else if FIndex > 0 then
begin
X := Index;
Y := FIndex - 1;
end else
begin
X := -FIndex - 1;
Y := Index;
end;
end;
{ Changes the meaning of Add to mean copy to the first empty string }
function TFlatGridStrings.Add(const S: string): Integer;
var
I: Integer;
begin
for I := 0 to Count - 1 do
if Strings[I] = '' then
begin
if S = '' then
Strings[I] := ' '
else
Strings[I] := S;
Result := I;
Exit;
end;
Result := -1;
end;
procedure TFlatGridStrings.Clear;
var
SSList: TFlatSparseLists;
I: Integer;
function BlankStr(TheIndex: Integer; TheItem: Pointer): Integer; far;
begin
Objects[TheIndex] := nil;
Strings[TheIndex] := '';
Result := 0;
end;
begin
if FIndex > 0 then
begin
SSList := TFlatSparseLists(TFlatSparseList(FGrid.FData)[FIndex - 1]);
if SSList <> nil then SSList.List.ForAll(@BlankStr);
end
else if FIndex < 0 then
for I := Count - 1 downto 0 do
begin
Objects[I] := nil;
Strings[I] := '';
end;
end;
procedure InvalidOp(const id: string);
begin
raise EInvalidGridOperation.Create(id);
end;
procedure TFlatGridStrings.Delete(Index: Integer);
begin
InvalidOp(sInvalidStringGridOp);
end;
function TFlatGridStrings.Get(Index: Integer): string;
var
X, Y: Integer;
begin
CalcXY(Index, X, Y);
if X < 0 then Result := '' else Result := FGrid.Cells[X, Y];
end;
function TFlatGridStrings.GetCount: Integer;
begin
{ Count of a row is the column count, and vice versa }
if FIndex = 0 then Result := 0
else if FIndex > 0 then Result := Integer(FGrid.ColCount)
else Result := Integer(FGrid.RowCount);
end;
function TFlatGridStrings.GetObject(Index: Integer): TObject;
var
X, Y: Integer;
begin
CalcXY(Index, X, Y);
if X < 0 then Result := nil else Result := FGrid.Objects[X, Y];
end;
procedure TFlatGridStrings.Insert(Index: Integer; const S: string);
begin
InvalidOp(sInvalidStringGridOp);
end;
procedure TFlatGridStrings.Put(Index: Integer; const S: string);
var
X, Y: Integer;
begin
CalcXY(Index, X, Y);
FGrid.Cells[X, Y] := S;
end;
procedure TFlatGridStrings.PutObject(Index: Integer; AObject: TObject);
var
X, Y: Integer;
begin
CalcXY(Index, X, Y);
FGrid.Objects[X, Y] := AObject;
end;
procedure TFlatGridStrings.SetUpdateState(Updating: Boolean);
begin
FGrid.SetUpdateState(Updating);
end;
{ TStringGrid }
constructor TFlatStringGrid.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
Initialize;
end;
destructor TFlatStringGrid.Destroy;
function FreeItem(TheIndex: Integer; TheItem: Pointer): Integer; far;
begin
TObject(TheItem).Free;
Result := 0;
end;
begin
if FRows <> nil then
begin
TFlatSparseList(FRows).ForAll(@FreeItem);
TFlatSparseList(FRows).Free;
end;
if FCols <> nil then
begin
TFlatSparseList(FCols).ForAll(@FreeItem);
TFlatSparseList(FCols).Free;
end;
if FData <> nil then
begin
TFlatSparseList(FData).ForAll(@FreeItem);
TFlatSparseList(FData).Free;
end;
inherited Destroy;
end;
procedure TFlatStringGrid.ColumnMoved(FromIndex, ToIndex: Longint);
function MoveColData(Index: Integer; ARow: TFlatSparseLists): Integer; far;
begin
ARow.Move(FromIndex, ToIndex);
Result := 0;
end;
begin
TFlatSparseList(FData).ForAll(@MoveColData);
Invalidate;
inherited ColumnMoved(FromIndex, ToIndex);
end;
procedure TFlatStringGrid.RowMoved(FromIndex, ToIndex: Longint);
begin
TFlatSparseList(FData).Move(FromIndex, ToIndex);
Invalidate;
inherited RowMoved(FromIndex, ToIndex);
end;
function TFlatStringGrid.GetEditText(ACol, ARow: Longint): string;
begin
Result := Cells[ACol, ARow];
if Assigned(OnGetEditText) then OnGetEditText(Self, ACol, ARow, Result);
end;
procedure TFlatStringGrid.SetEditText(ACol, ARow: Longint; const Value: string);
begin
DisableEditUpdate;
try
if Value <> Cells[ACol, ARow] then Cells[ACol, ARow] := Value;
finally
EnableEditUpdate;
end;
inherited SetEditText(ACol, ARow, Value);
end;
procedure TFlatStringGrid.DrawCell(ACol, ARow: Longint; ARect: TRect;
AState: TGridDrawState);
begin
if DefaultDrawing then
Canvas.TextRect(ARect, ARect.Left+2, ARect.Top+2, Cells[ACol, ARow]);
inherited DrawCell(ACol, ARow, ARect, AState);
end;
procedure TFlatStringGrid.DisableEditUpdate;
begin
Inc(FEditUpdate);
end;
procedure TFlatStringGrid.EnableEditUpdate;
begin
Dec(FEditUpdate);
end;
procedure TFlatStringGrid.Initialize;
var
quantum: TSPAQuantum;
begin
if FCols = nil then
begin
if ColCount > 512 then quantum := SPALarge else quantum := SPASmall;
FCols := TFlatSparseList.Create(quantum);
end;
if RowCount > 256 then quantum := SPALarge else quantum := SPASmall;
if FRows = nil then FRows := TFlatSparseList.Create(quantum);
if FData = nil then FData := TFlatSparseList.Create(quantum);
end;
procedure TFlatStringGrid.SetUpdateState(Updating: Boolean);
begin
FUpdating := Updating;
if not Updating and FNeedsUpdating then
begin
InvalidateGrid;
FNeedsUpdating := False;
end;
end;
procedure TFlatStringGrid.Update(ACol, ARow: Integer);
begin
if not FUpdating then InvalidateCell(ACol, ARow)
else FNeedsUpdating := True;
if (ACol = Col) and (ARow = Row) and (FEditUpdate = 0) then InvalidateEditor;
end;
function TFlatStringGrid.EnsureColRow(Index: Integer; IsCol: Boolean): TFlatGridStrings;
var
RCIndex: Integer;
PList: ^TFlatSparseList;
begin
if IsCol then PList := FCols else PList := FRows;
Result := TFlatGridStrings(PList^[Index]);
if Result = nil then
begin
if IsCol then RCIndex := -Index - 1 else RCIndex := Index + 1;
Result := TFlatGridStrings.Create(Self, RCIndex);
PList^[Index] := Result;
end;
end;
function TFlatStringGrid.EnsureDataRow(ARow: Integer): Pointer;
var
quantum: TSPAQuantum;
begin
Result := TFlatSparseLists(TFlatSparseList(FData)[ARow]);
if Result = nil then
begin
if ColCount > 512 then quantum := SPALarge else quantum := SPASmall;
Result := TFlatSparseLists.Create(quantum);
TFlatSparseList(FData)[ARow] := Result;
end;
end;
function TFlatStringGrid.GetCells(ACol, ARow: Integer): string;
var
ssl: TFlatSparseLists;
begin
ssl := TFlatSparseLists(TFlatSparseList(FData)[ARow]);
if ssl = nil then Result := '' else Result := ssl[ACol];
end;
function TFlatStringGrid.GetCols(Index: Integer): TStrings;
begin
Result := EnsureColRow(Index, True);
end;
function TFlatStringGrid.GetObjects(ACol, ARow: Integer): TObject;
var
ssl: TFlatSparseLists;
begin
ssl := TFlatSparseLists(TFlatSparseList(FData)[ARow]);
if ssl = nil then Result := nil else Result := ssl.Objects[ACol];
end;
function TFlatStringGrid.GetRows(Index: Integer): TStrings;
begin
Result := EnsureColRow(Index, False);
end;
procedure TFlatStringGrid.SetCells(ACol, ARow: Integer; const Value: string);
begin
TFlatGridStrings(EnsureDataRow(ARow))[ACol] := Value;
EnsureColRow(ACol, True);
EnsureColRow(ARow, False);
Update(ACol, ARow);
end;
procedure TFlatStringGrid.SetCols(Index: Integer; Value: TStrings);
begin
EnsureColRow(Index, True).Assign(Value);
end;
procedure TFlatStringGrid.SetObjects(ACol, ARow: Integer; Value: TObject);
begin
TFlatGridStrings(EnsureDataRow(ARow)).Objects[ACol] := Value;
EnsureColRow(ACol, True);
EnsureColRow(ARow, False);
Update(ACol, ARow);
end;
procedure TFlatStringGrid.SetRows(Index: Integer; Value: TStrings);
begin
EnsureColRow(Index, False).Assign(Value);
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -