📄 rvruler.pas
字号:
{*******************************************************}
{ }
{ TRVRuler: ruler for TRichViewEdit }
{ Inherited from TRuler by Pieter Zijlstra. }
{ Created by Sergey Tkachenko, basing on example }
{ code by Pieter Zijlstra. }
{ }
{ Sergey Tkachenko }
{ svt@trichview.com }
{ http://www.trichview.com }
{ }
{ Pieter Zijlstra }
{ p.zylstra@hccnet.nl }
{ http://home.hccnet.nl/p.zylstra/ }
{ }
{*******************************************************}
{ --------------------------------------------------------------------------
v1.1.1.0
v1.4.0.0 - changed LeftInset to Inset
v1.5.0.0 - added TableEditor
v1.6.0.0 - added tabs
v1.7.0.0 - improved table resizing
- added support for Bullets & Numbering.
v1.7.1.0 - Fix: the local OnCaretMove did not call the old handler.
v1.7.3.0 - Added two extra checks to see if FRichViewEdit is valid.
v1.7.5.0 - Added support for handling ruler in vertical mode.
New: property RVRulerOptions.
v1.7.5.1 - Minor code optimizations.
- Scroll document when top or bottom margin has changed so that the
document lines-up with the new top or bottom margin position.
v1.7.5.2 - Added On***Click event handlers.
v1.7.5.3 - New: RVRulerItemSelector, this is a component for selecting the
type of tab to be used when new tabs are added.
--------------------------------------------------------------------------
What does this ruler change:
- Left, first, right indents of the selected paragraphs
- RichViewEdit.LeftMargin, .RightMargin. Note: they are not paper margins,
they are "padding" of printable area.
- If rvoClientTextWidth is not in RichViewEdit.Options, it changes
RichViewEdit.MaxTextWidth and RichViewEdit.MinTextWidth. Note: they do
not affect printing.
--------------------------------------------------------------------------
Not implemented yet:
- ...
Working with TDBRichViewEdit is not tested.
--------------------------------------------------------------------------
Properties:
RichViewEdit: TCustomRichViewEdit - attached editor;
LineStyle: TPenStyle - style of lines.
Methods:
UpdateRulerIndents - updates ruler's indents from RichViewEdit.
Rarely needs to be called.
UpdateRulerMargins - updates ruler's margins from RichViewEdit
Must be called when margins of editor were changed, for example, after
reading RVF file.
--------------------------------------------------------------------------
Technical notes:
This component changes the following events of the assigned RichViewEdit:
OnCaretMove, OnHScrolled, OnVScrolled, OnResize, OnCurParaStyleChanged.
Its handlers for these events call old handlers. But you must not change
these events at run time after Ruler.RichViewEdit has been assigned.
}
unit RVRuler;
interface
{$I RV_Defs.inc}
uses
Windows, Classes, Graphics, Controls,
Ruler,
RVStyle, RVScroll, RichView, RVEdit,
RVItem, RVTable, RVMarker;
type
TRVRulerOption = (
rvroAutoAdjustInset,
rvroAutoAdjustMargins
);
TRVRulerOptions = set of TRVRulerOption;
const
DefaultRVRulerOptions = [rvroAutoAdjustInset, rvroAutoAdjustMargins];
type
TRVRuler = class(TRuler)
private
FControlCanvas: TControlCanvas;
FFirstIndent, FLeftIndent, FRightIndent: Integer;
FLineStyle: TPenStyle;
FRichViewEdit: TCustomRichViewEdit;
FRVEOldCaretMove,
FRVEOldHScrolled,
FRVEOldVScrolled,
FRVEOldResize,
FRVEOldCurParaStyleChanged: TNotifyEvent;
FSaveX: Integer;
FUpdating, FUpdatingTabs: Boolean;
FRulerInset: Integer;
FRVRulerOptions: TRVRulerOptions;
procedure AssignRichViewEditEvents;
procedure DrawMarkLine;
function GetListIndents(var FI, LI: Extended): Boolean;
procedure RichViewEditCaretMove(Sender: TObject);
procedure RichViewEditCurParaStyleChanged(Sender: TObject);
procedure RichViewEditHScrolled(Sender: TObject);
procedure RichViewEditVScrolled(Sender: TObject);
procedure RichViewEditParaStyleConversion(Sender: TCustomRichViewEdit;
StyleNo, UserData: Integer; AppliedToText: Boolean; var NewStyleNo: Integer);
{$IFDEF RICHVIEWDEF4}
procedure RichViewEditResize(Sender: TObject);
{$ENDIF}
procedure RestoreRichViewEditEvents;
procedure SetRichViewEdit(const Value: TCustomRichViewEdit);
procedure SetRVRulerOptions(const Value: TRVRulerOptions);
protected
procedure DoBiDiModeChanged; override;
procedure DoIndentChanged; override;
procedure DoLevelButtonUp(Direction: Integer); override;
procedure DoMarginChanged; override;
procedure DoTabChanged; override;
procedure DoRulerItemMove(X: Integer; Removing: Boolean); override;
procedure DoRulerItemRelease; override;
procedure DoRulerItemSelect(X: Integer); override;
procedure DoTableColumnChanged; override;
procedure DoTableRowChanged; override;
procedure Loaded; override;
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
public
constructor Create(AOwner: TComponent); override;
procedure AdjustPosition;
procedure UpdateRulerIndents;
procedure UpdateRulerMargins;
procedure UpdateTableEditor;
procedure UpdateListEditor;
published
property Inset default 0;
property LineStyle: TPenStyle read FLineStyle write FLineStyle default psDot;
property ListEditor;
property OnTableRowClick;
property OnTableRowDblClick;
property RichViewEdit: TCustomRichViewEdit read FRichViewEdit write SetRichViewEdit;
property RVRulerOptions: TRVRulerOptions read FRVRulerOptions write SetRVRulerOptions default DefaultRVRulerOptions;
property TableEditor;
end;
TRVRulerItemSelector = class(TRulerItemSelector)
end;
implementation
uses
RVClasses, RVTInplace;
function Min(const A, B: Integer): Integer;
begin
if A < B then
Result := A
else
Result := B;
end;
{=============================== TRVRuler =====================================}
constructor TRVRuler.Create(AOwner: TComponent);
begin
inherited;
RVRulerOptions := DefaultRVRulerOptions;
Inset := 0;
FLineStyle := psDot;
end;
{------------------------------------------------------------------------------}
procedure TRVRuler.Notification(AComponent: TComponent;
Operation: TOperation);
begin
inherited;
if (Operation = opRemove) and (AComponent = FRichViewEdit) then
begin
RestoreRichViewEditEvents;
FRichViewEdit := nil;
end;
end;
{------------------------------------------------------------------------------}
procedure TRVRuler.Loaded;
begin
inherited;
AssignRichViewEditEvents;
end;
{------------------------------------------------------------------------------}
procedure TRVRuler.DoBiDiModeChanged;
begin
inherited;
AdjustPosition;
end;
{------------------------------------------------------------------------------}
procedure TRVRuler.DoLevelButtonUp(Direction: Integer);
var
RVEditor: TCustomRichViewEdit;
begin
inherited;
if not Assigned(FRichViewEdit) then
Exit;
RVEditor := FRichViewEdit.TopLevelEditor;
RVEditor.BeginUndoGroup(rvutPara);
RVEditor.SetUndoGroupMode(True);
try
inherited;
RVEditor.ChangeListLevels(Direction);
finally
RVEditor.SetUndoGroupMode(False);
end;
end;
{------------------------------------------------------------------------------}
procedure TRVRuler.DoRulerItemSelect(X: Integer);
begin
inherited;
if not Assigned(RichViewEdit) then
Exit;
RichViewEdit.Update;
if not Assigned(FControlCanvas) then
FControlCanvas := TControlCanvas.Create;
with FControlCanvas do
begin
Control := RichViewEdit;
Pen.Color := clBlack;
Pen.Mode := pmXor;
Pen.Style := LineStyle;
end;
FSaveX := X - FRulerInset;
DrawMarkLine;
end;
{------------------------------------------------------------------------------}
procedure TRVRuler.DoRulerItemMove(X: Integer; Removing: Boolean);
begin
inherited;
if not Assigned(RichViewEdit) then
Exit;
DrawMarkLine;
if Removing then
FSaveX := -1
else
FSaveX := X - FRulerInset;
DrawMarkLine;
end;
{------------------------------------------------------------------------------}
procedure TRVRuler.DoRulerItemRelease;
begin
inherited;
DrawMarkLine;
FControlCanvas.Free;
FControlCanvas := nil;
if Assigned(FRichViewEdit) then
FRichViewEdit.Refresh;
end;
{------------------------------------------------------------------------------}
procedure TRVRuler.DrawMarkLine;
begin
if Assigned(FControlCanvas) then
with FControlCanvas do
if RulerType = rtHorizontal then
begin
if FSaveX >= 0 then
begin
MoveTo(FSaveX - FRichViewEdit.HScrollPos, 0);
LineTo(FSaveX - FRichViewEdit.HScrollPos, RichViewEdit.Height);
end;
end
else
begin
if FSaveX >= 0 then
begin
MoveTo(0,
FSaveX - FRichViewEdit.VScrollPos * FRichViewEdit.VSmallStep);
LineTo(RichViewEdit.Width,
FSaveX - FRichViewEdit.VScrollPos * FRichViewEdit.VSmallStep);
end;
end;
end;
{------------------------------------------------------------------------------}
procedure TRVRuler.DoMarginChanged;
var
DT, DB: Integer;
OldVPos: Integer;
BM, TM: Integer;
begin
inherited;
if not Assigned(FRichViewEdit) or FUpdating then Exit;
if not (rvroAutoAdjustMargins in RVRulerOptions) then Exit;
if (rvfoSaveLayout in FRichViewEdit.RVFOptions) and
not FRichViewEdit.CanChange then
Exit;
if RulerType = rtHorizontal then
begin
DT := 0;
DB := 0;
FRichViewEdit.LeftMargin := Round(UnitsToPixs(LeftMargin));
FRichViewEdit.RightMargin := Round(UnitsToPixs(RightMargin));
if not (rvoClientTextWidth in FRichViewEdit.Options) then
begin
FRichViewEdit.MinTextWidth :=
Round(UnitsToPixs(PageWidth) - FRichViewEdit.LeftMargin - FRichViewEdit.RightMargin);
FRichViewEdit.MaxTextWidth := FRichViewEdit.MinTextWidth;
end;
end
else
begin
TM := Round(UnitsToPixs(TopMargin));
BM := Round(UnitsToPixs(BottomMargin));
DT := TM - FRichViewEdit.TopMargin;
DB := BM - FRichViewEdit.BottomMargin;
FRichViewEdit.TopMargin := TM;
FRichViewEdit.BottomMargin := BM;
end;
FRichViewEdit.RVData.Format_(True, True, False, 0, FRichViewEdit.Canvas, False,
False, False);
if rvfoSaveLayout in FRichViewEdit.RVFOptions then
FRichViewEdit.Change;
// Scroll document in to position (line-up with new top or bottom margin pos).
OldVPos := FRichViewEdit.VScrollPos * FRichViewEdit.VSmallStep;
if DT <> 0 then
begin
if not ((OldVPos = 0) and (DT < 0)) then
FRichViewEdit.ScrollTo(OldVPos - DT)
end
else
with FRichViewEdit do
if (DB <> 0) then
if not (((VScrollMax - VScrollPos) <= VSmallStep) and (DB < 0)) then
FRichViewEdit.ScrollTo(OldVPos + DB);
UpdateRulerMargins;
UpdateTableEditor;
end;
{------------------------------------------------------------------------------}
procedure TRVRuler.DoTabChanged;
begin
FUpdatingTabs := True;
try
DoIndentChanged
finally
FUpdatingTabs := False;
end;
end;
{------------------------------------------------------------------------------}
procedure TRVRuler.DoIndentChanged;
var
FirstParaItemNo: Integer;
I: Integer;
ListLevel: Integer;
ListNo: Integer;
ListStyle: TRVListInfo;
M: Extended;
OldStyleConversionEvent: TRVStyleConversionEvent;
RVEditor: TCustomRichViewEdit;
RVListLevel: TRVListLevel;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -