git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.DevExpressVCL@29 05c56307-c608-d34a-929d-697000501d7a
3063 lines
91 KiB
ObjectPascal
3063 lines
91 KiB
ObjectPascal
{*******************************************************************}
|
|
{ }
|
|
{ ExpressWeb Framework by Developer Express }
|
|
{ Designer Module }
|
|
{ }
|
|
{ Copyright (c) 2000-2008 Developer Express Inc. }
|
|
{ ALL RIGHTS RESERVED }
|
|
{ }
|
|
{ The entire contents of this file is protected by U.S. and }
|
|
{ International Copyright Laws. Unauthorized reproduction, }
|
|
{ reverse-engineering, and distribution of all or any portion of }
|
|
{ the code contained in this file is strictly prohibited and may }
|
|
{ result in severe civil and criminal penalties and will be }
|
|
{ prosecuted to the maximum extent possible under the law. }
|
|
{ }
|
|
{ RESTRICTIONS }
|
|
{ }
|
|
{ THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES }
|
|
{ (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE }
|
|
{ SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS }
|
|
{ LICENSED TO DISTRIBUTE THE EXPRESSWEB FRAMEWORK AND ALL }
|
|
{ ACCOMPANYING VCL CLASSES AS PART OF AN EXECUTABLE WEB }
|
|
{ APPLICATION ONLY. }
|
|
{ }
|
|
{ THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED }
|
|
{ FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE }
|
|
{ COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE }
|
|
{ AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT }
|
|
{ AND PERMISSION FROM DEVELOPER EXPRESS INC. }
|
|
{ }
|
|
{ CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON }
|
|
{ ADDITIONAL RESTRICTIONS. }
|
|
{ }
|
|
{*******************************************************************}
|
|
|
|
unit cxWebHTMLDesigner;
|
|
|
|
interface
|
|
|
|
uses
|
|
Windows, SysUtils, Messages, Classes, Controls, ToolsAPI, Forms, Graphics,
|
|
ImgList, ExtCtrls, Menus, DesignIntf, DesignEditors, VCLEditors, VCLMenus,
|
|
DesignMenus, cxWebCustomDesigner, cxWebIntf, cxWebClasses, cxWebDsgnEnvOpt,
|
|
cxWebDsgnIntf, cxWebDsgnTypes, cxWebDsgnHTMLSource,
|
|
cxWebDsgnDelphiManager, MSHTML_TLB, cxWebDsgnHTMLConverter, cxWebRender,
|
|
cxWebDsgnHTMLCtrls, cxWebHTMLEditor, cxWebHTMLEdBar, cxWebHTMLEdIntf;
|
|
|
|
type
|
|
|
|
TcxWebHTMLDesigner = class;
|
|
|
|
TcxWebHTMLControl = class(TcxHTMLEditor)
|
|
private
|
|
FDesigner: TcxWebHTMLDesigner;
|
|
function GetMainParentElement: IHTMLElement;
|
|
procedure WMKeyDown(var Message: TWMKeyDown); message WM_KEYDOWN;
|
|
procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
|
|
protected
|
|
function ShowBorders: Boolean; override;
|
|
function ShowDetails: Boolean; override;
|
|
function ShowGrid: Boolean; override;
|
|
function SnapToGrid: Boolean; override;
|
|
function GridXSize: Integer; override;
|
|
function GridYSize: Integer; override;
|
|
function IsToolSelected: Boolean; override;
|
|
procedure GetViewLinkContent(const AElement: IHTMLElement; var AContent, ACSSContent, AInlineStyle: string); override;
|
|
function IsElementContainer(const AElement: IHTMLElement): Boolean; override;
|
|
function CanHaveBehavior(const AElement: IHTMLElement): Boolean; override;
|
|
function ContainerLayout(const AElement: IHTMLElement): TcxHTMLContainerLayout; override;
|
|
function CanElementSelect(const AElement: IHTMLElement): Boolean; override;
|
|
|
|
procedure DoOnKeyDown(const AEventObj: IHTMLEventObj); override;
|
|
function DoOnDblClick(const AEventObj: IHTMLEventObj): WordBool; override;
|
|
function DoOnDrop(const AEventObj: IHTMLEventObj): WordBool; override;
|
|
|
|
procedure GetHTMLElementsList(const AList: IInterfaceList); override;
|
|
public
|
|
procedure DeactivateInnerHMTLElement;
|
|
procedure RegisterEWFTags;
|
|
property MainParentElement: IHTMLElement read GetMainParentElement;
|
|
end;
|
|
|
|
TcxWebHTMLSourceEditorNotifier = class(TNotifierObject, IOTANotifier, IOTAEditorNotifier)
|
|
private
|
|
FDesigner: TcxWebHTMLDesigner;
|
|
FID: Integer;
|
|
FIsModified: Boolean;
|
|
protected
|
|
procedure AfterSave;
|
|
procedure BeforeSave;
|
|
procedure Destroyed;
|
|
procedure Modified;
|
|
procedure ViewNotification(const View: IOTAEditView; Operation: TOperation);
|
|
procedure ViewActivated(const View: IOTAEditView);
|
|
public
|
|
constructor Create(ADesigner: TcxWebHTMLDesigner);
|
|
destructor Destroy; override;
|
|
property ID: Integer read FID write FID;
|
|
property IsModified: Boolean read FIsModified write FIsModified;
|
|
end;
|
|
|
|
TcxWebFormNotifier = class(TNotifierObject, IOTANotifier, IOTAFormNotifier)
|
|
private
|
|
FID: Integer;
|
|
FDesigner: TcxWebHTMLDesigner;
|
|
FEditor: IOTAEditor;
|
|
protected
|
|
procedure AfterSave;
|
|
procedure BeforeSave;
|
|
procedure Destroyed;
|
|
procedure Modified;
|
|
procedure FormActivated;
|
|
procedure FormSaving;
|
|
procedure ComponentRenamed(ComponentHandle: TOTAHandle;
|
|
const OldName, NewName: string);
|
|
public
|
|
constructor Create(ADesigner: TcxWebHTMLDesigner);
|
|
destructor Destroy; override;
|
|
end;
|
|
|
|
TcxWebIDENotifier = class(TNotifierObject, IOTANotifier, IOTAIDENotifier)
|
|
private
|
|
FID: Integer;
|
|
FDesigner: TcxWebHTMLDesigner;
|
|
|
|
protected
|
|
procedure AfterSave;
|
|
procedure BeforeSave;
|
|
procedure Destroyed;
|
|
procedure Modified;
|
|
procedure FileNotification(NotifyCode: TOTAFileNotification;
|
|
const FileName: string; var Cancel: Boolean);
|
|
procedure BeforeCompile(const Project: IOTAProject; var Cancel: Boolean);
|
|
procedure AfterCompile(Succeeded: Boolean);
|
|
public
|
|
constructor Create(ADesigner: TcxWebHTMLDesigner);
|
|
destructor Destroy; override;
|
|
end;
|
|
|
|
TcxWebDesignerControlNotify = class(TInterfacedObject, IcxWebDesignerControlNotify)
|
|
private
|
|
FComponent: TComponent;
|
|
FDesigner: TcxWebHTMLDesigner;
|
|
FOldWidth, FOldHeight: Integer;
|
|
|
|
function GetWebControl: IcxWebControl;
|
|
public
|
|
constructor Create(ADesigner: TcxWebHTMLDesigner; AComponent: TComponent);
|
|
|
|
procedure BoundsChanged;
|
|
procedure ParentChanged;
|
|
procedure UpdateContext;
|
|
|
|
property WebControl: IcxWebControl read GetWebControl;
|
|
end;
|
|
|
|
TcxWebHTMLUndoItem = class
|
|
private
|
|
FStream: TMemoryStream;
|
|
FComponentClass: TComponentClass;
|
|
FName: string;
|
|
public
|
|
constructor Create(AComponentClass: TComponentClass; AName: string; AStream: TStream);
|
|
destructor Destroy; override;
|
|
|
|
property Name: string read FName;
|
|
property ComponentClass: TComponentClass read FComponentClass;
|
|
end;
|
|
|
|
TcxWebHTMLUndoItems = class
|
|
private
|
|
FDesigner: TcxWebHTMLDesigner;
|
|
FItems: TList;
|
|
public
|
|
constructor Create(ADesigner: TcxWebHTMLDesigner);
|
|
destructor Destroy; override;
|
|
procedure AddItem(AComponentClass: TComponentClass; AName: string; AStream: TStream);
|
|
function LastItem: TcxWebHTMLUndoItem;
|
|
procedure RestoreItem;
|
|
end;
|
|
|
|
TcxWebHTMLUndo = class
|
|
private
|
|
FDesigner: TcxWebHTMLDesigner;
|
|
FList: TList;
|
|
protected
|
|
function DesignerControl: TcxWebHTMLControl;
|
|
function LastItem: TcxWebHTMLUndoItems;
|
|
public
|
|
constructor Create(ADesigner: TcxWebHTMLDesigner);
|
|
destructor Destroy; override;
|
|
procedure Clear;
|
|
procedure Undo;
|
|
function CanUndo: Boolean;
|
|
function LastGroup: TcxWebHTMLUndoItems;
|
|
function CreateNewGroup: TcxWebHTMLUndoItems;
|
|
procedure AddDeletedComponent(AItem: TcxWebHTMLUndoItems; AComponent: TComponent);
|
|
end;
|
|
|
|
TcxWebHTMLDesigner = class(TcxWebCustomDesigner, IcxBaseHTMLElementCreatorNotify)
|
|
private
|
|
FDesignerControl: TcxWebHTMLControl;
|
|
FDesignerBar: TcxHTMLEditorBar;
|
|
FUndo: TcxWebHTMLUndo;
|
|
FHTMLSource: TcxWebDsgnHTMLSource;
|
|
FHTMLSourceEditorNotifier: TcxWebHTMLSourceEditorNotifier;
|
|
FEditorManagerListener: TcxWebDelphiEditorManagerListener;
|
|
FFormNotifier: IOTAFormNotifier;
|
|
FIDeNotifier: IOTAIDENotifier;
|
|
FHTMLSelectedControls: TList;
|
|
FHasHTMLLoaded: Boolean;
|
|
FHTMLSaving: Boolean;
|
|
FIsComponentInserting: Boolean;
|
|
FInsertingComponent: TComponent;
|
|
FInsertingComponentName: string;
|
|
FClipboardSelection: TList;
|
|
FStoredTags: TcxEWFStoredTags;
|
|
FChangedNames: TStringList;
|
|
FOldPositioningType: TcxWebPositioningType;
|
|
FHTMLBefore, FHTMLAfter: string;
|
|
// HTML Editor events
|
|
procedure DHTMLControlInsertControl(Sender: TObject; R: TRect; var HTML, InnerHTML: string;
|
|
var ParentElement: IHTMLElement);
|
|
procedure DHTMLControlInsertedControl(Sender: TObject; Element: IHTMLElement);
|
|
procedure DHTMLControlGetContext(AElement: IHTMLElement;
|
|
var AContent, ACSSContent, AInlineStyle: string);
|
|
procedure DHTMLControlParentChanged(ASender: TObject; ANewParent: IHTMLElement);
|
|
procedure DHTMLControlSelectionChanged(Sender: TObject);
|
|
procedure DHTMLControlMoved(Sender: TObject);
|
|
procedure DHTMLControlResized(Sender: TObject);
|
|
procedure DHTMLControlContextMenu(ASender: TObject; APos: TPoint;
|
|
AElement: IHTMLElement);
|
|
|
|
procedure DoEditorFormActivated(Sender: TObject);
|
|
|
|
// HTML & designer synchronization
|
|
procedure UpdateHTMLSource;
|
|
procedure UpdateDesignerHTML(ADeleteComponents: Boolean);
|
|
procedure UpdateHTMLControlContext(AComponent: TComponent);
|
|
procedure InsertWebDesignControl(AWebControl: IcxWebControl);
|
|
procedure DHTMLControlBoundsRectChanged(AIsMoved: Boolean);
|
|
procedure DoMapperElementChanged(Sender: TObject);
|
|
procedure HTMLChangeNotify(Sender: TObject);
|
|
|
|
procedure FreeComponents(AList: TList; ADelete: Boolean);
|
|
procedure CheckForDeletedControls;
|
|
procedure UpdateSelectedEWFBehaviors;
|
|
procedure InternalInsertHTMLControl(AComponent: TComponent;
|
|
ANewName: string; ANeedOffSet: Boolean);
|
|
|
|
//Selection
|
|
procedure ClearHTMLSelectedControls;
|
|
procedure ClearSelection;
|
|
procedure CreateHTMLSelectedControls;
|
|
function SelectionCount: Integer;
|
|
function IsComponentSelected: Boolean;
|
|
procedure InternalDHTMLControlSelectionChanged;
|
|
|
|
procedure ReadComponent(AComponent: TComponent);
|
|
procedure DoPaste;
|
|
procedure DoCopy;
|
|
protected
|
|
procedure IDEDesignerOptionsChagned; override;
|
|
|
|
function GetHTMLTemplateModified(var AFileName, AText: string): Boolean; override;
|
|
{ IcxBaseHTMLElementCreatorNotify }
|
|
procedure HTMLElementCreated(ABaseHTMLElement: TcxBaseHTMLElement);
|
|
function GetHTMLElementFileName: string;
|
|
procedure ReaderSetName(AReader: TReader; AComponent: TComponent; var AName: string); override;
|
|
public
|
|
constructor Create(AForm: TCustomForm; ADelphiDesigner: IDesigner); override;
|
|
destructor Destroy; override;
|
|
|
|
procedure Modified; override;
|
|
procedure ComponentCreated(AnItem: TComponent); override;
|
|
procedure ComponentDestroyed(AnItem: TComponent); override;
|
|
procedure ComponentChangedName(AComponent: TComponent; const AOldName, ANewName: string); override;
|
|
|
|
procedure CreateDesignerControl(AParentControl: TWinControl); override;
|
|
procedure DestroyDesignerControl; override;
|
|
function GetDesignerControl: TWinControl; override;
|
|
procedure RefreshDesignControls; override;
|
|
procedure UpdateDesignerControl; override;
|
|
procedure DesignerIdChanging; override;
|
|
procedure DesignerPositioningTypeChanged; override;
|
|
procedure DesignerActivated; override;
|
|
procedure DesignerDeactivated; override;
|
|
procedure PreviewShowing; override;
|
|
function GetControlPositioningType: TcxWebPositioningType; override;
|
|
|
|
class function GetID: Integer; override;
|
|
class function GetName: String; override;
|
|
|
|
function CanAlign: Boolean; override;
|
|
function CanAlignToGrid: Boolean; override;
|
|
function CanCopy: Boolean; override;
|
|
function CanCut: Boolean; override;
|
|
function CanDelete: Boolean; override;
|
|
function CanPaste: Boolean; override;
|
|
function CanSelectAll: Boolean; override;
|
|
function CanTabOrder: Boolean; override;
|
|
function CanUndo: Boolean; override;
|
|
|
|
procedure ScaleSelection(AScaleFactor: Integer); override;
|
|
procedure AlignSelection(AHorzAlign: TcxHorzAlign; AVertAlign: TcxVertAlign); override;
|
|
procedure SizeSelection(AHorzAffect: TcxSizeAffect; AVertAffect: TcxSizeAffect;
|
|
AHorzAbsolute: Integer; AVertAbsolute: Integer); override;
|
|
function ShowTabOrderSelectionDlg: Boolean; override;
|
|
|
|
{ IcxWebDesigner }
|
|
procedure AlignToGrid; override;
|
|
function CanSelect(const AControl: TComponent): Boolean; override;
|
|
procedure CopySelection; override;
|
|
procedure CutSelection; override;
|
|
procedure DeleteSelection; override;
|
|
procedure Edit(AComponent: TComponent); override;
|
|
procedure GetSelections(const AList: TList); override;
|
|
procedure PasteSelection; override;
|
|
procedure SelectAll; override;
|
|
procedure SelectionChanged(const AList: TList); override;
|
|
procedure Undo; override;
|
|
end;
|
|
|
|
|
|
implementation
|
|
|
|
uses
|
|
ComponentDesigner, cxWebDsgnFactory, cxWebStrs, StrUtils,
|
|
cxWebUtils, cxWebHTMLElementMapper, HTTPProd,
|
|
cxWebHTMLProd, cxWebDsgnUtils, Clipbrd, Variants, cxWebFileCacheManager,
|
|
cxWebPathConst, cxfmTabOrder, cxWebDsgnStrs;
|
|
|
|
{ TcxWebHTMLControl }
|
|
|
|
procedure TcxWebHTMLControl.GetHTMLElementsList(const AList: IInterfaceList);
|
|
begin
|
|
GetHTMLElements(Document, AList);
|
|
end;
|
|
|
|
procedure TcxWebHTMLControl.RegisterEWFTags;
|
|
var
|
|
I: Integer;
|
|
AStrings: TStringList;
|
|
begin
|
|
AStrings := TStringList.Create;
|
|
GetRegisterEWFTags(AStrings);
|
|
try
|
|
for I := 0 to AStrings.Count - 1 do
|
|
RegisterTags(scxEWF, [AStrings[I]]);
|
|
finally
|
|
AStrings.Free;
|
|
end;
|
|
end;
|
|
|
|
function TcxWebHTMLControl.GetMainParentElement: IHTMLElement;
|
|
begin
|
|
Result := GetDesignerHTMLMainParentElement(Document, FDesigner.Root);
|
|
end;
|
|
|
|
procedure TcxWebHTMLControl.WMKeyDown(var Message: TWMKeyDown);
|
|
begin
|
|
if Message.CharCode = VK_TAB then
|
|
Message.Result := 1
|
|
else inherited;
|
|
end;
|
|
|
|
procedure TcxWebHTMLControl.WMGetDlgCode(var Message: TWMGetDlgCode);
|
|
begin
|
|
Message.Result := DLGC_WANTARROWS or DLGC_WANTTAB;
|
|
end;
|
|
|
|
function TcxWebHTMLControl.ShowBorders: Boolean;
|
|
begin
|
|
Result := inherited ShowBorders;
|
|
end;
|
|
|
|
function TcxWebHTMLControl.ShowDetails: Boolean;
|
|
begin
|
|
Result := inherited ShowDetails;
|
|
end;
|
|
|
|
function TcxWebHTMLControl.ShowGrid: Boolean;
|
|
begin
|
|
Result := FDesigner.DisplayGrid;
|
|
end;
|
|
|
|
function TcxWebHTMLControl.SnapToGrid: Boolean;
|
|
begin
|
|
Result := FDesigner.SnapToGrid;
|
|
end;
|
|
|
|
function TcxWebHTMLControl.GridXSize: Integer;
|
|
begin
|
|
Result := FDesigner.GridSizeX;
|
|
end;
|
|
|
|
function TcxWebHTMLControl.GridYSize: Integer;
|
|
begin
|
|
Result := FDesigner.GridSizeY;
|
|
end;
|
|
|
|
function TcxWebHTMLControl.IsToolSelected: Boolean;
|
|
begin
|
|
Result := FDesigner.GetCurrComponentClass <> nil;
|
|
end;
|
|
|
|
type
|
|
TWinControlAccess = class(TWinControl);
|
|
|
|
procedure TcxWebHTMLControl.DoOnKeyDown(const AEventObj: IHTMLEventObj);
|
|
begin
|
|
if AEventObj <> nil then
|
|
case AEventObj.keyCode of
|
|
Integer('Z'):
|
|
//TODO
|
|
if AEventObj.ctrlKey then
|
|
begin
|
|
AEventObj.returnValue := False;
|
|
FDesigner.Undo;
|
|
end;
|
|
Integer('X'):
|
|
if AEventObj.ctrlKey then
|
|
begin
|
|
AEventObj.returnValue := False;
|
|
FDesigner.CutSelection;
|
|
end;
|
|
Integer('V'):
|
|
if AEventObj.ctrlKey then
|
|
begin
|
|
AEventObj.returnValue := False;
|
|
FDesigner.PasteSelection;
|
|
end;
|
|
Integer('C'):
|
|
if AEventObj.ctrlKey then
|
|
begin
|
|
AEventObj.returnValue := False;
|
|
FDesigner.CopySelection;
|
|
end;
|
|
VK_INSERT:
|
|
begin
|
|
if AEventObj.ctrlKey then
|
|
begin
|
|
AEventObj.returnValue := False;
|
|
FDesigner.CopySelection;
|
|
end
|
|
else
|
|
if AEventObj.shiftKey then
|
|
begin
|
|
AEventObj.returnValue := False;
|
|
FDesigner.PasteSelection;
|
|
end;
|
|
end;
|
|
VK_DELETE:
|
|
begin
|
|
if FDesigner.IsComponentSelected then
|
|
begin
|
|
AEventObj.returnValue := False;
|
|
FDesigner.DeleteSelection;
|
|
end;
|
|
end;
|
|
VK_F9, VK_F12:
|
|
begin
|
|
AEventObj.returnValue := False;
|
|
AEventObj.cancelBubble := True;
|
|
if (GetParentForm(self) <> nil) then
|
|
begin
|
|
try
|
|
Enabled := False;
|
|
finally
|
|
Enabled := True;
|
|
end;
|
|
PostMessage(GetParentForm(self).Handle, WM_KEYDOWN, AEventObj.keyCode, 0);
|
|
PostMessage(GetParentForm(self).Handle, WM_KEYUP, AEventObj.keyCode, 0);
|
|
end;
|
|
exit;
|
|
end;
|
|
end;
|
|
inherited DoOnKeyDown(AEventObj);
|
|
end;
|
|
|
|
function TcxWebHTMLControl.DoOnDblClick(const AEventObj: IHTMLEventObj): WordBool;
|
|
var
|
|
AComponent: TComponent;
|
|
begin
|
|
Result := inherited DoOnDblClick(AEventObj);
|
|
if (AEventObj.srcElement <> nil) then
|
|
begin
|
|
AComponent := GetComponentByHTMLElement(FDesigner.Root, AEventObj.srcElement);
|
|
if (AComponent <> nil) and not Supports(AComponent, IcxWebContainerControl) then
|
|
FDesigner.DelphiDesigner.Edit(AComponent);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxWebHTMLControl.GetViewLinkContent(const AElement: IHTMLElement;
|
|
var AContent, ACSSContent, AInlineStyle: string);
|
|
begin
|
|
inherited;
|
|
FDesigner.DHTMLControlGetContext(AElement, AContent, ACSSContent, AInlineStyle);
|
|
end;
|
|
|
|
function TcxWebHTMLControl.IsElementContainer(const AElement: IHTMLElement): Boolean;
|
|
var
|
|
AComponent: TComponent;
|
|
begin
|
|
AComponent := GetComponentByHTMLElement(FDesigner.Root, AElement);
|
|
Result := (AComponent <> nil) and Supports(AComponent, IcxWebContainerControl);
|
|
end;
|
|
|
|
function TcxWebHTMLControl.CanHaveBehavior(const AElement: IHTMLElement): Boolean;
|
|
begin
|
|
Result := not Supports(AElement, IHTMLFormElement) and
|
|
not SameText(AElement.tagName, 'form') ;
|
|
end;
|
|
|
|
function TcxWebHTMLControl.ContainerLayout(const AElement: IHTMLElement): TcxHTMLContainerLayout;
|
|
begin
|
|
Result := inherited ContainerLayout(AElement);
|
|
if Supports(AElement, IHTMLBodyElement) then
|
|
if FDesigner.PositioningType = cxptFlow then
|
|
Result := hclFlow
|
|
else
|
|
Result := hclGrid;
|
|
end;
|
|
|
|
function TcxWebHTMLControl.CanElementSelect(const AElement: IHTMLElement): Boolean;
|
|
begin
|
|
if AElement <> nil then
|
|
Result := not Supports(AElement, IHTMLBodyElement) and
|
|
not Supports(AElement, IHTMLFormElement) and
|
|
not SameText(AElement.tagName, 'form')
|
|
else
|
|
Result := False;
|
|
end;
|
|
|
|
procedure TcxWebHTMLControl.DeactivateInnerHMTLElement;
|
|
var
|
|
AElement: IHTMLElement;
|
|
begin
|
|
if not FDesigner.FHasHTMLLoaded then exit;
|
|
if (Selection.Count = 1) then
|
|
begin
|
|
AElement := Selection[0];
|
|
if (AElement <> nil) and not (AElement as IHTMLElement3).isDisabled and
|
|
(GetComponentByHTMLElement(FDesigner.Root, AElement) = nil) then
|
|
begin
|
|
try
|
|
FDesigner.BeginUpdate;
|
|
(AElement as IHTMLElement3).disabled := true;
|
|
(AElement as IHTMLElement3).disabled := false;
|
|
if AElement.ParentElement <> nil then
|
|
Selection.Add(AElement);
|
|
finally
|
|
FDesigner.CancelUpdate;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxWebHTMLControl.DoOnDrop(const AEventObj: IHTMLEventObj): WordBool;
|
|
begin
|
|
if AEventObj.ctrlKey and IsHTMLCustomElement(self.DraggingElement) then
|
|
begin
|
|
AEventObj.returnValue := False;
|
|
Result := False;
|
|
end else Result := inherited DoOnDrop(AEventObj);
|
|
end;
|
|
|
|
procedure UpdateHTMLElementStylePositions(AHTMLElement: IHTMLElement; AWebControl: IcxWebControl);
|
|
begin
|
|
with AWebControl.BoundsRect do
|
|
begin
|
|
AHTMLElement.style.pixelLeft := Left;
|
|
AHTMLElement.style.pixelTop := Top;
|
|
AHTMLElement.style.pixelWidth := Right - Left;
|
|
AHTMLElement.style.pixelHeight := Bottom - Top;
|
|
end;
|
|
end;
|
|
|
|
{ TcxWebDesignerControlNotify }
|
|
constructor TcxWebDesignerControlNotify.Create(ADesigner: TcxWebHTMLDesigner; AComponent: TComponent);
|
|
begin
|
|
FDesigner := ADesigner;
|
|
FComponent := AComponent;
|
|
end;
|
|
|
|
function TcxWebDesignerControlNotify.GetWebControl: IcxWebControl;
|
|
begin
|
|
Supports(FComponent, IcxWebControl, Result);
|
|
end;
|
|
|
|
procedure TcxWebDesignerControlNotify.BoundsChanged;
|
|
var
|
|
AHTMLElement: IHTMLElement;
|
|
AComponentName: string;
|
|
begin
|
|
if not FDesigner.FHasHTMLLoaded or FDesigner.FHTMLSaving then exit;
|
|
if FComponent.Name <> '' then
|
|
AComponentName := FComponent.Name
|
|
else AComponentName := FDesigner.FInsertingComponentName;
|
|
if AComponentName = '' then exit;
|
|
AHTMLElement := GetHTMLElementByComponentName(FDesigner.FDesignerControl.Document3, AComponentName);
|
|
if AHTMLElement <> nil then
|
|
UpdateHTMLElementStylePositions(AHTMLElement, WebControl);
|
|
with WebControl.BoundsRect do
|
|
begin
|
|
if (FOldWidth <> Right - Left) or
|
|
(FOldHeight <> Bottom - Top) then
|
|
UpdateContext;
|
|
FOldWidth := Right - Left;
|
|
FOldHeight := Bottom - Top;
|
|
if (FDesigner.UpdateCount = 0) then
|
|
begin
|
|
if not (FDesigner.FDesignerControl.State = esMoving) then
|
|
WebControl.UpdateControlPosition;
|
|
FDesigner.BeginUpdate;
|
|
try
|
|
FDesigner.DelphiDesigner.Modified;
|
|
finally
|
|
FDesigner.CancelUpdate;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxWebDesignerControlNotify.ParentChanged;
|
|
var
|
|
AWebParent: IcxWebContainerControl;
|
|
AParentElement, AElement: IHTMLElement;
|
|
AParentComponent: TComponent;
|
|
AParentNode, AElementNode: IHTMLDOMNode;
|
|
begin
|
|
if not FDesigner.FHasHTMLLoaded or (csDestroying in FComponent.ComponentState) then exit;
|
|
AWebParent := WebControl.Parent;
|
|
AElement := GetHTMLElementByComponentName(FDesigner.FDesignerControl.Document3, FComponent.Name);
|
|
AParentComponent := GetComponentByInterface(AWebParent);
|
|
if AParentComponent = nil then
|
|
AParentComponent := FDesigner.DelphiDesigner.Root;
|
|
AParentElement := GetHTMLElementByComponentName(FDesigner.FDesignerControl.Document3, AParentComponent.Name);
|
|
if AParentElement = nil then
|
|
AParentElement := FDesigner.FDesignerControl.Document.body;
|
|
if Supports(AElement, IHTMLDOMNode, AElementNode) and
|
|
Supports(AParentElement, IHTMLDOMNode, AParentNode) then
|
|
begin
|
|
// if not AParentElement.contains(AElement) then
|
|
if not IsEqualElement(AElement.parentElement, AParentElement) then
|
|
AParentNode.appendChild(AElementNode);
|
|
if FDesigner.PositioningType <> cxptFlow then
|
|
begin
|
|
if Supports(AParentComponent, IcxWebPage) then
|
|
AElement.style.setAttribute('position', 'absolute', 0)
|
|
else AElement.style.removeAttribute('position', 0);
|
|
end;
|
|
end;
|
|
WebControl.UpdateControlPosition;
|
|
end;
|
|
|
|
procedure TcxWebDesignerControlNotify.UpdateContext;
|
|
begin
|
|
if not (csDestroying in FDesigner.Root.ComponentState) and
|
|
FDesigner.FHasHTMLLoaded then
|
|
FDesigner.UpdateHTMLControlContext(FComponent);
|
|
end;
|
|
|
|
{ TcxWebHTMLUndoItem }
|
|
constructor TcxWebHTMLUndoItem.Create(AComponentClass: TComponentClass; AName: string; AStream: TStream);
|
|
begin
|
|
FStream := TMemoryStream.Create;
|
|
FStream.LoadFromStream(AStream);
|
|
FComponentClass := AComponentClass;
|
|
FName := AName;
|
|
end;
|
|
|
|
destructor TcxWebHTMLUndoItem.Destroy;
|
|
begin
|
|
FStream.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
{ TcxWebHTMLUndoItems }
|
|
constructor TcxWebHTMLUndoItems.Create(ADesigner: TcxWebHTMLDesigner);
|
|
begin
|
|
FDesigner := ADesigner;
|
|
FItems := TList.Create;
|
|
end;
|
|
|
|
destructor TcxWebHTMLUndoItems.Destroy;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to FItems.Count - 1 do
|
|
TcxWebHTMLUndoItem(FItems[I]).Free;
|
|
FItems.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TcxWebHTMLUndoItems.AddItem(AComponentClass: TComponentClass; AName: string; AStream: TStream);
|
|
begin
|
|
FItems.Add(TcxWebHTMLUndoItem.Create(AComponentClass, AName, AStream));
|
|
end;
|
|
|
|
function TcxWebHTMLUndoItems.LastItem: TcxWebHTMLUndoItem;
|
|
begin
|
|
if FItems.Count > 0 then
|
|
Result := TcxWebHTMLUndoItem(FItems.Last)
|
|
else Result := nil;
|
|
end;
|
|
|
|
procedure TcxWebHTMLUndoItems.RestoreItem;
|
|
var
|
|
AComponent: TComponent;
|
|
AName: string;
|
|
AWebControl: IcxWebControl;
|
|
begin
|
|
AComponent := LastItem.ComponentClass.Create(FDesigner.Root);
|
|
if FDesigner.Root.FindComponent(LastItem.Name) = nil then
|
|
AName := LastItem.Name
|
|
else
|
|
AName := FDesigner.DelphiDesigner.UniqueName(DropT(LastItem.ComponentClass.ClassName));
|
|
AComponent.Name := AName;
|
|
LastItem.FStream.ReadComponent(AComponent);
|
|
if Supports(AComponent, IcxWebControl, AWebControl) then
|
|
begin
|
|
AWebControl.UpdateControlPosition;
|
|
if (AWebControl.DesignerControl <> nil) then
|
|
AWebControl.DesignerControl.UpdateContext;
|
|
end;
|
|
FItems.Delete(FItems.Count - 1);
|
|
end;
|
|
|
|
|
|
{ TcxWebHTMLUndo }
|
|
constructor TcxWebHTMLUndo.Create(ADesigner: TcxWebHTMLDesigner);
|
|
begin
|
|
FDesigner := ADesigner;
|
|
FList := TList.Create;
|
|
end;
|
|
|
|
destructor TcxWebHTMLUndo.Destroy;
|
|
begin
|
|
Clear;
|
|
FList.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TcxWebHTMLUndo.Clear;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to FList.Count - 1 do
|
|
TcxWebHTMLUndoItem(FList[I]).Free;
|
|
FList.Clear;
|
|
end;
|
|
|
|
function TcxWebHTMLUndo.DesignerControl: TcxWebHTMLControl;
|
|
begin
|
|
Result := FDesigner.FDesignerControl;
|
|
end;
|
|
|
|
function TcxWebHTMLUndo.LastItem: TcxWebHTMLUndoItems;
|
|
begin
|
|
if FList.Count > 0 then
|
|
Result := TcxWebHTMLUndoItems(FList.Last)
|
|
else Result := nil;
|
|
end;
|
|
|
|
procedure TcxWebHTMLUndo.Undo;
|
|
begin
|
|
if not CanUndo then exit;
|
|
begin
|
|
while (LastGroup.LastItem <> nil) do
|
|
LastGroup.RestoreItem;
|
|
LastGroup.Free;
|
|
FList.Delete(FList.Count - 1);
|
|
end;
|
|
end;
|
|
|
|
function TcxWebHTMLUndo.CanUndo: Boolean;
|
|
begin
|
|
Result := LastGroup <> nil;
|
|
end;
|
|
|
|
function TcxWebHTMLUndo.LastGroup: TcxWebHTMLUndoItems;
|
|
begin
|
|
if FList.Count > 0 then
|
|
Result := TcxWebHTMLUndoItems(FList.Last)
|
|
else Result := nil;
|
|
end;
|
|
|
|
function TcxWebHTMLUndo.CreateNewGroup: TcxWebHTMLUndoItems;
|
|
begin
|
|
Result := TcxWebHTMLUndoItems.Create(FDesigner);
|
|
FList.Add(Result);
|
|
end;
|
|
|
|
procedure TcxWebHTMLUndo.AddDeletedComponent(AItem: TcxWebHTMLUndoItems; AComponent: TComponent);
|
|
var
|
|
AStream: TMemoryStream;
|
|
begin
|
|
if not Supports(AComponent, IcxWebControl) or
|
|
(csDestroying in FDesigner.Root.ComponentState) then exit;
|
|
AStream := TMemoryStream.Create;
|
|
try
|
|
AStream.WriteComponent(AComponent);
|
|
AItem.AddItem(TComponentClass(AComponent.ClassType),
|
|
AComponent.Name, AStream);
|
|
finally
|
|
AStream.Free;
|
|
end;
|
|
end;
|
|
|
|
|
|
{TcxWebHTMLSourceEditorNotifier}
|
|
constructor TcxWebHTMLSourceEditorNotifier.Create(ADesigner: TcxWebHTMLDesigner);
|
|
begin
|
|
FDesigner := ADesigner;
|
|
end;
|
|
|
|
destructor TcxWebHTMLSourceEditorNotifier.Destroy;
|
|
begin
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TcxWebHTMLSourceEditorNotifier.AfterSave;
|
|
begin
|
|
end;
|
|
|
|
procedure TcxWebHTMLSourceEditorNotifier.BeforeSave;
|
|
begin
|
|
end;
|
|
|
|
procedure TcxWebHTMLSourceEditorNotifier.Destroyed;
|
|
begin
|
|
end;
|
|
|
|
procedure TcxWebHTMLSourceEditorNotifier.Modified;
|
|
begin
|
|
FIsModified := True;
|
|
end;
|
|
|
|
procedure TcxWebHTMLSourceEditorNotifier.ViewNotification(const View: IOTAEditView; Operation: TOperation);
|
|
begin
|
|
end;
|
|
|
|
procedure TcxWebHTMLSourceEditorNotifier.ViewActivated(const View: IOTAEditView);
|
|
begin
|
|
|
|
end;
|
|
|
|
{ TcxWebFormNotifier }
|
|
constructor TcxWebFormNotifier.Create(ADesigner: TcxWebHTMLDesigner);
|
|
begin
|
|
FDesigner := ADesigner;
|
|
FEditor := (BorlandIDEServices as IOTAModuleServices).CurrentModule.CurrentEditor;
|
|
if FEditor <> nil then
|
|
FID := FEditor.AddNotifier(self);
|
|
end;
|
|
|
|
destructor TcxWebFormNotifier.Destroy;
|
|
begin
|
|
if FEditor <> nil then
|
|
FEditor.RemoveNotifier(FID);
|
|
FEditor := nil;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TcxWebFormNotifier.AfterSave;
|
|
begin
|
|
end;
|
|
|
|
procedure TcxWebFormNotifier.BeforeSave;
|
|
begin
|
|
FDesigner.UpdateHTMLSource;
|
|
end;
|
|
|
|
procedure TcxWebFormNotifier.Destroyed;
|
|
begin
|
|
end;
|
|
|
|
procedure TcxWebFormNotifier.Modified;
|
|
begin
|
|
end;
|
|
|
|
procedure TcxWebFormNotifier.FormActivated;
|
|
begin
|
|
end;
|
|
|
|
procedure TcxWebFormNotifier.FormSaving;
|
|
begin
|
|
FDesigner.UpdateHTMLSource;
|
|
end;
|
|
|
|
procedure TcxWebFormNotifier.ComponentRenamed(ComponentHandle: TOTAHandle; const OldName, NewName: string);
|
|
begin
|
|
end;
|
|
|
|
{ TcxWebIDENotifier }
|
|
constructor TcxWebIDENotifier.Create(ADesigner: TcxWebHTMLDesigner);
|
|
begin
|
|
FDesigner := ADesigner;
|
|
FID := (BorlandIDEServices as IOTAServices50).AddNotifier(self);
|
|
end;
|
|
|
|
destructor TcxWebIDENotifier.Destroy;
|
|
begin
|
|
(BorlandIDEServices as IOTAServices50).RemoveNotifier(FID);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TcxWebIDENotifier.AfterSave;
|
|
begin
|
|
end;
|
|
|
|
procedure TcxWebIDENotifier.BeforeSave;
|
|
begin
|
|
end;
|
|
|
|
procedure TcxWebIDENotifier.Destroyed;
|
|
begin
|
|
end;
|
|
|
|
procedure TcxWebIDENotifier.Modified;
|
|
begin
|
|
end;
|
|
|
|
procedure TcxWebIDENotifier.FileNotification(NotifyCode: TOTAFileNotification;
|
|
const FileName: string; var Cancel: Boolean);
|
|
var
|
|
AImplFileName, AIntfFileName, AFormFileName: string;
|
|
begin
|
|
if (NotifyCode = ofnFileOpened) and not (FDesigner.FHasHTMLLoaded) and
|
|
(FDesigner.FHTMLSource.SourceEditor = nil) then
|
|
begin
|
|
FDesigner.DelphiDesigner.ModuleFileNames(AImplFileName, AIntfFileName, AFormFileName);
|
|
if FileName = AImplFileName then
|
|
with FDesigner do
|
|
begin
|
|
FHTMLSource.ReRequestSourceEditor(FileName, nil);
|
|
if FHTMLSource.SourceEditor <> nil then
|
|
begin
|
|
FHTMLSourceEditorNotifier.ID := FHTMLSource.SourceEditor.AddNotifier(FHTMLSourceEditorNotifier);
|
|
UpdateDesignerHTML(False);
|
|
end;
|
|
end;
|
|
end;
|
|
if (NotifyCode = ofnFileOpening) then
|
|
begin
|
|
FDesigner.DelphiDesigner.ModuleFileNames(AImplFileName, AIntfFileName, AFormFileName);
|
|
if FileName = AFormFileName then
|
|
FDesigner.UpdateHTMLSource;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxWebIDENotifier.BeforeCompile(const Project: IOTAProject; var Cancel: Boolean);
|
|
begin
|
|
FDesigner.UpdateHTMLSource;
|
|
end;
|
|
|
|
procedure TcxWebIDENotifier.AfterCompile(Succeeded: Boolean);
|
|
begin
|
|
end;
|
|
|
|
|
|
type
|
|
TcxWebDesignerFileManager = class(TInterfacedObject, IDesignerFileManager)
|
|
private
|
|
function GetGlobalPath: string;
|
|
function GetJSScriptPath: string;
|
|
function GetImagePath: string;
|
|
protected
|
|
function QualifyFileName(const AFileName: string): string;
|
|
function GetStream(const AFileName: string; var AOwned: Boolean): TStream;
|
|
end;
|
|
|
|
function TcxWebDesignerFileManager.GetGlobalPath: string;
|
|
begin
|
|
Result := ExcludeTrailingPathDelimiter(ExtractFilePath(cxGetDesignerApplicationFileName));
|
|
if ExtractFileName(Result) = 'Lib' then
|
|
Result := ExtractFilePath(Result) // old installation
|
|
else
|
|
Result := ExtractFilePath(ExcludeTrailingPathDelimiter(ExtractFilePath(Result))); // new installation
|
|
end;
|
|
|
|
function TcxWebDesignerFileManager.GetJSScriptPath: string;
|
|
begin
|
|
Result := GetGlobalPath + cxWebJScriptDTPath + PathDelim;
|
|
end;
|
|
|
|
function TcxWebDesignerFileManager.GetImagePath: string;
|
|
begin
|
|
Result := GetGlobalPath + cxWebImageDTPath + PathDelim;
|
|
end;
|
|
|
|
function TcxWebDesignerFileManager.QualifyFileName(const AFileName: string): string;
|
|
var
|
|
AExt: string;
|
|
begin
|
|
AExt := UpperCase(ExtractFileExt(AFileName));
|
|
if (AExt <> '') and (AExt[1] = '.') then
|
|
AExt := Copy(AExt, 2, Length(AExt));
|
|
if AExt = 'JS' then
|
|
Result := GetJSScriptPath + AFileName
|
|
else
|
|
if (AExt = 'GIF') or (AExt = 'JPEG') or (AExt = 'BMP') or
|
|
(AExt = 'JPG') then
|
|
Result := GetImagePath + AFileName
|
|
else Result := AFileName;
|
|
Result := StringReplace(Result, '\', '/', [rfReplaceAll, rfIgnoreCase]);
|
|
end;
|
|
|
|
function TcxWebDesignerFileManager.GetStream(const AFileName: string; var AOwned: Boolean): TStream;
|
|
begin
|
|
Result := nil;
|
|
end;
|
|
|
|
var
|
|
FWebDesignerFileManager: TcxWebDesignerFileManager = nil;
|
|
FWebDesignerFileManagerCount: Integer = 0;
|
|
|
|
procedure AddDesignerFileManager;
|
|
begin
|
|
if FWebDesignerFileManager = nil then
|
|
begin
|
|
FWebDesignerFileManager := TcxWebDesignerFileManager.Create;
|
|
DesignerFileManager := FWebDesignerFileManager;
|
|
end;
|
|
Inc(FWebDesignerFileManagerCount);
|
|
end;
|
|
|
|
procedure ReleaseDesignerFileManager;
|
|
begin
|
|
Dec(FWebDesignerFileManagerCount);
|
|
if FWebDesignerFileManagerCount = 0 then
|
|
begin
|
|
FWebDesignerFileManager := nil;
|
|
DesignerFileManager := nil;
|
|
end;
|
|
end;
|
|
|
|
{ TcxWebHTMLDesigner }
|
|
constructor TcxWebHTMLDesigner.Create(AForm: TCustomForm; ADelphiDesigner: IDesigner);
|
|
begin
|
|
inherited Create(AForm, ADelphiDesigner);
|
|
FHTMLSelectedControls := TList.Create;
|
|
TcxWebFileCacheManager.Instance.IncDesignerCount;
|
|
AddDesignerFileManager;
|
|
FStoredTags := TcxEWFStoredTags.Create(Root);
|
|
end;
|
|
|
|
destructor TcxWebHTMLDesigner.Destroy;
|
|
begin
|
|
FStoredTags.Free;
|
|
ReleaseDesignerFileManager;
|
|
TcxWebFileCacheManager.Instance.DecDesignerCount;
|
|
FHTMLSelectedControls.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.Modified;
|
|
begin
|
|
inherited;
|
|
if FDesignerControl <> nil then
|
|
FDesignerControl.Modified := True;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.ComponentCreated(AnItem: TComponent);
|
|
var
|
|
AWebControl: IcxWebControl;
|
|
begin
|
|
if FHasHTMLLoaded and not (csLoading in AnItem.ComponentState) and
|
|
Supports(AnItem, IcxWebControl, AWebControl) then
|
|
begin
|
|
InsertWebDesignControl(AWebControl);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.ComponentDestroyed(AnItem: TComponent);
|
|
var
|
|
AHTMLElement: IHTMLElement;
|
|
begin
|
|
FStoredTags.Remove(AnItem);
|
|
AHTMLElement := GetHTMLElementByComponentName(FDesignerControl.Document3, AnItem.Name);
|
|
if AHTMLElement <> nil then
|
|
AHTMLElement.outerHTML := '';
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.ComponentChangedName(AComponent: TComponent; const AOldName, ANewName: string);
|
|
var
|
|
AHTMLElement: IHTMLElement;
|
|
AWebControl: IcxWebControl;
|
|
begin
|
|
if not FHasHTMLLoaded then exit;
|
|
AHTMLElement := GetHTMLElementByComponentName(FDesignerControl.Document3, AOldName);
|
|
if AHTMLElement <> nil then
|
|
AHTMLElement.id := ANewName
|
|
else
|
|
begin
|
|
if FHasHTMLLoaded and Supports(AComponent, IcxWebControl, AWebControl) and
|
|
(AOldName = '') and (ANewName <> '') and
|
|
not FIsComponentInserting then
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
InternalInsertHTMLControl(AComponent, ANewName, True);
|
|
finally
|
|
CancelUpdate;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.CreateDesignerControl(AParentControl: TWinControl);
|
|
|
|
procedure CreateDesignerBar;
|
|
begin
|
|
try
|
|
SendMessage(AParentControl.Handle, WM_SETREDRAW, Integer(False), 0);
|
|
FDesignerBar := TcxHTMLEditorBar.Create(nil);
|
|
FDesignerBar.Parent := AParentControl;
|
|
FDesignerBar.Align := alTop;
|
|
FDesignerBar.CreateActionControls;
|
|
FDesignerControl.Bar := FDesignerBar;
|
|
finally
|
|
SendMessage(AParentControl.Handle, WM_SETREDRAW, Integer(True), 0);
|
|
RedrawWindow(AParentControl.Handle, nil, 0, RDW_INVALIDATE or RDW_ALLCHILDREN);
|
|
AParentControl.Update;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
FDesignerControl := TcxWebHTMLControl.Create(nil);
|
|
FDesignerControl.FDesigner := self;
|
|
FDesignerControl.Parent := AParentControl;
|
|
FDesignerControl.RegisterEWFTags;
|
|
FDesignerControl.Align := alClient;
|
|
FDesignerControl.SetDesigning(False);
|
|
FDesignerControl.OnControlInsert := DHTMLControlInsertControl;
|
|
FDesignerControl.OnControlInserted := DHTMLControlInsertedControl;
|
|
FDesignerControl.OnSelectionChanged := DHTMLControlSelectionChanged;
|
|
FDesignerControl.OnMoved := DHTMLControlMoved;
|
|
FDesignerControl.OnResized := DHTMLControlResized;
|
|
FDesignerControl.OnShowContextMenu := DHTMLControlContextMenu;
|
|
FDesignerControl.OnParentChanged := DHTMLControlParentChanged;
|
|
|
|
CreateDesignerBar;
|
|
if GetParentForm(AParentControl) <> nil then
|
|
GetParentForm(AParentControl).ActiveControl := FDesignerControl;
|
|
|
|
FUndo := TcxWebHTMLUndo.Create(self);
|
|
|
|
FHTMLSource := TcxWebDsgnHTMLSource.Create('', DelphiDesigner);
|
|
|
|
FHTMLSourceEditorNotifier := TcxWebHTMLSourceEditorNotifier.Create(self);
|
|
if FHTMLSource.SourceEditor <> nil then
|
|
FHTMLSourceEditorNotifier.ID := FHTMLSource.SourceEditor.AddNotifier(FHTMLSourceEditorNotifier);
|
|
|
|
FEditorManagerListener := TcxWebDelphiEditorManagerListener.Create;
|
|
FEditorManagerListener.OnEditorFormActivated := DoEditorFormActivated;
|
|
FFormNotifier := TcxWebFormNotifier.Create(self);
|
|
FIDeNotifier := TcxWebIDENotifier.Create(self);
|
|
|
|
AddBaseHTMLElementCreatorNotify(self);
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.DestroyDesignerControl;
|
|
begin
|
|
FDesignerControl.OnDocumentChange := nil;
|
|
RemoveBaseHTMLElementCreatorNotify(self);
|
|
|
|
FHasHTMLLoaded := False;
|
|
FEditorManagerListener.Free;
|
|
|
|
if FHTMLSource.SourceEditor <> nil then
|
|
FHTMLSource.SourceEditor.RemoveNotifier(FHTMLSourceEditorNotifier.ID);
|
|
FHTMLSourceEditorNotifier := nil;
|
|
FFormNotifier._Release;
|
|
FFormNotifier := nil;
|
|
FIDENotifier._Release;
|
|
FIDENotifier := nil;
|
|
FHTMLSource.Free;
|
|
ClearHTMLSelectedControls;
|
|
|
|
FUndo.Free;
|
|
|
|
FDesignerControl.Bar := nil;
|
|
FDesignerBar.Free;
|
|
FDesignerBar := nil;
|
|
FDesignerControl.Free;
|
|
FDesignerControl := nil;
|
|
end;
|
|
|
|
function TcxWebHTMLDesigner.GetDesignerControl: TWinControl;
|
|
begin
|
|
Result := FDesignerControl;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.RefreshDesignControls;
|
|
begin
|
|
FOldPositioningType := PositioningType;
|
|
if FHTMLSource.SourceEditor <> nil then
|
|
UpdateDesignerHTML(False);
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.UpdateDesignerControl;
|
|
var
|
|
AList: IInterfaceList;
|
|
I: Integer;
|
|
begin
|
|
AList := CreateControlList;
|
|
for I := 0 to AList.Count - 1 do
|
|
begin
|
|
InsertWebDesignControl(IcxWebControl(AList[I]));
|
|
if (IcxWebControl(AList[I]).DesignerControl <> nil) and FHasHTMLLoaded then
|
|
with IcxWebControl(AList[I]).DesignerControl do
|
|
begin
|
|
ParentChanged;
|
|
BoundsChanged;
|
|
UpdateContext;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.DesignerIdChanging;
|
|
begin
|
|
if (Root <> nil) and not (csLoading in Root.ComponentState) then
|
|
UpdateHTMLSource;
|
|
end;
|
|
|
|
|
|
procedure TcxWebHTMLDesigner.DesignerPositioningTypeChanged;
|
|
|
|
procedure UpdatePositions(AAbsolute: Boolean);
|
|
var
|
|
AList: IInterfaceList;
|
|
I: Integer;
|
|
AStyle2: IHTMLStyle2;
|
|
begin
|
|
AList := TInterfaceList.Create;
|
|
GetHTMLElements(FDesignerControl.Document, AList);
|
|
for I := 0 to AList.Count - 1 do
|
|
if Supports(IHTMLElement(AList[I]).style, IHTMLStyle2, AStyle2) then
|
|
begin
|
|
if AAbsolute then
|
|
AStyle2.position := 'absolute' //TODO check the parent.
|
|
else AStyle2.position := '';
|
|
end;
|
|
if AAbsolute then
|
|
UpdateWebDesignerControlsPosition(Root, FDesignerControl.Document);
|
|
end;
|
|
|
|
begin
|
|
if not FHasHTMLLoaded then exit;
|
|
FDesignerControl.Wait;
|
|
if (FOldPositioningType = cxptFlow) then
|
|
UpdatePositions(True)
|
|
else
|
|
if (PositioningType = cxptFlow) then
|
|
UpdatePositions(False);
|
|
FDesignerControl.SetupControl;
|
|
|
|
FOldPositioningType := PositioningType;
|
|
if PositioningType = cxptGrid then
|
|
UpdateControlsPosition;
|
|
FDesignerControl.UndoManager.Clear;
|
|
FDesignerControl.Modified := True;
|
|
end;
|
|
|
|
class function TcxWebHTMLDesigner.GetID: Integer;
|
|
begin
|
|
Result := 2;
|
|
end;
|
|
|
|
class function TcxWebHTMLDesigner.GetName: String;
|
|
begin
|
|
Result := 'HTML'
|
|
end;
|
|
|
|
function TcxWebHTMLDesigner.CanAlign: Boolean;
|
|
begin
|
|
Result := PositioningType <> cxptFlow;
|
|
end;
|
|
|
|
function TcxWebHTMLDesigner.CanAlignToGrid: Boolean;
|
|
begin
|
|
Result := (PositioningType <> cxptFlow) and FDesignerControl.SnapToGrid;
|
|
end;
|
|
|
|
function TcxWebHTMLDesigner.CanCopy: Boolean;
|
|
begin
|
|
Result := (SelectionCount > 0) or FDesignerControl.Selection.CanCopy;
|
|
end;
|
|
|
|
function TcxWebHTMLDesigner.CanCut: Boolean;
|
|
begin
|
|
Result := CanCopy and CanDelete;
|
|
end;
|
|
|
|
function TcxWebHTMLDesigner.CanDelete: Boolean;
|
|
begin
|
|
Result := (inherited CanDelete);
|
|
if not Result and (SelectionCount = 0) then
|
|
Result := FDesignerControl.Selection.CanDelete;
|
|
end;
|
|
|
|
function TcxWebHTMLDesigner.CanPaste: Boolean;
|
|
begin
|
|
Result := (PositioningType <> cxptFlow) or FDesignerControl.Selection.CanPaste;
|
|
end;
|
|
|
|
function TcxWebHTMLDesigner.CanSelectAll: Boolean;
|
|
begin
|
|
Result := (Root.ComponentCount > 0);
|
|
end;
|
|
|
|
function TcxWebHTMLDesigner.CanTabOrder: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
function TcxWebHTMLDesigner.CanUndo: Boolean;
|
|
begin
|
|
Result := FUndo.CanUndo;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.ScaleSelection(AScaleFactor: Integer);
|
|
|
|
procedure ScaleControl(AControl: IHTMLElement);
|
|
begin
|
|
if not SameText((AControl as IHTMLElement2).currentStyle.position, 'static') then // Do not localize
|
|
begin
|
|
AControl.style.setAttribute('width', MulDiv(AControl.offsetWidth, AScaleFactor, 100), 0);
|
|
AControl.style.setAttribute('height', MulDiv(AControl.offsetHeight, AScaleFactor, 100), 0);
|
|
end;
|
|
end;
|
|
|
|
var
|
|
I: Integer;
|
|
begin
|
|
with FDesignerControl do
|
|
begin
|
|
UndoManager.BeginUndoBlock(scxCmdResize);
|
|
try
|
|
for I := 0 to Selection.Count - 1 do
|
|
ScaleControl(Selection[I]);
|
|
DHTMLControlBoundsRectChanged(False);
|
|
finally
|
|
UndoManager.EndUndoBlock;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function HorzCompareFunc(AItem1, AItem2: Pointer): Integer;
|
|
begin
|
|
Result := IHTMLElement(AItem1).offsetLeft - IHTMLElement(AItem2).offsetLeft;
|
|
end;
|
|
|
|
function VertCompareFunc(AItem1, AItem2: Pointer): Integer;
|
|
begin
|
|
Result := IHTMLElement(AItem1).offsetTop - IHTMLElement(AItem2).offsetTop;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.AlignSelection(AHorzAlign: TcxHorzAlign; AVertAlign: TcxVertAlign);
|
|
type
|
|
PcxAlignData = ^TcxAlignData;
|
|
TcxAlignData = record
|
|
CenterWidth: Integer;
|
|
CenterHeight: Integer;
|
|
MostLeft: Integer;
|
|
MostTop: Integer;
|
|
ParentWidth: Integer;
|
|
ParentHeight: Integer;
|
|
HorzDistance: Integer;
|
|
VertDistance: Integer;
|
|
HorzSortedList: TList;
|
|
VertSortedList: TList;
|
|
end;
|
|
var
|
|
AlignData: TcxAlignData;
|
|
Selections: IInterfaceList;
|
|
|
|
procedure CalcAlignData;
|
|
var
|
|
I: Integer;
|
|
Control: IHTMLElement;
|
|
LeftMost, RightMost,
|
|
TopMost, BottomMost: IHTMLElement;
|
|
begin
|
|
LeftMost := nil;
|
|
RightMost := nil;
|
|
TopMost := nil;
|
|
BottomMost := nil;
|
|
for I := 0 to FDesignerControl.Selection.Count - 1 do
|
|
begin
|
|
Control := FDesignerControl.Selection[I];
|
|
if not SameText((Control as IHTMLElement2).currentStyle.position, 'static') and // Do not localize
|
|
((Selections.Count = 0) or IsEqualElement(IHTMLElement(Selections[0]).offsetParent, Control.offsetParent)) then
|
|
begin
|
|
Selections.Add(Control);
|
|
if (LeftMost = nil) or (LeftMost.offsetLeft > Control.offsetLeft) then
|
|
LeftMost := Control;
|
|
if (RightMost = nil) or (RightMost.offsetLeft + RightMost.offsetWidth < Control.offsetLeft + Control.offsetWidth) then
|
|
RightMost := Control;
|
|
if (TopMost = nil) or (TopMost.offsetTop > Control.offsetTop) then
|
|
TopMost := Control;
|
|
if (BottomMost = nil) or (BottomMost.offsetTop + BottomMost.offsetHeight < Control.offsetTop + Control.offsetHeight) then
|
|
BottomMost := Control;
|
|
end;
|
|
end;
|
|
with AlignData do
|
|
begin
|
|
Control := IHTMLElement(Selections[0]);
|
|
if Control <> nil then
|
|
begin
|
|
CenterWidth := Control.offsetWidth;
|
|
CenterHeight := Control.offsetHeight;
|
|
Control := Control.offsetParent;
|
|
end;
|
|
if Control = nil then
|
|
Control := FDesignerControl.Document.body;
|
|
ParentWidth := (Control as IHTMLElement2).clientWidth;
|
|
ParentHeight := (Control as IHTMLElement2).clientHeight;
|
|
|
|
if Selections.Count > 1 then
|
|
begin
|
|
HorzDistance := (RightMost.offsetLeft - LeftMost.offsetLeft) div (Selections.Count - 1);
|
|
VertDistance := (BottomMost.offsetTop - TopMost.offsetTop) div (Selections.Count - 1);
|
|
end;
|
|
|
|
HorzSortedList := nil;
|
|
if AHorzAlign = haSpace then
|
|
begin
|
|
HorzSortedList := CloneList(Selections);
|
|
HorzSortedList.Sort(HorzCompareFunc);
|
|
end;
|
|
|
|
VertSortedList := nil;
|
|
if AVertAlign = vaSpace then
|
|
begin
|
|
VertSortedList := CloneList(Selections);
|
|
VertSortedList.Sort(VertCompareFunc);
|
|
end;
|
|
MostLeft := LeftMost.offsetLeft;
|
|
MostTop := TopMost.offsetTop;
|
|
end;
|
|
end;
|
|
|
|
function IndexOfElement(AList: TList; AElement: IHTMLElement): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := -1;
|
|
if (AList = nil) or (AElement = nil) then Exit;
|
|
for I := 0 to AList.Count - 1 do
|
|
if IsEqualElement(IHTMLElement(AList.Items[I]), AElement) then
|
|
begin
|
|
Result := I;
|
|
break;
|
|
end;
|
|
end;
|
|
|
|
procedure PlaceControls;
|
|
var
|
|
I, Index: Integer;
|
|
Control, FirstControl: IHTMLElement;
|
|
ALeft, ATop, AWidth, AHeight: Integer;
|
|
begin
|
|
FirstControl := IHTMLElement(Selections[0]);
|
|
with AlignData do
|
|
for I := 0 to Selections.Count - 1 do
|
|
begin
|
|
Control := IHTMLElement(Selections[I]);
|
|
ALeft := Control.offsetLeft;
|
|
ATop := Control.offsetTop;
|
|
AWidth := Control.offsetWidth;
|
|
AHeight := Control.offsetHeight;
|
|
case AHorzAlign of
|
|
cxWebDsgnTypes.haLeft:
|
|
ALeft := FirstControl.offsetLeft;
|
|
cxWebDsgnTypes.haCenter:
|
|
ALeft := FirstControl.offsetLeft - (AWidth - CenterWidth) div 2;
|
|
cxWebDsgnTypes.haRight:
|
|
ALeft := (FirstControl.offsetLeft + FirstControl.offsetWidth) - AWidth;
|
|
cxWebDsgnTypes.haSpace:
|
|
begin
|
|
Index := IndexOfElement(HorzSortedList, Control);
|
|
if (Index > 0) and (Index <> HorzSortedList.Count - 1) then
|
|
ALeft := MostLeft + HorzDistance * Index;
|
|
end;
|
|
cxWebDsgnTypes.haWinCenter:
|
|
ALeft := (ParentWidth - AWidth) div 2;
|
|
end;
|
|
case AVertAlign of
|
|
cxWebDsgnTypes.vaTop:
|
|
ATop := FirstControl.offsetTop;
|
|
cxWebDsgnTypes.vaCenter:
|
|
ATop := FirstControl.offsetTop - (AHeight - CenterHeight) div 2;
|
|
cxWebDsgnTypes.vaBottom:
|
|
ATop := (FirstControl.offsetTop + FirstControl.offsetHeight) - AHeight;
|
|
cxWebDsgnTypes.vaSpace:
|
|
begin
|
|
Index := IndexOfElement(VertSortedList, Control);
|
|
if (Index > 0) and (Index <> VertSortedList.Count - 1) then
|
|
ATop := MostTop + VertDistance * Index;
|
|
end;
|
|
cxWebDsgnTypes.vaWinCenter:
|
|
ATop := (ParentHeight - AHeight) div 2;
|
|
end;
|
|
Control.style.setAttribute('left', ALeft, 0);
|
|
Control.style.setAttribute('top', ATop, 0);
|
|
end;
|
|
end;
|
|
|
|
procedure FreeList(AList: TList);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if AList = nil then Exit;
|
|
for I := 0 to AList.Count - 1 do
|
|
IInterface(AList[I])._Release;
|
|
AList.Free;
|
|
end;
|
|
|
|
begin
|
|
if PositioningType = cxptFlow then Exit;
|
|
if (AHorzAlign = haNothing) and (AVertAlign = vaNothing) or
|
|
(SelectionCount = 0) then Exit;
|
|
with FDesignerControl do
|
|
begin
|
|
UndoManager.BeginUndoBlock(scxCmdAlign);
|
|
Selections := TInterfaceList.Create;
|
|
FillChar(AlignData, SizeOf(TcxAlignData), 0);
|
|
try
|
|
CalcAlignData;
|
|
PlaceControls;
|
|
DHTMLControlBoundsRectChanged(True);
|
|
finally
|
|
FreeList(AlignData.HorzSortedList);
|
|
FreeList(AlignData.VertSortedList);
|
|
UndoManager.EndUndoBlock;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.SizeSelection(AHorzAffect: TcxSizeAffect; AVertAffect: TcxSizeAffect;
|
|
AHorzAbsolute: Integer; AVertAbsolute: Integer);
|
|
var
|
|
I, AWidth, AHeight: Integer;
|
|
ACurrentWidth, ACurrentHeight: Integer;
|
|
begin
|
|
if (AHorzAffect = saNothing) and (AVertAffect = saNothing) then
|
|
Exit;
|
|
with FDesignerControl do
|
|
begin
|
|
UndoManager.BeginUndoBlock(scxCmdResize);
|
|
try
|
|
AWidth := -1;
|
|
AHeight := -1;
|
|
if (AHorzAffect in [saShrink, saGrow]) or (AVertAffect in [saShrink, saGrow]) then
|
|
for I := 0 to Selection.Count - 1 do
|
|
begin
|
|
if AHorzAffect in [saGrow, saShrink] then
|
|
begin
|
|
ACurrentWidth := Selection[I].offsetWidth;
|
|
case AHorzAffect of
|
|
saShrink:
|
|
if (ACurrentWidth < AWidth) or (AWidth = -1) then AWidth := ACurrentWidth;
|
|
saGrow:
|
|
if ACurrentWidth > AWidth then AWidth := ACurrentWidth;
|
|
end;
|
|
end;
|
|
if AVertAffect in [saGrow, saShrink] then
|
|
begin
|
|
ACurrentHeight := Selection[I].offsetHeight;
|
|
case AVertAffect of
|
|
saShrink:
|
|
if (ACurrentHeight < AHeight) or (AHeight = -1) then AHeight := ACurrentHeight;
|
|
saGrow:
|
|
if ACurrentHeight > AHeight then AHeight := ACurrentHeight;
|
|
end;
|
|
end;
|
|
end;
|
|
if AHorzAffect = saAbsolute then AWidth := AHorzAbsolute;
|
|
if AVertAffect = saAbsolute then AHeight := AVertAbsolute;
|
|
for I := 0 to Selection.Count - 1 do
|
|
begin
|
|
Selection[I].style.setAttribute('width', AWidth, 0);
|
|
Selection[I].style.setAttribute('height', AHeight, 0);
|
|
end;
|
|
DHTMLControlBoundsRectChanged(False);
|
|
finally
|
|
UndoManager.EndUndoBlock;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.AlignToGrid;
|
|
|
|
procedure AlignControlToGrid(AControl: IHTMLElement);
|
|
var
|
|
C: Integer;
|
|
begin
|
|
if not SameText((AControl as IHTMLElement2).currentStyle.position, 'static') then // Do not localize
|
|
begin
|
|
C := AControl.offsetTop + GridSizeY div 2;
|
|
AControl.style.setAttribute('top', GridSizeY * (C div GridSizeY), 0);
|
|
C := AControl.offsetLeft + GridSizeX div 2;
|
|
AControl.style.setAttribute('left', GridSizeX * (C div GridSizeX), 0);
|
|
end;
|
|
end;
|
|
|
|
var
|
|
I: Integer;
|
|
begin
|
|
with FDesignerControl do
|
|
begin
|
|
UndoManager.BeginUndoBlock(scxCmdAlign);
|
|
try
|
|
for I := 0 to Selection.Count - 1 do
|
|
AlignControlToGrid(Selection[I]);
|
|
DHTMLControlBoundsRectChanged(True);
|
|
finally
|
|
UndoManager.EndUndoBlock;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxWebHTMLDesigner.ShowTabOrderSelectionDlg: Boolean;
|
|
var
|
|
Container: IcxWebContainerControl;
|
|
Data: TcxTabOrderDlgData;
|
|
begin
|
|
if FDesignerControl.Selection.Count = 1 then
|
|
Supports(GetComponentByHTMLElement(Root, FDesignerControl.Selection[0]),
|
|
IcxWebContainerControl, Container);
|
|
if Container = nil then
|
|
Supports(Root, IcxWebContainerControl, Container);
|
|
if Container <> nil then
|
|
begin
|
|
FillChar(Data, SizeOf(TcxTabOrderDlgData), 0);
|
|
Data.Controls := TList.Create;
|
|
try
|
|
Container.GetTabOrderList(Data.Controls);
|
|
Result := cxShowTabOrderDialog(@Data);
|
|
if Result then
|
|
begin
|
|
Container.SetTabOrderList(Data.Controls);
|
|
DelphiDesigner.Modified;
|
|
end;
|
|
finally
|
|
Data.Controls.Free;
|
|
end;
|
|
end
|
|
else
|
|
Result := False;
|
|
end;
|
|
|
|
function TcxWebHTMLDesigner.CanSelect(const AControl: TComponent): Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.CopySelection;
|
|
begin
|
|
if CanCopy then
|
|
DoCopy;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.CutSelection;
|
|
begin
|
|
if CanCut then
|
|
begin
|
|
CopySelection;
|
|
DeleteSelection;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.DeleteSelection;
|
|
var
|
|
I: Integer;
|
|
AList: IDesignerSelections;
|
|
AComponentList: TList;
|
|
Element: IHTMLElement;
|
|
begin
|
|
if SelectionCount = 0 then
|
|
begin
|
|
FDesignerControl.Selection.Delete;
|
|
exit;
|
|
end;
|
|
|
|
AList := TDesignerSelections.Create;
|
|
DelphiDesigner.GetSelections(AList);
|
|
|
|
if AList.Count > 0 then
|
|
begin
|
|
BeginUpdate;
|
|
AComponentList := TList.Create;
|
|
try
|
|
for I := 0 to AList.Count - 1 do
|
|
if AList[I] is TcxWebHTMLElementMapper then
|
|
begin
|
|
Element := TcxWebHTMLElementMapper(AList[I]).Element;
|
|
if Element <> nil then
|
|
(Element as IHTMLDOMNode).removeNode(True);
|
|
end
|
|
else
|
|
if AList[I] is TComponent then
|
|
AComponentList.Add(AList[I]);
|
|
FreeComponents(AComponentList, False);
|
|
DelphiDesigner.DeleteSelection(True);
|
|
ClearSelection;
|
|
finally
|
|
AComponentList.Free;
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.Edit(AComponent: TComponent);
|
|
begin
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.GetSelections(const AList: TList);
|
|
var
|
|
ASelList: IDesignerSelections;
|
|
I: Integer;
|
|
begin
|
|
ASelList := TDesignerSelections.Create;
|
|
DelphiDesigner.GetSelections(ASelList);
|
|
for I := 0 to ASelList.Count - 1 do
|
|
AList.Add(ASelList.Items[I]);
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.PasteSelection;
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
DoPaste;
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.SelectAll;
|
|
begin
|
|
if CanSelectAll then DoSelectAll;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.SelectionChanged(const AList: TList);
|
|
|
|
procedure RemoveHTMLSelectedControls;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
I := 0;
|
|
while I < FHTMLSelectedControls.Count do
|
|
begin
|
|
if AList.IndexOf(FHTMLSelectedControls[I]) > -1 then
|
|
Inc(I)
|
|
else
|
|
begin
|
|
TcxWebHTMLElementMapper(FHTMLSelectedControls[I]).Free;
|
|
FHTMLSelectedControls.Delete(I);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure RemoveElementsFromSelection;
|
|
|
|
function HasElement(AElement: IHTMLElement): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := False;
|
|
for I := 0 to AList.Count - 1 do
|
|
if (TPersistent(AList[I]) is TComponent) and
|
|
Supports(TPersistent(AList[I]), IcxWebControl) then
|
|
begin
|
|
if AElement = GetHTMLElementByComponentName(FDesignerControl.Document3, TComponent(AList[I]).Name) then
|
|
begin
|
|
Result := True;
|
|
break;
|
|
end;
|
|
end else
|
|
if (TPersistent(AList[I]) is TcxWebHTMLElementMapper) and
|
|
(AElement = TcxWebHTMLElementMapper(AList[I]).Element) then
|
|
begin
|
|
Result := True;
|
|
break;
|
|
end;
|
|
end;
|
|
|
|
var
|
|
I: Integer;
|
|
AElementList: IInterfaceList;
|
|
AElement: IHTMLElement;
|
|
begin
|
|
AElementList := TInterfaceList.Create;
|
|
for I := 0 to FDesignerControl.Selection.Count - 1 do
|
|
begin
|
|
AElement := FDesignerControl.Selection[I];
|
|
if (AElement <> nil) and not HasElement(AElement) then
|
|
AElementList.Add(AElement);
|
|
end;
|
|
for I := 0 to AElementList.Count - 1 do
|
|
FDesignerControl.Selection.Remove(AElementList[I] as IHTMLElement);
|
|
end;
|
|
|
|
procedure SelectWebControls;
|
|
var
|
|
I: Integer;
|
|
AHTMLElement: IHTMLElement;
|
|
begin
|
|
for I := 0 to AList.Count - 1 do
|
|
if (TPersistent(AList[I]) is TComponent) and
|
|
Supports(TPersistent(AList[I]), IcxWebControl) then
|
|
begin
|
|
AHTMLElement := GetHTMLElementByComponentName(FDesignerControl.Document3, TComponent(AList[I]).Name);
|
|
if AHTMLElement <> nil then
|
|
FDesignerControl.Selection.Add(AHTMLElement);
|
|
end;
|
|
end;
|
|
|
|
procedure SelectHTMLElements;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to FHTMLSelectedControls.Count - 1 do
|
|
begin
|
|
if Supports(TcxWebHTMLElementMapper(FHTMLSelectedControls[I]).Element, IHTMLControlElement) then
|
|
FDesignerControl.Selection.Add(TcxWebHTMLElementMapper(FHTMLSelectedControls[I]).Element);
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
if not FHasHTMLLoaded then exit;
|
|
if UpdateCount <> 0 then exit;
|
|
BeginUpdate;
|
|
try
|
|
FDesignerControl.Wait;
|
|
RemoveHTMLSelectedControls;
|
|
RemoveElementsFromSelection;
|
|
SelectWebControls;
|
|
SelectHTMLElements;
|
|
finally
|
|
CancelUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.Undo;
|
|
begin
|
|
FUndo.Undo;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.IDEDesignerOptionsChagned;
|
|
begin
|
|
FDesignerControl.SetupControl;
|
|
end;
|
|
|
|
function TcxWebHTMLDesigner.GetHTMLTemplateModified(var AFileName, AText: string): Boolean;
|
|
begin
|
|
if (FHTMLSource <> nil) and
|
|
(FHTMLSource.FSourceEditor <> nil) and
|
|
(FHTMLSource.FSourceEditor.Modified
|
|
or not FileExists(FHTMLSource.FSourceEditor.FileName)) then
|
|
begin
|
|
Result := True;
|
|
AFileName := FHTMLSource.FSourceEditor.FileName;
|
|
AText := FHTMLSource.HTML;
|
|
end
|
|
else Result := inherited GetHTMLTemplateModified(AFileName, AText);
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.HTMLElementCreated(ABaseHTMLElement: TcxBaseHTMLElement);
|
|
var
|
|
R: TRect;
|
|
begin
|
|
FInsertingComponent := ABaseHTMLElement;
|
|
try
|
|
R.Left := FDesignerControl.ClientWidth div 2;
|
|
R.Right := R.Left;
|
|
R.Top := FDesignerControl.ClientHeight div 2;
|
|
R.Bottom := R.Top;
|
|
FDesignerControl.DoInsert(nil, R);
|
|
finally
|
|
FInsertingComponent := nil;
|
|
end;
|
|
end;
|
|
|
|
function TcxWebHTMLDesigner.GetHTMLElementFileName: string;
|
|
var
|
|
AIntfFileName, AFormFileName: string;
|
|
begin
|
|
DelphiDesigner.ModuleFileNames(Result, AIntfFileName, AFormFileName);
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.ReaderSetName(AReader: TReader;
|
|
AComponent: TComponent; var AName: string);
|
|
var
|
|
OldName: string;
|
|
begin
|
|
OldName := AName;
|
|
inherited;
|
|
if (FChangedNames <> nil) and not SameText(OldName, AName) then
|
|
FChangedNames.AddObject(OldName, AComponent);
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.DesignerActivated;
|
|
begin
|
|
inherited DesignerActivated;
|
|
if (FHTMLSourceEditorNotifier <> nil) and (FHTMLSourceEditorNotifier.IsModified) then
|
|
begin
|
|
try
|
|
BeginUpdate;
|
|
ShowDesignerPage;
|
|
finally
|
|
CancelUpdate;
|
|
end;
|
|
UpdateDesignerHTML(True);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.DesignerDeactivated;
|
|
begin
|
|
FDesignerControl.DeactivateInnerHMTLElement;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.PreviewShowing;
|
|
begin
|
|
FDesignerControl.DeactivateInnerHMTLElement;
|
|
ClearSelection;
|
|
UpdateHTMLSource;
|
|
end;
|
|
|
|
function TcxWebHTMLDesigner.GetControlPositioningType: TcxWebPositioningType;
|
|
begin
|
|
if GetShowingType = stDesigner then
|
|
Result := cxptFlow
|
|
else Result := PositioningType;
|
|
end;
|
|
|
|
{DHTML Control events}
|
|
procedure TcxWebHTMLDesigner.DHTMLControlInsertControl(Sender: TObject; R: TRect;
|
|
var HTML, InnerHTML: string; var ParentElement: IHTMLElement);
|
|
var
|
|
AComponentClass: TComponentClass;
|
|
|
|
function GetHTMLControlContext: string;
|
|
var
|
|
IsAbsolutePos: Boolean;
|
|
begin
|
|
IsAbsolutePos := PositioningType <> cxptFlow;
|
|
if IsAbsolutePos and
|
|
Supports(GetComponentByHTMLElement(Root, ParentElement), IcxWebControl) then
|
|
IsAbsolutePos := False;
|
|
Result := TcxBaseHTMLElementClass(AComponentClass).GetHTML(IsAbsolutePos, R);
|
|
InnerHTML := TcxBaseHTMLElementClass(AComponentClass).GetInnerHTML;
|
|
end;
|
|
|
|
function GetEWFControlContext: string;
|
|
var
|
|
AComponent: TComponent;
|
|
AWebControl: IcxWebControl;
|
|
AContainerControl: IcxWebContainerControl;
|
|
AParentComponent: TComponent;
|
|
AComponentName: string;
|
|
begin
|
|
if FInsertingComponent = nil then
|
|
begin
|
|
AComponent := CreateComponent(R.Left, R.Top, R.Right - R.Left, R.Bottom - R.Top);
|
|
if Supports(AComponent, IcxWebControl, AWebControl) and
|
|
((R.Right = R.Left) or (R.Bottom = R.Top)) then
|
|
with AWebControl.BoundsRect do
|
|
begin
|
|
R.Right := R.Left + Right - Left;
|
|
R.Bottom := R.Top + Bottom - Top;
|
|
end;
|
|
end else AComponent := FInsertingComponent;
|
|
if AComponent <> nil then
|
|
begin
|
|
if Supports(AComponent, IcxWebControl, AWebControl) then
|
|
begin
|
|
AWebControl.BoundsRect := R;
|
|
if (ParentElement <> nil) then
|
|
AParentComponent := GetComponentByHTMLElement(Root, ParentElement)
|
|
else AParentComponent := nil;
|
|
if AParentComponent = nil then
|
|
AParentComponent := Root;
|
|
if not Supports(AParentComponent, IcxWebContainerControl, AContainerControl) then
|
|
begin
|
|
if Supports(AParentComponent, IcxWebControl, AWebControl) then
|
|
AContainerControl := AWebControl.Parent;
|
|
end;
|
|
if AContainerControl = nil then
|
|
Supports(Root, IcxWebContainerControl, AContainerControl);
|
|
AWebControl.Parent := AContainerControl;
|
|
end;
|
|
if AComponent.Name <> '' then
|
|
AComponentName := AComponent.Name
|
|
else AComponentName := FInsertingComponentName;
|
|
Result := Format('<%0:s:%1:s id="%2:s"> </%0:s:%1:s>',
|
|
[scxEWF, GetDesignerHTMLClassName(AComponent.ClassName), AComponentName]);
|
|
InnerHTML := '';
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
FDesignerControl.Wait;
|
|
if FInsertingComponent = nil then
|
|
AComponentClass := GetCurrComponentClass
|
|
else AComponentClass := TComponentClass(FInsertingComponent.ClassType);
|
|
|
|
if not AComponentClass.InheritsFrom(TcxBaseHTMLElement) and
|
|
not Supports(AComponentClass, IcxWebControl) then
|
|
begin
|
|
CreateComponent(R.Left, R.Top, R.Right - R.Left, R.Bottom - R.Top);
|
|
end
|
|
else
|
|
begin
|
|
if (ParentElement = nil) or not IsHTMLCustomElement(ParentElement) then
|
|
ParentElement := FDesignerControl.MainParentElement;
|
|
try
|
|
FIsComponentInserting := True;
|
|
if AComponentClass.InheritsFrom(TcxBaseHTMLElement) then
|
|
HTML := GetHTMLControlContext
|
|
else begin
|
|
HTML := GetEWFControlContext;
|
|
end;
|
|
finally
|
|
FIsComponentInserting := False;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.DHTMLControlInsertedControl(Sender: TObject; Element: IHTMLElement);
|
|
var
|
|
AComponentClass: TComponentClass;
|
|
AComponent: TComponent;
|
|
AStyle2: IHTMLStyle2;
|
|
AWebControl: IcxWebControl;
|
|
begin
|
|
if Element = nil then exit;
|
|
if FInsertingComponent <> nil then
|
|
AComponent := FInsertingComponent
|
|
else AComponent := GetComponentByHTMLElement(Root, Element);
|
|
if (AComponent <> nil) and Supports(AComponent, IcxWebControl, AWebControl) then
|
|
begin
|
|
if PositioningType <> cxptFlow then
|
|
begin
|
|
if (GetComponentByInterface(AWebControl.Parent) = Root) and
|
|
Supports(Element.style, IHTMLStyle2, AStyle2) then
|
|
AStyle2.position := 'absolute';
|
|
end;
|
|
if (AWebControl.DesignerControl <> nil) then
|
|
AWebControl.DesignerControl.BoundsChanged;
|
|
end;
|
|
if FInsertingComponent = nil then
|
|
AComponentClass := GetCurrComponentClass
|
|
else AComponentClass := TComponentClass(FInsertingComponent.ClassType);
|
|
if (AComponentClass <> nil) and AComponentClass.InheritsFrom(TcxBaseHTMLElement) then
|
|
TcxBaseHTMLElementClass(AComponentClass).AfterElementCreated(Element);
|
|
if (AComponentClass <> nil) and (ActiveDesigner.Environment <> nil) then
|
|
ActiveDesigner.Environment.ResetCompClass;
|
|
FDesignerControl.Selection.Clear;
|
|
FDesignerControl.Selection.Add(Element);
|
|
InternalDHTMLControlSelectionChanged;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.DHTMLControlGetContext(AElement: IHTMLElement;
|
|
var AContent, ACSSContent, AInlineStyle: string);
|
|
var
|
|
AComponent: TComponent;
|
|
AWebControl: IcxWebControl;
|
|
begin
|
|
AComponent := GetComponentByHTMLElement(Root, AElement);
|
|
if (AComponent <> nil) and Supports(AComponent, IcxWebControl, AWebControl) then
|
|
begin
|
|
InsertWebDesignControl(AWebControl);
|
|
AContent := GetDesignInnerHTMLByWebControl(AComponent);
|
|
ACSSContent := GetDesignStyleByWebControl(AComponent);
|
|
AInlineStyle := GetDesignInlineStyleByWebControl(AComponent);
|
|
end else
|
|
begin
|
|
AContent := '';
|
|
ACSSContent := '';
|
|
AInlineStyle := '';
|
|
end;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.DHTMLControlParentChanged(ASender: TObject; ANewParent: IHTMLElement);
|
|
var
|
|
AParentControl: IcxWebContainerControl;
|
|
AParentComponent, AComponent: TComponent;
|
|
AWebControl: IcxWebControl;
|
|
I: Integer;
|
|
AElements: IInterfaceList;
|
|
begin
|
|
AParentComponent := nil;
|
|
while (AParentComponent = nil) and (ANewParent <> nil) do
|
|
begin
|
|
AParentComponent := GetComponentByHTMLElement(Root, ANewParent);
|
|
ANewParent := ANewParent.parentElement;
|
|
end;
|
|
AParentControl := nil;
|
|
if (AParentComponent <> nil) and Supports(AParentComponent, IcxWebControl, AWebControl) then
|
|
if not Supports(AParentComponent, IcxWebContainerControl, AParentControl) then
|
|
AParentControl := AWebControl.Parent;
|
|
if AParentControl = nil then
|
|
AParentControl := Root as IcxWebContainerControl;
|
|
|
|
AElements := TInterfaceList.Create;
|
|
for I := 0 to FDesignerControl.Selection.Count - 1 do
|
|
if FDesignerControl.Selection[I] <> nil then
|
|
AElements.Add(FDesignerControl.Selection[I]);
|
|
|
|
for I := 0 to AElements.Count - 1 do
|
|
begin
|
|
AComponent := GetComponentByHTMLElement(Root, AElements[I] as IHTMLElement);
|
|
if (PositioningType = cxptFlow) or Supports(AParentControl, IcxWebControl) then
|
|
(AElements[I] as IHTMLElement).style.removeAttribute('position', 0)
|
|
else (AElements[I] as IHTMLElement).style.setAttribute('position', 'absolute', 0);
|
|
if Supports(AComponent, IcxWebControl) then
|
|
(AComponent as IcxWebControl).Parent := AParentControl;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.ClearHTMLSelectedControls;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if FHTMLSelectedControls.Count = 0 then exit;
|
|
for I := 0 to FHTMLSelectedControls.Count - 1 do
|
|
TcxWebHTMLElementMapper(FHTMLSelectedControls[I]).Free;
|
|
FHTMLSelectedControls.Clear;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.ClearSelection;
|
|
var
|
|
AList: IDesignerSelections;
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
AList := TDesignerSelections.Create;
|
|
AList.Add(Root);
|
|
DelphiDesigner.SetSelections(AList);
|
|
ClearHTMLSelectedControls;
|
|
FDesignerControl.Selection.Clear;
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.CreateHTMLSelectedControls;
|
|
var
|
|
I: Integer;
|
|
AList: IDesignerSelections;
|
|
AHTMLElement: IHTMLElement;
|
|
AComponent: TComponent;
|
|
begin
|
|
FDesignerControl.Wait;
|
|
AList := TDesignerSelections.Create;
|
|
for I := 0 to FDesignerControl.Selection.Count - 1 do
|
|
begin
|
|
AHTMLElement := FDesignerControl.Selection[I];
|
|
AComponent := GetComponentByHTMLElement(Root, AHTMLElement);
|
|
if (AComponent = nil) and (AHTMLElement <> nil) then
|
|
begin
|
|
FHTMLSelectedControls.Add(WebHTMLElementMapperManager.CreateElementMapper(AHTMLElement));
|
|
TcxWebHTMLElementMapper(FHTMLSelectedControls.Last).onElementChanged := DoMapperElementChanged;
|
|
AList.Add(TPersistent(FHTMLSelectedControls.Last));
|
|
end else AList.Add(AComponent);
|
|
end;
|
|
if AList.Count > 0 then
|
|
DelphiDesigner.NoSelection;
|
|
DelphiDesigner.SetSelections(AList);
|
|
end;
|
|
|
|
function TcxWebHTMLDesigner.SelectionCount: Integer;
|
|
var
|
|
AList: IDesignerSelections;
|
|
begin
|
|
AList := TDesignerSelections.Create;
|
|
DelphiDesigner.GetSelections(AList);
|
|
if (AList.Count = 1) and (AList.Items[0] = Root) then
|
|
Result := 0
|
|
else
|
|
Result := AList.Count;
|
|
end;
|
|
|
|
function TcxWebHTMLDesigner.IsComponentSelected: Boolean;
|
|
var
|
|
AList: IDesignerSelections;
|
|
I: Integer;
|
|
begin
|
|
Result := False;
|
|
AList := TDesignerSelections.Create;
|
|
DelphiDesigner.GetSelections(AList);
|
|
for I := 0 to AList.Count - 1 do
|
|
if (AList.Items[I] is TComponent) and
|
|
not Supports(AList.Items[I], IcxWebControl) then
|
|
begin
|
|
Result := True;
|
|
break;
|
|
end
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.InternalDHTMLControlSelectionChanged;
|
|
|
|
function IsSelectionTheSame: Boolean;
|
|
var
|
|
I: Integer;
|
|
AList: IDesignerSelections;
|
|
AHTMLElement: IHTMLElement;
|
|
begin
|
|
AList := TDesignerSelections.Create;
|
|
DelphiDesigner.GetSelections(AList);
|
|
Result := FDesignerControl.Selection.Count = AList.Count;
|
|
if (FDesignerControl.Selection.Count = 0) and (AList.Count = 1) and (AList.Items[0] = Root) then
|
|
begin
|
|
Result := True;
|
|
exit;
|
|
end;
|
|
if not Result then exit;
|
|
if (FDesignerControl.Selection.Count = 1) and (FDesignerControl.Selection[0] = nil)
|
|
and (AList.Items[0] = Root) then exit;
|
|
for I := 0 to AList.Count - 1 do
|
|
begin
|
|
if (AList.Items[I] is TcxWebHTMLElementMapper) then
|
|
AHTMLElement := TcxWebHTMLElementMapper(AList.Items[I]).Element
|
|
else
|
|
if (AList.Items[I] is TComponent) then
|
|
AHTMLElement := GetHTMLElementByComponentName(FDesignerControl.Document3,
|
|
TComponent(AList.Items[I]).Name)
|
|
else AHTMLElement := nil;
|
|
Result := FDesignerControl.Selection.IndexOf(AHTMLElement) <> -1;
|
|
if not Result then
|
|
break;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
if (UpdateCount <> 0) or IsSelectionTheSame then exit;
|
|
BeginUpdate;
|
|
try
|
|
ClearHTMLSelectedControls;
|
|
CreateHTMLSelectedControls;
|
|
finally
|
|
CancelUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.DHTMLControlSelectionChanged(Sender: TObject);
|
|
begin
|
|
InternalDHTMLControlSelectionChanged;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.DHTMLControlMoved(Sender: TObject);
|
|
begin
|
|
DHTMLControlBoundsRectChanged(True);
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.DHTMLControlResized(Sender: TObject);
|
|
begin
|
|
DHTMLControlBoundsRectChanged(False);
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.DoEditorFormActivated(Sender: TObject);
|
|
begin
|
|
if not FHasHTMLLoaded then exit;
|
|
UpdateHTMLSource;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.DHTMLControlContextMenu(ASender: TObject; APos: TPoint;
|
|
AElement: IHTMLElement);
|
|
const
|
|
Filters: array[Boolean] of TcxLocalMenuFilters = ([], [cxlmComponent]);
|
|
var
|
|
AList: IDesignerSelections;
|
|
begin
|
|
AList := TDesignerSelections.Create;
|
|
DelphiDesigner.GetSelections(AList);
|
|
InvokeLocalMenuAtCursor(nil, Filters[AList.Count > 1]);
|
|
end;
|
|
|
|
|
|
procedure TcxWebHTMLDesigner.UpdateHTMLSource;
|
|
begin
|
|
try
|
|
FHTMLSaving := True;
|
|
FDesignerControl.Wait;
|
|
if FDesignerControl.Modified then
|
|
begin
|
|
FHTMLSource.HTML := FHTMLBefore +
|
|
GetTempateHTMLFromDesigner(Root, FDesignerControl.DocumentHTML,
|
|
FStoredTags, PositioningType) +
|
|
FHTMLAfter;
|
|
FHTMLSourceEditorNotifier.IsModified := False;
|
|
FDesignerControl.Modified := False;
|
|
end;
|
|
finally
|
|
FHTMLSaving := False;
|
|
end;
|
|
end;
|
|
|
|
var
|
|
FUpdateDesignerFailed: Boolean = False;
|
|
|
|
procedure TcxWebHTMLDesigner.UpdateDesignerHTML(ADeleteComponents: Boolean);
|
|
|
|
function PrepareHTMLSource(const AHTML: string): string;
|
|
var
|
|
P: PChar;
|
|
begin
|
|
Result := AHTML;
|
|
P := SearchBuf(PChar(Result), Length(Result), 0, 0, '<HTML');
|
|
if P <> nil then
|
|
begin
|
|
SetString(FHTMLBefore, PChar(Result), P - PChar(Result));
|
|
SetString(Result, P, PChar(Result) + Length(Result) - P);
|
|
end
|
|
else
|
|
FHTMLBefore := '';
|
|
P := SearchBuf(PChar(Result), Length(Result), Length(Result), 0, '</HTML>', []);
|
|
if P <> nil then
|
|
begin
|
|
P := P + 7;
|
|
SetString(FHTMLAfter, P, PChar(Result) + Length(Result) - P);
|
|
SetString(Result, PChar(Result), P - PChar(Result));
|
|
end
|
|
else
|
|
FHTMLAfter := '';
|
|
end;
|
|
|
|
begin
|
|
if FUpdateDesignerFailed then
|
|
begin
|
|
FUpdateDesignerFailed := False;
|
|
FHTMLSource.SourceEditor.Show;
|
|
exit;
|
|
end;
|
|
FUpdateDesignerFailed := True;
|
|
FDesignerControl.OnDocumentChange := nil;
|
|
if FHasHTMLLoaded then
|
|
ClearSelection;
|
|
FUndo.Clear;
|
|
try
|
|
FHasHTMLLoaded := False;
|
|
FDesignerControl.DocumentHTML := GetDesignHTMLContextFromTemplate(Root,
|
|
PrepareHTMLSource(FHTMLSource.HTML), FStoredTags, ADeleteComponents, PositioningType);
|
|
FUpdateDesignerFailed := False;
|
|
except
|
|
on E: EcxWebHTMLParserException do
|
|
FHTMLSource.ShowParserError(E.ParserError, E.ErrorStr, E.Message);
|
|
else raise;
|
|
end;
|
|
if FHTMLSource.FSourceEditor <> nil then
|
|
FDesignerControl.BaseURL := ExtractFilePath(FHTMLSource.FSourceEditor.FileName);
|
|
IDEDesignerOptionsChagned;
|
|
FDesignerControl.OnDocumentChange := HTMLChangeNotify;
|
|
FHasHTMLLoaded := True;
|
|
FHTMLSourceEditorNotifier.IsModified := False;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.UpdateHTMLControlContext(AComponent: TComponent);
|
|
var
|
|
AHTMLElement: IHTMLElement;
|
|
begin
|
|
if not FHasHTMLLoaded or Supports(AComponent, IcxWebContainerControl) then exit;
|
|
AHTMLElement := GetHTMLElementByComponentName(FDesignerControl.Document3, AComponent.Name);
|
|
if AHTMLElement <> nil then
|
|
FDesignerControl.UpdateViewLinkContent(AHTMLElement);
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.InsertWebDesignControl(AWebControl: IcxWebControl);
|
|
begin
|
|
if AWebControl.DesignerControl = nil then
|
|
AWebControl.DesignerControl := TcxWebDesignerControlNotify.Create(self, GetComponentByInterface(AWebControl));
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.DHTMLControlBoundsRectChanged(AIsMoved: Boolean);
|
|
var
|
|
I: Integer;
|
|
AComponent: TComponent;
|
|
AWebControl: IcxWebControl;
|
|
AHTMLElement: IHTMLElement;
|
|
R: TRect;
|
|
ASelectedList: IInterfaceList;
|
|
begin
|
|
ASelectedList := TInterfaceList.Create;
|
|
for I := 0 to FDesignerControl.Selection.Count - 1 do
|
|
if FDesignerControl.Selection[I] <> nil then
|
|
ASelectedList.Add(FDesignerControl.Selection[I]);
|
|
BeginUpdate;
|
|
try
|
|
for I := 0 to ASelectedList.Count - 1 do
|
|
begin
|
|
AHTMLElement := ASelectedList[I] as IHTMLElement;
|
|
AComponent := GetComponentByHTMLElement(Root, AHTMLElement);
|
|
if (AComponent <> nil) and Supports(AComponent, IcxWebControl, AWebControl) then
|
|
begin
|
|
with AHTMLElement.style do
|
|
if not AIsMoved then
|
|
SetRect(R, pixelLeft, pixelTop, pixelLeft + pixelWidth, pixelTop + pixelHeight)
|
|
else
|
|
begin
|
|
R := AWebControl.BoundsRect;
|
|
OffsetRect(R, pixelLeft - R.Left, pixelTop - R.Top);
|
|
end;
|
|
AWebControl.BoundsRect := R;
|
|
end;
|
|
end;
|
|
finally
|
|
CancelUpdate;
|
|
end;
|
|
for I := 0 to ASelectedList.Count - 1 do
|
|
begin
|
|
AHTMLElement := ASelectedList[I] as IHTMLElement;
|
|
AComponent := GetComponentByHTMLElement(Root, AHTMLElement);
|
|
if (AComponent <> nil) and Supports(AComponent, IcxWebControl, AWebControl) then
|
|
begin
|
|
AWebControl.UpdateControlPosition;
|
|
UpdateHTMLElementStylePositions(AHTMLElement, AWebControl);
|
|
end;
|
|
end;
|
|
DelphiDesigner.Modified;
|
|
BeginUpdate;
|
|
try
|
|
FDesignerControl.Selection.Empty;
|
|
for I := 0 to ASelectedList.Count - 1 do
|
|
if FDesignerControl.Selection.IndexOf(ASelectedList[I] as IHTMLElement) < 0 then
|
|
FDesignerControl.Selection.Add(ASelectedList[I] as IHTMLElement);
|
|
finally
|
|
CancelUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.DoMapperElementChanged(Sender: TObject);
|
|
begin
|
|
if (BorlandIDEServices as IOTAModuleServices).CurrentModule <> nil then
|
|
(BorlandIDEServices as IOTAModuleServices).CurrentModule.MarkModified;
|
|
BeginUpdate;
|
|
DelphiDesigner.Modified;
|
|
EndUpdate;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.HTMLChangeNotify(Sender: TObject);
|
|
begin
|
|
if (BorlandIDEServices as IOTAModuleServices).CurrentModule <> nil then
|
|
(BorlandIDEServices as IOTAModuleServices).CurrentModule.MarkModified;
|
|
BeginUpdate;
|
|
DelphiDesigner.Modified;
|
|
EndUpdate;
|
|
CheckForDeletedControls;
|
|
UpdateSelectedEWFBehaviors;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.FreeComponents(AList: TList; ADelete: Boolean);
|
|
|
|
function HasParentInList(AComponent: TComponent): Boolean;
|
|
var
|
|
I: Integer;
|
|
AParent: TComponent;
|
|
begin
|
|
Result := False;
|
|
AParent := AComponent.GetParentComponent;
|
|
while AParent <> nil do
|
|
begin
|
|
for I := 0 to AList.Count - 1 do
|
|
begin
|
|
if AParent = TComponent(AList[I]) then
|
|
begin
|
|
Result := True;
|
|
break;
|
|
end;
|
|
end;
|
|
AParent := AParent.GetParentComponent;
|
|
end;
|
|
end;
|
|
|
|
procedure RemoveChildren;
|
|
var
|
|
I: Integer;
|
|
AChildren: TList;
|
|
begin
|
|
AChildren := TList.Create;
|
|
try
|
|
for I := 0 to AList.Count - 1 do
|
|
if HasParentInList(TComponent(AList[I])) then
|
|
AChildren.Add(AList[I]);
|
|
for I := 0 to AChildren.Count - 1 do
|
|
AList.Remove(AChildren[I]);
|
|
finally
|
|
AChildren.Free;
|
|
end;
|
|
end;
|
|
|
|
var
|
|
I: Integer;
|
|
AItems: TcxWebHTMLUndoItems;
|
|
AComponent: TComponent;
|
|
begin
|
|
RemoveChildren;
|
|
if AList.Count > 0 then
|
|
begin
|
|
AItems := FUndo.CreateNewGroup;
|
|
for I := 0 to AList.Count - 1 do
|
|
begin
|
|
AComponent := TComponent(AList[I]);
|
|
FUndo.AddDeletedComponent(AItems, AComponent);
|
|
if ADelete or Supports(AComponent, IcxWebControl) then
|
|
FreeAndNil(AComponent);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.CheckForDeletedControls;
|
|
var
|
|
AList: TList;
|
|
I: Integer;
|
|
begin
|
|
AList := TList.Create;
|
|
for I := 0 to Root.ComponentCount - 1 do
|
|
if Supports(Root.Components[I], IcxWebControl) and
|
|
(GetHTMLElementByComponentName(FDesignerControl.Document3, Root.Components[I].Name) = nil) then
|
|
AList.Add(Root.Components[I]);
|
|
FreeComponents(AList, True);
|
|
if AList.Count > 0 then
|
|
try
|
|
BeginUpdate;
|
|
FDesignerControl.Selection.Clear;
|
|
finally
|
|
CancelUpdate;
|
|
end;
|
|
AList.Free;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.UpdateSelectedEWFBehaviors;
|
|
var
|
|
AList: IDesignerSelections;
|
|
AElement: IHTMLElement;
|
|
I: Integer;
|
|
begin
|
|
AList := TDesignerSelections.Create;
|
|
DelphiDesigner.GetSelections(AList);
|
|
for I := 0 to AList.Count - 1 do
|
|
if Supports(AList.Items[I], IcxWebControl) and
|
|
(AList.Items[I] is TComponent) then
|
|
AElement := GetHTMLElementByComponentName(FDesignerCOntrol.Document3, TComponent(AList.Items[I]).Name);
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.InternalInsertHTMLControl(AComponent: TComponent;
|
|
ANewName: string; ANeedOffSet: Boolean);
|
|
var
|
|
AWebControl: IcxWebControl;
|
|
AParentElement: IHTMLElement;
|
|
R: TRect;
|
|
AParent: TComponent;
|
|
begin
|
|
if not Supports(AComponent, IcxWebControl, AWebControl) then exit;
|
|
try
|
|
if ANewName = '' then
|
|
ANewName := AComponent.Name;
|
|
FInsertingComponentName := ANewName;
|
|
FInsertingComponent := AComponent;
|
|
AParentElement := nil;
|
|
AParent := AComponent.GetParentComponent;
|
|
if AParent <> nil then
|
|
AParentElement := GetHTMLElementByComponentName(FDesignerCOntrol.Document3, AParent.Name);
|
|
if AParentElement = nil then
|
|
AParentElement := FDesignerControl.MainParentElement;
|
|
R := AWebControl.BoundsRect;
|
|
if ANeedOffSet then
|
|
OffsetRect(R, (FDesignerControl.ClientWidth + R.Left - R.Right) div 2,
|
|
(FDesignerControl.ClientHeight + R.Top - R.Bottom) div 2);
|
|
FDesignerControl.DoInsert(AParentElement, R);
|
|
finally
|
|
FInsertingComponent := nil;
|
|
FInsertingComponentName := '';
|
|
end;
|
|
end;
|
|
|
|
{ Clipboard routines }
|
|
procedure EWFCopyStreamToClipboard(AComponentStream: TMemoryStream; const AHTML: string);
|
|
|
|
procedure CopyToClipboard(Format: Word; AStream: TMemoryStream);
|
|
var
|
|
Handle: THandle;
|
|
Mem: Pointer;
|
|
begin
|
|
Handle := GlobalAlloc(GMEM_MOVEABLE, AStream.Size);
|
|
Mem := GlobalLock(Handle);
|
|
Move(AStream.Memory^, Mem^, AStream.Size);
|
|
GlobalUnlock(Handle);
|
|
Clipboard.SetAsHandle(Format, Handle);
|
|
end;
|
|
|
|
var
|
|
AStream: TMemoryStream;
|
|
I: TValueType;
|
|
V: Integer;
|
|
begin
|
|
Clipboard.Open;
|
|
try
|
|
AStream := TMemoryStream.Create;
|
|
try
|
|
if AComponentStream <> nil then
|
|
begin
|
|
AComponentStream.Position := 0;
|
|
repeat
|
|
AComponentStream.Read(I, SizeOf(I));
|
|
AComponentStream.Seek(-SizeOf(I), 1);
|
|
if I = vaNull then Break;
|
|
ObjectBinaryToText(AComponentStream, AStream);
|
|
until False;
|
|
end;
|
|
if AHTML <> '' then
|
|
AStream.WriteBuffer(PChar(AHTML)^, Length(AHTML));
|
|
V := 0;
|
|
AStream.Write(V, 1);
|
|
CopyToClipboard(CF_TEXT, AStream);
|
|
finally
|
|
AStream.Free;
|
|
end;
|
|
finally
|
|
Clipboard.Close;
|
|
end;
|
|
end;
|
|
|
|
function EWFGetClipboardStream(var AHTML: string): TMemoryStream;
|
|
var
|
|
S, T: TMemoryStream;
|
|
Handle: THandle;
|
|
Mem: Pointer;
|
|
Format: Word;
|
|
V: TValueType;
|
|
ALength: Integer;
|
|
|
|
function AnotherObject(S: TStream): Boolean;
|
|
var
|
|
Buffer: array[0..255] of Char;
|
|
Position: Integer;
|
|
begin
|
|
Position := S.Position;
|
|
Buffer[S.Read(Buffer, SizeOf(Buffer))-1] := #0;
|
|
S.Position := Position;
|
|
Result := PossibleStream(Buffer);
|
|
end;
|
|
|
|
begin
|
|
AHTML := '';
|
|
Result := TMemoryStream.Create;
|
|
try
|
|
if Clipboard.HasFormat(CF_COMPONENTS) then
|
|
Format := CF_COMPONENTS else
|
|
Format := CF_TEXT;
|
|
Clipboard.Open;
|
|
try
|
|
Handle := Clipboard.GetAsHandle(Format);
|
|
Mem := GlobalLock(Handle);
|
|
try
|
|
Result.Write(Mem^, GlobalSize(Handle));
|
|
finally
|
|
GlobalUnlock(Handle);
|
|
end;
|
|
finally
|
|
Clipboard.Close;
|
|
end;
|
|
Result.Position := 0;
|
|
if Format = CF_TEXT then
|
|
begin
|
|
S := TMemoryStream.Create;
|
|
try
|
|
while AnotherObject(Result) do ObjectTextToBinary(Result, S);
|
|
if Result.Position < Result.Size - 1 then
|
|
begin
|
|
ALength := Result.Size - Result.Position;
|
|
SetLength(AHTML, ALength);
|
|
Result.ReadBuffer(AHTML[1], ALength);
|
|
end;
|
|
V := vaNull;
|
|
S.Write(V, SizeOf(V));
|
|
T := Result;
|
|
Result := nil;
|
|
T.Free;
|
|
except
|
|
S.Free;
|
|
raise;
|
|
end;
|
|
Result := S;
|
|
Result.Position := 0;
|
|
end;
|
|
except
|
|
Result.Free;
|
|
raise;
|
|
end;
|
|
end;
|
|
|
|
const
|
|
EWFHTMLSign = 'EWF_HTML';
|
|
|
|
procedure TcxWebHTMLDesigner.ReadComponent(AComponent: TComponent);
|
|
begin
|
|
FClipboardSelection.Add(AComponent);
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.DoPaste;
|
|
var
|
|
SaveElements: IInterfaceList;
|
|
|
|
procedure UpdateSelection;
|
|
var
|
|
I: Integer;
|
|
AList: IDesignerSelections;
|
|
AWebControl: IcxWebControl;
|
|
begin
|
|
if FClipboardSelection.Count = 0 then exit;
|
|
AList := TDesignerSelections.Create;
|
|
for I := 0 to FClipboardSelection.Count - 1 do
|
|
begin
|
|
AList.Add(TComponent(FClipboardSelection[I]));
|
|
if Supports(TComponent(FClipboardSelection[I]), IcxWebControl, AWebControl) and
|
|
(AWebControl.DesignerControl <> nil) then
|
|
AWebControl.DesignerControl.UpdateContext;
|
|
FDesignerControl.Selection.Add(GetHTMLElementByComponentName(FDesignerControl.Document3,
|
|
TComponent(FClipboardSelection[I]).Name));
|
|
end;
|
|
DelphiDesigner.SetSelections(AList);
|
|
end;
|
|
|
|
function FindNewElementByName(const AName: string): IHTMLElement;
|
|
|
|
function IsElementInList(AList: IInterfaceList; AElement: IHTMLElement): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := False;
|
|
for I := 0 to AList.Count - 1 do
|
|
if IsEqualElement(AList[I] as IHTMLElement, AElement) then
|
|
begin
|
|
Result := True;
|
|
break;
|
|
end;
|
|
end;
|
|
|
|
var
|
|
Elements: IHTMLElementCollection;
|
|
I: Integer;
|
|
begin
|
|
Result := nil;
|
|
Elements := FDesignerControl.Document3.getElementsByName(AName);
|
|
for I := 0 to Elements.length - 1 do
|
|
if not IsElementInList(SaveElements, Elements.item(I, 0) as IHTMLElement) then
|
|
begin
|
|
Result := Elements.item(I, 0) as IHTMLElement;
|
|
break;
|
|
end;
|
|
end;
|
|
|
|
procedure CreateDesignerControls;
|
|
var
|
|
I, Idx: Integer;
|
|
AList: IInterfaceList;
|
|
AFoundElement: IHTMLElement;
|
|
ASelectedList: IDesignerSelections;
|
|
AComponent: TComponent;
|
|
AParentControl: IcxWebContainerControl;
|
|
begin
|
|
AParentControl := nil;
|
|
if (SelectionCount > 0) then
|
|
begin
|
|
ASelectedList := TDesignerSelections.Create;
|
|
DelphiDesigner.GetSelections(ASelectedList);
|
|
if (ASelectedList.Count = 1) and (ASelectedList.Items[0] <> Root) then
|
|
Supports(ASelectedList.Items[0], IcxWebContainerControl, AParentControl);
|
|
end;
|
|
AList := CreateControlList;
|
|
for I := 0 to AList.Count - 1 do
|
|
begin
|
|
AComponent := GetComponentByInterface(AList[I]);
|
|
if (AComponent <> nil) and
|
|
(GetHTMLElementByComponentName(FDesignerControl.Document3, AComponent.Name) = nil) then
|
|
begin
|
|
Idx := FChangedNames.IndexOfObject(AComponent);
|
|
if Idx >= 0 then
|
|
begin
|
|
AFoundElement := FindNewElementByName(FChangedNames.Strings[Idx]);
|
|
if AFoundElement <> nil then
|
|
AFoundElement.id := AComponent.Name
|
|
else
|
|
InternalInsertHTMLControl(AComponent, '', False);
|
|
FChangedNames.Delete(Idx);
|
|
end
|
|
else
|
|
InternalInsertHTMLControl(AComponent, '', False);
|
|
if AParentControl <> nil then
|
|
IcxWebControl(AList[I]).Parent := AParentControl;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
var
|
|
AStream: TStream;
|
|
AReader: TReader;
|
|
AHTML: string;
|
|
ParentElement, Element: IHTMLElement;
|
|
I: Integer;
|
|
begin
|
|
AStream := EWFGetClipboardStream(AHTML);
|
|
SaveElements := TInterfaceList.Create;
|
|
for I := 0 to Root.ComponentCount - 1 do
|
|
begin
|
|
Element := GetHTMLElementByComponentName(FDesignerControl.Document3, Root.Components[I].Name);
|
|
if Element <> nil then
|
|
SaveElements.Add(Element);
|
|
end;
|
|
if AHTML <> '' then
|
|
begin
|
|
if Pos(EWFHTMLSign, AHTML) = 1 then
|
|
begin
|
|
AHTML := Copy(AHTML, Length(EWFHTMLSign) + 1, Length(AHTML));
|
|
ParentElement := nil;
|
|
if (FDesignerControl.Selection.Count = 1) and
|
|
Supports(FDesignerControl.Selection[0], IHTMLTextContainer) then
|
|
ParentElement := FDesignerControl.Selection[0];
|
|
if ParentElement = nil then
|
|
ParentElement := FDesignerControl.MainParentElement;
|
|
ParentElement.insertAdjacentHTML('beforeEnd', AHTML);
|
|
end
|
|
else
|
|
FDesignerControl.Selection.Paste;
|
|
FDesignerControl.Wait;
|
|
end;
|
|
if AStream.Size > 1 then
|
|
try
|
|
AReader := TReader.Create(AStream, 1024);
|
|
FClipboardSelection := TList.Create;
|
|
try
|
|
FChangedNames := TStringList.Create;
|
|
AReader.OnSetName := ReaderSetName;
|
|
AReader.OnFindMethod := ReaderFindMethod;
|
|
AReader.Parent := Root;
|
|
AReader.ReadComponents(Root, Root, ReadComponent);
|
|
CreateDesignerControls;
|
|
if PositioningType = cxptGrid then
|
|
UpdateControlsPosition;
|
|
UpdateSelection;
|
|
finally
|
|
AReader.Free;
|
|
FClipboardSelection.Free;
|
|
FreeAndNil(FChangedNames);
|
|
end;
|
|
finally
|
|
AStream.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxWebHTMLDesigner.DoCopy;
|
|
var
|
|
AStream: TMemoryStream;
|
|
AHTML: String;
|
|
|
|
procedure WriteSelectedComponents;
|
|
var
|
|
AList: IDesignerSelections;
|
|
|
|
function IsNotChild(AComponent: TComponent): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := True;
|
|
for I := 0 to AList.Count - 1 do
|
|
if (AList.Items[I] is TComponent) and (AList.Items[I] <> AComponent) and
|
|
(TComponent(AList.Items[I]) = AComponent.GetParentComponent) then
|
|
begin
|
|
Result := False;
|
|
break;
|
|
end;
|
|
end;
|
|
|
|
function NotInList(AComponent: TComponent): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := True;
|
|
for I := 0 to AList.Count - 1 do
|
|
if (AList[I] is TComponent) and (TComponent(AList[I]) = AComponent) then
|
|
begin
|
|
Result := False;
|
|
break;
|
|
end;
|
|
end;
|
|
|
|
var
|
|
V: Integer;
|
|
AWriter: TWriter;
|
|
I, J: Integer;
|
|
Elements: IHTMLElementCollection;
|
|
WebComp: TComponent;
|
|
begin
|
|
AList := TDesignerSelections.Create;
|
|
DelphiDesigner.GetSelections(AList);
|
|
if AList.Count > 0 then
|
|
begin
|
|
for I := 0 to FDesignerControl.Selection.Count - 1 do
|
|
begin
|
|
Elements := FDesignerControl.Selection[I].all as IHTMLElementCollection;
|
|
for J := 0 to Elements.length - 1 do
|
|
begin
|
|
WebComp := GetComponentByHTMLElement(Root, Elements.item(J, 0) as IHTMLElement);
|
|
if (WebComp <> nil) and NotInList(WebComp) then
|
|
AList.Add(WebComp);
|
|
end;
|
|
end;
|
|
AWriter := TWriter.Create(AStream, 4096);
|
|
try
|
|
AWriter.Root := DelphiDesigner.Root;
|
|
for I := 0 to AList.Count - 1 do
|
|
if (AList.Items[I] is TComponent) and
|
|
(AList.Items[I] <> Root) and IsNotChild(TComponent(AList.Items[I])) then
|
|
begin
|
|
AWriter.WriteSignature;
|
|
AWriter.WriteComponent(TComponent(AList.Items[I]));
|
|
end;
|
|
finally
|
|
AWriter.WriteListEnd;
|
|
AWriter.Free;
|
|
end;
|
|
if AStream.Size > 0 then
|
|
begin
|
|
V := 0;
|
|
AStream.Write(V, 1);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure GetHTMLText;
|
|
var
|
|
AList: IDesignerSelections;
|
|
I: Integer;
|
|
begin
|
|
AHTML := '';
|
|
AList := TDesignerSelections.Create;
|
|
DelphiDesigner.GetSelections(AList);
|
|
for I := 0 to AList.Count - 1 do
|
|
if (AList.Items[I] is TcxWebHTMLElementMapper) then
|
|
AHTML := AHTML + TcxWebHTMLElementMapper(AList.Items[I]).Element.outerHTML;
|
|
if AHTML <> '' then
|
|
AHTML := EWFHTMLSign + AHTML;
|
|
end;
|
|
|
|
begin
|
|
if SelectionCount = 0 then
|
|
FDesignerControl.Selection.Copy
|
|
else
|
|
begin
|
|
AStream := TMemoryStream.Create;
|
|
try
|
|
WriteSelectedComponents;
|
|
GetHTMLText;
|
|
if AStream.Size > 0 then
|
|
EWFCopyStreamToClipboard(AStream, AHTML)
|
|
else
|
|
EWFCopyStreamToClipboard(nil, AHTML);
|
|
finally
|
|
AStream.Free;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
type
|
|
PTransBuffer = ^TTransBuffer;
|
|
TTransBuffer = array[0..1] of SmallInt;
|
|
|
|
function GetIEVerInfo: string;
|
|
const
|
|
AFileName = 'mshtml';
|
|
AProductName = 'ProductVersion';
|
|
var
|
|
i: integer;
|
|
AInfoSize, AVerSize, dummy: DWORD;
|
|
ptrans: PTransBuffer;
|
|
typeStr: string;
|
|
value: PChar;
|
|
AVerBuf: pointer;
|
|
begin
|
|
Result := '';
|
|
AInfoSize := GetFileVersioninfoSize(AFileName, dummy);
|
|
if AInfoSize <> 0 then
|
|
begin
|
|
GetMem(AVerBuf, AInfoSize);
|
|
try
|
|
if GetFileVersionInfo(AFileName, 0, AInfoSize, AVerBuf) then
|
|
begin
|
|
VerQueryvalue(AVerBuf, '\VarFileInfo\Translation',
|
|
Pointer(ptrans), AInfoSize);
|
|
|
|
for I := 0 to AInfoSize div SizeOf(TTransBuffer) do
|
|
begin
|
|
typeStr := 'StringFileInfo\' + IntToHex(ptrans^[0], 4) + IntToHex(ptrans^[1], 4) + '\' + AProductName;
|
|
if VerQueryvalue(AVerBuf, PChar(typeStr), Pointer(value), AVerSize) then
|
|
begin
|
|
Result := Value;
|
|
break;
|
|
end;
|
|
ptrans := PTransBuffer(Integer(ptrans) + SizeOf(TTransBuffer));
|
|
end;
|
|
end;
|
|
finally
|
|
FreeMem(AVerBuf);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function IsIE5_5: Boolean;
|
|
var
|
|
AVerInfo: string;
|
|
|
|
function GetNextDigit: Integer;
|
|
var
|
|
ASt: string;
|
|
I: Integer;
|
|
begin
|
|
Result := 0;
|
|
if Pos('.', AVerInfo) > 0 then
|
|
begin
|
|
ASt := Copy(AVerInfo, 1, Pos('.', AVerInfo) - 1);
|
|
AVerInfo := Copy(AVerInfo, Pos('.', AVerInfo) + 1, Length(AVerInfo));
|
|
end else
|
|
begin
|
|
ASt := AVerInfo;
|
|
AVerInfo := '';
|
|
end;
|
|
if (ASt <> '') then
|
|
begin
|
|
for I := 1 to Length(ASt) do
|
|
if not (ASt[I] in ['0'..'9']) then
|
|
exit;
|
|
Result := StrToInt(ASt);
|
|
end;
|
|
end;
|
|
var
|
|
AVerNumber: Integer;
|
|
begin
|
|
Result := False;
|
|
AVerInfo := GetIEVerInfo;
|
|
if AVerInfo <> '' then
|
|
begin
|
|
AVerNumber := GetNextDigit;
|
|
cxWebHTMLDesignerMajorVersion := AVerNumber;
|
|
Result := AVerNumber > 4;
|
|
if Result and (AVerNumber = 5) then
|
|
Result :=GetNextDigit > 4;
|
|
end;
|
|
end;
|
|
|
|
initialization
|
|
if IsIE5_5 then
|
|
WebDesignerFactory.RegisterDesigner(TcxWebHTMLDesigner, True);
|
|
|
|
finalization
|
|
WebDesignerFactory.UnregisterDesigner(TcxWebHTMLDesigner);
|
|
|
|
end.
|