mirror of https://gitlab.com/basile.b/dexed.git
861 lines
24 KiB
Plaintext
861 lines
24 KiB
Plaintext
unit ce_symlist;
|
|
|
|
{$I ce_defines.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, TreeFilterEdit, Forms, Controls, Graphics, ExtCtrls, Menus,
|
|
ComCtrls, ce_widget, jsonparser, process, actnlist, Buttons, Clipbrd, LCLProc,
|
|
ce_common, ce_observer, ce_synmemo, ce_interfaces, ce_writableComponent,
|
|
ce_processes, ce_sharedres;
|
|
|
|
type
|
|
|
|
// Enumerates the possible symbol kind. To be kept in sync with the tool declaration.
|
|
TSymbolType = (
|
|
_alias,
|
|
_class,
|
|
_enum,
|
|
_error,
|
|
_function,
|
|
_interface,
|
|
_import,
|
|
_mixin,
|
|
_struct,
|
|
_template,
|
|
_union,
|
|
_unittest,
|
|
_variable,
|
|
_warning
|
|
);
|
|
|
|
TSymbolCollection = class;
|
|
|
|
// Encapsulates a symbol to enable structured serialization
|
|
TSymbol = class(TCollectionItem)
|
|
private
|
|
fline, fCol: nativeUint;
|
|
fName: string;
|
|
fType: TSymbolType;
|
|
fSubs: TSymbolCollection;
|
|
procedure setSubs(aValue: TSymbolCollection);
|
|
published
|
|
property line: nativeUint read fline write fLine;
|
|
property col: nativeUint read fCol write fCol;
|
|
property name: string read fName write fName;
|
|
property symType: TSymbolType read fType write fType;
|
|
property subs: TSymbolCollection read fSubs write setSubs;
|
|
public
|
|
constructor Create(ACollection: TCollection); override;
|
|
destructor destroy; override;
|
|
end;
|
|
|
|
// Encapsulates a the sub symbols.
|
|
TSymbolCollection = class(TCollection)
|
|
private
|
|
function getSub(index: Integer): TSymbol;
|
|
public
|
|
constructor create;
|
|
property sub[index: Integer]: TSymbol read getSub; default;
|
|
end;
|
|
|
|
// Serializable symbol list
|
|
TSymbolList = class(TComponent)
|
|
private
|
|
fSymbols: TSymbolCollection;
|
|
procedure setSymbols(aValue: TSymbolCollection);
|
|
published
|
|
property symbols: TSymbolCollection read fSymbols write setSymbols;
|
|
public
|
|
constructor create(aOwner: TCOmponent); override;
|
|
destructor destroy; override;
|
|
//
|
|
procedure LoadFromTool(str: TStream);
|
|
end;
|
|
|
|
TCESymbolListOptions = class(TWritableLfmTextComponent)
|
|
private
|
|
fAutoRefresh: boolean;
|
|
fRefreshOnChange: boolean;
|
|
fRefreshOnFocus: boolean;
|
|
fShowChildCategories: boolean;
|
|
fAutoRefreshDelay: Integer;
|
|
fSmartFilter: boolean;
|
|
fAutoExpandErrors: boolean;
|
|
fSmartExpander: boolean;
|
|
fSortSymbols: boolean;
|
|
fDeep: boolean;
|
|
published
|
|
property autoRefresh: boolean read fAutoRefresh write fAutoRefresh;
|
|
property refreshOnChange: boolean read fRefreshOnChange write fRefreshOnChange;
|
|
property refreshOnFocus: boolean read fRefreshOnFocus write fRefreshOnFocus;
|
|
property showChildCategories: boolean read fShowChildCategories write fShowChildCategories;
|
|
property autoRefreshDelay: Integer read fAutoRefreshDelay write fAutoRefreshDelay;
|
|
property smartFilter: boolean read fSmartFilter write fSmartFilter;
|
|
property autoExpandErrors: boolean read fAutoExpandErrors write fAutoExpandErrors;
|
|
property sortSymbols: boolean read fSortSymbols write fSortSymbols;
|
|
property smartExpander: boolean read fSmartExpander write fSmartExpander;
|
|
property deep: boolean read fDeep write fDeep default true;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
procedure Assign(Source: TPersistent); override;
|
|
procedure AssignTo(Dest: TPersistent); override;
|
|
end;
|
|
|
|
{ TCESymbolListWidget }
|
|
|
|
TCESymbolListWidget = class(TCEWidget, ICEMultiDocObserver, ICEEditableOptions)
|
|
btnRefresh: TBitBtn;
|
|
imgList: TImageList;
|
|
Panel1: TPanel;
|
|
Tree: TTreeView;
|
|
TreeFilterEdit1: TTreeFilterEdit;
|
|
procedure btnRefreshClick(Sender: TObject);
|
|
procedure TreeCompare(Sender: TObject; Node1, Node2: TTreeNode; var Compare: Integer);
|
|
procedure TreeFilterEdit1AfterFilter(Sender: TObject);
|
|
function TreeFilterEdit1FilterItem(Item: TObject; out Done: Boolean): Boolean;
|
|
procedure TreeFilterEdit1MouseEnter(Sender: TObject);
|
|
procedure TreeKeyPress(Sender: TObject; var Key: char);
|
|
private
|
|
fHasToolExe: boolean;
|
|
fToolExeName: string;
|
|
fOptions: TCESymbolListOptions;
|
|
fSyms: TSymbolList;
|
|
fMsgs: ICEMessagesDisplay;
|
|
fToolProc: TCEProcess;
|
|
fActCopyIdent: TAction;
|
|
fActRefresh: TAction;
|
|
fActRefreshOnChange: TAction;
|
|
fActRefreshOnFocus: TAction;
|
|
fActAutoRefresh: TAction;
|
|
fActSelectInSource: TAction;
|
|
fDoc: TCESynMemo;
|
|
fAutoRefresh: boolean;
|
|
fRefreshOnChange: boolean;
|
|
fRefreshOnFocus: boolean;
|
|
fDeep: boolean;
|
|
fShowChildCategories: boolean;
|
|
fSmartFilter: boolean;
|
|
fAutoExpandErrors: boolean;
|
|
fSortSymbols: boolean;
|
|
fSmartExpander: boolean;
|
|
ndAlias, ndClass, ndEnum, ndFunc, ndUni: TTreeNode;
|
|
ndImp, ndIntf, ndMix, ndStruct, ndTmp: TTreeNode;
|
|
ndVar, ndWarn, ndErr, ndUt: TTreeNode;
|
|
procedure TreeDblClick(Sender: TObject);
|
|
procedure actRefreshExecute(Sender: TObject);
|
|
procedure actAutoRefreshExecute(Sender: TObject);
|
|
procedure actRefreshOnChangeExecute(Sender: TObject);
|
|
procedure actRefreshOnFocusExecute(Sender: TObject);
|
|
procedure actCopyIdentExecute(Sender: TObject);
|
|
procedure updateVisibleCat;
|
|
procedure clearTree;
|
|
procedure smartExpand;
|
|
//
|
|
procedure checkIfHasToolExe;
|
|
procedure callToolProc;
|
|
procedure toolTerminated(sender: TObject);
|
|
//
|
|
procedure docNew(aDoc: TCESynMemo);
|
|
procedure docClosing(aDoc: TCESynMemo);
|
|
procedure docFocused(aDoc: TCESynMemo);
|
|
procedure docChanged(aDoc: TCESynMemo);
|
|
//
|
|
function optionedWantCategory(): string;
|
|
function optionedWantEditorKind: TOptionEditorKind;
|
|
function optionedWantContainer: TPersistent;
|
|
procedure optionedEvent(anEvent: TOptionEditorEvent);
|
|
function optionedOptionsModified: boolean;
|
|
protected
|
|
procedure updateDelayed; override;
|
|
//
|
|
function contextName: string; override;
|
|
function contextActionCount: integer; override;
|
|
function contextAction(index: integer): TAction; override;
|
|
//
|
|
procedure SetVisible(Value: boolean); override;
|
|
published
|
|
property autoRefresh: boolean read fAutoRefresh write fAutoRefresh;
|
|
property refreshOnChange: boolean read fRefreshOnChange write fRefreshOnChange;
|
|
property refreshOnFocus: boolean read fRefreshOnFocus write fRefreshOnFocus;
|
|
public
|
|
constructor create(aOwner: TComponent); override;
|
|
destructor destroy; override;
|
|
end;
|
|
|
|
implementation
|
|
{$R *.lfm}
|
|
|
|
const
|
|
OptsFname = 'symbollist.txt';
|
|
toolExeName = 'cesyms' + exeExt;
|
|
|
|
{$REGION Serializable symbols---------------------------------------------------}
|
|
constructor TSymbol.create(ACollection: TCollection);
|
|
begin
|
|
inherited create(ACollection);
|
|
fSubs := TSymbolCollection.create;
|
|
end;
|
|
|
|
destructor TSymbol.destroy;
|
|
begin
|
|
fSubs.Free;
|
|
inherited;
|
|
end;
|
|
|
|
procedure TSymbol.setSubs(aValue: TSymbolCollection);
|
|
begin
|
|
fSubs.Assign(aValue);
|
|
end;
|
|
|
|
constructor TSymbolCollection.create;
|
|
begin
|
|
inherited create(TSymbol);
|
|
end;
|
|
|
|
function TSymbolCollection.getSub(index: Integer): TSymbol;
|
|
begin
|
|
exit(TSymbol(self.Items[index]));
|
|
end;
|
|
|
|
constructor TSymbolList.create(aOwner: TCOmponent);
|
|
begin
|
|
inherited;
|
|
fSymbols := TSymbolCollection.create;
|
|
end;
|
|
|
|
destructor TSymbolList.destroy;
|
|
begin
|
|
fSymbols.free;
|
|
inherited;
|
|
end;
|
|
|
|
procedure TSymbolList.setSymbols(aValue: TSymbolCollection);
|
|
begin
|
|
fSymbols.Assign(aValue);
|
|
end;
|
|
|
|
procedure TSymbolList.LoadFromTool(str: TStream);
|
|
var
|
|
bin: TMemoryStream;
|
|
begin
|
|
bin := TMemoryStream.Create;
|
|
try
|
|
str.Position:=0;
|
|
try
|
|
ObjectTextToBinary(str, bin);
|
|
except
|
|
exit;
|
|
end;
|
|
bin.Position:=0;
|
|
bin.ReadComponent(self);
|
|
finally
|
|
bin.Free;
|
|
end;
|
|
end;
|
|
{$ENDREGION}
|
|
|
|
{$REGION TCESymbolListOptions --------------------------------------------------}
|
|
constructor TCESymbolListOptions.Create(AOwner: TComponent);
|
|
begin
|
|
inherited;
|
|
fDeep := true;
|
|
fRefreshOnFocus := true;
|
|
fShowChildCategories := true;
|
|
fAutoExpandErrors := true;
|
|
fAutoRefresh := true;
|
|
fSmartFilter := true;
|
|
fSortSymbols := false;
|
|
fAutoRefreshDelay := 750;
|
|
end;
|
|
|
|
procedure TCESymbolListOptions.Assign(Source: TPersistent);
|
|
var
|
|
widg: TCESymbolListWidget;
|
|
begin
|
|
if Source is TCESymbolListWidget then
|
|
begin
|
|
widg := TCESymbolListWidget(Source);
|
|
//
|
|
fDeep := widg.fDeep;
|
|
fAutoRefreshDelay := widg.updaterByDelayDuration;
|
|
fRefreshOnFocus := widg.fRefreshOnFocus;
|
|
fRefreshOnChange := widg.fRefreshOnChange;
|
|
fAutoRefresh := widg.fAutoRefresh;
|
|
fShowChildCategories := widg.fShowChildCategories;
|
|
fSmartFilter := widg.fSmartFilter;
|
|
fAutoExpandErrors := widg.fAutoExpandErrors;
|
|
fSortSymbols := widg.fSortSymbols;
|
|
fSmartExpander := widg.fSmartExpander;
|
|
end
|
|
else inherited;
|
|
end;
|
|
|
|
procedure TCESymbolListOptions.AssignTo(Dest: TPersistent);
|
|
var
|
|
widg: TCESymbolListWidget;
|
|
begin
|
|
if Dest is TCESymbolListWidget then
|
|
begin
|
|
widg := TCESymbolListWidget(Dest);
|
|
//
|
|
widg.updaterByDelayDuration := fAutoRefreshDelay;
|
|
widg.fRefreshOnFocus := fRefreshOnFocus;
|
|
widg.fRefreshOnChange := fRefreshOnChange;
|
|
widg.fAutoRefresh := fAutoRefresh;
|
|
widg.fShowChildCategories := fShowChildCategories;
|
|
widg.fSmartFilter := fSmartFilter;
|
|
widg.fAutoExpandErrors := fAutoExpandErrors;
|
|
widg.fSortSymbols := fSortSymbols;
|
|
widg.fSmartExpander := fSmartExpander;
|
|
widg.fDeep := fDeep;
|
|
//
|
|
widg.fActAutoRefresh.Checked := fAutoRefresh;
|
|
widg.fActRefreshOnChange.Checked:= fRefreshOnChange;
|
|
widg.fActRefreshOnFocus.Checked := fRefreshOnFocus;
|
|
end
|
|
else inherited;
|
|
end;
|
|
{$ENDREGION}
|
|
|
|
{$REGION Standard Comp/Obj------------------------------------------------------}
|
|
constructor TCESymbolListWidget.create(aOwner: TComponent);
|
|
var
|
|
fname: string;
|
|
begin
|
|
fAutoRefresh := false;
|
|
fRefreshOnFocus := true;
|
|
fRefreshOnChange := false;
|
|
checkIfHasToolExe;
|
|
//
|
|
fActCopyIdent := TAction.Create(self);
|
|
fActCopyIdent.OnExecute:=@actCopyIdentExecute;
|
|
fActCopyIdent.Caption := 'Copy identifier';
|
|
fActRefresh := TAction.Create(self);
|
|
fActRefresh.OnExecute := @actRefreshExecute;
|
|
fActRefresh.Caption := 'Refresh';
|
|
fActAutoRefresh := TAction.Create(self);
|
|
fActAutoRefresh.OnExecute := @actAutoRefreshExecute;
|
|
fActAutoRefresh.Caption := 'Auto-refresh';
|
|
fActAutoRefresh.AutoCheck := true;
|
|
fActAutoRefresh.Checked := fAutoRefresh;
|
|
fActRefreshOnChange := TAction.Create(self);
|
|
fActRefreshOnChange.OnExecute := @actRefreshOnChangeExecute;
|
|
fActRefreshOnChange.Caption := 'Refresh on change';
|
|
fActRefreshOnChange.AutoCheck := true;
|
|
fActRefreshOnChange.Checked := fRefreshOnChange;
|
|
fActRefreshOnFocus := TAction.Create(self);
|
|
fActRefreshOnFocus.OnExecute := @actRefreshOnFocusExecute;
|
|
fActRefreshOnFocus.Caption := 'Refresh on focused';
|
|
fActRefreshOnFocus.AutoCheck := true;
|
|
fActRefreshOnFocus.Checked := fRefreshOnFocus;
|
|
fActSelectInSource := TAction.Create(self);
|
|
fActSelectInSource.OnExecute := @TreeDblClick;
|
|
fActSelectInSource.Caption := 'Select in source';
|
|
//
|
|
inherited;
|
|
// allow empty name if owner is nil
|
|
fSyms := TSymbolList.create(nil);
|
|
//
|
|
fOptions := TCESymbolListOptions.Create(self);
|
|
fOptions.Name:= 'symbolListOptions';
|
|
fname := getCoeditDocPath + OptsFname;
|
|
if fname.fileExists then
|
|
fOptions.loadFromFile(fname);
|
|
fOptions.AssignTo(self);
|
|
//
|
|
ndAlias := Tree.Items[0];
|
|
ndClass := Tree.Items[1];
|
|
ndEnum := Tree.Items[2];
|
|
ndFunc := Tree.Items[3];
|
|
ndImp := Tree.Items[4];
|
|
ndIntf := Tree.Items[5];
|
|
ndMix := Tree.Items[6];
|
|
ndStruct := Tree.Items[7];
|
|
ndTmp := Tree.Items[8];
|
|
ndUni := Tree.Items[9];
|
|
ndUt := Tree.Items[10];
|
|
ndVar := Tree.Items[11];
|
|
ndWarn := Tree.Items[12];
|
|
ndErr := Tree.Items[13];
|
|
//
|
|
AssignPng(btnRefresh, 'ARROW_UPDATE');
|
|
//
|
|
Tree.OnDblClick := @TreeDblClick;
|
|
Tree.PopupMenu := contextMenu;
|
|
//
|
|
EntitiesConnector.addObserver(self);
|
|
end;
|
|
|
|
destructor TCESymbolListWidget.destroy;
|
|
begin
|
|
EntitiesConnector.removeObserver(self);
|
|
//
|
|
killProcess(fToolProc);
|
|
fSyms.Free;
|
|
//
|
|
fOptions.saveToFile(getCoeditDocPath + OptsFname);
|
|
fOptions.Free;
|
|
//
|
|
inherited;
|
|
end;
|
|
|
|
procedure TCESymbolListWidget.SetVisible(Value: boolean);
|
|
begin
|
|
inherited;
|
|
checkIfHasToolExe;
|
|
getMessageDisplay(fMsgs);
|
|
if Value then
|
|
callToolProc;
|
|
end;
|
|
{$ENDREGION}
|
|
|
|
{$REGION ICEContextualActions---------------------------------------------------}
|
|
function TCESymbolListWidget.contextName: string;
|
|
begin
|
|
result := 'Static explorer';
|
|
end;
|
|
|
|
function TCESymbolListWidget.contextActionCount: integer;
|
|
begin
|
|
result := 6;
|
|
end;
|
|
|
|
function TCESymbolListWidget.contextAction(index: integer): TAction;
|
|
begin
|
|
case index of
|
|
0: exit(fActSelectInSource);
|
|
1: exit(fActCopyIdent);
|
|
2: exit(fActRefresh);
|
|
3: exit(fActAutoRefresh);
|
|
4: exit(fActRefreshOnChange);
|
|
5: exit(fActRefreshOnFocus);
|
|
else result := nil;
|
|
end;
|
|
end;
|
|
|
|
procedure TCESymbolListWidget.actRefreshExecute(Sender: TObject);
|
|
begin
|
|
if Updating then exit;
|
|
callToolProc;
|
|
end;
|
|
|
|
procedure TCESymbolListWidget.actAutoRefreshExecute(Sender: TObject);
|
|
begin
|
|
autoRefresh := fActAutoRefresh.Checked;
|
|
//fOptions.Assign(self);
|
|
end;
|
|
|
|
procedure TCESymbolListWidget.actRefreshOnChangeExecute(Sender: TObject);
|
|
begin
|
|
refreshOnChange := fActRefreshOnChange.Checked;
|
|
fOptions.Assign(self);
|
|
end;
|
|
|
|
procedure TCESymbolListWidget.actRefreshOnFocusExecute(Sender: TObject);
|
|
begin
|
|
refreshOnFocus := fActRefreshOnFocus.Checked;
|
|
fOptions.Assign(self);
|
|
end;
|
|
|
|
procedure TCESymbolListWidget.actCopyIdentExecute(Sender: TObject);
|
|
begin
|
|
if Tree.Selected.isNotNil then
|
|
Clipboard.AsText:= Tree.Selected.Text;
|
|
end;
|
|
{$ENDREGION}
|
|
|
|
{$REGION ICEEditableOptions ----------------------------------------------------}
|
|
function TCESymbolListWidget.optionedWantCategory(): string;
|
|
begin
|
|
exit('Symbol list');
|
|
end;
|
|
|
|
function TCESymbolListWidget.optionedWantEditorKind: TOptionEditorKind;
|
|
begin
|
|
exit(oekGeneric);
|
|
end;
|
|
|
|
function TCESymbolListWidget.optionedWantContainer: TPersistent;
|
|
begin
|
|
fOptions.Assign(self);
|
|
exit(fOptions);
|
|
end;
|
|
|
|
procedure TCESymbolListWidget.optionedEvent(anEvent: TOptionEditorEvent);
|
|
begin
|
|
if anEvent <> oeeAccept then exit;
|
|
fOptions.AssignTo(self);
|
|
callToolProc;
|
|
end;
|
|
|
|
function TCESymbolListWidget.optionedOptionsModified: boolean;
|
|
begin
|
|
exit(false);
|
|
end;
|
|
{$ENDREGION}
|
|
|
|
{$REGION ICEMultiDocObserver ---------------------------------------------------}
|
|
procedure TCESymbolListWidget.docNew(aDoc: TCESynMemo);
|
|
begin
|
|
fDoc := aDoc;
|
|
beginDelayedUpdate;
|
|
end;
|
|
|
|
procedure TCESymbolListWidget.docClosing(aDoc: TCESynMemo);
|
|
begin
|
|
if fDoc <> aDoc then exit;
|
|
fDoc := nil;
|
|
clearTree;
|
|
updateVisibleCat;
|
|
end;
|
|
|
|
procedure TCESymbolListWidget.docFocused(aDoc: TCESynMemo);
|
|
begin
|
|
if fDoc = aDoc then exit;
|
|
fDoc := aDoc;
|
|
if not Visible then exit;
|
|
//
|
|
if fAutoRefresh then beginDelayedUpdate
|
|
else if fRefreshOnFocus then callToolProc;
|
|
end;
|
|
|
|
procedure TCESymbolListWidget.docChanged(aDoc: TCESynMemo);
|
|
begin
|
|
if fDoc <> aDoc then exit;
|
|
if not Visible then exit;
|
|
//
|
|
if fAutoRefresh then beginDelayedUpdate
|
|
else if fRefreshOnChange then callToolProc;
|
|
//
|
|
if fSmartExpander then
|
|
smartExpand;
|
|
end;
|
|
{$ENDREGION}
|
|
|
|
{$REGION Symbol-tree things ----------------------------------------------------}
|
|
procedure TCESymbolListWidget.updateDelayed;
|
|
begin
|
|
if not fAutoRefresh then exit;
|
|
callToolProc;
|
|
end;
|
|
|
|
procedure TCESymbolListWidget.btnRefreshClick(Sender: TObject);
|
|
begin
|
|
checkIfHasToolExe;
|
|
fActRefresh.Execute;
|
|
end;
|
|
|
|
procedure TCESymbolListWidget.TreeCompare(Sender: TObject; Node1,
|
|
Node2: TTreeNode; var Compare: Integer);
|
|
begin
|
|
Compare := CompareStr(Node1.Text, Node2.text);
|
|
end;
|
|
|
|
procedure TCESymbolListWidget.updateVisibleCat;
|
|
begin
|
|
if fDoc.isNotNil and fDoc.isDSource then
|
|
begin
|
|
ndAlias.Visible := ndAlias.Count > 0;
|
|
ndClass.Visible := ndClass.Count > 0;
|
|
ndEnum.Visible := ndEnum.Count > 0;
|
|
ndFunc.Visible := ndFunc.Count > 0;
|
|
ndImp.Visible := ndImp.Count > 0;
|
|
ndIntf.Visible := ndIntf.Count > 0;
|
|
ndMix.Visible := ndMix.Count > 0;
|
|
ndStruct.Visible:= ndStruct.Count > 0;
|
|
ndTmp.Visible := ndTmp.Count > 0;
|
|
ndUni.Visible := ndUni.Count > 0;
|
|
ndUt.Visible := ndUt.Count > 0;
|
|
ndVar.Visible := ndVar.Count > 0;
|
|
ndWarn.Visible := ndWarn.Count > 0;
|
|
ndErr.Visible := ndErr.Count > 0;
|
|
end else
|
|
begin
|
|
ndAlias.Visible := true;
|
|
ndClass.Visible := true;
|
|
ndEnum.Visible := true;
|
|
ndFunc.Visible := true;
|
|
ndImp.Visible := true;
|
|
ndIntf.Visible := true;
|
|
ndMix.Visible := true;
|
|
ndStruct.Visible:= true;
|
|
ndTmp.Visible := true;
|
|
ndUni.Visible := true;
|
|
ndUt.Visible := true;
|
|
ndVar.Visible := true;
|
|
ndWarn.Visible := true;
|
|
ndErr.Visible := true;
|
|
end;
|
|
end;
|
|
|
|
procedure TCESymbolListWidget.clearTree;
|
|
begin
|
|
ndAlias.DeleteChildren;
|
|
ndClass.DeleteChildren;
|
|
ndEnum.DeleteChildren;
|
|
ndFunc.DeleteChildren;
|
|
ndImp.DeleteChildren;
|
|
ndIntf.DeleteChildren;
|
|
ndMix.DeleteChildren;
|
|
ndStruct.DeleteChildren;
|
|
ndTmp.DeleteChildren;
|
|
ndUni.DeleteChildren;
|
|
ndUt.DeleteChildren;
|
|
ndVar.DeleteChildren;
|
|
ndWarn.DeleteChildren;
|
|
ndErr.DeleteChildren;
|
|
end;
|
|
|
|
procedure TCESymbolListWidget.TreeFilterEdit1AfterFilter(Sender: TObject);
|
|
begin
|
|
if TreeFilterEdit1.Filter.isEmpty then
|
|
updateVisibleCat;
|
|
end;
|
|
|
|
function TCESymbolListWidget.TreeFilterEdit1FilterItem(Item: TObject; out
|
|
Done: Boolean): Boolean;
|
|
begin
|
|
if not fSmartFilter then exit(false);
|
|
//
|
|
if TreeFilterEdit1.Filter.isNotEmpty then
|
|
tree.FullExpand
|
|
else if tree.Selected.isNil then
|
|
tree.FullCollapse
|
|
else tree.MakeSelectionVisible;
|
|
result := false;
|
|
end;
|
|
|
|
procedure TCESymbolListWidget.TreeFilterEdit1MouseEnter(Sender: TObject);
|
|
begin
|
|
if not fSmartFilter then exit;
|
|
//
|
|
tree.Selected := nil;
|
|
end;
|
|
|
|
procedure TCESymbolListWidget.TreeKeyPress(Sender: TObject; var Key: char);
|
|
begin
|
|
if Key = #13 then TreeDblClick(nil);
|
|
end;
|
|
|
|
procedure TCESymbolListWidget.TreeDblClick(Sender: TObject);
|
|
var
|
|
line: NativeUint;
|
|
begin
|
|
if fDoc.isNil then exit;
|
|
if Tree.Selected.isNil then exit;
|
|
if Tree.Selected.Data.isNil then exit;
|
|
//
|
|
{$PUSH}{$WARNINGS OFF}{$HINTS OFF}
|
|
line := NativeUInt(Tree.Selected.Data);
|
|
{$POP}
|
|
fDoc.CaretY := line;
|
|
fDoc.SelectLine;
|
|
end;
|
|
|
|
procedure TCESymbolListWidget.checkIfHasToolExe;
|
|
begin
|
|
fToolExeName := exeFullName(toolExeName);
|
|
fHasToolExe := fToolExeName.fileExists;
|
|
end;
|
|
|
|
procedure TCESymbolListWidget.callToolProc;
|
|
var
|
|
str: string;
|
|
begin
|
|
if not fHasToolExe then exit;
|
|
if fDoc.isNil then exit;
|
|
if (fDoc.Lines.Count = 0) or not fDoc.isDSource then
|
|
begin
|
|
clearTree;
|
|
updateVisibleCat;
|
|
exit;
|
|
end;
|
|
//
|
|
killProcess(fToolProc);
|
|
fToolProc := TCEProcess.Create(nil);
|
|
fToolProc.ShowWindow := swoHIDE;
|
|
fToolProc.Options := [poUsePipes];
|
|
fToolProc.Executable := fToolExeName;
|
|
fToolProc.OnTerminate := @toolTerminated;
|
|
fToolProc.CurrentDirectory := Application.ExeName.extractFileDir;
|
|
if fDeep then fToolProc.Parameters.Add('-d');
|
|
fToolProc.Execute;
|
|
str := fDoc.Text;
|
|
fToolProc.Input.Write(str[1], str.length);
|
|
fToolProc.CloseInput;
|
|
end;
|
|
|
|
procedure TCESymbolListWidget.toolTerminated(sender: TObject);
|
|
//
|
|
function getCatNode(node: TTreeNode; stype: TSymbolType ): TTreeNode;
|
|
//
|
|
function newCat(const aCat: string): TTreeNode;
|
|
begin
|
|
result := node.FindNode(aCat);
|
|
if result.isNil then
|
|
result := node.TreeNodes.AddChild(node, aCat);
|
|
case stype of
|
|
_alias : begin result.ImageIndex:=0; result.SelectedIndex:=0; end;
|
|
_class : begin result.ImageIndex:=1; result.SelectedIndex:=1; end;
|
|
_enum : begin result.ImageIndex:=2; result.SelectedIndex:=2; end;
|
|
_function : begin result.ImageIndex:=3; result.SelectedIndex:=3; end;
|
|
_import : begin result.ImageIndex:=4; result.SelectedIndex:=4; end;
|
|
_interface: begin result.ImageIndex:=5; result.SelectedIndex:=5; end;
|
|
_mixin : begin result.ImageIndex:=6; result.SelectedIndex:=6; end;
|
|
_struct : begin result.ImageIndex:=7; result.SelectedIndex:=7; end;
|
|
_template : begin result.ImageIndex:=8; result.SelectedIndex:=8; end;
|
|
_union : begin result.ImageIndex:=0; result.SelectedIndex:=0; end;
|
|
_unittest : begin result.ImageIndex:=1; result.SelectedIndex:=1; end;
|
|
_variable : begin result.ImageIndex:=2; result.SelectedIndex:=2; end;
|
|
_warning : begin result.ImageIndex:=9; result.SelectedIndex:=9; end;
|
|
_error : begin result.ImageIndex:=10; result.SelectedIndex:=10; end;
|
|
end;
|
|
end;
|
|
//
|
|
begin
|
|
result := nil;
|
|
if node.isNil then case stype of
|
|
_alias : exit(ndAlias);
|
|
_class : exit(ndClass);
|
|
_enum : exit(ndEnum);
|
|
_function : exit(ndFunc);
|
|
_import : exit(ndImp);
|
|
_interface: exit(ndIntf);
|
|
_mixin : exit(ndMix);
|
|
_struct : exit(ndStruct);
|
|
_template : exit(ndTmp);
|
|
_union : exit(ndUni);
|
|
_unittest : exit(ndUt);
|
|
_variable : exit(ndVar);
|
|
_warning : exit(ndWarn);
|
|
_error : exit(ndErr);
|
|
end else case stype of
|
|
_alias: exit(newCat('Alias'));
|
|
_class: exit(newCat('Class'));
|
|
_enum: exit(newCat('Enum'));
|
|
_function: exit(newCat('Function'));
|
|
_import: exit(newCat('Import'));
|
|
_interface: exit(newCat('Interface'));
|
|
_mixin: exit(newCat('Mixin'));
|
|
_struct: exit(newCat('Struct'));
|
|
_template: exit(newCat('Template'));
|
|
_union: exit(newCat('Union'));
|
|
_unittest: exit(newCat('Unittest'));
|
|
_variable: exit(newCat('Variable'));
|
|
_warning: exit(ndWarn);
|
|
_error: exit(ndErr);
|
|
end;
|
|
end;
|
|
//
|
|
procedure symbolToTreeNode(origin: TTreenode; sym: TSymbol);
|
|
var
|
|
cat: TTreeNode;
|
|
node: TTreeNode;
|
|
i: Integer;
|
|
begin
|
|
cat := getCatNode(origin, sym.symType);
|
|
{$PUSH}{$WARNINGS OFF}{$HINTS OFF}
|
|
node := tree.Items.AddChildObject(cat, sym.name, Pointer(sym.fline));
|
|
{$POP}
|
|
node.SelectedIndex:= cat.SelectedIndex;
|
|
node.ImageIndex:= cat.ImageIndex;
|
|
if not fShowChildCategories then
|
|
node := nil;
|
|
cat.Visible:=true;
|
|
for i := 0 to sym.subs.Count-1 do
|
|
symbolToTreeNode(node, sym.subs[i]);
|
|
end;
|
|
//
|
|
var
|
|
i: Integer;
|
|
flt: string;
|
|
begin
|
|
if ndAlias.isNil then exit;
|
|
clearTree;
|
|
updateVisibleCat;
|
|
if fDoc.isNil then exit;
|
|
//
|
|
fToolProc.OnTerminate := nil;
|
|
fToolProc.OnReadData := nil;
|
|
fToolProc.OutputStack.Position:=0;
|
|
if fToolProc.OutputStack.Size = 0 then exit;
|
|
fSyms.LoadFromTool(fToolProc.OutputStack);
|
|
//
|
|
flt := TreeFilterEdit1.Filter;
|
|
TreeFilterEdit1.Text := '';
|
|
tree.BeginUpdate;
|
|
for i := 0 to fSyms.symbols.Count-1 do
|
|
symbolToTreeNode(nil, fSyms.symbols[i]);
|
|
if fAutoExpandErrors then
|
|
begin
|
|
if ndWarn.Visible then
|
|
ndWarn.Expand(true);
|
|
if ndErr.Visible then
|
|
ndErr.Expand(true);
|
|
end;
|
|
if fSortSymbols then
|
|
for i:= 0 to tree.Items.Count-1 do
|
|
if Tree.Items[i].Count > 0 then
|
|
tree.Items[i].CustomSort(nil);
|
|
if fSmartExpander then
|
|
smartExpand;
|
|
tree.EndUpdate;
|
|
if flt.isNotEmpty then
|
|
TreeFilterEdit1.Text := flt;
|
|
end;
|
|
|
|
procedure TCESymbolListWidget.smartExpand;
|
|
var
|
|
i: integer;
|
|
target: NativeUint;
|
|
nearest: NativeUint = 0;
|
|
toExpand: TTreeNode = nil;
|
|
|
|
procedure look(root: TTreeNode);
|
|
var
|
|
i: integer;
|
|
line: NativeUint;
|
|
begin
|
|
for i := 0 to root.Count-1 do
|
|
begin
|
|
if root.Items[i].Data.isNil then
|
|
continue;
|
|
if root.Items[i].Parent.isNil then
|
|
continue;
|
|
case root.Items[i].Parent.Text of
|
|
'Alias', 'Enum', 'Import', 'Variable':
|
|
continue;
|
|
end;
|
|
{$PUSH}{$WARNINGS OFF}{$HINTS OFF}
|
|
line := NativeUInt(root.Items[i].Data);
|
|
{$POP}
|
|
if line > target then
|
|
continue;
|
|
if line > nearest then
|
|
begin
|
|
nearest := line;
|
|
toExpand := root.Items[i];
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
if fDoc.isNil then exit;
|
|
//
|
|
target := fDoc.CaretY;
|
|
for i := 0 to tree.Items.Count-1 do
|
|
look(tree.Items[i]);
|
|
if toExpand.isNotNil then
|
|
begin
|
|
tree.Selected := toExpand;
|
|
toExpand.MakeVisible;
|
|
end;
|
|
end;
|
|
{$ENDREGION --------------------------------------------------------------------}
|
|
|
|
initialization
|
|
RegisterClasses([TCESymbolListOptions]);
|
|
end.
|