mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-05-11 11:42:32 +02:00
392 lines
11 KiB
ObjectPascal
392 lines
11 KiB
ObjectPascal
{
|
|
*****************************************************************************
|
|
See the file COPYING.modifiedLGPL.txt, included in this distribution,
|
|
for details about the license.
|
|
*****************************************************************************
|
|
|
|
Author: Mattias Gaertner
|
|
|
|
Abstract:
|
|
Installs a HTML control in the IDE using TIpHtmlPanel.
|
|
}
|
|
unit IPIDEHTMLControl;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, LCLProc, Forms, Graphics, Controls, Dialogs, ExtCtrls, Menus,
|
|
IpMsg, Ipfilebroker, IpHtml, IDEHelpIntf, LazHelpIntf, LazIDEIntf;
|
|
|
|
type
|
|
TLazIPHtmlControl = class;
|
|
|
|
{ TLazIpHtmlDataProvider }
|
|
|
|
TLazIpHtmlDataProvider = class(TIpHtmlDataProvider)
|
|
private
|
|
FControl: TLazIPHtmlControl;
|
|
protected
|
|
function DoGetStream(const URL: string): TStream; override;
|
|
public
|
|
property Control: TLazIPHtmlControl read FControl;
|
|
end;
|
|
|
|
{ TLazIPHtmlControl }
|
|
|
|
TLazIPHtmlControl = class(TCustomPanel,TIDEHTMLControlIntf)
|
|
function DataProviderCanHandle(Sender: TObject; const {%H-}URL: string): Boolean;
|
|
procedure DataProviderCheckURL(Sender: TObject; const {%H-}URL: string;
|
|
var Available: Boolean; var ContentType: string);
|
|
procedure DataProviderGetHtml(Sender: TObject; const {%H-}URL: string;
|
|
const {%H-}aPostData: TIpFormDataEntity; var Stream: TStream);
|
|
procedure DataProviderGetImage(Sender: TIpHtmlNode; const URL: string;
|
|
var Picture: TPicture);
|
|
procedure DataProviderLeave(Sender: TIpHtml);
|
|
procedure DataProviderReportReference(Sender: TObject; const {%H-}URL: string);
|
|
procedure IPHTMLPanelHotClick(Sender: TObject);
|
|
private
|
|
FIDEProvider: TAbstractIDEHTMLProvider;
|
|
FIPHTMLPanel: TIpHtmlPanel;
|
|
FURL: string;
|
|
procedure SetIDEProvider(const AValue: TAbstractIDEHTMLProvider);
|
|
protected
|
|
procedure Notification(AComponent: TComponent; Operation: TOperation);
|
|
override;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
function GetURL: string;
|
|
procedure SetURL(const AValue: string);
|
|
property IDEProvider: TAbstractIDEHTMLProvider read FIDEProvider write SetIDEProvider;
|
|
procedure SetHTMLContent(Stream: TStream; const NewURL: string);
|
|
procedure GetPreferredControlSize(out AWidth, AHeight: integer);
|
|
property IPHTMLPanel: TIpHtmlPanel read FIPHTMLPanel;
|
|
end;
|
|
|
|
{ TLazIPHtmlControlClipboardPopup }
|
|
|
|
TLazIPHtmlControlClipboardPopup = class(TPopupMenu)
|
|
private
|
|
FCopy, FSelectAll: TMenuItem;
|
|
FPanel: TLazIPHtmlControl;
|
|
procedure DoCopy(Sender: TObject);
|
|
procedure DoSelectAll(Sender: TObject);
|
|
protected
|
|
procedure DoPopup(Sender: TObject); override;
|
|
public
|
|
constructor Create(AOwner: TComponent; APanel: TLazIPHtmlControl); reintroduce;
|
|
end;
|
|
|
|
function IPCreateLazIDEHTMLControl(Owner: TComponent;
|
|
var Provider: TAbstractIDEHTMLProvider;
|
|
{%H-}Flags: TIDEHTMLControlFlags = []): TControl;
|
|
|
|
procedure Register;
|
|
|
|
implementation
|
|
|
|
resourcestring
|
|
ipdCopy = '&Copy';
|
|
ipdSelectAll = 'Select &all';
|
|
|
|
procedure Register;
|
|
begin
|
|
CreateIDEHTMLControl:=@IPCreateLazIDEHTMLControl;
|
|
end;
|
|
|
|
function IPCreateLazIDEHTMLControl(Owner: TComponent;
|
|
var Provider: TAbstractIDEHTMLProvider;
|
|
Flags: TIDEHTMLControlFlags = []): TControl;
|
|
var
|
|
HTMLControl: TLazIPHtmlControl;
|
|
begin
|
|
//debugln(['IPCreateLazIDEHTMLControl ']);
|
|
HTMLControl:=TLazIPHtmlControl.Create(Owner);
|
|
Result:=HTMLControl;
|
|
if Provider=nil then
|
|
Provider:=CreateIDEHTMLProvider(HTMLControl);
|
|
//debugln(['IPCreateLazIDEHTMLControl Provider=',DbgSName(Provider)]);
|
|
HTMLControl.IDEProvider:=Provider;
|
|
|
|
if ihcWithClipboardMenu in Flags then
|
|
TLazIPHtmlControlClipboardPopup.Create(Owner, HTMLControl);
|
|
end;
|
|
|
|
{ TLazIPHtmlControlClipboardPopup }
|
|
|
|
procedure TLazIPHtmlControlClipboardPopup.DoCopy(Sender: TObject);
|
|
begin
|
|
if FPanel.IPHTMLPanel <> nil then
|
|
FPanel.IPHTMLPanel.CopyToClipboard;
|
|
end;
|
|
|
|
procedure TLazIPHtmlControlClipboardPopup.DoSelectAll(Sender: TObject);
|
|
begin
|
|
if FPanel.IPHTMLPanel <> nil then
|
|
FPanel.IPHTMLPanel.SelectAll;
|
|
end;
|
|
|
|
procedure TLazIPHtmlControlClipboardPopup.DoPopup(Sender: TObject);
|
|
begin
|
|
if FPanel.IPHTMLPanel <> nil then
|
|
FCopy.Enabled := FPanel.IPHTMLPanel.HaveSelection;
|
|
inherited DoPopup(Sender);
|
|
end;
|
|
|
|
constructor TLazIPHtmlControlClipboardPopup.Create(AOwner: TComponent;
|
|
APanel: TLazIPHtmlControl);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FPanel := APanel;
|
|
AutoPopup := True;
|
|
|
|
FCopy := TMenuItem.Create(Owner);
|
|
FCopy.Caption := ipdCopy;
|
|
FCopy.ShortCut := ShortCut(ord('C'), [ssCtrl]);
|
|
FCopy.OnClick := @DoCopy;
|
|
Items.Add(FCopy);
|
|
|
|
FSelectAll := TMenuItem.Create(Owner);
|
|
FSelectAll.Caption := ipdSelectAll;
|
|
FSelectAll.ShortCut := ShortCut(ord('A'), [ssCtrl]);
|
|
FSelectAll.OnClick := @DoSelectAll;
|
|
Items.Add(FSelectAll);
|
|
|
|
TControl(Owner).PopupMenu := Self;
|
|
end;
|
|
|
|
{ TLazIpHtmlDataProvider }
|
|
|
|
function TLazIpHtmlDataProvider.DoGetStream(const URL: string): TStream;
|
|
begin
|
|
//debugln(['TLazIpHtmlDataProvider.DoGetStream ',URL,' ',DbgSName(Control.IDEProvider)]);
|
|
Result:=Control.IDEProvider.GetStream(URL,false);
|
|
end;
|
|
|
|
{ TLazIPHtmlControl }
|
|
|
|
function TLazIPHtmlControl.DataProviderCanHandle(Sender: TObject;
|
|
const URL: string): Boolean;
|
|
begin
|
|
//debugln(['TLazIPHtmlControl.DataProviderCanHandle URL=',URL]);
|
|
Result:=false;
|
|
end;
|
|
|
|
procedure TLazIPHtmlControl.DataProviderCheckURL(Sender: TObject;
|
|
const URL: string; var Available: Boolean; var ContentType: string);
|
|
begin
|
|
//debugln(['TLazIPHtmlControl.DataProviderCheckURL URL=',URL]);
|
|
Available:=false;
|
|
ContentType:='';
|
|
end;
|
|
|
|
procedure TLazIPHtmlControl.DataProviderGetHtml(Sender: TObject;
|
|
const URL: string; const aPostData: TIpFormDataEntity; var Stream: TStream);
|
|
begin
|
|
//debugln(['TLazIPHtmlControl.DataProviderGetHtml URL=',URL]);
|
|
Stream:=nil;
|
|
end;
|
|
|
|
procedure TLazIPHtmlControl.DataProviderGetImage(Sender: TIpHtmlNode;
|
|
const URL: string; var Picture: TPicture);
|
|
var
|
|
URLType: string;
|
|
URLPath: string;
|
|
URLParams: string;
|
|
Filename: String;
|
|
Ext: String;
|
|
Stream: TStream;
|
|
NewURL: String;
|
|
begin
|
|
//DebugLn(['TIPLazHtmlControl.HTMLGetImageX URL=',URL]);
|
|
if IDEProvider=nil then exit;
|
|
NewURL:=IDEProvider.MakeURLAbsolute(IDEProvider.BaseURL,URL);
|
|
//DebugLn(['TIPLazHtmlControl.HTMLGetImageX NewURL=',NewURL,' Provider.BaseURL=',IDEProvider.BaseURL,' URL=',URL]);
|
|
|
|
Picture:=nil;
|
|
Stream:=nil;
|
|
try
|
|
try
|
|
SplitURL(NewURL,URLType,URLPath,URLParams);
|
|
if URLPath='' then
|
|
URLPath:=NewURL;
|
|
Filename:=URLPathToFilename(URLPath);
|
|
Ext:=ExtractFileExt(Filename);
|
|
//DebugLn(['TIPLazHtmlControl.HTMLGetImageX URLPath=',URLPath,' Filename=',Filename,' Ext=',Ext]);
|
|
Picture:=TPicture.Create;
|
|
// quick check if file format is supported (raises an exception)
|
|
Picture.FindGraphicClassWithFileExt(Ext);
|
|
// get stream
|
|
Stream:=IDEProvider.GetStream(NewURL,true);
|
|
// load picture
|
|
Picture.LoadFromStreamWithFileExt(Stream,Ext);
|
|
finally
|
|
if Stream<>nil then
|
|
IDEProvider.ReleaseStream(NewURL);
|
|
end;
|
|
except
|
|
on E: Exception do begin
|
|
FreeAndNil(Picture);
|
|
DebugLn(['TIPLazHtmlControl.HTMLGetImageX ERROR: ',E.Message]);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TLazIPHtmlControl.DataProviderLeave(Sender: TIpHtml);
|
|
begin
|
|
//debugln(['TLazIPHtmlControl.DataProviderLeave ']);
|
|
end;
|
|
|
|
procedure TLazIPHtmlControl.DataProviderReportReference(Sender: TObject;
|
|
const URL: string);
|
|
begin
|
|
//debugln(['TLazIPHtmlControl.DataProviderReportReference URL=',URL]);
|
|
end;
|
|
|
|
procedure TLazIPHtmlControl.IPHTMLPanelHotClick(Sender: TObject);
|
|
var
|
|
HotNode: TIpHtmlNode;
|
|
HRef: String;
|
|
//Target: String;
|
|
begin
|
|
HotNode:=FIPHTMLPanel.HotNode;
|
|
if HotNode is TIpHtmlNodeA then begin
|
|
HRef := TIpHtmlNodeA(HotNode).HRef;
|
|
//Target := TIpHtmlNodeA(HotNode).Target;
|
|
end else begin
|
|
HRef := TIpHtmlNodeAREA(HotNode).HRef;
|
|
//Target := TIpHtmlNodeAREA(HotNode).Target;
|
|
end;
|
|
//debugln(['TLazIPHtmlControl.IPHTMLPanelHotClick HRef="',HRef,'" Target="',Target,'"']);
|
|
IDEProvider.OpenURLAsync(HRef);
|
|
end;
|
|
|
|
procedure TLazIPHtmlControl.SetIDEProvider(
|
|
const AValue: TAbstractIDEHTMLProvider);
|
|
begin
|
|
if FIDEProvider=AValue then exit;
|
|
//debugln(['TLazIPHtmlControl.SetIDEProvider Old=',DbgSName(FIDEProvider),' New=',DbgSName(FIDEProvider)]);
|
|
if FIDEProvider<>nil then begin
|
|
IDEProvider.ControlIntf:=nil;
|
|
end;
|
|
FIDEProvider:=AValue;
|
|
if FIDEProvider<>nil then begin
|
|
FreeNotification(FIDEProvider);
|
|
IDEProvider.ControlIntf:=Self;
|
|
end;
|
|
end;
|
|
|
|
procedure TLazIPHtmlControl.Notification(AComponent: TComponent;
|
|
Operation: TOperation);
|
|
begin
|
|
inherited Notification(AComponent, Operation);
|
|
if Operation=opRemove then begin
|
|
if IDEProvider=AComponent then begin
|
|
if IDEProvider.ControlIntf=TIDEHTMLControlIntf(Self) then
|
|
IDEProvider.ControlIntf:=nil;
|
|
IDEProvider:=nil;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
constructor TLazIPHtmlControl.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FIPHTMLPanel:=TIpHtmlPanel.Create(Self);
|
|
with FIPHTMLPanel do begin
|
|
Name:='TLazIPHtmlControl_IPHTMLPanel';
|
|
Align:=alClient;
|
|
DefaultFontSize:=8;
|
|
MarginHeight:=2;
|
|
MarginWidth:=2;
|
|
Parent:=Self;
|
|
WantTabs := False;
|
|
OnHotClick:=@IPHTMLPanelHotClick;
|
|
end;
|
|
FIPHTMLPanel.DataProvider:=TLazIpHtmlDataProvider.Create(FIPHTMLPanel);
|
|
with TLazIpHtmlDataProvider(FIPHTMLPanel.DataProvider) do begin
|
|
FControl:=Self;
|
|
Name:='TLazIPHtmlControl_DataProvider';
|
|
OnCanHandle:=@DataProviderCanHandle;
|
|
OnGetHtml:=@DataProviderGetHtml;
|
|
OnGetImage:=@DataProviderGetImage;
|
|
OnLeave:=@DataProviderLeave;
|
|
OnCheckURL:=@DataProviderCheckURL;
|
|
OnReportReference:=@DataProviderReportReference;
|
|
end;
|
|
Caption:='';
|
|
BevelInner:=bvLowered;
|
|
end;
|
|
|
|
destructor TLazIPHtmlControl.Destroy;
|
|
begin
|
|
//debugln(['TLazIPHtmlControl.Destroy ',DbgSName(Self),' ',dbgs(Pointer(Self))]);
|
|
FreeAndNil(FIDEProvider);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TLazIPHtmlControl.GetURL: string;
|
|
begin
|
|
Result:=FURL;
|
|
end;
|
|
|
|
procedure TLazIPHtmlControl.SetURL(const AValue: string);
|
|
var
|
|
Stream: TStream;
|
|
NewHTML: TIpHtml;
|
|
NewURL: String;
|
|
begin
|
|
if IDEProvider=nil then raise Exception.Create('TIPLazHtmlControl.SetURL missing Provider');
|
|
if FURL=AValue then exit;
|
|
NewURL:=IDEProvider.MakeURLAbsolute(IDEProvider.BaseURL,AValue);
|
|
if FURL=NewURL then exit;
|
|
FURL:=NewURL;
|
|
try
|
|
Stream:=IDEProvider.GetStream(FURL,true);
|
|
try
|
|
NewHTML:=TIpHtml.Create; // Beware: Will be freed automatically TIpHtmlPanel
|
|
FIPHTMLPanel.SetHtml(NewHTML);
|
|
NewHTML.LoadFromStream(Stream);
|
|
finally
|
|
IDEProvider.ReleaseStream(FURL);
|
|
end;
|
|
except
|
|
on E: Exception do begin
|
|
MessageDlg('Unable to open HTML file',
|
|
'URL: '+FURL+#13
|
|
+'Error: '+E.Message,mtError,[mbCancel],0);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TLazIPHtmlControl.SetHTMLContent(Stream: TStream; const NewURL: string
|
|
);
|
|
var
|
|
NewHTML: TIpHtml;
|
|
begin
|
|
FURL:=NewURL;
|
|
try
|
|
NewHTML:=TIpHtml.Create; // Beware: Will be freed automatically TIpHtmlPanel
|
|
FIPHTMLPanel.SetHtml(NewHTML);
|
|
NewHTML.LoadFromStream(Stream);
|
|
except
|
|
on E: Exception do begin
|
|
MessageDlg('Unable to load HTML stream',
|
|
'URL: '+FURL+#13
|
|
+'Error: '+E.Message,mtError,[mbCancel],0);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TLazIPHtmlControl.GetPreferredControlSize(out AWidth, AHeight: integer);
|
|
begin
|
|
AWidth:=0;
|
|
AHeight:=0;
|
|
inherited GetPreferredSize(AWidth, AHeight);
|
|
end;
|
|
|
|
end.
|
|
|