
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@6953 8e941d3f-bd1b-0410-a28a-d453659cc2b4
1464 lines
37 KiB
ObjectPascal
1464 lines
37 KiB
ObjectPascal
unit JvDesignImp;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
LCLProc, LCLType, LResources, LCLIntf, LMessages,
|
|
SysUtils, Classes, Controls, Graphics, Forms, ExtCtrls, Contnrs,
|
|
JvDesignUtils, JvDesignSurface;
|
|
|
|
const
|
|
cJvDesignDefaultHandleWidth = 8;
|
|
|
|
type
|
|
TJvDesignHandle = class(TCustomControl)
|
|
private
|
|
FResizeable: Boolean;
|
|
protected
|
|
function HandleRect(AIndex: Integer): TRect;
|
|
function HitRect(APoint: TPoint): Integer;
|
|
procedure Paint; override;
|
|
procedure PaintEdge(const ARect: TRect);
|
|
procedure PaintHandle(const ARect: TRect);
|
|
procedure WMEraseBkgnd(var Msg: TLMEraseBkgnd); message LM_ERASEBKGND;
|
|
property Resizeable: Boolean read FResizeable write FResizeable;
|
|
end;
|
|
|
|
TJvDesignHandles = class(TComponent)
|
|
private
|
|
FContainer: TWinControl;
|
|
FSelected: TControl;
|
|
FResizeable: Boolean;
|
|
protected
|
|
function GetHandleWidth: Integer;
|
|
function GetSelectionRect: TRect;
|
|
function SelectedToScreenRect(const ARect: TRect): TRect;
|
|
procedure CreateHandles;
|
|
procedure SetContainer(const Value: TWinControl);
|
|
procedure SetHandleRects(const ARect: TRect);
|
|
procedure SetResizeable(const Value: Boolean);
|
|
procedure SetSelected(const Value: TControl);
|
|
procedure ShowHideHandles(AShow: Boolean);
|
|
public
|
|
Handles: array [0..3] of TJvDesignHandle;
|
|
constructor Create(AOwner: TComponent); override;
|
|
function HitRect(X, Y: Integer): TJvDesignHandleId;
|
|
function SelectedToContainer(const APt: TPoint): TPoint;
|
|
procedure RepaintHandles;
|
|
procedure UpdateHandles;
|
|
property Container: TWinControl read FContainer write SetContainer;
|
|
property HandleWidth: Integer read GetHandleWidth;
|
|
property Resizeable: Boolean read FResizeable write SetResizeable;
|
|
property Selected: TControl read FSelected write SetSelected;
|
|
end;
|
|
|
|
TJvDesignSelector = class(TJvDesignCustomSelector)
|
|
private
|
|
FHandles: TObjectList;
|
|
FHandleWidth: Integer;
|
|
protected
|
|
function FindHandles(AValue: TControl): TJvDesignHandles;
|
|
function GetCount: Integer; override;
|
|
function GetHandles(AIndex: Integer): TJvDesignHandles;
|
|
function GetSelection(AIndex: Integer): TControl; override;
|
|
procedure SetHandles(AIndex: Integer; AValue: TJvDesignHandles);
|
|
procedure SetHandleWidth(AValue: Integer);
|
|
procedure SetSelection(AIndex: Integer; AValue: TControl); override;
|
|
procedure ShowHideResizeHandles;
|
|
property Handles[AIndex: Integer]: TJvDesignHandles read GetHandles write SetHandles;
|
|
public
|
|
constructor Create(ASurface: TJvDesignSurface); override;
|
|
destructor Destroy; override;
|
|
function GetClientControl(AControl: TControl): TControl; override;
|
|
function GetCursor(AX, AY: Integer): TCursor; override;
|
|
function GetHitHandle(AX, AY: Integer): TJvDesignHandleId; override;
|
|
function IsSelected(AValue: TControl): Boolean; override;
|
|
procedure AddToSelection(AValue: TControl); override;
|
|
procedure ClearSelection; override;
|
|
procedure RemoveFromSelection(AValue: TControl); override;
|
|
procedure Update; override;
|
|
published
|
|
property HandleWidth: Integer read FHandleWidth write SetHandleWidth default cJvDesignDefaultHandleWidth;
|
|
end;
|
|
|
|
TJvDesignCustomMouseTool = class(TObject)
|
|
protected
|
|
FDragRect: TRect;
|
|
public
|
|
procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
|
|
X, Y: Integer); virtual; abstract;
|
|
procedure MouseMove(Shift: TShiftState; X, Y: Integer); virtual; abstract;
|
|
procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
|
|
X, Y: Integer); virtual; abstract;
|
|
property DragRect: TRect read FDragRect write FDragRect;
|
|
end;
|
|
|
|
TJvDesignDragMode = (dmNone, dmMove, dmResize, dmSelect, dmCreate);
|
|
|
|
TJvDesignAction = (daSelectParent, daDelete, daCopy, daCut, daPaste,
|
|
daNudgeLeft, daNudgeRight, daNudgeUp, daNudgeDown, daGrowWidth,
|
|
daShrinkWidth, daGrowHeight, daShrinkHeight, daLastAction = MaxInt);
|
|
|
|
TJvDesignController = class(TJvDesignCustomController)
|
|
private
|
|
FClicked: TControl;
|
|
FDragMode: TJvDesignDragMode;
|
|
FDragRect: TRect;
|
|
FKeyDownShift: TShiftState;
|
|
FMouseIsDown: Boolean;
|
|
FMouseTool: TJvDesignCustomMouseTool;
|
|
protected
|
|
function GetDragRect: TRect; override;
|
|
function KeyDown(AKeyCode: Cardinal): Boolean; override;
|
|
function KeyUp(AKeyCode: Cardinal): Boolean; override;
|
|
function MouseDown(Button: TMouseButton; X, Y: Integer; TheMessage: TLMMouse): Boolean; override;
|
|
function MouseMove(X, Y: Integer; TheMessage: TLMMouse): Boolean; override;
|
|
function MouseUp(Button: TMouseButton; X, Y: Integer; TheMessage: TLMMouse): Boolean; override;
|
|
procedure Action(AAction: TJvDesignAction);
|
|
end;
|
|
|
|
TJvDesignMouseTool = class(TJvDesignCustomMouseTool)
|
|
private
|
|
FSurface: TJvDesignSurface;
|
|
FMouseLast: TPoint;
|
|
FMouseStart: TPoint;
|
|
protected
|
|
function GetMouseDelta: TPoint; virtual;
|
|
public
|
|
constructor Create(AOwner: TJvDesignSurface); virtual;
|
|
property Surface: TJvDesignSurface read FSurface write FSurface;
|
|
end;
|
|
|
|
TJvDesignMover = class(TJvDesignMouseTool)
|
|
private
|
|
FDragRects: array of TRect;
|
|
protected
|
|
procedure ApplyDragRects;
|
|
procedure CalcDragRects;
|
|
procedure CalcPaintRects;
|
|
procedure PaintDragRects;
|
|
public
|
|
constructor Create(AOwner: TJvDesignSurface); override;
|
|
procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
|
|
X, Y: Integer); override;
|
|
procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
|
|
procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
|
|
X, Y: Integer); override;
|
|
end;
|
|
|
|
TJvDesignBander = class(TJvDesignMouseTool)
|
|
protected
|
|
function GetClient: TControl; virtual;
|
|
function GetPaintRect: TRect;
|
|
procedure CalcDragRect; virtual;
|
|
procedure PaintDragRect; virtual;
|
|
public
|
|
procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
|
|
X, Y: Integer); override;
|
|
procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
|
|
procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
|
|
X, Y: Integer); override;
|
|
end;
|
|
|
|
TJvDesignSizer = class(TJvDesignBander)
|
|
private
|
|
FHandleId: TJvDesignHandleId;
|
|
protected
|
|
function GetClient: TControl; override;
|
|
procedure ApplyDragRect;
|
|
procedure ApplyMouseDelta(X, Y: Integer);
|
|
procedure CalcDragRect; override;
|
|
public
|
|
constructor CreateSizer(AOwner: TJvDesignSurface; AHandle: TJvDesignHandleId);
|
|
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
|
|
end;
|
|
|
|
TJvDesignDesigner = class(TIDesigner)// TComponent, IDesignerHook)
|
|
private
|
|
FMessenger: TJvDesignCustomMessenger;
|
|
public
|
|
DDC: TDesignerDeviceContext;
|
|
constructor Create(AMessenger: TJvDesignCustomMessenger); reintroduce;
|
|
// IDesignerNotify interface
|
|
procedure Modified;
|
|
procedure Notification(AnObject: TPersistent; Operation: TOperation); reintroduce;
|
|
|
|
// IDesigner, IDesignerHook interface
|
|
function GetCustomForm: TCustomForm;
|
|
procedure SetCustomForm(Value: TCustomForm);
|
|
function GetIsControl: Boolean;
|
|
procedure SetIsControl(Value: Boolean);
|
|
function IsDesignMsg(Sender: TControl; var Msg: TLMessage): Boolean; override;
|
|
procedure PaintGrid; override;
|
|
procedure ValidateRename(AComponent: TComponent; const CurName, NewName: string); reintroduce;
|
|
function UniqueName(const BaseName: string): string; override;
|
|
function GetRoot: TComponent;
|
|
//{$IFDEF COMPILER9_UP}
|
|
//procedure PaintMenu;
|
|
//{$ENDIF COMPILER9_UP}
|
|
property Messenger: TJvDesignCustomMessenger read FMessenger write FMessenger;
|
|
property IsControl: Boolean read GetIsControl write SetIsControl;
|
|
property Form: TCustomForm read GetCustomForm write SetCustomForm;
|
|
end;
|
|
|
|
|
|
{TJvDesignDesigner = class(TIDesigner) //class(TComponent, IDesignerHook)
|
|
private
|
|
FMessenger: TJvDesignCustomMessenger;
|
|
public
|
|
constructor Create(AMessenger: TJvDesignCustomMessenger); reintroduce;
|
|
// IDesignerNotify interface
|
|
procedure Modified;
|
|
procedure Notification(AnObject: TPersistent; Operation: TOperation); reintroduce;
|
|
|
|
// IDesigner, IDesignerHook interface
|
|
function GetCustomForm: TCustomForm;
|
|
procedure SetCustomForm(Value: TCustomForm);
|
|
function GetIsControl: Boolean;
|
|
procedure SetIsControl(Value: Boolean);
|
|
function IsDesignMsg(Sender: TControl; var Msg: TMessage): Boolean;
|
|
procedure PaintGrid;
|
|
procedure ValidateRename(AComponent: TComponent; const CurName, NewName: string); reintroduce;
|
|
function UniqueName(const BaseName: string): string;
|
|
function GetRoot: TComponent;
|
|
{$IFDEF COMPILER9_UP}
|
|
procedure PaintMenu;
|
|
{$ENDIF COMPILER9_UP}
|
|
property Messenger: TJvDesignCustomMessenger read FMessenger write FMessenger;
|
|
property IsControl: Boolean read GetIsControl write SetIsControl;
|
|
property Form: TCustomForm read GetCustomForm write SetCustomForm;
|
|
end; }
|
|
|
|
TJvDesignDesignerMessenger = class(TJvDesignCustomMessenger)
|
|
private
|
|
FDesignedForm: TCustomForm;
|
|
FDesigner: TJvDesignDesigner;
|
|
protected
|
|
procedure SetComponentDesigning(AComponent: TComponent; ADesigning: Boolean);
|
|
procedure SetContainer(AValue: TWinControl); override;
|
|
procedure UndesignComponent(AComponent: TComponent);
|
|
public
|
|
constructor Create; override;
|
|
destructor Destroy; override;
|
|
procedure DesignComponent(AComponent: TComponent; ADesigning: Boolean); override;
|
|
end;
|
|
|
|
TJvDesignMessageHookList = class(TComponent)
|
|
private
|
|
FHooks: TObjectList;
|
|
FUser: TJvDesignCustomMessenger;
|
|
protected
|
|
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
|
|
public
|
|
constructor Create(AUser: TJvDesignCustomMessenger); reintroduce;
|
|
destructor Destroy; override;
|
|
procedure Clear;
|
|
procedure Hook(AClient: TWinControl);
|
|
procedure Unhook(AComponent: TComponent);
|
|
end;
|
|
|
|
TJvDesignWinControlHookMessenger = class(TJvDesignCustomMessenger)
|
|
private
|
|
FHooks: TJvDesignMessageHookList;
|
|
protected
|
|
procedure HookWinControl(AWinControl: TWinControl);
|
|
procedure UnhookWinControl(AWinControl: TWinControl);
|
|
procedure SetContainer(AValue: TWinControl); override;
|
|
public
|
|
constructor Create; override;
|
|
destructor Destroy; override;
|
|
procedure Clear; override;
|
|
procedure DesignComponent(AComponent: TComponent; ADesigning: Boolean); override;
|
|
end;
|
|
|
|
|
|
implementation
|
|
|
|
uses
|
|
JvResources, JvTypes;
|
|
|
|
var
|
|
ShadedBits: TBitmap;
|
|
|
|
function NeedShadedBits: TBitmap;
|
|
begin
|
|
if ShadedBits = nil then
|
|
begin
|
|
ShadedBits := TBitmap.Create;
|
|
with ShadedBits do
|
|
begin
|
|
Width := 4;
|
|
Height := 2;
|
|
Canvas.Pixels[0, 0] := clGray;
|
|
Canvas.Pixels[1, 0] := clBtnFace;
|
|
Canvas.Pixels[2, 0] := clBtnFace;
|
|
Canvas.Pixels[3, 0] := clBtnFace;
|
|
Canvas.Pixels[0, 1] := clBtnFace;
|
|
Canvas.Pixels[1, 1] := clBtnFace;
|
|
Canvas.Pixels[2, 1] := clGray;
|
|
Canvas.Pixels[3, 1] := clBtnFace;
|
|
end;
|
|
end;
|
|
Result := ShadedBits;
|
|
end;
|
|
|
|
procedure FreeShadedBits;
|
|
begin
|
|
FreeAndNil(ShadedBits);
|
|
end;
|
|
|
|
//=== { TJvDesignHandle } ====================================================
|
|
|
|
function TJvDesignHandle.HandleRect(AIndex: Integer): TRect;
|
|
var
|
|
W: Integer;
|
|
begin
|
|
W := TJvDesignHandles(Owner).HandleWidth;
|
|
case AIndex of
|
|
0:
|
|
Result := Rect(0, 0, W, W); // left-top
|
|
1:
|
|
Result := Rect((Width - W) div 2, 0, (Width + W) div 2, W); // middle-top
|
|
2:
|
|
Result := Rect(Width - W, 0, Width, W); // right-top
|
|
3:
|
|
Result := Rect(0, (Height - W) div 2, W, (Height + W) div 2); // left-center
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDesignHandle.WMEraseBkgnd(var Msg: TLMEraseBkgnd);
|
|
begin
|
|
Msg.Result := 1;
|
|
end;
|
|
|
|
procedure TJvDesignHandle.PaintHandle(const ARect: TRect);
|
|
begin
|
|
Canvas.Rectangle(ARect);
|
|
end;
|
|
|
|
procedure TJvDesignHandle.PaintEdge(const ARect: TRect);
|
|
begin
|
|
Canvas.FillRect(ClientRect);
|
|
end;
|
|
|
|
procedure TJvDesignHandle.Paint;
|
|
begin
|
|
//CV with Canvas. do
|
|
begin
|
|
Canvas.Brush.Bitmap := NeedShadedBits;
|
|
PaintEdge(ClientRect);
|
|
Canvas.Brush.Bitmap := nil;
|
|
Brush.Color := clWhite;
|
|
Canvas.Pen.Color := clBlack;
|
|
if Resizeable then
|
|
if Width > Height then
|
|
begin
|
|
PaintHandle(HandleRect(0));
|
|
PaintHandle(HandleRect(1));
|
|
PaintHandle(HandleRect(2));
|
|
end
|
|
else
|
|
begin
|
|
PaintHandle(HandleRect(3));
|
|
end
|
|
end;
|
|
end;
|
|
|
|
function TJvDesignHandle.HitRect(APoint: TPoint): Integer;
|
|
begin
|
|
Result := -1;
|
|
if Width > Height then
|
|
if PtInRect(HandleRect(0), APoint) then
|
|
Result := 0
|
|
else
|
|
if PtInRect(HandleRect(1), APoint) then
|
|
Result := 1
|
|
else
|
|
if PtInRect(HandleRect(2), APoint) then
|
|
Result := 2;
|
|
if Result < 0 then
|
|
if PtInRect(HandleRect(3), APoint) then
|
|
Result := 3;
|
|
end;
|
|
|
|
//=== { TJvDesignHandles } ===================================================
|
|
|
|
constructor TJvDesignHandles.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
CreateHandles;
|
|
Resizeable := True;
|
|
end;
|
|
|
|
procedure TJvDesignHandles.CreateHandles;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := Low(Handles) to High(Handles) do
|
|
Handles[I] := TJvDesignHandle.Create(Self);
|
|
end;
|
|
|
|
function TJvDesignHandles.GetHandleWidth: Integer;
|
|
begin
|
|
Result := TJvDesignSelector(Owner).HandleWidth;
|
|
end;
|
|
|
|
procedure TJvDesignHandles.SetContainer(const Value: TWinControl);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
FContainer := Value;
|
|
for I := Low(Handles) to High(Handles) do
|
|
with Handles[I] do
|
|
begin
|
|
Visible := False;
|
|
Parent := Container;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDesignHandles.SetSelected(const Value: TControl);
|
|
begin
|
|
if Selected <> Value then
|
|
begin
|
|
if Value is TJvDesignHandle then
|
|
FSelected := nil
|
|
else
|
|
FSelected := Value;
|
|
UpdateHandles;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDesignHandles.SetResizeable(const Value: Boolean);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
FResizeable := Value;
|
|
for I := Low(Handles) to High(Handles) do
|
|
Handles[I].Resizeable := Value;
|
|
end;
|
|
|
|
procedure TJvDesignHandles.ShowHideHandles(AShow: Boolean);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := Low(Handles) to High(Handles) do
|
|
with Handles[I] do
|
|
begin
|
|
Visible := AShow;
|
|
if AShow then
|
|
BringToFront;
|
|
Update;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDesignHandles.UpdateHandles;
|
|
begin
|
|
if (Selected <> nil) and (Container <> nil) and (Selected <> Container) then
|
|
begin
|
|
SetHandleRects(GetSelectionRect);
|
|
ShowHideHandles(True);
|
|
end
|
|
else
|
|
ShowHideHandles(False)
|
|
end;
|
|
|
|
procedure TJvDesignHandles.RepaintHandles;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := Low(Handles) to High(Handles) do
|
|
Handles[I].Repaint;
|
|
end;
|
|
|
|
function TJvDesignHandles.HitRect(X, Y: Integer): TJvDesignHandleId;
|
|
const
|
|
cRectIds: array [0..3, 0..3] of TJvDesignHandleId =
|
|
(
|
|
(dhLeftTop, dhMiddleTop, dhRightTop, dhNone),
|
|
(dhNone, dhNone, dhNone, dhLeftMiddle),
|
|
(dhNone, dhNone, dhNone, dhRightMiddle),
|
|
(dhLeftBottom, dhMiddleBottom, dhRightBottom, dhNone)
|
|
);
|
|
var
|
|
I, R: Integer;
|
|
begin
|
|
for I := 0 to 3 do
|
|
begin
|
|
with Handles[I] do
|
|
R := HitRect(Point(X - Left, Y - Top));
|
|
if R >= 0 then
|
|
begin
|
|
Result := cRectIds[I][R];
|
|
Exit;
|
|
end;
|
|
end;
|
|
Result := dhNone;
|
|
end;
|
|
|
|
function TJvDesignHandles.SelectedToContainer(const APt: TPoint): TPoint;
|
|
var
|
|
C: TControl;
|
|
begin
|
|
Result := APt;
|
|
C := Selected.Parent;
|
|
while (C <> Container) and (C <> nil) do
|
|
begin
|
|
Inc(Result.X, C.Left);
|
|
Inc(Result.Y, C.Top);
|
|
C := C.Parent;
|
|
end;
|
|
end;
|
|
|
|
function TJvDesignHandles.SelectedToScreenRect(const ARect: TRect): TRect;
|
|
var
|
|
P: TWinControl;
|
|
begin
|
|
if Selected = Container then
|
|
P := Container
|
|
else
|
|
P := Selected.Parent;
|
|
Result.TopLeft := P.ClientToScreen(ARect.TopLeft);
|
|
Result.BottomRight := P.ClientToScreen(ARect.BottomRight);
|
|
end;
|
|
|
|
function TJvDesignHandles.GetSelectionRect: TRect;
|
|
var
|
|
P: TPoint;
|
|
begin
|
|
if Selected = Container then
|
|
P := Point(0, 0)
|
|
else
|
|
P := SelectedToContainer(Selected.BoundsRect.TopLeft);
|
|
Result := Rect(P.X, P.Y, P.X + Selected.Width, P.Y + Selected.Height);
|
|
InflateRect(Result, -HandleWidth div 2, -HandleWidth div 2);
|
|
end;
|
|
|
|
procedure TJvDesignHandles.SetHandleRects(const ARect: TRect);
|
|
var
|
|
W: Integer;
|
|
begin
|
|
W := HandleWidth;
|
|
with ARect do
|
|
begin
|
|
Handles[0].BoundsRect := Rect(Left - W, Top - W, Right + W, Top);
|
|
Handles[1].BoundsRect := Rect(Left - W, Top, Left, Bottom);
|
|
Handles[2].BoundsRect := Rect(Right, Top, Right + W, Bottom);
|
|
Handles[3].BoundsRect := Rect(Left - W, Bottom, Right + W, Bottom + W);
|
|
end;
|
|
end;
|
|
|
|
//=== { TJvDesignSelector } ==================================================
|
|
|
|
constructor TJvDesignSelector.Create(ASurface: TJvDesignSurface);
|
|
begin
|
|
inherited Create(ASurface);
|
|
//ControllerClass := TJvDesignController;
|
|
FHandleWidth := cJvDesignDefaultHandleWidth;
|
|
FHandles := TObjectList.Create;
|
|
end;
|
|
|
|
destructor TJvDesignSelector.Destroy;
|
|
begin
|
|
FHandles.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TJvDesignSelector.SetHandleWidth(AValue: Integer);
|
|
begin
|
|
FHandleWidth := AValue;
|
|
Update;
|
|
end;
|
|
|
|
function TJvDesignSelector.GetCount: Integer;
|
|
begin
|
|
Result := FHandles.Count;
|
|
end;
|
|
|
|
function TJvDesignSelector.GetHandles(AIndex: Integer): TJvDesignHandles;
|
|
begin
|
|
Result := TJvDesignHandles(FHandles[AIndex]);
|
|
end;
|
|
|
|
procedure TJvDesignSelector.SetHandles(AIndex: Integer; AValue: TJvDesignHandles);
|
|
begin
|
|
FHandles[AIndex] := AValue;
|
|
end;
|
|
|
|
function TJvDesignSelector.GetSelection(AIndex: Integer): TControl;
|
|
begin
|
|
Result := Handles[AIndex].Selected;
|
|
end;
|
|
|
|
procedure TJvDesignSelector.SetSelection(AIndex: Integer; AValue: TControl);
|
|
begin
|
|
Handles[AIndex].Selected := AValue;
|
|
end;
|
|
|
|
function TJvDesignSelector.FindHandles(AValue: TControl): TJvDesignHandles;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := nil;
|
|
for I := 0 to Count - 1 do
|
|
begin
|
|
Result := Handles[I];
|
|
if Result.Selected = AValue then
|
|
Break
|
|
else
|
|
Result := nil;
|
|
end;
|
|
end;
|
|
|
|
function TJvDesignSelector.IsSelected(AValue: TControl): Boolean;
|
|
begin
|
|
Result := FindHandles(AValue) <> nil;
|
|
end;
|
|
|
|
procedure TJvDesignSelector.ClearSelection;
|
|
begin
|
|
//if not (csDestroying in ComponentState) then
|
|
FHandles.Clear;
|
|
end;
|
|
|
|
procedure TJvDesignSelector.ShowHideResizeHandles;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to Count - 1 do
|
|
with Handles[I] do
|
|
begin
|
|
Resizeable := (Count = 1);
|
|
RepaintHandles;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDesignSelector.AddToSelection(AValue: TControl);
|
|
var
|
|
H: TJvDesignHandles;
|
|
begin
|
|
if AValue = nil then
|
|
raise EJVCLException.CreateRes(@RsEDesignCannotSelect);
|
|
if not IsSelected(AValue) then
|
|
begin
|
|
H := TJvDesignHandles.Create(Self);
|
|
H.Container := Surface.Container;
|
|
H.Resizeable := Count = 0;
|
|
FHandles.Add(H);
|
|
H.Selected := AValue;
|
|
if Count = 2 then
|
|
ShowHideResizeHandles
|
|
else
|
|
H.UpdateHandles;
|
|
Surface.Messenger.DesignComponent(H.Handles[0], True);
|
|
Surface.Messenger.DesignComponent(H.Handles[1], True);
|
|
Surface.Messenger.DesignComponent(H.Handles[2], True);
|
|
Surface.Messenger.DesignComponent(H.Handles[3], True);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDesignSelector.RemoveFromSelection(AValue: TControl);
|
|
begin
|
|
if IsSelected(AValue) then
|
|
begin
|
|
FHandles.Remove(FindHandles(AValue));
|
|
Surface.SelectionChange;
|
|
end;
|
|
end;
|
|
|
|
function TJvDesignSelector.GetClientControl(AControl: TControl): TControl;
|
|
begin
|
|
if AControl is TJvDesignHandle then
|
|
Result := TJvDesignHandles(AControl.Owner).Selected
|
|
else
|
|
Result := AControl;
|
|
end;
|
|
|
|
procedure TJvDesignSelector.Update;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to Count - 1 do
|
|
Handles[I].UpdateHandles;
|
|
end;
|
|
|
|
function TJvDesignSelector.GetHitHandle(AX, AY: Integer): TJvDesignHandleId;
|
|
begin
|
|
if Count > 0 then
|
|
Result := Handles[0].HitRect(AX, AY)
|
|
else
|
|
Result := dhNone;
|
|
end;
|
|
|
|
function TJvDesignSelector.GetCursor(AX, AY: Integer): TCursor;
|
|
const
|
|
cCurs: array[TJvDesignHandleId] of TCursor =
|
|
(crHandPoint, crSizeNWSE, crSizeNS, crSizeNESW, crSizeWE, crSizeWE,
|
|
crSizeNESW, crSizeNS, crSizeNWSE);
|
|
begin
|
|
Result := cCurs[GetHitHandle(AX, AY)];
|
|
end;
|
|
|
|
//=== { TJvDesignController } ================================================
|
|
|
|
procedure TJvDesignController.Action(AAction: TJvDesignAction);
|
|
begin
|
|
with Surface do
|
|
case AAction of
|
|
daSelectParent:
|
|
SelectParent;
|
|
daDelete:
|
|
DeleteComponents;
|
|
daCopy:
|
|
CopyComponents;
|
|
daCut:
|
|
CutComponents;
|
|
daPaste:
|
|
PasteComponents;
|
|
daNudgeLeft:
|
|
NudgeComponents(-1, 0);
|
|
daNudgeRight:
|
|
NudgeComponents(1, 0);
|
|
daNudgeUp:
|
|
NudgeComponents(0, -1);
|
|
daNudgeDown:
|
|
NudgeComponents(0, 1);
|
|
daGrowWidth:
|
|
GrowComponents(1, 0);
|
|
daShrinkWidth:
|
|
GrowComponents(-1, 0);
|
|
daGrowHeight:
|
|
GrowComponents(0, 1);
|
|
daShrinkHeight:
|
|
GrowComponents(0, -1);
|
|
end;
|
|
Surface.UpdateDesigner;
|
|
end;
|
|
|
|
function TJvDesignController.GetDragRect: TRect;
|
|
begin
|
|
Result := FDragRect;
|
|
end;
|
|
|
|
function TJvDesignController.KeyDown(AKeyCode: Cardinal): Boolean;
|
|
|
|
function CtrlKeys: Boolean;
|
|
begin
|
|
Result := True;
|
|
case AKeyCode of
|
|
VK_LEFT:
|
|
Action(daNudgeLeft);
|
|
VK_RIGHT:
|
|
Action(daNudgeRight);
|
|
VK_UP:
|
|
Action(daNudgeUp);
|
|
VK_DOWN:
|
|
Action(daNudgeDown);
|
|
else
|
|
Result := False;
|
|
end;
|
|
end;
|
|
|
|
function ShiftKeys: Boolean;
|
|
begin
|
|
Result := True;
|
|
case AKeyCode of
|
|
VK_LEFT:
|
|
Action(daShrinkWidth);
|
|
VK_RIGHT:
|
|
Action(daGrowWidth);
|
|
VK_UP:
|
|
Action(daShrinkHeight);
|
|
VK_DOWN:
|
|
Action(daGrowHeight);
|
|
else
|
|
Result := False;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
FKeyDownShift := Shift666;
|
|
if ssCtrl in FKeyDownShift then
|
|
Result := CtrlKeys
|
|
else
|
|
if ssShift in FKeyDownShift then
|
|
Result := ShiftKeys
|
|
else
|
|
Result := False;
|
|
end;
|
|
|
|
function TJvDesignController.KeyUp(AKeyCode: Cardinal): Boolean;
|
|
|
|
function Keys: Boolean;
|
|
begin
|
|
Result := True;
|
|
case AKeyCode of
|
|
VK_ESCAPE:
|
|
Action(daSelectParent);
|
|
VK_DELETE:
|
|
Action(daDelete);
|
|
else
|
|
Result := False;
|
|
end;
|
|
end;
|
|
|
|
function CtrlKeys: Boolean;
|
|
begin
|
|
Result := True;
|
|
case AKeyCode of
|
|
Ord('C'):
|
|
Action(daCopy);
|
|
Ord('X'):
|
|
Action(daCut);
|
|
Ord('V'):
|
|
Action(daPaste);
|
|
else
|
|
Result := False;
|
|
end;
|
|
end;
|
|
|
|
function ShiftKeys: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
begin
|
|
FKeyDownShift := FKeyDownShift + Shift666;
|
|
if ssCtrl in FKeyDownShift then
|
|
Result := CtrlKeys
|
|
else
|
|
if ssShift in FKeyDownShift then
|
|
Result := ShiftKeys
|
|
else
|
|
Result := Keys;
|
|
FKeyDownShift := [];
|
|
end;
|
|
|
|
function TJvDesignController.MouseDown(Button: TMouseButton; X, Y: Integer; TheMessage: TLMMouse): Boolean;
|
|
var
|
|
HandleId: TJvDesignHandleId;
|
|
|
|
procedure CaptureMouse;
|
|
begin
|
|
FMouseIsDown := True;
|
|
Mouse.Capture := Surface.Container.Handle;
|
|
end;
|
|
|
|
procedure FocusSurface;
|
|
var
|
|
WasActive: Boolean;
|
|
begin
|
|
if not Surface.Container.Focused and Surface.Container.CanFocus then
|
|
begin
|
|
// Mantis 4732: deactivate the container otherwise SetFocus does not work
|
|
// This bug apparently only happens under certain rare conditions
|
|
// under windows but its fix does not seem to have any negative impact
|
|
// on systems where it does not happen.
|
|
WasActive := TJvDesignPanel(Surface.Container).Active;
|
|
if WasActive then
|
|
TJvDesignPanel(Surface.Container).Active := False;
|
|
|
|
Surface.Container.SetFocus;
|
|
|
|
if WasActive then
|
|
TJvDesignPanel(Surface.Container).Active := True;
|
|
end;
|
|
end;
|
|
|
|
procedure SelectDragMode;
|
|
begin
|
|
HandleId := dhNone;
|
|
if ssCtrl in Shift666 then
|
|
// Ctrl-drag selection has highest priority
|
|
FDragMode := dmSelect
|
|
else
|
|
begin
|
|
HandleId := Surface.GetHitHandle(X, Y);
|
|
if HandleId <> dhNone then
|
|
begin
|
|
FClicked := Surface.Selection[0];
|
|
FDragMode := dmResize;
|
|
end
|
|
else
|
|
begin
|
|
FClicked := Surface.FindControl(X, Y);
|
|
if (FClicked = Surface.Container) or (FClicked is TJvDesignHandle) then
|
|
FClicked := nil;
|
|
Surface.GetAddClass;
|
|
if Surface.AddClass <> '' then
|
|
// then object creation
|
|
FDragMode := dmCreate
|
|
else
|
|
if FClicked <> nil then
|
|
// moving is last
|
|
FDragMode := dmMove
|
|
else
|
|
// select by default
|
|
FDragMode := dmSelect;
|
|
end;
|
|
end;
|
|
if FClicked = nil then
|
|
FClicked := Surface.Container;
|
|
FClicked.Parent.DisableAlign;
|
|
end;
|
|
|
|
procedure CreateMouseTool;
|
|
begin
|
|
case FDragMode of
|
|
dmSelect, dmCreate:
|
|
begin
|
|
Surface.ClearSelection;
|
|
FMouseTool := TJvDesignBander.Create(Surface);
|
|
end;
|
|
dmMove:
|
|
begin
|
|
if ssShift in Shift666 then
|
|
Surface.Selector.AddToSelection(FClicked)
|
|
else
|
|
if not Surface.Selector.IsSelected(FClicked) then
|
|
Surface.Select(FClicked);
|
|
FMouseTool := TJvDesignMover.Create(Surface);
|
|
end;
|
|
dmResize:
|
|
begin
|
|
if not Surface.Selector.IsSelected(FClicked) then
|
|
Surface.Select(FClicked);
|
|
FMouseTool := TJvDesignSizer.CreateSizer(Surface, HandleId);
|
|
end;
|
|
end;
|
|
if FMouseTool <> nil then
|
|
FMouseTool.MouseDown(Button, Shift666, X, Y);
|
|
end;
|
|
|
|
begin
|
|
Shift666 := [];
|
|
if (TheMessage.Keys and MK_Shift) = MK_Shift then
|
|
Shift666 := Shift666 + [ssShift];
|
|
if (TheMessage.Keys and MK_Control) = MK_Control then
|
|
Shift666 := Shift666 + [ssCtrl];
|
|
FocusSurface;
|
|
CaptureMouse;
|
|
SelectDragMode;
|
|
CreateMouseTool;
|
|
Result := True;
|
|
end;
|
|
|
|
function TJvDesignController.MouseMove(X, Y: Integer; TheMessage: TLMMouse): Boolean;
|
|
begin
|
|
Shift666 := [];
|
|
if (TheMessage.Keys and MK_Shift) = MK_Shift then
|
|
Shift666 := Shift666 + [ssShift];
|
|
if (TheMessage.Keys and MK_Control) = MK_Control then
|
|
Shift666 := Shift666 + [ssCtrl];
|
|
|
|
if not FMouseIsDown then
|
|
SetCursor(Screen.Cursors[Surface.GetCursor(X, Y)])
|
|
else
|
|
begin
|
|
if FMouseTool <> nil then
|
|
FMouseTool.MouseMove(Shift666, X, Y);
|
|
end;
|
|
Result := True;
|
|
end;
|
|
|
|
function TJvDesignController.MouseUp(Button: TMouseButton; X, Y: Integer; TheMessage: TLMMouse): Boolean;
|
|
|
|
procedure ReleaseMouse;
|
|
begin
|
|
FMouseIsDown := False;
|
|
Mouse.Capture := 0;
|
|
end;
|
|
|
|
procedure EnableAlign;
|
|
begin
|
|
// If the debugger breaks in during a mouse operation,
|
|
// AlignDisabled can become stuck.
|
|
// This routine is to aid debugging only.
|
|
if FClicked <> nil then
|
|
//cv while FClicked.Parent.AlignDisabled do
|
|
FClicked.Parent.EnableAlign;
|
|
end;
|
|
|
|
procedure FinishMouseTool;
|
|
begin
|
|
if FMouseTool <> nil then
|
|
try
|
|
FMouseTool.MouseUp(Button, Shift666, X, Y);
|
|
FDragRect := DesignValidateRect(FMouseTool.DragRect);
|
|
case FDragMode of
|
|
dmCreate:
|
|
begin
|
|
if FClicked <> nil then
|
|
Surface.Select(FClicked);
|
|
Surface.AddComponent;
|
|
end;
|
|
else
|
|
Surface.SelectionChange;
|
|
end;
|
|
finally
|
|
FreeAndNil(FMouseTool);
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
Shift666 := [];
|
|
if (TheMessage.Keys and MK_Shift) = MK_Shift then
|
|
Shift666 := Shift666 + [ssShift];
|
|
if (TheMessage.Keys and MK_Control) = MK_Control then
|
|
Shift666 := Shift666 + [ssCtrl];
|
|
|
|
if FMouseIsDown then
|
|
begin
|
|
ReleaseMouse;
|
|
EnableAlign;
|
|
FinishMouseTool;
|
|
// We have to call UpdateDesigner for GraphicControls because they don't get
|
|
// WM_WINDOWPOSCHANGED messages that update the designer handles.
|
|
//CV LINUX if FClicked is TGraphicControl then
|
|
Surface.UpdateDesigner;
|
|
FClicked := nil;
|
|
end;
|
|
Result := True;
|
|
end;
|
|
|
|
//=== { TJvDesignMouseTool } =================================================
|
|
|
|
constructor TJvDesignMouseTool.Create(AOwner: TJvDesignSurface);
|
|
begin
|
|
Surface := AOwner;
|
|
end;
|
|
|
|
function TJvDesignMouseTool.GetMouseDelta: TPoint;
|
|
const
|
|
GridX = 4;
|
|
GridY = 4;
|
|
begin
|
|
with Result do
|
|
begin
|
|
X := FMouseLast.X - FMouseStart.X;
|
|
Dec(X, X mod GridX);
|
|
Y := FMouseLast.Y - FMouseStart.Y;
|
|
Dec(Y, Y mod GridY);
|
|
end;
|
|
end;
|
|
|
|
//=== { TJvDesignMover } =====================================================
|
|
|
|
constructor TJvDesignMover.Create(AOwner: TJvDesignSurface);
|
|
begin
|
|
inherited Create(AOwner);
|
|
SetLength(FDragRects, Surface.Count);
|
|
end;
|
|
|
|
procedure TJvDesignMover.CalcDragRects;
|
|
var
|
|
Delta: TPoint;
|
|
I: Integer;
|
|
begin
|
|
Delta := GetMouseDelta;
|
|
for I := 0 to Surface.Count - 1 do
|
|
with Surface.Selection[I] do
|
|
begin
|
|
FDragRects[I] := BoundsRect;
|
|
OffsetRect(FDragRects[I], Delta.X, Delta.Y);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDesignMover.CalcPaintRects;
|
|
var
|
|
I: Integer;
|
|
ScreenPoint: TPoint;
|
|
begin
|
|
CalcDragRects;
|
|
for I := 0 to Surface.Count - 1 do
|
|
begin
|
|
with Surface.Selection[I] do
|
|
ScreenPoint := Parent.ClientToScreen(Point(0, 0));
|
|
OffsetRect(FDragRects[I], ScreenPoint.X, ScreenPoint.Y);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDesignMover.PaintDragRects;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to Surface.Count - 1 do
|
|
DesignPaintRubberbandRect(Surface.Container, FDragRects[I], psDot);
|
|
end;
|
|
|
|
procedure TJvDesignMover.ApplyDragRects;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if (GetMouseDelta.X <> 0) or (GetMouseDelta.Y <> 0) then
|
|
begin
|
|
CalcDragRects;
|
|
for I := 0 to Surface.Count - 1 do
|
|
Surface.Selection[I].BoundsRect := FDragRects[I];
|
|
Surface.Change;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDesignMover.MouseDown(Button: TMouseButton; Shift: TShiftState;
|
|
X, Y: Integer);
|
|
begin
|
|
FMouseStart := Point(X, Y);
|
|
FMouseLast := FMouseStart;
|
|
CalcPaintRects;
|
|
PaintDragRects;
|
|
end;
|
|
|
|
procedure TJvDesignMover.MouseMove(Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
PaintDragRects;
|
|
FMouseLast := Point(X, Y);
|
|
CalcPaintRects;
|
|
PaintDragRects;
|
|
end;
|
|
|
|
procedure TJvDesignMover.MouseUp(Button: TMouseButton; Shift: TShiftState;
|
|
X, Y: Integer);
|
|
begin
|
|
PaintDragRects;
|
|
FMouseLast := Point(X, Y);
|
|
ApplyDragRects;
|
|
end;
|
|
|
|
//=== { TJvDesignBander } ====================================================
|
|
|
|
procedure TJvDesignBander.CalcDragRect;
|
|
begin
|
|
with GetMouseDelta do
|
|
begin
|
|
DragRect := Rect(0, 0, X, Y);
|
|
OffsetRect(FDragRect, FMouseStart.X, FMouseStart.Y);
|
|
end;
|
|
end;
|
|
|
|
function TJvDesignBander.GetClient: TControl;
|
|
begin
|
|
Result := Surface.Container;
|
|
end;
|
|
|
|
function TJvDesignBander.GetPaintRect: TRect;
|
|
begin
|
|
Result := FDragRect;
|
|
with GetClient.ClientToScreen(Point(0, 0)) do
|
|
OffsetRect(Result, X, Y);
|
|
end;
|
|
|
|
procedure TJvDesignBander.PaintDragRect;
|
|
begin
|
|
DesignPaintRubberbandRect(Surface.Container, GetPaintRect, psDot);
|
|
end;
|
|
|
|
procedure TJvDesignBander.MouseDown(Button: TMouseButton; Shift: TShiftState;
|
|
X, Y: Integer);
|
|
begin
|
|
FMouseStart := Point(X, Y);
|
|
FMouseLast := FMouseStart;
|
|
CalcDragRect;
|
|
PaintDragRect;
|
|
end;
|
|
|
|
procedure TJvDesignBander.MouseMove(Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
PaintDragRect;
|
|
FMouseLast := Point(X, Y);
|
|
CalcDragRect;
|
|
PaintDragRect;
|
|
end;
|
|
|
|
procedure TJvDesignBander.MouseUp(Button: TMouseButton; Shift: TShiftState;
|
|
X, Y: Integer);
|
|
begin
|
|
PaintDragRect;
|
|
CalcDragRect;
|
|
end;
|
|
|
|
//=== { TJvDesignSizer } =====================================================
|
|
|
|
constructor TJvDesignSizer.CreateSizer(AOwner: TJvDesignSurface; AHandle: TJvDesignHandleId);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FHandleId := AHandle;
|
|
end;
|
|
|
|
procedure TJvDesignSizer.ApplyMouseDelta(X, Y: Integer);
|
|
begin
|
|
case FHandleId of
|
|
dhLeftTop, dhMiddleTop, dhRightTop:
|
|
Inc(FDragRect.Top, Y);
|
|
dhLeftBottom, dhMiddleBottom, dhRightBottom:
|
|
Inc(FDragRect.Bottom, Y);
|
|
end;
|
|
case FHandleId of
|
|
dhLeftTop, dhLeftMiddle, dhLeftBottom:
|
|
Inc(FDragRect.Left, X);
|
|
dhRightTop, dhRightMiddle, dhRightBottom:
|
|
Inc(FDragRect.Right, X);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDesignSizer.CalcDragRect;
|
|
begin
|
|
FDragRect := Surface.Selection[0].BoundsRect;
|
|
with GetMouseDelta do
|
|
ApplyMouseDelta(X, Y);
|
|
FDragRect := DesignValidateRect(FDragRect);
|
|
end;
|
|
|
|
function TJvDesignSizer.GetClient: TControl;
|
|
begin
|
|
Result := Surface.Selection[0].Parent;
|
|
end;
|
|
|
|
procedure TJvDesignSizer.ApplyDragRect;
|
|
begin
|
|
Surface.Selection[0].BoundsRect := FDragRect;
|
|
Surface.Change;
|
|
end;
|
|
|
|
procedure TJvDesignSizer.MouseUp(Button: TMouseButton; Shift: TShiftState;
|
|
X, Y: Integer);
|
|
begin
|
|
inherited MouseUp(Button, Shift, X, Y);
|
|
ApplyDragRect;
|
|
end;
|
|
|
|
//=== { TJvDesignDesigner } ==================================================
|
|
|
|
constructor TJvDesignDesigner.Create(AMessenger: TJvDesignCustomMessenger);
|
|
begin
|
|
inherited Create;
|
|
DDC:=TDesignerDeviceContext.Create;
|
|
FMessenger := AMessenger;
|
|
end;
|
|
|
|
function TJvDesignDesigner.GetCustomForm: TCustomForm;
|
|
begin
|
|
Result := nil;
|
|
end;
|
|
|
|
function TJvDesignDesigner.GetIsControl: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
function TJvDesignDesigner.GetRoot: TComponent;
|
|
begin
|
|
Result := nil;
|
|
end;
|
|
|
|
function TJvDesignDesigner.IsDesignMsg(Sender: TControl; var Msg: TLMessage): Boolean;
|
|
begin
|
|
Result := Messenger.IsDesignMessage(Sender, Msg);
|
|
end;
|
|
|
|
procedure TJvDesignDesigner.Modified;
|
|
begin
|
|
//
|
|
end;
|
|
|
|
procedure TJvDesignDesigner.Notification(AnObject: TPersistent;
|
|
Operation: TOperation);
|
|
begin
|
|
//
|
|
end;
|
|
|
|
procedure TJvDesignDesigner.PaintGrid;
|
|
begin
|
|
//
|
|
end;
|
|
|
|
procedure TJvDesignDesigner.SetCustomForm(Value: TCustomForm);
|
|
begin
|
|
//
|
|
end;
|
|
|
|
procedure TJvDesignDesigner.SetIsControl(Value: Boolean);
|
|
begin
|
|
//
|
|
end;
|
|
|
|
function TJvDesignDesigner.UniqueName(const BaseName: string): string;
|
|
begin
|
|
//
|
|
end;
|
|
|
|
procedure TJvDesignDesigner.ValidateRename(AComponent: TComponent;
|
|
const CurName, NewName: string);
|
|
begin
|
|
//
|
|
end;
|
|
|
|
{$IFDEF COMPILER9_UP}
|
|
procedure TJvDesignDesigner.PaintMenu;
|
|
begin
|
|
//
|
|
end;
|
|
{$ENDIF COMPILER9_UP}
|
|
|
|
//=== { TJvDesignDesignerMessenger } =========================================
|
|
|
|
constructor TJvDesignDesignerMessenger.Create;
|
|
begin
|
|
FDesigner := TJvDesignDesigner.Create(Self);
|
|
end;
|
|
|
|
destructor TJvDesignDesignerMessenger.Destroy;
|
|
begin
|
|
if Container <> nil then
|
|
DesignChildren(Container, False);
|
|
if FDesignedForm <> nil then
|
|
FDesignedForm.Designer := nil;
|
|
FDesigner.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
type
|
|
TAccessComponent = class(TComponent);
|
|
|
|
procedure TJvDesignDesignerMessenger.SetComponentDesigning(AComponent: TComponent; ADesigning: Boolean);
|
|
begin
|
|
TAccessComponent(AComponent).SetDesigning(ADesigning);
|
|
end;
|
|
|
|
procedure TJvDesignDesignerMessenger.UndesignComponent(AComponent: TComponent);
|
|
begin
|
|
SetComponentDesigning(AComponent, False);
|
|
end;
|
|
|
|
procedure TJvDesignDesignerMessenger.DesignComponent(AComponent: TComponent; ADesigning: Boolean);
|
|
begin
|
|
SetComponentDesigning(AComponent, ADesigning);
|
|
end;
|
|
|
|
procedure TJvDesignDesignerMessenger.SetContainer(AValue: TWinControl);
|
|
|
|
function FindParentForm: TCustomForm;
|
|
var
|
|
P: TWinControl;
|
|
begin
|
|
P := Container;
|
|
while P.Parent <> nil do
|
|
P := P.Parent;
|
|
if not (P is TCustomForm) then
|
|
raise EJVCLException.CreateResFmt(@RsEOldestFmt , [ClassName]);
|
|
Result := TCustomForm(P);
|
|
end;
|
|
|
|
begin
|
|
inherited SetContainer(AValue);
|
|
if Container <> nil then
|
|
begin
|
|
FDesignedForm := FindParentForm;
|
|
FDesignedForm.Designer := FDesigner;
|
|
DesignChildren(Container, True);
|
|
end;
|
|
end;
|
|
|
|
//=== { TJvDesignMessageHookList } ===========================================
|
|
|
|
constructor TJvDesignMessageHookList.Create(AUser: TJvDesignCustomMessenger);
|
|
begin
|
|
inherited Create(nil);
|
|
FUser := AUser;
|
|
FHooks := TObjectList.Create;
|
|
FHooks.OwnsObjects := True;
|
|
end;
|
|
|
|
destructor TJvDesignMessageHookList.Destroy;
|
|
begin
|
|
FHooks.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TJvDesignMessageHookList.Clear;
|
|
begin
|
|
FHooks.Clear;
|
|
end;
|
|
|
|
procedure TJvDesignMessageHookList.Hook(AClient: TWinControl);
|
|
begin
|
|
AClient.FreeNotification(Self);
|
|
FHooks.Add(TJvDesignMessageHook.Create(FUser, AClient));
|
|
end;
|
|
|
|
procedure TJvDesignMessageHookList.Unhook(AComponent: TComponent);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to FHooks.Count - 1 do
|
|
if TJvDesignMessageHook(FHooks[I]).Client = AComponent then
|
|
begin
|
|
FHooks.Delete(I);
|
|
Break;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDesignMessageHookList.Notification(AComponent: TComponent;
|
|
Operation: TOperation);
|
|
begin
|
|
inherited Notification(AComponent, Operation);
|
|
if Operation = opRemove then
|
|
Unhook(AComponent);
|
|
end;
|
|
|
|
//=== { TJvDesignWinControlHookMessenger } ===================================
|
|
|
|
constructor TJvDesignWinControlHookMessenger.Create;
|
|
begin
|
|
inherited Create;
|
|
FHooks := TJvDesignMessageHookList.Create(Self);
|
|
end;
|
|
|
|
destructor TJvDesignWinControlHookMessenger.Destroy;
|
|
begin
|
|
FHooks.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TJvDesignWinControlHookMessenger.Clear;
|
|
begin
|
|
FHooks.Clear;
|
|
end;
|
|
|
|
procedure TJvDesignWinControlHookMessenger.DesignComponent(AComponent: TComponent; ADesigning: Boolean);
|
|
begin
|
|
if (AComponent is TWinControl) then
|
|
if ADesigning then
|
|
HookWinControl(TWinControl(AComponent))
|
|
else
|
|
UnhookWinControl(TWinControl(AComponent))
|
|
end;
|
|
|
|
procedure TJvDesignWinControlHookMessenger.HookWinControl(AWinControl: TWinControl);
|
|
begin
|
|
FHooks.Hook(AWinControl);
|
|
DesignChildren(AWinControl, True);
|
|
end;
|
|
|
|
procedure TJvDesignWinControlHookMessenger.UnhookWinControl(AWinControl: TWinControl);
|
|
begin
|
|
FHooks.Unhook(AWinControl);
|
|
DesignChildren(AWinControl, False);
|
|
end;
|
|
|
|
procedure TJvDesignWinControlHookMessenger.SetContainer(AValue: TWinControl);
|
|
begin
|
|
inherited SetContainer(AValue);
|
|
if Container <> nil then
|
|
DesignChildren(Container, True);
|
|
end;
|
|
|
|
initialization
|
|
|
|
finalization
|
|
FreeShadedBits;
|
|
|
|
end.
|
|
|
|
|