1
0
mirror of https://github.com/moparisthebest/Simba synced 2025-03-03 18:59:47 -05:00

Code hints work! Press ctrl + shift + space to activate it :).

This commit is contained in:
Raymond 2010-03-31 20:23:39 +02:00
parent 422fc0b923
commit d5c29d57ef
4 changed files with 521 additions and 132 deletions

View File

@ -29,7 +29,7 @@ interface
uses uses
Classes, SysUtils, FileUtil, LResources, Forms, SynHighlighterPas, SynEdit, SynEditMarkupHighAll, Classes, SysUtils, FileUtil, LResources, Forms, SynHighlighterPas, SynEdit, SynEditMarkupHighAll,
mmlpsthread,ComCtrls, SynEditKeyCmds, LCLType,MufasaBase, SynEditMarkupSpecialLine, Graphics, Controls, mmlpsthread,ComCtrls, SynEditKeyCmds, LCLType,MufasaBase, SynEditMarkupSpecialLine, Graphics, Controls,
v_ideCodeInsight, v_ideCodeParser, CastaliaPasLexTypes, CastaliaSimplePasPar, SynEditHighlighter; v_ideCodeInsight, v_ideCodeParser, CastaliaPasLexTypes, CastaliaSimplePasPar, SynEditHighlighter,synedittextbase;
const const
ecCodeCompletion = ecUserFirst; ecCodeCompletion = ecUserFirst;
ecCodeHints = ecUserFirst + 1; ecCodeHints = ecUserFirst + 1;
@ -125,6 +125,28 @@ begin
Result := Copy(s, sp, ep - sp + 1); Result := Copy(s, sp, ep - sp + 1);
end; end;
function PosToCaretXY(e : TSynEdit; pos : integer) : TPoint;
function llen(const data: string): integer;
begin
result := length(Data) + length(LineEnding);
end;
var
loop: integer;
count: integer;
Lines : TStrings;
begin
loop := 0;
count := 0;
Lines := e.Lines;
while (loop < Lines.Count) and (count + llen(Lines[loop]) < pos) do begin
count := count + llen(Lines[loop]);
inc(loop);
end;
result.x := pos - count;
result.y := loop + 1;
end;
{ TScriptFrame } { TScriptFrame }
procedure TScriptFrame.SynEditChange(Sender: TObject); procedure TScriptFrame.SynEditChange(Sender: TObject);
@ -214,6 +236,8 @@ begin
Form1.ActionFindNextExecute(Sender); Form1.ActionFindNextExecute(Sender);
key := 0; key := 0;
end; end;
if key = VK_ESCAPE then
Form1.ParamHint.Hide;
Form1.CodeCompletionForm.HandleKeyDown(Sender, Key, Shift); Form1.CodeCompletionForm.HandleKeyDown(Sender, Key, Shift);
end; end;
@ -257,17 +281,15 @@ var
mp: TCodeInsight; mp: TCodeInsight;
ms: TMemoryStream; ms: TMemoryStream;
ItemList, InsertList: TStringList; ItemList, InsertList: TStringList;
sp, ep,bcc,cc,bck: Integer; sp, ep,bcc,cc,bck,posi,bracketpos: Integer;
p: TPoint; p: TPoint;
s, Filter: string; s, Filter: string;
Attri: TSynHighlighterAttributes; Attri: TSynHighlighterAttributes;
d: TDeclaration; d: TDeclaration;
dd: TDeclaration; dd: TDeclaration;
begin begin
if ((not SynEdit.GetHighlighterAttriAtRowCol(SynEdit.CaretXY, s, Attri)) or (Attri.Name = 'Identifier')) then if (Command = ecCodeCompletion) and ((not SynEdit.GetHighlighterAttriAtRowCol(SynEdit.CaretXY, s, Attri)) or (Attri.Name = 'Identifier')) then
begin begin
if (Command = ecCodeCompletion) then
begin;
{form1.FunctionListShown(True); {form1.FunctionListShown(True);
with form1.frmFunctionList do with form1.frmFunctionList do
if editSearchList.CanFocus then if editSearchList.CanFocus then
@ -342,30 +364,33 @@ begin
ItemList.Free; ItemList.Free;
InsertList.Free; InsertList.Free;
end; end;
end else end;
if command = ecCodeHints then if command = ecCodeHints then
begin begin
if Form1.ParamHint.Visible = true then
form1.ParamHint.hide;
mp := TCodeInsight.Create; mp := TCodeInsight.Create;
mp.OnMessage := @form1.OnCCMessage; mp.OnMessage := @form1.OnCCMessage;
mp.OnFindInclude := @form1.OnCCFindInclude; mp.OnFindInclude := @form1.OnCCFindInclude;
ms := TMemoryStream.Create; ms := TMemoryStream.Create;
synedit.Lines.SaveToStream(ms); synedit.Lines.SaveToStream(ms);
try try
Synedit.GetWordBoundsAtRowCol(Synedit.CaretXY, sp, ep); Synedit.GetWordBoundsAtRowCol(Synedit.CaretXY, sp, ep);
mp.Run(ms, nil, Synedit.SelStart + (ep - Synedit.CaretX) - 1); mp.Run(ms, nil, Synedit.SelStart + (ep - Synedit.CaretX) - 1,true);
//mp.Position := Synedit.SelStart + (ep - Synedit.CaretX) - 1;
bcc := 1;
bck := 0;
cc := 0;
s := mp.GetExpressionAtPos(bcc, bck, cc, True);
if (s <> '') then
Delete(s, Length(s), 1);
bcc := 1;bck := 0;cc := 0;
s := mp.GetExpressionAtPos(bcc, bck, cc,posi, true);
bracketpos := posi + length(s);
if pos('(',s) > 0 then
begin;
bracketpos := pos('(',s) + posi;
delete(s,pos('(',s),length(s) - pos('(',s) + 1);
end;
d := mp.FindVarBase(s); d := mp.FindVarBase(s);
dd := nil; dd := nil;
//Find the declaration -> For example if one uses var x : TNotifyEvent..
//You have to get the owner of x, to find the declaration of TNotifyEvent etc..
while (d <> nil) and (d <> dd) and (d.Owner <> nil) and (not ((d is TciProcedureDeclaration) or (d.Owner is TciProcedureDeclaration))) do while (d <> nil) and (d <> dd) and (d.Owner <> nil) and (not ((d is TciProcedureDeclaration) or (d.Owner is TciProcedureDeclaration))) do
begin begin
dd := d; dd := d;
@ -381,19 +406,21 @@ begin
else else
Break; Break;
end; end;
//Yeah, we should have found the procedureDeclaration now!
if (d <> nil) and (d <> dd) and (d.Owner <> nil) and ((d is TciProcedureDeclaration) or (d.Owner is TciProcedureDeclaration)) then if (d <> nil) and (d <> dd) and (d.Owner <> nil) and ((d is TciProcedureDeclaration) or (d.Owner is TciProcedureDeclaration)) then
begin begin
if (not (d is TciProcedureDeclaration)) and (d.Owner is TciProcedureDeclaration) then if (not (d is TciProcedureDeclaration)) and (d.Owner is TciProcedureDeclaration) then
d := d.Owner; d := d.Owner;
if (TciProcedureDeclaration(d).SynParams <> '') then if (TciProcedureDeclaration(d).Params <> '') then
formWriteln(TciProcedureDeclaration(d).SynParams) Form1.ParamHint.Show(PosToCaretXY(synedit,posi + 1), PosToCaretXY(synedit,bracketpos),
TciProcedureDeclaration(d), synedit,mp)
else else
FormWriteln('<no parameters expected>'); FormWriteln('<no parameters expected>');
end; end;
finally except
FreeAndNil(ms); on e : exception do
FreeAndNil(mp); mDebugLn(e.message);
end; //Do not free the MP, we need to use this.
end; end;
end; end;
if Form1.CodeCompletionForm.Visible then if Form1.CodeCompletionForm.Visible then
@ -410,7 +437,6 @@ begin
Exit; Exit;
end; end;
end; end;
Form1.CodeCompletionForm.Hide; Form1.CodeCompletionForm.Hide;
end; end;
end; end;

View File

@ -344,6 +344,7 @@ type
CurrTab : TMufasaTab; //The current TMufasaTab CurrTab : TMufasaTab; //The current TMufasaTab
CodeCompletionForm: TAutoCompletePopup; CodeCompletionForm: TAutoCompletePopup;
CodeCompletionStart: TPoint; CodeCompletionStart: TPoint;
ParamHint : TParamHint;
Tabs : TList; Tabs : TList;
Manager: TIOManager; Manager: TIOManager;
OCR_Fonts: TMOCR; OCR_Fonts: TMOCR;
@ -1831,6 +1832,8 @@ begin
CodeCompletionForm := TAutoCompletePopup.Create(Self); CodeCompletionForm := TAutoCompletePopup.Create(Self);
CodeCompletionForm.InsertProc := @OnCompleteCode; CodeCompletionForm.InsertProc := @OnCompleteCode;
ParamHint := TParamHint.Create(self);
{$ifdef MSWindows} {$ifdef MSWindows}
ConsoleVisible := True; ConsoleVisible := True;
PrevWndProc := Windows.WNDPROC(GetWindowLong(self.handle,GWL_WNDPROC)); PrevWndProc := Windows.WNDPROC(GetWindowLong(self.handle,GWL_WNDPROC));
@ -1907,6 +1910,7 @@ begin
SetLength(DebugStream, 0); SetLength(DebugStream, 0);
RecentFiles.Free; RecentFiles.Free;
DebugCriticalSection.Free; DebugCriticalSection.Free;
ParamHint.Free;
{$ifdef MSWindows} {$ifdef MSWindows}
if not UnRegisterHotkey(Self.Handle,0) then if not UnRegisterHotkey(Self.Handle,0) then
mDebugLn('Unable to unregister ctrl + alt + s as global hotkey'); mDebugLn('Unable to unregister ctrl + alt + s as global hotkey');

View File

@ -6,11 +6,12 @@ interface
uses uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, Classes, SysUtils, Forms, Controls, Graphics, Dialogs,
StdCtrls, ExtCtrls, SynEdit, SynEditKeyCmds, StdCtrls, ExtCtrls, SynEdit, SynEditKeyCmds, v_ideCodeParser, v_ideCodeInsight,
{$IFDEF FPC} {$IFDEF FPC}
LMessages, LMessages,
lcltype lcltype,
mPasLex
{$ELSE} {$ELSE}
Windows, Windows,
Messages Messages
@ -81,16 +82,34 @@ type
property InsertProc: TInsertProc read getInsertProc write setInsertProc; property InsertProc: TInsertProc read getInsertProc write setInsertProc;
end; end;
{ TParamHint }
TParamHint = class(THintWindow) TParamHint = class(THintWindow)
private
fPreparedString : string;
LastParameterIndex : integer;
FSynEdit : TSynedit;
FStartPoint : TPoint;
FBracketPoint : TPoint;
FMP : TCodeInsight;
FDecl : TciProcedureDeclaration;
FParameters : TDeclarationArray;
procedure ParamHintHide(Sender: TObject);
procedure ApplicationIdle(Sender: TObject; var Done: Boolean);
procedure DrawHints(var MaxWidth, MaxHeight: Integer; Draw: boolean);
function PrepareParamString(out Str : string; out MustHide : boolean) : integer;
public public
constructor Create(TheOwner: TComponent); override; constructor Create(TheOwner: TComponent); override;
procedure CalculateBounds;
procedure UpdateHint;
procedure Paint; override; procedure Paint; override;
procedure Show(StartPoint,BracketPoint : TPoint;Decl : TciProcedureDeclaration; Editor : TSynedit; mp : TCodeInsight); reintroduce;
end; end;
implementation implementation
uses uses
StrUtils {$IFDEF FPC}, lclintf{$ENDIF}, Themes; StrUtils {$IFDEF FPC}, lclintf{$ENDIF},math, Themes;
procedure TAutoCompleteListBox.setItemList(List: TStrings); procedure TAutoCompleteListBox.setItemList(List: TStrings);
begin begin
@ -553,61 +572,391 @@ begin
Editor.SetFocus; Editor.SetFocus;
end; end;
function StringListPartToText(BeginPos, EndPos : TPoint; Strings :TStrings) : string;
var
i : integer;
begin;
result := '';
if endpos.y < beginpos.y then
exit;
if endpos.y >= strings.Count then
exit;
if beginpos.x > length(strings[beginpos.y]) then
exit;
if endpos.x > length(strings[endpos.y]) then
exit;
result := copy(strings[beginpos.y],beginpos.x, length(strings[beginpos.y]) - beginpos.x + 1);
for i := beginpos.y + 1 to endpos.y-1 do
result := result + strings[i];
if endpos.y <> beginpos.y then
result := result + copy(strings[endpos.y],0,endpos.x);
end;
function TParamHint.PrepareParamString(out Str: string; out MustHide : boolean): Integer;
var
Parser : TmwPasLex;
bracketcount, parameterindex,ParamC : integer;
ParamNames : TDeclarationArray;
typedecl : TDeclaration;
s,TypeStr,Params : string;//
i,ii :integer;
begin
result := -1;
MustHide := True;
Parser := TmwPasLex.Create;
parser.Origin:= PChar( StringListPartToText(Point(FBracketPoint.x,FBracketPoint.y-1),point(min(FSynEdit.LogicalCaretXY.x-1,length(FSynEdit.LineText)),FSynEdit.logicalcaretxy.y-1),FSynEdit.lines));
bracketcount := 0;
ParameterIndex := -1;
while parser.TokenID <> tkNull do
begin
case parser.tokenID of
tkRoundOpen,tkSquareOpen:
begin
inc(BracketCount);
if BracketCount = 1 then
ParameterIndex := 0;
end;
tkRoundClose, tkSquareClose:
begin
dec(BracketCount);
if bracketcount =0 then
exit;
end;
tkComma:
begin
if bracketcount = 1 then
inc(parameterIndex);
end;
end;
parser.NextNoJunk;
end;
if parameterindex = -1 then
exit;
if parameterindex = LastParameterIndex then
begin
mustHide := false;
str := fPreparedString;
result := parameterindex;
exit;
end;
str := '';
ParamC := 0;
typedecl := FDecl.Name;
if typedecl = nil then
exit;
if typedecl.shorttext = '' then
exit;
for i := 0 to high(FParameters) do
begin
if (FParameters[i] is TciConstParameter) then
s := 'const '
else if (FParameters[i] is TciOutParameter) then
s := 'out '
else if (FParameters[i] is TciInParameter) then
s := 'in '
else if (FParameters[i] is TciVarParameter) then
s := 'var '
else
s := '';
ParamNames:= FParameters[i].Items.GetItemsOfClass(TciParameterName);
TypeDecl := FParameters[i].Items.GetFirstItemOfClass(TciParameterType);
if TypeDecl <> nil then
TypeStr := ': ' + typedecl.ShortText
else
TypeStr := '';
Params := '';
for ii := 0 to high(ParamNames) do
begin;
if parameterindex = ParamC then //Found the current parameter index in the parameterdecl!
begin;
if s <> '' then
s := '\' + s + '\'; //If it has a const/var/in/out thingy, bold this as well
if TypeStr <> '' then //If has a type then bold the type
TypeStr := '\' + TypeStr + '\';
if Params <> '' then
Params := Params +', \' + ParamNames[ii].ShortText + '\'
else
Params := '\' + ParamNames[ii].ShortText + '\';
end else
begin;
if Params <> '' then
Params := Params +', ' + ParamNames[ii].ShortText
else
Params := ParamNames[ii].ShortText;
end;
inc(ParamC);
end;
if str <> '' then
str := str + ';' + s + Params + typestr
else
str := s + params + typestr;
end;
TypeDecl := FDecl.Items.GetFirstItemOfClass(TciReturnType);
if TypeDecl <> nil then
TypeStr := ': ' + typedecl.ShortText
else
TypeStr := '';
str := FDecl.Name.ShortText + '(' + str + ')' + TypeStr + ';';
str := StringReplace(str,'\\','',[rfReplaceAll]); //Delete all the \\, something like \const \\x\ is the same as \const x\
MustHide := False;
Result := parameterindex;
fPreparedString := str;
Parser.Free;
end;
constructor TParamHint.Create(TheOwner: TComponent); constructor TParamHint.Create(TheOwner: TComponent);
begin begin
inherited; inherited;
{$IFDEF FPC} {$IFDEF FPC}
AutoHide := False; AutoHide := False;
{$ENDIF} {$ENDIF}
OnHide:=@ParamHintHide;
LastParameterIndex:= -1;
Application.AddOnIdleHandler(@ApplicationIdle);
end;
procedure TParamHint.CalculateBounds;
var
DrawWidth: LongInt;
DrawHeight: LongInt;
ScreenTextXY: TPoint;
ClientXY: TPoint;
ScreenXY: TPoint;
begin
ScreenTextXY := FSynEdit.LogicalToPhysicalPos(FStartPoint);
ClientXY := FSynEdit.RowColumnToPixels(ScreenTextXY);
DrawWidth := FSynEdit.ClientWidth; //Maximum width it can have..
DrawHeight := ClientXY.y; //Maximum height it can have..
DrawHints(DrawWidth,DrawHeight,false); //Calculate the max size we need!
if DrawWidth<20 then DrawWidth:=20; //Some default values!
if DrawHeight<5 then DrawHeight:=5;
if ClientXY.X+DrawWidth>FSynedit.ClientWidth then //If we go out of bounds, lets put it to the left a bit.
ClientXY.X:=FSynedit.ClientWidth-DrawWidth;
if ClientXY.X<0 then //If we go to the left a lil bit to much, go to the right!
ClientXY.X:=0;
dec(ClientXY.Y,DrawHeight); //Move this a lil bit up!
if ClientXY.y < 0 then
ClientXY.y := 0;
ScreenXY:=FSynedit.ClientToScreen(ClientXY); //Position on the screen
dec(ScreenXY.Y,4); //Move it up a lilttle bit above your text, to make the shade come out better?
//Set the new position
BoundsRect:=Bounds(ScreenXY.X,ScreenXY.Y,DrawWidth,DrawHeight);
end;
procedure TParamHint.UpdateHint;
var
MustHide : boolean;
CursorXY : TPoint;
Line : string;
begin
if not self.Visible then
exit;
try
MustHide := True;
if not Assigned(FSynEdit) then
exit;
if FSynEdit.Focused = false then //No focus, hide this hint
exit; //Exits to the finally statement ;)
CursorXY := FSynEdit.LogicalCaretXY;
if (CursorXY.x <= FBracketPoint.x) and (CursorXY.y <= FBracketPoint.y) then //Cursor moved in front of the bracket
exit;
Line:=FSynEdit.Lines[FBracketPoint.Y-1];
if (length(Line)<FBracketPoint.X) or (not (Line[FBracketPoint.X] in ['(','['])) then
exit;
if PrepareParamString(Line,MustHide) = LastParameterIndex then
exit
else if not MustHide then
Self.Invalidate;
finally
if MustHide then
Self.hide;
end;
end;
procedure TParamHint.ParamHintHide(Sender: TObject);
begin
if FMP <> nil then
freeandnil(Fmp);
end;
procedure TParamHint.DrawHints(var MaxWidth, MaxHeight: Integer;
Draw: boolean);
var
HorizontalSpace: Integer;
VerticalSpace: Integer;
BackgroundColor, TextGrayColor, TextColor, PenColor: TColor;
TextGrayStyle, TextStyle: TFontStyles;
procedure DrawHint(const Line: string; var AHintRect: TRect);
var
ATextRect: TRect; //The area we can use
TokenRect: TRect; //The area the text takes up
TokenSize: TPoint; //The W/H the text takes up
TokenPos: TPoint; //The position where the text is drawn
UsedWidth: Integer; // maximum right token position
LineHeight: Integer; // Current line height
Bolding : boolean; //If we are in a bolding part.
Pos : integer;
StartPos : integer;
//Text takes up it's own Width/Height + the space around the text.
begin
ATextRect:=Rect(AHintRect.Left+HorizontalSpace,
AHintRect.Top+VerticalSpace,
AHintRect.Right-HorizontalSpace,
AHintRect.Bottom-VerticalSpace);//Possible area!
UsedWidth:=0;
LineHeight:=0;
TokenPos:=Point(ATextRect.Left,ATextRect.Top); //StartPoint like (0,0)
Bolding := False;
Pos := 0;
//Split the drawing up in words, that way we can split the function if it gets to long ;).
while (Pos < Length(Line)) do
begin
inc(Pos);
if (Line[Pos] = '\') then //Bold from now
begin;
if Draw then
begin
if not Bolding then
begin
Canvas.Font.Color := TextColor;
Canvas.Font.Style := TextStyle;
end else
begin
Canvas.Font.Color := TextGrayColor;
Canvas.Font.Style := TextGrayStyle;
end;
Bolding := not Bolding;
end;
continue;
end;
StartPos := Pos;
if (Line[Pos] in ['a'..'z', 'A'..'Z', '0'..'9', '_']) then //We are in a word, lets draw that completely ;)
begin
while ((Pos < length(line)) and (Line[Pos + 1] in ['a'..'z', 'A'..'Z', '0'..'9', '_'])) do
inc(pos);
end else
while ((Pos < length(line)) and not(Line[Pos + 1] in ['a'..'z', 'A'..'Z', '0'..'9', '_','\'])) do
inc(pos);
TokenRect:=Bounds(0,0,12345,1234); //Random rect
DrawText(Canvas.Handle,@Line[StartPos],Pos-StartPos + 1,TokenRect,
DT_SINGLELINE+DT_CALCRECT+DT_NOCLIP); //Calculate the size it takes to draw this text
TokenSize:=Point(TokenRect.Right,TokenRect.Bottom); //The size it takes to draw this text
if (LineHeight>0) and (TokenPos.X+TokenSize.X>ATextRect.Right) then //It doesn't fit.. Text = 2 long
begin
if Draw and (TokenPos.X<AHintRect.Right) then //Fill the rest of the area with blank info,
//since we are going to draw this text on the next line
Canvas.FillRect(Rect(TokenPos.X,TokenPos.Y-VerticalSpace,
AHintRect.Right,TokenPos.Y+LineHeight+VerticalSpace));
TokenPos:=Point(ATextRect.Left,TokenPos.y+LineHeight+VerticalSpace);//Lets start on the left side, one row below ;)
LineHeight:=0;
end;
OffsetRect(TokenRect,TokenPos.x,TokenPos.y); //Move the tokenrectangle to the tokenposition
if Draw then
begin
Canvas.FillRect(Rect(TokenRect.Left,TokenRect.Top-VerticalSpace,
TokenRect.Right,TokenRect.Bottom+VerticalSpace));//Fill the entire rect (means including the spaces above and below
DrawText(Canvas.Handle,@Line[StartPos],Pos-StartPos + 1,
TokenRect,DT_SINGLELINE+DT_NOCLIP); //Draw the text!
end;
if LineHeight<TokenSize.y then
LineHeight:=TokenSize.y; //the line has a bigger height than before.. The text H is bigger.
inc(TokenPos.X,TokenSize.x); //Move the tokenposition text-width to the right
if UsedWidth<TokenPos.X then //Calculate the max-width we've used!
UsedWidth:=TokenPos.X;
end;
if Draw and (TokenPos.X<AHintRect.Right) and (LineHeight>0) then //Fill the rest of the unused area
Canvas.FillRect(Rect(TokenPos.X,TokenPos.Y-VerticalSpace,
AHintRect.Right,TokenPos.Y+LineHeight+VerticalSpace));
if (not Draw) and (UsedWidth>0) then
AHintRect.Right:=UsedWidth+HorizontalSpace; //Calculate the width we actually need
AHintRect.Bottom:=TokenPos.Y+LineHeight+VerticalSpace;
end;
var
CurHintRect: TRect;
MustHide : boolean;
hintstr: string;
begin
if Draw then
begin
BackgroundColor:=clInfoBk;
TextGrayColor:=clInfoText;
TextGrayStyle:=[];
TextColor:=clInfoText;
TextStyle:=[fsBold];
PenColor:=clBlack;
end;
HorizontalSpace:=2; //The spaces around the text
VerticalSpace:=2;
if Draw then begin
Canvas.Brush.Color:=BackgroundColor;
Canvas.Font.Color:=TextGrayColor;
Canvas.Font.Style:=TextGrayStyle;
Canvas.Pen.Color:=PenColor;
end else begin
Canvas.Font.Style:=[fsBold]; //Let us calculate the maximum width we need :)
end;
CurHintRect:=Rect(0,0,MaxWidth,MaxHeight);
PrepareParamString(HintStr,MustHide);
if MustHide then
begin;
Self.Hide;
exit;
end;
DrawHint(HintStr, CurHintRect);
if Draw then //Fill the rest if needed.. (Possible if we calculated we need 2 rows, but turns out we need only 1 this time).
begin
if CurHintRect.Bottom<MaxHeight then
Canvas.FillRect(Rect(0,CurHintRect.Bottom,MaxWidth,MaxHeight));
// draw frame around window
Canvas.Frame(Rect(0,0,MaxWidth-1,MaxHeight-1));
end;
if not Draw then //Adjust the maxwidth/maxheight needed to draw this thingy!
begin
if CurHintRect.right<MaxWidth then
MaxWidth:=CurHintRect.right;
if CurHintRect.Bottom<MaxHeight then
MaxHeight:=CurHintRect.Bottom;
end;
end; end;
procedure TParamHint.Paint; procedure TParamHint.Paint;
function GetDrawTextFlags: Cardinal;
var var
EffectiveAlignment: TAlignment; MaxWidth,MaxHeight : integer;
begin begin
Result := DT_NOPREFIX or DT_VCENTER or DT_WORDBREAK; MaxWidth:= ClientWidth;
EffectiveAlignment := Alignment; MaxHeight := ClientHeight;
if BiDiMode <> bdLeftToRight then DrawHints(MaxWidth,MaxHeight,True);
begin
Result := Result or DT_RTLREADING;
//change alignment if is RTL
if BiDiMode = bdRightToLeft then
begin
case Alignment of
taLeftJustify: EffectiveAlignment := taRightJustify;
taRightJustify: EffectiveAlignment := taLeftJustify;
end;
end;
end;
case EffectiveAlignment of
taLeftJustify: Result := Result or DT_LEFT;
taCenter: Result := Result or DT_CENTER;
taRightJustify: Result := Result or DT_RIGHT;
end;
end; end;
var procedure TParamHint.Show(StartPoint,BracketPoint: TPoint;Decl : TciProcedureDeclaration; Editor: TSynedit; mp : TCodeInsight);
ARect: TRect;
Details: TThemedElementDetails;
begin begin
ARect := ClientRect; if self.Visible then
if Color = clInfoBk then // draw using themes self.hide;
begin FDecl := Decl;
Details := ThemeServices.GetElementDetails(tttStandardLink); Fmp := mp;
ThemeServices.DrawElement(Canvas.Handle, Details, ARect); FParameters:= Decl.GetParamDeclarations;
end if Length(FParameters) = 0 then //Method has no Parameters
else exit;
begin FSynEdit := Editor;
Canvas.Brush.Color := Color; FStartPoint:= StartPoint;
Canvas.Pen.Width := 1; FBracketPoint:= BracketPoint;
Canvas.FillRect(ARect); CalculateBounds; //Calculate the size we need!
DrawEdge(Canvas.Handle, ARect, BDR_RAISEDOUTER, BF_RECT); self.Visible := true;
end; end;
InflateRect(ARect, - 4, - 4);
Canvas.TextOut(ARect.Left, ARect.Top, Caption);
procedure TParamHint.ApplicationIdle(Sender: TObject; var Done: Boolean);
begin
if not Visible then exit;
UpdateHint;
end; end;
end. end.

View File

@ -16,6 +16,8 @@ type
TOnFindInclude = function(Sender: TObject; var FileName: string): Boolean of object; TOnFindInclude = function(Sender: TObject; var FileName: string): Boolean of object;
{ TCodeInsight }
TCodeInsight = class(TCodeParser) TCodeInsight = class(TCodeParser)
protected protected
fFileName: string; fFileName: string;
@ -49,6 +51,7 @@ type
function GetFuncType(FuncName, FuncClass: string; out Decl: TDeclaration; Return: TVarBase): Boolean; function GetFuncType(FuncName, FuncClass: string; out Decl: TDeclaration; Return: TVarBase): Boolean;
function FindStruct(s: string; out Decl: TDeclaration; Return: TVarBase; var ArrayCount: Integer): Boolean; function FindStruct(s: string; out Decl: TDeclaration; Return: TVarBase; var ArrayCount: Integer): Boolean;
public public
function GetExpressionAtPos(var BraceCount, BracketCount, CommaCount: Integer; out sp : Integer; IgnoreBrackets: Boolean = False): string; overload;
function GetExpressionAtPos(var BraceCount, BracketCount, CommaCount: Integer; IgnoreBrackets: Boolean = False): string; overload; function GetExpressionAtPos(var BraceCount, BracketCount, CommaCount: Integer; IgnoreBrackets: Boolean = False): string; overload;
function GetExpressionAtPos: string; overload; function GetExpressionAtPos: string; overload;
function FindVarBase(s: string; GetStruct: Boolean = False; Return: TVarBase = vbName): TDeclaration; function FindVarBase(s: string; GetStruct: Boolean = False; Return: TVarBase = vbName): TDeclaration;
@ -545,7 +548,7 @@ begin
end; end;
end; end;
function TCodeInsight.GetExpressionAtPos(var BraceCount, BracketCount, CommaCount: Integer; IgnoreBrackets: Boolean = False): string; function TCodeInsight.GetExpressionAtPos(var BraceCount, BracketCount,CommaCount: Integer; out sp: Integer; IgnoreBrackets: Boolean): string;
var var
i, StartPos, EndPos: Integer; i, StartPos, EndPos: Integer;
s: string; s: string;
@ -636,10 +639,17 @@ begin
LastWasDot := False; LastWasDot := False;
Dec(StartPos); Dec(StartPos);
end; end;
sp := startpos + d.StartPos;
Result := CompressWhiteSpace(Copy(s, StartPos + 1, EndPos - StartPos)); Result := CompressWhiteSpace(Copy(s, StartPos + 1, EndPos - StartPos));
end; end;
function TCodeInsight.GetExpressionAtPos(var BraceCount, BracketCount, CommaCount: Integer; IgnoreBrackets: Boolean = False): string;
var
sp : integer;
begin
result := GetExpressionAtPos(bracecount,bracketcount,commacount,sp,ignorebrackets);
end;
function TCodeInsight.GetExpressionAtPos: string; function TCodeInsight.GetExpressionAtPos: string;
var var
bcc, bkc, cc: Integer; bcc, bkc, cc: Integer;