FastReport_2022_VCL/LibD28x64/frxTableObjectClipboard.pas
2024-01-01 16:13:08 +01:00

324 lines
9.5 KiB
ObjectPascal

{******************************************}
{ }
{ FastReport VCL }
{ Table Object Clipboard Editors }
{ }
{ Copyright (c) 1998-2021 }
{ by Fast Reports Inc. }
{ }
{******************************************}
unit frxTableObjectClipboard;
interface
{$I frx.inc}
uses
SysUtils, Types, Classes, Variants, Controls,
frxClass;
type
TfrxRowColumnCopyPasteEditor = class(TfrxInPlaceEditor)
public
procedure CopyContent(CopyFrom: TfrxComponent; var EventParams: TfrxInteractiveEventsParams; Buffer: TStream; CopyAs: TfrxCopyPasteType = cptDefault); override;
procedure PasteContent(PasteTo: TfrxComponent; var EventParams: TfrxInteractiveEventsParams; Buffer: TStream; PasteAs: TfrxCopyPasteType = cptDefault); override;
function IsPasteAvailable(PasteTo: TfrxComponent; var EventParams: TfrxInteractiveEventsParams; PasteAs: TfrxCopyPasteType = cptDefault): Boolean; override;
end;
TfrxTableCellCopyPasteEditor = class(TfrxInPlaceEditor)
public
procedure CopyContent(CopyFrom: TfrxComponent; var EventParams: TfrxInteractiveEventsParams; Buffer: TStream; CopyAs: TfrxCopyPasteType = cptDefault); override;
procedure PasteContent(PasteTo: TfrxComponent; var EventParams: TfrxInteractiveEventsParams; Buffer: TStream; PasteAs: TfrxCopyPasteType = cptDefault); override;
function IsPasteAvailable(PasteTo: TfrxComponent; var EventParams: TfrxInteractiveEventsParams; PasteAs: TfrxCopyPasteType = cptDefault): Boolean; override;
end;
implementation
uses Math, frxTableObject,
frxInPlaceEditors, Clipbrd, frxXML, frxXMLSerializer,
frxUnicodeUtils, frxInPlaceClipboards
{$IFDEF Delphi10}
, WideStrings
{$ENDIF}
{$IFDEF FPC}
,Lazhelper
{$ENDIF} ;
const
ClipboardPrefix: String = '#FR6 clipboard#table#';
{ TfrxRowColumnCopyPasteEditor }
procedure TfrxRowColumnCopyPasteEditor.CopyContent(CopyFrom: TfrxComponent;
var EventParams: TfrxInteractiveEventsParams; Buffer: TStream; CopyAs: TfrxCopyPasteType);
var
aTable: TfrxTableObject;
i: Integer;
aBase: TfrxTableRowColumnBase;
ss: TStringStream;
aRoot: TfrxXMLItem;
wr: TfrxXMLWriter;
Writer: TfrxXMLSerializer;
aText: String;
begin
if not(CopyFrom is TfrxTableRowColumnBase) then
Exit;
aText := ClipboardPrefix;
aTable := TfrxTableObject.Create(nil);
try
aBase := TfrxTableRowColumnBase(CopyFrom);
if CopyFrom is TfrxTableRow then
begin
aTable.RowCount := 1;
aTable.ColumnCount := aBase.ParentTable.ColumnCount;
for i := 0 to aTable.ColumnCount - 1 do
aTable.Cells[i, 0].AssignAll(aBase.ParentTable.Cells[i, aBase.Index]);
end
else
begin
aTable.ColumnCount := 1;
aTable.RowCount := aBase.ParentTable.RowCount;
for i := 0 to aTable.RowCount - 1 do
aTable.Cells[0, i].AssignAll(aBase.ParentTable.Cells[aBase.Index, i]);
end;
ss := TStringStream.Create('');
Writer := TfrxXMLSerializer.Create(nil);
aRoot := TfrxXMLItem.Create;
wr := TfrxXMLWriter.Create(ss);
try
Writer.Owner := aBase.Report;
Writer.WriteRootComponent(aTable, True, aRoot);
wr.AutoIndent := False;
wr.WriteRootItem(aRoot);
aText := aText + ss.DataString;
finally
aRoot.Free;
wr.Free;
ss.Free;
Writer.Free;
end;
finally
aTable.Free;
end;
Clipboard.AsText := aText;
end;
function TfrxRowColumnCopyPasteEditor.IsPasteAvailable(PasteTo: TfrxComponent;
var EventParams: TfrxInteractiveEventsParams; PasteAs: TfrxCopyPasteType): Boolean;
function FastCheck: Boolean;
var
I, MaxLen: Integer;
sText: String;
begin
MaxLen := Length(ClipboardPrefix);
sText := Clipboard.AsText;
Result := False;
if MaxLen > Length(sText) then
Exit;
Result := True;
for i := 1 to MaxLen do
if sText[i] <> ClipboardPrefix[i] then
begin
Result := False;
break;
end;
end;
begin
Result := FastCheck;
end;
procedure TfrxRowColumnCopyPasteEditor.PasteContent(PasteTo: TfrxComponent;
var EventParams: TfrxInteractiveEventsParams; Buffer: TStream; PasteAs: TfrxCopyPasteType);
var
aTable: TfrxTableObject;
i, maxCount: Integer;
aBase: TfrxTableRowColumnBase;
aRow: TfrxTableRow;
aColumn: TfrxTableColumn;
ss: TStringStream;
aRoot: TfrxXMLItem;
wr: TfrxXMLReader;
Writer: TfrxXMLSerializer;
aText: String;
begin
aText := '';
aTable := TfrxTableObject.Create(nil);
try
if PasteTo is TfrxTableRowColumnBase then
begin
aBase := TfrxTableRowColumnBase(PasteTo);
ss := TStringStream.Create(Clipboard.AsText);
Writer := TfrxXMLSerializer.Create(nil);
aRoot := TfrxXMLItem.Create;
wr := TfrxXMLReader.Create(ss);
try
wr.ReadRootItem(aRoot);
Writer.Owner := aTable;
Writer.ReadRootComponent(aTable, aRoot);
finally
aRoot.Free;
wr.Free;
ss.Free;
Writer.Free;
end;
aTable.UpdateBounds;
i := aBase.Index;
if aBase is TfrxTableRow then
begin
maxCount := Min(aBase.ParentTable.ColumnCount, aTable.ColumnCount);
aRow := TfrxTableRow.Create(aBase.ParentTable);
aBase.ParentTable.InsertRow(i, aRow);
aRow.ParentTable.UpdateBounds;
for i := 0 to maxCount - 1 do
aBase.ParentTable.Cells[i, aRow.Index].AssignAll(aTable.Cells[i, 0]);
end
else
begin
maxCount := Min(aBase.ParentTable.RowCount, aTable.RowCount);
aColumn := TfrxTableColumn.Create(aBase.ParentTable);
aBase.ParentTable.InsertColumn(i, aColumn);
aColumn.ParentTable.UpdateBounds;
for i := 0 to maxCount - 1 do
aBase.ParentTable.Cells[aColumn.Index, i].AssignAll
(aTable.Cells[0, i]);
end;
end;
finally
aTable.Free;
end;
end;
{ TfrxTableCellCopyPasteEditor }
procedure TfrxTableCellCopyPasteEditor.CopyContent(CopyFrom: TfrxComponent;
var EventParams: TfrxInteractiveEventsParams; Buffer: TStream; CopyAs: TfrxCopyPasteType);
var
s: String;
table, NextTable: TfrxTableObject;
x, y, i: Integer;
bFirst: Boolean;
SkipList: TList;
function BuildString(sLines: TWideStrings): WideString;
var
i: Integer;
begin
Result := '';
for i := 0 to sLines.Count - 1 do
begin
Result := Result + sLines[i];
if i < sLines.Count - 1 then
Result := Result + ' ';
end;
end;
begin
if CopyFrom is TfrxTableCell then
begin
if Assigned(EventParams.SelectionList) and (EventParams.SelectionList.Count > 1) then
begin
SkipList := TList.Create;
try
for i := 0 to EventParams.SelectionList.Count - 1 do
if TObject(EventParams.SelectionList[i]) is TfrxTableCell then
begin
NextTable := TfrxTableCell(EventParams.SelectionList[i])
.ParentTable;
if SkipList.IndexOf(NextTable) <> -1 then
continue;
SkipList.Add(NextTable);
table := NextTable;
for Y := 0 to table.RowCount - 1 do
begin
bFirst := True;
for X := 0 to table.ColumnCount - 1 do
if table.Cells[X, Y].IsSelected then
begin
if bFirst then
bFirst := False
else
s := s + #9;
s := s + BuildString(table.Cells[X, Y].Lines);
end;
if not bFirst then
s := s + sLineBreak;
end;
end;
Clipboard.AsText := s;
finally
FreeAndNil(SkipList);
end;
end;
end;
end;
function TfrxTableCellCopyPasteEditor.IsPasteAvailable(PasteTo: TfrxComponent;
var EventParams: TfrxInteractiveEventsParams; PasteAs: TfrxCopyPasteType): Boolean;
begin
Result := True;
end;
procedure TfrxTableCellCopyPasteEditor.PasteContent(PasteTo: TfrxComponent;
var EventParams: TfrxInteractiveEventsParams; Buffer: TStream; PasteAs: TfrxCopyPasteType);
var
tCell: TfrxTableCell;
table: TfrxTableObject;
x, y, idx: Integer;
sText: String;
function GetCellText : String;
var
i: Integer;
begin
for i := idx to Length(sText) do
begin
if (sText[i] = #9) or (sText[i] = #$D) then
begin
Result := Copy(sText, idx, i - idx);
idx := i + 1;
if (sText[i] = #$D) then Inc(idx);
Exit;
end;
end;
Result := Copy(sText, idx, Length(sText) - idx);
end;
begin
if PasteTo is TfrxTableCell then
begin
sText := Clipboard.AsText;
tCell := TfrxTableCell(PasteTo);
table := tCell.ParentTable;
idx := 1;
for y := 0 to table.RowCount - 1 do
for x := 0 to table.ColumnCount - 1 do
if table.Cells[x, y].IsSelected then
begin
table.Cells[x, y].DataSet := nil;
table.Cells[x, y].DataField := '';
table.Cells[x, y].Text := GetCellText;
end;
end;
EventParams.Modified := True;
EventParams.Refresh := True;
end;
initialization
frxRegEditorsClasses.Register(TfrxTableRow, [TfrxRowColumnCopyPasteEditor], [[evDesigner]]);
frxRegEditorsClasses.Register(TfrxTableColumn, [TfrxRowColumnCopyPasteEditor], [[evDesigner]]);
frxRegEditorsClasses.Register(TfrxTableCell, [TfrxInPlaceMemoCopyPasteEditor], [[evDesigner, evPreview]]);
finalization
frxUnregisterEditorsClass(TfrxTableRow, TfrxRowColumnCopyPasteEditor);
frxUnregisterEditorsClass(TfrxTableColumn, TfrxRowColumnCopyPasteEditor);
frxUnregisterEditorsClass(TfrxTableCell, TfrxInPlaceMemoCopyPasteEditor);
end.