229 lines
7.7 KiB
ObjectPascal
229 lines
7.7 KiB
ObjectPascal
{******************************************}
|
|
{ }
|
|
{ FastReport VCL }
|
|
{ Cross Object Editors }
|
|
{ }
|
|
{ Copyright (c) 1998-2021 }
|
|
{ by Fast Reports Inc. }
|
|
{ }
|
|
{******************************************}
|
|
|
|
unit frxCrossInPlaceEditor;
|
|
|
|
interface
|
|
|
|
{$I frx.inc}
|
|
|
|
implementation
|
|
|
|
uses
|
|
{$IFDEF FPC}LazHelper{$ELSE}Windows{$ENDIF},
|
|
Types, Classes, SysUtils, Graphics, Controls, StdCtrls, ComCtrls, Forms, Menus,
|
|
Dialogs, frxClass, frxDesgn, frxDsgnIntf, frxUtils,
|
|
frxRes, frxDesgnWorkspace, frxCross
|
|
{$IFDEF Delphi6}
|
|
, Variants
|
|
{$ENDIF}
|
|
{$IFDEF Delphi10}
|
|
, WideStrings
|
|
{$ENDIF};
|
|
|
|
type
|
|
{ Inline editors }
|
|
TfrxHackCustomCrossView = class(TfrxCustomCrossView);
|
|
|
|
TfrxInPlaceCrossEditor = class(TfrxInPlaceEditor)
|
|
private
|
|
FDragActive: Boolean;
|
|
FActiveGrid: TfrxCrossEditGrid;
|
|
public
|
|
constructor Create(aClassRef: TfrxComponentClass; aOwner: TWinControl); override;
|
|
function HasCustomEditor: Boolean; override;
|
|
procedure DrawCustomEditor(aCanvas: TCanvas; aRect: TRect); override;
|
|
function DoCustomDragOver(Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean; var EventParams: TfrxInteractiveEventsParams): Boolean; override;
|
|
function DoCustomDragDrop(Source: TObject; X, Y: Integer; var EventParams: TfrxInteractiveEventsParams): Boolean; override;
|
|
procedure InitializeUI(var EventParams: TfrxInteractiveEventsParams); override;
|
|
procedure FinalizeUI(var EventParams: TfrxInteractiveEventsParams); override;
|
|
end;
|
|
|
|
{ TfrxMemoEditor }
|
|
|
|
|
|
{ TfrxInPlaceCrossEditor }
|
|
|
|
constructor TfrxInPlaceCrossEditor.Create(aClassRef: TfrxComponentClass;
|
|
aOwner: TWinControl);
|
|
begin
|
|
inherited;
|
|
end;
|
|
|
|
function TfrxInPlaceCrossEditor.DoCustomDragDrop(Source: TObject; X,
|
|
Y: Integer; var EventParams: TfrxInteractiveEventsParams): Boolean;
|
|
var
|
|
Node: TTreeNode;
|
|
i, selcount: Integer;
|
|
s: String;
|
|
cross: TfrxHackCustomCrossView;
|
|
begin
|
|
Inherited DoCustomDragDrop(Source, X, Y, EventParams);
|
|
Result := False;
|
|
cross := nil;
|
|
if Component is TfrxCustomCrossView then
|
|
cross := TfrxHackCustomCrossView(Component);
|
|
|
|
if Assigned(cross) then
|
|
with cross do
|
|
begin
|
|
selcount := TTreeView(Source).SelectionCount - 1;
|
|
for i := selcount downto 0 do
|
|
begin
|
|
Node := TTreeView(Source).Selections[i];
|
|
s := '';
|
|
if (Node <> nil) and (Node.Data <> nil) then
|
|
s := Report.GetAlias(TfrxDataSet(Node.Data));
|
|
if s <> '' then
|
|
begin
|
|
Result := True;
|
|
if DataSet = nil then
|
|
DataSet := TfrxDataSet(Node.Data);
|
|
if (FActiveGrid = seRightBottom) or
|
|
((FActiveGrid = seLeftTop) and (selcount - i >= 2)) then
|
|
begin
|
|
CellLevels := CellLevels + 1;
|
|
CellFields.Add(Node.Text);
|
|
end
|
|
else if (FActiveGrid = seRightTop) or
|
|
((FActiveGrid = seLeftTop) and (selcount - i = 1)) then
|
|
begin
|
|
ColumnLevels := ColumnLevels + 1;
|
|
ColumnFields.Add(Node.Text)
|
|
end
|
|
else if (FActiveGrid = seLeftBottom) or
|
|
((FActiveGrid = seLeftTop) and (selcount - i = 0)) then
|
|
begin
|
|
if (FActiveGrid = seLeftTop) then
|
|
begin
|
|
RowFields.Clear;
|
|
ColumnFields.Clear;
|
|
CellFields.Clear;
|
|
RowLevels := 0;
|
|
ColumnLevels := 0;
|
|
CellLevels := 0;
|
|
DataSet := TfrxDataSet(Node.Data);
|
|
end;
|
|
RowLevels := RowLevels + 1;
|
|
RowFields.Add(Node.Text)
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TfrxInPlaceCrossEditor.DoCustomDragOver(Source: TObject; X, Y: Integer;
|
|
State: TDragState; var Accept: Boolean; var EventParams: TfrxInteractiveEventsParams): Boolean;
|
|
var
|
|
cross: TfrxHackCustomCrossView;
|
|
begin
|
|
cross := nil;
|
|
Result := False;
|
|
if Component is TfrxCustomCrossView then
|
|
cross := TfrxHackCustomCrossView(Component);
|
|
with cross do
|
|
if (Source is TTreeView) and Assigned(cross) then
|
|
begin
|
|
FActiveGrid := seLeftTop;
|
|
if (AbsLeft + Width / 2 < X) and (AbsLeft + Width > X) and
|
|
(AbsTop + Height / 2 < Y) and (cross.AbsTop + cross.Height > Y) then
|
|
FActiveGrid := seRightBottom
|
|
else if (AbsLeft + Width / 2 < X) and (AbsLeft + Width > X) and
|
|
(AbsTop < Y) and (AbsTop + Height / 2 > Y) then
|
|
FActiveGrid := seRightTop
|
|
else if (AbsLeft < X) and (AbsLeft + Width / 2 > X) and
|
|
(AbsTop + Height / 2 < Y) and (AbsTop + Height > Y) then
|
|
FActiveGrid := seLeftBottom;
|
|
Accept := True;
|
|
Result := True;
|
|
end;
|
|
if Accept then
|
|
FDragActive := True;
|
|
end;
|
|
|
|
procedure TfrxInPlaceCrossEditor.DrawCustomEditor(aCanvas: TCanvas;
|
|
aRect: TRect);
|
|
var
|
|
TempRect: TRect;
|
|
s: String;
|
|
AbsLeft, AbsTop, Width, Height: Extended;
|
|
begin
|
|
AbsLeft := TfrxHackCustomCrossView(FComponent).AbsLeft;
|
|
AbsTop := TfrxHackCustomCrossView(FComponent).AbsTop;
|
|
Width := TfrxHackCustomCrossView(FComponent).Width;
|
|
Height := TfrxHackCustomCrossView(FComponent).Height;
|
|
{ TODO : Move strings to editor DrawCustomEditor }
|
|
if FDragActive and Assigned(aCanvas) then
|
|
begin
|
|
aCanvas.Brush.Color := clWhite;
|
|
aCanvas.FillRect(Rect(TfrxHackCustomCrossView(FComponent).FX, TfrxHackCustomCrossView(FComponent).FY, TfrxHackCustomCrossView(FComponent).FX1, TfrxHackCustomCrossView(FComponent).FY1));
|
|
aCanvas.MoveTo(Round((AbsLeft + Width / 2) * FScale), Round(AbsTop * FScale));
|
|
aCanvas.LineTo(Round((AbsLeft + Width / 2) * FScale), Round((AbsTop + Height) * FScale));
|
|
aCanvas.MoveTo(Round(AbsLeft * FScale), Round((AbsTop + Height / 2) * FScale));
|
|
aCanvas.LineTo(Round((AbsLeft + Width) * FScale), Round((AbsTop + Height / 2) * FScale));
|
|
aCanvas.Brush.Color := $00E8E3E3;
|
|
aCanvas.Brush.Style := bsSolid;
|
|
TempRect := Rect(Round(AbsLeft * FScale) + 1, Round(AbsTop * FScale) + 1, Round((AbsLeft + Width / 2) * FScale), Round((AbsTop + Height / 2) * FScale));
|
|
s := 'New table';
|
|
case FActiveGrid of
|
|
seRightTop:
|
|
begin
|
|
TempRect := Rect(Round((AbsLeft + Width/ 2) * FScale) + 1, Round(AbsTop * FScale) + 1, Round((AbsLeft + Width) * FScale) - 1, Round((AbsTop + Height / 2) * FScale) - 1);
|
|
s := 'Drop column';
|
|
end;
|
|
seLeftBottom:
|
|
begin
|
|
TempRect := Rect(Round(AbsLeft * FScale) + 1, Round((AbsTop + Height / 2) * FScale) + 1, Round((AbsLeft + Width / 2) * FScale), Round((AbsTop + Height) * FScale) - 1);
|
|
s := 'Drop row';
|
|
end;
|
|
seRightBottom:
|
|
begin
|
|
TempRect := Rect(Round((AbsLeft + Width/ 2) * FScale) + 1, Round((AbsTop + Height / 2) * FScale) + 1, Round((AbsLeft + Width) * FScale) - 1, Round((AbsTop + Height) * FScale) - 1);
|
|
s := 'Drop cell';
|
|
end;
|
|
end;
|
|
aCanvas.FillRect(TempRect);
|
|
//TempRect.Top := TempRect.Top + Round(Height * FScale / 10);
|
|
aCanvas.Font.Size := 12;
|
|
aCanvas.Font.Color := clBlack;
|
|
aCanvas.Pen.Color := clBlack;
|
|
aCanvas.Font.Height := Round(aCanvas.Font.Height * FScale);
|
|
aCanvas.Font.Style := [fsBold];
|
|
aCanvas.TextRect(TempRect, 4, 4, s);
|
|
end;
|
|
|
|
end;
|
|
|
|
procedure TfrxInPlaceCrossEditor.FinalizeUI(
|
|
var EventParams: TfrxInteractiveEventsParams);
|
|
begin
|
|
inherited;
|
|
FDragActive := False;
|
|
end;
|
|
|
|
function TfrxInPlaceCrossEditor.HasCustomEditor: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
procedure TfrxInPlaceCrossEditor.InitializeUI(
|
|
var EventParams: TfrxInteractiveEventsParams);
|
|
begin
|
|
inherited;
|
|
FDragActive := False;
|
|
end;
|
|
|
|
initialization
|
|
frxRegEditorsClasses.Register(TfrxDBCrossView, [TfrxInPlaceCrossEditor], []);
|
|
|
|
finalization
|
|
frxUnregisterEditorsClass(TfrxDBCrossView, TfrxInPlaceCrossEditor);
|
|
end.
|