mirror of
https://github.com/moparisthebest/Simba
synced 2025-03-03 10:51:49 -05:00
Code hints work! Press ctrl + shift + space to activate it :).
This commit is contained in:
parent
422fc0b923
commit
d5c29d57ef
@ -29,7 +29,7 @@ interface
|
||||
uses
|
||||
Classes, SysUtils, FileUtil, LResources, Forms, SynHighlighterPas, SynEdit, SynEditMarkupHighAll,
|
||||
mmlpsthread,ComCtrls, SynEditKeyCmds, LCLType,MufasaBase, SynEditMarkupSpecialLine, Graphics, Controls,
|
||||
v_ideCodeInsight, v_ideCodeParser, CastaliaPasLexTypes, CastaliaSimplePasPar, SynEditHighlighter;
|
||||
v_ideCodeInsight, v_ideCodeParser, CastaliaPasLexTypes, CastaliaSimplePasPar, SynEditHighlighter,synedittextbase;
|
||||
const
|
||||
ecCodeCompletion = ecUserFirst;
|
||||
ecCodeHints = ecUserFirst + 1;
|
||||
@ -125,6 +125,28 @@ begin
|
||||
Result := Copy(s, sp, ep - sp + 1);
|
||||
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 }
|
||||
|
||||
procedure TScriptFrame.SynEditChange(Sender: TObject);
|
||||
@ -214,6 +236,8 @@ begin
|
||||
Form1.ActionFindNextExecute(Sender);
|
||||
key := 0;
|
||||
end;
|
||||
if key = VK_ESCAPE then
|
||||
Form1.ParamHint.Hide;
|
||||
|
||||
Form1.CodeCompletionForm.HandleKeyDown(Sender, Key, Shift);
|
||||
end;
|
||||
@ -257,17 +281,15 @@ var
|
||||
mp: TCodeInsight;
|
||||
ms: TMemoryStream;
|
||||
ItemList, InsertList: TStringList;
|
||||
sp, ep,bcc,cc,bck: Integer;
|
||||
sp, ep,bcc,cc,bck,posi,bracketpos: Integer;
|
||||
p: TPoint;
|
||||
s, Filter: string;
|
||||
Attri: TSynHighlighterAttributes;
|
||||
d: TDeclaration;
|
||||
dd: TDeclaration;
|
||||
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
|
||||
if (Command = ecCodeCompletion) then
|
||||
begin;
|
||||
{form1.FunctionListShown(True);
|
||||
with form1.frmFunctionList do
|
||||
if editSearchList.CanFocus then
|
||||
@ -342,30 +364,33 @@ begin
|
||||
ItemList.Free;
|
||||
InsertList.Free;
|
||||
end;
|
||||
end else
|
||||
end;
|
||||
if command = ecCodeHints then
|
||||
begin
|
||||
if Form1.ParamHint.Visible = true then
|
||||
form1.ParamHint.hide;
|
||||
mp := TCodeInsight.Create;
|
||||
mp.OnMessage := @form1.OnCCMessage;
|
||||
mp.OnFindInclude := @form1.OnCCFindInclude;
|
||||
|
||||
ms := TMemoryStream.Create;
|
||||
synedit.Lines.SaveToStream(ms);
|
||||
|
||||
try
|
||||
Synedit.GetWordBoundsAtRowCol(Synedit.CaretXY, sp, ep);
|
||||
mp.Run(ms, nil, Synedit.SelStart + (ep - Synedit.CaretX) - 1);
|
||||
//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);
|
||||
mp.Run(ms, nil, Synedit.SelStart + (ep - Synedit.CaretX) - 1,true);
|
||||
|
||||
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);
|
||||
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
|
||||
begin
|
||||
dd := d;
|
||||
@ -381,19 +406,21 @@ begin
|
||||
else
|
||||
Break;
|
||||
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
|
||||
begin
|
||||
if (not (d is TciProcedureDeclaration)) and (d.Owner is TciProcedureDeclaration) then
|
||||
d := d.Owner;
|
||||
if (TciProcedureDeclaration(d).SynParams <> '') then
|
||||
formWriteln(TciProcedureDeclaration(d).SynParams)
|
||||
if (TciProcedureDeclaration(d).Params <> '') then
|
||||
Form1.ParamHint.Show(PosToCaretXY(synedit,posi + 1), PosToCaretXY(synedit,bracketpos),
|
||||
TciProcedureDeclaration(d), synedit,mp)
|
||||
else
|
||||
FormWriteln('<no parameters expected>');
|
||||
end;
|
||||
finally
|
||||
FreeAndNil(ms);
|
||||
FreeAndNil(mp);
|
||||
end;
|
||||
except
|
||||
on e : exception do
|
||||
mDebugLn(e.message);
|
||||
//Do not free the MP, we need to use this.
|
||||
end;
|
||||
end;
|
||||
if Form1.CodeCompletionForm.Visible then
|
||||
@ -410,7 +437,6 @@ begin
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
Form1.CodeCompletionForm.Hide;
|
||||
end;
|
||||
end;
|
||||
|
@ -344,6 +344,7 @@ type
|
||||
CurrTab : TMufasaTab; //The current TMufasaTab
|
||||
CodeCompletionForm: TAutoCompletePopup;
|
||||
CodeCompletionStart: TPoint;
|
||||
ParamHint : TParamHint;
|
||||
Tabs : TList;
|
||||
Manager: TIOManager;
|
||||
OCR_Fonts: TMOCR;
|
||||
@ -1831,6 +1832,8 @@ begin
|
||||
CodeCompletionForm := TAutoCompletePopup.Create(Self);
|
||||
CodeCompletionForm.InsertProc := @OnCompleteCode;
|
||||
|
||||
ParamHint := TParamHint.Create(self);
|
||||
|
||||
{$ifdef MSWindows}
|
||||
ConsoleVisible := True;
|
||||
PrevWndProc := Windows.WNDPROC(GetWindowLong(self.handle,GWL_WNDPROC));
|
||||
@ -1907,6 +1910,7 @@ begin
|
||||
SetLength(DebugStream, 0);
|
||||
RecentFiles.Free;
|
||||
DebugCriticalSection.Free;
|
||||
ParamHint.Free;
|
||||
{$ifdef MSWindows}
|
||||
if not UnRegisterHotkey(Self.Handle,0) then
|
||||
mDebugLn('Unable to unregister ctrl + alt + s as global hotkey');
|
||||
|
@ -6,11 +6,12 @@ interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, Forms, Controls, Graphics, Dialogs,
|
||||
StdCtrls, ExtCtrls, SynEdit, SynEditKeyCmds,
|
||||
StdCtrls, ExtCtrls, SynEdit, SynEditKeyCmds, v_ideCodeParser, v_ideCodeInsight,
|
||||
|
||||
{$IFDEF FPC}
|
||||
LMessages,
|
||||
lcltype
|
||||
lcltype,
|
||||
mPasLex
|
||||
{$ELSE}
|
||||
Windows,
|
||||
Messages
|
||||
@ -81,16 +82,34 @@ type
|
||||
property InsertProc: TInsertProc read getInsertProc write setInsertProc;
|
||||
end;
|
||||
|
||||
{ TParamHint }
|
||||
|
||||
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
|
||||
constructor Create(TheOwner: TComponent); override;
|
||||
procedure CalculateBounds;
|
||||
procedure UpdateHint;
|
||||
procedure Paint; override;
|
||||
procedure Show(StartPoint,BracketPoint : TPoint;Decl : TciProcedureDeclaration; Editor : TSynedit; mp : TCodeInsight); reintroduce;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
StrUtils {$IFDEF FPC}, lclintf{$ENDIF}, Themes;
|
||||
StrUtils {$IFDEF FPC}, lclintf{$ENDIF},math, Themes;
|
||||
|
||||
procedure TAutoCompleteListBox.setItemList(List: TStrings);
|
||||
begin
|
||||
@ -553,61 +572,391 @@ begin
|
||||
Editor.SetFocus;
|
||||
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);
|
||||
begin
|
||||
inherited;
|
||||
|
||||
{$IFDEF FPC}
|
||||
AutoHide := False;
|
||||
{$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;
|
||||
|
||||
procedure TParamHint.Paint;
|
||||
|
||||
function GetDrawTextFlags: Cardinal;
|
||||
var
|
||||
EffectiveAlignment: TAlignment;
|
||||
MaxWidth,MaxHeight : integer;
|
||||
begin
|
||||
Result := DT_NOPREFIX or DT_VCENTER or DT_WORDBREAK;
|
||||
EffectiveAlignment := Alignment;
|
||||
if BiDiMode <> bdLeftToRight then
|
||||
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;
|
||||
MaxWidth:= ClientWidth;
|
||||
MaxHeight := ClientHeight;
|
||||
DrawHints(MaxWidth,MaxHeight,True);
|
||||
end;
|
||||
|
||||
var
|
||||
ARect: TRect;
|
||||
Details: TThemedElementDetails;
|
||||
procedure TParamHint.Show(StartPoint,BracketPoint: TPoint;Decl : TciProcedureDeclaration; Editor: TSynedit; mp : TCodeInsight);
|
||||
begin
|
||||
ARect := ClientRect;
|
||||
if Color = clInfoBk then // draw using themes
|
||||
begin
|
||||
Details := ThemeServices.GetElementDetails(tttStandardLink);
|
||||
ThemeServices.DrawElement(Canvas.Handle, Details, ARect);
|
||||
end
|
||||
else
|
||||
begin
|
||||
Canvas.Brush.Color := Color;
|
||||
Canvas.Pen.Width := 1;
|
||||
Canvas.FillRect(ARect);
|
||||
DrawEdge(Canvas.Handle, ARect, BDR_RAISEDOUTER, BF_RECT);
|
||||
if self.Visible then
|
||||
self.hide;
|
||||
FDecl := Decl;
|
||||
Fmp := mp;
|
||||
FParameters:= Decl.GetParamDeclarations;
|
||||
if Length(FParameters) = 0 then //Method has no Parameters
|
||||
exit;
|
||||
FSynEdit := Editor;
|
||||
FStartPoint:= StartPoint;
|
||||
FBracketPoint:= BracketPoint;
|
||||
CalculateBounds; //Calculate the size we need!
|
||||
self.Visible := true;
|
||||
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.
|
||||
|
@ -16,6 +16,8 @@ type
|
||||
|
||||
TOnFindInclude = function(Sender: TObject; var FileName: string): Boolean of object;
|
||||
|
||||
{ TCodeInsight }
|
||||
|
||||
TCodeInsight = class(TCodeParser)
|
||||
protected
|
||||
fFileName: string;
|
||||
@ -49,6 +51,7 @@ type
|
||||
function GetFuncType(FuncName, FuncClass: string; out Decl: TDeclaration; Return: TVarBase): Boolean;
|
||||
function FindStruct(s: string; out Decl: TDeclaration; Return: TVarBase; var ArrayCount: Integer): Boolean;
|
||||
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: string; overload;
|
||||
function FindVarBase(s: string; GetStruct: Boolean = False; Return: TVarBase = vbName): TDeclaration;
|
||||
@ -545,7 +548,7 @@ begin
|
||||
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
|
||||
i, StartPos, EndPos: Integer;
|
||||
s: string;
|
||||
@ -636,10 +639,17 @@ begin
|
||||
LastWasDot := False;
|
||||
Dec(StartPos);
|
||||
end;
|
||||
|
||||
sp := startpos + d.StartPos;
|
||||
Result := CompressWhiteSpace(Copy(s, StartPos + 1, EndPos - StartPos));
|
||||
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;
|
||||
var
|
||||
bcc, bkc, cc: Integer;
|
||||
|
Loading…
x
Reference in New Issue
Block a user