separating paragraphs

General TRichView support forum. Please post your questions here
Post Reply
alexro
Posts: 8
Joined: Sun Mar 26, 2006 9:10 pm

separating paragraphs

Post by alexro »

I need to visually separate the first paragraph (make it kind of annotation) from the rest of the document. I think to implement this with a line similar to a page break. The problems I'm facing are:

1) how to draw this line
2) how to prevent it from deletion
3) how to update in case first paragraph will be deleted (the line should go after the first available paragraph)

If such line is very complicated (not possible) I will go with changing the first paragraph's background. Maybe other solution exists?

Please advice
Many thanks
Sergey Tkachenko
Site Admin
Posts: 17557
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Post by Sergey Tkachenko »

You can use a paragraph boder - hide all border sides except for the bottom side.
alexro
Posts: 8
Joined: Sun Mar 26, 2006 9:10 pm

Post by alexro »

Yes, this will be sufficient. Could you advice on how to ensure the style is applied to the first paragraph and only to the first paragraph regardless of the document changes?

Is it better to use OnIdle event or trap OnChange?

And how to enumerate the paragraphs?

Many thanks!
Sergey Tkachenko
Site Admin
Posts: 17557
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Post by Sergey Tkachenko »

I am afraid it's not possible to use some style only for the first paragraph.
User can copy-paste or drag&drop it, so you'll need to forbid drag&drop and pasting in RVF and RTF formats. I do not know if it's ok for your application.

You can set NextParaNo property of this heading paragraph style to the index of another paragraph style (for example, to 0). When the user presses Enter key at the end of header, a new paragraph will be added with this style.

Or, probably, you can edit this header in another RichViewEdit (with forbidden d&d and RVF/RTF copying). Something like WinHelp.

About enumerating paragraphs... What exactly do you want to enumerate?
alexro
Posts: 8
Joined: Sun Mar 26, 2006 9:10 pm

Post by alexro »

Sergey Tkachenko wrote: What exactly do you want to enumerate?
I'm looking for something like:

Paragraphs[0].Style:= SpecialStyle;
for I:= 1 to Paragraphs.Count - 1 do
begin
Paragraphs.Style:= GeneralStyle;
end

This will solve copy/pasting/dragging issue ...
Sergey Tkachenko
Site Admin
Posts: 17557
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Post by Sergey Tkachenko »

List of all paragraph attributes in document is RVStyle.ParaStyles collection.
MLefebvre
Posts: 191
Joined: Mon Aug 29, 2005 4:28 pm
Location: France
Contact:

Post by MLefebvre »

Few (alternative) suggestions :

1/ If your need is only at visual level, you might use the RVStyle.OnDrawStyleText / OnDrawParaBack events, to draw an additional horizontal line after the first paragraph whatever it is. To find the end of 1st paragraph, just loop on RV items and check IsParaStart(i). This may be used when printing as well.

2/ If you want to introduce a logical difference in this 1st paragraph, another solution is to insert a 1x1 table at the start of the document (with bottom border only), make this table non-deletable, and use a "do-not-want returns" style in the cell. You will have also to prevent from inserting anything before the table (using the OnChanging event). A drawback there is that this introduces a definite limit between the document "header" and the rest, that the end user will have to know about. Also, introducing Tables requires some more knowledge of RV if you have not done that before.

3/ Applying a specific para style to the 1st paragraph in all cases is more complex. May be you can do this in the OnChange event :
- Freeze display update
- Save caret location (see functions in RVLinear.pas)
- Select start of item 0 (with SetSelectionBounds)
- Disable onChange temporarily (or use BeginUpdate)
- ApplyParaStyle (SpecificParaStyle)
- Re-enable OnChange (or EndUpdate)
- Restore saved caret location
- Unfreeze and update display
Yet there is a remaining problem with the Undo. Ideally you should embed the user action and the complementary change above in one single Undo group so that they cannot be undone individually. And unfortunately I have not found a 100% safe solution for that (except disabling the Undo, which is a pity).

I hope this will help.
alexro
Posts: 8
Joined: Sun Mar 26, 2006 9:10 pm

Post by alexro »

MLefebvre wrote:Few (alternative) suggestions
No 1 is exactly what I want.

But I'm a bit lost: in DrawParaBack ParaNo is always 0, so it cant point to the first paragraph. And if I find the first paragraph looping through RVData.ItemCount/RVData.GetItem, how I get its canvas to draw a line?


Many thanks!
MLefebvre
Posts: 191
Joined: Mon Aug 29, 2005 4:28 pm
Location: France
Contact:

Post by MLefebvre »

ParaNo is not the paragraph number in the document, it is the index of the paragraph style that applies to the considered RV item.

Anyway I apologize, OnDrawParaBack is not the solution by itself, since it gives no information on the source item being drawn. Here is what I can suggest :
- Define a global int variable LastItemOf1stPara
- Create a procedure to update this variable :

Code: Select all

   LastItemOf1stPara := 0;
   with MyRV do
     while (LastItemOf1stPara < ItemCount-1)
       and not IsParaStart(LastItemOf1stPara+1) do
            Inc(LastItemOf1stPara);
- Call this procedure after you set up the initial content, and within the OnChange event.
- In the OnDrawStyleText, check whether Sender.ItemNo is equal to LastItemOf1stPara, and if so draw your line at Top+Height.

I hope this will help (yet probably Sergey could suggest a much smarter solution ...)
Sergey Tkachenko
Site Admin
Posts: 17557
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Post by Sergey Tkachenko »

OnDrawParaBack has hidden parameters
Sender.RVData and Sender.ItemNo define the last item in the drawn paragraph.
Example using these parameters:
http://www.trichview.com/forums/viewtopic.php?t=60
alexro
Posts: 8
Joined: Sun Mar 26, 2006 9:10 pm

Post by alexro »

It turned out to be less complicated as I thought initially:

procedure TrvActionsResource.txtStyleDrawParaBack(Sender: TRVStyle; Canvas: TCanvas; ParaNo: Integer; ARect: TRect; var DoDefault: Boolean);
var
I: Integer;
Data: TRichViewRVData;
begin

Data:= TRichViewRVData(Sender.RVData);
for I:= 1 to Data.ItemCount - 1 do
begin
if Data.IsParaStart(I) then
Break;
end;
if Sender.ItemNo < I then
begin
Canvas.Brush.Color:= $f5f5f5;
Canvas.FillRect(ARect);
Canvas.MoveTo(ARect.Left, ARect.Bottom);
Canvas.LineTo(ARect.Right, ARect.Bottom);
end

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

Post by Sergey Tkachenko »

It's ok, but some comments.
1) Sender.RVData is not neccessary TRichViewRVData (it's not so for cells). It's better to typecast it to TCustomRVData.
2) While it works, it's better to avoid using a for-loop variable (I) after the cycle.
Post Reply