⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rvruler.pas

📁 richviewaction 1.58 需要richview 1.9.46
💻 PAS
📖 第 1 页 / 共 3 页
字号:

{*******************************************************}
{                                                       }
{       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 + -