trichview.com Forum Index trichview.com
TRichView support forums
 

[Example] Smart indent


 
Post new topic   Reply to topic    trichview.com Forum Index -> Examples, Demos
    View previous topic :: View next topic  
Author Message
Sergey Tkachenko
Site Admin


Joined: 27 Aug 2005
Posts: 10717

PostPosted: Tue Sep 25, 2007 10:13 am    Post subject: [Example] Smart indent Reply with quote

Smart indent, programming style

When user presses Enter key, this code adds space characters at the beginning of new paragraph (as many spaces as at the beginning of the current paragraph).
Code:
// Returns count of space characters at the beginning of the current paragraph
function GetLeadingSpacesCount(rve: TCustomRichViewEdit): Integer;
var StartItemNo, ItemNo, i: Integer;
    s: String;
begin
  rve := rve.TopLevelEditor;
  ItemNo := rve.CurItemNo;
  while not rve.IsParaStart(ItemNo) do
    dec(ItemNo);
  Result := 0;
  StartItemNo := ItemNo;
  while ItemNo<rve.ItemCount do begin
    if (ItemNo>StartItemNo) and rve.IsParaStart(ItemNo) then
      exit;
    if rve.GetItemStyle(ItemNo)<0 then
      exit;
    s := rve.GetItemText(ItemNo);
    for i := 1 to Length(s) do
      if s[i]=' ' then
        inc(Result)
      else
        exit;
    inc(ItemNo);
  end;
end;

// Returns string consisting of Count space characters
function GetSpaces(Count: Integer): String;
var i: Integer;
begin
  SetLength(Result, Count);
  for i := 1 to Count do
    Result[i] := ' ';
end;

// OnKeyDown, indenting
procedure TForm1.RichViewEdit1KeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if Key=VK_RETURN then begin
    RichViewEdit1.InsertText(#13+GetSpaces(GetLeadingSpacesCount(RichViewEdit1)));
    Key := 0;
  end;
end;


Possibility to improve: when pressing Enter in the middle of paragraph, calculate how many space characters are to the right of the caret (so they will be at the beginning of the new paragraph) and take them into account.

2008-Dec-11: Updated for compatibility with TRichView 11 and Delphi 2009


Last edited by Sergey Tkachenko on Thu Dec 11, 2008 3:54 pm; edited 2 times in total
Back to top
View user's profile Send private message Visit poster's website
Sergey Tkachenko
Site Admin


Joined: 27 Aug 2005
Posts: 10717

PostPosted: Tue Oct 23, 2007 8:43 am    Post subject: Reply with quote

Smart indent/unindent, MS Word style

This code changes FirstIndent and LeftIndent of paragraph, if Tab/Backspace is pressed when the caret is at the beginning of paragraph. First, it changes FirstIndent. Next, if FirstIndent is already changed, it changes LeftIndent.
This code changes indents only if the caret is at the beginning of non-empty paragraph.

When the caret is at the beginning of a bulleted/numbered paragraph, Tab increases the list level.

This code uses its own procedures for OnParaStyleConversion event. Of course, you can integrate this code in existing event handler instead. But in this way, it's easy to integrate this code in existing application, even if it uses RichViewActions.

Code:
// Procedure for OnParaStyleConversion event.
// Changes paragraph's FirstIndent to UserData
procedure TForm3.ChangeFirstIndentConversion(Sender: TCustomRichViewEdit;
  StyleNo, UserData: Integer; AppliedToText: Boolean;
  var NewStyleNo: Integer);
var ParaStyle: TParaInfo;
begin
  ParaStyle := TParaInfo.Create(nil);
  ParaStyle.Assign(Sender.Style.ParaStyles[StyleNo]);
  ParaStyle.FirstIndent := UserData;
  ParaStyle.Standard := False;
  NewStyleNo := Sender.Style.ParaStyles.FindSuchStyle(StyleNo, ParaStyle,
    RVAllParaInfoProperties);
  if NewStyleNo<0 then begin
    Sender.Style.ParaStyles.Add.Assign(ParaStyle);
    NewStyleNo := Sender.Style.ParaStyles.Count-1;
  end;
  ParaStyle.Free;
end;

// Procedure for OnParaStyleConversion event.
// Changes paragraph's LeftIndent to UserData
// If UserData=0, resets FirstIndent as well.
procedure TForm3.ChangeLeftIndentConversion(Sender: TCustomRichViewEdit;
  StyleNo, UserData: Integer; AppliedToText: Boolean;
  var NewStyleNo: Integer);
var ParaStyle: TParaInfo;
begin
  ParaStyle := TParaInfo.Create(nil);
  ParaStyle.Assign(Sender.Style.ParaStyles[StyleNo]);
  ParaStyle.LeftIndent := UserData;
  if ParaStyle.LeftIndent=0 then
    ParaStyle.FirstIndent := 0;
  ParaStyle.Standard := False;
  NewStyleNo := Sender.Style.ParaStyles.FindSuchStyle(StyleNo, ParaStyle,
    RVAllParaInfoProperties);
  if NewStyleNo<0 then begin
    Sender.Style.ParaStyles.Add.Assign(ParaStyle);
    NewStyleNo := Sender.Style.ParaStyles.Count-1;
  end;
  ParaStyle.Free;
end;
 
function TForm3.ChangeIndent(rve: TCustomRichViewEdit;
  Step, Max: Integer): Boolean;
var OldParaStyleConversion: TRVStyleConversionEvent;
    FirstIndent, LeftIndent: Integer;
    ListNo, ListLevel, StartFrom: Integer;
    Reset: Boolean;
begin
  Result := False;
  OldParaStyleConversion := rve.OnParaStyleConversion;
  try
    rve := rve.TopLevelEditor;
    if rve.SelectionExists then
      exit;
    if (Step>0) and (rve.OffsetInCurItem<=rve.GetOffsBeforeItem(rve.CurItemNo)) and
       (rve.CurItemNo>0) and (rve.GetItemStyle(rve.CurItemNo-1)=rvsListMarker) then begin
       // changing list level
       rve.GetListMarkerInfo(rve.CurItemNo, ListNo, ListLevel, StartFrom, Reset);
       if (ListNo>=0) and (ListNo<rve.Style.ListStyles.Count) and
          (ListLevel+1<rve.Style.ListStyles[ListNo].Levels.Count) then begin
         rve.ChangeListLevels(+1);
         Result := True;
       end;
       exit;
    end;

    if (rve.OffsetInCurItem>rve.GetOffsBeforeItem(rve.CurItemNo)) or
      not rve.IsParaStart(rve.CurItemNo) then
      exit; // not at the beginning of paragraph
    if (rve.OffsetInCurItem>=rve.GetOffsAfterItem(rve.CurItemNo)) and
      ((rve.CurItemNo=rve.ItemCount-1) or rve.IsParaStart(rve.CurItemNo)) then
      exit; // empty paragraph, exiting
    FirstIndent := rve.Style.ParaStyles[rve.GetItemPara(rve.CurItemNo)].FirstIndent;
    LeftIndent  := rve.Style.ParaStyles[rve.GetItemPara(rve.CurItemNo)].LeftIndent;
    if Step>0 then begin
      if FirstIndent=0 then begin
        rve.OnParaStyleConversion := ChangeFirstIndentConversion;
        rve.ApplyParaStyleConversion(Step);
        Result := True;
        end
      else begin
        inc(LeftIndent, Step);
        if LeftIndent>Max then
          LeftIndent := Max;
        if LeftIndent>rve.Style.ParaStyles[rve.GetItemPara(rve.CurItemNo)].LeftIndent then begin
          rve.OnParaStyleConversion := ChangeLeftIndentConversion;
          rve.ApplyParaStyleConversion(LeftIndent);
          Result := True;
        end;
      end
      end
    else begin
     if FirstIndent>0 then begin
        rve.OnParaStyleConversion := ChangeFirstIndentConversion;
        rve.ApplyParaStyleConversion(0);
        Result := True;
        end
      else begin
        inc(LeftIndent, Step);
        if LeftIndent<0 then
          LeftIndent := 0;
        if (LeftIndent<rve.Style.ParaStyles[rve.GetItemPara(rve.CurItemNo)].LeftIndent) or
           (FirstIndent<>0) then begin
          rve.OnParaStyleConversion := ChangeLeftIndentConversion;
          rve.ApplyParaStyleConversion(LeftIndent);
          Result := True;
        end;
      end;
    end;
  finally
    rve.OnParaStyleConversion := OldParaStyleConversion;
  end;
end;
 
// OnKeyDown event
procedure TForm3.RichViewEdit1KeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if (Key=VK_BACK) and ChangeIndent(TCustomRichViewEdit(Sender), -48, 480) then
    Key := 0;
end;

// OnKeyPress event
procedure TForm3.RichViewEdit1KeyPress(Sender: TObject; var Key: Char);
begin
  if (Key=#9) and ChangeIndent(TCustomRichViewEdit(Sender), +48, 480) then
    Key := #0;
end;


Upd: 2011-Jun-26: changing list levels on Tab
Back to top
View user's profile Send private message Visit poster's website
jonjon



Joined: 27 Aug 2005
Posts: 224

PostPosted: Wed Jul 04, 2012 2:23 pm    Post subject: Reply with quote

Sergey,

I've added this code and it seems to be working fine however I'm missing the SHIFT-TAB feature, available in Word, to un-indent.
Can it be easily added to your sample ?

Thanks.
Back to top
View user's profile Send private message
Sergey Tkachenko
Site Admin


Joined: 27 Aug 2005
Posts: 10717

PostPosted: Thu Jul 05, 2012 11:47 am    Post subject: Reply with quote

This code unindents on BACKSPACE.
To add SHIFT+TAB, change

Code:
// OnKeyPress event
procedure TForm3.RichViewEdit1KeyPress(Sender: TObject; var Key: Char);
var step: Integer;
begin
  if Key=#9 then begin
    step := 48;
    if GetAsyncKeyState(VK_SHIFT)and$8000<>0 then
      step := -step;
    if ChangeIndent(TCustomRichViewEdit(Sender), step, 480) then
      Key := #0;
  end;
end;
Back to top
View user's profile Send private message Visit poster's website
jonjon



Joined: 27 Aug 2005
Posts: 224

PostPosted: Thu Jul 05, 2012 12:17 pm    Post subject: Reply with quote

Thanks Sergey but I can't get it to work on 13.10: TAB is working fine, Shift-Tab/Delete isn't. It looks like rve.IsParaStart is always returning false.
Back to top
View user's profile Send private message
Sergey Tkachenko
Site Admin


Joined: 27 Aug 2005
Posts: 10717

PostPosted: Fri Jul 13, 2012 8:49 am    Post subject: Reply with quote

Sorry, I cannot reproduce this problem. I added TForm3.ChangeFirstIndentConversion and the code
Code:
procedure TForm3.RichViewEdit1KeyPress(Sender: TObject; var Key: Char);
var step: Integer;
begin
  if Key=#9 then begin
    step := 48;
    if GetAsyncKeyState(VK_SHIFT)and$8000<>0 then
      step := -step;
    if ChangeIndent(TCustomRichViewEdit(Sender), step, 480) then
      Key := #0;
  end;
end;

in the ActionTest project, and it works on Tab and Shift+Tab as expected.

Note that this procedure works only in non-empty paragraphs, like in MS Word.
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    trichview.com Forum Index -> Examples, Demos All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group