| View previous topic :: View next topic |
| Author |
Message |
Sergey Tkachenko Site Admin
Joined: 27 Aug 2005 Posts: 9854
|
Posted: Tue Sep 25, 2007 10:13 am Post subject: [Example] Smart indent |
|
|
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 |
|
 |
Sergey Tkachenko Site Admin
Joined: 27 Aug 2005 Posts: 9854
|
Posted: Tue Oct 23, 2007 8:43 am Post subject: |
|
|
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 |
|
 |
jonjon
Joined: 27 Aug 2005 Posts: 211
|
Posted: Wed Jul 04, 2012 2:23 pm Post subject: |
|
|
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 |
|
 |
Sergey Tkachenko Site Admin
Joined: 27 Aug 2005 Posts: 9854
|
Posted: Thu Jul 05, 2012 11:47 am Post subject: |
|
|
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 |
|
 |
jonjon
Joined: 27 Aug 2005 Posts: 211
|
Posted: Thu Jul 05, 2012 12:17 pm Post subject: |
|
|
| 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 |
|
 |
Sergey Tkachenko Site Admin
Joined: 27 Aug 2005 Posts: 9854
|
Posted: Fri Jul 13, 2012 8:49 am Post subject: |
|
|
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 |
|
 |
|
|
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
|