lazarus/designer/objinspext.pas
mattias 632f4c9629 IDE: use IDEMessageDialog
git-svn-id: trunk@44274 -
2014-02-27 10:15:06 +00:00

454 lines
14 KiB
ObjectPascal

{
*****************************************************************************
See the file COPYING.modifiedLGPL.txt, included in this distribution,
for details about the license.
*****************************************************************************
Author: Mattias Gaertner
Abstract:
Extension for the Object Inspector.
- Favorites properties
}
unit ObjInspExt;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, LCLProc, Forms, Controls, Buttons, StdCtrls, TypInfo,
ExtCtrls, Dialogs, Menus, ComCtrls, Grids, CustomTimer,
DirectoryCacher, CodeToolManager, CodeCache, PropEdits,
LazIDEIntf, ProjectIntf, ObjectInspector, OIFavoriteProperties,
DialogProcs, FileUtil, LazConf, BaseIDEIntf, IDEDialogs, LazConfigStorage,
LazarusIDEStrConsts;
type
{ TOIAddRemoveFavoriteDlg }
TOIAddRemoveFavoriteDlg = class(TForm)
NoteLabel: TLabel;
ClassCombobox: TComboBox;
OkButton: TButton;
CancelButton: TButton;
procedure OkButtonClick(Sender: TObject);
private
FAddMode: Boolean;
FObjectInspector: TObjectInspectorDlg;
FPropertyName: string;
procedure SetAddMode(const AValue: Boolean);
procedure SetObjectInspector(const AValue: TObjectInspectorDlg);
procedure UpdateLabel;
procedure UpdateComboBox;
procedure UpdateMode;
public
constructor Create(TheOwner: TComponent); override;
public
property ObjectInspector: TObjectInspectorDlg read FObjectInspector
write SetObjectInspector;
property PropertyName: string read FPropertyName;
property AddMode: Boolean read FAddMode write SetAddMode;
end;
const
DefaultOIFavoriteConfigFilename = 'objectinspectorfavorites.xml';
var
DefaultOIFavoriteProperties: TOIFavoriteProperties;
function ShowAddRemoveFavoriteDialog(ObjInspector: TObjectInspectorDlg;
Add: Boolean): TModalResult;
function CreateDefaultOIFavoriteProperties: TOIFavoriteProperties;
function LoadOIFavoriteProperties: TOIFavoriteProperties;
procedure SaveOIFavoriteProperties(Favorites: TOIFavoriteProperties);
function GetOIFavoriteConfigFilename: string;
function FindDeclarationOfOIProperty(AnInspector: TObjectInspectorDlg;
Row: TOIPropertyGridRow; out Code: TCodeBuffer; out Caret: TPoint;
out NewTopLine: integer): Boolean;
implementation
function CreateDefaultOIFavoriteProperties: TOIFavoriteProperties;
procedure Add(ABaseClass: TPersistentClass; const APropertyName: string);
begin
Result.Add(TOIFavoriteProperty.Create(ABaseClass,APropertyName,true));
end;
begin
Result:=TOIFavoriteProperties.Create;
// TControl
Add(TComponent,'Name');
Add(TComponent,'Caption');
Add(TControl,'Anchors');
Add(TControl,'AutoSize');
Add(TControl,'OnClick');
Add(TControl,'OnEditingDone');
// miscellaneous
Add(TCustomGroupBox,'Align');
Add(TCustomImage,'Align');
Add(TCustomButton,'ModalResult');
Add(TCustomLabel,'WordWrap');
Add(TCustomEdit,'Text');
Add(TCustomMemo,'Lines');
Add(TCustomMemo,'Align');
Add(TCustomMemo,'ScrollBars');
Add(TCustomCheckBox,'Checked');
Add(TCustomRadioGroup,'Items');
Add(TCustomRadioGroup,'ItemIndex');
Add(TCustomForm,'OnCreate');
Add(TCustomForm,'OnDestroy');
Add(TCustomForm,'OnResize');
Add(TCustomListBox,'Items');
Add(TCustomListBox,'Align');
Add(TCustomTreeView,'Align');
Add(TCustomTreeView,'Options');
Add(TCustomPanel,'Align');
Add(TMenuItem,'OnClick');
Add(TCustomSpeedButton,'GroupIndex');
Add(TCustomSpeedButton,'Glyph');
Add(TCustomImage,'Picture');
Add(TCustomImage,'Align');
Add(TCustomTabControl,'Align');
Add(TScrollBox,'Align');
Add(TCustomGrid,'Align');
Add(TCustomGrid,'Options');
Add(TCustomGrid,'Columns');
Add(TCustomGrid,'ColCount');
Add(TCustomTreeView,'Align');
Add(TCustomTreeView,'Options');
Add(TCustomTimer,'OnTimer');
Result.DeleteDoubles;
end;
function ShowAddRemoveFavoriteDialog(ObjInspector: TObjectInspectorDlg;
Add: Boolean): TModalResult;
var
OIAddRemoveFavoriteDlg: TOIAddRemoveFavoriteDlg;
begin
OIAddRemoveFavoriteDlg:=TOIAddRemoveFavoriteDlg.Create(nil);
OIAddRemoveFavoriteDlg.ObjectInspector:=ObjInspector;
OIAddRemoveFavoriteDlg.AddMode:=Add;
Result:=OIAddRemoveFavoriteDlg.ShowModal;
OIAddRemoveFavoriteDlg.Free;
end;
function LoadOIFavoriteProperties: TOIFavoriteProperties;
var
ConfigStore: TConfigStorage;
begin
Result:=DefaultOIFavoriteProperties.CreateCopy;
{$IFDEF DebugFavoriteroperties}
debugln('LoadOIFavoriteProperties A FileExistsUTF8(GetOIFavoriteConfigFilename)=',dbgs(FileExistsUTF8(GetOIFavoriteConfigFilename)));
Result.WriteDebugReport;
{$ENDIF}
if not FileExistsUTF8(GetOIFavoriteConfigFilename) then exit;
try
ConfigStore:=DefaultConfigClass.Create(GetOIFavoriteConfigFilename,true);
try
Result.MergeConfig(ConfigStore,'ObjectInspector/Favorites/');
Result.Modified:=false;
finally
ConfigStore.Free;
end;
except
on E: Exception do begin
debugln('Error: LoadOIFavoriteProperties: unable to read ',
GetOIFavoriteConfigFilename);
end;
end;
end;
procedure SaveOIFavoriteProperties(Favorites: TOIFavoriteProperties);
var
ConfigStore: TConfigStorage;
DefaultFavorites: TOIFavoriteProperties;
begin
{$IFDEF DebugFavoriteroperties}
debugln('SaveOIFavoriteProperties Favorites.Modified=',dbgs(Favorites.Modified),
' FileExistsUTF8(GetOIFavoriteConfigFilename)=',dbgs(FileExistsUTF8(GetOIFavoriteConfigFilename)));
{$ENDIF}
if (not Favorites.Modified) and FileExistsUTF8(GetOIFavoriteConfigFilename)
then
exit;
DefaultFavorites:=CreateDefaulTOIFavoriteProperties;
try
if DefaultFavorites.IsEqual(Favorites) then exit;
{$IFDEF DebugFavoriteroperties}
debugln('SaveOIFavoriteProperties is not default');
DefaultFavorites.WriteDebugReport;
Favorites.WriteDebugReport;
{$ENDIF}
try
ConfigStore:=DefaultConfigClass.Create(GetOIFavoriteConfigFilename,false);
try
Favorites.SaveNewItemsToConfig(ConfigStore,'ObjectInspector/Favorites/',
DefaultFavorites);
ConfigStore.WriteToDisk;
Favorites.Modified:=false;
finally
ConfigStore.Free;
end;
except
on E: Exception do begin
debugln('Error: LoadOIFavoriteProperties: unable to write ',
GetOIFavoriteConfigFilename);
end;
end;
finally
DefaultFavorites.Free;
end;
end;
function GetOIFavoriteConfigFilename: string;
begin
Result:=AppendPathDelim(GetPrimaryConfigPath)+DefaultOIFavoriteConfigFilename;
end;
function FindDeclarationOfOIProperty(AnInspector: TObjectInspectorDlg;
Row: TOIPropertyGridRow; out Code: TCodeBuffer; out Caret: TPoint;
out NewTopLine: integer): Boolean;
var
PropPath: String;
LookupRoot: TPersistent;
AFile: TLazProjectFile;
NewCode: TCodeBuffer;
NewX, NewY: integer;
APersistent: TPersistent;
AnUnitName: String;
InFilename: String;
FilenameOfClass: string;
begin
Result:=false;
Code:=nil;
Caret:=Point(0,0);
// check Row
if AnInspector=nil then begin
DebugLn('FindDeclarationOfOIProperty AnInspector=nil');
exit;
end;
if Row=nil then
Row:=AnInspector.GetActivePropertyRow;
if Row=nil then begin
DebugLn('FindDeclarationOfOIProperty Row=nil');
exit;
end;
if Row.Editor=nil then begin
DebugLn('FindDeclarationOfOIProperty Row.Editor=nil Row=',Row.Name);
exit;
end;
// get first instance of property
APersistent:=Row.Editor.GetComponent(0);
if APersistent=nil then begin
DebugLn('FindDeclarationOfOIProperty APersistent=nil Row=',Row.Name);
exit;
end;
// get unit name of first instance
AnUnitName:=GetClassUnitName(APersistent.ClassType);
if AnUnitName='' then begin
DebugLn('FindDeclarationOfOIProperty no RTTI unit found for APersistent.ClassType=',DbgSName(APersistent.ClassType));
exit;
end;
// get lookup root
if Row.Editor.PropertyHook=nil then begin
debugln(['FindDeclarationOfOIProperty Row.Editor.PropertyHook=nil Row=',Row.Name]);
exit;
end;
LookupRoot:=Row.Editor.PropertyHook.LookupRoot;
if LookupRoot=nil then begin
debugln(['FindDeclarationOfOIProperty Row.Editor.PropertyHook.LookupRoot=nil Row=',Row.Name]);
exit;
end;
// get file of lookup root
AFile:=LazarusIDE.GetProjectFileWithRootComponent(TComponent(LookupRoot));
if AFile=nil then begin
DebugLn('FindDeclarationOfOIProperty AFile=nil Row=',Row.Name,' LookupRoot=',DbgSName(LookupRoot));
exit;
end;
InFilename:='';
FilenameOfClass:=CodeToolBoss.DirectoryCachePool.FindUnitSourceInCompletePath(
ExtractFilePath(AFile.Filename),AnUnitName,InFilename);
if FilenameOfClass='' then begin
debugln(['FindDeclarationOfOIProperty Row=',Row.Name,' Instance=',DbgSName(APersistent),' LookupRoot=',DbgSName(LookupRoot),' Unit not found: ',AnUnitName,' started search in directory of lookuproot: ',AFile.Filename]);
exit;
end;
if not LazarusIDE.BeginCodeTools then begin
DebugLn('FindDeclarationOfOIProperty LazarusIDE.BeginCodeTools failed');
exit;
end;
Code:=nil;
if LoadCodeBuffer(Code,FilenameOfClass,[],false)<>mrOk then begin
debugln(['FindDeclarationOfOIProperty LoadCodeBuffer failed of ',FilenameOfClass]);
exit;
end;
// find the property declaration
PropPath:=APersistent.ClassName+'.'+Row.Name;
if Row.Editor is TNestedPropertyEditor then begin
if Row.Parent=nil then begin
debugln(['FindDeclarationOfOIProperty missing parent row ',PropPath,' in unit ',Code.Filename,' Row.Editor=',DbgSName(Row.Editor)]);
exit;
end;
PropPath:=APersistent.ClassName+'.'+Row.Parent.Name+'.'+Row.Name;
end;
if not CodeToolBoss.FindDeclarationOfPropertyPath(Code,PropPath,NewCode,
NewX,NewY,NewTopLine) then
begin
debugln(['FindDeclarationOfOIProperty failed to find property ',PropPath,' in unit ',Code.Filename]);
exit;
end;
Code:=NewCode;
Caret:=Point(NewX,NewY);
//DebugLn('FindDeclarationOfOIProperty SUCCESS ',Code.Filename,' ',dbgs(Caret));
Result:=true;
end;
{ TOIAddRemoveFavoriteDlg }
procedure TOIAddRemoveFavoriteDlg.OkButtonClick(Sender: TObject);
var
NewClassName: String;
CurClass: TClass;
NewFavorite: TOIFavoriteProperty;
begin
NewClassName:=ClassCombobox.Text;
if (ObjectInspector<>nil) and (ObjectInspector.Selection<>nil)
and (ObjectInspector.Selection.Count>0) then begin
CurClass:=ObjectInspector.Selection[0].ClassType;
while CurClass.InheritsFrom(TPersistent) do begin
if CompareText(NewClassName,CurClass.ClassName)=0 then begin
NewFavorite:=TOIFavoriteProperty.Create(TPersistentClass(CurClass),
PropertyName,AddMode);
ObjectInspector.Favorites.DeleteConstraints(NewFavorite);
ObjectInspector.Favorites.Add(NewFavorite);
ObjectInspector.FavoriteGrid.BuildPropertyList;
ModalResult:=mrOk;
exit;
end;
CurClass:=CurClass.ClassParent;
end;
end;
IDEMessageDialog(lisClassNotFound, Format(lisOIFClassNotFound, ['"', NewClassName,
'"']), mtError,
[mbOk]);
end;
procedure TOIAddRemoveFavoriteDlg.SetObjectInspector(const AValue: TObjectInspectorDlg);
var
CurRow: TOIPropertyGridRow;
begin
if FObjectInspector=AValue then exit;
FObjectInspector:=AValue;
CurRow:=ObjectInspector.GetActivePropertyRow;
if (CurRow<>nil) and (CurRow.Editor<>nil) then
FPropertyName:=CurRow.Editor.GetName;
UpdateLabel;
UpdateComboBox;
end;
procedure TOIAddRemoveFavoriteDlg.SetAddMode(const AValue: Boolean);
begin
if FAddMode=AValue then exit;
FAddMode:=AValue;
UpdateMode;
end;
procedure TOIAddRemoveFavoriteDlg.UpdateLabel;
begin
NoteLabel.Caption:=Format(lisOIFChooseABaseClassForTheFavoriteProperty, [
'"', PropertyName, '"']);
end;
procedure TOIAddRemoveFavoriteDlg.UpdateComboBox;
var
CurClass: TClass;
NewItems: TStringList;
begin
NewItems:=TStringList.Create;
if (ObjectInspector<>nil) and (ObjectInspector.Selection<>nil)
and (ObjectInspector.Selection.Count>0) then begin
CurClass:=ObjectInspector.Selection[0].ClassType;
// add only classes, that are TPersistent and have a registered class
while CurClass.InheritsFrom(TPersistent) do begin
// add only registered classes
if GetClass(CurClass.ClassName)<>nil then
NewItems.Add(CurClass.ClassName);
CurClass:=CurClass.ClassParent;
end;
end;
ClassCombobox.Items.Assign(NewItems);
if ClassCombobox.Items.Count>0 then
ClassCombobox.ItemIndex:=0;
NewItems.Free;
end;
procedure TOIAddRemoveFavoriteDlg.UpdateMode;
begin
if AddMode then begin
Caption:=lisOIFAddToFavoriteProperties;
OkButton.Caption:=lisAdd;
end else begin
Caption:=lisOIFRemoveFromFavoriteProperties;
OkButton.Caption:=lisRemove;
end;
end;
constructor TOIAddRemoveFavoriteDlg.Create(TheOwner: TComponent);
begin
inherited CreateNew(TheOwner);
Name:='OIAddToFavoriteDlg';
Width:=300;
Height:=150;
Position:=poScreenCenter;
NoteLabel:=TLabel.Create(Self);
with NoteLabel do begin
Name:='NoteLabel';
SetBounds(5,5,Self.ClientWidth-10,50);
WordWrap:=true;
Parent:=Self;
end;
ClassCombobox:=TComboBox.Create(Self);
with ClassCombobox do begin
Name:='ClassCombobox';
SetBounds(5,60,200,Height);
Parent:=Self;
end;
OkButton:=TButton.Create(Self);
with OkButton do begin
Name:='AddButton';
SetBounds(5,100,80,25);
Caption:=lisAdd;
Parent:=Self;
OnClick:=@OkButtonClick;
end;
DefaultControl:=OkButton;
CancelButton:=TButton.Create(Self);
with CancelButton do begin
Name:='CancelButton';
SetBounds(120,100,80,25);
Caption:=lisCancel;
Parent:=Self;
ModalResult:=mrCancel;
end;
CancelControl:=CancelButton;
UpdateMode;
end;
initialization
DefaultOIFavoriteProperties:=CreateDefaultOIFavoriteProperties;
finalization
FreeAndNil(DefaultOIFavoriteProperties)
end.