Componentes.Terceros.DevExp.../official/x.48/ExpressWeb Framework/Sources/cxfmWebDsgn.pas
2010-01-18 18:33:24 +00:00

1311 lines
38 KiB
ObjectPascal

{*******************************************************************}
{ }
{ ExpressWeb Framework by Developer Express }
{ Designer Module }
{ }
{ Copyright (c) 2000-2009 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 cxfmWebDsgn;
{$I cxVer.inc}
interface
uses Classes, DesignIntf, DesignMenus,
{$IFDEF VCL}
Windows, Messages, Graphics, Controls, Forms, Menus, StdCtrls, ImgList,
ComCtrls, Buttons, ExtCtrls, ToolWin, DesignWindows, Dialogs,
cxWebHTMLEditor,
{$ELSE}
Qt, Types, QGraphics, QControls, QForms, QMenus, QStdCtrls, QImgList,
QComCtrls, QButtons, QExtCtrls, CLXDesignWindows, QDialogs,
{$ENDIF}
cxWebDsgnStrs, cxWebRender, cxWebClasses, cxWebControls, cxWebStdCtrls,
cxWebDsgnEnvOpt, cxWebDsgnIntf, cxWebIntf;
type
{$IFDEF LINUX}
TcxMozillaBrowser = class;
{$ENDIF}
TComponentContainer = class(TScrollBox);
TcxWebModuleState = (msForm, msHTMLResult, msPreview);
TcxWebModuleDesignWindow = class({$IFDEF VCL}TDesignWindow,{$ELSE}TCLXDesignWindow,{$ENDIF}
IcxDesignerWindow, IcxWebModuleDesignerNotify)
private
FContainerWindow: TComponentContainer;
FHSplitter: TSplitter;
FWebDesigner: TcxAbstractWebDesigner;
FModuleState: TcxWebModuleState;
FPanels: Array[TcxWebModuleState] of TPanel;
FButtons: Array[TcxWebModuleState] of TToolButton;
FHTMLResultMemo: TMemo;
FMemoMenu: TPopupMenu;
FFindDialog: TFindDialog;
{$IFDEF VCL}
FWebBrowser: TcxHTMLEditor;
{$ENDIF}
{$IFDEF LINUX}
FWebBrowser: TcxMozillaBrowser;
{$ENDIF}
ToolBar: TToolBar;
btnForm: TToolButton;
btnSource: TToolButton;
btnPreview: TToolButton;
procedure HSplitterCanResize(Sender: TObject; var NewSize: Integer; var Accept: Boolean);
procedure HSplitterMoved(Sender: TObject);
procedure btnFormClick(Sender: TObject);
procedure btnSourceClick(Sender: TObject);
procedure btnPreviewClick(Sender: TObject);
procedure DoOnPopup(Sender: TObject);
procedure DoFindText(Sender: TObject);
{$IFDEF VCL}
procedure DoFindClose(Sender: TObject);
{$ENDIF}
procedure DoCopyText(Sender: TObject);
procedure DoSelectText(Sender: TObject);
procedure CreateFormComponents;
procedure CreateDesigner;
procedure CreateDesignerControl;
procedure RecreateDesigner;
procedure CreateControls;
procedure DropDesigningInComponentState;
procedure ReadFormLayout;
procedure SaveFormPosition;
function IsDestroying: Boolean;
function IsOwnDesigner(const ADesigner: IDesigner; const AnItem: TPersistent): Boolean;
procedure DoOnActivate(Sender: TObject);
procedure DoOnDeactivate(Sender: TObject);
procedure SetModuleState(const Value: TcxWebModuleState);
procedure ModuleStateChanged;
procedure PrepareHTMLStrings;
procedure PrepareHTMLFile;
procedure EnableButtons(AEnabled: Boolean);
protected
{$IFDEF VCL}
procedure WMMove(var Message: TWMMove); message WM_MOVE;
procedure WMNCActivate(var Message: TWMNCActivate); message WM_NCACTIVATE;
{$ELSE}
function EventFilter(Sender: QObjectH; Event: QEventH): Boolean; override;
{$ENDIF}
{IcxWebModuleDesignerNotify}
procedure DesignerIDChanged;
procedure DesignerPositioningTypeChanged;
function IsSupportPositioningTypeChanged(APositioningType: TcxWebPositioningType): Boolean;
function GetControlPositioningType: TcxWebPositioningType;
{ IcxDesignerWindow }
function GetShowingType: TcxWebDesignerShowingType;
procedure ShowDesigner;
function GetDesignerCount: Integer;
function GetDesignerName(Index: Integer): String;
function GetDesignerID: Integer;
procedure Activated; override;
procedure KeyPress(var Key: Char); override;
function QueryInterface(const IID: TGUID; out Obj): HResult; override;
procedure Resize; override;
public
constructor CreateEx(AOwner: TComponent; const ADesigner: IDesigner;
out AComponentContainer: TWinControl);
destructor Destroy; override;
procedure ItemInserted(const ADesigner: IDesigner; Item: TPersistent); override;
procedure ItemDeleted(const ADesigner: IDesigner; Item: TPersistent); override;
procedure ValidateRename(AComponent: TComponent; const CurName, NewName: string); override;
{ IEditHandler }
function GetEditState: TEditState; override;
function EditAction(Action: TEditAction): Boolean; override;
{ IDesignNotification }
procedure DesignerClosed(const ADesigner: IDesigner; AGoingDormant: Boolean); override;
procedure DesignerOpened(const ADesigner: IDesigner; AResurrecting: Boolean); override;
procedure ItemsModified(const ADesigner: IDesigner); override;
{IcxWebModuleDesignerNotify}
procedure SelectionChanged(const ADesigner: IDesigner; const ASelection: IDesignerSelections); override;
property ModuleState: TcxWebModuleState read FModuleState write SetModuleState;
property WebDesigner: TcxAbstractWebDesigner read FWebDesigner;
end;
{$IFDEF LINUX}
TcxMozillaBrowser = class
private
FOwner: TcxWebModuleDesignWindow;
FBrowserPID: Integer;
procedure StartMozilla;
protected
property BrowserPID: Integer read FBrowserPID;
public
constructor Create(AOwner: TcxWebModuleDesignWindow);
destructor Destroy; override;
procedure Reload;
end;
{$ENDIF}
implementation
{$IFDEF VCL}
{$R *.dfm}
{$ELSE}
{$R *.xfm}
{$ENDIF}
uses SysUtils, ToolsAPI,
{$IFDEF VCL}
ActiveX,
{$ENDIF}
{$IFDEF LINUX}
Libc, Xlib,
{$ENDIF}
cxWebDsgnFactory, cxWebDsgnUtils, cxWebDsgnWebContext, cxWebDsgnConsts,
StrUtils;
{$IFNDEF VCL}
function GetRValue(Color: Integer): Byte;
begin
Result := Byte(Color);
end;
function GetGValue(Color: Integer): Byte;
begin
Result := Byte(Color shr 8);
end;
function GetBValue(Color: Integer): Byte;
begin
Result := Byte(Color shr 16);
end;
function RGB(R, G, B: Byte): Integer;
begin
Result := (R or (G shl 8) or (B shl 16));
end;
{$ENDIF}
function ShiftColor(AColor: TColor; ARed, AGreen, ABlue: Byte): TColor;
var
Red, Green, Blue: Integer;
begin
Red := GetRValue(AColor) + ARed;
if Red > High(Byte) then Red := High(Byte);
if Red < Low(Byte) then Red := Low(Byte);
Green := GetGValue(AColor) + AGreen;
if Green > High(Byte) then Green := High(Byte);
if Green < Low(Byte) then Green := Low(Byte);
Blue := GetBValue(AColor) + ABlue;
if Blue > High(Byte) then Blue := High(Byte);
if Blue < Low(Byte) then Blue := Low(Byte);
Result := RGB(Red, Green, Blue);
end;
type
TComponentAccess = class(TComponent);
TFormAccess = class(TForm);
{ TcxHSplitter }
TcxHSplitter = class(TSplitter)
protected
procedure Paint; override;
end;
procedure TcxHSplitter.Paint;
begin
with Canvas do
begin
if Top + Height + MinSize + 1 = Parent.Height then
begin
Brush.Color := clWindow;
FillRect(ClientRect);
end
else
begin
Pen.Color := clWindowText;
Brush.Color := clBtnFace;
Rectangle(ClientRect);
end;
end;
end;
{$IFDEF LINUX}
type
PXIDMapEntry = ^TXIDMapEntry;
TXIDMapEntry = record
HostWnd: QWidgetH;
ClientXID: TWindow;
end;
TXIDMap = class
private
FList: TList;
public
constructor Create;
destructor Destroy; override;
function Add(AHostWnd: QWidgetH; AClientXID: TWindow): Integer;
procedure Clear;
procedure Delete(AIndex: Integer);
function FindClientXID(AHostWnd: QWidgetH): TWindow;
function IndexOf(AHostWnd: QWidgetH): Integer;
procedure Remove(AHostWnd: QWidgetH);
end;
var
cxPrevEventFilter: X11EventFilter = nil;
XIDMap: TXIDMap;
{ TXIDMap }
constructor TXIDMap.Create;
begin
FList := TList.Create;
end;
destructor TXIDMap.Destroy;
begin
Clear;
FreeAndNil(FList);
inherited;
end;
function TXIDMap.Add(AHostWnd: QWidgetH; AClientXID: TWindow): Integer;
var
P: PXIDMapEntry;
begin
New(P);
P^.HostWnd := AHostWnd;
P^.ClientXID := AClientXID;
Result := FList.Add(P);
end;
procedure TXIDMap.Clear;
begin
while FList.Count > 0 do
Delete(FList.Count - 1);
end;
procedure TXIDMap.Delete(AIndex: Integer);
begin
Dispose(PXIDMapEntry(FList[AIndex]));
FList.Delete(AIndex);
end;
function TXIDMap.FindClientXID(AHostWnd: QWidgetH): TWindow;
var
Idx: Integer;
begin
Idx := IndexOf(AHostWnd);
if Idx <> -1 then
Result := PXIDMapEntry(FList[Idx])^.ClientXID
else
Result := 0;
end;
function TXIDMap.IndexOf(AHostWnd: QWidgetH): Integer;
var
I: Integer;
begin
Result := -1;
for I := 0 to FList.Count - 1 do
if PXIDMapEntry(FList[I])^.HostWnd = AHostWnd then
begin
Result := I;
break;
end;
end;
procedure TXIDMap.Remove(AHostWnd: QWidgetH);
var
Idx: Integer;
begin
Idx := IndexOf(AHostWnd);
if Idx <> -1 then
Delete(Idx);
end;
function cxMozillaEventFilter(XEvent: PXEvent): Boolean; cdecl;
var
XCM: PXClientMessageEvent;
begin
Result := False;
if XEvent^.xtype = ClientMessage then
begin
XCM := PXClientMessageEvent(XEvent);
if (XCM^.data.l[0] = 0) and (XCM^.data.l[2] = $0111) then
begin
XReparentWindow(XCM^.display, TWindow(XCM^.data.l[3]),
QWidget_winId(QWidgetH(XCM^.data.l[1])), 0, 0);
XIDMap.Add(QWidgetH(XCM^.data.l[1]), XCM^.data.l[3]);
Result := True;
end;
end;
end;
{$ENDIF}
{ TcxWebModuleDesignWindow }
constructor TcxWebModuleDesignWindow.CreateEx(AOwner: TComponent;
const ADesigner: IDesigner; out AComponentContainer: TWinControl);
begin
Designer := ADesigner;
CreateDesigner;
inherited Create(AOwner);
CreateFormComponents;
SetDesigning(True);
KeyPreview := True;
CreateControls;
AComponentContainer := FContainerWindow;
FModuleState := msForm;
ModuleStateChanged;
end;
procedure TcxWebModuleDesignWindow.CreateFormComponents;
function CreateButton(ACaption: string; AImageIndex: Integer; onClick: TNotifyEvent): TToolButton;
begin
Result := TToolButton.Create(ToolBar);
Result.Parent := ToolBar;
Result.Caption := ACaption;
Result.ImageIndex := AImageIndex;
Result.OnClick := onClick;
Result.AllowAllUp := False;
Result.Down := False;
Result.Grouped := True;
Result.Style := tbsCheck;
end;
begin
ToolBar := TToolBar.Create(self);
ToolBar.Parent := self;
ToolBar.Align := alBottom;
ToolBar.AutoSize := True;
ToolBar.BorderWidth := 1;
ToolBar.ButtonHeight := 24;
ToolBar.ButtonWidth := 85;
ToolBar.Flat := True;
ToolBar.ShowCaptions := True;
{$IFDEF VCL}
btnPreview := CreateButton(scxWebDsgnPreviewButton, 2, btnPreviewClick);
btnSource := CreateButton(scxWebDsgnResultButton, 1, btnSourceClick);
btnForm := CreateButton(scxWebDsgnFormButton, 0, btnFormClick);
{$ELSE}
btnForm := CreateButton(scxWebDsgnFormButton, 0, btnFormClick);
btnSource := CreateButton(scxWebDsgnResultButton, 1, btnSourceClick);
btnPreview := CreateButton(scxWebDsgnPreviewButton, 2, btnPreviewClick);
{$ENDIF}
btnForm.Down := True;
end;
destructor TcxWebModuleDesignWindow.Destroy;
begin
if Designer <> nil then
Designer.NoSelection;
if FWebDesigner <> nil then
begin
FWebDesigner.DestroyDesignerControl;
FWebDesigner.Free;
FWebDesigner := nil;
end;
{$IFNDEF LINUX}
FreeAndNil(FWebBrowser);
{$ENDIF}
inherited Destroy;
end;
{$IFDEF VCL}
procedure TcxWebModuleDesignWindow.WMMove(var Message: TWMMove);
begin
inherited;
SaveFormPosition;
end;
procedure TcxWebModuleDesignWindow.WMNCActivate(var Message: TWMNCActivate);
begin
inherited;
if Message.Active then
DoOnActivate(Self)
else
DoOnDeactivate(Self);
end;
{$ELSE}
function TcxWebModuleDesignWindow.EventFilter(Sender: QObjectH;
Event: QEventH): Boolean;
begin
Result := inherited EventFilter(Sender, Event);
case QEvent_type(Event) of
QEventType_WindowActivate: DoOnActivate(Self);
QEventType_WindowDeactivate: DoOnDeactivate(Self);
end;
end;
{$ENDIF}
{ IEditHandler }
function TcxWebModuleDesignWindow.GetEditState: TEditState;
begin
Result := [];
if WebDesigner <> nil then
with FWebDesigner do
begin
if CanUndo then Include(Result, esCanUndo);
if CanCut then Include(Result, esCanCut);
if CanCopy then Include(Result, esCanCopy);
if CanPaste then Include(Result, esCanPaste);
if CanDelete then Include(Result, esCanDelete);
{$IFNDEF DELPHI9}
if CanTabOrder then Include(Result, esCanTabOrder);
{$ENDIF}
if CanSelectAll then Include(Result, esCanSelectAll);
end;
end;
function TcxWebModuleDesignWindow.EditAction(Action: TEditAction): Boolean;
begin
Result := True;
if WebDesigner <> nil then
with FWebDesigner do
case Action of
eaUndo: Undo;
eaCut: CutSelection;
eaCopy: CopySelection;
eaPaste: PasteSelection;
eaDelete: DeleteSelection;
eaSelectAll: SelectAll;
{$IFNDEF DELPHI9}
eaAlignToGrid: AlignToGrid;
{$ENDIF}
end;
end;
{ IDesignNotification }
procedure TcxWebModuleDesignWindow.DesignerOpened(const ADesigner: IDesigner; AResurrecting: Boolean);
begin
if IsOwnDesigner(ADesigner, nil) then
begin
if WebDesigner <> nil then
begin
Caption := FWebDesigner.Root.Name;
ReadFormLayout;
DropDesigningInComponentState;
FWebDesigner.UpdateDesignerControl;
FWebDesigner.RefreshDesignControls;
end;
end;
end;
procedure TcxWebModuleDesignWindow.DesignerClosed(const ADesigner: IDesigner; AGoingDormant: Boolean);
begin
{$IFDEF VCL} //TODO check in Windows. It looks like it should be removed
if IsOwnDesigner(ADesigner, nil) then
begin
Destroying;
Release;
end;
{$ENDIF}
end;
procedure TcxWebModuleDesignWindow.ItemsModified(const ADesigner: IDesigner);
function IsEmptySelection: Boolean;
var
AList: IDesignerSelections;
begin
AList := TDesignerSelections.Create;
Designer.GetSelections(AList);
Result := (AList.Count = 0);
end;
begin
if not IsDestroying and IsOwnDesigner(ADesigner, nil) then
begin
if not IsEmptySelection then
ModuleState := msForm;
if FWebDesigner <> nil then
FWebDesigner.Modified;
end;
end;
{IcxWebModuleDesignerNotify}
procedure TcxWebModuleDesignWindow.SelectionChanged(const ADesigner: IDesigner;
const ASelection: IDesignerSelections);
var
List: TList;
begin
if not IsDestroying and IsOwnDesigner(ADesigner, nil) then
begin
List := TList.Create;
try
DesignerSelectionsToList(ASelection, List);
if FWebDesigner <> nil then
FWebDesigner.SelectionChanged(List);
finally
List.Free;
end;
end;
end;
{IcxWebModuleDesignerNotify}
procedure TcxWebModuleDesignWindow.DesignerIDChanged;
begin
if (FWebDesigner = nil) or (FWebDesigner.GetID <> GetDesignerID) then
begin
if ModuleState <> msForm then
ModuleState := msForm;
if FWebDesigner <> nil then
FWebDesigner.DesignerIdChanging;
RecreateDesigner;
if (FWebDesigner <> nil) and not (csLoading in Designer.Root.ComponentState) then
FWebDesigner.RefreshDesignControls;
end;
end;
procedure TcxWebModuleDesignWindow.DesignerPositioningTypeChanged;
begin
if (FWebDesigner <> nil) then
begin
if (ModuleState <> msForm) then
ModuleState := msForm;
FWebDesigner.DesignerPositioningTypeChanged;
end;
end;
function TcxWebModuleDesignWindow.IsSupportPositioningTypeChanged(APositioningType: TcxWebPositioningType): Boolean;
begin
if (FWebDesigner <> nil) then
Result := FWebDesigner.IsSupportPositioningTypeChanged(APositioningType)
else Result := False;
end;
function TcxWebModuleDesignWindow.GetControlPositioningType: TcxWebPositioningType;
begin
if (FWebDesigner <> nil) then
Result := FWebDesigner.GetControlPositioningType
else Result := cxptGrid;
end;
{ IcxDesignerWindow }
function TcxWebModuleDesignWindow.GetShowingType: TcxWebDesignerShowingType;
begin
if ModuleState = msForm then
Result := stDesigner
else Result := stPreview;
end;
procedure TcxWebModuleDesignWindow.ShowDesigner;
begin
ModuleState := msForm;
end;
function TcxWebModuleDesignWindow.GetDesignerCount: Integer;
begin
Result := WebDesignerFactory.Count;
end;
function TcxWebModuleDesignWindow.GetDesignerName(Index: Integer): String;
begin
Result := WebDesignerFactory[Index].GetName;
end;
procedure TcxWebModuleDesignWindow.Activated;
begin
inherited Activated;
if (FWebDesigner <> nil) and (FWebDesigner.DesignerControl <> nil) then
begin
{$IFDEF VCL}
Windows.SetFocus(FWebDesigner.DesignerControl.Handle);
{$ELSE}
QWidget_setFocus(FWebDesigner.DesignerControl.Handle);
{$ENDIF}
end;
end;
function TcxWebModuleDesignWindow.GetDesignerID: Integer;
begin
if (Designer.Root <> nil) and Supports(Designer.Root, IcxWebDesignerModule) then
Result := (Designer.Root as IcxWebDesignerModule).GetDesignerID
else Result := -1;
end;
procedure TcxWebModuleDesignWindow.KeyPress(var Key: char);
begin
if Key in [#13, #33..#126] then
begin
if Key = #13 then Key := #0;
ActivateInspector(Key);
Key := #0;
end;
inherited KeyPress(Key);
end;
function TcxWebModuleDesignWindow.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
if IsEqualGUID(IID, IEditHandler) then
begin
GetInterface(IID, Obj);
Result := S_OK;
end
else
Result := inherited QueryInterface(IID, Obj);
end;
procedure TcxWebModuleDesignWindow.Resize;
{$IFDEF LINUX}
var
BrowserXID: TWindow;
{$ENDIF}
begin
inherited;
SaveFormPosition;
{$IFDEF LINUX}
BrowserXID := XIDMap.FindClientXID(FPanels[msPreview].Handle);
if BrowserXID <> 0 then
XResizeWindow(Application.Display, BrowserXID,
Width, Height - ToolBar.Height);
{$ENDIF}
end;
procedure TcxWebModuleDesignWindow.ItemInserted(const ADesigner: IDesigner; Item: TPersistent);
begin
inherited ItemInserted(ADesigner, Item);
if IsOwnDesigner(ADesigner, Item) and (Item is TComponent) and (WebDesigner <> nil) then
WebDesigner.ComponentCreated(TComponent(Item));
end;
procedure TcxWebModuleDesignWindow.ItemDeleted(const ADesigner: IDesigner; Item: TPersistent);
begin
if IsOwnDesigner(ADesigner, Item) and (Item is TComponent) and (WebDesigner <> nil) then
WebDesigner.ComponentDestroyed(TComponent(Item));
inherited ItemDeleted(ADesigner, Item);
end;
procedure TcxWebModuleDesignWindow.ValidateRename(AComponent: TComponent;
const CurName, NewName: string);
begin
inherited ValidateRename(AComponent, CurName, NewName);
if (AComponent <> nil) and not (csDestroying in AComponent.ComponentState)
and not (csLoading in AComponent.ComponentState)
and (AComponent.Owner = Designer.Root)
and (WebDesigner <> nil) then
WebDesigner.ComponentChangedName(AComponent, CurName, NewName);
end;
procedure TcxWebModuleDesignWindow.HSplitterCanResize(Sender: TObject;
var NewSize: Integer; var Accept: Boolean);
begin
if TcxWebDesignerEnvironmentOptions.GetSnapControlsToGrid(Designer) then
begin
if NewSize < 0 then NewSize := 0;
end;
Accept := NewSize <= Height - 200;
end;
procedure TcxWebModuleDesignWindow.HSplitterMoved(Sender: TObject);
begin
TcxWebDesignerEnvironmentOptions.SetDividerPos(Designer,
FContainerWindow.Height + FHSplitter.Height + FHSplitter.MinSize);
end;
procedure TcxWebModuleDesignWindow.CreateDesigner;
begin
FWebDesigner := WebDesignerFactory.GetDesignerByID(GetDesignerID).Create(self, Designer);
InsertComponent(FWebDesigner.Root);
if (Designer.Root <> nil) and Supports(Designer.Root, IcxWebDesignerModule) then
(Designer.Root as IcxWebDesignerModule).SetDesignerID(FWebDesigner.GetID);
end;
procedure TcxWebModuleDesignWindow.CreateDesignerControl;
begin
if FWebDesigner <> nil then
begin
FWebDesigner.CreateDesignerControl(FPanels[msForm]);
TComponentAccess(FWebDesigner.DesignerControl).SetDesigning(False);
end;
end;
procedure TcxWebModuleDesignWindow.RecreateDesigner;
begin
if (FWebDesigner <> nil)
and (WebDesignerFactory.GetDesignerByID(GetDesignerID) = FWebDesigner.ClassType) then
exit;
if FWebDesigner <> nil then
begin
RemoveComponent(FWebDesigner.Root);
FWebDesigner.DestroyDesignerControl;
FWebDesigner.Free;
FWebDesigner := nil;
end;
CreateDesigner;
CreateDesignerControl;
FWebDesigner.UpdateDesignerControl;
end;
type
{$IFDEF VCL}
TWebBrowserHack = class(TcxHTMLEditor);
{$ENDIF}
TMemoHack = class(TMemo)
private
{$IFDEF VCL}
procedure WMContextMenu(var Message: TWMContextMenu); message WM_CONTEXTMENU;
procedure WMKeyDown(var Message: TWMKeyDown); message WM_KEYDOWN;
procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
{$ENDIF}
end;
{$IFDEF VCL}
procedure TMemoHack.WMContextMenu(var Message: TWMContextMenu);
begin
PopupMenu.PopupComponent := Self;
PopupMenu.Popup(Message.XPos, Message.YPos);
Message.Result := 1;
end;
procedure TMemoHack.WMGetDlgCode(var Message: TWMGetDlgCode);
begin
Message.Result := DLGC_WANTARROWS or DLGC_WANTTAB;
end;
procedure TMemoHack.WMKeyDown(var Message: TWMKeyDown);
begin
if Message.CharCode = VK_TAB then
Message.Result := 1
else inherited;
end;
{$ENDIF}
procedure TcxWebModuleDesignWindow.CreateControls;
procedure CreateHSplitter;
begin
FHSplitter := TcxHSplitter.Create(Self);
TComponentAccess(FHSplitter).SetDesigning(False);
FHSplitter.Parent := FPanels[msForm];
FHSplitter.Align := alBottom;
FHSplitter.AutoSnap := False;
FHSplitter.MinSize := 1;
FHSplitter.OnCanResize := HSplitterCanResize;
FHSplitter.OnMoved := HSplitterMoved;
end;
procedure CreateContainerWindow;
begin
FContainerWindow := TComponentContainer.Create(Self);
TComponentAccess(FContainerWindow).SetDesigning(True);
FContainerWindow.Parent := FPanels[msForm];
FContainerWindow.Align := alBottom;
FContainerWindow.Color := ShiftColor(ColorToRGB(clBtnFace), 10, 10, 10);
FContainerWindow.Height := TcxWebDesignerEnvironmentOptions.GetDividerPos(Designer)
- FHSplitter.Height - FHSplitter.MinSize;
FContainerWindow.Top := FContainerWindow.Parent.Height - FContainerWindow.Height;
FHSplitter.Align := alTop;
FHSplitter.Align := alBottom;
FContainerWindow.BorderStyle := bsNone;
end;
function CreatePanel: TPanel;
begin
Result := TPanel.Create(self);
Result.Parent := self;
Result.Align := alClient;
Result.BorderStyle := bsNone;
Result.BevelInner := bvNone;
Result.BevelOuter := bvNone;
end;
procedure CreatePopupMenu;
var
Item: TMenuItem;
begin
FMemoMenu := TPopupMenu.Create(self);
TComponentAccess(FMemoMenu).SetDesigning(False);
FMemoMenu.OnPopup := DoOnPopup;
FFindDialog := TFindDialog.Create(self);
TComponentAccess(FFindDialog).SetDesigning(False);
FFindDialog.Options := [frHideUpDown];
{$IFNDEF VCL}
FFindDialog.Modal := True;
FFindDialog.Title := 'Find Text';
{$ELSE}
FFindDialog.OnFind := DoFindText;
FFindDialog.OnClose := DoFindClose;
{$ENDIF}
Item := TMenuItem.Create(FMemoMenu);
Item.Caption := 'Find...';
Item.ShortCut := ShortCut({$IFDEF VCL}Ord('F'){$ELSE}Key_F{$ENDIF}, [ssCtrl]);
Item.OnClick := DoFindText;
FMemoMenu.Items.Add(Item);
Item := TMenuItem.Create(FMemoMenu);
Item.Caption := 'Find Next';
Item.ShortCut := ShortCut({$IFDEF VCL}VK_F3{$ELSE}Key_F3{$ENDIF}, []);
Item.OnClick := DoFindText;
Item.Enabled := False;
FMemoMenu.Items.Add(Item);
Item := TMenuItem.Create(FMemoMenu);
Item.Caption := '-';
FMemoMenu.Items.Add(Item);
Item := TMenuItem.Create(FMemoMenu);
Item.Caption := 'Copy';
Item.ShortCut := ShortCut({$IFDEF VCL}Ord('C'){$ELSE}Key_C{$ENDIF}, [ssCtrl]);
Item.OnClick := DoCopyText;
Item.Enabled := False;
FMemoMenu.Items.Add(Item);
Item := TMenuItem.Create(FMemoMenu);
Item.Caption := 'Select All';
Item.ShortCut := ShortCut({$IFDEF VCL}Ord('A'){$ELSE}Key_A{$ENDIF}, [ssCtrl]);
Item.OnClick := DoSelectText;
FMemoMenu.Items.Add(Item);
end;
procedure CreateHTMLResultMemo;
begin
FHTMLResultMemo := TMemoHack.Create(self);
TComponentAccess(FHTMLResultMemo).SetDesigning(False);
FHTMLResultMemo.Parent := FPanels[msHTMLResult];
FHTMLResultMemo.ScrollBars := ssBoth;
FHTMLResultMemo.WordWrap := False;
FHTMLResultMemo.Align := alClient;
FHTMLResultMemo.ReadOnly := True;
{$IFDEF VCL}
FHTMLResultMemo.HideSelection := False;
{$ENDIF}
CreatePopupMenu;
FHTMLResultMemo.PopupMenu := FMemoMenu;
end;
procedure CreateWebBrowser;
begin
{$IFDEF VCL}
FWebBrowser := TWebBrowserHack.Create(self, True);
TWebBrowserHack(FWebBrowser).SetParent(FPanels[msPreview]);
FWebBrowser.Align := alClient;
{$ENDIF}
{$IFDEF LINUX}
FWebBrowser := TcxMozillaBrowser.Create(self);
{$ENDIF}
end;
var
AState: TcxWebModuleState;
begin
for AState := Low(TcxWebModuleState) to High(TcxWebModuleState) do
FPanels[AState] := CreatePanel;
FButtons[msForm] := btnForm;
FButtons[msHTMLResult] := btnSource;
FButtons[msPreview] := btnPreview;
CreateHTMLResultMemo;
CreateWebBrowser;
CreateHSplitter;
CreateContainerWindow;
CreateDesignerControl;
end;
procedure TcxWebModuleDesignWindow.DropDesigningInComponentState;
var
I: Integer;
Component: TComponent;
begin
for I := 0 to ComponentCount - 1 do
begin
Component := Components[I];
if (Component <> Designer.GetRoot) and (Component <> FContainerWindow) then
TComponentAccess(Component).SetDesigning(False);
end;
end;
procedure TcxWebModuleDesignWindow.ReadFormLayout;
const
VisibleModuleSize = 10;
var
DesignOffset: TPoint;
DesignSize: TPoint;
begin
if (Designer.Root is TDataModule) then
begin
DesignOffset := TDataModule(Designer.Root).DesignOffset;
DesignSize := TDataModule(Designer.Root).DesignSize;
if (DesignOffset.X + DesignSize.X < VisibleModuleSize) then
DesignOffset.X := VisibleModuleSize - DesignSize.X;
if (DesignOffset.Y + DesignSize.Y < VisibleModuleSize) then
DesignOffset.Y := VisibleModuleSize - DesignSize.Y;
if ({$IFNDEF VCL}QForms.{$ENDIF}Screen.Width - DesignOffset.X < VisibleModuleSize) then
DesignOffset.X := {$IFNDEF VCL}QForms.{$ENDIF}Screen.Width - VisibleModuleSize;
if ({$IFNDEF VCL}QForms.{$ENDIF}Screen.Height - DesignOffset.Y < VisibleModuleSize) then
DesignOffset.Y := {$IFNDEF VCL}QForms.{$ENDIF}Screen.Height - VisibleModuleSize;
Left := DesignOffset.X;
Top := DesignOffset.Y;
Width := DesignSize.X;
Height := DesignSize.Y;
end;
end;
procedure TcxWebModuleDesignWindow.SaveFormPosition;
begin
if (Designer.Root is TDataModule) then
with TDataModule(Designer.Root) do
begin
DesignOffset := Point(Left, Top);
DesignSize := Point(Width, Height);
end;
end;
function TcxWebModuleDesignWindow.IsDestroying: Boolean;
begin
Result := csDestroying in ComponentState;
end;
function TcxWebModuleDesignWindow.IsOwnDesigner(const ADesigner: IDesigner;
const AnItem: TPersistent): Boolean;
begin
Result := (ADesigner = nil) or (ADesigner = Designer);
if Result and (AnItem <> nil) then
Result := FindRootDesigner(AnItem) = FindRootDesigner(Designer.Root);
(*
{$IFDEF VCL}
Result := (TFormAccess(Self).Designer as IDesignerNotify) = FindRootDesigner(AnItem);
{$ELSE}
if Supports(Designer, IDesignerNotify) then //TODO LINUX check it out
Result := (Designer as IDesignerNotify) = FindRootDesigner(AnItem);
{$ENDIF}
*)
end;
procedure TcxWebModuleDesignWindow.DoOnActivate(Sender: TObject);
begin
if (FWebDesigner <> nil) then
FWebDesigner.DesignerActivated;
end;
procedure TcxWebModuleDesignWindow.DoOnDeactivate(Sender: TObject);
begin
if (FWebDesigner <> nil) then
FWebDesigner.DesignerDeactivated;
end;
procedure TcxWebModuleDesignWindow.SetModuleState(const Value: TcxWebModuleState);
begin
if (FModuleState <> Value) then
begin
FModuleState := Value;
if (FWebDesigner <> nil) and (ModuleState <> msForm) then
FWebDesigner.PreviewShowing;
ModuleStateChanged;
end;
end;
procedure TcxWebModuleDesignWindow.ModuleStateChanged;
function IsSelected(AInstance: TPersistent): Boolean;
var
AList: IDesignerSelections;
begin
AList := TDesignerSelections.Create;
Designer.GetSelections(AList);
Result := (AList.Count = 1) and (AList.Items[0] = AInstance);
end;
function IsEmptySelection: Boolean;
var
AList: IDesignerSelections;
begin
AList := TDesignerSelections.Create;
Designer.GetSelections(AList);
Result := (AList.Count = 0);
end;
var
I: TcxWebModuleState;
begin
for I := Low(TcxWebModuleState) to High(TcxWebModuleState) do
FPanels[I].Visible := ModuleState = I;
if ModuleState = msHTMLResult then
{$IFDEF VCL}
Windows.SetFocus(FHTMLResultMemo.Handle);
{$ELSE}
QWidget_setFocus(FHTMLResultMemo.Handle);
{$ENDIF}
FButtons[ModuleState].Down := True;
if Designer <> nil then
if ModuleState = msForm then
begin
if IsEmptySelection or not IsSelected(Designer.Root) then
Designer.SelectComponent(Designer.Root);
end
else
Designer.NoSelection;
end;
procedure TcxWebModuleDesignWindow.EnableButtons(AEnabled: Boolean);
var
I: TcxWebModuleState;
begin
for I := Low(TcxWebModuleState) to High(TcxWebModuleState) do
FButtons[I].Enabled := AEnabled;
end;
procedure TcxWebModuleDesignWindow.btnFormClick(Sender: TObject);
begin
ModuleState := msForm;
end;
procedure TcxWebModuleDesignWindow.btnSourceClick(Sender: TObject);
procedure PrepareHTMLResultFont;
var
AFontName: string;
AFontSize: Integer;
begin
AFontName := FHTMLResultMemo.Font.Name;
AFontSize := FHTMLResultMemo.Font.Size;
if GetDelphiEditorFontInfo(AFontName, AFontSize) then
begin
FHTMLResultMemo.Font.Name := AFontName;
FHTMLResultMemo.Font.Size := AFontSize;
end;
end;
begin
EnableButtons(False);
try
{$IFDEF VCL}
if FWebBrowser.Busy then
FWebBrowser.NewDocument;
{$ENDIF}
ModuleState := msHTMLResult;
PrepareHTMLResultFont;
PrepareHTMLStrings;
finally
EnableButtons(True);
end;
end;
procedure TcxWebModuleDesignWindow.btnPreviewClick(Sender: TObject);
begin
EnableButtons(False);
ModuleState := msPreview;
PrepareHTMLFile;
EnableButtons(True);
end;
procedure TcxWebModuleDesignWindow.PrepareHTMLStrings;
begin
FHTMLResultMemo.Lines.Text := cxGetDesignWebContent(Designer);
end;
procedure TcxWebModuleDesignWindow.PrepareHTMLFile;
{$IFNDEF VCL}
var
PreviewFile: string;
{$ENDIF}
begin
if ModuleState <> msHTMLResult then
PrepareHTMLStrings;
{$IFDEF VCL}
FWebBrowser.DocumentHTML := FHTMLResultMemo.Lines.Text;
FWebBrowser.BaseURL := ExtractFilePath((BorlandIDEServices as IOTAModuleServices).CurrentModule.FileName);
{$ENDIF}
{$IFDEF LINUX}
PreviewFile := getenv('HOME') + '/.borland/preview';
FHTMLResultMemo.Lines.SaveToFile(PreviewFile);
FWebBrowser.Reload;
{$ENDIF}
end;
procedure TcxWebModuleDesignWindow.DoFindText(Sender: TObject);
var
SearchRes: Boolean;
{$IFDEF VCL}
Text: string;
SO: TStringSearchOptions;
MatchStr: PChar;
{$ELSE}
StartFrom: TCaretPos;
{$ENDIF}
begin
{$IFNDEF VCL}
StartFrom.Line := 0;
StartFrom.Col := 0;
{$ENDIF}
if (Sender is TMenuItem) and (TMenuItem(Sender).MenuIndex = 0) then
begin
if FFindDialog.Execute then
FMemoMenu.Items[1].Enabled := False;
{$IFDEF VCL}
Exit;
{$ENDIF}
end;
if FHTMLResultMemo.SelLength > 0 then
begin
{$IFNDEF VCL}
StartFrom.Line := FHTMLResultMemo.Selection.Line2;
StartFrom.Col := FHTMLResultMemo.Selection.Col2 + 1;
{$ENDIF}
end;
{$IFDEF VCL}
SO := [soDown];
if frMatchCase in FFindDialog.Options then
SO := SO + [soMatchCase];
if frWholeWord in FFindDialog.Options then
SO := SO + [soWholeWord];
Text := FHTMLResultMemo.Text;
MatchStr := SearchBuf(PChar(Text), Length(Text),
FHTMLResultMemo.SelStart, FHTMLResultMemo.SelLength, FFindDialog.FindText, SO);
SearchRes := MatchStr <> nil;
if SearchRes then
begin
FHTMLResultMemo.SelStart := MatchStr - PChar(Text);
FHTMLResultMemo.SelLength := Length(FFindDialog.FindText);
end;
{$ELSE}
SearchRes := FHTMLResultMemo.Search(FFindDialog.FindText,
frMatchCase in FFindDialog.Options, True,
frWholeWord in FFindDialog.Options, False,
StartFrom.Line, StartFrom.Col);
{$ENDIF}
if SearchRes then
FMemoMenu.Items[1].Enabled := True
else
MessageDlg({$IFNDEF VCL}'',{$ENDIF} 'Search string "' + FFindDialog.FindText + '" not found!',
mtInformation, [mbOk], 0);
end;
procedure TcxWebModuleDesignWindow.DoCopyText(Sender: TObject);
begin
FHTMLResultMemo.CopyToClipboard;
end;
procedure TcxWebModuleDesignWindow.DoSelectText(Sender: TObject);
begin
FHTMLResultMemo.SelectAll;
end;
procedure TcxWebModuleDesignWindow.DoOnPopup(Sender: TObject);
begin
FMemoMenu.Items[3].Enabled := (FHTMLResultMemo.SelLength > 0);
end;
{$IFDEF VCL}
procedure TcxWebModuleDesignWindow.DoFindClose(Sender: TObject);
begin
Windows.SetFocus(FHTMLResultMemo.Handle);
end;
{$ENDIF}
{$IFDEF LINUX}
{TcxMozillaBrowser}
constructor TcxMozillaBrowser.Create(AOwner: TcxWebModuleDesignWindow);
begin
inherited Create;
FOwner := AOwner;
FBrowserPID := 0;
end;
destructor TcxMozillaBrowser.Destroy;
begin
if FBrowserPID <> 0 then
kill(FBrowserPID, SIGTERM);
XIDMap.Remove(FOwner.FPanels[msPreview].Handle);
inherited;
end;
procedure TcxMozillaBrowser.StartMozilla;
const
BorMozPath = '/bin/mozilla/BorMozBrowser';
var
FArgv: array of PChar;
XID, Wnd: Integer;
Parent: TWidgetControl;
BrowserCmd: string;
begin
FBrowserPID := 0;
SetLength(FArgv, 8);
BrowserCmd := getenv('DELPHI') + BorMozPath;
if not FileExists(BrowserCmd) then Exit;
FArgv[0] := PChar(BrowserCmd);
Parent := FOwner.FPanels[msPreview];
Wnd := Integer(Parent.Handle);
XID := QWidget_winId(QWidgetH(Wnd));
FArgv[1] := PChar(IntToStr(XID)); // Host XID
FArgv[2] := PChar(IntToStr(Wnd)); // Host HWND
FArgv[3] := PChar(IntToStr(Parent.Left)); // Window x-coordinate
FArgv[4] := PChar(IntToStr(Parent.Top)); // Window y-coordinate
FArgv[5] := PChar(IntToStr(Parent.Height)); // Window height
FArgv[6] := PChar(IntToStr(Parent.Width)); // Window width
FArgv[7] := nil;
FBrowserPID := fork;
if FBrowserPID = 0 then
begin
execv(PChar(FArgv[0]), @FArgv[0]);
Exit;
end;
end;
procedure TcxMozillaBrowser.Reload;
begin
if (FBrowserPID = 0) or (kill(FBrowserPID, SIGUSR1) < 0) then
StartMozilla;
end;
{$ENDIF}
{$IFDEF LINUX}
initialization
XIDMap := TXIDMap.Create;
cxPrevEventFilter := Application.SetX11EventFilter(@cxMozillaEventFilter);
finalization
cxPrevEventFilter := Application.SetX11EventFilter(cxPrevEventFilter);
cxPrevEventFilter := nil;
FreeAndNil(XIDMap);
{$ENDIF}
end.