976 lines
28 KiB
ObjectPascal
976 lines
28 KiB
ObjectPascal
|
{******************************************}
|
||
|
{ }
|
||
|
{ FastReport VCL }
|
||
|
{ Basic InPlace Editors }
|
||
|
{ }
|
||
|
{ Copyright (c) 1998-2021 }
|
||
|
{ by Fast Reports Inc. }
|
||
|
{ }
|
||
|
{******************************************}
|
||
|
|
||
|
unit frxInPlaceEditors;
|
||
|
|
||
|
interface
|
||
|
|
||
|
{$I frx.inc}
|
||
|
|
||
|
uses
|
||
|
{$IFDEF FPC}LazHelper{$ELSE}Windows{$ENDIF},
|
||
|
Types, Classes, SysUtils, Graphics, Controls, StdCtrls, ComCtrls, Forms,
|
||
|
Menus, TypInfo,
|
||
|
Dialogs, frxClass, frxUtils, frxGraphicControls,
|
||
|
frxRes, frxUnicodeCtrls, frxUnicodeUtils, Buttons, frxPopupForm
|
||
|
{$IFDEF Delphi6}
|
||
|
, Variants
|
||
|
{$ENDIF}
|
||
|
{$IFDEF Delphi10}
|
||
|
, WideStrings
|
||
|
{$ENDIF};
|
||
|
|
||
|
type
|
||
|
TfrxInPlaceMemoEditorBase = class(TfrxInPlaceEditor)
|
||
|
private
|
||
|
procedure LinesChange(Sender: TObject);
|
||
|
procedure MemoKeyPress(Sender: TObject; var Key: Char);
|
||
|
procedure DoExit(Sender: TObject);
|
||
|
procedure MemoKeyDown(Sender: TObject; var Key: Word;
|
||
|
Shift: TShiftState);
|
||
|
protected
|
||
|
FInPlaceMemo: TCustomMemo;
|
||
|
FEdited: Boolean;
|
||
|
procedure InitControlFromComponent; virtual;
|
||
|
procedure InitComponentFromControl; virtual;
|
||
|
procedure EditDone;
|
||
|
procedure CreateMemo; virtual; abstract;
|
||
|
public
|
||
|
constructor Create(aClassRef: TfrxComponentClass;
|
||
|
aOwner: TWinControl); override;
|
||
|
destructor Destroy; override;
|
||
|
function HasCustomEditor: Boolean; override;
|
||
|
function DoMouseUp(X, Y: Integer; Button: TMouseButton;
|
||
|
Shift: TShiftState; var EventParams: TfrxInteractiveEventsParams): Boolean; override;
|
||
|
procedure EditInPlace(aParent: TComponent; aRect: TRect); override;
|
||
|
function EditInPlaceDone: Boolean; override;
|
||
|
function DoMouseWheel(Shift: TShiftState;
|
||
|
WheelDelta: Integer; MousePos: TPoint; var EventParams: TfrxInteractiveEventsParams): Boolean; override;
|
||
|
procedure FinalizeUI(var EventParams: TfrxInteractiveEventsParams); override;
|
||
|
end;
|
||
|
|
||
|
TfrxInPlaceTextEditorBase = class(TfrxInPlaceMemoEditorBase)
|
||
|
protected
|
||
|
procedure CreateMemo; override;
|
||
|
end;
|
||
|
|
||
|
TfrxInPlaceMemoEditor = class(TfrxInPlaceTextEditorBase)
|
||
|
protected
|
||
|
procedure InitControlFromComponent; override;
|
||
|
procedure InitComponentFromControl; override;
|
||
|
end;
|
||
|
|
||
|
TfrxInPlaceBaseChoiceEditor = class(TfrxInPlaceEditor)
|
||
|
protected
|
||
|
FDrawDragDrop: Boolean;
|
||
|
FDrawDropDown: Boolean;
|
||
|
FDrawButton: Boolean;
|
||
|
FModified: Boolean;
|
||
|
FListBox: TListBox;
|
||
|
FRect: TRect;
|
||
|
FPopUpRect: TRect;
|
||
|
FPopupForm: TfrxPopupForm;
|
||
|
|
||
|
procedure DoPopupHide(Sender: TObject);
|
||
|
procedure DoLBClick(Sender: TObject); virtual; abstract;
|
||
|
procedure LBDrawItem(Control: TWinControl; Index: Integer; aRect: TRect;
|
||
|
State: TOwnerDrawState); virtual; abstract;
|
||
|
function GetButtonSize: Integer; virtual; abstract;
|
||
|
function GetButtonBevelWidth: Integer;
|
||
|
function IsFillListBox: Boolean; virtual; abstract;
|
||
|
procedure CalcPopupBounds(out TopLeft: TPoint; out w, h: Integer); virtual; abstract;
|
||
|
function ListBoxCreate: TListBox; virtual;
|
||
|
procedure UpdateRect; virtual;
|
||
|
public
|
||
|
function GetActiveRect: TRect; override;
|
||
|
function ShowPopup(aParent: TComponent; aRect: TRect; X, Y: Integer): Boolean; virtual;
|
||
|
procedure DrawCustomEditor(aCanvas: TCanvas; aRect: TRect); override;
|
||
|
|
||
|
function DoMouseDown(X, Y: Integer; Button: TMouseButton; Shift: TShiftState;
|
||
|
var EventParams: TfrxInteractiveEventsParams): Boolean; override;
|
||
|
function DoMouseMove(X, Y: Integer; Shift: TShiftState;
|
||
|
var EventParams: TfrxInteractiveEventsParams): Boolean; override;
|
||
|
end;
|
||
|
|
||
|
TfrxInPlaceDataFiledEditor = class(TfrxInPlaceBaseChoiceEditor)
|
||
|
private
|
||
|
function GetParentDS: TfrxDataSet;
|
||
|
protected
|
||
|
procedure DoLBClick(Sender: TObject); override;
|
||
|
function IsFillListBox: Boolean; override;
|
||
|
function GetButtonSize: Integer; override;
|
||
|
procedure CalcPopupBounds(out TopLeft: TPoint; out w, h: Integer); override;
|
||
|
function ListBoxCreate: TListBox; override;
|
||
|
procedure LBDrawItem(Control: TWinControl; Index: Integer; aRect: TRect;
|
||
|
State: TOwnerDrawState); override;
|
||
|
public
|
||
|
procedure InitializeUI(var EventParams: TfrxInteractiveEventsParams); override;
|
||
|
procedure FinalizeUI(var EventParams: TfrxInteractiveEventsParams); 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;
|
||
|
|
||
|
end;
|
||
|
|
||
|
TfrxInPlaceBasePanelEditor = class(TfrxInPlaceEditor)
|
||
|
private
|
||
|
FButtonsPanel: TfrxSwitchButtonsPanel;
|
||
|
FSwitchMode: Boolean;
|
||
|
FPosition: TPoint;
|
||
|
function DestroyPanel: Boolean;
|
||
|
protected
|
||
|
FMouseDown: Boolean;
|
||
|
function GetItem(Index: Integer): Boolean; virtual; abstract;
|
||
|
procedure SetItem(Index: Integer; const Value: Boolean); virtual; abstract;
|
||
|
function Count: Integer; virtual; abstract;
|
||
|
function GetName(Index: Integer): String; virtual; abstract;
|
||
|
function GetColor(Index: Integer): TColor; virtual; abstract;
|
||
|
public
|
||
|
destructor Destroy; override;
|
||
|
procedure AfterConstruction; override;
|
||
|
procedure InitializeUI(var EventParams: TfrxInteractiveEventsParams); override;
|
||
|
procedure FinalizeUI(var EventParams: TfrxInteractiveEventsParams); override;
|
||
|
function GetActiveRect: TRect; override;
|
||
|
function DoMouseDown(X, Y: Integer; Button: TMouseButton;
|
||
|
Shift: TShiftState; var EventParams: TfrxInteractiveEventsParams): Boolean; override;
|
||
|
function DoMouseUp(X, Y: Integer; Button: TMouseButton;
|
||
|
Shift: TShiftState; var EventParams: TfrxInteractiveEventsParams): Boolean; override;
|
||
|
procedure DrawCustomEditor(aCanvas: TCanvas; aRect: TRect); override;
|
||
|
property Item[Index: Integer]: Boolean read GetItem write SetItem;
|
||
|
end;
|
||
|
|
||
|
implementation
|
||
|
|
||
|
uses
|
||
|
Math,
|
||
|
frxInPlaceClipboards, frxDataLinkInPlaceEditor;
|
||
|
|
||
|
const
|
||
|
frx_DefaultBtnSize = 16;
|
||
|
ListBoxItemHeight = 16;
|
||
|
|
||
|
type
|
||
|
{ InPlace editors }
|
||
|
TfrxHackView = class(TfrxView);
|
||
|
THackCustomMemo = class(TCustomMemo);
|
||
|
TfrxInPlaceBandEditor = class(TfrxInPlaceEditor)
|
||
|
private
|
||
|
FDrawDragDrop: Boolean;
|
||
|
public
|
||
|
constructor Create(aClassRef: TfrxComponentClass;
|
||
|
aOwner: TWinControl); override;
|
||
|
function HasCustomEditor: Boolean; override;
|
||
|
procedure FinalizeUI(var EventParams: TfrxInteractiveEventsParams); 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;
|
||
|
end;
|
||
|
|
||
|
|
||
|
{ TfrxMemoEditor }
|
||
|
|
||
|
constructor TfrxInPlaceMemoEditorBase.Create(aClassRef: TfrxComponentClass;
|
||
|
aOwner: TWinControl);
|
||
|
begin
|
||
|
inherited;
|
||
|
CreateMemo;
|
||
|
THackCustomMemo(FInPlaceMemo).OnExit := DoExit;
|
||
|
with THackCustomMemo(FInPlaceMemo) do
|
||
|
begin
|
||
|
Visible := False;
|
||
|
WordWrap := False;
|
||
|
OnChange := LinesChange;
|
||
|
OnKeyPress := MemoKeyPress;
|
||
|
OnKeyDown := MemoKeyDown;
|
||
|
Parent := FOwner;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TfrxInPlaceMemoEditorBase.DoExit(Sender: TObject);
|
||
|
begin
|
||
|
EditDone;
|
||
|
end;
|
||
|
|
||
|
function TfrxInPlaceMemoEditorBase.DoMouseUp(X, Y: Integer;
|
||
|
Button: TMouseButton; Shift: TShiftState; var EventParams: TfrxInteractiveEventsParams): Boolean;
|
||
|
begin
|
||
|
Result := inherited DoMouseUp(X, Y, Button, Shift, EventParams);
|
||
|
OnFinishInPlace := EventParams.OnFinish;
|
||
|
EditInPlaceDone;
|
||
|
if ((EventParams.EditMode = dtText) or ((EventParams.EventSender = esPreview) and (ssAlt in Shift) and (ferAllowInPreview in FComponent.Editable))) then
|
||
|
EditInPlace(EventParams.Sender as TComponent, Rect(TfrxHackView(FComponent).FX, TfrxHackView(FComponent).FY, TfrxHackView(FComponent).FX1, TfrxHackView(FComponent).FY1));
|
||
|
//OnFinishInPlace := EventParams.OnFinish;
|
||
|
end;
|
||
|
|
||
|
function TfrxInPlaceMemoEditorBase.DoMouseWheel(Shift: TShiftState;
|
||
|
WheelDelta: Integer; MousePos: TPoint;
|
||
|
var EventParams: TfrxInteractiveEventsParams): Boolean;
|
||
|
begin
|
||
|
Result := FInPlaceMemo.Visible;
|
||
|
end;
|
||
|
|
||
|
procedure TfrxInPlaceMemoEditorBase.EditDone;
|
||
|
begin
|
||
|
if (csDestroying in FInPlaceMemo.ComponentState) or
|
||
|
Assigned(FInPlaceMemo.Parent) and
|
||
|
(csDestroying in FInPlaceMemo.Parent.ComponentState) then
|
||
|
Exit;
|
||
|
if FInPlaceMemo.Modified then
|
||
|
begin
|
||
|
InitComponentFromControl;
|
||
|
DoFinishInPlace(Component, True, True);
|
||
|
FInPlaceMemo.Modified := False;
|
||
|
FEdited := True;
|
||
|
end;
|
||
|
FInPlaceMemo.Hide;
|
||
|
end;
|
||
|
|
||
|
procedure TfrxInPlaceMemoEditorBase.EditInPlace(aParent: TComponent; aRect: TRect);
|
||
|
var
|
||
|
View: TfrxView;
|
||
|
Scale: Extended;
|
||
|
r: TRect;
|
||
|
begin
|
||
|
View := TfrxView(Component);
|
||
|
Scale := FScale;
|
||
|
with THackCustomMemo(FInPlaceMemo) do
|
||
|
begin
|
||
|
|
||
|
r := Rect(Round(View.AbsLeft * Scale), Round(View.AbsTop * Scale),
|
||
|
Round((View.AbsLeft + View.Width) * Scale + 1),
|
||
|
Round((View.AbsTop + View.Height) * Scale + 1));
|
||
|
OffsetRect(r, Round(FOffsetX), Round(FOffsetY));
|
||
|
SetBounds(r.Left, r.Top, r.Right - r.Left, r.Bottom - r.Top);
|
||
|
InitControlFromComponent;
|
||
|
|
||
|
// FOriginalSize.cx := Width;
|
||
|
// FOriginalSize.cy := Height;
|
||
|
|
||
|
if View.Color = clNone then
|
||
|
Color := clWhite
|
||
|
else
|
||
|
Color := View.Color;
|
||
|
{$IFNDEF FPC}
|
||
|
Ctl3D := False;
|
||
|
{$ENDIF}
|
||
|
BorderStyle := bsNone;
|
||
|
|
||
|
Show;
|
||
|
SetFocus;
|
||
|
SelectAll;
|
||
|
FEdited := False;
|
||
|
end;
|
||
|
|
||
|
end;
|
||
|
|
||
|
function TfrxInPlaceMemoEditorBase.EditInPlaceDone: Boolean;
|
||
|
begin
|
||
|
EditDone;
|
||
|
Result := FEdited;
|
||
|
end;
|
||
|
|
||
|
procedure TfrxInPlaceMemoEditorBase.FinalizeUI(
|
||
|
var EventParams: TfrxInteractiveEventsParams);
|
||
|
begin
|
||
|
inherited;
|
||
|
EventParams.Refresh := EventParams.Refresh or EditInPlaceDone;
|
||
|
// EventParams.Modified := EventParams.Refresh;
|
||
|
end;
|
||
|
|
||
|
function TfrxInPlaceMemoEditorBase.HasCustomEditor: Boolean;
|
||
|
begin
|
||
|
Result := True;
|
||
|
end;
|
||
|
|
||
|
procedure TfrxInPlaceMemoEditorBase.InitComponentFromControl;
|
||
|
begin
|
||
|
//
|
||
|
end;
|
||
|
|
||
|
procedure TfrxInPlaceMemoEditorBase.InitControlFromComponent;
|
||
|
begin
|
||
|
//
|
||
|
end;
|
||
|
|
||
|
procedure TfrxInPlaceMemoEditorBase.MemoKeyDown(Sender: TObject; var Key: Word;
|
||
|
Shift: TShiftState);
|
||
|
begin
|
||
|
if (Key = $0D) and (ssCtrl in Shift) then
|
||
|
EditDone;
|
||
|
end;
|
||
|
|
||
|
procedure TfrxInPlaceMemoEditorBase.MemoKeyPress(Sender: TObject; var Key: Char);
|
||
|
begin
|
||
|
if Key = #27 then
|
||
|
begin
|
||
|
FInPlaceMemo.Modified := False;
|
||
|
EditDone;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TfrxInPlaceMemoEditorBase.LinesChange(Sender: TObject);
|
||
|
// var
|
||
|
// i, w0, w, h: Integer;
|
||
|
begin
|
||
|
{ h := (-FInPlaceMemo.Font.Height + 3) * FInPlaceMemo.Lines.Count + 4;
|
||
|
if h > FInPlaceMemo.Height - FInPlaceMemo.Font.Height then
|
||
|
FInPlaceMemo.Height := h;
|
||
|
|
||
|
TPanel(FInPlaceMemo.Parent).Canvas.Font := FInPlaceMemo.Font;
|
||
|
|
||
|
w := FInPlaceMemo.Width;
|
||
|
for i := 0 to FInPlaceMemo.Lines.Count - 1 do
|
||
|
begin
|
||
|
w0 := FDesigner.Canvas.TextWidth(FInPlaceMemo.Lines[i]) + 6;
|
||
|
if w0 > w then
|
||
|
w := w0;
|
||
|
end;
|
||
|
|
||
|
if w > FInPlaceMemo.Width then
|
||
|
FInPlaceMemo.Width := w; }
|
||
|
end;
|
||
|
|
||
|
{ TfrxInPlaceBandEditor }
|
||
|
|
||
|
constructor TfrxInPlaceBandEditor.Create(aClassRef: TfrxComponentClass;
|
||
|
aOwner: TWinControl);
|
||
|
begin
|
||
|
inherited;
|
||
|
|
||
|
end;
|
||
|
|
||
|
function TfrxInPlaceBandEditor.DoCustomDragDrop(Source: TObject;
|
||
|
X, Y: Integer; var EventParams: TfrxInteractiveEventsParams): Boolean;
|
||
|
var
|
||
|
Band: TfrxBand;
|
||
|
Node: TTreeNode;
|
||
|
i: Integer;
|
||
|
s: String;
|
||
|
aEventParams: TfrxInteractiveEventsParams;
|
||
|
e: TfrxEventObject;
|
||
|
c: TfrxComponent;
|
||
|
|
||
|
function GetComponentByIndex(Index: Integer): TfrxComponent;
|
||
|
var
|
||
|
i: Integer;
|
||
|
c: TfrxComponent;
|
||
|
begin
|
||
|
Result := nil;
|
||
|
for i := 0 to Band.Objects.Count - 1 do
|
||
|
if TObject(Band.Objects[i]) is TfrxComponent then
|
||
|
begin
|
||
|
c := TfrxComponent(Band.Objects[i]);
|
||
|
if c.IndexTag = Index then
|
||
|
begin
|
||
|
Result := c;
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
begin
|
||
|
Result := False;
|
||
|
if not FDrawDragDrop then Exit;
|
||
|
Band := nil;
|
||
|
if Component is TfrxBand then
|
||
|
Band := TfrxBand(Component);
|
||
|
if (Source is TTreeView) and Assigned(Band) then
|
||
|
with Band do
|
||
|
for i := TTreeView(Source).SelectionCount - 1 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
|
||
|
c := GetComponentByIndex(i + 1);
|
||
|
Result := True;
|
||
|
if Assigned(c) then
|
||
|
begin
|
||
|
// Result := True;
|
||
|
// pass helper class which helps to determanate sender
|
||
|
e := TfrxEventObject.Create;
|
||
|
try
|
||
|
e.Sender := Source;
|
||
|
e.Index := i;
|
||
|
aEventParams.EditorsList := Editors;
|
||
|
c.DragDrop(e, X, Y, aEventParams);
|
||
|
finally
|
||
|
e.Free;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TfrxInPlaceBandEditor.DoCustomDragOver(Source: TObject; X, Y: Integer;
|
||
|
State: TDragState; var Accept: Boolean; var EventParams: TfrxInteractiveEventsParams): Boolean;
|
||
|
var
|
||
|
Band: TfrxBand;
|
||
|
begin
|
||
|
Result := False;
|
||
|
Band := nil;
|
||
|
Accept := False;
|
||
|
if Component is TfrxBand then
|
||
|
Band := TfrxBand(Component);
|
||
|
if (Source is TTreeView) and Assigned(Band) and (Band.AbsLeft * FScale < X)
|
||
|
and ((Band.AbsLeft + Band.Width) * FScale > X) and
|
||
|
((Band.AbsTop - Band.BandDesignHeader) * FScale < Y) and
|
||
|
(Band.AbsTop * FScale > Y) then
|
||
|
begin
|
||
|
Accept := True;
|
||
|
Result := True;
|
||
|
end;
|
||
|
FDrawDragDrop := Accept;
|
||
|
EventParams.Refresh := True;
|
||
|
end;
|
||
|
|
||
|
procedure TfrxInPlaceBandEditor.DrawCustomEditor(aCanvas: TCanvas; aRect: TRect);
|
||
|
var
|
||
|
Band: TfrxBand;
|
||
|
begin
|
||
|
Band := TfrxBand(Component);
|
||
|
if FDrawDragDrop then
|
||
|
begin
|
||
|
frxResources.MainButtonImages.Draw(aCanvas, Round((Band.AbsLeft + Band.Width) * FScale / 2),
|
||
|
Round((Band.AbsTop - Band.BandDesignHeader) * FScale), 112);
|
||
|
TransparentFillRect(aCanvas.Handle, Round(Band.AbsLeft * FScale), Round((Band.AbsTop - Band.BandDesignHeader) * FScale),
|
||
|
Round((Band.AbsLeft + Band.Width) * FScale), Round(Band.AbsTop * FScale), clGray);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TfrxInPlaceBandEditor.FinalizeUI(
|
||
|
var EventParams: TfrxInteractiveEventsParams);
|
||
|
begin
|
||
|
EventParams.Refresh := FDrawDragDrop;
|
||
|
FDrawDragDrop := False;
|
||
|
end;
|
||
|
|
||
|
function TfrxInPlaceBandEditor.HasCustomEditor: Boolean;
|
||
|
begin
|
||
|
Result := inherited HasCustomEditor;
|
||
|
end;
|
||
|
|
||
|
{ TfrxInPlaceDataFiledEditor }
|
||
|
|
||
|
procedure TfrxInPlaceDataFiledEditor.CalcPopupBounds(out TopLeft: TPoint; out w, h: Integer);
|
||
|
var
|
||
|
r: TRect;
|
||
|
begin
|
||
|
r.Top := FRect.Top + GetButtonSize + 2;
|
||
|
r.Right := FRect.Right;
|
||
|
r.Left := r.Right - Round(140 * FDevicePPI / frx_DefaultPPI);
|
||
|
r.Bottom := r.Top + Round(162 * FDevicePPI / frx_DefaultPPI);
|
||
|
if r.Left < 0 then
|
||
|
begin
|
||
|
Inc(r.Right, -r.Left);
|
||
|
r.Left := 0;
|
||
|
end;
|
||
|
|
||
|
TopLeft := r.TopLeft;
|
||
|
w := Round((r.Right - r.Left) / (FDevicePPI / frx_DefaultPPI));
|
||
|
h := Round((r.Bottom - r.Top) / (FDevicePPI / frx_DefaultPPI));
|
||
|
end;
|
||
|
|
||
|
function TfrxInPlaceDataFiledEditor.DoCustomDragDrop(Source: TObject; X,
|
||
|
Y: Integer; var EventParams: TfrxInteractiveEventsParams): Boolean;
|
||
|
var
|
||
|
Memo: TfrxCustomMemoView;
|
||
|
View: TfrxView;
|
||
|
Node: TTreeNode;
|
||
|
i, nStart, nCount: Integer;
|
||
|
s: String;
|
||
|
begin
|
||
|
Result := False;
|
||
|
FDRawDragDrop := False;
|
||
|
Memo := nil;
|
||
|
nCount := 0;
|
||
|
nStart := 0;
|
||
|
if Component is TfrxCustomMemoView then
|
||
|
Memo := TfrxCustomMemoView(Component);
|
||
|
View := TfrxView(Component);
|
||
|
if (Source is TTreeView) and Assigned(View) then
|
||
|
begin
|
||
|
nCount := TTreeView(Source).SelectionCount - 1;
|
||
|
nStart := 0;
|
||
|
end
|
||
|
{ called from another editor with TfrxEventObject }
|
||
|
else if (Source is TfrxEventObject) and Assigned(View) then
|
||
|
begin
|
||
|
nStart := TfrxEventObject(Source).Index;
|
||
|
nCount := nStart;
|
||
|
Source := TfrxEventObject(Source).Sender;
|
||
|
end;
|
||
|
if (Source is TTreeView) then
|
||
|
|
||
|
with View do
|
||
|
for i := nCount downto nStart do
|
||
|
begin
|
||
|
Node := TTreeView(Source).Selections[i];
|
||
|
s := '';
|
||
|
EventParams.Refresh := True;
|
||
|
EventParams.Modified := True;
|
||
|
if (Node <> nil) and Assigned(Node.Data) and (TObject(Node.Data) is TfrxDataSet) then
|
||
|
s := Report.GetAlias(TfrxDataSet(Node.Data));
|
||
|
if s <> '' then
|
||
|
begin
|
||
|
Result := True;
|
||
|
if (nCount = nStart) or ((Memo = nil) and (i = nCount)) then
|
||
|
begin
|
||
|
DataSet := TfrxDataSet(Node.Data);
|
||
|
DataField := Node.Text;
|
||
|
Break;
|
||
|
end
|
||
|
else
|
||
|
begin
|
||
|
if i = nCount then
|
||
|
Memo.Text := '';
|
||
|
Memo.DataSet := nil;
|
||
|
Memo.DataField := '';
|
||
|
Memo.Text := Memo.Text + '[' + s + '."' + Node.Text + '"]';
|
||
|
end;
|
||
|
end
|
||
|
else if Assigned(Memo) then
|
||
|
begin
|
||
|
Result := True;
|
||
|
if i = nCount then
|
||
|
Memo.Text := '';
|
||
|
Memo.DataSet := nil;
|
||
|
Memo.DataField := '';
|
||
|
Memo.Text := Memo.Text + '[' + Node.Text + ']';
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TfrxInPlaceDataFiledEditor.DoCustomDragOver(Source: TObject; X,
|
||
|
Y: Integer; State: TDragState; var Accept: Boolean;
|
||
|
var EventParams: TfrxInteractiveEventsParams): Boolean;
|
||
|
var
|
||
|
View: TfrxView;
|
||
|
begin
|
||
|
Result := False;
|
||
|
View := nil;
|
||
|
if Component is TfrxView then
|
||
|
View := TfrxCustomMemoView(Component);
|
||
|
if (Source is TTreeView) and Assigned(View) then
|
||
|
begin
|
||
|
Accept := True;
|
||
|
Result := True;
|
||
|
FDrawDragDrop := True;
|
||
|
EventParams.Refresh := True;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TfrxInPlaceDataFiledEditor.DoLBClick(Sender: TObject);
|
||
|
var
|
||
|
i: Integer;
|
||
|
begin
|
||
|
if Component is TfrxView then
|
||
|
begin
|
||
|
TfrxView(Component).DataSet :=
|
||
|
GetParentDS;
|
||
|
TfrxView(Component).DataField :=
|
||
|
FListBox.Items[FListBox.ItemIndex];
|
||
|
end;
|
||
|
|
||
|
if Assigned(FComponents) then
|
||
|
for i := 0 to FComponents.Count - 1 do
|
||
|
if TObject(FComponents[i]) is Component.ClassType then
|
||
|
begin
|
||
|
TfrxView(FComponents[i]).DataSet :=
|
||
|
GetParentDS;
|
||
|
TfrxView(FComponents[i]).DataField :=
|
||
|
FListBox.Items[FListBox.ItemIndex];
|
||
|
end;
|
||
|
FModified := True;
|
||
|
FPopupForm.Hide;
|
||
|
end;
|
||
|
|
||
|
procedure TfrxInPlaceDataFiledEditor.FinalizeUI(var EventParams: TfrxInteractiveEventsParams);
|
||
|
begin
|
||
|
if not FLocked then
|
||
|
FDrawButton := False;
|
||
|
FDrawDragDrop := False;
|
||
|
end;
|
||
|
|
||
|
function TfrxInPlaceDataFiledEditor.GetButtonSize: Integer;
|
||
|
begin
|
||
|
Result := Round(frx_DefaultBtnSize * FDevicePPI / frx_DefaultPPI);
|
||
|
if (Result > FRect.Bottom - FRect.Top) and (Result > frx_DefaultBtnSize) then
|
||
|
Result := FRect.Bottom - FRect.Top;
|
||
|
Result := Result - Result mod 2;
|
||
|
end;
|
||
|
|
||
|
function TfrxInPlaceDataFiledEditor.GetParentDS: TfrxDataSet;
|
||
|
var
|
||
|
p: TfrxComponent;
|
||
|
begin
|
||
|
Result := nil;
|
||
|
p := FComponent.Parent;
|
||
|
while (p.Parent <> nil) and not(p is TfrxDataBand) do
|
||
|
p := p.Parent;
|
||
|
if (p is TfrxDataBand) then
|
||
|
Result := TfrxDataBand(p).DataSet;
|
||
|
end;
|
||
|
|
||
|
procedure TfrxInPlaceDataFiledEditor.InitializeUI(var EventParams: TfrxInteractiveEventsParams);
|
||
|
begin
|
||
|
inherited;
|
||
|
FModified := False;
|
||
|
FDrawButton := GetParentDS <> nil;
|
||
|
FDrawDragDrop := False;
|
||
|
UpdateRect;
|
||
|
end;
|
||
|
|
||
|
function TfrxInPlaceDataFiledEditor.IsFillListBox: Boolean;
|
||
|
var
|
||
|
ds: TfrxDataSet;
|
||
|
begin
|
||
|
ds := GetParentDS;
|
||
|
Result := ds <> nil;
|
||
|
if Result then
|
||
|
begin
|
||
|
ds.GetFieldList(FListBox.Items);
|
||
|
FListBox.ItemIndex := FListBox.Items.IndexOf(TfrxCustomMemoView(Component).DataField);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TfrxInPlaceDataFiledEditor.LBDrawItem(Control: TWinControl; Index: Integer; aRect: TRect; State: TOwnerDrawState);
|
||
|
begin
|
||
|
with FListBox do
|
||
|
begin
|
||
|
Canvas.FillRect(aRect);
|
||
|
frxResources.MainButtonImages.Draw(Canvas, aRect.Left, aRect.Top, 54);
|
||
|
Canvas.TextOut(aRect.Left + frxResources.MainButtonImages.Width + 2, aRect.Top + 1, Items[Index]);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TfrxInPlaceDataFiledEditor.ListBoxCreate: TListBox;
|
||
|
begin
|
||
|
Result := inherited ListBoxCreate;
|
||
|
Result.ItemHeight := ListBoxItemHeight;
|
||
|
end;
|
||
|
|
||
|
{ TfrxInPlaceBasePanelEditor }
|
||
|
|
||
|
procedure TfrxInPlaceBasePanelEditor.AfterConstruction;
|
||
|
begin
|
||
|
inherited;
|
||
|
FPosition := Point(1, 20);
|
||
|
end;
|
||
|
|
||
|
destructor TfrxInPlaceBasePanelEditor.Destroy;
|
||
|
begin
|
||
|
DestroyPanel;
|
||
|
inherited;
|
||
|
end;
|
||
|
|
||
|
function TfrxInPlaceBasePanelEditor.DestroyPanel: Boolean;
|
||
|
begin
|
||
|
Result := False;
|
||
|
if Assigned(FButtonsPanel) then
|
||
|
begin
|
||
|
Result := True;
|
||
|
FreeAndNil(FButtonsPanel);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TfrxInPlaceBasePanelEditor.DoMouseDown(X, Y: Integer; Button: TMouseButton;
|
||
|
Shift: TShiftState; var EventParams: TfrxInteractiveEventsParams): Boolean;
|
||
|
begin
|
||
|
Result := False;
|
||
|
FMouseDown := True;
|
||
|
end;
|
||
|
|
||
|
function TfrxInPlaceBasePanelEditor.DoMouseUp(X, Y: Integer; Button: TMouseButton;
|
||
|
Shift: TShiftState; var EventParams: TfrxInteractiveEventsParams): Boolean;
|
||
|
var
|
||
|
i: Integer;
|
||
|
btn: TfrxSwithcButton;
|
||
|
begin
|
||
|
Result := False;
|
||
|
if not Assigned(FButtonsPanel) or not FMouseDown then Exit;
|
||
|
FMouseDown := False;
|
||
|
btn := FButtonsPanel.DoClick(Round(X - (FComponent.AbsLeft + FComponent.Width) * FScale) + FButtonsPanel.CalcWidth - FPosition.X, Round(Y - FComponent.AbsTop * FScale) - FPosition.Y);
|
||
|
if btn <> nil then
|
||
|
for i := 0 to Count - 1 do
|
||
|
begin
|
||
|
if FSwitchMode then
|
||
|
begin
|
||
|
if (FButtonsPanel.Count > i) and (btn.Tag <> i) then
|
||
|
FButtonsPanel[i].Switch := False;
|
||
|
if btn.Switch = false and FSwitchMode then btn.Switch := True;
|
||
|
end;
|
||
|
Item[i] := FButtonsPanel[i].Switch;
|
||
|
end;
|
||
|
EventParams.Refresh := True;
|
||
|
end;
|
||
|
|
||
|
procedure TfrxInPlaceBasePanelEditor.DrawCustomEditor(aCanvas: TCanvas;
|
||
|
aRect: TRect);
|
||
|
begin
|
||
|
inherited;
|
||
|
if Assigned(FButtonsPanel) then
|
||
|
FButtonsPanel.Draw(aCanvas, aRect.Right - FButtonsPanel.CalcWidth - FPosition.X, aRect.Top + FPosition.Y);
|
||
|
end;
|
||
|
|
||
|
procedure TfrxInPlaceBasePanelEditor.FinalizeUI(var EventParams: TfrxInteractiveEventsParams);
|
||
|
begin
|
||
|
inherited;
|
||
|
EventParams.Refresh := DestroyPanel;
|
||
|
end;
|
||
|
|
||
|
function TfrxInPlaceBasePanelEditor.GetActiveRect: TRect;
|
||
|
begin
|
||
|
Result := inherited GetActiveRect;
|
||
|
end;
|
||
|
|
||
|
procedure TfrxInPlaceBasePanelEditor.InitializeUI(var EventParams: TfrxInteractiveEventsParams);
|
||
|
var
|
||
|
i: integer;
|
||
|
bFirst: Boolean;
|
||
|
begin
|
||
|
DestroyPanel;
|
||
|
EventParams.Refresh := True;
|
||
|
FButtonsPanel := TfrxSwitchButtonsPanel.Create;
|
||
|
FButtonsPanel.ShowColors := True;
|
||
|
FButtonsPanel.ShowCaption := True;
|
||
|
bFirst := True;
|
||
|
for i := 0 to Count - 1 do
|
||
|
if FButtonsPanel.Count - 1 < i then
|
||
|
with FButtonsPanel.AddButton(GetName(i)) do
|
||
|
begin
|
||
|
Switch := Item[i];
|
||
|
if bFirst and Switch then
|
||
|
begin
|
||
|
FSwitchMode := Switch and (EventParams.EventSender <> esDesigner);
|
||
|
bFirst := False;
|
||
|
end
|
||
|
else if Switch then
|
||
|
FSwitchMode := False;
|
||
|
Tag := i;
|
||
|
ColorTag := GetColor(i);
|
||
|
end;
|
||
|
FSwitchMode := FSwitchMode and (FButtonsPanel.Count > 1);
|
||
|
end;
|
||
|
|
||
|
{ TfrxInPlaceMemoEditor }
|
||
|
|
||
|
procedure TfrxInPlaceMemoEditor.InitControlFromComponent;
|
||
|
var
|
||
|
s: WideString;
|
||
|
MemoView: TfrxCustomMemoView;
|
||
|
function frxAlignToAlignment(HAlign: TfrxHAlign): TAlignment;
|
||
|
begin
|
||
|
case HAlign of
|
||
|
haLeft: Result := taLeftJustify;
|
||
|
haRight: Result := taRightJustify;
|
||
|
else
|
||
|
Result := taCenter;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
begin
|
||
|
MemoView := FComponent as TfrxCustomMemoView;
|
||
|
if not Assigned(MemoView) then Exit;
|
||
|
THackCustomMemo(FInPlaceMemo).WordWrap := MemoView.WordWrap;
|
||
|
THackCustomMemo(FInPlaceMemo).Alignment := frxAlignToAlignment(MemoView.HAlign);
|
||
|
s := MemoView.Text;
|
||
|
if (s <> '') and (s[Length(s)] = #10) then
|
||
|
Delete(s, Length(s) - 1, 2);
|
||
|
FInPlaceMemo.Text := s;
|
||
|
THackCustomMemo(FInPlaceMemo).Font.Assign(MemoView.Font);
|
||
|
THackCustomMemo(FInPlaceMemo).Font.Height := Round(THackCustomMemo(FInPlaceMemo).Font.Height * FScale);
|
||
|
end;
|
||
|
|
||
|
|
||
|
procedure TfrxInPlaceMemoEditor.InitComponentFromControl;
|
||
|
var
|
||
|
MemoView: TfrxCustomMemoView;
|
||
|
begin
|
||
|
MemoView := TfrxCustomMemoView(Component);
|
||
|
MemoView.Text := FInPlaceMemo.Text;
|
||
|
end;
|
||
|
|
||
|
{ TfrxInPlaceTextEditorBase }
|
||
|
|
||
|
procedure TfrxInPlaceTextEditorBase.CreateMemo;
|
||
|
begin
|
||
|
FInPlaceMemo := TUnicodeMemo.Create(nil);
|
||
|
end;
|
||
|
|
||
|
destructor TfrxInPlaceMemoEditorBase.Destroy;
|
||
|
begin
|
||
|
FInPlaceMemo.Free;
|
||
|
inherited;
|
||
|
end;
|
||
|
|
||
|
{ TfrxInPlaceBaseChoiceEditor }
|
||
|
|
||
|
function TfrxInPlaceBaseChoiceEditor.DoMouseDown(X, Y: Integer; Button: TMouseButton; Shift: TShiftState;
|
||
|
var EventParams: TfrxInteractiveEventsParams): Boolean;
|
||
|
begin
|
||
|
UpdateRect;
|
||
|
if not FLocked then
|
||
|
begin
|
||
|
OnFinishInPlace := EventParams.OnFinish;
|
||
|
ShowPopup(EventParams.Sender as TComponent, FRect, X, Y);
|
||
|
end;
|
||
|
Result := FLocked;
|
||
|
end;
|
||
|
|
||
|
function TfrxInPlaceBaseChoiceEditor.DoMouseMove(X, Y: Integer; Shift: TShiftState;
|
||
|
var EventParams: TfrxInteractiveEventsParams): Boolean;
|
||
|
begin
|
||
|
Result := False;
|
||
|
end;
|
||
|
|
||
|
procedure TfrxInPlaceBaseChoiceEditor.DoPopupHide(Sender: TObject);
|
||
|
begin
|
||
|
FLocked := False;
|
||
|
if Component <> nil then
|
||
|
DoFinishInPlace(Component, True, FModified);
|
||
|
FDrawDropDown := False;
|
||
|
OnFinishInPlace := nil;
|
||
|
FPopUpRect := Rect(0, 0, 0, 0);
|
||
|
end;
|
||
|
|
||
|
procedure TfrxInPlaceBaseChoiceEditor.DrawCustomEditor(aCanvas: TCanvas; aRect: TRect);
|
||
|
var
|
||
|
r: TRect;
|
||
|
rHeight, bSize: Integer;
|
||
|
begin
|
||
|
UpdateRect;
|
||
|
rHeight := FRect.Bottom - FRect.Top;
|
||
|
if FDrawDragDrop then
|
||
|
begin
|
||
|
frxResources.MainButtonImages.Draw(aCanvas, FRect.Left - 10,
|
||
|
FRect.Top + (rHeight - 5) div 2, 111);
|
||
|
TransparentFillRect(aCanvas.Handle, FRect.Left + 1, FRect.Top + 1,
|
||
|
FRect.Right - 1, FRect.Bottom - 1, clGray);
|
||
|
end;
|
||
|
if not FDrawButton then Exit;
|
||
|
// move same code to function
|
||
|
with aCanvas do
|
||
|
begin
|
||
|
bSize := GetButtonSize;
|
||
|
r.TopLeft := Point(FRect.Right - bSize, FRect.Top + 2);
|
||
|
r.BottomRight := Point(r.Left + bSize, r.Top + bSize);
|
||
|
DrawButtonFace(aCanvas, r, GetButtonBevelWidth, bsNew, False, False, False);
|
||
|
frxDrawArrow(aCanvas, r, clBlack, FDrawDropDown);
|
||
|
end;
|
||
|
// frxResources.WizardImages.Draw(aCanvas, aRect.Left + rWidth div 2 - 16, aRect.Top + rHeight div 2 - 16, Index, True);
|
||
|
end;
|
||
|
|
||
|
function TfrxInPlaceBaseChoiceEditor.GetActiveRect: TRect;
|
||
|
begin
|
||
|
if (FPopUpRect.Right <> 0) or (FPopUpRect.Bottom <> 0) then
|
||
|
Result := FPopUpRect
|
||
|
else
|
||
|
Result := inherited GetActiveRect;
|
||
|
end;
|
||
|
|
||
|
function TfrxInPlaceBaseChoiceEditor.GetButtonBevelWidth: Integer;
|
||
|
begin
|
||
|
Result := Round(GetButtonSize / frx_DefaultBtnSize);
|
||
|
end;
|
||
|
|
||
|
function TfrxInPlaceBaseChoiceEditor.ListBoxCreate: TListBox;
|
||
|
begin
|
||
|
Result := TListBox.Create(FPopupForm);
|
||
|
with Result do
|
||
|
begin
|
||
|
Parent := FPopupForm;
|
||
|
{$IFNDEF FPC}
|
||
|
Ctl3D := False;
|
||
|
{$ENDIF}
|
||
|
Align := alClient;
|
||
|
Style := lbOwnerDrawFixed;
|
||
|
OnClick := DoLBClick;
|
||
|
OnDrawItem := LBDrawItem;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TfrxInPlaceBaseChoiceEditor.ShowPopup(aParent: TComponent; aRect: TRect; X, Y: Integer): Boolean;
|
||
|
var
|
||
|
ButtonRect: TRect;
|
||
|
TopLeft: TPoint;
|
||
|
w, h: Integer;
|
||
|
c: TWinControl;
|
||
|
begin
|
||
|
Result := False;
|
||
|
|
||
|
ButtonRect := FRect;
|
||
|
ButtonRect.Left := ButtonRect.Right - GetButtonSize;
|
||
|
if not PtInRect(ButtonRect, Point(X, Y)) then
|
||
|
Exit;
|
||
|
|
||
|
FPopupForm := TfrxPopupForm.Create(aParent);
|
||
|
{$IFDEF FPC}
|
||
|
FPopupForm.PopupParent := Screen.ActiveForm;
|
||
|
{$ENDIF}
|
||
|
{$IFNDEF Linux}
|
||
|
FPopupForm.OnDestroy := DoPopupHide;
|
||
|
{$ENDIF}
|
||
|
|
||
|
FListBox := ListBoxCreate;
|
||
|
CalcPopupBounds(TopLeft, w, h);
|
||
|
FPopUpRect := Rect(0, 0, w, h);
|
||
|
c := aParent as TWinControl;
|
||
|
if c = nil then
|
||
|
c := Screen.ActiveForm;
|
||
|
TopLeft := c.ClientToScreen(TopLeft);
|
||
|
FPopupForm.SetBounds(TopLeft.X, TopLeft.Y, w, h);
|
||
|
|
||
|
if IsFillListBox then
|
||
|
begin
|
||
|
{$IFNDEF Linux}
|
||
|
FPopupForm.Show;
|
||
|
{$ELSE}
|
||
|
FPopupForm.ShowModal;
|
||
|
{$ENDIF}
|
||
|
FLocked := True;
|
||
|
Result := True;
|
||
|
FDrawDropDown := True;
|
||
|
{$IFDEF Linux}
|
||
|
DoPopupHide(Self);
|
||
|
{$ENDIF}
|
||
|
end
|
||
|
else
|
||
|
begin
|
||
|
FListBox.Free;
|
||
|
FPopupForm.Free;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TfrxInPlaceBaseChoiceEditor.UpdateRect;
|
||
|
begin
|
||
|
FRect := Rect(TfrxHackView(FComponent).FX, TfrxHackView(FComponent).FY, TfrxHackView(FComponent).FX1, TfrxHackView(FComponent).FY1);
|
||
|
end;
|
||
|
|
||
|
initialization
|
||
|
frxRegEditorsClasses.Register(TfrxMemoView, [TfrxInPlaceDataFiledEditor, TfrxInPlaceMemoEditor, TfrxInPlaceDataLinkEditor], [[evDesigner], [evDesigner, evPreview], [evDesigner, evPreview], [evDesigner]]);
|
||
|
frxRegEditorsClasses.Register(TfrxPictureView, [TfrxInPlaceDataFiledEditor, TfrxInPlaceDataLinkEditor], [[evDesigner], [evDesigner, evPreview]]);
|
||
|
frxRegEditorsClasses.Register(TfrxMasterData, [TfrxInPlaceBandEditor], [[evDesigner]]);
|
||
|
|
||
|
finalization
|
||
|
frxUnregisterEditorsClass(TfrxMemoView, TfrxInPlaceDataFiledEditor);
|
||
|
frxUnregisterEditorsClass(TfrxMemoView, TfrxInPlaceMemoEditor);
|
||
|
frxUnregisterEditorsClass(TfrxMemoView, TfrxInPlaceDataLinkEditor);
|
||
|
frxUnregisterEditorsClass(TfrxPictureView, TfrxInPlaceDataFiledEditor);
|
||
|
frxUnregisterEditorsClass(TfrxPictureView, TfrxInPlaceDataLinkEditor);
|
||
|
frxUnregisterEditorsClass(TfrxMasterData, TfrxInPlaceBandEditor);
|
||
|
end.
|