Move Sparta DockedFormEditor package from freesparta branch to trunk.

git-svn-id: trunk@50411 -
This commit is contained in:
juha 2015-11-19 00:19:56 +00:00
parent 5154a0d95b
commit 951fac1216
15 changed files with 4991 additions and 0 deletions

14
.gitattributes vendored
View File

@ -3530,6 +3530,20 @@ components/simpleideintf/examples/testh2pastool.lpr svneol=native#text/plain
components/simpleideintf/simpleide.pas svneol=native#text/plain
components/simpleideintf/simpleideintf.lpk svneol=native#text/plain
components/simpleideintf/simpleideintf.pas svneol=native#text/plain
components/sparta/dockedformeditor/source/sparta_designedform.pas svneol=native#text/pascal
components/sparta/dockedformeditor/source/sparta_fakecustom.pas svneol=native#text/pascal
components/sparta/dockedformeditor/source/sparta_fakeform.pas svneol=native#text/pascal
components/sparta/dockedformeditor/source/sparta_fakeframe.pas svneol=native#text/pascal
components/sparta/dockedformeditor/source/sparta_fakenoncontrol.pas svneol=native#text/pascal
components/sparta/dockedformeditor/source/sparta_hashutils.pas svneol=native#text/pascal
components/sparta/dockedformeditor/source/sparta_mainide.pas svneol=native#text/pascal
components/sparta/dockedformeditor/source/sparta_reg_dockedformeditor.pas svneol=native#text/pascal
components/sparta/dockedformeditor/source/sparta_resizer.pas svneol=native#text/pascal
components/sparta/dockedformeditor/source/sparta_resizerframe.lfm svneol=native#text/plain
components/sparta/dockedformeditor/source/sparta_resizerframe.pas svneol=native#text/pascal
components/sparta/dockedformeditor/source/spartaapi.pas svneol=native#text/pascal
components/sparta/dockedformeditor/sparta_dockedformeditor.lpk svneol=native#text/plain
components/sparta/dockedformeditor/sparta_dockedformeditor.pas svneol=native#text/pascal
components/sqldb/Makefile svneol=native#text/plain
components/sqldb/Makefile.compiled svneol=native#text/plain
components/sqldb/Makefile.fpc svneol=native#text/plain

View File

@ -0,0 +1,147 @@
{
*****************************************************************************
See the file COPYING.modifiedLGPL.txt, included in this distribution,
for details about the license.
*****************************************************************************
Author: Maciej Izak
DaThoX 2004-2015
FreeSparta.com
}
unit sparta_DesignedForm;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Controls, Forms, SrcEditorIntf;
type
IDesignedRealForm = interface
['{AAEC32EE-4ABE-4691-A172-FC67B66118DD}']
// bounds
function GetRealBounds(AIndex: Integer): Integer;
procedure SetRealBounds(AIndex: Integer; AValue: Integer);
property RealLeft: Integer index 0 read GetRealBounds write SetRealBounds;
property RealTop: Integer index 1 read GetRealBounds write SetRealBounds;
property RealWidth: Integer index 2 read GetRealBounds write SetRealBounds;
property RealHeight: Integer index 3 read GetRealBounds write SetRealBounds;
// setters
procedure SetRealBorderStyle(AVal: TFormBorderStyle);
procedure SetRealBorderIcons(AVal: TBorderIcons);
procedure SetRealFormStyle(AVal: TFormStyle);
procedure SetRealPopupMode(AVal: TPopupMode);
procedure SetRealPopupParent(AVal: TCustomForm);
// getters
function GetRealBorderStyle: TFormBorderStyle;
function GetRealBorderIcons: TBorderIcons;
function GetRealFormStyle: TFormStyle;
function GetRealPopupMode: TPopupMode;
function GetRealPopupParent: TCustomForm;
// properties
property RealBorderStyle: TFormBorderStyle read GetRealBorderStyle write SetRealBorderStyle;
property RealBorderIcons: TBorderIcons read GetRealBorderIcons write SetRealBorderIcons;
property RealFormStyle: TFormStyle read GetRealFormStyle write SetRealFormStyle;
property RealPopupMode: TPopupMode read GetRealPopupMode write SetRealPopupMode;
property RealPopupParent: TCustomForm read GetRealPopupParent write SetRealPopupParent;
end;
IDesignedRealFormHelper = interface(IDesignedRealForm)
function GetLogicalClientRect(ALogicalClientRect: TRect): TRect;
end;
IDesignedForm = interface(IDesignedRealForm)
['{5D30C0DE-4D51-4FB5-99FC-88900FAE6B66}']
procedure BeginUpdate;
procedure EndUpdate(AModified: Boolean = False);
function GetUpdate: Boolean;
property Update: Boolean read GetUpdate;
procedure ShowWindow;
procedure HideWindow;
// hacked values
function GetPublishedBounds(AIndex: Integer): Integer;
procedure SetPublishedBounds(AIndex: Integer; AValue: Integer);
property Left: Integer index 0 read GetPublishedBounds write SetPublishedBounds;
property Top: Integer index 1 read GetPublishedBounds write SetPublishedBounds;
property Width: Integer index 2 read GetPublishedBounds write SetPublishedBounds;
property Height: Integer index 3 read GetPublishedBounds write SetPublishedBounds;
// design form scroll system
procedure SetHorzScrollPosition(AValue: Integer);
procedure SetVertScrollPosition(AValue: Integer);
function GetHorzScrollPosition: Integer;
function GetVertScrollPosition: Integer;
property HorzScrollPosition: Integer read GetHorzScrollPosition write SetHorzScrollPosition;
property VertScrollPosition: Integer read GetVertScrollPosition write SetVertScrollPosition;
// on notify change
procedure SetOnChangeHackedBounds(const AValue: TNotifyEvent);
function GetOnChangeHackedBounds: TNotifyEvent;
property OnChangeHackedBounds: TNotifyEvent read GetOnChangeHackedBounds write SetOnChangeHackedBounds;
//
function GetForm: TCustomForm;
property Form: TCustomForm read GetForm;
// for last active window
function GetLastActiveSourceWindow: TSourceEditorWindowInterface;
procedure SetLastActiveSourceWindow(AValue: TSourceEditorWindowInterface);
property LastActiveSourceWindow: TSourceEditorWindowInterface read GetLastActiveSourceWindow write SetLastActiveSourceWindow;
end;
IDesignedFakeControl = interface
['{31708772-D9FF-42D8-88AD-D27663393177}']
end;
IDesignedFakeForm = interface
['{A887F50D-13A3-4048-AFFD-F07816FDD08A}']
// other hacked values
procedure SetFormBorderStyle(ANewStyle: TFormBorderStyle);
procedure SetBorderIcons(AVal: TBorderIcons);
procedure SetFormStyle(AValue : TFormStyle);
procedure SetCaption(const AValue: string);
function GetBorderStyle: TFormBorderStyle;
function GetBorderIcons: TBorderIcons;
function GetFormStyle: TFormStyle;
function GetCaption: string;
property BorderIcons: TBorderIcons read GetBorderIcons write SetBorderIcons;
property BorderStyle: TFormBorderStyle read GetBorderStyle write SetFormBorderStyle;
property FormStyle: TFormStyle read GetFormStyle write SetFormStyle;
property Caption: string read GetCaption write SetCaption;
end;
IDesignedFormBackground = interface
['{AC7F6594-1C2D-4424-977B-28053A79CE99}']
function GetMargin(const AIndex: Integer): Integer;
property LeftMargin: Integer index 0 read GetMargin;
property TopMargin: Integer index 1 read GetMargin;
property RightMargin: Integer index 2 read GetMargin;
property BottomMargin: Integer index 3 read GetMargin;
procedure SetParent(AValue: TWinControl);
function GetParent: TWinControl;
property Parent: TWinControl read GetParent write SetParent;
function GetDesignedForm: IDesignedForm;
property DesignedForm: IDesignedForm read GetDesignedForm;
procedure RefreshValues;
end;
implementation
end.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,215 @@
{
*****************************************************************************
See the file COPYING.modifiedLGPL.txt, included in this distribution,
for details about the license.
*****************************************************************************
Author: Maciej Izak
DaThoX 2004-2015
FreeSparta.com
}
unit sparta_FakeForm;
{$mode delphi}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, TypInfo, LCLIntf,
LCLType, sparta_DesignedForm, sparta_FakeCustom;
const
BorderStylesAllowAutoScroll = [bsSizeable, bsSizeToolWin];
type
{ TFakeForm }
TFakeForm = class(TFakeCustomForm, IDesignedFakeForm)
private
FHackVisible: Boolean;
FHackAutoScroll: Boolean;
FHackBorderStyle: TFormBorderStyle;
FHackBorderIcons: TBorderIcons;
FHackFormStyle: TFormStyle;
FPopupMode: TPopupMode;
FPopupParent: TCustomForm;
FHorzScrollBar: TControlScrollBar;
FVertScrollBar: TControlScrollBar;
FControlForHackedConstraints: TControl;
FHackConstraints: TSizeConstraints;
function IsAutoScrollStored: Boolean;
procedure SetHorzScrollBar(AValue: TControlScrollBar);
procedure SetVertScrollBar(AValue: TControlScrollBar);
procedure SetPopupMode(const AValue: TPopupMode);
procedure SetPopupParent(const AValue: TCustomForm);
procedure SetFormBorderStyle(ANewStyle: TFormBorderStyle);
procedure SetBorderIcons(AVal: TBorderIcons);
procedure SetFormStyle(AValue : TFormStyle);
procedure SetCaption(const AValue: string);
function GetBorderStyle: TFormBorderStyle;
function GetBorderIcons: TBorderIcons;
function GetFormStyle: TFormStyle;
function GetCaption: string;
public
property RealPopupMode: TPopupMode read GetRealPopupMode write SetRealPopupMode;
property RealPopupParent: TCustomForm read GetRealPopupParent write SetRealPopupParent;
constructor CreateNew(AOwner: TComponent; Num: Integer = 0); override;
destructor Destroy; override;
published
property AutoScroll: Boolean read FHackAutoScroll write FHackAutoScroll stored IsAutoScrollStored default False;
property BorderIcons: TBorderIcons read GetBorderIcons write SetBorderIcons default [biSystemMenu, biMinimize, biMaximize];
property BorderStyle: TFormBorderStyle read GetBorderStyle write SetFormBorderStyle default bsSizeable;
property FormStyle: TFormStyle read GetFormStyle write SetFormStyle default fsNormal;
property PopupMode: TPopupMode read FPopupMode write SetPopupMode default pmNone;
property PopupParent: TCustomForm read FPopupParent write SetPopupParent;
property HorzScrollBar: TControlScrollBar read FHorzScrollBar write SetHorzScrollBar;
property VertScrollBar: TControlScrollBar read FVertScrollBar write SetVertScrollBar;
property Constraints: TSizeConstraints read FHackConstraints write FHackConstraints;
property Caption: string read GetCaption write SetCaption;
property Visible: boolean read FHackVisible write FHackVisible;
end;
implementation
{ TFakeForm }
procedure TFakeForm.SetHorzScrollBar(AValue: TControlScrollBar);
begin
FHorzScrollBar.Assign(AValue);
end;
function TFakeForm.IsAutoScrollStored: Boolean;
begin
Result := BorderStyle in BorderStylesAllowAutoScroll;
end;
procedure TFakeForm.SetFormBorderStyle(ANewStyle: TFormBorderStyle);
begin
if FHackBorderStyle = ANewStyle then exit;
if not (ANewStyle in BorderStylesAllowAutoScroll) then
AutoScroll := False;
FHackBorderStyle := ANewStyle;
end;
procedure TFakeForm.SetBorderIcons(AVal: TBorderIcons);
begin
FHackBorderIcons := AVal;
end;
procedure TFakeForm.SetFormStyle(AValue: TFormStyle);
var
LHackFormStyle: TFormStyle;
Begin
if FHackFormStyle = AValue then
exit;
LHackFormStyle := FHackFormStyle;
FHackFormStyle := AValue;
if FHackFormStyle = fsSplash then
BorderStyle := bsNone
else
if LHackFormStyle = fsSplash then
BorderStyle := bsSizeable;
end;
procedure TFakeForm.SetCaption(const AValue: string);
begin
inherited Caption := AValue;
end;
procedure TFakeForm.SetPopupMode(const AValue: TPopupMode);
begin
if FPopupMode <> AValue then
begin
FPopupMode := AValue;
if FPopupMode = pmAuto then
PopupParent := nil;
end;
end;
procedure TFakeForm.SetPopupParent(const AValue: TCustomForm);
begin
if FPopupParent <> AValue then
begin
if FPopupParent <> nil then
FPopupParent.RemoveFreeNotification(Self);
FPopupParent := AValue;
if FPopupParent <> nil then
begin
FPopupParent.FreeNotification(Self);
FPopupMode := pmExplicit;
end;
end;
end;
function TFakeForm.GetBorderStyle: TFormBorderStyle;
begin
Result := FHackBorderStyle;
end;
function TFakeForm.GetBorderIcons: TBorderIcons;
begin
Result := FHackBorderIcons;
end;
function TFakeForm.GetFormStyle: TFormStyle;
begin
Result := FHackFormStyle;
end;
function TFakeForm.GetCaption: string;
begin
Result := inherited Caption;
end;
procedure TFakeForm.SetVertScrollBar(AValue: TControlScrollBar);
begin
FVertScrollBar.Assign(AValue);
end;
constructor TFakeForm.CreateNew(AOwner: TComponent; Num: Integer);
begin
inherited CreateNew(AOwner, Num);
FHorzScrollBar := TControlScrollBar.Create(Self, sbHorizontal);
FVertScrollBar := TControlScrollBar.Create(Self, sbVertical);
BorderIcons := inherited BorderIcons;
BorderStyle := inherited BorderStyle;
FormStyle := inherited FormStyle;
PopupMode := inherited PopupMode;
FControlForHackedConstraints := TControl.Create(nil);
FHackConstraints := TSizeConstraints.Create(FControlForHackedConstraints);
end;
destructor TFakeForm.Destroy;
begin
FHorzScrollBar.Free;
FVertScrollBar.Free;
FHackConstraints.Free;
FControlForHackedConstraints.Free;
inherited Destroy;
end;
end.

View File

@ -0,0 +1,29 @@
{
*****************************************************************************
See the file COPYING.modifiedLGPL.txt, included in this distribution,
for details about the license.
*****************************************************************************
Author: Maciej Izak
DaThoX 2004-2015
FreeSparta.com
}
unit sparta_FakeFrame;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, sparta_FakeCustom;
type
TFakeFrame = class(TFakeCustomFrame)
end;
implementation
end.

View File

@ -0,0 +1,29 @@
{
*****************************************************************************
See the file COPYING.modifiedLGPL.txt, included in this distribution,
for details about the license.
*****************************************************************************
Author: Maciej Izak
DaThoX 2004-2015
FreeSparta.com
}
unit sparta_FakeNonControl;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, sparta_FakeCustom;
type
TFakeNonControl = class(TFakeCustomNonControl)
end;
implementation
end.

View File

@ -0,0 +1,30 @@
unit sparta_HashUtils;
{$mode delphi}{$H+}
interface
uses
Classes, SysUtils;
{$IFNDEF USE_GENERICS_COLLECTIONS}
type
THash_TObject = record
class function Hash(A: TObject; B: SizeUInt): SizeUInt; static;
end;
{$ENDIF}
implementation
{$IFNDEF USE_GENERICS_COLLECTIONS}
class function THash_TObject.Hash(A: TObject; B: SizeUInt): SizeUInt;
begin
if A = nil then
Exit($2A and (b - 1));
Result := A.GetHashCode() and (b - 1);
end;
{$ENDIF}
end.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,65 @@
{
*****************************************************************************
See the file COPYING.modifiedLGPL.txt, included in this distribution,
for details about the license.
*****************************************************************************
Author: Maciej Izak
DaThoX 2004-2015
FreeSparta.com
}
unit sparta_reg_DockedFormEditor;
{$mode delphi}{$H+}
interface
uses
Classes, SysUtils, SrcEditorIntf, LazIDEIntf, ComCtrls, Controls, Forms, IDEImagesIntf,
Buttons, ExtCtrls, Graphics, IDEWindowIntf, sparta_MainIDE,
PropEdits, PropEditUtils, FormEditingIntf, ComponentEditors, EditBtn, TypInfo,
LCLIntf, LCLType, sparta_FakeForm, sparta_FakeNonControl, sparta_FakeFrame;
procedure Register;
implementation
procedure Register;
begin
FormEditingHook.StandardDesignerBaseClasses[DesignerBaseClassId_TForm] := TFakeForm;
FormEditingHook.NonFormProxyDesignerForm[NonControlProxyDesignerFormId] := TFakeNonControl;
FormEditingHook.NonFormProxyDesignerForm[FrameProxyDesignerFormId] := TFakeFrame;
Screen.AddHandlerFormAdded(TSpartaMainIDE.Screen_FormAdded);
Screen.AddHandlerRemoveForm(TSpartaMainIDE.Screen_FormDel);
{$IFDEF USE_POPUP_PARENT_DESIGNER}
TCustomForm(LazarusIDE.GetMainBar).AddHandlerOnBeforeDestruction(spartaIDE.OnBeforeClose);
{$ENDIF}
SourceEditorManagerIntf.RegisterChangeEvent(semWindowCreate, TSpartaMainIDE.WindowCreate);
SourceEditorManagerIntf.RegisterChangeEvent(semWindowDestroy, TSpartaMainIDE.WindowDestroy);
SourceEditorManagerIntf.RegisterChangeEvent(semWindowShow, TSpartaMainIDE.WindowShow);
SourceEditorManagerIntf.RegisterChangeEvent(semWindowHide, TSpartaMainIDE.WindowHide);
SourceEditorManagerIntf.RegisterChangeEvent(semEditorActivate, TSpartaMainIDE.EditorActivated);
SourceEditorManagerIntf.RegisterChangeEvent(semEditorDestroy, TSpartaMainIDE.EditorDestroyed);
SourceEditorManagerIntf.RegisterChangeEvent(semEditorCreate, TSpartaMainIDE.EditorCreate);
LazarusIDE.AddHandlerOnShowDesignerFormOfSource(TSpartaMainIDE.OnShowDesignerForm);
LazarusIDE.AddHandlerOnShowSourceOfActiveDesignerForm(TSpartaMainIDE.OnShowSrcEditor);
GlobalDesignHook.AddHandlerShowMethod(TSpartaMainIDE.OnShowMethod);
GlobalDesignHook.AddHandlerRefreshPropertyValues(TSpartaMainIDE.OnDesignRefreshPropertyValues);
IDETabMaster := TDTXTabMaster.Create;
IDEComponentsMaster := TDTXComponentsMaster.Create;
end;
finalization
Screen.RemoveHandlerFormAdded(TSpartaMainIDE.Screen_FormAdded);
Screen.RemoveHandlerRemoveForm(TSpartaMainIDE.Screen_FormDel);
IDETabMaster.Free;
IDEComponentsMaster.Free;
end.

View File

@ -0,0 +1,452 @@
{
*****************************************************************************
See the file COPYING.modifiedLGPL.txt, included in this distribution,
for details about the license.
*****************************************************************************
Author: Maciej Izak
DaThoX 2004-2015
FreeSparta.com
}
unit sparta_Resizer;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Controls, ExtCtrls, sparta_ResizerFrame, sparta_DesignedForm, Forms, Math, StdCtrls,
LCLType, LazIDEIntf, Buttons, SpartaAPI, Dialogs,
{$IFDEF USE_GENERICS_COLLECTIONS}
Generics.Defaults,
{$ENDIF}
FormEditingIntf;
type
{ TResizer }
TResizer = class(TComponent, IResizer)
private
FDesignedForm: IDesignedForm;
procedure SetDesignedForm(const AValue: IDesignedForm);
procedure SetDesignScroll(AIndex: Integer; AValue: Boolean);
procedure sbScroll(Sender: TObject; ScrollCode: TScrollCode;
var ScrollPos: Integer);
procedure FunnyButtonClick(Sender: TObject);
protected
// To perform proper behaviour for scroolbar with "PageSize" we need to remember real
// maximal values (is possible to scroll outside of range 0..(Max - PageSize),
// after mouse click in button responsible for changing value of scrollbar,
// our value is equal to Max :\). Workaround: we need to remember real max value in our own place
FRealMaxH: Integer;
FRealMaxV: Integer;
FSpecialMargin: array[0..3] of Integer;
FDesignScroll: array[0..1] of Boolean;
FParent: TWinControl;
class var
FStarter, FProfessional: TNotifyEvent;
public
pMainDTU: TPanel;
pMain: TPanel;
pAddons: TPanel;
pComponents: TPanel;
lInfo: TLabel;
sbShowComponents : TSpeedButton;
sbShowFormEditor: TSpeedButton;
sbShowAnchorEditor: TSpeedButton;
sbShowNonVisualEditor: TSpeedButton;
pDesignTimeUtils: TPanel;
sbV: TScrollBar;
sbH: TScrollBar;
bR: TButton;
FResizerFrame: TResizerFrame;
FMainDTU: ISTAMainDesignTimeUtil;
FEDTU: TList;
constructor Create(AParent: TWinControl);
destructor Destroy; override;
property DesignedForm: IDesignedForm read FDesignedForm write SetDesignedForm;
procedure TryBoundSizerToDesignedForm(Sender: TObject);
procedure NodePositioning(Sender: TObject; PositioningKind: TPositioningKind; PositioningCode: TPositioningCode);
property DesignScrollRight: Boolean index SB_Vert read FDesignScroll[SB_Vert] write SetDesignScroll;
property DesignScrollBottom: Boolean index SB_Horz read FDesignScroll[SB_Horz] write SetDesignScroll;
end;
implementation
{ TResizer }
procedure TResizer.SetDesignedForm(const AValue: IDesignedForm);
function FindFirstFormParent: TCustomForm;
begin
Result := TCustomForm(FResizerFrame.Parent);
while not (Result is TCustomForm) do
Result := TCustomForm(Result.Parent);
end;
var
LLookupRoot: TComponent;
begin
if FDesignedForm <> nil then
begin
FDesignedForm.OnChangeHackedBounds := nil;
end;
FDesignedForm := AValue;
if FDesignedForm <> nil then
begin
FDesignedForm.BeginUpdate;
{$IFDEF USE_POPUP_PARENT_DESIGNER}
FDesignedForm.RealPopupMode := pmExplicit;
// for dock/undock
FDesignedForm.RealPopupParent := nil;
FDesignedForm.RealPopupParent := FindFirstFormParent;
{$ELSE}
FDesignedForm.Form.ParentWindow := FResizerFrame.pClient.Handle;
{$ENDIF}
// for big forms (bigger than screen resolution) we need to refresh Real* values
DesignedForm.RealWidth := DesignedForm.Width;
DesignedForm.RealHeight := DesignedForm.Height;
FDesignedForm.EndUpdate;
FDesignedForm.OnChangeHackedBounds := @TryBoundSizerToDesignedForm;
// in this place DesignedForm should be initialized by current editor (+ "sizer")
// TODO some interfaces for utils (Design Time Utils - DTU) ?
LLookupRoot := LookupRoot(DesignedForm.Form);
if FMainDTU <> nil then
FMainDTU.Root := LLookupRoot;
end
else
begin
if FMainDTU <> nil then
FMainDTU.Root := nil;
end;
FResizerFrame.DesignedForm := AValue;
end;
procedure TResizer.SetDesignScroll(AIndex: Integer; AValue: Boolean);
procedure PerformScroll(AScroll: TScrollBar);
begin
AScroll.Visible := AValue;
AScroll.Position:=0;
end;
begin
if FDesignScroll[AIndex] = AValue then
Exit;
FDesignScroll[AIndex] := AValue;
case AIndex of
SB_Horz: PerformScroll(sbH);
SB_Vert: PerformScroll(sbV);
else
raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
end;
end;
procedure TResizer.sbScroll(Sender: TObject; ScrollCode: TScrollCode;
var ScrollPos: Integer);
var
LScrollPos: Integer;
begin
if FDesignedForm = nil then
Exit;
if ScrollCode <> scEndScroll then
FResizerFrame.HideSizeRects
else
FResizerFrame.ShowSizeRects;
FDesignedForm.BeginUpdate;
if Sender = sbV then
begin
// Warning - don't overflow the range! (go to description for FRealMaxV)
ScrollPos := Min(ScrollPos, FRealMaxV);
FResizerFrame.VerticalScrollPos := ScrollPos;
// scroll for form
with FResizerFrame do // -8 when we scaling the form and we don't need to scroll -> there is Max
LScrollPos := Max(ifthen(pBG.Top + BgTopMargin <= 0, ScrollPos - SIZER_RECT_SIZE - BgTopMargin, 0), 0);
FDesignedForm.VertScrollPosition := LScrollPos;
end;
if Sender = sbH then
begin
ScrollPos := Min(ScrollPos, FRealMaxH);
FResizerFrame.HorizontalScrollPos := ScrollPos;
// scroll for form
with FResizerFrame do
LScrollPos := Max(ifthen(pBG.Left + BgLeftMargin <= 0, ScrollPos - SIZER_RECT_SIZE - BgLeftMargin, 0), 0);
FDesignedForm.HorzScrollPosition := LScrollPos;
end;
FDesignedForm.EndUpdate;
FResizerFrame.PositionNodes(FResizerFrame);
FDesignedForm.Form.Invalidate;
end;
constructor TResizer.Create(AParent: TWinControl);
begin
inherited Create(AParent);
FParent := AParent;
// create layout
FEDTU := TList.Create;
if Assigned(FStarter) then
FStarter(Self);
pMainDTU := TPanel.Create(AParent);
with pMainDTU do
begin
Parent := AParent;
Align := alTop;
BevelOuter := bvNone;
Height := 0;
end;
pAddons := TPanel.Create(AParent);
pAddons.Parent := AParent;
pAddons.Align := alRight;
pAddons.BevelOuter := bvNone;
pAddons.Width:=0;
if DTUManager <> nil then
begin
FMainDTU := DTUManager.CreateMainDTU(pMainDTU, pAddons);
end;
// Funny button
bR := TButton.Create(AParent);
with bR do
begin
Parent := AParent;
Height := 17;
Width := 17;
AnchorSideRight.Control := pAddons;
AnchorSideBottom.Control := AParent;
AnchorSideBottom.Side := asrBottom;
Anchors := [akRight, akBottom];
Caption := 'R';
Visible := True;
OnClick := @FunnyButtonClick;
end;
sbV := TScrollBar.Create(AParent);
with sbV do
begin
Kind := sbVertical;
Parent := AParent;
AnchorSideTop.Control := pMainDTU;
AnchorSideTop.Side := asrBottom;
AnchorSideRight.Control := pAddons;
AnchorSideBottom.Control := bR;
Width := 17;
Anchors := [akTop, akRight, akBottom];
Visible := False;
OnScroll := @sbScroll;
end;
sbH := TScrollBar.Create(AParent);
with sbH do
begin
Parent := AParent;
AnchorSideLeft.Control := AParent;
AnchorSideRight.Control := bR;
AnchorSideBottom.Control := AParent;
AnchorSideBottom.Side := asrBottom;
Anchors := [akLeft, akRight, akBottom];
Visible := False;
OnScroll := @sbScroll;
end;
pMain := TPanel.Create(AParent);
with pMain do
begin
Parent := AParent;
AnchorSideLeft.Control := AParent;
AnchorSideTop.Control := pMainDTU;
AnchorSideTop.Side := asrBottom;
AnchorSideRight.Control := sbV;
AnchorSideBottom.Control := sbH;
Anchors := [akTop, akLeft, akRight, akBottom];
BevelOuter := bvNone;
end;
FResizerFrame := TResizerFrame.Create(AParent);
FResizerFrame.Parent := pMain;
FResizerFrame.Left := 0;
FResizerFrame.Top := 0;
FResizerFrame.OnNodePositioning := @NodePositioning;
pMain.OnChangeBounds:=@TryBoundSizerToDesignedForm;
end;
destructor TResizer.Destroy;
begin
FMainDTU := nil;
FEDTU.Free;
inherited Destroy;
end;
procedure TResizer.TryBoundSizerToDesignedForm(Sender: TObject);
var
LWidth, LHeight: Integer;
LScrollPos: Integer;
begin
if DesignedForm = nil then
Exit;
FResizerFrame.Constraints.MaxWidth := pMain.Width;
FResizerFrame.Constraints.MaxHeight := pMain.Height;
LWidth := DesignedForm.Width + FResizerFrame.BgLeftMargin + FResizerFrame.BgRightMargin + 2*FResizerFrame.SIZER_RECT_SIZE;
LHeight := DesignedForm.Height + FResizerFrame.BgTopMargin + FResizerFrame.BgBottomMargin + 2*FResizerFrame.SIZER_RECT_SIZE;
if not FResizerFrame.NodePositioning then
begin
FResizerFrame.Width := LWidth;
FResizerFrame.Height := LHeight;
// after enlargement and after reducing constrait not work for frame (LCL bug)
if FResizerFrame.Width > FResizerFrame.Constraints.MaxWidth then
FResizerFrame.Width := FResizerFrame.Constraints.MaxWidth;
if FResizerFrame.Height > FResizerFrame.Constraints.MaxHeight then
FResizerFrame.Height := FResizerFrame.Constraints.MaxHeight;
end;
FResizerFrame.PositionNodes(FResizerFrame);
DesignScrollBottom := FResizerFrame.Width < LWidth;
sbH.Max := LWidth;
FRealMaxH := LWidth - FResizerFrame.Width;
sbH.PageSize := FResizerFrame.Width;
if FResizerFrame.HorizontalScrollPos > FRealMaxH then
begin
FResizerFrame.HorizontalScrollPos := FRealMaxH;
LScrollPos := FResizerFrame.HorizontalScrollPos;
sbScroll(sbH, scEndScroll, LScrollPos);
end;
DesignScrollRight := FResizerFrame.Height < LHeight;
sbV.Max := LHeight;
FRealMaxV := LHeight - FResizerFrame.Height;
sbV.PageSize := FResizerFrame.Height;
if FResizerFrame.VerticalScrollPos > FRealMaxV then
begin
FResizerFrame.VerticalScrollPos := FRealMaxV;
LScrollPos := FResizerFrame.VerticalScrollPos;
sbScroll(sbV, scEndScroll, LScrollPos);
end;
{!}
FResizerFrame.ClientChangeBounds(nil);
// each editor can have scrolls in different positions.
// this is our place where we can call event to set scroll positions.
LScrollPos := FResizerFrame.VerticalScrollPos;
sbScroll(sbV, scEndScroll, LScrollPos);
LScrollPos := FResizerFrame.HorizontalScrollPos;
sbScroll(sbH, scEndScroll, LScrollPos);
if Supports(FDesignedForm, IDesignedFormBackground) then
(FDesignedForm as IDesignedFormBackground).RefreshValues;
end;
procedure TResizer.NodePositioning(Sender: TObject; PositioningKind: TPositioningKind; PositioningCode: TPositioningCode);
procedure Positioning;
var
LHiddenHeight, LNewHeight: Integer;
LHiddenWidth, LNewWidth: Integer;
begin
DesignedForm.BeginUpdate;
if pkRight in PositioningKind then
begin
LHiddenWidth := sbH.Position;
if LHiddenWidth > FResizerFrame.DesignedWidthToScroll then
LHiddenWidth := FResizerFrame.DesignedWidthToScroll;
// TODO - better handling of min width - same in TDesignedFormImpl.SetPublishedBounds (sparta_FakeCustom.pas)
LNewWidth := FResizerFrame.pClient.Width + LHiddenWidth;
DesignedForm.RealWidth := LNewWidth;
DesignedForm.Width := LNewWidth;
// perform minimal width (TODO)
{if LNewWidth < DesignedForm.Width then
begin
FResizerFrame.pClient.Width := DesignedForm.Width;
Application.HandleMessage;
Application.ProcessMessages;
end;}
end;
if pkBottom in PositioningKind then
begin
LHiddenHeight := sbV.Position;
if LHiddenHeight > FResizerFrame.DesignedHeightToScroll then
LHiddenHeight := FResizerFrame.DesignedHeightToScroll;
LNewHeight := FResizerFrame.pClient.Height + LHiddenHeight;
DesignedForm.RealHeight := LNewHeight;
DesignedForm.Height := LNewHeight;
// perform minimal height (TODO)
{if LNewHeight < DesignedForm.RealHeight then
begin
if FResizerFrame.pClient.Height < DesignedForm.RealHeight then
FResizerFrame.pClient.Height := DesignedForm.RealHeight;
Application.ProcessMessages;
end;}
end;
DesignedForm.EndUpdate;
end;
procedure PositioningEnd;
begin
TryBoundSizerToDesignedForm(nil);
end;
begin
if DesignedForm = nil then
Exit;
case PositioningCode of
pcPositioningEnd: PositioningEnd;
pcPositioning: Positioning;
end;
end;
procedure TResizer.FunnyButtonClick(Sender: TObject);
begin
ShowMessage('Funny button with no functionality!'
+ sLineBreak
+ sLineBreak +
'Regards'
+ sLineBreak +
'Maciej Izak'
+ sLineBreak
+ sLineBreak + 'DaThoX team FreeSparta.com project');
end;
end.

View File

@ -0,0 +1,188 @@
object ResizerFrame: TResizerFrame
Left = 0
Height = 460
Top = 0
Width = 320
ClientHeight = 460
ClientWidth = 320
Color = clDefault
ParentColor = False
TabOrder = 0
object pR: TPanel
AnchorSideTop.Control = Owner
Cursor = crSizeWE
Left = 295
Height = 443
Top = 0
Width = 8
Anchors = []
BevelOuter = bvNone
ClientHeight = 443
ClientWidth = 8
Color = clNone
ParentColor = False
TabOrder = 0
object pMarginR: TPanel
AnchorSideLeft.Control = pR
AnchorSideTop.Control = pR
AnchorSideBottom.Control = pR
AnchorSideBottom.Side = asrBottom
Left = 0
Height = 429
Top = 7
Width = 1
Anchors = [akTop, akLeft, akBottom]
BorderSpacing.Top = 7
BorderSpacing.Bottom = 7
BevelOuter = bvNone
Color = clWhite
ParentColor = False
TabOrder = 0
end
end
object pB: TPanel
AnchorSideLeft.Control = Owner
Cursor = crSizeNS
Left = 0
Height = 8
Top = 435
Width = 303
Anchors = [akLeft, akRight]
BevelOuter = bvNone
ClientHeight = 8
ClientWidth = 303
Color = clNone
ParentColor = False
TabOrder = 1
object pMarginB: TPanel
AnchorSideLeft.Control = pB
AnchorSideTop.Control = pB
AnchorSideRight.Control = pB
AnchorSideRight.Side = asrBottom
Left = 7
Height = 1
Top = 0
Width = 289
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Left = 7
BorderSpacing.Right = 7
TabOrder = 0
end
end
object pL: TPanel
AnchorSideLeft.Control = Owner
AnchorSideTop.Control = Owner
Left = 0
Height = 443
Top = 0
Width = 8
Anchors = []
BevelOuter = bvNone
ClientHeight = 443
ClientWidth = 8
Color = clNone
ParentColor = False
TabOrder = 2
object pMarginL: TPanel
AnchorSideTop.Control = pL
AnchorSideRight.Control = pL
AnchorSideRight.Side = asrBottom
AnchorSideBottom.Control = pL
AnchorSideBottom.Side = asrBottom
Left = 7
Height = 429
Top = 7
Width = 1
Anchors = [akTop, akRight, akBottom]
BorderSpacing.Top = 7
BorderSpacing.Bottom = 7
BevelOuter = bvNone
Color = clWhite
ParentColor = False
TabOrder = 0
end
end
object pT: TPanel
AnchorSideLeft.Control = Owner
AnchorSideTop.Control = Owner
Left = 0
Height = 8
Top = 0
Width = 303
Anchors = [akLeft, akRight]
BevelOuter = bvNone
ClientHeight = 8
ClientWidth = 303
Color = clNone
ParentColor = False
TabOrder = 3
object pMarginT: TPanel
AnchorSideLeft.Control = pT
AnchorSideRight.Control = pT
AnchorSideRight.Side = asrBottom
AnchorSideBottom.Control = pT
AnchorSideBottom.Side = asrBottom
Left = 7
Height = 1
Top = 7
Width = 289
Anchors = [akLeft, akRight, akBottom]
BorderSpacing.Left = 7
BorderSpacing.Right = 7
BevelOuter = bvNone
Color = clWhite
ParentColor = False
TabOrder = 0
end
end
object iResizerLineImg: TImage
Left = 216
Height = 6
Top = 32
Width = 6
AutoSize = True
Picture.Data = {
1754506F727461626C654E6574776F726B477261706869639100000089504E47
0D0A1A0A0000000D4948445200000006000000060806000000E0CCEF48000000
06624B474400FF00FF00FFA0BDA793000000097048597300000EC400000EC401
952B0E1B0000000774494D4507DD0A07131110E51DAB140000001E4944415408
D76358B060C17F06060606749A019BE082050BFE33D04107001B6C33AF54FD1B
500000000049454E44AE426082
}
Visible = False
end
object pBG: TPanel
AnchorSideLeft.Control = pL
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = pT
AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = pR
AnchorSideBottom.Control = pB
Left = 8
Height = 427
Top = 8
Width = 287
Anchors = [akTop, akLeft, akRight, akBottom]
BevelOuter = bvNone
Color = clNone
ParentColor = False
TabOrder = 4
end
object pClient: TPanel
AnchorSideLeft.Control = pL
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = pT
AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = pR
AnchorSideBottom.Control = pB
Left = 0
Height = 152
Top = 0
Width = 152
Anchors = []
BevelOuter = bvNone
Color = clNone
ParentColor = False
TabOrder = 5
end
end

View File

@ -0,0 +1,832 @@
{
*****************************************************************************
See the file COPYING.modifiedLGPL.txt, included in this distribution,
for details about the license.
*****************************************************************************
Author: Maciej Izak
DaThoX 2004-2015
FreeSparta.com
}
unit sparta_ResizerFrame;
{$mode delphi}{$H+}
interface
uses
Classes, contnrs, SysUtils, FileUtil, Forms, Controls, ExtCtrls, StdCtrls, Graphics, LCLType,
lclintf, sparta_DesignedForm, Math, FormEditingIntf, PropEdits;
type
{ TResizerFrame }
TPositioningCode = (pcPositioning, pcPositioningEnd);
TPositioningKind = set of (pkBottom, pkRight);
TPositioningEvent = procedure(Sender: TObject; PositioningKind: TPositioningKind; PositioningCode: TPositioningCode) of object;
TResizerFrame = class(TFrame)
iResizerLineImg: TImage;
pBG: TPanel;
pB: TPanel;
pClient: TPanel;
pL: TPanel;
pMarginB: TPanel;
pMarginL: TPanel;
pMarginR: TPanel;
pMarginT: TPanel;
pR: TPanel;
pT: TPanel;
procedure sbVerticalScroll(Sender: TObject; ScrollCode: TScrollCode;
var ScrollPos: Integer);
procedure sbHorizontalScroll(Sender: TObject; ScrollCode: TScrollCode;
var ScrollPos: Integer);
public const
SIZER_RECT_SIZE = 8;
SIZER_LINE_WIDTH = 8;
private
FVerticalScrollPos: Integer;
FHorizontalScrollPos: Integer;
FDesignedForm: IDesignedForm;
FBackground: IDesignedFormBackground;
procedure SetDesignedForm(const AValue: IDesignedForm);
private
{ private declarations }
FOnNodePositioning: TPositioningEvent;
FOnHorizontalScroll, FOnVerticalScroll: TScrollEvent;
FLastRightMarign: Integer;
FLastBottomMarign: Integer;
FNodes: TObjectList;
FNodePositioning: Boolean;
FOldPos, FDelta: TPoint;
FPositioningKind: TPositioningKind;
FMaxWidth, FMaxHeight: Integer;
FActivePropertyGridItemIndex: Integer;
FLastClientWidth, FLastClientHeight: Integer;
procedure PanelPaint(Sender: TObject);
procedure BGChangeBounds(Sender: TObject);
procedure CreateNodes;
procedure NodeMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure NodeMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
procedure NodeMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
function GetRightMargin: Integer;
function GetBottomMargin: Integer;
// dependent on scroll position
// for Vertical
function BottomSizerRectHeight: Integer;
function BottomSizerLineWidth: Integer;
function TopSizerRectTop: Integer;
function TopSizerLineWidth: Integer;
function VerticalSizerLineLength: Integer;
// for Horizontal
function RightSizerRectWidth: Integer;
function RightSizerLineWidth: Integer;
function LeftSizerRectLeft: Integer;
function LeftSizerLineWidth: Integer;
function HorizontalSizerLineLength: Integer;
function GetBackgroundMargin(const AIndex: Integer): Integer;
procedure TryBoundDesignedForm;
public
constructor Create(TheOwner: TComponent); override;
destructor Destroy; override;
property DesignedForm: IDesignedForm read FDesignedForm write SetDesignedForm;
procedure PositionNodes(AroundControl: TWinControl);
property NodePositioning: Boolean read FNodePositioning;
procedure ClientChangeBounds(Sender: TObject);
property RightMargin: Integer read GetRightMargin;
property BottomMargin: Integer read GetBottomMargin;
property OnNodePositioning: TPositioningEvent read FOnNodePositioning write FOnNodePositioning;
property BgLeftMargin: Integer index 0 read GetBackgroundMargin;
property BgTopMargin: Integer index 1 read GetBackgroundMargin;
property BgRightMargin: Integer index 2 read GetBackgroundMargin;
property BgBottomMargin: Integer index 3 read GetBackgroundMargin;
function DesignedWidthToScroll: Integer;
function DesignedHeightToScroll: Integer;
procedure HideSizeRects;
procedure HideSizeControls;
procedure ShowSizeRects;
procedure ShowSizeControls;
property VerticalScrollPos: Integer read FVerticalScrollPos write FVerticalScrollPos;
property HorizontalScrollPos: Integer read FHorizontalScrollPos write FHorizontalScrollPos;
end;
resourcestring
SArgumentOutOfRange = 'Argument out of range';
implementation
{$R *.lfm}
{ TResizerFrame }
// Tiles the source image over the given target canvas
procedure TileImage(const ASource: TImage; ATarget: TCanvas; AX, AY,
AWidth, AHeight: Integer);
var
LX, LY, LDeltaX, LDeltaY: Integer;
begin
LDeltaX := ASource.Width;
LDeltaY := ASource.Height;
LY := 0;
while LY < AHeight do
begin
LX := 0;
while LX < AWidth do
begin
ATarget.Draw(AX + LX, AY + LY, ASource.Picture.graphic);
Inc(LX, LDeltaX);
end;
Inc(LY, LDeltaY);
end;
end;
procedure TResizerFrame.sbVerticalScroll(Sender: TObject;
ScrollCode: TScrollCode; var ScrollPos: Integer);
begin
if ScrollCode <> scEndScroll then
HideSizeRects
else
ShowSizeRects;
FVerticalScrollPos := ScrollPos;
PositionNodes(Self);
if Assigned(FOnVerticalScroll)
// for refresh from this class, pass sender as nil.
// In other case program will go into infinity loop
and (Sender <> nil) then
FOnVerticalScroll(Sender, ScrollCode, ScrollPos);
end;
procedure TResizerFrame.sbHorizontalScroll(Sender: TObject;
ScrollCode: TScrollCode; var ScrollPos: Integer);
begin
if ScrollCode <> scEndScroll then
HideSizeRects
else
ShowSizeRects;
FHorizontalScrollPos := ScrollPos;
PositionNodes(Self);
if Assigned(FOnHorizontalScroll)
// for refresh from this class, pass sender as nil.
// In other case program will go into infinity loop
and (Sender <> nil) then
FOnHorizontalScroll(Sender, ScrollCode, ScrollPos);
end;
procedure TResizerFrame.SetDesignedForm(const AValue: IDesignedForm);
begin
FDesignedForm := AValue;
if FDesignedForm = nil then
FBackground := nil
else
if Supports(FDesignedForm, IDesignedFormBackground, FBackground) then
begin
FBackground.Parent := pBG;
end;
// special for QT (at start "design form" has wrong position)
TryBoundDesignedForm;
end;
procedure TResizerFrame.PanelPaint(Sender: TObject);
begin
if FNodePositioning then
Exit;
if Sender = pR then
TileImage(iResizerLineImg, pR.Canvas, 0, 0, SIZER_LINE_WIDTH, Height)
else if Sender = pB then
TileImage(iResizerLineImg, pB.Canvas, 0, 0, Width, SIZER_LINE_WIDTH)
else if Sender = pL then
TileImage(iResizerLineImg, pL.Canvas, 0, 0, SIZER_LINE_WIDTH, Height)
else if Sender = pT then
TileImage(iResizerLineImg, pT.Canvas, 0, 0, Width, SIZER_LINE_WIDTH);
end;
procedure TResizerFrame.ClientChangeBounds(Sender: TObject);
{$IFDEF USE_POPUP_PARENT_DESIGNER}
var
p: TPoint;
{$ENDIF}
begin
if (DesignedForm = nil) or FNodePositioning then
Exit;
FLastClientWidth := pClient.Width;
FLastClientHeight := pClient.Height;
(*
DesignedForm.BeginUpdate;
{$IFDEF USE_POPUP_PARENT_DESIGNER}
p := Point(0, 0);
p := pClient.ClientToScreen(p);
DesignedForm.RealLeft := p.x;
DesignedForm.RealTop := p.y;
{$ELSE}
DesignedForm.RealLeft := 0;
DesignedForm.RealTop := 0;
{$ENDIF}
DesignedForm.RealWidth := pClient.Width;
DesignedForm.RealHeight := pClient.Height;
DesignedForm.EndUpdate;
*)
end;
procedure TResizerFrame.BGChangeBounds(Sender: TObject);
begin
PositionNodes(Self);
end;
procedure TResizerFrame.HideSizeRects;
var
p: TObject;
wc: TWinControl absolute p;
begin
for p in FNodes do
if not (wc is TPanel) then
wc.Visible := False;
end;
procedure TResizerFrame.HideSizeControls;
begin
pL.Repaint;
pT.Repaint;
pR.Repaint;
pB.Repaint;
HideSizeRects;
pBG.Visible := False;
end;
procedure TResizerFrame.ShowSizeRects;
var
p: TObject;
wc: TWinControl absolute p;
begin
for p in FNodes do
wc.Visible := True;
end;
procedure TResizerFrame.ShowSizeControls;
begin
pL.Repaint;
pT.Repaint;
pR.Repaint;
pB.Repaint;
ShowSizeRects;
pBG.Visible := True;
end;
procedure TResizerFrame.CreateNodes;
var
Node: Integer;
Panel: TPanel;
begin
for Node := 0 to 7 do
begin
Panel := TPanel.Create(self);
with Panel do
begin
BevelOuter := bvNone;
Color := clBlack;
Name := 'Node' + IntToStr(Node);
Caption:='';
Width := SIZER_RECT_SIZE;
Height := SIZER_RECT_SIZE;
Parent := Self;
Visible := True;
FNodes.Add(Panel);
with TShape.Create(Panel) do
begin
Parent := Panel;
Align:= alClient;
if Node in [3,4,5] then
Brush.Color:=clBtnFace
else
Brush.Color:=clGray;
case Node of
{0,}4: Cursor := crSizeNWSE;
{1,}5: Cursor := crSizeNS;
//{2,}6: Cursor := crSizeNESW;
3{,7}: Cursor := crSizeWE;
end;
if Node in [3,4,5] then
begin
OnMouseDown := NodeMouseDown;
OnMouseMove := NodeMouseMove;
OnMouseUp := NodeMouseUp;
end;
end;
end;
end;
// extra resizers
pB.OnMouseDown := NodeMouseDown;
pB.OnMouseMove := NodeMouseMove;
pB.OnMouseUp := NodeMouseUp;
pR.OnMouseDown := NodeMouseDown;
pR.OnMouseMove := NodeMouseMove;
pR.OnMouseUp := NodeMouseUp;
FNodes.Add(pL);
FNodes.Add(pT);
FNodes.Add(pR);
FNodes.Add(pB);
end;
procedure TResizerFrame.NodeMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
LCtrlPoint: TPoint;
begin
if Sender is TGraphicControl then
Sender := TGraphicControl(Sender).Parent;
if (Enabled) AND (Sender is TWinControl) then
begin
FNodePositioning:=True;
// when we start resizing the rules do not apply to us :)
FMaxWidth := Constraints.MaxWidth;
FMaxHeight := Constraints.MaxHeight;
Constraints.MaxWidth := 0;
Constraints.MaxHeight := 0;
with pClient do
begin
Align := alClient;
if pBG.Left + BgLeftMargin <= 0 then
BorderSpacing.Left := Max(-pBG.Left - (FHorizontalScrollPos - SIZER_RECT_SIZE), 0)
else
BorderSpacing.Left := Max(pBG.Left + BgLeftMargin, 0);
if pBG.Top + BgTopMargin <= 0 then
BorderSpacing.Top := Max(-pBG.Top - (FVerticalScrollPos - SIZER_RECT_SIZE), 0)
else
BorderSpacing.Top := Max(pBG.Top + BgTopMargin, 0);
BorderSpacing.Right := Max(Self.Width - (pR.Left - BgRightMargin), 0);
BorderSpacing.Bottom := Max(Self.Height - (pB.Top - BgBottomMargin), 0);
end;
// when was active ActivePropertyGrid.ItemIndex for height or width during scaling
// there was problem with values :<
if ((Sender = pR) or (Sender = pB) or (FNodes.IndexOf(Sender) in [3,4,5])) and (FormEditingHook.GetCurrentObjectInspector <> nil) then
begin
FActivePropertyGridItemIndex := FormEditingHook.GetCurrentObjectInspector.GetActivePropertyGrid.ItemIndex;
FormEditingHook.GetCurrentObjectInspector.GetActivePropertyGrid.ItemIndex := -1;
end
else
FActivePropertyGridItemIndex := -1;
{$IF Defined(LCLWin32) or Defined(LCLWin64)}
SetCapture(TWinControl(Sender).Handle);
{$ENDIF}
GetCursorPos(FOldPos);
// perform first "click delta" to reduce leap
// + calculate delta created by scrollbars and theirs position...
FillChar(FDelta, SizeOf(FDelta), #0);
LCtrlPoint := (Sender as TWinControl).ScreenToClient(Mouse.CursorPos);
if Sender = pR then
begin
FDelta.X := -(LCtrlPoint.x - RightSizerLineWidth) + RightMargin;
FPositioningKind := [pkRight];
end
else if Sender = pB then
begin
FDelta.Y := -(LCtrlPoint.y - BottomSizerLineWidth) + BottomMargin;
FPositioningKind := [pkBottom];
end
else
case FNodes.IndexOf(Sender) of
3: // middle right
begin
FDelta.X := -(LCtrlPoint.x - RightSizerRectWidth) + RightMargin;
FPositioningKind := [pkRight];
end;
4: // right bottom
begin
FDelta.X := -(LCtrlPoint.x - RightSizerRectWidth) + RightMargin;
FDelta.Y := -(LCtrlPoint.y - BottomSizerRectHeight) + BottomMargin;
FPositioningKind := [pkRight, pkBottom];
end;
5: // middle bottom
begin
FDelta.Y := -(LCtrlPoint.y - BottomSizerRectHeight) + BottomMargin;
FPositioningKind := [pkBottom];
end;
end;
end;
end;
procedure TResizerFrame.NodeMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var
newPos: TPoint;
frmPoint : TPoint;
OldRect: TRect;
AdjL,AdjR,AdjT,AdjB: Boolean;
begin
// handle TPanel for resizing rectangles
if Sender is TGraphicControl then
Sender := TGraphicControl(Sender).Parent;
if FNodePositioning then
begin
begin
with TWinControl(Sender) do
begin
GetCursorPos(newPos);
if (newPos.x = FOldPos.x) and (newPos.y = FOldPos.y) then
Exit;
HideSizeControls;
with Self do
begin //resize
frmPoint := Self.ScreenToClient(Mouse.CursorPos);
frmPoint.x:= frmPoint.x + FDelta.x;
frmPoint.y:= frmPoint.y + FDelta.y;
OldRect := Self.BoundsRect;
AdjL := False;
AdjR := False;
AdjT := False;
AdjB := False;
case FNodes.IndexOf(TWinControl(Sender)) of
0: begin
//AdjL := True;
//AdjT := True;
end;
1: begin
//AdjT := True;
end;
2: begin
//AdjR := True;
//AdjT := True;
end;
3, 10: begin
AdjR := True;
end;
4: begin
AdjR := True;
AdjB := True;
end;
5, 11: begin
AdjB := True;
end;
6: begin
//AdjL := True;
//AdjB := True;
end;
7: begin
//AdjL := True;
end;
end;
if AdjL then
OldRect.Left := frmPoint.X;
if AdjR then
OldRect.Right := frmPoint.X;
if AdjT then
OldRect.Top := frmPoint.Y;
if AdjB then
OldRect.Bottom := frmPoint.Y;
SetBounds(OldRect.Left,OldRect.Top,OldRect.Right - OldRect.Left,OldRect.Bottom - OldRect.Top);
end;
//move node
Left := Left - FOldPos.X + newPos.X;
Top := Top - FOldPos.Y + newPos.Y;
FOldPos := newPos;
end;
end;
PositionNodes(Self);
if Assigned(OnNodePositioning) then
OnNodePositioning(Self, FPositioningKind, pcPositioning);
// the same operation as belowe exist in ClientChangeBounds but it is
// disabled for FNodePositioning = true
// we need to refresh this values after OnNodePositioning
FLastClientWidth := pClient.Width;
FLastClientHeight:= pClient.Height;
end;
end;
procedure TResizerFrame.NodeMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Sender is TGraphicControl then
Sender := TGraphicControl(Sender).Parent;
if FNodePositioning then
begin
Screen.Cursor := crDefault;
{$IF Defined(LCLWin32) or Defined(LCLWin64)}
ReleaseCapture;
{$ENDIF}
// restore last selected item in OI.
if FActivePropertyGridItemIndex <> -1 then
begin
if FormEditingHook.GetCurrentObjectInspector <> nil then
FormEditingHook.GetCurrentObjectInspector.GetActivePropertyGrid.ItemIndex := FActivePropertyGridItemIndex;
FActivePropertyGridItemIndex := -1;
end;
Constraints.MaxWidth := FMaxWidth;
Constraints.MaxHeight := FMaxHeight;
FNodePositioning := False;
ShowSizeControls;
if Assigned(OnNodePositioning) then
OnNodePositioning(Sender, FPositioningKind, pcPositioningEnd);
FPositioningKind := [];
pClient.Align := alNone;
BorderSpacing.Left := 0;
BorderSpacing.Top := 0;
BorderSpacing.Right := 0;
BorderSpacing.Bottom := 0;
PositionNodes(Self);
GlobalDesignHook.RefreshPropertyValues;
// after resizing, TFrame is frozen in Windows OS
// this is trick to workaraund IDE bug. Also for proper size for normal form
TryBoundDesignedForm;
end;
end;
function TResizerFrame.GetRightMargin: Integer;
begin
if not FNodePositioning then
FLastRightMarign := Width - (pR.Left + pR.Width);
Result := FLastRightMarign;
end;
function TResizerFrame.GetBottomMargin: Integer;
begin
if not FNodePositioning then
FLastBottomMarign := Height - (pB.Top + pB.Height);
Result := FLastBottomMarign;
end;
{-----------------------------------------------------------------------------------------------------------------------
for Vertical scroll
{----------------------------------------------------------------------------------------------------------------------}
function TResizerFrame.BottomSizerRectHeight: Integer;
begin
Result := SIZER_RECT_SIZE;
end;
function TResizerFrame.BottomSizerLineWidth: Integer;
begin
Result := SIZER_LINE_WIDTH;
end;
function TResizerFrame.TopSizerRectTop: Integer;
begin
Result := -FVerticalScrollPos;
end;
function TResizerFrame.TopSizerLineWidth: Integer;
begin
Result := SIZER_LINE_WIDTH;
end;
function TResizerFrame.VerticalSizerLineLength: Integer;
begin
Result := Height - BottomMargin;
end;
{-----------------------------------------------------------------------------------------------------------------------
for Horizontal scroll
{----------------------------------------------------------------------------------------------------------------------}
function TResizerFrame.RightSizerRectWidth: Integer;
begin
Result := SIZER_RECT_SIZE;
end;
function TResizerFrame.RightSizerLineWidth: Integer;
begin
Result := SIZER_LINE_WIDTH;
end;
function TResizerFrame.LeftSizerRectLeft: Integer;
begin
Result := -FHorizontalScrollPos;
end;
function TResizerFrame.LeftSizerLineWidth: Integer;
begin
Result := SIZER_LINE_WIDTH;
end;
function TResizerFrame.HorizontalSizerLineLength: Integer;
begin
Result := Width - RightMargin;
end;
function TResizerFrame.GetBackgroundMargin(const AIndex: Integer): Integer;
begin
if FBackground = nil then
Result := 0
else
Result := FBackground.GetMargin(AIndex);
end;
procedure TResizerFrame.TryBoundDesignedForm;
begin
if DesignedForm = nil then
Exit;
DesignedForm.BeginUpdate;
DesignedForm.RealWidth := DesignedForm.RealWidth + 1;
DesignedForm.RealWidth := DesignedForm.RealWidth - 1;
DesignedForm.EndUpdate;
HideSizeControls;
ShowSizeControls;
// for GTK2 resizing form (pClient is hidden under pBG)
{$IF DEFINED(LCLGtk2) OR DEFINED(LCLQt)}
pClient.SendToBack; // <--- this is a must.
{$ENDIF}
pClient.BringToFront;
end;
function TResizerFrame.DesignedWidthToScroll: Integer;
begin
if DesignedForm = nil then
Exit(0);
Result := DesignedForm.Width - FLastClientWidth;
//Result := DesignedForm.Width - DesignedForm.RealWidth;
end;
function TResizerFrame.DesignedHeightToScroll: Integer;
begin
if DesignedForm = nil then
Exit(0);
Result := DesignedForm.Height - FLastClientHeight;
//Result := DesignedForm.Height - DesignedForm.RealHeight;
end;
{}
constructor TResizerFrame.Create(TheOwner: TComponent);
begin
inherited Create(TheOwner);
FNodes := TObjectList.Create(False);
CreateNodes;
pL.OnPaint := PanelPaint;
pT.OnPaint := PanelPaint;
pR.OnPaint := PanelPaint;
pB.OnPaint := PanelPaint;
pClient.OnChangeBounds := ClientChangeBounds;
pBG.OnChangeBounds := BGChangeBounds;
PositionNodes(Self);
end;
destructor TResizerFrame.Destroy;
begin
FNodes.Free;
inherited Destroy;
end;
procedure TResizerFrame.PositionNodes(AroundControl: TWinControl);
var
Node,T,L,CT,CL,FR,FB,FT,FL: Integer;
TopLeft: TPoint;
begin
if FDesignedForm = nil then
Exit;
// positions of bars
if not FNodePositioning then
begin
pL.Left := -FHorizontalScrollPos;
pR.Left := FDesignedForm.Width - FHorizontalScrollPos + pL.Width + BgRightMargin + BgLeftMargin;
pT.Top := -FVerticalScrollPos;
pB.Top := FDesignedForm.Height - FVerticalScrollPos + pT.Height + BgBottomMargin + BgTopMargin;
// width and height
pL.Top:=0;
pL.Height := FDesignedForm.Height + 2*SIZER_RECT_SIZE + BgTopMargin + BgBottomMargin;
pR.Top:=0;
pR.Height := FDesignedForm.Height + 2*SIZER_RECT_SIZE + BgTopMargin + BgBottomMargin;
pT.Left:=0;
pT.Width := FDesignedForm.Width + 2*SIZER_RECT_SIZE + BgLeftMargin + BgRightMargin;
pB.Left:=0;
pB.Width := FDesignedForm.Width + 2*SIZER_RECT_SIZE + BgLeftMargin + BgRightMargin;
// client
if pBG.Left + BgLeftMargin <= 0 then
pClient.Left := -(pBG.Left) - (FHorizontalScrollPos - SIZER_RECT_SIZE)
else
pClient.Left := pBG.Left + BgLeftMargin;
if pBG.Top + BgTopMargin <= 0 then
pClient.Top := -(pBG.Top) - (FVerticalScrollPos - SIZER_RECT_SIZE)
else
pClient.Top := pBG.Top + BgTopMargin;
pClient.Height := Height - pClient.Top - Max(Height - (pB.Top - BgBottomMargin), 0);
pClient.Width := Width - pClient.Left - Max(Width - (pR.Left - BgRightMargin), 0);
end;
for Node := 0 to 7 do
begin
with AroundControl do
begin
FR := Width - RightSizerRectWidth - RightMargin;
FB := Height - BottomSizerRectHeight - BottomMargin;
FT := TopSizerRectTop;
FL := LeftSizerRectLeft;
CL := (FR - FL) div 2 + FL;
CT := (FB - FT) div 2 + FT;
case Node of
0: begin
T := FT;
L := FL;
end;
1: begin
T := FT;
L := CL;
end;
2: begin
T := FT;
L := FR;
end;
3: begin
T := CT;
L := FR;
end;
4: begin
T := FB;
L := FR;
end;
5: begin
T := FB;
L := CL;
end;
6: begin
T := FB;
L := FL;
end;
7: begin
T := CT;
L := FL;
end;
else
T := 0;
L := 0;
end;
TopLeft := (Classes.Point(L,T));
end;
with TPanel(FNodes[Node]) do
begin
Top := TopLeft.Y;
Left := TopLeft.X;
Repaint;
end;
end;
end;
end.

View File

@ -0,0 +1,123 @@
{
*****************************************************************************
See the file COPYING.modifiedLGPL.txt, included in this distribution,
for details about the license.
*****************************************************************************
Author: Maciej Izak
DaThoX 2004-2015
FreeSparta.com
}
unit SpartaAPI;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls;
type
IResizer = interface
['{C3D1A2C0-8AED-493B-9809-1F5C3A54A8A8}']
procedure TryBoundSizerToDesignedForm(Sender: TObject);
end;
ISTADesignTimeUtil = interface
['{E135BF89-AFA9-402A-9663-4F1536C7717A}']
function GetRoot: TPersistent;
procedure SetRoot(ARoot: TPersistent);
property Root: TPersistent read GetRoot write SetRoot;
end;
// Sparta Tools API
ISTAMainDesignTimeUtil = interface(ISTADesignTimeUtil)
['{53491607-D285-4050-9064-C764EB8E59B9}']
function GetShowNonVisualComponents: Boolean;
property ShowNonVisualComponents: Boolean read GetShowNonVisualComponents;
end;
ISTANonVisualComponentsUtil = interface(ISTADesignTimeUtil)
['{A181688F-572E-4724-AAF1-575B979A1EC2}']
function GetShowNonVisualComponents: Boolean;
property ShowNonVisualComponents: Boolean read GetShowNonVisualComponents;
end;
ISTAExtendedDesignTimeUtil = interface(ISTADesignTimeUtil)
['{1F484121-2295-4847-BFD9-A77C643EA3A7}']
// TODO OnShow
// TODO OnHide
// TODO UpdateRoot
// TODO FreeOnStrongHide...? free mem for some utils
procedure RefreshValues;
procedure SetParent(AWinCtrl: TWinControl);
function GetParent: TWinControl;
procedure SetVisible(AValue: Boolean);
function GetVisible: Boolean;
property Visible: Boolean read GetVisible write SetVisible;
property Parent: TWinControl read GetParent write SetParent;
end;
TSTADesignTimeUtil = class
end;
TSTADesignTimeUtilClass = class of TSTADesignTimeUtil;
TEDTU = class
public
class function AvailableForRoot(ARoot: TPersistent): Boolean; virtual; abstract;
class function CreateEDTUForRoot(TheOwner: TComponent; ARoot: TPersistent): ISTAExtendedDesignTimeUtil; virtual; abstract;
class function GlyphName: string; virtual; abstract;
end;
TEDTUClass = class of TEDTU;
{ TSTADesignTimeUtilsManager }
TSTADesignTimeUtilsManager = class
protected
function GetEDTUCount: Integer; virtual;
function GetEDTU(Index: Integer): TEDTUClass; virtual; abstract;
public
function CreateMainDTU(AParent, AAddons: TWinControl): ISTAMainDesignTimeUtil; virtual;
procedure RegisterEDTU(AEDTUClass: TEDTUClass); virtual;
procedure UnregisterEDTU(AEDTUClass: TEDTUClass); virtual;
property EDTUCount: Integer read GetEDTUCount;
property EDTU[Index: Integer]: TEDTUClass read GetEDTU;
end;
var
DTUManager: TSTADesignTimeUtilsManager = nil;
implementation
{ TSTADesignTimeUtilsManager }
function TSTADesignTimeUtilsManager.GetEDTUCount: Integer;
begin
Result := 0;
end;
function TSTADesignTimeUtilsManager.CreateMainDTU(AParent, AAddons: TWinControl
): ISTAMainDesignTimeUtil;
begin
Result := nil;
end;
procedure TSTADesignTimeUtilsManager.RegisterEDTU(AEDTUClass: TEDTUClass);
begin
end;
procedure TSTADesignTimeUtilsManager.UnregisterEDTU(AEDTUClass: TEDTUClass);
begin
end;
end.

View File

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<Package Version="4">
<PathDelim Value="\"/>
<Name Value="sparta_DockedFormEditor"/>
<Type Value="RunAndDesignTime"/>
<CompilerOptions>
<Version Value="11"/>
<PathDelim Value="\"/>
<SearchPaths>
<IncludeFiles Value="source"/>
<OtherUnitFiles Value="source"/>
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)\$(LCLWidgetType)"/>
</SearchPaths>
<Linking>
<Debugging>
<UseValgrind Value="True"/>
<UseExternalDbgSyms Value="True"/>
</Debugging>
</Linking>
<Other>
<CustomOptions Value="$(IDEBuildOptions)"/>
</Other>
</CompilerOptions>
<Files Count="11">
<Item1>
<Filename Value="source\sparta_reg_dockedformeditor.pas"/>
<HasRegisterProc Value="True"/>
<UnitName Value="sparta_reg_DockedFormEditor"/>
</Item1>
<Item2>
<Filename Value="source\sparta_designedform.pas"/>
<UnitName Value="sparta_DesignedForm"/>
</Item2>
<Item3>
<Filename Value="source\sparta_resizer.pas"/>
<UnitName Value="sparta_Resizer"/>
</Item3>
<Item4>
<Filename Value="source\sparta_resizerframe.pas"/>
<UnitName Value="sparta_ResizerFrame"/>
</Item4>
<Item5>
<Filename Value="source\spartaapi.pas"/>
<UnitName Value="SpartaAPI"/>
</Item5>
<Item6>
<Filename Value="source\sparta_fakecustom.pas"/>
<UnitName Value="sparta_FakeCustom"/>
</Item6>
<Item7>
<Filename Value="source\sparta_fakeform.pas"/>
<UnitName Value="sparta_FakeForm"/>
</Item7>
<Item8>
<Filename Value="source\sparta_fakeframe.pas"/>
<UnitName Value="sparta_FakeFrame"/>
</Item8>
<Item9>
<Filename Value="source\sparta_fakenoncontrol.pas"/>
<UnitName Value="sparta_FakeNonControl"/>
</Item9>
<Item10>
<Filename Value="source\sparta_mainide.pas"/>
<UnitName Value="sparta_MainIDE"/>
</Item10>
<Item11>
<Filename Value="source\sparta_hashutils.pas"/>
<UnitName Value="sparta_HashUtils"/>
</Item11>
</Files>
<RequiredPkgs Count="1">
<Item1>
<PackageName Value="IDEIntf"/>
</Item1>
</RequiredPkgs>
<UsageOptions>
<UnitPath Value="$(PkgOutDir)"/>
</UsageOptions>
<PublishOptions>
<Version Value="2"/>
</PublishOptions>
</Package>
</CONFIG>

View File

@ -0,0 +1,25 @@
{ This file was automatically created by Lazarus. Do not edit!
This source is only used to compile and install the package.
}
unit sparta_DockedFormEditor;
interface
uses
sparta_reg_DockedFormEditor, sparta_DesignedForm, sparta_Resizer,
sparta_ResizerFrame, SpartaAPI, sparta_FakeCustom, sparta_FakeForm,
sparta_FakeFrame, sparta_FakeNonControl, sparta_MainIDE, sparta_HashUtils,
LazarusPackageIntf;
implementation
procedure Register;
begin
RegisterUnit('sparta_reg_DockedFormEditor',
@sparta_reg_DockedFormEditor.Register);
end;
initialization
RegisterPackage('sparta_DockedFormEditor', @Register);
end.