diff --git a/Projects/SAMufasaGUI/framescript.pas b/Projects/SAMufasaGUI/framescript.pas index 06ade76..be99ab4 100644 --- a/Projects/SAMufasaGUI/framescript.pas +++ b/Projects/SAMufasaGUI/framescript.pas @@ -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,13 +236,15 @@ begin Form1.ActionFindNextExecute(Sender); key := 0; end; + if key = VK_ESCAPE then + Form1.ParamHint.Hide; Form1.CodeCompletionForm.HandleKeyDown(Sender, Key, Shift); end; procedure TScriptFrame.SynEditKeyPress(Sender: TObject; var Key: char); begin - Form1.CodeCompletionForm.HandleKeyPress(Sender, Key); + Form1.CodeCompletionForm.HandleKeyPress(Sender, Key); end; procedure TScriptFrame.SynEditMouseLink(Sender: TObject; X, Y: Integer; @@ -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 @@ -305,95 +327,100 @@ begin SynEdit.SelectedColor.Background:= clWhite; Synedit.MarkupByClass[TSynEditMarkupHighlightAllCaret].TempDisable; end;} - mp := TCodeInsight.Create; - mp.FileName := ScriptFile; - mp.OnMessage := @Form1.OnCCMessage; - mp.OnFindInclude := @Form1.OnCCFindInclude; + mp := TCodeInsight.Create; + mp.FileName := ScriptFile; + mp.OnMessage := @Form1.OnCCMessage; + mp.OnFindInclude := @Form1.OnCCFindInclude; - ms := TMemoryStream.Create; - ItemList := TStringList.Create; - InsertList := TStringList.Create; - InsertList.Sorted := True; + ms := TMemoryStream.Create; + ItemList := TStringList.Create; + InsertList := TStringList.Create; + InsertList.Sorted := True; - Synedit.Lines.SaveToStream(ms); + Synedit.Lines.SaveToStream(ms); - try - Filter := WordAtCaret(Synedit, sp, ep); - Form1.CodeCompletionStart := Point(sp, Synedit.CaretY); - mp.Run(ms, nil, Synedit.SelStart + (ep - Synedit.CaretX) - 1); + try + Filter := WordAtCaret(Synedit, sp, ep); + Form1.CodeCompletionStart := Point(sp, Synedit.CaretY); + mp.Run(ms, nil, Synedit.SelStart + (ep - Synedit.CaretX) - 1); - s := mp.GetExpressionAtPos; - if (s <> '') then - begin - sp := LastDelimiter('.', s); - if (sp > 0) then - Delete(s, sp, Length(s) - sp + 1) - else - s := ''; - end; - - mp.FillSynCompletionProposal(ItemList, InsertList, s); - p := SynEdit.ClientToScreen(SynEdit.RowColumnToPixels(Point(ep, SynEdit.CaretY))); - p.y := p.y + SynEdit.LineHeight; - Form1.CodeCompletionForm.Show(p, ItemList, InsertList, Filter, SynEdit); - finally - FreeAndNil(ms); - FreeAndNil(mp); - ItemList.Free; - InsertList.Free; + s := mp.GetExpressionAtPos; + if (s <> '') then + begin + sp := LastDelimiter('.', s); + if (sp > 0) then + Delete(s, sp, Length(s) - sp + 1) + else + s := ''; end; - end else - if command = ecCodeHints then - begin - mp := TCodeInsight.Create; - mp.OnMessage := @form1.OnCCMessage; - mp.OnFindInclude := @form1.OnCCFindInclude; - ms := TMemoryStream.Create; - synedit.Lines.SaveToStream(ms); + mp.FillSynCompletionProposal(ItemList, InsertList, s); + p := SynEdit.ClientToScreen(SynEdit.RowColumnToPixels(Point(ep, SynEdit.CaretY))); + p.y := p.y + SynEdit.LineHeight; + Form1.CodeCompletionForm.Show(p, ItemList, InsertList, Filter, SynEdit); + finally + FreeAndNil(ms); + FreeAndNil(mp); + ItemList.Free; + InsertList.Free; + end; + 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; - 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; + ms := TMemoryStream.Create; + synedit.Lines.SaveToStream(ms); + try + Synedit.GetWordBoundsAtRowCol(Synedit.CaretXY, sp, ep); + mp.Run(ms, nil, Synedit.SelStart + (ep - Synedit.CaretX) - 1,true); - bcc := 1; - bck := 0; - cc := 0; - s := mp.GetExpressionAtPos(bcc, bck, cc, True); - if (s <> '') then - Delete(s, Length(s), 1); - - d := mp.FindVarBase(s); - dd := nil; - while (d <> nil) and (d <> dd) and (d.Owner <> nil) and (not ((d is TciProcedureDeclaration) or (d.Owner is TciProcedureDeclaration))) do + 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; + d := d.Owner.Items.GetFirstItemOfClass(TciTypeKind); + if (d <> nil) then begin - dd := d; - d := d.Owner.Items.GetFirstItemOfClass(TciTypeKind); - if (d <> nil) then - begin - d := TciTypeKind(d).GetRealType; - if (d is TciReturnType) then - d := d.Owner; - end; - if (d <> nil) and (d.Owner <> nil) and (not ((d is TciProcedureDeclaration) or (d.Owner is TciProcedureDeclaration))) then - d := mp.FindVarBase(d.CleanText) - else - Break; - end; - 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 := TciTypeKind(d).GetRealType; + if (d is TciReturnType) then d := d.Owner; - if (TciProcedureDeclaration(d).SynParams <> '') then - formWriteln(TciProcedureDeclaration(d).SynParams) - else - FormWriteln(''); end; - finally - FreeAndNil(ms); - FreeAndNil(mp); + if (d <> nil) and (d.Owner <> nil) and (not ((d is TciProcedureDeclaration) or (d.Owner is TciProcedureDeclaration))) then + d := mp.FindVarBase(d.CleanText) + 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).Params <> '') then + Form1.ParamHint.Show(PosToCaretXY(synedit,posi + 1), PosToCaretXY(synedit,bracketpos), + TciProcedureDeclaration(d), synedit,mp) + else + FormWriteln(''); + 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; diff --git a/Projects/SAMufasaGUI/testunit.pas b/Projects/SAMufasaGUI/testunit.pas index 2d6c2fc..751848d 100644 --- a/Projects/SAMufasaGUI/testunit.pas +++ b/Projects/SAMufasaGUI/testunit.pas @@ -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'); diff --git a/Units/Misc/v_autocompleteform.pas b/Units/Misc/v_autocompleteform.pas index 204d3af..cf46c0a 100644 --- a/Units/Misc/v_autocompleteform.pas +++ b/Units/Misc/v_autocompleteform.pas @@ -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) 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.X0) 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 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; +var + MaxWidth,MaxHeight : integer; +begin + 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); - end; - InflateRect(ARect, - 4, - 4); - Canvas.TextOut(ARect.Left, ARect.Top, Caption); + 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; + + +procedure TParamHint.ApplicationIdle(Sender: TObject; var Done: Boolean); +begin + if not Visible then exit; + UpdateHint; end; end. diff --git a/Units/Misc/v_ideCodeInsight.pas b/Units/Misc/v_ideCodeInsight.pas index 57eafb7..9ab8d10 100644 --- a/Units/Misc/v_ideCodeInsight.pas +++ b/Units/Misc/v_ideCodeInsight.pas @@ -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;