Page 1 of 2

How to find first visible item in editor?

Posted: Thu Jul 20, 2023 4:35 pm
by dakota
Hi,

I need to know what the first visible paragraph is in a richview editor. For instance, for a TRichEdit, it would do

iFirstVisible := ARichEdit.Perform(EM_GETFIRSTVISIBLELINE, 0, 0,);

How can I get this information from a TRichViewEdit?

Thanks.

Dale

Re: How to find first visible item in editor?

Posted: Thu Jul 20, 2023 6:21 pm
by standay
This might be what you want:

Code: Select all

  FirstVisItemNo := rve.FirstItemVisible;
  LastVisItemNo := rve.LastItemVisible;

  FirstVisParaNo := rve.GetItemPara(FirstVisItemNo);
  LastVisParaNo := rve.GetItemPara(LastVisItemNo);
Stan

Re: How to find first visible item in editor?

Posted: Thu Jul 20, 2023 6:55 pm
by dakota
Thanks Stan!

It almost works. It does not seem to be consistent. If line 1 or 2 are at the top, it will still return 0, then if line three is at the top, it will return 1.

I'm trying to draw line numbers next to the editor.

Dale

Re: How to find first visible item in editor?

Posted: Thu Jul 20, 2023 7:37 pm
by Sergey Tkachenko
rve.FirstItemVisible returns the index of the first visible item.
An item is a document objects (text, picture, etc.). One line may contain several items, one text item may occupy several lines.

rve.GetItemPara returns information about paragraph attributes (an index in the collection rve.Style.ParaStyles). This is not what you need for drawing line numbers.

The main problem with line numbers: TRichView does not store them. Every time you need a line number, you need to calculate it (in a cycle from the beginning to the given document position).

I'll make a demo in the next couple of days.

PS: In ScaleRichView, line numbers is a bult-in feature, https://www.trichview.com/help-scaleric ... operty.htm

Re: How to find first visible item in editor?

Posted: Thu Jul 20, 2023 8:12 pm
by standay
Dakota, OK. With the regular richview editor which is what I use, getting paragraph numbers is easy, line numbers are much more involved. Maybe Sergey can come up with a demo that will work!

Stan

Re: How to find first visible item in editor?

Posted: Thu Jul 20, 2023 8:50 pm
by dakota
It's just basically a simple text editor for writing small scripts for our application (like a very basic code editor). Word wrapping is turned off so every line is a paragraph. I can write the numbers beside the editor using Canvas.TextOut, but I need to know what the first line (paragraph) is so that I know where to start numbering.

Thanks,

Dale

Re: How to find first visible item in editor?

Posted: Thu Jul 20, 2023 9:05 pm
by standay
This might work:

Code: Select all

  FirstVisItemNo := rve.FirstItemVisible;
  LastVisItemNo := rve.LastItemVisible;
  LineNum := rve.GetLineNo(FirstVisItemNo ,0);

  for i := FirstVisItemNo to LastVisItemNo do
  //draw LineNum + 1...
You might have issues if there is formatted text in a line.

Stan

Re: How to find first visible item in editor?

Posted: Fri Jul 21, 2023 2:34 pm
by dakota
Hi Stan,

The problem is that rve.FirstItemVisible is not giving me the correct results. In the example below it should return 4 but instead returns 2. Maybe I should be looking through the paragraphs and testing if their XY location falls in the document space (not quite sure how to do that yet but I think I can figure it out.). Seems like an inefficient approach but my little editor will usually only contain less than 200 lines.

Image

Dale

Re: How to find first visible item in editor?

Posted: Fri Jul 21, 2023 3:07 pm
by dakota
This is brute force, but it might work. This gives me the item number, and where it is. I can then test it to make sure it is on the document, and as an added bonus, since I have the coordinates, I can do a little math to make sure that my linenumbers line up properly where I print them outside of the editor. I probably need to clean up a few things but I think the basic idea shows promise.

Code: Select all

procedure TForm1.bntListVisibleClick(Sender: TObject);
var
  i:            integer;
  iDocX:        integer;
  iDocY:        integer;
  sRange:       string;
begin
  rvEditor.Format;
  Memo2.Clear;

  for i := 0 to rvEditor.ItemCount - 1 do begin
    if rvEditor.GetItemClientCoords(i, iDocX, iDocY) then begin
      if iDocY < 0 then begin
        sRange := ' too low';
      end else if iDocY > rvEditor.ClientHeight then begin
        sRange := ' too high';
      end else begin
        sRange := '';
      end;

      Memo2.Lines.Add('Item ' + IntToStr(i) + ' DocX: ' + IntToStr(iDocX) + '  DocY: ' + IntToStr(iDocY) + sRange);

    end else begin
      Memo2.Lines.Add('Item ' + IntToStr(i) + ' -------');
    end;
  end;
end;

Re: How to find first visible item in editor?

Posted: Fri Jul 21, 2023 3:11 pm
by standay
Well, I think the number returned by rve.GetLineNo(FirstVisItemNo ,0) is zero based so you have to add "1" to get a 1-based line number. Looks like you got that working.

FirstVisItemNo is the item number, not line number, there's no correlation between them. Item numbers are not line numbers which is why you have to call GetLineNo.

The rve stuff works very differently than the TRichText component. I had used rich text calls for a long time before I used the rve so it took me a while to get my head aound how it works!

I kept at it because the rve does a great job of text formatting once you get it working, and it handles images really well. I tried all sorts of things before settling on the rve.

Stan

Re: How to find first visible item in editor?

Posted: Fri Jul 21, 2023 3:16 pm
by standay
Also, I think item numbers are zero based as well. So, I would expect that line #4 to come back as item #3. So, you might need to adjust your first item value in the printout on the right. When I do something like you show in my app I get:
Image11.png
Image11.png (1.05 KiB) Viewed 32045 times
When I mouse over that text, the item on line 4 is item #3 in my statusbar. That's because I'm NOT adding 1 to the item number value. The first line item is 0, the next 1, the next 2, and the last 3. (sorry, had to edit this!)

Stan

Re: How to find first visible item in editor?

Posted: Fri Jul 21, 2023 3:57 pm
by dakota
Hi Stan,

I don't have any issues with it being zero based. The problem is when line 0 (or what I am calling the first line), rve.FIrstItemVisible returns 0, but when I then scroll so that line 1 is at the top, it still returns 0. Then when 2 is at the top, still 0, then it finally starts incrementing once 3 is at the top (row 3 returns 1, row 4 returns 2 etc.). I have no idea why.

I also realize that Items can be anything. In my editor, each paragraph is a line (no wordwrapping). I guess I need to figure out how to loop through paragraphs. I can then get their x,y location and test where it is on the document canvas. I'm getting there.

Dale

Re: How to find first visible item in editor?

Posted: Fri Jul 21, 2023 4:43 pm
by standay
That's really odd. I tried it and it works as expected.

Well, if you want to attach a zip of your project I'd take a look at it and see if I can see something. Otherwise, I don't know. Very strange.

Re: How to find first visible item in editor?

Posted: Fri Jul 21, 2023 5:40 pm
by dakota
Stan!

I'm really, really embarrassed! I've been programming for decades and I made the newbie mistake of getting a variable mixed up in my test routine. I was looking at bad data all along. FirstItemVisible is working now (and useful?). I found it when I was making a little demo for you. That's what happens when you rush to meet a deadline.

Thanks for your help with this.

Dale

Re: How to find first visible item in editor?

Posted: Fri Jul 21, 2023 6:54 pm
by standay
Been there, done that! Thanks for the update. I was beginning to think I'd lost what little is left of my mind!

Stan