Show Selection on Empty Lines

General TRichView support forum. Please post your questions here
Post Reply
standay
Posts: 274
Joined: Fri Jun 18, 2021 3:07 pm

Show Selection on Empty Lines

Post by standay »

Hi Sergey,

When working with a regular rve I've noticed if I have empty lines selected there is no visual feedback to tell you that. So, here are 2 examples of how it works normally:

Middle lines are actually selected
Middle lines are actually selected
Image1.png (3.18 KiB) Viewed 4305 times
All lines selected, middle lines don't show selection
All lines selected, middle lines don't show selection
Image3.png (3.46 KiB) Viewed 4305 times

What I'm used to is this with the same 2 examples showing all the selection areas:

Middle lines are selected; selection shown
Middle lines are selected; selection shown
Image2.png (3.21 KiB) Viewed 4305 times
All lines selected, middle lines DO show selection
All lines selected, middle lines DO show selection
Image4.png (3.56 KiB) Viewed 4305 times

I put some code in my rve's paint method (see below) and have it working. Maybe it will help others wanting to do the same thing.

However...

My questions are:

- Is there already a built-in way of doing this that I've missed? Some option or property?
If not, then
- Does the code I wrote (below) seem reasonable?
- Note that I draw the "pilcrow" symbol (¶) "manually" since my paint code "overwrites" the built-in ¶ in empty lines.
Image showing special chars visible
Image showing special chars visible
Image5.png (4.39 KiB) Viewed 4305 times
- Can you tell me where in the source you are drawing that ¶ symbol when rvscParagraph is in RVVisibleSpecialCharacters and they are being shown? I'm not sure what I've done will work in all circumstances and I think I'd be better off replicating whatever it is you're doing.

Thanks Sergey

Code: Select all

procedure TForm1.rvePaint(Sender: TCustomRichView; ACanvas: TCanvas;
  Prepaint: Boolean);
var
  i, YOffSet: integer;
  FStart, FSOff, FEnd, FEoff: integer;
  DItemStart, DOffStart, DItemEnd, DOffEnd: integer;
  DItem: TRVDrawLineInfo;
  r: TRect;
begin

  if Sender.ItemCount = 0 then exit;

  try

    //Selection Area Marker (vertical line in rve left margin at empty lines)
    if ShowSelMarker1.Checked and Sender.SelectionExists then 
    begin

      //Get current selection:
      Sender.GetSelectionBounds(FStart, FSOff, FEnd, FEoff, true);

      //Convert start/end items to DrawItems:
      Sender.RVData.Item2DrawItem(FStart,FSOff,DItemStart,DOffStart);
      Sender.RVData.Item2DrawItem(Fend,FEoff,DItemEnd,DOffEnd);

      //Draw selection color on any empty DrawItem lines
      for i := DItemStart to DItemEnd do
      begin

        DItem := Sender.RVData.DrawItems[i];
        r.Left := Sender.LeftMargin - 1;
        r.Right := r.Left + 6;

        YOffSet := ( Sender.VScrollPos * Sender.VSmallStep );
        r.Top := DItem.Top - YOffSet;
        r.Bottom := DITem.Top + DItem.Height  - YOffSet;

        ACanvas.Brush.Color := Sender.Style.SelColor;

        //DrawItem is empty:
        if (DItem.TextLength = 0) and //not an image:
           (Sender.GetItemStyle(DItem.ItemNo) = rvsNormal ) then
        begin
          ACanvas.FillRect(r);
          if (rvoShowSpecialCharacters in Sender.Options) and
             (rvscParagraph in RVVisibleSpecialCharacters) then
          begin

            ACanvas.Font.Size :=
              Sender.Style.TextStyles[Sender.GetItemStyle(DItem.ItemNo)].Size;
            ACanvas.Font.Name :=
              Sender.Style.TextStyles[Sender.GetItemStyle(DItem.ItemNo)].FontName;
            ACanvas.Font.Charset := DEFAULT_CHARSET;
            ACanvas.Font.Color := Sender.Style.SpecialCharactersColor;

            r.Right := r.Left + ACanvas.TextWidth(chr(182)); //chr(182) = '¶'
            ACanvas.FillRect(r);

            ACanvas.Brush.Style := bsClear;
            ACanvas.TextOut(r.Left,r.Top,chr(182));

          end;

        end;

      end;

    end;
...
Sergey Tkachenko
Site Admin
Posts: 17566
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Re: Show Selection on Empty Lines

Post by Sergey Tkachenko »

There are no standard way to display empty selected lines.
Pilcrow symbols are drawn in DrawParaMark procedure (which is inside TCustomRVFormattedData.PaintTo, in CRVFData.pas).

If the code works, I believe it's ok.
Sender.GetItemStyle(DItem.ItemNo) = rvsNormal
can be changed to
Sender.GetItemStyle(DItem.ItemNo) >= 0
to support all text items.
standay
Posts: 274
Joined: Fri Jun 18, 2021 3:07 pm

Re: Show Selection on Empty Lines

Post by standay »

Hi Sergey,

Thanks for the info. I looked at DrawParaMark and, as I suspected, there is a lot more going on in there than I'd want to try and replicate.

So, if I have special chars showing, I move my selection drawing into the left margin so I don't "stomp" on the special chars. When special chars are off (which is most of the time), I show the selection starting at the left margin 5px wide as before. Since I'm only interested in marking the empty lines, while not ideal, this will work. I want to keep it fairly simple to maintain!

Image21.png
Image21.png (6.56 KiB) Viewed 4173 times
Image22.png
Image22.png (5.64 KiB) Viewed 4173 times
Thanks again

Stan

Code: Select all

      //Get current selection:
      Sender.GetSelectionBounds(FStart, FSOff, FEnd, FEoff, true);

      //Convert start/end items to DrawItems:
      Sender.RVData.Item2DrawItem(FStart,FSOff,DItemStart,DOffStart);
      Sender.RVData.Item2DrawItem(Fend,FEoff,DItemEnd,DOffEnd);

      //Draw selection color on any empty DrawItem lines
      for i := DItemStart to DItemEnd do
      begin

        DItem := Sender.RVData.DrawItems[i];
        r.Left := Sender.LeftMargin - 1;
        r.Right := r.Left + 6;

        if (rvoShowSpecialCharacters in Sender.Options) and
           (rvscParagraph in RVVisibleSpecialCharacters) then
        begin
          r.Left := 0;
          r.Right := r.Left + Sender.LeftMargin - 1;
        end;

        YOffSet := ( Sender.VScrollPos * Sender.VSmallStep );
        r.Top := DItem.Top - YOffSet;
        r.Bottom := DITem.Top + DItem.Height  - YOffSet;

        ACanvas.Brush.Color := Sender.Style.SelColor;

        //DrawItem is empty:
        if (DItem.TextLength = 0) and //not an image:
           (Sender.GetItemStyle(DItem.ItemNo) >= 0 ) then
          ACanvas.FillRect(r);
         ...
         
Post Reply