Recent

Author Topic: TSynCompletion: Control of starting position  (Read 540 times)

jcfaria

  • New Member
  • *
  • Posts: 16
TSynCompletion: Control of starting position
« on: June 23, 2019, 02:02:47 pm »
Hello,

How can I control the position of the TSynCompletion proposition box?
I do not want it to exceed the window size of the synedit component, because if it is at the edge of the screen, it makes it difficult to see the options.


Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 5637
    • wiki
Re: TSynCompletion: Control of starting position
« Reply #1 on: June 23, 2019, 02:59:52 pm »
Doesn't look like there is a way....

You can overwrite TSynCompletion.GetCompletionFormClass in an inherited class, and return a form class that you can control. But that is at best a workaround.

I have not checked if TSynCompletion checks for screen borders. It should... If it does not, then that needs to be fixed (report on mantis).
That is (not tested), the completion form should not be (partly) outside the visible screen. If needed, it should appear above the text, instead of below.

jcfaria

  • New Member
  • *
  • Posts: 16
Re: TSynCompletion: Control of starting position
« Reply #2 on: June 23, 2019, 04:00:28 pm »
If I can not find a definitive solution, I will try to contact the SynEdit maintainer and suggest this behavior - to respect the limits of the application screen) - as default.

I'm trying to port an app from Delphi to FreePascal. In Delphi - by default - the box position is contained in the application screen.

Lazarus IDE uses the same synEdit component. However, in the IDE the check of boundaries of the screen is made somehow. Does anyone know how to circumvent the problem like in IDE?

lucamar

  • Hero Member
  • *****
  • Posts: 2030
Re: TSynCompletion: Control of starting position
« Reply #3 on: June 23, 2019, 04:49:05 pm »
Let me point that you do have the source for the IDE: You can look inside it yourself.

Just saying ... :)
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.2/2.0.4  - FPC 3.0.4 on:
(K|L)Ubuntu 12..16, Windows XP SP3, various DOSes.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 5637
    • wiki
Re: TSynCompletion: Control of starting position
« Reply #4 on: June 23, 2019, 05:38:45 pm »
If I can not find a definitive solution, I will try to contact the SynEdit maintainer and suggest this behavior - to respect the limits of the application screen) - as default.
That would be me... (with respect to the Lazarus fork)

Quote
Lazarus IDE uses the same synEdit component. However, in the IDE the check of boundaries of the screen is made somehow. Does anyone know how to circumvent the problem like in IDE?
Not exactly.

The SynEdit in Lazarus was forked more than a decade (probably more towards 2 decades) ago. It has since been independently developed.

There is a more recent port: https://wiki.lazarus.freepascal.org/SynEdit#SynEdit_2.0_port
(Also that page may have other valuable info... (logical/physical caret pos))
I have no idea how well that port is maintained....

In the IDE, file ide/SourceEditor.pp, line 124
TSourceEditCompletion=class(TSynCompletion)

I haven't checked it completely, but I think:
TSourceEditCompletion.ccComplete calls Manager.ActiveCompletionPlugin.Complete

And I have not tracked it any further.....

Anyway the point is, in the IDE the plugin does not check itself for the keypress. The IDE does in one of the "UserCommand" events of TSynEdit.
So the IDE can call   TSynBaseCompletion.Execute   with the desired coordinates.

You can do the same: Do not assign a keycombo to the Completion, instead hook the SynEdit event and call Execute yourself.

jcfaria

  • New Member
  • *
  • Posts: 16
Re: TSynCompletion: Control of starting position
« Reply #5 on: June 23, 2019, 06:22:55 pm »
Alo Martin,

Sorry, did not realize it was you who had answered first.  ;)

I am grateful for your work with the synEdit source code!
The quality of this component was one of the main reasons for migrating the Delphi project to Lazarus. The synEdit class is very important for the project in question.

I am grateful also for your enlightening answer on how to get around the problem presented.

Can you post a small illustrative example of the proposed solution?

All the best,

Edson

  • Hero Member
  • *****
  • Posts: 1044
Re: TSynCompletion: Control of starting position
« Reply #6 on: June 23, 2019, 07:14:48 pm »
According to this illustrative document: http://blog.pucp.edu.pe/blog/tito/wp-content/uploads/sites/610/2013/10/la_biblia_del_synedit_-_rev6.pdf if you control the moment the Completion windows appears, you can call the method Execute():

Code: Pascal  [Select]
  1. SynCompletion1: TSynCompletion;
  2. ...
  3. SynCompletion1.Execute('', x, y);
  4.  

And give the coordinates you want.
Lazarus 1.6 - FPC 3.0.0 - x86_64-win64 on  Windows 7

jcfaria

  • New Member
  • *
  • Posts: 16
Re: TSynCompletion: Control of starting position
« Reply #7 on: June 23, 2019, 07:19:19 pm »
Great and thanks!
I will try...

Edson

  • Hero Member
  • *****
  • Posts: 1044
Re: TSynCompletion: Control of starting position
« Reply #8 on: June 23, 2019, 07:24:16 pm »
If you want a more complete completion feature (like integrate with the syntax highlighter or include icons) you can use my library: https://github.com/t-edson/SynFacilCompletion
 
Lazarus 1.6 - FPC 3.0.0 - x86_64-win64 on  Windows 7

jcfaria

  • New Member
  • *
  • Posts: 16
Re: TSynCompletion: Control of starting position
« Reply #9 on: June 23, 2019, 07:35:52 pm »
Great and thanks!
I will try Edson...

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 5637
    • wiki
Re: TSynCompletion: Control of starting position
« Reply #10 on: June 23, 2019, 07:41:37 pm »
Open the editor for SynEdit.KeyStrokes (in OI), and add a new one: ecUserDefined1

Add an event for SynEdit.OnProcessUserCommand  (IIRC, maybe OnProcessCommand)

Code: Pascal  [Select]
  1. procedure TForm1.SynEdit1ProcessUserCommand(Sender: TObject; var Command: TSynEditorCommand;
  2.   var AChar: TUTF8Char; Data: pointer);
  3. begin
  4.   if Command := ecUserDefinedFirst + 1 then begin
  5.     // compute location, and invoke completion
  6.     Command := ecNone; //Handled
  7.   end;
  8. end;
  9.  

Look at TSynCompletion.ProcessSynCommand to see how to invoke.
 You need to copy GetPreviousToken as it is private....



jcfaria

  • New Member
  • *
  • Posts: 16
Re: TSynCompletion: Control of starting position
« Reply #11 on: June 24, 2019, 11:08:58 pm »
Hi Martin,

I did not quite understand the above proposal. ;D

Anyway, based on the previous suggestion, I took a look at the source code of the Lazarus IDE. The solution used by them was adapted into a small function that solved the problem very well.

Take a look and see if you find it useful to incorporate SynEdit source code. I think it will make life easier for users.

Code: Pascal  [Select]
  1. function fGetScreenRect(synEditor: TCustomSynEdit; iCol, iRow: Integer): TRect;
  2. begin
  3.   Result.TopLeft := synEditor.ClientToScreen(synEditor.RowColumnToPixels(Point(iCol,
  4.                                                                                iRow)));
  5.  
  6.   Result.BottomRight := synEditor.ClientToScreen(synEditor.RowColumnToPixels(Point(iCol+1,
  7.                                                                                    iRow+1)));
  8. end;
  9.  

Code: Pascal  [Select]
  1. procedure TmyForm.acCompletionExecute(Sender: TObject);
  2. var
  3.   sTmp: string;
  4.   iLen: integer;
  5.  
  6. begin
  7.   with synCompletion do begin
  8.     Editor:= synEditor;
  9.     LinesInWindow:= 20;
  10.     ItemList:= myList.Itens;
  11.     sTmp:= synEditor.GetWordAtRowCol(synEditor.CaretXY);
  12.     iLen:= Length(sTmp);
  13.     Execute(sTmp,
  14.             fGetScreenRect(synEditor,
  15.                            synEditor.CaretX - iLen,
  16.                            synEditor.CaretY));
  17.   end;
  18. end;
  19.