FastReport_FMX_2.8.12/LibD28/FMX.frxDesgnCtrls.pas
2024-07-06 22:41:12 +02:00

1299 lines
31 KiB
ObjectPascal

{******************************************}
{ }
{ FastReport v4.0 }
{ Designer controls }
{ }
{ Copyright (c) 1998-2008 }
{ by Alexander Tzyganenko, }
{ Fast Reports Inc. }
{ }
{******************************************}
unit FMX.frxDesgnCtrls;
interface
{$I fmx.inc}
{$I frx.inc}
{$I fmx.inc}
uses
System.SysUtils, System.Classes, System.Types, System.UITypes, FMX.Objects, FMX.Types,
FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.Layouts, FMX.frxClass, FMX.frxPictureCache,
System.Variants, FMX.TabControl, System.UIConsts
{$IFDEF DELPHI18}
,FMX.StdCtrls
{$ENDIF}
{$IFDEF DELPHI19}
, FMX.Graphics
{$ENDIF}
{$IFDEF DELPHI20}
, System.Math.Vectors
{$ENDIF}
{$IFDEF DELPHI28}
, FMX.BaseTypeAliases, FMX.FormTypeAliases
{$ENDIF};
type
TfrxRulerUnits = (ruCM, ruInches, ruPixels, ruChars);
{$I frxFMX_PlatformsAttribute.inc}
TfrxRuler = class(TPanel)
private
FOffset: Integer;
FScale: Double;
FStart: Integer;
FUnits: TfrxRulerUnits;
FPosition: Double;
FRulerSize: Integer;
FBitmap: TBitmap;
FNeedRedraw: Boolean;
FBackgroundColor: TAlphaColor;
procedure SetOffset(const Value: Integer);
procedure SetScale(const Value: Double);
procedure SetStart(const Value: Integer);
procedure SetUnits(const Value: TfrxRulerUnits);
procedure SetPosition(const Value: Double);
procedure SetRulerSize(const Value: Integer);
protected
procedure DoContentPaint(Sender: TObject; Canvas: TCanvas; const ARect: TRectF); virtual;
procedure DrawRuler;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure ApplyStyle; override;
published
property Offset: Integer read FOffset write SetOffset;
property Scale: Double read FScale write SetScale;
property Start: Integer read FStart write SetStart;
property Units: TfrxRulerUnits read FUnits write SetUnits default ruPixels;
property RulePosition: Double read FPosition write SetPosition;
property RulerSize: Integer read FRulerSize write SetRulerSize;
end;
TfrxScrollBox = class(TScrollBox)
private
FContent: TContent;
FOnPositionChanged: TNotifyEvent;
protected
procedure ApplyStyle; override;
procedure DoContentPaint(Sender: TObject; Canvas: TCanvas; const ARect: TRectF); virtual;
procedure DialogKey(var Key: Word; Shift: TShiftState); override;
procedure KeyDown(var Key: Word; var KeyChar: WideChar; Shift: TShiftState); override;
procedure KeyUp(var Key: Word; var KeyChar: WideChar; Shift: TShiftState); override;
{$IFDEF DELPHI18}
procedure HScrollChange; override;
procedure VScrollChange; override;
{$ELSE}
procedure HScrollChange(Sender: TObject); override;
procedure VScrollChange(Sender: TObject); override;
{$ENDIF}
{$IFDEF DELPHI18}
// public
// property HScrollBar;
// property VScrollBar;
{$ENDIF}
published
property OnPositionChanged: TNotifyEvent read FOnPositionChanged write FOnPositionChanged;
end;
TfrxTabControl = class(TTabControl)
protected
procedure ApplyStyle; override;
end;
TfrxCustomSelector = class(TPopup)
protected
FMouseOver: Boolean;
FX, FY: Single;
procedure DrawEdge(X, Y: Single); virtual; abstract;
procedure MouseMove(Shift: TShiftState; X, Y: Single); override;
procedure DoMouseEnter; override;
procedure DoMouseLeave; override;
public
constructor Create(AOwner: TComponent); override;
procedure Popup(AControl: TControl); reintroduce; overload;
end;
TfrxColorSelector = class(TfrxCustomSelector)
private
FColor: TColor;
FOnColorChanged: TNotifyEvent;
FBtnCaption: String;
protected
procedure DrawEdge(X, Y: Single); override;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Single); override;
public
constructor Create(AOwner: TComponent); override;
procedure DoPaint; override;
property Color: TColor read FColor write FColor;
property OnColorChanged: TNotifyEvent read FOnColorChanged write FOnColorChanged;
property BtnCaption: String read FBtnCaption write FBtnCaption;
end;
TfrxLineSelector = class(TfrxCustomSelector)
private
FStyle: Byte;
FOnStyleChanged: TNotifyEvent;
protected
procedure DrawEdge(X, Y: Single); override;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Single); override;
public
constructor Create(AOwner: TComponent); override;
procedure DoPaint; override;
property Style: Byte read FStyle;
property OnStyleChanged: TNotifyEvent read FOnStyleChanged write FOnStyleChanged;
end;
TfrxUndoBuffer = class(TObject)
private
FPictureCache: TfrxPictureCache;
FRedo: TList;
FUndo: TList;
function GetRedoCount: Integer;
function GetUndoCount: Integer;
procedure SetPictureFlag(ReportComponent: TfrxComponent; Flag: Boolean);
procedure SetPictures(ReportComponent: TfrxComponent);
public
constructor Create;
destructor Destroy; override;
procedure AddUndo(ReportComponent: TfrxComponent);
procedure AddRedo(ReportComponent: TfrxComponent);
procedure GetUndo(ReportComponent: TfrxComponent);
procedure GetRedo(ReportComponent: TfrxComponent);
procedure ClearUndo;
procedure ClearRedo;
property UndoCount: Integer read GetUndoCount;
property RedoCount: Integer read GetRedoCount;
property PictureCache: TfrxPictureCache read FPictureCache write FPictureCache;
end;
TfrxClipboard = class(TObject)
private
FDesigner: TfrxCustomDesigner;
FPictureCache: TfrxPictureCache;
function GetPasteAvailable: Boolean;
public
constructor Create(ADesigner: TfrxCustomDesigner);
procedure Copy;
procedure Paste;
property PasteAvailable: Boolean read GetPasteAvailable;
property PictureCache: TfrxPictureCache read FPictureCache write FPictureCache;
end;
implementation
uses
System.Math, FMX.frxDMPClass, FMX.frxDsgnIntf, FMX.frxCtrls, FMX.frxXMLSerializer, FMX.Platform,
FMX.frxUtils, FMX.frxXML, FMX.frxFMX;
const
Colors: array[0..47] of TAlphaColor =
(claNull, claWhite, claBlack, claMaroon, claGreen, claOlive, claNavy, claPurple,
claGray, claSilver, claTeal, claRed, claLime, claYellow, claBlue, claFuchsia,
$FFCCCCCC, $FFE4E4E4, claAqua, $FF00CCFF, $FF00CC98, $FF98FFFF, $FFFFCC00, $FFFF98CC,
$FFD8D8D8, $FFF0F0F0, $FFFFFFDC, $FFCAE4FF, $FFCCFFCC, $FFCCFFFF, $FFFFF4CC, $FFCC98FF,
claGray, $FF46DAFF, $FF9BEBFF, $FF00A47B, $FFFDBD97, $FFFED3BA, $FF6ACFFF, $FFFFF4CC,
claGray, claGray, claGray, claGray, claGray, claGray, claGray, claGray);
{ TfrxRuler }
procedure TfrxRuler.ApplyStyle;
var
StyleObject: TFmxObject;
begin
inherited;
StyleObject := GetStyleObject;
try
if StyleObject is TRectangle then
FBackgroundColor := TRectangle(StyleObject).Fill.Color
finally
StyleObject.Free;
end;
end;
constructor TfrxRuler.Create(AOwner: TComponent);
begin
inherited;
FScale := 1;
OnPaint := DoContentPaint;
StyleLookup := 'backgroundstyle';
FBackgroundColor := $FFF5F5F5;
FBitmap := TBitmap.Create(1, 1);
FNeedRedraw := True;
end;
destructor TfrxRuler.Destroy;
begin
FBitmap.Free;
inherited;
end;
procedure TfrxRuler.DoContentPaint(Sender: TObject; Canvas: TCanvas;
const ARect: TRectF);
var
SaveState: TCanvasSaveState;
procedure Line(x, y, dx, dy: Integer);
begin
Canvas.DrawLine(PointF(x + 0.5, y + 0.5), PointF(x + dx + 0.5, y + dy + 0.5), 1);
end;
procedure DrawLines;
var
i, dx: Single;
ofs: Integer;
begin
with Canvas do
begin
Stroke.Color := claBlack;
Stroke.Kind := TBrushKind.bkSolid;
Fill.Kind := TBrushKind.bkNone;
if FUnits = ruCM then
dx := fr01cm * FScale
else if FUnits = ruInches then
dx := fr01in * FScale
else if FUnits = ruChars then
begin
if Align = TAlignLayout.alLeft then
dx := fr1CharY * FScale / 10 else
dx := fr1CharX * FScale / 10
end
else
dx := FScale;
ofs := FOffset - FStart;
if FUnits = ruChars then
begin
if Align = TAlignLayout.alLeft then
Inc(ofs, Round(fr1CharY * FScale / 2)) else
Inc(ofs, Round(fr1CharX * FScale / 2))
end;
i := FPosition * dx;
if FUnits <> ruPixels then
i := i * 10;
if ofs + i >= FOffset then
if Align = TAlignLayout.alLeft then
Line(3, ofs + Round(i), 13, 0) else
Line(ofs + Round(i), 3, 0, 13);
end;
end;
begin
if FNeedRedraw then
begin
FNeedRedraw := False;
DrawRuler;
end;
SaveState := Canvas.SaveState;
try
Canvas.IntersectClipRect(ARect);
Canvas.DrawBitmap(FBitmap, RectF(0, 0, FBitmap.Width, FBitmap.Height), ARect, 1);
DrawLines;
finally
Canvas.RestoreState(SaveState);
end;
end;
procedure TfrxRuler.DrawRuler;
var
sz: Single;
SaveStateA, SaveStateB: TCanvasSaveState;
RMatrix, OldM: TMatrix;
procedure Line(x, y, dx, dy: Integer);
begin
FBitmap.Canvas.DrawLine(PointF(x + 0.5, y + 0.5), PointF(x + dx + 0.5, y + dy + 0.5), 1);
end;
procedure DrawLines;
var
i, dx, maxi, maxw, tx, ty: Single;
i1, h, w, w5, w10, ofs: Integer;
s: String;
begin
with FBitmap.Canvas do
begin
Stroke.Color := claBlack;
Stroke.Kind := TBrushKind.bkSolid;
Fill.Kind := TBrushKind.bkNone;
w5 := 5;
w10 := 10;
if FUnits = ruCM then
dx := fr01cm * FScale
else if FUnits = ruInches then
dx := fr01in * FScale
else if FUnits = ruChars then
begin
if Align = TAlignLayout.alLeft then
dx := fr1CharY * FScale / 10 else
dx := fr1CharX * FScale / 10
end
else
begin
dx := FScale;
w5 := 50;
w10 := 100;
end;
if FRulerSize = 0 then
begin
if Align = TAlignLayout.alLeft then
maxi := Height + FStart else
maxi := Self.Width + FStart;
end
else
maxi := FRulerSize;
if FUnits = ruPixels then
s := IntToStr(FStart + Round(maxi / dx)) else
s := IntToStr((FStart + Round(maxi / dx)) div 10);
maxw := TextWidth(s);
ofs := FOffset - FStart;
if FUnits = ruChars then
begin
if Align = TAlignLayout.alLeft then
Inc(ofs, Round(fr1CharY * FScale / 2)) else
Inc(ofs, Round(fr1CharX * FScale / 2))
end;
i := 0;
i1 := 0;
while i < maxi do
begin
h := 0;
if i1 = 0 then
h := 0
else if i1 mod w10 = 0 then
h := 6
else if i1 mod w5 = 0 then
h := 4
else if FUnits <> ruPixels then
h := 2;
if (h = 2) and (dx * w10 < 41) then
h := 0;
if (h = 4) and (dx * w10 < 21) then
h := 0;
w := 0;
if h = 6 then
begin
if maxw > dx * w10 * 1.5 then
w := w10 * 4
else if maxw > dx * w10 * 0.7 then
w := w10 * 2
else
w := w10;
end;
if FUnits = ruPixels then
s := IntToStr(i1) else
s := IntToStr(i1 div 10);
Fill.Color := claBlack;
Fill.Kind := TBrushKind.bkSolid;
if (w <> 0) and (i1 mod w = 0) and (ofs + i >= FOffset) then
begin
if Align = TAlignLayout.alLeft then
begin
tx := -(ofs + i - TextWidth(s) / 2 + 6);
ty := Self.Width - FBitmap.Canvas.TextHeight(s) - 8;
SaveStateB := SaveState;
SetMatrix(RMatrix);
end
else
begin
tx := ofs + Round(i) - TextWidth(s) / 2 + 1;
ty := 5;
end;
FillText(RectF(tx, ty, tx + 100, ty + 100), s, False, 1, [], TTextAlign.taLeading, TTextAlign.taLeading);
if Align = TAlignLayout.alLeft then
RestoreState(SaveStateB);
end
else if (h <> 0) and (ofs + i >= FOffset) then
if Align = TAlignLayout.alLeft then
Line(3 + (13 - h) div 2, ofs + Round(i), h, 0) else
Line(ofs + Round(i), 3 + (13 - h) div 2, 0, h);
i := i + dx;
Inc(i1);
end;
end;
end;
begin
FBitmap.SetSize(Round(Self.Width), Round(Self.Height));
FBitmap.Canvas.BeginScene();
SaveStateA := FBitmap.Canvas.SaveState;
try
with FBitmap.Canvas do
begin
Fill.Kind := TBrushKind.bkSolid;
Fill.Color := FBackgroundColor;
FillRect(RectF(0, 0, FBitmap.Width, FBitmap.Height), 1, 1, AllCorners, 1);
Fill.Color := claWhite;
{$IFDEF LINUX}
Font.Family := 'Liberation Sans';
{$ELSE}
Font.Family := 'Arial';
{$ENDIF}
Font.Size := 8;
if Align = TAlignLayout.alLeft then
begin
if FRulerSize = 0 then
sz := Self.Height
else
sz := FRulerSize + FOffset;
FillRect(RectF(3, FOffset, Self.Width - 5, sz), 1, 1, AllCorners, 1);
RMatrix := CreateRotationMatrix(-DegToRad(90));
//RMatrix.m31 := Self.GetAbsoluteRect.Left;
//RMatrix.m32 := Self.GetAbsoluteRect.Top;
RMatrix := MatrixMultiply(RMatrix, Matrix);
OldM := Matrix;
end
else
begin
if FRulerSize = 0 then
sz := Self.Width
else
sz := FRulerSize + FOffset;
FillRect(RectF(FOffset, 3, sz, Self.Height - 5), 1, 1, AllCorners, 1);
end;
end;
DrawLines;
finally
FBitmap.Canvas.RestoreState(SaveStateA);
FBitmap.Canvas.EndScene;
end;
end;
procedure TfrxRuler.SetOffset(const Value: Integer);
begin
FOffset := Value;
FNeedRedraw := True;
Repaint;
end;
procedure TfrxRuler.SetPosition(const Value: Double);
begin
FPosition := Value;
Repaint;
end;
procedure TfrxRuler.SetScale(const Value: Double);
begin
FScale := Value;
FNeedRedraw := True;
Repaint;
end;
procedure TfrxRuler.SetStart(const Value: Integer);
begin
FStart := Value;
FNeedRedraw := True;
Repaint;
end;
procedure TfrxRuler.SetUnits(const Value: TfrxRulerUnits);
begin
FUnits := Value;
FNeedRedraw := True;
Repaint;
end;
procedure TfrxRuler.SetRulerSize(const Value: Integer);
begin
FRulerSize := Value;
FNeedRedraw := True;
Repaint;
end;
{ TfrxScrollBox }
procedure TfrxScrollBox.ApplyStyle;
var
B: TFmxObject;
begin
inherited;
B := FindStyleResource('content');
if (B <> nil) and (B is TControl) then
begin
FContent := TContent(B);
FContent.OnPaint := DoContentPaint;
end;
end;
procedure TfrxScrollBox.DialogKey(var Key: Word; Shift: TShiftState);
begin
inherited;
end;
procedure TfrxScrollBox.DoContentPaint(Sender: TObject; Canvas: TCanvas;
const ARect: TRectF);
begin
Canvas.Fill.Kind := TBrushKind.bkSolid;
Canvas.Fill.Color := $FFE0E0E0;
Canvas.FillRect(ARect, 1, 1, AllCorners, 1, TCornerType.ctBevel);
end;
procedure TfrxScrollBox.KeyDown(var Key: Word; var KeyChar: WideChar; Shift: TShiftState);
//var
// i: Integer;
begin
inherited;
{for i := 0 to ControlCount - 1 do
if Controls[i] is TWinControl then
THackControl(Controls[i]).KeyDown(Key, Shift);}
end;
//procedure TfrxScrollBox.KeyPress(var Key: Char);
//var
// i: Integer;
//begin
// inherited;
// for i := 0 to ControlCount - 1 do
// if Controls[i] is TWinControl then
// THackControl(Controls[i]).KeyPress(Key);
//end;
procedure TfrxScrollBox.KeyUp(var Key: Word; var KeyChar: WideChar; Shift: TShiftState);
//var
// i: Integer;
begin
inherited;
{for i := 0 to ControlCount - 1 do
if Controls[i] is TWinControl then
THackControl(Controls[i]).KeyUp(Key, Shift);}
end;
{$IFDEF DELPHI18}
procedure TfrxScrollBox.HScrollChange;
{$ELSE}
procedure TfrxScrollBox.HScrollChange(Sender: TObject);
{$ENDIF}
begin
inherited;
if Assigned(FOnPositionChanged) then
FOnPositionChanged(Self);
end;
{$IFDEF DELPHI18}
procedure TfrxScrollBox.VScrollChange;
{$ELSE}
procedure TfrxScrollBox.VScrollChange(Sender: TObject);
{$ENDIF}
begin
inherited;
if Assigned(FOnPositionChanged) then
FOnPositionChanged(Self);
end;
{ TfrxCustomSelector }
constructor TfrxCustomSelector.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
StyleLookup := 'panelstyle';
end;
procedure TfrxCustomSelector.Popup(AControl: TControl);
begin
Tag := AControl.Tag;
PlacementTarget := AControl;
Popup;
end;
procedure TfrxCustomSelector.DoMouseEnter;
begin
FMouseOver := True;
Repaint;
end;
procedure TfrxCustomSelector.DoMouseLeave;
begin
FMouseOver := False;
Repaint;
end;
procedure TfrxCustomSelector.MouseMove(Shift: TShiftState; X, Y: Single);
begin
inherited;
FX := X;
FY := Y;
Repaint;
end;
{ TfrxColorSelector }
constructor TfrxColorSelector.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
Width := 155;
Height := 143;
FBtnCaption := 'Other...';
end;
procedure TfrxColorSelector.DrawEdge(X, Y: Single);
var
r: TRectF;
begin
X := Trunc((X - 5) / 18);
if X >= 8 then
X := 7;
Y := Trunc((Y - 5) / 18);
if Y < 6 then
r := RectF(X * 18 + 5.5, Y * 18 + 5.5, X * 18 + 23.5, Y * 18 + 23.5) else
r := RectF(5.5, 113.5, Width - 5.5, Height - 5.5);
with Canvas do
begin
Stroke.Kind := TBrushKind.bkSolid;
Stroke.Color := $FFC56A31;
DrawRect(r, 0, 0, AllCorners, 1);
InflateRect(r, -1, -1);
Stroke.Color := $FFE8E6E2;
DrawRect(r, 0, 0, AllCorners, 1);
InflateRect(r, -1, -1);
DrawRect(r, 0, 0, AllCorners, 1);
end;
end;
procedure TfrxColorSelector.MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Single);
//var
//cd: TColorDialog;
procedure AddCustomColor;
var
i: Integer;
Found: Boolean;
Empty: Integer;
begin
Found := False;
Empty := 0;
for i := 0 to 47 do
begin
if Colors[i] = Cardinal(FColor) then
Found := True;
if (i > 37) and (Colors[i] = claGray) and (Empty = 0) then
Empty := i;
end;
if Found then exit;
if Empty = 0 then
begin
for i := 40 to 46 do
Colors[i] := Colors[i + 1];
Empty := 47;
end;
Colors[Empty] := FColor
end;
begin
X := Trunc((X - 5) / 18);
if X >= 8 then
X := 7;
Y := Trunc((Y - 5) / 18);
if Y < 6 then
FColor := Colors[Round(X + Y * 8)]
else
begin
//TForm(Parent).AutoSize := False;
//Parent.Height := 0;
//cd := TColorDialog.Create(Self);
//cd.Options := [cdFullOpen];
//cd.Color := FColor;
//if cd.Execute then
// FColor := cd.Color else
// Exit;
// todo color selector form
AddCustomColor;
end;
ClosePopup;
if Assigned(FOnColorChanged) then
FOnColorChanged(Self);
end;
procedure TfrxColorSelector.DoPaint;
var
i, j: Integer;
s: String;
r: TRectF;
begin
inherited;
with Canvas do
begin
Fill.Kind := TBrushKind.bkSolid;
Stroke.Kind := TBrushKind.bkSolid;
for j := 0 to 5 do
for i := 0 to 7 do
begin
if (i = 0) and (j = 0) then
Fill.Color := claWhite else
Fill.Color := Colors[i + j * 8];
Stroke.Color := claGray;
r := RectF(i * 18 + 8.5, j * 18 + 8.5, i * 18 + 20.5, j * 18 + 20.5);
FillRect(r, 0, 0, AllCorners, 1);
DrawRect(r, 0, 0, AllCorners, 1);
if (i = 0) and (j = 0) then
begin
DrawLine(PointF(i * 18 + 10.5, j * 18 + 10.5), PointF(i * 18 + 18.5, j * 18 + 18.5), 1);
DrawLine(PointF(i * 18 + 18.5, j * 18 + 10.5), PointF(i * 18 + 10.5, j * 18 + 18.5), 1);
end;
end;
Stroke.Color := claGray;
Fill.Color := claGray;
s := FBtnCaption;
{$IFDEF LINUX}
DrawRect(RectF(8.5, 116.5, Width - 20, Height - 20), 0, 0, AllCorners, 1);
FillText(RectF(8.5, 116.5, Width - 20, Height - 20), s, False, 1, [], TTextAlign.taCenter, TTextAlign.taCenter)
{$ELSE}
DrawRect(RectF(8.5, 116.5, Width - 8.5, Height - 8.5), 0, 0, AllCorners, 1);
FillText(RectF(10, 116, Width - 10, Height - 8), s, False, 1, [], TTextAlign.taCenter, TTextAlign.taCenter)
{$ENDIF}
end;
if FMouseOver then
DrawEdge(FX, FY);
end;
{ TfrxLineSelector }
constructor TfrxLineSelector.Create(AOwner: TComponent);
begin
inherited;
Width := 98;
Height := 106;
end;
procedure TfrxLineSelector.DrawEdge(X, Y: Single);
var
r: TRectF;
begin
Y := Trunc((Y - 5) / 16);
if Y > 5 then
Y := 5;
r := RectF(5.5, Y * 16 + 5.5, Width - 6.5, Y * 16 + 19.5);
with Canvas do
begin
Stroke.Kind := TBrushKind.bkSolid;
Stroke.Color := claGray;
{$IFDEF Delphi25}
Stroke.Thickness := 1;
{$ELSE}
StrokeThickness := 1;
{$ENDIF}
DrawRect(r, 0, 0, AllCorners, 1);
end;
end;
procedure TfrxLineSelector.MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Single);
begin
Y := Trunc((Y - 5) / 16);
if Y > 5 then
Y := 5;
FStyle := Round(Y);
ClosePopup;
if Assigned(FOnStyleChanged) then
FOnStyleChanged(Self);
end;
procedure TfrxLineSelector.DoPaint;
var
i: Integer;
procedure DrawLine(Y, Style: Integer);
begin
if Style = 5 then
begin
Style := 0;
DrawLine(Y - 2, Style);
Inc(Y, 2);
end;
with Canvas do
begin
Stroke.Color := claBlack;
{$IFDEF Delphi25}
Stroke.Thickness := 2;
Stroke.Dash := TStrokeDash(Style);
{$ELSE}
StrokeDash := TStrokeDash(Style);
StrokeThickness := 2;
{$ENDIF}
DrawLine(PointF(7, Y), PointF(Self.Width - 8, Y), 1);
end;
end;
begin
inherited;
for i := 0 to 5 do
DrawLine(12 + i * 16, i);
if FMouseOver then
DrawEdge(FX, FY);
end;
{ TfrxUndoBuffer }
constructor TfrxUndoBuffer.Create;
begin
FRedo := TList.Create;
FUndo := TList.Create;
end;
destructor TfrxUndoBuffer.Destroy;
begin
ClearUndo;
ClearRedo;
FUndo.Free;
FRedo.Free;
inherited;
end;
procedure TfrxUndoBuffer.AddUndo(ReportComponent: TfrxComponent);
var
m: TMemoryStream;
begin
m := TMemoryStream.Create;
FUndo.Add(m);
SetPictureFlag(ReportComponent, False);
try
ReportComponent.SaveToStream(m);
finally
SetPictureFlag(ReportComponent, True);
end;
end;
procedure TfrxUndoBuffer.AddRedo(ReportComponent: TfrxComponent);
var
m: TMemoryStream;
begin
m := TMemoryStream.Create;
FRedo.Add(m);
SetPictureFlag(ReportComponent, False);
try
ReportComponent.SaveToStream(m);
finally
SetPictureFlag(ReportComponent, True);
end;
end;
procedure TfrxUndoBuffer.GetUndo(ReportComponent: TfrxComponent);
var
m: TMemoryStream;
IsReport: Boolean;
begin
IsReport := False;
if ReportComponent is TfrxReport then
isReport := True;
m := FUndo[FUndo.Count - 2];
m.Position := 0;
if IsReport then
TfrxReport(ReportComponent).Reloading := True;
try
ReportComponent.LoadFromStream(m);
finally
if IsReport then
TfrxReport(ReportComponent).Reloading := False;
end;
SetPictures(ReportComponent);
m := FUndo[FUndo.Count - 1];
m.Free;
FUndo.Delete(FUndo.Count - 1);
end;
procedure TfrxUndoBuffer.GetRedo(ReportComponent: TfrxComponent);
var
m: TMemoryStream;
IsReport: Boolean;
begin
IsReport := False;
if ReportComponent is TfrxReport then
isReport := True;
m := FRedo[FRedo.Count - 1];
m.Position := 0;
if IsReport then
TfrxReport(ReportComponent).Reloading := True;
try
ReportComponent.LoadFromStream(m);
finally
if IsReport then
TfrxReport(ReportComponent).Reloading := False;
end;
SetPictures(ReportComponent);
m.Free;
FRedo.Delete(FRedo.Count - 1);
end;
procedure TfrxUndoBuffer.ClearUndo;
begin
while FUndo.Count > 0 do
begin
TMemoryStream(FUndo[0]).Free;
FUndo.Delete(0);
end;
end;
procedure TfrxUndoBuffer.ClearRedo;
begin
while FRedo.Count > 0 do
begin
TMemoryStream(FRedo[0]).Free;
FRedo.Delete(0);
end;
end;
function TfrxUndoBuffer.GetRedoCount: Integer;
begin
Result := FRedo.Count;
end;
function TfrxUndoBuffer.GetUndoCount: Integer;
begin
Result := FUndo.Count;
end;
procedure TfrxUndoBuffer.SetPictureFlag(ReportComponent: TfrxComponent; Flag: Boolean);
var
i: Integer;
l: TList;
c: TfrxComponent;
begin
l := ReportComponent.AllObjects;
for i := 0 to l.Count - 1 do
begin
c := l[i];
if c is TfrxPictureView then
begin
TfrxPictureView(c).IsPictureStored := Flag;
TfrxPictureView(c).IsImageIndexStored := not Flag;
end;
end;
end;
procedure TfrxUndoBuffer.SetPictures(ReportComponent: TfrxComponent);
var
i: Integer;
l: TList;
c: TfrxComponent;
begin
l := ReportComponent.AllObjects;
for i := 0 to l.Count - 1 do
begin
c := l[i];
if c is TfrxPictureView then
FPictureCache.GetPicture(TfrxPictureView(c));
end;
end;
{ TfrxClipboard }
constructor TfrxClipboard.Create(ADesigner: TfrxCustomDesigner);
begin
FDesigner := ADesigner;
end;
procedure TfrxClipboard.Copy;
var
c, c1: TfrxComponent;
i, j: Integer;
text: String;
minX, minY: Extended;
List: TList;
Flag: Boolean;
procedure Write(c: TfrxComponent);
var
c1: TfrxComponent;
Writer: TfrxXMLSerializer;
begin
c1 := TfrxComponent(c.NewInstance);
c1.Create(FDesigner.Page);
if c is TfrxPictureView then
begin
TfrxPictureView(c).IsPictureStored := False;
TfrxPictureView(c).IsImageIndexStored := True;
end;
try
c1.Assign(c);
finally
if c is TfrxPictureView then
begin
TfrxPictureView(c).IsPictureStored := True;
TfrxPictureView(c).IsImageIndexStored := False;
TfrxPictureView(c1).IsImageIndexStored := True;
end;
end;
c1.Left := c1.Left - minX;
c1.Top := c.AbsTop - minY;
Writer := TfrxXMLSerializer.Create(nil);
Writer.Owner := c1.Report;
text := text + '<' + c1.ClassName + ' Name="' + c.Name + '"' + Writer.ObjToXML(c1) + '/>';
Writer.Free;
c1.Free;
end;
begin
text := '#FR3 clipboard#' + #10#13;
minX := 100000;
minY := 100000;
for i := 0 to FDesigner.SelectedObjects.Count - 1 do
begin
c := FDesigner.SelectedObjects[i];
if c.AbsLeft < minX then
minX := c.AbsLeft;
if c.AbsTop < minY then
minY := c.AbsTop;
end;
List := FDesigner.Page.AllObjects;
for i := 0 to List.Count - 1 do
begin
c := List[i];
if FDesigner.SelectedObjects.IndexOf(c) <> -1 then
begin
Write(c);
if c is TfrxBand then
begin
Flag := False;
for j := 0 to c.Objects.Count - 1 do
begin
c1 := c.Objects[j];
if FDesigner.SelectedObjects.IndexOf(c1) <> -1 then
Flag := True;
end;
if not Flag then
for j := 0 to c.Objects.Count - 1 do
Write(c.Objects[j]);
end;
end;
end;
SetClipboard(text);
end;
function TfrxClipboard.GetPasteAvailable: Boolean;
var
cb: Variant;
begin
Result := False;
try
cb := GetClipboard;
if cb <> null then
Result := (Pos('#FR3 clipboard#', cb) = 1);
except
Result := False;
end;
end;
procedure TfrxClipboard.Paste;
var
c: TfrxComponent;
sl: TStrings;
s: TStream;
List: TList;
NewCompName: string;
NewComp: TfrxComponent;
function ReadComponent_(AReader: TfrxXMLSerializer; Root: TfrxComponent): TfrxComponent;
var
rd: TfrxXMLReader;
RootItem: TfrxXMLItem;
begin
rd := TfrxXMLReader.Create(AReader.Stream);
RootItem := TfrxXMLItem.Create;
try
rd.ReadRootItem(RootItem, False);
Result := AReader.ReadComponentStr(Root, RootItem.Name + ' ' + RootItem.Text);
NewCompName := RootItem.Prop['Name'];
finally
rd.Free;
RootItem.Free;
end;
end;
function ReadComponent: TfrxComponent;
var
Reader: TfrxXMLSerializer;
begin
Reader := TfrxXMLSerializer.Create(s);
Result := ReadComponent_(Reader, FDesigner.Report);
Reader.Free;
end;
function FindBand(Band: TfrxComponent): Boolean;
var
i: Integer;
begin
Result := False;
for i := 0 to FDesigner.Page.Objects.Count - 1 do
if (FDesigner.Page.Objects[i] <> Band) and
(TObject(FDesigner.Page.Objects[i]) is Band.ClassType) then
Result := True;
end;
function CanInsert(c: TfrxComponent): Boolean;
begin
Result := True;
if (c is TfrxDialogControl) and (FDesigner.Page is TfrxReportPage) then
Result := False;
if not (c is TfrxDialogComponent) and not (c is TfrxDialogControl) and
(FDesigner.Page is TfrxDialogPage) then
Result := False;
if ((c is TfrxDMPMemoView) or (c is TfrxDMPLineView) or (c is TfrxDMPCommand)) and
not (FDesigner.Page is TfrxDMPPage) then
Result := False;
if not ((c is TfrxBand) or (c is TfrxDMPMemoView) or (c is TfrxDMPLineView) or
(c is TfrxDMPCommand)) and (FDesigner.Page is TfrxDMPPage) then
Result := False;
if not ((c is TfrxCustomLineView) or (c is TfrxCustomMemoView) or
(c is TfrxShapeView) or (c is TfrxDialogComponent)) and
(FDesigner.Page is TfrxDataPage) then
Result := False;
end;
procedure FindParent(c: TfrxComponent);
var
i: Integer;
Found: Boolean;
c1: TfrxComponent;
begin
Found := False;
if not (c is TfrxBand) then
for i := List.Count - 1 downto 0 do
begin
c1 := List[i];
if c1 is TfrxBand then
if (c.Top >= c1.Top) and (c.Top < c1.Top + c1.Height) then
begin
c.Parent := c1;
c.Top := c.Top - c1.Top;
Found := True;
break;
end;
end;
if not Found then
c.Parent := FDesigner.Page;
end;
begin
FDesigner.SelectedObjects.Clear;
sl := TStringList.Create;
sl.Text := GetClipboard;
sl.Delete(0);
s := TMemoryStream.Create;
sl.SaveToStream(s, TEncoding.UTF8);
sl.Free;
s.Position := 0;
List := TList.Create;
while s.Position < s.Size do
begin
c := ReadComponent;
if c = nil then break;
if (((c is TfrxReportTitle) or (c is TfrxReportSummary) or
(c is TfrxPageHeader) or (c is TfrxPageFooter) or
(c is TfrxColumnHeader) or (c is TfrxColumnFooter)) and FindBand(c)) or
not CanInsert(c) then
c.Free
else
begin
if c is TfrxPictureView then
FPictureCache.GetPicture(TfrxPictureView(c));
List.Add(c);
FindParent(c);
if FDesigner.IsPreviewDesigner then
NewComp := FDesigner.Report.FindObject(NewCompName) as TfrxComponent
else
NewComp := FDesigner.Report.FindComponent(NewCompName) as TfrxComponent;
if ((NewComp <> nil) and (NewComp <> c)) or (NewCompName = '') then
c.CreateUniqueName
else
c.Name := NewCompName;
c.GroupIndex := 0;
FDesigner.Objects.Add(c);
if c.Parent = FDesigner.Page then
FDesigner.SelectedObjects.Add(c);
c.OnPaste;
end;
end;
if FDesigner.SelectedObjects.Count = 0 then
FDesigner.SelectedObjects.Add(FDesigner.Page);
List.Free;
s.Free;
end;
{ TfrxTabControl }
procedure TfrxTabControl.ApplyStyle;
var
B: TFmxObject;
begin
inherited;
B := FindStyleResource('rectangle');
if (B <> nil) and (B is TRectangle) then
TRectangle(B).Sides := [];
end;
initialization
StartClassGroup(TFmxObject);
ActivateClassGroup(TFmxObject);
GroupDescendentsWith(TfrxRuler, TFmxObject);
GroupDescendentsWith(TfrxScrollBox, TFmxObject);
RegisterFmxClasses([TfrxRuler, TfrxScrollBox]);
end.